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.cs766
1 files changed, 545 insertions, 221 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e23f39f..7081ced 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 }
@@ -258,13 +386,16 @@ namespace OpenSim.Region.Framework.Scenes
258 set 386 set
259 { 387 {
260 m_regionHandle = value; 388 m_regionHandle = value;
261 lock (m_parts) 389 lockPartsForRead(true);
262 { 390 {
263 foreach (SceneObjectPart part in m_parts.Values) 391 foreach (SceneObjectPart part in m_parts.Values)
264 { 392 {
393
265 part.RegionHandle = m_regionHandle; 394 part.RegionHandle = m_regionHandle;
395
266 } 396 }
267 } 397 }
398 lockPartsForRead(false);
268 } 399 }
269 } 400 }
270 401
@@ -298,6 +429,9 @@ namespace OpenSim.Region.Framework.Scenes
298 { 429 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 430 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 431 }
432
433 lockPartsForRead(true);
434
301 if (RootPart.GetStatusSandbox()) 435 if (RootPart.GetStatusSandbox())
302 { 436 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 437 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -305,17 +439,18 @@ namespace OpenSim.Region.Framework.Scenes
305 RootPart.ScriptSetPhysicsStatus(false); 439 RootPart.ScriptSetPhysicsStatus(false);
306 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 440 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
307 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 441 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
442 lockPartsForRead(false);
308 return; 443 return;
309 } 444 }
310 } 445 }
311 lock (m_parts) 446
447 foreach (SceneObjectPart part in m_parts.Values)
312 { 448 {
313 foreach (SceneObjectPart part in m_parts.Values) 449 part.GroupPosition = val;
314 {
315 part.GroupPosition = val;
316 }
317 } 450 }
318 451
452 lockPartsForRead(false);
453
319 //if (m_rootPart.PhysActor != null) 454 //if (m_rootPart.PhysActor != null)
320 //{ 455 //{
321 //m_rootPart.PhysActor.Position = 456 //m_rootPart.PhysActor.Position =
@@ -457,6 +592,7 @@ namespace OpenSim.Region.Framework.Scenes
457 /// </summary> 592 /// </summary>
458 public SceneObjectGroup() 593 public SceneObjectGroup()
459 { 594 {
595
460 } 596 }
461 597
462 /// <summary> 598 /// <summary>
@@ -473,7 +609,7 @@ namespace OpenSim.Region.Framework.Scenes
473 /// Constructor. This object is added to the scene later via AttachToScene() 609 /// Constructor. This object is added to the scene later via AttachToScene()
474 /// </summary> 610 /// </summary>
475 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 611 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
476 { 612 {
477 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 613 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
478 } 614 }
479 615
@@ -504,13 +640,16 @@ namespace OpenSim.Region.Framework.Scenes
504 640
505 public void SetFromItemID(UUID AssetId) 641 public void SetFromItemID(UUID AssetId)
506 { 642 {
507 lock (m_parts) 643 lockPartsForRead(true);
508 { 644 {
509 foreach (SceneObjectPart part in m_parts.Values) 645 foreach (SceneObjectPart part in m_parts.Values)
510 { 646 {
647
511 part.FromItemID = AssetId; 648 part.FromItemID = AssetId;
649
512 } 650 }
513 } 651 }
652 lockPartsForRead(false);
514 } 653 }
515 654
516 public UUID GetFromItemID() 655 public UUID GetFromItemID()
@@ -523,6 +662,8 @@ namespace OpenSim.Region.Framework.Scenes
523 /// </summary> 662 /// </summary>
524 public virtual void AttachToBackup() 663 public virtual void AttachToBackup()
525 { 664 {
665 m_scene.SceneGraph.FireAttachToBackup(this);
666
526 if (InSceneBackup) 667 if (InSceneBackup)
527 { 668 {
528 //m_log.DebugFormat( 669 //m_log.DebugFormat(
@@ -579,10 +720,11 @@ namespace OpenSim.Region.Framework.Scenes
579 Vector3 maxScale = Vector3.Zero; 720 Vector3 maxScale = Vector3.Zero;
580 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 721 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
581 722
582 lock (m_parts) 723 lockPartsForRead(true);
583 { 724 {
584 foreach (SceneObjectPart part in m_parts.Values) 725 foreach (SceneObjectPart part in m_parts.Values)
585 { 726 {
727
586 Vector3 partscale = part.Scale; 728 Vector3 partscale = part.Scale;
587 Vector3 partoffset = part.OffsetPosition; 729 Vector3 partoffset = part.OffsetPosition;
588 730
@@ -593,8 +735,11 @@ namespace OpenSim.Region.Framework.Scenes
593 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 735 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; 736 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; 737 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
738
596 } 739 }
597 } 740 }
741 lockPartsForRead(false);
742
598 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 743 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
599 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 744 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
600 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 745 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -610,10 +755,11 @@ namespace OpenSim.Region.Framework.Scenes
610 755
611 EntityIntersection result = new EntityIntersection(); 756 EntityIntersection result = new EntityIntersection();
612 757
613 lock (m_parts) 758 lockPartsForRead(true);
614 { 759 {
615 foreach (SceneObjectPart part in m_parts.Values) 760 foreach (SceneObjectPart part in m_parts.Values)
616 { 761 {
762
617 // Temporary commented to stop compiler warning 763 // Temporary commented to stop compiler warning
618 //Vector3 partPosition = 764 //Vector3 partPosition =
619 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 765 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -641,8 +787,10 @@ namespace OpenSim.Region.Framework.Scenes
641 result.distance = inter.distance; 787 result.distance = inter.distance;
642 } 788 }
643 } 789 }
790
644 } 791 }
645 } 792 }
793 lockPartsForRead(false);
646 return result; 794 return result;
647 } 795 }
648 796
@@ -661,10 +809,11 @@ namespace OpenSim.Region.Framework.Scenes
661 minY = 256f; 809 minY = 256f;
662 minZ = 8192f; 810 minZ = 8192f;
663 811
664 lock(m_parts); 812 lockPartsForRead(true);
665 { 813 {
666 foreach (SceneObjectPart part in m_parts.Values) 814 foreach (SceneObjectPart part in m_parts.Values)
667 { 815 {
816
668 Vector3 worldPos = part.GetWorldPosition(); 817 Vector3 worldPos = part.GetWorldPosition();
669 Vector3 offset = worldPos - AbsolutePosition; 818 Vector3 offset = worldPos - AbsolutePosition;
670 Quaternion worldRot; 819 Quaternion worldRot;
@@ -723,6 +872,8 @@ namespace OpenSim.Region.Framework.Scenes
723 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 872 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
724 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 873 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
725 874
875
876
726 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 877 //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); 878 //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); 879 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -894,6 +1045,7 @@ namespace OpenSim.Region.Framework.Scenes
894 minZ = backBottomLeft.Z; 1045 minZ = backBottomLeft.Z;
895 } 1046 }
896 } 1047 }
1048 lockPartsForRead(false);
897 } 1049 }
898 1050
899 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 1051 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
@@ -929,21 +1081,29 @@ namespace OpenSim.Region.Framework.Scenes
929 1081
930 public void SaveScriptedState(XmlTextWriter writer) 1082 public void SaveScriptedState(XmlTextWriter writer)
931 { 1083 {
1084 SaveScriptedState(writer, false);
1085 }
1086
1087 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1088 {
932 XmlDocument doc = new XmlDocument(); 1089 XmlDocument doc = new XmlDocument();
933 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1090 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
934 1091
935 // Capture script state while holding the lock 1092 // Capture script state while holding the lock
936 lock (m_parts) 1093 lockPartsForRead(true);
937 { 1094 {
938 foreach (SceneObjectPart part in m_parts.Values) 1095 foreach (SceneObjectPart part in m_parts.Values)
939 { 1096 {
940 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 1097
1098 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(oldIDs);
941 foreach (UUID itemid in pstates.Keys) 1099 foreach (UUID itemid in pstates.Keys)
942 { 1100 {
943 states.Add(itemid, pstates[itemid]); 1101 states.Add(itemid, pstates[itemid]);
944 } 1102 }
1103
945 } 1104 }
946 } 1105 }
1106 lockPartsForRead(false);
947 1107
948 if (states.Count > 0) 1108 if (states.Count > 0)
949 { 1109 {
@@ -962,6 +1122,47 @@ namespace OpenSim.Region.Framework.Scenes
962 } 1122 }
963 1123
964 /// <summary> 1124 /// <summary>
1125 /// Add the avatar to this linkset (avatar is sat).
1126 /// </summary>
1127 /// <param name="agentID"></param>
1128 public void AddAvatar(UUID agentID)
1129 {
1130 ScenePresence presence;
1131 if (m_scene.TryGetScenePresence(agentID, out presence))
1132 {
1133 if (!m_linkedAvatars.Contains(presence))
1134 {
1135 m_linkedAvatars.Add(presence);
1136 }
1137 }
1138 }
1139
1140 /// <summary>
1141 /// Delete the avatar from this linkset (avatar is unsat).
1142 /// </summary>
1143 /// <param name="agentID"></param>
1144 public void DeleteAvatar(UUID agentID)
1145 {
1146 ScenePresence presence;
1147 if (m_scene.TryGetScenePresence(agentID, out presence))
1148 {
1149 if (m_linkedAvatars.Contains(presence))
1150 {
1151 m_linkedAvatars.Remove(presence);
1152 }
1153 }
1154 }
1155
1156 /// <summary>
1157 /// Returns the list of linked presences (avatars sat on this group)
1158 /// </summary>
1159 /// <param name="agentID"></param>
1160 public List<ScenePresence> GetLinkedAvatars()
1161 {
1162 return m_linkedAvatars;
1163 }
1164
1165 /// <summary>
965 /// Attach this scene object to the given avatar. 1166 /// Attach this scene object to the given avatar.
966 /// </summary> 1167 /// </summary>
967 /// <param name="agentID"></param> 1168 /// <param name="agentID"></param>
@@ -1112,13 +1313,16 @@ namespace OpenSim.Region.Framework.Scenes
1112 1313
1113 public override void UpdateMovement() 1314 public override void UpdateMovement()
1114 { 1315 {
1115 lock (m_parts) 1316 lockPartsForRead(true);
1116 { 1317 {
1117 foreach (SceneObjectPart part in m_parts.Values) 1318 foreach (SceneObjectPart part in m_parts.Values)
1118 { 1319 {
1320
1119 part.UpdateMovement(); 1321 part.UpdateMovement();
1322
1120 } 1323 }
1121 } 1324 }
1325 lockPartsForRead(false);
1122 } 1326 }
1123 1327
1124 public ushort GetTimeDilation() 1328 public ushort GetTimeDilation()
@@ -1162,7 +1366,7 @@ namespace OpenSim.Region.Framework.Scenes
1162 /// <param name="part"></param> 1366 /// <param name="part"></param>
1163 public void AddPart(SceneObjectPart part) 1367 public void AddPart(SceneObjectPart part)
1164 { 1368 {
1165 lock (m_parts) 1369 lockPartsForWrite(true);
1166 { 1370 {
1167 part.SetParent(this); 1371 part.SetParent(this);
1168 m_parts.Add(part.UUID, part); 1372 m_parts.Add(part.UUID, part);
@@ -1172,6 +1376,7 @@ namespace OpenSim.Region.Framework.Scenes
1172 if (part.LinkNum == 2 && RootPart != null) 1376 if (part.LinkNum == 2 && RootPart != null)
1173 RootPart.LinkNum = 1; 1377 RootPart.LinkNum = 1;
1174 } 1378 }
1379 lockPartsForWrite(false);
1175 } 1380 }
1176 1381
1177 /// <summary> 1382 /// <summary>
@@ -1179,28 +1384,33 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// </summary> 1384 /// </summary>
1180 private void UpdateParentIDs() 1385 private void UpdateParentIDs()
1181 { 1386 {
1182 lock (m_parts) 1387 lockPartsForRead(true);
1183 { 1388 {
1184 foreach (SceneObjectPart part in m_parts.Values) 1389 foreach (SceneObjectPart part in m_parts.Values)
1185 { 1390 {
1391
1186 if (part.UUID != m_rootPart.UUID) 1392 if (part.UUID != m_rootPart.UUID)
1187 { 1393 {
1188 part.ParentID = m_rootPart.LocalId; 1394 part.ParentID = m_rootPart.LocalId;
1189 } 1395 }
1396
1190 } 1397 }
1191 } 1398 }
1399 lockPartsForRead(false);
1192 } 1400 }
1193 1401
1194 public void RegenerateFullIDs() 1402 public void RegenerateFullIDs()
1195 { 1403 {
1196 lock (m_parts) 1404 lockPartsForRead(true);
1197 { 1405 {
1198 foreach (SceneObjectPart part in m_parts.Values) 1406 foreach (SceneObjectPart part in m_parts.Values)
1199 { 1407 {
1408
1200 part.UUID = UUID.Random(); 1409 part.UUID = UUID.Random();
1201 1410
1202 } 1411 }
1203 } 1412 }
1413 lockPartsForRead(false);
1204 } 1414 }
1205 1415
1206 // helper provided for parts. 1416 // helper provided for parts.
@@ -1281,27 +1491,32 @@ namespace OpenSim.Region.Framework.Scenes
1281 1491
1282 DetachFromBackup(); 1492 DetachFromBackup();
1283 1493
1284 lock (m_parts) 1494 lockPartsForRead(true);
1495 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1496 lockPartsForRead(false);
1497
1498 foreach (SceneObjectPart part in values)
1285 { 1499 {
1286 foreach (SceneObjectPart part in m_parts.Values)
1287 {
1288// part.Inventory.RemoveScriptInstances(); 1500// part.Inventory.RemoveScriptInstances();
1289 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1501
1502 Scene.ForEachScenePresence(delegate (ScenePresence sp)
1503 {
1504 if (sp.ParentID == LocalId)
1290 { 1505 {
1291 if (avatar.ParentID == LocalId) 1506 sp.StandUp();
1292 { 1507 }
1293 avatar.StandUp();
1294 }
1295 1508
1296 if (!silent) 1509 if (!silent)
1297 { 1510 {
1298 part.UpdateFlag = 0; 1511 part.UpdateFlag = 0;
1299 if (part == m_rootPart) 1512 if (part == m_rootPart)
1300 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1513 sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1301 } 1514 }
1302 }); 1515 });
1303 } 1516
1304 } 1517 }
1518
1519
1305 } 1520 }
1306 1521
1307 public void AddScriptLPS(int count) 1522 public void AddScriptLPS(int count)
@@ -1326,17 +1541,20 @@ namespace OpenSim.Region.Framework.Scenes
1326 1541
1327 scriptEvents aggregateScriptEvents=0; 1542 scriptEvents aggregateScriptEvents=0;
1328 1543
1329 lock (m_parts) 1544 lockPartsForRead(true);
1330 { 1545 {
1331 foreach (SceneObjectPart part in m_parts.Values) 1546 foreach (SceneObjectPart part in m_parts.Values)
1332 { 1547 {
1548
1333 if (part == null) 1549 if (part == null)
1334 continue; 1550 continue;
1335 if (part != RootPart) 1551 if (part != RootPart)
1336 part.ObjectFlags = objectflagupdate; 1552 part.ObjectFlags = objectflagupdate;
1337 aggregateScriptEvents |= part.AggregateScriptEvents; 1553 aggregateScriptEvents |= part.AggregateScriptEvents;
1554
1338 } 1555 }
1339 } 1556 }
1557 lockPartsForRead(false);
1340 1558
1341 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1559 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1342 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1560 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1378,42 +1596,52 @@ namespace OpenSim.Region.Framework.Scenes
1378 /// <param name="m_physicalPrim"></param> 1596 /// <param name="m_physicalPrim"></param>
1379 public void ApplyPhysics(bool m_physicalPrim) 1597 public void ApplyPhysics(bool m_physicalPrim)
1380 { 1598 {
1381 lock (m_parts) 1599 lockPartsForRead(true);
1600
1601 if (m_parts.Count > 1)
1382 { 1602 {
1383 if (m_parts.Count > 1) 1603 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1604 lockPartsForRead(false);
1605 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1606 foreach (SceneObjectPart part in values)
1384 { 1607 {
1385 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1608
1386 foreach (SceneObjectPart part in m_parts.Values) 1609 if (part.LocalId != m_rootPart.LocalId)
1387 { 1610 {
1388 if (part.LocalId != m_rootPart.LocalId) 1611 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1389 {
1390 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1391 }
1392 } 1612 }
1393 1613
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 } 1614 }
1615 // Hack to get the physics scene geometries in the right spot
1616 ResetChildPrimPhysicsPositions();
1617 }
1618 else
1619 {
1620 lockPartsForRead(false);
1621 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1401 } 1622 }
1402 } 1623 }
1403 1624
1404 public void SetOwnerId(UUID userId) 1625 public void SetOwnerId(UUID userId)
1405 { 1626 {
1406 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1627 ForEachPart(delegate(SceneObjectPart part)
1628 {
1629
1630 part.OwnerID = userId;
1631
1632 });
1407 } 1633 }
1408 1634
1409 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1635 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1410 { 1636 {
1411 lock (m_parts) 1637 lockPartsForRead(true);
1638 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1639 lockPartsForRead(false);
1640 foreach (SceneObjectPart part in values)
1412 { 1641 {
1413 foreach (SceneObjectPart part in m_parts.Values) 1642
1414 { 1643 whatToDo(part);
1415 whatToDo(part); 1644
1416 }
1417 } 1645 }
1418 } 1646 }
1419 1647
@@ -1511,15 +1739,17 @@ namespace OpenSim.Region.Framework.Scenes
1511 RootPart.SendFullUpdate( 1739 RootPart.SendFullUpdate(
1512 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1740 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1513 1741
1514 lock (m_parts) 1742 lockPartsForRead(true);
1515 { 1743 {
1516 foreach (SceneObjectPart part in m_parts.Values) 1744 foreach (SceneObjectPart part in m_parts.Values)
1517 { 1745 {
1746
1518 if (part != RootPart) 1747 if (part != RootPart)
1519 part.SendFullUpdate( 1748 part.SendFullUpdate(
1520 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1749 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1521 } 1750 }
1522 } 1751 }
1752 lockPartsForRead(false);
1523 } 1753 }
1524 1754
1525 #region Copying 1755 #region Copying
@@ -1588,10 +1818,11 @@ namespace OpenSim.Region.Framework.Scenes
1588 1818
1589 List<SceneObjectPart> partList; 1819 List<SceneObjectPart> partList;
1590 1820
1591 lock (m_parts) 1821 lockPartsForRead(true);
1592 { 1822
1593 partList = new List<SceneObjectPart>(m_parts.Values); 1823 partList = new List<SceneObjectPart>(m_parts.Values);
1594 } 1824
1825 lockPartsForRead(false);
1595 1826
1596 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1827 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1597 { 1828 {
@@ -1814,13 +2045,40 @@ namespace OpenSim.Region.Framework.Scenes
1814 } 2045 }
1815 } 2046 }
1816 2047
2048 public void rotLookAt(Quaternion target, float strength, float damping)
2049 {
2050 SceneObjectPart rootpart = m_rootPart;
2051 if (rootpart != null)
2052 {
2053 if (IsAttachment)
2054 {
2055 /*
2056 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2057 if (avatar != null)
2058 {
2059 Rotate the Av?
2060 } */
2061 }
2062 else
2063 {
2064 if (rootpart.PhysActor != null)
2065 { // APID must be implemented in your physics system for this to function.
2066 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2067 rootpart.PhysActor.APIDStrength = strength;
2068 rootpart.PhysActor.APIDDamping = damping;
2069 rootpart.PhysActor.APIDActive = true;
2070 }
2071 }
2072 }
2073 }
2074
1817 public void stopLookAt() 2075 public void stopLookAt()
1818 { 2076 {
1819 SceneObjectPart rootpart = m_rootPart; 2077 SceneObjectPart rootpart = m_rootPart;
1820 if (rootpart != null) 2078 if (rootpart != null)
1821 { 2079 {
1822 if (rootpart.PhysActor != null) 2080 if (rootpart.PhysActor != null)
1823 { 2081 { // APID must be implemented in your physics system for this to function.
1824 rootpart.PhysActor.APIDActive = false; 2082 rootpart.PhysActor.APIDActive = false;
1825 } 2083 }
1826 } 2084 }
@@ -1888,10 +2146,11 @@ namespace OpenSim.Region.Framework.Scenes
1888 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2146 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1889 newPart.SetParent(this); 2147 newPart.SetParent(this);
1890 2148
1891 lock (m_parts) 2149 lockPartsForWrite(true);
1892 { 2150 {
1893 m_parts.Add(newPart.UUID, newPart); 2151 m_parts.Add(newPart.UUID, newPart);
1894 } 2152 }
2153 lockPartsForWrite(false);
1895 2154
1896 SetPartAsNonRoot(newPart); 2155 SetPartAsNonRoot(newPart);
1897 2156
@@ -1954,7 +2213,7 @@ namespace OpenSim.Region.Framework.Scenes
1954 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2213 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1955 // return; 2214 // return;
1956 2215
1957 lock (m_parts) 2216 lockPartsForRead(true);
1958 { 2217 {
1959 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2218 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1960 2219
@@ -1974,9 +2233,12 @@ namespace OpenSim.Region.Framework.Scenes
1974 { 2233 {
1975 if (!IsSelected) 2234 if (!IsSelected)
1976 part.UpdateLookAt(); 2235 part.UpdateLookAt();
2236
1977 part.SendScheduledUpdates(); 2237 part.SendScheduledUpdates();
2238
1978 } 2239 }
1979 } 2240 }
2241 lockPartsForRead(false);
1980 } 2242 }
1981 2243
1982 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2244 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1985,27 +2247,29 @@ namespace OpenSim.Region.Framework.Scenes
1985 2247
1986 RootPart.AddFullUpdateToAvatar(presence); 2248 RootPart.AddFullUpdateToAvatar(presence);
1987 2249
1988 lock (m_parts) 2250 lockPartsForRead(true);
1989 { 2251 {
1990 foreach (SceneObjectPart part in m_parts.Values) 2252 foreach (SceneObjectPart part in m_parts.Values)
1991 { 2253 {
2254
1992 if (part != RootPart) 2255 if (part != RootPart)
1993 part.AddFullUpdateToAvatar(presence); 2256 part.AddFullUpdateToAvatar(presence);
2257
1994 } 2258 }
1995 } 2259 }
2260 lockPartsForRead(false);
1996 } 2261 }
1997 2262
1998 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2263 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1999 { 2264 {
2000// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2265 lockPartsForRead(true);
2001 2266
2002 lock (m_parts) 2267 foreach (SceneObjectPart part in m_parts.Values)
2003 { 2268 {
2004 foreach (SceneObjectPart part in m_parts.Values) 2269 part.AddTerseUpdateToAvatar(presence);
2005 {
2006 part.AddTerseUpdateToAvatar(presence);
2007 }
2008 } 2270 }
2271
2272 lockPartsForRead(false);
2009 } 2273 }
2010 2274
2011 /// <summary> 2275 /// <summary>
@@ -2013,20 +2277,23 @@ namespace OpenSim.Region.Framework.Scenes
2013 /// </summary> 2277 /// </summary>
2014 public void ScheduleGroupForFullUpdate() 2278 public void ScheduleGroupForFullUpdate()
2015 { 2279 {
2016 if (IsAttachment) 2280 //if (IsAttachment)
2017 m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); 2281 // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
2018 2282
2019 checkAtTargets(); 2283 checkAtTargets();
2020 RootPart.ScheduleFullUpdate(); 2284 RootPart.ScheduleFullUpdate();
2021 2285
2022 lock (m_parts) 2286 lockPartsForRead(true);
2023 { 2287 {
2024 foreach (SceneObjectPart part in m_parts.Values) 2288 foreach (SceneObjectPart part in m_parts.Values)
2025 { 2289 {
2290
2026 if (part != RootPart) 2291 if (part != RootPart)
2027 part.ScheduleFullUpdate(); 2292 part.ScheduleFullUpdate();
2293
2028 } 2294 }
2029 } 2295 }
2296 lockPartsForRead(false);
2030 } 2297 }
2031 2298
2032 /// <summary> 2299 /// <summary>
@@ -2034,37 +2301,38 @@ namespace OpenSim.Region.Framework.Scenes
2034 /// </summary> 2301 /// </summary>
2035 public void ScheduleGroupForTerseUpdate() 2302 public void ScheduleGroupForTerseUpdate()
2036 { 2303 {
2037// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2304 lockPartsForRead(true);
2038 2305 foreach (SceneObjectPart part in m_parts.Values)
2039 lock (m_parts)
2040 { 2306 {
2041 foreach (SceneObjectPart part in m_parts.Values) 2307 part.ScheduleTerseUpdate();
2042 {
2043 part.ScheduleTerseUpdate();
2044 }
2045 } 2308 }
2309
2310 lockPartsForRead(false);
2046 } 2311 }
2047 2312
2048 /// <summary> 2313 /// <summary>
2049 /// Immediately send a full update for this scene object. 2314 /// Immediately send a full update for this scene object.
2050 /// </summary> 2315 /// </summary>
2051 public void SendGroupFullUpdate() 2316 public void SendGroupFullUpdate()
2052 { 2317 {
2053 if (IsDeleted) 2318 if (IsDeleted)
2054 return; 2319 return;
2055 2320
2056// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2321// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2057 2322
2058 RootPart.SendFullUpdateToAllClients(); 2323 RootPart.SendFullUpdateToAllClients();
2059 2324
2060 lock (m_parts) 2325 lockPartsForRead(true);
2061 { 2326 {
2062 foreach (SceneObjectPart part in m_parts.Values) 2327 foreach (SceneObjectPart part in m_parts.Values)
2063 { 2328 {
2329
2064 if (part != RootPart) 2330 if (part != RootPart)
2065 part.SendFullUpdateToAllClients(); 2331 part.SendFullUpdateToAllClients();
2332
2066 } 2333 }
2067 } 2334 }
2335 lockPartsForRead(false);
2068 } 2336 }
2069 2337
2070 /// <summary> 2338 /// <summary>
@@ -2096,14 +2364,15 @@ namespace OpenSim.Region.Framework.Scenes
2096 { 2364 {
2097 if (IsDeleted) 2365 if (IsDeleted)
2098 return; 2366 return;
2099 2367
2100 lock (m_parts) 2368 lockPartsForRead(true);
2101 { 2369 {
2102 foreach (SceneObjectPart part in m_parts.Values) 2370 foreach (SceneObjectPart part in m_parts.Values)
2103 { 2371 {
2104 part.SendTerseUpdateToAllClients(); 2372 part.SendTerseUpdateToAllClients();
2105 } 2373 }
2106 } 2374 }
2375 lockPartsForRead(false);
2107 } 2376 }
2108 2377
2109 #endregion 2378 #endregion
@@ -2117,16 +2386,18 @@ namespace OpenSim.Region.Framework.Scenes
2117 /// <returns>null if no child part with that linknum or child part</returns> 2386 /// <returns>null if no child part with that linknum or child part</returns>
2118 public SceneObjectPart GetLinkNumPart(int linknum) 2387 public SceneObjectPart GetLinkNumPart(int linknum)
2119 { 2388 {
2120 lock (m_parts) 2389 lockPartsForRead(true);
2121 { 2390 {
2122 foreach (SceneObjectPart part in m_parts.Values) 2391 foreach (SceneObjectPart part in m_parts.Values)
2123 { 2392 {
2124 if (part.LinkNum == linknum) 2393 if (part.LinkNum == linknum)
2125 { 2394 {
2395 lockPartsForRead(false);
2126 return part; 2396 return part;
2127 } 2397 }
2128 } 2398 }
2129 } 2399 }
2400 lockPartsForRead(false);
2130 2401
2131 return null; 2402 return null;
2132 } 2403 }
@@ -2154,17 +2425,19 @@ namespace OpenSim.Region.Framework.Scenes
2154 public SceneObjectPart GetChildPart(uint localID) 2425 public SceneObjectPart GetChildPart(uint localID)
2155 { 2426 {
2156 //m_log.DebugFormat("Entered looking for {0}", localID); 2427 //m_log.DebugFormat("Entered looking for {0}", localID);
2157 lock (m_parts) 2428 lockPartsForRead(true);
2158 { 2429 {
2159 foreach (SceneObjectPart part in m_parts.Values) 2430 foreach (SceneObjectPart part in m_parts.Values)
2160 { 2431 {
2161 //m_log.DebugFormat("Found {0}", part.LocalId); 2432 //m_log.DebugFormat("Found {0}", part.LocalId);
2162 if (part.LocalId == localID) 2433 if (part.LocalId == localID)
2163 { 2434 {
2435 lockPartsForRead(false);
2164 return part; 2436 return part;
2165 } 2437 }
2166 } 2438 }
2167 } 2439 }
2440 lockPartsForRead(false);
2168 2441
2169 return null; 2442 return null;
2170 } 2443 }
@@ -2194,17 +2467,19 @@ namespace OpenSim.Region.Framework.Scenes
2194 public bool HasChildPrim(uint localID) 2467 public bool HasChildPrim(uint localID)
2195 { 2468 {
2196 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2469 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2197 lock (m_parts) 2470 lockPartsForRead(true);
2198 { 2471 {
2199 foreach (SceneObjectPart part in m_parts.Values) 2472 foreach (SceneObjectPart part in m_parts.Values)
2200 { 2473 {
2201 //m_log.DebugFormat("Found {0}", part.LocalId); 2474 //m_log.DebugFormat("Found {0}", part.LocalId);
2202 if (part.LocalId == localID) 2475 if (part.LocalId == localID)
2203 { 2476 {
2477 lockPartsForRead(false);
2204 return true; 2478 return true;
2205 } 2479 }
2206 } 2480 }
2207 } 2481 }
2482 lockPartsForRead(false);
2208 2483
2209 return false; 2484 return false;
2210 } 2485 }
@@ -2254,53 +2529,57 @@ namespace OpenSim.Region.Framework.Scenes
2254 if (m_rootPart.LinkNum == 0) 2529 if (m_rootPart.LinkNum == 0)
2255 m_rootPart.LinkNum = 1; 2530 m_rootPart.LinkNum = 1;
2256 2531
2257 lock (m_parts) 2532 lockPartsForWrite(true);
2258 { 2533
2259 m_parts.Add(linkPart.UUID, linkPart); 2534 m_parts.Add(linkPart.UUID, linkPart);
2535
2536 lockPartsForWrite(false);
2260 2537
2261 // Insert in terms of link numbers, the new links 2538 // Insert in terms of link numbers, the new links
2262 // before the current ones (with the exception of 2539 // before the current ones (with the exception of
2263 // the root prim. Shuffle the old ones up 2540 // the root prim. Shuffle the old ones up
2264 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2541 lockPartsForRead(true);
2542 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2543 {
2544 if (kvp.Value.LinkNum != 1)
2265 { 2545 {
2266 if (kvp.Value.LinkNum != 1) 2546 // Don't update root prim link number
2267 { 2547 kvp.Value.LinkNum += objectGroup.PrimCount;
2268 // Don't update root prim link number
2269 kvp.Value.LinkNum += objectGroup.PrimCount;
2270 }
2271 } 2548 }
2549 }
2550 lockPartsForRead(false);
2272 2551
2273 linkPart.LinkNum = 2; 2552 linkPart.LinkNum = 2;
2274 2553
2275 linkPart.SetParent(this); 2554 linkPart.SetParent(this);
2276 linkPart.CreateSelected = true; 2555 linkPart.CreateSelected = true;
2277 2556
2278 //if (linkPart.PhysActor != null) 2557 //if (linkPart.PhysActor != null)
2279 //{ 2558 //{
2280 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2559 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2281 2560
2282 //linkPart.PhysActor = null; 2561 //linkPart.PhysActor = null;
2283 //} 2562 //}
2284 2563
2285 //TODO: rest of parts 2564 //TODO: rest of parts
2286 int linkNum = 3; 2565 int linkNum = 3;
2287 foreach (SceneObjectPart part in objectGroup.Children.Values) 2566 foreach (SceneObjectPart part in objectGroup.Children.Values)
2567 {
2568 if (part.UUID != objectGroup.m_rootPart.UUID)
2288 { 2569 {
2289 if (part.UUID != objectGroup.m_rootPart.UUID) 2570 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2290 {
2291 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2292 }
2293 part.ClearUndoState();
2294 } 2571 }
2572 part.ClearUndoState();
2295 } 2573 }
2296 2574
2297 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2575 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2298 objectGroup.m_isDeleted = true; 2576 objectGroup.m_isDeleted = true;
2577
2578 objectGroup.lockPartsForWrite(true);
2299 2579
2300 lock (objectGroup.m_parts) 2580 objectGroup.m_parts.Clear();
2301 { 2581
2302 objectGroup.m_parts.Clear(); 2582 objectGroup.lockPartsForWrite(false);
2303 }
2304 2583
2305 // Can't do this yet since backup still makes use of the root part without any synchronization 2584 // Can't do this yet since backup still makes use of the root part without any synchronization
2306// objectGroup.m_rootPart = null; 2585// objectGroup.m_rootPart = null;
@@ -2370,11 +2649,12 @@ namespace OpenSim.Region.Framework.Scenes
2370 Quaternion worldRot = linkPart.GetWorldRotation(); 2649 Quaternion worldRot = linkPart.GetWorldRotation();
2371 2650
2372 // Remove the part from this object 2651 // Remove the part from this object
2373 lock (m_parts) 2652 lockPartsForWrite(true);
2374 { 2653 {
2375 m_parts.Remove(linkPart.UUID); 2654 m_parts.Remove(linkPart.UUID);
2376 } 2655 }
2377 2656 lockPartsForWrite(false);
2657 lockPartsForRead(true);
2378 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2658 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2379 RootPart.LinkNum = 0; 2659 RootPart.LinkNum = 0;
2380 else 2660 else
@@ -2385,6 +2665,7 @@ namespace OpenSim.Region.Framework.Scenes
2385 p.LinkNum--; 2665 p.LinkNum--;
2386 } 2666 }
2387 } 2667 }
2668 lockPartsForRead(false);
2388 2669
2389 linkPart.ParentID = 0; 2670 linkPart.ParentID = 0;
2390 linkPart.LinkNum = 0; 2671 linkPart.LinkNum = 0;
@@ -2428,6 +2709,8 @@ namespace OpenSim.Region.Framework.Scenes
2428 /// <param name="objectGroup"></param> 2709 /// <param name="objectGroup"></param>
2429 public virtual void DetachFromBackup() 2710 public virtual void DetachFromBackup()
2430 { 2711 {
2712 m_scene.SceneGraph.FireDetachFromBackup(this);
2713
2431 if (m_isBackedUp) 2714 if (m_isBackedUp)
2432 m_scene.EventManager.OnBackup -= ProcessBackup; 2715 m_scene.EventManager.OnBackup -= ProcessBackup;
2433 2716
@@ -2706,9 +2989,12 @@ namespace OpenSim.Region.Framework.Scenes
2706 2989
2707 if (selectionPart != null) 2990 if (selectionPart != null)
2708 { 2991 {
2709 lock (m_parts) 2992 lockPartsForRead(true);
2993 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2994 lockPartsForRead(false);
2995 foreach (SceneObjectPart part in parts)
2710 { 2996 {
2711 foreach (SceneObjectPart part in m_parts.Values) 2997 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2712 { 2998 {
2713 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2999 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2714 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 3000 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2718,12 +3004,13 @@ namespace OpenSim.Region.Framework.Scenes
2718 break; 3004 break;
2719 } 3005 }
2720 } 3006 }
3007 }
2721 3008
2722 foreach (SceneObjectPart part in m_parts.Values) 3009 foreach (SceneObjectPart part in parts)
2723 { 3010 {
2724 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3011 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2725 }
2726 } 3012 }
3013
2727 } 3014 }
2728 } 3015 }
2729 3016
@@ -2736,6 +3023,17 @@ namespace OpenSim.Region.Framework.Scenes
2736 } 3023 }
2737 } 3024 }
2738 3025
3026
3027
3028 /// <summary>
3029 /// Gets the number of parts
3030 /// </summary>
3031 /// <returns></returns>
3032 public int GetPartCount()
3033 {
3034 return Children.Count;
3035 }
3036
2739 /// <summary> 3037 /// <summary>
2740 /// Get the parts of this scene object 3038 /// Get the parts of this scene object
2741 /// </summary> 3039 /// </summary>
@@ -2809,11 +3107,9 @@ namespace OpenSim.Region.Framework.Scenes
2809 scale.Y = m_scene.m_maxNonphys; 3107 scale.Y = m_scene.m_maxNonphys;
2810 if (scale.Z > m_scene.m_maxNonphys) 3108 if (scale.Z > m_scene.m_maxNonphys)
2811 scale.Z = m_scene.m_maxNonphys; 3109 scale.Z = m_scene.m_maxNonphys;
2812
2813 SceneObjectPart part = GetChildPart(localID); 3110 SceneObjectPart part = GetChildPart(localID);
2814 if (part != null) 3111 if (part != null)
2815 { 3112 {
2816 part.Resize(scale);
2817 if (part.PhysActor != null) 3113 if (part.PhysActor != null)
2818 { 3114 {
2819 if (part.PhysActor.IsPhysical) 3115 if (part.PhysActor.IsPhysical)
@@ -2828,7 +3124,7 @@ namespace OpenSim.Region.Framework.Scenes
2828 part.PhysActor.Size = scale; 3124 part.PhysActor.Size = scale;
2829 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3125 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2830 } 3126 }
2831 //if (part.UUID != m_rootPart.UUID) 3127 part.Resize(scale);
2832 3128
2833 HasGroupChanged = true; 3129 HasGroupChanged = true;
2834 ScheduleGroupForFullUpdate(); 3130 ScheduleGroupForFullUpdate();
@@ -2870,73 +3166,71 @@ namespace OpenSim.Region.Framework.Scenes
2870 float y = (scale.Y / part.Scale.Y); 3166 float y = (scale.Y / part.Scale.Y);
2871 float z = (scale.Z / part.Scale.Z); 3167 float z = (scale.Z / part.Scale.Z);
2872 3168
2873 lock (m_parts) 3169 lockPartsForRead(true);
3170 if (x > 1.0f || y > 1.0f || z > 1.0f)
2874 { 3171 {
2875 if (x > 1.0f || y > 1.0f || z > 1.0f) 3172 foreach (SceneObjectPart obPart in m_parts.Values)
2876 { 3173 {
2877 foreach (SceneObjectPart obPart in m_parts.Values) 3174 if (obPart.UUID != m_rootPart.UUID)
2878 { 3175 {
2879 if (obPart.UUID != m_rootPart.UUID) 3176 Vector3 oldSize = new Vector3(obPart.Scale);
2880 { 3177 obPart.IgnoreUndoUpdate = true;
2881 obPart.IgnoreUndoUpdate = true;
2882 Vector3 oldSize = new Vector3(obPart.Scale);
2883 3178
2884 float f = 1.0f; 3179 float f = 1.0f;
2885 float a = 1.0f; 3180 float a = 1.0f;
2886 3181
2887 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3182 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3183 {
3184 if (oldSize.X*x > m_scene.m_maxPhys)
2888 { 3185 {
2889 if (oldSize.X*x > m_scene.m_maxPhys) 3186 f = m_scene.m_maxPhys / oldSize.X;
2890 { 3187 a = f / x;
2891 f = m_scene.m_maxPhys / oldSize.X; 3188 x *= a;
2892 a = f / x; 3189 y *= a;
2893 x *= a; 3190 z *= a;
2894 y *= a;
2895 z *= a;
2896 }
2897 if (oldSize.Y*y > m_scene.m_maxPhys)
2898 {
2899 f = m_scene.m_maxPhys / oldSize.Y;
2900 a = f / y;
2901 x *= a;
2902 y *= a;
2903 z *= a;
2904 }
2905 if (oldSize.Z*z > m_scene.m_maxPhys)
2906 {
2907 f = m_scene.m_maxPhys / oldSize.Z;
2908 a = f / z;
2909 x *= a;
2910 y *= a;
2911 z *= a;
2912 }
2913 } 3191 }
2914 else 3192 if (oldSize.Y*y > m_scene.m_maxPhys)
2915 { 3193 {
2916 if (oldSize.X*x > m_scene.m_maxNonphys) 3194 f = m_scene.m_maxPhys / oldSize.Y;
2917 { 3195 a = f / y;
2918 f = m_scene.m_maxNonphys / oldSize.X; 3196 x *= a;
2919 a = f / x; 3197 y *= a;
2920 x *= a; 3198 z *= a;
2921 y *= a; 3199 }
2922 z *= a; 3200 if (oldSize.Z*z > m_scene.m_maxPhys)
2923 } 3201 {
2924 if (oldSize.Y*y > m_scene.m_maxNonphys) 3202 f = m_scene.m_maxPhys / oldSize.Z;
2925 { 3203 a = f / z;
2926 f = m_scene.m_maxNonphys / oldSize.Y; 3204 x *= a;
2927 a = f / y; 3205 y *= a;
2928 x *= a; 3206 z *= a;
2929 y *= a; 3207 }
2930 z *= a; 3208 }
2931 } 3209 else
2932 if (oldSize.Z*z > m_scene.m_maxNonphys) 3210 {
2933 { 3211 if (oldSize.X*x > m_scene.m_maxNonphys)
2934 f = m_scene.m_maxNonphys / oldSize.Z; 3212 {
2935 a = f / z; 3213 f = m_scene.m_maxNonphys / oldSize.X;
2936 x *= a; 3214 a = f / x;
2937 y *= a; 3215 x *= a;
2938 z *= a; 3216 y *= a;
2939 } 3217 z *= a;
3218 }
3219 if (oldSize.Y*y > m_scene.m_maxNonphys)
3220 {
3221 f = m_scene.m_maxNonphys / oldSize.Y;
3222 a = f / y;
3223 x *= a;
3224 y *= a;
3225 z *= a;
3226 }
3227 if (oldSize.Z*z > m_scene.m_maxNonphys)
3228 {
3229 f = m_scene.m_maxNonphys / oldSize.Z;
3230 a = f / z;
3231 x *= a;
3232 y *= a;
3233 z *= a;
2940 } 3234 }
2941 obPart.IgnoreUndoUpdate = false; 3235 obPart.IgnoreUndoUpdate = false;
2942 obPart.StoreUndoState(); 3236 obPart.StoreUndoState();
@@ -2944,6 +3238,7 @@ namespace OpenSim.Region.Framework.Scenes
2944 } 3238 }
2945 } 3239 }
2946 } 3240 }
3241 lockPartsForRead(false);
2947 3242
2948 Vector3 prevScale = part.Scale; 3243 Vector3 prevScale = part.Scale;
2949 prevScale.X *= x; 3244 prevScale.X *= x;
@@ -2951,7 +3246,7 @@ namespace OpenSim.Region.Framework.Scenes
2951 prevScale.Z *= z; 3246 prevScale.Z *= z;
2952 part.Resize(prevScale); 3247 part.Resize(prevScale);
2953 3248
2954 lock (m_parts) 3249 lockPartsForRead(true);
2955 { 3250 {
2956 foreach (SceneObjectPart obPart in m_parts.Values) 3251 foreach (SceneObjectPart obPart in m_parts.Values)
2957 { 3252 {
@@ -2973,6 +3268,7 @@ namespace OpenSim.Region.Framework.Scenes
2973 obPart.StoreUndoState(); 3268 obPart.StoreUndoState();
2974 } 3269 }
2975 } 3270 }
3271 lockPartsForRead(false);
2976 3272
2977 if (part.PhysActor != null) 3273 if (part.PhysActor != null)
2978 { 3274 {
@@ -3075,7 +3371,7 @@ namespace OpenSim.Region.Framework.Scenes
3075 axDiff *= Quaternion.Inverse(partRotation); 3371 axDiff *= Quaternion.Inverse(partRotation);
3076 diff = axDiff; 3372 diff = axDiff;
3077 3373
3078 lock (m_parts) 3374 lockPartsForRead(true);
3079 { 3375 {
3080 foreach (SceneObjectPart obPart in m_parts.Values) 3376 foreach (SceneObjectPart obPart in m_parts.Values)
3081 { 3377 {
@@ -3085,6 +3381,7 @@ namespace OpenSim.Region.Framework.Scenes
3085 } 3381 }
3086 } 3382 }
3087 } 3383 }
3384 lockPartsForRead(false);
3088 3385
3089 AbsolutePosition = newPos; 3386 AbsolutePosition = newPos;
3090 3387
@@ -3218,25 +3515,25 @@ namespace OpenSim.Region.Framework.Scenes
3218 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3515 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3219 } 3516 }
3220 3517
3221 lock (m_parts) 3518 lockPartsForRead(true);
3519
3520 foreach (SceneObjectPart prim in m_parts.Values)
3222 { 3521 {
3223 foreach (SceneObjectPart prim in m_parts.Values) 3522 if (prim.UUID != m_rootPart.UUID)
3224 { 3523 {
3225 if (prim.UUID != m_rootPart.UUID) 3524 prim.IgnoreUndoUpdate = true;
3226 { 3525 Vector3 axPos = prim.OffsetPosition;
3227 prim.IgnoreUndoUpdate = true; 3526 axPos *= oldParentRot;
3228 Vector3 axPos = prim.OffsetPosition; 3527 axPos *= Quaternion.Inverse(axRot);
3229 axPos *= oldParentRot; 3528 prim.OffsetPosition = axPos;
3230 axPos *= Quaternion.Inverse(axRot); 3529 Quaternion primsRot = prim.RotationOffset;
3231 prim.OffsetPosition = axPos; 3530 Quaternion newRot = primsRot * oldParentRot;
3232 Quaternion primsRot = prim.RotationOffset; 3531 newRot *= Quaternion.Inverse(axRot);
3233 Quaternion newRot = primsRot * oldParentRot; 3532 prim.RotationOffset = newRot;
3234 newRot *= Quaternion.Inverse(axRot); 3533 prim.ScheduleTerseUpdate();
3235 prim.RotationOffset = newRot;
3236 prim.ScheduleTerseUpdate();
3237 }
3238 } 3534 }
3239 } 3535 }
3536
3240 foreach (SceneObjectPart childpart in Children.Values) 3537 foreach (SceneObjectPart childpart in Children.Values)
3241 { 3538 {
3242 if (childpart != m_rootPart) 3539 if (childpart != m_rootPart)
@@ -3245,6 +3542,9 @@ namespace OpenSim.Region.Framework.Scenes
3245 childpart.StoreUndoState(); 3542 childpart.StoreUndoState();
3246 } 3543 }
3247 } 3544 }
3545
3546 lockPartsForRead(false);
3547
3248 m_rootPart.ScheduleTerseUpdate(); 3548 m_rootPart.ScheduleTerseUpdate();
3249 } 3549 }
3250 3550
@@ -3366,7 +3666,7 @@ namespace OpenSim.Region.Framework.Scenes
3366 if (atTargets.Count > 0) 3666 if (atTargets.Count > 0)
3367 { 3667 {
3368 uint[] localids = new uint[0]; 3668 uint[] localids = new uint[0];
3369 lock (m_parts) 3669 lockPartsForRead(true);
3370 { 3670 {
3371 localids = new uint[m_parts.Count]; 3671 localids = new uint[m_parts.Count];
3372 int cntr = 0; 3672 int cntr = 0;
@@ -3376,6 +3676,7 @@ namespace OpenSim.Region.Framework.Scenes
3376 cntr++; 3676 cntr++;
3377 } 3677 }
3378 } 3678 }
3679 lockPartsForRead(false);
3379 3680
3380 for (int ctr = 0; ctr < localids.Length; ctr++) 3681 for (int ctr = 0; ctr < localids.Length; ctr++)
3381 { 3682 {
@@ -3394,7 +3695,7 @@ namespace OpenSim.Region.Framework.Scenes
3394 { 3695 {
3395 //trigger not_at_target 3696 //trigger not_at_target
3396 uint[] localids = new uint[0]; 3697 uint[] localids = new uint[0];
3397 lock (m_parts) 3698 lockPartsForRead(true);
3398 { 3699 {
3399 localids = new uint[m_parts.Count]; 3700 localids = new uint[m_parts.Count];
3400 int cntr = 0; 3701 int cntr = 0;
@@ -3404,7 +3705,8 @@ namespace OpenSim.Region.Framework.Scenes
3404 cntr++; 3705 cntr++;
3405 } 3706 }
3406 } 3707 }
3407 3708 lockPartsForRead(false);
3709
3408 for (int ctr = 0; ctr < localids.Length; ctr++) 3710 for (int ctr = 0; ctr < localids.Length; ctr++)
3409 { 3711 {
3410 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3712 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3445,7 +3747,8 @@ namespace OpenSim.Region.Framework.Scenes
3445 if (atRotTargets.Count > 0) 3747 if (atRotTargets.Count > 0)
3446 { 3748 {
3447 uint[] localids = new uint[0]; 3749 uint[] localids = new uint[0];
3448 lock (m_parts) 3750 lockPartsForRead(true);
3751 try
3449 { 3752 {
3450 localids = new uint[m_parts.Count]; 3753 localids = new uint[m_parts.Count];
3451 int cntr = 0; 3754 int cntr = 0;
@@ -3455,6 +3758,10 @@ namespace OpenSim.Region.Framework.Scenes
3455 cntr++; 3758 cntr++;
3456 } 3759 }
3457 } 3760 }
3761 finally
3762 {
3763 lockPartsForRead(false);
3764 }
3458 3765
3459 for (int ctr = 0; ctr < localids.Length; ctr++) 3766 for (int ctr = 0; ctr < localids.Length; ctr++)
3460 { 3767 {
@@ -3473,7 +3780,8 @@ namespace OpenSim.Region.Framework.Scenes
3473 { 3780 {
3474 //trigger not_at_target 3781 //trigger not_at_target
3475 uint[] localids = new uint[0]; 3782 uint[] localids = new uint[0];
3476 lock (m_parts) 3783 lockPartsForRead(true);
3784 try
3477 { 3785 {
3478 localids = new uint[m_parts.Count]; 3786 localids = new uint[m_parts.Count];
3479 int cntr = 0; 3787 int cntr = 0;
@@ -3483,6 +3791,10 @@ namespace OpenSim.Region.Framework.Scenes
3483 cntr++; 3791 cntr++;
3484 } 3792 }
3485 } 3793 }
3794 finally
3795 {
3796 lockPartsForRead(false);
3797 }
3486 3798
3487 for (int ctr = 0; ctr < localids.Length; ctr++) 3799 for (int ctr = 0; ctr < localids.Length; ctr++)
3488 { 3800 {
@@ -3496,19 +3808,20 @@ namespace OpenSim.Region.Framework.Scenes
3496 public float GetMass() 3808 public float GetMass()
3497 { 3809 {
3498 float retmass = 0f; 3810 float retmass = 0f;
3499 lock (m_parts) 3811 lockPartsForRead(true);
3500 { 3812 {
3501 foreach (SceneObjectPart part in m_parts.Values) 3813 foreach (SceneObjectPart part in m_parts.Values)
3502 { 3814 {
3503 retmass += part.GetMass(); 3815 retmass += part.GetMass();
3504 } 3816 }
3505 } 3817 }
3818 lockPartsForRead(false);
3506 return retmass; 3819 return retmass;
3507 } 3820 }
3508 3821
3509 public void CheckSculptAndLoad() 3822 public void CheckSculptAndLoad()
3510 { 3823 {
3511 lock (m_parts) 3824 lockPartsForRead(true);
3512 { 3825 {
3513 if (!IsDeleted) 3826 if (!IsDeleted)
3514 { 3827 {
@@ -3533,6 +3846,7 @@ namespace OpenSim.Region.Framework.Scenes
3533 } 3846 }
3534 } 3847 }
3535 } 3848 }
3849 lockPartsForRead(false);
3536 } 3850 }
3537 3851
3538 protected void AssetReceived(string id, Object sender, AssetBase asset) 3852 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3553,7 +3867,7 @@ namespace OpenSim.Region.Framework.Scenes
3553 /// <param name="client"></param> 3867 /// <param name="client"></param>
3554 public void SetGroup(UUID GroupID, IClientAPI client) 3868 public void SetGroup(UUID GroupID, IClientAPI client)
3555 { 3869 {
3556 lock (m_parts) 3870 lockPartsForRead(true);
3557 { 3871 {
3558 foreach (SceneObjectPart part in m_parts.Values) 3872 foreach (SceneObjectPart part in m_parts.Values)
3559 { 3873 {
@@ -3563,6 +3877,7 @@ namespace OpenSim.Region.Framework.Scenes
3563 3877
3564 HasGroupChanged = true; 3878 HasGroupChanged = true;
3565 } 3879 }
3880 lockPartsForRead(false);
3566 3881
3567 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3882 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3568 // for the same object with very different properties. The caller must schedule the update. 3883 // for the same object with very different properties. The caller must schedule the update.
@@ -3584,11 +3899,12 @@ namespace OpenSim.Region.Framework.Scenes
3584 3899
3585 public void SetAttachmentPoint(byte point) 3900 public void SetAttachmentPoint(byte point)
3586 { 3901 {
3587 lock (m_parts) 3902 lockPartsForRead(true);
3588 { 3903 {
3589 foreach (SceneObjectPart part in m_parts.Values) 3904 foreach (SceneObjectPart part in m_parts.Values)
3590 part.SetAttachmentPoint(point); 3905 part.SetAttachmentPoint(point);
3591 } 3906 }
3907 lockPartsForRead(false);
3592 } 3908 }
3593 3909
3594 #region ISceneObject 3910 #region ISceneObject
@@ -3622,6 +3938,14 @@ namespace OpenSim.Region.Framework.Scenes
3622 SetFromItemID(uuid); 3938 SetFromItemID(uuid);
3623 } 3939 }
3624 3940
3941 public void ResetOwnerChangeFlag()
3942 {
3943 ForEachPart(delegate(SceneObjectPart part)
3944 {
3945 part.ResetOwnerChangeFlag();
3946 });
3947 }
3948
3625 #endregion 3949 #endregion
3626 } 3950 }
3627} 3951}