diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 666 |
1 files changed, 531 insertions, 135 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 5f00f84..c870797 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -29,6 +29,7 @@ using System; | |||
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Drawing; | 30 | using System.Drawing; |
31 | using System.IO; | 31 | using System.IO; |
32 | using System.Diagnostics; | ||
32 | using System.Linq; | 33 | using System.Linq; |
33 | using System.Threading; | 34 | using System.Threading; |
34 | using System.Xml; | 35 | using System.Xml; |
@@ -105,8 +106,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
105 | /// since the group's last persistent backup | 106 | /// since the group's last persistent backup |
106 | /// </summary> | 107 | /// </summary> |
107 | private bool m_hasGroupChanged = false; | 108 | private bool m_hasGroupChanged = false; |
108 | private long timeFirstChanged; | 109 | private long timeFirstChanged = 0; |
109 | private long timeLastChanged; | 110 | private long timeLastChanged = 0; |
111 | private long m_maxPersistTime = 0; | ||
112 | private long m_minPersistTime = 0; | ||
113 | private Random m_rand; | ||
114 | private bool m_suspendUpdates; | ||
115 | private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>(); | ||
116 | |||
117 | public bool areUpdatesSuspended | ||
118 | { | ||
119 | get | ||
120 | { | ||
121 | return m_suspendUpdates; | ||
122 | } | ||
123 | set | ||
124 | { | ||
125 | m_suspendUpdates = value; | ||
126 | if (!value) | ||
127 | { | ||
128 | QueueForUpdateCheck(); | ||
129 | } | ||
130 | } | ||
131 | } | ||
110 | 132 | ||
111 | public bool HasGroupChanged | 133 | public bool HasGroupChanged |
112 | { | 134 | { |
@@ -114,9 +136,39 @@ namespace OpenSim.Region.Framework.Scenes | |||
114 | { | 136 | { |
115 | if (value) | 137 | if (value) |
116 | { | 138 | { |
139 | if (m_isBackedUp) | ||
140 | { | ||
141 | m_scene.SceneGraph.FireChangeBackup(this); | ||
142 | } | ||
117 | timeLastChanged = DateTime.Now.Ticks; | 143 | timeLastChanged = DateTime.Now.Ticks; |
118 | if (!m_hasGroupChanged) | 144 | if (!m_hasGroupChanged) |
119 | timeFirstChanged = DateTime.Now.Ticks; | 145 | timeFirstChanged = DateTime.Now.Ticks; |
146 | if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null) | ||
147 | { | ||
148 | if (m_rand == null) | ||
149 | { | ||
150 | byte[] val = new byte[16]; | ||
151 | m_rootPart.UUID.ToBytes(val, 0); | ||
152 | m_rand = new Random(BitConverter.ToInt32(val, 0)); | ||
153 | } | ||
154 | |||
155 | if (m_scene.GetRootAgentCount() == 0) | ||
156 | { | ||
157 | //If the region is empty, this change has been made by an automated process | ||
158 | //and thus we delay the persist time by a random amount between 1.5 and 2.5. | ||
159 | |||
160 | float factor = 1.5f + (float)(m_rand.NextDouble()); | ||
161 | m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor); | ||
162 | m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor); | ||
163 | } | ||
164 | else | ||
165 | { | ||
166 | //If the region is not empty, we want to obey the minimum and maximum persist times | ||
167 | //but add a random factor so we stagger the object persistance a little | ||
168 | m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5 | ||
169 | m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0 | ||
170 | } | ||
171 | } | ||
120 | } | 172 | } |
121 | m_hasGroupChanged = value; | 173 | m_hasGroupChanged = value; |
122 | } | 174 | } |
@@ -132,8 +184,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
132 | return false; | 184 | return false; |
133 | if (m_scene.ShuttingDown) | 185 | if (m_scene.ShuttingDown) |
134 | return true; | 186 | return true; |
187 | |||
188 | if (m_minPersistTime == 0 || m_maxPersistTime == 0) | ||
189 | { | ||
190 | m_maxPersistTime = m_scene.m_persistAfter; | ||
191 | m_minPersistTime = m_scene.m_dontPersistBefore; | ||
192 | } | ||
193 | |||
135 | long currentTime = DateTime.Now.Ticks; | 194 | long currentTime = DateTime.Now.Ticks; |
136 | if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) | 195 | |
196 | if (timeLastChanged == 0) timeLastChanged = currentTime; | ||
197 | if (timeFirstChanged == 0) timeFirstChanged = currentTime; | ||
198 | |||
199 | if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime) | ||
137 | return true; | 200 | return true; |
138 | return false; | 201 | return false; |
139 | } | 202 | } |
@@ -176,10 +239,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
176 | 239 | ||
177 | private bool m_scriptListens_atTarget; | 240 | private bool m_scriptListens_atTarget; |
178 | private bool m_scriptListens_notAtTarget; | 241 | private bool m_scriptListens_notAtTarget; |
179 | |||
180 | private bool m_scriptListens_atRotTarget; | 242 | private bool m_scriptListens_atRotTarget; |
181 | private bool m_scriptListens_notAtRotTarget; | 243 | private bool m_scriptListens_notAtRotTarget; |
182 | 244 | ||
245 | public bool m_dupeInProgress = false; | ||
183 | internal Dictionary<UUID, string> m_savedScriptState; | 246 | internal Dictionary<UUID, string> m_savedScriptState; |
184 | 247 | ||
185 | #region Properties | 248 | #region Properties |
@@ -219,7 +282,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
219 | public virtual Quaternion Rotation | 282 | public virtual Quaternion Rotation |
220 | { | 283 | { |
221 | get { return m_rotation; } | 284 | get { return m_rotation; } |
222 | set { m_rotation = value; } | 285 | set { |
286 | foreach(SceneObjectPart p in m_parts.GetArray()) | ||
287 | { | ||
288 | p.StoreUndoState(UndoType.STATE_GROUP_ROTATION); | ||
289 | } | ||
290 | m_rotation = value; | ||
291 | } | ||
223 | } | 292 | } |
224 | 293 | ||
225 | public Quaternion GroupRotation | 294 | public Quaternion GroupRotation |
@@ -293,7 +362,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
293 | { | 362 | { |
294 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); | 363 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); |
295 | } | 364 | } |
296 | 365 | ||
366 | foreach (SceneObjectPart part in m_parts.GetArray()) | ||
367 | { | ||
368 | part.IgnoreUndoUpdate = true; | ||
369 | } | ||
297 | if (RootPart.GetStatusSandbox()) | 370 | if (RootPart.GetStatusSandbox()) |
298 | { | 371 | { |
299 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) | 372 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) |
@@ -304,10 +377,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
304 | return; | 377 | return; |
305 | } | 378 | } |
306 | } | 379 | } |
307 | |||
308 | SceneObjectPart[] parts = m_parts.GetArray(); | 380 | SceneObjectPart[] parts = m_parts.GetArray(); |
309 | for (int i = 0; i < parts.Length; i++) | 381 | foreach (SceneObjectPart part in parts) |
310 | parts[i].GroupPosition = val; | 382 | { |
383 | part.IgnoreUndoUpdate = false; | ||
384 | part.StoreUndoState(UndoType.STATE_GROUP_POSITION); | ||
385 | part.GroupPosition = val; | ||
386 | if (!m_dupeInProgress) | ||
387 | { | ||
388 | part.TriggerScriptChangedEvent(Changed.POSITION); | ||
389 | } | ||
390 | } | ||
391 | if (!m_dupeInProgress) | ||
392 | { | ||
393 | foreach (ScenePresence av in m_linkedAvatars) | ||
394 | { | ||
395 | SceneObjectPart p; | ||
396 | if (m_parts.TryGetValue(av.LinkedPrim, out p)) | ||
397 | { | ||
398 | Vector3 offset = p.GetWorldPosition() - av.ParentPosition; | ||
399 | av.AbsolutePosition += offset; | ||
400 | av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition | ||
401 | av.SendFullUpdateToAllClients(); | ||
402 | } | ||
403 | } | ||
404 | } | ||
311 | 405 | ||
312 | //if (m_rootPart.PhysActor != null) | 406 | //if (m_rootPart.PhysActor != null) |
313 | //{ | 407 | //{ |
@@ -458,6 +552,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
458 | /// </summary> | 552 | /// </summary> |
459 | public SceneObjectGroup() | 553 | public SceneObjectGroup() |
460 | { | 554 | { |
555 | |||
461 | } | 556 | } |
462 | 557 | ||
463 | /// <summary> | 558 | /// <summary> |
@@ -474,7 +569,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
474 | /// Constructor. This object is added to the scene later via AttachToScene() | 569 | /// Constructor. This object is added to the scene later via AttachToScene() |
475 | /// </summary> | 570 | /// </summary> |
476 | public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) | 571 | public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) |
477 | { | 572 | { |
478 | SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); | 573 | SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); |
479 | } | 574 | } |
480 | 575 | ||
@@ -520,6 +615,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
520 | /// </summary> | 615 | /// </summary> |
521 | public virtual void AttachToBackup() | 616 | public virtual void AttachToBackup() |
522 | { | 617 | { |
618 | if (IsAttachment) return; | ||
619 | m_scene.SceneGraph.FireAttachToBackup(this); | ||
620 | |||
523 | if (InSceneBackup) | 621 | if (InSceneBackup) |
524 | { | 622 | { |
525 | //m_log.DebugFormat( | 623 | //m_log.DebugFormat( |
@@ -635,9 +733,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
635 | result.normal = inter.normal; | 733 | result.normal = inter.normal; |
636 | result.distance = inter.distance; | 734 | result.distance = inter.distance; |
637 | } | 735 | } |
736 | |||
638 | } | 737 | } |
639 | } | 738 | } |
640 | |||
641 | return result; | 739 | return result; |
642 | } | 740 | } |
643 | 741 | ||
@@ -657,17 +755,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
657 | minZ = 8192f; | 755 | minZ = 8192f; |
658 | 756 | ||
659 | SceneObjectPart[] parts = m_parts.GetArray(); | 757 | SceneObjectPart[] parts = m_parts.GetArray(); |
660 | for (int i = 0; i < parts.Length; i++) | 758 | foreach (SceneObjectPart part in parts) |
661 | { | 759 | { |
662 | SceneObjectPart part = parts[i]; | ||
663 | |||
664 | Vector3 worldPos = part.GetWorldPosition(); | 760 | Vector3 worldPos = part.GetWorldPosition(); |
665 | Vector3 offset = worldPos - AbsolutePosition; | 761 | Vector3 offset = worldPos - AbsolutePosition; |
666 | Quaternion worldRot; | 762 | Quaternion worldRot; |
667 | if (part.ParentID == 0) | 763 | if (part.ParentID == 0) |
764 | { | ||
668 | worldRot = part.RotationOffset; | 765 | worldRot = part.RotationOffset; |
766 | } | ||
669 | else | 767 | else |
768 | { | ||
670 | worldRot = part.GetWorldRotation(); | 769 | worldRot = part.GetWorldRotation(); |
770 | } | ||
671 | 771 | ||
672 | Vector3 frontTopLeft; | 772 | Vector3 frontTopLeft; |
673 | Vector3 frontTopRight; | 773 | Vector3 frontTopRight; |
@@ -679,6 +779,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
679 | Vector3 backBottomLeft; | 779 | Vector3 backBottomLeft; |
680 | Vector3 backBottomRight; | 780 | Vector3 backBottomRight; |
681 | 781 | ||
782 | // Vector3[] corners = new Vector3[8]; | ||
783 | |||
682 | Vector3 orig = Vector3.Zero; | 784 | Vector3 orig = Vector3.Zero; |
683 | 785 | ||
684 | frontTopLeft.X = orig.X - (part.Scale.X / 2); | 786 | frontTopLeft.X = orig.X - (part.Scale.X / 2); |
@@ -713,6 +815,38 @@ namespace OpenSim.Region.Framework.Scenes | |||
713 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); | 815 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); |
714 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); | 816 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); |
715 | 817 | ||
818 | |||
819 | |||
820 | //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); | ||
821 | //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); | ||
822 | //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); | ||
823 | //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z); | ||
824 | //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z); | ||
825 | //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z); | ||
826 | //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z); | ||
827 | //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z); | ||
828 | |||
829 | //for (int i = 0; i < 8; i++) | ||
830 | //{ | ||
831 | // corners[i] = corners[i] * worldRot; | ||
832 | // corners[i] += offset; | ||
833 | |||
834 | // if (corners[i].X > maxX) | ||
835 | // maxX = corners[i].X; | ||
836 | // if (corners[i].X < minX) | ||
837 | // minX = corners[i].X; | ||
838 | |||
839 | // if (corners[i].Y > maxY) | ||
840 | // maxY = corners[i].Y; | ||
841 | // if (corners[i].Y < minY) | ||
842 | // minY = corners[i].Y; | ||
843 | |||
844 | // if (corners[i].Z > maxZ) | ||
845 | // maxZ = corners[i].Y; | ||
846 | // if (corners[i].Z < minZ) | ||
847 | // minZ = corners[i].Z; | ||
848 | //} | ||
849 | |||
716 | frontTopLeft = frontTopLeft * worldRot; | 850 | frontTopLeft = frontTopLeft * worldRot; |
717 | frontTopRight = frontTopRight * worldRot; | 851 | frontTopRight = frontTopRight * worldRot; |
718 | frontBottomLeft = frontBottomLeft * worldRot; | 852 | frontBottomLeft = frontBottomLeft * worldRot; |
@@ -734,6 +868,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
734 | backTopLeft += offset; | 868 | backTopLeft += offset; |
735 | backTopRight += offset; | 869 | backTopRight += offset; |
736 | 870 | ||
871 | //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); | ||
872 | //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); | ||
873 | //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); | ||
874 | //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z); | ||
875 | //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z); | ||
876 | //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z); | ||
877 | //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z); | ||
878 | //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z); | ||
879 | |||
737 | if (frontTopRight.X > maxX) | 880 | if (frontTopRight.X > maxX) |
738 | maxX = frontTopRight.X; | 881 | maxX = frontTopRight.X; |
739 | if (frontTopLeft.X > maxX) | 882 | if (frontTopLeft.X > maxX) |
@@ -879,15 +1022,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
879 | 1022 | ||
880 | public void SaveScriptedState(XmlTextWriter writer) | 1023 | public void SaveScriptedState(XmlTextWriter writer) |
881 | { | 1024 | { |
1025 | SaveScriptedState(writer, false); | ||
1026 | } | ||
1027 | |||
1028 | public void SaveScriptedState(XmlTextWriter writer, bool oldIDs) | ||
1029 | { | ||
882 | XmlDocument doc = new XmlDocument(); | 1030 | XmlDocument doc = new XmlDocument(); |
883 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); | 1031 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); |
884 | 1032 | ||
885 | SceneObjectPart[] parts = m_parts.GetArray(); | 1033 | SceneObjectPart[] parts = m_parts.GetArray(); |
886 | for (int i = 0; i < parts.Length; i++) | 1034 | for (int i = 0; i < parts.Length; i++) |
887 | { | 1035 | { |
888 | Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); | 1036 | Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs); |
889 | foreach (KeyValuePair<UUID, string> kvp in pstates) | 1037 | foreach (KeyValuePair<UUID, string> kvp in pstates) |
890 | states.Add(kvp.Key, kvp.Value); | 1038 | states[kvp.Key] = kvp.Value; |
891 | } | 1039 | } |
892 | 1040 | ||
893 | if (states.Count > 0) | 1041 | if (states.Count > 0) |
@@ -906,6 +1054,118 @@ namespace OpenSim.Region.Framework.Scenes | |||
906 | } | 1054 | } |
907 | } | 1055 | } |
908 | 1056 | ||
1057 | /// <summary> | ||
1058 | /// Add the avatar to this linkset (avatar is sat). | ||
1059 | /// </summary> | ||
1060 | /// <param name="agentID"></param> | ||
1061 | public void AddAvatar(UUID agentID) | ||
1062 | { | ||
1063 | ScenePresence presence; | ||
1064 | if (m_scene.TryGetScenePresence(agentID, out presence)) | ||
1065 | { | ||
1066 | if (!m_linkedAvatars.Contains(presence)) | ||
1067 | { | ||
1068 | m_linkedAvatars.Add(presence); | ||
1069 | } | ||
1070 | } | ||
1071 | } | ||
1072 | |||
1073 | /// <summary> | ||
1074 | /// Delete the avatar from this linkset (avatar is unsat). | ||
1075 | /// </summary> | ||
1076 | /// <param name="agentID"></param> | ||
1077 | public void DeleteAvatar(UUID agentID) | ||
1078 | { | ||
1079 | ScenePresence presence; | ||
1080 | if (m_scene.TryGetScenePresence(agentID, out presence)) | ||
1081 | { | ||
1082 | if (m_linkedAvatars.Contains(presence)) | ||
1083 | { | ||
1084 | m_linkedAvatars.Remove(presence); | ||
1085 | } | ||
1086 | } | ||
1087 | } | ||
1088 | |||
1089 | /// <summary> | ||
1090 | /// Returns the list of linked presences (avatars sat on this group) | ||
1091 | /// </summary> | ||
1092 | /// <param name="agentID"></param> | ||
1093 | public List<ScenePresence> GetLinkedAvatars() | ||
1094 | { | ||
1095 | return m_linkedAvatars; | ||
1096 | } | ||
1097 | |||
1098 | /// <summary> | ||
1099 | /// Attach this scene object to the given avatar. | ||
1100 | /// </summary> | ||
1101 | /// <param name="agentID"></param> | ||
1102 | /// <param name="attachmentpoint"></param> | ||
1103 | /// <param name="AttachOffset"></param> | ||
1104 | public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent) | ||
1105 | { | ||
1106 | ScenePresence avatar = m_scene.GetScenePresence(agentID); | ||
1107 | if (avatar != null) | ||
1108 | { | ||
1109 | // don't attach attachments to child agents | ||
1110 | if (avatar.IsChildAgent) return; | ||
1111 | |||
1112 | // m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name); | ||
1113 | |||
1114 | DetachFromBackup(); | ||
1115 | |||
1116 | // Remove from database and parcel prim count | ||
1117 | m_scene.DeleteFromStorage(UUID); | ||
1118 | m_scene.EventManager.TriggerParcelPrimCountTainted(); | ||
1119 | |||
1120 | m_rootPart.AttachedAvatar = agentID; | ||
1121 | |||
1122 | //Anakin Lohner bug #3839 | ||
1123 | lock (m_parts) | ||
1124 | { | ||
1125 | foreach (SceneObjectPart p in m_parts.GetArray()) | ||
1126 | { | ||
1127 | p.AttachedAvatar = agentID; | ||
1128 | } | ||
1129 | } | ||
1130 | |||
1131 | if (m_rootPart.PhysActor != null) | ||
1132 | { | ||
1133 | m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor); | ||
1134 | m_rootPart.PhysActor = null; | ||
1135 | } | ||
1136 | |||
1137 | AbsolutePosition = AttachOffset; | ||
1138 | m_rootPart.AttachedPos = AttachOffset; | ||
1139 | m_rootPart.IsAttachment = true; | ||
1140 | |||
1141 | m_rootPart.SetParentLocalId(avatar.LocalId); | ||
1142 | SetAttachmentPoint(Convert.ToByte(attachmentpoint)); | ||
1143 | |||
1144 | avatar.AddAttachment(this); | ||
1145 | |||
1146 | if (!silent) | ||
1147 | { | ||
1148 | // Killing it here will cause the client to deselect it | ||
1149 | // It then reappears on the avatar, deselected | ||
1150 | // through the full update below | ||
1151 | // | ||
1152 | if (IsSelected) | ||
1153 | { | ||
1154 | m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId }); | ||
1155 | } | ||
1156 | |||
1157 | IsSelected = false; // fudge.... | ||
1158 | ScheduleGroupForFullUpdate(); | ||
1159 | } | ||
1160 | } | ||
1161 | else | ||
1162 | { | ||
1163 | m_log.WarnFormat( | ||
1164 | "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present", | ||
1165 | UUID, agentID, Scene.RegionInfo.RegionName); | ||
1166 | } | ||
1167 | } | ||
1168 | |||
909 | public byte GetAttachmentPoint() | 1169 | public byte GetAttachmentPoint() |
910 | { | 1170 | { |
911 | return m_rootPart.Shape.State; | 1171 | return m_rootPart.Shape.State; |
@@ -1032,7 +1292,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1032 | public void AddPart(SceneObjectPart part) | 1292 | public void AddPart(SceneObjectPart part) |
1033 | { | 1293 | { |
1034 | part.SetParent(this); | 1294 | part.SetParent(this); |
1035 | part.LinkNum = m_parts.Add(part.UUID, part); | 1295 | m_parts.Add(part.UUID, part); |
1296 | |||
1297 | part.LinkNum = m_parts.Count; | ||
1298 | |||
1036 | if (part.LinkNum == 2 && RootPart != null) | 1299 | if (part.LinkNum == 2 && RootPart != null) |
1037 | RootPart.LinkNum = 1; | 1300 | RootPart.LinkNum = 1; |
1038 | } | 1301 | } |
@@ -1116,7 +1379,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1116 | 1379 | ||
1117 | public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) | 1380 | public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) |
1118 | { | 1381 | { |
1119 | part.StoreUndoState(); | 1382 | part.StoreUndoState(UndoType.STATE_PRIM_ALL); |
1120 | part.OnGrab(offsetPos, remoteClient); | 1383 | part.OnGrab(offsetPos, remoteClient); |
1121 | } | 1384 | } |
1122 | 1385 | ||
@@ -1136,6 +1399,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1136 | /// <param name="silent">If true then deletion is not broadcast to clients</param> | 1399 | /// <param name="silent">If true then deletion is not broadcast to clients</param> |
1137 | public void DeleteGroupFromScene(bool silent) | 1400 | public void DeleteGroupFromScene(bool silent) |
1138 | { | 1401 | { |
1402 | // We need to keep track of this state in case this group is still queued for backup. | ||
1403 | m_isDeleted = true; | ||
1404 | |||
1405 | DetachFromBackup(); | ||
1406 | |||
1139 | SceneObjectPart[] parts = m_parts.GetArray(); | 1407 | SceneObjectPart[] parts = m_parts.GetArray(); |
1140 | for (int i = 0; i < parts.Length; i++) | 1408 | for (int i = 0; i < parts.Length; i++) |
1141 | { | 1409 | { |
@@ -1147,13 +1415,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1147 | avatar.StandUp(); | 1415 | avatar.StandUp(); |
1148 | 1416 | ||
1149 | if (!silent) | 1417 | if (!silent) |
1150 | { | ||
1151 | part.UpdateFlag = 0; | 1418 | part.UpdateFlag = 0; |
1152 | if (part == m_rootPart) | ||
1153 | avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); | ||
1154 | } | ||
1155 | }); | 1419 | }); |
1156 | } | 1420 | } |
1421 | |||
1422 | |||
1157 | } | 1423 | } |
1158 | 1424 | ||
1159 | public void AddScriptLPS(int count) | 1425 | public void AddScriptLPS(int count) |
@@ -1250,7 +1516,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1250 | 1516 | ||
1251 | public void SetOwnerId(UUID userId) | 1517 | public void SetOwnerId(UUID userId) |
1252 | { | 1518 | { |
1253 | ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); | 1519 | ForEachPart(delegate(SceneObjectPart part) |
1520 | { | ||
1521 | |||
1522 | part.OwnerID = userId; | ||
1523 | |||
1524 | }); | ||
1254 | } | 1525 | } |
1255 | 1526 | ||
1256 | public void ForEachPart(Action<SceneObjectPart> whatToDo) | 1527 | public void ForEachPart(Action<SceneObjectPart> whatToDo) |
@@ -1286,7 +1557,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1286 | // any exception propogate upwards. | 1557 | // any exception propogate upwards. |
1287 | try | 1558 | try |
1288 | { | 1559 | { |
1289 | if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart | 1560 | if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart |
1561 | m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things | ||
1562 | m_scene.LoadingPrims) // Land may not be valid yet | ||
1563 | |||
1290 | { | 1564 | { |
1291 | ILandObject parcel = m_scene.LandChannel.GetLandObject( | 1565 | ILandObject parcel = m_scene.LandChannel.GetLandObject( |
1292 | m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); | 1566 | m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); |
@@ -1311,6 +1585,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1311 | } | 1585 | } |
1312 | } | 1586 | } |
1313 | } | 1587 | } |
1588 | |||
1314 | } | 1589 | } |
1315 | 1590 | ||
1316 | if (HasGroupChanged) | 1591 | if (HasGroupChanged) |
@@ -1318,6 +1593,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
1318 | // don't backup while it's selected or you're asking for changes mid stream. | 1593 | // don't backup while it's selected or you're asking for changes mid stream. |
1319 | if (isTimeToPersist() || forcedBackup) | 1594 | if (isTimeToPersist() || forcedBackup) |
1320 | { | 1595 | { |
1596 | if (m_rootPart.PhysActor != null && | ||
1597 | (!m_rootPart.PhysActor.IsPhysical)) | ||
1598 | { | ||
1599 | // Possible ghost prim | ||
1600 | if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition) | ||
1601 | { | ||
1602 | foreach (SceneObjectPart part in m_parts.GetArray()) | ||
1603 | { | ||
1604 | // Re-set physics actor positions and | ||
1605 | // orientations | ||
1606 | part.GroupPosition = m_rootPart.GroupPosition; | ||
1607 | } | ||
1608 | } | ||
1609 | } | ||
1321 | // m_log.DebugFormat( | 1610 | // m_log.DebugFormat( |
1322 | // "[SCENE]: Storing {0}, {1} in {2}", | 1611 | // "[SCENE]: Storing {0}, {1} in {2}", |
1323 | // Name, UUID, m_scene.RegionInfo.RegionName); | 1612 | // Name, UUID, m_scene.RegionInfo.RegionName); |
@@ -1380,81 +1669,106 @@ namespace OpenSim.Region.Framework.Scenes | |||
1380 | /// <returns></returns> | 1669 | /// <returns></returns> |
1381 | public SceneObjectGroup Copy(bool userExposed) | 1670 | public SceneObjectGroup Copy(bool userExposed) |
1382 | { | 1671 | { |
1383 | SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); | 1672 | SceneObjectGroup dupe; |
1384 | dupe.m_isBackedUp = false; | 1673 | try |
1385 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); | 1674 | { |
1675 | m_dupeInProgress = true; | ||
1676 | dupe = (SceneObjectGroup)MemberwiseClone(); | ||
1677 | dupe.m_isBackedUp = false; | ||
1678 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); | ||
1386 | 1679 | ||
1387 | // Warning, The following code related to previousAttachmentStatus is needed so that clones of | 1680 | // Warning, The following code related to previousAttachmentStatus is needed so that clones of |
1388 | // attachments do not bordercross while they're being duplicated. This is hacktastic! | 1681 | // attachments do not bordercross while they're being duplicated. This is hacktastic! |
1389 | // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! | 1682 | // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! |
1390 | // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state | 1683 | // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state |
1391 | // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, | 1684 | // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, |
1392 | // then restore it's attachment state | 1685 | // then restore it's attachment state |
1393 | 1686 | ||
1394 | // This is only necessary when userExposed is false! | 1687 | // This is only necessary when userExposed is false! |
1395 | 1688 | ||
1396 | bool previousAttachmentStatus = dupe.RootPart.IsAttachment; | 1689 | bool previousAttachmentStatus = dupe.RootPart.IsAttachment; |
1397 | |||
1398 | if (!userExposed) | ||
1399 | dupe.RootPart.IsAttachment = true; | ||
1400 | 1690 | ||
1401 | dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); | 1691 | if (!userExposed) |
1692 | dupe.RootPart.IsAttachment = true; | ||
1402 | 1693 | ||
1403 | if (!userExposed) | 1694 | dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); |
1404 | { | 1695 | |
1405 | dupe.RootPart.IsAttachment = previousAttachmentStatus; | 1696 | if (!userExposed) |
1406 | } | 1697 | { |
1698 | dupe.RootPart.IsAttachment = previousAttachmentStatus; | ||
1699 | } | ||
1407 | 1700 | ||
1408 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); | 1701 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); |
1409 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; | 1702 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; |
1410 | 1703 | ||
1411 | if (userExposed) | 1704 | if (userExposed) |
1412 | dupe.m_rootPart.TrimPermissions(); | 1705 | dupe.m_rootPart.TrimPermissions(); |
1413 | 1706 | ||
1414 | List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); | 1707 | /// may need to create a new Physics actor. |
1415 | 1708 | if (dupe.RootPart.PhysActor != null && userExposed) | |
1416 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | ||
1417 | { | 1709 | { |
1418 | return p1.LinkNum.CompareTo(p2.LinkNum); | 1710 | PrimitiveBaseShape pbs = dupe.RootPart.Shape; |
1711 | |||
1712 | dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( | ||
1713 | dupe.RootPart.Name, | ||
1714 | pbs, | ||
1715 | dupe.RootPart.AbsolutePosition, | ||
1716 | dupe.RootPart.Scale, | ||
1717 | dupe.RootPart.RotationOffset, | ||
1718 | dupe.RootPart.PhysActor.IsPhysical); | ||
1719 | |||
1720 | dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; | ||
1721 | dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); | ||
1419 | } | 1722 | } |
1420 | ); | ||
1421 | 1723 | ||
1422 | foreach (SceneObjectPart part in partList) | 1724 | List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); |
1423 | { | 1725 | |
1424 | if (part.UUID != m_rootPart.UUID) | 1726 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) |
1727 | { | ||
1728 | return p1.LinkNum.CompareTo(p2.LinkNum); | ||
1729 | } | ||
1730 | ); | ||
1731 | |||
1732 | foreach (SceneObjectPart part in partList) | ||
1425 | { | 1733 | { |
1426 | SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); | 1734 | if (part.UUID != m_rootPart.UUID) |
1427 | newPart.LinkNum = part.LinkNum; | 1735 | { |
1428 | } | 1736 | SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); |
1737 | |||
1738 | newPart.LinkNum = part.LinkNum; | ||
1739 | } | ||
1429 | 1740 | ||
1430 | // Need to duplicate the physics actor as well | 1741 | // Need to duplicate the physics actor as well |
1431 | if (part.PhysActor != null && userExposed) | 1742 | if (part.PhysActor != null && userExposed) |
1743 | { | ||
1744 | PrimitiveBaseShape pbs = part.Shape; | ||
1745 | |||
1746 | part.PhysActor | ||
1747 | = m_scene.PhysicsScene.AddPrimShape( | ||
1748 | string.Format("{0}/{1}", part.Name, part.UUID), | ||
1749 | pbs, | ||
1750 | part.AbsolutePosition, | ||
1751 | part.Scale, | ||
1752 | part.RotationOffset, | ||
1753 | part.PhysActor.IsPhysical); | ||
1754 | |||
1755 | part.PhysActor.LocalID = part.LocalId; | ||
1756 | part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); | ||
1757 | } | ||
1758 | } | ||
1759 | if (userExposed) | ||
1432 | { | 1760 | { |
1433 | PrimitiveBaseShape pbs = part.Shape; | 1761 | dupe.UpdateParentIDs(); |
1434 | 1762 | dupe.HasGroupChanged = true; | |
1435 | part.PhysActor | 1763 | dupe.AttachToBackup(); |
1436 | = m_scene.PhysicsScene.AddPrimShape( | 1764 | |
1437 | string.Format("{0}/{1}", part.Name, part.UUID), | 1765 | ScheduleGroupForFullUpdate(); |
1438 | pbs, | ||
1439 | part.AbsolutePosition, | ||
1440 | part.Scale, | ||
1441 | part.RotationOffset, | ||
1442 | part.PhysActor.IsPhysical); | ||
1443 | |||
1444 | part.PhysActor.LocalID = part.LocalId; | ||
1445 | part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); | ||
1446 | } | 1766 | } |
1447 | } | 1767 | } |
1448 | 1768 | finally | |
1449 | if (userExposed) | ||
1450 | { | 1769 | { |
1451 | dupe.UpdateParentIDs(); | 1770 | m_dupeInProgress = false; |
1452 | dupe.HasGroupChanged = true; | ||
1453 | dupe.AttachToBackup(); | ||
1454 | |||
1455 | ScheduleGroupForFullUpdate(); | ||
1456 | } | 1771 | } |
1457 | |||
1458 | return dupe; | 1772 | return dupe; |
1459 | } | 1773 | } |
1460 | 1774 | ||
@@ -1645,13 +1959,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
1645 | } | 1959 | } |
1646 | } | 1960 | } |
1647 | 1961 | ||
1962 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
1963 | { | ||
1964 | SceneObjectPart rootpart = m_rootPart; | ||
1965 | if (rootpart != null) | ||
1966 | { | ||
1967 | if (IsAttachment) | ||
1968 | { | ||
1969 | /* | ||
1970 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
1971 | if (avatar != null) | ||
1972 | { | ||
1973 | Rotate the Av? | ||
1974 | } */ | ||
1975 | } | ||
1976 | else | ||
1977 | { | ||
1978 | if (rootpart.PhysActor != null) | ||
1979 | { // APID must be implemented in your physics system for this to function. | ||
1980 | rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); | ||
1981 | rootpart.PhysActor.APIDStrength = strength; | ||
1982 | rootpart.PhysActor.APIDDamping = damping; | ||
1983 | rootpart.PhysActor.APIDActive = true; | ||
1984 | } | ||
1985 | } | ||
1986 | } | ||
1987 | } | ||
1988 | |||
1648 | public void stopLookAt() | 1989 | public void stopLookAt() |
1649 | { | 1990 | { |
1650 | SceneObjectPart rootpart = m_rootPart; | 1991 | SceneObjectPart rootpart = m_rootPart; |
1651 | if (rootpart != null) | 1992 | if (rootpart != null) |
1652 | { | 1993 | { |
1653 | if (rootpart.PhysActor != null) | 1994 | if (rootpart.PhysActor != null) |
1654 | { | 1995 | { // APID must be implemented in your physics system for this to function. |
1655 | rootpart.PhysActor.APIDActive = false; | 1996 | rootpart.PhysActor.APIDActive = false; |
1656 | } | 1997 | } |
1657 | } | 1998 | } |
@@ -1717,6 +2058,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1717 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) | 2058 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) |
1718 | { | 2059 | { |
1719 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); | 2060 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); |
2061 | newPart.SetParent(this); | ||
2062 | |||
1720 | AddPart(newPart); | 2063 | AddPart(newPart); |
1721 | 2064 | ||
1722 | SetPartAsNonRoot(newPart); | 2065 | SetPartAsNonRoot(newPart); |
@@ -1863,11 +2206,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1863 | /// Immediately send a full update for this scene object. | 2206 | /// Immediately send a full update for this scene object. |
1864 | /// </summary> | 2207 | /// </summary> |
1865 | public void SendGroupFullUpdate() | 2208 | public void SendGroupFullUpdate() |
1866 | { | 2209 | { |
1867 | if (IsDeleted) | 2210 | if (IsDeleted) |
1868 | return; | 2211 | return; |
1869 | 2212 | ||
1870 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); | 2213 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); |
1871 | 2214 | ||
1872 | RootPart.SendFullUpdateToAllClients(); | 2215 | RootPart.SendFullUpdateToAllClients(); |
1873 | 2216 | ||
@@ -2056,12 +2399,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2056 | part.LinkNum += objectGroup.PrimCount; | 2399 | part.LinkNum += objectGroup.PrimCount; |
2057 | } | 2400 | } |
2058 | } | 2401 | } |
2402 | } | ||
2059 | 2403 | ||
2060 | linkPart.LinkNum = 2; | 2404 | linkPart.LinkNum = 2; |
2061 | 2405 | ||
2062 | linkPart.SetParent(this); | 2406 | linkPart.SetParent(this); |
2063 | linkPart.CreateSelected = true; | 2407 | linkPart.CreateSelected = true; |
2064 | 2408 | ||
2409 | lock (m_parts.SyncRoot) | ||
2410 | { | ||
2065 | //if (linkPart.PhysActor != null) | 2411 | //if (linkPart.PhysActor != null) |
2066 | //{ | 2412 | //{ |
2067 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); | 2413 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); |
@@ -2218,6 +2564,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2218 | /// <param name="objectGroup"></param> | 2564 | /// <param name="objectGroup"></param> |
2219 | public virtual void DetachFromBackup() | 2565 | public virtual void DetachFromBackup() |
2220 | { | 2566 | { |
2567 | m_scene.SceneGraph.FireDetachFromBackup(this); | ||
2568 | |||
2221 | if (m_isBackedUp) | 2569 | if (m_isBackedUp) |
2222 | m_scene.EventManager.OnBackup -= ProcessBackup; | 2570 | m_scene.EventManager.OnBackup -= ProcessBackup; |
2223 | 2571 | ||
@@ -2522,6 +2870,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2522 | } | 2870 | } |
2523 | } | 2871 | } |
2524 | 2872 | ||
2873 | |||
2874 | |||
2875 | /// <summary> | ||
2876 | /// Gets the number of parts | ||
2877 | /// </summary> | ||
2878 | /// <returns></returns> | ||
2879 | public int GetPartCount() | ||
2880 | { | ||
2881 | return Parts.Count(); | ||
2882 | } | ||
2883 | |||
2525 | /// <summary> | 2884 | /// <summary> |
2526 | /// Update the texture entry for this part | 2885 | /// Update the texture entry for this part |
2527 | /// </summary> | 2886 | /// </summary> |
@@ -2583,11 +2942,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2583 | scale.Y = m_scene.m_maxNonphys; | 2942 | scale.Y = m_scene.m_maxNonphys; |
2584 | if (scale.Z > m_scene.m_maxNonphys) | 2943 | if (scale.Z > m_scene.m_maxNonphys) |
2585 | scale.Z = m_scene.m_maxNonphys; | 2944 | scale.Z = m_scene.m_maxNonphys; |
2586 | |||
2587 | SceneObjectPart part = GetChildPart(localID); | 2945 | SceneObjectPart part = GetChildPart(localID); |
2588 | if (part != null) | 2946 | if (part != null) |
2589 | { | 2947 | { |
2590 | part.Resize(scale); | ||
2591 | if (part.PhysActor != null) | 2948 | if (part.PhysActor != null) |
2592 | { | 2949 | { |
2593 | if (part.PhysActor.IsPhysical) | 2950 | if (part.PhysActor.IsPhysical) |
@@ -2602,7 +2959,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2602 | part.PhysActor.Size = scale; | 2959 | part.PhysActor.Size = scale; |
2603 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); | 2960 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); |
2604 | } | 2961 | } |
2605 | //if (part.UUID != m_rootPart.UUID) | 2962 | part.Resize(scale); |
2606 | 2963 | ||
2607 | HasGroupChanged = true; | 2964 | HasGroupChanged = true; |
2608 | ScheduleGroupForFullUpdate(); | 2965 | ScheduleGroupForFullUpdate(); |
@@ -2624,7 +2981,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2624 | SceneObjectPart part = GetChildPart(localID); | 2981 | SceneObjectPart part = GetChildPart(localID); |
2625 | if (part != null) | 2982 | if (part != null) |
2626 | { | 2983 | { |
2627 | part.IgnoreUndoUpdate = true; | ||
2628 | if (scale.X > m_scene.m_maxNonphys) | 2984 | if (scale.X > m_scene.m_maxNonphys) |
2629 | scale.X = m_scene.m_maxNonphys; | 2985 | scale.X = m_scene.m_maxNonphys; |
2630 | if (scale.Y > m_scene.m_maxNonphys) | 2986 | if (scale.Y > m_scene.m_maxNonphys) |
@@ -2661,7 +3017,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2661 | 3017 | ||
2662 | if (part.PhysActor != null && part.PhysActor.IsPhysical) | 3018 | if (part.PhysActor != null && part.PhysActor.IsPhysical) |
2663 | { | 3019 | { |
2664 | if (oldSize.X * x > m_scene.m_maxPhys) | 3020 | if (oldSize.X*x > m_scene.m_maxPhys) |
2665 | { | 3021 | { |
2666 | f = m_scene.m_maxPhys / oldSize.X; | 3022 | f = m_scene.m_maxPhys / oldSize.X; |
2667 | a = f / x; | 3023 | a = f / x; |
@@ -2669,7 +3025,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2669 | y *= a; | 3025 | y *= a; |
2670 | z *= a; | 3026 | z *= a; |
2671 | } | 3027 | } |
2672 | if (oldSize.Y * y > m_scene.m_maxPhys) | 3028 | if (oldSize.Y*y > m_scene.m_maxPhys) |
2673 | { | 3029 | { |
2674 | f = m_scene.m_maxPhys / oldSize.Y; | 3030 | f = m_scene.m_maxPhys / oldSize.Y; |
2675 | a = f / y; | 3031 | a = f / y; |
@@ -2677,7 +3033,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2677 | y *= a; | 3033 | y *= a; |
2678 | z *= a; | 3034 | z *= a; |
2679 | } | 3035 | } |
2680 | if (oldSize.Z * z > m_scene.m_maxPhys) | 3036 | if (oldSize.Z*z > m_scene.m_maxPhys) |
2681 | { | 3037 | { |
2682 | f = m_scene.m_maxPhys / oldSize.Z; | 3038 | f = m_scene.m_maxPhys / oldSize.Z; |
2683 | a = f / z; | 3039 | a = f / z; |
@@ -2688,7 +3044,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2688 | } | 3044 | } |
2689 | else | 3045 | else |
2690 | { | 3046 | { |
2691 | if (oldSize.X * x > m_scene.m_maxNonphys) | 3047 | if (oldSize.X*x > m_scene.m_maxNonphys) |
2692 | { | 3048 | { |
2693 | f = m_scene.m_maxNonphys / oldSize.X; | 3049 | f = m_scene.m_maxNonphys / oldSize.X; |
2694 | a = f / x; | 3050 | a = f / x; |
@@ -2696,7 +3052,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2696 | y *= a; | 3052 | y *= a; |
2697 | z *= a; | 3053 | z *= a; |
2698 | } | 3054 | } |
2699 | if (oldSize.Y * y > m_scene.m_maxNonphys) | 3055 | if (oldSize.Y*y > m_scene.m_maxNonphys) |
2700 | { | 3056 | { |
2701 | f = m_scene.m_maxNonphys / oldSize.Y; | 3057 | f = m_scene.m_maxNonphys / oldSize.Y; |
2702 | a = f / y; | 3058 | a = f / y; |
@@ -2704,7 +3060,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2704 | y *= a; | 3060 | y *= a; |
2705 | z *= a; | 3061 | z *= a; |
2706 | } | 3062 | } |
2707 | if (oldSize.Z * z > m_scene.m_maxNonphys) | 3063 | if (oldSize.Z*z > m_scene.m_maxNonphys) |
2708 | { | 3064 | { |
2709 | f = m_scene.m_maxNonphys / oldSize.Z; | 3065 | f = m_scene.m_maxNonphys / oldSize.Z; |
2710 | a = f / z; | 3066 | a = f / z; |
@@ -2714,7 +3070,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2714 | } | 3070 | } |
2715 | } | 3071 | } |
2716 | obPart.IgnoreUndoUpdate = false; | 3072 | obPart.IgnoreUndoUpdate = false; |
2717 | obPart.StoreUndoState(); | ||
2718 | } | 3073 | } |
2719 | } | 3074 | } |
2720 | } | 3075 | } |
@@ -2722,8 +3077,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2722 | Vector3 prevScale = part.Scale; | 3077 | Vector3 prevScale = part.Scale; |
2723 | prevScale.X *= x; | 3078 | prevScale.X *= x; |
2724 | prevScale.Y *= y; | 3079 | prevScale.Y *= y; |
2725 | prevScale.Z *= z; | 3080 | prevScale.Z *= z;; |
3081 | |||
3082 | part.IgnoreUndoUpdate = false; | ||
3083 | part.StoreUndoState(UndoType.STATE_GROUP_SCALE); | ||
3084 | part.IgnoreUndoUpdate = true; | ||
2726 | part.Resize(prevScale); | 3085 | part.Resize(prevScale); |
3086 | part.IgnoreUndoUpdate = false; | ||
2727 | 3087 | ||
2728 | parts = m_parts.GetArray(); | 3088 | parts = m_parts.GetArray(); |
2729 | for (int i = 0; i < parts.Length; i++) | 3089 | for (int i = 0; i < parts.Length; i++) |
@@ -2732,19 +3092,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
2732 | obPart.IgnoreUndoUpdate = true; | 3092 | obPart.IgnoreUndoUpdate = true; |
2733 | if (obPart.UUID != m_rootPart.UUID) | 3093 | if (obPart.UUID != m_rootPart.UUID) |
2734 | { | 3094 | { |
2735 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); | 3095 | if (obPart.UUID != m_rootPart.UUID) |
2736 | currentpos.X *= x; | 3096 | { |
2737 | currentpos.Y *= y; | 3097 | obPart.IgnoreUndoUpdate = false; |
2738 | currentpos.Z *= z; | 3098 | obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE); |
2739 | Vector3 newSize = new Vector3(obPart.Scale); | 3099 | obPart.IgnoreUndoUpdate = true; |
2740 | newSize.X *= x; | 3100 | |
2741 | newSize.Y *= y; | 3101 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); |
2742 | newSize.Z *= z; | 3102 | currentpos.X *= x; |
2743 | obPart.Resize(newSize); | 3103 | currentpos.Y *= y; |
2744 | obPart.UpdateOffSet(currentpos); | 3104 | currentpos.Z *= z; |
3105 | Vector3 newSize = new Vector3(obPart.Scale); | ||
3106 | newSize.X *= x; | ||
3107 | newSize.Y *= y; | ||
3108 | newSize.Z *= z; | ||
3109 | obPart.Resize(newSize); | ||
3110 | obPart.UpdateOffSet(currentpos); | ||
3111 | } | ||
3112 | obPart.IgnoreUndoUpdate = false; | ||
2745 | } | 3113 | } |
2746 | obPart.IgnoreUndoUpdate = false; | 3114 | obPart.IgnoreUndoUpdate = false; |
2747 | obPart.StoreUndoState(); | ||
2748 | } | 3115 | } |
2749 | 3116 | ||
2750 | if (part.PhysActor != null) | 3117 | if (part.PhysActor != null) |
@@ -2754,7 +3121,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2754 | } | 3121 | } |
2755 | 3122 | ||
2756 | part.IgnoreUndoUpdate = false; | 3123 | part.IgnoreUndoUpdate = false; |
2757 | part.StoreUndoState(); | ||
2758 | HasGroupChanged = true; | 3124 | HasGroupChanged = true; |
2759 | ScheduleGroupForTerseUpdate(); | 3125 | ScheduleGroupForTerseUpdate(); |
2760 | } | 3126 | } |
@@ -2770,14 +3136,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2770 | /// <param name="pos"></param> | 3136 | /// <param name="pos"></param> |
2771 | public void UpdateGroupPosition(Vector3 pos) | 3137 | public void UpdateGroupPosition(Vector3 pos) |
2772 | { | 3138 | { |
2773 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
2774 | for (int i = 0; i < parts.Length; i++) | ||
2775 | parts[i].StoreUndoState(); | ||
2776 | |||
2777 | if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) | 3139 | if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) |
2778 | { | 3140 | { |
2779 | if (IsAttachment) | 3141 | if (IsAttachment) |
2780 | { | 3142 | { |
3143 | m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION); | ||
2781 | m_rootPart.AttachedPos = pos; | 3144 | m_rootPart.AttachedPos = pos; |
2782 | } | 3145 | } |
2783 | if (RootPart.GetStatusSandbox()) | 3146 | if (RootPart.GetStatusSandbox()) |
@@ -2811,7 +3174,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2811 | 3174 | ||
2812 | SceneObjectPart[] parts = m_parts.GetArray(); | 3175 | SceneObjectPart[] parts = m_parts.GetArray(); |
2813 | for (int i = 0; i < parts.Length; i++) | 3176 | for (int i = 0; i < parts.Length; i++) |
2814 | parts[i].StoreUndoState(); | 3177 | parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION); |
2815 | 3178 | ||
2816 | if (part != null) | 3179 | if (part != null) |
2817 | { | 3180 | { |
@@ -2836,7 +3199,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2836 | { | 3199 | { |
2837 | SceneObjectPart[] parts = m_parts.GetArray(); | 3200 | SceneObjectPart[] parts = m_parts.GetArray(); |
2838 | for (int i = 0; i < parts.Length; i++) | 3201 | for (int i = 0; i < parts.Length; i++) |
2839 | parts[i].StoreUndoState(); | 3202 | parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION); |
2840 | 3203 | ||
2841 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | 3204 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); |
2842 | Vector3 oldPos = | 3205 | Vector3 oldPos = |
@@ -2857,10 +3220,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
2857 | obPart.OffsetPosition = obPart.OffsetPosition + diff; | 3220 | obPart.OffsetPosition = obPart.OffsetPosition + diff; |
2858 | } | 3221 | } |
2859 | 3222 | ||
2860 | AbsolutePosition = newPos; | 3223 | //We have to set undoing here because otherwise an undo state will be saved |
3224 | if (!m_rootPart.Undoing) | ||
3225 | { | ||
3226 | m_rootPart.Undoing = true; | ||
3227 | AbsolutePosition = newPos; | ||
3228 | m_rootPart.Undoing = false; | ||
3229 | } | ||
3230 | else | ||
3231 | { | ||
3232 | AbsolutePosition = newPos; | ||
3233 | } | ||
2861 | 3234 | ||
2862 | HasGroupChanged = true; | 3235 | HasGroupChanged = true; |
2863 | ScheduleGroupForTerseUpdate(); | 3236 | if (m_rootPart.Undoing) |
3237 | { | ||
3238 | ScheduleGroupForFullUpdate(); | ||
3239 | } | ||
3240 | else | ||
3241 | { | ||
3242 | ScheduleGroupForTerseUpdate(); | ||
3243 | } | ||
2864 | } | 3244 | } |
2865 | 3245 | ||
2866 | public void OffsetForNewRegion(Vector3 offset) | 3246 | public void OffsetForNewRegion(Vector3 offset) |
@@ -2880,7 +3260,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2880 | { | 3260 | { |
2881 | SceneObjectPart[] parts = m_parts.GetArray(); | 3261 | SceneObjectPart[] parts = m_parts.GetArray(); |
2882 | for (int i = 0; i < parts.Length; i++) | 3262 | for (int i = 0; i < parts.Length; i++) |
2883 | parts[i].StoreUndoState(); | 3263 | parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION); |
2884 | 3264 | ||
2885 | m_rootPart.UpdateRotation(rot); | 3265 | m_rootPart.UpdateRotation(rot); |
2886 | 3266 | ||
@@ -2904,7 +3284,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2904 | { | 3284 | { |
2905 | SceneObjectPart[] parts = m_parts.GetArray(); | 3285 | SceneObjectPart[] parts = m_parts.GetArray(); |
2906 | for (int i = 0; i < parts.Length; i++) | 3286 | for (int i = 0; i < parts.Length; i++) |
2907 | parts[i].StoreUndoState(); | 3287 | parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION); |
2908 | 3288 | ||
2909 | m_rootPart.UpdateRotation(rot); | 3289 | m_rootPart.UpdateRotation(rot); |
2910 | 3290 | ||
@@ -2929,10 +3309,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2929 | public void UpdateSingleRotation(Quaternion rot, uint localID) | 3309 | public void UpdateSingleRotation(Quaternion rot, uint localID) |
2930 | { | 3310 | { |
2931 | SceneObjectPart part = GetChildPart(localID); | 3311 | SceneObjectPart part = GetChildPart(localID); |
2932 | |||
2933 | SceneObjectPart[] parts = m_parts.GetArray(); | 3312 | SceneObjectPart[] parts = m_parts.GetArray(); |
2934 | for (int i = 0; i < parts.Length; i++) | 3313 | for (int i = 0; i < parts.Length; i++) |
2935 | parts[i].StoreUndoState(); | 3314 | parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION); |
2936 | 3315 | ||
2937 | if (part != null) | 3316 | if (part != null) |
2938 | { | 3317 | { |
@@ -2960,15 +3339,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
2960 | if (part.UUID == m_rootPart.UUID) | 3339 | if (part.UUID == m_rootPart.UUID) |
2961 | { | 3340 | { |
2962 | UpdateRootRotation(rot); | 3341 | UpdateRootRotation(rot); |
2963 | AbsolutePosition = pos; | 3342 | if (!m_rootPart.Undoing) |
3343 | { | ||
3344 | m_rootPart.Undoing = true; | ||
3345 | AbsolutePosition = pos; | ||
3346 | m_rootPart.Undoing = false; | ||
3347 | } | ||
3348 | else | ||
3349 | { | ||
3350 | AbsolutePosition = pos; | ||
3351 | } | ||
2964 | } | 3352 | } |
2965 | else | 3353 | else |
2966 | { | 3354 | { |
3355 | part.StoreUndoState(UndoType.STATE_PRIM_ROTATION); | ||
2967 | part.IgnoreUndoUpdate = true; | 3356 | part.IgnoreUndoUpdate = true; |
2968 | part.UpdateRotation(rot); | 3357 | part.UpdateRotation(rot); |
2969 | part.OffsetPosition = pos; | 3358 | part.OffsetPosition = pos; |
2970 | part.IgnoreUndoUpdate = false; | 3359 | part.IgnoreUndoUpdate = false; |
2971 | part.StoreUndoState(); | ||
2972 | } | 3360 | } |
2973 | } | 3361 | } |
2974 | } | 3362 | } |
@@ -2982,7 +3370,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2982 | Quaternion axRot = rot; | 3370 | Quaternion axRot = rot; |
2983 | Quaternion oldParentRot = m_rootPart.RotationOffset; | 3371 | Quaternion oldParentRot = m_rootPart.RotationOffset; |
2984 | 3372 | ||
2985 | m_rootPart.StoreUndoState(); | 3373 | m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION); |
3374 | bool cancelUndo = false; | ||
3375 | if (!m_rootPart.Undoing) | ||
3376 | { | ||
3377 | m_rootPart.Undoing = true; | ||
3378 | cancelUndo = true; | ||
3379 | } | ||
2986 | m_rootPart.UpdateRotation(rot); | 3380 | m_rootPart.UpdateRotation(rot); |
2987 | if (m_rootPart.PhysActor != null) | 3381 | if (m_rootPart.PhysActor != null) |
2988 | { | 3382 | { |
@@ -3006,17 +3400,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3006 | newRot *= Quaternion.Inverse(axRot); | 3400 | newRot *= Quaternion.Inverse(axRot); |
3007 | prim.RotationOffset = newRot; | 3401 | prim.RotationOffset = newRot; |
3008 | prim.ScheduleTerseUpdate(); | 3402 | prim.ScheduleTerseUpdate(); |
3403 | prim.IgnoreUndoUpdate = false; | ||
3009 | } | 3404 | } |
3010 | } | 3405 | } |
3011 | 3406 | if (cancelUndo == true) | |
3012 | for (int i = 0; i < parts.Length; i++) | ||
3013 | { | 3407 | { |
3014 | SceneObjectPart childpart = parts[i]; | 3408 | m_rootPart.Undoing = false; |
3015 | if (childpart != m_rootPart) | ||
3016 | { | ||
3017 | childpart.IgnoreUndoUpdate = false; | ||
3018 | childpart.StoreUndoState(); | ||
3019 | } | ||
3020 | } | 3409 | } |
3021 | 3410 | ||
3022 | m_rootPart.ScheduleTerseUpdate(); | 3411 | m_rootPart.ScheduleTerseUpdate(); |
@@ -3242,7 +3631,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3242 | public float GetMass() | 3631 | public float GetMass() |
3243 | { | 3632 | { |
3244 | float retmass = 0f; | 3633 | float retmass = 0f; |
3245 | |||
3246 | SceneObjectPart[] parts = m_parts.GetArray(); | 3634 | SceneObjectPart[] parts = m_parts.GetArray(); |
3247 | for (int i = 0; i < parts.Length; i++) | 3635 | for (int i = 0; i < parts.Length; i++) |
3248 | retmass += parts[i].GetMass(); | 3636 | retmass += parts[i].GetMass(); |
@@ -3358,6 +3746,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3358 | SetFromItemID(uuid); | 3746 | SetFromItemID(uuid); |
3359 | } | 3747 | } |
3360 | 3748 | ||
3749 | public void ResetOwnerChangeFlag() | ||
3750 | { | ||
3751 | ForEachPart(delegate(SceneObjectPart part) | ||
3752 | { | ||
3753 | part.ResetOwnerChangeFlag(); | ||
3754 | }); | ||
3755 | } | ||
3756 | |||
3361 | #endregion | 3757 | #endregion |
3362 | } | 3758 | } |
3363 | } | 3759 | } |