aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs1703
1 files changed, 1433 insertions, 270 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 866a43c..a703377 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,12 +24,13 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.ComponentModel; 29using System.ComponentModel;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Drawing; 31using System.Drawing;
32using System.IO; 32using System.IO;
33using System.Diagnostics;
33using System.Linq; 34using System.Linq;
34using System.Threading; 35using System.Threading;
35using System.Xml; 36using System.Xml;
@@ -44,6 +45,7 @@ using PermissionMask = OpenSim.Framework.PermissionMask;
44 45
45namespace OpenSim.Region.Framework.Scenes 46namespace OpenSim.Region.Framework.Scenes
46{ 47{
48
47 [Flags] 49 [Flags]
48 public enum scriptEvents 50 public enum scriptEvents
49 { 51 {
@@ -79,14 +81,14 @@ namespace OpenSim.Region.Framework.Scenes
79 object_rez = 4194304 81 object_rez = 4194304
80 } 82 }
81 83
82 struct scriptPosTarget 84 public struct scriptPosTarget
83 { 85 {
84 public Vector3 targetPos; 86 public Vector3 targetPos;
85 public float tolerance; 87 public float tolerance;
86 public uint handle; 88 public uint handle;
87 } 89 }
88 90
89 struct scriptRotTarget 91 public struct scriptRotTarget
90 { 92 {
91 public Quaternion targetRot; 93 public Quaternion targetRot;
92 public float tolerance; 94 public float tolerance;
@@ -120,8 +122,17 @@ namespace OpenSim.Region.Framework.Scenes
120 /// since the group's last persistent backup 122 /// since the group's last persistent backup
121 /// </summary> 123 /// </summary>
122 private bool m_hasGroupChanged = false; 124 private bool m_hasGroupChanged = false;
125<<<<<<< HEAD
123 private long timeFirstChanged; 126 private long timeFirstChanged;
124 private long timeLastChanged; 127 private long timeLastChanged;
128=======
129 private long timeFirstChanged = 0;
130 private long timeLastChanged = 0;
131 private long m_maxPersistTime = 0;
132 private long m_minPersistTime = 0;
133// private Random m_rand;
134 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
135>>>>>>> avn/ubitvar
125 136
126 /// <summary> 137 /// <summary>
127 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage 138 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage
@@ -138,9 +149,44 @@ namespace OpenSim.Region.Framework.Scenes
138 { 149 {
139 if (value) 150 if (value)
140 { 151 {
152
153 if (m_isBackedUp)
154 {
155 m_scene.SceneGraph.FireChangeBackup(this);
156 }
141 timeLastChanged = DateTime.Now.Ticks; 157 timeLastChanged = DateTime.Now.Ticks;
142 if (!m_hasGroupChanged) 158 if (!m_hasGroupChanged)
143 timeFirstChanged = DateTime.Now.Ticks; 159 timeFirstChanged = DateTime.Now.Ticks;
160 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
161 {
162/*
163 if (m_rand == null)
164 {
165 byte[] val = new byte[16];
166 m_rootPart.UUID.ToBytes(val, 0);
167 m_rand = new Random(BitConverter.ToInt32(val, 0));
168 }
169 */
170 if (m_scene.GetRootAgentCount() == 0)
171 {
172 //If the region is empty, this change has been made by an automated process
173 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
174
175// float factor = 1.5f + (float)(m_rand.NextDouble());
176 float factor = 2.0f;
177 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
178 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
179 }
180 else
181 {
182 //If the region is not empty, we want to obey the minimum and maximum persist times
183 //but add a random factor so we stagger the object persistance a little
184// m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
185// m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
186 m_maxPersistTime = m_scene.m_persistAfter;
187 m_minPersistTime = m_scene.m_dontPersistBefore;
188 }
189 }
144 } 190 }
145 m_hasGroupChanged = value; 191 m_hasGroupChanged = value;
146 192
@@ -159,6 +205,7 @@ namespace OpenSim.Region.Framework.Scenes
159 /// the prims in the database still use the old SceneGroupID. That's a problem if the group 205 /// the prims in the database still use the old SceneGroupID. That's a problem if the group
160 /// is deleted, because we delete groups by searching for prims by their SceneGroupID. 206 /// is deleted, because we delete groups by searching for prims by their SceneGroupID.
161 /// </summary> 207 /// </summary>
208<<<<<<< HEAD
162 public bool GroupContainsForeignPrims 209 public bool GroupContainsForeignPrims
163 { 210 {
164 private set 211 private set
@@ -171,6 +218,9 @@ namespace OpenSim.Region.Framework.Scenes
171 get { return m_groupContainsForeignPrims; } 218 get { return m_groupContainsForeignPrims; }
172 } 219 }
173 220
221=======
222 public bool HasGroupChangedDueToDelink { get; set; }
223>>>>>>> avn/ubitvar
174 224
175 private bool isTimeToPersist() 225 private bool isTimeToPersist()
176 { 226 {
@@ -180,8 +230,19 @@ namespace OpenSim.Region.Framework.Scenes
180 return false; 230 return false;
181 if (m_scene.ShuttingDown) 231 if (m_scene.ShuttingDown)
182 return true; 232 return true;
233
234 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
235 {
236 m_maxPersistTime = m_scene.m_persistAfter;
237 m_minPersistTime = m_scene.m_dontPersistBefore;
238 }
239
183 long currentTime = DateTime.Now.Ticks; 240 long currentTime = DateTime.Now.Ticks;
184 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 241
242 if (timeLastChanged == 0) timeLastChanged = currentTime;
243 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
244
245 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
185 return true; 246 return true;
186 return false; 247 return false;
187 } 248 }
@@ -239,6 +300,11 @@ namespace OpenSim.Region.Framework.Scenes
239 { 300 {
240 AttachmentPoint = 0; 301 AttachmentPoint = 0;
241 302
303 // Don't zap trees
304 if (RootPart.Shape.PCode == (byte)PCode.Tree ||
305 RootPart.Shape.PCode == (byte)PCode.NewTree)
306 return;
307
242 // Even though we don't use child part state parameters for attachments any more, we still need to set 308 // Even though we don't use child part state parameters for attachments any more, we still need to set
243 // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if 309 // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if
244 // we store them correctly, scene objects that we receive from elsewhere might not. 310 // we store them correctly, scene objects that we receive from elsewhere might not.
@@ -284,6 +350,7 @@ namespace OpenSim.Region.Framework.Scenes
284 get { return RootPart.VolumeDetectActive; } 350 get { return RootPart.VolumeDetectActive; }
285 } 351 }
286 352
353<<<<<<< HEAD
287 private Vector3 lastPhysGroupPos; 354 private Vector3 lastPhysGroupPos;
288 private Quaternion lastPhysGroupRot; 355 private Quaternion lastPhysGroupRot;
289 356
@@ -291,6 +358,14 @@ namespace OpenSim.Region.Framework.Scenes
291 /// Is this entity set to be saved in persistent storage? 358 /// Is this entity set to be saved in persistent storage?
292 /// </summary> 359 /// </summary>
293 public bool Backup { get; private set; } 360 public bool Backup { get; private set; }
361=======
362 private bool m_isBackedUp;
363>>>>>>> avn/ubitvar
364
365 public bool IsBackedUp
366 {
367 get { return m_isBackedUp; }
368 }
294 369
295 protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>(); 370 protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>();
296 371
@@ -298,15 +373,25 @@ namespace OpenSim.Region.Framework.Scenes
298 protected SceneObjectPart m_rootPart; 373 protected SceneObjectPart m_rootPart;
299 // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>(); 374 // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
300 375
301 private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>(); 376 private SortedDictionary<uint, scriptPosTarget> m_targets = new SortedDictionary<uint, scriptPosTarget>();
302 private Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>(); 377 private SortedDictionary<uint, scriptRotTarget> m_rotTargets = new SortedDictionary<uint, scriptRotTarget>();
378
379 public SortedDictionary<uint, scriptPosTarget> AtTargets
380 {
381 get { return m_targets; }
382 }
383
384 public SortedDictionary<uint, scriptRotTarget> RotTargets
385 {
386 get { return m_rotTargets; }
387 }
303 388
304 private bool m_scriptListens_atTarget; 389 private bool m_scriptListens_atTarget;
305 private bool m_scriptListens_notAtTarget; 390 private bool m_scriptListens_notAtTarget;
306
307 private bool m_scriptListens_atRotTarget; 391 private bool m_scriptListens_atRotTarget;
308 private bool m_scriptListens_notAtRotTarget; 392 private bool m_scriptListens_notAtRotTarget;
309 393
394 public bool m_dupeInProgress = false;
310 internal Dictionary<UUID, string> m_savedScriptState; 395 internal Dictionary<UUID, string> m_savedScriptState;
311 396
312 #region Properties 397 #region Properties
@@ -343,6 +428,16 @@ namespace OpenSim.Region.Framework.Scenes
343 get { return m_parts.Count; } 428 get { return m_parts.Count; }
344 } 429 }
345 430
431// protected Quaternion m_rotation = Quaternion.Identity;
432//
433// public virtual Quaternion Rotation
434// {
435// get { return m_rotation; }
436// set {
437// m_rotation = value;
438// }
439// }
440
346 public Quaternion GroupRotation 441 public Quaternion GroupRotation
347 { 442 {
348 get { return m_rootPart.RotationOffset; } 443 get { return m_rootPart.RotationOffset; }
@@ -456,6 +551,10 @@ namespace OpenSim.Region.Framework.Scenes
456 public uint ParentID; 551 public uint ParentID;
457 } 552 }
458 553
554
555 public bool inTransit = false;
556 public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos);
557
459 /// <summary> 558 /// <summary>
460 /// The absolute position of this scene object in the scene 559 /// The absolute position of this scene object in the scene
461 /// </summary> 560 /// </summary>
@@ -465,9 +564,13 @@ namespace OpenSim.Region.Framework.Scenes
465 set 564 set
466 { 565 {
467 Vector3 val = value; 566 Vector3 val = value;
468 567 if (Scene != null
469 if (Scene != null) 568 && !Scene.PositionIsInCurrentRegion(val)
569 && !IsAttachmentCheckFull()
570 && !Scene.LoadingPrims
571 )
470 { 572 {
573<<<<<<< HEAD
471 if ( 574 if (
472 !Scene.PositionIsInCurrentRegion(val) 575 !Scene.PositionIsInCurrentRegion(val)
473 && !IsAttachmentCheckFull() 576 && !IsAttachmentCheckFull()
@@ -600,7 +703,15 @@ namespace OpenSim.Region.Framework.Scenes
600 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f); 703 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f);
601 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f); 704 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f);
602 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight); 705 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight);
706=======
707 if (!inTransit)
708 {
709 inTransit = true;
710 SOGCrossDelegate d = CrossAsync;
711 d.BeginInvoke(this, val, CrossAsyncCompleted, d);
712>>>>>>> avn/ubitvar
603 } 713 }
714 return;
604 } 715 }
605 716
606 if (RootPart.GetStatusSandbox()) 717 if (RootPart.GetStatusSandbox())
@@ -608,38 +719,235 @@ namespace OpenSim.Region.Framework.Scenes
608 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 719 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
609 { 720 {
610 RootPart.ScriptSetPhysicsStatus(false); 721 RootPart.ScriptSetPhysicsStatus(false);
611 722
612 if (Scene != null) 723 if (Scene != null)
613 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 724 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
614 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 725 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
615 726
616 return; 727 return;
617 } 728 }
618 } 729 }
619 730
620 // Restuff the new GroupPosition into each SOP of the linkset. 731 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
621 // This has the affect of resetting and tainting the physics actors. 732 if (m_dupeInProgress || IsDeleted)
733 triggerScriptEvent = false;
734
735 m_rootPart.GroupPosition = val;
736
737 // Restuff the new GroupPosition into each child SOP of the linkset.
738 // this is needed because physics may not have linksets but just loose SOPs in world
739
622 SceneObjectPart[] parts = m_parts.GetArray(); 740 SceneObjectPart[] parts = m_parts.GetArray();
623 for (int i = 0; i < parts.Length; i++)
624 parts[i].GroupPosition = val;
625 741
626 //if (m_rootPart.PhysActor != null) 742 foreach (SceneObjectPart part in parts)
627 //{ 743 {
628 //m_rootPart.PhysActor.Position = 744 if (part != m_rootPart)
629 //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y, 745 part.GroupPosition = val;
630 //m_rootPart.GroupPosition.Z); 746 }
631 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 747
632 //} 748 foreach (ScenePresence av in m_linkedAvatars)
633 749 {
750 av.sitSOGmoved();
751 }
752
753
754 // now that position is changed tell it to scripts
755 if (triggerScriptEvent)
756 {
757 foreach (SceneObjectPart part in parts)
758 {
759 part.TriggerScriptChangedEvent(Changed.POSITION);
760 }
761 }
762
634 if (Scene != null) 763 if (Scene != null)
635 Scene.EventManager.TriggerParcelPrimCountTainted(); 764 Scene.EventManager.TriggerParcelPrimCountTainted();
765
636 } 766 }
637 } 767 }
638 768
639 public override Vector3 Velocity 769 public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val)
640 { 770 {
641 get { return RootPart.Velocity; } 771 Scene sogScene = sog.m_scene;
642 set { RootPart.Velocity = value; } 772 IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>();
773
774 Vector3 newpos = Vector3.Zero;
775 OpenSim.Services.Interfaces.GridRegion destination = null;
776
777 if (sog.RootPart.DIE_AT_EDGE)
778 {
779 try
780 {
781 sogScene.DeleteSceneObject(sog, false);
782 }
783 catch (Exception)
784 {
785 m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border.");
786 }
787 return sog;
788 }
789
790 if (sog.RootPart.RETURN_AT_EDGE)
791 {
792 // We remove the object here
793 try
794 {
795 List<uint> localIDs = new List<uint>();
796 localIDs.Add(sog.RootPart.LocalId);
797 sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition,
798 "Returned at region cross");
799 sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero);
800 }
801 catch (Exception)
802 {
803 m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border.");
804 }
805 return sog;
806 }
807
808 if (sog.m_rootPart.KeyframeMotion != null)
809 sog.m_rootPart.KeyframeMotion.StartCrossingCheck();
810
811 if (entityTransfer == null)
812 return sog;
813
814 destination = entityTransfer.GetObjectDestination(sog, val, out newpos);
815 if (destination == null)
816 return sog;
817
818 if (sog.m_linkedAvatars.Count == 0)
819 {
820 entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true);
821 return sog;
822 }
823
824 string reason = String.Empty;
825 string version = String.Empty;
826
827 foreach (ScenePresence av in sog.m_linkedAvatars)
828 {
829 // We need to cross these agents. First, let's find
830 // out if any of them can't cross for some reason.
831 // We have to deny the crossing entirely if any
832 // of them are banned. Alternatively, we could
833 // unsit banned agents....
834
835 // We set the avatar position as being the object
836 // position to get the region to send to
837 if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, out version, out reason))
838 {
839 return sog;
840 }
841 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
842 }
843
844 // We unparent the SP quietly so that it won't
845 // be made to stand up
846
847 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
848
849 foreach (ScenePresence av in sog.m_linkedAvatars)
850 {
851 avtocrossInfo avinfo = new avtocrossInfo();
852 SceneObjectPart parentPart = sogScene.GetSceneObjectPart(av.ParentID);
853 if (parentPart != null)
854 av.ParentUUID = parentPart.UUID;
855
856 avinfo.av = av;
857 avinfo.ParentID = av.ParentID;
858 avsToCross.Add(avinfo);
859
860 av.PrevSitOffset = av.OffsetPosition;
861 av.ParentID = 0;
862 }
863
864 if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true))
865 {
866 foreach (avtocrossInfo avinfo in avsToCross)
867 {
868 ScenePresence av = avinfo.av;
869 if (!av.IsInTransit) // just in case...
870 {
871 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
872
873 av.IsInTransit = true;
874
875// CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
876// d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
877 entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, version);
878 if(av.IsChildAgent)
879 {
880 if (av.ParentUUID != UUID.Zero)
881 {
882 av.ClearControls();
883 av.ParentPart = null;
884 }
885 }
886 av.ParentUUID = UUID.Zero;
887 // In any case
888 av.IsInTransit = false;
889
890 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname);
891 }
892 else
893 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val);
894 }
895 avsToCross.Clear();
896 return sog;
897 }
898 else // cross failed, put avas back ??
899 {
900 foreach (avtocrossInfo avinfo in avsToCross)
901 {
902 ScenePresence av = avinfo.av;
903 av.ParentUUID = UUID.Zero;
904 av.ParentID = avinfo.ParentID;
905 }
906 }
907 avsToCross.Clear();
908
909 return sog;
910 }
911
912 public void CrossAsyncCompleted(IAsyncResult iar)
913 {
914 SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState;
915 SceneObjectGroup sog = icon.EndInvoke(iar);
916
917 if (!sog.IsDeleted)
918 {
919 SceneObjectPart rootp = sog.m_rootPart;
920 Vector3 oldp = rootp.GroupPosition;
921 oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f);
922 oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f);
923 rootp.GroupPosition = oldp;
924
925 SceneObjectPart[] parts = sog.m_parts.GetArray();
926
927 foreach (SceneObjectPart part in parts)
928 {
929 if (part != rootp)
930 part.GroupPosition = oldp;
931 }
932
933 foreach (ScenePresence av in sog.m_linkedAvatars)
934 {
935 av.sitSOGmoved();
936 }
937
938 sog.Velocity = Vector3.Zero;
939
940 if (sog.m_rootPart.KeyframeMotion != null)
941 sog.m_rootPart.KeyframeMotion.CrossingFailure();
942
943 if (sog.RootPart.PhysActor != null)
944 {
945 sog.RootPart.PhysActor.CrossingFailure();
946 }
947
948 sog.inTransit = false;
949 sog.ScheduleGroupForFullUpdate();
950 }
643 } 951 }
644 952
645 private void CrossAgentToNewRegionCompleted(ScenePresence agent) 953 private void CrossAgentToNewRegionCompleted(ScenePresence agent)
@@ -649,6 +957,7 @@ namespace OpenSim.Region.Framework.Scenes
649 { 957 {
650 if (agent.ParentUUID != UUID.Zero) 958 if (agent.ParentUUID != UUID.Zero)
651 { 959 {
960 agent.HandleForceReleaseControls(agent.ControllingClient,agent.UUID);
652 agent.ParentPart = null; 961 agent.ParentPart = null;
653// agent.ParentPosition = Vector3.Zero; 962// agent.ParentPosition = Vector3.Zero;
654// agent.ParentUUID = UUID.Zero; 963// agent.ParentUUID = UUID.Zero;
@@ -666,6 +975,12 @@ namespace OpenSim.Region.Framework.Scenes
666 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); 975 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
667 } 976 }
668 977
978 public override Vector3 Velocity
979 {
980 get { return RootPart.Velocity; }
981 set { RootPart.Velocity = value; }
982 }
983
669 public override uint LocalId 984 public override uint LocalId
670 { 985 {
671 get { return m_rootPart.LocalId; } 986 get { return m_rootPart.LocalId; }
@@ -740,6 +1055,11 @@ namespace OpenSim.Region.Framework.Scenes
740 m_isSelected = value; 1055 m_isSelected = value;
741 // Tell physics engine that group is selected 1056 // Tell physics engine that group is selected
742 1057
1058 // this is not right
1059 // but ode engines should only really need to know about root part
1060 // so they can put entire object simulation on hold and not colliding
1061 // keep as was for now
1062
743 PhysicsActor pa = m_rootPart.PhysActor; 1063 PhysicsActor pa = m_rootPart.PhysActor;
744 if (pa != null) 1064 if (pa != null)
745 { 1065 {
@@ -761,13 +1081,47 @@ namespace OpenSim.Region.Framework.Scenes
761 } 1081 }
762 } 1082 }
763 1083
1084 public void PartSelectChanged(bool partSelect)
1085 {
1086 // any part selected makes group selected
1087 if (m_isSelected == partSelect)
1088 return;
1089
1090 if (partSelect)
1091 {
1092 IsSelected = partSelect;
1093// if (!IsAttachment)
1094// ScheduleGroupForFullUpdate();
1095 }
1096 else
1097 {
1098 // bad bad bad 2 heavy for large linksets
1099 // since viewer does send lot of (un)selects
1100 // this needs to be replaced by a specific list or count ?
1101 // but that will require extra code in several places
1102
1103 SceneObjectPart[] parts = m_parts.GetArray();
1104 for (int i = 0; i < parts.Length; i++)
1105 {
1106 SceneObjectPart part = parts[i];
1107 if (part.IsSelected)
1108 return;
1109 }
1110 IsSelected = partSelect;
1111// if (!IsAttachment)
1112// {
1113// ScheduleGroupForFullUpdate();
1114// }
1115 }
1116 }
1117 // PlaySoundMasterPrim no longer in use to remove
764 private SceneObjectPart m_PlaySoundMasterPrim = null; 1118 private SceneObjectPart m_PlaySoundMasterPrim = null;
765 public SceneObjectPart PlaySoundMasterPrim 1119 public SceneObjectPart PlaySoundMasterPrim
766 { 1120 {
767 get { return m_PlaySoundMasterPrim; } 1121 get { return m_PlaySoundMasterPrim; }
768 set { m_PlaySoundMasterPrim = value; } 1122 set { m_PlaySoundMasterPrim = value; }
769 } 1123 }
770 1124 // PlaySoundSlavePrims no longer in use to remove
771 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); 1125 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>();
772 public List<SceneObjectPart> PlaySoundSlavePrims 1126 public List<SceneObjectPart> PlaySoundSlavePrims
773 { 1127 {
@@ -775,6 +1129,7 @@ namespace OpenSim.Region.Framework.Scenes
775 set { m_PlaySoundSlavePrims = value; } 1129 set { m_PlaySoundSlavePrims = value; }
776 } 1130 }
777 1131
1132 // LoopSoundMasterPrim no longer in use to remove
778 private SceneObjectPart m_LoopSoundMasterPrim = null; 1133 private SceneObjectPart m_LoopSoundMasterPrim = null;
779 public SceneObjectPart LoopSoundMasterPrim 1134 public SceneObjectPart LoopSoundMasterPrim
780 { 1135 {
@@ -782,6 +1137,7 @@ namespace OpenSim.Region.Framework.Scenes
782 set { m_LoopSoundMasterPrim = value; } 1137 set { m_LoopSoundMasterPrim = value; }
783 } 1138 }
784 1139
1140 // m_LoopSoundSlavePrims no longer in use to remove
785 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); 1141 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>();
786 public List<SceneObjectPart> LoopSoundSlavePrims 1142 public List<SceneObjectPart> LoopSoundSlavePrims
787 { 1143 {
@@ -861,6 +1217,7 @@ namespace OpenSim.Region.Framework.Scenes
861 /// </summary> 1217 /// </summary>
862 public SceneObjectGroup() 1218 public SceneObjectGroup()
863 { 1219 {
1220
864 } 1221 }
865 1222
866 /// <summary> 1223 /// <summary>
@@ -878,8 +1235,8 @@ namespace OpenSim.Region.Framework.Scenes
878 /// Constructor. This object is added to the scene later via AttachToScene() 1235 /// Constructor. This object is added to the scene later via AttachToScene()
879 /// </summary> 1236 /// </summary>
880 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 1237 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
881 :this(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)) 1238 {
882 { 1239 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
883 } 1240 }
884 1241
885 /// <summary> 1242 /// <summary>
@@ -954,7 +1311,14 @@ namespace OpenSim.Region.Framework.Scenes
954 /// </summary> 1311 /// </summary>
955 public virtual void AttachToBackup() 1312 public virtual void AttachToBackup()
956 { 1313 {
1314<<<<<<< HEAD
957 if (CanBeBackedUp) 1315 if (CanBeBackedUp)
1316=======
1317 if (IsAttachment) return;
1318 m_scene.SceneGraph.FireAttachToBackup(this);
1319
1320 if (InSceneBackup)
1321>>>>>>> avn/ubitvar
958 { 1322 {
959// m_log.DebugFormat( 1323// m_log.DebugFormat(
960// "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID); 1324// "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID);
@@ -1001,6 +1365,13 @@ namespace OpenSim.Region.Framework.Scenes
1001 1365
1002 ApplyPhysics(); 1366 ApplyPhysics();
1003 1367
1368 if (RootPart.PhysActor != null)
1369 RootPart.Force = RootPart.Force;
1370 if (RootPart.PhysActor != null)
1371 RootPart.Torque = RootPart.Torque;
1372 if (RootPart.PhysActor != null)
1373 RootPart.Buoyancy = RootPart.Buoyancy;
1374
1004 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 1375 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
1005 // for the same object with very different properties. The caller must schedule the update. 1376 // for the same object with very different properties. The caller must schedule the update.
1006 //ScheduleGroupForFullUpdate(); 1377 //ScheduleGroupForFullUpdate();
@@ -1016,6 +1387,10 @@ namespace OpenSim.Region.Framework.Scenes
1016 EntityIntersection result = new EntityIntersection(); 1387 EntityIntersection result = new EntityIntersection();
1017 1388
1018 SceneObjectPart[] parts = m_parts.GetArray(); 1389 SceneObjectPart[] parts = m_parts.GetArray();
1390
1391 // Find closest hit here
1392 float idist = float.MaxValue;
1393
1019 for (int i = 0; i < parts.Length; i++) 1394 for (int i = 0; i < parts.Length; i++)
1020 { 1395 {
1021 SceneObjectPart part = parts[i]; 1396 SceneObjectPart part = parts[i];
@@ -1030,11 +1405,6 @@ namespace OpenSim.Region.Framework.Scenes
1030 1405
1031 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 1406 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
1032 1407
1033 // This may need to be updated to the maximum draw distance possible..
1034 // We might (and probably will) be checking for prim creation from other sims
1035 // when the camera crosses the border.
1036 float idist = Constants.RegionSize;
1037
1038 if (inter.HitTF) 1408 if (inter.HitTF)
1039 { 1409 {
1040 // We need to find the closest prim to return to the testcaller along the ray 1410 // We need to find the closest prim to return to the testcaller along the ray
@@ -1045,10 +1415,11 @@ namespace OpenSim.Region.Framework.Scenes
1045 result.obj = part; 1415 result.obj = part;
1046 result.normal = inter.normal; 1416 result.normal = inter.normal;
1047 result.distance = inter.distance; 1417 result.distance = inter.distance;
1418
1419 idist = inter.distance;
1048 } 1420 }
1049 } 1421 }
1050 } 1422 }
1051
1052 return result; 1423 return result;
1053 } 1424 }
1054 1425
@@ -1060,25 +1431,36 @@ namespace OpenSim.Region.Framework.Scenes
1060 /// <returns></returns> 1431 /// <returns></returns>
1061 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 1432 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
1062 { 1433 {
1434<<<<<<< HEAD
1063 maxX = -256f; 1435 maxX = -256f;
1064 maxY = -256f; 1436 maxY = -256f;
1065 maxZ = -256f; 1437 maxZ = -256f;
1066 minX = 10000f; 1438 minX = 10000f;
1067 minY = 10000f; 1439 minY = 10000f;
1068 minZ = 10000f; 1440 minZ = 10000f;
1441=======
1442 maxX = float.MinValue;
1443 maxY = float.MinValue;
1444 maxZ = float.MinValue;
1445 minX = float.MaxValue;
1446 minY = float.MaxValue;
1447 minZ = float.MaxValue;
1448>>>>>>> avn/ubitvar
1069 1449
1070 SceneObjectPart[] parts = m_parts.GetArray(); 1450 SceneObjectPart[] parts = m_parts.GetArray();
1071 for (int i = 0; i < parts.Length; i++) 1451 foreach (SceneObjectPart part in parts)
1072 { 1452 {
1073 SceneObjectPart part = parts[i];
1074
1075 Vector3 worldPos = part.GetWorldPosition(); 1453 Vector3 worldPos = part.GetWorldPosition();
1076 Vector3 offset = worldPos - AbsolutePosition; 1454 Vector3 offset = worldPos - AbsolutePosition;
1077 Quaternion worldRot; 1455 Quaternion worldRot;
1078 if (part.ParentID == 0) 1456 if (part.ParentID == 0)
1457 {
1079 worldRot = part.RotationOffset; 1458 worldRot = part.RotationOffset;
1459 }
1080 else 1460 else
1461 {
1081 worldRot = part.GetWorldRotation(); 1462 worldRot = part.GetWorldRotation();
1463 }
1082 1464
1083 Vector3 frontTopLeft; 1465 Vector3 frontTopLeft;
1084 Vector3 frontTopRight; 1466 Vector3 frontTopRight;
@@ -1090,6 +1472,8 @@ namespace OpenSim.Region.Framework.Scenes
1090 Vector3 backBottomLeft; 1472 Vector3 backBottomLeft;
1091 Vector3 backBottomRight; 1473 Vector3 backBottomRight;
1092 1474
1475 // Vector3[] corners = new Vector3[8];
1476
1093 Vector3 orig = Vector3.Zero; 1477 Vector3 orig = Vector3.Zero;
1094 1478
1095 frontTopLeft.X = orig.X - (part.Scale.X / 2); 1479 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -1124,6 +1508,38 @@ namespace OpenSim.Region.Framework.Scenes
1124 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1508 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
1125 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1509 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
1126 1510
1511
1512
1513 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1514 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1515 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1516 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1517 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1518 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1519 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1520 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1521
1522 //for (int i = 0; i < 8; i++)
1523 //{
1524 // corners[i] = corners[i] * worldRot;
1525 // corners[i] += offset;
1526
1527 // if (corners[i].X > maxX)
1528 // maxX = corners[i].X;
1529 // if (corners[i].X < minX)
1530 // minX = corners[i].X;
1531
1532 // if (corners[i].Y > maxY)
1533 // maxY = corners[i].Y;
1534 // if (corners[i].Y < minY)
1535 // minY = corners[i].Y;
1536
1537 // if (corners[i].Z > maxZ)
1538 // maxZ = corners[i].Y;
1539 // if (corners[i].Z < minZ)
1540 // minZ = corners[i].Z;
1541 //}
1542
1127 frontTopLeft = frontTopLeft * worldRot; 1543 frontTopLeft = frontTopLeft * worldRot;
1128 frontTopRight = frontTopRight * worldRot; 1544 frontTopRight = frontTopRight * worldRot;
1129 frontBottomLeft = frontBottomLeft * worldRot; 1545 frontBottomLeft = frontBottomLeft * worldRot;
@@ -1145,6 +1561,15 @@ namespace OpenSim.Region.Framework.Scenes
1145 backTopLeft += offset; 1561 backTopLeft += offset;
1146 backTopRight += offset; 1562 backTopRight += offset;
1147 1563
1564 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1565 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1566 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1567 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1568 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1569 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1570 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1571 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1572
1148 if (frontTopRight.X > maxX) 1573 if (frontTopRight.X > maxX)
1149 maxX = frontTopRight.X; 1574 maxX = frontTopRight.X;
1150 if (frontTopLeft.X > maxX) 1575 if (frontTopLeft.X > maxX)
@@ -1288,17 +1713,118 @@ namespace OpenSim.Region.Framework.Scenes
1288 1713
1289 #endregion 1714 #endregion
1290 1715
1716 public void GetResourcesCosts(SceneObjectPart apart,
1717 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1718 {
1719 // this information may need to be cached
1720
1721 float cost;
1722 float tmpcost;
1723
1724 bool ComplexCost = false;
1725
1726 SceneObjectPart p;
1727 SceneObjectPart[] parts;
1728
1729 lock (m_parts)
1730 {
1731 parts = m_parts.GetArray();
1732 }
1733
1734 int nparts = parts.Length;
1735
1736
1737 for (int i = 0; i < nparts; i++)
1738 {
1739 p = parts[i];
1740
1741 if (p.UsesComplexCost)
1742 {
1743 ComplexCost = true;
1744 break;
1745 }
1746 }
1747
1748 if (ComplexCost)
1749 {
1750 linksetResCost = 0;
1751 linksetPhysCost = 0;
1752 partCost = 0;
1753 partPhysCost = 0;
1754
1755 for (int i = 0; i < nparts; i++)
1756 {
1757 p = parts[i];
1758
1759 cost = p.StreamingCost;
1760 tmpcost = p.SimulationCost;
1761 if (tmpcost > cost)
1762 cost = tmpcost;
1763 tmpcost = p.PhysicsCost;
1764 if (tmpcost > cost)
1765 cost = tmpcost;
1766
1767 linksetPhysCost += tmpcost;
1768 linksetResCost += cost;
1769
1770 if (p == apart)
1771 {
1772 partCost = cost;
1773 partPhysCost = tmpcost;
1774 }
1775 }
1776 }
1777 else
1778 {
1779 partPhysCost = 1.0f;
1780 partCost = 1.0f;
1781 linksetResCost = (float)nparts;
1782 linksetPhysCost = linksetResCost;
1783 }
1784 }
1785
1786 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1787 {
1788 SceneObjectPart p;
1789 SceneObjectPart[] parts;
1790
1791 lock (m_parts)
1792 {
1793 parts = m_parts.GetArray();
1794 }
1795
1796 int nparts = parts.Length;
1797
1798 PhysCost = 0;
1799 StreamCost = 0;
1800 SimulCost = 0;
1801
1802 for (int i = 0; i < nparts; i++)
1803 {
1804 p = parts[i];
1805
1806 StreamCost += p.StreamingCost;
1807 SimulCost += p.SimulationCost;
1808 PhysCost += p.PhysicsCost;
1809 }
1810 }
1811
1291 public void SaveScriptedState(XmlTextWriter writer) 1812 public void SaveScriptedState(XmlTextWriter writer)
1292 { 1813 {
1814 SaveScriptedState(writer, false);
1815 }
1816
1817 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1818 {
1293 XmlDocument doc = new XmlDocument(); 1819 XmlDocument doc = new XmlDocument();
1294 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1820 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
1295 1821
1296 SceneObjectPart[] parts = m_parts.GetArray(); 1822 SceneObjectPart[] parts = m_parts.GetArray();
1297 for (int i = 0; i < parts.Length; i++) 1823 for (int i = 0; i < parts.Length; i++)
1298 { 1824 {
1299 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1825 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
1300 foreach (KeyValuePair<UUID, string> kvp in pstates) 1826 foreach (KeyValuePair<UUID, string> kvp in pstates)
1301 states.Add(kvp.Key, kvp.Value); 1827 states[kvp.Key] = kvp.Value;
1302 } 1828 }
1303 1829
1304 if (states.Count > 0) 1830 if (states.Count > 0)
@@ -1317,6 +1843,183 @@ namespace OpenSim.Region.Framework.Scenes
1317 } 1843 }
1318 } 1844 }
1319 1845
1846<<<<<<< HEAD
1847
1848 /// <summary>
1849 ///
1850 /// </summary>
1851 /// <param name="part"></param>
1852 private void SetPartAsNonRoot(SceneObjectPart part)
1853 {
1854 part.ParentID = m_rootPart.LocalId;
1855 part.ClearUndoState();
1856=======
1857 /// <summary>
1858 /// Add the avatar to this linkset (avatar is sat).
1859 /// </summary>
1860 /// <param name="agentID"></param>
1861 public void AddAvatar(UUID agentID)
1862 {
1863 ScenePresence presence;
1864 if (m_scene.TryGetScenePresence(agentID, out presence))
1865 {
1866 if (!m_linkedAvatars.Contains(presence))
1867 {
1868 m_linkedAvatars.Add(presence);
1869 }
1870 }
1871 }
1872
1873 /// <summary>
1874 /// Delete the avatar from this linkset (avatar is unsat).
1875 /// </summary>
1876 /// <param name="agentID"></param>
1877 public void DeleteAvatar(UUID agentID)
1878 {
1879 ScenePresence presence;
1880 if (m_scene.TryGetScenePresence(agentID, out presence))
1881 {
1882 if (m_linkedAvatars.Contains(presence))
1883 {
1884 m_linkedAvatars.Remove(presence);
1885 }
1886 }
1887 }
1888
1889 /// <summary>
1890 /// Returns the list of linked presences (avatars sat on this group)
1891 /// </summary>
1892 /// <param name="agentID"></param>
1893 public List<ScenePresence> GetLinkedAvatars()
1894 {
1895 return m_linkedAvatars;
1896>>>>>>> avn/ubitvar
1897 }
1898
1899 /// <summary>
1900 /// Attach this scene object to the given avatar.
1901 /// </summary>
1902 /// <param name="agentID"></param>
1903 /// <param name="attachmentpoint"></param>
1904 /// <param name="AttachOffset"></param>
1905 private void AttachToAgent(
1906 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1907 {
1908 if (avatar != null)
1909 {
1910 // don't attach attachments to child agents
1911 if (avatar.IsChildAgent) return;
1912
1913 // Remove from database and parcel prim count
1914 m_scene.DeleteFromStorage(so.UUID);
1915 m_scene.EventManager.TriggerParcelPrimCountTainted();
1916
1917 so.AttachedAvatar = avatar.UUID;
1918
1919 if (so.RootPart.PhysActor != null)
1920 {
1921 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1922 so.RootPart.PhysActor = null;
1923 }
1924
1925 so.AbsolutePosition = attachOffset;
1926 so.RootPart.AttachedPos = attachOffset;
1927 so.IsAttachment = true;
1928 so.RootPart.SetParentLocalId(avatar.LocalId);
1929 so.AttachmentPoint = attachmentpoint;
1930
1931 avatar.AddAttachment(this);
1932
1933 if (!silent)
1934 {
1935 // Killing it here will cause the client to deselect it
1936 // It then reappears on the avatar, deselected
1937 // through the full update below
1938 //
1939 if (IsSelected)
1940 {
1941 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1942 }
1943
1944 IsSelected = false; // fudge....
1945 ScheduleGroupForFullUpdate();
1946 }
1947 }
1948 else
1949 {
1950 m_log.WarnFormat(
1951 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1952 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1953 }
1954 }
1955
1956 public byte GetAttachmentPoint()
1957 {
1958 return m_rootPart.Shape.State;
1959 }
1960
1961 public void DetachToGround()
1962 {
1963 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1964 if (avatar == null)
1965 return;
1966 m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State;
1967 m_rootPart.AttachedPos = m_rootPart.OffsetPosition;
1968 avatar.RemoveAttachment(this);
1969
1970 Vector3 detachedpos = new Vector3(127f,127f,127f);
1971 if (avatar == null)
1972 return;
1973
1974 detachedpos = avatar.AbsolutePosition;
1975 FromItemID = UUID.Zero;
1976
1977 AbsolutePosition = detachedpos;
1978 AttachedAvatar = UUID.Zero;
1979
1980 //SceneObjectPart[] parts = m_parts.GetArray();
1981 //for (int i = 0; i < parts.Length; i++)
1982 // parts[i].AttachedAvatar = UUID.Zero;
1983
1984 m_rootPart.SetParentLocalId(0);
1985 AttachmentPoint = (byte)0;
1986 // must check if buildind should be true or false here
1987// m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1988 ApplyPhysics();
1989
1990 HasGroupChanged = true;
1991 RootPart.Rezzed = DateTime.Now;
1992 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1993 AttachToBackup();
1994 m_scene.EventManager.TriggerParcelPrimCountTainted();
1995 m_rootPart.ScheduleFullUpdate();
1996 m_rootPart.ClearUndoState();
1997 }
1998
1999 public void DetachToInventoryPrep()
2000 {
2001 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
2002 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
2003 if (avatar != null)
2004 {
2005 //detachedpos = avatar.AbsolutePosition;
2006 avatar.RemoveAttachment(this);
2007 }
2008
2009 AttachedAvatar = UUID.Zero;
2010
2011 /*SceneObjectPart[] parts = m_parts.GetArray();
2012 for (int i = 0; i < parts.Length; i++)
2013 parts[i].AttachedAvatar = UUID.Zero;*/
2014
2015 m_rootPart.SetParentLocalId(0);
2016 //m_rootPart.SetAttachmentPoint((byte)0);
2017 IsAttachment = false;
2018 AbsolutePosition = m_rootPart.AttachedPos;
2019 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
2020 //AttachToBackup();
2021 //m_rootPart.ScheduleFullUpdate();
2022 }
1320 2023
1321 /// <summary> 2024 /// <summary>
1322 /// 2025 ///
@@ -1358,7 +2061,10 @@ namespace OpenSim.Region.Framework.Scenes
1358 public void AddPart(SceneObjectPart part) 2061 public void AddPart(SceneObjectPart part)
1359 { 2062 {
1360 part.SetParent(this); 2063 part.SetParent(this);
1361 part.LinkNum = m_parts.Add(part.UUID, part); 2064 m_parts.Add(part.UUID, part);
2065
2066 part.LinkNum = m_parts.Count;
2067
1362 if (part.LinkNum == 2) 2068 if (part.LinkNum == 2)
1363 RootPart.LinkNum = 1; 2069 RootPart.LinkNum = 1;
1364 } 2070 }
@@ -1384,6 +2090,14 @@ namespace OpenSim.Region.Framework.Scenes
1384 parts[i].UUID = UUID.Random(); 2090 parts[i].UUID = UUID.Random();
1385 } 2091 }
1386 2092
2093 // helper provided for parts.
2094 public int GetSceneMaxUndo()
2095 {
2096 if (m_scene != null)
2097 return m_scene.MaxUndoCount;
2098 return 5;
2099 }
2100
1387 // justincc: I don't believe this hack is needed any longer, especially since the physics 2101 // justincc: I don't believe this hack is needed any longer, especially since the physics
1388 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false 2102 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false
1389 // this method was preventing proper reload of scene objects. 2103 // this method was preventing proper reload of scene objects.
@@ -1405,11 +2119,21 @@ namespace OpenSim.Region.Framework.Scenes
1405 // Setting this SOG's absolute position also loops through and sets the positions 2119 // Setting this SOG's absolute position also loops through and sets the positions
1406 // of the SOP's in this SOG's linkset. This has the side affect of making sure 2120 // of the SOP's in this SOG's linkset. This has the side affect of making sure
1407 // the physics world matches the simulated world. 2121 // the physics world matches the simulated world.
1408 AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? 2122 // AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
1409 2123
1410 // teravus: AbsolutePosition is NOT a normal property! 2124 // teravus: AbsolutePosition is NOT a normal property!
1411 // the code in the getter of AbsolutePosition is significantly different then the code in the setter! 2125 // the code in the getter of AbsolutePosition is significantly different then the code in the setter!
1412 // jhurliman: Then why is it a property instead of two methods? 2126 // jhurliman: Then why is it a property instead of two methods?
2127
2128 // do only what is supposed to do
2129 Vector3 groupPosition = m_rootPart.GroupPosition;
2130 SceneObjectPart[] parts = m_parts.GetArray();
2131
2132 foreach (SceneObjectPart part in parts)
2133 {
2134 if (part != m_rootPart)
2135 part.GroupPosition = groupPosition;
2136 }
1413 } 2137 }
1414 2138
1415 public UUID GetPartsFullID(uint localID) 2139 public UUID GetPartsFullID(uint localID)
@@ -1441,7 +2165,7 @@ namespace OpenSim.Region.Framework.Scenes
1441// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 2165// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1442// remoteClient.Name, part.Name, part.LocalId, offsetPos); 2166// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1443 2167
1444 part.StoreUndoState(); 2168// part.StoreUndoState();
1445 part.OnGrab(offsetPos, remoteClient); 2169 part.OnGrab(offsetPos, remoteClient);
1446 } 2170 }
1447 2171
@@ -1461,28 +2185,43 @@ namespace OpenSim.Region.Framework.Scenes
1461 /// <param name="silent">If true then deletion is not broadcast to clients</param> 2185 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1462 public void DeleteGroupFromScene(bool silent) 2186 public void DeleteGroupFromScene(bool silent)
1463 { 2187 {
2188 // We need to keep track of this state in case this group is still queued for backup.
2189 IsDeleted = true;
2190
2191 DetachFromBackup();
2192
1464 SceneObjectPart[] parts = m_parts.GetArray(); 2193 SceneObjectPart[] parts = m_parts.GetArray();
1465 for (int i = 0; i < parts.Length; i++) 2194 for (int i = 0; i < parts.Length; i++)
1466 { 2195 {
1467 SceneObjectPart part = parts[i]; 2196 SceneObjectPart part = parts[i];
1468 2197
1469 Scene.ForEachScenePresence(sp => 2198 if (Scene != null)
1470 { 2199 {
2200<<<<<<< HEAD
1471 if (!sp.IsChildAgent && sp.ParentID == part.LocalId) 2201 if (!sp.IsChildAgent && sp.ParentID == part.LocalId)
1472 sp.StandUp(); 2202 sp.StandUp();
1473 2203
1474 if (!silent) 2204 if (!silent)
2205=======
2206 Scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
2207>>>>>>> avn/ubitvar
1475 { 2208 {
1476 part.ClearUpdateSchedule(); 2209 if (avatar.ParentID == LocalId)
1477 if (part == m_rootPart) 2210 avatar.StandUp();
2211
2212 if (!silent)
1478 { 2213 {
1479 if (!IsAttachment 2214 part.ClearUpdateSchedule();
1480 || AttachedAvatar == sp.UUID 2215 if (part == m_rootPart)
1481 || !HasPrivateAttachmentPoint) 2216 {
1482 sp.ControllingClient.SendKillObject(new List<uint> { part.LocalId }); 2217 if (!IsAttachment
2218 || AttachedAvatar == avatar.ControllingClient.AgentId
2219 || !HasPrivateAttachmentPoint)
2220 avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
2221 }
1483 } 2222 }
1484 } 2223 });
1485 }); 2224 }
1486 } 2225 }
1487 } 2226 }
1488 2227
@@ -1553,28 +2292,43 @@ namespace OpenSim.Region.Framework.Scenes
1553 /// </summary> 2292 /// </summary>
1554 public void ApplyPhysics() 2293 public void ApplyPhysics()
1555 { 2294 {
1556 // Apply physics to the root prim
1557 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1558
1559 // Apply physics to child prims
1560 SceneObjectPart[] parts = m_parts.GetArray(); 2295 SceneObjectPart[] parts = m_parts.GetArray();
1561 if (parts.Length > 1) 2296 if (parts.Length > 1)
1562 { 2297 {
2298 ResetChildPrimPhysicsPositions();
2299
2300 // Apply physics to the root prim
2301 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
2302
2303
1563 for (int i = 0; i < parts.Length; i++) 2304 for (int i = 0; i < parts.Length; i++)
1564 { 2305 {
1565 SceneObjectPart part = parts[i]; 2306 SceneObjectPart part = parts[i];
1566 if (part.LocalId != m_rootPart.LocalId) 2307 if (part.LocalId != m_rootPart.LocalId)
1567 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 2308 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1568 } 2309 }
1569
1570 // Hack to get the physics scene geometries in the right spot 2310 // Hack to get the physics scene geometries in the right spot
1571 ResetChildPrimPhysicsPositions(); 2311// ResetChildPrimPhysicsPositions();
2312 if (m_rootPart.PhysActor != null)
2313 {
2314 m_rootPart.PhysActor.Building = false;
2315 }
2316 }
2317 else
2318 {
2319 // Apply physics to the root prim
2320 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1572 } 2321 }
1573 } 2322 }
1574 2323
1575 public void SetOwnerId(UUID userId) 2324 public void SetOwnerId(UUID userId)
1576 { 2325 {
1577 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 2326 ForEachPart(delegate(SceneObjectPart part)
2327 {
2328
2329 part.OwnerID = userId;
2330
2331 });
1578 } 2332 }
1579 2333
1580 public void ForEachPart(Action<SceneObjectPart> whatToDo) 2334 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1599,18 +2353,24 @@ namespace OpenSim.Region.Framework.Scenes
1599 return; 2353 return;
1600 } 2354 }
1601 2355
1602 if (IsDeleted || UUID == UUID.Zero) 2356 if (IsDeleted || inTransit || UUID == UUID.Zero)
1603 { 2357 {
1604// m_log.DebugFormat( 2358// m_log.DebugFormat(
1605// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID); 2359// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID);
1606 return; 2360 return;
1607 } 2361 }
1608 2362
2363 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
2364 return;
2365
1609 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 2366 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1610 // any exception propogate upwards. 2367 // any exception propogate upwards.
1611 try 2368 try
1612 { 2369 {
1613 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 2370 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
2371 !m_scene.LoginsEnabled || // We're starting up or doing maintenance, don't mess with things
2372 m_scene.LoadingPrims) // Land may not be valid yet
2373
1614 { 2374 {
1615 ILandObject parcel = m_scene.LandChannel.GetLandObject( 2375 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1616 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 2376 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1637,6 +2397,7 @@ namespace OpenSim.Region.Framework.Scenes
1637 } 2397 }
1638 } 2398 }
1639 } 2399 }
2400
1640 } 2401 }
1641 2402
1642 if (m_scene.UseBackup && HasGroupChanged) 2403 if (m_scene.UseBackup && HasGroupChanged)
@@ -1644,10 +2405,31 @@ namespace OpenSim.Region.Framework.Scenes
1644 // don't backup while it's selected or you're asking for changes mid stream. 2405 // don't backup while it's selected or you're asking for changes mid stream.
1645 if (isTimeToPersist() || forcedBackup) 2406 if (isTimeToPersist() || forcedBackup)
1646 { 2407 {
2408 if (m_rootPart.PhysActor != null &&
2409 (!m_rootPart.PhysActor.IsPhysical))
2410 {
2411 // Possible ghost prim
2412 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
2413 {
2414 foreach (SceneObjectPart part in m_parts.GetArray())
2415 {
2416 // Re-set physics actor positions and
2417 // orientations
2418 part.GroupPosition = m_rootPart.GroupPosition;
2419 }
2420 }
2421 }
1647// m_log.DebugFormat( 2422// m_log.DebugFormat(
1648// "[SCENE]: Storing {0}, {1} in {2}", 2423// "[SCENE]: Storing {0}, {1} in {2}",
1649// Name, UUID, m_scene.RegionInfo.RegionName); 2424// Name, UUID, m_scene.RegionInfo.RegionName);
1650 2425
2426 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2427 {
2428 RootPart.Shape.LastAttachPoint = RootPart.Shape.State;
2429 RootPart.Shape.State = 0;
2430 ScheduleGroupForFullUpdate();
2431 }
2432
1651 SceneObjectGroup backup_group = Copy(false); 2433 SceneObjectGroup backup_group = Copy(false);
1652 backup_group.RootPart.Velocity = RootPart.Velocity; 2434 backup_group.RootPart.Velocity = RootPart.Velocity;
1653 backup_group.RootPart.Acceleration = RootPart.Acceleration; 2435 backup_group.RootPart.Acceleration = RootPart.Acceleration;
@@ -1657,13 +2439,22 @@ namespace OpenSim.Region.Framework.Scenes
1657 GroupContainsForeignPrims = false; 2439 GroupContainsForeignPrims = false;
1658 2440
1659 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); 2441 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
2442
1660 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); 2443 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
1661 2444
1662 backup_group.ForEachPart(delegate(SceneObjectPart part) 2445 backup_group.ForEachPart(delegate(SceneObjectPart part)
1663 { 2446 {
1664 part.Inventory.ProcessInventoryBackup(datastore); 2447 part.Inventory.ProcessInventoryBackup(datastore);
2448
2449 // take the change to delete things
2450 if(part.KeyframeMotion != null)
2451 {
2452 part.KeyframeMotion.Delete();
2453 part.KeyframeMotion = null;
2454 }
1665 }); 2455 });
1666 2456
2457
1667 backup_group = null; 2458 backup_group = null;
1668 } 2459 }
1669// else 2460// else
@@ -1713,6 +2504,7 @@ namespace OpenSim.Region.Framework.Scenes
1713 /// <returns></returns> 2504 /// <returns></returns>
1714 public SceneObjectGroup Copy(bool userExposed) 2505 public SceneObjectGroup Copy(bool userExposed)
1715 { 2506 {
2507<<<<<<< HEAD
1716 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up 2508 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up
1717 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator 2509 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
1718 // but not between regions on different simulators). Really, all copying should be done explicitly. 2510 // but not between regions on different simulators). Really, all copying should be done explicitly.
@@ -1721,18 +2513,32 @@ namespace OpenSim.Region.Framework.Scenes
1721 dupe.Backup = false; 2513 dupe.Backup = false;
1722 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2514 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1723 dupe.m_sittingAvatars = new List<ScenePresence>(); 2515 dupe.m_sittingAvatars = new List<ScenePresence>();
2516=======
2517 m_dupeInProgress = true;
2518 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
2519 dupe.m_isBackedUp = false;
2520 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
2521
2522 dupe.inTransit = inTransit; // this shouldn't be needed TEST
2523
2524 // new group as no sitting avatars
2525 dupe.m_linkedAvatars = new List<ScenePresence>();
2526 dupe.m_sittingAvatars = new List<UUID>();
2527
2528>>>>>>> avn/ubitvar
1724 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 2529 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1725 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 2530 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
2531
1726 2532
1727 if (userExposed) 2533 if (userExposed)
1728 dupe.m_rootPart.TrimPermissions(); 2534 dupe.m_rootPart.TrimPermissions();
1729 2535
1730 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2536 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1731 2537
1732 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2538 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1733 { 2539 {
1734 return p1.LinkNum.CompareTo(p2.LinkNum); 2540 return p1.LinkNum.CompareTo(p2.LinkNum);
1735 } 2541 }
1736 ); 2542 );
1737 2543
1738 foreach (SceneObjectPart part in partList) 2544 foreach (SceneObjectPart part in partList)
@@ -1742,43 +2548,56 @@ namespace OpenSim.Region.Framework.Scenes
1742 { 2548 {
1743 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2549 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1744 newPart.LinkNum = part.LinkNum; 2550 newPart.LinkNum = part.LinkNum;
1745 } 2551// if (userExposed)
2552 newPart.ParentID = dupe.m_rootPart.LocalId;
2553 }
1746 else 2554 else
1747 { 2555 {
1748 newPart = dupe.m_rootPart; 2556 newPart = dupe.m_rootPart;
1749 } 2557 }
2558/*
2559 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2560 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1750 2561
1751 // Need to duplicate the physics actor as well 2562 // Need to duplicate the physics actor as well
1752 PhysicsActor originalPartPa = part.PhysActor; 2563 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1753 if (originalPartPa != null && userExposed)
1754 { 2564 {
1755 PrimitiveBaseShape pbs = newPart.Shape; 2565 PrimitiveBaseShape pbs = newPart.Shape;
1756
1757 newPart.PhysActor 2566 newPart.PhysActor
1758 = m_scene.PhysicsScene.AddPrimShape( 2567 = m_scene.PhysicsScene.AddPrimShape(
1759 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2568 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1760 pbs, 2569 pbs,
1761 newPart.AbsolutePosition, 2570 newPart.AbsolutePosition,
1762 newPart.Scale, 2571 newPart.Scale,
1763 newPart.RotationOffset, 2572 newPart.GetWorldRotation(),
1764 originalPartPa.IsPhysical, 2573 isphys,
2574 isphan,
1765 newPart.LocalId); 2575 newPart.LocalId);
1766 2576
1767 newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); 2577 newPart.DoPhysicsPropertyUpdate(isphys, true);
1768 } 2578 */
2579 if (userExposed)
2580 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2581// }
2582 // copy keyframemotion
1769 if (part.KeyframeMotion != null) 2583 if (part.KeyframeMotion != null)
1770 newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe); 2584 newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe);
1771 } 2585 }
1772 2586
1773 if (userExposed) 2587 if (userExposed)
1774 { 2588 {
1775 dupe.UpdateParentIDs(); 2589// done above dupe.UpdateParentIDs();
2590
2591 if (dupe.m_rootPart.PhysActor != null)
2592 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2593
1776 dupe.HasGroupChanged = true; 2594 dupe.HasGroupChanged = true;
1777 dupe.AttachToBackup(); 2595 dupe.AttachToBackup();
1778 2596
1779 ScheduleGroupForFullUpdate(); 2597 ScheduleGroupForFullUpdate();
1780 } 2598 }
1781 2599
2600 m_dupeInProgress = false;
1782 return dupe; 2601 return dupe;
1783 } 2602 }
1784 2603
@@ -1790,7 +2609,13 @@ namespace OpenSim.Region.Framework.Scenes
1790 /// <param name="cGroupID"></param> 2609 /// <param name="cGroupID"></param>
1791 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2610 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1792 { 2611 {
1793 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2612 SceneObjectPart newpart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed);
2613// SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2614// newpart.LocalId = m_scene.AllocateLocalId();
2615
2616 SetRootPart(newpart);
2617 if (userExposed)
2618 RootPart.Velocity = Vector3.Zero; // In case source is moving
1794 } 2619 }
1795 2620
1796 public void ScriptSetPhysicsStatus(bool usePhysics) 2621 public void ScriptSetPhysicsStatus(bool usePhysics)
@@ -1848,13 +2673,14 @@ namespace OpenSim.Region.Framework.Scenes
1848 2673
1849 if (pa != null) 2674 if (pa != null)
1850 { 2675 {
1851 pa.AddForce(impulse, true); 2676 // false to be applied as a impulse
2677 pa.AddForce(impulse, false);
1852 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2678 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1853 } 2679 }
1854 } 2680 }
1855 } 2681 }
1856 2682
1857 public void applyAngularImpulse(Vector3 impulse) 2683 public void ApplyAngularImpulse(Vector3 impulse)
1858 { 2684 {
1859 PhysicsActor pa = RootPart.PhysActor; 2685 PhysicsActor pa = RootPart.PhysActor;
1860 2686
@@ -1862,21 +2688,8 @@ namespace OpenSim.Region.Framework.Scenes
1862 { 2688 {
1863 if (!IsAttachment) 2689 if (!IsAttachment)
1864 { 2690 {
1865 pa.AddAngularForce(impulse, true); 2691 // false to be applied as a impulse
1866 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2692 pa.AddAngularForce(impulse, false);
1867 }
1868 }
1869 }
1870
1871 public void setAngularImpulse(Vector3 impulse)
1872 {
1873 PhysicsActor pa = RootPart.PhysActor;
1874
1875 if (pa != null)
1876 {
1877 if (!IsAttachment)
1878 {
1879 pa.Torque = impulse;
1880 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2693 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1881 } 2694 }
1882 } 2695 }
@@ -1884,21 +2697,15 @@ namespace OpenSim.Region.Framework.Scenes
1884 2697
1885 public Vector3 GetTorque() 2698 public Vector3 GetTorque()
1886 { 2699 {
1887 PhysicsActor pa = RootPart.PhysActor; 2700 return RootPart.Torque;
1888
1889 if (pa != null)
1890 {
1891 if (!IsAttachment)
1892 {
1893 Vector3 torque = pa.Torque;
1894 return torque;
1895 }
1896 }
1897
1898 return Vector3.Zero;
1899 } 2701 }
1900 2702
2703<<<<<<< HEAD
1901 public void MoveToTarget(Vector3 target, float tau) 2704 public void MoveToTarget(Vector3 target, float tau)
2705=======
2706 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
2707 public void moveToTarget(Vector3 target, float tau)
2708>>>>>>> avn/ubitvar
1902 { 2709 {
1903 if (IsAttachment) 2710 if (IsAttachment)
1904 { 2711 {
@@ -1925,6 +2732,7 @@ namespace OpenSim.Region.Framework.Scenes
1925 if (IsAttachment) 2732 if (IsAttachment)
1926 { 2733 {
1927 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 2734 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
2735<<<<<<< HEAD
1928 2736
1929 if (avatar != null) 2737 if (avatar != null)
1930 avatar.ResetMoveToTarget(); 2738 avatar.ResetMoveToTarget();
@@ -1938,10 +2746,64 @@ namespace OpenSim.Region.Framework.Scenes
1938 pa.PIDActive = false; 2746 pa.PIDActive = false;
1939 2747
1940 ScheduleGroupForTerseUpdate(); 2748 ScheduleGroupForTerseUpdate();
2749=======
2750 if (avatar != null)
2751 {
2752 avatar.ResetMoveToTarget();
2753 }
2754 }
2755 else
2756 {
2757 PhysicsActor pa = RootPart.PhysActor;
2758
2759 if (pa != null)
2760 pa.PIDActive = false;
2761
2762 RootPart.ScheduleTerseUpdate(); // send a stop information
2763 }
2764 }
2765
2766 public void rotLookAt(Quaternion target, float strength, float damping)
2767 {
2768 SceneObjectPart rootpart = m_rootPart;
2769 if (rootpart != null)
2770 {
2771 if (IsAttachment)
2772 {
2773 /*
2774 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2775 if (avatar != null)
2776 {
2777 Rotate the Av?
2778 } */
2779 }
2780 else
2781 {
2782 if (rootpart.PhysActor != null)
2783 { // APID must be implemented in your physics system for this to function.
2784 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2785 rootpart.PhysActor.APIDStrength = strength;
2786 rootpart.PhysActor.APIDDamping = damping;
2787 rootpart.PhysActor.APIDActive = true;
2788 }
2789>>>>>>> avn/ubitvar
1941 } 2790 }
1942 } 2791 }
1943 } 2792 }
2793
2794 public void stopLookAt()
2795 {
2796 SceneObjectPart rootpart = m_rootPart;
2797 if (rootpart != null)
2798 {
2799 if (rootpart.PhysActor != null)
2800 { // APID must be implemented in your physics system for this to function.
2801 rootpart.PhysActor.APIDActive = false;
2802 }
2803 }
1944 2804
2805 }
2806
1945 /// <summary> 2807 /// <summary>
1946 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2808 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1947 /// </summary> 2809 /// </summary>
@@ -1958,7 +2820,7 @@ namespace OpenSim.Region.Framework.Scenes
1958 { 2820 {
1959 pa.PIDHoverHeight = height; 2821 pa.PIDHoverHeight = height;
1960 pa.PIDHoverType = hoverType; 2822 pa.PIDHoverType = hoverType;
1961 pa.PIDTau = tau; 2823 pa.PIDHoverTau = tau;
1962 pa.PIDHoverActive = true; 2824 pa.PIDHoverActive = true;
1963 } 2825 }
1964 else 2826 else
@@ -1999,6 +2861,9 @@ namespace OpenSim.Region.Framework.Scenes
1999 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2861 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
2000 { 2862 {
2001 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2863 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2864// SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2865// newPart.LocalId = m_scene.AllocateLocalId();
2866
2002 AddPart(newPart); 2867 AddPart(newPart);
2003 2868
2004 SetPartAsNonRoot(newPart); 2869 SetPartAsNonRoot(newPart);
@@ -2048,6 +2913,7 @@ namespace OpenSim.Region.Framework.Scenes
2048 2913
2049 #endregion 2914 #endregion
2050 2915
2916
2051 public override void Update() 2917 public override void Update()
2052 { 2918 {
2053 // Check that the group was not deleted before the scheduled update 2919 // Check that the group was not deleted before the scheduled update
@@ -2055,7 +2921,7 @@ namespace OpenSim.Region.Framework.Scenes
2055 // an object has been deleted from a scene before update was processed. 2921 // an object has been deleted from a scene before update was processed.
2056 // A more fundamental overhaul of the update mechanism is required to eliminate all 2922 // A more fundamental overhaul of the update mechanism is required to eliminate all
2057 // the race conditions. 2923 // the race conditions.
2058 if (IsDeleted) 2924 if (IsDeleted || inTransit)
2059 return; 2925 return;
2060 2926
2061 // Even temporary objects take part in physics (e.g. temp-on-rez bullets) 2927 // Even temporary objects take part in physics (e.g. temp-on-rez bullets)
@@ -2066,18 +2932,17 @@ namespace OpenSim.Region.Framework.Scenes
2066 // check to see if the physical position or rotation warrant an update. 2932 // check to see if the physical position or rotation warrant an update.
2067 if (m_rootPart.UpdateFlag == UpdateRequired.NONE) 2933 if (m_rootPart.UpdateFlag == UpdateRequired.NONE)
2068 { 2934 {
2069 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2935 // rootpart SendScheduledUpdates will check if a update is needed
2070 2936 m_rootPart.UpdateFlag = UpdateRequired.TERSE;
2071 if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) 2937 }
2072 {
2073 m_rootPart.UpdateFlag = UpdateRequired.TERSE;
2074 lastPhysGroupPos = AbsolutePosition;
2075 }
2076 2938
2077 if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) 2939 if (IsAttachment)
2940 {
2941 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2942 if (sp != null)
2078 { 2943 {
2079 m_rootPart.UpdateFlag = UpdateRequired.TERSE; 2944 sp.SendAttachmentScheduleUpdate(this);
2080 lastPhysGroupRot = GroupRotation; 2945 return;
2081 } 2946 }
2082 } 2947 }
2083 2948
@@ -2137,20 +3002,30 @@ namespace OpenSim.Region.Framework.Scenes
2137 /// Immediately send a full update for this scene object. 3002 /// Immediately send a full update for this scene object.
2138 /// </summary> 3003 /// </summary>
2139 public void SendGroupFullUpdate() 3004 public void SendGroupFullUpdate()
2140 { 3005 {
2141 if (IsDeleted) 3006 if (IsDeleted)
2142 return; 3007 return;
2143 3008
2144// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 3009// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2145 3010
2146 RootPart.SendFullUpdateToAllClients(); 3011 if (IsAttachment)
3012 {
3013 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
3014 if (sp != null)
3015 {
3016 sp.SendAttachmentUpdate(this,UpdateRequired.FULL);
3017 return;
3018 }
3019 }
3020
3021 RootPart.SendFullUpdateToAllClientsInternal();
2147 3022
2148 SceneObjectPart[] parts = m_parts.GetArray(); 3023 SceneObjectPart[] parts = m_parts.GetArray();
2149 for (int i = 0; i < parts.Length; i++) 3024 for (int i = 0; i < parts.Length; i++)
2150 { 3025 {
2151 SceneObjectPart part = parts[i]; 3026 SceneObjectPart part = parts[i];
2152 if (part != RootPart) 3027 if (part != RootPart)
2153 part.SendFullUpdateToAllClients(); 3028 part.SendFullUpdateToAllClientsInternal();
2154 } 3029 }
2155 } 3030 }
2156 3031
@@ -2162,7 +3037,7 @@ namespace OpenSim.Region.Framework.Scenes
2162 /// </summary> 3037 /// </summary>
2163 public void SendGroupRootTerseUpdate() 3038 public void SendGroupRootTerseUpdate()
2164 { 3039 {
2165 if (IsDeleted) 3040 if (IsDeleted || inTransit)
2166 return; 3041 return;
2167 3042
2168 RootPart.SendTerseUpdateToAllClients(); 3043 RootPart.SendTerseUpdateToAllClients();
@@ -2181,12 +3056,22 @@ namespace OpenSim.Region.Framework.Scenes
2181 /// </summary> 3056 /// </summary>
2182 public void SendGroupTerseUpdate() 3057 public void SendGroupTerseUpdate()
2183 { 3058 {
2184 if (IsDeleted) 3059 if (IsDeleted || inTransit)
2185 return; 3060 return;
2186 3061
3062 if (IsAttachment)
3063 {
3064 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
3065 if (sp != null)
3066 {
3067 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
3068 return;
3069 }
3070 }
3071
2187 SceneObjectPart[] parts = m_parts.GetArray(); 3072 SceneObjectPart[] parts = m_parts.GetArray();
2188 for (int i = 0; i < parts.Length; i++) 3073 for (int i = 0; i < parts.Length; i++)
2189 parts[i].SendTerseUpdateToAllClients(); 3074 parts[i].SendTerseUpdateToAllClientsInternal();
2190 } 3075 }
2191 3076
2192 /// <summary> 3077 /// <summary>
@@ -2294,9 +3179,41 @@ namespace OpenSim.Region.Framework.Scenes
2294 return; 3179 return;
2295 } 3180 }
2296 3181
3182 // physical prims count limit
3183 // not very eficient :(
3184
3185 if (UsesPhysics && m_scene.m_linksetPhysCapacity > 0 && (PrimCount + objectGroup.PrimCount) >
3186 m_scene.m_linksetPhysCapacity)
3187 {
3188 int cntr = 0;
3189 foreach (SceneObjectPart part in Parts)
3190 {
3191 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
3192 cntr++;
3193 }
3194 foreach (SceneObjectPart part in objectGroup.Parts)
3195 {
3196 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
3197 cntr++;
3198 }
3199
3200 if (cntr > m_scene.m_linksetPhysCapacity)
3201 {
3202 // cancel physics
3203 RootPart.Flags &= ~PrimFlags.Physics;
3204 ApplyPhysics();
3205 }
3206 }
3207
3208
2297 // 'linkPart' == the root of the group being linked into this group 3209 // 'linkPart' == the root of the group being linked into this group
2298 SceneObjectPart linkPart = objectGroup.m_rootPart; 3210 SceneObjectPart linkPart = objectGroup.m_rootPart;
2299 3211
3212 if (m_rootPart.PhysActor != null)
3213 m_rootPart.PhysActor.Building = true;
3214 if (linkPart.PhysActor != null)
3215 linkPart.PhysActor.Building = true;
3216
2300 // physics flags from group to be applied to linked parts 3217 // physics flags from group to be applied to linked parts
2301 bool grpusephys = UsesPhysics; 3218 bool grpusephys = UsesPhysics;
2302 bool grptemporary = IsTemporary; 3219 bool grptemporary = IsTemporary;
@@ -2313,22 +3230,24 @@ namespace OpenSim.Region.Framework.Scenes
2313 // First move the new group's root SOP's position to be relative to ours 3230 // First move the new group's root SOP's position to be relative to ours
2314 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not, 3231 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not,
2315 // this code can be reordered to have a more logical flow.) 3232 // this code can be reordered to have a more logical flow.)
2316 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; 3233 linkPart.setOffsetPosition(linkPart.GroupPosition - AbsolutePosition);
2317 // Assign the new parent to the root of the old group 3234 // Assign the new parent to the root of the old group
2318 linkPart.ParentID = m_rootPart.LocalId; 3235 linkPart.ParentID = m_rootPart.LocalId;
2319 // Now that it's a child, it's group position is our root position 3236 // Now that it's a child, it's group position is our root position
2320 linkPart.GroupPosition = AbsolutePosition; 3237 linkPart.setGroupPosition(AbsolutePosition);
2321 3238
2322 Vector3 axPos = linkPart.OffsetPosition;
2323 // Rotate the linking root SOP's position to be relative to the new root prim 3239 // Rotate the linking root SOP's position to be relative to the new root prim
2324 Quaternion parentRot = m_rootPart.RotationOffset; 3240 Quaternion parentRot = m_rootPart.RotationOffset;
2325 axPos *= Quaternion.Inverse(parentRot);
2326 linkPart.OffsetPosition = axPos;
2327 3241
2328 // Make the linking root SOP's rotation relative to the new root prim 3242 // Make the linking root SOP's rotation relative to the new root prim
2329 Quaternion oldRot = linkPart.RotationOffset; 3243 Quaternion oldRot = linkPart.RotationOffset;
2330 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3244 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot;
2331 linkPart.RotationOffset = newRot; 3245 linkPart.setRotationOffset(newRot);
3246
3247 Vector3 axPos = linkPart.OffsetPosition;
3248 axPos *= Quaternion.Conjugate(parentRot);
3249 linkPart.OffsetPosition = axPos;
3250
2332 3251
2333 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. 3252 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset.
2334 // Now that we know this SOG has at least two SOPs in it, the new root 3253 // Now that we know this SOG has at least two SOPs in it, the new root
@@ -2358,10 +3277,12 @@ namespace OpenSim.Region.Framework.Scenes
2358 m_parts.Add(linkPart.UUID, linkPart); 3277 m_parts.Add(linkPart.UUID, linkPart);
2359 3278
2360 linkPart.SetParent(this); 3279 linkPart.SetParent(this);
3280 m_scene.updateScenePartGroup(linkPart, this);
3281
2361 linkPart.CreateSelected = true; 3282 linkPart.CreateSelected = true;
2362 3283
2363 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now 3284 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2364 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive); 3285 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2365 3286
2366 // If the added SOP is physical, also tell the physics engine about the link relationship. 3287 // If the added SOP is physical, also tell the physics engine about the link relationship.
2367 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 3288 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
@@ -2371,6 +3292,7 @@ namespace OpenSim.Region.Framework.Scenes
2371 } 3292 }
2372 3293
2373 linkPart.LinkNum = linkNum++; 3294 linkPart.LinkNum = linkNum++;
3295 linkPart.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2374 3296
2375 // Get a list of the SOP's in the old group in order of their linknum's. 3297 // Get a list of the SOP's in the old group in order of their linknum's.
2376 SceneObjectPart[] ogParts = objectGroup.Parts; 3298 SceneObjectPart[] ogParts = objectGroup.Parts;
@@ -2389,7 +3311,7 @@ namespace OpenSim.Region.Framework.Scenes
2389 3311
2390 // Update the physics flags for the newly added SOP 3312 // Update the physics flags for the newly added SOP
2391 // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??) 3313 // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??)
2392 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive); 3314 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2393 3315
2394 // If the added SOP is physical, also tell the physics engine about the link relationship. 3316 // If the added SOP is physical, also tell the physics engine about the link relationship.
2395 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 3317 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
@@ -2407,7 +3329,7 @@ namespace OpenSim.Region.Framework.Scenes
2407 objectGroup.IsDeleted = true; 3329 objectGroup.IsDeleted = true;
2408 3330
2409 objectGroup.m_parts.Clear(); 3331 objectGroup.m_parts.Clear();
2410 3332
2411 // Can't do this yet since backup still makes use of the root part without any synchronization 3333 // Can't do this yet since backup still makes use of the root part without any synchronization
2412// objectGroup.m_rootPart = null; 3334// objectGroup.m_rootPart = null;
2413 3335
@@ -2423,6 +3345,9 @@ namespace OpenSim.Region.Framework.Scenes
2423 // unmoved prims! 3345 // unmoved prims!
2424 ResetChildPrimPhysicsPositions(); 3346 ResetChildPrimPhysicsPositions();
2425 3347
3348 if (m_rootPart.PhysActor != null)
3349 m_rootPart.PhysActor.Building = false;
3350
2426 //HasGroupChanged = true; 3351 //HasGroupChanged = true;
2427 //ScheduleGroupForFullUpdate(); 3352 //ScheduleGroupForFullUpdate();
2428 } 3353 }
@@ -2490,7 +3415,10 @@ namespace OpenSim.Region.Framework.Scenes
2490// m_log.DebugFormat( 3415// m_log.DebugFormat(
2491// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 3416// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2492// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 3417// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2493 3418
3419 if (m_rootPart.PhysActor != null)
3420 m_rootPart.PhysActor.Building = true;
3421
2494 linkPart.ClearUndoState(); 3422 linkPart.ClearUndoState();
2495 3423
2496 Vector3 worldPos = linkPart.GetWorldPosition(); 3424 Vector3 worldPos = linkPart.GetWorldPosition();
@@ -2545,20 +3473,18 @@ namespace OpenSim.Region.Framework.Scenes
2545 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; 3473 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
2546 linkPart.OffsetPosition = new Vector3(0, 0, 0); 3474 linkPart.OffsetPosition = new Vector3(0, 0, 0);
2547 */ 3475 */
2548 linkPart.GroupPosition = worldPos; 3476 linkPart.setGroupPosition(worldPos);
2549 linkPart.OffsetPosition = Vector3.Zero; 3477 linkPart.setOffsetPosition(Vector3.Zero);
2550 linkPart.RotationOffset = worldRot; 3478 linkPart.setRotationOffset(worldRot);
2551 3479
2552 // Create a new SOG to go around this unlinked and unattached SOP 3480 // Create a new SOG to go around this unlinked and unattached SOP
2553 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); 3481 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
2554 3482
2555 m_scene.AddNewSceneObject(objectGroup, true); 3483 m_scene.AddNewSceneObject(objectGroup, true);
2556 3484
2557 if (sendEvents)
2558 linkPart.TriggerScriptChangedEvent(Changed.LINK);
2559
2560 linkPart.Rezzed = RootPart.Rezzed; 3485 linkPart.Rezzed = RootPart.Rezzed;
2561 3486
3487<<<<<<< HEAD
2562 // We must persist the delinked group to the database immediately, for safety. The problem 3488 // We must persist the delinked group to the database immediately, for safety. The problem
2563 // is that although in memory the new group has a new SceneGroupID, in the database it 3489 // is that although in memory the new group has a new SceneGroupID, in the database it
2564 // still has the parent group's SceneGroupID (until the next backup). This means that if the 3490 // still has the parent group's SceneGroupID (until the next backup). This means that if the
@@ -2569,6 +3495,22 @@ namespace OpenSim.Region.Framework.Scenes
2569 // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case 3495 // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case
2570 // because the delinked group doesn't know when the source group is deleted.) 3496 // because the delinked group doesn't know when the source group is deleted.)
2571 m_scene.ForceSceneObjectBackup(objectGroup); 3497 m_scene.ForceSceneObjectBackup(objectGroup);
3498=======
3499 // When we delete a group, we currently have to force persist to the database if the object id has changed
3500 // (since delete works by deleting all rows which have a given object id)
3501
3502 // this is as it seems to be in sl now
3503 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
3504 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
3505
3506 if (m_rootPart.PhysActor != null)
3507 m_rootPart.PhysActor.Building = false;
3508
3509 objectGroup.HasGroupChangedDueToDelink = true;
3510>>>>>>> avn/ubitvar
3511
3512 if (sendEvents)
3513 linkPart.TriggerScriptChangedEvent(Changed.LINK);
2572 3514
2573 return objectGroup; 3515 return objectGroup;
2574 } 3516 }
@@ -2579,7 +3521,13 @@ namespace OpenSim.Region.Framework.Scenes
2579 /// <param name="objectGroup"></param> 3521 /// <param name="objectGroup"></param>
2580 public virtual void DetachFromBackup() 3522 public virtual void DetachFromBackup()
2581 { 3523 {
3524<<<<<<< HEAD
2582 if (Backup && Scene != null) 3525 if (Backup && Scene != null)
3526=======
3527 if (m_scene != null)
3528 m_scene.SceneGraph.FireDetachFromBackup(this);
3529 if (m_isBackedUp && Scene != null)
3530>>>>>>> avn/ubitvar
2583 m_scene.EventManager.OnBackup -= ProcessBackup; 3531 m_scene.EventManager.OnBackup -= ProcessBackup;
2584 3532
2585 Backup = false; 3533 Backup = false;
@@ -2595,14 +3543,14 @@ namespace OpenSim.Region.Framework.Scenes
2595 Quaternion parentRot = oldGroupRotation; 3543 Quaternion parentRot = oldGroupRotation;
2596 Quaternion oldRot = part.RotationOffset; 3544 Quaternion oldRot = part.RotationOffset;
2597 3545
2598 // Move our position to not be relative to the old parent 3546 // Move our position in world
2599 Vector3 axPos = part.OffsetPosition; 3547 Vector3 axPos = part.OffsetPosition;
2600 axPos *= parentRot; 3548 axPos *= parentRot;
2601 part.OffsetPosition = axPos; 3549 Vector3 newPos = oldGroupPosition + axPos;
2602 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 3550 part.setGroupPosition(newPos);
2603 part.OffsetPosition = Vector3.Zero; 3551 part.setOffsetPosition(Vector3.Zero);
2604 3552
2605 // Compution our rotation to be not relative to the old parent 3553 // Compution our rotation in world
2606 Quaternion worldRot = parentRot * oldRot; 3554 Quaternion worldRot = parentRot * oldRot;
2607 part.RotationOffset = worldRot; 3555 part.RotationOffset = worldRot;
2608 3556
@@ -2613,29 +3561,32 @@ namespace OpenSim.Region.Framework.Scenes
2613 3561
2614 part.LinkNum = linkNum; 3562 part.LinkNum = linkNum;
2615 3563
3564 m_scene.updateScenePartGroup(part, this);
3565
2616 // Compute the new position of this SOP relative to the group position 3566 // Compute the new position of this SOP relative to the group position
2617 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 3567 part.setOffsetPosition(newPos - AbsolutePosition);
2618 3568
2619 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. 3569 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times.
2620 // It would have the affect of setting the physics engine position multiple 3570 // It would have the affect of setting the physics engine position multiple
2621 // times. In theory, that is not necessary but I don't have a good linkset 3571 // times. In theory, that is not necessary but I don't have a good linkset
2622 // test to know that cleaning up this code wouldn't break things.) 3572 // test to know that cleaning up this code wouldn't break things.)
2623 3573
2624 // Rotate the relative position by the rotation of the group
2625 Quaternion rootRotation = m_rootPart.RotationOffset;
2626 Vector3 pos = part.OffsetPosition;
2627 pos *= Quaternion.Inverse(rootRotation);
2628 part.OffsetPosition = pos;
2629
2630 // Compute the SOP's rotation relative to the rotation of the group. 3574 // Compute the SOP's rotation relative to the rotation of the group.
2631 parentRot = m_rootPart.RotationOffset; 3575 parentRot = m_rootPart.RotationOffset;
3576
2632 oldRot = part.RotationOffset; 3577 oldRot = part.RotationOffset;
2633 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3578 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot;
2634 part.RotationOffset = newRot; 3579 part.setRotationOffset(newRot);
3580
3581 Vector3 pos = part.OffsetPosition;
3582 pos *= Quaternion.Conjugate(parentRot);
3583
3584 part.OffsetPosition = pos; // update position and orientation on physics also
2635 3585
2636 // Since this SOP's state has changed, push those changes into the physics engine 3586 // Since this SOP's state has changed, push those changes into the physics engine
2637 // and the simulator. 3587 // and the simulator.
2638 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3588 // done on caller
3589// part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2639 } 3590 }
2640 3591
2641 /// <summary> 3592 /// <summary>
@@ -2663,10 +3614,14 @@ namespace OpenSim.Region.Framework.Scenes
2663 { 3614 {
2664 if (!BlockGrabOverride && !part.BlockGrab) 3615 if (!BlockGrabOverride && !part.BlockGrab)
2665 { 3616 {
2666 Vector3 llmoveforce = pos - AbsolutePosition; 3617/* Vector3 llmoveforce = pos - AbsolutePosition;
2667 Vector3 grabforce = llmoveforce; 3618 Vector3 grabforce = llmoveforce;
2668 grabforce = (grabforce / 10) * pa.Mass; 3619 grabforce = (grabforce / 10) * pa.Mass;
2669 pa.AddForce(grabforce, true); 3620 */
3621 // empirically convert distance diference to a impulse
3622 Vector3 grabforce = pos - AbsolutePosition;
3623 grabforce = grabforce * (pa.Mass/ 10.0f);
3624 pa.AddForce(grabforce, false);
2670 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 3625 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
2671 } 3626 }
2672 } 3627 }
@@ -2880,6 +3835,8 @@ namespace OpenSim.Region.Framework.Scenes
2880 /// <param name="SetVolumeDetect"></param> 3835 /// <param name="SetVolumeDetect"></param>
2881 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) 3836 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect)
2882 { 3837 {
3838 HasGroupChanged = true;
3839
2883 SceneObjectPart selectionPart = GetPart(localID); 3840 SceneObjectPart selectionPart = GetPart(localID);
2884 3841
2885 if (Scene != null) 3842 if (Scene != null)
@@ -2905,8 +3862,12 @@ namespace OpenSim.Region.Framework.Scenes
2905 { 3862 {
2906 SceneObjectPart[] parts = m_parts.GetArray(); 3863 SceneObjectPart[] parts = m_parts.GetArray();
2907 3864
2908 if (Scene != null) 3865 if (Scene != null && UsePhysics)
2909 { 3866 {
3867 int maxprims = m_scene.m_linksetPhysCapacity;
3868 bool checkShape = (maxprims > 0 &&
3869 parts.Length > maxprims);
3870
2910 for (int i = 0; i < parts.Length; i++) 3871 for (int i = 0; i < parts.Length; i++)
2911 { 3872 {
2912 SceneObjectPart part = parts[i]; 3873 SceneObjectPart part = parts[i];
@@ -2917,11 +3878,34 @@ namespace OpenSim.Region.Framework.Scenes
2917 UsePhysics = false; // Reset physics 3878 UsePhysics = false; // Reset physics
2918 break; 3879 break;
2919 } 3880 }
3881
3882 if (checkShape && part.PhysicsShapeType != (byte)PhysicsShapeType.None)
3883 {
3884 if (--maxprims < 0)
3885 {
3886 UsePhysics = false;
3887 break;
3888 }
3889 }
2920 } 3890 }
2921 } 3891 }
2922 3892
2923 for (int i = 0; i < parts.Length; i++) 3893 if (parts.Length > 1)
2924 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3894 {
3895 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3896
3897 for (int i = 0; i < parts.Length; i++)
3898 {
3899
3900 if (parts[i].UUID != m_rootPart.UUID)
3901 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3902 }
3903
3904 if (m_rootPart.PhysActor != null)
3905 m_rootPart.PhysActor.Building = false;
3906 }
3907 else
3908 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
2925 } 3909 }
2926 } 3910 }
2927 3911
@@ -2934,6 +3918,17 @@ namespace OpenSim.Region.Framework.Scenes
2934 } 3918 }
2935 } 3919 }
2936 3920
3921
3922
3923 /// <summary>
3924 /// Gets the number of parts
3925 /// </summary>
3926 /// <returns></returns>
3927 public int GetPartCount()
3928 {
3929 return Parts.Count();
3930 }
3931
2937 /// <summary> 3932 /// <summary>
2938 /// Update the texture entry for this part 3933 /// Update the texture entry for this part
2939 /// </summary> 3934 /// </summary>
@@ -2978,7 +3973,27 @@ namespace OpenSim.Region.Framework.Scenes
2978 { 3973 {
2979 RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF); 3974 RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
2980 3975
3976<<<<<<< HEAD
2981 AdjustChildPrimPermissions(Scene.Permissions.IsGod(AgentID)); 3977 AdjustChildPrimPermissions(Scene.Permissions.IsGod(AgentID));
3978=======
3979 bool god = Scene.Permissions.IsGod(AgentID);
3980
3981 if (field == 1 && god)
3982 {
3983 ForEachPart(part =>
3984 {
3985 part.BaseMask = RootPart.BaseMask;
3986 });
3987 }
3988
3989 AdjustChildPrimPermissions();
3990>>>>>>> avn/ubitvar
3991
3992 if (field == 1 && god) // Base mask was set. Update all child part inventories
3993 {
3994 foreach (SceneObjectPart part in Parts)
3995 part.Inventory.ApplyGodPermissions(RootPart.BaseMask);
3996 }
2982 3997
2983 HasGroupChanged = true; 3998 HasGroupChanged = true;
2984 3999
@@ -3025,8 +4040,6 @@ namespace OpenSim.Region.Framework.Scenes
3025 4040
3026 PhysicsActor pa = m_rootPart.PhysActor; 4041 PhysicsActor pa = m_rootPart.PhysActor;
3027 4042
3028 RootPart.StoreUndoState(true);
3029
3030 if (Scene != null) 4043 if (Scene != null)
3031 { 4044 {
3032 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); 4045 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X));
@@ -3054,7 +4067,6 @@ namespace OpenSim.Region.Framework.Scenes
3054 SceneObjectPart obPart = parts[i]; 4067 SceneObjectPart obPart = parts[i];
3055 if (obPart.UUID != m_rootPart.UUID) 4068 if (obPart.UUID != m_rootPart.UUID)
3056 { 4069 {
3057// obPart.IgnoreUndoUpdate = true;
3058 Vector3 oldSize = new Vector3(obPart.Scale); 4070 Vector3 oldSize = new Vector3(obPart.Scale);
3059 4071
3060 float f = 1.0f; 4072 float f = 1.0f;
@@ -3166,8 +4178,6 @@ namespace OpenSim.Region.Framework.Scenes
3166 z *= a; 4178 z *= a;
3167 } 4179 }
3168 } 4180 }
3169
3170// obPart.IgnoreUndoUpdate = false;
3171 } 4181 }
3172 } 4182 }
3173 } 4183 }
@@ -3177,9 +4187,7 @@ namespace OpenSim.Region.Framework.Scenes
3177 prevScale.Y *= y; 4187 prevScale.Y *= y;
3178 prevScale.Z *= z; 4188 prevScale.Z *= z;
3179 4189
3180// RootPart.IgnoreUndoUpdate = true;
3181 RootPart.Resize(prevScale); 4190 RootPart.Resize(prevScale);
3182// RootPart.IgnoreUndoUpdate = false;
3183 4191
3184 for (int i = 0; i < parts.Length; i++) 4192 for (int i = 0; i < parts.Length; i++)
3185 { 4193 {
@@ -3187,8 +4195,6 @@ namespace OpenSim.Region.Framework.Scenes
3187 4195
3188 if (obPart.UUID != m_rootPart.UUID) 4196 if (obPart.UUID != m_rootPart.UUID)
3189 { 4197 {
3190 obPart.IgnoreUndoUpdate = true;
3191
3192 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 4198 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
3193 currentpos.X *= x; 4199 currentpos.X *= x;
3194 currentpos.Y *= y; 4200 currentpos.Y *= y;
@@ -3201,16 +4207,12 @@ namespace OpenSim.Region.Framework.Scenes
3201 4207
3202 obPart.Resize(newSize); 4208 obPart.Resize(newSize);
3203 obPart.UpdateOffSet(currentpos); 4209 obPart.UpdateOffSet(currentpos);
3204
3205 obPart.IgnoreUndoUpdate = false;
3206 } 4210 }
3207 4211
3208// obPart.IgnoreUndoUpdate = false; 4212 HasGroupChanged = true;
3209// obPart.StoreUndoState(); 4213 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
4214 ScheduleGroupForTerseUpdate();
3210 } 4215 }
3211
3212// m_log.DebugFormat(
3213// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
3214 } 4216 }
3215 4217
3216 #endregion 4218 #endregion
@@ -3223,14 +4225,6 @@ namespace OpenSim.Region.Framework.Scenes
3223 /// <param name="pos"></param> 4225 /// <param name="pos"></param>
3224 public void UpdateGroupPosition(Vector3 pos) 4226 public void UpdateGroupPosition(Vector3 pos)
3225 { 4227 {
3226// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
3227
3228 RootPart.StoreUndoState(true);
3229
3230// SceneObjectPart[] parts = m_parts.GetArray();
3231// for (int i = 0; i < parts.Length; i++)
3232// parts[i].StoreUndoState();
3233
3234 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 4228 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
3235 { 4229 {
3236 if (IsAttachment) 4230 if (IsAttachment)
@@ -3263,21 +4257,17 @@ namespace OpenSim.Region.Framework.Scenes
3263 /// </summary> 4257 /// </summary>
3264 /// <param name="pos"></param> 4258 /// <param name="pos"></param>
3265 /// <param name="localID"></param> 4259 /// <param name="localID"></param>
4260 ///
4261
3266 public void UpdateSinglePosition(Vector3 pos, uint localID) 4262 public void UpdateSinglePosition(Vector3 pos, uint localID)
3267 { 4263 {
3268 SceneObjectPart part = GetPart(localID); 4264 SceneObjectPart part = GetPart(localID);
3269 4265
3270// SceneObjectPart[] parts = m_parts.GetArray();
3271// for (int i = 0; i < parts.Length; i++)
3272// parts[i].StoreUndoState();
3273
3274 if (part != null) 4266 if (part != null)
3275 { 4267 {
3276// m_log.DebugFormat( 4268// unlock parts position change
3277// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 4269 if (m_rootPart.PhysActor != null)
3278 4270 m_rootPart.PhysActor.Building = true;
3279 part.StoreUndoState(false);
3280 part.IgnoreUndoUpdate = true;
3281 4271
3282 if (part.UUID == m_rootPart.UUID) 4272 if (part.UUID == m_rootPart.UUID)
3283 { 4273 {
@@ -3288,8 +4278,10 @@ namespace OpenSim.Region.Framework.Scenes
3288 part.UpdateOffSet(pos); 4278 part.UpdateOffSet(pos);
3289 } 4279 }
3290 4280
4281 if (m_rootPart.PhysActor != null)
4282 m_rootPart.PhysActor.Building = false;
4283
3291 HasGroupChanged = true; 4284 HasGroupChanged = true;
3292 part.IgnoreUndoUpdate = false;
3293 } 4285 }
3294 } 4286 }
3295 4287
@@ -3299,13 +4291,7 @@ namespace OpenSim.Region.Framework.Scenes
3299 /// <param name="newPos"></param> 4291 /// <param name="newPos"></param>
3300 public void UpdateRootPosition(Vector3 newPos) 4292 public void UpdateRootPosition(Vector3 newPos)
3301 { 4293 {
3302// m_log.DebugFormat( 4294 // needs to be called with phys building true
3303// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
3304
3305// SceneObjectPart[] parts = m_parts.GetArray();
3306// for (int i = 0; i < parts.Length; i++)
3307// parts[i].StoreUndoState();
3308
3309 Vector3 oldPos; 4295 Vector3 oldPos;
3310 4296
3311 if (IsAttachment) 4297 if (IsAttachment)
@@ -3326,12 +4312,19 @@ namespace OpenSim.Region.Framework.Scenes
3326 } 4312 }
3327 4313
3328 AbsolutePosition = newPos; 4314 AbsolutePosition = newPos;
3329 4315
3330 if (IsAttachment) 4316 if (IsAttachment)
3331 m_rootPart.AttachedPos = newPos; 4317 m_rootPart.AttachedPos = newPos;
3332 4318
3333 HasGroupChanged = true; 4319 HasGroupChanged = true;
3334 ScheduleGroupForTerseUpdate(); 4320 if (m_rootPart.Undoing)
4321 {
4322 ScheduleGroupForFullUpdate();
4323 }
4324 else
4325 {
4326 ScheduleGroupForTerseUpdate();
4327 }
3335 } 4328 }
3336 4329
3337 #endregion 4330 #endregion
@@ -3344,24 +4337,16 @@ namespace OpenSim.Region.Framework.Scenes
3344 /// <param name="rot"></param> 4337 /// <param name="rot"></param>
3345 public void UpdateGroupRotationR(Quaternion rot) 4338 public void UpdateGroupRotationR(Quaternion rot)
3346 { 4339 {
3347// m_log.DebugFormat(
3348// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
3349
3350// SceneObjectPart[] parts = m_parts.GetArray();
3351// for (int i = 0; i < parts.Length; i++)
3352// parts[i].StoreUndoState();
3353
3354 m_rootPart.StoreUndoState(true);
3355
3356 m_rootPart.UpdateRotation(rot); 4340 m_rootPart.UpdateRotation(rot);
3357 4341
4342/* this is done by rootpart RotationOffset set called by UpdateRotation
3358 PhysicsActor actor = m_rootPart.PhysActor; 4343 PhysicsActor actor = m_rootPart.PhysActor;
3359 if (actor != null) 4344 if (actor != null)
3360 { 4345 {
3361 actor.Orientation = m_rootPart.RotationOffset; 4346 actor.Orientation = m_rootPart.RotationOffset;
3362 m_scene.PhysicsScene.AddPhysicsActorTaint(actor); 4347 m_scene.PhysicsScene.AddPhysicsActorTaint(actor);
3363 } 4348 }
3364 4349*/
3365 HasGroupChanged = true; 4350 HasGroupChanged = true;
3366 ScheduleGroupForTerseUpdate(); 4351 ScheduleGroupForTerseUpdate();
3367 } 4352 }
@@ -3373,16 +4358,6 @@ namespace OpenSim.Region.Framework.Scenes
3373 /// <param name="rot"></param> 4358 /// <param name="rot"></param>
3374 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 4359 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
3375 { 4360 {
3376// m_log.DebugFormat(
3377// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
3378
3379// SceneObjectPart[] parts = m_parts.GetArray();
3380// for (int i = 0; i < parts.Length; i++)
3381// parts[i].StoreUndoState();
3382
3383 RootPart.StoreUndoState(true);
3384 RootPart.IgnoreUndoUpdate = true;
3385
3386 m_rootPart.UpdateRotation(rot); 4361 m_rootPart.UpdateRotation(rot);
3387 4362
3388 PhysicsActor actor = m_rootPart.PhysActor; 4363 PhysicsActor actor = m_rootPart.PhysActor;
@@ -3401,8 +4376,6 @@ namespace OpenSim.Region.Framework.Scenes
3401 4376
3402 HasGroupChanged = true; 4377 HasGroupChanged = true;
3403 ScheduleGroupForTerseUpdate(); 4378 ScheduleGroupForTerseUpdate();
3404
3405 RootPart.IgnoreUndoUpdate = false;
3406 } 4379 }
3407 4380
3408 /// <summary> 4381 /// <summary>
@@ -3415,13 +4388,11 @@ namespace OpenSim.Region.Framework.Scenes
3415 SceneObjectPart part = GetPart(localID); 4388 SceneObjectPart part = GetPart(localID);
3416 4389
3417 SceneObjectPart[] parts = m_parts.GetArray(); 4390 SceneObjectPart[] parts = m_parts.GetArray();
3418 for (int i = 0; i < parts.Length; i++)
3419 parts[i].StoreUndoState();
3420 4391
3421 if (part != null) 4392 if (part != null)
3422 { 4393 {
3423// m_log.DebugFormat( 4394 if (m_rootPart.PhysActor != null)
3424// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 4395 m_rootPart.PhysActor.Building = true;
3425 4396
3426 if (part.UUID == m_rootPart.UUID) 4397 if (part.UUID == m_rootPart.UUID)
3427 { 4398 {
@@ -3431,6 +4402,9 @@ namespace OpenSim.Region.Framework.Scenes
3431 { 4402 {
3432 part.UpdateRotation(rot); 4403 part.UpdateRotation(rot);
3433 } 4404 }
4405
4406 if (m_rootPart.PhysActor != null)
4407 m_rootPart.PhysActor.Building = false;
3434 } 4408 }
3435 } 4409 }
3436 4410
@@ -3444,12 +4418,8 @@ namespace OpenSim.Region.Framework.Scenes
3444 SceneObjectPart part = GetPart(localID); 4418 SceneObjectPart part = GetPart(localID);
3445 if (part != null) 4419 if (part != null)
3446 { 4420 {
3447// m_log.DebugFormat( 4421 if (m_rootPart.PhysActor != null)
3448// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 4422 m_rootPart.PhysActor.Building = true;
3449// part.Name, part.LocalId, rot);
3450
3451 part.StoreUndoState();
3452 part.IgnoreUndoUpdate = true;
3453 4423
3454 if (part.UUID == m_rootPart.UUID) 4424 if (part.UUID == m_rootPart.UUID)
3455 { 4425 {
@@ -3462,7 +4432,8 @@ namespace OpenSim.Region.Framework.Scenes
3462 part.OffsetPosition = pos; 4432 part.OffsetPosition = pos;
3463 } 4433 }
3464 4434
3465 part.IgnoreUndoUpdate = false; 4435 if (m_rootPart.PhysActor != null)
4436 m_rootPart.PhysActor.Building = false;
3466 } 4437 }
3467 } 4438 }
3468 4439
@@ -3472,15 +4443,12 @@ namespace OpenSim.Region.Framework.Scenes
3472 /// <param name="rot"></param> 4443 /// <param name="rot"></param>
3473 public void UpdateRootRotation(Quaternion rot) 4444 public void UpdateRootRotation(Quaternion rot)
3474 { 4445 {
3475// m_log.DebugFormat( 4446 // needs to be called with phys building true
3476// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
3477// Name, LocalId, rot);
3478
3479 Quaternion axRot = rot; 4447 Quaternion axRot = rot;
3480 Quaternion oldParentRot = m_rootPart.RotationOffset; 4448 Quaternion oldParentRot = m_rootPart.RotationOffset;
3481 4449
3482 m_rootPart.StoreUndoState(); 4450 //Don't use UpdateRotation because it schedules an update prematurely
3483 m_rootPart.UpdateRotation(rot); 4451 m_rootPart.RotationOffset = rot;
3484 4452
3485 PhysicsActor pa = m_rootPart.PhysActor; 4453 PhysicsActor pa = m_rootPart.PhysActor;
3486 4454
@@ -3496,35 +4464,145 @@ namespace OpenSim.Region.Framework.Scenes
3496 SceneObjectPart prim = parts[i]; 4464 SceneObjectPart prim = parts[i];
3497 if (prim.UUID != m_rootPart.UUID) 4465 if (prim.UUID != m_rootPart.UUID)
3498 { 4466 {
3499 prim.IgnoreUndoUpdate = true; 4467 Quaternion NewRot = oldParentRot * prim.RotationOffset;
4468 NewRot = Quaternion.Inverse(axRot) * NewRot;
4469 prim.RotationOffset = NewRot;
4470
3500 Vector3 axPos = prim.OffsetPosition; 4471 Vector3 axPos = prim.OffsetPosition;
4472
3501 axPos *= oldParentRot; 4473 axPos *= oldParentRot;
3502 axPos *= Quaternion.Inverse(axRot); 4474 axPos *= Quaternion.Inverse(axRot);
3503 prim.OffsetPosition = axPos; 4475 prim.OffsetPosition = axPos;
3504 Quaternion primsRot = prim.RotationOffset;
3505 Quaternion newRot = oldParentRot * primsRot;
3506 newRot = Quaternion.Inverse(axRot) * newRot;
3507 prim.RotationOffset = newRot;
3508 prim.ScheduleTerseUpdate();
3509 prim.IgnoreUndoUpdate = false;
3510 } 4476 }
3511 } 4477 }
3512 4478
3513// for (int i = 0; i < parts.Length; i++) 4479 HasGroupChanged = true;
3514// { 4480 ScheduleGroupForFullUpdate();
3515// SceneObjectPart childpart = parts[i]; 4481 }
3516// if (childpart != m_rootPart)
3517// {
3518//// childpart.IgnoreUndoUpdate = false;
3519//// childpart.StoreUndoState();
3520// }
3521// }
3522 4482
3523 m_rootPart.ScheduleTerseUpdate(); 4483 private enum updatetype :int
4484 {
4485 none = 0,
4486 partterse = 1,
4487 partfull = 2,
4488 groupterse = 3,
4489 groupfull = 4
4490 }
3524 4491
3525// m_log.DebugFormat( 4492 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
3526// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 4493 {
3527// Name, LocalId, rot); 4494 // TODO this still as excessive *.Schedule*Update()s
4495
4496 if (part != null && part.ParentGroup != null)
4497 {
4498 ObjectChangeType change = data.change;
4499 bool togroup = ((change & ObjectChangeType.Group) != 0);
4500 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
4501
4502 SceneObjectGroup group = part.ParentGroup;
4503 PhysicsActor pha = group.RootPart.PhysActor;
4504
4505 updatetype updateType = updatetype.none;
4506
4507 if (togroup)
4508 {
4509 // related to group
4510 if ((change & (ObjectChangeType.Rotation | ObjectChangeType.Position)) != 0)
4511 {
4512 if ((change & ObjectChangeType.Rotation) != 0)
4513 {
4514 group.RootPart.UpdateRotation(data.rotation);
4515 updateType = updatetype.none;
4516 }
4517 if ((change & ObjectChangeType.Position) != 0)
4518 {
4519 if (IsAttachment || m_scene.Permissions.CanObjectEntry(group.UUID, false, data.position))
4520 UpdateGroupPosition(data.position);
4521 updateType = updatetype.groupterse;
4522 }
4523 else
4524 // ugly rotation update of all parts
4525 {
4526 group.ResetChildPrimPhysicsPositions();
4527 }
4528
4529 }
4530 if ((change & ObjectChangeType.Scale) != 0)
4531 {
4532 if (pha != null)
4533 pha.Building = true;
4534
4535 group.GroupResize(data.scale);
4536 updateType = updatetype.none;
4537
4538 if (pha != null)
4539 pha.Building = false;
4540 }
4541 }
4542 else
4543 {
4544 // related to single prim in a link-set ( ie group)
4545 if (pha != null)
4546 pha.Building = true;
4547
4548 // root part is special
4549 // parts offset positions or rotations need to change also
4550
4551 if (part == group.RootPart)
4552 {
4553 if ((change & ObjectChangeType.Rotation) != 0)
4554 group.UpdateRootRotation(data.rotation);
4555 if ((change & ObjectChangeType.Position) != 0)
4556 group.UpdateRootPosition(data.position);
4557 if ((change & ObjectChangeType.Scale) != 0)
4558 part.Resize(data.scale);
4559 }
4560 else
4561 {
4562 if ((change & ObjectChangeType.Position) != 0)
4563 {
4564 part.OffsetPosition = data.position;
4565 updateType = updatetype.partterse;
4566 }
4567 if ((change & ObjectChangeType.Rotation) != 0)
4568 {
4569 part.UpdateRotation(data.rotation);
4570 updateType = updatetype.none;
4571 }
4572 if ((change & ObjectChangeType.Scale) != 0)
4573 {
4574 part.Resize(data.scale);
4575 updateType = updatetype.none;
4576 }
4577 }
4578
4579 if (pha != null)
4580 pha.Building = false;
4581 }
4582
4583 if (updateType != updatetype.none)
4584 {
4585 group.HasGroupChanged = true;
4586
4587 switch (updateType)
4588 {
4589 case updatetype.partterse:
4590 part.ScheduleTerseUpdate();
4591 break;
4592 case updatetype.partfull:
4593 part.ScheduleFullUpdate();
4594 break;
4595 case updatetype.groupterse:
4596 group.ScheduleGroupForTerseUpdate();
4597 break;
4598 case updatetype.groupfull:
4599 group.ScheduleGroupForFullUpdate();
4600 break;
4601 default:
4602 break;
4603 }
4604 }
4605 }
3528 } 4606 }
3529 4607
3530 #endregion 4608 #endregion
@@ -3565,6 +4643,8 @@ namespace OpenSim.Region.Framework.Scenes
3565 waypoint.handle = handle; 4643 waypoint.handle = handle;
3566 lock (m_rotTargets) 4644 lock (m_rotTargets)
3567 { 4645 {
4646 if (m_rotTargets.Count >= 8)
4647 m_rotTargets.Remove(m_rotTargets.ElementAt(0).Key);
3568 m_rotTargets.Add(handle, waypoint); 4648 m_rotTargets.Add(handle, waypoint);
3569 } 4649 }
3570 m_scene.AddGroupTarget(this); 4650 m_scene.AddGroupTarget(this);
@@ -3590,6 +4670,8 @@ namespace OpenSim.Region.Framework.Scenes
3590 waypoint.handle = handle; 4670 waypoint.handle = handle;
3591 lock (m_targets) 4671 lock (m_targets)
3592 { 4672 {
4673 if (m_targets.Count >= 8)
4674 m_targets.Remove(m_targets.ElementAt(0).Key);
3593 m_targets.Add(handle, waypoint); 4675 m_targets.Add(handle, waypoint);
3594 } 4676 }
3595 m_scene.AddGroupTarget(this); 4677 m_scene.AddGroupTarget(this);
@@ -3623,10 +4705,11 @@ namespace OpenSim.Region.Framework.Scenes
3623 scriptPosTarget target = m_targets[idx]; 4705 scriptPosTarget target = m_targets[idx];
3624 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance) 4706 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance)
3625 { 4707 {
4708 at_target = true;
4709
3626 // trigger at_target 4710 // trigger at_target
3627 if (m_scriptListens_atTarget) 4711 if (m_scriptListens_atTarget)
3628 { 4712 {
3629 at_target = true;
3630 scriptPosTarget att = new scriptPosTarget(); 4713 scriptPosTarget att = new scriptPosTarget();
3631 att.targetPos = target.targetPos; 4714 att.targetPos = target.targetPos;
3632 att.tolerance = target.tolerance; 4715 att.tolerance = target.tolerance;
@@ -3744,11 +4827,50 @@ namespace OpenSim.Region.Framework.Scenes
3744 } 4827 }
3745 } 4828 }
3746 } 4829 }
3747 4830
4831 public Vector3 GetGeometricCenter()
4832 {
4833 // this is not real geometric center but a average of positions relative to root prim acording to
4834 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
4835 // ignoring tortured prims details since sl also seems to ignore
4836 // so no real use in doing it on physics
4837
4838 Vector3 gc = Vector3.Zero;
4839
4840 int nparts = m_parts.Count;
4841 if (nparts <= 1)
4842 return gc;
4843
4844 SceneObjectPart[] parts = m_parts.GetArray();
4845 nparts = parts.Length; // just in case it changed
4846 if (nparts <= 1)
4847 return gc;
4848
4849 Quaternion parentRot = RootPart.RotationOffset;
4850 Vector3 pPos;
4851
4852 // average all parts positions
4853 for (int i = 0; i < nparts; i++)
4854 {
4855 // do it directly
4856 // gc += parts[i].GetWorldPosition();
4857 if (parts[i] != RootPart)
4858 {
4859 pPos = parts[i].OffsetPosition;
4860 gc += pPos;
4861 }
4862
4863 }
4864 gc /= nparts;
4865
4866 // relative to root:
4867// gc -= AbsolutePosition;
4868 return gc;
4869 }
4870
3748 public float GetMass() 4871 public float GetMass()
3749 { 4872 {
3750 float retmass = 0f; 4873 float retmass = 0f;
3751
3752 SceneObjectPart[] parts = m_parts.GetArray(); 4874 SceneObjectPart[] parts = m_parts.GetArray();
3753 for (int i = 0; i < parts.Length; i++) 4875 for (int i = 0; i < parts.Length; i++)
3754 retmass += parts[i].GetMass(); 4876 retmass += parts[i].GetMass();
@@ -3756,6 +4878,39 @@ namespace OpenSim.Region.Framework.Scenes
3756 return retmass; 4878 return retmass;
3757 } 4879 }
3758 4880
4881 // center of mass of full object
4882 public Vector3 GetCenterOfMass()
4883 {
4884 PhysicsActor pa = RootPart.PhysActor;
4885
4886 if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null)
4887 {
4888 // physics knows better about center of mass of physical prims
4889 Vector3 tmp = pa.CenterOfMass;
4890 return tmp;
4891 }
4892
4893 Vector3 Ptot = Vector3.Zero;
4894 float totmass = 0f;
4895 float m;
4896
4897 SceneObjectPart[] parts = m_parts.GetArray();
4898 for (int i = 0; i < parts.Length; i++)
4899 {
4900 m = parts[i].GetMass();
4901 Ptot += parts[i].GetPartCenterOfMass() * m;
4902 totmass += m;
4903 }
4904
4905 if (totmass == 0)
4906 totmass = 0;
4907 else
4908 totmass = 1 / totmass;
4909 Ptot *= totmass;
4910
4911 return Ptot;
4912 }
4913
3759 /// <summary> 4914 /// <summary>
3760 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that 4915 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that
3761 /// the physics engine can use it. 4916 /// the physics engine can use it.
@@ -3935,6 +5090,14 @@ namespace OpenSim.Region.Framework.Scenes
3935 FromItemID = uuid; 5090 FromItemID = uuid;
3936 } 5091 }
3937 5092
5093 public void ResetOwnerChangeFlag()
5094 {
5095 ForEachPart(delegate(SceneObjectPart part)
5096 {
5097 part.ResetOwnerChangeFlag();
5098 });
5099 }
5100
3938 #endregion 5101 #endregion
3939 } 5102 }
3940} 5103}