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.cs1062
1 files changed, 733 insertions, 329 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index a2c3c07..3c3f4b7 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 }
@@ -180,8 +317,8 @@ namespace OpenSim.Region.Framework.Scenes
180 private bool m_scriptListens_notAtTarget = false; 317 private bool m_scriptListens_notAtTarget = false;
181 318
182 private bool m_scriptListens_atRotTarget = false; 319 private bool m_scriptListens_atRotTarget = false;
183 private bool m_scriptListens_notAtRotTarget = false; 320 private bool m_scriptListens_notAtRotTarget = false;
184 321 public bool m_dupeInProgress = false;
185 internal Dictionary<UUID, string> m_savedScriptState = null; 322 internal Dictionary<UUID, string> m_savedScriptState = null;
186 323
187 #region Properties 324 #region Properties
@@ -221,7 +358,21 @@ namespace OpenSim.Region.Framework.Scenes
221 public virtual Quaternion Rotation 358 public virtual Quaternion Rotation
222 { 359 {
223 get { return m_rotation; } 360 get { return m_rotation; }
224 set { m_rotation = value; } 361 set {
362 lockPartsForRead(true);
363 try
364 {
365 foreach(SceneObjectPart p in m_parts.Values)
366 {
367 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
368 }
369 }
370 finally
371 {
372 lockPartsForRead(false);
373 }
374 m_rotation = value;
375 }
225 } 376 }
226 377
227 public Quaternion GroupRotation 378 public Quaternion GroupRotation
@@ -258,13 +409,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 409 set
259 { 410 {
260 m_regionHandle = value; 411 m_regionHandle = value;
261 lock (m_parts) 412 lockPartsForRead(true);
262 { 413 {
263 foreach (SceneObjectPart part in m_parts.Values) 414 foreach (SceneObjectPart part in m_parts.Values)
264 { 415 {
416
265 part.RegionHandle = m_regionHandle; 417 part.RegionHandle = m_regionHandle;
418
266 } 419 }
267 } 420 }
421 lockPartsForRead(false);
268 } 422 }
269 } 423 }
270 424
@@ -298,6 +452,12 @@ namespace OpenSim.Region.Framework.Scenes
298 { 452 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 453 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 454 }
455
456 lockPartsForRead(true);
457 foreach (SceneObjectPart part in m_parts.Values)
458 {
459 part.IgnoreUndoUpdate = true;
460 }
301 if (RootPart.GetStatusSandbox()) 461 if (RootPart.GetStatusSandbox())
302 { 462 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 463 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,15 +465,31 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 465 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 466 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 467 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
468 lockPartsForRead(false);
308 return; 469 return;
309 } 470 }
310 } 471 }
311 lock (m_parts) 472 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
473 lockPartsForRead(false);
474 foreach (SceneObjectPart part in parts)
312 { 475 {
313 foreach (SceneObjectPart part in m_parts.Values) 476 part.IgnoreUndoUpdate = false;
314 { 477 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
315 part.GroupPosition = val; 478 part.GroupPosition = val;
479 if (!m_dupeInProgress)
480 {
481 part.TriggerScriptChangedEvent(Changed.POSITION);
316 } 482 }
483 }
484 if (!m_dupeInProgress)
485 {
486 foreach (ScenePresence av in m_linkedAvatars)
487 {
488 Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition;
489 av.AbsolutePosition += offset;
490 av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
491 av.SendFullUpdateToAllClients();
492 }
317 } 493 }
318 494
319 //if (m_rootPart.PhysActor != null) 495 //if (m_rootPart.PhysActor != null)
@@ -457,6 +633,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 633 /// </summary>
458 public SceneObjectGroup() 634 public SceneObjectGroup()
459 { 635 {
636
460 } 637 }
461 638
462 /// <summary> 639 /// <summary>
@@ -473,7 +650,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 650 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 651 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 652 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 653 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 654 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 655 }
479 656
@@ -504,13 +681,16 @@ namespace OpenSim.Region.Framework.Scenes
504 681
505 public void SetFromItemID(UUID AssetId) 682 public void SetFromItemID(UUID AssetId)
506 { 683 {
507 lock (m_parts) 684 lockPartsForRead(true);
508 { 685 {
509 foreach (SceneObjectPart part in m_parts.Values) 686 foreach (SceneObjectPart part in m_parts.Values)
510 { 687 {
688
511 part.FromItemID = AssetId; 689 part.FromItemID = AssetId;
690
512 } 691 }
513 } 692 }
693 lockPartsForRead(false);
514 } 694 }
515 695
516 public UUID GetFromItemID() 696 public UUID GetFromItemID()
@@ -523,6 +703,9 @@ namespace OpenSim.Region.Framework.Scenes
523 /// </summary> 703 /// </summary>
524 public virtual void AttachToBackup() 704 public virtual void AttachToBackup()
525 { 705 {
706 if (IsAttachment) return;
707 m_scene.SceneGraph.FireAttachToBackup(this);
708
526 if (InSceneBackup) 709 if (InSceneBackup)
527 { 710 {
528 //m_log.DebugFormat( 711 //m_log.DebugFormat(
@@ -579,7 +762,7 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 762 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 763 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 764
582 lock (m_parts) 765 lockPartsForRead(true);
583 { 766 {
584 foreach (SceneObjectPart part in m_parts.Values) 767 foreach (SceneObjectPart part in m_parts.Values)
585 { 768 {
@@ -593,8 +776,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 776 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; 777 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; 778 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
779
596 } 780 }
597 } 781 }
782 lockPartsForRead(false);
783
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 784 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 785 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 786 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +796,11 @@ namespace OpenSim.Region.Framework.Scenes
610 796
611 EntityIntersection result = new EntityIntersection(); 797 EntityIntersection result = new EntityIntersection();
612 798
613 lock (m_parts) 799 lockPartsForRead(true);
614 { 800 {
615 foreach (SceneObjectPart part in m_parts.Values) 801 foreach (SceneObjectPart part in m_parts.Values)
616 { 802 {
803
617 // Temporary commented to stop compiler warning 804 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 805 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 806 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +828,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 828 result.distance = inter.distance;
642 } 829 }
643 } 830 }
831
644 } 832 }
645 } 833 }
834 lockPartsForRead(false);
646 return result; 835 return result;
647 } 836 }
648 837
@@ -661,10 +850,11 @@ namespace OpenSim.Region.Framework.Scenes
661 minY = 256f; 850 minY = 256f;
662 minZ = 8192f; 851 minZ = 8192f;
663 852
664 lock(m_parts); 853 lockPartsForRead(true);
665 { 854 {
666 foreach (SceneObjectPart part in m_parts.Values) 855 foreach (SceneObjectPart part in m_parts.Values)
667 { 856 {
857
668 Vector3 worldPos = part.GetWorldPosition(); 858 Vector3 worldPos = part.GetWorldPosition();
669 Vector3 offset = worldPos - AbsolutePosition; 859 Vector3 offset = worldPos - AbsolutePosition;
670 Quaternion worldRot; 860 Quaternion worldRot;
@@ -723,6 +913,8 @@ namespace OpenSim.Region.Framework.Scenes
723 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 913 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
724 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 914 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
725 915
916
917
726 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 918 //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); 919 //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); 920 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -894,6 +1086,7 @@ namespace OpenSim.Region.Framework.Scenes
894 minZ = backBottomLeft.Z; 1086 minZ = backBottomLeft.Z;
895 } 1087 }
896 } 1088 }
1089 lockPartsForRead(false);
897 } 1090 }
898 1091
899 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 1092 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
@@ -929,21 +1122,29 @@ namespace OpenSim.Region.Framework.Scenes
929 1122
930 public void SaveScriptedState(XmlTextWriter writer) 1123 public void SaveScriptedState(XmlTextWriter writer)
931 { 1124 {
1125 SaveScriptedState(writer, false);
1126 }
1127
1128 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1129 {
932 XmlDocument doc = new XmlDocument(); 1130 XmlDocument doc = new XmlDocument();
933 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1131 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
934 1132
935 // Capture script state while holding the lock 1133 // Capture script state while holding the lock
936 lock (m_parts) 1134 lockPartsForRead(true);
937 { 1135 {
938 foreach (SceneObjectPart part in m_parts.Values) 1136 foreach (SceneObjectPart part in m_parts.Values)
939 { 1137 {
940 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1138
1139 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
941 foreach (UUID itemid in pstates.Keys) 1140 foreach (UUID itemid in pstates.Keys)
942 { 1141 {
943 states.Add(itemid, pstates[itemid]); 1142 states.Add(itemid, pstates[itemid]);
944 } 1143 }
1144
945 } 1145 }
946 } 1146 }
1147 lockPartsForRead(false);
947 1148
948 if (states.Count > 0) 1149 if (states.Count > 0)
949 { 1150 {
@@ -962,6 +1163,47 @@ namespace OpenSim.Region.Framework.Scenes
962 } 1163 }
963 1164
964 /// <summary> 1165 /// <summary>
1166 /// Add the avatar to this linkset (avatar is sat).
1167 /// </summary>
1168 /// <param name="agentID"></param>
1169 public void AddAvatar(UUID agentID)
1170 {
1171 ScenePresence presence;
1172 if (m_scene.TryGetScenePresence(agentID, out presence))
1173 {
1174 if (!m_linkedAvatars.Contains(presence))
1175 {
1176 m_linkedAvatars.Add(presence);
1177 }
1178 }
1179 }
1180
1181 /// <summary>
1182 /// Delete the avatar from this linkset (avatar is unsat).
1183 /// </summary>
1184 /// <param name="agentID"></param>
1185 public void DeleteAvatar(UUID agentID)
1186 {
1187 ScenePresence presence;
1188 if (m_scene.TryGetScenePresence(agentID, out presence))
1189 {
1190 if (m_linkedAvatars.Contains(presence))
1191 {
1192 m_linkedAvatars.Remove(presence);
1193 }
1194 }
1195 }
1196
1197 /// <summary>
1198 /// Returns the list of linked presences (avatars sat on this group)
1199 /// </summary>
1200 /// <param name="agentID"></param>
1201 public List<ScenePresence> GetLinkedAvatars()
1202 {
1203 return m_linkedAvatars;
1204 }
1205
1206 /// <summary>
965 /// Attach this scene object to the given avatar. 1207 /// Attach this scene object to the given avatar.
966 /// </summary> 1208 /// </summary>
967 /// <param name="agentID"></param> 1209 /// <param name="agentID"></param>
@@ -1112,13 +1354,16 @@ namespace OpenSim.Region.Framework.Scenes
1112 1354
1113 public override void UpdateMovement() 1355 public override void UpdateMovement()
1114 { 1356 {
1115 lock (m_parts) 1357 lockPartsForRead(true);
1116 { 1358 {
1117 foreach (SceneObjectPart part in m_parts.Values) 1359 foreach (SceneObjectPart part in m_parts.Values)
1118 { 1360 {
1361
1119 part.UpdateMovement(); 1362 part.UpdateMovement();
1363
1120 } 1364 }
1121 } 1365 }
1366 lockPartsForRead(false);
1122 } 1367 }
1123 1368
1124 public ushort GetTimeDilation() 1369 public ushort GetTimeDilation()
@@ -1162,7 +1407,7 @@ namespace OpenSim.Region.Framework.Scenes
1162 /// <param name="part"></param> 1407 /// <param name="part"></param>
1163 public void AddPart(SceneObjectPart part) 1408 public void AddPart(SceneObjectPart part)
1164 { 1409 {
1165 lock (m_parts) 1410 lockPartsForWrite(true);
1166 { 1411 {
1167 part.SetParent(this); 1412 part.SetParent(this);
1168 m_parts.Add(part.UUID, part); 1413 m_parts.Add(part.UUID, part);
@@ -1172,6 +1417,7 @@ namespace OpenSim.Region.Framework.Scenes
1172 if (part.LinkNum == 2 && RootPart != null) 1417 if (part.LinkNum == 2 && RootPart != null)
1173 RootPart.LinkNum = 1; 1418 RootPart.LinkNum = 1;
1174 } 1419 }
1420 lockPartsForWrite(false);
1175 } 1421 }
1176 1422
1177 /// <summary> 1423 /// <summary>
@@ -1179,28 +1425,33 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// </summary> 1425 /// </summary>
1180 private void UpdateParentIDs() 1426 private void UpdateParentIDs()
1181 { 1427 {
1182 lock (m_parts) 1428 lockPartsForRead(true);
1183 { 1429 {
1184 foreach (SceneObjectPart part in m_parts.Values) 1430 foreach (SceneObjectPart part in m_parts.Values)
1185 { 1431 {
1432
1186 if (part.UUID != m_rootPart.UUID) 1433 if (part.UUID != m_rootPart.UUID)
1187 { 1434 {
1188 part.ParentID = m_rootPart.LocalId; 1435 part.ParentID = m_rootPart.LocalId;
1189 } 1436 }
1437
1190 } 1438 }
1191 } 1439 }
1440 lockPartsForRead(false);
1192 } 1441 }
1193 1442
1194 public void RegenerateFullIDs() 1443 public void RegenerateFullIDs()
1195 { 1444 {
1196 lock (m_parts) 1445 lockPartsForRead(true);
1197 { 1446 {
1198 foreach (SceneObjectPart part in m_parts.Values) 1447 foreach (SceneObjectPart part in m_parts.Values)
1199 { 1448 {
1449
1200 part.UUID = UUID.Random(); 1450 part.UUID = UUID.Random();
1201 1451
1202 } 1452 }
1203 } 1453 }
1454 lockPartsForRead(false);
1204 } 1455 }
1205 1456
1206 // helper provided for parts. 1457 // helper provided for parts.
@@ -1261,7 +1512,7 @@ namespace OpenSim.Region.Framework.Scenes
1261 1512
1262 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1513 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1263 { 1514 {
1264 part.StoreUndoState(); 1515 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1265 part.OnGrab(offsetPos, remoteClient); 1516 part.OnGrab(offsetPos, remoteClient);
1266 } 1517 }
1267 1518
@@ -1281,27 +1532,32 @@ namespace OpenSim.Region.Framework.Scenes
1281 1532
1282 DetachFromBackup(); 1533 DetachFromBackup();
1283 1534
1284 lock (m_parts) 1535 lockPartsForRead(true);
1536 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1537 lockPartsForRead(false);
1538
1539 foreach (SceneObjectPart part in values)
1285 { 1540 {
1286 foreach (SceneObjectPart part in m_parts.Values)
1287 {
1288// part.Inventory.RemoveScriptInstances(); 1541// part.Inventory.RemoveScriptInstances();
1289 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1542
1543 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1544 {
1545 if (sp.ParentID == LocalId)
1290 { 1546 {
1291 if (avatar.ParentID == LocalId) 1547 sp.StandUp();
1292 { 1548 }
1293 avatar.StandUp();
1294 }
1295 1549
1296 if (!silent) 1550 if (!silent)
1297 { 1551 {
1298 part.UpdateFlag = 0; 1552 part.UpdateFlag = 0;
1299 if (part == m_rootPart) 1553 if (part == m_rootPart)
1300 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1554 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1301 } 1555 }
1302 }); 1556 });
1303 } 1557
1304 } 1558 }
1559
1560
1305 } 1561 }
1306 1562
1307 public void AddScriptLPS(int count) 1563 public void AddScriptLPS(int count)
@@ -1326,17 +1582,20 @@ namespace OpenSim.Region.Framework.Scenes
1326 1582
1327 scriptEvents aggregateScriptEvents=0; 1583 scriptEvents aggregateScriptEvents=0;
1328 1584
1329 lock (m_parts) 1585 lockPartsForRead(true);
1330 { 1586 {
1331 foreach (SceneObjectPart part in m_parts.Values) 1587 foreach (SceneObjectPart part in m_parts.Values)
1332 { 1588 {
1589
1333 if (part == null) 1590 if (part == null)
1334 continue; 1591 continue;
1335 if (part != RootPart) 1592 if (part != RootPart)
1336 part.ObjectFlags = objectflagupdate; 1593 part.ObjectFlags = objectflagupdate;
1337 aggregateScriptEvents |= part.AggregateScriptEvents; 1594 aggregateScriptEvents |= part.AggregateScriptEvents;
1595
1338 } 1596 }
1339 } 1597 }
1598 lockPartsForRead(false);
1340 1599
1341 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1600 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1342 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1601 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1378,42 +1637,52 @@ namespace OpenSim.Region.Framework.Scenes
1378 /// <param name="m_physicalPrim"></param> 1637 /// <param name="m_physicalPrim"></param>
1379 public void ApplyPhysics(bool m_physicalPrim) 1638 public void ApplyPhysics(bool m_physicalPrim)
1380 { 1639 {
1381 lock (m_parts) 1640 lockPartsForRead(true);
1641
1642 if (m_parts.Count > 1)
1382 { 1643 {
1383 if (m_parts.Count > 1) 1644 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1645 lockPartsForRead(false);
1646 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1647 foreach (SceneObjectPart part in values)
1384 { 1648 {
1385 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1649
1386 foreach (SceneObjectPart part in m_parts.Values) 1650 if (part.LocalId != m_rootPart.LocalId)
1387 { 1651 {
1388 if (part.LocalId != m_rootPart.LocalId) 1652 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1389 {
1390 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1391 }
1392 } 1653 }
1393 1654
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 } 1655 }
1656 // Hack to get the physics scene geometries in the right spot
1657 ResetChildPrimPhysicsPositions();
1658 }
1659 else
1660 {
1661 lockPartsForRead(false);
1662 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1401 } 1663 }
1402 } 1664 }
1403 1665
1404 public void SetOwnerId(UUID userId) 1666 public void SetOwnerId(UUID userId)
1405 { 1667 {
1406 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1668 ForEachPart(delegate(SceneObjectPart part)
1669 {
1670
1671 part.OwnerID = userId;
1672
1673 });
1407 } 1674 }
1408 1675
1409 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1676 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1410 { 1677 {
1411 lock (m_parts) 1678 lockPartsForRead(true);
1679 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1680 lockPartsForRead(false);
1681 foreach (SceneObjectPart part in values)
1412 { 1682 {
1413 foreach (SceneObjectPart part in m_parts.Values) 1683
1414 { 1684 whatToDo(part);
1415 whatToDo(part); 1685
1416 }
1417 } 1686 }
1418 } 1687 }
1419 1688
@@ -1436,7 +1705,10 @@ namespace OpenSim.Region.Framework.Scenes
1436 1705
1437 try 1706 try
1438 { 1707 {
1439 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1708 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1709 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1710 m_scene.LoadingPrims) // Land may not be valid yet
1711
1440 { 1712 {
1441 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1713 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1442 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1714 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1468,9 +1740,9 @@ namespace OpenSim.Region.Framework.Scenes
1468 // don't backup while it's selected or you're asking for changes mid stream. 1740 // don't backup while it's selected or you're asking for changes mid stream.
1469 if ((isTimeToPersist()) || (forcedBackup)) 1741 if ((isTimeToPersist()) || (forcedBackup))
1470 { 1742 {
1471 m_log.DebugFormat( 1743 // m_log.DebugFormat(
1472 "[SCENE]: Storing {0}, {1} in {2}", 1744 // "[SCENE]: Storing {0}, {1} in {2}",
1473 Name, UUID, m_scene.RegionInfo.RegionName); 1745 // Name, UUID, m_scene.RegionInfo.RegionName);
1474 1746
1475 SceneObjectGroup backup_group = Copy(false); 1747 SceneObjectGroup backup_group = Copy(false);
1476 backup_group.RootPart.Velocity = RootPart.Velocity; 1748 backup_group.RootPart.Velocity = RootPart.Velocity;
@@ -1512,15 +1784,17 @@ namespace OpenSim.Region.Framework.Scenes
1512 RootPart.SendFullUpdate( 1784 RootPart.SendFullUpdate(
1513 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1785 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1514 1786
1515 lock (m_parts) 1787 lockPartsForRead(true);
1516 { 1788 {
1517 foreach (SceneObjectPart part in m_parts.Values) 1789 foreach (SceneObjectPart part in m_parts.Values)
1518 { 1790 {
1791
1519 if (part != RootPart) 1792 if (part != RootPart)
1520 part.SendFullUpdate( 1793 part.SendFullUpdate(
1521 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1794 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1522 } 1795 }
1523 } 1796 }
1797 lockPartsForRead(false);
1524 } 1798 }
1525 1799
1526 #region Copying 1800 #region Copying
@@ -1531,87 +1805,96 @@ namespace OpenSim.Region.Framework.Scenes
1531 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> 1805 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
1532 /// <returns></returns> 1806 /// <returns></returns>
1533 public SceneObjectGroup Copy(bool userExposed) 1807 public SceneObjectGroup Copy(bool userExposed)
1534 { 1808 {
1535 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1809 SceneObjectGroup dupe;
1536 dupe.m_isBackedUp = false; 1810 try
1537 dupe.m_parts = new Dictionary<UUID, SceneObjectPart>(); 1811 {
1538 1812 m_dupeInProgress = true;
1539 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1813 dupe = (SceneObjectGroup)MemberwiseClone();
1540 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1814 dupe.m_isBackedUp = false;
1541 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 1815 dupe.m_parts = new Dictionary<UUID, SceneObjectPart>();
1542 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state 1816
1543 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, 1817 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1544 // then restore it's attachment state 1818 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1545 1819 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
1546 // This is only necessary when userExposed is false! 1820 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1547 1821 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1548 bool previousAttachmentStatus = dupe.RootPart.IsAttachment; 1822 // then restore it's attachment state
1549 1823
1550 if (!userExposed) 1824 // This is only necessary when userExposed is false!
1551 dupe.RootPart.IsAttachment = true; 1825
1552 1826 bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
1553 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1827
1554 1828 if (!userExposed)
1555 if (!userExposed) 1829 dupe.RootPart.IsAttachment = true;
1556 { 1830
1557 dupe.RootPart.IsAttachment = previousAttachmentStatus; 1831 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1558 } 1832
1559 1833 if (!userExposed)
1560 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1834 {
1561 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 1835 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1562 1836 }
1563 if (userExposed) 1837
1564 dupe.m_rootPart.TrimPermissions(); 1838 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1565 1839 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1566 /// may need to create a new Physics actor. 1840
1567 if (dupe.RootPart.PhysActor != null && userExposed) 1841 if (userExposed)
1568 { 1842 dupe.m_rootPart.TrimPermissions();
1569 PrimitiveBaseShape pbs = dupe.RootPart.Shape; 1843
1570 1844 /// may need to create a new Physics actor.
1571 dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( 1845 if (dupe.RootPart.PhysActor != null && userExposed)
1572 dupe.RootPart.Name, 1846 {
1573 pbs, 1847 PrimitiveBaseShape pbs = dupe.RootPart.Shape;
1574 dupe.RootPart.AbsolutePosition, 1848
1575 dupe.RootPart.Scale, 1849 dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape(
1576 dupe.RootPart.RotationOffset, 1850 dupe.RootPart.Name,
1577 dupe.RootPart.PhysActor.IsPhysical); 1851 pbs,
1578 1852 dupe.RootPart.AbsolutePosition,
1579 dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; 1853 dupe.RootPart.Scale,
1580 dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); 1854 dupe.RootPart.RotationOffset,
1581 } 1855 dupe.RootPart.PhysActor.IsPhysical);
1582 1856
1583 List<SceneObjectPart> partList; 1857 dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId;
1584 1858 dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true);
1585 lock (m_parts) 1859 }
1586 { 1860
1587 partList = new List<SceneObjectPart>(m_parts.Values); 1861 List<SceneObjectPart> partList;
1588 } 1862
1589 1863 lockPartsForRead(true);
1590 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1864
1591 { 1865 partList = new List<SceneObjectPart>(m_parts.Values);
1592 return p1.LinkNum.CompareTo(p2.LinkNum); 1866
1593 } 1867 lockPartsForRead(false);
1594 ); 1868
1595 1869 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1596 foreach (SceneObjectPart part in partList) 1870 {
1597 { 1871 return p1.LinkNum.CompareTo(p2.LinkNum);
1598 if (part.UUID != m_rootPart.UUID) 1872 }
1599 { 1873 );
1600 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 1874
1601 1875 foreach (SceneObjectPart part in partList)
1602 newPart.LinkNum = part.LinkNum; 1876 {
1603 } 1877 if (part.UUID != m_rootPart.UUID)
1604 } 1878 {
1605 1879 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1606 if (userExposed) 1880
1607 { 1881 newPart.LinkNum = part.LinkNum;
1608 dupe.UpdateParentIDs(); 1882 }
1609 dupe.HasGroupChanged = true; 1883 }
1610 dupe.AttachToBackup(); 1884
1611 1885 if (userExposed)
1612 ScheduleGroupForFullUpdate(); 1886 {
1887 dupe.UpdateParentIDs();
1888 dupe.HasGroupChanged = true;
1889 dupe.AttachToBackup();
1890
1891 ScheduleGroupForFullUpdate();
1892 }
1893 }
1894 finally
1895 {
1896 m_dupeInProgress = false;
1613 } 1897 }
1614
1615 return dupe; 1898 return dupe;
1616 } 1899 }
1617 1900
@@ -1802,13 +2085,40 @@ namespace OpenSim.Region.Framework.Scenes
1802 } 2085 }
1803 } 2086 }
1804 2087
2088 public void rotLookAt(Quaternion target, float strength, float damping)
2089 {
2090 SceneObjectPart rootpart = m_rootPart;
2091 if (rootpart != null)
2092 {
2093 if (IsAttachment)
2094 {
2095 /*
2096 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2097 if (avatar != null)
2098 {
2099 Rotate the Av?
2100 } */
2101 }
2102 else
2103 {
2104 if (rootpart.PhysActor != null)
2105 { // APID must be implemented in your physics system for this to function.
2106 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2107 rootpart.PhysActor.APIDStrength = strength;
2108 rootpart.PhysActor.APIDDamping = damping;
2109 rootpart.PhysActor.APIDActive = true;
2110 }
2111 }
2112 }
2113 }
2114
1805 public void stopLookAt() 2115 public void stopLookAt()
1806 { 2116 {
1807 SceneObjectPart rootpart = m_rootPart; 2117 SceneObjectPart rootpart = m_rootPart;
1808 if (rootpart != null) 2118 if (rootpart != null)
1809 { 2119 {
1810 if (rootpart.PhysActor != null) 2120 if (rootpart.PhysActor != null)
1811 { 2121 { // APID must be implemented in your physics system for this to function.
1812 rootpart.PhysActor.APIDActive = false; 2122 rootpart.PhysActor.APIDActive = false;
1813 } 2123 }
1814 } 2124 }
@@ -1876,10 +2186,11 @@ namespace OpenSim.Region.Framework.Scenes
1876 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2186 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1877 newPart.SetParent(this); 2187 newPart.SetParent(this);
1878 2188
1879 lock (m_parts) 2189 lockPartsForWrite(true);
1880 { 2190 {
1881 m_parts.Add(newPart.UUID, newPart); 2191 m_parts.Add(newPart.UUID, newPart);
1882 } 2192 }
2193 lockPartsForWrite(false);
1883 2194
1884 SetPartAsNonRoot(newPart); 2195 SetPartAsNonRoot(newPart);
1885 2196
@@ -1942,7 +2253,7 @@ namespace OpenSim.Region.Framework.Scenes
1942 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2253 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1943 // return; 2254 // return;
1944 2255
1945 lock (m_parts) 2256 lockPartsForRead(true);
1946 { 2257 {
1947 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2258 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1948 2259
@@ -1962,9 +2273,12 @@ namespace OpenSim.Region.Framework.Scenes
1962 { 2273 {
1963 if (!IsSelected) 2274 if (!IsSelected)
1964 part.UpdateLookAt(); 2275 part.UpdateLookAt();
2276
1965 part.SendScheduledUpdates(); 2277 part.SendScheduledUpdates();
2278
1966 } 2279 }
1967 } 2280 }
2281 lockPartsForRead(false);
1968 } 2282 }
1969 2283
1970 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2284 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1973,27 +2287,29 @@ namespace OpenSim.Region.Framework.Scenes
1973 2287
1974 RootPart.AddFullUpdateToAvatar(presence); 2288 RootPart.AddFullUpdateToAvatar(presence);
1975 2289
1976 lock (m_parts) 2290 lockPartsForRead(true);
1977 { 2291 {
1978 foreach (SceneObjectPart part in m_parts.Values) 2292 foreach (SceneObjectPart part in m_parts.Values)
1979 { 2293 {
2294
1980 if (part != RootPart) 2295 if (part != RootPart)
1981 part.AddFullUpdateToAvatar(presence); 2296 part.AddFullUpdateToAvatar(presence);
2297
1982 } 2298 }
1983 } 2299 }
2300 lockPartsForRead(false);
1984 } 2301 }
1985 2302
1986 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2303 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1987 { 2304 {
1988// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2305 lockPartsForRead(true);
1989 2306
1990 lock (m_parts) 2307 foreach (SceneObjectPart part in m_parts.Values)
1991 { 2308 {
1992 foreach (SceneObjectPart part in m_parts.Values) 2309 part.AddTerseUpdateToAvatar(presence);
1993 {
1994 part.AddTerseUpdateToAvatar(presence);
1995 }
1996 } 2310 }
2311
2312 lockPartsForRead(false);
1997 } 2313 }
1998 2314
1999 /// <summary> 2315 /// <summary>
@@ -2007,14 +2323,17 @@ namespace OpenSim.Region.Framework.Scenes
2007 checkAtTargets(); 2323 checkAtTargets();
2008 RootPart.ScheduleFullUpdate(); 2324 RootPart.ScheduleFullUpdate();
2009 2325
2010 lock (m_parts) 2326 lockPartsForRead(true);
2011 { 2327 {
2012 foreach (SceneObjectPart part in m_parts.Values) 2328 foreach (SceneObjectPart part in m_parts.Values)
2013 { 2329 {
2330
2014 if (part != RootPart) 2331 if (part != RootPart)
2015 part.ScheduleFullUpdate(); 2332 part.ScheduleFullUpdate();
2333
2016 } 2334 }
2017 } 2335 }
2336 lockPartsForRead(false);
2018 } 2337 }
2019 2338
2020 /// <summary> 2339 /// <summary>
@@ -2022,37 +2341,38 @@ namespace OpenSim.Region.Framework.Scenes
2022 /// </summary> 2341 /// </summary>
2023 public void ScheduleGroupForTerseUpdate() 2342 public void ScheduleGroupForTerseUpdate()
2024 { 2343 {
2025// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2344 lockPartsForRead(true);
2026 2345 foreach (SceneObjectPart part in m_parts.Values)
2027 lock (m_parts)
2028 { 2346 {
2029 foreach (SceneObjectPart part in m_parts.Values) 2347 part.ScheduleTerseUpdate();
2030 {
2031 part.ScheduleTerseUpdate();
2032 }
2033 } 2348 }
2349
2350 lockPartsForRead(false);
2034 } 2351 }
2035 2352
2036 /// <summary> 2353 /// <summary>
2037 /// Immediately send a full update for this scene object. 2354 /// Immediately send a full update for this scene object.
2038 /// </summary> 2355 /// </summary>
2039 public void SendGroupFullUpdate() 2356 public void SendGroupFullUpdate()
2040 { 2357 {
2041 if (IsDeleted) 2358 if (IsDeleted)
2042 return; 2359 return;
2043 2360
2044// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2361// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2045 2362
2046 RootPart.SendFullUpdateToAllClients(); 2363 RootPart.SendFullUpdateToAllClients();
2047 2364
2048 lock (m_parts) 2365 lockPartsForRead(true);
2049 { 2366 {
2050 foreach (SceneObjectPart part in m_parts.Values) 2367 foreach (SceneObjectPart part in m_parts.Values)
2051 { 2368 {
2369
2052 if (part != RootPart) 2370 if (part != RootPart)
2053 part.SendFullUpdateToAllClients(); 2371 part.SendFullUpdateToAllClients();
2372
2054 } 2373 }
2055 } 2374 }
2375 lockPartsForRead(false);
2056 } 2376 }
2057 2377
2058 /// <summary> 2378 /// <summary>
@@ -2084,14 +2404,15 @@ namespace OpenSim.Region.Framework.Scenes
2084 { 2404 {
2085 if (IsDeleted) 2405 if (IsDeleted)
2086 return; 2406 return;
2087 2407
2088 lock (m_parts) 2408 lockPartsForRead(true);
2089 { 2409 {
2090 foreach (SceneObjectPart part in m_parts.Values) 2410 foreach (SceneObjectPart part in m_parts.Values)
2091 { 2411 {
2092 part.SendTerseUpdateToAllClients(); 2412 part.SendTerseUpdateToAllClients();
2093 } 2413 }
2094 } 2414 }
2415 lockPartsForRead(false);
2095 } 2416 }
2096 2417
2097 #endregion 2418 #endregion
@@ -2105,16 +2426,18 @@ namespace OpenSim.Region.Framework.Scenes
2105 /// <returns>null if no child part with that linknum or child part</returns> 2426 /// <returns>null if no child part with that linknum or child part</returns>
2106 public SceneObjectPart GetLinkNumPart(int linknum) 2427 public SceneObjectPart GetLinkNumPart(int linknum)
2107 { 2428 {
2108 lock (m_parts) 2429 lockPartsForRead(true);
2109 { 2430 {
2110 foreach (SceneObjectPart part in m_parts.Values) 2431 foreach (SceneObjectPart part in m_parts.Values)
2111 { 2432 {
2112 if (part.LinkNum == linknum) 2433 if (part.LinkNum == linknum)
2113 { 2434 {
2435 lockPartsForRead(false);
2114 return part; 2436 return part;
2115 } 2437 }
2116 } 2438 }
2117 } 2439 }
2440 lockPartsForRead(false);
2118 2441
2119 return null; 2442 return null;
2120 } 2443 }
@@ -2142,17 +2465,19 @@ namespace OpenSim.Region.Framework.Scenes
2142 public SceneObjectPart GetChildPart(uint localID) 2465 public SceneObjectPart GetChildPart(uint localID)
2143 { 2466 {
2144 //m_log.DebugFormat("Entered looking for {0}", localID); 2467 //m_log.DebugFormat("Entered looking for {0}", localID);
2145 lock (m_parts) 2468 lockPartsForRead(true);
2146 { 2469 {
2147 foreach (SceneObjectPart part in m_parts.Values) 2470 foreach (SceneObjectPart part in m_parts.Values)
2148 { 2471 {
2149 //m_log.DebugFormat("Found {0}", part.LocalId); 2472 //m_log.DebugFormat("Found {0}", part.LocalId);
2150 if (part.LocalId == localID) 2473 if (part.LocalId == localID)
2151 { 2474 {
2475 lockPartsForRead(false);
2152 return part; 2476 return part;
2153 } 2477 }
2154 } 2478 }
2155 } 2479 }
2480 lockPartsForRead(false);
2156 2481
2157 return null; 2482 return null;
2158 } 2483 }
@@ -2182,17 +2507,19 @@ namespace OpenSim.Region.Framework.Scenes
2182 public bool HasChildPrim(uint localID) 2507 public bool HasChildPrim(uint localID)
2183 { 2508 {
2184 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2509 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2185 lock (m_parts) 2510 lockPartsForRead(true);
2186 { 2511 {
2187 foreach (SceneObjectPart part in m_parts.Values) 2512 foreach (SceneObjectPart part in m_parts.Values)
2188 { 2513 {
2189 //m_log.DebugFormat("Found {0}", part.LocalId); 2514 //m_log.DebugFormat("Found {0}", part.LocalId);
2190 if (part.LocalId == localID) 2515 if (part.LocalId == localID)
2191 { 2516 {
2517 lockPartsForRead(false);
2192 return true; 2518 return true;
2193 } 2519 }
2194 } 2520 }
2195 } 2521 }
2522 lockPartsForRead(false);
2196 2523
2197 return false; 2524 return false;
2198 } 2525 }
@@ -2242,53 +2569,57 @@ namespace OpenSim.Region.Framework.Scenes
2242 if (m_rootPart.LinkNum == 0) 2569 if (m_rootPart.LinkNum == 0)
2243 m_rootPart.LinkNum = 1; 2570 m_rootPart.LinkNum = 1;
2244 2571
2245 lock (m_parts) 2572 lockPartsForWrite(true);
2246 { 2573
2247 m_parts.Add(linkPart.UUID, linkPart); 2574 m_parts.Add(linkPart.UUID, linkPart);
2575
2576 lockPartsForWrite(false);
2248 2577
2249 // Insert in terms of link numbers, the new links 2578 // Insert in terms of link numbers, the new links
2250 // before the current ones (with the exception of 2579 // before the current ones (with the exception of
2251 // the root prim. Shuffle the old ones up 2580 // the root prim. Shuffle the old ones up
2252 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2581 lockPartsForRead(true);
2582 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2583 {
2584 if (kvp.Value.LinkNum != 1)
2253 { 2585 {
2254 if (kvp.Value.LinkNum != 1) 2586 // Don't update root prim link number
2255 { 2587 kvp.Value.LinkNum += objectGroup.PrimCount;
2256 // Don't update root prim link number
2257 kvp.Value.LinkNum += objectGroup.PrimCount;
2258 }
2259 } 2588 }
2589 }
2590 lockPartsForRead(false);
2260 2591
2261 linkPart.LinkNum = 2; 2592 linkPart.LinkNum = 2;
2262 2593
2263 linkPart.SetParent(this); 2594 linkPart.SetParent(this);
2264 linkPart.CreateSelected = true; 2595 linkPart.CreateSelected = true;
2265 2596
2266 //if (linkPart.PhysActor != null) 2597 //if (linkPart.PhysActor != null)
2267 //{ 2598 //{
2268 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2599 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2269 2600
2270 //linkPart.PhysActor = null; 2601 //linkPart.PhysActor = null;
2271 //} 2602 //}
2272 2603
2273 //TODO: rest of parts 2604 //TODO: rest of parts
2274 int linkNum = 3; 2605 int linkNum = 3;
2275 foreach (SceneObjectPart part in objectGroup.Children.Values) 2606 foreach (SceneObjectPart part in objectGroup.Children.Values)
2607 {
2608 if (part.UUID != objectGroup.m_rootPart.UUID)
2276 { 2609 {
2277 if (part.UUID != objectGroup.m_rootPart.UUID) 2610 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2278 {
2279 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2280 }
2281 part.ClearUndoState();
2282 } 2611 }
2612 part.ClearUndoState();
2283 } 2613 }
2284 2614
2285 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2615 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2286 objectGroup.m_isDeleted = true; 2616 objectGroup.m_isDeleted = true;
2617
2618 objectGroup.lockPartsForWrite(true);
2287 2619
2288 lock (objectGroup.m_parts) 2620 objectGroup.m_parts.Clear();
2289 { 2621
2290 objectGroup.m_parts.Clear(); 2622 objectGroup.lockPartsForWrite(false);
2291 }
2292 2623
2293 // Can't do this yet since backup still makes use of the root part without any synchronization 2624 // Can't do this yet since backup still makes use of the root part without any synchronization
2294// objectGroup.m_rootPart = null; 2625// objectGroup.m_rootPart = null;
@@ -2358,11 +2689,12 @@ namespace OpenSim.Region.Framework.Scenes
2358 Quaternion worldRot = linkPart.GetWorldRotation(); 2689 Quaternion worldRot = linkPart.GetWorldRotation();
2359 2690
2360 // Remove the part from this object 2691 // Remove the part from this object
2361 lock (m_parts) 2692 lockPartsForWrite(true);
2362 { 2693 {
2363 m_parts.Remove(linkPart.UUID); 2694 m_parts.Remove(linkPart.UUID);
2364 } 2695 }
2365 2696 lockPartsForWrite(false);
2697 lockPartsForRead(true);
2366 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2698 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2367 RootPart.LinkNum = 0; 2699 RootPart.LinkNum = 0;
2368 else 2700 else
@@ -2373,6 +2705,7 @@ namespace OpenSim.Region.Framework.Scenes
2373 p.LinkNum--; 2705 p.LinkNum--;
2374 } 2706 }
2375 } 2707 }
2708 lockPartsForRead(false);
2376 2709
2377 linkPart.ParentID = 0; 2710 linkPart.ParentID = 0;
2378 linkPart.LinkNum = 0; 2711 linkPart.LinkNum = 0;
@@ -2416,6 +2749,8 @@ namespace OpenSim.Region.Framework.Scenes
2416 /// <param name="objectGroup"></param> 2749 /// <param name="objectGroup"></param>
2417 public virtual void DetachFromBackup() 2750 public virtual void DetachFromBackup()
2418 { 2751 {
2752 m_scene.SceneGraph.FireDetachFromBackup(this);
2753
2419 if (m_isBackedUp) 2754 if (m_isBackedUp)
2420 m_scene.EventManager.OnBackup -= ProcessBackup; 2755 m_scene.EventManager.OnBackup -= ProcessBackup;
2421 2756
@@ -2694,9 +3029,12 @@ namespace OpenSim.Region.Framework.Scenes
2694 3029
2695 if (selectionPart != null) 3030 if (selectionPart != null)
2696 { 3031 {
2697 lock (m_parts) 3032 lockPartsForRead(true);
3033 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
3034 lockPartsForRead(false);
3035 foreach (SceneObjectPart part in parts)
2698 { 3036 {
2699 foreach (SceneObjectPart part in m_parts.Values) 3037 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2700 { 3038 {
2701 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 3039 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2702 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 3040 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2706,12 +3044,13 @@ namespace OpenSim.Region.Framework.Scenes
2706 break; 3044 break;
2707 } 3045 }
2708 } 3046 }
3047 }
2709 3048
2710 foreach (SceneObjectPart part in m_parts.Values) 3049 foreach (SceneObjectPart part in parts)
2711 { 3050 {
2712 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3051 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2713 }
2714 } 3052 }
3053
2715 } 3054 }
2716 } 3055 }
2717 3056
@@ -2724,6 +3063,17 @@ namespace OpenSim.Region.Framework.Scenes
2724 } 3063 }
2725 } 3064 }
2726 3065
3066
3067
3068 /// <summary>
3069 /// Gets the number of parts
3070 /// </summary>
3071 /// <returns></returns>
3072 public int GetPartCount()
3073 {
3074 return Children.Count;
3075 }
3076
2727 /// <summary> 3077 /// <summary>
2728 /// Get the parts of this scene object 3078 /// Get the parts of this scene object
2729 /// </summary> 3079 /// </summary>
@@ -2797,11 +3147,9 @@ namespace OpenSim.Region.Framework.Scenes
2797 scale.Y = m_scene.m_maxNonphys; 3147 scale.Y = m_scene.m_maxNonphys;
2798 if (scale.Z > m_scene.m_maxNonphys) 3148 if (scale.Z > m_scene.m_maxNonphys)
2799 scale.Z = m_scene.m_maxNonphys; 3149 scale.Z = m_scene.m_maxNonphys;
2800
2801 SceneObjectPart part = GetChildPart(localID); 3150 SceneObjectPart part = GetChildPart(localID);
2802 if (part != null) 3151 if (part != null)
2803 { 3152 {
2804 part.Resize(scale);
2805 if (part.PhysActor != null) 3153 if (part.PhysActor != null)
2806 { 3154 {
2807 if (part.PhysActor.IsPhysical) 3155 if (part.PhysActor.IsPhysical)
@@ -2816,7 +3164,7 @@ namespace OpenSim.Region.Framework.Scenes
2816 part.PhysActor.Size = scale; 3164 part.PhysActor.Size = scale;
2817 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3165 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2818 } 3166 }
2819 //if (part.UUID != m_rootPart.UUID) 3167 part.Resize(scale);
2820 3168
2821 HasGroupChanged = true; 3169 HasGroupChanged = true;
2822 ScheduleGroupForFullUpdate(); 3170 ScheduleGroupForFullUpdate();
@@ -2838,7 +3186,6 @@ namespace OpenSim.Region.Framework.Scenes
2838 SceneObjectPart part = GetChildPart(localID); 3186 SceneObjectPart part = GetChildPart(localID);
2839 if (part != null) 3187 if (part != null)
2840 { 3188 {
2841 part.IgnoreUndoUpdate = true;
2842 if (scale.X > m_scene.m_maxNonphys) 3189 if (scale.X > m_scene.m_maxNonphys)
2843 scale.X = m_scene.m_maxNonphys; 3190 scale.X = m_scene.m_maxNonphys;
2844 if (scale.Y > m_scene.m_maxNonphys) 3191 if (scale.Y > m_scene.m_maxNonphys)
@@ -2858,94 +3205,100 @@ namespace OpenSim.Region.Framework.Scenes
2858 float y = (scale.Y / part.Scale.Y); 3205 float y = (scale.Y / part.Scale.Y);
2859 float z = (scale.Z / part.Scale.Z); 3206 float z = (scale.Z / part.Scale.Z);
2860 3207
2861 lock (m_parts) 3208 lockPartsForRead(true);
3209 if (x > 1.0f || y > 1.0f || z > 1.0f)
2862 { 3210 {
2863 if (x > 1.0f || y > 1.0f || z > 1.0f) 3211 foreach (SceneObjectPart obPart in m_parts.Values)
2864 { 3212 {
2865 foreach (SceneObjectPart obPart in m_parts.Values) 3213 if (obPart.UUID != m_rootPart.UUID)
2866 { 3214 {
2867 if (obPart.UUID != m_rootPart.UUID) 3215 Vector3 oldSize = new Vector3(obPart.Scale);
2868 { 3216 obPart.IgnoreUndoUpdate = true;
2869 obPart.IgnoreUndoUpdate = true;
2870 Vector3 oldSize = new Vector3(obPart.Scale);
2871 3217
2872 float f = 1.0f; 3218 float f = 1.0f;
2873 float a = 1.0f; 3219 float a = 1.0f;
2874 3220
2875 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3221 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3222 {
3223 if (oldSize.X*x > m_scene.m_maxPhys)
2876 { 3224 {
2877 if (oldSize.X*x > m_scene.m_maxPhys) 3225 f = m_scene.m_maxPhys / oldSize.X;
2878 { 3226 a = f / x;
2879 f = m_scene.m_maxPhys / oldSize.X; 3227 x *= a;
2880 a = f / x; 3228 y *= a;
2881 x *= a; 3229 z *= a;
2882 y *= a;
2883 z *= a;
2884 }
2885 if (oldSize.Y*y > m_scene.m_maxPhys)
2886 {
2887 f = m_scene.m_maxPhys / oldSize.Y;
2888 a = f / y;
2889 x *= a;
2890 y *= a;
2891 z *= a;
2892 }
2893 if (oldSize.Z*z > m_scene.m_maxPhys)
2894 {
2895 f = m_scene.m_maxPhys / oldSize.Z;
2896 a = f / z;
2897 x *= a;
2898 y *= a;
2899 z *= a;
2900 }
2901 } 3230 }
2902 else 3231 if (oldSize.Y*y > m_scene.m_maxPhys)
3232 {
3233 f = m_scene.m_maxPhys / oldSize.Y;
3234 a = f / y;
3235 x *= a;
3236 y *= a;
3237 z *= a;
3238 }
3239 if (oldSize.Z*z > m_scene.m_maxPhys)
3240 {
3241 f = m_scene.m_maxPhys / oldSize.Z;
3242 a = f / z;
3243 x *= a;
3244 y *= a;
3245 z *= a;
3246 }
3247 }
3248 else
3249 {
3250 if (oldSize.X*x > m_scene.m_maxNonphys)
3251 {
3252 f = m_scene.m_maxNonphys / oldSize.X;
3253 a = f / x;
3254 x *= a;
3255 y *= a;
3256 z *= a;
3257 }
3258 if (oldSize.Y*y > m_scene.m_maxNonphys)
3259 {
3260 f = m_scene.m_maxNonphys / oldSize.Y;
3261 a = f / y;
3262 x *= a;
3263 y *= a;
3264 z *= a;
3265 }
3266 if (oldSize.Z*z > m_scene.m_maxNonphys)
2903 { 3267 {
2904 if (oldSize.X*x > m_scene.m_maxNonphys) 3268 f = m_scene.m_maxNonphys / oldSize.Z;
2905 { 3269 a = f / z;
2906 f = m_scene.m_maxNonphys / oldSize.X; 3270 x *= a;
2907 a = f / x; 3271 y *= a;
2908 x *= a; 3272 z *= a;
2909 y *= a;
2910 z *= a;
2911 }
2912 if (oldSize.Y*y > m_scene.m_maxNonphys)
2913 {
2914 f = m_scene.m_maxNonphys / oldSize.Y;
2915 a = f / y;
2916 x *= a;
2917 y *= a;
2918 z *= a;
2919 }
2920 if (oldSize.Z*z > m_scene.m_maxNonphys)
2921 {
2922 f = m_scene.m_maxNonphys / oldSize.Z;
2923 a = f / z;
2924 x *= a;
2925 y *= a;
2926 z *= a;
2927 }
2928 } 3273 }
2929 obPart.IgnoreUndoUpdate = false; 3274
2930 obPart.StoreUndoState();
2931 } 3275 }
2932 } 3276 }
2933 } 3277 }
2934 } 3278 }
3279 lockPartsForRead(false);
2935 3280
2936 Vector3 prevScale = part.Scale; 3281 Vector3 prevScale = part.Scale;
2937 prevScale.X *= x; 3282 prevScale.X *= x;
2938 prevScale.Y *= y; 3283 prevScale.Y *= y;
2939 prevScale.Z *= z; 3284 prevScale.Z *= z;;
3285
3286 part.IgnoreUndoUpdate = false;
3287 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3288 part.IgnoreUndoUpdate = true;
2940 part.Resize(prevScale); 3289 part.Resize(prevScale);
3290 part.IgnoreUndoUpdate = false;
2941 3291
2942 lock (m_parts) 3292 lockPartsForRead(true);
2943 { 3293 {
2944 foreach (SceneObjectPart obPart in m_parts.Values) 3294 foreach (SceneObjectPart obPart in m_parts.Values)
2945 { 3295 {
2946 obPart.IgnoreUndoUpdate = true;
2947 if (obPart.UUID != m_rootPart.UUID) 3296 if (obPart.UUID != m_rootPart.UUID)
2948 { 3297 {
3298 obPart.IgnoreUndoUpdate = false;
3299 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3300 obPart.IgnoreUndoUpdate = true;
3301
2949 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3302 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2950 currentpos.X *= x; 3303 currentpos.X *= x;
2951 currentpos.Y *= y; 3304 currentpos.Y *= y;
@@ -2958,9 +3311,9 @@ namespace OpenSim.Region.Framework.Scenes
2958 obPart.UpdateOffSet(currentpos); 3311 obPart.UpdateOffSet(currentpos);
2959 } 3312 }
2960 obPart.IgnoreUndoUpdate = false; 3313 obPart.IgnoreUndoUpdate = false;
2961 obPart.StoreUndoState();
2962 } 3314 }
2963 } 3315 }
3316 lockPartsForRead(false);
2964 3317
2965 if (part.PhysActor != null) 3318 if (part.PhysActor != null)
2966 { 3319 {
@@ -2969,7 +3322,6 @@ namespace OpenSim.Region.Framework.Scenes
2969 } 3322 }
2970 3323
2971 part.IgnoreUndoUpdate = false; 3324 part.IgnoreUndoUpdate = false;
2972 part.StoreUndoState();
2973 HasGroupChanged = true; 3325 HasGroupChanged = true;
2974 ScheduleGroupForTerseUpdate(); 3326 ScheduleGroupForTerseUpdate();
2975 } 3327 }
@@ -2985,14 +3337,11 @@ namespace OpenSim.Region.Framework.Scenes
2985 /// <param name="pos"></param> 3337 /// <param name="pos"></param>
2986 public void UpdateGroupPosition(Vector3 pos) 3338 public void UpdateGroupPosition(Vector3 pos)
2987 { 3339 {
2988 foreach (SceneObjectPart part in Children.Values)
2989 {
2990 part.StoreUndoState();
2991 }
2992 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3340 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2993 { 3341 {
2994 if (IsAttachment) 3342 if (IsAttachment)
2995 { 3343 {
3344 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2996 m_rootPart.AttachedPos = pos; 3345 m_rootPart.AttachedPos = pos;
2997 } 3346 }
2998 if (RootPart.GetStatusSandbox()) 3347 if (RootPart.GetStatusSandbox())
@@ -3025,7 +3374,7 @@ namespace OpenSim.Region.Framework.Scenes
3025 SceneObjectPart part = GetChildPart(localID); 3374 SceneObjectPart part = GetChildPart(localID);
3026 foreach (SceneObjectPart parts in Children.Values) 3375 foreach (SceneObjectPart parts in Children.Values)
3027 { 3376 {
3028 parts.StoreUndoState(); 3377 parts.StoreUndoState(UndoType.STATE_PRIM_POSITION);
3029 } 3378 }
3030 if (part != null) 3379 if (part != null)
3031 { 3380 {
@@ -3050,7 +3399,7 @@ namespace OpenSim.Region.Framework.Scenes
3050 { 3399 {
3051 foreach (SceneObjectPart part in Children.Values) 3400 foreach (SceneObjectPart part in Children.Values)
3052 { 3401 {
3053 part.StoreUndoState(); 3402 part.StoreUndoState(UndoType.STATE_PRIM_POSITION);
3054 } 3403 }
3055 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3404 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3056 Vector3 oldPos = 3405 Vector3 oldPos =
@@ -3063,7 +3412,7 @@ namespace OpenSim.Region.Framework.Scenes
3063 axDiff *= Quaternion.Inverse(partRotation); 3412 axDiff *= Quaternion.Inverse(partRotation);
3064 diff = axDiff; 3413 diff = axDiff;
3065 3414
3066 lock (m_parts) 3415 lockPartsForRead(true);
3067 { 3416 {
3068 foreach (SceneObjectPart obPart in m_parts.Values) 3417 foreach (SceneObjectPart obPart in m_parts.Values)
3069 { 3418 {
@@ -3073,11 +3422,29 @@ namespace OpenSim.Region.Framework.Scenes
3073 } 3422 }
3074 } 3423 }
3075 } 3424 }
3425 lockPartsForRead(false);
3076 3426
3077 AbsolutePosition = newPos; 3427 //We have to set undoing here because otherwise an undo state will be saved
3428 if (!m_rootPart.Undoing)
3429 {
3430 m_rootPart.Undoing = true;
3431 AbsolutePosition = newPos;
3432 m_rootPart.Undoing = false;
3433 }
3434 else
3435 {
3436 AbsolutePosition = newPos;
3437 }
3078 3438
3079 HasGroupChanged = true; 3439 HasGroupChanged = true;
3080 ScheduleGroupForTerseUpdate(); 3440 if (m_rootPart.Undoing)
3441 {
3442 ScheduleGroupForFullUpdate();
3443 }
3444 else
3445 {
3446 ScheduleGroupForTerseUpdate();
3447 }
3081 } 3448 }
3082 3449
3083 public void OffsetForNewRegion(Vector3 offset) 3450 public void OffsetForNewRegion(Vector3 offset)
@@ -3097,7 +3464,7 @@ namespace OpenSim.Region.Framework.Scenes
3097 { 3464 {
3098 foreach (SceneObjectPart parts in Children.Values) 3465 foreach (SceneObjectPart parts in Children.Values)
3099 { 3466 {
3100 parts.StoreUndoState(); 3467 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3101 } 3468 }
3102 m_rootPart.UpdateRotation(rot); 3469 m_rootPart.UpdateRotation(rot);
3103 3470
@@ -3121,7 +3488,7 @@ namespace OpenSim.Region.Framework.Scenes
3121 { 3488 {
3122 foreach (SceneObjectPart parts in Children.Values) 3489 foreach (SceneObjectPart parts in Children.Values)
3123 { 3490 {
3124 parts.StoreUndoState(); 3491 parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3125 } 3492 }
3126 m_rootPart.UpdateRotation(rot); 3493 m_rootPart.UpdateRotation(rot);
3127 3494
@@ -3148,7 +3515,7 @@ namespace OpenSim.Region.Framework.Scenes
3148 SceneObjectPart part = GetChildPart(localID); 3515 SceneObjectPart part = GetChildPart(localID);
3149 foreach (SceneObjectPart parts in Children.Values) 3516 foreach (SceneObjectPart parts in Children.Values)
3150 { 3517 {
3151 parts.StoreUndoState(); 3518 parts.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3152 } 3519 }
3153 if (part != null) 3520 if (part != null)
3154 { 3521 {
@@ -3176,15 +3543,24 @@ namespace OpenSim.Region.Framework.Scenes
3176 if (part.UUID == m_rootPart.UUID) 3543 if (part.UUID == m_rootPart.UUID)
3177 { 3544 {
3178 UpdateRootRotation(rot); 3545 UpdateRootRotation(rot);
3179 AbsolutePosition = pos; 3546 if (!m_rootPart.Undoing)
3547 {
3548 m_rootPart.Undoing = true;
3549 AbsolutePosition = pos;
3550 m_rootPart.Undoing = false;
3551 }
3552 else
3553 {
3554 AbsolutePosition = pos;
3555 }
3180 } 3556 }
3181 else 3557 else
3182 { 3558 {
3559 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3183 part.IgnoreUndoUpdate = true; 3560 part.IgnoreUndoUpdate = true;
3184 part.UpdateRotation(rot); 3561 part.UpdateRotation(rot);
3185 part.OffsetPosition = pos; 3562 part.OffsetPosition = pos;
3186 part.IgnoreUndoUpdate = false; 3563 part.IgnoreUndoUpdate = false;
3187 part.StoreUndoState();
3188 } 3564 }
3189 } 3565 }
3190 } 3566 }
@@ -3198,7 +3574,13 @@ namespace OpenSim.Region.Framework.Scenes
3198 Quaternion axRot = rot; 3574 Quaternion axRot = rot;
3199 Quaternion oldParentRot = m_rootPart.RotationOffset; 3575 Quaternion oldParentRot = m_rootPart.RotationOffset;
3200 3576
3201 m_rootPart.StoreUndoState(); 3577 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3578 bool cancelUndo = false;
3579 if (!m_rootPart.Undoing)
3580 {
3581 m_rootPart.Undoing = true;
3582 cancelUndo = true;
3583 }
3202 m_rootPart.UpdateRotation(rot); 3584 m_rootPart.UpdateRotation(rot);
3203 if (m_rootPart.PhysActor != null) 3585 if (m_rootPart.PhysActor != null)
3204 { 3586 {
@@ -3206,33 +3588,31 @@ namespace OpenSim.Region.Framework.Scenes
3206 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3588 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3207 } 3589 }
3208 3590
3209 lock (m_parts) 3591 lockPartsForRead(true);
3592
3593 foreach (SceneObjectPart prim in m_parts.Values)
3210 { 3594 {
3211 foreach (SceneObjectPart prim in m_parts.Values) 3595 if (prim.UUID != m_rootPart.UUID)
3212 { 3596 {
3213 if (prim.UUID != m_rootPart.UUID) 3597 prim.IgnoreUndoUpdate = true;
3214 { 3598 Vector3 axPos = prim.OffsetPosition;
3215 prim.IgnoreUndoUpdate = true; 3599 axPos *= oldParentRot;
3216 Vector3 axPos = prim.OffsetPosition; 3600 axPos *= Quaternion.Inverse(axRot);
3217 axPos *= oldParentRot; 3601 prim.OffsetPosition = axPos;
3218 axPos *= Quaternion.Inverse(axRot); 3602 Quaternion primsRot = prim.RotationOffset;
3219 prim.OffsetPosition = axPos; 3603 Quaternion newRot = primsRot * oldParentRot;
3220 Quaternion primsRot = prim.RotationOffset; 3604 newRot *= Quaternion.Inverse(axRot);
3221 Quaternion newRot = primsRot * oldParentRot; 3605 prim.RotationOffset = newRot;
3222 newRot *= Quaternion.Inverse(axRot); 3606 prim.ScheduleTerseUpdate();
3223 prim.RotationOffset = newRot; 3607 prim.IgnoreUndoUpdate = false;
3224 prim.ScheduleTerseUpdate();
3225 }
3226 } 3608 }
3227 } 3609 }
3228 foreach (SceneObjectPart childpart in Children.Values) 3610 if (cancelUndo == true)
3229 { 3611 {
3230 if (childpart != m_rootPart) 3612 m_rootPart.Undoing = false;
3231 {
3232 childpart.IgnoreUndoUpdate = false;
3233 childpart.StoreUndoState();
3234 }
3235 } 3613 }
3614 lockPartsForRead(false);
3615
3236 m_rootPart.ScheduleTerseUpdate(); 3616 m_rootPart.ScheduleTerseUpdate();
3237 } 3617 }
3238 3618
@@ -3354,7 +3734,7 @@ namespace OpenSim.Region.Framework.Scenes
3354 if (atTargets.Count > 0) 3734 if (atTargets.Count > 0)
3355 { 3735 {
3356 uint[] localids = new uint[0]; 3736 uint[] localids = new uint[0];
3357 lock (m_parts) 3737 lockPartsForRead(true);
3358 { 3738 {
3359 localids = new uint[m_parts.Count]; 3739 localids = new uint[m_parts.Count];
3360 int cntr = 0; 3740 int cntr = 0;
@@ -3364,6 +3744,7 @@ namespace OpenSim.Region.Framework.Scenes
3364 cntr++; 3744 cntr++;
3365 } 3745 }
3366 } 3746 }
3747 lockPartsForRead(false);
3367 3748
3368 for (int ctr = 0; ctr < localids.Length; ctr++) 3749 for (int ctr = 0; ctr < localids.Length; ctr++)
3369 { 3750 {
@@ -3382,7 +3763,7 @@ namespace OpenSim.Region.Framework.Scenes
3382 { 3763 {
3383 //trigger not_at_target 3764 //trigger not_at_target
3384 uint[] localids = new uint[0]; 3765 uint[] localids = new uint[0];
3385 lock (m_parts) 3766 lockPartsForRead(true);
3386 { 3767 {
3387 localids = new uint[m_parts.Count]; 3768 localids = new uint[m_parts.Count];
3388 int cntr = 0; 3769 int cntr = 0;
@@ -3392,7 +3773,8 @@ namespace OpenSim.Region.Framework.Scenes
3392 cntr++; 3773 cntr++;
3393 } 3774 }
3394 } 3775 }
3395 3776 lockPartsForRead(false);
3777
3396 for (int ctr = 0; ctr < localids.Length; ctr++) 3778 for (int ctr = 0; ctr < localids.Length; ctr++)
3397 { 3779 {
3398 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3780 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3433,7 +3815,8 @@ namespace OpenSim.Region.Framework.Scenes
3433 if (atRotTargets.Count > 0) 3815 if (atRotTargets.Count > 0)
3434 { 3816 {
3435 uint[] localids = new uint[0]; 3817 uint[] localids = new uint[0];
3436 lock (m_parts) 3818 lockPartsForRead(true);
3819 try
3437 { 3820 {
3438 localids = new uint[m_parts.Count]; 3821 localids = new uint[m_parts.Count];
3439 int cntr = 0; 3822 int cntr = 0;
@@ -3443,6 +3826,10 @@ namespace OpenSim.Region.Framework.Scenes
3443 cntr++; 3826 cntr++;
3444 } 3827 }
3445 } 3828 }
3829 finally
3830 {
3831 lockPartsForRead(false);
3832 }
3446 3833
3447 for (int ctr = 0; ctr < localids.Length; ctr++) 3834 for (int ctr = 0; ctr < localids.Length; ctr++)
3448 { 3835 {
@@ -3461,7 +3848,8 @@ namespace OpenSim.Region.Framework.Scenes
3461 { 3848 {
3462 //trigger not_at_target 3849 //trigger not_at_target
3463 uint[] localids = new uint[0]; 3850 uint[] localids = new uint[0];
3464 lock (m_parts) 3851 lockPartsForRead(true);
3852 try
3465 { 3853 {
3466 localids = new uint[m_parts.Count]; 3854 localids = new uint[m_parts.Count];
3467 int cntr = 0; 3855 int cntr = 0;
@@ -3471,6 +3859,10 @@ namespace OpenSim.Region.Framework.Scenes
3471 cntr++; 3859 cntr++;
3472 } 3860 }
3473 } 3861 }
3862 finally
3863 {
3864 lockPartsForRead(false);
3865 }
3474 3866
3475 for (int ctr = 0; ctr < localids.Length; ctr++) 3867 for (int ctr = 0; ctr < localids.Length; ctr++)
3476 { 3868 {
@@ -3484,19 +3876,20 @@ namespace OpenSim.Region.Framework.Scenes
3484 public float GetMass() 3876 public float GetMass()
3485 { 3877 {
3486 float retmass = 0f; 3878 float retmass = 0f;
3487 lock (m_parts) 3879 lockPartsForRead(true);
3488 { 3880 {
3489 foreach (SceneObjectPart part in m_parts.Values) 3881 foreach (SceneObjectPart part in m_parts.Values)
3490 { 3882 {
3491 retmass += part.GetMass(); 3883 retmass += part.GetMass();
3492 } 3884 }
3493 } 3885 }
3886 lockPartsForRead(false);
3494 return retmass; 3887 return retmass;
3495 } 3888 }
3496 3889
3497 public void CheckSculptAndLoad() 3890 public void CheckSculptAndLoad()
3498 { 3891 {
3499 lock (m_parts) 3892 lockPartsForRead(true);
3500 { 3893 {
3501 if (!IsDeleted) 3894 if (!IsDeleted)
3502 { 3895 {
@@ -3521,6 +3914,7 @@ namespace OpenSim.Region.Framework.Scenes
3521 } 3914 }
3522 } 3915 }
3523 } 3916 }
3917 lockPartsForRead(false);
3524 } 3918 }
3525 3919
3526 protected void AssetReceived(string id, Object sender, AssetBase asset) 3920 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3541,7 +3935,7 @@ namespace OpenSim.Region.Framework.Scenes
3541 /// <param name="client"></param> 3935 /// <param name="client"></param>
3542 public void SetGroup(UUID GroupID, IClientAPI client) 3936 public void SetGroup(UUID GroupID, IClientAPI client)
3543 { 3937 {
3544 lock (m_parts) 3938 lockPartsForRead(true);
3545 { 3939 {
3546 foreach (SceneObjectPart part in m_parts.Values) 3940 foreach (SceneObjectPart part in m_parts.Values)
3547 { 3941 {
@@ -3551,6 +3945,7 @@ namespace OpenSim.Region.Framework.Scenes
3551 3945
3552 HasGroupChanged = true; 3946 HasGroupChanged = true;
3553 } 3947 }
3948 lockPartsForRead(false);
3554 3949
3555 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3950 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3556 // for the same object with very different properties. The caller must schedule the update. 3951 // for the same object with very different properties. The caller must schedule the update.
@@ -3572,11 +3967,12 @@ namespace OpenSim.Region.Framework.Scenes
3572 3967
3573 public void SetAttachmentPoint(byte point) 3968 public void SetAttachmentPoint(byte point)
3574 { 3969 {
3575 lock (m_parts) 3970 lockPartsForRead(true);
3576 { 3971 {
3577 foreach (SceneObjectPart part in m_parts.Values) 3972 foreach (SceneObjectPart part in m_parts.Values)
3578 part.SetAttachmentPoint(point); 3973 part.SetAttachmentPoint(point);
3579 } 3974 }
3975 lockPartsForRead(false);
3580 } 3976 }
3581 3977
3582 #region ISceneObject 3978 #region ISceneObject
@@ -3610,6 +4006,14 @@ namespace OpenSim.Region.Framework.Scenes
3610 SetFromItemID(uuid); 4006 SetFromItemID(uuid);
3611 } 4007 }
3612 4008
4009 public void ResetOwnerChangeFlag()
4010 {
4011 ForEachPart(delegate(SceneObjectPart part)
4012 {
4013 part.ResetOwnerChangeFlag();
4014 });
4015 }
4016
3613 #endregion 4017 #endregion
3614 } 4018 }
3615} 4019}