aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs2
-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.cs12
-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.cs557
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs98
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs380
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs471
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs11
11 files changed, 1135 insertions, 545 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs b/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs
index 78bd622..7312799 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs
@@ -103,6 +103,8 @@ namespace OpenSim.Region.Framework.Interfaces
103 103
104 void StoreRegionSettings(RegionSettings rs); 104 void StoreRegionSettings(RegionSettings rs);
105 RegionSettings LoadRegionSettings(UUID regionUUID); 105 RegionSettings LoadRegionSettings(UUID regionUUID);
106 RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID);
107 void StoreRegionWindlightSettings(RegionMeta7WindlightData wl);
106 108
107 void Shutdown(); 109 void Shutdown();
108 } 110 }
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..a86e263 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -193,7 +193,9 @@ 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();
196 public event OnMakeRootAgentDelegate OnMakeRootAgent; 197 public event OnMakeRootAgentDelegate OnMakeRootAgent;
198 public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile;
197 199
198 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); 200 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel);
199 201
@@ -411,6 +413,7 @@ namespace OpenSim.Region.Framework.Scenes
411 private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage; 413 private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage;
412 private ClientClosed handlerClientClosed = null; //OnClientClosed; 414 private ClientClosed handlerClientClosed = null; //OnClientClosed;
413 private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent; 415 private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent;
416 private OnSaveNewWindlightProfileDelegate handlerSaveNewWindlightProfile = null; //OnSaveNewWindlightProfile;
414 private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent; 417 private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent;
415 private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick; 418 private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick;
416 private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps; 419 private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps;
@@ -772,6 +775,15 @@ namespace OpenSim.Region.Framework.Scenes
772 } 775 }
773 } 776 }
774 777
778 public void TriggerOnSaveNewWindlightProfile()
779 {
780 handlerSaveNewWindlightProfile = OnSaveNewWindlightProfile;
781 if (handlerSaveNewWindlightProfile != null)
782 {
783 handlerSaveNewWindlightProfile();
784 }
785 }
786
775 public void TriggerOnMakeRootAgent(ScenePresence presence) 787 public void TriggerOnMakeRootAgent(ScenePresence presence)
776 { 788 {
777 handlerMakeRootAgent = OnMakeRootAgent; 789 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 eb284c1..104d22b 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();
@@ -1506,6 +1520,19 @@ namespace OpenSim.Region.Framework.Scenes
1506 { 1520 {
1507 m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 1521 m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID);
1508 } 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();
1535 }
1509 1536
1510 /// <summary> 1537 /// <summary>
1511 /// Loads the World heightmap 1538 /// Loads the World heightmap
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index cb87212..eacd219 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 {
@@ -1735,6 +1854,45 @@ namespace OpenSim.Region.Framework.Scenes
1735 } 1854 }
1736 } 1855 }
1737 1856
1857 public void rotLookAt(Quaternion target, float strength, float damping)
1858 {
1859 SceneObjectPart rootpart = m_rootPart;
1860 if (rootpart != null)
1861 {
1862 if (IsAttachment)
1863 {
1864 /*
1865 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1866 if (avatar != null)
1867 {
1868 Rotate the Av?
1869 } */
1870 }
1871 else
1872 {
1873 if (rootpart.PhysActor != null)
1874 {
1875 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1876 rootpart.PhysActor.APIDStrength = strength;
1877 rootpart.PhysActor.APIDDamping = damping;
1878 rootpart.PhysActor.APIDActive = true;
1879 }
1880 }
1881 }
1882 }
1883 public void stopLookAt()
1884 {
1885 SceneObjectPart rootpart = m_rootPart;
1886 if (rootpart != null)
1887 {
1888 if (rootpart.PhysActor != null)
1889 {
1890 rootpart.PhysActor.APIDActive = false;
1891 }
1892 }
1893
1894 }
1895
1738 /// <summary> 1896 /// <summary>
1739 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 1897 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1740 /// </summary> 1898 /// </summary>
@@ -1796,10 +1954,11 @@ namespace OpenSim.Region.Framework.Scenes
1796 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 1954 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1797 newPart.SetParent(this); 1955 newPart.SetParent(this);
1798 1956
1799 lock (m_parts) 1957 lockPartsForWrite(true);
1800 { 1958 {
1801 m_parts.Add(newPart.UUID, newPart); 1959 m_parts.Add(newPart.UUID, newPart);
1802 } 1960 }
1961 lockPartsForWrite(false);
1803 1962
1804 SetPartAsNonRoot(newPart); 1963 SetPartAsNonRoot(newPart);
1805 1964
@@ -1862,7 +2021,7 @@ namespace OpenSim.Region.Framework.Scenes
1862 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 2021 //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1863 // return; 2022 // return;
1864 2023
1865 lock (m_parts) 2024 lockPartsForRead(true);
1866 { 2025 {
1867 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2026 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
1868 2027
@@ -1880,34 +2039,43 @@ namespace OpenSim.Region.Framework.Scenes
1880 2039
1881 foreach (SceneObjectPart part in m_parts.Values) 2040 foreach (SceneObjectPart part in m_parts.Values)
1882 { 2041 {
2042
1883 part.SendScheduledUpdates(); 2043 part.SendScheduledUpdates();
2044
1884 } 2045 }
1885 } 2046 }
2047 lockPartsForRead(false);
1886 } 2048 }
1887 2049
1888 public void ScheduleFullUpdateToAvatar(ScenePresence presence) 2050 public void ScheduleFullUpdateToAvatar(ScenePresence presence)
1889 { 2051 {
1890 RootPart.AddFullUpdateToAvatar(presence); 2052 RootPart.AddFullUpdateToAvatar(presence);
1891 2053
1892 lock (m_parts) 2054 lockPartsForRead(true);
1893 { 2055 {
1894 foreach (SceneObjectPart part in m_parts.Values) 2056 foreach (SceneObjectPart part in m_parts.Values)
1895 { 2057 {
2058
1896 if (part != RootPart) 2059 if (part != RootPart)
1897 part.AddFullUpdateToAvatar(presence); 2060 part.AddFullUpdateToAvatar(presence);
2061
1898 } 2062 }
1899 } 2063 }
2064 lockPartsForRead(false);
1900 } 2065 }
1901 2066
1902 public void ScheduleTerseUpdateToAvatar(ScenePresence presence) 2067 public void ScheduleTerseUpdateToAvatar(ScenePresence presence)
1903 { 2068 {
1904 lock (m_parts) 2069 lockPartsForRead(true);
1905 { 2070 {
1906 foreach (SceneObjectPart part in m_parts.Values) 2071 foreach (SceneObjectPart part in m_parts.Values)
1907 { 2072 {
2073
1908 part.AddTerseUpdateToAvatar(presence); 2074 part.AddTerseUpdateToAvatar(presence);
2075
1909 } 2076 }
1910 } 2077 }
2078 lockPartsForRead(false);
1911 } 2079 }
1912 2080
1913 /// <summary> 2081 /// <summary>
@@ -1918,14 +2086,17 @@ namespace OpenSim.Region.Framework.Scenes
1918 checkAtTargets(); 2086 checkAtTargets();
1919 RootPart.ScheduleFullUpdate(); 2087 RootPart.ScheduleFullUpdate();
1920 2088
1921 lock (m_parts) 2089 lockPartsForRead(true);
1922 { 2090 {
1923 foreach (SceneObjectPart part in m_parts.Values) 2091 foreach (SceneObjectPart part in m_parts.Values)
1924 { 2092 {
2093
1925 if (part != RootPart) 2094 if (part != RootPart)
1926 part.ScheduleFullUpdate(); 2095 part.ScheduleFullUpdate();
2096
1927 } 2097 }
1928 } 2098 }
2099 lockPartsForRead(false);
1929 } 2100 }
1930 2101
1931 /// <summary> 2102 /// <summary>
@@ -1933,13 +2104,16 @@ namespace OpenSim.Region.Framework.Scenes
1933 /// </summary> 2104 /// </summary>
1934 public void ScheduleGroupForTerseUpdate() 2105 public void ScheduleGroupForTerseUpdate()
1935 { 2106 {
1936 lock (m_parts) 2107 lockPartsForRead(true);
1937 { 2108 {
1938 foreach (SceneObjectPart part in m_parts.Values) 2109 foreach (SceneObjectPart part in m_parts.Values)
1939 { 2110 {
2111
1940 part.ScheduleTerseUpdate(); 2112 part.ScheduleTerseUpdate();
2113
1941 } 2114 }
1942 } 2115 }
2116 lockPartsForRead(false);
1943 } 2117 }
1944 2118
1945 /// <summary> 2119 /// <summary>
@@ -1952,14 +2126,17 @@ namespace OpenSim.Region.Framework.Scenes
1952 2126
1953 RootPart.SendFullUpdateToAllClients(); 2127 RootPart.SendFullUpdateToAllClients();
1954 2128
1955 lock (m_parts) 2129 lockPartsForRead(true);
1956 { 2130 {
1957 foreach (SceneObjectPart part in m_parts.Values) 2131 foreach (SceneObjectPart part in m_parts.Values)
1958 { 2132 {
2133
1959 if (part != RootPart) 2134 if (part != RootPart)
1960 part.SendFullUpdateToAllClients(); 2135 part.SendFullUpdateToAllClients();
2136
1961 } 2137 }
1962 } 2138 }
2139 lockPartsForRead(false);
1963 } 2140 }
1964 2141
1965 /// <summary> 2142 /// <summary>
@@ -1990,14 +2167,15 @@ namespace OpenSim.Region.Framework.Scenes
1990 { 2167 {
1991 if (IsDeleted) 2168 if (IsDeleted)
1992 return; 2169 return;
1993 2170
1994 lock (m_parts) 2171 lockPartsForRead(true);
1995 { 2172 {
1996 foreach (SceneObjectPart part in m_parts.Values) 2173 foreach (SceneObjectPart part in m_parts.Values)
1997 { 2174 {
1998 part.SendTerseUpdateToAllClients(); 2175 part.SendTerseUpdateToAllClients();
1999 } 2176 }
2000 } 2177 }
2178 lockPartsForRead(false);
2001 } 2179 }
2002 2180
2003 #endregion 2181 #endregion
@@ -2011,16 +2189,18 @@ namespace OpenSim.Region.Framework.Scenes
2011 /// <returns>null if no child part with that linknum or child part</returns> 2189 /// <returns>null if no child part with that linknum or child part</returns>
2012 public SceneObjectPart GetLinkNumPart(int linknum) 2190 public SceneObjectPart GetLinkNumPart(int linknum)
2013 { 2191 {
2014 lock (m_parts) 2192 lockPartsForRead(true);
2015 { 2193 {
2016 foreach (SceneObjectPart part in m_parts.Values) 2194 foreach (SceneObjectPart part in m_parts.Values)
2017 { 2195 {
2018 if (part.LinkNum == linknum) 2196 if (part.LinkNum == linknum)
2019 { 2197 {
2198 lockPartsForRead(false);
2020 return part; 2199 return part;
2021 } 2200 }
2022 } 2201 }
2023 } 2202 }
2203 lockPartsForRead(false);
2024 2204
2025 return null; 2205 return null;
2026 } 2206 }
@@ -2048,17 +2228,19 @@ namespace OpenSim.Region.Framework.Scenes
2048 public SceneObjectPart GetChildPart(uint localID) 2228 public SceneObjectPart GetChildPart(uint localID)
2049 { 2229 {
2050 //m_log.DebugFormat("Entered looking for {0}", localID); 2230 //m_log.DebugFormat("Entered looking for {0}", localID);
2051 lock (m_parts) 2231 lockPartsForRead(true);
2052 { 2232 {
2053 foreach (SceneObjectPart part in m_parts.Values) 2233 foreach (SceneObjectPart part in m_parts.Values)
2054 { 2234 {
2055 //m_log.DebugFormat("Found {0}", part.LocalId); 2235 //m_log.DebugFormat("Found {0}", part.LocalId);
2056 if (part.LocalId == localID) 2236 if (part.LocalId == localID)
2057 { 2237 {
2238 lockPartsForRead(false);
2058 return part; 2239 return part;
2059 } 2240 }
2060 } 2241 }
2061 } 2242 }
2243 lockPartsForRead(false);
2062 2244
2063 return null; 2245 return null;
2064 } 2246 }
@@ -2088,17 +2270,19 @@ namespace OpenSim.Region.Framework.Scenes
2088 public bool HasChildPrim(uint localID) 2270 public bool HasChildPrim(uint localID)
2089 { 2271 {
2090 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); 2272 //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID);
2091 lock (m_parts) 2273 lockPartsForRead(true);
2092 { 2274 {
2093 foreach (SceneObjectPart part in m_parts.Values) 2275 foreach (SceneObjectPart part in m_parts.Values)
2094 { 2276 {
2095 //m_log.DebugFormat("Found {0}", part.LocalId); 2277 //m_log.DebugFormat("Found {0}", part.LocalId);
2096 if (part.LocalId == localID) 2278 if (part.LocalId == localID)
2097 { 2279 {
2280 lockPartsForRead(false);
2098 return true; 2281 return true;
2099 } 2282 }
2100 } 2283 }
2101 } 2284 }
2285 lockPartsForRead(false);
2102 2286
2103 return false; 2287 return false;
2104 } 2288 }
@@ -2148,53 +2332,57 @@ namespace OpenSim.Region.Framework.Scenes
2148 if (m_rootPart.LinkNum == 0) 2332 if (m_rootPart.LinkNum == 0)
2149 m_rootPart.LinkNum = 1; 2333 m_rootPart.LinkNum = 1;
2150 2334
2151 lock (m_parts) 2335 lockPartsForWrite(true);
2152 { 2336
2153 m_parts.Add(linkPart.UUID, linkPart); 2337 m_parts.Add(linkPart.UUID, linkPart);
2338
2339 lockPartsForWrite(false);
2154 2340
2155 // Insert in terms of link numbers, the new links 2341 // Insert in terms of link numbers, the new links
2156 // before the current ones (with the exception of 2342 // before the current ones (with the exception of
2157 // the root prim. Shuffle the old ones up 2343 // the root prim. Shuffle the old ones up
2158 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts) 2344 lockPartsForRead(true);
2345 foreach (KeyValuePair<UUID, SceneObjectPart> kvp in m_parts)
2346 {
2347 if (kvp.Value.LinkNum != 1)
2159 { 2348 {
2160 if (kvp.Value.LinkNum != 1) 2349 // Don't update root prim link number
2161 { 2350 kvp.Value.LinkNum += objectGroup.PrimCount;
2162 // Don't update root prim link number
2163 kvp.Value.LinkNum += objectGroup.PrimCount;
2164 }
2165 } 2351 }
2352 }
2353 lockPartsForRead(false);
2166 2354
2167 linkPart.LinkNum = 2; 2355 linkPart.LinkNum = 2;
2168 2356
2169 linkPart.SetParent(this); 2357 linkPart.SetParent(this);
2170 linkPart.AddFlag(PrimFlags.CreateSelected); 2358 linkPart.AddFlag(PrimFlags.CreateSelected);
2171 2359
2172 //if (linkPart.PhysActor != null) 2360 //if (linkPart.PhysActor != null)
2173 //{ 2361 //{
2174 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2362 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
2175 2363
2176 //linkPart.PhysActor = null; 2364 //linkPart.PhysActor = null;
2177 //} 2365 //}
2178 2366
2179 //TODO: rest of parts 2367 //TODO: rest of parts
2180 int linkNum = 3; 2368 int linkNum = 3;
2181 foreach (SceneObjectPart part in objectGroup.Children.Values) 2369 foreach (SceneObjectPart part in objectGroup.Children.Values)
2370 {
2371 if (part.UUID != objectGroup.m_rootPart.UUID)
2182 { 2372 {
2183 if (part.UUID != objectGroup.m_rootPart.UUID) 2373 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2184 {
2185 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2186 }
2187 part.ClearUndoState();
2188 } 2374 }
2375 part.ClearUndoState();
2189 } 2376 }
2190 2377
2191 m_scene.UnlinkSceneObject(objectGroup.UUID, true); 2378 m_scene.UnlinkSceneObject(objectGroup.UUID, true);
2192 objectGroup.m_isDeleted = true; 2379 objectGroup.m_isDeleted = true;
2380
2381 objectGroup.lockPartsForWrite(true);
2193 2382
2194 lock (objectGroup.m_parts) 2383 objectGroup.m_parts.Clear();
2195 { 2384
2196 objectGroup.m_parts.Clear(); 2385 objectGroup.lockPartsForWrite(false);
2197 }
2198 2386
2199 // Can't do this yet since backup still makes use of the root part without any synchronization 2387 // Can't do this yet since backup still makes use of the root part without any synchronization
2200// objectGroup.m_rootPart = null; 2388// objectGroup.m_rootPart = null;
@@ -2253,11 +2441,12 @@ namespace OpenSim.Region.Framework.Scenes
2253 Quaternion worldRot = linkPart.GetWorldRotation(); 2441 Quaternion worldRot = linkPart.GetWorldRotation();
2254 2442
2255 // Remove the part from this object 2443 // Remove the part from this object
2256 lock (m_parts) 2444 lockPartsForWrite(true);
2257 { 2445 {
2258 m_parts.Remove(linkPart.UUID); 2446 m_parts.Remove(linkPart.UUID);
2259 } 2447 }
2260 2448 lockPartsForWrite(false);
2449 lockPartsForRead(true);
2261 if (m_parts.Count == 1 && RootPart != null) //Single prim is left 2450 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2262 RootPart.LinkNum = 0; 2451 RootPart.LinkNum = 0;
2263 else 2452 else
@@ -2268,6 +2457,7 @@ namespace OpenSim.Region.Framework.Scenes
2268 p.LinkNum--; 2457 p.LinkNum--;
2269 } 2458 }
2270 } 2459 }
2460 lockPartsForRead(false);
2271 2461
2272 linkPart.ParentID = 0; 2462 linkPart.ParentID = 0;
2273 linkPart.LinkNum = 0; 2463 linkPart.LinkNum = 0;
@@ -2585,9 +2775,12 @@ namespace OpenSim.Region.Framework.Scenes
2585 2775
2586 if (selectionPart != null) 2776 if (selectionPart != null)
2587 { 2777 {
2588 lock (m_parts) 2778 lockPartsForRead(true);
2779 List<SceneObjectPart> parts = new List<SceneObjectPart>(m_parts.Values);
2780 lockPartsForRead(false);
2781 foreach (SceneObjectPart part in parts)
2589 { 2782 {
2590 foreach (SceneObjectPart part in m_parts.Values) 2783 if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0)
2591 { 2784 {
2592 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax || 2785 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2593 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax || 2786 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
@@ -2597,12 +2790,13 @@ namespace OpenSim.Region.Framework.Scenes
2597 break; 2790 break;
2598 } 2791 }
2599 } 2792 }
2793 }
2600 2794
2601 foreach (SceneObjectPart part in m_parts.Values) 2795 foreach (SceneObjectPart part in parts)
2602 { 2796 {
2603 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2797 part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2604 }
2605 } 2798 }
2799
2606 } 2800 }
2607 } 2801 }
2608 2802
@@ -2688,11 +2882,9 @@ namespace OpenSim.Region.Framework.Scenes
2688 scale.Y = m_scene.m_maxNonphys; 2882 scale.Y = m_scene.m_maxNonphys;
2689 if (scale.Z > m_scene.m_maxNonphys) 2883 if (scale.Z > m_scene.m_maxNonphys)
2690 scale.Z = m_scene.m_maxNonphys; 2884 scale.Z = m_scene.m_maxNonphys;
2691
2692 SceneObjectPart part = GetChildPart(localID); 2885 SceneObjectPart part = GetChildPart(localID);
2693 if (part != null) 2886 if (part != null)
2694 { 2887 {
2695 part.Resize(scale);
2696 if (part.PhysActor != null) 2888 if (part.PhysActor != null)
2697 { 2889 {
2698 if (part.PhysActor.IsPhysical) 2890 if (part.PhysActor.IsPhysical)
@@ -2707,7 +2899,7 @@ namespace OpenSim.Region.Framework.Scenes
2707 part.PhysActor.Size = scale; 2899 part.PhysActor.Size = scale;
2708 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2900 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2709 } 2901 }
2710 //if (part.UUID != m_rootPart.UUID) 2902 part.Resize(scale);
2711 2903
2712 HasGroupChanged = true; 2904 HasGroupChanged = true;
2713 ScheduleGroupForFullUpdate(); 2905 ScheduleGroupForFullUpdate();
@@ -2748,77 +2940,76 @@ namespace OpenSim.Region.Framework.Scenes
2748 float y = (scale.Y / part.Scale.Y); 2940 float y = (scale.Y / part.Scale.Y);
2749 float z = (scale.Z / part.Scale.Z); 2941 float z = (scale.Z / part.Scale.Z);
2750 2942
2751 lock (m_parts) 2943 lockPartsForRead(true);
2944 if (x > 1.0f || y > 1.0f || z > 1.0f)
2752 { 2945 {
2753 if (x > 1.0f || y > 1.0f || z > 1.0f) 2946 foreach (SceneObjectPart obPart in m_parts.Values)
2754 { 2947 {
2755 foreach (SceneObjectPart obPart in m_parts.Values) 2948 if (obPart.UUID != m_rootPart.UUID)
2756 { 2949 {
2757 if (obPart.UUID != m_rootPart.UUID) 2950 Vector3 oldSize = new Vector3(obPart.Scale);
2758 {
2759 Vector3 oldSize = new Vector3(obPart.Scale);
2760 2951
2761 float f = 1.0f; 2952 float f = 1.0f;
2762 float a = 1.0f; 2953 float a = 1.0f;
2763 2954
2764 if (part.PhysActor != null && part.PhysActor.IsPhysical) 2955 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2956 {
2957 if (oldSize.X*x > m_scene.m_maxPhys)
2765 { 2958 {
2766 if (oldSize.X*x > m_scene.m_maxPhys) 2959 f = m_scene.m_maxPhys / oldSize.X;
2767 { 2960 a = f / x;
2768 f = m_scene.m_maxPhys / oldSize.X; 2961 x *= a;
2769 a = f / x; 2962 y *= a;
2770 x *= a; 2963 z *= a;
2771 y *= a;
2772 z *= a;
2773 }
2774 if (oldSize.Y*y > m_scene.m_maxPhys)
2775 {
2776 f = m_scene.m_maxPhys / oldSize.Y;
2777 a = f / y;
2778 x *= a;
2779 y *= a;
2780 z *= a;
2781 }
2782 if (oldSize.Z*z > m_scene.m_maxPhys)
2783 {
2784 f = m_scene.m_maxPhys / oldSize.Z;
2785 a = f / z;
2786 x *= a;
2787 y *= a;
2788 z *= a;
2789 }
2790 } 2964 }
2791 else 2965 if (oldSize.Y*y > m_scene.m_maxPhys)
2966 {
2967 f = m_scene.m_maxPhys / oldSize.Y;
2968 a = f / y;
2969 x *= a;
2970 y *= a;
2971 z *= a;
2972 }
2973 if (oldSize.Z*z > m_scene.m_maxPhys)
2974 {
2975 f = m_scene.m_maxPhys / oldSize.Z;
2976 a = f / z;
2977 x *= a;
2978 y *= a;
2979 z *= a;
2980 }
2981 }
2982 else
2983 {
2984 if (oldSize.X*x > m_scene.m_maxNonphys)
2985 {
2986 f = m_scene.m_maxNonphys / oldSize.X;
2987 a = f / x;
2988 x *= a;
2989 y *= a;
2990 z *= a;
2991 }
2992 if (oldSize.Y*y > m_scene.m_maxNonphys)
2993 {
2994 f = m_scene.m_maxNonphys / oldSize.Y;
2995 a = f / y;
2996 x *= a;
2997 y *= a;
2998 z *= a;
2999 }
3000 if (oldSize.Z*z > m_scene.m_maxNonphys)
2792 { 3001 {
2793 if (oldSize.X*x > m_scene.m_maxNonphys) 3002 f = m_scene.m_maxNonphys / oldSize.Z;
2794 { 3003 a = f / z;
2795 f = m_scene.m_maxNonphys / oldSize.X; 3004 x *= a;
2796 a = f / x; 3005 y *= a;
2797 x *= a; 3006 z *= a;
2798 y *= a;
2799 z *= a;
2800 }
2801 if (oldSize.Y*y > m_scene.m_maxNonphys)
2802 {
2803 f = m_scene.m_maxNonphys / oldSize.Y;
2804 a = f / y;
2805 x *= a;
2806 y *= a;
2807 z *= a;
2808 }
2809 if (oldSize.Z*z > m_scene.m_maxNonphys)
2810 {
2811 f = m_scene.m_maxNonphys / oldSize.Z;
2812 a = f / z;
2813 x *= a;
2814 y *= a;
2815 z *= a;
2816 }
2817 } 3007 }
2818 } 3008 }
2819 } 3009 }
2820 } 3010 }
2821 } 3011 }
3012 lockPartsForRead(false);
2822 3013
2823 Vector3 prevScale = part.Scale; 3014 Vector3 prevScale = part.Scale;
2824 prevScale.X *= x; 3015 prevScale.X *= x;
@@ -2826,7 +3017,7 @@ namespace OpenSim.Region.Framework.Scenes
2826 prevScale.Z *= z; 3017 prevScale.Z *= z;
2827 part.Resize(prevScale); 3018 part.Resize(prevScale);
2828 3019
2829 lock (m_parts) 3020 lockPartsForRead(true);
2830 { 3021 {
2831 foreach (SceneObjectPart obPart in m_parts.Values) 3022 foreach (SceneObjectPart obPart in m_parts.Values)
2832 { 3023 {
@@ -2845,6 +3036,7 @@ namespace OpenSim.Region.Framework.Scenes
2845 } 3036 }
2846 } 3037 }
2847 } 3038 }
3039 lockPartsForRead(false);
2848 3040
2849 if (part.PhysActor != null) 3041 if (part.PhysActor != null)
2850 { 3042 {
@@ -2925,7 +3117,7 @@ namespace OpenSim.Region.Framework.Scenes
2925 axDiff *= Quaternion.Inverse(partRotation); 3117 axDiff *= Quaternion.Inverse(partRotation);
2926 diff = axDiff; 3118 diff = axDiff;
2927 3119
2928 lock (m_parts) 3120 lockPartsForRead(true);
2929 { 3121 {
2930 foreach (SceneObjectPart obPart in m_parts.Values) 3122 foreach (SceneObjectPart obPart in m_parts.Values)
2931 { 3123 {
@@ -2935,6 +3127,7 @@ namespace OpenSim.Region.Framework.Scenes
2935 } 3127 }
2936 } 3128 }
2937 } 3129 }
3130 lockPartsForRead(false);
2938 3131
2939 AbsolutePosition = newPos; 3132 AbsolutePosition = newPos;
2940 3133
@@ -3052,7 +3245,7 @@ namespace OpenSim.Region.Framework.Scenes
3052 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 3245 m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3053 } 3246 }
3054 3247
3055 lock (m_parts) 3248 lockPartsForRead(true);
3056 { 3249 {
3057 foreach (SceneObjectPart prim in m_parts.Values) 3250 foreach (SceneObjectPart prim in m_parts.Values)
3058 { 3251 {
@@ -3070,6 +3263,7 @@ namespace OpenSim.Region.Framework.Scenes
3070 } 3263 }
3071 } 3264 }
3072 } 3265 }
3266 lockPartsForRead(false);
3073 3267
3074 m_rootPart.ScheduleTerseUpdate(); 3268 m_rootPart.ScheduleTerseUpdate();
3075 } 3269 }
@@ -3168,7 +3362,7 @@ namespace OpenSim.Region.Framework.Scenes
3168 if (atTargets.Count > 0) 3362 if (atTargets.Count > 0)
3169 { 3363 {
3170 uint[] localids = new uint[0]; 3364 uint[] localids = new uint[0];
3171 lock (m_parts) 3365 lockPartsForRead(true);
3172 { 3366 {
3173 localids = new uint[m_parts.Count]; 3367 localids = new uint[m_parts.Count];
3174 int cntr = 0; 3368 int cntr = 0;
@@ -3178,6 +3372,7 @@ namespace OpenSim.Region.Framework.Scenes
3178 cntr++; 3372 cntr++;
3179 } 3373 }
3180 } 3374 }
3375 lockPartsForRead(false);
3181 3376
3182 for (int ctr = 0; ctr < localids.Length; ctr++) 3377 for (int ctr = 0; ctr < localids.Length; ctr++)
3183 { 3378 {
@@ -3196,7 +3391,7 @@ namespace OpenSim.Region.Framework.Scenes
3196 { 3391 {
3197 //trigger not_at_target 3392 //trigger not_at_target
3198 uint[] localids = new uint[0]; 3393 uint[] localids = new uint[0];
3199 lock (m_parts) 3394 lockPartsForRead(true);
3200 { 3395 {
3201 localids = new uint[m_parts.Count]; 3396 localids = new uint[m_parts.Count];
3202 int cntr = 0; 3397 int cntr = 0;
@@ -3206,7 +3401,8 @@ namespace OpenSim.Region.Framework.Scenes
3206 cntr++; 3401 cntr++;
3207 } 3402 }
3208 } 3403 }
3209 3404 lockPartsForRead(false);
3405
3210 for (int ctr = 0; ctr < localids.Length; ctr++) 3406 for (int ctr = 0; ctr < localids.Length; ctr++)
3211 { 3407 {
3212 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 3408 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3219,19 +3415,20 @@ namespace OpenSim.Region.Framework.Scenes
3219 public float GetMass() 3415 public float GetMass()
3220 { 3416 {
3221 float retmass = 0f; 3417 float retmass = 0f;
3222 lock (m_parts) 3418 lockPartsForRead(true);
3223 { 3419 {
3224 foreach (SceneObjectPart part in m_parts.Values) 3420 foreach (SceneObjectPart part in m_parts.Values)
3225 { 3421 {
3226 retmass += part.GetMass(); 3422 retmass += part.GetMass();
3227 } 3423 }
3228 } 3424 }
3425 lockPartsForRead(false);
3229 return retmass; 3426 return retmass;
3230 } 3427 }
3231 3428
3232 public void CheckSculptAndLoad() 3429 public void CheckSculptAndLoad()
3233 { 3430 {
3234 lock (m_parts) 3431 lockPartsForRead(true);
3235 { 3432 {
3236 if (!IsDeleted) 3433 if (!IsDeleted)
3237 { 3434 {
@@ -3256,6 +3453,7 @@ namespace OpenSim.Region.Framework.Scenes
3256 } 3453 }
3257 } 3454 }
3258 } 3455 }
3456 lockPartsForRead(false);
3259 } 3457 }
3260 3458
3261 protected void AssetReceived(string id, Object sender, AssetBase asset) 3459 protected void AssetReceived(string id, Object sender, AssetBase asset)
@@ -3276,7 +3474,7 @@ namespace OpenSim.Region.Framework.Scenes
3276 /// <param name="client"></param> 3474 /// <param name="client"></param>
3277 public void SetGroup(UUID GroupID, IClientAPI client) 3475 public void SetGroup(UUID GroupID, IClientAPI client)
3278 { 3476 {
3279 lock (m_parts) 3477 lockPartsForRead(true);
3280 { 3478 {
3281 foreach (SceneObjectPart part in m_parts.Values) 3479 foreach (SceneObjectPart part in m_parts.Values)
3282 { 3480 {
@@ -3286,7 +3484,7 @@ namespace OpenSim.Region.Framework.Scenes
3286 3484
3287 HasGroupChanged = true; 3485 HasGroupChanged = true;
3288 } 3486 }
3289 3487 lockPartsForRead(false);
3290 ScheduleGroupForFullUpdate(); 3488 ScheduleGroupForFullUpdate();
3291 } 3489 }
3292 3490
@@ -3305,11 +3503,12 @@ namespace OpenSim.Region.Framework.Scenes
3305 3503
3306 public void SetAttachmentPoint(byte point) 3504 public void SetAttachmentPoint(byte point)
3307 { 3505 {
3308 lock (m_parts) 3506 lockPartsForRead(true);
3309 { 3507 {
3310 foreach (SceneObjectPart part in m_parts.Values) 3508 foreach (SceneObjectPart part in m_parts.Values)
3311 part.SetAttachmentPoint(point); 3509 part.SetAttachmentPoint(point);
3312 } 3510 }
3511 lockPartsForRead(false);
3313 } 3512 }
3314 3513
3315 #region ISceneObject 3514 #region ISceneObject
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index b6916f2..a23c11e 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
@@ -508,9 +513,16 @@ namespace OpenSim.Region.Framework.Scenes
508 { 513 {
509 // If this is a linkset, we don't want the physics engine mucking up our group position here. 514 // If this is a linkset, we don't want the physics engine mucking up our group position here.
510 PhysicsActor actor = PhysActor; 515 PhysicsActor actor = PhysActor;
511 if (actor != null && _parentID == 0) 516 if (actor != null)
512 { 517 {
513 m_groupPosition = actor.Position; 518 if (_parentID == 0)
519 {
520 m_groupPosition = actor.Position;
521 }
522 else
523 {
524 m_groupPosition = ParentGroup.AbsolutePosition; // KF+Casper Update Child prims too!
525 }
514 } 526 }
515 527
516 if (IsAttachment) 528 if (IsAttachment)
@@ -837,7 +849,8 @@ namespace OpenSim.Region.Framework.Scenes
837 if (IsAttachment) 849 if (IsAttachment)
838 return GroupPosition; 850 return GroupPosition;
839 851
840 return m_offsetPosition + m_groupPosition; } 852// return m_offsetPosition + m_groupPosition; }
853 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
841 } 854 }
842 855
843 public SceneObjectGroup ParentGroup 856 public SceneObjectGroup ParentGroup
@@ -989,6 +1002,13 @@ namespace OpenSim.Region.Framework.Scenes
989 get { return _flags; } 1002 get { return _flags; }
990 set { _flags = value; } 1003 set { _flags = value; }
991 } 1004 }
1005
1006 [XmlIgnore]
1007 public bool IsOccupied // KF If an av is sittingon this prim
1008 {
1009 get { return m_occupied; }
1010 set { m_occupied = value; }
1011 }
992 1012
993 [XmlIgnore] 1013 [XmlIgnore]
994 public UUID SitTargetAvatar 1014 public UUID SitTargetAvatar
@@ -1064,14 +1084,6 @@ namespace OpenSim.Region.Framework.Scenes
1064 } 1084 }
1065 } 1085 }
1066 1086
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) 1087 private void SendObjectPropertiesToClient(UUID AgentID)
1076 { 1088 {
1077 ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); 1089 ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences();
@@ -1739,9 +1751,13 @@ namespace OpenSim.Region.Framework.Scenes
1739 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 1751 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
1740 1752
1741 Vector3 axPos = OffsetPosition; 1753 Vector3 axPos = OffsetPosition;
1742
1743 axPos *= parentRot; 1754 axPos *= parentRot;
1744 Vector3 translationOffsetPosition = axPos; 1755 Vector3 translationOffsetPosition = axPos;
1756
1757 int tx = (int)GroupPosition.X;
1758 int ty = (int)GroupPosition.Y;
1759 int tz = (int)GroupPosition.Z;
1760
1745 return GroupPosition + translationOffsetPosition; 1761 return GroupPosition + translationOffsetPosition;
1746 } 1762 }
1747 1763
@@ -2109,17 +2125,18 @@ namespace OpenSim.Region.Framework.Scenes
2109 //Trys to fetch sound id from prim's inventory. 2125 //Trys to fetch sound id from prim's inventory.
2110 //Prim's inventory doesn't support non script items yet 2126 //Prim's inventory doesn't support non script items yet
2111 2127
2112 lock (TaskInventory) 2128 TaskInventory.LockItemsForRead(true);
2129
2130 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2113 { 2131 {
2114 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2132 if (item.Value.Name == sound)
2115 { 2133 {
2116 if (item.Value.Name == sound) 2134 soundID = item.Value.ItemID;
2117 { 2135 break;
2118 soundID = item.Value.ItemID;
2119 break;
2120 }
2121 } 2136 }
2122 } 2137 }
2138
2139 TaskInventory.LockItemsForRead(false);
2123 } 2140 }
2124 2141
2125 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars(); 2142 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
@@ -2185,6 +2202,11 @@ namespace OpenSim.Region.Framework.Scenes
2185 ParentGroup.HasGroupChanged = true; 2202 ParentGroup.HasGroupChanged = true;
2186 ScheduleFullUpdate(); 2203 ScheduleFullUpdate();
2187 } 2204 }
2205
2206 public void RotLookAt(Quaternion target, float strength, float damping)
2207 {
2208 m_parentGroup.rotLookAt(target, strength, damping);
2209 }
2188 2210
2189 /// <summary> 2211 /// <summary>
2190 /// Schedules this prim for a full update 2212 /// Schedules this prim for a full update
@@ -2389,8 +2411,8 @@ namespace OpenSim.Region.Framework.Scenes
2389 { 2411 {
2390 const float ROTATION_TOLERANCE = 0.01f; 2412 const float ROTATION_TOLERANCE = 0.01f;
2391 const float VELOCITY_TOLERANCE = 0.001f; 2413 const float VELOCITY_TOLERANCE = 0.001f;
2392 const float POSITION_TOLERANCE = 0.05f; 2414 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2393 const int TIME_MS_TOLERANCE = 3000; 2415 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2394 2416
2395 if (m_updateFlag == 1) 2417 if (m_updateFlag == 1)
2396 { 2418 {
@@ -2404,7 +2426,7 @@ namespace OpenSim.Region.Framework.Scenes
2404 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 2426 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
2405 { 2427 {
2406 AddTerseUpdateToAllAvatars(); 2428 AddTerseUpdateToAllAvatars();
2407 ClearUpdateSchedule(); 2429
2408 2430
2409 // This causes the Scene to 'poll' physical objects every couple of frames 2431 // This causes the Scene to 'poll' physical objects every couple of frames
2410 // bad, so it's been replaced by an event driven method. 2432 // bad, so it's been replaced by an event driven method.
@@ -2422,16 +2444,18 @@ namespace OpenSim.Region.Framework.Scenes
2422 m_lastAngularVelocity = AngularVelocity; 2444 m_lastAngularVelocity = AngularVelocity;
2423 m_lastTerseSent = Environment.TickCount; 2445 m_lastTerseSent = Environment.TickCount;
2424 } 2446 }
2447 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
2448 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
2425 } 2449 }
2426 else 2450 else
2427 { 2451 {
2428 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 2452 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
2429 { 2453 {
2430 AddFullUpdateToAllAvatars(); 2454 AddFullUpdateToAllAvatars();
2431 ClearUpdateSchedule(); 2455 m_updateFlag = 0; //Same here
2432 } 2456 }
2433 } 2457 }
2434 ClearUpdateSchedule(); 2458 m_updateFlag = 0;
2435 } 2459 }
2436 2460
2437 /// <summary> 2461 /// <summary>
@@ -2458,17 +2482,16 @@ namespace OpenSim.Region.Framework.Scenes
2458 if (!UUID.TryParse(sound, out soundID)) 2482 if (!UUID.TryParse(sound, out soundID))
2459 { 2483 {
2460 // search sound file from inventory 2484 // search sound file from inventory
2461 lock (TaskInventory) 2485 TaskInventory.LockItemsForRead(true);
2486 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2462 { 2487 {
2463 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2488 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2464 { 2489 {
2465 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 2490 soundID = item.Value.ItemID;
2466 { 2491 break;
2467 soundID = item.Value.ItemID;
2468 break;
2469 }
2470 } 2492 }
2471 } 2493 }
2494 TaskInventory.LockItemsForRead(false);
2472 } 2495 }
2473 2496
2474 if (soundID == UUID.Zero) 2497 if (soundID == UUID.Zero)
@@ -2684,6 +2707,13 @@ namespace OpenSim.Region.Framework.Scenes
2684 SetText(text); 2707 SetText(text);
2685 } 2708 }
2686 2709
2710 public void StopLookAt()
2711 {
2712 m_parentGroup.stopLookAt();
2713
2714 m_parentGroup.ScheduleGroupForTerseUpdate();
2715 }
2716
2687 public void StopMoveToTarget() 2717 public void StopMoveToTarget()
2688 { 2718 {
2689 m_parentGroup.stopMoveToTarget(); 2719 m_parentGroup.stopMoveToTarget();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 22eedba..b57d912 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -80,7 +80,9 @@ namespace OpenSim.Region.Framework.Scenes
80 /// </value> 80 /// </value>
81 protected internal TaskInventoryDictionary Items 81 protected internal TaskInventoryDictionary Items
82 { 82 {
83 get { return m_items; } 83 get {
84 return m_items;
85 }
84 set 86 set
85 { 87 {
86 m_items = value; 88 m_items = value;
@@ -116,22 +118,25 @@ namespace OpenSim.Region.Framework.Scenes
116 /// <param name="linkNum">Link number for the part</param> 118 /// <param name="linkNum">Link number for the part</param>
117 public void ResetInventoryIDs() 119 public void ResetInventoryIDs()
118 { 120 {
119 lock (Items) 121 m_items.LockItemsForWrite(true);
122
123 if (0 == Items.Count)
120 { 124 {
121 if (0 == Items.Count) 125 m_items.LockItemsForWrite(false);
122 return; 126 return;
127 }
123 128
124 HasInventoryChanged = true; 129 HasInventoryChanged = true;
125 m_part.ParentGroup.HasGroupChanged = true; 130 m_part.ParentGroup.HasGroupChanged = true;
126 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 131 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
127 Items.Clear(); 132 Items.Clear();
128 133
129 foreach (TaskInventoryItem item in items) 134 foreach (TaskInventoryItem item in items)
130 { 135 {
131 item.ResetIDs(m_part.UUID); 136 item.ResetIDs(m_part.UUID);
132 Items.Add(item.ItemID, item); 137 Items.Add(item.ItemID, item);
133 }
134 } 138 }
139 m_items.LockItemsForWrite(false);
135 } 140 }
136 141
137 /// <summary> 142 /// <summary>
@@ -140,25 +145,25 @@ namespace OpenSim.Region.Framework.Scenes
140 /// <param name="ownerId"></param> 145 /// <param name="ownerId"></param>
141 public void ChangeInventoryOwner(UUID ownerId) 146 public void ChangeInventoryOwner(UUID ownerId)
142 { 147 {
143 lock (Items) 148 m_items.LockItemsForWrite(true);
149 if (0 == Items.Count)
144 { 150 {
145 if (0 == Items.Count) 151 m_items.LockItemsForWrite(false);
146 { 152 return;
147 return; 153 }
148 }
149 154
150 HasInventoryChanged = true; 155 HasInventoryChanged = true;
151 m_part.ParentGroup.HasGroupChanged = true; 156 m_part.ParentGroup.HasGroupChanged = true;
152 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
153 foreach (TaskInventoryItem item in items) 158 foreach (TaskInventoryItem item in items)
159 {
160 if (ownerId != item.OwnerID)
154 { 161 {
155 if (ownerId != item.OwnerID) 162 item.LastOwnerID = item.OwnerID;
156 { 163 item.OwnerID = ownerId;
157 item.LastOwnerID = item.OwnerID;
158 item.OwnerID = ownerId;
159 }
160 } 164 }
161 } 165 }
166 m_items.LockItemsForWrite(false);
162 } 167 }
163 168
164 /// <summary> 169 /// <summary>
@@ -167,24 +172,24 @@ namespace OpenSim.Region.Framework.Scenes
167 /// <param name="groupID"></param> 172 /// <param name="groupID"></param>
168 public void ChangeInventoryGroup(UUID groupID) 173 public void ChangeInventoryGroup(UUID groupID)
169 { 174 {
170 lock (Items) 175 m_items.LockItemsForWrite(true);
176 if (0 == Items.Count)
171 { 177 {
172 if (0 == Items.Count) 178 m_items.LockItemsForWrite(false);
173 { 179 return;
174 return; 180 }
175 }
176 181
177 HasInventoryChanged = true; 182 HasInventoryChanged = true;
178 m_part.ParentGroup.HasGroupChanged = true; 183 m_part.ParentGroup.HasGroupChanged = true;
179 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 184 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
180 foreach (TaskInventoryItem item in items) 185 foreach (TaskInventoryItem item in items)
186 {
187 if (groupID != item.GroupID)
181 { 188 {
182 if (groupID != item.GroupID) 189 item.GroupID = groupID;
183 {
184 item.GroupID = groupID;
185 }
186 } 190 }
187 } 191 }
192 m_items.LockItemsForWrite(false);
188 } 193 }
189 194
190 /// <summary> 195 /// <summary>
@@ -192,14 +197,14 @@ namespace OpenSim.Region.Framework.Scenes
192 /// </summary> 197 /// </summary>
193 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 198 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
194 { 199 {
195 lock (m_items) 200 Items.LockItemsForRead(true);
201 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
202 Items.LockItemsForRead(false);
203 foreach (TaskInventoryItem item in items)
196 { 204 {
197 foreach (TaskInventoryItem item in Items.Values) 205 if ((int)InventoryType.LSL == item.InvType)
198 { 206 {
199 if ((int)InventoryType.LSL == item.InvType) 207 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
200 {
201 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
202 }
203 } 208 }
204 } 209 }
205 } 210 }
@@ -209,17 +214,20 @@ namespace OpenSim.Region.Framework.Scenes
209 /// </summary> 214 /// </summary>
210 public void RemoveScriptInstances() 215 public void RemoveScriptInstances()
211 { 216 {
212 lock (Items) 217 Items.LockItemsForRead(true);
218 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
219 Items.LockItemsForRead(false);
220
221 foreach (TaskInventoryItem item in items)
213 { 222 {
214 foreach (TaskInventoryItem item in Items.Values) 223 if ((int)InventoryType.LSL == item.InvType)
215 { 224 {
216 if ((int)InventoryType.LSL == item.InvType) 225 RemoveScriptInstance(item.ItemID);
217 { 226 m_part.RemoveScriptEvents(item.ItemID);
218 RemoveScriptInstance(item.ItemID);
219 m_part.RemoveScriptEvents(item.ItemID);
220 }
221 } 227 }
222 } 228 }
229
230
223 } 231 }
224 232
225 /// <summary> 233 /// <summary>
@@ -244,8 +252,10 @@ namespace OpenSim.Region.Framework.Scenes
244 if (stateSource == 1 && // Prim crossing 252 if (stateSource == 1 && // Prim crossing
245 m_part.ParentGroup.Scene.m_trustBinaries) 253 m_part.ParentGroup.Scene.m_trustBinaries)
246 { 254 {
255 m_items.LockItemsForWrite(true);
247 m_items[item.ItemID].PermsMask = 0; 256 m_items[item.ItemID].PermsMask = 0;
248 m_items[item.ItemID].PermsGranter = UUID.Zero; 257 m_items[item.ItemID].PermsGranter = UUID.Zero;
258 m_items.LockItemsForWrite(false);
249 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 259 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
250 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 260 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
251 m_part.ParentGroup.AddActiveScriptCount(1); 261 m_part.ParentGroup.AddActiveScriptCount(1);
@@ -267,8 +277,10 @@ namespace OpenSim.Region.Framework.Scenes
267 { 277 {
268 if (m_part.ParentGroup.m_savedScriptState != null) 278 if (m_part.ParentGroup.m_savedScriptState != null)
269 RestoreSavedScriptState(item.OldItemID, item.ItemID); 279 RestoreSavedScriptState(item.OldItemID, item.ItemID);
280 m_items.LockItemsForWrite(true);
270 m_items[item.ItemID].PermsMask = 0; 281 m_items[item.ItemID].PermsMask = 0;
271 m_items[item.ItemID].PermsGranter = UUID.Zero; 282 m_items[item.ItemID].PermsGranter = UUID.Zero;
283 m_items.LockItemsForWrite(false);
272 string script = Utils.BytesToString(asset.Data); 284 string script = Utils.BytesToString(asset.Data);
273 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 285 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
274 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 286 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
@@ -303,14 +315,17 @@ namespace OpenSim.Region.Framework.Scenes
303 /// </param> 315 /// </param>
304 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 316 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
305 { 317 {
306 lock (m_items) 318 m_items.LockItemsForRead(true);
319 if (m_items.ContainsKey(itemId))
307 { 320 {
308 if (m_items.ContainsKey(itemId)) 321 if (m_items.ContainsKey(itemId))
309 { 322 {
323 m_items.LockItemsForRead(false);
310 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); 324 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
311 } 325 }
312 else 326 else
313 { 327 {
328 m_items.LockItemsForRead(false);
314 m_log.ErrorFormat( 329 m_log.ErrorFormat(
315 "[PRIM INVENTORY]: " + 330 "[PRIM INVENTORY]: " +
316 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 331 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
@@ -318,6 +333,15 @@ namespace OpenSim.Region.Framework.Scenes
318 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 333 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
319 } 334 }
320 } 335 }
336 else
337 {
338 m_items.LockItemsForRead(false);
339 m_log.ErrorFormat(
340 "[PRIM INVENTORY]: " +
341 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}",
342 itemId, m_part.Name, m_part.UUID);
343 }
344
321 } 345 }
322 346
323 /// <summary> 347 /// <summary>
@@ -349,11 +373,16 @@ namespace OpenSim.Region.Framework.Scenes
349 /// <returns></returns> 373 /// <returns></returns>
350 private bool InventoryContainsName(string name) 374 private bool InventoryContainsName(string name)
351 { 375 {
352 foreach (TaskInventoryItem item in Items.Values) 376 m_items.LockItemsForRead(true);
377 foreach (TaskInventoryItem item in m_items.Values)
353 { 378 {
354 if (item.Name == name) 379 if (item.Name == name)
380 {
381 m_items.LockItemsForRead(false);
355 return true; 382 return true;
383 }
356 } 384 }
385 m_items.LockItemsForRead(false);
357 return false; 386 return false;
358 } 387 }
359 388
@@ -395,7 +424,9 @@ namespace OpenSim.Region.Framework.Scenes
395 /// <param name="item"></param> 424 /// <param name="item"></param>
396 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 425 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
397 { 426 {
427 m_items.LockItemsForRead(true);
398 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values); 428 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
429 m_items.LockItemsForRead(false);
399 foreach (TaskInventoryItem i in il) 430 foreach (TaskInventoryItem i in il)
400 { 431 {
401 if (i.Name == item.Name) 432 if (i.Name == item.Name)
@@ -432,15 +463,14 @@ namespace OpenSim.Region.Framework.Scenes
432 item.ParentPartID = m_part.UUID; 463 item.ParentPartID = m_part.UUID;
433 item.Name = name; 464 item.Name = name;
434 465
435 lock (m_items) 466 m_items.LockItemsForWrite(true);
436 { 467 m_items.Add(item.ItemID, item);
437 m_items.Add(item.ItemID, item); 468 m_items.LockItemsForWrite(false);
438
439 if (allowedDrop) 469 if (allowedDrop)
440 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 470 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
441 else 471 else
442 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 472 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
443 } 473
444 474
445 m_inventorySerial++; 475 m_inventorySerial++;
446 //m_inventorySerial += 2; 476 //m_inventorySerial += 2;
@@ -457,14 +487,13 @@ namespace OpenSim.Region.Framework.Scenes
457 /// <param name="items"></param> 487 /// <param name="items"></param>
458 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 488 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
459 { 489 {
460 lock (m_items) 490 m_items.LockItemsForWrite(true);
491 foreach (TaskInventoryItem item in items)
461 { 492 {
462 foreach (TaskInventoryItem item in items) 493 m_items.Add(item.ItemID, item);
463 { 494 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
464 m_items.Add(item.ItemID, item);
465 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
466 }
467 } 495 }
496 m_items.LockItemsForWrite(false);
468 497
469 m_inventorySerial++; 498 m_inventorySerial++;
470 } 499 }
@@ -477,8 +506,9 @@ namespace OpenSim.Region.Framework.Scenes
477 public TaskInventoryItem GetInventoryItem(UUID itemId) 506 public TaskInventoryItem GetInventoryItem(UUID itemId)
478 { 507 {
479 TaskInventoryItem item; 508 TaskInventoryItem item;
509 m_items.LockItemsForRead(true);
480 m_items.TryGetValue(itemId, out item); 510 m_items.TryGetValue(itemId, out item);
481 511 m_items.LockItemsForRead(false);
482 return item; 512 return item;
483 } 513 }
484 514
@@ -490,46 +520,46 @@ namespace OpenSim.Region.Framework.Scenes
490 /// <returns>false if the item did not exist, true if the update occurred successfully</returns> 520 /// <returns>false if the item did not exist, true if the update occurred successfully</returns>
491 public bool UpdateInventoryItem(TaskInventoryItem item) 521 public bool UpdateInventoryItem(TaskInventoryItem item)
492 { 522 {
493 lock (m_items) 523 m_items.LockItemsForWrite(true);
524
525 if (m_items.ContainsKey(item.ItemID))
494 { 526 {
495 if (m_items.ContainsKey(item.ItemID)) 527 item.ParentID = m_part.UUID;
528 item.ParentPartID = m_part.UUID;
529 item.Flags = m_items[item.ItemID].Flags;
530 if (item.AssetID == UUID.Zero)
496 { 531 {
497 item.ParentID = m_part.UUID; 532 item.AssetID = m_items[item.ItemID].AssetID;
498 item.ParentPartID = m_part.UUID; 533 }
499 item.Flags = m_items[item.ItemID].Flags; 534 else if ((InventoryType)item.Type == InventoryType.Notecard)
500 if (item.AssetID == UUID.Zero) 535 {
501 { 536 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
502 item.AssetID = m_items[item.ItemID].AssetID;
503 }
504 else if ((InventoryType)item.Type == InventoryType.Notecard)
505 {
506 ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID);
507 537
508 if (presence != null) 538 if (presence != null)
509 { 539 {
510 presence.ControllingClient.SendAgentAlertMessage( 540 presence.ControllingClient.SendAgentAlertMessage(
511 "Notecard saved", false); 541 "Notecard saved", false);
512 }
513 } 542 }
543 }
514 544
515 m_items[item.ItemID] = item; 545 m_items[item.ItemID] = item;
516 m_inventorySerial++; 546 m_inventorySerial++;
517 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 547 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
518
519 HasInventoryChanged = true;
520 m_part.ParentGroup.HasGroupChanged = true;
521 548
522 return true; 549 HasInventoryChanged = true;
523 } 550 m_part.ParentGroup.HasGroupChanged = true;
524 else 551 m_items.LockItemsForWrite(false);
525 { 552 return true;
526 m_log.ErrorFormat( 553 }
527 "[PRIM INVENTORY]: " + 554 else
528 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 555 {
529 item.ItemID, m_part.Name, m_part.UUID, 556 m_log.ErrorFormat(
530 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 557 "[PRIM INVENTORY]: " +
531 } 558 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
559 item.ItemID, m_part.Name, m_part.UUID,
560 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
532 } 561 }
562 m_items.LockItemsForWrite(false);
533 563
534 return false; 564 return false;
535 } 565 }
@@ -542,52 +572,54 @@ namespace OpenSim.Region.Framework.Scenes
542 /// in this prim's inventory.</returns> 572 /// in this prim's inventory.</returns>
543 public int RemoveInventoryItem(UUID itemID) 573 public int RemoveInventoryItem(UUID itemID)
544 { 574 {
545 lock (m_items) 575 m_items.LockItemsForRead(true);
576
577 if (m_items.ContainsKey(itemID))
546 { 578 {
547 if (m_items.ContainsKey(itemID)) 579 int type = m_items[itemID].InvType;
580 m_items.LockItemsForRead(false);
581 if (type == 10) // Script
548 { 582 {
549 int type = m_items[itemID].InvType; 583 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
550 if (type == 10) // Script 584 }
551 { 585 m_items.LockItemsForWrite(true);
552 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 586 m_items.Remove(itemID);
553 } 587 m_items.LockItemsForWrite(false);
554 m_items.Remove(itemID); 588 m_inventorySerial++;
555 m_inventorySerial++; 589 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
556 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
557
558 HasInventoryChanged = true;
559 m_part.ParentGroup.HasGroupChanged = true;
560 590
561 int scriptcount = 0; 591 HasInventoryChanged = true;
562 lock (m_items) 592 m_part.ParentGroup.HasGroupChanged = true;
563 {
564 foreach (TaskInventoryItem item in m_items.Values)
565 {
566 if (item.Type == 10)
567 {
568 scriptcount++;
569 }
570 }
571 }
572 593
573 if (scriptcount <= 0) 594 int scriptcount = 0;
595 m_items.LockItemsForRead(true);
596 foreach (TaskInventoryItem item in m_items.Values)
597 {
598 if (item.Type == 10)
574 { 599 {
575 m_part.RemFlag(PrimFlags.Scripted); 600 scriptcount++;
576 } 601 }
577
578 m_part.ScheduleFullUpdate();
579
580 return type;
581 } 602 }
582 else 603 m_items.LockItemsForRead(false);
604
605
606 if (scriptcount <= 0)
583 { 607 {
584 m_log.ErrorFormat( 608 m_part.RemFlag(PrimFlags.Scripted);
585 "[PRIM INVENTORY]: " +
586 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
587 itemID, m_part.Name, m_part.UUID,
588 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
589 } 609 }
610
611 m_part.ScheduleFullUpdate();
612
613 return type;
614 }
615 else
616 {
617 m_log.ErrorFormat(
618 "[PRIM INVENTORY]: " +
619 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
620 itemID, m_part.Name, m_part.UUID);
590 } 621 }
622 m_items.LockItemsForWrite(false);
591 623
592 return -1; 624 return -1;
593 } 625 }
@@ -640,52 +672,53 @@ namespace OpenSim.Region.Framework.Scenes
640 // isn't available (such as drag from prim inventory to agent inventory) 672 // isn't available (such as drag from prim inventory to agent inventory)
641 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 673 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
642 674
643 lock (m_items) 675 m_items.LockItemsForRead(true);
676
677 foreach (TaskInventoryItem item in m_items.Values)
644 { 678 {
645 foreach (TaskInventoryItem item in m_items.Values) 679 UUID ownerID = item.OwnerID;
646 { 680 uint everyoneMask = 0;
647 UUID ownerID = item.OwnerID; 681 uint baseMask = item.BasePermissions;
648 uint everyoneMask = 0; 682 uint ownerMask = item.CurrentPermissions;
649 uint baseMask = item.BasePermissions;
650 uint ownerMask = item.CurrentPermissions;
651 683
652 invString.AddItemStart(); 684 invString.AddItemStart();
653 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 685 invString.AddNameValueLine("item_id", item.ItemID.ToString());
654 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 686 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
655 687
656 invString.AddPermissionsStart(); 688 invString.AddPermissionsStart();
657 689
658 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 690 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
659 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 691 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
660 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); 692 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0));
661 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); 693 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
662 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); 694 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
663 695
664 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 696 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
665 invString.AddNameValueLine("owner_id", ownerID.ToString()); 697 invString.AddNameValueLine("owner_id", ownerID.ToString());
666 698
667 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 699 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
668 700
669 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 701 invString.AddNameValueLine("group_id", item.GroupID.ToString());
670 invString.AddSectionEnd(); 702 invString.AddSectionEnd();
671 703
672 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 704 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
673 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); 705 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
674 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); 706 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
675 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 707 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
676 708
677 invString.AddSaleStart(); 709 invString.AddSaleStart();
678 invString.AddNameValueLine("sale_type", "not"); 710 invString.AddNameValueLine("sale_type", "not");
679 invString.AddNameValueLine("sale_price", "0"); 711 invString.AddNameValueLine("sale_price", "0");
680 invString.AddSectionEnd(); 712 invString.AddSectionEnd();
681 713
682 invString.AddNameValueLine("name", item.Name + "|"); 714 invString.AddNameValueLine("name", item.Name + "|");
683 invString.AddNameValueLine("desc", item.Description + "|"); 715 invString.AddNameValueLine("desc", item.Description + "|");
684 716
685 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 717 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
686 invString.AddSectionEnd(); 718 invString.AddSectionEnd();
687 }
688 } 719 }
720 int count = m_items.Count;
721 m_items.LockItemsForRead(false);
689 722
690 fileData = Utils.StringToBytes(invString.BuildString); 723 fileData = Utils.StringToBytes(invString.BuildString);
691 724
@@ -706,10 +739,9 @@ namespace OpenSim.Region.Framework.Scenes
706 { 739 {
707 if (HasInventoryChanged) 740 if (HasInventoryChanged)
708 { 741 {
709 lock (Items) 742 Items.LockItemsForRead(true);
710 { 743 datastore.StorePrimInventory(m_part.UUID, Items.Values);
711 datastore.StorePrimInventory(m_part.UUID, Items.Values); 744 Items.LockItemsForRead(false);
712 }
713 745
714 HasInventoryChanged = false; 746 HasInventoryChanged = false;
715 } 747 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 2710cff..c67463a 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,7 +115,9 @@ 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
119 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
120 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
117 private Vector3 m_lastPosition; 121 private Vector3 m_lastPosition;
118 private Quaternion m_lastRotation; 122 private Quaternion m_lastRotation;
119 private Vector3 m_lastVelocity; 123 private Vector3 m_lastVelocity;
@@ -145,7 +149,6 @@ namespace OpenSim.Region.Framework.Scenes
145 private int m_perfMonMS; 149 private int m_perfMonMS;
146 150
147 private bool m_setAlwaysRun; 151 private bool m_setAlwaysRun;
148
149 private bool m_forceFly; 152 private bool m_forceFly;
150 private bool m_flyDisabled; 153 private bool m_flyDisabled;
151 154
@@ -169,7 +172,8 @@ namespace OpenSim.Region.Framework.Scenes
169 protected RegionInfo m_regionInfo; 172 protected RegionInfo m_regionInfo;
170 protected ulong crossingFromRegion; 173 protected ulong crossingFromRegion;
171 174
172 private readonly Vector3[] Dir_Vectors = new Vector3[6]; 175 private readonly Vector3[] Dir_Vectors = new Vector3[11];
176 private bool m_isNudging = false;
173 177
174 // Position of agent's camera in world (region cordinates) 178 // Position of agent's camera in world (region cordinates)
175 protected Vector3 m_CameraCenter; 179 protected Vector3 m_CameraCenter;
@@ -194,6 +198,7 @@ namespace OpenSim.Region.Framework.Scenes
194 private bool m_autopilotMoving; 198 private bool m_autopilotMoving;
195 private Vector3 m_autoPilotTarget; 199 private Vector3 m_autoPilotTarget;
196 private bool m_sitAtAutoTarget; 200 private bool m_sitAtAutoTarget;
201 private Vector3 m_initialSitTarget; //KF: First estimate of where to sit
197 202
198 private string m_nextSitAnimation = String.Empty; 203 private string m_nextSitAnimation = String.Empty;
199 204
@@ -204,6 +209,9 @@ namespace OpenSim.Region.Framework.Scenes
204 private bool m_followCamAuto; 209 private bool m_followCamAuto;
205 210
206 private int m_movementUpdateCount; 211 private int m_movementUpdateCount;
212 private int m_lastColCount = -1; //KF: Look for Collision chnages
213 private int m_updateCount = 0; //KF: Update Anims for a while
214 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
207 215
208 private const int NumMovementsBetweenRayCast = 5; 216 private const int NumMovementsBetweenRayCast = 5;
209 217
@@ -233,6 +241,10 @@ namespace OpenSim.Region.Framework.Scenes
233 DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, 241 DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
234 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 242 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
235 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 243 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
244 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
245 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
246 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
247 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 248 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
237 } 249 }
238 250
@@ -658,10 +670,7 @@ namespace OpenSim.Region.Framework.Scenes
658 670
659 671
660 AdjustKnownSeeds(); 672 AdjustKnownSeeds();
661
662 // TODO: I think, this won't send anything, as we are still a child here...
663 Animator.TrySetMovementAnimation("STAND"); 673 Animator.TrySetMovementAnimation("STAND");
664
665 // we created a new ScenePresence (a new child agent) in a fresh region. 674 // we created a new ScenePresence (a new child agent) in a fresh region.
666 // Request info about all the (root) agents in this region 675 // 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) 676 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -717,21 +726,47 @@ namespace OpenSim.Region.Framework.Scenes
717 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 726 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
718 Dir_Vectors[4] = Vector3.UnitZ; //UP 727 Dir_Vectors[4] = Vector3.UnitZ; //UP
719 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 728 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
720 Dir_Vectors[5] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 729 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
730 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
731 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
732 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
733 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
721 } 734 }
722 735
723 private Vector3[] GetWalkDirectionVectors() 736 private Vector3[] GetWalkDirectionVectors()
724 { 737 {
725 Vector3[] vector = new Vector3[6]; 738 Vector3[] vector = new Vector3[11];
726 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 739 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 740 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
728 vector[2] = Vector3.UnitY; //LEFT 741 vector[2] = Vector3.UnitY; //LEFT
729 vector[3] = -Vector3.UnitY; //RIGHT 742 vector[3] = -Vector3.UnitY; //RIGHT
730 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 743 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 744 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 745 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
746 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
747 vector[8] = Vector3.UnitY; //LEFT_NUDGE
748 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
749 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
733 return vector; 750 return vector;
734 } 751 }
752
753 private bool[] GetDirectionIsNudge()
754 {
755 bool[] isNudge = new bool[11];
756 isNudge[0] = false; //FORWARD
757 isNudge[1] = false; //BACK
758 isNudge[2] = false; //LEFT
759 isNudge[3] = false; //RIGHT
760 isNudge[4] = false; //UP
761 isNudge[5] = false; //DOWN
762 isNudge[6] = true; //FORWARD_NUDGE
763 isNudge[7] = true; //BACK_NUDGE
764 isNudge[8] = true; //LEFT_NUDGE
765 isNudge[9] = true; //RIGHT_NUDGE
766 isNudge[10] = true; //DOWN_Nudge
767 return isNudge;
768 }
769
735 770
736 #endregion 771 #endregion
737 772
@@ -995,7 +1030,9 @@ namespace OpenSim.Region.Framework.Scenes
995 { 1030 {
996 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1031 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
997 } 1032 }
998 1033
1034 m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim.
1035
999 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1036 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))); 1037 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
1001 } 1038 }
@@ -1230,7 +1267,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); 1267 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1231 } 1268 }
1232 } 1269 }
1233
1234 lock (scriptedcontrols) 1270 lock (scriptedcontrols)
1235 { 1271 {
1236 if (scriptedcontrols.Count > 0) 1272 if (scriptedcontrols.Count > 0)
@@ -1245,9 +1281,7 @@ namespace OpenSim.Region.Framework.Scenes
1245 1281
1246 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1282 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1247 { 1283 {
1248 // TODO: This doesn't prevent the user from walking yet. 1284 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"); 1285 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1252 } 1286 }
1253 1287
@@ -1292,6 +1326,11 @@ namespace OpenSim.Region.Framework.Scenes
1292 update_rotation = true; 1326 update_rotation = true;
1293 } 1327 }
1294 1328
1329 //guilty until proven innocent..
1330 bool Nudging = true;
1331 //Basically, if there is at least one non-nudge control then we don't need
1332 //to worry about stopping the avatar
1333
1295 if (m_parentID == 0) 1334 if (m_parentID == 0)
1296 { 1335 {
1297 bool bAllowUpdateMoveToPosition = false; 1336 bool bAllowUpdateMoveToPosition = false;
@@ -1306,6 +1345,12 @@ namespace OpenSim.Region.Framework.Scenes
1306 else 1345 else
1307 dirVectors = Dir_Vectors; 1346 dirVectors = Dir_Vectors;
1308 1347
1348 bool[] isNudge = GetDirectionIsNudge();
1349
1350
1351
1352
1353
1309 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1354 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1310 { 1355 {
1311 if (((uint)flags & (uint)DCF) != 0) 1356 if (((uint)flags & (uint)DCF) != 0)
@@ -1315,6 +1360,10 @@ namespace OpenSim.Region.Framework.Scenes
1315 try 1360 try
1316 { 1361 {
1317 agent_control_v3 += dirVectors[i]; 1362 agent_control_v3 += dirVectors[i];
1363 if (isNudge[i] == false)
1364 {
1365 Nudging = false;
1366 }
1318 } 1367 }
1319 catch (IndexOutOfRangeException) 1368 catch (IndexOutOfRangeException)
1320 { 1369 {
@@ -1376,6 +1425,9 @@ namespace OpenSim.Region.Framework.Scenes
1376 // Ignore z component of vector 1425 // Ignore z component of vector
1377 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1426 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1378 LocalVectorToTarget2D.Normalize(); 1427 LocalVectorToTarget2D.Normalize();
1428
1429 //We're not nudging
1430 Nudging = false;
1379 agent_control_v3 += LocalVectorToTarget2D; 1431 agent_control_v3 += LocalVectorToTarget2D;
1380 1432
1381 // update avatar movement flags. the avatar coordinate system is as follows: 1433 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1464,7 +1516,7 @@ namespace OpenSim.Region.Framework.Scenes
1464 // m_log.DebugFormat( 1516 // m_log.DebugFormat(
1465 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1517 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1466 1518
1467 AddNewMovement(agent_control_v3, q); 1519 AddNewMovement(agent_control_v3, q, Nudging);
1468 1520
1469 1521
1470 } 1522 }
@@ -1485,7 +1537,6 @@ namespace OpenSim.Region.Framework.Scenes
1485 m_sitAtAutoTarget = false; 1537 m_sitAtAutoTarget = false;
1486 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1538 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1487 //proxy.PCode = (byte)PCode.ParticleSystem; 1539 //proxy.PCode = (byte)PCode.ParticleSystem;
1488
1489 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1540 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1490 proxyObjectGroup.AttachToScene(m_scene); 1541 proxyObjectGroup.AttachToScene(m_scene);
1491 1542
@@ -1527,7 +1578,7 @@ namespace OpenSim.Region.Framework.Scenes
1527 } 1578 }
1528 m_moveToPositionInProgress = true; 1579 m_moveToPositionInProgress = true;
1529 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1580 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1530 } 1581 }
1531 catch (Exception ex) 1582 catch (Exception ex)
1532 { 1583 {
1533 //Why did I get this error? 1584 //Why did I get this error?
@@ -1549,7 +1600,7 @@ namespace OpenSim.Region.Framework.Scenes
1549 Velocity = Vector3.Zero; 1600 Velocity = Vector3.Zero;
1550 SendFullUpdateToAllClients(); 1601 SendFullUpdateToAllClients();
1551 1602
1552 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1603 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1553 } 1604 }
1554 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1605 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1555 m_requestedSitTargetUUID = UUID.Zero; 1606 m_requestedSitTargetUUID = UUID.Zero;
@@ -1587,38 +1638,51 @@ namespace OpenSim.Region.Framework.Scenes
1587 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 1638 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1588 if (part != null) 1639 if (part != null)
1589 { 1640 {
1641 part.TaskInventory.LockItemsForRead(true);
1590 TaskInventoryDictionary taskIDict = part.TaskInventory; 1642 TaskInventoryDictionary taskIDict = part.TaskInventory;
1591 if (taskIDict != null) 1643 if (taskIDict != null)
1592 { 1644 {
1593 lock (taskIDict) 1645 foreach (UUID taskID in taskIDict.Keys)
1594 { 1646 {
1595 foreach (UUID taskID in taskIDict.Keys) 1647 UnRegisterControlEventsToScript(LocalId, taskID);
1596 { 1648 taskIDict[taskID].PermsMask &= ~(
1597 UnRegisterControlEventsToScript(LocalId, taskID); 1649 2048 | //PERMISSION_CONTROL_CAMERA
1598 taskIDict[taskID].PermsMask &= ~( 1650 4); // PERMISSION_TAKE_CONTROLS
1599 2048 | //PERMISSION_CONTROL_CAMERA
1600 4); // PERMISSION_TAKE_CONTROLS
1601 }
1602 } 1651 }
1603
1604 } 1652 }
1653 part.TaskInventory.LockItemsForRead(false);
1605 // Reset sit target. 1654 // Reset sit target.
1606 if (part.GetAvatarOnSitTarget() == UUID) 1655 if (part.GetAvatarOnSitTarget() == UUID)
1607 part.SetAvatarOnSitTarget(UUID.Zero); 1656 part.SetAvatarOnSitTarget(UUID.Zero);
1608
1609 m_parentPosition = part.GetWorldPosition(); 1657 m_parentPosition = part.GetWorldPosition();
1610 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1658 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1611 } 1659 }
1660 // part.GetWorldRotation() is the rotation of the object being sat on
1661 // Rotation is the sittiing Av's rotation
1662
1663 Quaternion partRot;
1664 if (part.LinkNum == 1)
1665 { // Root prim of linkset
1666 partRot = part.ParentGroup.RootPart.RotationOffset;
1667 }
1668 else
1669 { // single or child prim
1670 partRot = part.GetWorldRotation();
1671 }
1672 Quaternion partIRot = Quaternion.Inverse(partRot);
1673
1674 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1675 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1676 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ( m_pos * partRot); // + av sit offset!
1612 1677
1613 if (m_physicsActor == null) 1678 if (m_physicsActor == null)
1614 { 1679 {
1615 AddToPhysicalScene(false); 1680 AddToPhysicalScene(false);
1616 } 1681 }
1617 1682 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1618 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight);
1619 m_parentPosition = Vector3.Zero; 1683 m_parentPosition = Vector3.Zero;
1620 1684 m_parentID = 0;
1621 m_parentID = 0; 1685 part.IsOccupied = false;
1622 SendFullUpdateToAllClients(); 1686 SendFullUpdateToAllClients();
1623 m_requestedSitTargetID = 0; 1687 m_requestedSitTargetID = 0;
1624 if ((m_physicsActor != null) && (m_avHeight > 0)) 1688 if ((m_physicsActor != null) && (m_avHeight > 0))
@@ -1626,7 +1690,6 @@ namespace OpenSim.Region.Framework.Scenes
1626 SetHeight(m_avHeight); 1690 SetHeight(m_avHeight);
1627 } 1691 }
1628 } 1692 }
1629
1630 Animator.TrySetMovementAnimation("STAND"); 1693 Animator.TrySetMovementAnimation("STAND");
1631 } 1694 }
1632 1695
@@ -1657,13 +1720,9 @@ namespace OpenSim.Region.Framework.Scenes
1657 Vector3 avSitOffSet = part.SitTargetPosition; 1720 Vector3 avSitOffSet = part.SitTargetPosition;
1658 Quaternion avSitOrientation = part.SitTargetOrientation; 1721 Quaternion avSitOrientation = part.SitTargetOrientation;
1659 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1722 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1660 1723 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1661 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1724 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1662 bool SitTargetisSet = 1725 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 { 1726 {
1668 //switch the target to this prim 1727 //switch the target to this prim
1669 return part; 1728 return part;
@@ -1677,84 +1736,146 @@ namespace OpenSim.Region.Framework.Scenes
1677 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1736 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1678 { 1737 {
1679 bool autopilot = true; 1738 bool autopilot = true;
1739 Vector3 autopilotTarget = new Vector3();
1740 Quaternion sitOrientation = Quaternion.Identity;
1680 Vector3 pos = new Vector3(); 1741 Vector3 pos = new Vector3();
1681 Quaternion sitOrientation = pSitOrientation;
1682 Vector3 cameraEyeOffset = Vector3.Zero; 1742 Vector3 cameraEyeOffset = Vector3.Zero;
1683 Vector3 cameraAtOffset = Vector3.Zero; 1743 Vector3 cameraAtOffset = Vector3.Zero;
1684 bool forceMouselook = false; 1744 bool forceMouselook = false;
1685 1745
1686 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1746 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1687 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1747 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1688 if (part != null) 1748 if (part == null) return;
1689 { 1749
1690 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1750 // 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 1751 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1692 1752
1693 // Is a sit target available? 1753 // part is the prim to sit on
1694 Vector3 avSitOffSet = part.SitTargetPosition; 1754 // offset is the world-ref vector distance from that prim center to the click-spot
1695 Quaternion avSitOrientation = part.SitTargetOrientation; 1755 // UUID is the UUID of the Avatar doing the clicking
1696 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1756
1697 1757 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1698 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1758
1699 bool SitTargetisSet = 1759 // Is a sit target available?
1700 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1760 Vector3 avSitOffSet = part.SitTargetPosition;
1701 ( 1761 Quaternion avSitOrientation = part.SitTargetOrientation;
1702 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1762
1703 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1763 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 1764 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1705 ) 1765 Quaternion partRot;
1706 )); 1766 if (part.LinkNum == 1)
1707 1767 { // Root prim of linkset
1708 if (SitTargetisSet && SitTargetUnOccupied) 1768 partRot = part.ParentGroup.RootPart.RotationOffset;
1709 { 1769 }
1710 part.SetAvatarOnSitTarget(UUID); 1770 else
1711 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1771 { // single or child prim
1712 sitOrientation = avSitOrientation; 1772 partRot = part.GetWorldRotation();
1713 autopilot = false; 1773 }
1714 } 1774 Quaternion partIRot = Quaternion.Inverse(partRot);
1715 1775//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1716 pos = part.AbsolutePosition + offset; 1776 // Sit analysis rewritten by KF 091125
1717 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1777 if (SitTargetisSet) // scipted sit
1718 //{ 1778 {
1719 // offset = pos; 1779 if (!part.IsOccupied)
1720 //autopilot = false; 1780 {
1721 //} 1781//Console.WriteLine("Scripted, unoccupied");
1722 if (m_physicsActor != null) 1782 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1723 { 1783 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 1784 sitOrientation = avSitOrientation; // Change rotatione to the scripted one
1725 // We can remove the physicsActor until they stand up. 1785 autopilot = false; // Jump direct to scripted llSitPos()
1726 m_sitAvatarHeight = m_physicsActor.Size.Z; 1786 }
1727 1787 else
1728 if (autopilot) 1788 {
1729 { 1789//Console.WriteLine("Scripted, occupied");
1730 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1790 return;
1731 { 1791 }
1732 autopilot = false; 1792 }
1793 else // Not Scripted
1794 {
1795 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
1796 {
1797 // large prim & offset, ignore if other Avs sitting
1798// offset.Z -= 0.05f;
1799 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
1800 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
1801
1802//Console.WriteLine(" offset ={0}", offset);
1803//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
1804//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
1805
1806 }
1807 else // small offset
1808 {
1809//Console.WriteLine("Small offset");
1810 if (!part.IsOccupied)
1811 {
1812 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
1813 autopilotTarget = part.AbsolutePosition;
1814 }
1815 else return; // occupied small
1816 } // end large/small
1817 } // end Scripted/not
1818 cameraAtOffset = part.GetCameraAtOffset();
1819 cameraEyeOffset = part.GetCameraEyeOffset();
1820 forceMouselook = part.GetForceMouselook();
1821 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
1822 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
1733 1823
1734 RemoveFromPhysicalScene(); 1824 if (m_physicsActor != null)
1735 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 1825 {
1736 } 1826 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1737 } 1827 // We can remove the physicsActor until they stand up.
1738 else 1828 m_sitAvatarHeight = m_physicsActor.Size.Z;
1829 if (autopilot)
1830 { // its not a scripted sit
1831// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
1832 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
1739 { 1833 {
1834 autopilot = false; // close enough
1740 RemoveFromPhysicalScene(); 1835 RemoveFromPhysicalScene();
1741 } 1836 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
1837 } // else the autopilot will get us close
1838 }
1839 else
1840 { // its a scripted sit
1841 RemoveFromPhysicalScene();
1742 } 1842 }
1743
1744 cameraAtOffset = part.GetCameraAtOffset();
1745 cameraEyeOffset = part.GetCameraEyeOffset();
1746 forceMouselook = part.GetForceMouselook();
1747 } 1843 }
1844 else return; // physactor is null!
1748 1845
1749 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 1846 Vector3 offsetr; // = offset * partIRot;
1750 m_requestedSitTargetUUID = targetID; 1847 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
1848 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
1849 if (part.LinkNum < 2)
1850 { // Single, or Root prim of linkset, target is ClickOffset * RootRot
1851 offsetr = offset * partIRot;
1852 }
1853 else
1854 { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
1855 offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
1856 (offset * partRot);
1857 }
1858
1859//Console.WriteLine(" ");
1860//Console.WriteLine("link number ={0}", part.LinkNum);
1861//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
1862//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
1863//Console.WriteLine("Click offst ={0}", offset);
1864//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
1865//Console.WriteLine("offsetr ={0}", offsetr);
1866//Console.WriteLine("Camera At ={0}", cameraAtOffset);
1867//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
1868
1869 ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
1870 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1751 // This calls HandleAgentSit twice, once from here, and the client calls 1871 // This calls HandleAgentSit twice, once from here, and the client calls
1752 // HandleAgentSit itself after it gets to the location 1872 // HandleAgentSit itself after it gets to the location
1753 // It doesn't get to the location until we've moved them there though 1873 // It doesn't get to the location until we've moved them there though
1754 // which happens in HandleAgentSit :P 1874 // which happens in HandleAgentSit :P
1755 m_autopilotMoving = autopilot; 1875 m_autopilotMoving = autopilot;
1756 m_autoPilotTarget = pos; 1876 m_autoPilotTarget = autopilotTarget;
1757 m_sitAtAutoTarget = autopilot; 1877 m_sitAtAutoTarget = autopilot;
1878 m_initialSitTarget = autopilotTarget;
1758 if (!autopilot) 1879 if (!autopilot)
1759 HandleAgentSit(remoteClient, UUID); 1880 HandleAgentSit(remoteClient, UUID);
1760 } 1881 }
@@ -2051,29 +2172,62 @@ namespace OpenSim.Region.Framework.Scenes
2051 { 2172 {
2052 if (part.GetAvatarOnSitTarget() == UUID) 2173 if (part.GetAvatarOnSitTarget() == UUID)
2053 { 2174 {
2175//Console.WriteLine("Scripted Sit");
2176 // Scripted sit
2054 Vector3 sitTargetPos = part.SitTargetPosition; 2177 Vector3 sitTargetPos = part.SitTargetPosition;
2055 Quaternion sitTargetOrient = part.SitTargetOrientation; 2178 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); 2179 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2063 m_pos += SIT_TARGET_ADJUSTMENT; 2180 m_pos += SIT_TARGET_ADJUSTMENT;
2064 m_bodyRot = sitTargetOrient; 2181 m_bodyRot = sitTargetOrient;
2065 //Rotation = sitTargetOrient;
2066 m_parentPosition = part.AbsolutePosition; 2182 m_parentPosition = part.AbsolutePosition;
2067 2183 part.IsOccupied = true;
2068 //SendTerseUpdateToAllClients();
2069 } 2184 }
2070 else 2185 else
2071 { 2186 {
2072 m_pos -= part.AbsolutePosition; 2187 // if m_avUnscriptedSitPos is zero then Av sits above center
2188 // Else Av sits at m_avUnscriptedSitPos
2189
2190 // Non-scripted sit by Kitto Flora 21Nov09
2191 // Calculate angle of line from prim to Av
2192 Quaternion partIRot;
2193 if (part.LinkNum == 1)
2194 { // Root prim of linkset
2195 partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2196 }
2197 else
2198 { // single or child prim
2199 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2200 }
2201 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2202 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2203 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2204 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2205 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2206 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2207 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2208 // Av sits at world euler <0,0, z>, translated by part rotation
2209 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2210
2073 m_parentPosition = part.AbsolutePosition; 2211 m_parentPosition = part.AbsolutePosition;
2074 } 2212 part.IsOccupied = true;
2075 } 2213 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2076 else 2214 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2215 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2216 m_avUnscriptedSitPos; // adds click offset, if any
2217 //Set up raytrace to find top surface of prim
2218 Vector3 size = part.Scale;
2219 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2220 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2221 Vector3 down = new Vector3(0f, 0f, -1f);
2222//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2223 m_scene.PhysicsScene.RaycastWorld(
2224 start, // Vector3 position,
2225 down, // Vector3 direction,
2226 mag, // float length,
2227 SitAltitudeCallback); // retMethod
2228 } // end scripted/not
2229 }
2230 else // no Av
2077 { 2231 {
2078 return; 2232 return;
2079 } 2233 }
@@ -2085,11 +2239,36 @@ namespace OpenSim.Region.Framework.Scenes
2085 2239
2086 Animator.TrySetMovementAnimation(sitAnimation); 2240 Animator.TrySetMovementAnimation(sitAnimation);
2087 SendFullUpdateToAllClients(); 2241 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 } 2242 }
2243
2244 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2245 {
2246 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2247 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2248 if(hitYN)
2249 {
2250 // m_pos = Av offset from prim center to make look like on center
2251 // m_parentPosition = Actual center pos of prim
2252 // collisionPoint = spot on prim where we want to sit
2253 // collisionPoint.Z = global sit surface height
2254 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2255 Quaternion partIRot;
2256 if (part.LinkNum == 1)
2257 { // Root prim of linkset
2258 partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2259 }
2260 else
2261 { // single or child prim
2262 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2263 }
2264 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2265 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2266//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2267 m_pos += offset;
2268// ControllingClient.SendClearFollowCamProperties(part.UUID);
2269
2270 }
2271 } // End SitAltitudeCallback KF.
2093 2272
2094 /// <summary> 2273 /// <summary>
2095 /// Event handler for the 'Always run' setting on the client 2274 /// Event handler for the 'Always run' setting on the client
@@ -2119,7 +2298,7 @@ namespace OpenSim.Region.Framework.Scenes
2119 /// </summary> 2298 /// </summary>
2120 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2299 /// <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. 2300 /// <param name="rotation">The direction in which this avatar should now face.
2122 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2301 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2123 { 2302 {
2124 if (m_isChildAgent) 2303 if (m_isChildAgent)
2125 { 2304 {
@@ -2193,7 +2372,7 @@ namespace OpenSim.Region.Framework.Scenes
2193 2372
2194 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2373 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2195 m_forceToApply = direc; 2374 m_forceToApply = direc;
2196 2375 m_isNudging = Nudging;
2197 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2376 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2198 } 2377 }
2199 2378
@@ -2208,7 +2387,7 @@ namespace OpenSim.Region.Framework.Scenes
2208 const float POSITION_TOLERANCE = 0.05f; 2387 const float POSITION_TOLERANCE = 0.05f;
2209 //const int TIME_MS_TOLERANCE = 3000; 2388 //const int TIME_MS_TOLERANCE = 3000;
2210 2389
2211 SendPrimUpdates(); 2390
2212 2391
2213 if (m_newCoarseLocations) 2392 if (m_newCoarseLocations)
2214 { 2393 {
@@ -2244,6 +2423,9 @@ namespace OpenSim.Region.Framework.Scenes
2244 CheckForBorderCrossing(); 2423 CheckForBorderCrossing();
2245 CheckForSignificantMovement(); // sends update to the modules. 2424 CheckForSignificantMovement(); // sends update to the modules.
2246 } 2425 }
2426
2427 //Sending prim updates AFTER the avatar terse updates are sent
2428 SendPrimUpdates();
2247 } 2429 }
2248 2430
2249 #endregion 2431 #endregion
@@ -3097,14 +3279,25 @@ namespace OpenSim.Region.Framework.Scenes
3097 { 3279 {
3098 if (m_forceToApply.HasValue) 3280 if (m_forceToApply.HasValue)
3099 { 3281 {
3100 Vector3 force = m_forceToApply.Value;
3101 3282
3283 Vector3 force = m_forceToApply.Value;
3102 m_updateflag = true; 3284 m_updateflag = true;
3103// movementvector = force;
3104 Velocity = force; 3285 Velocity = force;
3105 3286
3106 m_forceToApply = null; 3287 m_forceToApply = null;
3107 } 3288 }
3289 else
3290 {
3291 if (m_isNudging)
3292 {
3293 Vector3 force = Vector3.Zero;
3294
3295 m_updateflag = true;
3296 Velocity = force;
3297 m_isNudging = false;
3298 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3299 }
3300 }
3108 } 3301 }
3109 3302
3110 public override void SetText(string text, Vector3 color, double alpha) 3303 public override void SetText(string text, Vector3 color, double alpha)
@@ -3156,18 +3349,29 @@ namespace OpenSim.Region.Framework.Scenes
3156 { 3349 {
3157 if (e == null) 3350 if (e == null)
3158 return; 3351 return;
3159 3352
3160 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3353 // 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 3354 // as of this comment the interval is set in AddToPhysicalScene
3163 if (Animator!=null) 3355 if (Animator!=null)
3164 Animator.UpdateMovementAnimations(); 3356 {
3357 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3358 { // else its will lock out other animation changes, like ground sit.
3359 Animator.UpdateMovementAnimations();
3360 m_updateCount--;
3361 }
3362 }
3165 3363
3166 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3364 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3167 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3365 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3168 3366
3169 CollisionPlane = Vector4.UnitW; 3367 CollisionPlane = Vector4.UnitW;
3170 3368
3369 if (m_lastColCount != coldata.Count)
3370 {
3371 m_updateCount = UPDATE_COUNT;
3372 m_lastColCount = coldata.Count;
3373 }
3374
3171 if (coldata.Count != 0 && Animator != null) 3375 if (coldata.Count != 0 && Animator != null)
3172 { 3376 {
3173 switch (Animator.CurrentMovementAnimation) 3377 switch (Animator.CurrentMovementAnimation)
@@ -3815,5 +4019,16 @@ namespace OpenSim.Region.Framework.Scenes
3815 m_reprioritization_called = false; 4019 m_reprioritization_called = false;
3816 } 4020 }
3817 } 4021 }
4022
4023 private Vector3 Quat2Euler(Quaternion rot){
4024 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4025 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4026 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4027 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4028 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4029 return(new Vector3(x,y,z));
4030 }
4031
4032
3818 } 4033 }
3819} \ No newline at end of file 4034}
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;