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 4ec530e..f3964c2 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 | ||
@@ -522,6 +617,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
522 | /// </summary> | 617 | /// </summary> |
523 | public virtual void AttachToBackup() | 618 | public virtual void AttachToBackup() |
524 | { | 619 | { |
620 | if (IsAttachment) return; | ||
621 | m_scene.SceneGraph.FireAttachToBackup(this); | ||
622 | |||
525 | if (InSceneBackup) | 623 | if (InSceneBackup) |
526 | { | 624 | { |
527 | //m_log.DebugFormat( | 625 | //m_log.DebugFormat( |
@@ -637,9 +735,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
637 | result.normal = inter.normal; | 735 | result.normal = inter.normal; |
638 | result.distance = inter.distance; | 736 | result.distance = inter.distance; |
639 | } | 737 | } |
738 | |||
640 | } | 739 | } |
641 | } | 740 | } |
642 | |||
643 | return result; | 741 | return result; |
644 | } | 742 | } |
645 | 743 | ||
@@ -659,17 +757,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
659 | minZ = 8192f; | 757 | minZ = 8192f; |
660 | 758 | ||
661 | SceneObjectPart[] parts = m_parts.GetArray(); | 759 | SceneObjectPart[] parts = m_parts.GetArray(); |
662 | for (int i = 0; i < parts.Length; i++) | 760 | foreach (SceneObjectPart part in parts) |
663 | { | 761 | { |
664 | SceneObjectPart part = parts[i]; | ||
665 | |||
666 | Vector3 worldPos = part.GetWorldPosition(); | 762 | Vector3 worldPos = part.GetWorldPosition(); |
667 | Vector3 offset = worldPos - AbsolutePosition; | 763 | Vector3 offset = worldPos - AbsolutePosition; |
668 | Quaternion worldRot; | 764 | Quaternion worldRot; |
669 | if (part.ParentID == 0) | 765 | if (part.ParentID == 0) |
766 | { | ||
670 | worldRot = part.RotationOffset; | 767 | worldRot = part.RotationOffset; |
768 | } | ||
671 | else | 769 | else |
770 | { | ||
672 | worldRot = part.GetWorldRotation(); | 771 | worldRot = part.GetWorldRotation(); |
772 | } | ||
673 | 773 | ||
674 | Vector3 frontTopLeft; | 774 | Vector3 frontTopLeft; |
675 | Vector3 frontTopRight; | 775 | Vector3 frontTopRight; |
@@ -681,6 +781,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
681 | Vector3 backBottomLeft; | 781 | Vector3 backBottomLeft; |
682 | Vector3 backBottomRight; | 782 | Vector3 backBottomRight; |
683 | 783 | ||
784 | // Vector3[] corners = new Vector3[8]; | ||
785 | |||
684 | Vector3 orig = Vector3.Zero; | 786 | Vector3 orig = Vector3.Zero; |
685 | 787 | ||
686 | frontTopLeft.X = orig.X - (part.Scale.X / 2); | 788 | frontTopLeft.X = orig.X - (part.Scale.X / 2); |
@@ -715,6 +817,38 @@ namespace OpenSim.Region.Framework.Scenes | |||
715 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); | 817 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); |
716 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); | 818 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); |
717 | 819 | ||
820 | |||
821 | |||
822 | //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); | ||
823 | //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); | ||
824 | //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); | ||
825 | //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z); | ||
826 | //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z); | ||
827 | //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z); | ||
828 | //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z); | ||
829 | //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z); | ||
830 | |||
831 | //for (int i = 0; i < 8; i++) | ||
832 | //{ | ||
833 | // corners[i] = corners[i] * worldRot; | ||
834 | // corners[i] += offset; | ||
835 | |||
836 | // if (corners[i].X > maxX) | ||
837 | // maxX = corners[i].X; | ||
838 | // if (corners[i].X < minX) | ||
839 | // minX = corners[i].X; | ||
840 | |||
841 | // if (corners[i].Y > maxY) | ||
842 | // maxY = corners[i].Y; | ||
843 | // if (corners[i].Y < minY) | ||
844 | // minY = corners[i].Y; | ||
845 | |||
846 | // if (corners[i].Z > maxZ) | ||
847 | // maxZ = corners[i].Y; | ||
848 | // if (corners[i].Z < minZ) | ||
849 | // minZ = corners[i].Z; | ||
850 | //} | ||
851 | |||
718 | frontTopLeft = frontTopLeft * worldRot; | 852 | frontTopLeft = frontTopLeft * worldRot; |
719 | frontTopRight = frontTopRight * worldRot; | 853 | frontTopRight = frontTopRight * worldRot; |
720 | frontBottomLeft = frontBottomLeft * worldRot; | 854 | frontBottomLeft = frontBottomLeft * worldRot; |
@@ -736,6 +870,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
736 | backTopLeft += offset; | 870 | backTopLeft += offset; |
737 | backTopRight += offset; | 871 | backTopRight += offset; |
738 | 872 | ||
873 | //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); | ||
874 | //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); | ||
875 | //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); | ||
876 | //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z); | ||
877 | //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z); | ||
878 | //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z); | ||
879 | //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z); | ||
880 | //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z); | ||
881 | |||
739 | if (frontTopRight.X > maxX) | 882 | if (frontTopRight.X > maxX) |
740 | maxX = frontTopRight.X; | 883 | maxX = frontTopRight.X; |
741 | if (frontTopLeft.X > maxX) | 884 | if (frontTopLeft.X > maxX) |
@@ -881,15 +1024,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
881 | 1024 | ||
882 | public void SaveScriptedState(XmlTextWriter writer) | 1025 | public void SaveScriptedState(XmlTextWriter writer) |
883 | { | 1026 | { |
1027 | SaveScriptedState(writer, false); | ||
1028 | } | ||
1029 | |||
1030 | public void SaveScriptedState(XmlTextWriter writer, bool oldIDs) | ||
1031 | { | ||
884 | XmlDocument doc = new XmlDocument(); | 1032 | XmlDocument doc = new XmlDocument(); |
885 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); | 1033 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); |
886 | 1034 | ||
887 | SceneObjectPart[] parts = m_parts.GetArray(); | 1035 | SceneObjectPart[] parts = m_parts.GetArray(); |
888 | for (int i = 0; i < parts.Length; i++) | 1036 | for (int i = 0; i < parts.Length; i++) |
889 | { | 1037 | { |
890 | Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); | 1038 | Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs); |
891 | foreach (KeyValuePair<UUID, string> kvp in pstates) | 1039 | foreach (KeyValuePair<UUID, string> kvp in pstates) |
892 | states.Add(kvp.Key, kvp.Value); | 1040 | states[kvp.Key] = kvp.Value; |
893 | } | 1041 | } |
894 | 1042 | ||
895 | if (states.Count > 0) | 1043 | if (states.Count > 0) |
@@ -908,6 +1056,118 @@ namespace OpenSim.Region.Framework.Scenes | |||
908 | } | 1056 | } |
909 | } | 1057 | } |
910 | 1058 | ||
1059 | /// <summary> | ||
1060 | /// Add the avatar to this linkset (avatar is sat). | ||
1061 | /// </summary> | ||
1062 | /// <param name="agentID"></param> | ||
1063 | public void AddAvatar(UUID agentID) | ||
1064 | { | ||
1065 | ScenePresence presence; | ||
1066 | if (m_scene.TryGetScenePresence(agentID, out presence)) | ||
1067 | { | ||
1068 | if (!m_linkedAvatars.Contains(presence)) | ||
1069 | { | ||
1070 | m_linkedAvatars.Add(presence); | ||
1071 | } | ||
1072 | } | ||
1073 | } | ||
1074 | |||
1075 | /// <summary> | ||
1076 | /// Delete the avatar from this linkset (avatar is unsat). | ||
1077 | /// </summary> | ||
1078 | /// <param name="agentID"></param> | ||
1079 | public void DeleteAvatar(UUID agentID) | ||
1080 | { | ||
1081 | ScenePresence presence; | ||
1082 | if (m_scene.TryGetScenePresence(agentID, out presence)) | ||
1083 | { | ||
1084 | if (m_linkedAvatars.Contains(presence)) | ||
1085 | { | ||
1086 | m_linkedAvatars.Remove(presence); | ||
1087 | } | ||
1088 | } | ||
1089 | } | ||
1090 | |||
1091 | /// <summary> | ||
1092 | /// Returns the list of linked presences (avatars sat on this group) | ||
1093 | /// </summary> | ||
1094 | /// <param name="agentID"></param> | ||
1095 | public List<ScenePresence> GetLinkedAvatars() | ||
1096 | { | ||
1097 | return m_linkedAvatars; | ||
1098 | } | ||
1099 | |||
1100 | /// <summary> | ||
1101 | /// Attach this scene object to the given avatar. | ||
1102 | /// </summary> | ||
1103 | /// <param name="agentID"></param> | ||
1104 | /// <param name="attachmentpoint"></param> | ||
1105 | /// <param name="AttachOffset"></param> | ||
1106 | public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent) | ||
1107 | { | ||
1108 | ScenePresence avatar = m_scene.GetScenePresence(agentID); | ||
1109 | if (avatar != null) | ||
1110 | { | ||
1111 | // don't attach attachments to child agents | ||
1112 | if (avatar.IsChildAgent) return; | ||
1113 | |||
1114 | // m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name); | ||
1115 | |||
1116 | DetachFromBackup(); | ||
1117 | |||
1118 | // Remove from database and parcel prim count | ||
1119 | m_scene.DeleteFromStorage(UUID); | ||
1120 | m_scene.EventManager.TriggerParcelPrimCountTainted(); | ||
1121 | |||
1122 | m_rootPart.AttachedAvatar = agentID; | ||
1123 | |||
1124 | //Anakin Lohner bug #3839 | ||
1125 | lock (m_parts) | ||
1126 | { | ||
1127 | foreach (SceneObjectPart p in m_parts.GetArray()) | ||
1128 | { | ||
1129 | p.AttachedAvatar = agentID; | ||
1130 | } | ||
1131 | } | ||
1132 | |||
1133 | if (m_rootPart.PhysActor != null) | ||
1134 | { | ||
1135 | m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor); | ||
1136 | m_rootPart.PhysActor = null; | ||
1137 | } | ||
1138 | |||
1139 | AbsolutePosition = AttachOffset; | ||
1140 | m_rootPart.AttachedPos = AttachOffset; | ||
1141 | m_rootPart.IsAttachment = true; | ||
1142 | |||
1143 | m_rootPart.SetParentLocalId(avatar.LocalId); | ||
1144 | SetAttachmentPoint(Convert.ToByte(attachmentpoint)); | ||
1145 | |||
1146 | avatar.AddAttachment(this); | ||
1147 | |||
1148 | if (!silent) | ||
1149 | { | ||
1150 | // Killing it here will cause the client to deselect it | ||
1151 | // It then reappears on the avatar, deselected | ||
1152 | // through the full update below | ||
1153 | // | ||
1154 | if (IsSelected) | ||
1155 | { | ||
1156 | m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId }); | ||
1157 | } | ||
1158 | |||
1159 | IsSelected = false; // fudge.... | ||
1160 | ScheduleGroupForFullUpdate(); | ||
1161 | } | ||
1162 | } | ||
1163 | else | ||
1164 | { | ||
1165 | m_log.WarnFormat( | ||
1166 | "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present", | ||
1167 | UUID, agentID, Scene.RegionInfo.RegionName); | ||
1168 | } | ||
1169 | } | ||
1170 | |||
911 | public byte GetAttachmentPoint() | 1171 | public byte GetAttachmentPoint() |
912 | { | 1172 | { |
913 | return m_rootPart.Shape.State; | 1173 | return m_rootPart.Shape.State; |
@@ -1034,7 +1294,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1034 | public void AddPart(SceneObjectPart part) | 1294 | public void AddPart(SceneObjectPart part) |
1035 | { | 1295 | { |
1036 | part.SetParent(this); | 1296 | part.SetParent(this); |
1037 | part.LinkNum = m_parts.Add(part.UUID, part); | 1297 | m_parts.Add(part.UUID, part); |
1298 | |||
1299 | part.LinkNum = m_parts.Count; | ||
1300 | |||
1038 | if (part.LinkNum == 2 && RootPart != null) | 1301 | if (part.LinkNum == 2 && RootPart != null) |
1039 | RootPart.LinkNum = 1; | 1302 | RootPart.LinkNum = 1; |
1040 | } | 1303 | } |
@@ -1118,7 +1381,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1118 | 1381 | ||
1119 | public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) | 1382 | public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) |
1120 | { | 1383 | { |
1121 | part.StoreUndoState(); | 1384 | part.StoreUndoState(UndoType.STATE_PRIM_ALL); |
1122 | part.OnGrab(offsetPos, remoteClient); | 1385 | part.OnGrab(offsetPos, remoteClient); |
1123 | } | 1386 | } |
1124 | 1387 | ||
@@ -1138,6 +1401,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1138 | /// <param name="silent">If true then deletion is not broadcast to clients</param> | 1401 | /// <param name="silent">If true then deletion is not broadcast to clients</param> |
1139 | public void DeleteGroupFromScene(bool silent) | 1402 | public void DeleteGroupFromScene(bool silent) |
1140 | { | 1403 | { |
1404 | // We need to keep track of this state in case this group is still queued for backup. | ||
1405 | m_isDeleted = true; | ||
1406 | |||
1407 | DetachFromBackup(); | ||
1408 | |||
1141 | SceneObjectPart[] parts = m_parts.GetArray(); | 1409 | SceneObjectPart[] parts = m_parts.GetArray(); |
1142 | for (int i = 0; i < parts.Length; i++) | 1410 | for (int i = 0; i < parts.Length; i++) |
1143 | { | 1411 | { |
@@ -1149,13 +1417,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1149 | avatar.StandUp(); | 1417 | avatar.StandUp(); |
1150 | 1418 | ||
1151 | if (!silent) | 1419 | if (!silent) |
1152 | { | ||
1153 | part.UpdateFlag = 0; | 1420 | part.UpdateFlag = 0; |
1154 | if (part == m_rootPart) | ||
1155 | avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); | ||
1156 | } | ||
1157 | }); | 1421 | }); |
1158 | } | 1422 | } |
1423 | |||
1424 | |||
1159 | } | 1425 | } |
1160 | 1426 | ||
1161 | public void AddScriptLPS(int count) | 1427 | public void AddScriptLPS(int count) |
@@ -1252,7 +1518,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1252 | 1518 | ||
1253 | public void SetOwnerId(UUID userId) | 1519 | public void SetOwnerId(UUID userId) |
1254 | { | 1520 | { |
1255 | ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); | 1521 | ForEachPart(delegate(SceneObjectPart part) |
1522 | { | ||
1523 | |||
1524 | part.OwnerID = userId; | ||
1525 | |||
1526 | }); | ||
1256 | } | 1527 | } |
1257 | 1528 | ||
1258 | public void ForEachPart(Action<SceneObjectPart> whatToDo) | 1529 | public void ForEachPart(Action<SceneObjectPart> whatToDo) |
@@ -1284,11 +1555,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1284 | return; | 1555 | return; |
1285 | } | 1556 | } |
1286 | 1557 | ||
1558 | if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) | ||
1559 | return; | ||
1560 | |||
1287 | // Since this is the top of the section of call stack for backing up a particular scene object, don't let | 1561 | // Since this is the top of the section of call stack for backing up a particular scene object, don't let |
1288 | // any exception propogate upwards. | 1562 | // any exception propogate upwards. |
1289 | try | 1563 | try |
1290 | { | 1564 | { |
1291 | if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart | 1565 | if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart |
1566 | m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things | ||
1567 | m_scene.LoadingPrims) // Land may not be valid yet | ||
1568 | |||
1292 | { | 1569 | { |
1293 | ILandObject parcel = m_scene.LandChannel.GetLandObject( | 1570 | ILandObject parcel = m_scene.LandChannel.GetLandObject( |
1294 | m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); | 1571 | m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); |
@@ -1313,6 +1590,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1313 | } | 1590 | } |
1314 | } | 1591 | } |
1315 | } | 1592 | } |
1593 | |||
1316 | } | 1594 | } |
1317 | 1595 | ||
1318 | if (HasGroupChanged) | 1596 | if (HasGroupChanged) |
@@ -1320,6 +1598,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
1320 | // don't backup while it's selected or you're asking for changes mid stream. | 1598 | // don't backup while it's selected or you're asking for changes mid stream. |
1321 | if (isTimeToPersist() || forcedBackup) | 1599 | if (isTimeToPersist() || forcedBackup) |
1322 | { | 1600 | { |
1601 | if (m_rootPart.PhysActor != null && | ||
1602 | (!m_rootPart.PhysActor.IsPhysical)) | ||
1603 | { | ||
1604 | // Possible ghost prim | ||
1605 | if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition) | ||
1606 | { | ||
1607 | foreach (SceneObjectPart part in m_parts.GetArray()) | ||
1608 | { | ||
1609 | // Re-set physics actor positions and | ||
1610 | // orientations | ||
1611 | part.GroupPosition = m_rootPart.GroupPosition; | ||
1612 | } | ||
1613 | } | ||
1614 | } | ||
1323 | // m_log.DebugFormat( | 1615 | // m_log.DebugFormat( |
1324 | // "[SCENE]: Storing {0}, {1} in {2}", | 1616 | // "[SCENE]: Storing {0}, {1} in {2}", |
1325 | // Name, UUID, m_scene.RegionInfo.RegionName); | 1617 | // Name, UUID, m_scene.RegionInfo.RegionName); |
@@ -1382,81 +1674,89 @@ namespace OpenSim.Region.Framework.Scenes | |||
1382 | /// <returns></returns> | 1674 | /// <returns></returns> |
1383 | public SceneObjectGroup Copy(bool userExposed) | 1675 | public SceneObjectGroup Copy(bool userExposed) |
1384 | { | 1676 | { |
1385 | SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); | 1677 | SceneObjectGroup dupe; |
1386 | dupe.m_isBackedUp = false; | 1678 | try |
1387 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); | 1679 | { |
1388 | 1680 | m_dupeInProgress = true; | |
1389 | // Warning, The following code related to previousAttachmentStatus is needed so that clones of | 1681 | dupe = (SceneObjectGroup)MemberwiseClone(); |
1390 | // attachments do not bordercross while they're being duplicated. This is hacktastic! | 1682 | dupe.m_isBackedUp = false; |
1391 | // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! | 1683 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); |
1392 | // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state | ||
1393 | // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, | ||
1394 | // then restore it's attachment state | ||
1395 | |||
1396 | // This is only necessary when userExposed is false! | ||
1397 | 1684 | ||
1398 | bool previousAttachmentStatus = dupe.RootPart.IsAttachment; | 1685 | // Warning, The following code related to previousAttachmentStatus is needed so that clones of |
1399 | 1686 | // attachments do not bordercross while they're being duplicated. This is hacktastic! | |
1400 | if (!userExposed) | 1687 | // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! |
1401 | dupe.RootPart.IsAttachment = true; | 1688 | // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state |
1689 | // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, | ||
1690 | // then restore it's attachment state | ||
1402 | 1691 | ||
1403 | dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); | 1692 | // This is only necessary when userExposed is false! |
1404 | 1693 | ||
1405 | if (!userExposed) | 1694 | bool previousAttachmentStatus = dupe.RootPart.IsAttachment; |
1406 | { | ||
1407 | dupe.RootPart.IsAttachment = previousAttachmentStatus; | ||
1408 | } | ||
1409 | 1695 | ||
1410 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); | 1696 | if (!userExposed) |
1411 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; | 1697 | dupe.RootPart.IsAttachment = true; |
1412 | 1698 | ||
1413 | if (userExposed) | 1699 | dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); |
1414 | dupe.m_rootPart.TrimPermissions(); | ||
1415 | 1700 | ||
1416 | List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); | 1701 | if (!userExposed) |
1417 | |||
1418 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | ||
1419 | { | 1702 | { |
1420 | return p1.LinkNum.CompareTo(p2.LinkNum); | 1703 | dupe.RootPart.IsAttachment = previousAttachmentStatus; |
1421 | } | 1704 | } |
1422 | ); | ||
1423 | 1705 | ||
1424 | foreach (SceneObjectPart part in partList) | 1706 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); |
1425 | { | 1707 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; |
1426 | if (part.UUID != m_rootPart.UUID) | 1708 | |
1709 | if (userExposed) | ||
1710 | dupe.m_rootPart.TrimPermissions(); | ||
1711 | |||
1712 | List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); | ||
1713 | |||
1714 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | ||
1715 | { | ||
1716 | return p1.LinkNum.CompareTo(p2.LinkNum); | ||
1717 | } | ||
1718 | ); | ||
1719 | |||
1720 | foreach (SceneObjectPart part in partList) | ||
1427 | { | 1721 | { |
1428 | SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); | 1722 | if (part.UUID != m_rootPart.UUID) |
1429 | newPart.LinkNum = part.LinkNum; | 1723 | { |
1430 | } | 1724 | SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); |
1431 | 1725 | ||
1432 | // Need to duplicate the physics actor as well | 1726 | newPart.LinkNum = part.LinkNum; |
1433 | if (part.PhysActor != null && userExposed) | 1727 | } |
1728 | |||
1729 | // Need to duplicate the physics actor as well | ||
1730 | if (part.PhysActor != null && userExposed) | ||
1731 | { | ||
1732 | PrimitiveBaseShape pbs = part.Shape; | ||
1733 | |||
1734 | part.PhysActor | ||
1735 | = m_scene.PhysicsScene.AddPrimShape( | ||
1736 | string.Format("{0}/{1}", part.Name, part.UUID), | ||
1737 | pbs, | ||
1738 | part.AbsolutePosition, | ||
1739 | part.Scale, | ||
1740 | part.RotationOffset, | ||
1741 | part.PhysActor.IsPhysical); | ||
1742 | |||
1743 | part.PhysActor.LocalID = part.LocalId; | ||
1744 | part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); | ||
1745 | } | ||
1746 | } | ||
1747 | if (userExposed) | ||
1434 | { | 1748 | { |
1435 | PrimitiveBaseShape pbs = part.Shape; | 1749 | dupe.UpdateParentIDs(); |
1436 | 1750 | dupe.HasGroupChanged = true; | |
1437 | part.PhysActor | 1751 | dupe.AttachToBackup(); |
1438 | = m_scene.PhysicsScene.AddPrimShape( | 1752 | |
1439 | string.Format("{0}/{1}", part.Name, part.UUID), | 1753 | ScheduleGroupForFullUpdate(); |
1440 | pbs, | ||
1441 | part.AbsolutePosition, | ||
1442 | part.Scale, | ||
1443 | part.RotationOffset, | ||
1444 | part.PhysActor.IsPhysical); | ||
1445 | |||
1446 | part.PhysActor.LocalID = part.LocalId; | ||
1447 | part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); | ||
1448 | } | 1754 | } |
1449 | } | 1755 | } |
1450 | 1756 | finally | |
1451 | if (userExposed) | ||
1452 | { | 1757 | { |
1453 | dupe.UpdateParentIDs(); | 1758 | m_dupeInProgress = false; |
1454 | dupe.HasGroupChanged = true; | ||
1455 | dupe.AttachToBackup(); | ||
1456 | |||
1457 | ScheduleGroupForFullUpdate(); | ||
1458 | } | 1759 | } |
1459 | |||
1460 | return dupe; | 1760 | return dupe; |
1461 | } | 1761 | } |
1462 | 1762 | ||
@@ -1647,13 +1947,40 @@ namespace OpenSim.Region.Framework.Scenes | |||
1647 | } | 1947 | } |
1648 | } | 1948 | } |
1649 | 1949 | ||
1950 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
1951 | { | ||
1952 | SceneObjectPart rootpart = m_rootPart; | ||
1953 | if (rootpart != null) | ||
1954 | { | ||
1955 | if (IsAttachment) | ||
1956 | { | ||
1957 | /* | ||
1958 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
1959 | if (avatar != null) | ||
1960 | { | ||
1961 | Rotate the Av? | ||
1962 | } */ | ||
1963 | } | ||
1964 | else | ||
1965 | { | ||
1966 | if (rootpart.PhysActor != null) | ||
1967 | { // APID must be implemented in your physics system for this to function. | ||
1968 | rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); | ||
1969 | rootpart.PhysActor.APIDStrength = strength; | ||
1970 | rootpart.PhysActor.APIDDamping = damping; | ||
1971 | rootpart.PhysActor.APIDActive = true; | ||
1972 | } | ||
1973 | } | ||
1974 | } | ||
1975 | } | ||
1976 | |||
1650 | public void stopLookAt() | 1977 | public void stopLookAt() |
1651 | { | 1978 | { |
1652 | SceneObjectPart rootpart = m_rootPart; | 1979 | SceneObjectPart rootpart = m_rootPart; |
1653 | if (rootpart != null) | 1980 | if (rootpart != null) |
1654 | { | 1981 | { |
1655 | if (rootpart.PhysActor != null) | 1982 | if (rootpart.PhysActor != null) |
1656 | { | 1983 | { // APID must be implemented in your physics system for this to function. |
1657 | rootpart.PhysActor.APIDActive = false; | 1984 | rootpart.PhysActor.APIDActive = false; |
1658 | } | 1985 | } |
1659 | } | 1986 | } |
@@ -1719,6 +2046,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1719 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) | 2046 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) |
1720 | { | 2047 | { |
1721 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); | 2048 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); |
2049 | newPart.SetParent(this); | ||
2050 | |||
1722 | AddPart(newPart); | 2051 | AddPart(newPart); |
1723 | 2052 | ||
1724 | SetPartAsNonRoot(newPart); | 2053 | SetPartAsNonRoot(newPart); |
@@ -1865,11 +2194,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1865 | /// Immediately send a full update for this scene object. | 2194 | /// Immediately send a full update for this scene object. |
1866 | /// </summary> | 2195 | /// </summary> |
1867 | public void SendGroupFullUpdate() | 2196 | public void SendGroupFullUpdate() |
1868 | { | 2197 | { |
1869 | if (IsDeleted) | 2198 | if (IsDeleted) |
1870 | return; | 2199 | return; |
1871 | 2200 | ||
1872 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); | 2201 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); |
1873 | 2202 | ||
1874 | RootPart.SendFullUpdateToAllClients(); | 2203 | RootPart.SendFullUpdateToAllClients(); |
1875 | 2204 | ||
@@ -2058,12 +2387,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
2058 | part.LinkNum += objectGroup.PrimCount; | 2387 | part.LinkNum += objectGroup.PrimCount; |
2059 | } | 2388 | } |
2060 | } | 2389 | } |
2390 | } | ||
2061 | 2391 | ||
2062 | linkPart.LinkNum = 2; | 2392 | linkPart.LinkNum = 2; |
2063 | 2393 | ||
2064 | linkPart.SetParent(this); | 2394 | linkPart.SetParent(this); |
2065 | linkPart.CreateSelected = true; | 2395 | linkPart.CreateSelected = true; |
2066 | 2396 | ||
2397 | lock (m_parts.SyncRoot) | ||
2398 | { | ||
2067 | //if (linkPart.PhysActor != null) | 2399 | //if (linkPart.PhysActor != null) |
2068 | //{ | 2400 | //{ |
2069 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); | 2401 | // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); |
@@ -2220,6 +2552,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2220 | /// <param name="objectGroup"></param> | 2552 | /// <param name="objectGroup"></param> |
2221 | public virtual void DetachFromBackup() | 2553 | public virtual void DetachFromBackup() |
2222 | { | 2554 | { |
2555 | m_scene.SceneGraph.FireDetachFromBackup(this); | ||
2556 | |||
2223 | if (m_isBackedUp) | 2557 | if (m_isBackedUp) |
2224 | m_scene.EventManager.OnBackup -= ProcessBackup; | 2558 | m_scene.EventManager.OnBackup -= ProcessBackup; |
2225 | 2559 | ||
@@ -2524,6 +2858,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2524 | } | 2858 | } |
2525 | } | 2859 | } |
2526 | 2860 | ||
2861 | |||
2862 | |||
2863 | /// <summary> | ||
2864 | /// Gets the number of parts | ||
2865 | /// </summary> | ||
2866 | /// <returns></returns> | ||
2867 | public int GetPartCount() | ||
2868 | { | ||
2869 | return Parts.Count(); | ||
2870 | } | ||
2871 | |||
2527 | /// <summary> | 2872 | /// <summary> |
2528 | /// Update the texture entry for this part | 2873 | /// Update the texture entry for this part |
2529 | /// </summary> | 2874 | /// </summary> |
@@ -2585,11 +2930,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2585 | scale.Y = m_scene.m_maxNonphys; | 2930 | scale.Y = m_scene.m_maxNonphys; |
2586 | if (scale.Z > m_scene.m_maxNonphys) | 2931 | if (scale.Z > m_scene.m_maxNonphys) |
2587 | scale.Z = m_scene.m_maxNonphys; | 2932 | scale.Z = m_scene.m_maxNonphys; |
2588 | |||
2589 | SceneObjectPart part = GetChildPart(localID); | 2933 | SceneObjectPart part = GetChildPart(localID); |
2590 | if (part != null) | 2934 | if (part != null) |
2591 | { | 2935 | { |
2592 | part.Resize(scale); | ||
2593 | if (part.PhysActor != null) | 2936 | if (part.PhysActor != null) |
2594 | { | 2937 | { |
2595 | if (part.PhysActor.IsPhysical) | 2938 | if (part.PhysActor.IsPhysical) |
@@ -2604,7 +2947,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2604 | part.PhysActor.Size = scale; | 2947 | part.PhysActor.Size = scale; |
2605 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); | 2948 | m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); |
2606 | } | 2949 | } |
2607 | //if (part.UUID != m_rootPart.UUID) | 2950 | part.Resize(scale); |
2608 | 2951 | ||
2609 | HasGroupChanged = true; | 2952 | HasGroupChanged = true; |
2610 | part.TriggerScriptChangedEvent(Changed.SCALE); | 2953 | part.TriggerScriptChangedEvent(Changed.SCALE); |
@@ -2627,7 +2970,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2627 | SceneObjectPart part = GetChildPart(localID); | 2970 | SceneObjectPart part = GetChildPart(localID); |
2628 | if (part != null) | 2971 | if (part != null) |
2629 | { | 2972 | { |
2630 | part.IgnoreUndoUpdate = true; | ||
2631 | if (scale.X > m_scene.m_maxNonphys) | 2973 | if (scale.X > m_scene.m_maxNonphys) |
2632 | scale.X = m_scene.m_maxNonphys; | 2974 | scale.X = m_scene.m_maxNonphys; |
2633 | if (scale.Y > m_scene.m_maxNonphys) | 2975 | if (scale.Y > m_scene.m_maxNonphys) |
@@ -2664,7 +3006,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2664 | 3006 | ||
2665 | if (part.PhysActor != null && part.PhysActor.IsPhysical) | 3007 | if (part.PhysActor != null && part.PhysActor.IsPhysical) |
2666 | { | 3008 | { |
2667 | if (oldSize.X * x > m_scene.m_maxPhys) | 3009 | if (oldSize.X*x > m_scene.m_maxPhys) |
2668 | { | 3010 | { |
2669 | f = m_scene.m_maxPhys / oldSize.X; | 3011 | f = m_scene.m_maxPhys / oldSize.X; |
2670 | a = f / x; | 3012 | a = f / x; |
@@ -2672,7 +3014,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2672 | y *= a; | 3014 | y *= a; |
2673 | z *= a; | 3015 | z *= a; |
2674 | } | 3016 | } |
2675 | if (oldSize.Y * y > m_scene.m_maxPhys) | 3017 | if (oldSize.Y*y > m_scene.m_maxPhys) |
2676 | { | 3018 | { |
2677 | f = m_scene.m_maxPhys / oldSize.Y; | 3019 | f = m_scene.m_maxPhys / oldSize.Y; |
2678 | a = f / y; | 3020 | a = f / y; |
@@ -2680,7 +3022,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2680 | y *= a; | 3022 | y *= a; |
2681 | z *= a; | 3023 | z *= a; |
2682 | } | 3024 | } |
2683 | if (oldSize.Z * z > m_scene.m_maxPhys) | 3025 | if (oldSize.Z*z > m_scene.m_maxPhys) |
2684 | { | 3026 | { |
2685 | f = m_scene.m_maxPhys / oldSize.Z; | 3027 | f = m_scene.m_maxPhys / oldSize.Z; |
2686 | a = f / z; | 3028 | a = f / z; |
@@ -2691,7 +3033,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2691 | } | 3033 | } |
2692 | else | 3034 | else |
2693 | { | 3035 | { |
2694 | if (oldSize.X * x > m_scene.m_maxNonphys) | 3036 | if (oldSize.X*x > m_scene.m_maxNonphys) |
2695 | { | 3037 | { |
2696 | f = m_scene.m_maxNonphys / oldSize.X; | 3038 | f = m_scene.m_maxNonphys / oldSize.X; |
2697 | a = f / x; | 3039 | a = f / x; |
@@ -2699,7 +3041,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2699 | y *= a; | 3041 | y *= a; |
2700 | z *= a; | 3042 | z *= a; |
2701 | } | 3043 | } |
2702 | if (oldSize.Y * y > m_scene.m_maxNonphys) | 3044 | if (oldSize.Y*y > m_scene.m_maxNonphys) |
2703 | { | 3045 | { |
2704 | f = m_scene.m_maxNonphys / oldSize.Y; | 3046 | f = m_scene.m_maxNonphys / oldSize.Y; |
2705 | a = f / y; | 3047 | a = f / y; |
@@ -2707,7 +3049,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2707 | y *= a; | 3049 | y *= a; |
2708 | z *= a; | 3050 | z *= a; |
2709 | } | 3051 | } |
2710 | if (oldSize.Z * z > m_scene.m_maxNonphys) | 3052 | if (oldSize.Z*z > m_scene.m_maxNonphys) |
2711 | { | 3053 | { |
2712 | f = m_scene.m_maxNonphys / oldSize.Z; | 3054 | f = m_scene.m_maxNonphys / oldSize.Z; |
2713 | a = f / z; | 3055 | a = f / z; |
@@ -2717,7 +3059,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2717 | } | 3059 | } |
2718 | } | 3060 | } |
2719 | obPart.IgnoreUndoUpdate = false; | 3061 | obPart.IgnoreUndoUpdate = false; |
2720 | obPart.StoreUndoState(); | ||
2721 | } | 3062 | } |
2722 | } | 3063 | } |
2723 | } | 3064 | } |
@@ -2725,8 +3066,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2725 | Vector3 prevScale = part.Scale; | 3066 | Vector3 prevScale = part.Scale; |
2726 | prevScale.X *= x; | 3067 | prevScale.X *= x; |
2727 | prevScale.Y *= y; | 3068 | prevScale.Y *= y; |
2728 | prevScale.Z *= z; | 3069 | prevScale.Z *= z;; |
3070 | |||
3071 | part.IgnoreUndoUpdate = false; | ||
3072 | part.StoreUndoState(UndoType.STATE_GROUP_SCALE); | ||
3073 | part.IgnoreUndoUpdate = true; | ||
2729 | part.Resize(prevScale); | 3074 | part.Resize(prevScale); |
3075 | part.IgnoreUndoUpdate = false; | ||
2730 | 3076 | ||
2731 | parts = m_parts.GetArray(); | 3077 | parts = m_parts.GetArray(); |
2732 | for (int i = 0; i < parts.Length; i++) | 3078 | for (int i = 0; i < parts.Length; i++) |
@@ -2735,19 +3081,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
2735 | obPart.IgnoreUndoUpdate = true; | 3081 | obPart.IgnoreUndoUpdate = true; |
2736 | if (obPart.UUID != m_rootPart.UUID) | 3082 | if (obPart.UUID != m_rootPart.UUID) |
2737 | { | 3083 | { |
2738 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); | 3084 | if (obPart.UUID != m_rootPart.UUID) |
2739 | currentpos.X *= x; | 3085 | { |
2740 | currentpos.Y *= y; | 3086 | obPart.IgnoreUndoUpdate = false; |
2741 | currentpos.Z *= z; | 3087 | obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE); |
2742 | Vector3 newSize = new Vector3(obPart.Scale); | 3088 | obPart.IgnoreUndoUpdate = true; |
2743 | newSize.X *= x; | 3089 | |
2744 | newSize.Y *= y; | 3090 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); |
2745 | newSize.Z *= z; | 3091 | currentpos.X *= x; |
2746 | obPart.Resize(newSize); | 3092 | currentpos.Y *= y; |
2747 | obPart.UpdateOffSet(currentpos); | 3093 | currentpos.Z *= z; |
3094 | Vector3 newSize = new Vector3(obPart.Scale); | ||
3095 | newSize.X *= x; | ||
3096 | newSize.Y *= y; | ||
3097 | newSize.Z *= z; | ||
3098 | obPart.Resize(newSize); | ||
3099 | obPart.UpdateOffSet(currentpos); | ||
3100 | } | ||
3101 | obPart.IgnoreUndoUpdate = false; | ||
2748 | } | 3102 | } |
2749 | obPart.IgnoreUndoUpdate = false; | 3103 | obPart.IgnoreUndoUpdate = false; |
2750 | obPart.StoreUndoState(); | ||
2751 | } | 3104 | } |
2752 | 3105 | ||
2753 | if (part.PhysActor != null) | 3106 | if (part.PhysActor != null) |
@@ -2757,7 +3110,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2757 | } | 3110 | } |
2758 | 3111 | ||
2759 | part.IgnoreUndoUpdate = false; | 3112 | part.IgnoreUndoUpdate = false; |
2760 | part.StoreUndoState(); | ||
2761 | HasGroupChanged = true; | 3113 | HasGroupChanged = true; |
2762 | m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); | 3114 | m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); |
2763 | ScheduleGroupForTerseUpdate(); | 3115 | ScheduleGroupForTerseUpdate(); |
@@ -2774,14 +3126,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
2774 | /// <param name="pos"></param> | 3126 | /// <param name="pos"></param> |
2775 | public void UpdateGroupPosition(Vector3 pos) | 3127 | public void UpdateGroupPosition(Vector3 pos) |
2776 | { | 3128 | { |
2777 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
2778 | for (int i = 0; i < parts.Length; i++) | ||
2779 | parts[i].StoreUndoState(); | ||
2780 | |||
2781 | if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) | 3129 | if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) |
2782 | { | 3130 | { |
2783 | if (IsAttachment) | 3131 | if (IsAttachment) |
2784 | { | 3132 | { |
3133 | m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION); | ||
2785 | m_rootPart.AttachedPos = pos; | 3134 | m_rootPart.AttachedPos = pos; |
2786 | } | 3135 | } |
2787 | if (RootPart.GetStatusSandbox()) | 3136 | if (RootPart.GetStatusSandbox()) |
@@ -2815,7 +3164,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2815 | 3164 | ||
2816 | SceneObjectPart[] parts = m_parts.GetArray(); | 3165 | SceneObjectPart[] parts = m_parts.GetArray(); |
2817 | for (int i = 0; i < parts.Length; i++) | 3166 | for (int i = 0; i < parts.Length; i++) |
2818 | parts[i].StoreUndoState(); | 3167 | parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION); |
2819 | 3168 | ||
2820 | if (part != null) | 3169 | if (part != null) |
2821 | { | 3170 | { |
@@ -2840,7 +3189,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2840 | { | 3189 | { |
2841 | SceneObjectPart[] parts = m_parts.GetArray(); | 3190 | SceneObjectPart[] parts = m_parts.GetArray(); |
2842 | for (int i = 0; i < parts.Length; i++) | 3191 | for (int i = 0; i < parts.Length; i++) |
2843 | parts[i].StoreUndoState(); | 3192 | parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION); |
2844 | 3193 | ||
2845 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); | 3194 | Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); |
2846 | Vector3 oldPos = | 3195 | Vector3 oldPos = |
@@ -2861,10 +3210,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
2861 | obPart.OffsetPosition = obPart.OffsetPosition + diff; | 3210 | obPart.OffsetPosition = obPart.OffsetPosition + diff; |
2862 | } | 3211 | } |
2863 | 3212 | ||
2864 | AbsolutePosition = newPos; | 3213 | //We have to set undoing here because otherwise an undo state will be saved |
3214 | if (!m_rootPart.Undoing) | ||
3215 | { | ||
3216 | m_rootPart.Undoing = true; | ||
3217 | AbsolutePosition = newPos; | ||
3218 | m_rootPart.Undoing = false; | ||
3219 | } | ||
3220 | else | ||
3221 | { | ||
3222 | AbsolutePosition = newPos; | ||
3223 | } | ||
2865 | 3224 | ||
2866 | HasGroupChanged = true; | 3225 | HasGroupChanged = true; |
2867 | ScheduleGroupForTerseUpdate(); | 3226 | if (m_rootPart.Undoing) |
3227 | { | ||
3228 | ScheduleGroupForFullUpdate(); | ||
3229 | } | ||
3230 | else | ||
3231 | { | ||
3232 | ScheduleGroupForTerseUpdate(); | ||
3233 | } | ||
2868 | } | 3234 | } |
2869 | 3235 | ||
2870 | public void OffsetForNewRegion(Vector3 offset) | 3236 | public void OffsetForNewRegion(Vector3 offset) |
@@ -2884,7 +3250,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2884 | { | 3250 | { |
2885 | SceneObjectPart[] parts = m_parts.GetArray(); | 3251 | SceneObjectPart[] parts = m_parts.GetArray(); |
2886 | for (int i = 0; i < parts.Length; i++) | 3252 | for (int i = 0; i < parts.Length; i++) |
2887 | parts[i].StoreUndoState(); | 3253 | parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION); |
2888 | 3254 | ||
2889 | m_rootPart.UpdateRotation(rot); | 3255 | m_rootPart.UpdateRotation(rot); |
2890 | 3256 | ||
@@ -2908,7 +3274,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2908 | { | 3274 | { |
2909 | SceneObjectPart[] parts = m_parts.GetArray(); | 3275 | SceneObjectPart[] parts = m_parts.GetArray(); |
2910 | for (int i = 0; i < parts.Length; i++) | 3276 | for (int i = 0; i < parts.Length; i++) |
2911 | parts[i].StoreUndoState(); | 3277 | parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION); |
2912 | 3278 | ||
2913 | m_rootPart.UpdateRotation(rot); | 3279 | m_rootPart.UpdateRotation(rot); |
2914 | 3280 | ||
@@ -2933,10 +3299,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2933 | public void UpdateSingleRotation(Quaternion rot, uint localID) | 3299 | public void UpdateSingleRotation(Quaternion rot, uint localID) |
2934 | { | 3300 | { |
2935 | SceneObjectPart part = GetChildPart(localID); | 3301 | SceneObjectPart part = GetChildPart(localID); |
2936 | |||
2937 | SceneObjectPart[] parts = m_parts.GetArray(); | 3302 | SceneObjectPart[] parts = m_parts.GetArray(); |
2938 | for (int i = 0; i < parts.Length; i++) | 3303 | for (int i = 0; i < parts.Length; i++) |
2939 | parts[i].StoreUndoState(); | 3304 | parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION); |
2940 | 3305 | ||
2941 | if (part != null) | 3306 | if (part != null) |
2942 | { | 3307 | { |
@@ -2964,15 +3329,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
2964 | if (part.UUID == m_rootPart.UUID) | 3329 | if (part.UUID == m_rootPart.UUID) |
2965 | { | 3330 | { |
2966 | UpdateRootRotation(rot); | 3331 | UpdateRootRotation(rot); |
2967 | AbsolutePosition = pos; | 3332 | if (!m_rootPart.Undoing) |
3333 | { | ||
3334 | m_rootPart.Undoing = true; | ||
3335 | AbsolutePosition = pos; | ||
3336 | m_rootPart.Undoing = false; | ||
3337 | } | ||
3338 | else | ||
3339 | { | ||
3340 | AbsolutePosition = pos; | ||
3341 | } | ||
2968 | } | 3342 | } |
2969 | else | 3343 | else |
2970 | { | 3344 | { |
3345 | part.StoreUndoState(UndoType.STATE_PRIM_ROTATION); | ||
2971 | part.IgnoreUndoUpdate = true; | 3346 | part.IgnoreUndoUpdate = true; |
2972 | part.UpdateRotation(rot); | 3347 | part.UpdateRotation(rot); |
2973 | part.OffsetPosition = pos; | 3348 | part.OffsetPosition = pos; |
2974 | part.IgnoreUndoUpdate = false; | 3349 | part.IgnoreUndoUpdate = false; |
2975 | part.StoreUndoState(); | ||
2976 | } | 3350 | } |
2977 | } | 3351 | } |
2978 | } | 3352 | } |
@@ -2986,7 +3360,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2986 | Quaternion axRot = rot; | 3360 | Quaternion axRot = rot; |
2987 | Quaternion oldParentRot = m_rootPart.RotationOffset; | 3361 | Quaternion oldParentRot = m_rootPart.RotationOffset; |
2988 | 3362 | ||
2989 | m_rootPart.StoreUndoState(); | 3363 | m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION); |
3364 | bool cancelUndo = false; | ||
3365 | if (!m_rootPart.Undoing) | ||
3366 | { | ||
3367 | m_rootPart.Undoing = true; | ||
3368 | cancelUndo = true; | ||
3369 | } | ||
2990 | m_rootPart.UpdateRotation(rot); | 3370 | m_rootPart.UpdateRotation(rot); |
2991 | if (m_rootPart.PhysActor != null) | 3371 | if (m_rootPart.PhysActor != null) |
2992 | { | 3372 | { |
@@ -3010,17 +3390,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3010 | newRot *= Quaternion.Inverse(axRot); | 3390 | newRot *= Quaternion.Inverse(axRot); |
3011 | prim.RotationOffset = newRot; | 3391 | prim.RotationOffset = newRot; |
3012 | prim.ScheduleTerseUpdate(); | 3392 | prim.ScheduleTerseUpdate(); |
3393 | prim.IgnoreUndoUpdate = false; | ||
3013 | } | 3394 | } |
3014 | } | 3395 | } |
3015 | 3396 | if (cancelUndo == true) | |
3016 | for (int i = 0; i < parts.Length; i++) | ||
3017 | { | 3397 | { |
3018 | SceneObjectPart childpart = parts[i]; | 3398 | m_rootPart.Undoing = false; |
3019 | if (childpart != m_rootPart) | ||
3020 | { | ||
3021 | childpart.IgnoreUndoUpdate = false; | ||
3022 | childpart.StoreUndoState(); | ||
3023 | } | ||
3024 | } | 3399 | } |
3025 | 3400 | ||
3026 | m_rootPart.ScheduleTerseUpdate(); | 3401 | m_rootPart.ScheduleTerseUpdate(); |
@@ -3246,7 +3621,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3246 | public float GetMass() | 3621 | public float GetMass() |
3247 | { | 3622 | { |
3248 | float retmass = 0f; | 3623 | float retmass = 0f; |
3249 | |||
3250 | SceneObjectPart[] parts = m_parts.GetArray(); | 3624 | SceneObjectPart[] parts = m_parts.GetArray(); |
3251 | for (int i = 0; i < parts.Length; i++) | 3625 | for (int i = 0; i < parts.Length; i++) |
3252 | retmass += parts[i].GetMass(); | 3626 | retmass += parts[i].GetMass(); |
@@ -3362,6 +3736,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3362 | SetFromItemID(uuid); | 3736 | SetFromItemID(uuid); |
3363 | } | 3737 | } |
3364 | 3738 | ||
3739 | public void ResetOwnerChangeFlag() | ||
3740 | { | ||
3741 | ForEachPart(delegate(SceneObjectPart part) | ||
3742 | { | ||
3743 | part.ResetOwnerChangeFlag(); | ||
3744 | }); | ||
3745 | } | ||
3746 | |||
3365 | #endregion | 3747 | #endregion |
3366 | } | 3748 | } |
3367 | } | 3749 | } |