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 1ca390a..c48ce3b 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
@@ -1580,10 +1810,11 @@ namespace OpenSim.Region.Framework.Scenes
1580 1810
1581 List<SceneObjectPart> partList; 1811 List<SceneObjectPart> partList;
1582 1812
1583 lock (m_parts) 1813 lockPartsForRead(true);
1584 { 1814
1585 partList = new List<SceneObjectPart>(m_parts.Values); 1815 partList = new List<SceneObjectPart>(m_parts.Values);
1586 } 1816
1817 lockPartsForRead(false);
1587 1818
1588 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1819 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1589 { 1820 {
@@ -1800,13 +2031,40 @@ namespace OpenSim.Region.Framework.Scenes
1800 } 2031 }
1801 } 2032 }
1802 2033
2034 public void rotLookAt(Quaternion target, float strength, float damping)
2035 {
2036 SceneObjectPart rootpart = m_rootPart;
2037 if (rootpart != null)
2038 {
2039 if (IsAttachment)
2040 {
2041 /*
2042 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2043 if (avatar != null)
2044 {
2045 Rotate the Av?
2046 } */
2047 }
2048 else
2049 {
2050 if (rootpart.PhysActor != null)
2051 { // APID must be implemented in your physics system for this to function.
2052 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2053 rootpart.PhysActor.APIDStrength = strength;
2054 rootpart.PhysActor.APIDDamping = damping;
2055 rootpart.PhysActor.APIDActive = true;
2056 }
2057 }
2058 }
2059 }
2060
1803 public void stopLookAt() 2061 public void stopLookAt()
1804 { 2062 {
1805 SceneObjectPart rootpart = m_rootPart; 2063 SceneObjectPart rootpart = m_rootPart;
1806 if (rootpart != null) 2064 if (rootpart != null)
1807 { 2065 {
1808 if (rootpart.PhysActor != null) 2066 if (rootpart.PhysActor != null)
1809 { 2067 { // APID must be implemented in your physics system for this to function.
1810 rootpart.PhysActor.APIDActive = false; 2068 rootpart.PhysActor.APIDActive = false;
1811 } 2069 }
1812 } 2070 }
@@ -1874,10 +2132,11 @@ namespace OpenSim.Region.Framework.Scenes
1874 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2132 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1875 newPart.SetParent(this); 2133 newPart.SetParent(this);
1876 2134
1877 lock (m_parts) 2135 lockPartsForWrite(true);
1878 { 2136 {
1879 m_parts.Add(newPart.UUID, newPart); 2137 m_parts.Add(newPart.UUID, newPart);
1880 } 2138 }
2139 lockPartsForWrite(false);
1881 2140
1882 SetPartAsNonRoot(newPart); 2141 SetPartAsNonRoot(newPart);
1883 2142
@@ -1940,7 +2199,7 @@ namespace OpenSim.Region.Framework.Scenes
1940 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2199 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1941 // return; 2200 // return;
1942 2201
1943 lock (m_parts) 2202 lockPartsForRead(true);
1944 { 2203 {
1945 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2204 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1946 2205
@@ -1960,9 +2219,12 @@ namespace OpenSim.Region.Framework.Scenes
1960 { 2219 {
1961 if (!IsSelected) 2220 if (!IsSelected)
1962 part.UpdateLookAt(); 2221 part.UpdateLookAt();
2222
1963 part.SendScheduledUpdates(); 2223 part.SendScheduledUpdates();
2224
1964 } 2225 }
1965 } 2226 }
2227 lockPartsForRead(false);
1966 } 2228 }
1967 2229
1968 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2230 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
@@ -1971,27 +2233,29 @@ namespace OpenSim.Region.Framework.Scenes
1971 2233
1972 RootPart.AddFullUpdateToAvatar(presence); 2234 RootPart.AddFullUpdateToAvatar(presence);
1973 2235
1974 lock (m_parts) 2236 lockPartsForRead(true);
1975 { 2237 {
1976 foreach (SceneObjectPart part in m_parts.Values) 2238 foreach (SceneObjectPart part in m_parts.Values)
1977 { 2239 {
2240
1978 if (part != RootPart) 2241 if (part != RootPart)
1979 part.AddFullUpdateToAvatar(presence); 2242 part.AddFullUpdateToAvatar(presence);
2243
1980 } 2244 }
1981 } 2245 }
2246 lockPartsForRead(false);
1982 } 2247 }
1983 2248
1984 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2249 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1985 { 2250 {
1986// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 2251 lockPartsForRead(true);
1987 2252
1988 lock (m_parts) 2253 foreach (SceneObjectPart part in m_parts.Values)
1989 { 2254 {
1990 foreach (SceneObjectPart part in m_parts.Values) 2255 part.AddTerseUpdateToAvatar(presence);
1991 {
1992 part.AddTerseUpdateToAvatar(presence);
1993 }
1994 } 2256 }
2257
2258 lockPartsForRead(false);
1995 } 2259 }
1996 2260
1997 /// <summary> 2261 /// <summary>
@@ -1999,20 +2263,23 @@ namespace OpenSim.Region.Framework.Scenes
1999 /// </summary> 2263 /// </summary>
2000 public void ScheduleGroupForFullUpdate() 2264 public void ScheduleGroupForFullUpdate()
2001 { 2265 {
2002 if (IsAttachment) 2266 //if (IsAttachment)
2003 m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); 2267 // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
2004 2268
2005 checkAtTargets(); 2269 checkAtTargets();
2006 RootPart.ScheduleFullUpdate(); 2270 RootPart.ScheduleFullUpdate();
2007 2271
2008 lock (m_parts) 2272 lockPartsForRead(true);
2009 { 2273 {
2010 foreach (SceneObjectPart part in m_parts.Values) 2274 foreach (SceneObjectPart part in m_parts.Values)
2011 { 2275 {
2276
2012 if (part != RootPart) 2277 if (part != RootPart)
2013 part.ScheduleFullUpdate(); 2278 part.ScheduleFullUpdate();
2279
2014 } 2280 }
2015 } 2281 }
2282 lockPartsForRead(false);
2016 } 2283 }
2017 2284
2018 /// <summary> 2285 /// <summary>
@@ -2020,37 +2287,38 @@ namespace OpenSim.Region.Framework.Scenes
2020 /// </summary> 2287 /// </summary>
2021 public void ScheduleGroupForTerseUpdate() 2288 public void ScheduleGroupForTerseUpdate()
2022 { 2289 {
2023// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 2290 lockPartsForRead(true);
2024 2291 foreach (SceneObjectPart part in m_parts.Values)
2025 lock (m_parts)
2026 { 2292 {
2027 foreach (SceneObjectPart part in m_parts.Values) 2293 part.ScheduleTerseUpdate();
2028 {
2029 part.ScheduleTerseUpdate();
2030 }
2031 } 2294 }
2295
2296 lockPartsForRead(false);
2032 } 2297 }
2033 2298
2034 /// <summary> 2299 /// <summary>
2035 /// Immediately send a full update for this scene object. 2300 /// Immediately send a full update for this scene object.
2036 /// </summary> 2301 /// </summary>
2037 public void SendGroupFullUpdate() 2302 public void SendGroupFullUpdate()
2038 { 2303 {
2039 if (IsDeleted) 2304 if (IsDeleted)
2040 return; 2305 return;
2041 2306
2042// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2307// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2043 2308
2044 RootPart.SendFullUpdateToAllClients(); 2309 RootPart.SendFullUpdateToAllClients();
2045 2310
2046 lock (m_parts) 2311 lockPartsForRead(true);
2047 { 2312 {
2048 foreach (SceneObjectPart part in m_parts.Values) 2313 foreach (SceneObjectPart part in m_parts.Values)
2049 { 2314 {
2315
2050 if (part != RootPart) 2316 if (part != RootPart)
2051 part.SendFullUpdateToAllClients(); 2317 part.SendFullUpdateToAllClients();
2318
2052 } 2319 }
2053 } 2320 }
2321 lockPartsForRead(false);
2054 } 2322 }
2055 2323
2056 /// <summary> 2324 /// <summary>
@@ -2082,14 +2350,15 @@ namespace OpenSim.Region.Framework.Scenes
2082 { 2350 {
2083 if (IsDeleted) 2351 if (IsDeleted)
2084 return; 2352 return;
2085 2353
2086 lock (m_parts) 2354 lockPartsForRead(true);
2087 { 2355 {
2088 foreach (SceneObjectPart part in m_parts.Values) 2356 foreach (SceneObjectPart part in m_parts.Values)
2089 { 2357 {
2090 part.SendTerseUpdateToAllClients(); 2358 part.SendTerseUpdateToAllClients();
2091 } 2359 }
2092 } 2360 }
2361 lockPartsForRead(false);
2093 } 2362 }
2094 2363
2095 #endregion 2364 #endregion
@@ -2103,16 +2372,18 @@ namespace OpenSim.Region.Framework.Scenes
2103 /// <returns>null if no child part with that linknum or child part</returns> 2372 /// <returns>null if no child part with that linknum or child part</returns>
2104 public SceneObjectPart GetLinkNumPart(int linknum) 2373 public SceneObjectPart GetLinkNumPart(int linknum)
2105 { 2374 {
2106 lock (m_parts) 2375 lockPartsForRead(true);
2107 { 2376 {
2108 foreach (SceneObjectPart part in m_parts.Values) 2377 foreach (SceneObjectPart part in m_parts.Values)
2109 { 2378 {
2110 if (part.LinkNum == linknum) 2379 if (part.LinkNum == linknum)
2111 { 2380 {
2381 lockPartsForRead(false);
2112 return part; 2382 return part;
2113 } 2383 }
2114 } 2384 }
2115 } 2385 }
2386 lockPartsForRead(false);
2116 2387
2117 return null; 2388 return null;
2118 } 2389 }
@@ -2140,17 +2411,19 @@ namespace OpenSim.Region.Framework.Scenes
2140 public SceneObjectPart GetChildPart(uint localID) 2411 public SceneObjectPart GetChildPart(uint localID)
2141 { 2412 {
2142 //m_log.DebugFormat("Entered looking for {0}", localID); 2413 //m_log.DebugFormat("Entered looking for {0}", localID);
2143 lock (m_parts) 2414 lockPartsForRead(true);
2144 { 2415 {
2145 foreach (SceneObjectPart part in m_parts.Values) 2416 foreach (SceneObjectPart part in m_parts.Values)
2146 { 2417 {
2147 //m_log.DebugFormat("Found {0}", part.LocalId); 2418 //m_log.DebugFormat("Found {0}", part.LocalId);
2148 if (part.LocalId == localID) 2419 if (part.LocalId == localID)
2149 { 2420 {
2421 lockPartsForRead(false);
2150 return part; 2422 return part;
2151 } 2423 }
2152 } 2424 }
2153 } 2425 }
2426 lockPartsForRead(false);
2154 2427
2155 return null; 2428 return null;
2156 } 2429 }
@@ -2180,17 +2453,19 @@ namespace OpenSim.Region.Framework.Scenes
2180 public bool HasChildPrim(uint localID) 2453 public bool HasChildPrim(uint localID)
2181 { 2454 {
2182 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2455 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2183 lock (m_parts) 2456 lockPartsForRead(true);
2184 { 2457 {
2185 foreach (SceneObjectPart part in m_parts.Values) 2458 foreach (SceneObjectPart part in m_parts.Values)
2186 { 2459 {
2187 //m_log.DebugFormat("Found {0}", part.LocalId); 2460 //m_log.DebugFormat("Found {0}", part.LocalId);
2188 if (part.LocalId == localID) 2461 if (part.LocalId == localID)
2189 { 2462 {
2463 lockPartsForRead(false);
2190 return true; 2464 return true;
2191 } 2465 }
2192 } 2466 }
2193 } 2467 }
2468 lockPartsForRead(false);
2194 2469
2195 return false; 2470 return false;
2196 } 2471 }
@@ -2240,53 +2515,57 @@ namespace OpenSim.Region.Framework.Scenes
2240 if (m_rootPart.LinkNum == 0) 2515 if (m_rootPart.LinkNum == 0)
2241 m_rootPart.LinkNum = 1; 2516 m_rootPart.LinkNum = 1;
2242 2517
2243 lock (m_parts) 2518 lockPartsForWrite(true);
2244 { 2519
2245 m_parts.Add(linkPart.UUID, linkPart); 2520 m_parts.Add(linkPart.UUID, linkPart);
2521
2522 lockPartsForWrite(false);
2246 2523
2247 // Insert in terms of link numbers, the new links 2524 // Insert in terms of link numbers, the new links
2248 // before the current ones (with the exception of 2525 // before the current ones (with the exception of
2249 // the root prim. Shuffle the old ones up 2526 // the root prim. Shuffle the old ones up
2250 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2527 lockPartsForRead(true);
2528 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2529 {
2530 if (kvp.Value.LinkNum != 1)
2251 { 2531 {
2252 if (kvp.Value.LinkNum != 1) 2532 // Don't update root prim link number
2253 { 2533 kvp.Value.LinkNum += objectGroup.PrimCount;
2254 // Don't update root prim link number
2255 kvp.Value.LinkNum += objectGroup.PrimCount;
2256 }
2257 } 2534 }
2535 }
2536 lockPartsForRead(false);
2258 2537
2259 linkPart.LinkNum = 2; 2538 linkPart.LinkNum = 2;
2260 2539
2261 linkPart.SetParent(this); 2540 linkPart.SetParent(this);
2262 linkPart.CreateSelected = true; 2541 linkPart.CreateSelected = true;
2263 2542
2264 //if (linkPart.PhysActor != null) 2543 //if (linkPart.PhysActor != null)
2265 //{ 2544 //{
2266 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2545 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2267 2546
2268 //linkPart.PhysActor = null; 2547 //linkPart.PhysActor = null;
2269 //} 2548 //}
2270 2549
2271 //TODO: rest of parts 2550 //TODO: rest of parts
2272 int linkNum = 3; 2551 int linkNum = 3;
2273 foreach (SceneObjectPart part in objectGroup.Children.Values) 2552 foreach (SceneObjectPart part in objectGroup.Children.Values)
2553 {
2554 if (part.UUID != objectGroup.m_rootPart.UUID)
2274 { 2555 {
2275 if (part.UUID != objectGroup.m_rootPart.UUID) 2556 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2276 {
2277 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2278 }
2279 part.ClearUndoState();
2280 } 2557 }
2558 part.ClearUndoState();
2281 } 2559 }
2282 2560
2283 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2561 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2284 objectGroup.m_isDeleted = true; 2562 objectGroup.m_isDeleted = true;
2563
2564 objectGroup.lockPartsForWrite(true);
2285 2565
2286 lock (objectGroup.m_parts) 2566 objectGroup.m_parts.Clear();
2287 { 2567
2288 objectGroup.m_parts.Clear(); 2568 objectGroup.lockPartsForWrite(false);
2289 }
2290 2569
2291 // Can't do this yet since backup still makes use of the root part without any synchronization 2570 // Can't do this yet since backup still makes use of the root part without any synchronization
2292// objectGroup.m_rootPart = null; 2571// objectGroup.m_rootPart = null;
@@ -2356,11 +2635,12 @@ namespace OpenSim.Region.Framework.Scenes
2356 Quaternion worldRot = linkPart.GetWorldRotation(); 2635 Quaternion worldRot = linkPart.GetWorldRotation();
2357 2636
2358 // Remove the part from this object 2637 // Remove the part from this object
2359 lock (m_parts) 2638 lockPartsForWrite(true);
2360 { 2639 {
2361 m_parts.Remove(linkPart.UUID); 2640 m_parts.Remove(linkPart.UUID);
2362 } 2641 }
2363 2642 lockPartsForWrite(false);
2643 lockPartsForRead(true);
2364 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2644 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2365 RootPart.LinkNum = 0; 2645 RootPart.LinkNum = 0;
2366 else 2646 else
@@ -2371,6 +2651,7 @@ namespace OpenSim.Region.Framework.Scenes
2371 p.LinkNum--; 2651 p.LinkNum--;
2372 } 2652 }
2373 } 2653 }
2654 lockPartsForRead(false);
2374 2655
2375 linkPart.ParentID = 0; 2656 linkPart.ParentID = 0;
2376 linkPart.LinkNum = 0; 2657 linkPart.LinkNum = 0;
@@ -2414,6 +2695,8 @@ namespace OpenSim.Region.Framework.Scenes
2414 /// <param name="objectGroup"></param> 2695 /// <param name="objectGroup"></param>
2415 public virtual void DetachFromBackup() 2696 public virtual void DetachFromBackup()
2416 { 2697 {
2698 m_scene.SceneGraph.FireDetachFromBackup(this);
2699
2417 if (m_isBackedUp) 2700 if (m_isBackedUp)
2418 m_scene.EventManager.OnBackup -= ProcessBackup; 2701 m_scene.EventManager.OnBackup -= ProcessBackup;
2419 2702
@@ -2692,9 +2975,12 @@ namespace OpenSim.Region.Framework.Scenes
2692 2975
2693 if (selectionPart != null) 2976 if (selectionPart != null)
2694 { 2977 {
2695 lock (m_parts) 2978 lockPartsForRead(true);
2979 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2980 lockPartsForRead(false);
2981 foreach (SceneObjectPart part in parts)
2696 { 2982 {
2697 foreach (SceneObjectPart part in m_parts.Values) 2983 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2698 { 2984 {
2699 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2985 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2700 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2986 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2704,12 +2990,13 @@ namespace OpenSim.Region.Framework.Scenes
2704 break; 2990 break;
2705 } 2991 }
2706 } 2992 }
2993 }
2707 2994
2708 foreach (SceneObjectPart part in m_parts.Values) 2995 foreach (SceneObjectPart part in parts)
2709 { 2996 {
2710 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2997 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2711 }
2712 } 2998 }
2999
2713 } 3000 }
2714 } 3001 }
2715 3002
@@ -2722,6 +3009,17 @@ namespace OpenSim.Region.Framework.Scenes
2722 } 3009 }
2723 } 3010 }
2724 3011
3012
3013
3014 /// <summary>
3015 /// Gets the number of parts
3016 /// </summary>
3017 /// <returns></returns>
3018 public int GetPartCount()
3019 {
3020 return Children.Count;
3021 }
3022
2725 /// <summary> 3023 /// <summary>
2726 /// Get the parts of this scene object 3024 /// Get the parts of this scene object
2727 /// </summary> 3025 /// </summary>
@@ -2795,11 +3093,9 @@ namespace OpenSim.Region.Framework.Scenes
2795 scale.Y = m_scene.m_maxNonphys; 3093 scale.Y = m_scene.m_maxNonphys;
2796 if (scale.Z > m_scene.m_maxNonphys) 3094 if (scale.Z > m_scene.m_maxNonphys)
2797 scale.Z = m_scene.m_maxNonphys; 3095 scale.Z = m_scene.m_maxNonphys;
2798
2799 SceneObjectPart part = GetChildPart(localID); 3096 SceneObjectPart part = GetChildPart(localID);
2800 if (part != null) 3097 if (part != null)
2801 { 3098 {
2802 part.Resize(scale);
2803 if (part.PhysActor != null) 3099 if (part.PhysActor != null)
2804 { 3100 {
2805 if (part.PhysActor.IsPhysical) 3101 if (part.PhysActor.IsPhysical)
@@ -2814,7 +3110,7 @@ namespace OpenSim.Region.Framework.Scenes
2814 part.PhysActor.Size = scale; 3110 part.PhysActor.Size = scale;
2815 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3111 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2816 } 3112 }
2817 //if (part.UUID != m_rootPart.UUID) 3113 part.Resize(scale);
2818 3114
2819 HasGroupChanged = true; 3115 HasGroupChanged = true;
2820 ScheduleGroupForFullUpdate(); 3116 ScheduleGroupForFullUpdate();
@@ -2856,73 +3152,71 @@ namespace OpenSim.Region.Framework.Scenes
2856 float y = (scale.Y / part.Scale.Y); 3152 float y = (scale.Y / part.Scale.Y);
2857 float z = (scale.Z / part.Scale.Z); 3153 float z = (scale.Z / part.Scale.Z);
2858 3154
2859 lock (m_parts) 3155 lockPartsForRead(true);
3156 if (x > 1.0f || y > 1.0f || z > 1.0f)
2860 { 3157 {
2861 if (x > 1.0f || y > 1.0f || z > 1.0f) 3158 foreach (SceneObjectPart obPart in m_parts.Values)
2862 { 3159 {
2863 foreach (SceneObjectPart obPart in m_parts.Values) 3160 if (obPart.UUID != m_rootPart.UUID)
2864 { 3161 {
2865 if (obPart.UUID != m_rootPart.UUID) 3162 Vector3 oldSize = new Vector3(obPart.Scale);
2866 { 3163 obPart.IgnoreUndoUpdate = true;
2867 obPart.IgnoreUndoUpdate = true;
2868 Vector3 oldSize = new Vector3(obPart.Scale);
2869 3164
2870 float f = 1.0f; 3165 float f = 1.0f;
2871 float a = 1.0f; 3166 float a = 1.0f;
2872 3167
2873 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3168 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3169 {
3170 if (oldSize.X*x > m_scene.m_maxPhys)
2874 { 3171 {
2875 if (oldSize.X*x > m_scene.m_maxPhys) 3172 f = m_scene.m_maxPhys / oldSize.X;
2876 { 3173 a = f / x;
2877 f = m_scene.m_maxPhys / oldSize.X; 3174 x *= a;
2878 a = f / x; 3175 y *= a;
2879 x *= a; 3176 z *= a;
2880 y *= a;
2881 z *= a;
2882 }
2883 if (oldSize.Y*y > m_scene.m_maxPhys)
2884 {
2885 f = m_scene.m_maxPhys / oldSize.Y;
2886 a = f / y;
2887 x *= a;
2888 y *= a;
2889 z *= a;
2890 }
2891 if (oldSize.Z*z > m_scene.m_maxPhys)
2892 {
2893 f = m_scene.m_maxPhys / oldSize.Z;
2894 a = f / z;
2895 x *= a;
2896 y *= a;
2897 z *= a;
2898 }
2899 } 3177 }
2900 else 3178 if (oldSize.Y*y > m_scene.m_maxPhys)
2901 { 3179 {
2902 if (oldSize.X*x > m_scene.m_maxNonphys) 3180 f = m_scene.m_maxPhys / oldSize.Y;
2903 { 3181 a = f / y;
2904 f = m_scene.m_maxNonphys / oldSize.X; 3182 x *= a;
2905 a = f / x; 3183 y *= a;
2906 x *= a; 3184 z *= a;
2907 y *= a; 3185 }
2908 z *= a; 3186 if (oldSize.Z*z > m_scene.m_maxPhys)
2909 } 3187 {
2910 if (oldSize.Y*y > m_scene.m_maxNonphys) 3188 f = m_scene.m_maxPhys / oldSize.Z;
2911 { 3189 a = f / z;
2912 f = m_scene.m_maxNonphys / oldSize.Y; 3190 x *= a;
2913 a = f / y; 3191 y *= a;
2914 x *= a; 3192 z *= a;
2915 y *= a; 3193 }
2916 z *= a; 3194 }
2917 } 3195 else
2918 if (oldSize.Z*z > m_scene.m_maxNonphys) 3196 {
2919 { 3197 if (oldSize.X*x > m_scene.m_maxNonphys)
2920 f = m_scene.m_maxNonphys / oldSize.Z; 3198 {
2921 a = f / z; 3199 f = m_scene.m_maxNonphys / oldSize.X;
2922 x *= a; 3200 a = f / x;
2923 y *= a; 3201 x *= a;
2924 z *= a; 3202 y *= a;
2925 } 3203 z *= a;
3204 }
3205 if (oldSize.Y*y > m_scene.m_maxNonphys)
3206 {
3207 f = m_scene.m_maxNonphys / oldSize.Y;
3208 a = f / y;
3209 x *= a;
3210 y *= a;
3211 z *= a;
3212 }
3213 if (oldSize.Z*z > m_scene.m_maxNonphys)
3214 {
3215 f = m_scene.m_maxNonphys / oldSize.Z;
3216 a = f / z;
3217 x *= a;
3218 y *= a;
3219 z *= a;
2926 } 3220 }
2927 obPart.IgnoreUndoUpdate = false; 3221 obPart.IgnoreUndoUpdate = false;
2928 obPart.StoreUndoState(); 3222 obPart.StoreUndoState();
@@ -2930,6 +3224,7 @@ namespace OpenSim.Region.Framework.Scenes
2930 } 3224 }
2931 } 3225 }
2932 } 3226 }
3227 lockPartsForRead(false);
2933 3228
2934 Vector3 prevScale = part.Scale; 3229 Vector3 prevScale = part.Scale;
2935 prevScale.X *= x; 3230 prevScale.X *= x;
@@ -2937,7 +3232,7 @@ namespace OpenSim.Region.Framework.Scenes
2937 prevScale.Z *= z; 3232 prevScale.Z *= z;
2938 part.Resize(prevScale); 3233 part.Resize(prevScale);
2939 3234
2940 lock (m_parts) 3235 lockPartsForRead(true);
2941 { 3236 {
2942 foreach (SceneObjectPart obPart in m_parts.Values) 3237 foreach (SceneObjectPart obPart in m_parts.Values)
2943 { 3238 {
@@ -2959,6 +3254,7 @@ namespace OpenSim.Region.Framework.Scenes
2959 obPart.StoreUndoState(); 3254 obPart.StoreUndoState();
2960 } 3255 }
2961 } 3256 }
3257 lockPartsForRead(false);
2962 3258
2963 if (part.PhysActor != null) 3259 if (part.PhysActor != null)
2964 { 3260 {
@@ -3061,7 +3357,7 @@ namespace OpenSim.Region.Framework.Scenes
3061 axDiff *= Quaternion.Inverse(partRotation); 3357 axDiff *= Quaternion.Inverse(partRotation);
3062 diff = axDiff; 3358 diff = axDiff;
3063 3359
3064 lock (m_parts) 3360 lockPartsForRead(true);
3065 { 3361 {
3066 foreach (SceneObjectPart obPart in m_parts.Values) 3362 foreach (SceneObjectPart obPart in m_parts.Values)
3067 { 3363 {
@@ -3071,6 +3367,7 @@ namespace OpenSim.Region.Framework.Scenes
3071 } 3367 }
3072 } 3368 }
3073 } 3369 }
3370 lockPartsForRead(false);
3074 3371
3075 AbsolutePosition = newPos; 3372 AbsolutePosition = newPos;
3076 3373
@@ -3204,25 +3501,25 @@ namespace OpenSim.Region.Framework.Scenes
3204 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3501 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3205 } 3502 }
3206 3503
3207 lock (m_parts) 3504 lockPartsForRead(true);
3505
3506 foreach (SceneObjectPart prim in m_parts.Values)
3208 { 3507 {
3209 foreach (SceneObjectPart prim in m_parts.Values) 3508 if (prim.UUID != m_rootPart.UUID)
3210 { 3509 {
3211 if (prim.UUID != m_rootPart.UUID) 3510 prim.IgnoreUndoUpdate = true;
3212 { 3511 Vector3 axPos = prim.OffsetPosition;
3213 prim.IgnoreUndoUpdate = true; 3512 axPos *= oldParentRot;
3214 Vector3 axPos = prim.OffsetPosition; 3513 axPos *= Quaternion.Inverse(axRot);
3215 axPos *= oldParentRot; 3514 prim.OffsetPosition = axPos;
3216 axPos *= Quaternion.Inverse(axRot); 3515 Quaternion primsRot = prim.RotationOffset;
3217 prim.OffsetPosition = axPos; 3516 Quaternion newRot = primsRot * oldParentRot;
3218 Quaternion primsRot = prim.RotationOffset; 3517 newRot *= Quaternion.Inverse(axRot);
3219 Quaternion newRot = primsRot * oldParentRot; 3518 prim.RotationOffset = newRot;
3220 newRot *= Quaternion.Inverse(axRot); 3519 prim.ScheduleTerseUpdate();
3221 prim.RotationOffset = newRot;
3222 prim.ScheduleTerseUpdate();
3223 }
3224 } 3520 }
3225 } 3521 }
3522
3226 foreach (SceneObjectPart childpart in Children.Values) 3523 foreach (SceneObjectPart childpart in Children.Values)
3227 { 3524 {
3228 if (childpart != m_rootPart) 3525 if (childpart != m_rootPart)
@@ -3231,6 +3528,9 @@ namespace OpenSim.Region.Framework.Scenes
3231 childpart.StoreUndoState(); 3528 childpart.StoreUndoState();
3232 } 3529 }
3233 } 3530 }
3531
3532 lockPartsForRead(false);
3533
3234 m_rootPart.ScheduleTerseUpdate(); 3534 m_rootPart.ScheduleTerseUpdate();
3235 } 3535 }
3236 3536
@@ -3352,7 +3652,7 @@ namespace OpenSim.Region.Framework.Scenes
3352 if (atTargets.Count > 0) 3652 if (atTargets.Count > 0)
3353 { 3653 {
3354 uint[] localids = new uint[0]; 3654 uint[] localids = new uint[0];
3355 lock (m_parts) 3655 lockPartsForRead(true);
3356 { 3656 {
3357 localids = new uint[m_parts.Count]; 3657 localids = new uint[m_parts.Count];
3358 int cntr = 0; 3658 int cntr = 0;
@@ -3362,6 +3662,7 @@ namespace OpenSim.Region.Framework.Scenes
3362 cntr++; 3662 cntr++;
3363 } 3663 }
3364 } 3664 }
3665 lockPartsForRead(false);
3365 3666
3366 for (int ctr = 0; ctr < localids.Length; ctr++) 3667 for (int ctr = 0; ctr < localids.Length; ctr++)
3367 { 3668 {
@@ -3380,7 +3681,7 @@ namespace OpenSim.Region.Framework.Scenes
3380 { 3681 {
3381 //trigger not_at_target 3682 //trigger not_at_target
3382 uint[] localids = new uint[0]; 3683 uint[] localids = new uint[0];
3383 lock (m_parts) 3684 lockPartsForRead(true);
3384 { 3685 {
3385 localids = new uint[m_parts.Count]; 3686 localids = new uint[m_parts.Count];
3386 int cntr = 0; 3687 int cntr = 0;
@@ -3390,7 +3691,8 @@ namespace OpenSim.Region.Framework.Scenes
3390 cntr++; 3691 cntr++;
3391 } 3692 }
3392 } 3693 }
3393 3694 lockPartsForRead(false);
3695
3394 for (int ctr = 0; ctr < localids.Length; ctr++) 3696 for (int ctr = 0; ctr < localids.Length; ctr++)
3395 { 3697 {
3396 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3698 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3431,7 +3733,8 @@ namespace OpenSim.Region.Framework.Scenes
3431 if (atRotTargets.Count > 0) 3733 if (atRotTargets.Count > 0)
3432 { 3734 {
3433 uint[] localids = new uint[0]; 3735 uint[] localids = new uint[0];
3434 lock (m_parts) 3736 lockPartsForRead(true);
3737 try
3435 { 3738 {
3436 localids = new uint[m_parts.Count]; 3739 localids = new uint[m_parts.Count];
3437 int cntr = 0; 3740 int cntr = 0;
@@ -3441,6 +3744,10 @@ namespace OpenSim.Region.Framework.Scenes
3441 cntr++; 3744 cntr++;
3442 } 3745 }
3443 } 3746 }
3747 finally
3748 {
3749 lockPartsForRead(false);
3750 }
3444 3751
3445 for (int ctr = 0; ctr < localids.Length; ctr++) 3752 for (int ctr = 0; ctr < localids.Length; ctr++)
3446 { 3753 {
@@ -3459,7 +3766,8 @@ namespace OpenSim.Region.Framework.Scenes
3459 { 3766 {
3460 //trigger not_at_target 3767 //trigger not_at_target
3461 uint[] localids = new uint[0]; 3768 uint[] localids = new uint[0];
3462 lock (m_parts) 3769 lockPartsForRead(true);
3770 try
3463 { 3771 {
3464 localids = new uint[m_parts.Count]; 3772 localids = new uint[m_parts.Count];
3465 int cntr = 0; 3773 int cntr = 0;
@@ -3469,6 +3777,10 @@ namespace OpenSim.Region.Framework.Scenes
3469 cntr++; 3777 cntr++;
3470 } 3778 }
3471 } 3779 }
3780 finally
3781 {
3782 lockPartsForRead(false);
3783 }
3472 3784
3473 for (int ctr = 0; ctr < localids.Length; ctr++) 3785 for (int ctr = 0; ctr < localids.Length; ctr++)
3474 { 3786 {
@@ -3482,19 +3794,20 @@ namespace OpenSim.Region.Framework.Scenes
3482 public float GetMass() 3794 public float GetMass()
3483 { 3795 {
3484 float retmass = 0f; 3796 float retmass = 0f;
3485 lock (m_parts) 3797 lockPartsForRead(true);
3486 { 3798 {
3487 foreach (SceneObjectPart part in m_parts.Values) 3799 foreach (SceneObjectPart part in m_parts.Values)
3488 { 3800 {
3489 retmass += part.GetMass(); 3801 retmass += part.GetMass();
3490 } 3802 }
3491 } 3803 }
3804 lockPartsForRead(false);
3492 return retmass; 3805 return retmass;
3493 } 3806 }
3494 3807
3495 public void CheckSculptAndLoad() 3808 public void CheckSculptAndLoad()
3496 { 3809 {
3497 lock (m_parts) 3810 lockPartsForRead(true);
3498 { 3811 {
3499 if (!IsDeleted) 3812 if (!IsDeleted)
3500 { 3813 {
@@ -3519,6 +3832,7 @@ namespace OpenSim.Region.Framework.Scenes
3519 } 3832 }
3520 } 3833 }
3521 } 3834 }
3835 lockPartsForRead(false);
3522 } 3836 }
3523 3837
3524 protected void AssetReceived(string id, Object sender, AssetBase asset) 3838 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3539,7 +3853,7 @@ namespace OpenSim.Region.Framework.Scenes
3539 /// <param name="client"></param> 3853 /// <param name="client"></param>
3540 public void SetGroup(UUID GroupID, IClientAPI client) 3854 public void SetGroup(UUID GroupID, IClientAPI client)
3541 { 3855 {
3542 lock (m_parts) 3856 lockPartsForRead(true);
3543 { 3857 {
3544 foreach (SceneObjectPart part in m_parts.Values) 3858 foreach (SceneObjectPart part in m_parts.Values)
3545 { 3859 {
@@ -3549,6 +3863,7 @@ namespace OpenSim.Region.Framework.Scenes
3549 3863
3550 HasGroupChanged = true; 3864 HasGroupChanged = true;
3551 } 3865 }
3866 lockPartsForRead(false);
3552 3867
3553 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3868 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3554 // for the same object with very different properties. The caller must schedule the update. 3869 // for the same object with very different properties. The caller must schedule the update.
@@ -3570,11 +3885,12 @@ namespace OpenSim.Region.Framework.Scenes
3570 3885
3571 public void SetAttachmentPoint(byte point) 3886 public void SetAttachmentPoint(byte point)
3572 { 3887 {
3573 lock (m_parts) 3888 lockPartsForRead(true);
3574 { 3889 {
3575 foreach (SceneObjectPart part in m_parts.Values) 3890 foreach (SceneObjectPart part in m_parts.Values)
3576 part.SetAttachmentPoint(point); 3891 part.SetAttachmentPoint(point);
3577 } 3892 }
3893 lockPartsForRead(false);
3578 } 3894 }
3579 3895
3580 #region ISceneObject 3896 #region ISceneObject
@@ -3608,6 +3924,14 @@ namespace OpenSim.Region.Framework.Scenes
3608 SetFromItemID(uuid); 3924 SetFromItemID(uuid);
3609 } 3925 }
3610 3926
3927 public void ResetOwnerChangeFlag()
3928 {
3929 ForEachPart(delegate(SceneObjectPart part)
3930 {
3931 part.ResetOwnerChangeFlag();
3932 });
3933 }
3934
3611 #endregion 3935 #endregion
3612 } 3936 }
3613} 3937}