aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Data/MSSQL/MSSQLSimulationData.cs4
-rw-r--r--OpenSim/Data/MySQL/MySQLSimulationData.cs2
-rw-r--r--OpenSim/Data/SQLite/SQLiteSimulationData.cs2
-rw-r--r--OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs2
-rw-r--r--OpenSim/Data/Tests/RegionTests.cs14
-rw-r--r--OpenSim/Framework/MapAndArray.cs188
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs7
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs53
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs58
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs1409
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs5
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs19
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs35
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs9
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs169
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs45
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs91
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs11
-rw-r--r--OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs2
32 files changed, 1057 insertions, 1204 deletions
diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
index 8eae0a2..1da52b4 100644
--- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
@@ -241,7 +241,7 @@ namespace OpenSim.Data.MSSQL
241 /// <param name="regionUUID"></param> 241 /// <param name="regionUUID"></param>
242 public void StoreObject(SceneObjectGroup obj, UUID regionUUID) 242 public void StoreObject(SceneObjectGroup obj, UUID regionUUID)
243 { 243 {
244 _Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Children.Count); 244 _Log.DebugFormat("[MSSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Parts.Length);
245 245
246 using (SqlConnection conn = new SqlConnection(m_connectionString)) 246 using (SqlConnection conn = new SqlConnection(m_connectionString))
247 { 247 {
@@ -250,7 +250,7 @@ namespace OpenSim.Data.MSSQL
250 250
251 try 251 try
252 { 252 {
253 foreach (SceneObjectPart sceneObjectPart in obj.Children.Values) 253 foreach (SceneObjectPart sceneObjectPart in obj.Parts)
254 { 254 {
255 //Update prim 255 //Update prim
256 using (SqlCommand sqlCommand = conn.CreateCommand()) 256 using (SqlCommand sqlCommand = conn.CreateCommand())
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index 87f6d07..3450e2f 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -144,7 +144,7 @@ namespace OpenSim.Data.MySQL
144 dbcon.Open(); 144 dbcon.Open();
145 MySqlCommand cmd = dbcon.CreateCommand(); 145 MySqlCommand cmd = dbcon.CreateCommand();
146 146
147 foreach (SceneObjectPart prim in obj.Children.Values) 147 foreach (SceneObjectPart prim in obj.Parts)
148 { 148 {
149 cmd.Parameters.Clear(); 149 cmd.Parameters.Clear();
150 150
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index 3e9bc3f..ebe6da8 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -368,7 +368,7 @@ namespace OpenSim.Data.SQLite
368 368
369 lock (ds) 369 lock (ds)
370 { 370 {
371 foreach (SceneObjectPart prim in obj.Children.Values) 371 foreach (SceneObjectPart prim in obj.Parts)
372 { 372 {
373// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); 373// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID);
374 addPrim(prim, obj.UUID, regionUUID); 374 addPrim(prim, obj.UUID, regionUUID);
diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs
index 2dde926..ce18a42 100644
--- a/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLiteLegacy/SQLiteSimulationData.cs
@@ -335,7 +335,7 @@ namespace OpenSim.Data.SQLiteLegacy
335 335
336 lock (ds) 336 lock (ds)
337 { 337 {
338 foreach (SceneObjectPart prim in obj.Children.Values) 338 foreach (SceneObjectPart prim in obj.Parts)
339 { 339 {
340// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); 340// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID);
341 addPrim(prim, obj.UUID, regionUUID); 341 addPrim(prim, obj.UUID, regionUUID);
diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs
index a081462..23d498d 100644
--- a/OpenSim/Data/Tests/RegionTests.cs
+++ b/OpenSim/Data/Tests/RegionTests.cs
@@ -232,15 +232,15 @@ namespace OpenSim.Data.Tests
232 sog.AddPart(p2); 232 sog.AddPart(p2);
233 sog.AddPart(p3); 233 sog.AddPart(p3);
234 234
235 SceneObjectPart[] parts = sog.GetParts(); 235 SceneObjectPart[] parts = sog.Parts;
236 Assert.That(parts.Length,Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))"); 236 Assert.That(parts.Length,Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))");
237 237
238 db.StoreObject(sog, newregion); 238 db.StoreObject(sog, newregion);
239 List<SceneObjectGroup> sogs = db.LoadObjects(newregion); 239 List<SceneObjectGroup> sogs = db.LoadObjects(newregion);
240 Assert.That(sogs.Count,Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))"); 240 Assert.That(sogs.Count,Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))");
241 SceneObjectGroup newsog = sogs[0]; 241 SceneObjectGroup newsog = sogs[0];
242 242
243 SceneObjectPart[] newparts = newsog.GetParts(); 243 SceneObjectPart[] newparts = newsog.Parts;
244 Assert.That(newparts.Length,Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))"); 244 Assert.That(newparts.Length,Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))");
245 245
246 Assert.That(newsog.HasChildPrim(tmp0), "Assert.That(newsog.HasChildPrim(tmp0))"); 246 Assert.That(newsog.HasChildPrim(tmp0), "Assert.That(newsog.HasChildPrim(tmp0))");
@@ -560,7 +560,7 @@ namespace OpenSim.Data.Tests
560 } 560 }
561 561
562 SceneObjectGroup retsog = FindSOG("Test SOG", region4); 562 SceneObjectGroup retsog = FindSOG("Test SOG", region4);
563 SceneObjectPart[] parts = retsog.GetParts(); 563 SceneObjectPart[] parts = retsog.Parts;
564 for (int i=0;i<30;i++) 564 for (int i=0;i<30;i++)
565 { 565 {
566 SceneObjectPart cursop = mydic[parts[i].UUID]; 566 SceneObjectPart cursop = mydic[parts[i].UUID];
@@ -607,7 +607,7 @@ namespace OpenSim.Data.Tests
607 sog.AddPart(p2); 607 sog.AddPart(p2);
608 sog.AddPart(p3); 608 sog.AddPart(p3);
609 609
610 SceneObjectPart[] parts = sog.GetParts(); 610 SceneObjectPart[] parts = sog.Parts;
611 Assert.That(parts.Length, Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))"); 611 Assert.That(parts.Length, Is.EqualTo(4), "Assert.That(parts.Length,Is.EqualTo(4))");
612 612
613 db.StoreObject(sog, newregion); 613 db.StoreObject(sog, newregion);
@@ -615,7 +615,7 @@ namespace OpenSim.Data.Tests
615 Assert.That(sogs.Count, Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))"); 615 Assert.That(sogs.Count, Is.EqualTo(1), "Assert.That(sogs.Count,Is.EqualTo(1))");
616 SceneObjectGroup newsog = sogs[0]; 616 SceneObjectGroup newsog = sogs[0];
617 617
618 SceneObjectPart[] newparts = newsog.GetParts(); 618 SceneObjectPart[] newparts = newsog.Parts;
619 Assert.That(newparts.Length, Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))"); 619 Assert.That(newparts.Length, Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))");
620 620
621 Assert.That(newsog, Constraints.PropertyCompareConstraint(sog) 621 Assert.That(newsog, Constraints.PropertyCompareConstraint(sog)
@@ -625,7 +625,7 @@ namespace OpenSim.Data.Tests
625 .IgnoreProperty(x=>x.RegionHandle) 625 .IgnoreProperty(x=>x.RegionHandle)
626 .IgnoreProperty(x=>x.RegionUUID) 626 .IgnoreProperty(x=>x.RegionUUID)
627 .IgnoreProperty(x=>x.Scene) 627 .IgnoreProperty(x=>x.Scene)
628 .IgnoreProperty(x=>x.Children) 628 .IgnoreProperty(x=>x.Parts)
629 .IgnoreProperty(x=>x.PassCollision) 629 .IgnoreProperty(x=>x.PassCollision)
630 .IgnoreProperty(x=>x.RootPart)); 630 .IgnoreProperty(x=>x.RootPart));
631 } 631 }
diff --git a/OpenSim/Framework/MapAndArray.cs b/OpenSim/Framework/MapAndArray.cs
new file mode 100644
index 0000000..bbe6a9e
--- /dev/null
+++ b/OpenSim/Framework/MapAndArray.cs
@@ -0,0 +1,188 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30
31namespace OpenSim.Framework
32{
33 /// <summary>
34 /// Stores two synchronized collections: a mutable dictionary and an
35 /// immutable array. Slower inserts/removes than a normal dictionary,
36 /// but provides safe iteration while maintaining fast hash lookups
37 /// </summary>
38 /// <typeparam name="TKey">Key type to use for hash lookups</typeparam>
39 /// <typeparam name="TValue">Value type to store</typeparam>
40 public sealed class MapAndArray<TKey, TValue>
41 {
42 private Dictionary<TKey, TValue> m_dict;
43 private TValue[] m_array;
44 private object m_syncRoot = new object();
45
46 /// <summary>Number of values currently stored in the collection</summary>
47 public int Count { get { return m_array.Length; } }
48 /// <summary>NOTE: This collection is thread safe. You do not need to
49 /// acquire a lock to add, remove, or enumerate entries. This
50 /// synchronization object should only be locked for larger
51 /// transactions</summary>
52 public object SyncRoot { get { return m_syncRoot; } }
53
54 /// <summary>
55 /// Constructor
56 /// </summary>
57 public MapAndArray()
58 {
59 m_dict = new Dictionary<TKey, TValue>();
60 m_array = new TValue[0];
61 }
62
63 /// <summary>
64 /// Constructor
65 /// </summary>
66 /// <param name="capacity">Initial capacity of the dictionary</param>
67 public MapAndArray(int capacity)
68 {
69 m_dict = new Dictionary<TKey, TValue>(capacity);
70 m_array = new TValue[0];
71 }
72
73 /// <summary>
74 /// Adds a key/value pair to the collection, or updates an existing key
75 /// with a new value
76 /// </summary>
77 /// <param name="key">Key to add or update</param>
78 /// <param name="value">Value to add</param>
79 /// <returns>True if a new key was added, false if an existing key was
80 /// updated</returns>
81 public bool AddOrReplace(TKey key, TValue value)
82 {
83 lock (m_syncRoot)
84 {
85 bool containedKey = m_dict.ContainsKey(key);
86
87 m_dict[key] = value;
88 CreateArray();
89
90 return !containedKey;
91 }
92 }
93
94 /// <summary>
95 /// Adds a key/value pair to the collection. This will throw an
96 /// exception if the key is already present in the collection
97 /// </summary>
98 /// <param name="key">Key to add or update</param>
99 /// <param name="value">Value to add</param>
100 /// <returns>Index of the inserted item</returns>
101 public int Add(TKey key, TValue value)
102 {
103 lock (m_syncRoot)
104 {
105 m_dict.Add(key, value);
106 CreateArray();
107 return m_array.Length;
108 }
109 }
110
111 /// <summary>
112 /// Removes a key/value pair from the collection
113 /// </summary>
114 /// <param name="key">Key to remove</param>
115 /// <returns>True if the key was found and removed, otherwise false</returns>
116 public bool Remove(TKey key)
117 {
118 lock (m_syncRoot)
119 {
120 bool removed = m_dict.Remove(key);
121 CreateArray();
122
123 return removed;
124 }
125 }
126
127 /// <summary>
128 /// Determines whether the collections contains a specified key
129 /// </summary>
130 /// <param name="key">Key to search for</param>
131 /// <returns>True if the key was found, otherwise false</returns>
132 public bool ContainsKey(TKey key)
133 {
134 return m_dict.ContainsKey(key);
135 }
136
137 /// <summary>
138 /// Gets the value associated with the specified key
139 /// </summary>
140 /// <param name="key">Key of the value to get</param>
141 /// <param name="value">Will contain the value associated with the
142 /// given key if the key is found. If the key is not found it will
143 /// contain the default value for the type of the value parameter</param>
144 /// <returns>True if the key was found and a value was retrieved,
145 /// otherwise false</returns>
146 public bool TryGetValue(TKey key, out TValue value)
147 {
148 lock (m_syncRoot)
149 return m_dict.TryGetValue(key, out value);
150 }
151
152 /// <summary>
153 /// Clears all key/value pairs from the collection
154 /// </summary>
155 public void Clear()
156 {
157 lock (m_syncRoot)
158 {
159 m_dict = new Dictionary<TKey, TValue>();
160 m_array = new TValue[0];
161 }
162 }
163
164 /// <summary>
165 /// Gets a reference to the immutable array of values stored in this
166 /// collection. This array is thread safe for iteration
167 /// </summary>
168 /// <returns>A thread safe reference ton an array of all of the stored
169 /// values</returns>
170 public TValue[] GetArray()
171 {
172 return m_array;
173 }
174
175 private void CreateArray()
176 {
177 // Rebuild the array from the dictionary. This method must be
178 // called from inside a lock
179 TValue[] array = new TValue[m_dict.Count];
180 int i = 0;
181
182 foreach (TValue value in m_dict.Values)
183 array[i++] = value;
184
185 m_array = array;
186 }
187 }
188}
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 1ebac42..cb39e46 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -567,13 +567,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
567 so.RootPart.AttachedAvatar = avatar.UUID; 567 so.RootPart.AttachedAvatar = avatar.UUID;
568 568
569 //Anakin Lohner bug #3839 569 //Anakin Lohner bug #3839
570 lock (so.Children) 570 SceneObjectPart[] parts = so.Parts;
571 { 571 for (int i = 0; i < parts.Length; i++)
572 foreach (SceneObjectPart p in so.Children.Values) 572 parts[i].AttachedAvatar = avatar.UUID;
573 {
574 p.AttachedAvatar = avatar.UUID;
575 }
576 }
577 573
578 if (so.RootPart.PhysActor != null) 574 if (so.RootPart.PhysActor != null)
579 { 575 {
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 4c4eeff..c1d6cd3 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -594,10 +594,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
594 rootPart.Name = item.Name; 594 rootPart.Name = item.Name;
595 rootPart.Description = item.Description; 595 rootPart.Description = item.Description;
596 596
597 List<SceneObjectPart> partList = null;
598 lock (group.Children)
599 partList = new List<SceneObjectPart>(group.Children.Values);
600
601 group.SetGroup(remoteClient.ActiveGroupId, remoteClient); 597 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
602 if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) 598 if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0)
603 { 599 {
@@ -607,7 +603,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
607 603
608 if (m_Scene.Permissions.PropagatePermissions()) 604 if (m_Scene.Permissions.PropagatePermissions())
609 { 605 {
610 foreach (SceneObjectPart part in partList) 606 foreach (SceneObjectPart part in group.Parts)
611 { 607 {
612 part.EveryoneMask = item.EveryOnePermissions; 608 part.EveryoneMask = item.EveryOnePermissions;
613 part.NextOwnerMask = item.NextPermissions; 609 part.NextOwnerMask = item.NextPermissions;
@@ -618,7 +614,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
618 } 614 }
619 } 615 }
620 616
621 foreach (SceneObjectPart part in partList) 617 foreach (SceneObjectPart part in group.Parts)
622 { 618 {
623 if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) 619 if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0)
624 { 620 {
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 1fba6c2..6b538f6 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -243,11 +243,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
243 // to the same scene (when this is possible). 243 // to the same scene (when this is possible).
244 sceneObject.ResetIDs(); 244 sceneObject.ResetIDs();
245 245
246 List<SceneObjectPart> partList = null; 246 foreach (SceneObjectPart part in sceneObject.Parts)
247 lock (sceneObject.Children)
248 partList = new List<SceneObjectPart>(sceneObject.Children.Values);
249
250 foreach (SceneObjectPart part in partList)
251 { 247 {
252 if (!ResolveUserUuid(part.CreatorID)) 248 if (!ResolveUserUuid(part.CreatorID))
253 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; 249 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index db50339..d91c36c 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -128,14 +128,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
128 group.SetOwnerId(remoteClient.AgentId); 128 group.SetOwnerId(remoteClient.AgentId);
129 group.SetRootPartOwner(part, remoteClient.AgentId, remoteClient.ActiveGroupId); 129 group.SetRootPartOwner(part, remoteClient.AgentId, remoteClient.ActiveGroupId);
130 130
131 List<SceneObjectPart> partList = null;
132
133 lock (group.Children)
134 partList = new List<SceneObjectPart>(group.Children.Values);
135
136 if (m_scene.Permissions.PropagatePermissions()) 131 if (m_scene.Permissions.PropagatePermissions())
137 { 132 {
138 foreach (SceneObjectPart child in partList) 133 foreach (SceneObjectPart child in group.Parts)
139 { 134 {
140 child.Inventory.ChangeInventoryOwner(remoteClient.AgentId); 135 child.Inventory.ChangeInventoryOwner(remoteClient.AgentId);
141 child.TriggerScriptChangedEvent(Changed.OWNER); 136 child.TriggerScriptChangedEvent(Changed.OWNER);
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs
index 1bd1371..c83ac85 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs
@@ -229,11 +229,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
229 Color mapdotspot = Color.Gray; // Default color when prim color is white 229 Color mapdotspot = Color.Gray; // Default color when prim color is white
230 230
231 // Loop over prim in group 231 // Loop over prim in group
232 List<SceneObjectPart> partList = null; 232 foreach (SceneObjectPart part in mapdot.Parts)
233 lock (mapdot.Children)
234 partList = new List<SceneObjectPart>(mapdot.Children.Values);
235
236 foreach (SceneObjectPart part in partList)
237 { 233 {
238 if (part == null) 234 if (part == null)
239 continue; 235 continue;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 838c648..8011154 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -2051,9 +2051,7 @@ namespace OpenSim.Region.Framework.Scenes
2051 sog.SetGroup(groupID, remoteClient); 2051 sog.SetGroup(groupID, remoteClient);
2052 sog.ScheduleGroupForFullUpdate(); 2052 sog.ScheduleGroupForFullUpdate();
2053 2053
2054 List<SceneObjectPart> partList = null; 2054 SceneObjectPart[] partList = sog.Parts;
2055 lock (sog.Children)
2056 partList = new List<SceneObjectPart>(sog.Children.Values);
2057 2055
2058 foreach (SceneObjectPart child in partList) 2056 foreach (SceneObjectPart child in partList)
2059 child.Inventory.ChangeInventoryOwner(ownerID); 2057 child.Inventory.ChangeInventoryOwner(ownerID);
@@ -2066,9 +2064,7 @@ namespace OpenSim.Region.Framework.Scenes
2066 if (sog.GroupID != groupID) 2064 if (sog.GroupID != groupID)
2067 continue; 2065 continue;
2068 2066
2069 List<SceneObjectPart> partList = null; 2067 SceneObjectPart[] partList = sog.Parts;
2070 lock (sog.Children)
2071 partList = new List<SceneObjectPart>(sog.Children.Values);
2072 2068
2073 foreach (SceneObjectPart child in partList) 2069 foreach (SceneObjectPart child in partList)
2074 { 2070 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 7788e43..4d97db7 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -161,11 +161,8 @@ namespace OpenSim.Region.Framework.Scenes
161 bool foundPrim = false; 161 bool foundPrim = false;
162 162
163 SceneObjectGroup sog = ent as SceneObjectGroup; 163 SceneObjectGroup sog = ent as SceneObjectGroup;
164
165 List<SceneObjectPart> partList = null;
166 lock (sog.Children)
167 partList = new List<SceneObjectPart>(sog.Children.Values);
168 164
165 SceneObjectPart[] partList = sog.Parts;
169 foreach (SceneObjectPart part in partList) 166 foreach (SceneObjectPart part in partList)
170 { 167 {
171 if (part.LocalId == primLocalID) 168 if (part.LocalId == primLocalID)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 8a90bc8..fe0ab5b 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1785,7 +1785,7 @@ namespace OpenSim.Region.Framework.Scenes
1785 { 1785 {
1786 m_log.ErrorFormat( 1786 m_log.ErrorFormat(
1787 "[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children", 1787 "[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
1788 group.Children == null ? 0 : group.PrimCount); 1788 group.Parts == null ? 0 : group.PrimCount);
1789 } 1789 }
1790 1790
1791 AddRestoredSceneObject(group, true, true); 1791 AddRestoredSceneObject(group, true, true);
@@ -2091,9 +2091,7 @@ namespace OpenSim.Region.Framework.Scenes
2091 group.RemoveScriptInstances(true); 2091 group.RemoveScriptInstances(true);
2092 } 2092 }
2093 2093
2094 List<SceneObjectPart> partList = null; 2094 SceneObjectPart[] partList = group.Parts;
2095 lock (group.Children)
2096 partList = new List<SceneObjectPart>(group.Children.Values);
2097 2095
2098 foreach (SceneObjectPart part in partList) 2096 foreach (SceneObjectPart part in partList)
2099 { 2097 {
@@ -2465,11 +2463,9 @@ namespace OpenSim.Region.Framework.Scenes
2465 2463
2466 // Force allocation of new LocalId 2464 // Force allocation of new LocalId
2467 // 2465 //
2468 lock (sceneObject.Children) 2466 SceneObjectPart[] parts = sceneObject.Parts;
2469 { 2467 for (int i = 0; i < parts.Length; i++)
2470 foreach (SceneObjectPart p in sceneObject.Children.Values) 2468 parts[i].LocalId = 0;
2471 p.LocalId = 0;
2472 }
2473 2469
2474 if (sceneObject.IsAttachmentCheckFull()) // Attachment 2470 if (sceneObject.IsAttachmentCheckFull()) // Attachment
2475 { 2471 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 85ff32e..28b80bb 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -348,9 +348,7 @@ namespace OpenSim.Region.Framework.Scenes
348 if (Entities.ContainsKey(sceneObject.UUID)) 348 if (Entities.ContainsKey(sceneObject.UUID))
349 return false; 349 return false;
350 350
351 List<SceneObjectPart> children; 351 SceneObjectPart[] children = sceneObject.Parts;
352 lock (sceneObject.Children)
353 children = new List<SceneObjectPart>(sceneObject.Children.Values);
354 352
355 // Clamp child prim sizes and add child prims to the m_numPrim count 353 // Clamp child prim sizes and add child prims to the m_numPrim count
356 if (m_parentScene.m_clampPrimSize) 354 if (m_parentScene.m_clampPrimSize)
@@ -369,7 +367,7 @@ namespace OpenSim.Region.Framework.Scenes
369 part.Shape.Scale = scale; 367 part.Shape.Scale = scale;
370 } 368 }
371 } 369 }
372 m_numPrim += children.Count; 370 m_numPrim += children.Length;
373 371
374 sceneObject.AttachToScene(m_parentScene); 372 sceneObject.AttachToScene(m_parentScene);
375 373
@@ -426,15 +424,17 @@ namespace OpenSim.Region.Framework.Scenes
426 424
427 lock (SceneObjectGroupsByFullID) 425 lock (SceneObjectGroupsByFullID)
428 { 426 {
429 foreach (SceneObjectPart part in grp.Children.Values) 427 SceneObjectPart[] parts = grp.Parts;
430 SceneObjectGroupsByFullID.Remove(part.UUID); 428 for (int i = 0; i < parts.Length; i++)
429 SceneObjectGroupsByFullID.Remove(parts[i].UUID);
431 SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); 430 SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID);
432 } 431 }
433 432
434 lock (SceneObjectGroupsByLocalID) 433 lock (SceneObjectGroupsByLocalID)
435 { 434 {
436 foreach (SceneObjectPart part in grp.Children.Values) 435 SceneObjectPart[] parts = grp.Parts;
437 SceneObjectGroupsByLocalID.Remove(part.LocalId); 436 for (int i = 0; i < parts.Length; i++)
437 SceneObjectGroupsByLocalID.Remove(parts[i].LocalId);
438 SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); 438 SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId);
439 } 439 }
440 440
@@ -887,11 +887,8 @@ namespace OpenSim.Region.Framework.Scenes
887 887
888 if (sog != null) 888 if (sog != null)
889 { 889 {
890 lock (sog.Children) 890 if (sog.ContainsPart(fullID))
891 { 891 return sog;
892 if (sog.Children.ContainsKey(fullID))
893 return sog;
894 }
895 892
896 lock (SceneObjectGroupsByFullID) 893 lock (SceneObjectGroupsByFullID)
897 SceneObjectGroupsByFullID.Remove(fullID); 894 SceneObjectGroupsByFullID.Remove(fullID);
@@ -965,7 +962,7 @@ namespace OpenSim.Region.Framework.Scenes
965 { 962 {
966 if (entity is SceneObjectGroup) 963 if (entity is SceneObjectGroup)
967 { 964 {
968 foreach (SceneObjectPart p in ((SceneObjectGroup)entity).GetParts()) 965 foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts)
969 { 966 {
970 if (p.Name == name) 967 if (p.Name == name)
971 { 968 {
@@ -1626,14 +1623,8 @@ namespace OpenSim.Region.Framework.Scenes
1626 // 1623 //
1627 SceneObjectGroup group = root.ParentGroup; 1624 SceneObjectGroup group = root.ParentGroup;
1628 1625
1629 List<SceneObjectPart> newSet = null; 1626 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1630 int numChildren = -1; 1627 int numChildren = newSet.Count;
1631
1632 lock (group.Children)
1633 {
1634 newSet = new List<SceneObjectPart>(group.Children.Values);
1635 numChildren = group.PrimCount;
1636 }
1637 1628
1638 // If there are prims left in a link set, but the root is 1629 // If there are prims left in a link set, but the root is
1639 // slated for unlink, we need to do this 1630 // slated for unlink, we need to do this
@@ -1711,16 +1702,13 @@ namespace OpenSim.Region.Framework.Scenes
1711 if (ent is SceneObjectGroup) 1702 if (ent is SceneObjectGroup)
1712 { 1703 {
1713 SceneObjectGroup sog = ent as SceneObjectGroup; 1704 SceneObjectGroup sog = ent as SceneObjectGroup;
1714 1705
1715 lock (sog.Children) 1706 foreach (SceneObjectPart part in sog.Parts)
1716 { 1707 {
1717 foreach (KeyValuePair<UUID, SceneObjectPart> subent in sog.Children) 1708 if (part.LocalId == localID)
1718 { 1709 {
1719 if (subent.Value.LocalId == localID) 1710 objid = part.UUID;
1720 { 1711 obj = part;
1721 objid = subent.Key;
1722 obj = subent.Value;
1723 }
1724 } 1712 }
1725 } 1713 }
1726 } 1714 }
@@ -1796,8 +1784,7 @@ namespace OpenSim.Region.Framework.Scenes
1796 copy.SetOwnerId(AgentID); 1784 copy.SetOwnerId(AgentID);
1797 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); 1785 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1798 1786
1799 List<SceneObjectPart> partList = 1787 SceneObjectPart[] partList = copy.Parts;
1800 new List<SceneObjectPart>(copy.Children.Values);
1801 1788
1802 if (m_parentScene.Permissions.PropagatePermissions()) 1789 if (m_parentScene.Permissions.PropagatePermissions())
1803 { 1790 {
@@ -1822,7 +1809,7 @@ namespace OpenSim.Region.Framework.Scenes
1822 // think it's selected, so it will never send a deselect... 1809 // think it's selected, so it will never send a deselect...
1823 copy.IsSelected = false; 1810 copy.IsSelected = false;
1824 1811
1825 m_numPrim += copy.Children.Count; 1812 m_numPrim += copy.Parts.Length;
1826 1813
1827 if (rot != Quaternion.Identity) 1814 if (rot != Quaternion.Identity)
1828 { 1815 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 9a01a28..a86223c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -46,13 +46,9 @@ namespace OpenSim.Region.Framework.Scenes
46 /// </summary> 46 /// </summary>
47 public void ForceInventoryPersistence() 47 public void ForceInventoryPersistence()
48 { 48 {
49 lock (m_parts) 49 SceneObjectPart[] parts = m_parts.GetArray();
50 { 50 for (int i = 0; i < parts.Length; i++)
51 foreach (SceneObjectPart part in m_parts.Values) 51 parts[i].Inventory.ForceInventoryPersistence();
52 {
53 part.Inventory.ForceInventoryPersistence();
54 }
55 }
56 } 52 }
57 53
58 /// <summary> 54 /// <summary>
@@ -64,10 +60,9 @@ namespace OpenSim.Region.Framework.Scenes
64 // Don't start scripts if they're turned off in the region! 60 // Don't start scripts if they're turned off in the region!
65 if (!m_scene.RegionInfo.RegionSettings.DisableScripts) 61 if (!m_scene.RegionInfo.RegionSettings.DisableScripts)
66 { 62 {
67 foreach (SceneObjectPart part in m_parts.Values) 63 SceneObjectPart[] parts = m_parts.GetArray();
68 { 64 for (int i = 0; i < parts.Length; i++)
69 part.Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource); 65 parts[i].Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource);
70 }
71 } 66 }
72 } 67 }
73 68
@@ -80,13 +75,9 @@ namespace OpenSim.Region.Framework.Scenes
80 /// </param> 75 /// </param>
81 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 76 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
82 { 77 {
83 lock (m_parts) 78 SceneObjectPart[] parts = m_parts.GetArray();
84 { 79 for (int i = 0; i < parts.Length; i++)
85 foreach (SceneObjectPart part in m_parts.Values) 80 parts[i].Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
86 {
87 part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted);
88 }
89 }
90 } 81 }
91 82
92 /// <summary> 83 /// <summary>
@@ -283,8 +274,11 @@ namespace OpenSim.Region.Framework.Scenes
283 PermissionMask.Transfer) | 7; 274 PermissionMask.Transfer) | 7;
284 275
285 uint ownerMask = 0x7fffffff; 276 uint ownerMask = 0x7fffffff;
286 foreach (SceneObjectPart part in m_parts.Values) 277
278 SceneObjectPart[] parts = m_parts.GetArray();
279 for (int i = 0; i < parts.Length; i++)
287 { 280 {
281 SceneObjectPart part = parts[i];
288 ownerMask &= part.OwnerMask; 282 ownerMask &= part.OwnerMask;
289 perms &= part.Inventory.MaskEffectivePermissions(); 283 perms &= part.Inventory.MaskEffectivePermissions();
290 } 284 }
@@ -312,39 +306,40 @@ namespace OpenSim.Region.Framework.Scenes
312 306
313 public void ApplyNextOwnerPermissions() 307 public void ApplyNextOwnerPermissions()
314 { 308 {
315 foreach (SceneObjectPart part in m_parts.Values) 309 SceneObjectPart[] parts = m_parts.GetArray();
316 { 310 for (int i = 0; i < parts.Length; i++)
317 part.ApplyNextOwnerPermissions(); 311 parts[i].ApplyNextOwnerPermissions();
318 }
319 } 312 }
320 313
321 public string GetStateSnapshot() 314 public string GetStateSnapshot()
322 { 315 {
323 Dictionary<UUID, string> states = new Dictionary<UUID, string>(); 316 Dictionary<UUID, string> states = new Dictionary<UUID, string>();
324 317
325 foreach (SceneObjectPart part in m_parts.Values) 318 SceneObjectPart[] parts = m_parts.GetArray();
319 for (int i = 0; i < parts.Length; i++)
326 { 320 {
321 SceneObjectPart part = parts[i];
327 foreach (KeyValuePair<UUID, string> s in part.Inventory.GetScriptStates()) 322 foreach (KeyValuePair<UUID, string> s in part.Inventory.GetScriptStates())
328 states[s.Key] = s.Value; 323 states[s.Key] = s.Value;
329 } 324 }
330 325
331 if (states.Count < 1) 326 if (states.Count < 1)
332 return ""; 327 return String.Empty;
333 328
334 XmlDocument xmldoc = new XmlDocument(); 329 XmlDocument xmldoc = new XmlDocument();
335 330
336 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, 331 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
337 "", ""); 332 String.Empty, String.Empty);
338 333
339 xmldoc.AppendChild(xmlnode); 334 xmldoc.AppendChild(xmlnode);
340 XmlElement rootElement = xmldoc.CreateElement("", "ScriptData", 335 XmlElement rootElement = xmldoc.CreateElement("", "ScriptData",
341 ""); 336 String.Empty);
342 337
343 xmldoc.AppendChild(rootElement); 338 xmldoc.AppendChild(rootElement);
344 339
345 340
346 XmlElement wrapper = xmldoc.CreateElement("", "ScriptStates", 341 XmlElement wrapper = xmldoc.CreateElement("", "ScriptStates",
347 ""); 342 String.Empty);
348 343
349 rootElement.AppendChild(wrapper); 344 rootElement.AppendChild(wrapper);
350 345
@@ -424,10 +419,9 @@ namespace OpenSim.Region.Framework.Scenes
424 419
425 public void ResumeScripts() 420 public void ResumeScripts()
426 { 421 {
427 foreach (SceneObjectPart part in m_parts.Values) 422 SceneObjectPart[] parts = m_parts.GetArray();
428 { 423 for (int i = 0; i < parts.Length; i++)
429 part.Inventory.ResumeScripts(); 424 parts[i].Inventory.ResumeScripts();
430 }
431 } 425 }
432 } 426 }
433} 427}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index f9a8d41..c984afc 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -158,17 +158,14 @@ namespace OpenSim.Region.Framework.Scenes
158 } 158 }
159 } 159 }
160 160
161 public float scriptScore = 0f; 161 public float scriptScore;
162 162
163 private Vector3 lastPhysGroupPos; 163 private Vector3 lastPhysGroupPos;
164 private Quaternion lastPhysGroupRot; 164 private Quaternion lastPhysGroupRot;
165 165
166 private bool m_isBackedUp = false; 166 private bool m_isBackedUp;
167 167
168 /// <summary> 168 protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>();
169 /// The constituent parts of this group
170 /// </summary>
171 protected Dictionary<UUID, SceneObjectPart> m_parts = new Dictionary<UUID, SceneObjectPart>();
172 169
173 protected ulong m_regionHandle; 170 protected ulong m_regionHandle;
174 protected SceneObjectPart m_rootPart; 171 protected SceneObjectPart m_rootPart;
@@ -177,13 +174,13 @@ namespace OpenSim.Region.Framework.Scenes
177 private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>(); 174 private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>();
178 private Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>(); 175 private Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>();
179 176
180 private bool m_scriptListens_atTarget = false; 177 private bool m_scriptListens_atTarget;
181 private bool m_scriptListens_notAtTarget = false; 178 private bool m_scriptListens_notAtTarget;
182 179
183 private bool m_scriptListens_atRotTarget = false; 180 private bool m_scriptListens_atRotTarget;
184 private bool m_scriptListens_notAtRotTarget = false; 181 private bool m_scriptListens_notAtRotTarget;
185 182
186 internal Dictionary<UUID, string> m_savedScriptState = null; 183 internal Dictionary<UUID, string> m_savedScriptState;
187 184
188 #region Properties 185 #region Properties
189 186
@@ -194,7 +191,7 @@ namespace OpenSim.Region.Framework.Scenes
194 { 191 {
195 get { 192 get {
196 if (RootPart == null) 193 if (RootPart == null)
197 return ""; 194 return String.Empty;
198 return RootPart.Name; 195 return RootPart.Name;
199 } 196 }
200 set { RootPart.Name = value; } 197 set { RootPart.Name = value; }
@@ -214,7 +211,7 @@ namespace OpenSim.Region.Framework.Scenes
214 /// </summary> 211 /// </summary>
215 public int PrimCount 212 public int PrimCount
216 { 213 {
217 get { lock (m_parts) { return m_parts.Count; } } 214 get { return m_parts.Count; }
218 } 215 }
219 216
220 protected Quaternion m_rotation = Quaternion.Identity; 217 protected Quaternion m_rotation = Quaternion.Identity;
@@ -236,16 +233,14 @@ namespace OpenSim.Region.Framework.Scenes
236 set { m_rootPart.GroupID = value; } 233 set { m_rootPart.GroupID = value; }
237 } 234 }
238 235
239 /// <value> 236 public SceneObjectPart[] Parts
240 /// The parts of this scene object group. You must lock this property before using it. 237 {
241 /// If you're doing anything other than reading values, please take a copy of the values rather than locking 238 get { return m_parts.GetArray(); }
242 /// the dictionary for the entirety of the operation. This increases liveness and reduces the danger of deadlock 239 }
243 /// If you want to know the number of children, consider using the PrimCount property instead 240
244 /// </value> 241 public bool ContainsPart(UUID partID)
245 public Dictionary<UUID, SceneObjectPart> Children
246 { 242 {
247 get { return m_parts; } 243 return m_parts.ContainsKey(partID);
248 set { m_parts = value; }
249 } 244 }
250 245
251 /// <value> 246 /// <value>
@@ -262,13 +257,9 @@ namespace OpenSim.Region.Framework.Scenes
262 set 257 set
263 { 258 {
264 m_regionHandle = value; 259 m_regionHandle = value;
265 lock (m_parts) 260 SceneObjectPart[] parts = m_parts.GetArray();
266 { 261 for (int i = 0; i < parts.Length; i++)
267 foreach (SceneObjectPart part in m_parts.Values) 262 parts[i].RegionHandle = value;
268 {
269 part.RegionHandle = m_regionHandle;
270 }
271 }
272 } 263 }
273 } 264 }
274 265
@@ -313,14 +304,10 @@ namespace OpenSim.Region.Framework.Scenes
313 return; 304 return;
314 } 305 }
315 } 306 }
316 307
317 lock (m_parts) 308 SceneObjectPart[] parts = m_parts.GetArray();
318 { 309 for (int i = 0; i < parts.Length; i++)
319 foreach (SceneObjectPart part in m_parts.Values) 310 parts[i].GroupPosition = val;
320 {
321 part.GroupPosition = val;
322 }
323 }
324 311
325 //if (m_rootPart.PhysActor != null) 312 //if (m_rootPart.PhysActor != null)
326 //{ 313 //{
@@ -342,14 +329,9 @@ namespace OpenSim.Region.Framework.Scenes
342 { 329 {
343 get { return m_rootPart.UUID; } 330 get { return m_rootPart.UUID; }
344 set 331 set
345 { 332 {
346 m_rootPart.UUID = value; 333 m_rootPart.UUID = value;
347 334 m_parts.AddOrReplace(value, m_rootPart);
348 lock (m_parts)
349 {
350 m_parts.Remove(m_rootPart.UUID);
351 m_parts.Add(m_rootPart.UUID, m_rootPart);
352 }
353 } 335 }
354 } 336 }
355 337
@@ -411,12 +393,12 @@ namespace OpenSim.Region.Framework.Scenes
411 { 393 {
412 m_rootPart.PhysActor.Selected = value; 394 m_rootPart.PhysActor.Selected = value;
413 // Pass it on to the children. 395 // Pass it on to the children.
414 foreach (SceneObjectPart child in Children.Values) 396 SceneObjectPart[] parts = m_parts.GetArray();
397 for (int i = 0; i < parts.Length; i++)
415 { 398 {
399 SceneObjectPart child = parts[i];
416 if (child.PhysActor != null) 400 if (child.PhysActor != null)
417 {
418 child.PhysActor.Selected = value; 401 child.PhysActor.Selected = value;
419 }
420 } 402 }
421 } 403 }
422 } 404 }
@@ -519,13 +501,9 @@ namespace OpenSim.Region.Framework.Scenes
519 501
520 public void SetFromItemID(UUID AssetId) 502 public void SetFromItemID(UUID AssetId)
521 { 503 {
522 lock (m_parts) 504 SceneObjectPart[] parts = m_parts.GetArray();
523 { 505 for (int i = 0; i < parts.Length; i++)
524 foreach (SceneObjectPart part in m_parts.Values) 506 parts[i].FromItemID = AssetId;
525 {
526 part.FromItemID = AssetId;
527 }
528 }
529 } 507 }
530 508
531 public UUID GetFromItemID() 509 public UUID GetFromItemID()
@@ -564,23 +542,18 @@ namespace OpenSim.Region.Framework.Scenes
564 if (m_rootPart.LocalId == 0) 542 if (m_rootPart.LocalId == 0)
565 m_rootPart.LocalId = m_scene.AllocateLocalId(); 543 m_rootPart.LocalId = m_scene.AllocateLocalId();
566 544
567 lock (m_parts) 545 SceneObjectPart[] parts = m_parts.GetArray();
546 for (int i = 0; i < parts.Length; i++)
568 { 547 {
569 foreach (SceneObjectPart part in m_parts.Values) 548 SceneObjectPart part = parts[i];
570 { 549 if (Object.ReferenceEquals(part, m_rootPart))
571 if (Object.ReferenceEquals(part, m_rootPart)) 550 continue;
572 { 551
573 continue; 552 if (part.LocalId == 0)
574 } 553 part.LocalId = m_scene.AllocateLocalId();
575 554
576 if (part.LocalId == 0) 555 part.ParentID = m_rootPart.LocalId;
577 { 556 //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID);
578 part.LocalId = m_scene.AllocateLocalId();
579 }
580
581 part.ParentID = m_rootPart.LocalId;
582 //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID);
583 }
584 } 557 }
585 558
586 ApplyPhysics(m_scene.m_physicalPrim); 559 ApplyPhysics(m_scene.m_physicalPrim);
@@ -596,22 +569,22 @@ namespace OpenSim.Region.Framework.Scenes
596 Vector3 maxScale = Vector3.Zero; 569 Vector3 maxScale = Vector3.Zero;
597 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 570 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
598 571
599 lock (m_parts) 572 SceneObjectPart[] parts = m_parts.GetArray();
573 for (int i = 0; i < parts.Length; i++)
600 { 574 {
601 foreach (SceneObjectPart part in m_parts.Values) 575 SceneObjectPart part = parts[i];
602 { 576 Vector3 partscale = part.Scale;
603 Vector3 partscale = part.Scale; 577 Vector3 partoffset = part.OffsetPosition;
604 Vector3 partoffset = part.OffsetPosition;
605 578
606 minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X; 579 minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X;
607 minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y; 580 minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y;
608 minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z; 581 minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z;
609 582
610 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 583 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
611 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 584 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
612 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 585 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
613 }
614 } 586 }
587
615 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 588 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
616 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 589 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
617 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 590 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -627,39 +600,40 @@ namespace OpenSim.Region.Framework.Scenes
627 600
628 EntityIntersection result = new EntityIntersection(); 601 EntityIntersection result = new EntityIntersection();
629 602
630 lock (m_parts) 603 SceneObjectPart[] parts = m_parts.GetArray();
604 for (int i = 0; i < parts.Length; i++)
631 { 605 {
632 foreach (SceneObjectPart part in m_parts.Values) 606 SceneObjectPart part = parts[i];
633 {
634 // Temporary commented to stop compiler warning
635 //Vector3 partPosition =
636 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
637 Quaternion parentrotation = GroupRotation;
638 607
639 // Telling the prim to raytrace. 608 // Temporary commented to stop compiler warning
640 //EntityIntersection inter = part.TestIntersection(hRay, parentrotation); 609 //Vector3 partPosition =
610 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
611 Quaternion parentrotation = GroupRotation;
641 612
642 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation,frontFacesOnly, faceCenters); 613 // Telling the prim to raytrace.
614 //EntityIntersection inter = part.TestIntersection(hRay, parentrotation);
643 615
644 // This may need to be updated to the maximum draw distance possible.. 616 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
645 // We might (and probably will) be checking for prim creation from other sims
646 // when the camera crosses the border.
647 float idist = Constants.RegionSize;
648 617
649 if (inter.HitTF) 618 // This may need to be updated to the maximum draw distance possible..
619 // We might (and probably will) be checking for prim creation from other sims
620 // when the camera crosses the border.
621 float idist = Constants.RegionSize;
622
623 if (inter.HitTF)
624 {
625 // We need to find the closest prim to return to the testcaller along the ray
626 if (inter.distance < idist)
650 { 627 {
651 // We need to find the closest prim to return to the testcaller along the ray 628 result.HitTF = true;
652 if (inter.distance < idist) 629 result.ipoint = inter.ipoint;
653 { 630 result.obj = part;
654 result.HitTF = true; 631 result.normal = inter.normal;
655 result.ipoint = inter.ipoint; 632 result.distance = inter.distance;
656 result.obj = part;
657 result.normal = inter.normal;
658 result.distance = inter.distance;
659 }
660 } 633 }
661 } 634 }
662 } 635 }
636
663 return result; 637 return result;
664 } 638 }
665 639
@@ -678,238 +652,193 @@ namespace OpenSim.Region.Framework.Scenes
678 minY = 256f; 652 minY = 256f;
679 minZ = 8192f; 653 minZ = 8192f;
680 654
681 lock (m_parts) 655 SceneObjectPart[] parts = m_parts.GetArray();
656 for (int i = 0; i < parts.Length; i++)
682 { 657 {
683 foreach (SceneObjectPart part in m_parts.Values) 658 SceneObjectPart part = parts[i];
684 {
685 Vector3 worldPos = part.GetWorldPosition();
686 Vector3 offset = worldPos - AbsolutePosition;
687 Quaternion worldRot;
688 if (part.ParentID == 0)
689 {
690 worldRot = part.RotationOffset;
691 }
692 else
693 {
694 worldRot = part.GetWorldRotation();
695 }
696 659
697 Vector3 frontTopLeft; 660 Vector3 worldPos = part.GetWorldPosition();
698 Vector3 frontTopRight; 661 Vector3 offset = worldPos - AbsolutePosition;
699 Vector3 frontBottomLeft; 662 Quaternion worldRot;
700 Vector3 frontBottomRight; 663 if (part.ParentID == 0)
701 664 worldRot = part.RotationOffset;
702 Vector3 backTopLeft; 665 else
703 Vector3 backTopRight; 666 worldRot = part.GetWorldRotation();
704 Vector3 backBottomLeft; 667
705 Vector3 backBottomRight; 668 Vector3 frontTopLeft;
706 669 Vector3 frontTopRight;
707 // Vector3[] corners = new Vector3[8]; 670 Vector3 frontBottomLeft;
708 671 Vector3 frontBottomRight;
709 Vector3 orig = Vector3.Zero; 672
710 673 Vector3 backTopLeft;
711 frontTopLeft.X = orig.X - (part.Scale.X / 2); 674 Vector3 backTopRight;
712 frontTopLeft.Y = orig.Y - (part.Scale.Y / 2); 675 Vector3 backBottomLeft;
713 frontTopLeft.Z = orig.Z + (part.Scale.Z / 2); 676 Vector3 backBottomRight;
714 677
715 frontTopRight.X = orig.X - (part.Scale.X / 2); 678 Vector3 orig = Vector3.Zero;
716 frontTopRight.Y = orig.Y + (part.Scale.Y / 2); 679
717 frontTopRight.Z = orig.Z + (part.Scale.Z / 2); 680 frontTopLeft.X = orig.X - (part.Scale.X / 2);
718 681 frontTopLeft.Y = orig.Y - (part.Scale.Y / 2);
719 frontBottomLeft.X = orig.X - (part.Scale.X / 2); 682 frontTopLeft.Z = orig.Z + (part.Scale.Z / 2);
720 frontBottomLeft.Y = orig.Y - (part.Scale.Y / 2); 683
721 frontBottomLeft.Z = orig.Z - (part.Scale.Z / 2); 684 frontTopRight.X = orig.X - (part.Scale.X / 2);
722 685 frontTopRight.Y = orig.Y + (part.Scale.Y / 2);
723 frontBottomRight.X = orig.X - (part.Scale.X / 2); 686 frontTopRight.Z = orig.Z + (part.Scale.Z / 2);
724 frontBottomRight.Y = orig.Y + (part.Scale.Y / 2); 687
725 frontBottomRight.Z = orig.Z - (part.Scale.Z / 2); 688 frontBottomLeft.X = orig.X - (part.Scale.X / 2);
726 689 frontBottomLeft.Y = orig.Y - (part.Scale.Y / 2);
727 backTopLeft.X = orig.X + (part.Scale.X / 2); 690 frontBottomLeft.Z = orig.Z - (part.Scale.Z / 2);
728 backTopLeft.Y = orig.Y - (part.Scale.Y / 2); 691
729 backTopLeft.Z = orig.Z + (part.Scale.Z / 2); 692 frontBottomRight.X = orig.X - (part.Scale.X / 2);
730 693 frontBottomRight.Y = orig.Y + (part.Scale.Y / 2);
731 backTopRight.X = orig.X + (part.Scale.X / 2); 694 frontBottomRight.Z = orig.Z - (part.Scale.Z / 2);
732 backTopRight.Y = orig.Y + (part.Scale.Y / 2); 695
733 backTopRight.Z = orig.Z + (part.Scale.Z / 2); 696 backTopLeft.X = orig.X + (part.Scale.X / 2);
734 697 backTopLeft.Y = orig.Y - (part.Scale.Y / 2);
735 backBottomLeft.X = orig.X + (part.Scale.X / 2); 698 backTopLeft.Z = orig.Z + (part.Scale.Z / 2);
736 backBottomLeft.Y = orig.Y - (part.Scale.Y / 2); 699
737 backBottomLeft.Z = orig.Z - (part.Scale.Z / 2); 700 backTopRight.X = orig.X + (part.Scale.X / 2);
738 701 backTopRight.Y = orig.Y + (part.Scale.Y / 2);
739 backBottomRight.X = orig.X + (part.Scale.X / 2); 702 backTopRight.Z = orig.Z + (part.Scale.Z / 2);
740 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 703
741 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 704 backBottomLeft.X = orig.X + (part.Scale.X / 2);
742 705 backBottomLeft.Y = orig.Y - (part.Scale.Y / 2);
743 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 706 backBottomLeft.Z = orig.Z - (part.Scale.Z / 2);
744 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 707
745 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 708 backBottomRight.X = orig.X + (part.Scale.X / 2);
746 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z); 709 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
747 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z); 710 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
748 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z); 711
749 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z); 712 frontTopLeft = frontTopLeft * worldRot;
750 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z); 713 frontTopRight = frontTopRight * worldRot;
751 714 frontBottomLeft = frontBottomLeft * worldRot;
752 //for (int i = 0; i < 8; i++) 715 frontBottomRight = frontBottomRight * worldRot;
753 //{ 716
754 // corners[i] = corners[i] * worldRot; 717 backBottomLeft = backBottomLeft * worldRot;
755 // corners[i] += offset; 718 backBottomRight = backBottomRight * worldRot;
756 719 backTopLeft = backTopLeft * worldRot;
757 // if (corners[i].X > maxX) 720 backTopRight = backTopRight * worldRot;
758 // maxX = corners[i].X; 721
759 // if (corners[i].X < minX) 722
760 // minX = corners[i].X; 723 frontTopLeft += offset;
761 724 frontTopRight += offset;
762 // if (corners[i].Y > maxY) 725 frontBottomLeft += offset;
763 // maxY = corners[i].Y; 726 frontBottomRight += offset;
764 // if (corners[i].Y < minY) 727
765 // minY = corners[i].Y; 728 backBottomLeft += offset;
766 729 backBottomRight += offset;
767 // if (corners[i].Z > maxZ) 730 backTopLeft += offset;
768 // maxZ = corners[i].Y; 731 backTopRight += offset;
769 // if (corners[i].Z < minZ) 732
770 // minZ = corners[i].Z; 733 if (frontTopRight.X > maxX)
771 //} 734 maxX = frontTopRight.X;
772 735 if (frontTopLeft.X > maxX)
773 frontTopLeft = frontTopLeft * worldRot; 736 maxX = frontTopLeft.X;
774 frontTopRight = frontTopRight * worldRot; 737 if (frontBottomRight.X > maxX)
775 frontBottomLeft = frontBottomLeft * worldRot; 738 maxX = frontBottomRight.X;
776 frontBottomRight = frontBottomRight * worldRot; 739 if (frontBottomLeft.X > maxX)
777 740 maxX = frontBottomLeft.X;
778 backBottomLeft = backBottomLeft * worldRot; 741
779 backBottomRight = backBottomRight * worldRot; 742 if (backTopRight.X > maxX)
780 backTopLeft = backTopLeft * worldRot; 743 maxX = backTopRight.X;
781 backTopRight = backTopRight * worldRot; 744 if (backTopLeft.X > maxX)
782 745 maxX = backTopLeft.X;
783 746 if (backBottomRight.X > maxX)
784 frontTopLeft += offset; 747 maxX = backBottomRight.X;
785 frontTopRight += offset; 748 if (backBottomLeft.X > maxX)
786 frontBottomLeft += offset; 749 maxX = backBottomLeft.X;
787 frontBottomRight += offset; 750
788 751 if (frontTopRight.X < minX)
789 backBottomLeft += offset; 752 minX = frontTopRight.X;
790 backBottomRight += offset; 753 if (frontTopLeft.X < minX)
791 backTopLeft += offset; 754 minX = frontTopLeft.X;
792 backTopRight += offset; 755 if (frontBottomRight.X < minX)
793 756 minX = frontBottomRight.X;
794 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 757 if (frontBottomLeft.X < minX)
795 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 758 minX = frontBottomLeft.X;
796 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 759
797 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z); 760 if (backTopRight.X < minX)
798 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z); 761 minX = backTopRight.X;
799 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z); 762 if (backTopLeft.X < minX)
800 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z); 763 minX = backTopLeft.X;
801 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z); 764 if (backBottomRight.X < minX)
802 765 minX = backBottomRight.X;
803 if (frontTopRight.X > maxX) 766 if (backBottomLeft.X < minX)
804 maxX = frontTopRight.X; 767 minX = backBottomLeft.X;
805 if (frontTopLeft.X > maxX) 768
806 maxX = frontTopLeft.X; 769 //
807 if (frontBottomRight.X > maxX) 770 if (frontTopRight.Y > maxY)
808 maxX = frontBottomRight.X; 771 maxY = frontTopRight.Y;
809 if (frontBottomLeft.X > maxX) 772 if (frontTopLeft.Y > maxY)
810 maxX = frontBottomLeft.X; 773 maxY = frontTopLeft.Y;
811 774 if (frontBottomRight.Y > maxY)
812 if (backTopRight.X > maxX) 775 maxY = frontBottomRight.Y;
813 maxX = backTopRight.X; 776 if (frontBottomLeft.Y > maxY)
814 if (backTopLeft.X > maxX) 777 maxY = frontBottomLeft.Y;
815 maxX = backTopLeft.X; 778
816 if (backBottomRight.X > maxX) 779 if (backTopRight.Y > maxY)
817 maxX = backBottomRight.X; 780 maxY = backTopRight.Y;
818 if (backBottomLeft.X > maxX) 781 if (backTopLeft.Y > maxY)
819 maxX = backBottomLeft.X; 782 maxY = backTopLeft.Y;
820 783 if (backBottomRight.Y > maxY)
821 if (frontTopRight.X < minX) 784 maxY = backBottomRight.Y;
822 minX = frontTopRight.X; 785 if (backBottomLeft.Y > maxY)
823 if (frontTopLeft.X < minX) 786 maxY = backBottomLeft.Y;
824 minX = frontTopLeft.X; 787
825 if (frontBottomRight.X < minX) 788 if (frontTopRight.Y < minY)
826 minX = frontBottomRight.X; 789 minY = frontTopRight.Y;
827 if (frontBottomLeft.X < minX) 790 if (frontTopLeft.Y < minY)
828 minX = frontBottomLeft.X; 791 minY = frontTopLeft.Y;
829 792 if (frontBottomRight.Y < minY)
830 if (backTopRight.X < minX) 793 minY = frontBottomRight.Y;
831 minX = backTopRight.X; 794 if (frontBottomLeft.Y < minY)
832 if (backTopLeft.X < minX) 795 minY = frontBottomLeft.Y;
833 minX = backTopLeft.X; 796
834 if (backBottomRight.X < minX) 797 if (backTopRight.Y < minY)
835 minX = backBottomRight.X; 798 minY = backTopRight.Y;
836 if (backBottomLeft.X < minX) 799 if (backTopLeft.Y < minY)
837 minX = backBottomLeft.X; 800 minY = backTopLeft.Y;
838 801 if (backBottomRight.Y < minY)
839 // 802 minY = backBottomRight.Y;
840 if (frontTopRight.Y > maxY) 803 if (backBottomLeft.Y < minY)
841 maxY = frontTopRight.Y; 804 minY = backBottomLeft.Y;
842 if (frontTopLeft.Y > maxY) 805
843 maxY = frontTopLeft.Y; 806 //
844 if (frontBottomRight.Y > maxY) 807 if (frontTopRight.Z > maxZ)
845 maxY = frontBottomRight.Y; 808 maxZ = frontTopRight.Z;
846 if (frontBottomLeft.Y > maxY) 809 if (frontTopLeft.Z > maxZ)
847 maxY = frontBottomLeft.Y; 810 maxZ = frontTopLeft.Z;
848 811 if (frontBottomRight.Z > maxZ)
849 if (backTopRight.Y > maxY) 812 maxZ = frontBottomRight.Z;
850 maxY = backTopRight.Y; 813 if (frontBottomLeft.Z > maxZ)
851 if (backTopLeft.Y > maxY) 814 maxZ = frontBottomLeft.Z;
852 maxY = backTopLeft.Y; 815
853 if (backBottomRight.Y > maxY) 816 if (backTopRight.Z > maxZ)
854 maxY = backBottomRight.Y; 817 maxZ = backTopRight.Z;
855 if (backBottomLeft.Y > maxY) 818 if (backTopLeft.Z > maxZ)
856 maxY = backBottomLeft.Y; 819 maxZ = backTopLeft.Z;
857 820 if (backBottomRight.Z > maxZ)
858 if (frontTopRight.Y < minY) 821 maxZ = backBottomRight.Z;
859 minY = frontTopRight.Y; 822 if (backBottomLeft.Z > maxZ)
860 if (frontTopLeft.Y < minY) 823 maxZ = backBottomLeft.Z;
861 minY = frontTopLeft.Y; 824
862 if (frontBottomRight.Y < minY) 825 if (frontTopRight.Z < minZ)
863 minY = frontBottomRight.Y; 826 minZ = frontTopRight.Z;
864 if (frontBottomLeft.Y < minY) 827 if (frontTopLeft.Z < minZ)
865 minY = frontBottomLeft.Y; 828 minZ = frontTopLeft.Z;
866 829 if (frontBottomRight.Z < minZ)
867 if (backTopRight.Y < minY) 830 minZ = frontBottomRight.Z;
868 minY = backTopRight.Y; 831 if (frontBottomLeft.Z < minZ)
869 if (backTopLeft.Y < minY) 832 minZ = frontBottomLeft.Z;
870 minY = backTopLeft.Y; 833
871 if (backBottomRight.Y < minY) 834 if (backTopRight.Z < minZ)
872 minY = backBottomRight.Y; 835 minZ = backTopRight.Z;
873 if (backBottomLeft.Y < minY) 836 if (backTopLeft.Z < minZ)
874 minY = backBottomLeft.Y; 837 minZ = backTopLeft.Z;
875 838 if (backBottomRight.Z < minZ)
876 // 839 minZ = backBottomRight.Z;
877 if (frontTopRight.Z > maxZ) 840 if (backBottomLeft.Z < minZ)
878 maxZ = frontTopRight.Z; 841 minZ = backBottomLeft.Z;
879 if (frontTopLeft.Z > maxZ)
880 maxZ = frontTopLeft.Z;
881 if (frontBottomRight.Z > maxZ)
882 maxZ = frontBottomRight.Z;
883 if (frontBottomLeft.Z > maxZ)
884 maxZ = frontBottomLeft.Z;
885
886 if (backTopRight.Z > maxZ)
887 maxZ = backTopRight.Z;
888 if (backTopLeft.Z > maxZ)
889 maxZ = backTopLeft.Z;
890 if (backBottomRight.Z > maxZ)
891 maxZ = backBottomRight.Z;
892 if (backBottomLeft.Z > maxZ)
893 maxZ = backBottomLeft.Z;
894
895 if (frontTopRight.Z < minZ)
896 minZ = frontTopRight.Z;
897 if (frontTopLeft.Z < minZ)
898 minZ = frontTopLeft.Z;
899 if (frontBottomRight.Z < minZ)
900 minZ = frontBottomRight.Z;
901 if (frontBottomLeft.Z < minZ)
902 minZ = frontBottomLeft.Z;
903
904 if (backTopRight.Z < minZ)
905 minZ = backTopRight.Z;
906 if (backTopLeft.Z < minZ)
907 minZ = backTopLeft.Z;
908 if (backBottomRight.Z < minZ)
909 minZ = backBottomRight.Z;
910 if (backBottomLeft.Z < minZ)
911 minZ = backBottomLeft.Z;
912 }
913 } 842 }
914 } 843 }
915 844
@@ -949,17 +878,12 @@ namespace OpenSim.Region.Framework.Scenes
949 XmlDocument doc = new XmlDocument(); 878 XmlDocument doc = new XmlDocument();
950 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 879 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
951 880
952 // Capture script state while holding the lock 881 SceneObjectPart[] parts = m_parts.GetArray();
953 lock (m_parts) 882 for (int i = 0; i < parts.Length; i++)
954 { 883 {
955 foreach (SceneObjectPart part in m_parts.Values) 884 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates();
956 { 885 foreach (KeyValuePair<UUID, string> kvp in pstates)
957 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 886 states.Add(kvp.Key, kvp.Value);
958 foreach (UUID itemid in pstates.Keys)
959 {
960 states.Add(itemid, pstates[itemid]);
961 }
962 }
963 } 887 }
964 888
965 if (states.Count > 0) 889 if (states.Count > 0)
@@ -1005,15 +929,10 @@ namespace OpenSim.Region.Framework.Scenes
1005 929
1006 AbsolutePosition = detachedpos; 930 AbsolutePosition = detachedpos;
1007 m_rootPart.AttachedAvatar = UUID.Zero; 931 m_rootPart.AttachedAvatar = UUID.Zero;
1008 932
1009 //Anakin Lohner bug #3839 933 SceneObjectPart[] parts = m_parts.GetArray();
1010 lock (m_parts) 934 for (int i = 0; i < parts.Length; i++)
1011 { 935 parts[i].AttachedAvatar = UUID.Zero;
1012 foreach (SceneObjectPart p in m_parts.Values)
1013 {
1014 p.AttachedAvatar = UUID.Zero;
1015 }
1016 }
1017 936
1018 m_rootPart.SetParentLocalId(0); 937 m_rootPart.SetParentLocalId(0);
1019 SetAttachmentPoint((byte)0); 938 SetAttachmentPoint((byte)0);
@@ -1038,15 +957,10 @@ namespace OpenSim.Region.Framework.Scenes
1038 } 957 }
1039 958
1040 m_rootPart.AttachedAvatar = UUID.Zero; 959 m_rootPart.AttachedAvatar = UUID.Zero;
1041 960
1042 //Anakin Lohner bug #3839 961 SceneObjectPart[] parts = m_parts.GetArray();
1043 lock (m_parts) 962 for (int i = 0; i < parts.Length; i++)
1044 { 963 parts[i].AttachedAvatar = UUID.Zero;
1045 foreach (SceneObjectPart p in m_parts.Values)
1046 {
1047 p.AttachedAvatar = UUID.Zero;
1048 }
1049 }
1050 964
1051 m_rootPart.SetParentLocalId(0); 965 m_rootPart.SetParentLocalId(0);
1052 //m_rootPart.SetAttachmentPoint((byte)0); 966 //m_rootPart.SetAttachmentPoint((byte)0);
@@ -1069,13 +983,9 @@ namespace OpenSim.Region.Framework.Scenes
1069 983
1070 public override void UpdateMovement() 984 public override void UpdateMovement()
1071 { 985 {
1072 lock (m_parts) 986 SceneObjectPart[] parts = m_parts.GetArray();
1073 { 987 for (int i = 0; i < parts.Length; i++)
1074 foreach (SceneObjectPart part in m_parts.Values) 988 parts[i].UpdateMovement();
1075 {
1076 part.UpdateMovement();
1077 }
1078 }
1079 } 989 }
1080 990
1081 public ushort GetTimeDilation() 991 public ushort GetTimeDilation()
@@ -1108,8 +1018,7 @@ namespace OpenSim.Region.Framework.Scenes
1108 part.ParentID = 0; 1018 part.ParentID = 0;
1109 part.LinkNum = 0; 1019 part.LinkNum = 0;
1110 1020
1111 lock (m_parts) 1021 m_parts.Add(m_rootPart.UUID, m_rootPart);
1112 m_parts.Add(m_rootPart.UUID, m_rootPart);
1113 } 1022 }
1114 1023
1115 /// <summary> 1024 /// <summary>
@@ -1118,16 +1027,10 @@ namespace OpenSim.Region.Framework.Scenes
1118 /// <param name="part"></param> 1027 /// <param name="part"></param>
1119 public void AddPart(SceneObjectPart part) 1028 public void AddPart(SceneObjectPart part)
1120 { 1029 {
1121 lock (m_parts) 1030 part.SetParent(this);
1122 { 1031 part.LinkNum = m_parts.Add(part.UUID, part);
1123 part.SetParent(this); 1032 if (part.LinkNum == 2 && RootPart != null)
1124 m_parts.Add(part.UUID, part); 1033 RootPart.LinkNum = 1;
1125
1126 part.LinkNum = m_parts.Count;
1127
1128 if (part.LinkNum == 2 && RootPart != null)
1129 RootPart.LinkNum = 1;
1130 }
1131 } 1034 }
1132 1035
1133 /// <summary> 1036 /// <summary>
@@ -1135,28 +1038,20 @@ namespace OpenSim.Region.Framework.Scenes
1135 /// </summary> 1038 /// </summary>
1136 private void UpdateParentIDs() 1039 private void UpdateParentIDs()
1137 { 1040 {
1138 lock (m_parts) 1041 SceneObjectPart[] parts = m_parts.GetArray();
1042 for (int i = 0; i < parts.Length; i++)
1139 { 1043 {
1140 foreach (SceneObjectPart part in m_parts.Values) 1044 SceneObjectPart part = parts[i];
1141 { 1045 if (part.UUID != m_rootPart.UUID)
1142 if (part.UUID != m_rootPart.UUID) 1046 part.ParentID = m_rootPart.LocalId;
1143 {
1144 part.ParentID = m_rootPart.LocalId;
1145 }
1146 }
1147 } 1047 }
1148 } 1048 }
1149 1049
1150 public void RegenerateFullIDs() 1050 public void RegenerateFullIDs()
1151 { 1051 {
1152 lock (m_parts) 1052 SceneObjectPart[] parts = m_parts.GetArray();
1153 { 1053 for (int i = 0; i < parts.Length; i++)
1154 foreach (SceneObjectPart part in m_parts.Values) 1054 parts[i].UUID = UUID.Random();
1155 {
1156 part.UUID = UUID.Random();
1157
1158 }
1159 }
1160 } 1055 }
1161 1056
1162 // helper provided for parts. 1057 // helper provided for parts.
@@ -1189,7 +1084,7 @@ namespace OpenSim.Region.Framework.Scenes
1189 1084
1190 // teravus: AbsolutePosition is NOT a normal property! 1085 // teravus: AbsolutePosition is NOT a normal property!
1191 // the code in the getter of AbsolutePosition is significantly different then the code in the setter! 1086 // the code in the getter of AbsolutePosition is significantly different then the code in the setter!
1192 1087 // jhurliman: Then why is it a property instead of two methods?
1193 } 1088 }
1194 1089
1195 public UUID GetPartsFullID(uint localID) 1090 public UUID GetPartsFullID(uint localID)
@@ -1237,19 +1132,15 @@ namespace OpenSim.Region.Framework.Scenes
1237 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1132 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1238 public void DeleteGroupFromScene(bool silent) 1133 public void DeleteGroupFromScene(bool silent)
1239 { 1134 {
1240 List<SceneObjectPart> parts; 1135 SceneObjectPart[] parts = m_parts.GetArray();
1241 1136 for (int i = 0; i < parts.Length; i++)
1242 lock (m_parts)
1243 parts = m_parts.Values.ToList();
1244
1245 foreach (SceneObjectPart part in parts)
1246 { 1137 {
1138 SceneObjectPart part = parts[i];
1139
1247 Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1140 Scene.ForEachScenePresence(delegate(ScenePresence avatar)
1248 { 1141 {
1249 if (avatar.ParentID == LocalId) 1142 if (avatar.ParentID == LocalId)
1250 {
1251 avatar.StandUp(); 1143 avatar.StandUp();
1252 }
1253 1144
1254 if (!silent) 1145 if (!silent)
1255 { 1146 {
@@ -1283,16 +1174,15 @@ namespace OpenSim.Region.Framework.Scenes
1283 1174
1284 scriptEvents aggregateScriptEvents = 0; 1175 scriptEvents aggregateScriptEvents = 0;
1285 1176
1286 lock (m_parts) 1177 SceneObjectPart[] parts = m_parts.GetArray();
1178 for (int i = 0; i < parts.Length; i++)
1287 { 1179 {
1288 foreach (SceneObjectPart part in m_parts.Values) 1180 SceneObjectPart part = parts[i];
1289 { 1181 if (part == null)
1290 if (part == null) 1182 continue;
1291 continue; 1183 if (part != RootPart)
1292 if (part != RootPart) 1184 part.Flags = objectflagupdate;
1293 part.Flags = objectflagupdate; 1185 aggregateScriptEvents |= part.AggregateScriptEvents;
1294 aggregateScriptEvents |= part.AggregateScriptEvents;
1295 }
1296 } 1186 }
1297 1187
1298 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1188 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
@@ -1335,26 +1225,22 @@ namespace OpenSim.Region.Framework.Scenes
1335 /// <param name="m_physicalPrim"></param> 1225 /// <param name="m_physicalPrim"></param>
1336 public void ApplyPhysics(bool m_physicalPrim) 1226 public void ApplyPhysics(bool m_physicalPrim)
1337 { 1227 {
1338 lock (m_parts) 1228 // Apply physics to the root prim
1229 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1230
1231 // Apply physics to child prims
1232 SceneObjectPart[] parts = m_parts.GetArray();
1233 if (parts.Length > 1)
1339 { 1234 {
1340 if (m_parts.Count > 1) 1235 for (int i = 0; i < parts.Length; i++)
1341 {
1342 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1343 foreach (SceneObjectPart part in m_parts.Values)
1344 {
1345 if (part.LocalId != m_rootPart.LocalId)
1346 {
1347 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1348 }
1349 }
1350
1351 // Hack to get the physics scene geometries in the right spot
1352 ResetChildPrimPhysicsPositions();
1353 }
1354 else
1355 { 1236 {
1356 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1237 SceneObjectPart part = parts[i];
1238 if (part.LocalId != m_rootPart.LocalId)
1239 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1357 } 1240 }
1241
1242 // Hack to get the physics scene geometries in the right spot
1243 ResetChildPrimPhysicsPositions();
1358 } 1244 }
1359 } 1245 }
1360 1246
@@ -1365,13 +1251,9 @@ namespace OpenSim.Region.Framework.Scenes
1365 1251
1366 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1252 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1367 { 1253 {
1368 lock (m_parts) 1254 SceneObjectPart[] parts = m_parts.GetArray();
1369 { 1255 for (int i = 0; i < parts.Length; i++)
1370 foreach (SceneObjectPart part in m_parts.Values) 1256 whatToDo(parts[i]);
1371 {
1372 whatToDo(part);
1373 }
1374 }
1375 } 1257 }
1376 1258
1377 #region Events 1259 #region Events
@@ -1476,14 +1358,12 @@ namespace OpenSim.Region.Framework.Scenes
1476 RootPart.SendFullUpdate( 1358 RootPart.SendFullUpdate(
1477 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1359 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1478 1360
1479 lock (m_parts) 1361 SceneObjectPart[] parts = m_parts.GetArray();
1362 for (int i = 0; i < parts.Length; i++)
1480 { 1363 {
1481 foreach (SceneObjectPart part in m_parts.Values) 1364 SceneObjectPart part = parts[i];
1482 { 1365 if (part != RootPart)
1483 if (part != RootPart) 1366 part.SendFullUpdate(remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1484 part.SendFullUpdate(
1485 remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1486 }
1487 } 1367 }
1488 } 1368 }
1489 1369
@@ -1498,7 +1378,7 @@ namespace OpenSim.Region.Framework.Scenes
1498 { 1378 {
1499 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1379 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1500 dupe.m_isBackedUp = false; 1380 dupe.m_isBackedUp = false;
1501 dupe.m_parts = new Dictionary<UUID, SceneObjectPart>(); 1381 dupe.m_parts.Clear();
1502 1382
1503 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1383 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1504 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1384 // attachments do not bordercross while they're being duplicated. This is hacktastic!
@@ -1527,12 +1407,7 @@ namespace OpenSim.Region.Framework.Scenes
1527 if (userExposed) 1407 if (userExposed)
1528 dupe.m_rootPart.TrimPermissions(); 1408 dupe.m_rootPart.TrimPermissions();
1529 1409
1530 List<SceneObjectPart> partList; 1410 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1531
1532 lock (m_parts)
1533 {
1534 partList = new List<SceneObjectPart>(m_parts.Values);
1535 }
1536 1411
1537 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1412 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1538 { 1413 {
@@ -1837,17 +1712,10 @@ namespace OpenSim.Region.Framework.Scenes
1837 /// <param name="cGroupID"></param> 1712 /// <param name="cGroupID"></param>
1838 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 1713 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1839 { 1714 {
1840 SceneObjectPart newPart = null; 1715 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1841 1716 AddPart(newPart);
1842 lock (m_parts)
1843 {
1844 newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1845 newPart.SetParent(this);
1846 m_parts.Add(newPart.UUID, newPart);
1847 }
1848 1717
1849 SetPartAsNonRoot(newPart); 1718 SetPartAsNonRoot(newPart);
1850
1851 return newPart; 1719 return newPart;
1852 } 1720 }
1853 1721
@@ -1859,9 +1727,9 @@ namespace OpenSim.Region.Framework.Scenes
1859 /// </summary> 1727 /// </summary>
1860 public void ResetIDs() 1728 public void ResetIDs()
1861 { 1729 {
1862 lock (m_parts) 1730 lock (m_parts.SyncRoot)
1863 { 1731 {
1864 List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values); 1732 List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.GetArray());
1865 m_parts.Clear(); 1733 m_parts.Clear();
1866 foreach (SceneObjectPart part in partsList) 1734 foreach (SceneObjectPart part in partsList)
1867 { 1735 {
@@ -1877,7 +1745,6 @@ namespace OpenSim.Region.Framework.Scenes
1877 /// <param name="part"></param> 1745 /// <param name="part"></param>
1878 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags) 1746 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags)
1879 { 1747 {
1880
1881 remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask, 1748 remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask,
1882 RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask, 1749 RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask,
1883 RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category, 1750 RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category,
@@ -1922,12 +1789,10 @@ namespace OpenSim.Region.Framework.Scenes
1922 lastPhysGroupRot = GroupRotation; 1789 lastPhysGroupRot = GroupRotation;
1923 } 1790 }
1924 1791
1925 List<SceneObjectPart> partList = null; 1792 SceneObjectPart[] parts = m_parts.GetArray();
1926 lock (m_parts) 1793 for (int i = 0; i < parts.Length; i++)
1927 partList = new List<SceneObjectPart>(m_parts.Values);
1928
1929 foreach (SceneObjectPart part in partList)
1930 { 1794 {
1795 SceneObjectPart part = parts[i];
1931 if (!IsSelected) 1796 if (!IsSelected)
1932 part.UpdateLookAt(); 1797 part.UpdateLookAt();
1933 part.SendScheduledUpdates(); 1798 part.SendScheduledUpdates();
@@ -1940,27 +1805,22 @@ namespace OpenSim.Region.Framework.Scenes
1940 1805
1941 RootPart.AddFullUpdateToAvatar(presence); 1806 RootPart.AddFullUpdateToAvatar(presence);
1942 1807
1943 lock (m_parts) 1808 SceneObjectPart[] parts = m_parts.GetArray();
1809 for (int i = 0; i < parts.Length; i++)
1944 { 1810 {
1945 foreach (SceneObjectPart part in m_parts.Values) 1811 SceneObjectPart part = parts[i];
1946 { 1812 if (part != RootPart)
1947 if (part != RootPart) 1813 part.AddFullUpdateToAvatar(presence);
1948 part.AddFullUpdateToAvatar(presence);
1949 }
1950 } 1814 }
1951 } 1815 }
1952 1816
1953 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 1817 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1954 { 1818 {
1955// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); 1819// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name);
1956 1820
1957 lock (m_parts) 1821 SceneObjectPart[] parts = m_parts.GetArray();
1958 { 1822 for (int i = 0; i < parts.Length; i++)
1959 foreach (SceneObjectPart part in m_parts.Values) 1823 parts[i].AddTerseUpdateToAvatar(presence);
1960 {
1961 part.AddTerseUpdateToAvatar(presence);
1962 }
1963 }
1964 } 1824 }
1965 1825
1966 /// <summary> 1826 /// <summary>
@@ -1974,13 +1834,12 @@ namespace OpenSim.Region.Framework.Scenes
1974 checkAtTargets(); 1834 checkAtTargets();
1975 RootPart.ScheduleFullUpdate(); 1835 RootPart.ScheduleFullUpdate();
1976 1836
1977 lock (m_parts) 1837 SceneObjectPart[] parts = m_parts.GetArray();
1838 for (int i = 0; i < parts.Length; i++)
1978 { 1839 {
1979 foreach (SceneObjectPart part in m_parts.Values) 1840 SceneObjectPart part = parts[i];
1980 { 1841 if (part != RootPart)
1981 if (part != RootPart) 1842 part.ScheduleFullUpdate();
1982 part.ScheduleFullUpdate();
1983 }
1984 } 1843 }
1985 } 1844 }
1986 1845
@@ -1990,14 +1849,10 @@ namespace OpenSim.Region.Framework.Scenes
1990 public void ScheduleGroupForTerseUpdate() 1849 public void ScheduleGroupForTerseUpdate()
1991 { 1850 {
1992// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); 1851// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID);
1993 1852
1994 lock (m_parts) 1853 SceneObjectPart[] parts = m_parts.GetArray();
1995 { 1854 for (int i = 0; i < parts.Length; i++)
1996 foreach (SceneObjectPart part in m_parts.Values) 1855 parts[i].ScheduleTerseUpdate();
1997 {
1998 part.ScheduleTerseUpdate();
1999 }
2000 }
2001 } 1856 }
2002 1857
2003 /// <summary> 1858 /// <summary>
@@ -2012,13 +1867,12 @@ namespace OpenSim.Region.Framework.Scenes
2012 1867
2013 RootPart.SendFullUpdateToAllClients(); 1868 RootPart.SendFullUpdateToAllClients();
2014 1869
2015 lock (m_parts) 1870 SceneObjectPart[] parts = m_parts.GetArray();
1871 for (int i = 0; i < parts.Length; i++)
2016 { 1872 {
2017 foreach (SceneObjectPart part in m_parts.Values) 1873 SceneObjectPart part = parts[i];
2018 { 1874 if (part != RootPart)
2019 if (part != RootPart) 1875 part.SendFullUpdateToAllClients();
2020 part.SendFullUpdateToAllClients();
2021 }
2022 } 1876 }
2023 } 1877 }
2024 1878
@@ -2051,14 +1905,10 @@ namespace OpenSim.Region.Framework.Scenes
2051 { 1905 {
2052 if (IsDeleted) 1906 if (IsDeleted)
2053 return; 1907 return;
2054 1908
2055 lock (m_parts) 1909 SceneObjectPart[] parts = m_parts.GetArray();
2056 { 1910 for (int i = 0; i < parts.Length; i++)
2057 foreach (SceneObjectPart part in m_parts.Values) 1911 parts[i].SendTerseUpdateToAllClients();
2058 {
2059 part.SendTerseUpdateToAllClients();
2060 }
2061 }
2062 } 1912 }
2063 1913
2064 #endregion 1914 #endregion
@@ -2072,15 +1922,11 @@ namespace OpenSim.Region.Framework.Scenes
2072 /// <returns>null if no child part with that linknum or child part</returns> 1922 /// <returns>null if no child part with that linknum or child part</returns>
2073 public SceneObjectPart GetLinkNumPart(int linknum) 1923 public SceneObjectPart GetLinkNumPart(int linknum)
2074 { 1924 {
2075 lock (m_parts) 1925 SceneObjectPart[] parts = m_parts.GetArray();
1926 for (int i = 0; i < parts.Length; i++)
2076 { 1927 {
2077 foreach (SceneObjectPart part in m_parts.Values) 1928 if (parts[i].LinkNum == linknum)
2078 { 1929 return parts[i];
2079 if (part.LinkNum == linknum)
2080 {
2081 return part;
2082 }
2083 }
2084 } 1930 }
2085 1931
2086 return null; 1932 return null;
@@ -2094,8 +1940,7 @@ namespace OpenSim.Region.Framework.Scenes
2094 public SceneObjectPart GetChildPart(UUID primID) 1940 public SceneObjectPart GetChildPart(UUID primID)
2095 { 1941 {
2096 SceneObjectPart childPart; 1942 SceneObjectPart childPart;
2097 lock (m_parts) 1943 m_parts.TryGetValue(primID, out childPart);
2098 m_parts.TryGetValue(primID, out childPart);
2099 return childPart; 1944 return childPart;
2100 } 1945 }
2101 1946
@@ -2106,17 +1951,11 @@ namespace OpenSim.Region.Framework.Scenes
2106 /// <returns>null if a child part with the local ID was not found</returns> 1951 /// <returns>null if a child part with the local ID was not found</returns>
2107 public SceneObjectPart GetChildPart(uint localID) 1952 public SceneObjectPart GetChildPart(uint localID)
2108 { 1953 {
2109 //m_log.DebugFormat("Entered looking for {0}", localID); 1954 SceneObjectPart[] parts = m_parts.GetArray();
2110 lock (m_parts) 1955 for (int i = 0; i < parts.Length; i++)
2111 { 1956 {
2112 foreach (SceneObjectPart part in m_parts.Values) 1957 if (parts[i].LocalId == localID)
2113 { 1958 return parts[i];
2114 //m_log.DebugFormat("Found {0}", part.LocalId);
2115 if (part.LocalId == localID)
2116 {
2117 return part;
2118 }
2119 }
2120 } 1959 }
2121 1960
2122 return null; 1961 return null;
@@ -2130,13 +1969,7 @@ namespace OpenSim.Region.Framework.Scenes
2130 /// <returns></returns> 1969 /// <returns></returns>
2131 public bool HasChildPrim(UUID primID) 1970 public bool HasChildPrim(UUID primID)
2132 { 1971 {
2133 lock (m_parts) 1972 return m_parts.ContainsKey(primID);
2134 {
2135 if (m_parts.ContainsKey(primID))
2136 return true;
2137 }
2138
2139 return false;
2140 } 1973 }
2141 1974
2142 /// <summary> 1975 /// <summary>
@@ -2147,17 +1980,11 @@ namespace OpenSim.Region.Framework.Scenes
2147 /// <returns></returns> 1980 /// <returns></returns>
2148 public bool HasChildPrim(uint localID) 1981 public bool HasChildPrim(uint localID)
2149 { 1982 {
2150 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 1983 SceneObjectPart[] parts = m_parts.GetArray();
2151 lock (m_parts) 1984 for (int i = 0; i < parts.Length; i++)
2152 { 1985 {
2153 foreach (SceneObjectPart part in m_parts.Values) 1986 if (parts[i].LocalId == localID)
2154 { 1987 return true;
2155 //m_log.DebugFormat("Found {0}", part.LocalId);
2156 if (part.LocalId == localID)
2157 {
2158 return true;
2159 }
2160 }
2161 } 1988 }
2162 1989
2163 return false; 1990 return false;
@@ -2208,19 +2035,21 @@ namespace OpenSim.Region.Framework.Scenes
2208 if (m_rootPart.LinkNum == 0) 2035 if (m_rootPart.LinkNum == 0)
2209 m_rootPart.LinkNum = 1; 2036 m_rootPart.LinkNum = 1;
2210 2037
2211 lock (m_parts) 2038 lock (m_parts.SyncRoot)
2212 { 2039 {
2213 m_parts.Add(linkPart.UUID, linkPart); 2040 m_parts.Add(linkPart.UUID, linkPart);
2214 2041
2215 // Insert in terms of link numbers, the new links 2042 // Insert in terms of link numbers, the new links
2216 // before the current ones (with the exception of 2043 // before the current ones (with the exception of
2217 // the root prim. Shuffle the old ones up 2044 // the root prim. Shuffle the old ones up
2218 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2045 SceneObjectPart[] parts = m_parts.GetArray();
2046 for (int i = 0; i < parts.Length; i++)
2219 { 2047 {
2220 if (kvp.Value.LinkNum != 1) 2048 SceneObjectPart part = parts[i];
2049 if (part.LinkNum != 1)
2221 { 2050 {
2222 // Don't update root prim link number 2051 // Don't update root prim link number
2223 kvp.Value.LinkNum += objectGroup.PrimCount; 2052 part.LinkNum += objectGroup.PrimCount;
2224 } 2053 }
2225 } 2054 }
2226 2055
@@ -2232,29 +2061,26 @@ namespace OpenSim.Region.Framework.Scenes
2232 //if (linkPart.PhysActor != null) 2061 //if (linkPart.PhysActor != null)
2233 //{ 2062 //{
2234 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2063 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2235 2064
2236 //linkPart.PhysActor = null; 2065 //linkPart.PhysActor = null;
2237 //} 2066 //}
2238 2067
2239 //TODO: rest of parts 2068 //TODO: rest of parts
2240 int linkNum = 3; 2069 int linkNum = 3;
2241 foreach (SceneObjectPart part in objectGroup.Children.Values) 2070 SceneObjectPart[] ogParts = objectGroup.Parts;
2071 for (int i = 0; i < ogParts.Length; i++)
2242 { 2072 {
2073 SceneObjectPart part = ogParts[i];
2243 if (part.UUID != objectGroup.m_rootPart.UUID) 2074 if (part.UUID != objectGroup.m_rootPart.UUID)
2244 {
2245 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2075 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2246 }
2247 part.ClearUndoState(); 2076 part.ClearUndoState();
2248 } 2077 }
2249 } 2078 }
2250 2079
2251 m_scene.UnlinkSceneObject(objectGroup, true); 2080 m_scene.UnlinkSceneObject(objectGroup, true);
2252 objectGroup.m_isDeleted = true; 2081 objectGroup.m_isDeleted = true;
2253 2082
2254 lock (objectGroup.m_parts) 2083 objectGroup.m_parts.Clear();
2255 {
2256 objectGroup.m_parts.Clear();
2257 }
2258 2084
2259 // Can't do this yet since backup still makes use of the root part without any synchronization 2085 // Can't do this yet since backup still makes use of the root part without any synchronization
2260// objectGroup.m_rootPart = null; 2086// objectGroup.m_rootPart = null;
@@ -2324,20 +2150,24 @@ namespace OpenSim.Region.Framework.Scenes
2324 Quaternion worldRot = linkPart.GetWorldRotation(); 2150 Quaternion worldRot = linkPart.GetWorldRotation();
2325 2151
2326 // Remove the part from this object 2152 // Remove the part from this object
2327 lock (m_parts) 2153 lock (m_parts.SyncRoot)
2328 { 2154 {
2329 m_parts.Remove(linkPart.UUID); 2155 m_parts.Remove(linkPart.UUID);
2330 2156
2331 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2157 SceneObjectPart[] parts = m_parts.GetArray();
2158
2159 if (parts.Length == 1 && RootPart != null)
2332 { 2160 {
2161 // Single prim left
2333 RootPart.LinkNum = 0; 2162 RootPart.LinkNum = 0;
2334 } 2163 }
2335 else 2164 else
2336 { 2165 {
2337 foreach (SceneObjectPart p in m_parts.Values) 2166 for (int i = 0; i < parts.Length; i++)
2338 { 2167 {
2339 if (p.LinkNum > linkPart.LinkNum) 2168 SceneObjectPart part = parts[i];
2340 p.LinkNum--; 2169 if (part.LinkNum > linkPart.LinkNum)
2170 part.LinkNum--;
2341 } 2171 }
2342 } 2172 }
2343 } 2173 }
@@ -2409,7 +2239,6 @@ namespace OpenSim.Region.Framework.Scenes
2409 part.SetParent(this); 2239 part.SetParent(this);
2410 part.ParentID = m_rootPart.LocalId; 2240 part.ParentID = m_rootPart.LocalId;
2411 2241
2412 // Caller locks m_parts for us
2413 m_parts.Add(part.UUID, part); 2242 m_parts.Add(part.UUID, part);
2414 2243
2415 part.LinkNum = linkNum; 2244 part.LinkNum = linkNum;
@@ -2662,24 +2491,21 @@ namespace OpenSim.Region.Framework.Scenes
2662 2491
2663 if (selectionPart != null) 2492 if (selectionPart != null)
2664 { 2493 {
2665 lock (m_parts) 2494 SceneObjectPart[] parts = m_parts.GetArray();
2495 for (int i = 0; i < parts.Length; i++)
2666 { 2496 {
2667 foreach (SceneObjectPart part in m_parts.Values) 2497 SceneObjectPart part = parts[i];
2498 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2499 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
2500 part.Scale.Z > m_scene.RegionInfo.PhysPrimMax)
2668 { 2501 {
2669 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2502 UsePhysics = false; // Reset physics
2670 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2503 break;
2671 part.Scale.Z > m_scene.RegionInfo.PhysPrimMax)
2672 {
2673 UsePhysics = false; // Reset physics
2674 break;
2675 }
2676 }
2677
2678 foreach (SceneObjectPart part in m_parts.Values)
2679 {
2680 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2681 } 2504 }
2682 } 2505 }
2506
2507 for (int i = 0; i < parts.Length; i++)
2508 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2683 } 2509 }
2684 } 2510 }
2685 2511
@@ -2693,18 +2519,6 @@ namespace OpenSim.Region.Framework.Scenes
2693 } 2519 }
2694 2520
2695 /// <summary> 2521 /// <summary>
2696 /// Get the parts of this scene object
2697 /// </summary>
2698 /// <returns></returns>
2699 public SceneObjectPart[] GetParts()
2700 {
2701 int numParts = Children.Count;
2702 SceneObjectPart[] partArray = new SceneObjectPart[numParts];
2703 Children.Values.CopyTo(partArray, 0);
2704 return partArray;
2705 }
2706
2707 /// <summary>
2708 /// Update the texture entry for this part 2522 /// Update the texture entry for this part
2709 /// </summary> 2523 /// </summary>
2710 /// <param name="localID"></param> 2524 /// <param name="localID"></param>
@@ -2721,12 +2535,9 @@ namespace OpenSim.Region.Framework.Scenes
2721 public void UpdatePermissions(UUID AgentID, byte field, uint localID, 2535 public void UpdatePermissions(UUID AgentID, byte field, uint localID,
2722 uint mask, byte addRemTF) 2536 uint mask, byte addRemTF)
2723 { 2537 {
2724 List<SceneObjectPart> partList = null; 2538 SceneObjectPart[] parts = m_parts.GetArray();
2725 lock (m_parts) 2539 for (int i = 0; i < parts.Length; i++)
2726 partList = new List<SceneObjectPart>(m_parts.Values); 2540 parts[i].UpdatePermissions(AgentID, field, localID, mask, addRemTF);
2727
2728 foreach (SceneObjectPart part in partList)
2729 part.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
2730 2541
2731 HasGroupChanged = true; 2542 HasGroupChanged = true;
2732 } 2543 }
@@ -2829,77 +2640,77 @@ namespace OpenSim.Region.Framework.Scenes
2829 float y = (scale.Y / part.Scale.Y); 2640 float y = (scale.Y / part.Scale.Y);
2830 float z = (scale.Z / part.Scale.Z); 2641 float z = (scale.Z / part.Scale.Z);
2831 2642
2832 lock (m_parts) 2643 SceneObjectPart[] parts;
2644 if (x > 1.0f || y > 1.0f || z > 1.0f)
2833 { 2645 {
2834 if (x > 1.0f || y > 1.0f || z > 1.0f) 2646 parts = m_parts.GetArray();
2647 for (int i = 0; i < parts.Length; i++)
2835 { 2648 {
2836 foreach (SceneObjectPart obPart in m_parts.Values) 2649 SceneObjectPart obPart = parts[i];
2650 if (obPart.UUID != m_rootPart.UUID)
2837 { 2651 {
2838 if (obPart.UUID != m_rootPart.UUID) 2652 obPart.IgnoreUndoUpdate = true;
2839 { 2653 Vector3 oldSize = new Vector3(obPart.Scale);
2840 obPart.IgnoreUndoUpdate = true;
2841 Vector3 oldSize = new Vector3(obPart.Scale);
2842 2654
2843 float f = 1.0f; 2655 float f = 1.0f;
2844 float a = 1.0f; 2656 float a = 1.0f;
2845 2657
2846 if (part.PhysActor != null && part.PhysActor.IsPhysical) 2658 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2659 {
2660 if (oldSize.X * x > m_scene.m_maxPhys)
2661 {
2662 f = m_scene.m_maxPhys / oldSize.X;
2663 a = f / x;
2664 x *= a;
2665 y *= a;
2666 z *= a;
2667 }
2668 if (oldSize.Y * y > m_scene.m_maxPhys)
2669 {
2670 f = m_scene.m_maxPhys / oldSize.Y;
2671 a = f / y;
2672 x *= a;
2673 y *= a;
2674 z *= a;
2675 }
2676 if (oldSize.Z * z > m_scene.m_maxPhys)
2677 {
2678 f = m_scene.m_maxPhys / oldSize.Z;
2679 a = f / z;
2680 x *= a;
2681 y *= a;
2682 z *= a;
2683 }
2684 }
2685 else
2686 {
2687 if (oldSize.X * x > m_scene.m_maxNonphys)
2688 {
2689 f = m_scene.m_maxNonphys / oldSize.X;
2690 a = f / x;
2691 x *= a;
2692 y *= a;
2693 z *= a;
2694 }
2695 if (oldSize.Y * y > m_scene.m_maxNonphys)
2847 { 2696 {
2848 if (oldSize.X*x > m_scene.m_maxPhys) 2697 f = m_scene.m_maxNonphys / oldSize.Y;
2849 { 2698 a = f / y;
2850 f = m_scene.m_maxPhys / oldSize.X; 2699 x *= a;
2851 a = f / x; 2700 y *= a;
2852 x *= a; 2701 z *= a;
2853 y *= a;
2854 z *= a;
2855 }
2856 if (oldSize.Y*y > m_scene.m_maxPhys)
2857 {
2858 f = m_scene.m_maxPhys / oldSize.Y;
2859 a = f / y;
2860 x *= a;
2861 y *= a;
2862 z *= a;
2863 }
2864 if (oldSize.Z*z > m_scene.m_maxPhys)
2865 {
2866 f = m_scene.m_maxPhys / oldSize.Z;
2867 a = f / z;
2868 x *= a;
2869 y *= a;
2870 z *= a;
2871 }
2872 } 2702 }
2873 else 2703 if (oldSize.Z * z > m_scene.m_maxNonphys)
2874 { 2704 {
2875 if (oldSize.X*x > m_scene.m_maxNonphys) 2705 f = m_scene.m_maxNonphys / oldSize.Z;
2876 { 2706 a = f / z;
2877 f = m_scene.m_maxNonphys / oldSize.X; 2707 x *= a;
2878 a = f / x; 2708 y *= a;
2879 x *= a; 2709 z *= a;
2880 y *= a;
2881 z *= a;
2882 }
2883 if (oldSize.Y*y > m_scene.m_maxNonphys)
2884 {
2885 f = m_scene.m_maxNonphys / oldSize.Y;
2886 a = f / y;
2887 x *= a;
2888 y *= a;
2889 z *= a;
2890 }
2891 if (oldSize.Z*z > m_scene.m_maxNonphys)
2892 {
2893 f = m_scene.m_maxNonphys / oldSize.Z;
2894 a = f / z;
2895 x *= a;
2896 y *= a;
2897 z *= a;
2898 }
2899 } 2710 }
2900 obPart.IgnoreUndoUpdate = false;
2901 obPart.StoreUndoState();
2902 } 2711 }
2712 obPart.IgnoreUndoUpdate = false;
2713 obPart.StoreUndoState();
2903 } 2714 }
2904 } 2715 }
2905 } 2716 }
@@ -2910,27 +2721,26 @@ namespace OpenSim.Region.Framework.Scenes
2910 prevScale.Z *= z; 2721 prevScale.Z *= z;
2911 part.Resize(prevScale); 2722 part.Resize(prevScale);
2912 2723
2913 lock (m_parts) 2724 parts = m_parts.GetArray();
2725 for (int i = 0; i < parts.Length; i++)
2914 { 2726 {
2915 foreach (SceneObjectPart obPart in m_parts.Values) 2727 SceneObjectPart obPart = parts[i];
2728 obPart.IgnoreUndoUpdate = true;
2729 if (obPart.UUID != m_rootPart.UUID)
2916 { 2730 {
2917 obPart.IgnoreUndoUpdate = true; 2731 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2918 if (obPart.UUID != m_rootPart.UUID) 2732 currentpos.X *= x;
2919 { 2733 currentpos.Y *= y;
2920 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 2734 currentpos.Z *= z;
2921 currentpos.X *= x; 2735 Vector3 newSize = new Vector3(obPart.Scale);
2922 currentpos.Y *= y; 2736 newSize.X *= x;
2923 currentpos.Z *= z; 2737 newSize.Y *= y;
2924 Vector3 newSize = new Vector3(obPart.Scale); 2738 newSize.Z *= z;
2925 newSize.X *= x; 2739 obPart.Resize(newSize);
2926 newSize.Y *= y; 2740 obPart.UpdateOffSet(currentpos);
2927 newSize.Z *= z;
2928 obPart.Resize(newSize);
2929 obPart.UpdateOffSet(currentpos);
2930 }
2931 obPart.IgnoreUndoUpdate = false;
2932 obPart.StoreUndoState();
2933 } 2741 }
2742 obPart.IgnoreUndoUpdate = false;
2743 obPart.StoreUndoState();
2934 } 2744 }
2935 2745
2936 if (part.PhysActor != null) 2746 if (part.PhysActor != null)
@@ -2956,10 +2766,10 @@ namespace OpenSim.Region.Framework.Scenes
2956 /// <param name="pos"></param> 2766 /// <param name="pos"></param>
2957 public void UpdateGroupPosition(Vector3 pos) 2767 public void UpdateGroupPosition(Vector3 pos)
2958 { 2768 {
2959 foreach (SceneObjectPart part in Children.Values) 2769 SceneObjectPart[] parts = m_parts.GetArray();
2960 { 2770 for (int i = 0; i < parts.Length; i++)
2961 part.StoreUndoState(); 2771 parts[i].StoreUndoState();
2962 } 2772
2963 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 2773 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2964 { 2774 {
2965 if (IsAttachment) 2775 if (IsAttachment)
@@ -2994,10 +2804,11 @@ namespace OpenSim.Region.Framework.Scenes
2994 public void UpdateSinglePosition(Vector3 pos, uint localID) 2804 public void UpdateSinglePosition(Vector3 pos, uint localID)
2995 { 2805 {
2996 SceneObjectPart part = GetChildPart(localID); 2806 SceneObjectPart part = GetChildPart(localID);
2997 foreach (SceneObjectPart parts in Children.Values) 2807
2998 { 2808 SceneObjectPart[] parts = m_parts.GetArray();
2999 parts.StoreUndoState(); 2809 for (int i = 0; i < parts.Length; i++)
3000 } 2810 parts[i].StoreUndoState();
2811
3001 if (part != null) 2812 if (part != null)
3002 { 2813 {
3003 if (part.UUID == m_rootPart.UUID) 2814 if (part.UUID == m_rootPart.UUID)
@@ -3019,10 +2830,10 @@ namespace OpenSim.Region.Framework.Scenes
3019 /// <param name="pos"></param> 2830 /// <param name="pos"></param>
3020 private void UpdateRootPosition(Vector3 pos) 2831 private void UpdateRootPosition(Vector3 pos)
3021 { 2832 {
3022 foreach (SceneObjectPart part in Children.Values) 2833 SceneObjectPart[] parts = m_parts.GetArray();
3023 { 2834 for (int i = 0; i < parts.Length; i++)
3024 part.StoreUndoState(); 2835 parts[i].StoreUndoState();
3025 } 2836
3026 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 2837 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3027 Vector3 oldPos = 2838 Vector3 oldPos =
3028 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 2839 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
@@ -3034,15 +2845,12 @@ namespace OpenSim.Region.Framework.Scenes
3034 axDiff *= Quaternion.Inverse(partRotation); 2845 axDiff *= Quaternion.Inverse(partRotation);
3035 diff = axDiff; 2846 diff = axDiff;
3036 2847
3037 lock (m_parts) 2848 parts = m_parts.GetArray();
2849 for (int i = 0; i < parts.Length; i++)
3038 { 2850 {
3039 foreach (SceneObjectPart obPart in m_parts.Values) 2851 SceneObjectPart obPart = parts[i];
3040 { 2852 if (obPart.UUID != m_rootPart.UUID)
3041 if (obPart.UUID != m_rootPart.UUID) 2853 obPart.OffsetPosition = obPart.OffsetPosition + diff;
3042 {
3043 obPart.OffsetPosition = obPart.OffsetPosition + diff;
3044 }
3045 }
3046 } 2854 }
3047 2855
3048 AbsolutePosition = newPos; 2856 AbsolutePosition = newPos;
@@ -3066,10 +2874,10 @@ namespace OpenSim.Region.Framework.Scenes
3066 /// <param name="rot"></param> 2874 /// <param name="rot"></param>
3067 public void UpdateGroupRotationR(Quaternion rot) 2875 public void UpdateGroupRotationR(Quaternion rot)
3068 { 2876 {
3069 foreach (SceneObjectPart parts in Children.Values) 2877 SceneObjectPart[] parts = m_parts.GetArray();
3070 { 2878 for (int i = 0; i < parts.Length; i++)
3071 parts.StoreUndoState(); 2879 parts[i].StoreUndoState();
3072 } 2880
3073 m_rootPart.UpdateRotation(rot); 2881 m_rootPart.UpdateRotation(rot);
3074 2882
3075 PhysicsActor actor = m_rootPart.PhysActor; 2883 PhysicsActor actor = m_rootPart.PhysActor;
@@ -3090,10 +2898,10 @@ namespace OpenSim.Region.Framework.Scenes
3090 /// <param name="rot"></param> 2898 /// <param name="rot"></param>
3091 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 2899 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
3092 { 2900 {
3093 foreach (SceneObjectPart parts in Children.Values) 2901 SceneObjectPart[] parts = m_parts.GetArray();
3094 { 2902 for (int i = 0; i < parts.Length; i++)
3095 parts.StoreUndoState(); 2903 parts[i].StoreUndoState();
3096 } 2904
3097 m_rootPart.UpdateRotation(rot); 2905 m_rootPart.UpdateRotation(rot);
3098 2906
3099 PhysicsActor actor = m_rootPart.PhysActor; 2907 PhysicsActor actor = m_rootPart.PhysActor;
@@ -3117,10 +2925,11 @@ namespace OpenSim.Region.Framework.Scenes
3117 public void UpdateSingleRotation(Quaternion rot, uint localID) 2925 public void UpdateSingleRotation(Quaternion rot, uint localID)
3118 { 2926 {
3119 SceneObjectPart part = GetChildPart(localID); 2927 SceneObjectPart part = GetChildPart(localID);
3120 foreach (SceneObjectPart parts in Children.Values) 2928
3121 { 2929 SceneObjectPart[] parts = m_parts.GetArray();
3122 parts.StoreUndoState(); 2930 for (int i = 0; i < parts.Length; i++)
3123 } 2931 parts[i].StoreUndoState();
2932
3124 if (part != null) 2933 if (part != null)
3125 { 2934 {
3126 if (part.UUID == m_rootPart.UUID) 2935 if (part.UUID == m_rootPart.UUID)
@@ -3177,33 +2986,35 @@ namespace OpenSim.Region.Framework.Scenes
3177 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 2986 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3178 } 2987 }
3179 2988
3180 lock (m_parts) 2989 SceneObjectPart[] parts = m_parts.GetArray();
2990 for (int i = 0; i < parts.Length; i++)
3181 { 2991 {
3182 foreach (SceneObjectPart prim in m_parts.Values) 2992 SceneObjectPart prim = parts[i];
2993 if (prim.UUID != m_rootPart.UUID)
3183 { 2994 {
3184 if (prim.UUID != m_rootPart.UUID) 2995 prim.IgnoreUndoUpdate = true;
3185 { 2996 Vector3 axPos = prim.OffsetPosition;
3186 prim.IgnoreUndoUpdate = true; 2997 axPos *= oldParentRot;
3187 Vector3 axPos = prim.OffsetPosition; 2998 axPos *= Quaternion.Inverse(axRot);
3188 axPos *= oldParentRot; 2999 prim.OffsetPosition = axPos;
3189 axPos *= Quaternion.Inverse(axRot); 3000 Quaternion primsRot = prim.RotationOffset;
3190 prim.OffsetPosition = axPos; 3001 Quaternion newRot = primsRot * oldParentRot;
3191 Quaternion primsRot = prim.RotationOffset; 3002 newRot *= Quaternion.Inverse(axRot);
3192 Quaternion newRot = primsRot * oldParentRot; 3003 prim.RotationOffset = newRot;
3193 newRot *= Quaternion.Inverse(axRot); 3004 prim.ScheduleTerseUpdate();
3194 prim.RotationOffset = newRot;
3195 prim.ScheduleTerseUpdate();
3196 }
3197 } 3005 }
3198 } 3006 }
3199 foreach (SceneObjectPart childpart in Children.Values) 3007
3008 for (int i = 0; i < parts.Length; i++)
3200 { 3009 {
3010 SceneObjectPart childpart = parts[i];
3201 if (childpart != m_rootPart) 3011 if (childpart != m_rootPart)
3202 { 3012 {
3203 childpart.IgnoreUndoUpdate = false; 3013 childpart.IgnoreUndoUpdate = false;
3204 childpart.StoreUndoState(); 3014 childpart.StoreUndoState();
3205 } 3015 }
3206 } 3016 }
3017
3207 m_rootPart.ScheduleTerseUpdate(); 3018 m_rootPart.ScheduleTerseUpdate();
3208 } 3019 }
3209 3020
@@ -3324,17 +3135,10 @@ namespace OpenSim.Region.Framework.Scenes
3324 3135
3325 if (atTargets.Count > 0) 3136 if (atTargets.Count > 0)
3326 { 3137 {
3327 uint[] localids = new uint[0]; 3138 SceneObjectPart[] parts = m_parts.GetArray();
3328 lock (m_parts) 3139 uint[] localids = new uint[parts.Length];
3329 { 3140 for (int i = 0; i < parts.Length; i++)
3330 localids = new uint[m_parts.Count]; 3141 localids[i] = parts[i].LocalId;
3331 int cntr = 0;
3332 foreach (SceneObjectPart part in m_parts.Values)
3333 {
3334 localids[cntr] = part.LocalId;
3335 cntr++;
3336 }
3337 }
3338 3142
3339 for (int ctr = 0; ctr < localids.Length; ctr++) 3143 for (int ctr = 0; ctr < localids.Length; ctr++)
3340 { 3144 {
@@ -3352,17 +3156,10 @@ namespace OpenSim.Region.Framework.Scenes
3352 if (m_scriptListens_notAtTarget && !at_target) 3156 if (m_scriptListens_notAtTarget && !at_target)
3353 { 3157 {
3354 //trigger not_at_target 3158 //trigger not_at_target
3355 uint[] localids = new uint[0]; 3159 SceneObjectPart[] parts = m_parts.GetArray();
3356 lock (m_parts) 3160 uint[] localids = new uint[parts.Length];
3357 { 3161 for (int i = 0; i < parts.Length; i++)
3358 localids = new uint[m_parts.Count]; 3162 localids[i] = parts[i].LocalId;
3359 int cntr = 0;
3360 foreach (SceneObjectPart part in m_parts.Values)
3361 {
3362 localids[cntr] = part.LocalId;
3363 cntr++;
3364 }
3365 }
3366 3163
3367 for (int ctr = 0; ctr < localids.Length; ctr++) 3164 for (int ctr = 0; ctr < localids.Length; ctr++)
3368 { 3165 {
@@ -3403,17 +3200,10 @@ namespace OpenSim.Region.Framework.Scenes
3403 3200
3404 if (atRotTargets.Count > 0) 3201 if (atRotTargets.Count > 0)
3405 { 3202 {
3406 uint[] localids = new uint[0]; 3203 SceneObjectPart[] parts = m_parts.GetArray();
3407 lock (m_parts) 3204 uint[] localids = new uint[parts.Length];
3408 { 3205 for (int i = 0; i < parts.Length; i++)
3409 localids = new uint[m_parts.Count]; 3206 localids[i] = parts[i].LocalId;
3410 int cntr = 0;
3411 foreach (SceneObjectPart part in m_parts.Values)
3412 {
3413 localids[cntr] = part.LocalId;
3414 cntr++;
3415 }
3416 }
3417 3207
3418 for (int ctr = 0; ctr < localids.Length; ctr++) 3208 for (int ctr = 0; ctr < localids.Length; ctr++)
3419 { 3209 {
@@ -3431,17 +3221,10 @@ namespace OpenSim.Region.Framework.Scenes
3431 if (m_scriptListens_notAtRotTarget && !at_Rottarget) 3221 if (m_scriptListens_notAtRotTarget && !at_Rottarget)
3432 { 3222 {
3433 //trigger not_at_target 3223 //trigger not_at_target
3434 uint[] localids = new uint[0]; 3224 SceneObjectPart[] parts = m_parts.GetArray();
3435 lock (m_parts) 3225 uint[] localids = new uint[parts.Length];
3436 { 3226 for (int i = 0; i < parts.Length; i++)
3437 localids = new uint[m_parts.Count]; 3227 localids[i] = parts[i].LocalId;
3438 int cntr = 0;
3439 foreach (SceneObjectPart part in m_parts.Values)
3440 {
3441 localids[cntr] = part.LocalId;
3442 cntr++;
3443 }
3444 }
3445 3228
3446 for (int ctr = 0; ctr < localids.Length; ctr++) 3229 for (int ctr = 0; ctr < localids.Length; ctr++)
3447 { 3230 {
@@ -3455,40 +3238,36 @@ namespace OpenSim.Region.Framework.Scenes
3455 public float GetMass() 3238 public float GetMass()
3456 { 3239 {
3457 float retmass = 0f; 3240 float retmass = 0f;
3458 lock (m_parts) 3241
3459 { 3242 SceneObjectPart[] parts = m_parts.GetArray();
3460 foreach (SceneObjectPart part in m_parts.Values) 3243 for (int i = 0; i < parts.Length; i++)
3461 { 3244 retmass += parts[i].GetMass();
3462 retmass += part.GetMass(); 3245
3463 }
3464 }
3465 return retmass; 3246 return retmass;
3466 } 3247 }
3467 3248
3468 public void CheckSculptAndLoad() 3249 public void CheckSculptAndLoad()
3469 { 3250 {
3470 lock (m_parts) 3251 if (IsDeleted)
3252 return;
3253 if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
3254 return;
3255
3256 SceneObjectPart[] parts = m_parts.GetArray();
3257 for (int i = 0; i < parts.Length; i++)
3471 { 3258 {
3472 if (!IsDeleted) 3259 SceneObjectPart part = parts[i];
3260 if (part.Shape.SculptEntry && part.Shape.SculptTexture != UUID.Zero)
3473 { 3261 {
3474 if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == 0) 3262 // check if a previously decoded sculpt map has been cached
3263 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + part.Shape.SculptTexture.ToString())))
3475 { 3264 {
3476 foreach (SceneObjectPart part in m_parts.Values) 3265 part.SculptTextureCallback(part.Shape.SculptTexture, null);
3477 { 3266 }
3478 if (part.Shape.SculptEntry && part.Shape.SculptTexture != UUID.Zero) 3267 else
3479 { 3268 {
3480 // check if a previously decoded sculpt map has been cached 3269 m_scene.AssetService.Get(
3481 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + part.Shape.SculptTexture.ToString()))) 3270 part.Shape.SculptTexture.ToString(), part, AssetReceived);
3482 {
3483 part.SculptTextureCallback(part.Shape.SculptTexture, null);
3484 }
3485 else
3486 {
3487 m_scene.AssetService.Get(
3488 part.Shape.SculptTexture.ToString(), part, AssetReceived);
3489 }
3490 }
3491 }
3492 } 3271 }
3493 } 3272 }
3494 } 3273 }
@@ -3512,15 +3291,12 @@ namespace OpenSim.Region.Framework.Scenes
3512 /// <param name="client"></param> 3291 /// <param name="client"></param>
3513 public void SetGroup(UUID GroupID, IClientAPI client) 3292 public void SetGroup(UUID GroupID, IClientAPI client)
3514 { 3293 {
3515 lock (m_parts) 3294 SceneObjectPart[] parts = m_parts.GetArray();
3295 for (int i = 0; i < parts.Length; i++)
3516 { 3296 {
3517 foreach (SceneObjectPart part in m_parts.Values) 3297 SceneObjectPart part = parts[i];
3518 { 3298 part.SetGroup(GroupID, client);
3519 part.SetGroup(GroupID, client); 3299 part.Inventory.ChangeInventoryGroup(GroupID);
3520 part.Inventory.ChangeInventoryGroup(GroupID);
3521 }
3522
3523 HasGroupChanged = true;
3524 } 3300 }
3525 3301
3526 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 3302 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
@@ -3530,10 +3306,9 @@ namespace OpenSim.Region.Framework.Scenes
3530 3306
3531 public void TriggerScriptChangedEvent(Changed val) 3307 public void TriggerScriptChangedEvent(Changed val)
3532 { 3308 {
3533 foreach (SceneObjectPart part in Children.Values) 3309 SceneObjectPart[] parts = m_parts.GetArray();
3534 { 3310 for (int i = 0; i < parts.Length; i++)
3535 part.TriggerScriptChangedEvent(val); 3311 parts[i].TriggerScriptChangedEvent(val);
3536 }
3537 } 3312 }
3538 3313
3539 public override string ToString() 3314 public override string ToString()
@@ -3543,11 +3318,9 @@ namespace OpenSim.Region.Framework.Scenes
3543 3318
3544 public void SetAttachmentPoint(byte point) 3319 public void SetAttachmentPoint(byte point)
3545 { 3320 {
3546 lock (m_parts) 3321 SceneObjectPart[] parts = m_parts.GetArray();
3547 { 3322 for (int i = 0; i < parts.Length; i++)
3548 foreach (SceneObjectPart part in m_parts.Values) 3323 parts[i].SetAttachmentPoint(point);
3549 part.SetAttachmentPoint(point);
3550 }
3551 } 3324 }
3552 3325
3553 #region ISceneObject 3326 #region ISceneObject
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 53ddb5d..0e3daf76 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -603,10 +603,7 @@ namespace OpenSim.Region.Framework.Scenes
603 rootPart.Name = item.Name; 603 rootPart.Name = item.Name;
604 rootPart.Description = item.Description; 604 rootPart.Description = item.Description;
605 605
606 List<SceneObjectPart> partList = null; 606 SceneObjectPart[] partList = group.Parts;
607
608 lock (group.Children)
609 partList = new List<SceneObjectPart>(group.Children.Values);
610 607
611 group.SetGroup(m_part.GroupID, null); 608 group.SetGroup(m_part.GroupID, null);
612 609
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a77f38c..a4533fa 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1709,7 +1709,7 @@ namespace OpenSim.Region.Framework.Scenes
1709 // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used. 1709 // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used.
1710 1710
1711 // Get our own copy of the part array, and sort into the order we want to test 1711 // Get our own copy of the part array, and sort into the order we want to test
1712 SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts(); 1712 SceneObjectPart[] partArray = targetPart.ParentGroup.Parts;
1713 Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2) 1713 Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2)
1714 { 1714 {
1715 // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1) 1715 // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1)
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 5bdaa17..f5f6b90 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -158,16 +158,15 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
158 writer.WriteEndElement(); 158 writer.WriteEndElement();
159 writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); 159 writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
160 160
161 lock (sceneObject.Children) 161 SceneObjectPart[] parts = sceneObject.Parts;
162 for (int i = 0; i < parts.Length; i++)
162 { 163 {
163 foreach (SceneObjectPart part in sceneObject.Children.Values) 164 SceneObjectPart part = parts[i];
165 if (part.UUID != sceneObject.RootPart.UUID)
164 { 166 {
165 if (part.UUID != sceneObject.RootPart.UUID) 167 writer.WriteStartElement(String.Empty, "Part", String.Empty);
166 { 168 ToOriginalXmlFormat(part, writer);
167 writer.WriteStartElement(String.Empty, "Part", String.Empty); 169 writer.WriteEndElement();
168 ToOriginalXmlFormat(part, writer);
169 writer.WriteEndElement();
170 }
171 } 170 }
172 } 171 }
173 172
@@ -281,15 +280,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
281 sceneObject.RootPart.ToXml(writer); 280 sceneObject.RootPart.ToXml(writer);
282 writer.WriteStartElement(String.Empty, "OtherParts", String.Empty); 281 writer.WriteStartElement(String.Empty, "OtherParts", String.Empty);
283 282
284 lock (sceneObject.Children) 283 SceneObjectPart[] parts = sceneObject.Parts;
284 for (int i = 0; i < parts.Length; i++)
285 { 285 {
286 foreach (SceneObjectPart part in sceneObject.Children.Values) 286 SceneObjectPart part = parts[i];
287 { 287 if (part.UUID != sceneObject.RootPart.UUID)
288 if (part.UUID != sceneObject.RootPart.UUID) 288 part.ToXml(writer);
289 {
290 part.ToXml(writer);
291 }
292 }
293 } 289 }
294 290
295 writer.WriteEndElement(); // End of OtherParts 291 writer.WriteEndElement(); // End of OtherParts
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
index 7d9a6a9..9244bc3 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
68 SceneObjectGroup dupeSo 68 SceneObjectGroup dupeSo
69 = scene.SceneGraph.DuplicateObject( 69 = scene.SceneGraph.DuplicateObject(
70 part1.LocalId, new Vector3(10, 0, 0), 0, ownerId, UUID.Zero, Quaternion.Identity); 70 part1.LocalId, new Vector3(10, 0, 0), 0, ownerId, UUID.Zero, Quaternion.Identity);
71 Assert.That(dupeSo.Children.Count, Is.EqualTo(2)); 71 Assert.That(dupeSo.Parts.Length, Is.EqualTo(2));
72 72
73 SceneObjectPart dupePart1 = dupeSo.GetLinkNumPart(1); 73 SceneObjectPart dupePart1 = dupeSo.GetLinkNumPart(1);
74 SceneObjectPart dupePart2 = dupeSo.GetLinkNumPart(2); 74 SceneObjectPart dupePart2 = dupeSo.GetLinkNumPart(2);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
index 60824be..f57cf98 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
@@ -81,12 +81,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests
81 // FIXME: Can't do this test yet since group 2 still has its root part! We can't yet null this since 81 // FIXME: Can't do this test yet since group 2 still has its root part! We can't yet null this since
82 // it might cause SOG.ProcessBackup() to fail due to the race condition. This really needs to be fixed. 82 // it might cause SOG.ProcessBackup() to fail due to the race condition. This really needs to be fixed.
83 Assert.That(grp2.IsDeleted, "SOG 2 was not registered as deleted after link."); 83 Assert.That(grp2.IsDeleted, "SOG 2 was not registered as deleted after link.");
84 Assert.That(grp2.Children.Count, Is.EqualTo(0), "Group 2 still contained children after delink."); 84 Assert.That(grp2.Parts.Length, Is.EqualTo(0), "Group 2 still contained children after delink.");
85 Assert.That(grp1.Children.Count == 2); 85 Assert.That(grp1.Parts.Length == 2);
86 86
87 if (debugtest) 87 if (debugtest)
88 { 88 {
89 m_log.Debug("parts: " + grp1.Children.Count); 89 m_log.Debug("parts: " + grp1.Parts.Length);
90 m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation); 90 m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation);
91 m_log.Debug("Group1: Prim1: OffsetPosition:"+ part1.OffsetPosition+", OffsetRotation:"+part1.RotationOffset); 91 m_log.Debug("Group1: Prim1: OffsetPosition:"+ part1.OffsetPosition+", OffsetRotation:"+part1.RotationOffset);
92 m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+part2.RotationOffset); 92 m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+part2.RotationOffset);
@@ -126,7 +126,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
126 if (debugtest) 126 if (debugtest)
127 m_log.Debug("Group2: Prim2: OffsetPosition:" + part2.AbsolutePosition + ", OffsetRotation:" + part2.RotationOffset); 127 m_log.Debug("Group2: Prim2: OffsetPosition:" + part2.AbsolutePosition + ", OffsetRotation:" + part2.RotationOffset);
128 128
129 Assert.That(grp1.Children.Count, Is.EqualTo(1), "Group 1 still contained part2 after delink."); 129 Assert.That(grp1.Parts.Length, Is.EqualTo(1), "Group 1 still contained part2 after delink.");
130 Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero"); 130 Assert.That(part2.AbsolutePosition == Vector3.Zero, "The absolute position should be zero");
131 } 131 }
132 132
@@ -177,22 +177,22 @@ namespace OpenSim.Region.Framework.Scenes.Tests
177 grp3.LinkToGroup(grp4); 177 grp3.LinkToGroup(grp4);
178 178
179 // At this point we should have 4 parts total in two groups. 179 // At this point we should have 4 parts total in two groups.
180 Assert.That(grp1.Children.Count == 2, "Group1 children count should be 2"); 180 Assert.That(grp1.Parts.Length == 2, "Group1 children count should be 2");
181 Assert.That(grp2.IsDeleted, "Group 2 was not registered as deleted after link."); 181 Assert.That(grp2.IsDeleted, "Group 2 was not registered as deleted after link.");
182 Assert.That(grp2.Children.Count, Is.EqualTo(0), "Group 2 still contained parts after delink."); 182 Assert.That(grp2.Parts.Length, Is.EqualTo(0), "Group 2 still contained parts after delink.");
183 Assert.That(grp3.Children.Count == 2, "Group3 children count should be 2"); 183 Assert.That(grp3.Parts.Length == 2, "Group3 children count should be 2");
184 Assert.That(grp4.IsDeleted, "Group 4 was not registered as deleted after link."); 184 Assert.That(grp4.IsDeleted, "Group 4 was not registered as deleted after link.");
185 Assert.That(grp4.Children.Count, Is.EqualTo(0), "Group 4 still contained parts after delink."); 185 Assert.That(grp4.Parts.Length, Is.EqualTo(0), "Group 4 still contained parts after delink.");
186 186
187 if (debugtest) 187 if (debugtest)
188 { 188 {
189 m_log.Debug("--------After Link-------"); 189 m_log.Debug("--------After Link-------");
190 m_log.Debug("Group1: parts:" + grp1.Children.Count); 190 m_log.Debug("Group1: parts:" + grp1.Parts.Length);
191 m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation); 191 m_log.Debug("Group1: Pos:"+grp1.AbsolutePosition+", Rot:"+grp1.Rotation);
192 m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset); 192 m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset);
193 m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+ part2.RotationOffset); 193 m_log.Debug("Group1: Prim2: OffsetPosition:"+part2.OffsetPosition+", OffsetRotation:"+ part2.RotationOffset);
194 194
195 m_log.Debug("Group3: parts:"+grp3.Children.Count); 195 m_log.Debug("Group3: parts:" + grp3.Parts.Length);
196 m_log.Debug("Group3: Pos:"+grp3.AbsolutePosition+", Rot:"+grp3.Rotation); 196 m_log.Debug("Group3: Pos:"+grp3.AbsolutePosition+", Rot:"+grp3.Rotation);
197 m_log.Debug("Group3: Prim1: OffsetPosition:"+part3.OffsetPosition+", OffsetRotation:"+part3.RotationOffset); 197 m_log.Debug("Group3: Prim1: OffsetPosition:"+part3.OffsetPosition+", OffsetRotation:"+part3.RotationOffset);
198 m_log.Debug("Group3: Prim2: OffsetPosition:"+part4.OffsetPosition+", OffsetRotation:"+part4.RotationOffset); 198 m_log.Debug("Group3: Prim2: OffsetPosition:"+part4.OffsetPosition+", OffsetRotation:"+part4.RotationOffset);
@@ -240,12 +240,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests
240 if (debugtest) 240 if (debugtest)
241 { 241 {
242 m_log.Debug("--------After De-Link-------"); 242 m_log.Debug("--------After De-Link-------");
243 m_log.Debug("Group1: parts:" + grp1.Children.Count); 243 m_log.Debug("Group1: parts:" + grp1.Parts.Length);
244 m_log.Debug("Group1: Pos:" + grp1.AbsolutePosition + ", Rot:" + grp1.Rotation); 244 m_log.Debug("Group1: Pos:" + grp1.AbsolutePosition + ", Rot:" + grp1.Rotation);
245 m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset); 245 m_log.Debug("Group1: Prim1: OffsetPosition:" + part1.OffsetPosition + ", OffsetRotation:" + part1.RotationOffset);
246 m_log.Debug("Group1: Prim2: OffsetPosition:" + part2.OffsetPosition + ", OffsetRotation:" + part2.RotationOffset); 246 m_log.Debug("Group1: Prim2: OffsetPosition:" + part2.OffsetPosition + ", OffsetRotation:" + part2.RotationOffset);
247 247
248 m_log.Debug("Group3: parts:" + grp3.Children.Count); 248 m_log.Debug("Group3: parts:" + grp3.Parts.Length);
249 m_log.Debug("Group3: Pos:" + grp3.AbsolutePosition + ", Rot:" + grp3.Rotation); 249 m_log.Debug("Group3: Pos:" + grp3.AbsolutePosition + ", Rot:" + grp3.Rotation);
250 m_log.Debug("Group3: Prim1: OffsetPosition:" + part3.OffsetPosition + ", OffsetRotation:" + part3.RotationOffset); 250 m_log.Debug("Group3: Prim1: OffsetPosition:" + part3.OffsetPosition + ", OffsetRotation:" + part3.RotationOffset);
251 m_log.Debug("Group3: Prim2: OffsetPosition:" + part4.OffsetPosition + ", OffsetRotation:" + part4.RotationOffset); 251 m_log.Debug("Group3: Prim2: OffsetPosition:" + part4.OffsetPosition + ", OffsetRotation:" + part4.RotationOffset);
@@ -295,9 +295,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
295 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); 295 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID);
296 296
297 Assert.That(storedObjects.Count, Is.EqualTo(1)); 297 Assert.That(storedObjects.Count, Is.EqualTo(1));
298 Assert.That(storedObjects[0].Children.Count, Is.EqualTo(2)); 298 Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(2));
299 Assert.That(storedObjects[0].Children.ContainsKey(rootPartUuid)); 299 Assert.That(storedObjects[0].ContainsPart(rootPartUuid));
300 Assert.That(storedObjects[0].Children.ContainsKey(linkPartUuid)); 300 Assert.That(storedObjects[0].ContainsPart(linkPartUuid));
301 } 301 }
302 302
303 /// <summary> 303 /// <summary>
@@ -338,8 +338,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
338 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); 338 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID);
339 339
340 Assert.That(storedObjects.Count, Is.EqualTo(1)); 340 Assert.That(storedObjects.Count, Is.EqualTo(1));
341 Assert.That(storedObjects[0].Children.Count, Is.EqualTo(1)); 341 Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(1));
342 Assert.That(storedObjects[0].Children.ContainsKey(rootPartUuid)); 342 Assert.That(storedObjects[0].ContainsPart(rootPartUuid));
343 } 343 }
344 } 344 }
345} 345}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index e3965ce..65baa52 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -121,8 +121,11 @@ namespace OpenSim.Region.Framework.Scenes
121// m_log.DebugFormat( 121// m_log.DebugFormat(
122// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); 122// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
123 123
124 foreach (SceneObjectPart part in sceneObject.GetParts()) 124 SceneObjectPart[] parts = sceneObject.Parts;
125 for (int i = 0; i < parts.Length; i++)
125 { 126 {
127 SceneObjectPart part = parts[i];
128
126// m_log.DebugFormat( 129// m_log.DebugFormat(
127// "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); 130// "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID);
128 131
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
index d21b652..7f64ebd 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMEntityCollection.cs
@@ -121,19 +121,16 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
121 continue; 121 continue;
122 temp = (SceneObjectGroup) currObj; 122 temp = (SceneObjectGroup) currObj;
123 123
124 lock (temp.Children) 124 if (m_CMEntityHash.ContainsKey(temp.UUID))
125 { 125 {
126 if (m_CMEntityHash.ContainsKey(temp.UUID)) 126 foreach (SceneObjectPart part in temp.Parts)
127 { 127 if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID))
128 foreach (SceneObjectPart part in temp.Children.Values)
129 if (!((ContentManagementEntity)m_CMEntityHash[temp.UUID]).HasChildPrim(part.UUID))
130 missingList.Add(part);
131 }
132 else //Entire group is missing from revision. (and is a new part in region)
133 {
134 foreach (SceneObjectPart part in temp.Children.Values)
135 missingList.Add(part); 128 missingList.Add(part);
136 } 129 }
130 else //Entire group is missing from revision. (and is a new part in region)
131 {
132 foreach (SceneObjectPart part in temp.Parts)
133 missingList.Add(part);
137 } 134 }
138 } 135 }
139 return missingList; 136 return missingList;
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
index 0b02a9f..3a6996e 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs
@@ -167,11 +167,11 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
167 public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group) 167 public void RemoveOrUpdateDeletedEntity(SceneObjectGroup group)
168 { 168 {
169 // Deal with new parts not revisioned that have been deleted. 169 // Deal with new parts not revisioned that have been deleted.
170 lock (group.Children) 170 SceneObjectPart[] parts = group.Parts;
171 for (int i = 0; i < parts.Length; i++)
171 { 172 {
172 foreach (SceneObjectPart part in group.Children.Values) 173 if (m_MetaEntityCollection.Auras.ContainsKey(parts[i].UUID))
173 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) 174 m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(parts[i].UUID);
174 m_MetaEntityCollection.RemoveNewlyCreatedEntityAura(part.UUID);
175 } 175 }
176 } 176 }
177 177
@@ -210,12 +210,10 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
210 { 210 {
211 temp = SceneObjectSerializer.FromXml2Format(xml); 211 temp = SceneObjectSerializer.FromXml2Format(xml);
212 temp.SetScene(scene); 212 temp.SetScene(scene);
213 213
214 lock (temp.Children) 214 SceneObjectPart[] parts = temp.Parts;
215 { 215 for (int i = 0; i < parts.Length; i++)
216 foreach (SceneObjectPart part in temp.Children.Values) 216 parts[i].RegionHandle = scene.RegionInfo.RegionHandle;
217 part.RegionHandle = scene.RegionInfo.RegionHandle;
218 }
219 217
220 ReplacementList.Add(temp.UUID, (EntityBase)temp); 218 ReplacementList.Add(temp.UUID, (EntityBase)temp);
221 } 219 }
@@ -346,17 +344,16 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
346 System.Collections.ArrayList auraList = new System.Collections.ArrayList(); 344 System.Collections.ArrayList auraList = new System.Collections.ArrayList();
347 if (group == null) 345 if (group == null)
348 return null; 346 return null;
349 347
350 lock (group.Children) 348 SceneObjectPart[] parts = group.Parts;
349 for (int i = 0; i < parts.Length; i++)
351 { 350 {
352 foreach (SceneObjectPart part in group.Children.Values) 351 SceneObjectPart part = parts[i];
352 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID))
353 { 353 {
354 if (m_MetaEntityCollection.Auras.ContainsKey(part.UUID)) 354 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0, 254, 0), part.Scale);
355 { 355 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition();
356 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).SetAura(new Vector3(0,254,0), part.Scale); 356 auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
357 ((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]).RootPart.GroupPosition = part.GetWorldPosition();
358 auraList.Add((AuraMetaEntity)m_MetaEntityCollection.Auras[part.UUID]);
359 }
360 } 357 }
361 } 358 }
362 359
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
index f75f40a..3807ccd 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMView.cs
@@ -186,12 +186,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
186 ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll(); 186 ((ContentManagementEntity)m_model.MetaEntityCollection.Entities[group.UUID]).SendFullDiffUpdateToAll();
187 187
188 // Deal with new parts not revisioned that have been deleted. 188 // Deal with new parts not revisioned that have been deleted.
189 lock (group.Children) 189 foreach (SceneObjectPart part in group.Parts)
190 { 190 if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID))
191 foreach (SceneObjectPart part in group.Children.Values) 191 ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll();
192 if (m_model.MetaEntityCollection.Auras.ContainsKey(part.UUID))
193 ((AuraMetaEntity)m_model.MetaEntityCollection.Auras[part.UUID]).HideFromAll();
194 }
195 } 192 }
196 193
197 public void SendMetaEntitiesToNewClient(IClientAPI client) 194 public void SendMetaEntitiesToNewClient(IClientAPI client)
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
index 49d20e1..0248f36 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs
@@ -132,33 +132,30 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
132 // if group is not contained in scene's list 132 // if group is not contained in scene's list
133 if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID)) 133 if (!ContainsKey(sceneEntityList, m_UnchangedEntity.UUID))
134 { 134 {
135 lock (m_UnchangedEntity.Children) 135 foreach (SceneObjectPart part in m_UnchangedEntity.Parts)
136 { 136 {
137 foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) 137 // if scene list no longer contains this part, display translucent part and mark with red aura
138 if (!ContainsKey(sceneEntityList, part.UUID))
138 { 139 {
139 // if scene list no longer contains this part, display translucent part and mark with red aura 140 // if already displaying a red aura over part, make sure its red
140 if (!ContainsKey(sceneEntityList, part.UUID)) 141 if (m_AuraEntities.ContainsKey(part.UUID))
141 { 142 {
142 // if already displaying a red aura over part, make sure its red 143 m_AuraEntities[part.UUID].SetAura(new Vector3(254, 0, 0), part.Scale);
143 if (m_AuraEntities.ContainsKey(part.UUID)) 144 }
144 { 145 else
145 m_AuraEntities[part.UUID].SetAura(new Vector3(254,0,0), part.Scale); 146 {
146 } 147 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
147 else 148 part.GetWorldPosition(),
148 { 149 MetaEntity.TRANSLUCENT,
149 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, 150 new Vector3(254, 0, 0),
150 part.GetWorldPosition(), 151 part.Scale
151 MetaEntity.TRANSLUCENT, 152 );
152 new Vector3(254,0,0), 153 m_AuraEntities.Add(part.UUID, auraGroup);
153 part.Scale
154 );
155 m_AuraEntities.Add(part.UUID, auraGroup);
156 }
157 SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum);
158 SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT);
159 } 154 }
160 // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id 155 SceneObjectPart metaPart = m_Entity.GetLinkNumPart(part.LinkNum);
156 SetPartTransparency(metaPart, MetaEntity.TRANSLUCENT);
161 } 157 }
158 // otherwise, scene will not contain the part. note: a group can not remove a part without changing group id
162 } 159 }
163 160
164 // a deleted part has no where to point a beam particle system, 161 // a deleted part has no where to point a beam particle system,
@@ -183,11 +180,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
183 /// </summary> 180 /// </summary>
184 public bool HasChildPrim(UUID uuid) 181 public bool HasChildPrim(UUID uuid)
185 { 182 {
186 lock (m_UnchangedEntity.Children) 183 return m_UnchangedEntity.ContainsPart(uuid);
187 if (m_UnchangedEntity.Children.ContainsKey(uuid))
188 return true;
189
190 return false;
191 } 184 }
192 185
193 /// <summary> 186 /// <summary>
@@ -195,12 +188,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
195 /// </summary> 188 /// </summary>
196 public bool HasChildPrim(uint localID) 189 public bool HasChildPrim(uint localID)
197 { 190 {
198 lock (m_UnchangedEntity.Children) 191 foreach (SceneObjectPart part in m_UnchangedEntity.Parts)
199 { 192 if (part.LocalId == localID)
200 foreach (SceneObjectPart part in m_UnchangedEntity.Children.Values) 193 return true;
201 if (part.LocalId == localID)
202 return true;
203 }
204 194
205 return false; 195 return false;
206 } 196 }
@@ -237,72 +227,37 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
237 // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user 227 // Use "UnchangedEntity" to do comparisons because its text, transparency, and other attributes will be just as the user
238 // had originally saved. 228 // had originally saved.
239 // m_Entity will NOT necessarily be the same entity as the user had saved. 229 // m_Entity will NOT necessarily be the same entity as the user had saved.
240 lock (m_UnchangedEntity.Children) 230 foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Parts)
241 { 231 {
242 foreach (SceneObjectPart UnchangedPart in m_UnchangedEntity.Children.Values) 232 //This is the part that we use to show changes.
233 metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum);
234 if (sceneEntityGroup.ContainsPart(UnchangedPart.UUID))
243 { 235 {
244 //This is the part that we use to show changes. 236 sceneEntityPart = sceneEntityGroup.GetChildPart(UnchangedPart.UUID);
245 metaEntityPart = m_Entity.GetLinkNumPart(UnchangedPart.LinkNum); 237 differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart);
246 if (sceneEntityGroup.Children.ContainsKey(UnchangedPart.UUID)) 238 if (differences != Diff.NONE)
239 metaEntityPart.Text = "CHANGE: " + differences.ToString();
240 if (differences != 0)
247 { 241 {
248 sceneEntityPart = sceneEntityGroup.Children[UnchangedPart.UUID]; 242 // Root Part that has been modified
249 differences = Difference.FindDifferences(UnchangedPart, sceneEntityPart); 243 if ((differences & Diff.POSITION) > 0)
250 if (differences != Diff.NONE)
251 metaEntityPart.Text = "CHANGE: " + differences.ToString();
252 if (differences != 0)
253 {
254 // Root Part that has been modified
255 if ((differences&Diff.POSITION) > 0)
256 {
257 // If the position of any part has changed, make sure the RootPart of the
258 // meta entity is pointing with a beam particle system
259 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
260 {
261 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
262 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
263 }
264 BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene,
265 m_UnchangedEntity.RootPart.GetWorldPosition(),
266 MetaEntity.TRANSLUCENT,
267 sceneEntityPart,
268 new Vector3(0,0,254)
269 );
270 m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup);
271 }
272
273 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
274 {
275 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
276 m_AuraEntities.Remove(UnchangedPart.UUID);
277 }
278 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
279 UnchangedPart.GetWorldPosition(),
280 MetaEntity.TRANSLUCENT,
281 new Vector3(0,0,254),
282 UnchangedPart.Scale
283 );
284 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
285 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
286
287 DiffersFromSceneGroup = true;
288 }
289 else // no differences between scene part and meta part
290 { 244 {
245 // If the position of any part has changed, make sure the RootPart of the
246 // meta entity is pointing with a beam particle system
291 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID)) 247 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
292 { 248 {
293 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll(); 249 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
294 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID); 250 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
295 } 251 }
296 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) 252 BeamMetaEntity beamGroup = new BeamMetaEntity(m_Entity.Scene,
297 { 253 m_UnchangedEntity.RootPart.GetWorldPosition(),
298 m_AuraEntities[UnchangedPart.UUID].HideFromAll(); 254 MetaEntity.TRANSLUCENT,
299 m_AuraEntities.Remove(UnchangedPart.UUID); 255 sceneEntityPart,
300 } 256 new Vector3(0, 0, 254)
301 SetPartTransparency(metaEntityPart, MetaEntity.NONE); 257 );
258 m_BeamEntities.Add(m_UnchangedEntity.RootPart.UUID, beamGroup);
302 } 259 }
303 } 260
304 else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted.
305 {
306 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID)) 261 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
307 { 262 {
308 m_AuraEntities[UnchangedPart.UUID].HideFromAll(); 263 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
@@ -311,14 +266,46 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
311 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene, 266 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
312 UnchangedPart.GetWorldPosition(), 267 UnchangedPart.GetWorldPosition(),
313 MetaEntity.TRANSLUCENT, 268 MetaEntity.TRANSLUCENT,
314 new Vector3(254,0,0), 269 new Vector3(0, 0, 254),
315 UnchangedPart.Scale 270 UnchangedPart.Scale
316 ); 271 );
317 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup); 272 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
318 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT); 273 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
319 274
320 DiffersFromSceneGroup = true; 275 DiffersFromSceneGroup = true;
321 } 276 }
277 else // no differences between scene part and meta part
278 {
279 if (m_BeamEntities.ContainsKey(m_UnchangedEntity.RootPart.UUID))
280 {
281 m_BeamEntities[m_UnchangedEntity.RootPart.UUID].HideFromAll();
282 m_BeamEntities.Remove(m_UnchangedEntity.RootPart.UUID);
283 }
284 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
285 {
286 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
287 m_AuraEntities.Remove(UnchangedPart.UUID);
288 }
289 SetPartTransparency(metaEntityPart, MetaEntity.NONE);
290 }
291 }
292 else //The entity currently in the scene is missing parts from the metaentity saved, so mark parts red as deleted.
293 {
294 if (m_AuraEntities.ContainsKey(UnchangedPart.UUID))
295 {
296 m_AuraEntities[UnchangedPart.UUID].HideFromAll();
297 m_AuraEntities.Remove(UnchangedPart.UUID);
298 }
299 AuraMetaEntity auraGroup = new AuraMetaEntity(m_Entity.Scene,
300 UnchangedPart.GetWorldPosition(),
301 MetaEntity.TRANSLUCENT,
302 new Vector3(254, 0, 0),
303 UnchangedPart.Scale
304 );
305 m_AuraEntities.Add(UnchangedPart.UUID, auraGroup);
306 SetPartTransparency(metaEntityPart, MetaEntity.TRANSLUCENT);
307
308 DiffersFromSceneGroup = true;
322 } 309 }
323 } 310 }
324 311
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
index d7838c5..c7b1ed7 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs
@@ -98,10 +98,9 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
98 98
99 #region Public Properties 99 #region Public Properties
100 100
101 public Dictionary<UUID, SceneObjectPart> Children 101 public SceneObjectPart[] Parts
102 { 102 {
103 get { return m_Entity.Children; } 103 get { return m_Entity.Parts; }
104 set { m_Entity.Children = value; }
105 } 104 }
106 105
107 public uint LocalId 106 public uint LocalId
@@ -150,19 +149,17 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
150 { 149 {
151 //make new uuids 150 //make new uuids
152 Dictionary<UUID, SceneObjectPart> parts = new Dictionary<UUID, SceneObjectPart>(); 151 Dictionary<UUID, SceneObjectPart> parts = new Dictionary<UUID, SceneObjectPart>();
153 152
154 lock (m_Entity.Children) 153 foreach (SceneObjectPart part in m_Entity.Parts)
155 { 154 {
156 foreach (SceneObjectPart part in m_Entity.Children.Values) 155 part.ResetIDs(part.LinkNum);
157 { 156 parts.Add(part.UUID, part);
158 part.ResetIDs(part.LinkNum);
159 parts.Add(part.UUID, part);
160 }
161
162 //finalize
163 m_Entity.RootPart.PhysActor = null;
164 m_Entity.Children = parts;
165 } 157 }
158
159 //finalize
160 m_Entity.RootPart.PhysActor = null;
161 foreach (SceneObjectPart part in parts.Values)
162 m_Entity.AddPart(part);
166 } 163 }
167 164
168 #endregion Protected Methods 165 #endregion Protected Methods
@@ -177,11 +174,8 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
177 //This deletes the group without removing from any databases. 174 //This deletes the group without removing from any databases.
178 //This is important because we are not IN any database. 175 //This is important because we are not IN any database.
179 //m_Entity.FakeDeleteGroup(); 176 //m_Entity.FakeDeleteGroup();
180 lock (m_Entity.Children) 177 foreach (SceneObjectPart part in m_Entity.Parts)
181 { 178 client.SendKillObject(m_Entity.RegionHandle, part.LocalId);
182 foreach (SceneObjectPart part in m_Entity.Children.Values)
183 client.SendKillObject(m_Entity.RegionHandle, part.LocalId);
184 }
185 } 179 }
186 180
187 /// <summary> 181 /// <summary>
@@ -189,15 +183,12 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
189 /// </summary> 183 /// </summary>
190 public virtual void HideFromAll() 184 public virtual void HideFromAll()
191 { 185 {
192 lock (m_Entity.Children) 186 foreach (SceneObjectPart part in m_Entity.Parts)
193 { 187 {
194 foreach (SceneObjectPart part in m_Entity.Children.Values) 188 m_Entity.Scene.ForEachClient(
195 { 189 delegate(IClientAPI controller)
196 m_Entity.Scene.ForEachClient( 190 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
197 delegate(IClientAPI controller) 191 );
198 { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); }
199 );
200 }
201 } 192 }
202 } 193 }
203 194
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
index 59ad9d8..faed522 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
@@ -193,11 +193,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
193 193
194 int i = 0; 194 int i = 0;
195 195
196 List<SceneObjectPart> partList = null; 196 foreach (SceneObjectPart part in my.ParentGroup.Parts)
197 lock (my.ParentGroup.Children)
198 partList = new List<SceneObjectPart>(my.ParentGroup.Children.Values);
199
200 foreach (SceneObjectPart part in partList)
201 { 197 {
202 rets[i++] = new SOPObject(m_rootScene, part.LocalId, m_security); 198 rets[i++] = new SOPObject(m_rootScene, part.LocalId, m_security);
203 } 199 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 0692fdb..01c026e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -236,8 +236,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
236 case ScriptBaseClass.LINK_SET: 236 case ScriptBaseClass.LINK_SET:
237 if (m_host.ParentGroup != null) 237 if (m_host.ParentGroup != null)
238 { 238 {
239 lock (m_host.ParentGroup.Children) 239 return new List<SceneObjectPart>(m_host.ParentGroup.Parts);
240 return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
241 } 240 }
242 return ret; 241 return ret;
243 242
@@ -254,8 +253,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
254 if (m_host.ParentGroup == null) 253 if (m_host.ParentGroup == null)
255 return new List<SceneObjectPart>(); 254 return new List<SceneObjectPart>();
256 255
257 lock (m_host.ParentGroup.Children) 256 ret = new List<SceneObjectPart>(m_host.ParentGroup.Parts);
258 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
259 257
260 if (ret.Contains(m_host)) 258 if (ret.Contains(m_host))
261 ret.Remove(m_host); 259 ret.Remove(m_host);
@@ -265,8 +263,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
265 if (m_host.ParentGroup == null) 263 if (m_host.ParentGroup == null)
266 return new List<SceneObjectPart>(); 264 return new List<SceneObjectPart>();
267 265
268 lock (m_host.ParentGroup.Children) 266 ret = new List<SceneObjectPart>(m_host.ParentGroup.Parts);
269 ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values);
270 267
271 if (ret.Contains(m_host.ParentGroup.RootPart)) 268 if (ret.Contains(m_host.ParentGroup.RootPart))
272 ret.Remove(m_host.ParentGroup.RootPart); 269 ret.Remove(m_host.ParentGroup.RootPart);
@@ -1187,16 +1184,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1187 if (group == null) 1184 if (group == null)
1188 return; 1185 return;
1189 bool allow = true; 1186 bool allow = true;
1190 1187
1191 lock (group.Children) 1188 foreach (SceneObjectPart part in group.Parts)
1192 { 1189 {
1193 foreach (SceneObjectPart part in group.Children.Values) 1190 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
1194 { 1191 {
1195 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) 1192 allow = false;
1196 { 1193 break;
1197 allow = false;
1198 break;
1199 }
1200 } 1194 }
1201 } 1195 }
1202 1196
@@ -3617,18 +3611,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3617 case ScriptBaseClass.LINK_ALL_OTHERS: 3611 case ScriptBaseClass.LINK_ALL_OTHERS:
3618 case ScriptBaseClass.LINK_ALL_CHILDREN: 3612 case ScriptBaseClass.LINK_ALL_CHILDREN:
3619 case ScriptBaseClass.LINK_THIS: 3613 case ScriptBaseClass.LINK_THIS:
3620 lock (parentPrim.Children) 3614 foreach (SceneObjectPart part in parentPrim.Parts)
3621 { 3615 {
3622 foreach (SceneObjectPart part in parentPrim.Children.Values) 3616 if (part.UUID != m_host.UUID)
3623 { 3617 {
3624 if (part.UUID != m_host.UUID) 3618 childPrim = part;
3625 { 3619 break;
3626 childPrim = part;
3627 break;
3628 }
3629 } 3620 }
3630 break;
3631 } 3621 }
3622 break;
3632 default: 3623 default:
3633 childPrim = parentPrim.GetLinkNumPart(linknum); 3624 childPrim = parentPrim.GetLinkNumPart(linknum);
3634 if (childPrim.UUID == m_host.UUID) 3625 if (childPrim.UUID == m_host.UUID)
@@ -3639,30 +3630,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3639 if (linknum == ScriptBaseClass.LINK_ROOT) 3630 if (linknum == ScriptBaseClass.LINK_ROOT)
3640 { 3631 {
3641 // Restructuring Multiple Prims. 3632 // Restructuring Multiple Prims.
3642 lock (parentPrim.Children) 3633 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3634 parts.Remove(parentPrim.RootPart);
3635 foreach (SceneObjectPart part in parts)
3643 { 3636 {
3644 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); 3637 parentPrim.DelinkFromGroup(part.LocalId, true);
3645 parts.Remove(parentPrim.RootPart); 3638 }
3639 parentPrim.HasGroupChanged = true;
3640 parentPrim.ScheduleGroupForFullUpdate();
3641 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3642
3643 if (parts.Count > 0)
3644 {
3645 SceneObjectPart newRoot = parts[0];
3646 parts.Remove(newRoot);
3646 foreach (SceneObjectPart part in parts) 3647 foreach (SceneObjectPart part in parts)
3647 { 3648 {
3648 parentPrim.DelinkFromGroup(part.LocalId, true); 3649 part.UpdateFlag = 0;
3649 } 3650 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3650 parentPrim.HasGroupChanged = true;
3651 parentPrim.ScheduleGroupForFullUpdate();
3652 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3653
3654 if (parts.Count > 0)
3655 {
3656 SceneObjectPart newRoot = parts[0];
3657 parts.Remove(newRoot);
3658 foreach (SceneObjectPart part in parts)
3659 {
3660 part.UpdateFlag = 0;
3661 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
3662 }
3663 newRoot.ParentGroup.HasGroupChanged = true;
3664 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3665 } 3651 }
3652 newRoot.ParentGroup.HasGroupChanged = true;
3653 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
3666 } 3654 }
3667 } 3655 }
3668 else 3656 else
@@ -3684,19 +3672,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3684 if (parentPrim.RootPart.AttachmentPoint != 0) 3672 if (parentPrim.RootPart.AttachmentPoint != 0)
3685 return; // Fail silently if attached 3673 return; // Fail silently if attached
3686 3674
3687 lock (parentPrim.Children) 3675 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
3676 parts.Remove(parentPrim.RootPart);
3677
3678 foreach (SceneObjectPart part in parts)
3688 { 3679 {
3689 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); 3680 parentPrim.DelinkFromGroup(part.LocalId, true);
3690 parts.Remove(parentPrim.RootPart); 3681 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3691
3692 foreach (SceneObjectPart part in parts)
3693 {
3694 parentPrim.DelinkFromGroup(part.LocalId, true);
3695 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
3696 }
3697 parentPrim.HasGroupChanged = true;
3698 parentPrim.ScheduleGroupForFullUpdate();
3699 } 3682 }
3683 parentPrim.HasGroupChanged = true;
3684 parentPrim.ScheduleGroupForFullUpdate();
3700 } 3685 }
3701 3686
3702 public LSL_String llGetLinkKey(int linknum) 3687 public LSL_String llGetLinkKey(int linknum)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 41501f2..3575889 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -209,15 +209,12 @@ namespace OpenSim.Region.ScriptEngine.Shared
209 else 209 else
210 Type = 0x02; // Passive 210 Type = 0x02; // Passive
211 211
212 lock (part.ParentGroup.Children) 212 foreach (SceneObjectPart p in part.ParentGroup.Parts)
213 { 213 {
214 foreach (SceneObjectPart p in part.ParentGroup.Children.Values) 214 if (p.Inventory.ContainsScripts())
215 { 215 {
216 if (p.Inventory.ContainsScripts()) 216 Type |= 0x08; // Scripted
217 { 217 break;
218 Type |= 0x08; // Scripted
219 break;
220 }
221 } 218 }
222 } 219 }
223 220
diff --git a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
index de6e815..2e5020b 100644
--- a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs
@@ -163,7 +163,7 @@ namespace OpenSim.Data.Null
163 // We can't simply store groups here because on delinking, OpenSim will not update the original group 163 // We can't simply store groups here because on delinking, OpenSim will not update the original group
164 // directly. Rather, the newly delinked parts will be updated to be in their own scene object group 164 // directly. Rather, the newly delinked parts will be updated to be in their own scene object group
165 // Therefore, we need to store parts rather than groups. 165 // Therefore, we need to store parts rather than groups.
166 foreach (SceneObjectPart prim in obj.Children.Values) 166 foreach (SceneObjectPart prim in obj.Parts)
167 { 167 {
168 m_log.DebugFormat( 168 m_log.DebugFormat(
169 "[MOCK REGION DATA PLUGIN]: Storing part {0} {1} in object {2} {3} in region {4}", 169 "[MOCK REGION DATA PLUGIN]: Storing part {0} {1} in object {2} {3} in region {4}",