diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 661 |
1 files changed, 530 insertions, 131 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 5513584..a00a7c4 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(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 | { |
@@ -1154,6 +1422,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1154 | } | 1422 | } |
1155 | }); | 1423 | }); |
1156 | } | 1424 | } |
1425 | |||
1426 | |||
1157 | } | 1427 | } |
1158 | 1428 | ||
1159 | public void AddScriptLPS(int count) | 1429 | public void AddScriptLPS(int count) |
@@ -1250,7 +1520,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1250 | 1520 | ||
1251 | public void SetOwnerId(UUID userId) | 1521 | public void SetOwnerId(UUID userId) |
1252 | { | 1522 | { |
1253 | ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); | 1523 | ForEachPart(delegate(SceneObjectPart part) |
1524 | { | ||
1525 | |||
1526 | part.OwnerID = userId; | ||
1527 | |||
1528 | }); | ||
1254 | } | 1529 | } |
1255 | 1530 | ||
1256 | public void ForEachPart(Action<SceneObjectPart> whatToDo) | 1531 | public void ForEachPart(Action<SceneObjectPart> whatToDo) |
@@ -1286,7 +1561,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1286 | // any exception propogate upwards. | 1561 | // any exception propogate upwards. |
1287 | try | 1562 | try |
1288 | { | 1563 | { |
1289 | if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart | 1564 | if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart |
1565 | m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things | ||
1566 | m_scene.LoadingPrims) // Land may not be valid yet | ||
1567 | |||
1290 | { | 1568 | { |
1291 | ILandObject parcel = m_scene.LandChannel.GetLandObject( | 1569 | ILandObject parcel = m_scene.LandChannel.GetLandObject( |
1292 | m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); | 1570 | m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); |
@@ -1318,6 +1596,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
1318 | // don't backup while it's selected or you're asking for changes mid stream. | 1596 | // don't backup while it's selected or you're asking for changes mid stream. |
1319 | if (isTimeToPersist() || forcedBackup) | 1597 | if (isTimeToPersist() || forcedBackup) |
1320 | { | 1598 | { |
1599 | if (m_rootPart.PhysActor != null && | ||
1600 | (!m_rootPart.PhysActor.IsPhysical)) | ||
1601 | { | ||
1602 | // Possible ghost prim | ||
1603 | if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition) | ||
1604 | { | ||
1605 | foreach (SceneObjectPart part in m_parts.GetArray()) | ||
1606 | { | ||
1607 | // Re-set physics actor positions and | ||
1608 | // orientations | ||
1609 | part.GroupPosition = m_rootPart.GroupPosition; | ||
1610 | } | ||
1611 | } | ||
1612 | } | ||
1321 | // m_log.DebugFormat( | 1613 | // m_log.DebugFormat( |
1322 | // "[SCENE]: Storing {0}, {1} in {2}", | 1614 | // "[SCENE]: Storing {0}, {1} in {2}", |
1323 | // Name, UUID, m_scene.RegionInfo.RegionName); | 1615 | // Name, UUID, m_scene.RegionInfo.RegionName); |
@@ -1380,81 +1672,106 @@ namespace OpenSim.Region.Framework.Scenes | |||
1380 | /// <returns></returns> | 1672 | /// <returns></returns> |
1381 | public SceneObjectGroup Copy(bool userExposed) | 1673 | public SceneObjectGroup Copy(bool userExposed) |
1382 | { | 1674 | { |
1383 | SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); | 1675 | SceneObjectGroup dupe; |
1384 | dupe.m_isBackedUp = false; | 1676 | try |
1385 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); | 1677 | { |
1678 | m_dupeInProgress = true; | ||
1679 | dupe = (SceneObjectGroup)MemberwiseClone(); | ||
1680 | dupe.m_isBackedUp = false; | ||
1681 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); | ||
1386 | 1682 | ||
1387 | // Warning, The following code related to previousAttachmentStatus is needed so that clones of | 1683 | // 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! | 1684 | // 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! | 1685 | // 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 | 1686 | // 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, | 1687 | // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, |
1392 | // then restore it's attachment state | 1688 | // then restore it's attachment state |
1393 | 1689 | ||
1394 | // This is only necessary when userExposed is false! | 1690 | // This is only necessary when userExposed is false! |
1395 | 1691 | ||
1396 | bool previousAttachmentStatus = dupe.RootPart.IsAttachment; | 1692 | bool previousAttachmentStatus = dupe.RootPart.IsAttachment; |
1397 | |||
1398 | if (!userExposed) | ||
1399 | dupe.RootPart.IsAttachment = true; | ||
1400 | 1693 | ||
1401 | dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); | 1694 | if (!userExposed) |
1695 | dupe.RootPart.IsAttachment = true; | ||
1402 | 1696 | ||
1403 | if (!userExposed) | 1697 | dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); |
1404 | { | ||
1405 | dupe.RootPart.IsAttachment = previousAttachmentStatus; | ||
1406 | } | ||
1407 | 1698 | ||
1408 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); | 1699 | if (!userExposed) |
1409 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; | 1700 | { |
1701 | dupe.RootPart.IsAttachment = previousAttachmentStatus; | ||
1702 | } | ||
1410 | 1703 | ||
1411 | if (userExposed) | 1704 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); |
1412 | dupe.m_rootPart.TrimPermissions(); | 1705 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; |
1413 | 1706 | ||
1414 | List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); | 1707 | if (userExposed) |
1415 | 1708 | dupe.m_rootPart.TrimPermissions(); | |
1416 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | 1709 | |
1710 | /// may need to create a new Physics actor. | ||
1711 | if (dupe.RootPart.PhysActor != null && userExposed) | ||
1417 | { | 1712 | { |
1418 | return p1.LinkNum.CompareTo(p2.LinkNum); | 1713 | PrimitiveBaseShape pbs = dupe.RootPart.Shape; |
1714 | |||
1715 | dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( | ||
1716 | dupe.RootPart.Name, | ||
1717 | pbs, | ||
1718 | dupe.RootPart.AbsolutePosition, | ||
1719 | dupe.RootPart.Scale, | ||
1720 | dupe.RootPart.RotationOffset, | ||
1721 | dupe.RootPart.PhysActor.IsPhysical); | ||
1722 | |||
1723 | dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; | ||
1724 | dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); | ||
1419 | } | 1725 | } |
1420 | ); | ||
1421 | 1726 | ||
1422 | foreach (SceneObjectPart part in partList) | 1727 | List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); |
1423 | { | 1728 | |
1424 | if (part.UUID != m_rootPart.UUID) | 1729 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) |
1730 | { | ||
1731 | return p1.LinkNum.CompareTo(p2.LinkNum); | ||
1732 | } | ||
1733 | ); | ||
1734 | |||
1735 | foreach (SceneObjectPart part in partList) | ||
1425 | { | 1736 | { |
1426 | SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); | 1737 | if (part.UUID != m_rootPart.UUID) |
1427 | newPart.LinkNum = part.LinkNum; | 1738 | { |
1428 | } | 1739 | SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); |
1740 | |||
1741 | newPart.LinkNum = part.LinkNum; | ||
1742 | } | ||
1429 | 1743 | ||
1430 | // Need to duplicate the physics actor as well | 1744 | // Need to duplicate the physics actor as well |
1431 | if (part.PhysActor != null && userExposed) | 1745 | if (part.PhysActor != null && userExposed) |
1746 | { | ||
1747 | PrimitiveBaseShape pbs = part.Shape; | ||
1748 | |||
1749 | part.PhysActor | ||
1750 | = m_scene.PhysicsScene.AddPrimShape( | ||
1751 | string.Format("{0}/{1}", part.Name, part.UUID), | ||
1752 | pbs, | ||
1753 | part.AbsolutePosition, | ||
1754 | part.Scale, | ||
1755 | part.RotationOffset, | ||
1756 | part.PhysActor.IsPhysical); | ||
1757 | |||
1758 | part.PhysActor.LocalID = part.LocalId; | ||
1759 | part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); | ||
1760 | } | ||
1761 | } | ||
1762 | if (userExposed) | ||
1432 | { | 1763 | { |
1433 | PrimitiveBaseShape pbs = part.Shape; | 1764 | dupe.UpdateParentIDs(); |
1434 | 1765 | dupe.HasGroupChanged = true; | |
1435 | part.PhysActor | 1766 | dupe.AttachToBackup(); |
1436 | = m_scene.PhysicsScene.AddPrimShape( | 1767 | |
1437 | string.Format("{0}/{1}", part.Name, part.UUID), | 1768 | 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 | } | 1769 | } |
1447 | } | 1770 | } |
1448 | 1771 | finally | |
1449 | if (userExposed) | ||
1450 | { | 1772 | { |
1451 | dupe.UpdateParentIDs(); | 1773 | m_dupeInProgress = false; |
1452 | dupe.HasGroupChanged = true; | ||
1453 | dupe.AttachToBackup(); | ||
1454 | |||
1455 | ScheduleGroupForFullUpdate(); | ||
1456 | } | 1774 | } |
1457 | |||
1458 | return dupe; | 1775 | return dupe; |
1459 | } | 1776 | } |
1460 | 1777 | ||
@@ -1645,13 +1962,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
1645 | } | 1962 | } |
1646 | } | 1963 | } |
1647 | 1964 | ||
1965 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
1966 | { | ||
1967 | SceneObjectPart rootpart = m_rootPart; | ||
1968 | if (rootpart != null) | ||
1969 | { | ||
1970 | if (IsAttachment) | ||
1971 | { | ||
1972 | /* | ||
1973 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
1974 | if (avatar != null) | ||
1975 | { | ||
1976 | Rotate the Av? | ||
1977 | } */ | ||
1978 | } | ||
1979 | else | ||
1980 | { | ||
1981 | if (rootpart.PhysActor != null) | ||
1982 | { // APID must be implemented in your physics system for this to function. | ||
1983 | rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); | ||
1984 | rootpart.PhysActor.APIDStrength = strength; | ||
1985 | rootpart.PhysActor.APIDDamping = damping; | ||
1986 | rootpart.PhysActor.APIDActive = true; | ||
1987 | } | ||
1988 | } | ||
1989 | } | ||
1990 | } | ||
1991 | |||
1648 | public void stopLookAt() | 1992 | public void stopLookAt() |
1649 | { | 1993 | { |
1650 | SceneObjectPart rootpart = m_rootPart; | 1994 | SceneObjectPart rootpart = m_rootPart; |
1651 | if (rootpart != null) | 1995 | if (rootpart != null) |
1652 | { | 1996 | { |
1653 | if (rootpart.PhysActor != null) | 1997 | if (rootpart.PhysActor != null) |
1654 | { | 1998 | { // APID must be implemented in your physics system for this to function. |
1655 | rootpart.PhysActor.APIDActive = false; | 1999 | rootpart.PhysActor.APIDActive = false; |
1656 | } | 2000 | } |
1657 | } | 2001 | } |
@@ -1717,6 +2061,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1717 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) | 2061 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) |
1718 | { | 2062 | { |
1719 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); | 2063 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); |
2064 | newPart.SetParent(this); | ||
2065 | |||
1720 | AddPart(newPart); | 2066 | AddPart(newPart); |
1721 | 2067 | ||
1722 | SetPartAsNonRoot(newPart); | 2068 | SetPartAsNonRoot(newPart); |
@@ -1863,11 +2209,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1863 | /// Immediately send a full update for this scene object. | 2209 | /// Immediately send a full update for this scene object. |
1864 | /// </summary> | 2210 | /// </summary> |
1865 | public void SendGroupFullUpdate() | 2211 | public void SendGroupFullUpdate() |
1866 | { | 2212 | { |
1867 | if (IsDeleted) | 2213 | if (IsDeleted) |
1868 | return; | 2214 | return; |
1869 | 2215 | ||
1870 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); | 2216 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); |
1871 | 2217 | ||
1872 | RootPart.SendFullUpdateToAllClients(); | 2218 | RootPart.SendFullUpdateToAllClients(); |
1873 | 2219 | ||
@@ -2056,12 +2402,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2056 | part.LinkNum += objectGroup.PrimCount; | 2402 | part.LinkNum += objectGroup.PrimCount; |
2057 | } | 2403 | } |
2058 | } | 2404 | } |
2405 | } | ||
2059 | 2406 | ||
2060 | linkPart.LinkNum = 2; | 2407 | linkPart.LinkNum = 2; |
2061 | 2408 | ||
2062 | linkPart.SetParent(this); | 2409 | linkPart.SetParent(this); |
2063 | linkPart.CreateSelected = true; | 2410 | linkPart.CreateSelected = true; |
2064 | 2411 | ||
2412 | lock (m_parts.SyncRoot) | ||
2413 | { | ||
2065 | //if (linkPart.PhysActor != null) | 2414 | //if (linkPart.PhysActor != null) |
2066 | //{ | 2415 | //{ |
2067 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); | 2416 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); |
@@ -2218,6 +2567,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2218 | /// <param name="objectGroup"></param> | 2567 | /// <param name="objectGroup"></param> |
2219 | public virtual void DetachFromBackup() | 2568 | public virtual void DetachFromBackup() |
2220 | { | 2569 | { |
2570 | m_scene.SceneGraph.FireDetachFromBackup(this); | ||
2571 | |||
2221 | if (m_isBackedUp) | 2572 | if (m_isBackedUp) |
2222 | m_scene.EventManager.OnBackup -= ProcessBackup; | 2573 | m_scene.EventManager.OnBackup -= ProcessBackup; |
2223 | 2574 | ||
@@ -2522,6 +2873,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2522 | } | 2873 | } |
2523 | } | 2874 | } |
2524 | 2875 | ||
2876 | |||
2877 | |||
2878 | /// <summary> | ||
2879 | /// Gets the number of parts | ||
2880 | /// </summary> | ||
2881 | /// <returns></returns> | ||
2882 | public int GetPartCount() | ||
2883 | { | ||
2884 | return Parts.Count(); | ||
2885 | } | ||
2886 | |||
2525 | /// <summary> | 2887 | /// <summary> |
2526 | /// Update the texture entry for this part | 2888 | /// Update the texture entry for this part |
2527 | /// </summary> | 2889 | /// </summary> |
@@ -2583,11 +2945,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2583 | scale.Y = m_scene.m_maxNonphys; | 2945 | scale.Y = m_scene.m_maxNonphys; |
2584 | if (scale.Z > m_scene.m_maxNonphys) | 2946 | if (scale.Z > m_scene.m_maxNonphys) |
2585 | scale.Z = m_scene.m_maxNonphys; | 2947 | scale.Z = m_scene.m_maxNonphys; |
2586 | |||
2587 | SceneObjectPart part = GetChildPart(localID); | 2948 | SceneObjectPart part = GetChildPart(localID); |
2588 | if (part != null) | 2949 | if (part != null) |
2589 | { | 2950 | { |
2590 | part.Resize(scale); | ||
2591 | if (part.PhysActor != null) | 2951 | if (part.PhysActor != null) |
2592 | { | 2952 | { |
2593 | if (part.PhysActor.IsPhysical) | 2953 | if (part.PhysActor.IsPhysical) |
@@ -2602,7 +2962,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2602 | part.PhysActor.Size = scale; | 2962 | part.PhysActor.Size = scale; |
2603 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); | 2963 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); |
2604 | } | 2964 | } |
2605 | //if (part.UUID != m_rootPart.UUID) | 2965 | part.Resize(scale); |
2606 | 2966 | ||
2607 | HasGroupChanged = true; | 2967 | HasGroupChanged = true; |
2608 | ScheduleGroupForFullUpdate(); | 2968 | ScheduleGroupForFullUpdate(); |
@@ -2624,7 +2984,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2624 | SceneObjectPart part = GetChildPart(localID); | 2984 | SceneObjectPart part = GetChildPart(localID); |
2625 | if (part != null) | 2985 | if (part != null) |
2626 | { | 2986 | { |
2627 | part.IgnoreUndoUpdate = true; | ||
2628 | if (scale.X > m_scene.m_maxNonphys) | 2987 | if (scale.X > m_scene.m_maxNonphys) |
2629 | scale.X = m_scene.m_maxNonphys; | 2988 | scale.X = m_scene.m_maxNonphys; |
2630 | if (scale.Y > m_scene.m_maxNonphys) | 2989 | if (scale.Y > m_scene.m_maxNonphys) |
@@ -2661,7 +3020,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2661 | 3020 | ||
2662 | if (part.PhysActor != null && part.PhysActor.IsPhysical) | 3021 | if (part.PhysActor != null && part.PhysActor.IsPhysical) |
2663 | { | 3022 | { |
2664 | if (oldSize.X * x > m_scene.m_maxPhys) | 3023 | if (oldSize.X*x > m_scene.m_maxPhys) |
2665 | { | 3024 | { |
2666 | f = m_scene.m_maxPhys / oldSize.X; | 3025 | f = m_scene.m_maxPhys / oldSize.X; |
2667 | a = f / x; | 3026 | a = f / x; |
@@ -2669,7 +3028,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2669 | y *= a; | 3028 | y *= a; |
2670 | z *= a; | 3029 | z *= a; |
2671 | } | 3030 | } |
2672 | if (oldSize.Y * y > m_scene.m_maxPhys) | 3031 | if (oldSize.Y*y > m_scene.m_maxPhys) |
2673 | { | 3032 | { |
2674 | f = m_scene.m_maxPhys / oldSize.Y; | 3033 | f = m_scene.m_maxPhys / oldSize.Y; |
2675 | a = f / y; | 3034 | a = f / y; |
@@ -2677,7 +3036,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2677 | y *= a; | 3036 | y *= a; |
2678 | z *= a; | 3037 | z *= a; |
2679 | } | 3038 | } |
2680 | if (oldSize.Z * z > m_scene.m_maxPhys) | 3039 | if (oldSize.Z*z > m_scene.m_maxPhys) |
2681 | { | 3040 | { |
2682 | f = m_scene.m_maxPhys / oldSize.Z; | 3041 | f = m_scene.m_maxPhys / oldSize.Z; |
2683 | a = f / z; | 3042 | a = f / z; |
@@ -2688,7 +3047,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2688 | } | 3047 | } |
2689 | else | 3048 | else |
2690 | { | 3049 | { |
2691 | if (oldSize.X * x > m_scene.m_maxNonphys) | 3050 | if (oldSize.X*x > m_scene.m_maxNonphys) |
2692 | { | 3051 | { |
2693 | f = m_scene.m_maxNonphys / oldSize.X; | 3052 | f = m_scene.m_maxNonphys / oldSize.X; |
2694 | a = f / x; | 3053 | a = f / x; |
@@ -2696,7 +3055,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2696 | y *= a; | 3055 | y *= a; |
2697 | z *= a; | 3056 | z *= a; |
2698 | } | 3057 | } |
2699 | if (oldSize.Y * y > m_scene.m_maxNonphys) | 3058 | if (oldSize.Y*y > m_scene.m_maxNonphys) |
2700 | { | 3059 | { |
2701 | f = m_scene.m_maxNonphys / oldSize.Y; | 3060 | f = m_scene.m_maxNonphys / oldSize.Y; |
2702 | a = f / y; | 3061 | a = f / y; |
@@ -2704,7 +3063,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2704 | y *= a; | 3063 | y *= a; |
2705 | z *= a; | 3064 | z *= a; |
2706 | } | 3065 | } |
2707 | if (oldSize.Z * z > m_scene.m_maxNonphys) | 3066 | if (oldSize.Z*z > m_scene.m_maxNonphys) |
2708 | { | 3067 | { |
2709 | f = m_scene.m_maxNonphys / oldSize.Z; | 3068 | f = m_scene.m_maxNonphys / oldSize.Z; |
2710 | a = f / z; | 3069 | a = f / z; |
@@ -2714,7 +3073,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2714 | } | 3073 | } |
2715 | } | 3074 | } |
2716 | obPart.IgnoreUndoUpdate = false; | 3075 | obPart.IgnoreUndoUpdate = false; |
2717 | obPart.StoreUndoState(); | ||
2718 | } | 3076 | } |
2719 | } | 3077 | } |
2720 | } | 3078 | } |
@@ -2722,8 +3080,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2722 | Vector3 prevScale = part.Scale; | 3080 | Vector3 prevScale = part.Scale; |
2723 | prevScale.X *= x; | 3081 | prevScale.X *= x; |
2724 | prevScale.Y *= y; | 3082 | prevScale.Y *= y; |
2725 | prevScale.Z *= z; | 3083 | prevScale.Z *= z;; |
3084 | |||
3085 | part.IgnoreUndoUpdate = false; | ||
3086 | part.StoreUndoState(UndoType.STATE_GROUP_SCALE); | ||
3087 | part.IgnoreUndoUpdate = true; | ||
2726 | part.Resize(prevScale); | 3088 | part.Resize(prevScale); |
3089 | part.IgnoreUndoUpdate = false; | ||
2727 | 3090 | ||
2728 | parts = m_parts.GetArray(); | 3091 | parts = m_parts.GetArray(); |
2729 | for (int i = 0; i < parts.Length; i++) | 3092 | for (int i = 0; i < parts.Length; i++) |
@@ -2732,19 +3095,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
2732 | obPart.IgnoreUndoUpdate = true; | 3095 | obPart.IgnoreUndoUpdate = true; |
2733 | if (obPart.UUID != m_rootPart.UUID) | 3096 | if (obPart.UUID != m_rootPart.UUID) |
2734 | { | 3097 | { |
2735 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); | 3098 | if (obPart.UUID != m_rootPart.UUID) |
2736 | currentpos.X *= x; | 3099 | { |
2737 | currentpos.Y *= y; | 3100 | obPart.IgnoreUndoUpdate = false; |
2738 | currentpos.Z *= z; | 3101 | obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE); |
2739 | Vector3 newSize = new Vector3(obPart.Scale); | 3102 | obPart.IgnoreUndoUpdate = true; |
2740 | newSize.X *= x; | 3103 | |
2741 | newSize.Y *= y; | 3104 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); |
2742 | newSize.Z *= z; | 3105 | currentpos.X *= x; |
2743 | obPart.Resize(newSize); | 3106 | currentpos.Y *= y; |
2744 | obPart.UpdateOffSet(currentpos); | 3107 | currentpos.Z *= z; |
3108 | Vector3 newSize = new Vector3(obPart.Scale); | ||
3109 | newSize.X *= x; | ||
3110 | newSize.Y *= y; | ||
3111 | newSize.Z *= z; | ||
3112 | obPart.Resize(newSize); | ||
3113 | obPart.UpdateOffSet(currentpos); | ||
3114 | } | ||
3115 | obPart.IgnoreUndoUpdate = false; | ||
2745 | } | 3116 | } |
2746 | obPart.IgnoreUndoUpdate = false; | 3117 | obPart.IgnoreUndoUpdate = false; |
2747 | obPart.StoreUndoState(); | ||
2748 | } | 3118 | } |
2749 | 3119 | ||
2750 | if (part.PhysActor != null) | 3120 | if (part.PhysActor != null) |
@@ -2754,7 +3124,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2754 | } | 3124 | } |
2755 | 3125 | ||
2756 | part.IgnoreUndoUpdate = false; | 3126 | part.IgnoreUndoUpdate = false; |
2757 | part.StoreUndoState(); | ||
2758 | HasGroupChanged = true; | 3127 | HasGroupChanged = true; |
2759 | ScheduleGroupForTerseUpdate(); | 3128 | ScheduleGroupForTerseUpdate(); |
2760 | } | 3129 | } |
@@ -2770,14 +3139,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2770 | /// <param name="pos"></param> | 3139 | /// <param name="pos"></param> |
2771 | public void UpdateGroupPosition(Vector3 pos) | 3140 | public void UpdateGroupPosition(Vector3 pos) |
2772 | { | 3141 | { |
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)) | 3142 | if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) |
2778 | { | 3143 | { |
2779 | if (IsAttachment) | 3144 | if (IsAttachment) |
2780 | { | 3145 | { |
3146 | m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION); | ||
2781 | m_rootPart.AttachedPos = pos; | 3147 | m_rootPart.AttachedPos = pos; |
2782 | } | 3148 | } |
2783 | if (RootPart.GetStatusSandbox()) | 3149 | if (RootPart.GetStatusSandbox()) |
@@ -2811,7 +3177,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2811 | 3177 | ||
2812 | SceneObjectPart[] parts = m_parts.GetArray(); | 3178 | SceneObjectPart[] parts = m_parts.GetArray(); |
2813 | for (int i = 0; i < parts.Length; i++) | 3179 | for (int i = 0; i < parts.Length; i++) |
2814 | parts[i].StoreUndoState(); | 3180 | parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION); |
2815 | 3181 | ||
2816 | if (part != null) | 3182 | if (part != null) |
2817 | { | 3183 | { |
@@ -2836,7 +3202,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2836 | { | 3202 | { |
2837 | SceneObjectPart[] parts = m_parts.GetArray(); | 3203 | SceneObjectPart[] parts = m_parts.GetArray(); |
2838 | for (int i = 0; i < parts.Length; i++) | 3204 | for (int i = 0; i < parts.Length; i++) |
2839 | parts[i].StoreUndoState(); | 3205 | parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION); |
2840 | 3206 | ||
2841 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | 3207 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); |
2842 | Vector3 oldPos = | 3208 | Vector3 oldPos = |
@@ -2857,10 +3223,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
2857 | obPart.OffsetPosition = obPart.OffsetPosition + diff; | 3223 | obPart.OffsetPosition = obPart.OffsetPosition + diff; |
2858 | } | 3224 | } |
2859 | 3225 | ||
2860 | AbsolutePosition = newPos; | 3226 | //We have to set undoing here because otherwise an undo state will be saved |
3227 | if (!m_rootPart.Undoing) | ||
3228 | { | ||
3229 | m_rootPart.Undoing = true; | ||
3230 | AbsolutePosition = newPos; | ||
3231 | m_rootPart.Undoing = false; | ||
3232 | } | ||
3233 | else | ||
3234 | { | ||
3235 | AbsolutePosition = newPos; | ||
3236 | } | ||
2861 | 3237 | ||
2862 | HasGroupChanged = true; | 3238 | HasGroupChanged = true; |
2863 | ScheduleGroupForTerseUpdate(); | 3239 | if (m_rootPart.Undoing) |
3240 | { | ||
3241 | ScheduleGroupForFullUpdate(); | ||
3242 | } | ||
3243 | else | ||
3244 | { | ||
3245 | ScheduleGroupForTerseUpdate(); | ||
3246 | } | ||
2864 | } | 3247 | } |
2865 | 3248 | ||
2866 | public void OffsetForNewRegion(Vector3 offset) | 3249 | public void OffsetForNewRegion(Vector3 offset) |
@@ -2880,7 +3263,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2880 | { | 3263 | { |
2881 | SceneObjectPart[] parts = m_parts.GetArray(); | 3264 | SceneObjectPart[] parts = m_parts.GetArray(); |
2882 | for (int i = 0; i < parts.Length; i++) | 3265 | for (int i = 0; i < parts.Length; i++) |
2883 | parts[i].StoreUndoState(); | 3266 | parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION); |
2884 | 3267 | ||
2885 | m_rootPart.UpdateRotation(rot); | 3268 | m_rootPart.UpdateRotation(rot); |
2886 | 3269 | ||
@@ -2904,7 +3287,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2904 | { | 3287 | { |
2905 | SceneObjectPart[] parts = m_parts.GetArray(); | 3288 | SceneObjectPart[] parts = m_parts.GetArray(); |
2906 | for (int i = 0; i < parts.Length; i++) | 3289 | for (int i = 0; i < parts.Length; i++) |
2907 | parts[i].StoreUndoState(); | 3290 | parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION); |
2908 | 3291 | ||
2909 | m_rootPart.UpdateRotation(rot); | 3292 | m_rootPart.UpdateRotation(rot); |
2910 | 3293 | ||
@@ -2929,10 +3312,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2929 | public void UpdateSingleRotation(Quaternion rot, uint localID) | 3312 | public void UpdateSingleRotation(Quaternion rot, uint localID) |
2930 | { | 3313 | { |
2931 | SceneObjectPart part = GetChildPart(localID); | 3314 | SceneObjectPart part = GetChildPart(localID); |
2932 | |||
2933 | SceneObjectPart[] parts = m_parts.GetArray(); | 3315 | SceneObjectPart[] parts = m_parts.GetArray(); |
2934 | for (int i = 0; i < parts.Length; i++) | 3316 | for (int i = 0; i < parts.Length; i++) |
2935 | parts[i].StoreUndoState(); | 3317 | parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION); |
2936 | 3318 | ||
2937 | if (part != null) | 3319 | if (part != null) |
2938 | { | 3320 | { |
@@ -2960,15 +3342,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
2960 | if (part.UUID == m_rootPart.UUID) | 3342 | if (part.UUID == m_rootPart.UUID) |
2961 | { | 3343 | { |
2962 | UpdateRootRotation(rot); | 3344 | UpdateRootRotation(rot); |
2963 | AbsolutePosition = pos; | 3345 | if (!m_rootPart.Undoing) |
3346 | { | ||
3347 | m_rootPart.Undoing = true; | ||
3348 | AbsolutePosition = pos; | ||
3349 | m_rootPart.Undoing = false; | ||
3350 | } | ||
3351 | else | ||
3352 | { | ||
3353 | AbsolutePosition = pos; | ||
3354 | } | ||
2964 | } | 3355 | } |
2965 | else | 3356 | else |
2966 | { | 3357 | { |
3358 | part.StoreUndoState(UndoType.STATE_PRIM_ROTATION); | ||
2967 | part.IgnoreUndoUpdate = true; | 3359 | part.IgnoreUndoUpdate = true; |
2968 | part.UpdateRotation(rot); | 3360 | part.UpdateRotation(rot); |
2969 | part.OffsetPosition = pos; | 3361 | part.OffsetPosition = pos; |
2970 | part.IgnoreUndoUpdate = false; | 3362 | part.IgnoreUndoUpdate = false; |
2971 | part.StoreUndoState(); | ||
2972 | } | 3363 | } |
2973 | } | 3364 | } |
2974 | } | 3365 | } |
@@ -2982,7 +3373,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2982 | Quaternion axRot = rot; | 3373 | Quaternion axRot = rot; |
2983 | Quaternion oldParentRot = m_rootPart.RotationOffset; | 3374 | Quaternion oldParentRot = m_rootPart.RotationOffset; |
2984 | 3375 | ||
2985 | m_rootPart.StoreUndoState(); | 3376 | m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION); |
3377 | bool cancelUndo = false; | ||
3378 | if (!m_rootPart.Undoing) | ||
3379 | { | ||
3380 | m_rootPart.Undoing = true; | ||
3381 | cancelUndo = true; | ||
3382 | } | ||
2986 | m_rootPart.UpdateRotation(rot); | 3383 | m_rootPart.UpdateRotation(rot); |
2987 | if (m_rootPart.PhysActor != null) | 3384 | if (m_rootPart.PhysActor != null) |
2988 | { | 3385 | { |
@@ -3006,17 +3403,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3006 | newRot *= Quaternion.Inverse(axRot); | 3403 | newRot *= Quaternion.Inverse(axRot); |
3007 | prim.RotationOffset = newRot; | 3404 | prim.RotationOffset = newRot; |
3008 | prim.ScheduleTerseUpdate(); | 3405 | prim.ScheduleTerseUpdate(); |
3406 | prim.IgnoreUndoUpdate = false; | ||
3009 | } | 3407 | } |
3010 | } | 3408 | } |
3011 | 3409 | if (cancelUndo == true) | |
3012 | for (int i = 0; i < parts.Length; i++) | ||
3013 | { | 3410 | { |
3014 | SceneObjectPart childpart = parts[i]; | 3411 | m_rootPart.Undoing = false; |
3015 | if (childpart != m_rootPart) | ||
3016 | { | ||
3017 | childpart.IgnoreUndoUpdate = false; | ||
3018 | childpart.StoreUndoState(); | ||
3019 | } | ||
3020 | } | 3412 | } |
3021 | 3413 | ||
3022 | m_rootPart.ScheduleTerseUpdate(); | 3414 | m_rootPart.ScheduleTerseUpdate(); |
@@ -3242,7 +3634,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3242 | public float GetMass() | 3634 | public float GetMass() |
3243 | { | 3635 | { |
3244 | float retmass = 0f; | 3636 | float retmass = 0f; |
3245 | |||
3246 | SceneObjectPart[] parts = m_parts.GetArray(); | 3637 | SceneObjectPart[] parts = m_parts.GetArray(); |
3247 | for (int i = 0; i < parts.Length; i++) | 3638 | for (int i = 0; i < parts.Length; i++) |
3248 | retmass += parts[i].GetMass(); | 3639 | retmass += parts[i].GetMass(); |
@@ -3358,6 +3749,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3358 | SetFromItemID(uuid); | 3749 | SetFromItemID(uuid); |
3359 | } | 3750 | } |
3360 | 3751 | ||
3752 | public void ResetOwnerChangeFlag() | ||
3753 | { | ||
3754 | ForEachPart(delegate(SceneObjectPart part) | ||
3755 | { | ||
3756 | part.ResetOwnerChangeFlag(); | ||
3757 | }); | ||
3758 | } | ||
3759 | |||
3361 | #endregion | 3760 | #endregion |
3362 | } | 3761 | } |
3363 | } | 3762 | } |