diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 656 |
1 files changed, 519 insertions, 137 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 5f00f84..79f7162 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) |
@@ -1282,11 +1553,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1282 | return; | 1553 | return; |
1283 | } | 1554 | } |
1284 | 1555 | ||
1556 | if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) | ||
1557 | return; | ||
1558 | |||
1285 | // Since this is the top of the section of call stack for backing up a particular scene object, don't let | 1559 | // Since this is the top of the section of call stack for backing up a particular scene object, don't let |
1286 | // any exception propogate upwards. | 1560 | // any exception propogate upwards. |
1287 | try | 1561 | try |
1288 | { | 1562 | { |
1289 | if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart | 1563 | if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart |
1564 | m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things | ||
1565 | m_scene.LoadingPrims) // Land may not be valid yet | ||
1566 | |||
1290 | { | 1567 | { |
1291 | ILandObject parcel = m_scene.LandChannel.GetLandObject( | 1568 | ILandObject parcel = m_scene.LandChannel.GetLandObject( |
1292 | m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); | 1569 | m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); |
@@ -1311,6 +1588,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1311 | } | 1588 | } |
1312 | } | 1589 | } |
1313 | } | 1590 | } |
1591 | |||
1314 | } | 1592 | } |
1315 | 1593 | ||
1316 | if (HasGroupChanged) | 1594 | if (HasGroupChanged) |
@@ -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,89 @@ 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 | { |
1386 | 1678 | m_dupeInProgress = true; | |
1387 | // Warning, The following code related to previousAttachmentStatus is needed so that clones of | 1679 | dupe = (SceneObjectGroup)MemberwiseClone(); |
1388 | // attachments do not bordercross while they're being duplicated. This is hacktastic! | 1680 | dupe.m_isBackedUp = false; |
1389 | // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! | 1681 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); |
1390 | // 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, | ||
1392 | // then restore it's attachment state | ||
1393 | |||
1394 | // This is only necessary when userExposed is false! | ||
1395 | 1682 | ||
1396 | bool previousAttachmentStatus = dupe.RootPart.IsAttachment; | 1683 | // Warning, The following code related to previousAttachmentStatus is needed so that clones of |
1397 | 1684 | // attachments do not bordercross while they're being duplicated. This is hacktastic! | |
1398 | if (!userExposed) | 1685 | // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! |
1399 | dupe.RootPart.IsAttachment = true; | 1686 | // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state |
1687 | // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, | ||
1688 | // then restore it's attachment state | ||
1400 | 1689 | ||
1401 | dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); | 1690 | // This is only necessary when userExposed is false! |
1402 | 1691 | ||
1403 | if (!userExposed) | 1692 | bool previousAttachmentStatus = dupe.RootPart.IsAttachment; |
1404 | { | ||
1405 | dupe.RootPart.IsAttachment = previousAttachmentStatus; | ||
1406 | } | ||
1407 | 1693 | ||
1408 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); | 1694 | if (!userExposed) |
1409 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; | 1695 | dupe.RootPart.IsAttachment = true; |
1410 | 1696 | ||
1411 | if (userExposed) | 1697 | dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); |
1412 | dupe.m_rootPart.TrimPermissions(); | ||
1413 | 1698 | ||
1414 | List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); | 1699 | if (!userExposed) |
1415 | |||
1416 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | ||
1417 | { | 1700 | { |
1418 | return p1.LinkNum.CompareTo(p2.LinkNum); | 1701 | dupe.RootPart.IsAttachment = previousAttachmentStatus; |
1419 | } | 1702 | } |
1420 | ); | ||
1421 | 1703 | ||
1422 | foreach (SceneObjectPart part in partList) | 1704 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); |
1423 | { | 1705 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; |
1424 | if (part.UUID != m_rootPart.UUID) | 1706 | |
1707 | if (userExposed) | ||
1708 | dupe.m_rootPart.TrimPermissions(); | ||
1709 | |||
1710 | List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); | ||
1711 | |||
1712 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | ||
1713 | { | ||
1714 | return p1.LinkNum.CompareTo(p2.LinkNum); | ||
1715 | } | ||
1716 | ); | ||
1717 | |||
1718 | foreach (SceneObjectPart part in partList) | ||
1425 | { | 1719 | { |
1426 | SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); | 1720 | if (part.UUID != m_rootPart.UUID) |
1427 | newPart.LinkNum = part.LinkNum; | 1721 | { |
1428 | } | 1722 | SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); |
1429 | 1723 | ||
1430 | // Need to duplicate the physics actor as well | 1724 | newPart.LinkNum = part.LinkNum; |
1431 | if (part.PhysActor != null && userExposed) | 1725 | } |
1726 | |||
1727 | // Need to duplicate the physics actor as well | ||
1728 | if (part.PhysActor != null && userExposed) | ||
1729 | { | ||
1730 | PrimitiveBaseShape pbs = part.Shape; | ||
1731 | |||
1732 | part.PhysActor | ||
1733 | = m_scene.PhysicsScene.AddPrimShape( | ||
1734 | string.Format("{0}/{1}", part.Name, part.UUID), | ||
1735 | pbs, | ||
1736 | part.AbsolutePosition, | ||
1737 | part.Scale, | ||
1738 | part.RotationOffset, | ||
1739 | part.PhysActor.IsPhysical); | ||
1740 | |||
1741 | part.PhysActor.LocalID = part.LocalId; | ||
1742 | part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); | ||
1743 | } | ||
1744 | } | ||
1745 | if (userExposed) | ||
1432 | { | 1746 | { |
1433 | PrimitiveBaseShape pbs = part.Shape; | 1747 | dupe.UpdateParentIDs(); |
1434 | 1748 | dupe.HasGroupChanged = true; | |
1435 | part.PhysActor | 1749 | dupe.AttachToBackup(); |
1436 | = m_scene.PhysicsScene.AddPrimShape( | 1750 | |
1437 | string.Format("{0}/{1}", part.Name, part.UUID), | 1751 | 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 | } | 1752 | } |
1447 | } | 1753 | } |
1448 | 1754 | finally | |
1449 | if (userExposed) | ||
1450 | { | 1755 | { |
1451 | dupe.UpdateParentIDs(); | 1756 | m_dupeInProgress = false; |
1452 | dupe.HasGroupChanged = true; | ||
1453 | dupe.AttachToBackup(); | ||
1454 | |||
1455 | ScheduleGroupForFullUpdate(); | ||
1456 | } | 1757 | } |
1457 | |||
1458 | return dupe; | 1758 | return dupe; |
1459 | } | 1759 | } |
1460 | 1760 | ||
@@ -1645,13 +1945,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
1645 | } | 1945 | } |
1646 | } | 1946 | } |
1647 | 1947 | ||
1948 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
1949 | { | ||
1950 | SceneObjectPart rootpart = m_rootPart; | ||
1951 | if (rootpart != null) | ||
1952 | { | ||
1953 | if (IsAttachment) | ||
1954 | { | ||
1955 | /* | ||
1956 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
1957 | if (avatar != null) | ||
1958 | { | ||
1959 | Rotate the Av? | ||
1960 | } */ | ||
1961 | } | ||
1962 | else | ||
1963 | { | ||
1964 | if (rootpart.PhysActor != null) | ||
1965 | { // APID must be implemented in your physics system for this to function. | ||
1966 | rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); | ||
1967 | rootpart.PhysActor.APIDStrength = strength; | ||
1968 | rootpart.PhysActor.APIDDamping = damping; | ||
1969 | rootpart.PhysActor.APIDActive = true; | ||
1970 | } | ||
1971 | } | ||
1972 | } | ||
1973 | } | ||
1974 | |||
1648 | public void stopLookAt() | 1975 | public void stopLookAt() |
1649 | { | 1976 | { |
1650 | SceneObjectPart rootpart = m_rootPart; | 1977 | SceneObjectPart rootpart = m_rootPart; |
1651 | if (rootpart != null) | 1978 | if (rootpart != null) |
1652 | { | 1979 | { |
1653 | if (rootpart.PhysActor != null) | 1980 | if (rootpart.PhysActor != null) |
1654 | { | 1981 | { // APID must be implemented in your physics system for this to function. |
1655 | rootpart.PhysActor.APIDActive = false; | 1982 | rootpart.PhysActor.APIDActive = false; |
1656 | } | 1983 | } |
1657 | } | 1984 | } |
@@ -1717,6 +2044,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1717 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) | 2044 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) |
1718 | { | 2045 | { |
1719 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); | 2046 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); |
2047 | newPart.SetParent(this); | ||
2048 | |||
1720 | AddPart(newPart); | 2049 | AddPart(newPart); |
1721 | 2050 | ||
1722 | SetPartAsNonRoot(newPart); | 2051 | SetPartAsNonRoot(newPart); |
@@ -1863,11 +2192,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1863 | /// Immediately send a full update for this scene object. | 2192 | /// Immediately send a full update for this scene object. |
1864 | /// </summary> | 2193 | /// </summary> |
1865 | public void SendGroupFullUpdate() | 2194 | public void SendGroupFullUpdate() |
1866 | { | 2195 | { |
1867 | if (IsDeleted) | 2196 | if (IsDeleted) |
1868 | return; | 2197 | return; |
1869 | 2198 | ||
1870 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); | 2199 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); |
1871 | 2200 | ||
1872 | RootPart.SendFullUpdateToAllClients(); | 2201 | RootPart.SendFullUpdateToAllClients(); |
1873 | 2202 | ||
@@ -2056,12 +2385,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2056 | part.LinkNum += objectGroup.PrimCount; | 2385 | part.LinkNum += objectGroup.PrimCount; |
2057 | } | 2386 | } |
2058 | } | 2387 | } |
2388 | } | ||
2059 | 2389 | ||
2060 | linkPart.LinkNum = 2; | 2390 | linkPart.LinkNum = 2; |
2061 | 2391 | ||
2062 | linkPart.SetParent(this); | 2392 | linkPart.SetParent(this); |
2063 | linkPart.CreateSelected = true; | 2393 | linkPart.CreateSelected = true; |
2064 | 2394 | ||
2395 | lock (m_parts.SyncRoot) | ||
2396 | { | ||
2065 | //if (linkPart.PhysActor != null) | 2397 | //if (linkPart.PhysActor != null) |
2066 | //{ | 2398 | //{ |
2067 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); | 2399 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); |
@@ -2218,6 +2550,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2218 | /// <param name="objectGroup"></param> | 2550 | /// <param name="objectGroup"></param> |
2219 | public virtual void DetachFromBackup() | 2551 | public virtual void DetachFromBackup() |
2220 | { | 2552 | { |
2553 | m_scene.SceneGraph.FireDetachFromBackup(this); | ||
2554 | |||
2221 | if (m_isBackedUp) | 2555 | if (m_isBackedUp) |
2222 | m_scene.EventManager.OnBackup -= ProcessBackup; | 2556 | m_scene.EventManager.OnBackup -= ProcessBackup; |
2223 | 2557 | ||
@@ -2522,6 +2856,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2522 | } | 2856 | } |
2523 | } | 2857 | } |
2524 | 2858 | ||
2859 | |||
2860 | |||
2861 | /// <summary> | ||
2862 | /// Gets the number of parts | ||
2863 | /// </summary> | ||
2864 | /// <returns></returns> | ||
2865 | public int GetPartCount() | ||
2866 | { | ||
2867 | return Parts.Count(); | ||
2868 | } | ||
2869 | |||
2525 | /// <summary> | 2870 | /// <summary> |
2526 | /// Update the texture entry for this part | 2871 | /// Update the texture entry for this part |
2527 | /// </summary> | 2872 | /// </summary> |
@@ -2583,11 +2928,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2583 | scale.Y = m_scene.m_maxNonphys; | 2928 | scale.Y = m_scene.m_maxNonphys; |
2584 | if (scale.Z > m_scene.m_maxNonphys) | 2929 | if (scale.Z > m_scene.m_maxNonphys) |
2585 | scale.Z = m_scene.m_maxNonphys; | 2930 | scale.Z = m_scene.m_maxNonphys; |
2586 | |||
2587 | SceneObjectPart part = GetChildPart(localID); | 2931 | SceneObjectPart part = GetChildPart(localID); |
2588 | if (part != null) | 2932 | if (part != null) |
2589 | { | 2933 | { |
2590 | part.Resize(scale); | ||
2591 | if (part.PhysActor != null) | 2934 | if (part.PhysActor != null) |
2592 | { | 2935 | { |
2593 | if (part.PhysActor.IsPhysical) | 2936 | if (part.PhysActor.IsPhysical) |
@@ -2602,7 +2945,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2602 | part.PhysActor.Size = scale; | 2945 | part.PhysActor.Size = scale; |
2603 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); | 2946 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); |
2604 | } | 2947 | } |
2605 | //if (part.UUID != m_rootPart.UUID) | 2948 | part.Resize(scale); |
2606 | 2949 | ||
2607 | HasGroupChanged = true; | 2950 | HasGroupChanged = true; |
2608 | ScheduleGroupForFullUpdate(); | 2951 | ScheduleGroupForFullUpdate(); |
@@ -2624,7 +2967,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2624 | SceneObjectPart part = GetChildPart(localID); | 2967 | SceneObjectPart part = GetChildPart(localID); |
2625 | if (part != null) | 2968 | if (part != null) |
2626 | { | 2969 | { |
2627 | part.IgnoreUndoUpdate = true; | ||
2628 | if (scale.X > m_scene.m_maxNonphys) | 2970 | if (scale.X > m_scene.m_maxNonphys) |
2629 | scale.X = m_scene.m_maxNonphys; | 2971 | scale.X = m_scene.m_maxNonphys; |
2630 | if (scale.Y > m_scene.m_maxNonphys) | 2972 | if (scale.Y > m_scene.m_maxNonphys) |
@@ -2661,7 +3003,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2661 | 3003 | ||
2662 | if (part.PhysActor != null && part.PhysActor.IsPhysical) | 3004 | if (part.PhysActor != null && part.PhysActor.IsPhysical) |
2663 | { | 3005 | { |
2664 | if (oldSize.X * x > m_scene.m_maxPhys) | 3006 | if (oldSize.X*x > m_scene.m_maxPhys) |
2665 | { | 3007 | { |
2666 | f = m_scene.m_maxPhys / oldSize.X; | 3008 | f = m_scene.m_maxPhys / oldSize.X; |
2667 | a = f / x; | 3009 | a = f / x; |
@@ -2669,7 +3011,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2669 | y *= a; | 3011 | y *= a; |
2670 | z *= a; | 3012 | z *= a; |
2671 | } | 3013 | } |
2672 | if (oldSize.Y * y > m_scene.m_maxPhys) | 3014 | if (oldSize.Y*y > m_scene.m_maxPhys) |
2673 | { | 3015 | { |
2674 | f = m_scene.m_maxPhys / oldSize.Y; | 3016 | f = m_scene.m_maxPhys / oldSize.Y; |
2675 | a = f / y; | 3017 | a = f / y; |
@@ -2677,7 +3019,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2677 | y *= a; | 3019 | y *= a; |
2678 | z *= a; | 3020 | z *= a; |
2679 | } | 3021 | } |
2680 | if (oldSize.Z * z > m_scene.m_maxPhys) | 3022 | if (oldSize.Z*z > m_scene.m_maxPhys) |
2681 | { | 3023 | { |
2682 | f = m_scene.m_maxPhys / oldSize.Z; | 3024 | f = m_scene.m_maxPhys / oldSize.Z; |
2683 | a = f / z; | 3025 | a = f / z; |
@@ -2688,7 +3030,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2688 | } | 3030 | } |
2689 | else | 3031 | else |
2690 | { | 3032 | { |
2691 | if (oldSize.X * x > m_scene.m_maxNonphys) | 3033 | if (oldSize.X*x > m_scene.m_maxNonphys) |
2692 | { | 3034 | { |
2693 | f = m_scene.m_maxNonphys / oldSize.X; | 3035 | f = m_scene.m_maxNonphys / oldSize.X; |
2694 | a = f / x; | 3036 | a = f / x; |
@@ -2696,7 +3038,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2696 | y *= a; | 3038 | y *= a; |
2697 | z *= a; | 3039 | z *= a; |
2698 | } | 3040 | } |
2699 | if (oldSize.Y * y > m_scene.m_maxNonphys) | 3041 | if (oldSize.Y*y > m_scene.m_maxNonphys) |
2700 | { | 3042 | { |
2701 | f = m_scene.m_maxNonphys / oldSize.Y; | 3043 | f = m_scene.m_maxNonphys / oldSize.Y; |
2702 | a = f / y; | 3044 | a = f / y; |
@@ -2704,7 +3046,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2704 | y *= a; | 3046 | y *= a; |
2705 | z *= a; | 3047 | z *= a; |
2706 | } | 3048 | } |
2707 | if (oldSize.Z * z > m_scene.m_maxNonphys) | 3049 | if (oldSize.Z*z > m_scene.m_maxNonphys) |
2708 | { | 3050 | { |
2709 | f = m_scene.m_maxNonphys / oldSize.Z; | 3051 | f = m_scene.m_maxNonphys / oldSize.Z; |
2710 | a = f / z; | 3052 | a = f / z; |
@@ -2714,7 +3056,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2714 | } | 3056 | } |
2715 | } | 3057 | } |
2716 | obPart.IgnoreUndoUpdate = false; | 3058 | obPart.IgnoreUndoUpdate = false; |
2717 | obPart.StoreUndoState(); | ||
2718 | } | 3059 | } |
2719 | } | 3060 | } |
2720 | } | 3061 | } |
@@ -2722,8 +3063,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2722 | Vector3 prevScale = part.Scale; | 3063 | Vector3 prevScale = part.Scale; |
2723 | prevScale.X *= x; | 3064 | prevScale.X *= x; |
2724 | prevScale.Y *= y; | 3065 | prevScale.Y *= y; |
2725 | prevScale.Z *= z; | 3066 | prevScale.Z *= z;; |
3067 | |||
3068 | part.IgnoreUndoUpdate = false; | ||
3069 | part.StoreUndoState(UndoType.STATE_GROUP_SCALE); | ||
3070 | part.IgnoreUndoUpdate = true; | ||
2726 | part.Resize(prevScale); | 3071 | part.Resize(prevScale); |
3072 | part.IgnoreUndoUpdate = false; | ||
2727 | 3073 | ||
2728 | parts = m_parts.GetArray(); | 3074 | parts = m_parts.GetArray(); |
2729 | for (int i = 0; i < parts.Length; i++) | 3075 | for (int i = 0; i < parts.Length; i++) |
@@ -2732,19 +3078,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
2732 | obPart.IgnoreUndoUpdate = true; | 3078 | obPart.IgnoreUndoUpdate = true; |
2733 | if (obPart.UUID != m_rootPart.UUID) | 3079 | if (obPart.UUID != m_rootPart.UUID) |
2734 | { | 3080 | { |
2735 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); | 3081 | if (obPart.UUID != m_rootPart.UUID) |
2736 | currentpos.X *= x; | 3082 | { |
2737 | currentpos.Y *= y; | 3083 | obPart.IgnoreUndoUpdate = false; |
2738 | currentpos.Z *= z; | 3084 | obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE); |
2739 | Vector3 newSize = new Vector3(obPart.Scale); | 3085 | obPart.IgnoreUndoUpdate = true; |
2740 | newSize.X *= x; | 3086 | |
2741 | newSize.Y *= y; | 3087 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); |
2742 | newSize.Z *= z; | 3088 | currentpos.X *= x; |
2743 | obPart.Resize(newSize); | 3089 | currentpos.Y *= y; |
2744 | obPart.UpdateOffSet(currentpos); | 3090 | currentpos.Z *= z; |
3091 | Vector3 newSize = new Vector3(obPart.Scale); | ||
3092 | newSize.X *= x; | ||
3093 | newSize.Y *= y; | ||
3094 | newSize.Z *= z; | ||
3095 | obPart.Resize(newSize); | ||
3096 | obPart.UpdateOffSet(currentpos); | ||
3097 | } | ||
3098 | obPart.IgnoreUndoUpdate = false; | ||
2745 | } | 3099 | } |
2746 | obPart.IgnoreUndoUpdate = false; | 3100 | obPart.IgnoreUndoUpdate = false; |
2747 | obPart.StoreUndoState(); | ||
2748 | } | 3101 | } |
2749 | 3102 | ||
2750 | if (part.PhysActor != null) | 3103 | if (part.PhysActor != null) |
@@ -2754,7 +3107,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2754 | } | 3107 | } |
2755 | 3108 | ||
2756 | part.IgnoreUndoUpdate = false; | 3109 | part.IgnoreUndoUpdate = false; |
2757 | part.StoreUndoState(); | ||
2758 | HasGroupChanged = true; | 3110 | HasGroupChanged = true; |
2759 | ScheduleGroupForTerseUpdate(); | 3111 | ScheduleGroupForTerseUpdate(); |
2760 | } | 3112 | } |
@@ -2770,14 +3122,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2770 | /// <param name="pos"></param> | 3122 | /// <param name="pos"></param> |
2771 | public void UpdateGroupPosition(Vector3 pos) | 3123 | public void UpdateGroupPosition(Vector3 pos) |
2772 | { | 3124 | { |
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)) | 3125 | if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) |
2778 | { | 3126 | { |
2779 | if (IsAttachment) | 3127 | if (IsAttachment) |
2780 | { | 3128 | { |
3129 | m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION); | ||
2781 | m_rootPart.AttachedPos = pos; | 3130 | m_rootPart.AttachedPos = pos; |
2782 | } | 3131 | } |
2783 | if (RootPart.GetStatusSandbox()) | 3132 | if (RootPart.GetStatusSandbox()) |
@@ -2811,7 +3160,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2811 | 3160 | ||
2812 | SceneObjectPart[] parts = m_parts.GetArray(); | 3161 | SceneObjectPart[] parts = m_parts.GetArray(); |
2813 | for (int i = 0; i < parts.Length; i++) | 3162 | for (int i = 0; i < parts.Length; i++) |
2814 | parts[i].StoreUndoState(); | 3163 | parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION); |
2815 | 3164 | ||
2816 | if (part != null) | 3165 | if (part != null) |
2817 | { | 3166 | { |
@@ -2836,7 +3185,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2836 | { | 3185 | { |
2837 | SceneObjectPart[] parts = m_parts.GetArray(); | 3186 | SceneObjectPart[] parts = m_parts.GetArray(); |
2838 | for (int i = 0; i < parts.Length; i++) | 3187 | for (int i = 0; i < parts.Length; i++) |
2839 | parts[i].StoreUndoState(); | 3188 | parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION); |
2840 | 3189 | ||
2841 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | 3190 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); |
2842 | Vector3 oldPos = | 3191 | Vector3 oldPos = |
@@ -2857,10 +3206,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
2857 | obPart.OffsetPosition = obPart.OffsetPosition + diff; | 3206 | obPart.OffsetPosition = obPart.OffsetPosition + diff; |
2858 | } | 3207 | } |
2859 | 3208 | ||
2860 | AbsolutePosition = newPos; | 3209 | //We have to set undoing here because otherwise an undo state will be saved |
3210 | if (!m_rootPart.Undoing) | ||
3211 | { | ||
3212 | m_rootPart.Undoing = true; | ||
3213 | AbsolutePosition = newPos; | ||
3214 | m_rootPart.Undoing = false; | ||
3215 | } | ||
3216 | else | ||
3217 | { | ||
3218 | AbsolutePosition = newPos; | ||
3219 | } | ||
2861 | 3220 | ||
2862 | HasGroupChanged = true; | 3221 | HasGroupChanged = true; |
2863 | ScheduleGroupForTerseUpdate(); | 3222 | if (m_rootPart.Undoing) |
3223 | { | ||
3224 | ScheduleGroupForFullUpdate(); | ||
3225 | } | ||
3226 | else | ||
3227 | { | ||
3228 | ScheduleGroupForTerseUpdate(); | ||
3229 | } | ||
2864 | } | 3230 | } |
2865 | 3231 | ||
2866 | public void OffsetForNewRegion(Vector3 offset) | 3232 | public void OffsetForNewRegion(Vector3 offset) |
@@ -2880,7 +3246,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2880 | { | 3246 | { |
2881 | SceneObjectPart[] parts = m_parts.GetArray(); | 3247 | SceneObjectPart[] parts = m_parts.GetArray(); |
2882 | for (int i = 0; i < parts.Length; i++) | 3248 | for (int i = 0; i < parts.Length; i++) |
2883 | parts[i].StoreUndoState(); | 3249 | parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION); |
2884 | 3250 | ||
2885 | m_rootPart.UpdateRotation(rot); | 3251 | m_rootPart.UpdateRotation(rot); |
2886 | 3252 | ||
@@ -2904,7 +3270,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2904 | { | 3270 | { |
2905 | SceneObjectPart[] parts = m_parts.GetArray(); | 3271 | SceneObjectPart[] parts = m_parts.GetArray(); |
2906 | for (int i = 0; i < parts.Length; i++) | 3272 | for (int i = 0; i < parts.Length; i++) |
2907 | parts[i].StoreUndoState(); | 3273 | parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION); |
2908 | 3274 | ||
2909 | m_rootPart.UpdateRotation(rot); | 3275 | m_rootPart.UpdateRotation(rot); |
2910 | 3276 | ||
@@ -2929,10 +3295,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2929 | public void UpdateSingleRotation(Quaternion rot, uint localID) | 3295 | public void UpdateSingleRotation(Quaternion rot, uint localID) |
2930 | { | 3296 | { |
2931 | SceneObjectPart part = GetChildPart(localID); | 3297 | SceneObjectPart part = GetChildPart(localID); |
2932 | |||
2933 | SceneObjectPart[] parts = m_parts.GetArray(); | 3298 | SceneObjectPart[] parts = m_parts.GetArray(); |
2934 | for (int i = 0; i < parts.Length; i++) | 3299 | for (int i = 0; i < parts.Length; i++) |
2935 | parts[i].StoreUndoState(); | 3300 | parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION); |
2936 | 3301 | ||
2937 | if (part != null) | 3302 | if (part != null) |
2938 | { | 3303 | { |
@@ -2960,15 +3325,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
2960 | if (part.UUID == m_rootPart.UUID) | 3325 | if (part.UUID == m_rootPart.UUID) |
2961 | { | 3326 | { |
2962 | UpdateRootRotation(rot); | 3327 | UpdateRootRotation(rot); |
2963 | AbsolutePosition = pos; | 3328 | if (!m_rootPart.Undoing) |
3329 | { | ||
3330 | m_rootPart.Undoing = true; | ||
3331 | AbsolutePosition = pos; | ||
3332 | m_rootPart.Undoing = false; | ||
3333 | } | ||
3334 | else | ||
3335 | { | ||
3336 | AbsolutePosition = pos; | ||
3337 | } | ||
2964 | } | 3338 | } |
2965 | else | 3339 | else |
2966 | { | 3340 | { |
3341 | part.StoreUndoState(UndoType.STATE_PRIM_ROTATION); | ||
2967 | part.IgnoreUndoUpdate = true; | 3342 | part.IgnoreUndoUpdate = true; |
2968 | part.UpdateRotation(rot); | 3343 | part.UpdateRotation(rot); |
2969 | part.OffsetPosition = pos; | 3344 | part.OffsetPosition = pos; |
2970 | part.IgnoreUndoUpdate = false; | 3345 | part.IgnoreUndoUpdate = false; |
2971 | part.StoreUndoState(); | ||
2972 | } | 3346 | } |
2973 | } | 3347 | } |
2974 | } | 3348 | } |
@@ -2982,7 +3356,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2982 | Quaternion axRot = rot; | 3356 | Quaternion axRot = rot; |
2983 | Quaternion oldParentRot = m_rootPart.RotationOffset; | 3357 | Quaternion oldParentRot = m_rootPart.RotationOffset; |
2984 | 3358 | ||
2985 | m_rootPart.StoreUndoState(); | 3359 | m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION); |
3360 | bool cancelUndo = false; | ||
3361 | if (!m_rootPart.Undoing) | ||
3362 | { | ||
3363 | m_rootPart.Undoing = true; | ||
3364 | cancelUndo = true; | ||
3365 | } | ||
2986 | m_rootPart.UpdateRotation(rot); | 3366 | m_rootPart.UpdateRotation(rot); |
2987 | if (m_rootPart.PhysActor != null) | 3367 | if (m_rootPart.PhysActor != null) |
2988 | { | 3368 | { |
@@ -3006,17 +3386,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3006 | newRot *= Quaternion.Inverse(axRot); | 3386 | newRot *= Quaternion.Inverse(axRot); |
3007 | prim.RotationOffset = newRot; | 3387 | prim.RotationOffset = newRot; |
3008 | prim.ScheduleTerseUpdate(); | 3388 | prim.ScheduleTerseUpdate(); |
3389 | prim.IgnoreUndoUpdate = false; | ||
3009 | } | 3390 | } |
3010 | } | 3391 | } |
3011 | 3392 | if (cancelUndo == true) | |
3012 | for (int i = 0; i < parts.Length; i++) | ||
3013 | { | 3393 | { |
3014 | SceneObjectPart childpart = parts[i]; | 3394 | m_rootPart.Undoing = false; |
3015 | if (childpart != m_rootPart) | ||
3016 | { | ||
3017 | childpart.IgnoreUndoUpdate = false; | ||
3018 | childpart.StoreUndoState(); | ||
3019 | } | ||
3020 | } | 3395 | } |
3021 | 3396 | ||
3022 | m_rootPart.ScheduleTerseUpdate(); | 3397 | m_rootPart.ScheduleTerseUpdate(); |
@@ -3242,7 +3617,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3242 | public float GetMass() | 3617 | public float GetMass() |
3243 | { | 3618 | { |
3244 | float retmass = 0f; | 3619 | float retmass = 0f; |
3245 | |||
3246 | SceneObjectPart[] parts = m_parts.GetArray(); | 3620 | SceneObjectPart[] parts = m_parts.GetArray(); |
3247 | for (int i = 0; i < parts.Length; i++) | 3621 | for (int i = 0; i < parts.Length; i++) |
3248 | retmass += parts[i].GetMass(); | 3622 | retmass += parts[i].GetMass(); |
@@ -3358,6 +3732,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3358 | SetFromItemID(uuid); | 3732 | SetFromItemID(uuid); |
3359 | } | 3733 | } |
3360 | 3734 | ||
3735 | public void ResetOwnerChangeFlag() | ||
3736 | { | ||
3737 | ForEachPart(delegate(SceneObjectPart part) | ||
3738 | { | ||
3739 | part.ResetOwnerChangeFlag(); | ||
3740 | }); | ||
3741 | } | ||
3742 | |||
3361 | #endregion | 3743 | #endregion |
3362 | } | 3744 | } |
3363 | } | 3745 | } |