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.cs883
1 files changed, 632 insertions, 251 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 17275d0..dbf493c 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,16 +465,17 @@ 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 foreach (SceneObjectPart part in m_parts.Values)
312 { 473 {
313 foreach (SceneObjectPart part in m_parts.Values) 474 part.IgnoreUndoUpdate = false;
314 { 475 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
315 part.GroupPosition = val; 476 part.GroupPosition = val;
316 }
317 } 477 }
478 lockPartsForRead(false);
318 479
319 //if (m_rootPart.PhysActor != null) 480 //if (m_rootPart.PhysActor != null)
320 //{ 481 //{
@@ -457,6 +618,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 618 /// </summary>
458 public SceneObjectGroup() 619 public SceneObjectGroup()
459 { 620 {
621
460 } 622 }
461 623
462 /// <summary> 624 /// <summary>
@@ -473,7 +635,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 635 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 636 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 637 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 638 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 639 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 640 }
479 641
@@ -504,13 +666,16 @@ namespace OpenSim.Region.Framework.Scenes
504 666
505 public void SetFromItemID(UUID AssetId) 667 public void SetFromItemID(UUID AssetId)
506 { 668 {
507 lock (m_parts) 669 lockPartsForRead(true);
508 { 670 {
509 foreach (SceneObjectPart part in m_parts.Values) 671 foreach (SceneObjectPart part in m_parts.Values)
510 { 672 {
673
511 part.FromItemID = AssetId; 674 part.FromItemID = AssetId;
675
512 } 676 }
513 } 677 }
678 lockPartsForRead(false);
514 } 679 }
515 680
516 public UUID GetFromItemID() 681 public UUID GetFromItemID()
@@ -523,6 +688,9 @@ namespace OpenSim.Region.Framework.Scenes
523 /// </summary> 688 /// </summary>
524 public virtual void AttachToBackup() 689 public virtual void AttachToBackup()
525 { 690 {
691 if (IsAttachment) return;
692 m_scene.SceneGraph.FireAttachToBackup(this);
693
526 if (InSceneBackup) 694 if (InSceneBackup)
527 { 695 {
528 //m_log.DebugFormat( 696 //m_log.DebugFormat(
@@ -579,7 +747,7 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 747 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 748 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 749
582 lock (m_parts) 750 lockPartsForRead(true);
583 { 751 {
584 foreach (SceneObjectPart part in m_parts.Values) 752 foreach (SceneObjectPart part in m_parts.Values)
585 { 753 {
@@ -593,8 +761,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 761 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; 762 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; 763 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
764
596 } 765 }
597 } 766 }
767 lockPartsForRead(false);
768
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 769 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 770 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 771 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +781,11 @@ namespace OpenSim.Region.Framework.Scenes
610 781
611 EntityIntersection result = new EntityIntersection(); 782 EntityIntersection result = new EntityIntersection();
612 783
613 lock (m_parts) 784 lockPartsForRead(true);
614 { 785 {
615 foreach (SceneObjectPart part in m_parts.Values) 786 foreach (SceneObjectPart part in m_parts.Values)
616 { 787 {
788
617 // Temporary commented to stop compiler warning 789 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 790 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 791 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +813,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 813 result.distance = inter.distance;
642 } 814 }
643 } 815 }
816
644 } 817 }
645 } 818 }
819 lockPartsForRead(false);
646 return result; 820 return result;
647 } 821 }
648 822
@@ -661,10 +835,11 @@ namespace OpenSim.Region.Framework.Scenes
661 minY = 256f; 835 minY = 256f;
662 minZ = 8192f; 836 minZ = 8192f;
663 837
664 lock(m_parts); 838 lockPartsForRead(true);
665 { 839 {
666 foreach (SceneObjectPart part in m_parts.Values) 840 foreach (SceneObjectPart part in m_parts.Values)
667 { 841 {
842
668 Vector3 worldPos = part.GetWorldPosition(); 843 Vector3 worldPos = part.GetWorldPosition();
669 Vector3 offset = worldPos - AbsolutePosition; 844 Vector3 offset = worldPos - AbsolutePosition;
670 Quaternion worldRot; 845 Quaternion worldRot;
@@ -723,6 +898,8 @@ namespace OpenSim.Region.Framework.Scenes
723 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 898 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
724 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 899 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
725 900
901
902
726 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 903 //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); 904 //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); 905 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -894,6 +1071,7 @@ namespace OpenSim.Region.Framework.Scenes
894 minZ = backBottomLeft.Z; 1071 minZ = backBottomLeft.Z;
895 } 1072 }
896 } 1073 }
1074 lockPartsForRead(false);
897 } 1075 }
898 1076
899 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 1077 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
@@ -929,21 +1107,29 @@ namespace OpenSim.Region.Framework.Scenes
929 1107
930 public void SaveScriptedState(XmlTextWriter writer) 1108 public void SaveScriptedState(XmlTextWriter writer)
931 { 1109 {
1110 SaveScriptedState(writer, false);
1111 }
1112
1113 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1114 {
932 XmlDocument doc = new XmlDocument(); 1115 XmlDocument doc = new XmlDocument();
933 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1116 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
934 1117
935 // Capture script state while holding the lock 1118 // Capture script state while holding the lock
936 lock (m_parts) 1119 lockPartsForRead(true);
937 { 1120 {
938 foreach (SceneObjectPart part in m_parts.Values) 1121 foreach (SceneObjectPart part in m_parts.Values)
939 { 1122 {
940 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1123
1124 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
941 foreach (UUID itemid in pstates.Keys) 1125 foreach (UUID itemid in pstates.Keys)
942 { 1126 {
943 states.Add(itemid, pstates[itemid]); 1127 states.Add(itemid, pstates[itemid]);
944 } 1128 }
1129
945 } 1130 }
946 } 1131 }
1132 lockPartsForRead(false);
947 1133
948 if (states.Count > 0) 1134 if (states.Count > 0)
949 { 1135 {
@@ -962,6 +1148,47 @@ namespace OpenSim.Region.Framework.Scenes
962 } 1148 }
963 1149
964 /// <summary> 1150 /// <summary>
1151 /// Add the avatar to this linkset (avatar is sat).
1152 /// </summary>
1153 /// <param name="agentID"></param>
1154 public void AddAvatar(UUID agentID)
1155 {
1156 ScenePresence presence;
1157 if (m_scene.TryGetScenePresence(agentID, out presence))
1158 {
1159 if (!m_linkedAvatars.Contains(presence))
1160 {
1161 m_linkedAvatars.Add(presence);
1162 }
1163 }
1164 }
1165
1166 /// <summary>
1167 /// Delete the avatar from this linkset (avatar is unsat).
1168 /// </summary>
1169 /// <param name="agentID"></param>
1170 public void DeleteAvatar(UUID agentID)
1171 {
1172 ScenePresence presence;
1173 if (m_scene.TryGetScenePresence(agentID, out presence))
1174 {
1175 if (m_linkedAvatars.Contains(presence))
1176 {
1177 m_linkedAvatars.Remove(presence);
1178 }
1179 }
1180 }
1181
1182 /// <summary>
1183 /// Returns the list of linked presences (avatars sat on this group)
1184 /// </summary>
1185 /// <param name="agentID"></param>
1186 public List<ScenePresence> GetLinkedAvatars()
1187 {
1188 return m_linkedAvatars;
1189 }
1190
1191 /// <summary>
965 /// Attach this scene object to the given avatar. 1192 /// Attach this scene object to the given avatar.
966 /// </summary> 1193 /// </summary>
967 /// <param name="agentID"></param> 1194 /// <param name="agentID"></param>
@@ -1112,13 +1339,16 @@ namespace OpenSim.Region.Framework.Scenes
1112 1339
1113 public override void UpdateMovement() 1340 public override void UpdateMovement()
1114 { 1341 {
1115 lock (m_parts) 1342 lockPartsForRead(true);
1116 { 1343 {
1117 foreach (SceneObjectPart part in m_parts.Values) 1344 foreach (SceneObjectPart part in m_parts.Values)
1118 { 1345 {
1346
1119 part.UpdateMovement(); 1347 part.UpdateMovement();
1348
1120 } 1349 }
1121 } 1350 }
1351 lockPartsForRead(false);
1122 } 1352 }
1123 1353
1124 public ushort GetTimeDilation() 1354 public ushort GetTimeDilation()
@@ -1162,7 +1392,7 @@ namespace OpenSim.Region.Framework.Scenes
1162 /// <param name="part"></param> 1392 /// <param name="part"></param>
1163 public void AddPart(SceneObjectPart part) 1393 public void AddPart(SceneObjectPart part)
1164 { 1394 {
1165 lock (m_parts) 1395 lockPartsForWrite(true);
1166 { 1396 {
1167 part.SetParent(this); 1397 part.SetParent(this);
1168 m_parts.Add(part.UUID, part); 1398 m_parts.Add(part.UUID, part);
@@ -1172,6 +1402,7 @@ namespace OpenSim.Region.Framework.Scenes
1172 if (part.LinkNum == 2 && RootPart != null) 1402 if (part.LinkNum == 2 && RootPart != null)
1173 RootPart.LinkNum = 1; 1403 RootPart.LinkNum = 1;
1174 } 1404 }
1405 lockPartsForWrite(false);
1175 } 1406 }
1176 1407
1177 /// <summary> 1408 /// <summary>
@@ -1179,28 +1410,33 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// </summary> 1410 /// </summary>
1180 private void UpdateParentIDs() 1411 private void UpdateParentIDs()
1181 { 1412 {
1182 lock (m_parts) 1413 lockPartsForRead(true);
1183 { 1414 {
1184 foreach (SceneObjectPart part in m_parts.Values) 1415 foreach (SceneObjectPart part in m_parts.Values)
1185 { 1416 {
1417
1186 if (part.UUID != m_rootPart.UUID) 1418 if (part.UUID != m_rootPart.UUID)
1187 { 1419 {
1188 part.ParentID = m_rootPart.LocalId; 1420 part.ParentID = m_rootPart.LocalId;
1189 } 1421 }
1422
1190 } 1423 }
1191 } 1424 }
1425 lockPartsForRead(false);
1192 } 1426 }
1193 1427
1194 public void RegenerateFullIDs() 1428 public void RegenerateFullIDs()
1195 { 1429 {
1196 lock (m_parts) 1430 lockPartsForRead(true);
1197 { 1431 {
1198 foreach (SceneObjectPart part in m_parts.Values) 1432 foreach (SceneObjectPart part in m_parts.Values)
1199 { 1433 {
1434
1200 part.UUID = UUID.Random(); 1435 part.UUID = UUID.Random();
1201 1436
1202 } 1437 }
1203 } 1438 }
1439 lockPartsForRead(false);
1204 } 1440 }
1205 1441
1206 // helper provided for parts. 1442 // helper provided for parts.
@@ -1261,7 +1497,7 @@ namespace OpenSim.Region.Framework.Scenes
1261 1497
1262 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1498 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1263 { 1499 {
1264 part.StoreUndoState(); 1500 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1265 part.OnGrab(offsetPos, remoteClient); 1501 part.OnGrab(offsetPos, remoteClient);
1266 } 1502 }
1267 1503
@@ -1281,27 +1517,32 @@ namespace OpenSim.Region.Framework.Scenes
1281 1517
1282 DetachFromBackup(); 1518 DetachFromBackup();
1283 1519
1284 lock (m_parts) 1520 lockPartsForRead(true);
1521 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1522 lockPartsForRead(false);
1523
1524 foreach (SceneObjectPart part in values)
1285 { 1525 {
1286 foreach (SceneObjectPart part in m_parts.Values)
1287 {
1288// part.Inventory.RemoveScriptInstances(); 1526// part.Inventory.RemoveScriptInstances();
1289 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1527
1528 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1529 {
1530 if (sp.ParentID == LocalId)
1290 { 1531 {
1291 if (avatar.ParentID == LocalId) 1532 sp.StandUp();
1292 { 1533 }
1293 avatar.StandUp();
1294 }
1295 1534
1296 if (!silent) 1535 if (!silent)
1297 { 1536 {
1298 part.UpdateFlag = 0; 1537 part.UpdateFlag = 0;
1299 if (part == m_rootPart) 1538 if (part == m_rootPart)
1300 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1539 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1301 } 1540 }
1302 }); 1541 });
1303 } 1542
1304 } 1543 }
1544
1545
1305 } 1546 }
1306 1547
1307 public void AddScriptLPS(int count) 1548 public void AddScriptLPS(int count)
@@ -1326,17 +1567,20 @@ namespace OpenSim.Region.Framework.Scenes
1326 1567
1327 scriptEvents aggregateScriptEvents=0; 1568 scriptEvents aggregateScriptEvents=0;
1328 1569
1329 lock (m_parts) 1570 lockPartsForRead(true);
1330 { 1571 {
1331 foreach (SceneObjectPart part in m_parts.Values) 1572 foreach (SceneObjectPart part in m_parts.Values)
1332 { 1573 {
1574
1333 if (part == null) 1575 if (part == null)
1334 continue; 1576 continue;
1335 if (part != RootPart) 1577 if (part != RootPart)
1336 part.ObjectFlags = objectflagupdate; 1578 part.ObjectFlags = objectflagupdate;
1337 aggregateScriptEvents |= part.AggregateScriptEvents; 1579 aggregateScriptEvents |= part.AggregateScriptEvents;
1580
1338 } 1581 }
1339 } 1582 }
1583 lockPartsForRead(false);
1340 1584
1341 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1585 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1342 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1586 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1378,42 +1622,52 @@ namespace OpenSim.Region.Framework.Scenes
1378 /// <param name="m_physicalPrim"></param> 1622 /// <param name="m_physicalPrim"></param>
1379 public void ApplyPhysics(bool m_physicalPrim) 1623 public void ApplyPhysics(bool m_physicalPrim)
1380 { 1624 {
1381 lock (m_parts) 1625 lockPartsForRead(true);
1626
1627 if (m_parts.Count > 1)
1382 { 1628 {
1383 if (m_parts.Count > 1) 1629 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1630 lockPartsForRead(false);
1631 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1632 foreach (SceneObjectPart part in values)
1384 { 1633 {
1385 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1634
1386 foreach (SceneObjectPart part in m_parts.Values) 1635 if (part.LocalId != m_rootPart.LocalId)
1387 { 1636 {
1388 if (part.LocalId != m_rootPart.LocalId) 1637 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1389 {
1390 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1391 }
1392 } 1638 }
1393 1639
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 } 1640 }
1641 // Hack to get the physics scene geometries in the right spot
1642 ResetChildPrimPhysicsPositions();
1643 }
1644 else
1645 {
1646 lockPartsForRead(false);
1647 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1401 } 1648 }
1402 } 1649 }
1403 1650
1404 public void SetOwnerId(UUID userId) 1651 public void SetOwnerId(UUID userId)
1405 { 1652 {
1406 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1653 ForEachPart(delegate(SceneObjectPart part)
1654 {
1655
1656 part.OwnerID = userId;
1657
1658 });
1407 } 1659 }
1408 1660
1409 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1661 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1410 { 1662 {
1411 lock (m_parts) 1663 lockPartsForRead(true);
1664 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1665 lockPartsForRead(false);
1666 foreach (SceneObjectPart part in values)
1412 { 1667 {
1413 foreach (SceneObjectPart part in m_parts.Values) 1668
1414 { 1669 whatToDo(part);
1415 whatToDo(part); 1670
1416 }
1417 } 1671 }
1418 } 1672 }
1419 1673
@@ -1436,7 +1690,10 @@ namespace OpenSim.Region.Framework.Scenes
1436 1690
1437 try 1691 try
1438 { 1692 {
1439 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1693 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1694 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1695 m_scene.LoadingPrims) // Land may not be valid yet
1696
1440 { 1697 {
1441 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1698 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1442 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1699 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1511,15 +1768,17 @@ namespace OpenSim.Region.Framework.Scenes
1511 RootPart.SendFullUpdate( 1768 RootPart.SendFullUpdate(
1512 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1769 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1513 1770
1514 lock (m_parts) 1771 lockPartsForRead(true);
1515 { 1772 {
1516 foreach (SceneObjectPart part in m_parts.Values) 1773 foreach (SceneObjectPart part in m_parts.Values)
1517 { 1774 {
1775
1518 if (part != RootPart) 1776 if (part != RootPart)
1519 part.SendFullUpdate( 1777 part.SendFullUpdate(
1520 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1778 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1521 } 1779 }
1522 } 1780 }
1781 lockPartsForRead(false);
1523 } 1782 }
1524 1783
1525 #region Copying 1784 #region Copying
@@ -1580,10 +1839,11 @@ namespace OpenSim.Region.Framework.Scenes
1580 1839
1581 List<SceneObjectPart> partList; 1840 List<SceneObjectPart> partList;
1582 1841
1583 lock (m_parts) 1842 lockPartsForRead(true);
1584 { 1843
1585 partList = new List<SceneObjectPart>(m_parts.Values); 1844 partList = new List<SceneObjectPart>(m_parts.Values);
1586 } 1845
1846 lockPartsForRead(false);
1587 1847
1588 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1848 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1589 { 1849 {
@@ -1800,13 +2060,40 @@ namespace OpenSim.Region.Framework.Scenes
1800 } 2060 }
1801 } 2061 }
1802 2062
2063 public void rotLookAt(Quaternion target, float strength, float damping)
2064 {
2065 SceneObjectPart rootpart = m_rootPart;
2066 if (rootpart != null)
2067 {
2068 if (IsAttachment)
2069 {
2070 /*
2071 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2072 if (avatar != null)
2073 {
2074 Rotate the Av?
2075 } */
2076 }
2077 else
2078 {
2079 if (rootpart.PhysActor != null)
2080 { // APID must be implemented in your physics system for this to function.
2081 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2082 rootpart.PhysActor.APIDStrength = strength;
2083 rootpart.PhysActor.APIDDamping = damping;
2084 rootpart.PhysActor.APIDActive = true;
2085 }
2086 }
2087 }
2088 }
2089
1803 public void stopLookAt() 2090 public void stopLookAt()
1804 { 2091 {
1805 SceneObjectPart rootpart = m_rootPart; 2092 SceneObjectPart rootpart = m_rootPart;
1806 if (rootpart != null) 2093 if (rootpart != null)
1807 { 2094 {
1808 if (rootpart.PhysActor != null) 2095 if (rootpart.PhysActor != null)
1809 { 2096 { // APID must be implemented in your physics system for this to function.
1810 rootpart.PhysActor.APIDActive = false; 2097 rootpart.PhysActor.APIDActive = false;
1811 } 2098 }
1812 } 2099 }
@@ -1874,10 +2161,11 @@ namespace OpenSim.Region.Framework.Scenes
1874 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2161 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1875 newPart.SetParent(this); 2162 newPart.SetParent(this);
1876 2163
1877 lock (m_parts) 2164 lockPartsForWrite(true);
1878 { 2165 {
1879 m_parts.Add(newPart.UUID, newPart); 2166 m_parts.Add(newPart.UUID, newPart);
1880 } 2167 }
2168 lockPartsForWrite(false);
1881 2169
1882 SetPartAsNonRoot(newPart); 2170 SetPartAsNonRoot(newPart);
1883 2171
@@ -1940,7 +2228,7 @@ namespace OpenSim.Region.Framework.Scenes
1940 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2228 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1941 // return; 2229 // return;
1942 2230
1943 lock (m_parts) 2231 lockPartsForRead(true);
1944 { 2232 {
1945 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2233 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1946 2234
@@ -1960,9 +2248,12 @@ namespace OpenSim.Region.Framework.Scenes
1960 { 2248 {
1961 if (!IsSelected) 2249 if (!IsSelected)
1962 part.UpdateLookAt(); 2250 part.UpdateLookAt();
2251
1963 part.SendScheduledUpdates(); 2252 part.SendScheduledUpdates();
2253
1964 } 2254 }
1965 } 2255 }
2256 lockPartsForRead(false);
1966 } 2257 }
1967 2258
1968 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2259 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1971,27 +2262,29 @@ namespace OpenSim.Region.Framework.Scenes
1971 2262
1972 RootPart.AddFullUpdateToAvatar(presence); 2263 RootPart.AddFullUpdateToAvatar(presence);
1973 2264
1974 lock (m_parts) 2265 lockPartsForRead(true);
1975 { 2266 {
1976 foreach (SceneObjectPart part in m_parts.Values) 2267 foreach (SceneObjectPart part in m_parts.Values)
1977 { 2268 {
2269
1978 if (part != RootPart) 2270 if (part != RootPart)
1979 part.AddFullUpdateToAvatar(presence); 2271 part.AddFullUpdateToAvatar(presence);
2272
1980 } 2273 }
1981 } 2274 }
2275 lockPartsForRead(false);
1982 } 2276 }
1983 2277
1984 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2278 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1985 { 2279 {
1986// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2280 lockPartsForRead(true);
1987 2281
1988 lock (m_parts) 2282 foreach (SceneObjectPart part in m_parts.Values)
1989 { 2283 {
1990 foreach (SceneObjectPart part in m_parts.Values) 2284 part.AddTerseUpdateToAvatar(presence);
1991 {
1992 part.AddTerseUpdateToAvatar(presence);
1993 }
1994 } 2285 }
2286
2287 lockPartsForRead(false);
1995 } 2288 }
1996 2289
1997 /// <summary> 2290 /// <summary>
@@ -1999,20 +2292,23 @@ namespace OpenSim.Region.Framework.Scenes
1999 /// </summary> 2292 /// </summary>
2000 public void ScheduleGroupForFullUpdate() 2293 public void ScheduleGroupForFullUpdate()
2001 { 2294 {
2002 if (IsAttachment) 2295 //if (IsAttachment)
2003 m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); 2296 // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
2004 2297
2005 checkAtTargets(); 2298 checkAtTargets();
2006 RootPart.ScheduleFullUpdate(); 2299 RootPart.ScheduleFullUpdate();
2007 2300
2008 lock (m_parts) 2301 lockPartsForRead(true);
2009 { 2302 {
2010 foreach (SceneObjectPart part in m_parts.Values) 2303 foreach (SceneObjectPart part in m_parts.Values)
2011 { 2304 {
2305
2012 if (part != RootPart) 2306 if (part != RootPart)
2013 part.ScheduleFullUpdate(); 2307 part.ScheduleFullUpdate();
2308
2014 } 2309 }
2015 } 2310 }
2311 lockPartsForRead(false);
2016 } 2312 }
2017 2313
2018 /// <summary> 2314 /// <summary>
@@ -2020,37 +2316,38 @@ namespace OpenSim.Region.Framework.Scenes
2020 /// </summary> 2316 /// </summary>
2021 public void ScheduleGroupForTerseUpdate() 2317 public void ScheduleGroupForTerseUpdate()
2022 { 2318 {
2023// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2319 lockPartsForRead(true);
2024 2320 foreach (SceneObjectPart part in m_parts.Values)
2025 lock (m_parts)
2026 { 2321 {
2027 foreach (SceneObjectPart part in m_parts.Values) 2322 part.ScheduleTerseUpdate();
2028 {
2029 part.ScheduleTerseUpdate();
2030 }
2031 } 2323 }
2324
2325 lockPartsForRead(false);
2032 } 2326 }
2033 2327
2034 /// <summary> 2328 /// <summary>
2035 /// Immediately send a full update for this scene object. 2329 /// Immediately send a full update for this scene object.
2036 /// </summary> 2330 /// </summary>
2037 public void SendGroupFullUpdate() 2331 public void SendGroupFullUpdate()
2038 { 2332 {
2039 if (IsDeleted) 2333 if (IsDeleted)
2040 return; 2334 return;
2041 2335
2042// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2336// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2043 2337
2044 RootPart.SendFullUpdateToAllClients(); 2338 RootPart.SendFullUpdateToAllClients();
2045 2339
2046 lock (m_parts) 2340 lockPartsForRead(true);
2047 { 2341 {
2048 foreach (SceneObjectPart part in m_parts.Values) 2342 foreach (SceneObjectPart part in m_parts.Values)
2049 { 2343 {
2344
2050 if (part != RootPart) 2345 if (part != RootPart)
2051 part.SendFullUpdateToAllClients(); 2346 part.SendFullUpdateToAllClients();
2347
2052 } 2348 }
2053 } 2349 }
2350 lockPartsForRead(false);
2054 } 2351 }
2055 2352
2056 /// <summary> 2353 /// <summary>
@@ -2082,14 +2379,15 @@ namespace OpenSim.Region.Framework.Scenes
2082 { 2379 {
2083 if (IsDeleted) 2380 if (IsDeleted)
2084 return; 2381 return;
2085 2382
2086 lock (m_parts) 2383 lockPartsForRead(true);
2087 { 2384 {
2088 foreach (SceneObjectPart part in m_parts.Values) 2385 foreach (SceneObjectPart part in m_parts.Values)
2089 { 2386 {
2090 part.SendTerseUpdateToAllClients(); 2387 part.SendTerseUpdateToAllClients();
2091 } 2388 }
2092 } 2389 }
2390 lockPartsForRead(false);
2093 } 2391 }
2094 2392
2095 #endregion 2393 #endregion
@@ -2103,16 +2401,18 @@ namespace OpenSim.Region.Framework.Scenes
2103 /// <returns>null if no child part with that linknum or child part</returns> 2401 /// <returns>null if no child part with that linknum or child part</returns>
2104 public SceneObjectPart GetLinkNumPart(int linknum) 2402 public SceneObjectPart GetLinkNumPart(int linknum)
2105 { 2403 {
2106 lock (m_parts) 2404 lockPartsForRead(true);
2107 { 2405 {
2108 foreach (SceneObjectPart part in m_parts.Values) 2406 foreach (SceneObjectPart part in m_parts.Values)
2109 { 2407 {
2110 if (part.LinkNum == linknum) 2408 if (part.LinkNum == linknum)
2111 { 2409 {
2410 lockPartsForRead(false);
2112 return part; 2411 return part;
2113 } 2412 }
2114 } 2413 }
2115 } 2414 }
2415 lockPartsForRead(false);
2116 2416
2117 return null; 2417 return null;
2118 } 2418 }
@@ -2140,17 +2440,19 @@ namespace OpenSim.Region.Framework.Scenes
2140 public SceneObjectPart GetChildPart(uint localID) 2440 public SceneObjectPart GetChildPart(uint localID)
2141 { 2441 {
2142 //m_log.DebugFormat("Entered looking for {0}", localID); 2442 //m_log.DebugFormat("Entered looking for {0}", localID);
2143 lock (m_parts) 2443 lockPartsForRead(true);
2144 { 2444 {
2145 foreach (SceneObjectPart part in m_parts.Values) 2445 foreach (SceneObjectPart part in m_parts.Values)
2146 { 2446 {
2147 //m_log.DebugFormat("Found {0}", part.LocalId); 2447 //m_log.DebugFormat("Found {0}", part.LocalId);
2148 if (part.LocalId == localID) 2448 if (part.LocalId == localID)
2149 { 2449 {
2450 lockPartsForRead(false);
2150 return part; 2451 return part;
2151 } 2452 }
2152 } 2453 }
2153 } 2454 }
2455 lockPartsForRead(false);
2154 2456
2155 return null; 2457 return null;
2156 } 2458 }
@@ -2180,17 +2482,19 @@ namespace OpenSim.Region.Framework.Scenes
2180 public bool HasChildPrim(uint localID) 2482 public bool HasChildPrim(uint localID)
2181 { 2483 {
2182 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2484 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2183 lock (m_parts) 2485 lockPartsForRead(true);
2184 { 2486 {
2185 foreach (SceneObjectPart part in m_parts.Values) 2487 foreach (SceneObjectPart part in m_parts.Values)
2186 { 2488 {
2187 //m_log.DebugFormat("Found {0}", part.LocalId); 2489 //m_log.DebugFormat("Found {0}", part.LocalId);
2188 if (part.LocalId == localID) 2490 if (part.LocalId == localID)
2189 { 2491 {
2492 lockPartsForRead(false);
2190 return true; 2493 return true;
2191 } 2494 }
2192 } 2495 }
2193 } 2496 }
2497 lockPartsForRead(false);
2194 2498
2195 return false; 2499 return false;
2196 } 2500 }
@@ -2240,53 +2544,57 @@ namespace OpenSim.Region.Framework.Scenes
2240 if (m_rootPart.LinkNum == 0) 2544 if (m_rootPart.LinkNum == 0)
2241 m_rootPart.LinkNum = 1; 2545 m_rootPart.LinkNum = 1;
2242 2546
2243 lock (m_parts) 2547 lockPartsForWrite(true);
2244 { 2548
2245 m_parts.Add(linkPart.UUID, linkPart); 2549 m_parts.Add(linkPart.UUID, linkPart);
2246 2550
2247 // Insert in terms of link numbers, the new links 2551 lockPartsForWrite(false);
2248 // before the current ones (with the exception of 2552
2249 // the root prim. Shuffle the old ones up 2553 // Insert in terms of link numbers, the new links
2250 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2554 // before the current ones (with the exception of
2555 // the root prim. Shuffle the old ones up
2556 lockPartsForRead(true);
2557 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2558 {
2559 if (kvp.Value.LinkNum != 1)
2251 { 2560 {
2252 if (kvp.Value.LinkNum != 1) 2561 // Don't update root prim link number
2253 { 2562 kvp.Value.LinkNum += objectGroup.PrimCount;
2254 // Don't update root prim link number
2255 kvp.Value.LinkNum += objectGroup.PrimCount;
2256 }
2257 } 2563 }
2564 }
2565 lockPartsForRead(false);
2258 2566
2259 linkPart.LinkNum = 2; 2567 linkPart.LinkNum = 2;
2260 2568
2261 linkPart.SetParent(this); 2569 linkPart.SetParent(this);
2262 linkPart.CreateSelected = true; 2570 linkPart.CreateSelected = true;
2263 2571
2264 //if (linkPart.PhysActor != null) 2572 //if (linkPart.PhysActor != null)
2265 //{ 2573 //{
2266 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2574 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2267 2575
2268 //linkPart.PhysActor = null; 2576 //linkPart.PhysActor = null;
2269 //} 2577 //}
2270 2578
2271 //TODO: rest of parts 2579 //TODO: rest of parts
2272 int linkNum = 3; 2580 int linkNum = 3;
2273 foreach (SceneObjectPart part in objectGroup.Children.Values) 2581 foreach (SceneObjectPart part in objectGroup.Children.Values)
2582 {
2583 if (part.UUID != objectGroup.m_rootPart.UUID)
2274 { 2584 {
2275 if (part.UUID != objectGroup.m_rootPart.UUID) 2585 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2276 {
2277 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2278 }
2279 part.ClearUndoState();
2280 } 2586 }
2587 part.ClearUndoState();
2281 } 2588 }
2282 2589
2283 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2590 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2284 objectGroup.m_isDeleted = true; 2591 objectGroup.m_isDeleted = true;
2592
2593 objectGroup.lockPartsForWrite(true);
2285 2594
2286 lock (objectGroup.m_parts) 2595 objectGroup.m_parts.Clear();
2287 { 2596
2288 objectGroup.m_parts.Clear(); 2597 objectGroup.lockPartsForWrite(false);
2289 }
2290 2598
2291 // Can't do this yet since backup still makes use of the root part without any synchronization 2599 // Can't do this yet since backup still makes use of the root part without any synchronization
2292// objectGroup.m_rootPart = null; 2600// objectGroup.m_rootPart = null;
@@ -2356,11 +2664,12 @@ namespace OpenSim.Region.Framework.Scenes
2356 Quaternion worldRot = linkPart.GetWorldRotation(); 2664 Quaternion worldRot = linkPart.GetWorldRotation();
2357 2665
2358 // Remove the part from this object 2666 // Remove the part from this object
2359 lock (m_parts) 2667 lockPartsForWrite(true);
2360 { 2668 {
2361 m_parts.Remove(linkPart.UUID); 2669 m_parts.Remove(linkPart.UUID);
2362 } 2670 }
2363 2671 lockPartsForWrite(false);
2672 lockPartsForRead(true);
2364 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2673 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2365 RootPart.LinkNum = 0; 2674 RootPart.LinkNum = 0;
2366 else 2675 else
@@ -2371,6 +2680,7 @@ namespace OpenSim.Region.Framework.Scenes
2371 p.LinkNum--; 2680 p.LinkNum--;
2372 } 2681 }
2373 } 2682 }
2683 lockPartsForRead(false);
2374 2684
2375 linkPart.ParentID = 0; 2685 linkPart.ParentID = 0;
2376 linkPart.LinkNum = 0; 2686 linkPart.LinkNum = 0;
@@ -2414,6 +2724,8 @@ namespace OpenSim.Region.Framework.Scenes
2414 /// <param name="objectGroup"></param> 2724 /// <param name="objectGroup"></param>
2415 public virtual void DetachFromBackup() 2725 public virtual void DetachFromBackup()
2416 { 2726 {
2727 m_scene.SceneGraph.FireDetachFromBackup(this);
2728
2417 if (m_isBackedUp) 2729 if (m_isBackedUp)
2418 m_scene.EventManager.OnBackup -= ProcessBackup; 2730 m_scene.EventManager.OnBackup -= ProcessBackup;
2419 2731
@@ -2692,9 +3004,12 @@ namespace OpenSim.Region.Framework.Scenes
2692 3004
2693 if (selectionPart != null) 3005 if (selectionPart != null)
2694 { 3006 {
2695 lock (m_parts) 3007 lockPartsForRead(true);
3008 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
3009 lockPartsForRead(false);
3010 foreach (SceneObjectPart part in parts)
2696 { 3011 {
2697 foreach (SceneObjectPart part in m_parts.Values) 3012 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2698 { 3013 {
2699 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 3014 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2700 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 3015 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2704,12 +3019,13 @@ namespace OpenSim.Region.Framework.Scenes
2704 break; 3019 break;
2705 } 3020 }
2706 } 3021 }
3022 }
2707 3023
2708 foreach (SceneObjectPart part in m_parts.Values) 3024 foreach (SceneObjectPart part in parts)
2709 { 3025 {
2710 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3026 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2711 }
2712 } 3027 }
3028
2713 } 3029 }
2714 } 3030 }
2715 3031
@@ -2722,6 +3038,17 @@ namespace OpenSim.Region.Framework.Scenes
2722 } 3038 }
2723 } 3039 }
2724 3040
3041
3042
3043 /// <summary>
3044 /// Gets the number of parts
3045 /// </summary>
3046 /// <returns></returns>
3047 public int GetPartCount()
3048 {
3049 return Children.Count;
3050 }
3051
2725 /// <summary> 3052 /// <summary>
2726 /// Get the parts of this scene object 3053 /// Get the parts of this scene object
2727 /// </summary> 3054 /// </summary>
@@ -2795,11 +3122,9 @@ namespace OpenSim.Region.Framework.Scenes
2795 scale.Y = m_scene.m_maxNonphys; 3122 scale.Y = m_scene.m_maxNonphys;
2796 if (scale.Z > m_scene.m_maxNonphys) 3123 if (scale.Z > m_scene.m_maxNonphys)
2797 scale.Z = m_scene.m_maxNonphys; 3124 scale.Z = m_scene.m_maxNonphys;
2798
2799 SceneObjectPart part = GetChildPart(localID); 3125 SceneObjectPart part = GetChildPart(localID);
2800 if (part != null) 3126 if (part != null)
2801 { 3127 {
2802 part.Resize(scale);
2803 if (part.PhysActor != null) 3128 if (part.PhysActor != null)
2804 { 3129 {
2805 if (part.PhysActor.IsPhysical) 3130 if (part.PhysActor.IsPhysical)
@@ -2814,7 +3139,7 @@ namespace OpenSim.Region.Framework.Scenes
2814 part.PhysActor.Size = scale; 3139 part.PhysActor.Size = scale;
2815 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3140 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2816 } 3141 }
2817 //if (part.UUID != m_rootPart.UUID) 3142 part.Resize(scale);
2818 3143
2819 HasGroupChanged = true; 3144 HasGroupChanged = true;
2820 ScheduleGroupForFullUpdate(); 3145 ScheduleGroupForFullUpdate();
@@ -2836,7 +3161,6 @@ namespace OpenSim.Region.Framework.Scenes
2836 SceneObjectPart part = GetChildPart(localID); 3161 SceneObjectPart part = GetChildPart(localID);
2837 if (part != null) 3162 if (part != null)
2838 { 3163 {
2839 part.IgnoreUndoUpdate = true;
2840 if (scale.X > m_scene.m_maxNonphys) 3164 if (scale.X > m_scene.m_maxNonphys)
2841 scale.X = m_scene.m_maxNonphys; 3165 scale.X = m_scene.m_maxNonphys;
2842 if (scale.Y > m_scene.m_maxNonphys) 3166 if (scale.Y > m_scene.m_maxNonphys)
@@ -2856,94 +3180,100 @@ namespace OpenSim.Region.Framework.Scenes
2856 float y = (scale.Y / part.Scale.Y); 3180 float y = (scale.Y / part.Scale.Y);
2857 float z = (scale.Z / part.Scale.Z); 3181 float z = (scale.Z / part.Scale.Z);
2858 3182
2859 lock (m_parts) 3183 lockPartsForRead(true);
3184 if (x > 1.0f || y > 1.0f || z > 1.0f)
2860 { 3185 {
2861 if (x > 1.0f || y > 1.0f || z > 1.0f) 3186 foreach (SceneObjectPart obPart in m_parts.Values)
2862 { 3187 {
2863 foreach (SceneObjectPart obPart in m_parts.Values) 3188 if (obPart.UUID != m_rootPart.UUID)
2864 { 3189 {
2865 if (obPart.UUID != m_rootPart.UUID) 3190 Vector3 oldSize = new Vector3(obPart.Scale);
2866 { 3191 obPart.IgnoreUndoUpdate = true;
2867 obPart.IgnoreUndoUpdate = true;
2868 Vector3 oldSize = new Vector3(obPart.Scale);
2869 3192
2870 float f = 1.0f; 3193 float f = 1.0f;
2871 float a = 1.0f; 3194 float a = 1.0f;
2872 3195
2873 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3196 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3197 {
3198 if (oldSize.X*x > m_scene.m_maxPhys)
2874 { 3199 {
2875 if (oldSize.X*x > m_scene.m_maxPhys) 3200 f = m_scene.m_maxPhys / oldSize.X;
2876 { 3201 a = f / x;
2877 f = m_scene.m_maxPhys / oldSize.X; 3202 x *= a;
2878 a = f / x; 3203 y *= a;
2879 x *= a; 3204 z *= a;
2880 y *= a;
2881 z *= a;
2882 }
2883 if (oldSize.Y*y > m_scene.m_maxPhys)
2884 {
2885 f = m_scene.m_maxPhys / oldSize.Y;
2886 a = f / y;
2887 x *= a;
2888 y *= a;
2889 z *= a;
2890 }
2891 if (oldSize.Z*z > m_scene.m_maxPhys)
2892 {
2893 f = m_scene.m_maxPhys / oldSize.Z;
2894 a = f / z;
2895 x *= a;
2896 y *= a;
2897 z *= a;
2898 }
2899 } 3205 }
2900 else 3206 if (oldSize.Y*y > m_scene.m_maxPhys)
3207 {
3208 f = m_scene.m_maxPhys / oldSize.Y;
3209 a = f / y;
3210 x *= a;
3211 y *= a;
3212 z *= a;
3213 }
3214 if (oldSize.Z*z > m_scene.m_maxPhys)
3215 {
3216 f = m_scene.m_maxPhys / oldSize.Z;
3217 a = f / z;
3218 x *= a;
3219 y *= a;
3220 z *= a;
3221 }
3222 }
3223 else
3224 {
3225 if (oldSize.X*x > m_scene.m_maxNonphys)
3226 {
3227 f = m_scene.m_maxNonphys / oldSize.X;
3228 a = f / x;
3229 x *= a;
3230 y *= a;
3231 z *= a;
3232 }
3233 if (oldSize.Y*y > m_scene.m_maxNonphys)
3234 {
3235 f = m_scene.m_maxNonphys / oldSize.Y;
3236 a = f / y;
3237 x *= a;
3238 y *= a;
3239 z *= a;
3240 }
3241 if (oldSize.Z*z > m_scene.m_maxNonphys)
2901 { 3242 {
2902 if (oldSize.X*x > m_scene.m_maxNonphys) 3243 f = m_scene.m_maxNonphys / oldSize.Z;
2903 { 3244 a = f / z;
2904 f = m_scene.m_maxNonphys / oldSize.X; 3245 x *= a;
2905 a = f / x; 3246 y *= a;
2906 x *= a; 3247 z *= a;
2907 y *= a;
2908 z *= a;
2909 }
2910 if (oldSize.Y*y > m_scene.m_maxNonphys)
2911 {
2912 f = m_scene.m_maxNonphys / oldSize.Y;
2913 a = f / y;
2914 x *= a;
2915 y *= a;
2916 z *= a;
2917 }
2918 if (oldSize.Z*z > m_scene.m_maxNonphys)
2919 {
2920 f = m_scene.m_maxNonphys / oldSize.Z;
2921 a = f / z;
2922 x *= a;
2923 y *= a;
2924 z *= a;
2925 }
2926 } 3248 }
2927 obPart.IgnoreUndoUpdate = false; 3249
2928 obPart.StoreUndoState();
2929 } 3250 }
2930 } 3251 }
2931 } 3252 }
2932 } 3253 }
3254 lockPartsForRead(false);
2933 3255
2934 Vector3 prevScale = part.Scale; 3256 Vector3 prevScale = part.Scale;
2935 prevScale.X *= x; 3257 prevScale.X *= x;
2936 prevScale.Y *= y; 3258 prevScale.Y *= y;
2937 prevScale.Z *= z; 3259 prevScale.Z *= z;;
3260
3261 part.IgnoreUndoUpdate = false;
3262 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3263 part.IgnoreUndoUpdate = true;
2938 part.Resize(prevScale); 3264 part.Resize(prevScale);
3265 part.IgnoreUndoUpdate = false;
2939 3266
2940 lock (m_parts) 3267 lockPartsForRead(true);
2941 { 3268 {
2942 foreach (SceneObjectPart obPart in m_parts.Values) 3269 foreach (SceneObjectPart obPart in m_parts.Values)
2943 { 3270 {
2944 obPart.IgnoreUndoUpdate = true;
2945 if (obPart.UUID != m_rootPart.UUID) 3271 if (obPart.UUID != m_rootPart.UUID)
2946 { 3272 {
3273 obPart.IgnoreUndoUpdate = false;
3274 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3275 obPart.IgnoreUndoUpdate = true;
3276
2947 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3277 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2948 currentpos.X *= x; 3278 currentpos.X *= x;
2949 currentpos.Y *= y; 3279 currentpos.Y *= y;
@@ -2956,9 +3286,9 @@ namespace OpenSim.Region.Framework.Scenes
2956 obPart.UpdateOffSet(currentpos); 3286 obPart.UpdateOffSet(currentpos);
2957 } 3287 }
2958 obPart.IgnoreUndoUpdate = false; 3288 obPart.IgnoreUndoUpdate = false;
2959 obPart.StoreUndoState();
2960 } 3289 }
2961 } 3290 }
3291 lockPartsForRead(false);
2962 3292
2963 if (part.PhysActor != null) 3293 if (part.PhysActor != null)
2964 { 3294 {
@@ -2967,7 +3297,6 @@ namespace OpenSim.Region.Framework.Scenes
2967 } 3297 }
2968 3298
2969 part.IgnoreUndoUpdate = false; 3299 part.IgnoreUndoUpdate = false;
2970 part.StoreUndoState();
2971 HasGroupChanged = true; 3300 HasGroupChanged = true;
2972 ScheduleGroupForTerseUpdate(); 3301 ScheduleGroupForTerseUpdate();
2973 } 3302 }
@@ -2983,14 +3312,11 @@ namespace OpenSim.Region.Framework.Scenes
2983 /// <param name="pos"></param> 3312 /// <param name="pos"></param>
2984 public void UpdateGroupPosition(Vector3 pos) 3313 public void UpdateGroupPosition(Vector3 pos)
2985 { 3314 {
2986 foreach (SceneObjectPart part in Children.Values)
2987 {
2988 part.StoreUndoState();
2989 }
2990 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3315 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2991 { 3316 {
2992 if (IsAttachment) 3317 if (IsAttachment)
2993 { 3318 {
3319 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2994 m_rootPart.AttachedPos = pos; 3320 m_rootPart.AttachedPos = pos;
2995 } 3321 }
2996 if (RootPart.GetStatusSandbox()) 3322 if (RootPart.GetStatusSandbox())
@@ -3023,7 +3349,7 @@ namespace OpenSim.Region.Framework.Scenes
3023 SceneObjectPart part = GetChildPart(localID); 3349 SceneObjectPart part = GetChildPart(localID);
3024 foreach (SceneObjectPart parts in Children.Values) 3350 foreach (SceneObjectPart parts in Children.Values)
3025 { 3351 {
3026 parts.StoreUndoState(); 3352 parts.StoreUndoState(UndoType.STATE_PRIM_POSITION);
3027 } 3353 }
3028 if (part != null) 3354 if (part != null)
3029 { 3355 {
@@ -3048,7 +3374,7 @@ namespace OpenSim.Region.Framework.Scenes
3048 { 3374 {
3049 foreach (SceneObjectPart part in Children.Values) 3375 foreach (SceneObjectPart part in Children.Values)
3050 { 3376 {
3051 part.StoreUndoState(); 3377 part.StoreUndoState(UndoType.STATE_PRIM_POSITION);
3052 } 3378 }
3053 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3379 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3054 Vector3 oldPos = 3380 Vector3 oldPos =
@@ -3061,7 +3387,7 @@ namespace OpenSim.Region.Framework.Scenes
3061 axDiff *= Quaternion.Inverse(partRotation); 3387 axDiff *= Quaternion.Inverse(partRotation);
3062 diff = axDiff; 3388 diff = axDiff;
3063 3389
3064 lock (m_parts) 3390 lockPartsForRead(true);
3065 { 3391 {
3066 foreach (SceneObjectPart obPart in m_parts.Values) 3392 foreach (SceneObjectPart obPart in m_parts.Values)
3067 { 3393 {
@@ -3071,11 +3397,29 @@ namespace OpenSim.Region.Framework.Scenes
3071 } 3397 }
3072 } 3398 }
3073 } 3399 }
3400 lockPartsForRead(false);
3074 3401
3075 AbsolutePosition = newPos; 3402 //We have to set undoing here because otherwise an undo state will be saved
3403 if (!m_rootPart.Undoing)
3404 {
3405 m_rootPart.Undoing = true;
3406 AbsolutePosition = newPos;
3407 m_rootPart.Undoing = false;
3408 }
3409 else
3410 {
3411 AbsolutePosition = newPos;
3412 }
3076 3413
3077 HasGroupChanged = true; 3414 HasGroupChanged = true;
3078 ScheduleGroupForTerseUpdate(); 3415 if (m_rootPart.Undoing)
3416 {
3417 ScheduleGroupForFullUpdate();
3418 }
3419 else
3420 {
3421 ScheduleGroupForTerseUpdate();
3422 }
3079 } 3423 }
3080 3424
3081 public void OffsetForNewRegion(Vector3 offset) 3425 public void OffsetForNewRegion(Vector3 offset)
@@ -3095,7 +3439,7 @@ namespace OpenSim.Region.Framework.Scenes
3095 { 3439 {
3096 foreach (SceneObjectPart parts in Children.Values) 3440 foreach (SceneObjectPart parts in Children.Values)
3097 { 3441 {
3098 parts.StoreUndoState(); 3442 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3099 } 3443 }
3100 m_rootPart.UpdateRotation(rot); 3444 m_rootPart.UpdateRotation(rot);
3101 3445
@@ -3119,7 +3463,7 @@ namespace OpenSim.Region.Framework.Scenes
3119 { 3463 {
3120 foreach (SceneObjectPart parts in Children.Values) 3464 foreach (SceneObjectPart parts in Children.Values)
3121 { 3465 {
3122 parts.StoreUndoState(); 3466 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3123 } 3467 }
3124 m_rootPart.UpdateRotation(rot); 3468 m_rootPart.UpdateRotation(rot);
3125 3469
@@ -3146,7 +3490,7 @@ namespace OpenSim.Region.Framework.Scenes
3146 SceneObjectPart part = GetChildPart(localID); 3490 SceneObjectPart part = GetChildPart(localID);
3147 foreach (SceneObjectPart parts in Children.Values) 3491 foreach (SceneObjectPart parts in Children.Values)
3148 { 3492 {
3149 parts.StoreUndoState(); 3493 parts.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3150 } 3494 }
3151 if (part != null) 3495 if (part != null)
3152 { 3496 {
@@ -3174,15 +3518,24 @@ namespace OpenSim.Region.Framework.Scenes
3174 if (part.UUID == m_rootPart.UUID) 3518 if (part.UUID == m_rootPart.UUID)
3175 { 3519 {
3176 UpdateRootRotation(rot); 3520 UpdateRootRotation(rot);
3177 AbsolutePosition = pos; 3521 if (!m_rootPart.Undoing)
3522 {
3523 m_rootPart.Undoing = true;
3524 AbsolutePosition = pos;
3525 m_rootPart.Undoing = false;
3526 }
3527 else
3528 {
3529 AbsolutePosition = pos;
3530 }
3178 } 3531 }
3179 else 3532 else
3180 { 3533 {
3534 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3181 part.IgnoreUndoUpdate = true; 3535 part.IgnoreUndoUpdate = true;
3182 part.UpdateRotation(rot); 3536 part.UpdateRotation(rot);
3183 part.OffsetPosition = pos; 3537 part.OffsetPosition = pos;
3184 part.IgnoreUndoUpdate = false; 3538 part.IgnoreUndoUpdate = false;
3185 part.StoreUndoState();
3186 } 3539 }
3187 } 3540 }
3188 } 3541 }
@@ -3196,7 +3549,13 @@ namespace OpenSim.Region.Framework.Scenes
3196 Quaternion axRot = rot; 3549 Quaternion axRot = rot;
3197 Quaternion oldParentRot = m_rootPart.RotationOffset; 3550 Quaternion oldParentRot = m_rootPart.RotationOffset;
3198 3551
3199 m_rootPart.StoreUndoState(); 3552 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3553 bool cancelUndo = false;
3554 if (!m_rootPart.Undoing)
3555 {
3556 m_rootPart.Undoing = true;
3557 cancelUndo = true;
3558 }
3200 m_rootPart.UpdateRotation(rot); 3559 m_rootPart.UpdateRotation(rot);
3201 if (m_rootPart.PhysActor != null) 3560 if (m_rootPart.PhysActor != null)
3202 { 3561 {
@@ -3204,33 +3563,31 @@ namespace OpenSim.Region.Framework.Scenes
3204 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3563 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3205 } 3564 }
3206 3565
3207 lock (m_parts) 3566 lockPartsForRead(true);
3567
3568 foreach (SceneObjectPart prim in m_parts.Values)
3208 { 3569 {
3209 foreach (SceneObjectPart prim in m_parts.Values) 3570 if (prim.UUID != m_rootPart.UUID)
3210 { 3571 {
3211 if (prim.UUID != m_rootPart.UUID) 3572 prim.IgnoreUndoUpdate = true;
3212 { 3573 Vector3 axPos = prim.OffsetPosition;
3213 prim.IgnoreUndoUpdate = true; 3574 axPos *= oldParentRot;
3214 Vector3 axPos = prim.OffsetPosition; 3575 axPos *= Quaternion.Inverse(axRot);
3215 axPos *= oldParentRot; 3576 prim.OffsetPosition = axPos;
3216 axPos *= Quaternion.Inverse(axRot); 3577 Quaternion primsRot = prim.RotationOffset;
3217 prim.OffsetPosition = axPos; 3578 Quaternion newRot = primsRot * oldParentRot;
3218 Quaternion primsRot = prim.RotationOffset; 3579 newRot *= Quaternion.Inverse(axRot);
3219 Quaternion newRot = primsRot * oldParentRot; 3580 prim.RotationOffset = newRot;
3220 newRot *= Quaternion.Inverse(axRot); 3581 prim.ScheduleTerseUpdate();
3221 prim.RotationOffset = newRot; 3582 prim.IgnoreUndoUpdate = false;
3222 prim.ScheduleTerseUpdate();
3223 }
3224 } 3583 }
3225 } 3584 }
3226 foreach (SceneObjectPart childpart in Children.Values) 3585 if (cancelUndo == true)
3227 { 3586 {
3228 if (childpart != m_rootPart) 3587 m_rootPart.Undoing = false;
3229 {
3230 childpart.IgnoreUndoUpdate = false;
3231 childpart.StoreUndoState();
3232 }
3233 } 3588 }
3589 lockPartsForRead(false);
3590
3234 m_rootPart.ScheduleTerseUpdate(); 3591 m_rootPart.ScheduleTerseUpdate();
3235 } 3592 }
3236 3593
@@ -3352,7 +3709,7 @@ namespace OpenSim.Region.Framework.Scenes
3352 if (atTargets.Count > 0) 3709 if (atTargets.Count > 0)
3353 { 3710 {
3354 uint[] localids = new uint[0]; 3711 uint[] localids = new uint[0];
3355 lock (m_parts) 3712 lockPartsForRead(true);
3356 { 3713 {
3357 localids = new uint[m_parts.Count]; 3714 localids = new uint[m_parts.Count];
3358 int cntr = 0; 3715 int cntr = 0;
@@ -3362,6 +3719,7 @@ namespace OpenSim.Region.Framework.Scenes
3362 cntr++; 3719 cntr++;
3363 } 3720 }
3364 } 3721 }
3722 lockPartsForRead(false);
3365 3723
3366 for (int ctr = 0; ctr < localids.Length; ctr++) 3724 for (int ctr = 0; ctr < localids.Length; ctr++)
3367 { 3725 {
@@ -3380,7 +3738,7 @@ namespace OpenSim.Region.Framework.Scenes
3380 { 3738 {
3381 //trigger not_at_target 3739 //trigger not_at_target
3382 uint[] localids = new uint[0]; 3740 uint[] localids = new uint[0];
3383 lock (m_parts) 3741 lockPartsForRead(true);
3384 { 3742 {
3385 localids = new uint[m_parts.Count]; 3743 localids = new uint[m_parts.Count];
3386 int cntr = 0; 3744 int cntr = 0;
@@ -3390,7 +3748,8 @@ namespace OpenSim.Region.Framework.Scenes
3390 cntr++; 3748 cntr++;
3391 } 3749 }
3392 } 3750 }
3393 3751 lockPartsForRead(false);
3752
3394 for (int ctr = 0; ctr < localids.Length; ctr++) 3753 for (int ctr = 0; ctr < localids.Length; ctr++)
3395 { 3754 {
3396 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3755 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3431,7 +3790,8 @@ namespace OpenSim.Region.Framework.Scenes
3431 if (atRotTargets.Count > 0) 3790 if (atRotTargets.Count > 0)
3432 { 3791 {
3433 uint[] localids = new uint[0]; 3792 uint[] localids = new uint[0];
3434 lock (m_parts) 3793 lockPartsForRead(true);
3794 try
3435 { 3795 {
3436 localids = new uint[m_parts.Count]; 3796 localids = new uint[m_parts.Count];
3437 int cntr = 0; 3797 int cntr = 0;
@@ -3441,6 +3801,10 @@ namespace OpenSim.Region.Framework.Scenes
3441 cntr++; 3801 cntr++;
3442 } 3802 }
3443 } 3803 }
3804 finally
3805 {
3806 lockPartsForRead(false);
3807 }
3444 3808
3445 for (int ctr = 0; ctr < localids.Length; ctr++) 3809 for (int ctr = 0; ctr < localids.Length; ctr++)
3446 { 3810 {
@@ -3459,7 +3823,8 @@ namespace OpenSim.Region.Framework.Scenes
3459 { 3823 {
3460 //trigger not_at_target 3824 //trigger not_at_target
3461 uint[] localids = new uint[0]; 3825 uint[] localids = new uint[0];
3462 lock (m_parts) 3826 lockPartsForRead(true);
3827 try
3463 { 3828 {
3464 localids = new uint[m_parts.Count]; 3829 localids = new uint[m_parts.Count];
3465 int cntr = 0; 3830 int cntr = 0;
@@ -3469,6 +3834,10 @@ namespace OpenSim.Region.Framework.Scenes
3469 cntr++; 3834 cntr++;
3470 } 3835 }
3471 } 3836 }
3837 finally
3838 {
3839 lockPartsForRead(false);
3840 }
3472 3841
3473 for (int ctr = 0; ctr < localids.Length; ctr++) 3842 for (int ctr = 0; ctr < localids.Length; ctr++)
3474 { 3843 {
@@ -3482,19 +3851,20 @@ namespace OpenSim.Region.Framework.Scenes
3482 public float GetMass() 3851 public float GetMass()
3483 { 3852 {
3484 float retmass = 0f; 3853 float retmass = 0f;
3485 lock (m_parts) 3854 lockPartsForRead(true);
3486 { 3855 {
3487 foreach (SceneObjectPart part in m_parts.Values) 3856 foreach (SceneObjectPart part in m_parts.Values)
3488 { 3857 {
3489 retmass += part.GetMass(); 3858 retmass += part.GetMass();
3490 } 3859 }
3491 } 3860 }
3861 lockPartsForRead(false);
3492 return retmass; 3862 return retmass;
3493 } 3863 }
3494 3864
3495 public void CheckSculptAndLoad() 3865 public void CheckSculptAndLoad()
3496 { 3866 {
3497 lock (m_parts) 3867 lockPartsForRead(true);
3498 { 3868 {
3499 if (!IsDeleted) 3869 if (!IsDeleted)
3500 { 3870 {
@@ -3519,6 +3889,7 @@ namespace OpenSim.Region.Framework.Scenes
3519 } 3889 }
3520 } 3890 }
3521 } 3891 }
3892 lockPartsForRead(false);
3522 } 3893 }
3523 3894
3524 protected void AssetReceived(string id, Object sender, AssetBase asset) 3895 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3539,7 +3910,7 @@ namespace OpenSim.Region.Framework.Scenes
3539 /// <param name="client"></param> 3910 /// <param name="client"></param>
3540 public void SetGroup(UUID GroupID, IClientAPI client) 3911 public void SetGroup(UUID GroupID, IClientAPI client)
3541 { 3912 {
3542 lock (m_parts) 3913 lockPartsForRead(true);
3543 { 3914 {
3544 foreach (SceneObjectPart part in m_parts.Values) 3915 foreach (SceneObjectPart part in m_parts.Values)
3545 { 3916 {
@@ -3549,6 +3920,7 @@ namespace OpenSim.Region.Framework.Scenes
3549 3920
3550 HasGroupChanged = true; 3921 HasGroupChanged = true;
3551 } 3922 }
3923 lockPartsForRead(false);
3552 3924
3553 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3925 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3554 // for the same object with very different properties. The caller must schedule the update. 3926 // for the same object with very different properties. The caller must schedule the update.
@@ -3570,11 +3942,12 @@ namespace OpenSim.Region.Framework.Scenes
3570 3942
3571 public void SetAttachmentPoint(byte point) 3943 public void SetAttachmentPoint(byte point)
3572 { 3944 {
3573 lock (m_parts) 3945 lockPartsForRead(true);
3574 { 3946 {
3575 foreach (SceneObjectPart part in m_parts.Values) 3947 foreach (SceneObjectPart part in m_parts.Values)
3576 part.SetAttachmentPoint(point); 3948 part.SetAttachmentPoint(point);
3577 } 3949 }
3950 lockPartsForRead(false);
3578 } 3951 }
3579 3952
3580 #region ISceneObject 3953 #region ISceneObject
@@ -3608,6 +3981,14 @@ namespace OpenSim.Region.Framework.Scenes
3608 SetFromItemID(uuid); 3981 SetFromItemID(uuid);
3609 } 3982 }
3610 3983
3984 public void ResetOwnerChangeFlag()
3985 {
3986 ForEachPart(delegate(SceneObjectPart part)
3987 {
3988 part.ResetOwnerChangeFlag();
3989 });
3990 }
3991
3611 #endregion 3992 #endregion
3612 } 3993 }
3613} 3994}