aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/EntityManager.cs79
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs519
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs97
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs380
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs514
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs11
10 files changed, 1133 insertions, 561 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index c314596..e98f0e7 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -53,8 +53,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
53 { 53 {
54 get { return m_movementAnimation; } 54 get { return m_movementAnimation; }
55 } 55 }
56 protected string m_movementAnimation = "DEFAULT"; 56 // protected string m_movementAnimation = "DEFAULT"; //KF: 'DEFAULT' does not exist!
57 57 protected string m_movementAnimation = "CROUCH"; //KF: CROUCH ensures reliable Av Anim. init.
58 private int m_animTickFall; 58 private int m_animTickFall;
59 private int m_animTickJump; 59 private int m_animTickJump;
60 60
@@ -123,17 +123,22 @@ namespace OpenSim.Region.Framework.Scenes.Animation
123 /// </summary> 123 /// </summary>
124 public void TrySetMovementAnimation(string anim) 124 public void TrySetMovementAnimation(string anim)
125 { 125 {
126 //m_log.DebugFormat("Updating movement animation to {0}", anim); 126//Console.WriteLine("Updating movement animation to {0}", anim);
127 127
128 if (!m_scenePresence.IsChildAgent) 128 if (!m_scenePresence.IsChildAgent)
129 { 129 {
130 if (m_animations.TrySetDefaultAnimation( 130 if (m_animations.TrySetDefaultAnimation(
131 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID)) 131 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID))
132 { 132 {
133//Console.WriteLine("TSMA {0} success.", anim);
133 // 16384 is CHANGED_ANIMATION 134 // 16384 is CHANGED_ANIMATION
134 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 }); 135 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 });
135 SendAnimPack(); 136 SendAnimPack();
136 } 137 }
138 else
139 {
140//Console.WriteLine("TSMA {0} fail.", anim);
141 }
137 } 142 }
138 } 143 }
139 144
@@ -156,10 +161,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
156 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 161 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
157 162
158 // Check control flags 163 // Check control flags
159 bool heldForward = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; 164 bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS);
160 bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; 165 bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
161 bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; 166 bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
162 bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG; 167 bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG);
163 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; 168 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
164 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; 169 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
165 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; 170 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
@@ -312,7 +317,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
312 public void UpdateMovementAnimations() 317 public void UpdateMovementAnimations()
313 { 318 {
314 m_movementAnimation = GetMovementAnimation(); 319 m_movementAnimation = GetMovementAnimation();
315 320//Console.WriteLine("UMA got {0}", m_movementAnimation);
316 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump) 321 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
317 { 322 {
318 // This was the previous behavior before PREJUMP 323 // This was the previous behavior before PREJUMP
@@ -450,4 +455,4 @@ namespace OpenSim.Region.Framework.Scenes.Animation
450 m_scenePresence = null; 455 m_scenePresence = null;
451 } 456 }
452 } 457 }
453} \ No newline at end of file 458}
diff --git a/OpenSim/Region/Framework/Scenes/EntityManager.cs b/OpenSim/Region/Framework/Scenes/EntityManager.cs
index 099fcce..c246e32 100644
--- a/OpenSim/Region/Framework/Scenes/EntityManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EntityManager.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Scenes
40 private readonly Dictionary<UUID,EntityBase> m_eb_uuid = new Dictionary<UUID, EntityBase>(); 40 private readonly Dictionary<UUID,EntityBase> m_eb_uuid = new Dictionary<UUID, EntityBase>();
41 private readonly Dictionary<uint, EntityBase> m_eb_localID = new Dictionary<uint, EntityBase>(); 41 private readonly Dictionary<uint, EntityBase> m_eb_localID = new Dictionary<uint, EntityBase>();
42 //private readonly Dictionary<UUID, ScenePresence> m_pres_uuid = new Dictionary<UUID, ScenePresence>(); 42 //private readonly Dictionary<UUID, ScenePresence> m_pres_uuid = new Dictionary<UUID, ScenePresence>();
43 private readonly Object m_lock = new Object(); 43 private System.Threading.ReaderWriterLockSlim m_lock = new System.Threading.ReaderWriterLockSlim();
44 44
45 [Obsolete("Use Add() instead.")] 45 [Obsolete("Use Add() instead.")]
46 public void Add(UUID id, EntityBase eb) 46 public void Add(UUID id, EntityBase eb)
@@ -50,7 +50,8 @@ namespace OpenSim.Region.Framework.Scenes
50 50
51 public void Add(EntityBase entity) 51 public void Add(EntityBase entity)
52 { 52 {
53 lock (m_lock) 53 m_lock.EnterWriteLock();
54 try
54 { 55 {
55 try 56 try
56 { 57 {
@@ -62,11 +63,16 @@ namespace OpenSim.Region.Framework.Scenes
62 m_log.ErrorFormat("Add Entity failed: {0}", e.Message); 63 m_log.ErrorFormat("Add Entity failed: {0}", e.Message);
63 } 64 }
64 } 65 }
66 finally
67 {
68 m_lock.ExitWriteLock();
69 }
65 } 70 }
66 71
67 public void InsertOrReplace(EntityBase entity) 72 public void InsertOrReplace(EntityBase entity)
68 { 73 {
69 lock (m_lock) 74 m_lock.EnterWriteLock();
75 try
70 { 76 {
71 try 77 try
72 { 78 {
@@ -78,15 +84,24 @@ namespace OpenSim.Region.Framework.Scenes
78 m_log.ErrorFormat("Insert or Replace Entity failed: {0}", e.Message); 84 m_log.ErrorFormat("Insert or Replace Entity failed: {0}", e.Message);
79 } 85 }
80 } 86 }
87 finally
88 {
89 m_lock.ExitWriteLock();
90 }
81 } 91 }
82 92
83 public void Clear() 93 public void Clear()
84 { 94 {
85 lock (m_lock) 95 m_lock.EnterWriteLock();
96 try
86 { 97 {
87 m_eb_uuid.Clear(); 98 m_eb_uuid.Clear();
88 m_eb_localID.Clear(); 99 m_eb_localID.Clear();
89 } 100 }
101 finally
102 {
103 m_lock.ExitWriteLock();
104 }
90 } 105 }
91 106
92 public int Count 107 public int Count
@@ -123,7 +138,8 @@ namespace OpenSim.Region.Framework.Scenes
123 138
124 public bool Remove(uint localID) 139 public bool Remove(uint localID)
125 { 140 {
126 lock (m_lock) 141 m_lock.EnterWriteLock();
142 try
127 { 143 {
128 try 144 try
129 { 145 {
@@ -141,11 +157,16 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 157 return false;
142 } 158 }
143 } 159 }
160 finally
161 {
162 m_lock.ExitWriteLock();
163 }
144 } 164 }
145 165
146 public bool Remove(UUID id) 166 public bool Remove(UUID id)
147 { 167 {
148 lock (m_lock) 168 m_lock.EnterWriteLock();
169 try
149 { 170 {
150 try 171 try
151 { 172 {
@@ -163,13 +184,18 @@ namespace OpenSim.Region.Framework.Scenes
163 return false; 184 return false;
164 } 185 }
165 } 186 }
187 finally
188 {
189 m_lock.ExitWriteLock();
190 }
166 } 191 }
167 192
168 public List<EntityBase> GetAllByType<T>() 193 public List<EntityBase> GetAllByType<T>()
169 { 194 {
170 List<EntityBase> tmp = new List<EntityBase>(); 195 List<EntityBase> tmp = new List<EntityBase>();
171 196
172 lock (m_lock) 197 m_lock.EnterReadLock();
198 try
173 { 199 {
174 try 200 try
175 { 201 {
@@ -187,23 +213,33 @@ namespace OpenSim.Region.Framework.Scenes
187 tmp = null; 213 tmp = null;
188 } 214 }
189 } 215 }
216 finally
217 {
218 m_lock.ExitReadLock();
219 }
190 220
191 return tmp; 221 return tmp;
192 } 222 }
193 223
194 public List<EntityBase> GetEntities() 224 public List<EntityBase> GetEntities()
195 { 225 {
196 lock (m_lock) 226 m_lock.EnterReadLock();
227 try
197 { 228 {
198 return new List<EntityBase>(m_eb_uuid.Values); 229 return new List<EntityBase>(m_eb_uuid.Values);
199 } 230 }
231 finally
232 {
233 m_lock.ExitReadLock();
234 }
200 } 235 }
201 236
202 public EntityBase this[UUID id] 237 public EntityBase this[UUID id]
203 { 238 {
204 get 239 get
205 { 240 {
206 lock (m_lock) 241 m_lock.EnterReadLock();
242 try
207 { 243 {
208 EntityBase entity; 244 EntityBase entity;
209 if (m_eb_uuid.TryGetValue(id, out entity)) 245 if (m_eb_uuid.TryGetValue(id, out entity))
@@ -211,6 +247,10 @@ namespace OpenSim.Region.Framework.Scenes
211 else 247 else
212 return null; 248 return null;
213 } 249 }
250 finally
251 {
252 m_lock.ExitReadLock();
253 }
214 } 254 }
215 set 255 set
216 { 256 {
@@ -222,7 +262,8 @@ namespace OpenSim.Region.Framework.Scenes
222 { 262 {
223 get 263 get
224 { 264 {
225 lock (m_lock) 265 m_lock.EnterReadLock();
266 try
226 { 267 {
227 EntityBase entity; 268 EntityBase entity;
228 if (m_eb_localID.TryGetValue(localID, out entity)) 269 if (m_eb_localID.TryGetValue(localID, out entity))
@@ -230,6 +271,10 @@ namespace OpenSim.Region.Framework.Scenes
230 else 271 else
231 return null; 272 return null;
232 } 273 }
274 finally
275 {
276 m_lock.ExitReadLock();
277 }
233 } 278 }
234 set 279 set
235 { 280 {
@@ -239,18 +284,28 @@ namespace OpenSim.Region.Framework.Scenes
239 284
240 public bool TryGetValue(UUID key, out EntityBase obj) 285 public bool TryGetValue(UUID key, out EntityBase obj)
241 { 286 {
242 lock (m_lock) 287 m_lock.EnterReadLock();
288 try
243 { 289 {
244 return m_eb_uuid.TryGetValue(key, out obj); 290 return m_eb_uuid.TryGetValue(key, out obj);
245 } 291 }
292 finally
293 {
294 m_lock.ExitReadLock();
295 }
246 } 296 }
247 297
248 public bool TryGetValue(uint key, out EntityBase obj) 298 public bool TryGetValue(uint key, out EntityBase obj)
249 { 299 {
250 lock (m_lock) 300 m_lock.EnterReadLock();
301 try
251 { 302 {
252 return m_eb_localID.TryGetValue(key, out obj); 303 return m_eb_localID.TryGetValue(key, out obj);
253 } 304 }
305 finally
306 {
307 m_lock.ExitReadLock();
308 }
254 } 309 }
255 310
256 /// <summary> 311 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 753344d..68e73b1 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -193,7 +193,11 @@ namespace OpenSim.Region.Framework.Scenes
193 public event OnMakeChildAgentDelegate OnMakeChildAgent; 193 public event OnMakeChildAgentDelegate OnMakeChildAgent;
194 194
195 public delegate void OnMakeRootAgentDelegate(ScenePresence presence); 195 public delegate void OnMakeRootAgentDelegate(ScenePresence presence);
196 public delegate void OnSaveNewWindlightProfileDelegate();
197 public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionMeta7WindlightData wl, UUID user);
196 public event OnMakeRootAgentDelegate OnMakeRootAgent; 198 public event OnMakeRootAgentDelegate OnMakeRootAgent;
199 public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted;
200 public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile;
197 201
198 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); 202 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel);
199 203
@@ -411,6 +415,8 @@ namespace OpenSim.Region.Framework.Scenes
411 private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage; 415 private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage;
412 private ClientClosed handlerClientClosed = null; //OnClientClosed; 416 private ClientClosed handlerClientClosed = null; //OnClientClosed;
413 private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent; 417 private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent;
418 private OnSaveNewWindlightProfileDelegate handlerSaveNewWindlightProfile = null; //OnSaveNewWindlightProfile;
419 private OnSendNewWindlightProfileTargetedDelegate handlerSendNewWindlightProfileTargeted = null; //OnSendNewWindlightProfileTargeted;
414 private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent; 420 private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent;
415 private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick; 421 private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick;
416 private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps; 422 private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps;
@@ -772,6 +778,24 @@ namespace OpenSim.Region.Framework.Scenes
772 } 778 }
773 } 779 }
774 780
781 public void TriggerOnSendNewWindlightProfileTargeted(RegionMeta7WindlightData wl, UUID user)
782 {
783 handlerSendNewWindlightProfileTargeted = OnSendNewWindlightProfileTargeted;
784 if (handlerSendNewWindlightProfileTargeted != null)
785 {
786 handlerSendNewWindlightProfileTargeted(wl, user);
787 }
788 }
789
790 public void TriggerOnSaveNewWindlightProfile()
791 {
792 handlerSaveNewWindlightProfile = OnSaveNewWindlightProfile;
793 if (handlerSaveNewWindlightProfile != null)
794 {
795 handlerSaveNewWindlightProfile();
796 }
797 }
798
775 public void TriggerOnMakeRootAgent(ScenePresence presence) 799 public void TriggerOnMakeRootAgent(ScenePresence presence)
776 { 800 {
777 handlerMakeRootAgent = OnMakeRootAgent; 801 handlerMakeRootAgent = OnMakeRootAgent;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 0b0c205..7ca779a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -840,8 +840,12 @@ namespace OpenSim.Region.Framework.Scenes
840 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 840 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
841 { 841 {
842 SceneObjectPart part = GetSceneObjectPart(localID); 842 SceneObjectPart part = GetSceneObjectPart(localID);
843 SceneObjectGroup group = part.ParentGroup; 843 SceneObjectGroup group = null;
844 if (group != null) 844 if (part != null)
845 {
846 group = part.ParentGroup;
847 }
848 if (part != null && group != null)
845 { 849 {
846 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 850 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
847 if (item == null) 851 if (item == null)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index f79eb5d..265129c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -539,6 +539,8 @@ namespace OpenSim.Region.Framework.Scenes
539 539
540 // Load region settings 540 // Load region settings
541 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID); 541 m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID);
542 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(m_regInfo.RegionID);
543
542 if (m_storageManager.EstateDataStore != null) 544 if (m_storageManager.EstateDataStore != null)
543 { 545 {
544 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID); 546 m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID);
@@ -886,6 +888,15 @@ namespace OpenSim.Region.Framework.Scenes
886 /// <param name="seconds">float indicating duration before restart.</param> 888 /// <param name="seconds">float indicating duration before restart.</param>
887 public virtual void Restart(float seconds) 889 public virtual void Restart(float seconds)
888 { 890 {
891 Restart(seconds, true);
892 }
893
894 /// <summary>
895 /// Given float seconds, this will restart the region. showDialog will optionally alert the users.
896 /// </summary>
897 /// <param name="seconds">float indicating duration before restart.</param>
898 public virtual void Restart(float seconds, bool showDialog)
899 {
889 // notifications are done in 15 second increments 900 // notifications are done in 15 second increments
890 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request 901 // so .. if the number of seconds is less then 15 seconds, it's not really a restart request
891 // It's a 'Cancel restart' request. 902 // It's a 'Cancel restart' request.
@@ -906,8 +917,11 @@ namespace OpenSim.Region.Framework.Scenes
906 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); 917 m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed);
907 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); 918 m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes");
908 m_restartTimer.Start(); 919 m_restartTimer.Start();
909 m_dialogModule.SendNotificationToUsersInRegion( 920 if (showDialog)
921 {
922 m_dialogModule.SendNotificationToUsersInRegion(
910 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0))); 923 UUID.Random(), String.Empty, RegionInfo.RegionName + String.Format(": Restarting in {0} Minutes", (int)(seconds / 60.0)));
924 }
911 } 925 }
912 } 926 }
913 927
@@ -1189,16 +1203,16 @@ namespace OpenSim.Region.Framework.Scenes
1189 // Check if any objects have reached their targets 1203 // Check if any objects have reached their targets
1190 CheckAtTargets(); 1204 CheckAtTargets();
1191 1205
1192 // Update SceneObjectGroups that have scheduled themselves for updates
1193 // Objects queue their updates onto all scene presences
1194 if (m_frame % m_update_objects == 0)
1195 m_sceneGraph.UpdateObjectGroups();
1196
1197 // Run through all ScenePresences looking for updates 1206 // Run through all ScenePresences looking for updates
1198 // Presence updates and queued object updates for each presence are sent to clients 1207 // Presence updates and queued object updates for each presence are sent to clients
1199 if (m_frame % m_update_presences == 0) 1208 if (m_frame % m_update_presences == 0)
1200 m_sceneGraph.UpdatePresences(); 1209 m_sceneGraph.UpdatePresences();
1201 1210
1211 // Update SceneObjectGroups that have scheduled themselves for updates
1212 // Objects queue their updates onto all scene presences
1213 if (m_frame % m_update_objects == 0)
1214 m_sceneGraph.UpdateObjectGroups();
1215
1202 int tmpPhysicsMS2 = Util.EnvironmentTickCount(); 1216 int tmpPhysicsMS2 = Util.EnvironmentTickCount();
1203 if ((m_frame % m_update_physics == 0) && m_physics_enabled) 1217 if ((m_frame % m_update_physics == 0) && m_physics_enabled)
1204 m_sceneGraph.UpdatePreparePhysics(); 1218 m_sceneGraph.UpdatePreparePhysics();
@@ -1505,6 +1519,19 @@ namespace OpenSim.Region.Framework.Scenes
1505 public void SaveTerrain() 1519 public void SaveTerrain()
1506 { 1520 {
1507 m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 1521 m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1522 }
1523
1524 public void StoreWindlightProfile(RegionMeta7WindlightData wl)
1525 {
1526 m_regInfo.WindlightSettings = wl;
1527 m_storageManager.DataStore.StoreRegionWindlightSettings(wl);
1528 m_eventManager.TriggerOnSaveNewWindlightProfile();
1529 }
1530
1531 public void LoadWindlightProfile()
1532 {
1533 m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(RegionInfo.RegionID);
1534 m_eventManager.TriggerOnSaveNewWindlightProfile();
1508 } 1535 }
1509 1536
1510 /// <summary> 1537 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e9ed066..f8498c6 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -98,6 +98,72 @@ namespace OpenSim.Region.Framework.Scenes
98 private bool m_hasGroupChanged = false; 98 private bool m_hasGroupChanged = false;
99 private long timeFirstChanged; 99 private long timeFirstChanged;
100 private long timeLastChanged; 100 private long timeLastChanged;
101 private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim();
102
103 public void lockPartsForRead(bool locked)
104 {
105 if (locked)
106 {
107 if (m_partsLock.RecursiveReadCount > 0)
108 {
109 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
110 m_partsLock.ExitReadLock();
111 }
112 if (m_partsLock.RecursiveWriteCount > 0)
113 {
114 m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed.");
115 m_partsLock.ExitWriteLock();
116 }
117
118 while (!m_partsLock.TryEnterReadLock(60000))
119 {
120 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
121 if (m_partsLock.IsWriteLockHeld)
122 {
123 m_partsLock = new System.Threading.ReaderWriterLockSlim();
124 }
125 }
126 }
127 else
128 {
129 if (m_partsLock.RecursiveReadCount > 0)
130 {
131 m_partsLock.ExitReadLock();
132 }
133 }
134 }
135 public void lockPartsForWrite(bool locked)
136 {
137 if (locked)
138 {
139 if (m_partsLock.RecursiveReadCount > 0)
140 {
141 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
142 m_partsLock.ExitReadLock();
143 }
144 if (m_partsLock.RecursiveWriteCount > 0)
145 {
146 m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
147 m_partsLock.ExitWriteLock();
148 }
149
150 while (!m_partsLock.TryEnterWriteLock(60000))
151 {
152 m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
153 if (m_partsLock.IsWriteLockHeld)
154 {
155 m_partsLock = new System.Threading.ReaderWriterLockSlim();
156 }
157 }
158 }
159 else
160 {
161 if (m_partsLock.RecursiveWriteCount > 0)
162 {
163 m_partsLock.ExitWriteLock();
164 }
165 }
166 }
101 167
102 public bool HasGroupChanged 168 public bool HasGroupChanged
103 { 169 {
@@ -243,13 +309,16 @@ namespace OpenSim.Region.Framework.Scenes
243 set 309 set
244 { 310 {
245 m_regionHandle = value; 311 m_regionHandle = value;
246 lock (m_parts) 312 lockPartsForRead(true);
247 { 313 {
248 foreach (SceneObjectPart part in m_parts.Values) 314 foreach (SceneObjectPart part in m_parts.Values)
249 { 315 {
316
250 part.RegionHandle = m_regionHandle; 317 part.RegionHandle = m_regionHandle;
318
251 } 319 }
252 } 320 }
321 lockPartsForRead(false);
253 } 322 }
254 } 323 }
255 324
@@ -275,13 +344,16 @@ namespace OpenSim.Region.Framework.Scenes
275 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 344 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
276 } 345 }
277 346
278 lock (m_parts) 347 lockPartsForRead(true);
279 { 348 {
280 foreach (SceneObjectPart part in m_parts.Values) 349 foreach (SceneObjectPart part in m_parts.Values)
281 { 350 {
351
282 part.GroupPosition = val; 352 part.GroupPosition = val;
353
283 } 354 }
284 } 355 }
356 lockPartsForRead(false);
285 357
286 //if (m_rootPart.PhysActor != null) 358 //if (m_rootPart.PhysActor != null)
287 //{ 359 //{
@@ -432,13 +504,16 @@ namespace OpenSim.Region.Framework.Scenes
432 504
433 public void SetFromItemID(UUID AssetId) 505 public void SetFromItemID(UUID AssetId)
434 { 506 {
435 lock (m_parts) 507 lockPartsForRead(true);
436 { 508 {
437 foreach (SceneObjectPart part in m_parts.Values) 509 foreach (SceneObjectPart part in m_parts.Values)
438 { 510 {
511
439 part.FromItemID = AssetId; 512 part.FromItemID = AssetId;
513
440 } 514 }
441 } 515 }
516 lockPartsForRead(false);
442 } 517 }
443 518
444 public UUID GetFromItemID() 519 public UUID GetFromItemID()
@@ -505,10 +580,11 @@ namespace OpenSim.Region.Framework.Scenes
505 Vector3 maxScale = Vector3.Zero; 580 Vector3 maxScale = Vector3.Zero;
506 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 581 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
507 582
508 lock (m_parts) 583 lockPartsForRead(true);
509 { 584 {
510 foreach (SceneObjectPart part in m_parts.Values) 585 foreach (SceneObjectPart part in m_parts.Values)
511 { 586 {
587
512 Vector3 partscale = part.Scale; 588 Vector3 partscale = part.Scale;
513 Vector3 partoffset = part.OffsetPosition; 589 Vector3 partoffset = part.OffsetPosition;
514 590
@@ -519,8 +595,11 @@ namespace OpenSim.Region.Framework.Scenes
519 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 595 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
520 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 596 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
521 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 597 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
598
522 } 599 }
523 } 600 }
601 lockPartsForRead(false);
602
524 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 603 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
525 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 604 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
526 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 605 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
@@ -536,10 +615,11 @@ namespace OpenSim.Region.Framework.Scenes
536 615
537 EntityIntersection result = new EntityIntersection(); 616 EntityIntersection result = new EntityIntersection();
538 617
539 lock (m_parts) 618 lockPartsForRead(true);
540 { 619 {
541 foreach (SceneObjectPart part in m_parts.Values) 620 foreach (SceneObjectPart part in m_parts.Values)
542 { 621 {
622
543 // Temporary commented to stop compiler warning 623 // Temporary commented to stop compiler warning
544 //Vector3 partPosition = 624 //Vector3 partPosition =
545 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); 625 // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z);
@@ -567,8 +647,10 @@ namespace OpenSim.Region.Framework.Scenes
567 result.distance = inter.distance; 647 result.distance = inter.distance;
568 } 648 }
569 } 649 }
650
570 } 651 }
571 } 652 }
653 lockPartsForRead(false);
572 return result; 654 return result;
573 } 655 }
574 656
@@ -581,10 +663,11 @@ namespace OpenSim.Region.Framework.Scenes
581 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) 663 public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight)
582 { 664 {
583 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; 665 float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f;
584 lock (m_parts) 666 lockPartsForRead(true);
585 { 667 {
586 foreach (SceneObjectPart part in m_parts.Values) 668 foreach (SceneObjectPart part in m_parts.Values)
587 { 669 {
670
588 Vector3 worldPos = part.GetWorldPosition(); 671 Vector3 worldPos = part.GetWorldPosition();
589 Vector3 offset = worldPos - AbsolutePosition; 672 Vector3 offset = worldPos - AbsolutePosition;
590 Quaternion worldRot; 673 Quaternion worldRot;
@@ -643,6 +726,8 @@ namespace OpenSim.Region.Framework.Scenes
643 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 726 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
644 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 727 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
645 728
729
730
646 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); 731 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
647 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); 732 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
648 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); 733 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
@@ -814,6 +899,7 @@ namespace OpenSim.Region.Framework.Scenes
814 minZ = backBottomLeft.Z; 899 minZ = backBottomLeft.Z;
815 } 900 }
816 } 901 }
902 lockPartsForRead(false);
817 903
818 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); 904 Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ);
819 905
@@ -842,17 +928,20 @@ namespace OpenSim.Region.Framework.Scenes
842 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 928 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
843 929
844 // Capture script state while holding the lock 930 // Capture script state while holding the lock
845 lock (m_parts) 931 lockPartsForRead(true);
846 { 932 {
847 foreach (SceneObjectPart part in m_parts.Values) 933 foreach (SceneObjectPart part in m_parts.Values)
848 { 934 {
935
849 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates(); 936 Dictionary<UUID,string> pstates = part.Inventory.GetScriptStates();
850 foreach (UUID itemid in pstates.Keys) 937 foreach (UUID itemid in pstates.Keys)
851 { 938 {
852 states.Add(itemid, pstates[itemid]); 939 states.Add(itemid, pstates[itemid]);
853 } 940 }
941
854 } 942 }
855 } 943 }
944 lockPartsForRead(false);
856 945
857 if (states.Count > 0) 946 if (states.Count > 0)
858 { 947 {
@@ -1014,13 +1103,16 @@ namespace OpenSim.Region.Framework.Scenes
1014 1103
1015 public override void UpdateMovement() 1104 public override void UpdateMovement()
1016 { 1105 {
1017 lock (m_parts) 1106 lockPartsForRead(true);
1018 { 1107 {
1019 foreach (SceneObjectPart part in m_parts.Values) 1108 foreach (SceneObjectPart part in m_parts.Values)
1020 { 1109 {
1110
1021 part.UpdateMovement(); 1111 part.UpdateMovement();
1112
1022 } 1113 }
1023 } 1114 }
1115 lockPartsForRead(false);
1024 } 1116 }
1025 1117
1026 public ushort GetTimeDilation() 1118 public ushort GetTimeDilation()
@@ -1064,7 +1156,7 @@ namespace OpenSim.Region.Framework.Scenes
1064 /// <param name="part"></param> 1156 /// <param name="part"></param>
1065 public void AddPart(SceneObjectPart part) 1157 public void AddPart(SceneObjectPart part)
1066 { 1158 {
1067 lock (m_parts) 1159 lockPartsForWrite(true);
1068 { 1160 {
1069 part.SetParent(this); 1161 part.SetParent(this);
1070 m_parts.Add(part.UUID, part); 1162 m_parts.Add(part.UUID, part);
@@ -1074,6 +1166,7 @@ namespace OpenSim.Region.Framework.Scenes
1074 if (part.LinkNum == 2 && RootPart != null) 1166 if (part.LinkNum == 2 && RootPart != null)
1075 RootPart.LinkNum = 1; 1167 RootPart.LinkNum = 1;
1076 } 1168 }
1169 lockPartsForWrite(false);
1077 } 1170 }
1078 1171
1079 /// <summary> 1172 /// <summary>
@@ -1081,28 +1174,33 @@ namespace OpenSim.Region.Framework.Scenes
1081 /// </summary> 1174 /// </summary>
1082 private void UpdateParentIDs() 1175 private void UpdateParentIDs()
1083 { 1176 {
1084 lock (m_parts) 1177 lockPartsForRead(true);
1085 { 1178 {
1086 foreach (SceneObjectPart part in m_parts.Values) 1179 foreach (SceneObjectPart part in m_parts.Values)
1087 { 1180 {
1181
1088 if (part.UUID != m_rootPart.UUID) 1182 if (part.UUID != m_rootPart.UUID)
1089 { 1183 {
1090 part.ParentID = m_rootPart.LocalId; 1184 part.ParentID = m_rootPart.LocalId;
1091 } 1185 }
1186
1092 } 1187 }
1093 } 1188 }
1189 lockPartsForRead(false);
1094 } 1190 }
1095 1191
1096 public void RegenerateFullIDs() 1192 public void RegenerateFullIDs()
1097 { 1193 {
1098 lock (m_parts) 1194 lockPartsForRead(true);
1099 { 1195 {
1100 foreach (SceneObjectPart part in m_parts.Values) 1196 foreach (SceneObjectPart part in m_parts.Values)
1101 { 1197 {
1198
1102 part.UUID = UUID.Random(); 1199 part.UUID = UUID.Random();
1103 1200
1104 } 1201 }
1105 } 1202 }
1203 lockPartsForRead(false);
1106 } 1204 }
1107 1205
1108 // helper provided for parts. 1206 // helper provided for parts.
@@ -1183,29 +1281,33 @@ namespace OpenSim.Region.Framework.Scenes
1183 1281
1184 DetachFromBackup(); 1282 DetachFromBackup();
1185 1283
1186 lock (m_parts) 1284 lockPartsForRead(true);
1285 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1286 lockPartsForRead(false);
1287
1288 foreach (SceneObjectPart part in values)
1187 { 1289 {
1188 foreach (SceneObjectPart part in m_parts.Values)
1189 {
1190// part.Inventory.RemoveScriptInstances(); 1290// part.Inventory.RemoveScriptInstances();
1191 1291
1192 ScenePresence[] avatars = Scene.GetScenePresences(); 1292 ScenePresence[] avatars = Scene.GetScenePresences();
1193 for (int i = 0; i < avatars.Length; i++) 1293 for (int i = 0; i < avatars.Length; i++)
1294 {
1295 if (avatars[i].ParentID == LocalId)
1194 { 1296 {
1195 if (avatars[i].ParentID == LocalId) 1297 avatars[i].StandUp();
1196 { 1298 }
1197 avatars[i].StandUp();
1198 }
1199 1299
1200 if (!silent) 1300 if (!silent)
1201 { 1301 {
1202 part.UpdateFlag = 0; 1302 part.UpdateFlag = 0;
1203 if (part == m_rootPart) 1303 if (part == m_rootPart)
1204 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1304 avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1205 }
1206 } 1305 }
1207 } 1306 }
1307
1208 } 1308 }
1309
1310
1209 } 1311 }
1210 1312
1211 public void AddScriptLPS(int count) 1313 public void AddScriptLPS(int count)
@@ -1230,17 +1332,20 @@ namespace OpenSim.Region.Framework.Scenes
1230 1332
1231 scriptEvents aggregateScriptEvents=0; 1333 scriptEvents aggregateScriptEvents=0;
1232 1334
1233 lock (m_parts) 1335 lockPartsForRead(true);
1234 { 1336 {
1235 foreach (SceneObjectPart part in m_parts.Values) 1337 foreach (SceneObjectPart part in m_parts.Values)
1236 { 1338 {
1339
1237 if (part == null) 1340 if (part == null)
1238 continue; 1341 continue;
1239 if (part != RootPart) 1342 if (part != RootPart)
1240 part.ObjectFlags = objectflagupdate; 1343 part.ObjectFlags = objectflagupdate;
1241 aggregateScriptEvents |= part.AggregateScriptEvents; 1344 aggregateScriptEvents |= part.AggregateScriptEvents;
1345
1242 } 1346 }
1243 } 1347 }
1348 lockPartsForRead(false);
1244 1349
1245 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); 1350 m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0);
1246 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); 1351 m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0);
@@ -1273,42 +1378,52 @@ namespace OpenSim.Region.Framework.Scenes
1273 /// <param name="m_physicalPrim"></param> 1378 /// <param name="m_physicalPrim"></param>
1274 public void ApplyPhysics(bool m_physicalPrim) 1379 public void ApplyPhysics(bool m_physicalPrim)
1275 { 1380 {
1276 lock (m_parts) 1381 lockPartsForRead(true);
1382
1383 if (m_parts.Count > 1)
1277 { 1384 {
1278 if (m_parts.Count > 1) 1385 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1386 lockPartsForRead(false);
1387 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1388 foreach (SceneObjectPart part in values)
1279 { 1389 {
1280 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); 1390
1281 foreach (SceneObjectPart part in m_parts.Values) 1391 if (part.LocalId != m_rootPart.LocalId)
1282 { 1392 {
1283 if (part.LocalId != m_rootPart.LocalId) 1393 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1284 {
1285 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim);
1286 }
1287 } 1394 }
1288 1395
1289 // Hack to get the physics scene geometries in the right spot
1290 ResetChildPrimPhysicsPositions();
1291 }
1292 else
1293 {
1294 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1295 } 1396 }
1397 // Hack to get the physics scene geometries in the right spot
1398 ResetChildPrimPhysicsPositions();
1399 }
1400 else
1401 {
1402 lockPartsForRead(false);
1403 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim);
1296 } 1404 }
1297 } 1405 }
1298 1406
1299 public void SetOwnerId(UUID userId) 1407 public void SetOwnerId(UUID userId)
1300 { 1408 {
1301 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1409 ForEachPart(delegate(SceneObjectPart part)
1410 {
1411
1412 part.OwnerID = userId;
1413
1414 });
1302 } 1415 }
1303 1416
1304 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1417 public void ForEachPart(Action<SceneObjectPart> whatToDo)
1305 { 1418 {
1306 lock (m_parts) 1419 lockPartsForRead(true);
1420 List<SceneObjectPart> values = new List<SceneObjectPart>(m_parts.Values);
1421 lockPartsForRead(false);
1422 foreach (SceneObjectPart part in values)
1307 { 1423 {
1308 foreach (SceneObjectPart part in m_parts.Values) 1424
1309 { 1425 whatToDo(part);
1310 whatToDo(part); 1426
1311 }
1312 } 1427 }
1313 } 1428 }
1314 1429
@@ -1407,14 +1522,17 @@ namespace OpenSim.Region.Framework.Scenes
1407 { 1522 {
1408 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); 1523 SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID));
1409 1524
1410 lock (m_parts) 1525 lockPartsForRead(true);
1411 { 1526 {
1412 foreach (SceneObjectPart part in m_parts.Values) 1527 foreach (SceneObjectPart part in m_parts.Values)
1413 { 1528 {
1529
1414 if (part != RootPart) 1530 if (part != RootPart)
1415 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); 1531 SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID));
1532
1416 } 1533 }
1417 } 1534 }
1535 lockPartsForRead(false);
1418 } 1536 }
1419 1537
1420 /// <summary> 1538 /// <summary>
@@ -1509,10 +1627,11 @@ namespace OpenSim.Region.Framework.Scenes
1509 1627
1510 List<SceneObjectPart> partList; 1628 List<SceneObjectPart> partList;
1511 1629
1512 lock (m_parts) 1630 lockPartsForRead(true);
1513 { 1631
1514 partList = new List<SceneObjectPart>(m_parts.Values); 1632 partList = new List<SceneObjectPart>(m_parts.Values);
1515 } 1633
1634 lockPartsForRead(false);
1516 1635
1517 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1636 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1518 { 1637 {
@@ -1761,6 +1880,7 @@ namespace OpenSim.Region.Framework.Scenes
1761 } 1880 }
1762 } 1881 }
1763 } 1882 }
1883
1764 public void stopLookAt() 1884 public void stopLookAt()
1765 { 1885 {
1766 SceneObjectPart rootpart = m_rootPart; 1886 SceneObjectPart rootpart = m_rootPart;
@@ -1835,10 +1955,11 @@ namespace OpenSim.Region.Framework.Scenes
1835 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 1955 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1836 newPart.SetParent(this); 1956 newPart.SetParent(this);
1837 1957
1838 lock (m_parts) 1958 lockPartsForWrite(true);
1839 { 1959 {
1840 m_parts.Add(newPart.UUID, newPart); 1960 m_parts.Add(newPart.UUID, newPart);
1841 } 1961 }
1962 lockPartsForWrite(false);
1842 1963
1843 SetPartAsNonRoot(newPart); 1964 SetPartAsNonRoot(newPart);
1844 1965
@@ -1901,7 +2022,7 @@ namespace OpenSim.Region.Framework.Scenes
1901 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2022 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1902 // return; 2023 // return;
1903 2024
1904 lock (m_parts) 2025 lockPartsForRead(true);
1905 { 2026 {
1906 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2027 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1907 2028
@@ -1919,34 +2040,43 @@ namespace OpenSim.Region.Framework.Scenes
1919 2040
1920 foreach (SceneObjectPart part in m_parts.Values) 2041 foreach (SceneObjectPart part in m_parts.Values)
1921 { 2042 {
2043
1922 part.SendScheduledUpdates(); 2044 part.SendScheduledUpdates();
2045
1923 } 2046 }
1924 } 2047 }
2048 lockPartsForRead(false);
1925 } 2049 }
1926 2050
1927 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2051 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
1928 { 2052 {
1929 RootPart.AddFullUpdateToAvatar(presence); 2053 RootPart.AddFullUpdateToAvatar(presence);
1930 2054
1931 lock (m_parts) 2055 lockPartsForRead(true);
1932 { 2056 {
1933 foreach (SceneObjectPart part in m_parts.Values) 2057 foreach (SceneObjectPart part in m_parts.Values)
1934 { 2058 {
2059
1935 if (part != RootPart) 2060 if (part != RootPart)
1936 part.AddFullUpdateToAvatar(presence); 2061 part.AddFullUpdateToAvatar(presence);
2062
1937 } 2063 }
1938 } 2064 }
2065 lockPartsForRead(false);
1939 } 2066 }
1940 2067
1941 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2068 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1942 { 2069 {
1943 lock (m_parts) 2070 lockPartsForRead(true);
1944 { 2071 {
1945 foreach (SceneObjectPart part in m_parts.Values) 2072 foreach (SceneObjectPart part in m_parts.Values)
1946 { 2073 {
2074
1947 part.AddTerseUpdateToAvatar(presence); 2075 part.AddTerseUpdateToAvatar(presence);
2076
1948 } 2077 }
1949 } 2078 }
2079 lockPartsForRead(false);
1950 } 2080 }
1951 2081
1952 /// <summary> 2082 /// <summary>
@@ -1957,14 +2087,17 @@ namespace OpenSim.Region.Framework.Scenes
1957 checkAtTargets(); 2087 checkAtTargets();
1958 RootPart.ScheduleFullUpdate(); 2088 RootPart.ScheduleFullUpdate();
1959 2089
1960 lock (m_parts) 2090 lockPartsForRead(true);
1961 { 2091 {
1962 foreach (SceneObjectPart part in m_parts.Values) 2092 foreach (SceneObjectPart part in m_parts.Values)
1963 { 2093 {
2094
1964 if (part != RootPart) 2095 if (part != RootPart)
1965 part.ScheduleFullUpdate(); 2096 part.ScheduleFullUpdate();
2097
1966 } 2098 }
1967 } 2099 }
2100 lockPartsForRead(false);
1968 } 2101 }
1969 2102
1970 /// <summary> 2103 /// <summary>
@@ -1972,13 +2105,16 @@ namespace OpenSim.Region.Framework.Scenes
1972 /// </summary> 2105 /// </summary>
1973 public void ScheduleGroupForTerseUpdate() 2106 public void ScheduleGroupForTerseUpdate()
1974 { 2107 {
1975 lock (m_parts) 2108 lockPartsForRead(true);
1976 { 2109 {
1977 foreach (SceneObjectPart part in m_parts.Values) 2110 foreach (SceneObjectPart part in m_parts.Values)
1978 { 2111 {
2112
1979 part.ScheduleTerseUpdate(); 2113 part.ScheduleTerseUpdate();
2114
1980 } 2115 }
1981 } 2116 }
2117 lockPartsForRead(false);
1982 } 2118 }
1983 2119
1984 /// <summary> 2120 /// <summary>
@@ -1991,14 +2127,17 @@ namespace OpenSim.Region.Framework.Scenes
1991 2127
1992 RootPart.SendFullUpdateToAllClients(); 2128 RootPart.SendFullUpdateToAllClients();
1993 2129
1994 lock (m_parts) 2130 lockPartsForRead(true);
1995 { 2131 {
1996 foreach (SceneObjectPart part in m_parts.Values) 2132 foreach (SceneObjectPart part in m_parts.Values)
1997 { 2133 {
2134
1998 if (part != RootPart) 2135 if (part != RootPart)
1999 part.SendFullUpdateToAllClients(); 2136 part.SendFullUpdateToAllClients();
2137
2000 } 2138 }
2001 } 2139 }
2140 lockPartsForRead(false);
2002 } 2141 }
2003 2142
2004 /// <summary> 2143 /// <summary>
@@ -2029,14 +2168,15 @@ namespace OpenSim.Region.Framework.Scenes
2029 { 2168 {
2030 if (IsDeleted) 2169 if (IsDeleted)
2031 return; 2170 return;
2032 2171
2033 lock (m_parts) 2172 lockPartsForRead(true);
2034 { 2173 {
2035 foreach (SceneObjectPart part in m_parts.Values) 2174 foreach (SceneObjectPart part in m_parts.Values)
2036 { 2175 {
2037 part.SendTerseUpdateToAllClients(); 2176 part.SendTerseUpdateToAllClients();
2038 } 2177 }
2039 } 2178 }
2179 lockPartsForRead(false);
2040 } 2180 }
2041 2181
2042 #endregion 2182 #endregion
@@ -2050,16 +2190,18 @@ namespace OpenSim.Region.Framework.Scenes
2050 /// <returns>null if no child part with that linknum or child part</returns> 2190 /// <returns>null if no child part with that linknum or child part</returns>
2051 public SceneObjectPart GetLinkNumPart(int linknum) 2191 public SceneObjectPart GetLinkNumPart(int linknum)
2052 { 2192 {
2053 lock (m_parts) 2193 lockPartsForRead(true);
2054 { 2194 {
2055 foreach (SceneObjectPart part in m_parts.Values) 2195 foreach (SceneObjectPart part in m_parts.Values)
2056 { 2196 {
2057 if (part.LinkNum == linknum) 2197 if (part.LinkNum == linknum)
2058 { 2198 {
2199 lockPartsForRead(false);
2059 return part; 2200 return part;
2060 } 2201 }
2061 } 2202 }
2062 } 2203 }
2204 lockPartsForRead(false);
2063 2205
2064 return null; 2206 return null;
2065 } 2207 }
@@ -2087,17 +2229,19 @@ namespace OpenSim.Region.Framework.Scenes
2087 public SceneObjectPart GetChildPart(uint localID) 2229 public SceneObjectPart GetChildPart(uint localID)
2088 { 2230 {
2089 //m_log.DebugFormat("Entered looking for {0}", localID); 2231 //m_log.DebugFormat("Entered looking for {0}", localID);
2090 lock (m_parts) 2232 lockPartsForRead(true);
2091 { 2233 {
2092 foreach (SceneObjectPart part in m_parts.Values) 2234 foreach (SceneObjectPart part in m_parts.Values)
2093 { 2235 {
2094 //m_log.DebugFormat("Found {0}", part.LocalId); 2236 //m_log.DebugFormat("Found {0}", part.LocalId);
2095 if (part.LocalId == localID) 2237 if (part.LocalId == localID)
2096 { 2238 {
2239 lockPartsForRead(false);
2097 return part; 2240 return part;
2098 } 2241 }
2099 } 2242 }
2100 } 2243 }
2244 lockPartsForRead(false);
2101 2245
2102 return null; 2246 return null;
2103 } 2247 }
@@ -2127,17 +2271,19 @@ namespace OpenSim.Region.Framework.Scenes
2127 public bool HasChildPrim(uint localID) 2271 public bool HasChildPrim(uint localID)
2128 { 2272 {
2129 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2273 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2130 lock (m_parts) 2274 lockPartsForRead(true);
2131 { 2275 {
2132 foreach (SceneObjectPart part in m_parts.Values) 2276 foreach (SceneObjectPart part in m_parts.Values)
2133 { 2277 {
2134 //m_log.DebugFormat("Found {0}", part.LocalId); 2278 //m_log.DebugFormat("Found {0}", part.LocalId);
2135 if (part.LocalId == localID) 2279 if (part.LocalId == localID)
2136 { 2280 {
2281 lockPartsForRead(false);
2137 return true; 2282 return true;
2138 } 2283 }
2139 } 2284 }
2140 } 2285 }
2286 lockPartsForRead(false);
2141 2287
2142 return false; 2288 return false;
2143 } 2289 }
@@ -2187,53 +2333,57 @@ namespace OpenSim.Region.Framework.Scenes
2187 if (m_rootPart.LinkNum == 0) 2333 if (m_rootPart.LinkNum == 0)
2188 m_rootPart.LinkNum = 1; 2334 m_rootPart.LinkNum = 1;
2189 2335
2190 lock (m_parts) 2336 lockPartsForWrite(true);
2191 { 2337
2192 m_parts.Add(linkPart.UUID, linkPart); 2338 m_parts.Add(linkPart.UUID, linkPart);
2193 2339
2194 // Insert in terms of link numbers, the new links 2340 lockPartsForWrite(false);
2195 // before the current ones (with the exception of 2341
2196 // the root prim. Shuffle the old ones up 2342 // Insert in terms of link numbers, the new links
2197 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2343 // before the current ones (with the exception of
2344 // the root prim. Shuffle the old ones up
2345 lockPartsForRead(true);
2346 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2347 {
2348 if (kvp.Value.LinkNum != 1)
2198 { 2349 {
2199 if (kvp.Value.LinkNum != 1) 2350 // Don't update root prim link number
2200 { 2351 kvp.Value.LinkNum += objectGroup.PrimCount;
2201 // Don't update root prim link number
2202 kvp.Value.LinkNum += objectGroup.PrimCount;
2203 }
2204 } 2352 }
2353 }
2354 lockPartsForRead(false);
2205 2355
2206 linkPart.LinkNum = 2; 2356 linkPart.LinkNum = 2;
2207 2357
2208 linkPart.SetParent(this); 2358 linkPart.SetParent(this);
2209 linkPart.AddFlag(PrimFlags.CreateSelected); 2359 linkPart.AddFlag(PrimFlags.CreateSelected);
2210 2360
2211 //if (linkPart.PhysActor != null) 2361 //if (linkPart.PhysActor != null)
2212 //{ 2362 //{
2213 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2363 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2214 2364
2215 //linkPart.PhysActor = null; 2365 //linkPart.PhysActor = null;
2216 //} 2366 //}
2217 2367
2218 //TODO: rest of parts 2368 //TODO: rest of parts
2219 int linkNum = 3; 2369 int linkNum = 3;
2220 foreach (SceneObjectPart part in objectGroup.Children.Values) 2370 foreach (SceneObjectPart part in objectGroup.Children.Values)
2371 {
2372 if (part.UUID != objectGroup.m_rootPart.UUID)
2221 { 2373 {
2222 if (part.UUID != objectGroup.m_rootPart.UUID) 2374 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2223 {
2224 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2225 }
2226 part.ClearUndoState();
2227 } 2375 }
2376 part.ClearUndoState();
2228 } 2377 }
2229 2378
2230 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2379 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2231 objectGroup.m_isDeleted = true; 2380 objectGroup.m_isDeleted = true;
2381
2382 objectGroup.lockPartsForWrite(true);
2232 2383
2233 lock (objectGroup.m_parts) 2384 objectGroup.m_parts.Clear();
2234 { 2385
2235 objectGroup.m_parts.Clear(); 2386 objectGroup.lockPartsForWrite(false);
2236 }
2237 2387
2238 // Can't do this yet since backup still makes use of the root part without any synchronization 2388 // Can't do this yet since backup still makes use of the root part without any synchronization
2239// objectGroup.m_rootPart = null; 2389// objectGroup.m_rootPart = null;
@@ -2292,11 +2442,12 @@ namespace OpenSim.Region.Framework.Scenes
2292 Quaternion worldRot = linkPart.GetWorldRotation(); 2442 Quaternion worldRot = linkPart.GetWorldRotation();
2293 2443
2294 // Remove the part from this object 2444 // Remove the part from this object
2295 lock (m_parts) 2445 lockPartsForWrite(true);
2296 { 2446 {
2297 m_parts.Remove(linkPart.UUID); 2447 m_parts.Remove(linkPart.UUID);
2298 } 2448 }
2299 2449 lockPartsForWrite(false);
2450 lockPartsForRead(true);
2300 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2451 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2301 RootPart.LinkNum = 0; 2452 RootPart.LinkNum = 0;
2302 else 2453 else
@@ -2307,6 +2458,7 @@ namespace OpenSim.Region.Framework.Scenes
2307 p.LinkNum--; 2458 p.LinkNum--;
2308 } 2459 }
2309 } 2460 }
2461 lockPartsForRead(false);
2310 2462
2311 linkPart.ParentID = 0; 2463 linkPart.ParentID = 0;
2312 linkPart.LinkNum = 0; 2464 linkPart.LinkNum = 0;
@@ -2624,9 +2776,12 @@ namespace OpenSim.Region.Framework.Scenes
2624 2776
2625 if (selectionPart != null) 2777 if (selectionPart != null)
2626 { 2778 {
2627 lock (m_parts) 2779 lockPartsForRead(true);
2780 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2781 lockPartsForRead(false);
2782 foreach (SceneObjectPart part in parts)
2628 { 2783 {
2629 foreach (SceneObjectPart part in m_parts.Values) 2784 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2630 { 2785 {
2631 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2786 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2632 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2787 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2636,12 +2791,13 @@ namespace OpenSim.Region.Framework.Scenes
2636 break; 2791 break;
2637 } 2792 }
2638 } 2793 }
2794 }
2639 2795
2640 foreach (SceneObjectPart part in m_parts.Values) 2796 foreach (SceneObjectPart part in parts)
2641 { 2797 {
2642 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2798 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2643 }
2644 } 2799 }
2800
2645 } 2801 }
2646 } 2802 }
2647 2803
@@ -2727,11 +2883,9 @@ namespace OpenSim.Region.Framework.Scenes
2727 scale.Y = m_scene.m_maxNonphys; 2883 scale.Y = m_scene.m_maxNonphys;
2728 if (scale.Z > m_scene.m_maxNonphys) 2884 if (scale.Z > m_scene.m_maxNonphys)
2729 scale.Z = m_scene.m_maxNonphys; 2885 scale.Z = m_scene.m_maxNonphys;
2730
2731 SceneObjectPart part = GetChildPart(localID); 2886 SceneObjectPart part = GetChildPart(localID);
2732 if (part != null) 2887 if (part != null)
2733 { 2888 {
2734 part.Resize(scale);
2735 if (part.PhysActor != null) 2889 if (part.PhysActor != null)
2736 { 2890 {
2737 if (part.PhysActor.IsPhysical) 2891 if (part.PhysActor.IsPhysical)
@@ -2746,7 +2900,7 @@ namespace OpenSim.Region.Framework.Scenes
2746 part.PhysActor.Size = scale; 2900 part.PhysActor.Size = scale;
2747 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2901 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2748 } 2902 }
2749 //if (part.UUID != m_rootPart.UUID) 2903 part.Resize(scale);
2750 2904
2751 HasGroupChanged = true; 2905 HasGroupChanged = true;
2752 ScheduleGroupForFullUpdate(); 2906 ScheduleGroupForFullUpdate();
@@ -2787,77 +2941,76 @@ namespace OpenSim.Region.Framework.Scenes
2787 float y = (scale.Y / part.Scale.Y); 2941 float y = (scale.Y / part.Scale.Y);
2788 float z = (scale.Z / part.Scale.Z); 2942 float z = (scale.Z / part.Scale.Z);
2789 2943
2790 lock (m_parts) 2944 lockPartsForRead(true);
2945 if (x > 1.0f || y > 1.0f || z > 1.0f)
2791 { 2946 {
2792 if (x > 1.0f || y > 1.0f || z > 1.0f) 2947 foreach (SceneObjectPart obPart in m_parts.Values)
2793 { 2948 {
2794 foreach (SceneObjectPart obPart in m_parts.Values) 2949 if (obPart.UUID != m_rootPart.UUID)
2795 { 2950 {
2796 if (obPart.UUID != m_rootPart.UUID) 2951 Vector3 oldSize = new Vector3(obPart.Scale);
2797 {
2798 Vector3 oldSize = new Vector3(obPart.Scale);
2799 2952
2800 float f = 1.0f; 2953 float f = 1.0f;
2801 float a = 1.0f; 2954 float a = 1.0f;
2802 2955
2803 if (part.PhysActor != null && part.PhysActor.IsPhysical) 2956 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2957 {
2958 if (oldSize.X*x > m_scene.m_maxPhys)
2804 { 2959 {
2805 if (oldSize.X*x > m_scene.m_maxPhys) 2960 f = m_scene.m_maxPhys / oldSize.X;
2806 { 2961 a = f / x;
2807 f = m_scene.m_maxPhys / oldSize.X; 2962 x *= a;
2808 a = f / x; 2963 y *= a;
2809 x *= a; 2964 z *= a;
2810 y *= a;
2811 z *= a;
2812 }
2813 if (oldSize.Y*y > m_scene.m_maxPhys)
2814 {
2815 f = m_scene.m_maxPhys / oldSize.Y;
2816 a = f / y;
2817 x *= a;
2818 y *= a;
2819 z *= a;
2820 }
2821 if (oldSize.Z*z > m_scene.m_maxPhys)
2822 {
2823 f = m_scene.m_maxPhys / oldSize.Z;
2824 a = f / z;
2825 x *= a;
2826 y *= a;
2827 z *= a;
2828 }
2829 } 2965 }
2830 else 2966 if (oldSize.Y*y > m_scene.m_maxPhys)
2967 {
2968 f = m_scene.m_maxPhys / oldSize.Y;
2969 a = f / y;
2970 x *= a;
2971 y *= a;
2972 z *= a;
2973 }
2974 if (oldSize.Z*z > m_scene.m_maxPhys)
2975 {
2976 f = m_scene.m_maxPhys / oldSize.Z;
2977 a = f / z;
2978 x *= a;
2979 y *= a;
2980 z *= a;
2981 }
2982 }
2983 else
2984 {
2985 if (oldSize.X*x > m_scene.m_maxNonphys)
2986 {
2987 f = m_scene.m_maxNonphys / oldSize.X;
2988 a = f / x;
2989 x *= a;
2990 y *= a;
2991 z *= a;
2992 }
2993 if (oldSize.Y*y > m_scene.m_maxNonphys)
2831 { 2994 {
2832 if (oldSize.X*x > m_scene.m_maxNonphys) 2995 f = m_scene.m_maxNonphys / oldSize.Y;
2833 { 2996 a = f / y;
2834 f = m_scene.m_maxNonphys / oldSize.X; 2997 x *= a;
2835 a = f / x; 2998 y *= a;
2836 x *= a; 2999 z *= a;
2837 y *= a; 3000 }
2838 z *= a; 3001 if (oldSize.Z*z > m_scene.m_maxNonphys)
2839 } 3002 {
2840 if (oldSize.Y*y > m_scene.m_maxNonphys) 3003 f = m_scene.m_maxNonphys / oldSize.Z;
2841 { 3004 a = f / z;
2842 f = m_scene.m_maxNonphys / oldSize.Y; 3005 x *= a;
2843 a = f / y; 3006 y *= a;
2844 x *= a; 3007 z *= a;
2845 y *= a;
2846 z *= a;
2847 }
2848 if (oldSize.Z*z > m_scene.m_maxNonphys)
2849 {
2850 f = m_scene.m_maxNonphys / oldSize.Z;
2851 a = f / z;
2852 x *= a;
2853 y *= a;
2854 z *= a;
2855 }
2856 } 3008 }
2857 } 3009 }
2858 } 3010 }
2859 } 3011 }
2860 } 3012 }
3013 lockPartsForRead(false);
2861 3014
2862 Vector3 prevScale = part.Scale; 3015 Vector3 prevScale = part.Scale;
2863 prevScale.X *= x; 3016 prevScale.X *= x;
@@ -2865,7 +3018,7 @@ namespace OpenSim.Region.Framework.Scenes
2865 prevScale.Z *= z; 3018 prevScale.Z *= z;
2866 part.Resize(prevScale); 3019 part.Resize(prevScale);
2867 3020
2868 lock (m_parts) 3021 lockPartsForRead(true);
2869 { 3022 {
2870 foreach (SceneObjectPart obPart in m_parts.Values) 3023 foreach (SceneObjectPart obPart in m_parts.Values)
2871 { 3024 {
@@ -2884,6 +3037,7 @@ namespace OpenSim.Region.Framework.Scenes
2884 } 3037 }
2885 } 3038 }
2886 } 3039 }
3040 lockPartsForRead(false);
2887 3041
2888 if (part.PhysActor != null) 3042 if (part.PhysActor != null)
2889 { 3043 {
@@ -2964,7 +3118,7 @@ namespace OpenSim.Region.Framework.Scenes
2964 axDiff *= Quaternion.Inverse(partRotation); 3118 axDiff *= Quaternion.Inverse(partRotation);
2965 diff = axDiff; 3119 diff = axDiff;
2966 3120
2967 lock (m_parts) 3121 lockPartsForRead(true);
2968 { 3122 {
2969 foreach (SceneObjectPart obPart in m_parts.Values) 3123 foreach (SceneObjectPart obPart in m_parts.Values)
2970 { 3124 {
@@ -2974,6 +3128,7 @@ namespace OpenSim.Region.Framework.Scenes
2974 } 3128 }
2975 } 3129 }
2976 } 3130 }
3131 lockPartsForRead(false);
2977 3132
2978 AbsolutePosition = newPos; 3133 AbsolutePosition = newPos;
2979 3134
@@ -3091,7 +3246,7 @@ namespace OpenSim.Region.Framework.Scenes
3091 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3246 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3092 } 3247 }
3093 3248
3094 lock (m_parts) 3249 lockPartsForRead(true);
3095 { 3250 {
3096 foreach (SceneObjectPart prim in m_parts.Values) 3251 foreach (SceneObjectPart prim in m_parts.Values)
3097 { 3252 {
@@ -3109,6 +3264,7 @@ namespace OpenSim.Region.Framework.Scenes
3109 } 3264 }
3110 } 3265 }
3111 } 3266 }
3267 lockPartsForRead(false);
3112 3268
3113 m_rootPart.ScheduleTerseUpdate(); 3269 m_rootPart.ScheduleTerseUpdate();
3114 } 3270 }
@@ -3207,7 +3363,7 @@ namespace OpenSim.Region.Framework.Scenes
3207 if (atTargets.Count > 0) 3363 if (atTargets.Count > 0)
3208 { 3364 {
3209 uint[] localids = new uint[0]; 3365 uint[] localids = new uint[0];
3210 lock (m_parts) 3366 lockPartsForRead(true);
3211 { 3367 {
3212 localids = new uint[m_parts.Count]; 3368 localids = new uint[m_parts.Count];
3213 int cntr = 0; 3369 int cntr = 0;
@@ -3217,6 +3373,7 @@ namespace OpenSim.Region.Framework.Scenes
3217 cntr++; 3373 cntr++;
3218 } 3374 }
3219 } 3375 }
3376 lockPartsForRead(false);
3220 3377
3221 for (int ctr = 0; ctr < localids.Length; ctr++) 3378 for (int ctr = 0; ctr < localids.Length; ctr++)
3222 { 3379 {
@@ -3235,7 +3392,7 @@ namespace OpenSim.Region.Framework.Scenes
3235 { 3392 {
3236 //trigger not_at_target 3393 //trigger not_at_target
3237 uint[] localids = new uint[0]; 3394 uint[] localids = new uint[0];
3238 lock (m_parts) 3395 lockPartsForRead(true);
3239 { 3396 {
3240 localids = new uint[m_parts.Count]; 3397 localids = new uint[m_parts.Count];
3241 int cntr = 0; 3398 int cntr = 0;
@@ -3245,7 +3402,8 @@ namespace OpenSim.Region.Framework.Scenes
3245 cntr++; 3402 cntr++;
3246 } 3403 }
3247 } 3404 }
3248 3405 lockPartsForRead(false);
3406
3249 for (int ctr = 0; ctr < localids.Length; ctr++) 3407 for (int ctr = 0; ctr < localids.Length; ctr++)
3250 { 3408 {
3251 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3409 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3258,19 +3416,20 @@ namespace OpenSim.Region.Framework.Scenes
3258 public float GetMass() 3416 public float GetMass()
3259 { 3417 {
3260 float retmass = 0f; 3418 float retmass = 0f;
3261 lock (m_parts) 3419 lockPartsForRead(true);
3262 { 3420 {
3263 foreach (SceneObjectPart part in m_parts.Values) 3421 foreach (SceneObjectPart part in m_parts.Values)
3264 { 3422 {
3265 retmass += part.GetMass(); 3423 retmass += part.GetMass();
3266 } 3424 }
3267 } 3425 }
3426 lockPartsForRead(false);
3268 return retmass; 3427 return retmass;
3269 } 3428 }
3270 3429
3271 public void CheckSculptAndLoad() 3430 public void CheckSculptAndLoad()
3272 { 3431 {
3273 lock (m_parts) 3432 lockPartsForRead(true);
3274 { 3433 {
3275 if (!IsDeleted) 3434 if (!IsDeleted)
3276 { 3435 {
@@ -3295,6 +3454,7 @@ namespace OpenSim.Region.Framework.Scenes
3295 } 3454 }
3296 } 3455 }
3297 } 3456 }
3457 lockPartsForRead(false);
3298 } 3458 }
3299 3459
3300 protected void AssetReceived(string id, Object sender, AssetBase asset) 3460 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3315,7 +3475,7 @@ namespace OpenSim.Region.Framework.Scenes
3315 /// <param name="client"></param> 3475 /// <param name="client"></param>
3316 public void SetGroup(UUID GroupID, IClientAPI client) 3476 public void SetGroup(UUID GroupID, IClientAPI client)
3317 { 3477 {
3318 lock (m_parts) 3478 lockPartsForRead(true);
3319 { 3479 {
3320 foreach (SceneObjectPart part in m_parts.Values) 3480 foreach (SceneObjectPart part in m_parts.Values)
3321 { 3481 {
@@ -3325,7 +3485,7 @@ namespace OpenSim.Region.Framework.Scenes
3325 3485
3326 HasGroupChanged = true; 3486 HasGroupChanged = true;
3327 } 3487 }
3328 3488 lockPartsForRead(false);
3329 ScheduleGroupForFullUpdate(); 3489 ScheduleGroupForFullUpdate();
3330 } 3490 }
3331 3491
@@ -3344,11 +3504,12 @@ namespace OpenSim.Region.Framework.Scenes
3344 3504
3345 public void SetAttachmentPoint(byte point) 3505 public void SetAttachmentPoint(byte point)
3346 { 3506 {
3347 lock (m_parts) 3507 lockPartsForRead(true);
3348 { 3508 {
3349 foreach (SceneObjectPart part in m_parts.Values) 3509 foreach (SceneObjectPart part in m_parts.Values)
3350 part.SetAttachmentPoint(point); 3510 part.SetAttachmentPoint(point);
3351 } 3511 }
3512 lockPartsForRead(false);
3352 } 3513 }
3353 3514
3354 #region ISceneObject 3515 #region ISceneObject
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index c0243a5..6b562e5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -212,6 +212,7 @@ namespace OpenSim.Region.Framework.Scenes
212 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 212 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
213 private Vector3 m_sitTargetPosition; 213 private Vector3 m_sitTargetPosition;
214 private string m_sitAnimation = "SIT"; 214 private string m_sitAnimation = "SIT";
215 private bool m_occupied; // KF if any av is sitting on this prim
215 private string m_text = String.Empty; 216 private string m_text = String.Empty;
216 private string m_touchName = String.Empty; 217 private string m_touchName = String.Empty;
217 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 218 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -389,12 +390,16 @@ namespace OpenSim.Region.Framework.Scenes
389 } 390 }
390 391
391 /// <value> 392 /// <value>
392 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 393 /// Get the inventory list
393 /// </value> 394 /// </value>
394 public TaskInventoryDictionary TaskInventory 395 public TaskInventoryDictionary TaskInventory
395 { 396 {
396 get { return m_inventory.Items; } 397 get {
397 set { m_inventory.Items = value; } 398 return m_inventory.Items;
399 }
400 set {
401 m_inventory.Items = value;
402 }
398 } 403 }
399 404
400 public uint ObjectFlags 405 public uint ObjectFlags
@@ -527,7 +532,6 @@ namespace OpenSim.Region.Framework.Scenes
527 StoreUndoState(); 532 StoreUndoState();
528 533
529 m_groupPosition = value; 534 m_groupPosition = value;
530
531 PhysicsActor actor = PhysActor; 535 PhysicsActor actor = PhysActor;
532 if (actor != null) 536 if (actor != null)
533 { 537 {
@@ -837,7 +841,8 @@ namespace OpenSim.Region.Framework.Scenes
837 if (IsAttachment) 841 if (IsAttachment)
838 return GroupPosition; 842 return GroupPosition;
839 843
840 return m_offsetPosition + m_groupPosition; } 844// return m_offsetPosition + m_groupPosition; }
845 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
841 } 846 }
842 847
843 public SceneObjectGroup ParentGroup 848 public SceneObjectGroup ParentGroup
@@ -989,6 +994,13 @@ namespace OpenSim.Region.Framework.Scenes
989 get { return _flags; } 994 get { return _flags; }
990 set { _flags = value; } 995 set { _flags = value; }
991 } 996 }
997
998 [XmlIgnore]
999 public bool IsOccupied // KF If an av is sittingon this prim
1000 {
1001 get { return m_occupied; }
1002 set { m_occupied = value; }
1003 }
992 1004
993 [XmlIgnore] 1005 [XmlIgnore]
994 public UUID SitTargetAvatar 1006 public UUID SitTargetAvatar
@@ -1064,14 +1076,6 @@ namespace OpenSim.Region.Framework.Scenes
1064 } 1076 }
1065 } 1077 }
1066 1078
1067 /// <summary>
1068 /// Clear all pending updates of parts to clients
1069 /// </summary>
1070 private void ClearUpdateSchedule()
1071 {
1072 m_updateFlag = 0;
1073 }
1074
1075 private void SendObjectPropertiesToClient(UUID AgentID) 1079 private void SendObjectPropertiesToClient(UUID AgentID)
1076 { 1080 {
1077 ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); 1081 ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
@@ -1737,12 +1741,17 @@ namespace OpenSim.Region.Framework.Scenes
1737 public Vector3 GetWorldPosition() 1741 public Vector3 GetWorldPosition()
1738 { 1742 {
1739 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 1743 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1740
1741 Vector3 axPos = OffsetPosition; 1744 Vector3 axPos = OffsetPosition;
1742
1743 axPos *= parentRot; 1745 axPos *= parentRot;
1744 Vector3 translationOffsetPosition = axPos; 1746 Vector3 translationOffsetPosition = axPos;
1745 return GroupPosition + translationOffsetPosition; 1747 if(_parentID == 0)
1748 {
1749 return GroupPosition;
1750 }
1751 else
1752 {
1753 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
1754 }
1746 } 1755 }
1747 1756
1748 /// <summary> 1757 /// <summary>
@@ -1753,7 +1762,7 @@ namespace OpenSim.Region.Framework.Scenes
1753 { 1762 {
1754 Quaternion newRot; 1763 Quaternion newRot;
1755 1764
1756 if (this.LinkNum == 0) 1765 if (this.LinkNum < 2) //KF Single or root prim
1757 { 1766 {
1758 newRot = RotationOffset; 1767 newRot = RotationOffset;
1759 } 1768 }
@@ -2109,17 +2118,18 @@ namespace OpenSim.Region.Framework.Scenes
2109 //Trys to fetch sound id from prim's inventory. 2118 //Trys to fetch sound id from prim's inventory.
2110 //Prim's inventory doesn't support non script items yet 2119 //Prim's inventory doesn't support non script items yet
2111 2120
2112 lock (TaskInventory) 2121 TaskInventory.LockItemsForRead(true);
2122
2123 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2113 { 2124 {
2114 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2125 if (item.Value.Name == sound)
2115 { 2126 {
2116 if (item.Value.Name == sound) 2127 soundID = item.Value.ItemID;
2117 { 2128 break;
2118 soundID = item.Value.ItemID;
2119 break;
2120 }
2121 } 2129 }
2122 } 2130 }
2131
2132 TaskInventory.LockItemsForRead(false);
2123 } 2133 }
2124 2134
2125 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars(); 2135 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
@@ -2394,8 +2404,8 @@ namespace OpenSim.Region.Framework.Scenes
2394 { 2404 {
2395 const float ROTATION_TOLERANCE = 0.01f; 2405 const float ROTATION_TOLERANCE = 0.01f;
2396 const float VELOCITY_TOLERANCE = 0.001f; 2406 const float VELOCITY_TOLERANCE = 0.001f;
2397 const float POSITION_TOLERANCE = 0.05f; 2407 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2398 const int TIME_MS_TOLERANCE = 3000; 2408 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2399 2409
2400 if (m_updateFlag == 1) 2410 if (m_updateFlag == 1)
2401 { 2411 {
@@ -2409,7 +2419,7 @@ namespace OpenSim.Region.Framework.Scenes
2409 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2419 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2410 { 2420 {
2411 AddTerseUpdateToAllAvatars(); 2421 AddTerseUpdateToAllAvatars();
2412 ClearUpdateSchedule(); 2422
2413 2423
2414 // This causes the Scene to 'poll' physical objects every couple of frames 2424 // This causes the Scene to 'poll' physical objects every couple of frames
2415 // bad, so it's been replaced by an event driven method. 2425 // bad, so it's been replaced by an event driven method.
@@ -2427,16 +2437,18 @@ namespace OpenSim.Region.Framework.Scenes
2427 m_lastAngularVelocity = AngularVelocity; 2437 m_lastAngularVelocity = AngularVelocity;
2428 m_lastTerseSent = Environment.TickCount; 2438 m_lastTerseSent = Environment.TickCount;
2429 } 2439 }
2440 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
2441 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
2430 } 2442 }
2431 else 2443 else
2432 { 2444 {
2433 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 2445 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
2434 { 2446 {
2435 AddFullUpdateToAllAvatars(); 2447 AddFullUpdateToAllAvatars();
2436 ClearUpdateSchedule(); 2448 m_updateFlag = 0; //Same here
2437 } 2449 }
2438 } 2450 }
2439 ClearUpdateSchedule(); 2451 m_updateFlag = 0;
2440 } 2452 }
2441 2453
2442 /// <summary> 2454 /// <summary>
@@ -2463,17 +2475,16 @@ namespace OpenSim.Region.Framework.Scenes
2463 if (!UUID.TryParse(sound, out soundID)) 2475 if (!UUID.TryParse(sound, out soundID))
2464 { 2476 {
2465 // search sound file from inventory 2477 // search sound file from inventory
2466 lock (TaskInventory) 2478 TaskInventory.LockItemsForRead(true);
2479 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2467 { 2480 {
2468 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2481 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2469 { 2482 {
2470 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 2483 soundID = item.Value.ItemID;
2471 { 2484 break;
2472 soundID = item.Value.ItemID;
2473 break;
2474 }
2475 } 2485 }
2476 } 2486 }
2487 TaskInventory.LockItemsForRead(false);
2477 } 2488 }
2478 2489
2479 if (soundID == UUID.Zero) 2490 if (soundID == UUID.Zero)
@@ -2674,13 +2685,6 @@ namespace OpenSim.Region.Framework.Scenes
2674 ScheduleFullUpdate(); 2685 ScheduleFullUpdate();
2675 } 2686 }
2676 2687
2677 public void StopLookAt()
2678 {
2679 m_parentGroup.stopLookAt();
2680
2681 m_parentGroup.ScheduleGroupForTerseUpdate();
2682 }
2683
2684 /// <summary> 2688 /// <summary>
2685 /// Set the text displayed for this part. 2689 /// Set the text displayed for this part.
2686 /// </summary> 2690 /// </summary>
@@ -2696,6 +2700,13 @@ namespace OpenSim.Region.Framework.Scenes
2696 SetText(text); 2700 SetText(text);
2697 } 2701 }
2698 2702
2703 public void StopLookAt()
2704 {
2705 m_parentGroup.stopLookAt();
2706
2707 m_parentGroup.ScheduleGroupForTerseUpdate();
2708 }
2709
2699 public void StopMoveToTarget() 2710 public void StopMoveToTarget()
2700 { 2711 {
2701 m_parentGroup.stopMoveToTarget(); 2712 m_parentGroup.stopMoveToTarget();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index b98747a..cdd23bd 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -81,7 +81,9 @@ namespace OpenSim.Region.Framework.Scenes
81 /// </value> 81 /// </value>
82 protected internal TaskInventoryDictionary Items 82 protected internal TaskInventoryDictionary Items
83 { 83 {
84 get { return m_items; } 84 get {
85 return m_items;
86 }
85 set 87 set
86 { 88 {
87 m_items = value; 89 m_items = value;
@@ -117,22 +119,25 @@ namespace OpenSim.Region.Framework.Scenes
117 /// <param name="linkNum">Link number for the part</param> 119 /// <param name="linkNum">Link number for the part</param>
118 public void ResetInventoryIDs() 120 public void ResetInventoryIDs()
119 { 121 {
120 lock (Items) 122 m_items.LockItemsForWrite(true);
123
124 if (0 == Items.Count)
121 { 125 {
122 if (0 == Items.Count) 126 m_items.LockItemsForWrite(false);
123 return; 127 return;
128 }
124 129
125 HasInventoryChanged = true; 130 HasInventoryChanged = true;
126 m_part.ParentGroup.HasGroupChanged = true; 131 m_part.ParentGroup.HasGroupChanged = true;
127 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 132 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
128 Items.Clear(); 133 Items.Clear();
129 134
130 foreach (TaskInventoryItem item in items) 135 foreach (TaskInventoryItem item in items)
131 { 136 {
132 item.ResetIDs(m_part.UUID); 137 item.ResetIDs(m_part.UUID);
133 Items.Add(item.ItemID, item); 138 Items.Add(item.ItemID, item);
134 }
135 } 139 }
140 m_items.LockItemsForWrite(false);
136 } 141 }
137 142
138 /// <summary> 143 /// <summary>
@@ -141,25 +146,25 @@ namespace OpenSim.Region.Framework.Scenes
141 /// <param name="ownerId"></param> 146 /// <param name="ownerId"></param>
142 public void ChangeInventoryOwner(UUID ownerId) 147 public void ChangeInventoryOwner(UUID ownerId)
143 { 148 {
144 lock (Items) 149 m_items.LockItemsForWrite(true);
150 if (0 == Items.Count)
145 { 151 {
146 if (0 == Items.Count) 152 m_items.LockItemsForWrite(false);
147 { 153 return;
148 return; 154 }
149 }
150 155
151 HasInventoryChanged = true; 156 HasInventoryChanged = true;
152 m_part.ParentGroup.HasGroupChanged = true; 157 m_part.ParentGroup.HasGroupChanged = true;
153 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 158 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
154 foreach (TaskInventoryItem item in items) 159 foreach (TaskInventoryItem item in items)
160 {
161 if (ownerId != item.OwnerID)
155 { 162 {
156 if (ownerId != item.OwnerID) 163 item.LastOwnerID = item.OwnerID;
157 { 164 item.OwnerID = ownerId;
158 item.LastOwnerID = item.OwnerID;
159 item.OwnerID = ownerId;
160 }
161 } 165 }
162 } 166 }
167 m_items.LockItemsForWrite(false);
163 } 168 }
164 169
165 /// <summary> 170 /// <summary>
@@ -168,24 +173,24 @@ namespace OpenSim.Region.Framework.Scenes
168 /// <param name="groupID"></param> 173 /// <param name="groupID"></param>
169 public void ChangeInventoryGroup(UUID groupID) 174 public void ChangeInventoryGroup(UUID groupID)
170 { 175 {
171 lock (Items) 176 m_items.LockItemsForWrite(true);
177 if (0 == Items.Count)
172 { 178 {
173 if (0 == Items.Count) 179 m_items.LockItemsForWrite(false);
174 { 180 return;
175 return; 181 }
176 }
177 182
178 HasInventoryChanged = true; 183 HasInventoryChanged = true;
179 m_part.ParentGroup.HasGroupChanged = true; 184 m_part.ParentGroup.HasGroupChanged = true;
180 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 185 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
181 foreach (TaskInventoryItem item in items) 186 foreach (TaskInventoryItem item in items)
187 {
188 if (groupID != item.GroupID)
182 { 189 {
183 if (groupID != item.GroupID) 190 item.GroupID = groupID;
184 {
185 item.GroupID = groupID;
186 }
187 } 191 }
188 } 192 }
193 m_items.LockItemsForWrite(false);
189 } 194 }
190 195
191 /// <summary> 196 /// <summary>
@@ -193,14 +198,14 @@ namespace OpenSim.Region.Framework.Scenes
193 /// </summary> 198 /// </summary>
194 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 199 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
195 { 200 {
196 lock (m_items) 201 Items.LockItemsForRead(true);
202 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
203 Items.LockItemsForRead(false);
204 foreach (TaskInventoryItem item in items)
197 { 205 {
198 foreach (TaskInventoryItem item in Items.Values) 206 if ((int)InventoryType.LSL == item.InvType)
199 { 207 {
200 if ((int)InventoryType.LSL == item.InvType) 208 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
201 {
202 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
203 }
204 } 209 }
205 } 210 }
206 } 211 }
@@ -210,17 +215,20 @@ namespace OpenSim.Region.Framework.Scenes
210 /// </summary> 215 /// </summary>
211 public void RemoveScriptInstances() 216 public void RemoveScriptInstances()
212 { 217 {
213 lock (Items) 218 Items.LockItemsForRead(true);
219 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
220 Items.LockItemsForRead(false);
221
222 foreach (TaskInventoryItem item in items)
214 { 223 {
215 foreach (TaskInventoryItem item in Items.Values) 224 if ((int)InventoryType.LSL == item.InvType)
216 { 225 {
217 if ((int)InventoryType.LSL == item.InvType) 226 RemoveScriptInstance(item.ItemID);
218 { 227 m_part.RemoveScriptEvents(item.ItemID);
219 RemoveScriptInstance(item.ItemID);
220 m_part.RemoveScriptEvents(item.ItemID);
221 }
222 } 228 }
223 } 229 }
230
231
224 } 232 }
225 233
226 /// <summary> 234 /// <summary>
@@ -245,8 +253,10 @@ namespace OpenSim.Region.Framework.Scenes
245 if (stateSource == 1 && // Prim crossing 253 if (stateSource == 1 && // Prim crossing
246 m_part.ParentGroup.Scene.m_trustBinaries) 254 m_part.ParentGroup.Scene.m_trustBinaries)
247 { 255 {
256 m_items.LockItemsForWrite(true);
248 m_items[item.ItemID].PermsMask = 0; 257 m_items[item.ItemID].PermsMask = 0;
249 m_items[item.ItemID].PermsGranter = UUID.Zero; 258 m_items[item.ItemID].PermsGranter = UUID.Zero;
259 m_items.LockItemsForWrite(false);
250 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 260 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
251 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 261 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
252 m_part.ParentGroup.AddActiveScriptCount(1); 262 m_part.ParentGroup.AddActiveScriptCount(1);
@@ -268,8 +278,10 @@ namespace OpenSim.Region.Framework.Scenes
268 { 278 {
269 if (m_part.ParentGroup.m_savedScriptState != null) 279 if (m_part.ParentGroup.m_savedScriptState != null)
270 RestoreSavedScriptState(item.OldItemID, item.ItemID); 280 RestoreSavedScriptState(item.OldItemID, item.ItemID);
281 m_items.LockItemsForWrite(true);
271 m_items[item.ItemID].PermsMask = 0; 282 m_items[item.ItemID].PermsMask = 0;
272 m_items[item.ItemID].PermsGranter = UUID.Zero; 283 m_items[item.ItemID].PermsGranter = UUID.Zero;
284 m_items.LockItemsForWrite(false);
273 string script = Utils.BytesToString(asset.Data); 285 string script = Utils.BytesToString(asset.Data);
274 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 286 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
275 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 287 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
@@ -345,14 +357,17 @@ namespace OpenSim.Region.Framework.Scenes
345 /// </param> 357 /// </param>
346 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 358 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
347 { 359 {
348 lock (m_items) 360 m_items.LockItemsForRead(true);
361 if (m_items.ContainsKey(itemId))
349 { 362 {
350 if (m_items.ContainsKey(itemId)) 363 if (m_items.ContainsKey(itemId))
351 { 364 {
365 m_items.LockItemsForRead(false);
352 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); 366 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
353 } 367 }
354 else 368 else
355 { 369 {
370 m_items.LockItemsForRead(false);
356 m_log.ErrorFormat( 371 m_log.ErrorFormat(
357 "[PRIM INVENTORY]: " + 372 "[PRIM INVENTORY]: " +
358 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 373 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
@@ -360,6 +375,15 @@ namespace OpenSim.Region.Framework.Scenes
360 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 375 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
361 } 376 }
362 } 377 }
378 else
379 {
380 m_items.LockItemsForRead(false);
381 m_log.ErrorFormat(
382 "[PRIM INVENTORY]: " +
383 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}",
384 itemId, m_part.Name, m_part.UUID);
385 }
386
363 } 387 }
364 388
365 /// <summary> 389 /// <summary>
@@ -391,11 +415,16 @@ namespace OpenSim.Region.Framework.Scenes
391 /// <returns></returns> 415 /// <returns></returns>
392 private bool InventoryContainsName(string name) 416 private bool InventoryContainsName(string name)
393 { 417 {
394 foreach (TaskInventoryItem item in Items.Values) 418 m_items.LockItemsForRead(true);
419 foreach (TaskInventoryItem item in m_items.Values)
395 { 420 {
396 if (item.Name == name) 421 if (item.Name == name)
422 {
423 m_items.LockItemsForRead(false);
397 return true; 424 return true;
425 }
398 } 426 }
427 m_items.LockItemsForRead(false);
399 return false; 428 return false;
400 } 429 }
401 430
@@ -437,7 +466,9 @@ namespace OpenSim.Region.Framework.Scenes
437 /// <param name="item"></param> 466 /// <param name="item"></param>
438 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 467 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
439 { 468 {
469 m_items.LockItemsForRead(true);
440 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values); 470 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
471 m_items.LockItemsForRead(false);
441 foreach (TaskInventoryItem i in il) 472 foreach (TaskInventoryItem i in il)
442 { 473 {
443 if (i.Name == item.Name) 474 if (i.Name == item.Name)
@@ -474,15 +505,14 @@ namespace OpenSim.Region.Framework.Scenes
474 item.ParentPartID = m_part.UUID; 505 item.ParentPartID = m_part.UUID;
475 item.Name = name; 506 item.Name = name;
476 507
477 lock (m_items) 508 m_items.LockItemsForWrite(true);
478 { 509 m_items.Add(item.ItemID, item);
479 m_items.Add(item.ItemID, item); 510 m_items.LockItemsForWrite(false);
480
481 if (allowedDrop) 511 if (allowedDrop)
482 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 512 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
483 else 513 else
484 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 514 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
485 } 515
486 516
487 m_inventorySerial++; 517 m_inventorySerial++;
488 //m_inventorySerial += 2; 518 //m_inventorySerial += 2;
@@ -499,14 +529,13 @@ namespace OpenSim.Region.Framework.Scenes
499 /// <param name="items"></param> 529 /// <param name="items"></param>
500 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 530 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
501 { 531 {
502 lock (m_items) 532 m_items.LockItemsForWrite(true);
533 foreach (TaskInventoryItem item in items)
503 { 534 {
504 foreach (TaskInventoryItem item in items) 535 m_items.Add(item.ItemID, item);
505 { 536 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
506 m_items.Add(item.ItemID, item);
507 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
508 }
509 } 537 }
538 m_items.LockItemsForWrite(false);
510 539
511 m_inventorySerial++; 540 m_inventorySerial++;
512 } 541 }
@@ -519,8 +548,9 @@ namespace OpenSim.Region.Framework.Scenes
519 public TaskInventoryItem GetInventoryItem(UUID itemId) 548 public TaskInventoryItem GetInventoryItem(UUID itemId)
520 { 549 {
521 TaskInventoryItem item; 550 TaskInventoryItem item;
551 m_items.LockItemsForRead(true);
522 m_items.TryGetValue(itemId, out item); 552 m_items.TryGetValue(itemId, out item);
523 553 m_items.LockItemsForRead(false);
524 return item; 554 return item;
525 } 555 }
526 556
@@ -532,46 +562,46 @@ namespace OpenSim.Region.Framework.Scenes
532 /// <returns>false if the item did not exist, true if the update occurred successfully</returns> 562 /// <returns>false if the item did not exist, true if the update occurred successfully</returns>
533 public bool UpdateInventoryItem(TaskInventoryItem item) 563 public bool UpdateInventoryItem(TaskInventoryItem item)
534 { 564 {
535 lock (m_items) 565 m_items.LockItemsForWrite(true);
566
567 if (m_items.ContainsKey(item.ItemID))
536 { 568 {
537 if (m_items.ContainsKey(item.ItemID)) 569 item.ParentID = m_part.UUID;
570 item.ParentPartID = m_part.UUID;
571 item.Flags = m_items[item.ItemID].Flags;
572 if (item.AssetID == UUID.Zero)
538 { 573 {
539 item.ParentID = m_part.UUID; 574 item.AssetID = m_items[item.ItemID].AssetID;
540 item.ParentPartID = m_part.UUID; 575 }
541 item.Flags = m_items[item.ItemID].Flags; 576 else if ((InventoryType)item.Type == InventoryType.Notecard)
542 if (item.AssetID == UUID.Zero) 577 {
543 { 578 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
544 item.AssetID = m_items[item.ItemID].AssetID;
545 }
546 else if ((InventoryType)item.Type == InventoryType.Notecard)
547 {
548 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
549 579
550 if (presence != null) 580 if (presence != null)
551 { 581 {
552 presence.ControllingClient.SendAgentAlertMessage( 582 presence.ControllingClient.SendAgentAlertMessage(
553 "Notecard saved", false); 583 "Notecard saved", false);
554 }
555 } 584 }
585 }
556 586
557 m_items[item.ItemID] = item; 587 m_items[item.ItemID] = item;
558 m_inventorySerial++; 588 m_inventorySerial++;
559 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 589 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
560
561 HasInventoryChanged = true;
562 m_part.ParentGroup.HasGroupChanged = true;
563 590
564 return true; 591 HasInventoryChanged = true;
565 } 592 m_part.ParentGroup.HasGroupChanged = true;
566 else 593 m_items.LockItemsForWrite(false);
567 { 594 return true;
568 m_log.ErrorFormat( 595 }
569 "[PRIM INVENTORY]: " + 596 else
570 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 597 {
571 item.ItemID, m_part.Name, m_part.UUID, 598 m_log.ErrorFormat(
572 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 599 "[PRIM INVENTORY]: " +
573 } 600 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
601 item.ItemID, m_part.Name, m_part.UUID,
602 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
574 } 603 }
604 m_items.LockItemsForWrite(false);
575 605
576 return false; 606 return false;
577 } 607 }
@@ -584,52 +614,54 @@ namespace OpenSim.Region.Framework.Scenes
584 /// in this prim's inventory.</returns> 614 /// in this prim's inventory.</returns>
585 public int RemoveInventoryItem(UUID itemID) 615 public int RemoveInventoryItem(UUID itemID)
586 { 616 {
587 lock (m_items) 617 m_items.LockItemsForRead(true);
618
619 if (m_items.ContainsKey(itemID))
588 { 620 {
589 if (m_items.ContainsKey(itemID)) 621 int type = m_items[itemID].InvType;
622 m_items.LockItemsForRead(false);
623 if (type == 10) // Script
590 { 624 {
591 int type = m_items[itemID].InvType; 625 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
592 if (type == 10) // Script 626 }
593 { 627 m_items.LockItemsForWrite(true);
594 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 628 m_items.Remove(itemID);
595 } 629 m_items.LockItemsForWrite(false);
596 m_items.Remove(itemID); 630 m_inventorySerial++;
597 m_inventorySerial++; 631 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
598 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
599
600 HasInventoryChanged = true;
601 m_part.ParentGroup.HasGroupChanged = true;
602 632
603 int scriptcount = 0; 633 HasInventoryChanged = true;
604 lock (m_items) 634 m_part.ParentGroup.HasGroupChanged = true;
605 {
606 foreach (TaskInventoryItem item in m_items.Values)
607 {
608 if (item.Type == 10)
609 {
610 scriptcount++;
611 }
612 }
613 }
614 635
615 if (scriptcount <= 0) 636 int scriptcount = 0;
637 m_items.LockItemsForRead(true);
638 foreach (TaskInventoryItem item in m_items.Values)
639 {
640 if (item.Type == 10)
616 { 641 {
617 m_part.RemFlag(PrimFlags.Scripted); 642 scriptcount++;
618 } 643 }
619
620 m_part.ScheduleFullUpdate();
621
622 return type;
623 } 644 }
624 else 645 m_items.LockItemsForRead(false);
646
647
648 if (scriptcount <= 0)
625 { 649 {
626 m_log.ErrorFormat( 650 m_part.RemFlag(PrimFlags.Scripted);
627 "[PRIM INVENTORY]: " +
628 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
629 itemID, m_part.Name, m_part.UUID,
630 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
631 } 651 }
652
653 m_part.ScheduleFullUpdate();
654
655 return type;
656 }
657 else
658 {
659 m_log.ErrorFormat(
660 "[PRIM INVENTORY]: " +
661 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
662 itemID, m_part.Name, m_part.UUID);
632 } 663 }
664 m_items.LockItemsForWrite(false);
633 665
634 return -1; 666 return -1;
635 } 667 }
@@ -682,52 +714,53 @@ namespace OpenSim.Region.Framework.Scenes
682 // isn't available (such as drag from prim inventory to agent inventory) 714 // isn't available (such as drag from prim inventory to agent inventory)
683 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 715 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
684 716
685 lock (m_items) 717 m_items.LockItemsForRead(true);
718
719 foreach (TaskInventoryItem item in m_items.Values)
686 { 720 {
687 foreach (TaskInventoryItem item in m_items.Values) 721 UUID ownerID = item.OwnerID;
688 { 722 uint everyoneMask = 0;
689 UUID ownerID = item.OwnerID; 723 uint baseMask = item.BasePermissions;
690 uint everyoneMask = 0; 724 uint ownerMask = item.CurrentPermissions;
691 uint baseMask = item.BasePermissions;
692 uint ownerMask = item.CurrentPermissions;
693 725
694 invString.AddItemStart(); 726 invString.AddItemStart();
695 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 727 invString.AddNameValueLine("item_id", item.ItemID.ToString());
696 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 728 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
697 729
698 invString.AddPermissionsStart(); 730 invString.AddPermissionsStart();
699 731
700 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 732 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
701 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 733 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
702 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); 734 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0));
703 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); 735 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
704 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); 736 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
705 737
706 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 738 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
707 invString.AddNameValueLine("owner_id", ownerID.ToString()); 739 invString.AddNameValueLine("owner_id", ownerID.ToString());
708 740
709 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 741 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
710 742
711 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 743 invString.AddNameValueLine("group_id", item.GroupID.ToString());
712 invString.AddSectionEnd(); 744 invString.AddSectionEnd();
713 745
714 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 746 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
715 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); 747 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
716 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); 748 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
717 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 749 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
718 750
719 invString.AddSaleStart(); 751 invString.AddSaleStart();
720 invString.AddNameValueLine("sale_type", "not"); 752 invString.AddNameValueLine("sale_type", "not");
721 invString.AddNameValueLine("sale_price", "0"); 753 invString.AddNameValueLine("sale_price", "0");
722 invString.AddSectionEnd(); 754 invString.AddSectionEnd();
723 755
724 invString.AddNameValueLine("name", item.Name + "|"); 756 invString.AddNameValueLine("name", item.Name + "|");
725 invString.AddNameValueLine("desc", item.Description + "|"); 757 invString.AddNameValueLine("desc", item.Description + "|");
726 758
727 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 759 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
728 invString.AddSectionEnd(); 760 invString.AddSectionEnd();
729 }
730 } 761 }
762 int count = m_items.Count;
763 m_items.LockItemsForRead(false);
731 764
732 fileData = Utils.StringToBytes(invString.BuildString); 765 fileData = Utils.StringToBytes(invString.BuildString);
733 766
@@ -748,10 +781,9 @@ namespace OpenSim.Region.Framework.Scenes
748 { 781 {
749 if (HasInventoryChanged) 782 if (HasInventoryChanged)
750 { 783 {
751 lock (Items) 784 Items.LockItemsForRead(true);
752 { 785 datastore.StorePrimInventory(m_part.UUID, Items.Values);
753 datastore.StorePrimInventory(m_part.UUID, Items.Values); 786 Items.LockItemsForRead(false);
754 }
755 787
756 HasInventoryChanged = false; 788 HasInventoryChanged = false;
757 } 789 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 289ba47..a3ad7ca 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -73,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes
73// { 73// {
74// m_log.Debug("[ScenePresence] Destructor called"); 74// m_log.Debug("[ScenePresence] Destructor called");
75// } 75// }
76 76
77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
78 78
79 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; 79 private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
@@ -89,7 +89,9 @@ namespace OpenSim.Region.Framework.Scenes
89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
90 /// issue #1716 90 /// issue #1716
91 /// </summary> 91 /// </summary>
92 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 92// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
93 // Value revised by KF 091121 by comparison with SL.
94 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
93 95
94 public UUID currentParcelUUID = UUID.Zero; 96 public UUID currentParcelUUID = UUID.Zero;
95 97
@@ -113,8 +115,11 @@ namespace OpenSim.Region.Framework.Scenes
113 public Vector3 lastKnownAllowedPosition; 115 public Vector3 lastKnownAllowedPosition;
114 public bool sentMessageAboutRestrictedParcelFlyingDown; 116 public bool sentMessageAboutRestrictedParcelFlyingDown;
115 public Vector4 CollisionPlane = Vector4.UnitW; 117 public Vector4 CollisionPlane = Vector4.UnitW;
116 118
117 private Vector3 m_lastPosition; 119 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
120 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
121 private Vector3 m_lastPosition;
122 private Vector3 m_lastWorldPosition;
118 private Quaternion m_lastRotation; 123 private Quaternion m_lastRotation;
119 private Vector3 m_lastVelocity; 124 private Vector3 m_lastVelocity;
120 //private int m_lastTerseSent; 125 //private int m_lastTerseSent;
@@ -145,7 +150,6 @@ namespace OpenSim.Region.Framework.Scenes
145 private int m_perfMonMS; 150 private int m_perfMonMS;
146 151
147 private bool m_setAlwaysRun; 152 private bool m_setAlwaysRun;
148
149 private bool m_forceFly; 153 private bool m_forceFly;
150 private bool m_flyDisabled; 154 private bool m_flyDisabled;
151 155
@@ -169,7 +173,8 @@ namespace OpenSim.Region.Framework.Scenes
169 protected RegionInfo m_regionInfo; 173 protected RegionInfo m_regionInfo;
170 protected ulong crossingFromRegion; 174 protected ulong crossingFromRegion;
171 175
172 private readonly Vector3[] Dir_Vectors = new Vector3[6]; 176 private readonly Vector3[] Dir_Vectors = new Vector3[11];
177 private bool m_isNudging = false;
173 178
174 // Position of agent's camera in world (region cordinates) 179 // Position of agent's camera in world (region cordinates)
175 protected Vector3 m_CameraCenter; 180 protected Vector3 m_CameraCenter;
@@ -194,6 +199,7 @@ namespace OpenSim.Region.Framework.Scenes
194 private bool m_autopilotMoving; 199 private bool m_autopilotMoving;
195 private Vector3 m_autoPilotTarget; 200 private Vector3 m_autoPilotTarget;
196 private bool m_sitAtAutoTarget; 201 private bool m_sitAtAutoTarget;
202 private Vector3 m_initialSitTarget; //KF: First estimate of where to sit
197 203
198 private string m_nextSitAnimation = String.Empty; 204 private string m_nextSitAnimation = String.Empty;
199 205
@@ -204,6 +210,9 @@ namespace OpenSim.Region.Framework.Scenes
204 private bool m_followCamAuto; 210 private bool m_followCamAuto;
205 211
206 private int m_movementUpdateCount; 212 private int m_movementUpdateCount;
213 private int m_lastColCount = -1; //KF: Look for Collision chnages
214 private int m_updateCount = 0; //KF: Update Anims for a while
215 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
207 216
208 private const int NumMovementsBetweenRayCast = 5; 217 private const int NumMovementsBetweenRayCast = 5;
209 218
@@ -233,6 +242,10 @@ namespace OpenSim.Region.Framework.Scenes
233 DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, 242 DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
234 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 243 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
235 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 244 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
245 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
246 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
247 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
248 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
236 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 249 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
237 } 250 }
238 251
@@ -658,10 +671,7 @@ namespace OpenSim.Region.Framework.Scenes
658 671
659 672
660 AdjustKnownSeeds(); 673 AdjustKnownSeeds();
661
662 // TODO: I think, this won't send anything, as we are still a child here...
663 Animator.TrySetMovementAnimation("STAND"); 674 Animator.TrySetMovementAnimation("STAND");
664
665 // we created a new ScenePresence (a new child agent) in a fresh region. 675 // we created a new ScenePresence (a new child agent) in a fresh region.
666 // Request info about all the (root) agents in this region 676 // Request info about all the (root) agents in this region
667 // Note: This won't send data *to* other clients in that region (children don't send) 677 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -717,21 +727,47 @@ namespace OpenSim.Region.Framework.Scenes
717 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 727 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
718 Dir_Vectors[4] = Vector3.UnitZ; //UP 728 Dir_Vectors[4] = Vector3.UnitZ; //UP
719 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 729 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
720 Dir_Vectors[5] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 730 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
731 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
732 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
733 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
734 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
721 } 735 }
722 736
723 private Vector3[] GetWalkDirectionVectors() 737 private Vector3[] GetWalkDirectionVectors()
724 { 738 {
725 Vector3[] vector = new Vector3[6]; 739 Vector3[] vector = new Vector3[11];
726 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 740 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
727 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 741 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
728 vector[2] = Vector3.UnitY; //LEFT 742 vector[2] = Vector3.UnitY; //LEFT
729 vector[3] = -Vector3.UnitY; //RIGHT 743 vector[3] = -Vector3.UnitY; //RIGHT
730 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 744 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
731 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 745 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
732 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 746 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
747 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
748 vector[8] = Vector3.UnitY; //LEFT_NUDGE
749 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
750 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
733 return vector; 751 return vector;
734 } 752 }
753
754 private bool[] GetDirectionIsNudge()
755 {
756 bool[] isNudge = new bool[11];
757 isNudge[0] = false; //FORWARD
758 isNudge[1] = false; //BACK
759 isNudge[2] = false; //LEFT
760 isNudge[3] = false; //RIGHT
761 isNudge[4] = false; //UP
762 isNudge[5] = false; //DOWN
763 isNudge[6] = true; //FORWARD_NUDGE
764 isNudge[7] = true; //BACK_NUDGE
765 isNudge[8] = true; //LEFT_NUDGE
766 isNudge[9] = true; //RIGHT_NUDGE
767 isNudge[10] = true; //DOWN_Nudge
768 return isNudge;
769 }
770
735 771
736 #endregion 772 #endregion
737 773
@@ -995,7 +1031,9 @@ namespace OpenSim.Region.Framework.Scenes
995 { 1031 {
996 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1032 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
997 } 1033 }
998 1034
1035 m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim.
1036
999 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1037 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
1000 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); 1038 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
1001 } 1039 }
@@ -1230,7 +1268,6 @@ namespace OpenSim.Region.Framework.Scenes
1230 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1268 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1231 } 1269 }
1232 } 1270 }
1233
1234 lock (scriptedcontrols) 1271 lock (scriptedcontrols)
1235 { 1272 {
1236 if (scriptedcontrols.Count > 0) 1273 if (scriptedcontrols.Count > 0)
@@ -1245,9 +1282,7 @@ namespace OpenSim.Region.Framework.Scenes
1245 1282
1246 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1283 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1247 { 1284 {
1248 // TODO: This doesn't prevent the user from walking yet. 1285 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1249 // Setting parent ID would fix this, if we knew what value
1250 // to use. Or we could add a m_isSitting variable.
1251 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 1286 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1252 } 1287 }
1253 1288
@@ -1292,6 +1327,11 @@ namespace OpenSim.Region.Framework.Scenes
1292 update_rotation = true; 1327 update_rotation = true;
1293 } 1328 }
1294 1329
1330 //guilty until proven innocent..
1331 bool Nudging = true;
1332 //Basically, if there is at least one non-nudge control then we don't need
1333 //to worry about stopping the avatar
1334
1295 if (m_parentID == 0) 1335 if (m_parentID == 0)
1296 { 1336 {
1297 bool bAllowUpdateMoveToPosition = false; 1337 bool bAllowUpdateMoveToPosition = false;
@@ -1306,6 +1346,12 @@ namespace OpenSim.Region.Framework.Scenes
1306 else 1346 else
1307 dirVectors = Dir_Vectors; 1347 dirVectors = Dir_Vectors;
1308 1348
1349 bool[] isNudge = GetDirectionIsNudge();
1350
1351
1352
1353
1354
1309 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1355 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1310 { 1356 {
1311 if (((uint)flags & (uint)DCF) != 0) 1357 if (((uint)flags & (uint)DCF) != 0)
@@ -1315,6 +1361,10 @@ namespace OpenSim.Region.Framework.Scenes
1315 try 1361 try
1316 { 1362 {
1317 agent_control_v3 += dirVectors[i]; 1363 agent_control_v3 += dirVectors[i];
1364 if (isNudge[i] == false)
1365 {
1366 Nudging = false;
1367 }
1318 } 1368 }
1319 catch (IndexOutOfRangeException) 1369 catch (IndexOutOfRangeException)
1320 { 1370 {
@@ -1376,6 +1426,9 @@ namespace OpenSim.Region.Framework.Scenes
1376 // Ignore z component of vector 1426 // Ignore z component of vector
1377 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1427 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1378 LocalVectorToTarget2D.Normalize(); 1428 LocalVectorToTarget2D.Normalize();
1429
1430 //We're not nudging
1431 Nudging = false;
1379 agent_control_v3 += LocalVectorToTarget2D; 1432 agent_control_v3 += LocalVectorToTarget2D;
1380 1433
1381 // update avatar movement flags. the avatar coordinate system is as follows: 1434 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1464,7 +1517,7 @@ namespace OpenSim.Region.Framework.Scenes
1464 // m_log.DebugFormat( 1517 // m_log.DebugFormat(
1465 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1518 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1466 1519
1467 AddNewMovement(agent_control_v3, q); 1520 AddNewMovement(agent_control_v3, q, Nudging);
1468 1521
1469 1522
1470 } 1523 }
@@ -1485,7 +1538,6 @@ namespace OpenSim.Region.Framework.Scenes
1485 m_sitAtAutoTarget = false; 1538 m_sitAtAutoTarget = false;
1486 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1539 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1487 //proxy.PCode = (byte)PCode.ParticleSystem; 1540 //proxy.PCode = (byte)PCode.ParticleSystem;
1488
1489 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1541 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1490 proxyObjectGroup.AttachToScene(m_scene); 1542 proxyObjectGroup.AttachToScene(m_scene);
1491 1543
@@ -1527,7 +1579,7 @@ namespace OpenSim.Region.Framework.Scenes
1527 } 1579 }
1528 m_moveToPositionInProgress = true; 1580 m_moveToPositionInProgress = true;
1529 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1581 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1530 } 1582 }
1531 catch (Exception ex) 1583 catch (Exception ex)
1532 { 1584 {
1533 //Why did I get this error? 1585 //Why did I get this error?
@@ -1549,7 +1601,7 @@ namespace OpenSim.Region.Framework.Scenes
1549 Velocity = Vector3.Zero; 1601 Velocity = Vector3.Zero;
1550 SendFullUpdateToAllClients(); 1602 SendFullUpdateToAllClients();
1551 1603
1552 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1604 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1553 } 1605 }
1554 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1606 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1555 m_requestedSitTargetUUID = UUID.Zero; 1607 m_requestedSitTargetUUID = UUID.Zero;
@@ -1587,46 +1639,79 @@ namespace OpenSim.Region.Framework.Scenes
1587 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 1639 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1588 if (part != null) 1640 if (part != null)
1589 { 1641 {
1642 part.TaskInventory.LockItemsForRead(true);
1590 TaskInventoryDictionary taskIDict = part.TaskInventory; 1643 TaskInventoryDictionary taskIDict = part.TaskInventory;
1591 if (taskIDict != null) 1644 if (taskIDict != null)
1592 { 1645 {
1593 lock (taskIDict) 1646 foreach (UUID taskID in taskIDict.Keys)
1594 { 1647 {
1595 foreach (UUID taskID in taskIDict.Keys) 1648 UnRegisterControlEventsToScript(LocalId, taskID);
1596 { 1649 taskIDict[taskID].PermsMask &= ~(
1597 UnRegisterControlEventsToScript(LocalId, taskID); 1650 2048 | //PERMISSION_CONTROL_CAMERA
1598 taskIDict[taskID].PermsMask &= ~( 1651 4); // PERMISSION_TAKE_CONTROLS
1599 2048 | //PERMISSION_CONTROL_CAMERA
1600 4); // PERMISSION_TAKE_CONTROLS
1601 }
1602 } 1652 }
1603
1604 } 1653 }
1654 part.TaskInventory.LockItemsForRead(false);
1605 // Reset sit target. 1655 // Reset sit target.
1606 if (part.GetAvatarOnSitTarget() == UUID) 1656 if (part.GetAvatarOnSitTarget() == UUID)
1607 part.SetAvatarOnSitTarget(UUID.Zero); 1657 part.SetAvatarOnSitTarget(UUID.Zero);
1608
1609 m_parentPosition = part.GetWorldPosition(); 1658 m_parentPosition = part.GetWorldPosition();
1610 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1659 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1611 } 1660 }
1612 1661 // part.GetWorldRotation() is the rotation of the object being sat on
1613 if (m_physicsActor == null) 1662 // Rotation is the sittiing Av's rotation
1614 { 1663
1615 AddToPhysicalScene(false); 1664 Quaternion partRot;
1665// if (part.LinkNum == 1)
1666// { // Root prim of linkset
1667// partRot = part.ParentGroup.RootPart.RotationOffset;
1668// }
1669// else
1670// { // single or child prim
1671
1672// }
1673 if (part == null) //CW: Part may be gone. llDie() for example.
1674 {
1675 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1676 }
1677 else
1678 {
1679 partRot = part.GetWorldRotation();
1680 }
1681
1682 Quaternion partIRot = Quaternion.Inverse(partRot);
1683
1684 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1685 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1686
1687
1688 if (m_physicsActor == null)
1689 {
1690 AddToPhysicalScene(false);
1691 }
1692 //CW: If the part isn't null then we can set the current position
1693 if (part != null)
1694 {
1695 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
1696 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1697 part.IsOccupied = false;
1698 }
1699 else
1700 {
1701 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1702 AbsolutePosition = m_lastWorldPosition;
1616 } 1703 }
1617 1704
1618 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1705 m_parentPosition = Vector3.Zero;
1619 m_parentPosition = Vector3.Zero; 1706 m_parentID = 0;
1620
1621 m_parentID = 0;
1622 SendFullUpdateToAllClients(); 1707 SendFullUpdateToAllClients();
1623 m_requestedSitTargetID = 0; 1708 m_requestedSitTargetID = 0;
1709
1624 if ((m_physicsActor != null) && (m_avHeight > 0)) 1710 if ((m_physicsActor != null) && (m_avHeight > 0))
1625 { 1711 {
1626 SetHeight(m_avHeight); 1712 SetHeight(m_avHeight);
1627 } 1713 }
1628 } 1714 }
1629
1630 Animator.TrySetMovementAnimation("STAND"); 1715 Animator.TrySetMovementAnimation("STAND");
1631 } 1716 }
1632 1717
@@ -1657,13 +1742,9 @@ namespace OpenSim.Region.Framework.Scenes
1657 Vector3 avSitOffSet = part.SitTargetPosition; 1742 Vector3 avSitOffSet = part.SitTargetPosition;
1658 Quaternion avSitOrientation = part.SitTargetOrientation; 1743 Quaternion avSitOrientation = part.SitTargetOrientation;
1659 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1744 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1660 1745 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1661 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1746 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1662 bool SitTargetisSet = 1747 if (SitTargetisSet && !SitTargetOccupied)
1663 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1664 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1665
1666 if (SitTargetisSet && SitTargetUnOccupied)
1667 { 1748 {
1668 //switch the target to this prim 1749 //switch the target to this prim
1669 return part; 1750 return part;
@@ -1677,84 +1758,152 @@ namespace OpenSim.Region.Framework.Scenes
1677 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1758 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1678 { 1759 {
1679 bool autopilot = true; 1760 bool autopilot = true;
1761 Vector3 autopilotTarget = new Vector3();
1762 Quaternion sitOrientation = Quaternion.Identity;
1680 Vector3 pos = new Vector3(); 1763 Vector3 pos = new Vector3();
1681 Quaternion sitOrientation = pSitOrientation;
1682 Vector3 cameraEyeOffset = Vector3.Zero; 1764 Vector3 cameraEyeOffset = Vector3.Zero;
1683 Vector3 cameraAtOffset = Vector3.Zero; 1765 Vector3 cameraAtOffset = Vector3.Zero;
1684 bool forceMouselook = false; 1766 bool forceMouselook = false;
1685 1767
1686 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1768 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1687 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1769 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1688 if (part != null) 1770 if (part == null) return;
1689 { 1771
1690 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1772 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1691 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1773 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1692 1774
1693 // Is a sit target available? 1775 // part is the prim to sit on
1694 Vector3 avSitOffSet = part.SitTargetPosition; 1776 // offset is the world-ref vector distance from that prim center to the click-spot
1695 Quaternion avSitOrientation = part.SitTargetOrientation; 1777 // UUID is the UUID of the Avatar doing the clicking
1696 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1778
1697 1779 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1698 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1780
1699 bool SitTargetisSet = 1781 // Is a sit target available?
1700 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1782 Vector3 avSitOffSet = part.SitTargetPosition;
1701 ( 1783 Quaternion avSitOrientation = part.SitTargetOrientation;
1702 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1784
1703 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1785 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1704 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1786 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1705 ) 1787 Quaternion partRot;
1706 )); 1788// if (part.LinkNum == 1)
1707 1789// { // Root prim of linkset
1708 if (SitTargetisSet && SitTargetUnOccupied) 1790// partRot = part.ParentGroup.RootPart.RotationOffset;
1709 { 1791// }
1710 part.SetAvatarOnSitTarget(UUID); 1792// else
1711 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1793// { // single or child prim
1712 sitOrientation = avSitOrientation; 1794 partRot = part.GetWorldRotation();
1713 autopilot = false; 1795// }
1714 } 1796 Quaternion partIRot = Quaternion.Inverse(partRot);
1715 1797//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1716 pos = part.AbsolutePosition + offset; 1798 // Sit analysis rewritten by KF 091125
1717 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1799 if (SitTargetisSet) // scipted sit
1718 //{ 1800 {
1719 // offset = pos; 1801 if (!part.IsOccupied)
1720 //autopilot = false; 1802 {
1721 //} 1803//Console.WriteLine("Scripted, unoccupied");
1722 if (m_physicsActor != null) 1804 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1723 { 1805 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1724 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1806 sitOrientation = avSitOrientation; // Change rotatione to the scripted one
1725 // We can remove the physicsActor until they stand up. 1807 autopilot = false; // Jump direct to scripted llSitPos()
1726 m_sitAvatarHeight = m_physicsActor.Size.Z; 1808 }
1727 1809 else
1728 if (autopilot) 1810 {
1729 { 1811//Console.WriteLine("Scripted, occupied");
1730 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1812 return;
1731 { 1813 }
1732 autopilot = false; 1814 }
1815 else // Not Scripted
1816 {
1817 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
1818 {
1819 // large prim & offset, ignore if other Avs sitting
1820// offset.Z -= 0.05f;
1821 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
1822 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
1823
1824//Console.WriteLine(" offset ={0}", offset);
1825//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
1826//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
1827
1828 }
1829 else // small offset
1830 {
1831//Console.WriteLine("Small offset");
1832 if (!part.IsOccupied)
1833 {
1834 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
1835 autopilotTarget = part.AbsolutePosition;
1836 }
1837 else return; // occupied small
1838 } // end large/small
1839 } // end Scripted/not
1840 cameraAtOffset = part.GetCameraAtOffset();
1841 cameraEyeOffset = part.GetCameraEyeOffset();
1842 forceMouselook = part.GetForceMouselook();
1843 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
1844 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
1733 1845
1734 RemoveFromPhysicalScene(); 1846 if (m_physicsActor != null)
1735 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1847 {
1736 } 1848 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1737 } 1849 // We can remove the physicsActor until they stand up.
1738 else 1850 m_sitAvatarHeight = m_physicsActor.Size.Z;
1851 if (autopilot)
1852 { // its not a scripted sit
1853// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
1854 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
1739 { 1855 {
1856 autopilot = false; // close enough
1857 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1858 Not using the part's position because returning the AV to the last known standing
1859 position is likely to be more friendly, isn't it? */
1740 RemoveFromPhysicalScene(); 1860 RemoveFromPhysicalScene();
1741 } 1861 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
1862 } // else the autopilot will get us close
1863 }
1864 else
1865 { // its a scripted sit
1866 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
1867 I *am* using the part's position this time because we have no real idea how far away
1868 the avatar is from the sit target. */
1869 RemoveFromPhysicalScene();
1742 } 1870 }
1743
1744 cameraAtOffset = part.GetCameraAtOffset();
1745 cameraEyeOffset = part.GetCameraEyeOffset();
1746 forceMouselook = part.GetForceMouselook();
1747 } 1871 }
1748 1872 else return; // physactor is null!
1749 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 1873
1750 m_requestedSitTargetUUID = targetID; 1874 Vector3 offsetr; // = offset * partIRot;
1875 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
1876 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
1877 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
1878 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
1879 offsetr = offset * partIRot;
1880//
1881 // else
1882 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
1883 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
1884 // (offset * partRot);
1885 // }
1886
1887//Console.WriteLine(" ");
1888//Console.WriteLine("link number ={0}", part.LinkNum);
1889//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
1890//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
1891//Console.WriteLine("Click offst ={0}", offset);
1892//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
1893//Console.WriteLine("offsetr ={0}", offsetr);
1894//Console.WriteLine("Camera At ={0}", cameraAtOffset);
1895//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
1896
1897 ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
1898 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1751 // This calls HandleAgentSit twice, once from here, and the client calls 1899 // This calls HandleAgentSit twice, once from here, and the client calls
1752 // HandleAgentSit itself after it gets to the location 1900 // HandleAgentSit itself after it gets to the location
1753 // It doesn't get to the location until we've moved them there though 1901 // It doesn't get to the location until we've moved them there though
1754 // which happens in HandleAgentSit :P 1902 // which happens in HandleAgentSit :P
1755 m_autopilotMoving = autopilot; 1903 m_autopilotMoving = autopilot;
1756 m_autoPilotTarget = pos; 1904 m_autoPilotTarget = autopilotTarget;
1757 m_sitAtAutoTarget = autopilot; 1905 m_sitAtAutoTarget = autopilot;
1906 m_initialSitTarget = autopilotTarget;
1758 if (!autopilot) 1907 if (!autopilot)
1759 HandleAgentSit(remoteClient, UUID); 1908 HandleAgentSit(remoteClient, UUID);
1760 } 1909 }
@@ -2049,31 +2198,65 @@ namespace OpenSim.Region.Framework.Scenes
2049 { 2198 {
2050 if (part != null) 2199 if (part != null)
2051 { 2200 {
2201//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2052 if (part.GetAvatarOnSitTarget() == UUID) 2202 if (part.GetAvatarOnSitTarget() == UUID)
2053 { 2203 {
2204//Console.WriteLine("Scripted Sit");
2205 // Scripted sit
2054 Vector3 sitTargetPos = part.SitTargetPosition; 2206 Vector3 sitTargetPos = part.SitTargetPosition;
2055 Quaternion sitTargetOrient = part.SitTargetOrientation; 2207 Quaternion sitTargetOrient = part.SitTargetOrientation;
2056
2057 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2058 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2059
2060 //Quaternion result = (sitTargetOrient * vq) * nq;
2061
2062 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2208 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2063 m_pos += SIT_TARGET_ADJUSTMENT; 2209 m_pos += SIT_TARGET_ADJUSTMENT;
2064 m_bodyRot = sitTargetOrient; 2210 m_bodyRot = sitTargetOrient;
2065 //Rotation = sitTargetOrient;
2066 m_parentPosition = part.AbsolutePosition; 2211 m_parentPosition = part.AbsolutePosition;
2067 2212 part.IsOccupied = true;
2068 //SendTerseUpdateToAllClients();
2069 } 2213 }
2070 else 2214 else
2071 { 2215 {
2072 m_pos -= part.AbsolutePosition; 2216 // if m_avUnscriptedSitPos is zero then Av sits above center
2217 // Else Av sits at m_avUnscriptedSitPos
2218
2219 // Non-scripted sit by Kitto Flora 21Nov09
2220 // Calculate angle of line from prim to Av
2221 Quaternion partIRot;
2222// if (part.LinkNum == 1)
2223// { // Root prim of linkset
2224// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2225// }
2226// else
2227// { // single or child prim
2228 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2229// }
2230 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2231 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2232 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2233 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2234 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2235 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2236 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2237 // Av sits at world euler <0,0, z>, translated by part rotation
2238 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2239
2073 m_parentPosition = part.AbsolutePosition; 2240 m_parentPosition = part.AbsolutePosition;
2074 } 2241 part.IsOccupied = true;
2075 } 2242 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2076 else 2243 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2244 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2245 m_avUnscriptedSitPos; // adds click offset, if any
2246 //Set up raytrace to find top surface of prim
2247 Vector3 size = part.Scale;
2248 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2249 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2250 Vector3 down = new Vector3(0f, 0f, -1f);
2251//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2252 m_scene.PhysicsScene.RaycastWorld(
2253 start, // Vector3 position,
2254 down, // Vector3 direction,
2255 mag, // float length,
2256 SitAltitudeCallback); // retMethod
2257 } // end scripted/not
2258 }
2259 else // no Av
2077 { 2260 {
2078 return; 2261 return;
2079 } 2262 }
@@ -2085,11 +2268,36 @@ namespace OpenSim.Region.Framework.Scenes
2085 2268
2086 Animator.TrySetMovementAnimation(sitAnimation); 2269 Animator.TrySetMovementAnimation(sitAnimation);
2087 SendFullUpdateToAllClients(); 2270 SendFullUpdateToAllClients();
2088 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2089 // So we're also sending a terse update (which has avatar rotation)
2090 // [Update] We do now.
2091 //SendTerseUpdateToAllClients();
2092 } 2271 }
2272
2273 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2274 {
2275 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2276 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2277 if(hitYN)
2278 {
2279 // m_pos = Av offset from prim center to make look like on center
2280 // m_parentPosition = Actual center pos of prim
2281 // collisionPoint = spot on prim where we want to sit
2282 // collisionPoint.Z = global sit surface height
2283 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2284 Quaternion partIRot;
2285// if (part.LinkNum == 1)
2286/// { // Root prim of linkset
2287// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2288// }
2289// else
2290// { // single or child prim
2291 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2292// }
2293 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2294 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2295//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2296 m_pos += offset;
2297// ControllingClient.SendClearFollowCamProperties(part.UUID);
2298
2299 }
2300 } // End SitAltitudeCallback KF.
2093 2301
2094 /// <summary> 2302 /// <summary>
2095 /// Event handler for the 'Always run' setting on the client 2303 /// Event handler for the 'Always run' setting on the client
@@ -2119,7 +2327,7 @@ namespace OpenSim.Region.Framework.Scenes
2119 /// </summary> 2327 /// </summary>
2120 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2328 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2121 /// <param name="rotation">The direction in which this avatar should now face. 2329 /// <param name="rotation">The direction in which this avatar should now face.
2122 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2330 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2123 { 2331 {
2124 if (m_isChildAgent) 2332 if (m_isChildAgent)
2125 { 2333 {
@@ -2193,7 +2401,7 @@ namespace OpenSim.Region.Framework.Scenes
2193 2401
2194 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2402 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2195 m_forceToApply = direc; 2403 m_forceToApply = direc;
2196 2404 m_isNudging = Nudging;
2197 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2405 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2198 } 2406 }
2199 2407
@@ -2208,7 +2416,7 @@ namespace OpenSim.Region.Framework.Scenes
2208 const float POSITION_TOLERANCE = 0.05f; 2416 const float POSITION_TOLERANCE = 0.05f;
2209 //const int TIME_MS_TOLERANCE = 3000; 2417 //const int TIME_MS_TOLERANCE = 3000;
2210 2418
2211 SendPrimUpdates(); 2419
2212 2420
2213 if (m_newCoarseLocations) 2421 if (m_newCoarseLocations)
2214 { 2422 {
@@ -2244,6 +2452,9 @@ namespace OpenSim.Region.Framework.Scenes
2244 CheckForBorderCrossing(); 2452 CheckForBorderCrossing();
2245 CheckForSignificantMovement(); // sends update to the modules. 2453 CheckForSignificantMovement(); // sends update to the modules.
2246 } 2454 }
2455
2456 //Sending prim updates AFTER the avatar terse updates are sent
2457 SendPrimUpdates();
2247 } 2458 }
2248 2459
2249 #endregion 2460 #endregion
@@ -3097,14 +3308,25 @@ namespace OpenSim.Region.Framework.Scenes
3097 { 3308 {
3098 if (m_forceToApply.HasValue) 3309 if (m_forceToApply.HasValue)
3099 { 3310 {
3100 Vector3 force = m_forceToApply.Value;
3101 3311
3312 Vector3 force = m_forceToApply.Value;
3102 m_updateflag = true; 3313 m_updateflag = true;
3103// movementvector = force;
3104 Velocity = force; 3314 Velocity = force;
3105 3315
3106 m_forceToApply = null; 3316 m_forceToApply = null;
3107 } 3317 }
3318 else
3319 {
3320 if (m_isNudging)
3321 {
3322 Vector3 force = Vector3.Zero;
3323
3324 m_updateflag = true;
3325 Velocity = force;
3326 m_isNudging = false;
3327 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3328 }
3329 }
3108 } 3330 }
3109 3331
3110 public override void SetText(string text, Vector3 color, double alpha) 3332 public override void SetText(string text, Vector3 color, double alpha)
@@ -3156,18 +3378,29 @@ namespace OpenSim.Region.Framework.Scenes
3156 { 3378 {
3157 if (e == null) 3379 if (e == null)
3158 return; 3380 return;
3159 3381
3160 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3382 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3161 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3162 // as of this comment the interval is set in AddToPhysicalScene 3383 // as of this comment the interval is set in AddToPhysicalScene
3163 if (Animator!=null) 3384 if (Animator!=null)
3164 Animator.UpdateMovementAnimations(); 3385 {
3386 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3387 { // else its will lock out other animation changes, like ground sit.
3388 Animator.UpdateMovementAnimations();
3389 m_updateCount--;
3390 }
3391 }
3165 3392
3166 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3393 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3167 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3394 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3168 3395
3169 CollisionPlane = Vector4.UnitW; 3396 CollisionPlane = Vector4.UnitW;
3170 3397
3398 if (m_lastColCount != coldata.Count)
3399 {
3400 m_updateCount = UPDATE_COUNT;
3401 m_lastColCount = coldata.Count;
3402 }
3403
3171 if (coldata.Count != 0 && Animator != null) 3404 if (coldata.Count != 0 && Animator != null)
3172 { 3405 {
3173 switch (Animator.CurrentMovementAnimation) 3406 switch (Animator.CurrentMovementAnimation)
@@ -3815,5 +4048,16 @@ namespace OpenSim.Region.Framework.Scenes
3815 m_reprioritization_called = false; 4048 m_reprioritization_called = false;
3816 } 4049 }
3817 } 4050 }
4051
4052 private Vector3 Quat2Euler(Quaternion rot){
4053 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4054 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4055 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4056 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4057 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4058 return(new Vector3(x,y,z));
4059 }
4060
4061
3818 } 4062 }
3819} \ No newline at end of file 4063}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
index 8a27b7b..5abbb82 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -101,7 +101,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests
101 { 101 {
102 throw new NotImplementedException(); 102 throw new NotImplementedException();
103 } 103 }
104 104 public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID)
105 {
106 //This connector doesn't support the windlight module yet
107 //Return default LL windlight settings
108 return new RegionMeta7WindlightData();
109 }
110 public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl)
111 {
112 //This connector doesn't support the windlight module yet
113 }
105 public RegionSettings LoadRegionSettings(UUID regionUUID) 114 public RegionSettings LoadRegionSettings(UUID regionUUID)
106 { 115 {
107 return null; 116 return null;