aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs892
1 files changed, 641 insertions, 251 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e26e4ae..8ce79a2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -104,8 +104,104 @@ namespace OpenSim.Region.Framework.Scenes
104 /// since the group's last persistent backup 104 /// since the group's last persistent backup
105 /// </summary> 105 /// </summary>
106 private bool m_hasGroupChanged = false; 106 private bool m_hasGroupChanged = false;
107 private long timeFirstChanged; 107 private long timeFirstChanged = 0;
108 private long timeLastChanged; 108 private long timeLastChanged = 0;
109 private long m_maxPersistTime = 0;
110 private long m_minPersistTime = 0;
111 private Random m_rand;
112 private bool m_suspendUpdates;
113 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
114 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
115
116 public bool areUpdatesSuspended
117 {
118 get
119 {
120 return m_suspendUpdates;
121 }
122 set
123 {
124 m_suspendUpdates = value;
125 if (!value)
126 {
127 QueueForUpdateCheck();
128 }
129 }
130 }
131
132 public void lockPartsForRead(bool locked)
133 {
134 if (locked)
135 {
136 if (m_partsLock.RecursiveReadCount > 0)
137 {
138 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
139 try
140 {
141 m_partsLock.ExitReadLock();
142 }
143 catch { } // Ignore errors, to allow resync
144 }
145 if (m_partsLock.RecursiveWriteCount > 0)
146 {
147 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested (write lock exists on this thread). This should not happen and means something needs to be fixed.");
148 try
149 {
150 m_partsLock.ExitWriteLock();
151 }
152 catch { }
153
154 }
155
156 while (!m_partsLock.TryEnterReadLock(60000))
157 {
158 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
159 if (m_partsLock.IsWriteLockHeld)
160 {
161 m_partsLock = new System.Threading.ReaderWriterLockSlim();
162 }
163 }
164 }
165 else
166 {
167 if (m_partsLock.RecursiveReadCount > 0)
168 {
169 m_partsLock.ExitReadLock();
170 }
171 }
172 }
173 public void lockPartsForWrite(bool locked)
174 {
175 if (locked)
176 {
177 if (m_partsLock.RecursiveReadCount > 0)
178 {
179 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
180 m_partsLock.ExitReadLock();
181 }
182 if (m_partsLock.RecursiveWriteCount > 0)
183 {
184 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
185 m_partsLock.ExitWriteLock();
186 }
187
188 while (!m_partsLock.TryEnterWriteLock(60000))
189 {
190 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
191 if (m_partsLock.IsWriteLockHeld)
192 {
193 m_partsLock = new System.Threading.ReaderWriterLockSlim();
194 }
195 }
196 }
197 else
198 {
199 if (m_partsLock.RecursiveWriteCount > 0)
200 {
201 m_partsLock.ExitWriteLock();
202 }
203 }
204 }
109 205
110 public bool HasGroupChanged 206 public bool HasGroupChanged
111 { 207 {
@@ -113,9 +209,39 @@ namespace OpenSim.Region.Framework.Scenes
113 { 209 {
114 if (value) 210 if (value)
115 { 211 {
212 if (m_isBackedUp)
213 {
214 m_scene.SceneGraph.FireChangeBackup(this);
215 }
116 timeLastChanged = DateTime.Now.Ticks; 216 timeLastChanged = DateTime.Now.Ticks;
117 if (!m_hasGroupChanged) 217 if (!m_hasGroupChanged)
118 timeFirstChanged = DateTime.Now.Ticks; 218 timeFirstChanged = DateTime.Now.Ticks;
219 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
220 {
221 if (m_rand == null)
222 {
223 byte[] val = new byte[16];
224 m_rootPart.UUID.ToBytes(val, 0);
225 m_rand = new Random(BitConverter.ToInt32(val, 0));
226 }
227
228 if (m_scene.GetRootAgentCount() == 0)
229 {
230 //If the region is empty, this change has been made by an automated process
231 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
232
233 float factor = 1.5f + (float)(m_rand.NextDouble());
234 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
235 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
236 }
237 else
238 {
239 //If the region is not empty, we want to obey the minimum and maximum persist times
240 //but add a random factor so we stagger the object persistance a little
241 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
242 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
243 }
244 }
119 } 245 }
120 m_hasGroupChanged = value; 246 m_hasGroupChanged = value;
121 } 247 }
@@ -131,8 +257,19 @@ namespace OpenSim.Region.Framework.Scenes
131 return false; 257 return false;
132 if (m_scene.ShuttingDown) 258 if (m_scene.ShuttingDown)
133 return true; 259 return true;
260
261 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
262 {
263 m_maxPersistTime = m_scene.m_persistAfter;
264 m_minPersistTime = m_scene.m_dontPersistBefore;
265 }
266
134 long currentTime = DateTime.Now.Ticks; 267 long currentTime = DateTime.Now.Ticks;
135 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 268
269 if (timeLastChanged == 0) timeLastChanged = currentTime;
270 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
271
272 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
136 return true; 273 return true;
137 return false; 274 return false;
138 } 275 }
@@ -221,7 +358,21 @@ namespace OpenSim.Region.Framework.Scenes
221 public virtual Quaternion Rotation 358 public virtual Quaternion Rotation
222 { 359 {
223 get { return m_rotation; } 360 get { return m_rotation; }
224 set { m_rotation = value; } 361 set {
362 lockPartsForRead(true);
363 try
364 {
365 foreach(SceneObjectPart p in m_parts.Values)
366 {
367 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
368 }
369 }
370 finally
371 {
372 lockPartsForRead(false);
373 }
374 m_rotation = value;
375 }
225 } 376 }
226 377
227 public Quaternion GroupRotation 378 public Quaternion GroupRotation
@@ -258,13 +409,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 409 set
259 { 410 {
260 m_regionHandle = value; 411 m_regionHandle = value;
261 lock (m_parts) 412 lockPartsForRead(true);
262 { 413 {
263 foreach (SceneObjectPart part in m_parts.Values) 414 foreach (SceneObjectPart part in m_parts.Values)
264 { 415 {
416
265 part.RegionHandle = m_regionHandle; 417 part.RegionHandle = m_regionHandle;
418
266 } 419 }
267 } 420 }
421 lockPartsForRead(false);
268 } 422 }
269 } 423 }
270 424
@@ -298,6 +452,12 @@ namespace OpenSim.Region.Framework.Scenes
298 { 452 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 453 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 454 }
455
456 lockPartsForRead(true);
457 foreach (SceneObjectPart part in m_parts.Values)
458 {
459 part.IgnoreUndoUpdate = true;
460 }
301 if (RootPart.GetStatusSandbox()) 461 if (RootPart.GetStatusSandbox())
302 { 462 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 463 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,15 +465,25 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 465 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 466 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 467 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
468 lockPartsForRead(false);
308 return; 469 return;
309 } 470 }
310 } 471 }
311 lock (m_parts) 472 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
473 lockPartsForRead(false);
474 foreach (SceneObjectPart part in parts)
312 { 475 {
313 foreach (SceneObjectPart part in m_parts.Values) 476 part.IgnoreUndoUpdate = false;
314 { 477 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
315 part.GroupPosition = val; 478 part.GroupPosition = val;
316 } 479 }
480
481 foreach (ScenePresence av in m_linkedAvatars)
482 {
483 Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition;
484 av.AbsolutePosition += offset;
485 av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
486 av.SendFullUpdateToAllClients();
317 } 487 }
318 488
319 //if (m_rootPart.PhysActor != null) 489 //if (m_rootPart.PhysActor != null)
@@ -457,6 +627,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 627 /// </summary>
458 public SceneObjectGroup() 628 public SceneObjectGroup()
459 { 629 {
630
460 } 631 }
461 632
462 /// <summary> 633 /// <summary>
@@ -473,7 +644,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 644 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 645 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 646 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 647 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 648 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 649 }
479 650
@@ -504,13 +675,16 @@ namespace OpenSim.Region.Framework.Scenes
504 675
505 public void SetFromItemID(UUID AssetId) 676 public void SetFromItemID(UUID AssetId)
506 { 677 {
507 lock (m_parts) 678 lockPartsForRead(true);
508 { 679 {
509 foreach (SceneObjectPart part in m_parts.Values) 680 foreach (SceneObjectPart part in m_parts.Values)
510 { 681 {
682
511 part.FromItemID = AssetId; 683 part.FromItemID = AssetId;
684
512 } 685 }
513 } 686 }
687 lockPartsForRead(false);
514 } 688 }
515 689
516 public UUID GetFromItemID() 690 public UUID GetFromItemID()
@@ -523,6 +697,9 @@ namespace OpenSim.Region.Framework.Scenes
523 /// </summary> 697 /// </summary>
524 public virtual void AttachToBackup() 698 public virtual void AttachToBackup()
525 { 699 {
700 if (IsAttachment) return;
701 m_scene.SceneGraph.FireAttachToBackup(this);
702
526 if (InSceneBackup) 703 if (InSceneBackup)
527 { 704 {
528 //m_log.DebugFormat( 705 //m_log.DebugFormat(
@@ -579,7 +756,7 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 756 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 757 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 758
582 lock (m_parts) 759 lockPartsForRead(true);
583 { 760 {
584 foreach (SceneObjectPart part in m_parts.Values) 761 foreach (SceneObjectPart part in m_parts.Values)
585 { 762 {
@@ -593,8 +770,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 770 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
594 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 771 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
595 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 772 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
773
596 } 774 }
597 } 775 }
776 lockPartsForRead(false);
777
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 778 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 779 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 780 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +790,11 @@ namespace OpenSim.Region.Framework.Scenes
610 790
611 EntityIntersection result = new EntityIntersection(); 791 EntityIntersection result = new EntityIntersection();
612 792
613 lock (m_parts) 793 lockPartsForRead(true);
614 { 794 {
615 foreach (SceneObjectPart part in m_parts.Values) 795 foreach (SceneObjectPart part in m_parts.Values)
616 { 796 {
797
617 // Temporary commented to stop compiler warning 798 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 799 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 800 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +822,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 822 result.distance = inter.distance;
642 } 823 }
643 } 824 }
825
644 } 826 }
645 } 827 }
828 lockPartsForRead(false);
646 return result; 829 return result;
647 } 830 }
648 831
@@ -661,10 +844,11 @@ namespace OpenSim.Region.Framework.Scenes
661 minY = 256f; 844 minY = 256f;
662 minZ = 8192f; 845 minZ = 8192f;
663 846
664 lock(m_parts); 847 lockPartsForRead(true);
665 { 848 {
666 foreach (SceneObjectPart part in m_parts.Values) 849 foreach (SceneObjectPart part in m_parts.Values)
667 { 850 {
851
668 Vector3 worldPos = part.GetWorldPosition(); 852 Vector3 worldPos = part.GetWorldPosition();
669 Vector3 offset = worldPos - AbsolutePosition; 853 Vector3 offset = worldPos - AbsolutePosition;
670 Quaternion worldRot; 854 Quaternion worldRot;
@@ -723,6 +907,8 @@ namespace OpenSim.Region.Framework.Scenes
723 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 907 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
724 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 908 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
725 909
910
911
726 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 912 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
727 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 913 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
728 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 914 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -894,6 +1080,7 @@ namespace OpenSim.Region.Framework.Scenes
894 minZ = backBottomLeft.Z; 1080 minZ = backBottomLeft.Z;
895 } 1081 }
896 } 1082 }
1083 lockPartsForRead(false);
897 } 1084 }
898 1085
899 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 1086 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
@@ -929,21 +1116,29 @@ namespace OpenSim.Region.Framework.Scenes
929 1116
930 public void SaveScriptedState(XmlTextWriter writer) 1117 public void SaveScriptedState(XmlTextWriter writer)
931 { 1118 {
1119 SaveScriptedState(writer, false);
1120 }
1121
1122 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1123 {
932 XmlDocument doc = new XmlDocument(); 1124 XmlDocument doc = new XmlDocument();
933 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1125 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
934 1126
935 // Capture script state while holding the lock 1127 // Capture script state while holding the lock
936 lock (m_parts) 1128 lockPartsForRead(true);
937 { 1129 {
938 foreach (SceneObjectPart part in m_parts.Values) 1130 foreach (SceneObjectPart part in m_parts.Values)
939 { 1131 {
940 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1132
1133 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
941 foreach (UUID itemid in pstates.Keys) 1134 foreach (UUID itemid in pstates.Keys)
942 { 1135 {
943 states.Add(itemid, pstates[itemid]); 1136 states.Add(itemid, pstates[itemid]);
944 } 1137 }
1138
945 } 1139 }
946 } 1140 }
1141 lockPartsForRead(false);
947 1142
948 if (states.Count > 0) 1143 if (states.Count > 0)
949 { 1144 {
@@ -962,6 +1157,47 @@ namespace OpenSim.Region.Framework.Scenes
962 } 1157 }
963 1158
964 /// <summary> 1159 /// <summary>
1160 /// Add the avatar to this linkset (avatar is sat).
1161 /// </summary>
1162 /// <param name="agentID"></param>
1163 public void AddAvatar(UUID agentID)
1164 {
1165 ScenePresence presence;
1166 if (m_scene.TryGetScenePresence(agentID, out presence))
1167 {
1168 if (!m_linkedAvatars.Contains(presence))
1169 {
1170 m_linkedAvatars.Add(presence);
1171 }
1172 }
1173 }
1174
1175 /// <summary>
1176 /// Delete the avatar from this linkset (avatar is unsat).
1177 /// </summary>
1178 /// <param name="agentID"></param>
1179 public void DeleteAvatar(UUID agentID)
1180 {
1181 ScenePresence presence;
1182 if (m_scene.TryGetScenePresence(agentID, out presence))
1183 {
1184 if (m_linkedAvatars.Contains(presence))
1185 {
1186 m_linkedAvatars.Remove(presence);
1187 }
1188 }
1189 }
1190
1191 /// <summary>
1192 /// Returns the list of linked presences (avatars sat on this group)
1193 /// </summary>
1194 /// <param name="agentID"></param>
1195 public List<ScenePresence> GetLinkedAvatars()
1196 {
1197 return m_linkedAvatars;
1198 }
1199
1200 /// <summary>
965 /// Attach this scene object to the given avatar. 1201 /// Attach this scene object to the given avatar.
966 /// </summary> 1202 /// </summary>
967 /// <param name="agentID"></param> 1203 /// <param name="agentID"></param>
@@ -1112,13 +1348,16 @@ namespace OpenSim.Region.Framework.Scenes
1112 1348
1113 public override void UpdateMovement() 1349 public override void UpdateMovement()
1114 { 1350 {
1115 lock (m_parts) 1351 lockPartsForRead(true);
1116 { 1352 {
1117 foreach (SceneObjectPart part in m_parts.Values) 1353 foreach (SceneObjectPart part in m_parts.Values)
1118 { 1354 {
1355
1119 part.UpdateMovement(); 1356 part.UpdateMovement();
1357
1120 } 1358 }
1121 } 1359 }
1360 lockPartsForRead(false);
1122 } 1361 }
1123 1362
1124 public ushort GetTimeDilation() 1363 public ushort GetTimeDilation()
@@ -1162,7 +1401,7 @@ namespace OpenSim.Region.Framework.Scenes
1162 /// <param name="part"></param> 1401 /// <param name="part"></param>
1163 public void AddPart(SceneObjectPart part) 1402 public void AddPart(SceneObjectPart part)
1164 { 1403 {
1165 lock (m_parts) 1404 lockPartsForWrite(true);
1166 { 1405 {
1167 part.SetParent(this); 1406 part.SetParent(this);
1168 m_parts.Add(part.UUID, part); 1407 m_parts.Add(part.UUID, part);
@@ -1172,6 +1411,7 @@ namespace OpenSim.Region.Framework.Scenes
1172 if (part.LinkNum == 2 && RootPart != null) 1411 if (part.LinkNum == 2 && RootPart != null)
1173 RootPart.LinkNum = 1; 1412 RootPart.LinkNum = 1;
1174 } 1413 }
1414 lockPartsForWrite(false);
1175 } 1415 }
1176 1416
1177 /// <summary> 1417 /// <summary>
@@ -1179,28 +1419,33 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// </summary> 1419 /// </summary>
1180 private void UpdateParentIDs() 1420 private void UpdateParentIDs()
1181 { 1421 {
1182 lock (m_parts) 1422 lockPartsForRead(true);
1183 { 1423 {
1184 foreach (SceneObjectPart part in m_parts.Values) 1424 foreach (SceneObjectPart part in m_parts.Values)
1185 { 1425 {
1426
1186 if (part.UUID != m_rootPart.UUID) 1427 if (part.UUID != m_rootPart.UUID)
1187 { 1428 {
1188 part.ParentID = m_rootPart.LocalId; 1429 part.ParentID = m_rootPart.LocalId;
1189 } 1430 }
1431
1190 } 1432 }
1191 } 1433 }
1434 lockPartsForRead(false);
1192 } 1435 }
1193 1436
1194 public void RegenerateFullIDs() 1437 public void RegenerateFullIDs()
1195 { 1438 {
1196 lock (m_parts) 1439 lockPartsForRead(true);
1197 { 1440 {
1198 foreach (SceneObjectPart part in m_parts.Values) 1441 foreach (SceneObjectPart part in m_parts.Values)
1199 { 1442 {
1443
1200 part.UUID = UUID.Random(); 1444 part.UUID = UUID.Random();
1201 1445
1202 } 1446 }
1203 } 1447 }
1448 lockPartsForRead(false);
1204 } 1449 }
1205 1450
1206 // helper provided for parts. 1451 // helper provided for parts.
@@ -1261,7 +1506,7 @@ namespace OpenSim.Region.Framework.Scenes
1261 1506
1262 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1507 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1263 { 1508 {
1264 part.StoreUndoState(); 1509 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1265 part.OnGrab(offsetPos, remoteClient); 1510 part.OnGrab(offsetPos, remoteClient);
1266 } 1511 }
1267 1512
@@ -1281,27 +1526,32 @@ namespace OpenSim.Region.Framework.Scenes
1281 1526
1282 DetachFromBackup(); 1527 DetachFromBackup();
1283 1528
1284 lock (m_parts) 1529 lockPartsForRead(true);
1530 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1531 lockPartsForRead(false);
1532
1533 foreach (SceneObjectPart part in values)
1285 { 1534 {
1286 foreach (SceneObjectPart part in m_parts.Values)
1287 {
1288// part.Inventory.RemoveScriptInstances(); 1535// part.Inventory.RemoveScriptInstances();
1289 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1536
1537 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1538 {
1539 if (sp.ParentID == LocalId)
1290 { 1540 {
1291 if (avatar.ParentID == LocalId) 1541 sp.StandUp();
1292 { 1542 }
1293 avatar.StandUp();
1294 }
1295 1543
1296 if (!silent) 1544 if (!silent)
1297 { 1545 {
1298 part.UpdateFlag = 0; 1546 part.UpdateFlag = 0;
1299 if (part == m_rootPart) 1547 if (part == m_rootPart)
1300 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1548 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1301 } 1549 }
1302 }); 1550 });
1303 } 1551
1304 } 1552 }
1553
1554
1305 } 1555 }
1306 1556
1307 public void AddScriptLPS(int count) 1557 public void AddScriptLPS(int count)
@@ -1326,17 +1576,20 @@ namespace OpenSim.Region.Framework.Scenes
1326 1576
1327 scriptEvents aggregateScriptEvents=0; 1577 scriptEvents aggregateScriptEvents=0;
1328 1578
1329 lock (m_parts) 1579 lockPartsForRead(true);
1330 { 1580 {
1331 foreach (SceneObjectPart part in m_parts.Values) 1581 foreach (SceneObjectPart part in m_parts.Values)
1332 { 1582 {
1583
1333 if (part == null) 1584 if (part == null)
1334 continue; 1585 continue;
1335 if (part != RootPart) 1586 if (part != RootPart)
1336 part.ObjectFlags = objectflagupdate; 1587 part.ObjectFlags = objectflagupdate;
1337 aggregateScriptEvents |= part.AggregateScriptEvents; 1588 aggregateScriptEvents |= part.AggregateScriptEvents;
1589
1338 } 1590 }
1339 } 1591 }
1592 lockPartsForRead(false);
1340 1593
1341 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1594 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1342 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1595 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1378,42 +1631,52 @@ namespace OpenSim.Region.Framework.Scenes
1378 /// <param name="m_physicalPrim"></param> 1631 /// <param name="m_physicalPrim"></param>
1379 public void ApplyPhysics(bool m_physicalPrim) 1632 public void ApplyPhysics(bool m_physicalPrim)
1380 { 1633 {
1381 lock (m_parts) 1634 lockPartsForRead(true);
1635
1636 if (m_parts.Count > 1)
1382 { 1637 {
1383 if (m_parts.Count > 1) 1638 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1639 lockPartsForRead(false);
1640 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1641 foreach (SceneObjectPart part in values)
1384 { 1642 {
1385 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1643
1386 foreach (SceneObjectPart part in m_parts.Values) 1644 if (part.LocalId != m_rootPart.LocalId)
1387 { 1645 {
1388 if (part.LocalId != m_rootPart.LocalId) 1646 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1389 {
1390 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1391 }
1392 } 1647 }
1393 1648
1394 // Hack to get the physics scene geometries in the right spot
1395 ResetChildPrimPhysicsPositions();
1396 }
1397 else
1398 {
1399 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1400 } 1649 }
1650 // Hack to get the physics scene geometries in the right spot
1651 ResetChildPrimPhysicsPositions();
1652 }
1653 else
1654 {
1655 lockPartsForRead(false);
1656 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1401 } 1657 }
1402 } 1658 }
1403 1659
1404 public void SetOwnerId(UUID userId) 1660 public void SetOwnerId(UUID userId)
1405 { 1661 {
1406 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1662 ForEachPart(delegate(SceneObjectPart part)
1663 {
1664
1665 part.OwnerID = userId;
1666
1667 });
1407 } 1668 }
1408 1669
1409 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1670 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1410 { 1671 {
1411 lock (m_parts) 1672 lockPartsForRead(true);
1673 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1674 lockPartsForRead(false);
1675 foreach (SceneObjectPart part in values)
1412 { 1676 {
1413 foreach (SceneObjectPart part in m_parts.Values) 1677
1414 { 1678 whatToDo(part);
1415 whatToDo(part); 1679
1416 }
1417 } 1680 }
1418 } 1681 }
1419 1682
@@ -1436,7 +1699,10 @@ namespace OpenSim.Region.Framework.Scenes
1436 1699
1437 try 1700 try
1438 { 1701 {
1439 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1702 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1703 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1704 m_scene.LoadingPrims) // Land may not be valid yet
1705
1440 { 1706 {
1441 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1707 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1442 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1708 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1512,15 +1778,17 @@ namespace OpenSim.Region.Framework.Scenes
1512 RootPart.SendFullUpdate( 1778 RootPart.SendFullUpdate(
1513 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1779 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1514 1780
1515 lock (m_parts) 1781 lockPartsForRead(true);
1516 { 1782 {
1517 foreach (SceneObjectPart part in m_parts.Values) 1783 foreach (SceneObjectPart part in m_parts.Values)
1518 { 1784 {
1785
1519 if (part != RootPart) 1786 if (part != RootPart)
1520 part.SendFullUpdate( 1787 part.SendFullUpdate(
1521 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1788 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1522 } 1789 }
1523 } 1790 }
1791 lockPartsForRead(false);
1524 } 1792 }
1525 1793
1526 #region Copying 1794 #region Copying
@@ -1582,10 +1850,11 @@ namespace OpenSim.Region.Framework.Scenes
1582 1850
1583 List<SceneObjectPart> partList; 1851 List<SceneObjectPart> partList;
1584 1852
1585 lock (m_parts) 1853 lockPartsForRead(true);
1586 { 1854
1587 partList = new List<SceneObjectPart>(m_parts.Values); 1855 partList = new List<SceneObjectPart>(m_parts.Values);
1588 } 1856
1857 lockPartsForRead(false);
1589 1858
1590 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1859 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1591 { 1860 {
@@ -1802,13 +2071,40 @@ namespace OpenSim.Region.Framework.Scenes
1802 } 2071 }
1803 } 2072 }
1804 2073
2074 public void rotLookAt(Quaternion target, float strength, float damping)
2075 {
2076 SceneObjectPart rootpart = m_rootPart;
2077 if (rootpart != null)
2078 {
2079 if (IsAttachment)
2080 {
2081 /*
2082 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2083 if (avatar != null)
2084 {
2085 Rotate the Av?
2086 } */
2087 }
2088 else
2089 {
2090 if (rootpart.PhysActor != null)
2091 { // APID must be implemented in your physics system for this to function.
2092 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2093 rootpart.PhysActor.APIDStrength = strength;
2094 rootpart.PhysActor.APIDDamping = damping;
2095 rootpart.PhysActor.APIDActive = true;
2096 }
2097 }
2098 }
2099 }
2100
1805 public void stopLookAt() 2101 public void stopLookAt()
1806 { 2102 {
1807 SceneObjectPart rootpart = m_rootPart; 2103 SceneObjectPart rootpart = m_rootPart;
1808 if (rootpart != null) 2104 if (rootpart != null)
1809 { 2105 {
1810 if (rootpart.PhysActor != null) 2106 if (rootpart.PhysActor != null)
1811 { 2107 { // APID must be implemented in your physics system for this to function.
1812 rootpart.PhysActor.APIDActive = false; 2108 rootpart.PhysActor.APIDActive = false;
1813 } 2109 }
1814 } 2110 }
@@ -1876,10 +2172,11 @@ namespace OpenSim.Region.Framework.Scenes
1876 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2172 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1877 newPart.SetParent(this); 2173 newPart.SetParent(this);
1878 2174
1879 lock (m_parts) 2175 lockPartsForWrite(true);
1880 { 2176 {
1881 m_parts.Add(newPart.UUID, newPart); 2177 m_parts.Add(newPart.UUID, newPart);
1882 } 2178 }
2179 lockPartsForWrite(false);
1883 2180
1884 SetPartAsNonRoot(newPart); 2181 SetPartAsNonRoot(newPart);
1885 2182
@@ -1942,7 +2239,7 @@ namespace OpenSim.Region.Framework.Scenes
1942 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2239 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1943 // return; 2240 // return;
1944 2241
1945 lock (m_parts) 2242 lockPartsForRead(true);
1946 { 2243 {
1947 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2244 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1948 2245
@@ -1962,9 +2259,12 @@ namespace OpenSim.Region.Framework.Scenes
1962 { 2259 {
1963 if (!IsSelected) 2260 if (!IsSelected)
1964 part.UpdateLookAt(); 2261 part.UpdateLookAt();
2262
1965 part.SendScheduledUpdates(); 2263 part.SendScheduledUpdates();
2264
1966 } 2265 }
1967 } 2266 }
2267 lockPartsForRead(false);
1968 } 2268 }
1969 2269
1970 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2270 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1973,27 +2273,29 @@ namespace OpenSim.Region.Framework.Scenes
1973 2273
1974 RootPart.AddFullUpdateToAvatar(presence); 2274 RootPart.AddFullUpdateToAvatar(presence);
1975 2275
1976 lock (m_parts) 2276 lockPartsForRead(true);
1977 { 2277 {
1978 foreach (SceneObjectPart part in m_parts.Values) 2278 foreach (SceneObjectPart part in m_parts.Values)
1979 { 2279 {
2280
1980 if (part != RootPart) 2281 if (part != RootPart)
1981 part.AddFullUpdateToAvatar(presence); 2282 part.AddFullUpdateToAvatar(presence);
2283
1982 } 2284 }
1983 } 2285 }
2286 lockPartsForRead(false);
1984 } 2287 }
1985 2288
1986 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2289 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1987 { 2290 {
1988// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2291 lockPartsForRead(true);
1989 2292
1990 lock (m_parts) 2293 foreach (SceneObjectPart part in m_parts.Values)
1991 { 2294 {
1992 foreach (SceneObjectPart part in m_parts.Values) 2295 part.AddTerseUpdateToAvatar(presence);
1993 {
1994 part.AddTerseUpdateToAvatar(presence);
1995 }
1996 } 2296 }
2297
2298 lockPartsForRead(false);
1997 } 2299 }
1998 2300
1999 /// <summary> 2301 /// <summary>
@@ -2001,20 +2303,23 @@ namespace OpenSim.Region.Framework.Scenes
2001 /// </summary> 2303 /// </summary>
2002 public void ScheduleGroupForFullUpdate() 2304 public void ScheduleGroupForFullUpdate()
2003 { 2305 {
2004 if (IsAttachment) 2306 //if (IsAttachment)
2005 m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); 2307 // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
2006 2308
2007 checkAtTargets(); 2309 checkAtTargets();
2008 RootPart.ScheduleFullUpdate(); 2310 RootPart.ScheduleFullUpdate();
2009 2311
2010 lock (m_parts) 2312 lockPartsForRead(true);
2011 { 2313 {
2012 foreach (SceneObjectPart part in m_parts.Values) 2314 foreach (SceneObjectPart part in m_parts.Values)
2013 { 2315 {
2316
2014 if (part != RootPart) 2317 if (part != RootPart)
2015 part.ScheduleFullUpdate(); 2318 part.ScheduleFullUpdate();
2319
2016 } 2320 }
2017 } 2321 }
2322 lockPartsForRead(false);
2018 } 2323 }
2019 2324
2020 /// <summary> 2325 /// <summary>
@@ -2022,37 +2327,38 @@ namespace OpenSim.Region.Framework.Scenes
2022 /// </summary> 2327 /// </summary>
2023 public void ScheduleGroupForTerseUpdate() 2328 public void ScheduleGroupForTerseUpdate()
2024 { 2329 {
2025// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2330 lockPartsForRead(true);
2026 2331 foreach (SceneObjectPart part in m_parts.Values)
2027 lock (m_parts)
2028 { 2332 {
2029 foreach (SceneObjectPart part in m_parts.Values) 2333 part.ScheduleTerseUpdate();
2030 {
2031 part.ScheduleTerseUpdate();
2032 }
2033 } 2334 }
2335
2336 lockPartsForRead(false);
2034 } 2337 }
2035 2338
2036 /// <summary> 2339 /// <summary>
2037 /// Immediately send a full update for this scene object. 2340 /// Immediately send a full update for this scene object.
2038 /// </summary> 2341 /// </summary>
2039 public void SendGroupFullUpdate() 2342 public void SendGroupFullUpdate()
2040 { 2343 {
2041 if (IsDeleted) 2344 if (IsDeleted)
2042 return; 2345 return;
2043 2346
2044// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2347// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2045 2348
2046 RootPart.SendFullUpdateToAllClients(); 2349 RootPart.SendFullUpdateToAllClients();
2047 2350
2048 lock (m_parts) 2351 lockPartsForRead(true);
2049 { 2352 {
2050 foreach (SceneObjectPart part in m_parts.Values) 2353 foreach (SceneObjectPart part in m_parts.Values)
2051 { 2354 {
2355
2052 if (part != RootPart) 2356 if (part != RootPart)
2053 part.SendFullUpdateToAllClients(); 2357 part.SendFullUpdateToAllClients();
2358
2054 } 2359 }
2055 } 2360 }
2361 lockPartsForRead(false);
2056 } 2362 }
2057 2363
2058 /// <summary> 2364 /// <summary>
@@ -2084,14 +2390,15 @@ namespace OpenSim.Region.Framework.Scenes
2084 { 2390 {
2085 if (IsDeleted) 2391 if (IsDeleted)
2086 return; 2392 return;
2087 2393
2088 lock (m_parts) 2394 lockPartsForRead(true);
2089 { 2395 {
2090 foreach (SceneObjectPart part in m_parts.Values) 2396 foreach (SceneObjectPart part in m_parts.Values)
2091 { 2397 {
2092 part.SendTerseUpdateToAllClients(); 2398 part.SendTerseUpdateToAllClients();
2093 } 2399 }
2094 } 2400 }
2401 lockPartsForRead(false);
2095 } 2402 }
2096 2403
2097 #endregion 2404 #endregion
@@ -2105,16 +2412,18 @@ namespace OpenSim.Region.Framework.Scenes
2105 /// <returns>null if no child part with that linknum or child part</returns> 2412 /// <returns>null if no child part with that linknum or child part</returns>
2106 public SceneObjectPart GetLinkNumPart(int linknum) 2413 public SceneObjectPart GetLinkNumPart(int linknum)
2107 { 2414 {
2108 lock (m_parts) 2415 lockPartsForRead(true);
2109 { 2416 {
2110 foreach (SceneObjectPart part in m_parts.Values) 2417 foreach (SceneObjectPart part in m_parts.Values)
2111 { 2418 {
2112 if (part.LinkNum == linknum) 2419 if (part.LinkNum == linknum)
2113 { 2420 {
2421 lockPartsForRead(false);
2114 return part; 2422 return part;
2115 } 2423 }
2116 } 2424 }
2117 } 2425 }
2426 lockPartsForRead(false);
2118 2427
2119 return null; 2428 return null;
2120 } 2429 }
@@ -2142,17 +2451,19 @@ namespace OpenSim.Region.Framework.Scenes
2142 public SceneObjectPart GetChildPart(uint localID) 2451 public SceneObjectPart GetChildPart(uint localID)
2143 { 2452 {
2144 //m_log.DebugFormat("Entered looking for {0}", localID); 2453 //m_log.DebugFormat("Entered looking for {0}", localID);
2145 lock (m_parts) 2454 lockPartsForRead(true);
2146 { 2455 {
2147 foreach (SceneObjectPart part in m_parts.Values) 2456 foreach (SceneObjectPart part in m_parts.Values)
2148 { 2457 {
2149 //m_log.DebugFormat("Found {0}", part.LocalId); 2458 //m_log.DebugFormat("Found {0}", part.LocalId);
2150 if (part.LocalId == localID) 2459 if (part.LocalId == localID)
2151 { 2460 {
2461 lockPartsForRead(false);
2152 return part; 2462 return part;
2153 } 2463 }
2154 } 2464 }
2155 } 2465 }
2466 lockPartsForRead(false);
2156 2467
2157 return null; 2468 return null;
2158 } 2469 }
@@ -2182,17 +2493,19 @@ namespace OpenSim.Region.Framework.Scenes
2182 public bool HasChildPrim(uint localID) 2493 public bool HasChildPrim(uint localID)
2183 { 2494 {
2184 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2495 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2185 lock (m_parts) 2496 lockPartsForRead(true);
2186 { 2497 {
2187 foreach (SceneObjectPart part in m_parts.Values) 2498 foreach (SceneObjectPart part in m_parts.Values)
2188 { 2499 {
2189 //m_log.DebugFormat("Found {0}", part.LocalId); 2500 //m_log.DebugFormat("Found {0}", part.LocalId);
2190 if (part.LocalId == localID) 2501 if (part.LocalId == localID)
2191 { 2502 {
2503 lockPartsForRead(false);
2192 return true; 2504 return true;
2193 } 2505 }
2194 } 2506 }
2195 } 2507 }
2508 lockPartsForRead(false);
2196 2509
2197 return false; 2510 return false;
2198 } 2511 }
@@ -2242,53 +2555,57 @@ namespace OpenSim.Region.Framework.Scenes
2242 if (m_rootPart.LinkNum == 0) 2555 if (m_rootPart.LinkNum == 0)
2243 m_rootPart.LinkNum = 1; 2556 m_rootPart.LinkNum = 1;
2244 2557
2245 lock (m_parts) 2558 lockPartsForWrite(true);
2246 { 2559
2247 m_parts.Add(linkPart.UUID, linkPart); 2560 m_parts.Add(linkPart.UUID, linkPart);
2561
2562 lockPartsForWrite(false);
2248 2563
2249 // Insert in terms of link numbers, the new links 2564 // Insert in terms of link numbers, the new links
2250 // before the current ones (with the exception of 2565 // before the current ones (with the exception of
2251 // the root prim. Shuffle the old ones up 2566 // the root prim. Shuffle the old ones up
2252 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2567 lockPartsForRead(true);
2568 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2569 {
2570 if (kvp.Value.LinkNum != 1)
2253 { 2571 {
2254 if (kvp.Value.LinkNum != 1) 2572 // Don't update root prim link number
2255 { 2573 kvp.Value.LinkNum += objectGroup.PrimCount;
2256 // Don't update root prim link number
2257 kvp.Value.LinkNum += objectGroup.PrimCount;
2258 }
2259 } 2574 }
2575 }
2576 lockPartsForRead(false);
2260 2577
2261 linkPart.LinkNum = 2; 2578 linkPart.LinkNum = 2;
2262 2579
2263 linkPart.SetParent(this); 2580 linkPart.SetParent(this);
2264 linkPart.CreateSelected = true; 2581 linkPart.CreateSelected = true;
2265 2582
2266 //if (linkPart.PhysActor != null) 2583 //if (linkPart.PhysActor != null)
2267 //{ 2584 //{
2268 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2585 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2269 2586
2270 //linkPart.PhysActor = null; 2587 //linkPart.PhysActor = null;
2271 //} 2588 //}
2272 2589
2273 //TODO: rest of parts 2590 //TODO: rest of parts
2274 int linkNum = 3; 2591 int linkNum = 3;
2275 foreach (SceneObjectPart part in objectGroup.Children.Values) 2592 foreach (SceneObjectPart part in objectGroup.Children.Values)
2593 {
2594 if (part.UUID != objectGroup.m_rootPart.UUID)
2276 { 2595 {
2277 if (part.UUID != objectGroup.m_rootPart.UUID) 2596 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2278 {
2279 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2280 }
2281 part.ClearUndoState();
2282 } 2597 }
2598 part.ClearUndoState();
2283 } 2599 }
2284 2600
2285 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2601 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2286 objectGroup.m_isDeleted = true; 2602 objectGroup.m_isDeleted = true;
2603
2604 objectGroup.lockPartsForWrite(true);
2287 2605
2288 lock (objectGroup.m_parts) 2606 objectGroup.m_parts.Clear();
2289 { 2607
2290 objectGroup.m_parts.Clear(); 2608 objectGroup.lockPartsForWrite(false);
2291 }
2292 2609
2293 // Can't do this yet since backup still makes use of the root part without any synchronization 2610 // Can't do this yet since backup still makes use of the root part without any synchronization
2294// objectGroup.m_rootPart = null; 2611// objectGroup.m_rootPart = null;
@@ -2358,11 +2675,12 @@ namespace OpenSim.Region.Framework.Scenes
2358 Quaternion worldRot = linkPart.GetWorldRotation(); 2675 Quaternion worldRot = linkPart.GetWorldRotation();
2359 2676
2360 // Remove the part from this object 2677 // Remove the part from this object
2361 lock (m_parts) 2678 lockPartsForWrite(true);
2362 { 2679 {
2363 m_parts.Remove(linkPart.UUID); 2680 m_parts.Remove(linkPart.UUID);
2364 } 2681 }
2365 2682 lockPartsForWrite(false);
2683 lockPartsForRead(true);
2366 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2684 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2367 RootPart.LinkNum = 0; 2685 RootPart.LinkNum = 0;
2368 else 2686 else
@@ -2373,6 +2691,7 @@ namespace OpenSim.Region.Framework.Scenes
2373 p.LinkNum--; 2691 p.LinkNum--;
2374 } 2692 }
2375 } 2693 }
2694 lockPartsForRead(false);
2376 2695
2377 linkPart.ParentID = 0; 2696 linkPart.ParentID = 0;
2378 linkPart.LinkNum = 0; 2697 linkPart.LinkNum = 0;
@@ -2416,6 +2735,8 @@ namespace OpenSim.Region.Framework.Scenes
2416 /// <param name="objectGroup"></param> 2735 /// <param name="objectGroup"></param>
2417 public virtual void DetachFromBackup() 2736 public virtual void DetachFromBackup()
2418 { 2737 {
2738 m_scene.SceneGraph.FireDetachFromBackup(this);
2739
2419 if (m_isBackedUp) 2740 if (m_isBackedUp)
2420 m_scene.EventManager.OnBackup -= ProcessBackup; 2741 m_scene.EventManager.OnBackup -= ProcessBackup;
2421 2742
@@ -2694,9 +3015,12 @@ namespace OpenSim.Region.Framework.Scenes
2694 3015
2695 if (selectionPart != null) 3016 if (selectionPart != null)
2696 { 3017 {
2697 lock (m_parts) 3018 lockPartsForRead(true);
3019 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
3020 lockPartsForRead(false);
3021 foreach (SceneObjectPart part in parts)
2698 { 3022 {
2699 foreach (SceneObjectPart part in m_parts.Values) 3023 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2700 { 3024 {
2701 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 3025 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2702 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 3026 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2706,12 +3030,13 @@ namespace OpenSim.Region.Framework.Scenes
2706 break; 3030 break;
2707 } 3031 }
2708 } 3032 }
3033 }
2709 3034
2710 foreach (SceneObjectPart part in m_parts.Values) 3035 foreach (SceneObjectPart part in parts)
2711 { 3036 {
2712 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3037 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2713 }
2714 } 3038 }
3039
2715 } 3040 }
2716 } 3041 }
2717 3042
@@ -2724,6 +3049,17 @@ namespace OpenSim.Region.Framework.Scenes
2724 } 3049 }
2725 } 3050 }
2726 3051
3052
3053
3054 /// <summary>
3055 /// Gets the number of parts
3056 /// </summary>
3057 /// <returns></returns>
3058 public int GetPartCount()
3059 {
3060 return Children.Count;
3061 }
3062
2727 /// <summary> 3063 /// <summary>
2728 /// Get the parts of this scene object 3064 /// Get the parts of this scene object
2729 /// </summary> 3065 /// </summary>
@@ -2797,11 +3133,9 @@ namespace OpenSim.Region.Framework.Scenes
2797 scale.Y = m_scene.m_maxNonphys; 3133 scale.Y = m_scene.m_maxNonphys;
2798 if (scale.Z > m_scene.m_maxNonphys) 3134 if (scale.Z > m_scene.m_maxNonphys)
2799 scale.Z = m_scene.m_maxNonphys; 3135 scale.Z = m_scene.m_maxNonphys;
2800
2801 SceneObjectPart part = GetChildPart(localID); 3136 SceneObjectPart part = GetChildPart(localID);
2802 if (part != null) 3137 if (part != null)
2803 { 3138 {
2804 part.Resize(scale);
2805 if (part.PhysActor != null) 3139 if (part.PhysActor != null)
2806 { 3140 {
2807 if (part.PhysActor.IsPhysical) 3141 if (part.PhysActor.IsPhysical)
@@ -2816,7 +3150,7 @@ namespace OpenSim.Region.Framework.Scenes
2816 part.PhysActor.Size = scale; 3150 part.PhysActor.Size = scale;
2817 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3151 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2818 } 3152 }
2819 //if (part.UUID != m_rootPart.UUID) 3153 part.Resize(scale);
2820 3154
2821 HasGroupChanged = true; 3155 HasGroupChanged = true;
2822 ScheduleGroupForFullUpdate(); 3156 ScheduleGroupForFullUpdate();
@@ -2838,7 +3172,6 @@ namespace OpenSim.Region.Framework.Scenes
2838 SceneObjectPart part = GetChildPart(localID); 3172 SceneObjectPart part = GetChildPart(localID);
2839 if (part != null) 3173 if (part != null)
2840 { 3174 {
2841 part.IgnoreUndoUpdate = true;
2842 if (scale.X > m_scene.m_maxNonphys) 3175 if (scale.X > m_scene.m_maxNonphys)
2843 scale.X = m_scene.m_maxNonphys; 3176 scale.X = m_scene.m_maxNonphys;
2844 if (scale.Y > m_scene.m_maxNonphys) 3177 if (scale.Y > m_scene.m_maxNonphys)
@@ -2858,94 +3191,100 @@ namespace OpenSim.Region.Framework.Scenes
2858 float y = (scale.Y / part.Scale.Y); 3191 float y = (scale.Y / part.Scale.Y);
2859 float z = (scale.Z / part.Scale.Z); 3192 float z = (scale.Z / part.Scale.Z);
2860 3193
2861 lock (m_parts) 3194 lockPartsForRead(true);
3195 if (x > 1.0f || y > 1.0f || z > 1.0f)
2862 { 3196 {
2863 if (x > 1.0f || y > 1.0f || z > 1.0f) 3197 foreach (SceneObjectPart obPart in m_parts.Values)
2864 { 3198 {
2865 foreach (SceneObjectPart obPart in m_parts.Values) 3199 if (obPart.UUID != m_rootPart.UUID)
2866 { 3200 {
2867 if (obPart.UUID != m_rootPart.UUID) 3201 Vector3 oldSize = new Vector3(obPart.Scale);
2868 { 3202 obPart.IgnoreUndoUpdate = true;
2869 obPart.IgnoreUndoUpdate = true;
2870 Vector3 oldSize = new Vector3(obPart.Scale);
2871 3203
2872 float f = 1.0f; 3204 float f = 1.0f;
2873 float a = 1.0f; 3205 float a = 1.0f;
2874 3206
2875 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3207 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3208 {
3209 if (oldSize.X*x > m_scene.m_maxPhys)
2876 { 3210 {
2877 if (oldSize.X*x > m_scene.m_maxPhys) 3211 f = m_scene.m_maxPhys / oldSize.X;
2878 { 3212 a = f / x;
2879 f = m_scene.m_maxPhys / oldSize.X; 3213 x *= a;
2880 a = f / x; 3214 y *= a;
2881 x *= a; 3215 z *= a;
2882 y *= a;
2883 z *= a;
2884 }
2885 if (oldSize.Y*y > m_scene.m_maxPhys)
2886 {
2887 f = m_scene.m_maxPhys / oldSize.Y;
2888 a = f / y;
2889 x *= a;
2890 y *= a;
2891 z *= a;
2892 }
2893 if (oldSize.Z*z > m_scene.m_maxPhys)
2894 {
2895 f = m_scene.m_maxPhys / oldSize.Z;
2896 a = f / z;
2897 x *= a;
2898 y *= a;
2899 z *= a;
2900 }
2901 } 3216 }
2902 else 3217 if (oldSize.Y*y > m_scene.m_maxPhys)
3218 {
3219 f = m_scene.m_maxPhys / oldSize.Y;
3220 a = f / y;
3221 x *= a;
3222 y *= a;
3223 z *= a;
3224 }
3225 if (oldSize.Z*z > m_scene.m_maxPhys)
3226 {
3227 f = m_scene.m_maxPhys / oldSize.Z;
3228 a = f / z;
3229 x *= a;
3230 y *= a;
3231 z *= a;
3232 }
3233 }
3234 else
3235 {
3236 if (oldSize.X*x > m_scene.m_maxNonphys)
3237 {
3238 f = m_scene.m_maxNonphys / oldSize.X;
3239 a = f / x;
3240 x *= a;
3241 y *= a;
3242 z *= a;
3243 }
3244 if (oldSize.Y*y > m_scene.m_maxNonphys)
3245 {
3246 f = m_scene.m_maxNonphys / oldSize.Y;
3247 a = f / y;
3248 x *= a;
3249 y *= a;
3250 z *= a;
3251 }
3252 if (oldSize.Z*z > m_scene.m_maxNonphys)
2903 { 3253 {
2904 if (oldSize.X*x > m_scene.m_maxNonphys) 3254 f = m_scene.m_maxNonphys / oldSize.Z;
2905 { 3255 a = f / z;
2906 f = m_scene.m_maxNonphys / oldSize.X; 3256 x *= a;
2907 a = f / x; 3257 y *= a;
2908 x *= a; 3258 z *= a;
2909 y *= a;
2910 z *= a;
2911 }
2912 if (oldSize.Y*y > m_scene.m_maxNonphys)
2913 {
2914 f = m_scene.m_maxNonphys / oldSize.Y;
2915 a = f / y;
2916 x *= a;
2917 y *= a;
2918 z *= a;
2919 }
2920 if (oldSize.Z*z > m_scene.m_maxNonphys)
2921 {
2922 f = m_scene.m_maxNonphys / oldSize.Z;
2923 a = f / z;
2924 x *= a;
2925 y *= a;
2926 z *= a;
2927 }
2928 } 3259 }
2929 obPart.IgnoreUndoUpdate = false; 3260
2930 obPart.StoreUndoState();
2931 } 3261 }
2932 } 3262 }
2933 } 3263 }
2934 } 3264 }
3265 lockPartsForRead(false);
2935 3266
2936 Vector3 prevScale = part.Scale; 3267 Vector3 prevScale = part.Scale;
2937 prevScale.X *= x; 3268 prevScale.X *= x;
2938 prevScale.Y *= y; 3269 prevScale.Y *= y;
2939 prevScale.Z *= z; 3270 prevScale.Z *= z;;
3271
3272 part.IgnoreUndoUpdate = false;
3273 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3274 part.IgnoreUndoUpdate = true;
2940 part.Resize(prevScale); 3275 part.Resize(prevScale);
3276 part.IgnoreUndoUpdate = false;
2941 3277
2942 lock (m_parts) 3278 lockPartsForRead(true);
2943 { 3279 {
2944 foreach (SceneObjectPart obPart in m_parts.Values) 3280 foreach (SceneObjectPart obPart in m_parts.Values)
2945 { 3281 {
2946 obPart.IgnoreUndoUpdate = true;
2947 if (obPart.UUID != m_rootPart.UUID) 3282 if (obPart.UUID != m_rootPart.UUID)
2948 { 3283 {
3284 obPart.IgnoreUndoUpdate = false;
3285 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3286 obPart.IgnoreUndoUpdate = true;
3287
2949 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3288 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2950 currentpos.X *= x; 3289 currentpos.X *= x;
2951 currentpos.Y *= y; 3290 currentpos.Y *= y;
@@ -2958,9 +3297,9 @@ namespace OpenSim.Region.Framework.Scenes
2958 obPart.UpdateOffSet(currentpos); 3297 obPart.UpdateOffSet(currentpos);
2959 } 3298 }
2960 obPart.IgnoreUndoUpdate = false; 3299 obPart.IgnoreUndoUpdate = false;
2961 obPart.StoreUndoState();
2962 } 3300 }
2963 } 3301 }
3302 lockPartsForRead(false);
2964 3303
2965 if (part.PhysActor != null) 3304 if (part.PhysActor != null)
2966 { 3305 {
@@ -2969,7 +3308,6 @@ namespace OpenSim.Region.Framework.Scenes
2969 } 3308 }
2970 3309
2971 part.IgnoreUndoUpdate = false; 3310 part.IgnoreUndoUpdate = false;
2972 part.StoreUndoState();
2973 HasGroupChanged = true; 3311 HasGroupChanged = true;
2974 ScheduleGroupForTerseUpdate(); 3312 ScheduleGroupForTerseUpdate();
2975 } 3313 }
@@ -2985,14 +3323,11 @@ namespace OpenSim.Region.Framework.Scenes
2985 /// <param name="pos"></param> 3323 /// <param name="pos"></param>
2986 public void UpdateGroupPosition(Vector3 pos) 3324 public void UpdateGroupPosition(Vector3 pos)
2987 { 3325 {
2988 foreach (SceneObjectPart part in Children.Values)
2989 {
2990 part.StoreUndoState();
2991 }
2992 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3326 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2993 { 3327 {
2994 if (IsAttachment) 3328 if (IsAttachment)
2995 { 3329 {
3330 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2996 m_rootPart.AttachedPos = pos; 3331 m_rootPart.AttachedPos = pos;
2997 } 3332 }
2998 if (RootPart.GetStatusSandbox()) 3333 if (RootPart.GetStatusSandbox())
@@ -3025,7 +3360,7 @@ namespace OpenSim.Region.Framework.Scenes
3025 SceneObjectPart part = GetChildPart(localID); 3360 SceneObjectPart part = GetChildPart(localID);
3026 foreach (SceneObjectPart parts in Children.Values) 3361 foreach (SceneObjectPart parts in Children.Values)
3027 { 3362 {
3028 parts.StoreUndoState(); 3363 parts.StoreUndoState(UndoType.STATE_PRIM_POSITION);
3029 } 3364 }
3030 if (part != null) 3365 if (part != null)
3031 { 3366 {
@@ -3050,7 +3385,7 @@ namespace OpenSim.Region.Framework.Scenes
3050 { 3385 {
3051 foreach (SceneObjectPart part in Children.Values) 3386 foreach (SceneObjectPart part in Children.Values)
3052 { 3387 {
3053 part.StoreUndoState(); 3388 part.StoreUndoState(UndoType.STATE_PRIM_POSITION);
3054 } 3389 }
3055 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3390 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3056 Vector3 oldPos = 3391 Vector3 oldPos =
@@ -3063,7 +3398,7 @@ namespace OpenSim.Region.Framework.Scenes
3063 axDiff *= Quaternion.Inverse(partRotation); 3398 axDiff *= Quaternion.Inverse(partRotation);
3064 diff = axDiff; 3399 diff = axDiff;
3065 3400
3066 lock (m_parts) 3401 lockPartsForRead(true);
3067 { 3402 {
3068 foreach (SceneObjectPart obPart in m_parts.Values) 3403 foreach (SceneObjectPart obPart in m_parts.Values)
3069 { 3404 {
@@ -3073,11 +3408,29 @@ namespace OpenSim.Region.Framework.Scenes
3073 } 3408 }
3074 } 3409 }
3075 } 3410 }
3411 lockPartsForRead(false);
3076 3412
3077 AbsolutePosition = newPos; 3413 //We have to set undoing here because otherwise an undo state will be saved
3414 if (!m_rootPart.Undoing)
3415 {
3416 m_rootPart.Undoing = true;
3417 AbsolutePosition = newPos;
3418 m_rootPart.Undoing = false;
3419 }
3420 else
3421 {
3422 AbsolutePosition = newPos;
3423 }
3078 3424
3079 HasGroupChanged = true; 3425 HasGroupChanged = true;
3080 ScheduleGroupForTerseUpdate(); 3426 if (m_rootPart.Undoing)
3427 {
3428 ScheduleGroupForFullUpdate();
3429 }
3430 else
3431 {
3432 ScheduleGroupForTerseUpdate();
3433 }
3081 } 3434 }
3082 3435
3083 public void OffsetForNewRegion(Vector3 offset) 3436 public void OffsetForNewRegion(Vector3 offset)
@@ -3097,7 +3450,7 @@ namespace OpenSim.Region.Framework.Scenes
3097 { 3450 {
3098 foreach (SceneObjectPart parts in Children.Values) 3451 foreach (SceneObjectPart parts in Children.Values)
3099 { 3452 {
3100 parts.StoreUndoState(); 3453 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3101 } 3454 }
3102 m_rootPart.UpdateRotation(rot); 3455 m_rootPart.UpdateRotation(rot);
3103 3456
@@ -3121,7 +3474,7 @@ namespace OpenSim.Region.Framework.Scenes
3121 { 3474 {
3122 foreach (SceneObjectPart parts in Children.Values) 3475 foreach (SceneObjectPart parts in Children.Values)
3123 { 3476 {
3124 parts.StoreUndoState(); 3477 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3125 } 3478 }
3126 m_rootPart.UpdateRotation(rot); 3479 m_rootPart.UpdateRotation(rot);
3127 3480
@@ -3148,7 +3501,7 @@ namespace OpenSim.Region.Framework.Scenes
3148 SceneObjectPart part = GetChildPart(localID); 3501 SceneObjectPart part = GetChildPart(localID);
3149 foreach (SceneObjectPart parts in Children.Values) 3502 foreach (SceneObjectPart parts in Children.Values)
3150 { 3503 {
3151 parts.StoreUndoState(); 3504 parts.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3152 } 3505 }
3153 if (part != null) 3506 if (part != null)
3154 { 3507 {
@@ -3176,15 +3529,24 @@ namespace OpenSim.Region.Framework.Scenes
3176 if (part.UUID == m_rootPart.UUID) 3529 if (part.UUID == m_rootPart.UUID)
3177 { 3530 {
3178 UpdateRootRotation(rot); 3531 UpdateRootRotation(rot);
3179 AbsolutePosition = pos; 3532 if (!m_rootPart.Undoing)
3533 {
3534 m_rootPart.Undoing = true;
3535 AbsolutePosition = pos;
3536 m_rootPart.Undoing = false;
3537 }
3538 else
3539 {
3540 AbsolutePosition = pos;
3541 }
3180 } 3542 }
3181 else 3543 else
3182 { 3544 {
3545 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3183 part.IgnoreUndoUpdate = true; 3546 part.IgnoreUndoUpdate = true;
3184 part.UpdateRotation(rot); 3547 part.UpdateRotation(rot);
3185 part.OffsetPosition = pos; 3548 part.OffsetPosition = pos;
3186 part.IgnoreUndoUpdate = false; 3549 part.IgnoreUndoUpdate = false;
3187 part.StoreUndoState();
3188 } 3550 }
3189 } 3551 }
3190 } 3552 }
@@ -3198,7 +3560,13 @@ namespace OpenSim.Region.Framework.Scenes
3198 Quaternion axRot = rot; 3560 Quaternion axRot = rot;
3199 Quaternion oldParentRot = m_rootPart.RotationOffset; 3561 Quaternion oldParentRot = m_rootPart.RotationOffset;
3200 3562
3201 m_rootPart.StoreUndoState(); 3563 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3564 bool cancelUndo = false;
3565 if (!m_rootPart.Undoing)
3566 {
3567 m_rootPart.Undoing = true;
3568 cancelUndo = true;
3569 }
3202 m_rootPart.UpdateRotation(rot); 3570 m_rootPart.UpdateRotation(rot);
3203 if (m_rootPart.PhysActor != null) 3571 if (m_rootPart.PhysActor != null)
3204 { 3572 {
@@ -3206,33 +3574,31 @@ namespace OpenSim.Region.Framework.Scenes
3206 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3574 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3207 } 3575 }
3208 3576
3209 lock (m_parts) 3577 lockPartsForRead(true);
3578
3579 foreach (SceneObjectPart prim in m_parts.Values)
3210 { 3580 {
3211 foreach (SceneObjectPart prim in m_parts.Values) 3581 if (prim.UUID != m_rootPart.UUID)
3212 { 3582 {
3213 if (prim.UUID != m_rootPart.UUID) 3583 prim.IgnoreUndoUpdate = true;
3214 { 3584 Vector3 axPos = prim.OffsetPosition;
3215 prim.IgnoreUndoUpdate = true; 3585 axPos *= oldParentRot;
3216 Vector3 axPos = prim.OffsetPosition; 3586 axPos *= Quaternion.Inverse(axRot);
3217 axPos *= oldParentRot; 3587 prim.OffsetPosition = axPos;
3218 axPos *= Quaternion.Inverse(axRot); 3588 Quaternion primsRot = prim.RotationOffset;
3219 prim.OffsetPosition = axPos; 3589 Quaternion newRot = primsRot * oldParentRot;
3220 Quaternion primsRot = prim.RotationOffset; 3590 newRot *= Quaternion.Inverse(axRot);
3221 Quaternion newRot = primsRot * oldParentRot; 3591 prim.RotationOffset = newRot;
3222 newRot *= Quaternion.Inverse(axRot); 3592 prim.ScheduleTerseUpdate();
3223 prim.RotationOffset = newRot; 3593 prim.IgnoreUndoUpdate = false;
3224 prim.ScheduleTerseUpdate();
3225 }
3226 } 3594 }
3227 } 3595 }
3228 foreach (SceneObjectPart childpart in Children.Values) 3596 if (cancelUndo == true)
3229 { 3597 {
3230 if (childpart != m_rootPart) 3598 m_rootPart.Undoing = false;
3231 {
3232 childpart.IgnoreUndoUpdate = false;
3233 childpart.StoreUndoState();
3234 }
3235 } 3599 }
3600 lockPartsForRead(false);
3601
3236 m_rootPart.ScheduleTerseUpdate(); 3602 m_rootPart.ScheduleTerseUpdate();
3237 } 3603 }
3238 3604
@@ -3354,7 +3720,7 @@ namespace OpenSim.Region.Framework.Scenes
3354 if (atTargets.Count > 0) 3720 if (atTargets.Count > 0)
3355 { 3721 {
3356 uint[] localids = new uint[0]; 3722 uint[] localids = new uint[0];
3357 lock (m_parts) 3723 lockPartsForRead(true);
3358 { 3724 {
3359 localids = new uint[m_parts.Count]; 3725 localids = new uint[m_parts.Count];
3360 int cntr = 0; 3726 int cntr = 0;
@@ -3364,6 +3730,7 @@ namespace OpenSim.Region.Framework.Scenes
3364 cntr++; 3730 cntr++;
3365 } 3731 }
3366 } 3732 }
3733 lockPartsForRead(false);
3367 3734
3368 for (int ctr = 0; ctr < localids.Length; ctr++) 3735 for (int ctr = 0; ctr < localids.Length; ctr++)
3369 { 3736 {
@@ -3382,7 +3749,7 @@ namespace OpenSim.Region.Framework.Scenes
3382 { 3749 {
3383 //trigger not_at_target 3750 //trigger not_at_target
3384 uint[] localids = new uint[0]; 3751 uint[] localids = new uint[0];
3385 lock (m_parts) 3752 lockPartsForRead(true);
3386 { 3753 {
3387 localids = new uint[m_parts.Count]; 3754 localids = new uint[m_parts.Count];
3388 int cntr = 0; 3755 int cntr = 0;
@@ -3392,7 +3759,8 @@ namespace OpenSim.Region.Framework.Scenes
3392 cntr++; 3759 cntr++;
3393 } 3760 }
3394 } 3761 }
3395 3762 lockPartsForRead(false);
3763
3396 for (int ctr = 0; ctr < localids.Length; ctr++) 3764 for (int ctr = 0; ctr < localids.Length; ctr++)
3397 { 3765 {
3398 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3766 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3433,7 +3801,8 @@ namespace OpenSim.Region.Framework.Scenes
3433 if (atRotTargets.Count > 0) 3801 if (atRotTargets.Count > 0)
3434 { 3802 {
3435 uint[] localids = new uint[0]; 3803 uint[] localids = new uint[0];
3436 lock (m_parts) 3804 lockPartsForRead(true);
3805 try
3437 { 3806 {
3438 localids = new uint[m_parts.Count]; 3807 localids = new uint[m_parts.Count];
3439 int cntr = 0; 3808 int cntr = 0;
@@ -3443,6 +3812,10 @@ namespace OpenSim.Region.Framework.Scenes
3443 cntr++; 3812 cntr++;
3444 } 3813 }
3445 } 3814 }
3815 finally
3816 {
3817 lockPartsForRead(false);
3818 }
3446 3819
3447 for (int ctr = 0; ctr < localids.Length; ctr++) 3820 for (int ctr = 0; ctr < localids.Length; ctr++)
3448 { 3821 {
@@ -3461,7 +3834,8 @@ namespace OpenSim.Region.Framework.Scenes
3461 { 3834 {
3462 //trigger not_at_target 3835 //trigger not_at_target
3463 uint[] localids = new uint[0]; 3836 uint[] localids = new uint[0];
3464 lock (m_parts) 3837 lockPartsForRead(true);
3838 try
3465 { 3839 {
3466 localids = new uint[m_parts.Count]; 3840 localids = new uint[m_parts.Count];
3467 int cntr = 0; 3841 int cntr = 0;
@@ -3471,6 +3845,10 @@ namespace OpenSim.Region.Framework.Scenes
3471 cntr++; 3845 cntr++;
3472 } 3846 }
3473 } 3847 }
3848 finally
3849 {
3850 lockPartsForRead(false);
3851 }
3474 3852
3475 for (int ctr = 0; ctr < localids.Length; ctr++) 3853 for (int ctr = 0; ctr < localids.Length; ctr++)
3476 { 3854 {
@@ -3484,19 +3862,20 @@ namespace OpenSim.Region.Framework.Scenes
3484 public float GetMass() 3862 public float GetMass()
3485 { 3863 {
3486 float retmass = 0f; 3864 float retmass = 0f;
3487 lock (m_parts) 3865 lockPartsForRead(true);
3488 { 3866 {
3489 foreach (SceneObjectPart part in m_parts.Values) 3867 foreach (SceneObjectPart part in m_parts.Values)
3490 { 3868 {
3491 retmass += part.GetMass(); 3869 retmass += part.GetMass();
3492 } 3870 }
3493 } 3871 }
3872 lockPartsForRead(false);
3494 return retmass; 3873 return retmass;
3495 } 3874 }
3496 3875
3497 public void CheckSculptAndLoad() 3876 public void CheckSculptAndLoad()
3498 { 3877 {
3499 lock (m_parts) 3878 lockPartsForRead(true);
3500 { 3879 {
3501 if (!IsDeleted) 3880 if (!IsDeleted)
3502 { 3881 {
@@ -3521,6 +3900,7 @@ namespace OpenSim.Region.Framework.Scenes
3521 } 3900 }
3522 } 3901 }
3523 } 3902 }
3903 lockPartsForRead(false);
3524 } 3904 }
3525 3905
3526 protected void AssetReceived(string id, Object sender, AssetBase asset) 3906 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3541,7 +3921,7 @@ namespace OpenSim.Region.Framework.Scenes
3541 /// <param name="client"></param> 3921 /// <param name="client"></param>
3542 public void SetGroup(UUID GroupID, IClientAPI client) 3922 public void SetGroup(UUID GroupID, IClientAPI client)
3543 { 3923 {
3544 lock (m_parts) 3924 lockPartsForRead(true);
3545 { 3925 {
3546 foreach (SceneObjectPart part in m_parts.Values) 3926 foreach (SceneObjectPart part in m_parts.Values)
3547 { 3927 {
@@ -3551,6 +3931,7 @@ namespace OpenSim.Region.Framework.Scenes
3551 3931
3552 HasGroupChanged = true; 3932 HasGroupChanged = true;
3553 } 3933 }
3934 lockPartsForRead(false);
3554 3935
3555 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3936 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3556 // for the same object with very different properties. The caller must schedule the update. 3937 // for the same object with very different properties. The caller must schedule the update.
@@ -3572,11 +3953,12 @@ namespace OpenSim.Region.Framework.Scenes
3572 3953
3573 public void SetAttachmentPoint(byte point) 3954 public void SetAttachmentPoint(byte point)
3574 { 3955 {
3575 lock (m_parts) 3956 lockPartsForRead(true);
3576 { 3957 {
3577 foreach (SceneObjectPart part in m_parts.Values) 3958 foreach (SceneObjectPart part in m_parts.Values)
3578 part.SetAttachmentPoint(point); 3959 part.SetAttachmentPoint(point);
3579 } 3960 }
3961 lockPartsForRead(false);
3580 } 3962 }
3581 3963
3582 #region ISceneObject 3964 #region ISceneObject
@@ -3610,6 +3992,14 @@ namespace OpenSim.Region.Framework.Scenes
3610 SetFromItemID(uuid); 3992 SetFromItemID(uuid);
3611 } 3993 }
3612 3994
3995 public void ResetOwnerChangeFlag()
3996 {
3997 ForEachPart(delegate(SceneObjectPart part)
3998 {
3999 part.ResetOwnerChangeFlag();
4000 });
4001 }
4002
3613 #endregion 4003 #endregion
3614 } 4004 }
3615} 4005}