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.cs869
1 files changed, 619 insertions, 250 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 1ca390a..7053c02 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -104,8 +104,95 @@ 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 m_partsLock.ExitReadLock();
140 }
141 if (m_partsLock.RecursiveWriteCount > 0)
142 {
143 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.");
144 m_partsLock.ExitWriteLock();
145 }
146
147 while (!m_partsLock.TryEnterReadLock(60000))
148 {
149 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.");
150 if (m_partsLock.IsWriteLockHeld)
151 {
152 m_partsLock = new System.Threading.ReaderWriterLockSlim();
153 }
154 }
155 }
156 else
157 {
158 if (m_partsLock.RecursiveReadCount > 0)
159 {
160 m_partsLock.ExitReadLock();
161 }
162 }
163 }
164 public void lockPartsForWrite(bool locked)
165 {
166 if (locked)
167 {
168 if (m_partsLock.RecursiveReadCount > 0)
169 {
170 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.");
171 m_partsLock.ExitReadLock();
172 }
173 if (m_partsLock.RecursiveWriteCount > 0)
174 {
175 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
176 m_partsLock.ExitWriteLock();
177 }
178
179 while (!m_partsLock.TryEnterWriteLock(60000))
180 {
181 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.");
182 if (m_partsLock.IsWriteLockHeld)
183 {
184 m_partsLock = new System.Threading.ReaderWriterLockSlim();
185 }
186 }
187 }
188 else
189 {
190 if (m_partsLock.RecursiveWriteCount > 0)
191 {
192 m_partsLock.ExitWriteLock();
193 }
194 }
195 }
109 196
110 public bool HasGroupChanged 197 public bool HasGroupChanged
111 { 198 {
@@ -113,9 +200,39 @@ namespace OpenSim.Region.Framework.Scenes
113 { 200 {
114 if (value) 201 if (value)
115 { 202 {
203 if (m_isBackedUp)
204 {
205 m_scene.SceneGraph.FireChangeBackup(this);
206 }
116 timeLastChanged = DateTime.Now.Ticks; 207 timeLastChanged = DateTime.Now.Ticks;
117 if (!m_hasGroupChanged) 208 if (!m_hasGroupChanged)
118 timeFirstChanged = DateTime.Now.Ticks; 209 timeFirstChanged = DateTime.Now.Ticks;
210 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
211 {
212 if (m_rand == null)
213 {
214 byte[] val = new byte[16];
215 m_rootPart.UUID.ToBytes(val, 0);
216 m_rand = new Random(BitConverter.ToInt32(val, 0));
217 }
218
219 if (m_scene.GetRootAgentCount() == 0)
220 {
221 //If the region is empty, this change has been made by an automated process
222 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
223
224 float factor = 1.5f + (float)(m_rand.NextDouble());
225 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
226 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
227 }
228 else
229 {
230 //If the region is not empty, we want to obey the minimum and maximum persist times
231 //but add a random factor so we stagger the object persistance a little
232 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
233 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
234 }
235 }
119 } 236 }
120 m_hasGroupChanged = value; 237 m_hasGroupChanged = value;
121 } 238 }
@@ -131,8 +248,19 @@ namespace OpenSim.Region.Framework.Scenes
131 return false; 248 return false;
132 if (m_scene.ShuttingDown) 249 if (m_scene.ShuttingDown)
133 return true; 250 return true;
251
252 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
253 {
254 m_maxPersistTime = m_scene.m_persistAfter;
255 m_minPersistTime = m_scene.m_dontPersistBefore;
256 }
257
134 long currentTime = DateTime.Now.Ticks; 258 long currentTime = DateTime.Now.Ticks;
135 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 259
260 if (timeLastChanged == 0) timeLastChanged = currentTime;
261 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
262
263 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
136 return true; 264 return true;
137 return false; 265 return false;
138 } 266 }
@@ -221,7 +349,21 @@ namespace OpenSim.Region.Framework.Scenes
221 public virtual Quaternion Rotation 349 public virtual Quaternion Rotation
222 { 350 {
223 get { return m_rotation; } 351 get { return m_rotation; }
224 set { m_rotation = value; } 352 set {
353 lockPartsForRead(true);
354 try
355 {
356 foreach(SceneObjectPart p in m_parts.Values)
357 {
358 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
359 }
360 }
361 finally
362 {
363 lockPartsForRead(false);
364 }
365 m_rotation = value;
366 }
225 } 367 }
226 368
227 public Quaternion GroupRotation 369 public Quaternion GroupRotation
@@ -258,13 +400,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 400 set
259 { 401 {
260 m_regionHandle = value; 402 m_regionHandle = value;
261 lock (m_parts) 403 lockPartsForRead(true);
262 { 404 {
263 foreach (SceneObjectPart part in m_parts.Values) 405 foreach (SceneObjectPart part in m_parts.Values)
264 { 406 {
407
265 part.RegionHandle = m_regionHandle; 408 part.RegionHandle = m_regionHandle;
409
266 } 410 }
267 } 411 }
412 lockPartsForRead(false);
268 } 413 }
269 } 414 }
270 415
@@ -298,6 +443,12 @@ namespace OpenSim.Region.Framework.Scenes
298 { 443 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 444 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 445 }
446
447 lockPartsForRead(true);
448 foreach (SceneObjectPart part in m_parts.Values)
449 {
450 part.IgnoreUndoUpdate = true;
451 }
301 if (RootPart.GetStatusSandbox()) 452 if (RootPart.GetStatusSandbox())
302 { 453 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 454 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,16 +456,17 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 456 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 457 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 458 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
459 lockPartsForRead(false);
308 return; 460 return;
309 } 461 }
310 } 462 }
311 lock (m_parts) 463 foreach (SceneObjectPart part in m_parts.Values)
312 { 464 {
313 foreach (SceneObjectPart part in m_parts.Values) 465 part.IgnoreUndoUpdate = false;
314 { 466 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
315 part.GroupPosition = val; 467 part.GroupPosition = val;
316 }
317 } 468 }
469 lockPartsForRead(false);
318 470
319 //if (m_rootPart.PhysActor != null) 471 //if (m_rootPart.PhysActor != null)
320 //{ 472 //{
@@ -457,6 +609,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 609 /// </summary>
458 public SceneObjectGroup() 610 public SceneObjectGroup()
459 { 611 {
612
460 } 613 }
461 614
462 /// <summary> 615 /// <summary>
@@ -473,7 +626,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 626 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 627 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 628 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 629 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 630 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 631 }
479 632
@@ -504,13 +657,16 @@ namespace OpenSim.Region.Framework.Scenes
504 657
505 public void SetFromItemID(UUID AssetId) 658 public void SetFromItemID(UUID AssetId)
506 { 659 {
507 lock (m_parts) 660 lockPartsForRead(true);
508 { 661 {
509 foreach (SceneObjectPart part in m_parts.Values) 662 foreach (SceneObjectPart part in m_parts.Values)
510 { 663 {
664
511 part.FromItemID = AssetId; 665 part.FromItemID = AssetId;
666
512 } 667 }
513 } 668 }
669 lockPartsForRead(false);
514 } 670 }
515 671
516 public UUID GetFromItemID() 672 public UUID GetFromItemID()
@@ -523,6 +679,9 @@ namespace OpenSim.Region.Framework.Scenes
523 /// </summary> 679 /// </summary>
524 public virtual void AttachToBackup() 680 public virtual void AttachToBackup()
525 { 681 {
682 if (IsAttachment) return;
683 m_scene.SceneGraph.FireAttachToBackup(this);
684
526 if (InSceneBackup) 685 if (InSceneBackup)
527 { 686 {
528 //m_log.DebugFormat( 687 //m_log.DebugFormat(
@@ -579,7 +738,7 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 738 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 739 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 740
582 lock (m_parts) 741 lockPartsForRead(true);
583 { 742 {
584 foreach (SceneObjectPart part in m_parts.Values) 743 foreach (SceneObjectPart part in m_parts.Values)
585 { 744 {
@@ -593,8 +752,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 752 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; 753 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; 754 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
755
596 } 756 }
597 } 757 }
758 lockPartsForRead(false);
759
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 760 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 761 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 762 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +772,11 @@ namespace OpenSim.Region.Framework.Scenes
610 772
611 EntityIntersection result = new EntityIntersection(); 773 EntityIntersection result = new EntityIntersection();
612 774
613 lock (m_parts) 775 lockPartsForRead(true);
614 { 776 {
615 foreach (SceneObjectPart part in m_parts.Values) 777 foreach (SceneObjectPart part in m_parts.Values)
616 { 778 {
779
617 // Temporary commented to stop compiler warning 780 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 781 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 782 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +804,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 804 result.distance = inter.distance;
642 } 805 }
643 } 806 }
807
644 } 808 }
645 } 809 }
810 lockPartsForRead(false);
646 return result; 811 return result;
647 } 812 }
648 813
@@ -661,10 +826,11 @@ namespace OpenSim.Region.Framework.Scenes
661 minY = 256f; 826 minY = 256f;
662 minZ = 8192f; 827 minZ = 8192f;
663 828
664 lock(m_parts); 829 lockPartsForRead(true);
665 { 830 {
666 foreach (SceneObjectPart part in m_parts.Values) 831 foreach (SceneObjectPart part in m_parts.Values)
667 { 832 {
833
668 Vector3 worldPos = part.GetWorldPosition(); 834 Vector3 worldPos = part.GetWorldPosition();
669 Vector3 offset = worldPos - AbsolutePosition; 835 Vector3 offset = worldPos - AbsolutePosition;
670 Quaternion worldRot; 836 Quaternion worldRot;
@@ -723,6 +889,8 @@ namespace OpenSim.Region.Framework.Scenes
723 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 889 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
724 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 890 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
725 891
892
893
726 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 894 //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); 895 //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); 896 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -894,6 +1062,7 @@ namespace OpenSim.Region.Framework.Scenes
894 minZ = backBottomLeft.Z; 1062 minZ = backBottomLeft.Z;
895 } 1063 }
896 } 1064 }
1065 lockPartsForRead(false);
897 } 1066 }
898 1067
899 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 1068 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
@@ -929,21 +1098,29 @@ namespace OpenSim.Region.Framework.Scenes
929 1098
930 public void SaveScriptedState(XmlTextWriter writer) 1099 public void SaveScriptedState(XmlTextWriter writer)
931 { 1100 {
1101 SaveScriptedState(writer, false);
1102 }
1103
1104 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1105 {
932 XmlDocument doc = new XmlDocument(); 1106 XmlDocument doc = new XmlDocument();
933 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1107 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
934 1108
935 // Capture script state while holding the lock 1109 // Capture script state while holding the lock
936 lock (m_parts) 1110 lockPartsForRead(true);
937 { 1111 {
938 foreach (SceneObjectPart part in m_parts.Values) 1112 foreach (SceneObjectPart part in m_parts.Values)
939 { 1113 {
940 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1114
1115 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
941 foreach (UUID itemid in pstates.Keys) 1116 foreach (UUID itemid in pstates.Keys)
942 { 1117 {
943 states.Add(itemid, pstates[itemid]); 1118 states.Add(itemid, pstates[itemid]);
944 } 1119 }
1120
945 } 1121 }
946 } 1122 }
1123 lockPartsForRead(false);
947 1124
948 if (states.Count > 0) 1125 if (states.Count > 0)
949 { 1126 {
@@ -962,6 +1139,47 @@ namespace OpenSim.Region.Framework.Scenes
962 } 1139 }
963 1140
964 /// <summary> 1141 /// <summary>
1142 /// Add the avatar to this linkset (avatar is sat).
1143 /// </summary>
1144 /// <param name="agentID"></param>
1145 public void AddAvatar(UUID agentID)
1146 {
1147 ScenePresence presence;
1148 if (m_scene.TryGetScenePresence(agentID, out presence))
1149 {
1150 if (!m_linkedAvatars.Contains(presence))
1151 {
1152 m_linkedAvatars.Add(presence);
1153 }
1154 }
1155 }
1156
1157 /// <summary>
1158 /// Delete the avatar from this linkset (avatar is unsat).
1159 /// </summary>
1160 /// <param name="agentID"></param>
1161 public void DeleteAvatar(UUID agentID)
1162 {
1163 ScenePresence presence;
1164 if (m_scene.TryGetScenePresence(agentID, out presence))
1165 {
1166 if (m_linkedAvatars.Contains(presence))
1167 {
1168 m_linkedAvatars.Remove(presence);
1169 }
1170 }
1171 }
1172
1173 /// <summary>
1174 /// Returns the list of linked presences (avatars sat on this group)
1175 /// </summary>
1176 /// <param name="agentID"></param>
1177 public List<ScenePresence> GetLinkedAvatars()
1178 {
1179 return m_linkedAvatars;
1180 }
1181
1182 /// <summary>
965 /// Attach this scene object to the given avatar. 1183 /// Attach this scene object to the given avatar.
966 /// </summary> 1184 /// </summary>
967 /// <param name="agentID"></param> 1185 /// <param name="agentID"></param>
@@ -1112,13 +1330,16 @@ namespace OpenSim.Region.Framework.Scenes
1112 1330
1113 public override void UpdateMovement() 1331 public override void UpdateMovement()
1114 { 1332 {
1115 lock (m_parts) 1333 lockPartsForRead(true);
1116 { 1334 {
1117 foreach (SceneObjectPart part in m_parts.Values) 1335 foreach (SceneObjectPart part in m_parts.Values)
1118 { 1336 {
1337
1119 part.UpdateMovement(); 1338 part.UpdateMovement();
1339
1120 } 1340 }
1121 } 1341 }
1342 lockPartsForRead(false);
1122 } 1343 }
1123 1344
1124 public ushort GetTimeDilation() 1345 public ushort GetTimeDilation()
@@ -1162,7 +1383,7 @@ namespace OpenSim.Region.Framework.Scenes
1162 /// <param name="part"></param> 1383 /// <param name="part"></param>
1163 public void AddPart(SceneObjectPart part) 1384 public void AddPart(SceneObjectPart part)
1164 { 1385 {
1165 lock (m_parts) 1386 lockPartsForWrite(true);
1166 { 1387 {
1167 part.SetParent(this); 1388 part.SetParent(this);
1168 m_parts.Add(part.UUID, part); 1389 m_parts.Add(part.UUID, part);
@@ -1172,6 +1393,7 @@ namespace OpenSim.Region.Framework.Scenes
1172 if (part.LinkNum == 2 && RootPart != null) 1393 if (part.LinkNum == 2 && RootPart != null)
1173 RootPart.LinkNum = 1; 1394 RootPart.LinkNum = 1;
1174 } 1395 }
1396 lockPartsForWrite(false);
1175 } 1397 }
1176 1398
1177 /// <summary> 1399 /// <summary>
@@ -1179,28 +1401,33 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// </summary> 1401 /// </summary>
1180 private void UpdateParentIDs() 1402 private void UpdateParentIDs()
1181 { 1403 {
1182 lock (m_parts) 1404 lockPartsForRead(true);
1183 { 1405 {
1184 foreach (SceneObjectPart part in m_parts.Values) 1406 foreach (SceneObjectPart part in m_parts.Values)
1185 { 1407 {
1408
1186 if (part.UUID != m_rootPart.UUID) 1409 if (part.UUID != m_rootPart.UUID)
1187 { 1410 {
1188 part.ParentID = m_rootPart.LocalId; 1411 part.ParentID = m_rootPart.LocalId;
1189 } 1412 }
1413
1190 } 1414 }
1191 } 1415 }
1416 lockPartsForRead(false);
1192 } 1417 }
1193 1418
1194 public void RegenerateFullIDs() 1419 public void RegenerateFullIDs()
1195 { 1420 {
1196 lock (m_parts) 1421 lockPartsForRead(true);
1197 { 1422 {
1198 foreach (SceneObjectPart part in m_parts.Values) 1423 foreach (SceneObjectPart part in m_parts.Values)
1199 { 1424 {
1425
1200 part.UUID = UUID.Random(); 1426 part.UUID = UUID.Random();
1201 1427
1202 } 1428 }
1203 } 1429 }
1430 lockPartsForRead(false);
1204 } 1431 }
1205 1432
1206 // helper provided for parts. 1433 // helper provided for parts.
@@ -1261,7 +1488,7 @@ namespace OpenSim.Region.Framework.Scenes
1261 1488
1262 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1489 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1263 { 1490 {
1264 part.StoreUndoState(); 1491 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1265 part.OnGrab(offsetPos, remoteClient); 1492 part.OnGrab(offsetPos, remoteClient);
1266 } 1493 }
1267 1494
@@ -1281,27 +1508,32 @@ namespace OpenSim.Region.Framework.Scenes
1281 1508
1282 DetachFromBackup(); 1509 DetachFromBackup();
1283 1510
1284 lock (m_parts) 1511 lockPartsForRead(true);
1512 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1513 lockPartsForRead(false);
1514
1515 foreach (SceneObjectPart part in values)
1285 { 1516 {
1286 foreach (SceneObjectPart part in m_parts.Values)
1287 {
1288// part.Inventory.RemoveScriptInstances(); 1517// part.Inventory.RemoveScriptInstances();
1289 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1518
1519 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1520 {
1521 if (sp.ParentID == LocalId)
1290 { 1522 {
1291 if (avatar.ParentID == LocalId) 1523 sp.StandUp();
1292 { 1524 }
1293 avatar.StandUp();
1294 }
1295 1525
1296 if (!silent) 1526 if (!silent)
1297 { 1527 {
1298 part.UpdateFlag = 0; 1528 part.UpdateFlag = 0;
1299 if (part == m_rootPart) 1529 if (part == m_rootPart)
1300 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1530 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1301 } 1531 }
1302 }); 1532 });
1303 } 1533
1304 } 1534 }
1535
1536
1305 } 1537 }
1306 1538
1307 public void AddScriptLPS(int count) 1539 public void AddScriptLPS(int count)
@@ -1326,17 +1558,20 @@ namespace OpenSim.Region.Framework.Scenes
1326 1558
1327 scriptEvents aggregateScriptEvents=0; 1559 scriptEvents aggregateScriptEvents=0;
1328 1560
1329 lock (m_parts) 1561 lockPartsForRead(true);
1330 { 1562 {
1331 foreach (SceneObjectPart part in m_parts.Values) 1563 foreach (SceneObjectPart part in m_parts.Values)
1332 { 1564 {
1565
1333 if (part == null) 1566 if (part == null)
1334 continue; 1567 continue;
1335 if (part != RootPart) 1568 if (part != RootPart)
1336 part.ObjectFlags = objectflagupdate; 1569 part.ObjectFlags = objectflagupdate;
1337 aggregateScriptEvents |= part.AggregateScriptEvents; 1570 aggregateScriptEvents |= part.AggregateScriptEvents;
1571
1338 } 1572 }
1339 } 1573 }
1574 lockPartsForRead(false);
1340 1575
1341 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1576 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1342 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1577 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1378,42 +1613,52 @@ namespace OpenSim.Region.Framework.Scenes
1378 /// <param name="m_physicalPrim"></param> 1613 /// <param name="m_physicalPrim"></param>
1379 public void ApplyPhysics(bool m_physicalPrim) 1614 public void ApplyPhysics(bool m_physicalPrim)
1380 { 1615 {
1381 lock (m_parts) 1616 lockPartsForRead(true);
1617
1618 if (m_parts.Count > 1)
1382 { 1619 {
1383 if (m_parts.Count > 1) 1620 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1621 lockPartsForRead(false);
1622 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1623 foreach (SceneObjectPart part in values)
1384 { 1624 {
1385 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1625
1386 foreach (SceneObjectPart part in m_parts.Values) 1626 if (part.LocalId != m_rootPart.LocalId)
1387 { 1627 {
1388 if (part.LocalId != m_rootPart.LocalId) 1628 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1389 {
1390 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1391 }
1392 } 1629 }
1393 1630
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 } 1631 }
1632 // Hack to get the physics scene geometries in the right spot
1633 ResetChildPrimPhysicsPositions();
1634 }
1635 else
1636 {
1637 lockPartsForRead(false);
1638 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1401 } 1639 }
1402 } 1640 }
1403 1641
1404 public void SetOwnerId(UUID userId) 1642 public void SetOwnerId(UUID userId)
1405 { 1643 {
1406 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1644 ForEachPart(delegate(SceneObjectPart part)
1645 {
1646
1647 part.OwnerID = userId;
1648
1649 });
1407 } 1650 }
1408 1651
1409 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1652 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1410 { 1653 {
1411 lock (m_parts) 1654 lockPartsForRead(true);
1655 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1656 lockPartsForRead(false);
1657 foreach (SceneObjectPart part in values)
1412 { 1658 {
1413 foreach (SceneObjectPart part in m_parts.Values) 1659
1414 { 1660 whatToDo(part);
1415 whatToDo(part); 1661
1416 }
1417 } 1662 }
1418 } 1663 }
1419 1664
@@ -1511,15 +1756,17 @@ namespace OpenSim.Region.Framework.Scenes
1511 RootPart.SendFullUpdate( 1756 RootPart.SendFullUpdate(
1512 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1757 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1513 1758
1514 lock (m_parts) 1759 lockPartsForRead(true);
1515 { 1760 {
1516 foreach (SceneObjectPart part in m_parts.Values) 1761 foreach (SceneObjectPart part in m_parts.Values)
1517 { 1762 {
1763
1518 if (part != RootPart) 1764 if (part != RootPart)
1519 part.SendFullUpdate( 1765 part.SendFullUpdate(
1520 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1766 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1521 } 1767 }
1522 } 1768 }
1769 lockPartsForRead(false);
1523 } 1770 }
1524 1771
1525 #region Copying 1772 #region Copying
@@ -1580,10 +1827,11 @@ namespace OpenSim.Region.Framework.Scenes
1580 1827
1581 List<SceneObjectPart> partList; 1828 List<SceneObjectPart> partList;
1582 1829
1583 lock (m_parts) 1830 lockPartsForRead(true);
1584 { 1831
1585 partList = new List<SceneObjectPart>(m_parts.Values); 1832 partList = new List<SceneObjectPart>(m_parts.Values);
1586 } 1833
1834 lockPartsForRead(false);
1587 1835
1588 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1836 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1589 { 1837 {
@@ -1800,13 +2048,40 @@ namespace OpenSim.Region.Framework.Scenes
1800 } 2048 }
1801 } 2049 }
1802 2050
2051 public void rotLookAt(Quaternion target, float strength, float damping)
2052 {
2053 SceneObjectPart rootpart = m_rootPart;
2054 if (rootpart != null)
2055 {
2056 if (IsAttachment)
2057 {
2058 /*
2059 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2060 if (avatar != null)
2061 {
2062 Rotate the Av?
2063 } */
2064 }
2065 else
2066 {
2067 if (rootpart.PhysActor != null)
2068 { // APID must be implemented in your physics system for this to function.
2069 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2070 rootpart.PhysActor.APIDStrength = strength;
2071 rootpart.PhysActor.APIDDamping = damping;
2072 rootpart.PhysActor.APIDActive = true;
2073 }
2074 }
2075 }
2076 }
2077
1803 public void stopLookAt() 2078 public void stopLookAt()
1804 { 2079 {
1805 SceneObjectPart rootpart = m_rootPart; 2080 SceneObjectPart rootpart = m_rootPart;
1806 if (rootpart != null) 2081 if (rootpart != null)
1807 { 2082 {
1808 if (rootpart.PhysActor != null) 2083 if (rootpart.PhysActor != null)
1809 { 2084 { // APID must be implemented in your physics system for this to function.
1810 rootpart.PhysActor.APIDActive = false; 2085 rootpart.PhysActor.APIDActive = false;
1811 } 2086 }
1812 } 2087 }
@@ -1874,10 +2149,11 @@ namespace OpenSim.Region.Framework.Scenes
1874 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2149 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1875 newPart.SetParent(this); 2150 newPart.SetParent(this);
1876 2151
1877 lock (m_parts) 2152 lockPartsForWrite(true);
1878 { 2153 {
1879 m_parts.Add(newPart.UUID, newPart); 2154 m_parts.Add(newPart.UUID, newPart);
1880 } 2155 }
2156 lockPartsForWrite(false);
1881 2157
1882 SetPartAsNonRoot(newPart); 2158 SetPartAsNonRoot(newPart);
1883 2159
@@ -1940,7 +2216,7 @@ namespace OpenSim.Region.Framework.Scenes
1940 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2216 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1941 // return; 2217 // return;
1942 2218
1943 lock (m_parts) 2219 lockPartsForRead(true);
1944 { 2220 {
1945 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2221 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1946 2222
@@ -1960,9 +2236,12 @@ namespace OpenSim.Region.Framework.Scenes
1960 { 2236 {
1961 if (!IsSelected) 2237 if (!IsSelected)
1962 part.UpdateLookAt(); 2238 part.UpdateLookAt();
2239
1963 part.SendScheduledUpdates(); 2240 part.SendScheduledUpdates();
2241
1964 } 2242 }
1965 } 2243 }
2244 lockPartsForRead(false);
1966 } 2245 }
1967 2246
1968 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2247 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1971,27 +2250,29 @@ namespace OpenSim.Region.Framework.Scenes
1971 2250
1972 RootPart.AddFullUpdateToAvatar(presence); 2251 RootPart.AddFullUpdateToAvatar(presence);
1973 2252
1974 lock (m_parts) 2253 lockPartsForRead(true);
1975 { 2254 {
1976 foreach (SceneObjectPart part in m_parts.Values) 2255 foreach (SceneObjectPart part in m_parts.Values)
1977 { 2256 {
2257
1978 if (part != RootPart) 2258 if (part != RootPart)
1979 part.AddFullUpdateToAvatar(presence); 2259 part.AddFullUpdateToAvatar(presence);
2260
1980 } 2261 }
1981 } 2262 }
2263 lockPartsForRead(false);
1982 } 2264 }
1983 2265
1984 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2266 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1985 { 2267 {
1986// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2268 lockPartsForRead(true);
1987 2269
1988 lock (m_parts) 2270 foreach (SceneObjectPart part in m_parts.Values)
1989 { 2271 {
1990 foreach (SceneObjectPart part in m_parts.Values) 2272 part.AddTerseUpdateToAvatar(presence);
1991 {
1992 part.AddTerseUpdateToAvatar(presence);
1993 }
1994 } 2273 }
2274
2275 lockPartsForRead(false);
1995 } 2276 }
1996 2277
1997 /// <summary> 2278 /// <summary>
@@ -1999,20 +2280,23 @@ namespace OpenSim.Region.Framework.Scenes
1999 /// </summary> 2280 /// </summary>
2000 public void ScheduleGroupForFullUpdate() 2281 public void ScheduleGroupForFullUpdate()
2001 { 2282 {
2002 if (IsAttachment) 2283 //if (IsAttachment)
2003 m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); 2284 // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
2004 2285
2005 checkAtTargets(); 2286 checkAtTargets();
2006 RootPart.ScheduleFullUpdate(); 2287 RootPart.ScheduleFullUpdate();
2007 2288
2008 lock (m_parts) 2289 lockPartsForRead(true);
2009 { 2290 {
2010 foreach (SceneObjectPart part in m_parts.Values) 2291 foreach (SceneObjectPart part in m_parts.Values)
2011 { 2292 {
2293
2012 if (part != RootPart) 2294 if (part != RootPart)
2013 part.ScheduleFullUpdate(); 2295 part.ScheduleFullUpdate();
2296
2014 } 2297 }
2015 } 2298 }
2299 lockPartsForRead(false);
2016 } 2300 }
2017 2301
2018 /// <summary> 2302 /// <summary>
@@ -2020,37 +2304,38 @@ namespace OpenSim.Region.Framework.Scenes
2020 /// </summary> 2304 /// </summary>
2021 public void ScheduleGroupForTerseUpdate() 2305 public void ScheduleGroupForTerseUpdate()
2022 { 2306 {
2023// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2307 lockPartsForRead(true);
2024 2308 foreach (SceneObjectPart part in m_parts.Values)
2025 lock (m_parts)
2026 { 2309 {
2027 foreach (SceneObjectPart part in m_parts.Values) 2310 part.ScheduleTerseUpdate();
2028 {
2029 part.ScheduleTerseUpdate();
2030 }
2031 } 2311 }
2312
2313 lockPartsForRead(false);
2032 } 2314 }
2033 2315
2034 /// <summary> 2316 /// <summary>
2035 /// Immediately send a full update for this scene object. 2317 /// Immediately send a full update for this scene object.
2036 /// </summary> 2318 /// </summary>
2037 public void SendGroupFullUpdate() 2319 public void SendGroupFullUpdate()
2038 { 2320 {
2039 if (IsDeleted) 2321 if (IsDeleted)
2040 return; 2322 return;
2041 2323
2042// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2324// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2043 2325
2044 RootPart.SendFullUpdateToAllClients(); 2326 RootPart.SendFullUpdateToAllClients();
2045 2327
2046 lock (m_parts) 2328 lockPartsForRead(true);
2047 { 2329 {
2048 foreach (SceneObjectPart part in m_parts.Values) 2330 foreach (SceneObjectPart part in m_parts.Values)
2049 { 2331 {
2332
2050 if (part != RootPart) 2333 if (part != RootPart)
2051 part.SendFullUpdateToAllClients(); 2334 part.SendFullUpdateToAllClients();
2335
2052 } 2336 }
2053 } 2337 }
2338 lockPartsForRead(false);
2054 } 2339 }
2055 2340
2056 /// <summary> 2341 /// <summary>
@@ -2082,14 +2367,15 @@ namespace OpenSim.Region.Framework.Scenes
2082 { 2367 {
2083 if (IsDeleted) 2368 if (IsDeleted)
2084 return; 2369 return;
2085 2370
2086 lock (m_parts) 2371 lockPartsForRead(true);
2087 { 2372 {
2088 foreach (SceneObjectPart part in m_parts.Values) 2373 foreach (SceneObjectPart part in m_parts.Values)
2089 { 2374 {
2090 part.SendTerseUpdateToAllClients(); 2375 part.SendTerseUpdateToAllClients();
2091 } 2376 }
2092 } 2377 }
2378 lockPartsForRead(false);
2093 } 2379 }
2094 2380
2095 #endregion 2381 #endregion
@@ -2103,16 +2389,18 @@ namespace OpenSim.Region.Framework.Scenes
2103 /// <returns>null if no child part with that linknum or child part</returns> 2389 /// <returns>null if no child part with that linknum or child part</returns>
2104 public SceneObjectPart GetLinkNumPart(int linknum) 2390 public SceneObjectPart GetLinkNumPart(int linknum)
2105 { 2391 {
2106 lock (m_parts) 2392 lockPartsForRead(true);
2107 { 2393 {
2108 foreach (SceneObjectPart part in m_parts.Values) 2394 foreach (SceneObjectPart part in m_parts.Values)
2109 { 2395 {
2110 if (part.LinkNum == linknum) 2396 if (part.LinkNum == linknum)
2111 { 2397 {
2398 lockPartsForRead(false);
2112 return part; 2399 return part;
2113 } 2400 }
2114 } 2401 }
2115 } 2402 }
2403 lockPartsForRead(false);
2116 2404
2117 return null; 2405 return null;
2118 } 2406 }
@@ -2140,17 +2428,19 @@ namespace OpenSim.Region.Framework.Scenes
2140 public SceneObjectPart GetChildPart(uint localID) 2428 public SceneObjectPart GetChildPart(uint localID)
2141 { 2429 {
2142 //m_log.DebugFormat("Entered looking for {0}", localID); 2430 //m_log.DebugFormat("Entered looking for {0}", localID);
2143 lock (m_parts) 2431 lockPartsForRead(true);
2144 { 2432 {
2145 foreach (SceneObjectPart part in m_parts.Values) 2433 foreach (SceneObjectPart part in m_parts.Values)
2146 { 2434 {
2147 //m_log.DebugFormat("Found {0}", part.LocalId); 2435 //m_log.DebugFormat("Found {0}", part.LocalId);
2148 if (part.LocalId == localID) 2436 if (part.LocalId == localID)
2149 { 2437 {
2438 lockPartsForRead(false);
2150 return part; 2439 return part;
2151 } 2440 }
2152 } 2441 }
2153 } 2442 }
2443 lockPartsForRead(false);
2154 2444
2155 return null; 2445 return null;
2156 } 2446 }
@@ -2180,17 +2470,19 @@ namespace OpenSim.Region.Framework.Scenes
2180 public bool HasChildPrim(uint localID) 2470 public bool HasChildPrim(uint localID)
2181 { 2471 {
2182 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2472 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2183 lock (m_parts) 2473 lockPartsForRead(true);
2184 { 2474 {
2185 foreach (SceneObjectPart part in m_parts.Values) 2475 foreach (SceneObjectPart part in m_parts.Values)
2186 { 2476 {
2187 //m_log.DebugFormat("Found {0}", part.LocalId); 2477 //m_log.DebugFormat("Found {0}", part.LocalId);
2188 if (part.LocalId == localID) 2478 if (part.LocalId == localID)
2189 { 2479 {
2480 lockPartsForRead(false);
2190 return true; 2481 return true;
2191 } 2482 }
2192 } 2483 }
2193 } 2484 }
2485 lockPartsForRead(false);
2194 2486
2195 return false; 2487 return false;
2196 } 2488 }
@@ -2240,53 +2532,57 @@ namespace OpenSim.Region.Framework.Scenes
2240 if (m_rootPart.LinkNum == 0) 2532 if (m_rootPart.LinkNum == 0)
2241 m_rootPart.LinkNum = 1; 2533 m_rootPart.LinkNum = 1;
2242 2534
2243 lock (m_parts) 2535 lockPartsForWrite(true);
2244 { 2536
2245 m_parts.Add(linkPart.UUID, linkPart); 2537 m_parts.Add(linkPart.UUID, linkPart);
2538
2539 lockPartsForWrite(false);
2246 2540
2247 // Insert in terms of link numbers, the new links 2541 // Insert in terms of link numbers, the new links
2248 // before the current ones (with the exception of 2542 // before the current ones (with the exception of
2249 // the root prim. Shuffle the old ones up 2543 // the root prim. Shuffle the old ones up
2250 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2544 lockPartsForRead(true);
2545 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2546 {
2547 if (kvp.Value.LinkNum != 1)
2251 { 2548 {
2252 if (kvp.Value.LinkNum != 1) 2549 // Don't update root prim link number
2253 { 2550 kvp.Value.LinkNum += objectGroup.PrimCount;
2254 // Don't update root prim link number
2255 kvp.Value.LinkNum += objectGroup.PrimCount;
2256 }
2257 } 2551 }
2552 }
2553 lockPartsForRead(false);
2258 2554
2259 linkPart.LinkNum = 2; 2555 linkPart.LinkNum = 2;
2260 2556
2261 linkPart.SetParent(this); 2557 linkPart.SetParent(this);
2262 linkPart.CreateSelected = true; 2558 linkPart.CreateSelected = true;
2263 2559
2264 //if (linkPart.PhysActor != null) 2560 //if (linkPart.PhysActor != null)
2265 //{ 2561 //{
2266 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2562 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2267 2563
2268 //linkPart.PhysActor = null; 2564 //linkPart.PhysActor = null;
2269 //} 2565 //}
2270 2566
2271 //TODO: rest of parts 2567 //TODO: rest of parts
2272 int linkNum = 3; 2568 int linkNum = 3;
2273 foreach (SceneObjectPart part in objectGroup.Children.Values) 2569 foreach (SceneObjectPart part in objectGroup.Children.Values)
2570 {
2571 if (part.UUID != objectGroup.m_rootPart.UUID)
2274 { 2572 {
2275 if (part.UUID != objectGroup.m_rootPart.UUID) 2573 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2276 {
2277 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2278 }
2279 part.ClearUndoState();
2280 } 2574 }
2575 part.ClearUndoState();
2281 } 2576 }
2282 2577
2283 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2578 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2284 objectGroup.m_isDeleted = true; 2579 objectGroup.m_isDeleted = true;
2580
2581 objectGroup.lockPartsForWrite(true);
2285 2582
2286 lock (objectGroup.m_parts) 2583 objectGroup.m_parts.Clear();
2287 { 2584
2288 objectGroup.m_parts.Clear(); 2585 objectGroup.lockPartsForWrite(false);
2289 }
2290 2586
2291 // Can't do this yet since backup still makes use of the root part without any synchronization 2587 // Can't do this yet since backup still makes use of the root part without any synchronization
2292// objectGroup.m_rootPart = null; 2588// objectGroup.m_rootPart = null;
@@ -2356,11 +2652,12 @@ namespace OpenSim.Region.Framework.Scenes
2356 Quaternion worldRot = linkPart.GetWorldRotation(); 2652 Quaternion worldRot = linkPart.GetWorldRotation();
2357 2653
2358 // Remove the part from this object 2654 // Remove the part from this object
2359 lock (m_parts) 2655 lockPartsForWrite(true);
2360 { 2656 {
2361 m_parts.Remove(linkPart.UUID); 2657 m_parts.Remove(linkPart.UUID);
2362 } 2658 }
2363 2659 lockPartsForWrite(false);
2660 lockPartsForRead(true);
2364 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2661 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2365 RootPart.LinkNum = 0; 2662 RootPart.LinkNum = 0;
2366 else 2663 else
@@ -2371,6 +2668,7 @@ namespace OpenSim.Region.Framework.Scenes
2371 p.LinkNum--; 2668 p.LinkNum--;
2372 } 2669 }
2373 } 2670 }
2671 lockPartsForRead(false);
2374 2672
2375 linkPart.ParentID = 0; 2673 linkPart.ParentID = 0;
2376 linkPart.LinkNum = 0; 2674 linkPart.LinkNum = 0;
@@ -2414,6 +2712,8 @@ namespace OpenSim.Region.Framework.Scenes
2414 /// <param name="objectGroup"></param> 2712 /// <param name="objectGroup"></param>
2415 public virtual void DetachFromBackup() 2713 public virtual void DetachFromBackup()
2416 { 2714 {
2715 m_scene.SceneGraph.FireDetachFromBackup(this);
2716
2417 if (m_isBackedUp) 2717 if (m_isBackedUp)
2418 m_scene.EventManager.OnBackup -= ProcessBackup; 2718 m_scene.EventManager.OnBackup -= ProcessBackup;
2419 2719
@@ -2692,9 +2992,12 @@ namespace OpenSim.Region.Framework.Scenes
2692 2992
2693 if (selectionPart != null) 2993 if (selectionPart != null)
2694 { 2994 {
2695 lock (m_parts) 2995 lockPartsForRead(true);
2996 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2997 lockPartsForRead(false);
2998 foreach (SceneObjectPart part in parts)
2696 { 2999 {
2697 foreach (SceneObjectPart part in m_parts.Values) 3000 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2698 { 3001 {
2699 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 3002 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2700 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 3003 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2704,12 +3007,13 @@ namespace OpenSim.Region.Framework.Scenes
2704 break; 3007 break;
2705 } 3008 }
2706 } 3009 }
3010 }
2707 3011
2708 foreach (SceneObjectPart part in m_parts.Values) 3012 foreach (SceneObjectPart part in parts)
2709 { 3013 {
2710 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3014 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2711 }
2712 } 3015 }
3016
2713 } 3017 }
2714 } 3018 }
2715 3019
@@ -2722,6 +3026,17 @@ namespace OpenSim.Region.Framework.Scenes
2722 } 3026 }
2723 } 3027 }
2724 3028
3029
3030
3031 /// <summary>
3032 /// Gets the number of parts
3033 /// </summary>
3034 /// <returns></returns>
3035 public int GetPartCount()
3036 {
3037 return Children.Count;
3038 }
3039
2725 /// <summary> 3040 /// <summary>
2726 /// Get the parts of this scene object 3041 /// Get the parts of this scene object
2727 /// </summary> 3042 /// </summary>
@@ -2795,11 +3110,9 @@ namespace OpenSim.Region.Framework.Scenes
2795 scale.Y = m_scene.m_maxNonphys; 3110 scale.Y = m_scene.m_maxNonphys;
2796 if (scale.Z > m_scene.m_maxNonphys) 3111 if (scale.Z > m_scene.m_maxNonphys)
2797 scale.Z = m_scene.m_maxNonphys; 3112 scale.Z = m_scene.m_maxNonphys;
2798
2799 SceneObjectPart part = GetChildPart(localID); 3113 SceneObjectPart part = GetChildPart(localID);
2800 if (part != null) 3114 if (part != null)
2801 { 3115 {
2802 part.Resize(scale);
2803 if (part.PhysActor != null) 3116 if (part.PhysActor != null)
2804 { 3117 {
2805 if (part.PhysActor.IsPhysical) 3118 if (part.PhysActor.IsPhysical)
@@ -2814,7 +3127,7 @@ namespace OpenSim.Region.Framework.Scenes
2814 part.PhysActor.Size = scale; 3127 part.PhysActor.Size = scale;
2815 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3128 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2816 } 3129 }
2817 //if (part.UUID != m_rootPart.UUID) 3130 part.Resize(scale);
2818 3131
2819 HasGroupChanged = true; 3132 HasGroupChanged = true;
2820 ScheduleGroupForFullUpdate(); 3133 ScheduleGroupForFullUpdate();
@@ -2836,7 +3149,6 @@ namespace OpenSim.Region.Framework.Scenes
2836 SceneObjectPart part = GetChildPart(localID); 3149 SceneObjectPart part = GetChildPart(localID);
2837 if (part != null) 3150 if (part != null)
2838 { 3151 {
2839 part.IgnoreUndoUpdate = true;
2840 if (scale.X > m_scene.m_maxNonphys) 3152 if (scale.X > m_scene.m_maxNonphys)
2841 scale.X = m_scene.m_maxNonphys; 3153 scale.X = m_scene.m_maxNonphys;
2842 if (scale.Y > m_scene.m_maxNonphys) 3154 if (scale.Y > m_scene.m_maxNonphys)
@@ -2856,94 +3168,100 @@ namespace OpenSim.Region.Framework.Scenes
2856 float y = (scale.Y / part.Scale.Y); 3168 float y = (scale.Y / part.Scale.Y);
2857 float z = (scale.Z / part.Scale.Z); 3169 float z = (scale.Z / part.Scale.Z);
2858 3170
2859 lock (m_parts) 3171 lockPartsForRead(true);
3172 if (x > 1.0f || y > 1.0f || z > 1.0f)
2860 { 3173 {
2861 if (x > 1.0f || y > 1.0f || z > 1.0f) 3174 foreach (SceneObjectPart obPart in m_parts.Values)
2862 { 3175 {
2863 foreach (SceneObjectPart obPart in m_parts.Values) 3176 if (obPart.UUID != m_rootPart.UUID)
2864 { 3177 {
2865 if (obPart.UUID != m_rootPart.UUID) 3178 Vector3 oldSize = new Vector3(obPart.Scale);
2866 { 3179 obPart.IgnoreUndoUpdate = true;
2867 obPart.IgnoreUndoUpdate = true;
2868 Vector3 oldSize = new Vector3(obPart.Scale);
2869 3180
2870 float f = 1.0f; 3181 float f = 1.0f;
2871 float a = 1.0f; 3182 float a = 1.0f;
2872 3183
2873 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3184 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3185 {
3186 if (oldSize.X*x > m_scene.m_maxPhys)
2874 { 3187 {
2875 if (oldSize.X*x > m_scene.m_maxPhys) 3188 f = m_scene.m_maxPhys / oldSize.X;
2876 { 3189 a = f / x;
2877 f = m_scene.m_maxPhys / oldSize.X; 3190 x *= a;
2878 a = f / x; 3191 y *= a;
2879 x *= a; 3192 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 } 3193 }
2900 else 3194 if (oldSize.Y*y > m_scene.m_maxPhys)
3195 {
3196 f = m_scene.m_maxPhys / oldSize.Y;
3197 a = f / y;
3198 x *= a;
3199 y *= a;
3200 z *= a;
3201 }
3202 if (oldSize.Z*z > m_scene.m_maxPhys)
3203 {
3204 f = m_scene.m_maxPhys / oldSize.Z;
3205 a = f / z;
3206 x *= a;
3207 y *= a;
3208 z *= a;
3209 }
3210 }
3211 else
3212 {
3213 if (oldSize.X*x > m_scene.m_maxNonphys)
3214 {
3215 f = m_scene.m_maxNonphys / oldSize.X;
3216 a = f / x;
3217 x *= a;
3218 y *= a;
3219 z *= a;
3220 }
3221 if (oldSize.Y*y > m_scene.m_maxNonphys)
3222 {
3223 f = m_scene.m_maxNonphys / oldSize.Y;
3224 a = f / y;
3225 x *= a;
3226 y *= a;
3227 z *= a;
3228 }
3229 if (oldSize.Z*z > m_scene.m_maxNonphys)
2901 { 3230 {
2902 if (oldSize.X*x > m_scene.m_maxNonphys) 3231 f = m_scene.m_maxNonphys / oldSize.Z;
2903 { 3232 a = f / z;
2904 f = m_scene.m_maxNonphys / oldSize.X; 3233 x *= a;
2905 a = f / x; 3234 y *= a;
2906 x *= a; 3235 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 } 3236 }
2927 obPart.IgnoreUndoUpdate = false; 3237
2928 obPart.StoreUndoState();
2929 } 3238 }
2930 } 3239 }
2931 } 3240 }
2932 } 3241 }
3242 lockPartsForRead(false);
2933 3243
2934 Vector3 prevScale = part.Scale; 3244 Vector3 prevScale = part.Scale;
2935 prevScale.X *= x; 3245 prevScale.X *= x;
2936 prevScale.Y *= y; 3246 prevScale.Y *= y;
2937 prevScale.Z *= z; 3247 prevScale.Z *= z;;
3248
3249 part.IgnoreUndoUpdate = false;
3250 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3251 part.IgnoreUndoUpdate = true;
2938 part.Resize(prevScale); 3252 part.Resize(prevScale);
3253 part.IgnoreUndoUpdate = false;
2939 3254
2940 lock (m_parts) 3255 lockPartsForRead(true);
2941 { 3256 {
2942 foreach (SceneObjectPart obPart in m_parts.Values) 3257 foreach (SceneObjectPart obPart in m_parts.Values)
2943 { 3258 {
2944 obPart.IgnoreUndoUpdate = true;
2945 if (obPart.UUID != m_rootPart.UUID) 3259 if (obPart.UUID != m_rootPart.UUID)
2946 { 3260 {
3261 obPart.IgnoreUndoUpdate = false;
3262 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3263 obPart.IgnoreUndoUpdate = true;
3264
2947 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3265 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2948 currentpos.X *= x; 3266 currentpos.X *= x;
2949 currentpos.Y *= y; 3267 currentpos.Y *= y;
@@ -2956,9 +3274,9 @@ namespace OpenSim.Region.Framework.Scenes
2956 obPart.UpdateOffSet(currentpos); 3274 obPart.UpdateOffSet(currentpos);
2957 } 3275 }
2958 obPart.IgnoreUndoUpdate = false; 3276 obPart.IgnoreUndoUpdate = false;
2959 obPart.StoreUndoState();
2960 } 3277 }
2961 } 3278 }
3279 lockPartsForRead(false);
2962 3280
2963 if (part.PhysActor != null) 3281 if (part.PhysActor != null)
2964 { 3282 {
@@ -2967,7 +3285,6 @@ namespace OpenSim.Region.Framework.Scenes
2967 } 3285 }
2968 3286
2969 part.IgnoreUndoUpdate = false; 3287 part.IgnoreUndoUpdate = false;
2970 part.StoreUndoState();
2971 HasGroupChanged = true; 3288 HasGroupChanged = true;
2972 ScheduleGroupForTerseUpdate(); 3289 ScheduleGroupForTerseUpdate();
2973 } 3290 }
@@ -2983,14 +3300,11 @@ namespace OpenSim.Region.Framework.Scenes
2983 /// <param name="pos"></param> 3300 /// <param name="pos"></param>
2984 public void UpdateGroupPosition(Vector3 pos) 3301 public void UpdateGroupPosition(Vector3 pos)
2985 { 3302 {
2986 foreach (SceneObjectPart part in Children.Values)
2987 {
2988 part.StoreUndoState();
2989 }
2990 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3303 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2991 { 3304 {
2992 if (IsAttachment) 3305 if (IsAttachment)
2993 { 3306 {
3307 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2994 m_rootPart.AttachedPos = pos; 3308 m_rootPart.AttachedPos = pos;
2995 } 3309 }
2996 if (RootPart.GetStatusSandbox()) 3310 if (RootPart.GetStatusSandbox())
@@ -3023,7 +3337,7 @@ namespace OpenSim.Region.Framework.Scenes
3023 SceneObjectPart part = GetChildPart(localID); 3337 SceneObjectPart part = GetChildPart(localID);
3024 foreach (SceneObjectPart parts in Children.Values) 3338 foreach (SceneObjectPart parts in Children.Values)
3025 { 3339 {
3026 parts.StoreUndoState(); 3340 parts.StoreUndoState(UndoType.STATE_PRIM_POSITION);
3027 } 3341 }
3028 if (part != null) 3342 if (part != null)
3029 { 3343 {
@@ -3048,7 +3362,7 @@ namespace OpenSim.Region.Framework.Scenes
3048 { 3362 {
3049 foreach (SceneObjectPart part in Children.Values) 3363 foreach (SceneObjectPart part in Children.Values)
3050 { 3364 {
3051 part.StoreUndoState(); 3365 part.StoreUndoState(UndoType.STATE_PRIM_POSITION);
3052 } 3366 }
3053 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3367 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3054 Vector3 oldPos = 3368 Vector3 oldPos =
@@ -3061,7 +3375,7 @@ namespace OpenSim.Region.Framework.Scenes
3061 axDiff *= Quaternion.Inverse(partRotation); 3375 axDiff *= Quaternion.Inverse(partRotation);
3062 diff = axDiff; 3376 diff = axDiff;
3063 3377
3064 lock (m_parts) 3378 lockPartsForRead(true);
3065 { 3379 {
3066 foreach (SceneObjectPart obPart in m_parts.Values) 3380 foreach (SceneObjectPart obPart in m_parts.Values)
3067 { 3381 {
@@ -3071,11 +3385,29 @@ namespace OpenSim.Region.Framework.Scenes
3071 } 3385 }
3072 } 3386 }
3073 } 3387 }
3388 lockPartsForRead(false);
3074 3389
3075 AbsolutePosition = newPos; 3390 //We have to set undoing here because otherwise an undo state will be saved
3391 if (!m_rootPart.Undoing)
3392 {
3393 m_rootPart.Undoing = true;
3394 AbsolutePosition = newPos;
3395 m_rootPart.Undoing = false;
3396 }
3397 else
3398 {
3399 AbsolutePosition = newPos;
3400 }
3076 3401
3077 HasGroupChanged = true; 3402 HasGroupChanged = true;
3078 ScheduleGroupForTerseUpdate(); 3403 if (m_rootPart.Undoing)
3404 {
3405 ScheduleGroupForFullUpdate();
3406 }
3407 else
3408 {
3409 ScheduleGroupForTerseUpdate();
3410 }
3079 } 3411 }
3080 3412
3081 public void OffsetForNewRegion(Vector3 offset) 3413 public void OffsetForNewRegion(Vector3 offset)
@@ -3095,7 +3427,7 @@ namespace OpenSim.Region.Framework.Scenes
3095 { 3427 {
3096 foreach (SceneObjectPart parts in Children.Values) 3428 foreach (SceneObjectPart parts in Children.Values)
3097 { 3429 {
3098 parts.StoreUndoState(); 3430 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3099 } 3431 }
3100 m_rootPart.UpdateRotation(rot); 3432 m_rootPart.UpdateRotation(rot);
3101 3433
@@ -3119,7 +3451,7 @@ namespace OpenSim.Region.Framework.Scenes
3119 { 3451 {
3120 foreach (SceneObjectPart parts in Children.Values) 3452 foreach (SceneObjectPart parts in Children.Values)
3121 { 3453 {
3122 parts.StoreUndoState(); 3454 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3123 } 3455 }
3124 m_rootPart.UpdateRotation(rot); 3456 m_rootPart.UpdateRotation(rot);
3125 3457
@@ -3146,7 +3478,7 @@ namespace OpenSim.Region.Framework.Scenes
3146 SceneObjectPart part = GetChildPart(localID); 3478 SceneObjectPart part = GetChildPart(localID);
3147 foreach (SceneObjectPart parts in Children.Values) 3479 foreach (SceneObjectPart parts in Children.Values)
3148 { 3480 {
3149 parts.StoreUndoState(); 3481 parts.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3150 } 3482 }
3151 if (part != null) 3483 if (part != null)
3152 { 3484 {
@@ -3174,15 +3506,24 @@ namespace OpenSim.Region.Framework.Scenes
3174 if (part.UUID == m_rootPart.UUID) 3506 if (part.UUID == m_rootPart.UUID)
3175 { 3507 {
3176 UpdateRootRotation(rot); 3508 UpdateRootRotation(rot);
3177 AbsolutePosition = pos; 3509 if (!m_rootPart.Undoing)
3510 {
3511 m_rootPart.Undoing = true;
3512 AbsolutePosition = pos;
3513 m_rootPart.Undoing = false;
3514 }
3515 else
3516 {
3517 AbsolutePosition = pos;
3518 }
3178 } 3519 }
3179 else 3520 else
3180 { 3521 {
3522 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3181 part.IgnoreUndoUpdate = true; 3523 part.IgnoreUndoUpdate = true;
3182 part.UpdateRotation(rot); 3524 part.UpdateRotation(rot);
3183 part.OffsetPosition = pos; 3525 part.OffsetPosition = pos;
3184 part.IgnoreUndoUpdate = false; 3526 part.IgnoreUndoUpdate = false;
3185 part.StoreUndoState();
3186 } 3527 }
3187 } 3528 }
3188 } 3529 }
@@ -3196,7 +3537,13 @@ namespace OpenSim.Region.Framework.Scenes
3196 Quaternion axRot = rot; 3537 Quaternion axRot = rot;
3197 Quaternion oldParentRot = m_rootPart.RotationOffset; 3538 Quaternion oldParentRot = m_rootPart.RotationOffset;
3198 3539
3199 m_rootPart.StoreUndoState(); 3540 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3541 bool cancelUndo = false;
3542 if (!m_rootPart.Undoing)
3543 {
3544 m_rootPart.Undoing = true;
3545 cancelUndo = true;
3546 }
3200 m_rootPart.UpdateRotation(rot); 3547 m_rootPart.UpdateRotation(rot);
3201 if (m_rootPart.PhysActor != null) 3548 if (m_rootPart.PhysActor != null)
3202 { 3549 {
@@ -3204,33 +3551,31 @@ namespace OpenSim.Region.Framework.Scenes
3204 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3551 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3205 } 3552 }
3206 3553
3207 lock (m_parts) 3554 lockPartsForRead(true);
3555
3556 foreach (SceneObjectPart prim in m_parts.Values)
3208 { 3557 {
3209 foreach (SceneObjectPart prim in m_parts.Values) 3558 if (prim.UUID != m_rootPart.UUID)
3210 { 3559 {
3211 if (prim.UUID != m_rootPart.UUID) 3560 prim.IgnoreUndoUpdate = true;
3212 { 3561 Vector3 axPos = prim.OffsetPosition;
3213 prim.IgnoreUndoUpdate = true; 3562 axPos *= oldParentRot;
3214 Vector3 axPos = prim.OffsetPosition; 3563 axPos *= Quaternion.Inverse(axRot);
3215 axPos *= oldParentRot; 3564 prim.OffsetPosition = axPos;
3216 axPos *= Quaternion.Inverse(axRot); 3565 Quaternion primsRot = prim.RotationOffset;
3217 prim.OffsetPosition = axPos; 3566 Quaternion newRot = primsRot * oldParentRot;
3218 Quaternion primsRot = prim.RotationOffset; 3567 newRot *= Quaternion.Inverse(axRot);
3219 Quaternion newRot = primsRot * oldParentRot; 3568 prim.RotationOffset = newRot;
3220 newRot *= Quaternion.Inverse(axRot); 3569 prim.ScheduleTerseUpdate();
3221 prim.RotationOffset = newRot; 3570 prim.IgnoreUndoUpdate = false;
3222 prim.ScheduleTerseUpdate();
3223 }
3224 } 3571 }
3225 } 3572 }
3226 foreach (SceneObjectPart childpart in Children.Values) 3573 if (cancelUndo == true)
3227 { 3574 {
3228 if (childpart != m_rootPart) 3575 m_rootPart.Undoing = false;
3229 {
3230 childpart.IgnoreUndoUpdate = false;
3231 childpart.StoreUndoState();
3232 }
3233 } 3576 }
3577 lockPartsForRead(false);
3578
3234 m_rootPart.ScheduleTerseUpdate(); 3579 m_rootPart.ScheduleTerseUpdate();
3235 } 3580 }
3236 3581
@@ -3352,7 +3697,7 @@ namespace OpenSim.Region.Framework.Scenes
3352 if (atTargets.Count > 0) 3697 if (atTargets.Count > 0)
3353 { 3698 {
3354 uint[] localids = new uint[0]; 3699 uint[] localids = new uint[0];
3355 lock (m_parts) 3700 lockPartsForRead(true);
3356 { 3701 {
3357 localids = new uint[m_parts.Count]; 3702 localids = new uint[m_parts.Count];
3358 int cntr = 0; 3703 int cntr = 0;
@@ -3362,6 +3707,7 @@ namespace OpenSim.Region.Framework.Scenes
3362 cntr++; 3707 cntr++;
3363 } 3708 }
3364 } 3709 }
3710 lockPartsForRead(false);
3365 3711
3366 for (int ctr = 0; ctr < localids.Length; ctr++) 3712 for (int ctr = 0; ctr < localids.Length; ctr++)
3367 { 3713 {
@@ -3380,7 +3726,7 @@ namespace OpenSim.Region.Framework.Scenes
3380 { 3726 {
3381 //trigger not_at_target 3727 //trigger not_at_target
3382 uint[] localids = new uint[0]; 3728 uint[] localids = new uint[0];
3383 lock (m_parts) 3729 lockPartsForRead(true);
3384 { 3730 {
3385 localids = new uint[m_parts.Count]; 3731 localids = new uint[m_parts.Count];
3386 int cntr = 0; 3732 int cntr = 0;
@@ -3390,7 +3736,8 @@ namespace OpenSim.Region.Framework.Scenes
3390 cntr++; 3736 cntr++;
3391 } 3737 }
3392 } 3738 }
3393 3739 lockPartsForRead(false);
3740
3394 for (int ctr = 0; ctr < localids.Length; ctr++) 3741 for (int ctr = 0; ctr < localids.Length; ctr++)
3395 { 3742 {
3396 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3743 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3431,7 +3778,8 @@ namespace OpenSim.Region.Framework.Scenes
3431 if (atRotTargets.Count > 0) 3778 if (atRotTargets.Count > 0)
3432 { 3779 {
3433 uint[] localids = new uint[0]; 3780 uint[] localids = new uint[0];
3434 lock (m_parts) 3781 lockPartsForRead(true);
3782 try
3435 { 3783 {
3436 localids = new uint[m_parts.Count]; 3784 localids = new uint[m_parts.Count];
3437 int cntr = 0; 3785 int cntr = 0;
@@ -3441,6 +3789,10 @@ namespace OpenSim.Region.Framework.Scenes
3441 cntr++; 3789 cntr++;
3442 } 3790 }
3443 } 3791 }
3792 finally
3793 {
3794 lockPartsForRead(false);
3795 }
3444 3796
3445 for (int ctr = 0; ctr < localids.Length; ctr++) 3797 for (int ctr = 0; ctr < localids.Length; ctr++)
3446 { 3798 {
@@ -3459,7 +3811,8 @@ namespace OpenSim.Region.Framework.Scenes
3459 { 3811 {
3460 //trigger not_at_target 3812 //trigger not_at_target
3461 uint[] localids = new uint[0]; 3813 uint[] localids = new uint[0];
3462 lock (m_parts) 3814 lockPartsForRead(true);
3815 try
3463 { 3816 {
3464 localids = new uint[m_parts.Count]; 3817 localids = new uint[m_parts.Count];
3465 int cntr = 0; 3818 int cntr = 0;
@@ -3469,6 +3822,10 @@ namespace OpenSim.Region.Framework.Scenes
3469 cntr++; 3822 cntr++;
3470 } 3823 }
3471 } 3824 }
3825 finally
3826 {
3827 lockPartsForRead(false);
3828 }
3472 3829
3473 for (int ctr = 0; ctr < localids.Length; ctr++) 3830 for (int ctr = 0; ctr < localids.Length; ctr++)
3474 { 3831 {
@@ -3482,19 +3839,20 @@ namespace OpenSim.Region.Framework.Scenes
3482 public float GetMass() 3839 public float GetMass()
3483 { 3840 {
3484 float retmass = 0f; 3841 float retmass = 0f;
3485 lock (m_parts) 3842 lockPartsForRead(true);
3486 { 3843 {
3487 foreach (SceneObjectPart part in m_parts.Values) 3844 foreach (SceneObjectPart part in m_parts.Values)
3488 { 3845 {
3489 retmass += part.GetMass(); 3846 retmass += part.GetMass();
3490 } 3847 }
3491 } 3848 }
3849 lockPartsForRead(false);
3492 return retmass; 3850 return retmass;
3493 } 3851 }
3494 3852
3495 public void CheckSculptAndLoad() 3853 public void CheckSculptAndLoad()
3496 { 3854 {
3497 lock (m_parts) 3855 lockPartsForRead(true);
3498 { 3856 {
3499 if (!IsDeleted) 3857 if (!IsDeleted)
3500 { 3858 {
@@ -3519,6 +3877,7 @@ namespace OpenSim.Region.Framework.Scenes
3519 } 3877 }
3520 } 3878 }
3521 } 3879 }
3880 lockPartsForRead(false);
3522 } 3881 }
3523 3882
3524 protected void AssetReceived(string id, Object sender, AssetBase asset) 3883 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3539,7 +3898,7 @@ namespace OpenSim.Region.Framework.Scenes
3539 /// <param name="client"></param> 3898 /// <param name="client"></param>
3540 public void SetGroup(UUID GroupID, IClientAPI client) 3899 public void SetGroup(UUID GroupID, IClientAPI client)
3541 { 3900 {
3542 lock (m_parts) 3901 lockPartsForRead(true);
3543 { 3902 {
3544 foreach (SceneObjectPart part in m_parts.Values) 3903 foreach (SceneObjectPart part in m_parts.Values)
3545 { 3904 {
@@ -3549,6 +3908,7 @@ namespace OpenSim.Region.Framework.Scenes
3549 3908
3550 HasGroupChanged = true; 3909 HasGroupChanged = true;
3551 } 3910 }
3911 lockPartsForRead(false);
3552 3912
3553 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3913 // 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. 3914 // for the same object with very different properties. The caller must schedule the update.
@@ -3570,11 +3930,12 @@ namespace OpenSim.Region.Framework.Scenes
3570 3930
3571 public void SetAttachmentPoint(byte point) 3931 public void SetAttachmentPoint(byte point)
3572 { 3932 {
3573 lock (m_parts) 3933 lockPartsForRead(true);
3574 { 3934 {
3575 foreach (SceneObjectPart part in m_parts.Values) 3935 foreach (SceneObjectPart part in m_parts.Values)
3576 part.SetAttachmentPoint(point); 3936 part.SetAttachmentPoint(point);
3577 } 3937 }
3938 lockPartsForRead(false);
3578 } 3939 }
3579 3940
3580 #region ISceneObject 3941 #region ISceneObject
@@ -3608,6 +3969,14 @@ namespace OpenSim.Region.Framework.Scenes
3608 SetFromItemID(uuid); 3969 SetFromItemID(uuid);
3609 } 3970 }
3610 3971
3972 public void ResetOwnerChangeFlag()
3973 {
3974 ForEachPart(delegate(SceneObjectPart part)
3975 {
3976 part.ResetOwnerChangeFlag();
3977 });
3978 }
3979
3611 #endregion 3980 #endregion
3612 } 3981 }
3613} 3982}