diff options
author | onefang | 2019-09-11 16:36:50 +1000 |
---|---|---|
committer | onefang | 2019-09-11 16:36:50 +1000 |
commit | 50cd1ffd32f69228e566f2b0b89f86ea0d9fe489 (patch) | |
tree | 52f2ab0c04f1a5d7d6ac5dc872981b4b156447e7 /OpenSim/Region/Framework/Scenes/SceneGraph.cs | |
parent | Renamed branch to SledjChisl. (diff) | |
parent | Bump to release flavour, build 0. (diff) | |
download | opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.zip opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.gz opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.bz2 opensim-SC_OLD-50cd1ffd32f69228e566f2b0b89f86ea0d9fe489.tar.xz |
Merge branch 'SledjChisl'
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 833 |
1 files changed, 466 insertions, 367 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index e0080f2..61a243d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
41 | { | 41 | { |
42 | public delegate void PhysicsCrash(); | 42 | public delegate void PhysicsCrash(); |
43 | 43 | ||
44 | public delegate void AttachToBackupDelegate(SceneObjectGroup sog); | ||
45 | |||
46 | public delegate void DetachFromBackupDelegate(SceneObjectGroup sog); | ||
47 | |||
48 | public delegate void ChangedBackupDelegate(SceneObjectGroup sog); | ||
49 | |||
44 | /// <summary> | 50 | /// <summary> |
45 | /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components | 51 | /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components |
46 | /// should be migrated out over time. | 52 | /// should be migrated out over time. |
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
54 | protected internal event PhysicsCrash UnRecoverableError; | 60 | protected internal event PhysicsCrash UnRecoverableError; |
55 | private PhysicsCrash handlerPhysicsCrash = null; | 61 | private PhysicsCrash handlerPhysicsCrash = null; |
56 | 62 | ||
63 | public event AttachToBackupDelegate OnAttachToBackup; | ||
64 | public event DetachFromBackupDelegate OnDetachFromBackup; | ||
65 | public event ChangedBackupDelegate OnChangeBackup; | ||
66 | |||
57 | #endregion | 67 | #endregion |
58 | 68 | ||
59 | #region Fields | 69 | #region Fields |
60 | 70 | ||
61 | protected object m_presenceLock = new object(); | 71 | protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); |
62 | protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); | 72 | protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); |
63 | protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); | 73 | protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); |
64 | 74 | ||
@@ -77,21 +87,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
77 | protected int m_scriptLPS = 0; | 87 | protected int m_scriptLPS = 0; |
78 | 88 | ||
79 | protected internal PhysicsScene _PhyScene; | 89 | protected internal PhysicsScene _PhyScene; |
80 | 90 | ||
81 | /// <summary> | 91 | /// <summary> |
82 | /// Index the SceneObjectGroup for each part by the root part's UUID. | 92 | /// Index the SceneObjectGroup for each part by the root part's UUID. |
83 | /// </summary> | 93 | /// </summary> |
84 | protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>(); | 94 | protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>(); |
85 | 95 | ||
86 | /// <summary> | 96 | /// <summary> |
87 | /// Index the SceneObjectGroup for each part by that part's UUID. | 97 | /// Index the SceneObjectGroup for each part by that part's UUID. |
88 | /// </summary> | 98 | /// </summary> |
89 | protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullPartID = new Dictionary<UUID, SceneObjectGroup>(); | 99 | protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullPartID = new Dictionary<UUID, SceneObjectGroup>(); |
90 | 100 | ||
91 | /// <summary> | 101 | /// <summary> |
92 | /// Index the SceneObjectGroup for each part by that part's local ID. | 102 | /// Index the SceneObjectGroup for each part by that part's local ID. |
93 | /// </summary> | 103 | /// </summary> |
94 | protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>(); | 104 | protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>(); |
95 | 105 | ||
96 | /// <summary> | 106 | /// <summary> |
97 | /// Lock to prevent object group update, linking, delinking and duplication operations from running concurrently. | 107 | /// Lock to prevent object group update, linking, delinking and duplication operations from running concurrently. |
@@ -111,11 +121,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
111 | 121 | ||
112 | public PhysicsScene PhysicsScene | 122 | public PhysicsScene PhysicsScene |
113 | { | 123 | { |
114 | get | 124 | get |
115 | { | 125 | { |
116 | if (_PhyScene == null) | 126 | if (_PhyScene == null) |
117 | _PhyScene = m_parentScene.RequestModuleInterface<PhysicsScene>(); | 127 | _PhyScene = m_parentScene.RequestModuleInterface<PhysicsScene>(); |
118 | return _PhyScene; | 128 | return _PhyScene; |
119 | } | 129 | } |
120 | set | 130 | set |
121 | { | 131 | { |
@@ -134,13 +144,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
134 | 144 | ||
135 | protected internal void Close() | 145 | protected internal void Close() |
136 | { | 146 | { |
137 | lock (m_presenceLock) | 147 | m_scenePresencesLock.EnterWriteLock(); |
148 | try | ||
138 | { | 149 | { |
139 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); | 150 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); |
140 | List<ScenePresence> newlist = new List<ScenePresence>(); | 151 | List<ScenePresence> newlist = new List<ScenePresence>(); |
141 | m_scenePresenceMap = newmap; | 152 | m_scenePresenceMap = newmap; |
142 | m_scenePresenceArray = newlist; | 153 | m_scenePresenceArray = newlist; |
143 | } | 154 | } |
155 | finally | ||
156 | { | ||
157 | m_scenePresencesLock.ExitWriteLock(); | ||
158 | } | ||
144 | 159 | ||
145 | lock (SceneObjectGroupsByFullID) | 160 | lock (SceneObjectGroupsByFullID) |
146 | SceneObjectGroupsByFullID.Clear(); | 161 | SceneObjectGroupsByFullID.Clear(); |
@@ -200,13 +215,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
200 | // the joint in the Scene does not exist in the PhysicsScene. | 215 | // the joint in the Scene does not exist in the PhysicsScene. |
201 | // | 216 | // |
202 | // To solve this, we have an event in the PhysicsScene that is fired when a joint | 217 | // To solve this, we have an event in the PhysicsScene that is fired when a joint |
203 | // has changed position (because one of its associated PhysicsActors has changed | 218 | // has changed position (because one of its associated PhysicsActors has changed |
204 | // position). | 219 | // position). |
205 | // | 220 | // |
206 | // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate(). | 221 | // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate(). |
222 | |||
207 | return PhysicsScene.Simulate((float)elapsed); | 223 | return PhysicsScene.Simulate((float)elapsed); |
208 | } | 224 | } |
209 | 225 | ||
226 | protected internal void ProcessPhysicsPreSimulation() | ||
227 | { | ||
228 | if(PhysicsScene != null) | ||
229 | PhysicsScene.ProcessPreSimulation(); | ||
230 | } | ||
231 | |||
210 | protected internal void UpdateScenePresenceMovement() | 232 | protected internal void UpdateScenePresenceMovement() |
211 | { | 233 | { |
212 | ForEachScenePresence(delegate(ScenePresence presence) | 234 | ForEachScenePresence(delegate(ScenePresence presence) |
@@ -220,17 +242,32 @@ namespace OpenSim.Region.Framework.Scenes | |||
220 | coarseLocations = new List<Vector3>(); | 242 | coarseLocations = new List<Vector3>(); |
221 | avatarUUIDs = new List<UUID>(); | 243 | avatarUUIDs = new List<UUID>(); |
222 | 244 | ||
245 | // coarse locations are sent as BYTE, so limited to the 255m max of normal regions | ||
246 | // try to work around that scale down X and Y acording to region size, so reducing the resolution | ||
247 | // | ||
248 | // viewers need to scale up | ||
249 | float scaleX = (float)m_parentScene.RegionInfo.RegionSizeX / (float)Constants.RegionSize; | ||
250 | if (scaleX == 0) | ||
251 | scaleX = 1.0f; | ||
252 | scaleX = 1.0f / scaleX; | ||
253 | float scaleY = (float)m_parentScene.RegionInfo.RegionSizeY / (float)Constants.RegionSize; | ||
254 | if (scaleY == 0) | ||
255 | scaleY = 1.0f; | ||
256 | scaleY = 1.0f / scaleY; | ||
257 | |||
223 | List<ScenePresence> presences = GetScenePresences(); | 258 | List<ScenePresence> presences = GetScenePresences(); |
224 | for (int i = 0; i < Math.Min(presences.Count, maxLocations); ++i) | 259 | for (int i = 0; i < Math.Min(presences.Count, maxLocations); ++i) |
225 | { | 260 | { |
226 | ScenePresence sp = presences[i]; | 261 | ScenePresence sp = presences[i]; |
227 | 262 | ||
228 | // If this presence is a child agent, we don't want its coarse locations | 263 | // If this presence is a child agent, we don't want its coarse locations |
229 | if (sp.IsChildAgent) | 264 | if (sp.IsChildAgent) |
230 | continue; | 265 | continue; |
266 | Vector3 pos = sp.AbsolutePosition; | ||
267 | pos.X *= scaleX; | ||
268 | pos.Y *= scaleY; | ||
231 | 269 | ||
232 | coarseLocations.Add(sp.AbsolutePosition); | 270 | coarseLocations.Add(pos); |
233 | |||
234 | avatarUUIDs.Add(sp.UUID); | 271 | avatarUUIDs.Add(sp.UUID); |
235 | } | 272 | } |
236 | } | 273 | } |
@@ -261,15 +298,55 @@ namespace OpenSim.Region.Framework.Scenes | |||
261 | protected internal bool AddRestoredSceneObject( | 298 | protected internal bool AddRestoredSceneObject( |
262 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 299 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
263 | { | 300 | { |
301 | // temporary checks to remove after varsize suport | ||
302 | float regionSizeX = m_parentScene.RegionInfo.RegionSizeX; | ||
303 | if (regionSizeX == 0) | ||
304 | regionSizeX = Constants.RegionSize; | ||
305 | float regionSizeY = m_parentScene.RegionInfo.RegionSizeY; | ||
306 | if (regionSizeY == 0) | ||
307 | regionSizeY = Constants.RegionSize; | ||
308 | |||
309 | // KF: Check for out-of-region, move inside and make static. | ||
310 | Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, | ||
311 | sceneObject.RootPart.GroupPosition.Y, | ||
312 | sceneObject.RootPart.GroupPosition.Z); | ||
313 | bool clampZ = m_parentScene.ClampNegativeZ; | ||
314 | |||
315 | if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || (npos.Z < 0.0 && clampZ) || | ||
316 | npos.X > regionSizeX || | ||
317 | npos.Y > regionSizeY)) | ||
318 | { | ||
319 | if (npos.X < 0.0) npos.X = 1.0f; | ||
320 | if (npos.Y < 0.0) npos.Y = 1.0f; | ||
321 | if (npos.Z < 0.0 && clampZ) npos.Z = 0.0f; | ||
322 | if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f; | ||
323 | if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f; | ||
324 | |||
325 | SceneObjectPart rootpart = sceneObject.RootPart; | ||
326 | rootpart.GroupPosition = npos; | ||
327 | |||
328 | foreach (SceneObjectPart part in sceneObject.Parts) | ||
329 | { | ||
330 | if (part == rootpart) | ||
331 | continue; | ||
332 | part.GroupPosition = npos; | ||
333 | } | ||
334 | rootpart.Velocity = Vector3.Zero; | ||
335 | rootpart.AngularVelocity = Vector3.Zero; | ||
336 | rootpart.Acceleration = Vector3.Zero; | ||
337 | } | ||
338 | |||
339 | bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | ||
340 | |||
264 | if (attachToBackup && (!alreadyPersisted)) | 341 | if (attachToBackup && (!alreadyPersisted)) |
265 | { | 342 | { |
266 | sceneObject.ForceInventoryPersistence(); | 343 | sceneObject.ForceInventoryPersistence(); |
267 | sceneObject.HasGroupChanged = true; | 344 | sceneObject.HasGroupChanged = true; |
268 | } | 345 | } |
269 | 346 | sceneObject.InvalidateDeepEffectivePerms(); | |
270 | return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | 347 | return ret; |
271 | } | 348 | } |
272 | 349 | ||
273 | /// <summary> | 350 | /// <summary> |
274 | /// Add a newly created object to the scene. This will both update the scene, and send information about the | 351 | /// Add a newly created object to the scene. This will both update the scene, and send information about the |
275 | /// new object to all clients interested in the scene. | 352 | /// new object to all clients interested in the scene. |
@@ -284,18 +361,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
284 | /// </returns> | 361 | /// </returns> |
285 | protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) | 362 | protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) |
286 | { | 363 | { |
287 | // Ensure that we persist this new scene object if it's not an | 364 | |
365 | bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | ||
366 | |||
367 | // Ensure that we persist this new scene object if it's not an | ||
288 | // attachment | 368 | // attachment |
369 | |||
289 | if (attachToBackup) | 370 | if (attachToBackup) |
290 | sceneObject.HasGroupChanged = true; | 371 | sceneObject.HasGroupChanged = true; |
291 | 372 | ||
292 | return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | 373 | return ret; |
293 | } | 374 | } |
294 | 375 | ||
295 | /// <summary> | 376 | /// <summary> |
296 | /// Add a newly created object to the scene. | 377 | /// Add a newly created object to the scene. |
297 | /// </summary> | 378 | /// </summary> |
298 | /// | 379 | /// |
299 | /// This method does not send updates to the client - callers need to handle this themselves. | 380 | /// This method does not send updates to the client - callers need to handle this themselves. |
300 | /// Caller should also trigger EventManager.TriggerObjectAddedToScene | 381 | /// Caller should also trigger EventManager.TriggerObjectAddedToScene |
301 | /// <param name="sceneObject"></param> | 382 | /// <param name="sceneObject"></param> |
@@ -307,26 +388,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
307 | public bool AddNewSceneObject( | 388 | public bool AddNewSceneObject( |
308 | SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) | 389 | SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) |
309 | { | 390 | { |
310 | AddNewSceneObject(sceneObject, attachToBackup, false); | ||
311 | |||
312 | if (pos != null) | 391 | if (pos != null) |
313 | sceneObject.AbsolutePosition = (Vector3)pos; | 392 | sceneObject.AbsolutePosition = (Vector3)pos; |
314 | 393 | ||
394 | if (rot != null) | ||
395 | sceneObject.UpdateGroupRotationR((Quaternion)rot); | ||
396 | |||
397 | AddNewSceneObject(sceneObject, attachToBackup, false); | ||
398 | |||
315 | if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) | 399 | if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) |
316 | { | 400 | { |
317 | sceneObject.ClearPartAttachmentData(); | 401 | sceneObject.ClearPartAttachmentData(); |
318 | } | 402 | } |
319 | 403 | ||
320 | if (rot != null) | ||
321 | sceneObject.UpdateGroupRotationR((Quaternion)rot); | ||
322 | |||
323 | PhysicsActor pa = sceneObject.RootPart.PhysActor; | 404 | PhysicsActor pa = sceneObject.RootPart.PhysActor; |
324 | if (pa != null && pa.IsPhysical && vel != Vector3.Zero) | 405 | if (pa != null && pa.IsPhysical && vel != Vector3.Zero) |
325 | { | 406 | { |
326 | sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); | 407 | sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); |
327 | sceneObject.Velocity = vel; | ||
328 | } | 408 | } |
329 | 409 | ||
330 | return true; | 410 | return true; |
331 | } | 411 | } |
332 | 412 | ||
@@ -351,6 +431,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
351 | /// </returns> | 431 | /// </returns> |
352 | protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) | 432 | protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) |
353 | { | 433 | { |
434 | if (sceneObject == null) | ||
435 | { | ||
436 | m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object"); | ||
437 | return false; | ||
438 | } | ||
354 | if (sceneObject.UUID == UUID.Zero) | 439 | if (sceneObject.UUID == UUID.Zero) |
355 | { | 440 | { |
356 | m_log.ErrorFormat( | 441 | m_log.ErrorFormat( |
@@ -383,9 +468,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
383 | { | 468 | { |
384 | Vector3 scale = part.Shape.Scale; | 469 | Vector3 scale = part.Shape.Scale; |
385 | 470 | ||
386 | scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); | 471 | scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); |
387 | scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); | 472 | scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); |
388 | scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); | 473 | scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); |
389 | 474 | ||
390 | part.Shape.Scale = scale; | 475 | part.Shape.Scale = scale; |
391 | } | 476 | } |
@@ -406,36 +491,39 @@ namespace OpenSim.Region.Framework.Scenes | |||
406 | 491 | ||
407 | sceneObject.AttachToScene(m_parentScene); | 492 | sceneObject.AttachToScene(m_parentScene); |
408 | 493 | ||
409 | if (sendClientUpdates) | ||
410 | sceneObject.ScheduleGroupForFullUpdate(); | ||
411 | |||
412 | Entities.Add(sceneObject); | 494 | Entities.Add(sceneObject); |
413 | 495 | ||
414 | if (attachToBackup) | ||
415 | sceneObject.AttachToBackup(); | ||
416 | |||
417 | lock (SceneObjectGroupsByFullID) | 496 | lock (SceneObjectGroupsByFullID) |
418 | SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; | 497 | SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; |
419 | 498 | ||
420 | lock (SceneObjectGroupsByFullPartID) | 499 | foreach (SceneObjectPart part in parts) |
421 | { | 500 | { |
422 | foreach (SceneObjectPart part in parts) | 501 | lock (SceneObjectGroupsByFullPartID) |
423 | SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; | 502 | SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; |
424 | } | ||
425 | 503 | ||
426 | lock (SceneObjectGroupsByLocalPartID) | 504 | lock (SceneObjectGroupsByLocalPartID) |
427 | { | ||
428 | // m_log.DebugFormat( | ||
429 | // "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}", | ||
430 | // sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName); | ||
431 | |||
432 | foreach (SceneObjectPart part in parts) | ||
433 | SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; | 505 | SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; |
434 | } | 506 | } |
435 | 507 | ||
508 | if (sendClientUpdates) | ||
509 | sceneObject.ScheduleGroupForFullUpdate(); | ||
510 | |||
511 | if (attachToBackup) | ||
512 | sceneObject.AttachToBackup(); | ||
513 | |||
436 | return true; | 514 | return true; |
437 | } | 515 | } |
438 | 516 | ||
517 | public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp) | ||
518 | { | ||
519 | // no tests, caller has responsability... | ||
520 | lock (SceneObjectGroupsByFullPartID) | ||
521 | SceneObjectGroupsByFullPartID[part.UUID] = grp; | ||
522 | |||
523 | lock (SceneObjectGroupsByLocalPartID) | ||
524 | SceneObjectGroupsByLocalPartID[part.LocalId] = grp; | ||
525 | } | ||
526 | |||
439 | /// <summary> | 527 | /// <summary> |
440 | /// Delete an object from the scene | 528 | /// Delete an object from the scene |
441 | /// </summary> | 529 | /// </summary> |
@@ -461,6 +549,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
461 | // that are part of the Scene Object being removed | 549 | // that are part of the Scene Object being removed |
462 | m_numTotalPrim -= grp.PrimCount; | 550 | m_numTotalPrim -= grp.PrimCount; |
463 | 551 | ||
552 | bool isPh = (grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics; | ||
553 | int nphysparts = 0; | ||
464 | // Go through all parts (primitives and meshes) of this Scene Object | 554 | // Go through all parts (primitives and meshes) of this Scene Object |
465 | foreach (SceneObjectPart part in grp.Parts) | 555 | foreach (SceneObjectPart part in grp.Parts) |
466 | { | 556 | { |
@@ -471,30 +561,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
471 | m_numMesh--; | 561 | m_numMesh--; |
472 | else | 562 | else |
473 | m_numPrim--; | 563 | m_numPrim--; |
564 | |||
565 | if(isPh && part.PhysicsShapeType != (byte)PhysShapeType.none) | ||
566 | nphysparts++; | ||
474 | } | 567 | } |
475 | 568 | ||
476 | if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) | 569 | if (nphysparts > 0 ) |
477 | RemovePhysicalPrim(grp.PrimCount); | 570 | RemovePhysicalPrim(nphysparts); |
478 | } | 571 | } |
479 | 572 | ||
573 | bool ret = Entities.Remove(uuid); | ||
574 | |||
480 | lock (SceneObjectGroupsByFullID) | 575 | lock (SceneObjectGroupsByFullID) |
481 | SceneObjectGroupsByFullID.Remove(grp.UUID); | 576 | SceneObjectGroupsByFullID.Remove(grp.UUID); |
482 | 577 | ||
483 | lock (SceneObjectGroupsByFullPartID) | 578 | SceneObjectPart[] parts = grp.Parts; |
579 | for (int i = 0; i < parts.Length; i++) | ||
484 | { | 580 | { |
485 | SceneObjectPart[] parts = grp.Parts; | 581 | lock (SceneObjectGroupsByFullPartID) |
486 | for (int i = 0; i < parts.Length; i++) | ||
487 | SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); | 582 | SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); |
488 | } | ||
489 | 583 | ||
490 | lock (SceneObjectGroupsByLocalPartID) | 584 | lock (SceneObjectGroupsByLocalPartID) |
491 | { | ||
492 | SceneObjectPart[] parts = grp.Parts; | ||
493 | for (int i = 0; i < parts.Length; i++) | ||
494 | SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); | 585 | SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); |
495 | } | 586 | } |
496 | 587 | ||
497 | return Entities.Remove(uuid); | 588 | return ret; |
498 | } | 589 | } |
499 | 590 | ||
500 | /// <summary> | 591 | /// <summary> |
@@ -509,6 +600,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
509 | m_updateList[obj.UUID] = obj; | 600 | m_updateList[obj.UUID] = obj; |
510 | } | 601 | } |
511 | 602 | ||
603 | public void FireAttachToBackup(SceneObjectGroup obj) | ||
604 | { | ||
605 | if (OnAttachToBackup != null) | ||
606 | { | ||
607 | OnAttachToBackup(obj); | ||
608 | } | ||
609 | } | ||
610 | |||
611 | public void FireDetachFromBackup(SceneObjectGroup obj) | ||
612 | { | ||
613 | if (OnDetachFromBackup != null) | ||
614 | { | ||
615 | OnDetachFromBackup(obj); | ||
616 | } | ||
617 | } | ||
618 | |||
619 | public void FireChangeBackup(SceneObjectGroup obj) | ||
620 | { | ||
621 | if (OnChangeBackup != null) | ||
622 | { | ||
623 | OnChangeBackup(obj); | ||
624 | } | ||
625 | } | ||
626 | |||
512 | /// <summary> | 627 | /// <summary> |
513 | /// Process all pending updates | 628 | /// Process all pending updates |
514 | /// </summary> | 629 | /// </summary> |
@@ -520,7 +635,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
520 | { | 635 | { |
521 | List<SceneObjectGroup> updates; | 636 | List<SceneObjectGroup> updates; |
522 | 637 | ||
523 | // Some updates add more updates to the updateList. | 638 | // Some updates add more updates to the updateList. |
524 | // Get the current list of updates and clear the list before iterating | 639 | // Get the current list of updates and clear the list before iterating |
525 | lock (m_updateList) | 640 | lock (m_updateList) |
526 | { | 641 | { |
@@ -600,7 +715,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
600 | 715 | ||
601 | Entities[presence.UUID] = presence; | 716 | Entities[presence.UUID] = presence; |
602 | 717 | ||
603 | lock (m_presenceLock) | 718 | m_scenePresencesLock.EnterWriteLock(); |
719 | try | ||
604 | { | 720 | { |
605 | m_numChildAgents++; | 721 | m_numChildAgents++; |
606 | 722 | ||
@@ -626,6 +742,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
626 | m_scenePresenceMap = newmap; | 742 | m_scenePresenceMap = newmap; |
627 | m_scenePresenceArray = newlist; | 743 | m_scenePresenceArray = newlist; |
628 | } | 744 | } |
745 | finally | ||
746 | { | ||
747 | m_scenePresencesLock.ExitWriteLock(); | ||
748 | } | ||
629 | 749 | ||
630 | return presence; | 750 | return presence; |
631 | } | 751 | } |
@@ -642,11 +762,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
642 | agentID); | 762 | agentID); |
643 | } | 763 | } |
644 | 764 | ||
645 | lock (m_presenceLock) | 765 | m_scenePresencesLock.EnterWriteLock(); |
766 | try | ||
646 | { | 767 | { |
647 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 768 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
648 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 769 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
649 | 770 | ||
650 | // Remove the presence reference from the dictionary | 771 | // Remove the presence reference from the dictionary |
651 | if (newmap.ContainsKey(agentID)) | 772 | if (newmap.ContainsKey(agentID)) |
652 | { | 773 | { |
@@ -664,6 +785,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
664 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); | 785 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); |
665 | } | 786 | } |
666 | } | 787 | } |
788 | finally | ||
789 | { | ||
790 | m_scenePresencesLock.ExitWriteLock(); | ||
791 | } | ||
667 | } | 792 | } |
668 | 793 | ||
669 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) | 794 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) |
@@ -754,7 +879,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
754 | #endregion | 879 | #endregion |
755 | 880 | ||
756 | #region Get Methods | 881 | #region Get Methods |
757 | 882 | ||
758 | /// <summary> | 883 | /// <summary> |
759 | /// Get the controlling client for the given avatar, if there is one. | 884 | /// Get the controlling client for the given avatar, if there is one. |
760 | /// | 885 | /// |
@@ -892,7 +1017,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
892 | m_log.WarnFormat( | 1017 | m_log.WarnFormat( |
893 | "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.", | 1018 | "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.", |
894 | sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); | 1019 | sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); |
895 | 1020 | m_log.WarnFormat("stack: {0}", Environment.StackTrace); | |
896 | SceneObjectGroupsByLocalPartID.Remove(localID); | 1021 | SceneObjectGroupsByLocalPartID.Remove(localID); |
897 | } | 1022 | } |
898 | } | 1023 | } |
@@ -1066,11 +1191,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1066 | protected internal SceneObjectPart GetSceneObjectPart(uint localID) | 1191 | protected internal SceneObjectPart GetSceneObjectPart(uint localID) |
1067 | { | 1192 | { |
1068 | SceneObjectGroup group = GetGroupByPrim(localID); | 1193 | SceneObjectGroup group = GetGroupByPrim(localID); |
1069 | if (group == null) | 1194 | if (group == null || group.IsDeleted) |
1070 | return null; | 1195 | return null; |
1071 | return group.GetPart(localID); | 1196 | return group.GetPart(localID); |
1072 | } | 1197 | } |
1073 | 1198 | ||
1074 | /// <summary> | 1199 | /// <summary> |
1075 | /// Get a prim by name from the scene (will return the first | 1200 | /// Get a prim by name from the scene (will return the first |
1076 | /// found, if there are more than one prim with the same name) | 1201 | /// found, if there are more than one prim with the same name) |
@@ -1089,7 +1214,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1089 | foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts) | 1214 | foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts) |
1090 | { | 1215 | { |
1091 | // m_log.DebugFormat("[SCENE GRAPH]: Part {0} has name {1}", p.UUID, p.Name); | 1216 | // m_log.DebugFormat("[SCENE GRAPH]: Part {0} has name {1}", p.UUID, p.Name); |
1092 | 1217 | ||
1093 | if (p.Name == name) | 1218 | if (p.Name == name) |
1094 | { | 1219 | { |
1095 | sop = p; | 1220 | sop = p; |
@@ -1188,7 +1313,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1188 | /// <summary> | 1313 | /// <summary> |
1189 | /// Performs action on all scene presences. This can ultimately run the actions in parallel but | 1314 | /// Performs action on all scene presences. This can ultimately run the actions in parallel but |
1190 | /// any delegates passed in will need to implement their own locking on data they reference and | 1315 | /// any delegates passed in will need to implement their own locking on data they reference and |
1191 | /// modify outside of the scope of the delegate. | 1316 | /// modify outside of the scope of the delegate. |
1192 | /// </summary> | 1317 | /// </summary> |
1193 | /// <param name="action"></param> | 1318 | /// <param name="action"></param> |
1194 | public void ForEachScenePresence(Action<ScenePresence> action) | 1319 | public void ForEachScenePresence(Action<ScenePresence> action) |
@@ -1223,11 +1348,57 @@ namespace OpenSim.Region.Framework.Scenes | |||
1223 | } | 1348 | } |
1224 | } | 1349 | } |
1225 | } | 1350 | } |
1226 | 1351 | ||
1227 | #endregion | 1352 | #endregion |
1228 | 1353 | ||
1229 | #region Client Event handlers | 1354 | #region Client Event handlers |
1230 | 1355 | ||
1356 | protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient) | ||
1357 | { | ||
1358 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
1359 | ObjectChangeData data = (ObjectChangeData)odata; | ||
1360 | |||
1361 | if (part != null) | ||
1362 | { | ||
1363 | SceneObjectGroup grp = part.ParentGroup; | ||
1364 | if (grp != null) | ||
1365 | { | ||
1366 | if (m_parentScene.Permissions.CanEditObject(grp, remoteClient)) | ||
1367 | { | ||
1368 | // These two are exceptions SL makes in the interpretation | ||
1369 | // of the change flags. Must check them here because otherwise | ||
1370 | // the group flag (see below) would be lost | ||
1371 | if (data.change == ObjectChangeType.groupS) | ||
1372 | data.change = ObjectChangeType.primS; | ||
1373 | if (data.change == ObjectChangeType.groupPS) | ||
1374 | data.change = ObjectChangeType.primPS; | ||
1375 | part.StoreUndoState(data.change); // lets test only saving what we changed | ||
1376 | grp.doChangeObject(part, (ObjectChangeData)data); | ||
1377 | } | ||
1378 | else | ||
1379 | { | ||
1380 | // Is this any kind of group operation? | ||
1381 | if ((data.change & ObjectChangeType.Group) != 0) | ||
1382 | { | ||
1383 | // Is a move and/or rotation requested? | ||
1384 | if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0) | ||
1385 | { | ||
1386 | // Are we allowed to move it? | ||
1387 | if (m_parentScene.Permissions.CanMoveObject(grp, remoteClient)) | ||
1388 | { | ||
1389 | // Strip all but move and rotation from request | ||
1390 | data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation); | ||
1391 | |||
1392 | part.StoreUndoState(data.change); | ||
1393 | grp.doChangeObject(part, (ObjectChangeData)data); | ||
1394 | } | ||
1395 | } | ||
1396 | } | ||
1397 | } | ||
1398 | } | ||
1399 | } | ||
1400 | } | ||
1401 | |||
1231 | /// <summary> | 1402 | /// <summary> |
1232 | /// Update the scale of an individual prim. | 1403 | /// Update the scale of an individual prim. |
1233 | /// </summary> | 1404 | /// </summary> |
@@ -1240,9 +1411,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
1240 | 1411 | ||
1241 | if (part != null) | 1412 | if (part != null) |
1242 | { | 1413 | { |
1243 | if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) | 1414 | if (m_parentScene.Permissions.CanEditObject(part.ParentGroup, remoteClient)) |
1244 | { | 1415 | { |
1416 | bool physbuild = false; | ||
1417 | if (part.ParentGroup.RootPart.PhysActor != null) | ||
1418 | { | ||
1419 | part.ParentGroup.RootPart.PhysActor.Building = true; | ||
1420 | physbuild = true; | ||
1421 | } | ||
1422 | |||
1245 | part.Resize(scale); | 1423 | part.Resize(scale); |
1424 | |||
1425 | if (physbuild) | ||
1426 | part.ParentGroup.RootPart.PhysActor.Building = false; | ||
1246 | } | 1427 | } |
1247 | } | 1428 | } |
1248 | } | 1429 | } |
@@ -1252,9 +1433,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
1252 | SceneObjectGroup group = GetGroupByPrim(localID); | 1433 | SceneObjectGroup group = GetGroupByPrim(localID); |
1253 | if (group != null) | 1434 | if (group != null) |
1254 | { | 1435 | { |
1255 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1436 | if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) |
1256 | { | 1437 | { |
1438 | bool physbuild = false; | ||
1439 | if (group.RootPart.PhysActor != null) | ||
1440 | { | ||
1441 | group.RootPart.PhysActor.Building = true; | ||
1442 | physbuild = true; | ||
1443 | } | ||
1444 | |||
1257 | group.GroupResize(scale); | 1445 | group.GroupResize(scale); |
1446 | |||
1447 | if (physbuild) | ||
1448 | group.RootPart.PhysActor.Building = false; | ||
1258 | } | 1449 | } |
1259 | } | 1450 | } |
1260 | } | 1451 | } |
@@ -1288,7 +1479,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1288 | SceneObjectGroup group = GetGroupByPrim(localID); | 1479 | SceneObjectGroup group = GetGroupByPrim(localID); |
1289 | if (group != null) | 1480 | if (group != null) |
1290 | { | 1481 | { |
1291 | if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) | 1482 | if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) |
1292 | { | 1483 | { |
1293 | group.UpdateSingleRotation(rot, localID); | 1484 | group.UpdateSingleRotation(rot, localID); |
1294 | } | 1485 | } |
@@ -1306,7 +1497,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1306 | SceneObjectGroup group = GetGroupByPrim(localID); | 1497 | SceneObjectGroup group = GetGroupByPrim(localID); |
1307 | if (group != null) | 1498 | if (group != null) |
1308 | { | 1499 | { |
1309 | if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) | 1500 | if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) |
1310 | { | 1501 | { |
1311 | group.UpdateSingleRotation(rot, pos, localID); | 1502 | group.UpdateSingleRotation(rot, pos, localID); |
1312 | } | 1503 | } |
@@ -1324,7 +1515,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1324 | SceneObjectGroup group = GetGroupByPrim(localID); | 1515 | SceneObjectGroup group = GetGroupByPrim(localID); |
1325 | if (group != null) | 1516 | if (group != null) |
1326 | { | 1517 | { |
1327 | if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) | 1518 | if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) |
1328 | { | 1519 | { |
1329 | group.UpdateGroupRotationR(rot); | 1520 | group.UpdateGroupRotationR(rot); |
1330 | } | 1521 | } |
@@ -1343,7 +1534,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1343 | SceneObjectGroup group = GetGroupByPrim(localID); | 1534 | SceneObjectGroup group = GetGroupByPrim(localID); |
1344 | if (group != null) | 1535 | if (group != null) |
1345 | { | 1536 | { |
1346 | if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) | 1537 | if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) |
1347 | { | 1538 | { |
1348 | group.UpdateGroupRotationPR(pos, rot); | 1539 | group.UpdateGroupRotationPR(pos, rot); |
1349 | } | 1540 | } |
@@ -1361,7 +1552,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1361 | SceneObjectGroup group = GetGroupByPrim(localID); | 1552 | SceneObjectGroup group = GetGroupByPrim(localID); |
1362 | if (group != null) | 1553 | if (group != null) |
1363 | { | 1554 | { |
1364 | if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId) || group.IsAttachment) | 1555 | if (m_parentScene.Permissions.CanMoveObject(group, remoteClient) || group.IsAttachment) |
1365 | { | 1556 | { |
1366 | group.UpdateSinglePosition(pos, localID); | 1557 | group.UpdateSinglePosition(pos, localID); |
1367 | } | 1558 | } |
@@ -1376,30 +1567,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
1376 | /// <param name="remoteClient"></param> | 1567 | /// <param name="remoteClient"></param> |
1377 | public void UpdatePrimGroupPosition(uint localId, Vector3 pos, IClientAPI remoteClient) | 1568 | public void UpdatePrimGroupPosition(uint localId, Vector3 pos, IClientAPI remoteClient) |
1378 | { | 1569 | { |
1379 | UpdatePrimGroupPosition(localId, pos, remoteClient.AgentId); | ||
1380 | } | ||
1381 | |||
1382 | /// <summary> | ||
1383 | /// Update the position of the given group. | ||
1384 | /// </summary> | ||
1385 | /// <param name="localId"></param> | ||
1386 | /// <param name="pos"></param> | ||
1387 | /// <param name="updatingAgentId"></param> | ||
1388 | public void UpdatePrimGroupPosition(uint localId, Vector3 pos, UUID updatingAgentId) | ||
1389 | { | ||
1390 | SceneObjectGroup group = GetGroupByPrim(localId); | 1570 | SceneObjectGroup group = GetGroupByPrim(localId); |
1391 | 1571 | ||
1392 | if (group != null) | 1572 | if (group != null) |
1393 | { | 1573 | { |
1394 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) | 1574 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) |
1395 | { | 1575 | { |
1396 | if (m_parentScene.AttachmentsModule != null) | 1576 | // Set the new attachment point data in the object |
1397 | m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); | 1577 | byte attachmentPoint = (byte)group.AttachmentPoint; |
1578 | group.UpdateGroupPosition(pos); | ||
1579 | group.IsAttachment = false; | ||
1580 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
1581 | group.AttachmentPoint = attachmentPoint; | ||
1582 | group.HasGroupChanged = true; | ||
1398 | } | 1583 | } |
1399 | else | 1584 | else |
1400 | { | 1585 | { |
1401 | if (m_parentScene.Permissions.CanMoveObject(group.UUID, updatingAgentId) | 1586 | if (m_parentScene.Permissions.CanMoveObject(group, remoteClient) |
1402 | && m_parentScene.Permissions.CanObjectEntry(group.UUID, false, pos)) | 1587 | && m_parentScene.Permissions.CanObjectEntry(group, false, pos)) |
1403 | { | 1588 | { |
1404 | group.UpdateGroupPosition(pos); | 1589 | group.UpdateGroupPosition(pos); |
1405 | } | 1590 | } |
@@ -1419,13 +1604,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
1419 | /// <param name="remoteClient"></param> | 1604 | /// <param name="remoteClient"></param> |
1420 | protected internal void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient) | 1605 | protected internal void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient) |
1421 | { | 1606 | { |
1422 | SceneObjectGroup group = GetGroupByPrim(localID); | 1607 | SceneObjectPart part = GetSceneObjectPart(localID); |
1423 | 1608 | if(part == null) | |
1424 | if (group != null) | 1609 | return; |
1610 | |||
1611 | SceneObjectGroup group = part.ParentGroup; | ||
1612 | if (group != null && !group.IsDeleted) | ||
1425 | { | 1613 | { |
1426 | if (m_parentScene.Permissions.CanEditObject(group.UUID,remoteClient.AgentId)) | 1614 | if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) |
1427 | { | 1615 | { |
1428 | group.UpdateTextureEntry(localID, texture); | 1616 | part.UpdateTextureEntry(texture); |
1429 | } | 1617 | } |
1430 | } | 1618 | } |
1431 | } | 1619 | } |
@@ -1447,11 +1635,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1447 | SceneObjectGroup group = GetGroupByPrim(localID); | 1635 | SceneObjectGroup group = GetGroupByPrim(localID); |
1448 | if (group != null) | 1636 | if (group != null) |
1449 | { | 1637 | { |
1450 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1638 | if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) |
1451 | { | 1639 | { |
1452 | // VolumeDetect can't be set via UI and will always be off when a change is made there | 1640 | // VolumeDetect can't be set via UI and will always be off when a change is made there |
1453 | // now only change volume dtc if phantom off | 1641 | // now only change volume dtc if phantom off |
1454 | 1642 | ||
1643 | bool wantedPhys = UsePhysics; | ||
1455 | if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data | 1644 | if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data |
1456 | { | 1645 | { |
1457 | bool vdtc; | 1646 | bool vdtc; |
@@ -1460,7 +1649,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1460 | else // else turn it off | 1649 | else // else turn it off |
1461 | vdtc = false; | 1650 | vdtc = false; |
1462 | 1651 | ||
1463 | group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, vdtc); | 1652 | group.UpdateFlags(UsePhysics, SetTemporary, SetPhantom, vdtc); |
1464 | } | 1653 | } |
1465 | else | 1654 | else |
1466 | { | 1655 | { |
@@ -1468,77 +1657,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
1468 | if (part != null) | 1657 | if (part != null) |
1469 | { | 1658 | { |
1470 | part.UpdateExtraPhysics(PhysData); | 1659 | part.UpdateExtraPhysics(PhysData); |
1471 | if (part.UpdatePhysRequired) | 1660 | if (remoteClient != null) |
1472 | remoteClient.SendPartPhysicsProprieties(part); | 1661 | remoteClient.SendPartPhysicsProprieties(part); |
1473 | } | 1662 | } |
1474 | } | 1663 | } |
1475 | } | ||
1476 | } | ||
1477 | } | ||
1478 | |||
1479 | /// <summary> | ||
1480 | /// Move the given object | ||
1481 | /// </summary> | ||
1482 | /// <param name="objectID"></param> | ||
1483 | /// <param name="offset"></param> | ||
1484 | /// <param name="pos"></param> | ||
1485 | /// <param name="remoteClient"></param> | ||
1486 | protected internal void MoveObject(UUID objectID, Vector3 offset, Vector3 pos, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs) | ||
1487 | { | ||
1488 | SceneObjectGroup group = GetGroupByPrim(objectID); | ||
1489 | if (group != null) | ||
1490 | { | ||
1491 | if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) | ||
1492 | { | ||
1493 | group.GrabMovement(objectID, offset, pos, remoteClient); | ||
1494 | } | ||
1495 | 1664 | ||
1496 | // This is outside the above permissions condition | 1665 | if (wantedPhys != group.UsesPhysics && remoteClient != null) |
1497 | // so that if the object is locked the client moving the object | 1666 | { |
1498 | // get's it's position on the simulator even if it was the same as before | 1667 | if(m_parentScene.m_linksetPhysCapacity != 0) |
1499 | // This keeps the moving user's client in sync with the rest of the world. | 1668 | remoteClient.SendAlertMessage("Object physics cancelled because it exceeds limits for physical prims, either size or number of primswith shape type not set to None"); |
1500 | group.SendGroupTerseUpdate(); | 1669 | else |
1501 | } | 1670 | remoteClient.SendAlertMessage("Object physics cancelled because it exceeds size limits for physical prims"); |
1502 | } | 1671 | |
1503 | 1672 | group.RootPart.ScheduleFullUpdate(); | |
1504 | /// <summary> | 1673 | } |
1505 | /// Start spinning the given object | ||
1506 | /// </summary> | ||
1507 | /// <param name="objectID"></param> | ||
1508 | /// <param name="rotation"></param> | ||
1509 | /// <param name="remoteClient"></param> | ||
1510 | protected internal void SpinStart(UUID objectID, IClientAPI remoteClient) | ||
1511 | { | ||
1512 | SceneObjectGroup group = GetGroupByPrim(objectID); | ||
1513 | if (group != null) | ||
1514 | { | ||
1515 | if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) | ||
1516 | { | ||
1517 | group.SpinStart(remoteClient); | ||
1518 | } | ||
1519 | } | ||
1520 | } | ||
1521 | |||
1522 | /// <summary> | ||
1523 | /// Spin the given object | ||
1524 | /// </summary> | ||
1525 | /// <param name="objectID"></param> | ||
1526 | /// <param name="rotation"></param> | ||
1527 | /// <param name="remoteClient"></param> | ||
1528 | protected internal void SpinObject(UUID objectID, Quaternion rotation, IClientAPI remoteClient) | ||
1529 | { | ||
1530 | SceneObjectGroup group = GetGroupByPrim(objectID); | ||
1531 | if (group != null) | ||
1532 | { | ||
1533 | if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) | ||
1534 | { | ||
1535 | group.SpinMovement(rotation, remoteClient); | ||
1536 | } | 1674 | } |
1537 | // This is outside the above permissions condition | ||
1538 | // so that if the object is locked the client moving the object | ||
1539 | // get's it's position on the simulator even if it was the same as before | ||
1540 | // This keeps the moving user's client in sync with the rest of the world. | ||
1541 | group.SendGroupTerseUpdate(); | ||
1542 | } | 1675 | } |
1543 | } | 1676 | } |
1544 | 1677 | ||
@@ -1552,7 +1685,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1552 | SceneObjectGroup group = GetGroupByPrim(primLocalID); | 1685 | SceneObjectGroup group = GetGroupByPrim(primLocalID); |
1553 | if (group != null) | 1686 | if (group != null) |
1554 | { | 1687 | { |
1555 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1688 | if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) |
1556 | { | 1689 | { |
1557 | group.SetPartName(Util.CleanString(name), primLocalID); | 1690 | group.SetPartName(Util.CleanString(name), primLocalID); |
1558 | group.HasGroupChanged = true; | 1691 | group.HasGroupChanged = true; |
@@ -1570,7 +1703,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1570 | SceneObjectGroup group = GetGroupByPrim(primLocalID); | 1703 | SceneObjectGroup group = GetGroupByPrim(primLocalID); |
1571 | if (group != null) | 1704 | if (group != null) |
1572 | { | 1705 | { |
1573 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1706 | if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) |
1574 | { | 1707 | { |
1575 | group.SetPartDescription(Util.CleanString(description), primLocalID); | 1708 | group.SetPartDescription(Util.CleanString(description), primLocalID); |
1576 | group.HasGroupChanged = true; | 1709 | group.HasGroupChanged = true; |
@@ -1592,13 +1725,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1592 | SceneObjectGroup group = GetGroupByPrim(primLocalID); | 1725 | SceneObjectGroup group = GetGroupByPrim(primLocalID); |
1593 | if (group != null) | 1726 | if (group != null) |
1594 | { | 1727 | { |
1595 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1728 | if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) |
1596 | { | 1729 | { |
1597 | SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID); | 1730 | SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID); |
1598 | if (part != null) | 1731 | if (part != null) |
1599 | { | 1732 | { |
1600 | part.ClickAction = Convert.ToByte(clickAction); | 1733 | part.ClickAction = Convert.ToByte(clickAction); |
1601 | group.HasGroupChanged = true; | 1734 | group.HasGroupChanged = true; |
1602 | } | 1735 | } |
1603 | } | 1736 | } |
1604 | } | 1737 | } |
@@ -1609,13 +1742,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1609 | SceneObjectGroup group = GetGroupByPrim(primLocalID); | 1742 | SceneObjectGroup group = GetGroupByPrim(primLocalID); |
1610 | if (group != null) | 1743 | if (group != null) |
1611 | { | 1744 | { |
1612 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1745 | if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) |
1613 | { | 1746 | { |
1614 | SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID); | 1747 | SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID); |
1615 | if (part != null) | 1748 | if (part != null) |
1616 | { | 1749 | { |
1617 | part.Material = Convert.ToByte(material); | 1750 | part.Material = Convert.ToByte(material); |
1618 | group.HasGroupChanged = true; | 1751 | group.HasGroupChanged = true; |
1752 | remoteClient.SendPartPhysicsProprieties(part); | ||
1619 | } | 1753 | } |
1620 | } | 1754 | } |
1621 | } | 1755 | } |
@@ -1694,12 +1828,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1694 | return; | 1828 | return; |
1695 | 1829 | ||
1696 | Monitor.Enter(m_updateLock); | 1830 | Monitor.Enter(m_updateLock); |
1831 | |||
1697 | try | 1832 | try |
1698 | { | 1833 | { |
1834 | |||
1699 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | 1835 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); |
1700 | 1836 | ||
1701 | // We do this in reverse to get the link order of the prims correct | 1837 | // We do this in reverse to get the link order of the prims correct |
1702 | for (int i = 0 ; i < children.Count ; i++) | 1838 | for (int i = 0; i < children.Count; i++) |
1703 | { | 1839 | { |
1704 | SceneObjectGroup child = children[i].ParentGroup; | 1840 | SceneObjectGroup child = children[i].ParentGroup; |
1705 | 1841 | ||
@@ -1710,9 +1846,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1710 | // Make sure no child prim is set for sale | 1846 | // Make sure no child prim is set for sale |
1711 | // So that, on delink, no prims are unwittingly | 1847 | // So that, on delink, no prims are unwittingly |
1712 | // left for sale and sold off | 1848 | // left for sale and sold off |
1713 | child.RootPart.ObjectSaleType = 0; | 1849 | |
1714 | child.RootPart.SalePrice = 10; | 1850 | if (child != null) |
1715 | childGroups.Add(child); | 1851 | { |
1852 | child.RootPart.ObjectSaleType = 0; | ||
1853 | child.RootPart.SalePrice = 10; | ||
1854 | childGroups.Add(child); | ||
1855 | } | ||
1716 | } | 1856 | } |
1717 | 1857 | ||
1718 | foreach (SceneObjectGroup child in childGroups) | 1858 | foreach (SceneObjectGroup child in childGroups) |
@@ -1725,7 +1865,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1725 | 1865 | ||
1726 | // this is here so physics gets updated! | 1866 | // this is here so physics gets updated! |
1727 | // Don't remove! Bad juju! Stay away! or fix physics! | 1867 | // Don't remove! Bad juju! Stay away! or fix physics! |
1728 | child.AbsolutePosition = child.AbsolutePosition; | 1868 | // already done in LinkToGroup |
1869 | // child.AbsolutePosition = child.AbsolutePosition; | ||
1729 | } | 1870 | } |
1730 | } | 1871 | } |
1731 | 1872 | ||
@@ -1741,6 +1882,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1741 | } | 1882 | } |
1742 | finally | 1883 | finally |
1743 | { | 1884 | { |
1885 | /* | ||
1886 | lock (SceneObjectGroupsByLocalPartID) | ||
1887 | { | ||
1888 | foreach (SceneObjectPart part in parentGroup.Parts) | ||
1889 | SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; | ||
1890 | } | ||
1891 | */ | ||
1892 | parentGroup.AdjustChildPrimPermissions(false); | ||
1893 | parentGroup.HasGroupChanged = true; | ||
1894 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); | ||
1895 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1744 | Monitor.Exit(m_updateLock); | 1896 | Monitor.Exit(m_updateLock); |
1745 | } | 1897 | } |
1746 | } | 1898 | } |
@@ -1761,42 +1913,50 @@ namespace OpenSim.Region.Framework.Scenes | |||
1761 | // | 1913 | // |
1762 | foreach (SceneObjectPart part in prims) | 1914 | foreach (SceneObjectPart part in prims) |
1763 | { | 1915 | { |
1764 | if (part != null) | 1916 | if(part == null) |
1917 | continue; | ||
1918 | SceneObjectGroup parentSOG = part.ParentGroup; | ||
1919 | if(parentSOG == null || | ||
1920 | parentSOG.IsDeleted || | ||
1921 | parentSOG.inTransit || | ||
1922 | parentSOG.PrimCount == 1) | ||
1923 | continue; | ||
1924 | |||
1925 | if (!affectedGroups.Contains(parentSOG)) | ||
1765 | { | 1926 | { |
1766 | if (part.KeyframeMotion != null) | 1927 | affectedGroups.Add(parentSOG); |
1767 | { | 1928 | if(parentSOG.RootPart.PhysActor != null) |
1768 | part.KeyframeMotion.Stop(); | 1929 | parentSOG.RootPart.PhysActor.Building = true; |
1769 | part.KeyframeMotion = null; | 1930 | } |
1770 | } | ||
1771 | if (part.ParentGroup.PrimCount != 1) // Skip single | ||
1772 | { | ||
1773 | if (part.LinkNum < 2) // Root | ||
1774 | { | ||
1775 | rootParts.Add(part); | ||
1776 | } | ||
1777 | else | ||
1778 | { | ||
1779 | part.LastOwnerID = part.ParentGroup.RootPart.LastOwnerID; | ||
1780 | childParts.Add(part); | ||
1781 | } | ||
1782 | 1931 | ||
1783 | SceneObjectGroup group = part.ParentGroup; | 1932 | if (part.KeyframeMotion != null) |
1784 | if (!affectedGroups.Contains(group)) | 1933 | { |
1785 | affectedGroups.Add(group); | 1934 | part.KeyframeMotion.Stop(); |
1786 | } | 1935 | part.KeyframeMotion = null; |
1936 | } | ||
1937 | |||
1938 | if (part.LinkNum < 2) // Root | ||
1939 | { | ||
1940 | rootParts.Add(part); | ||
1941 | } | ||
1942 | else | ||
1943 | { | ||
1944 | part.LastOwnerID = part.ParentGroup.RootPart.LastOwnerID; | ||
1945 | part.RezzerID = part.ParentGroup.RootPart.RezzerID; | ||
1946 | childParts.Add(part); | ||
1787 | } | 1947 | } |
1788 | } | 1948 | } |
1789 | 1949 | ||
1790 | foreach (SceneObjectPart child in childParts) | 1950 | if (childParts.Count > 0) |
1791 | { | 1951 | { |
1792 | // Unlink all child parts from their groups | 1952 | foreach (SceneObjectPart child in childParts) |
1793 | // | 1953 | { |
1794 | child.ParentGroup.DelinkFromGroup(child, true); | 1954 | // Unlink all child parts from their groups |
1795 | 1955 | child.ParentGroup.DelinkFromGroup(child, true); | |
1796 | // These are not in affected groups and will not be | 1956 | //child.ParentGroup is now other |
1797 | // handled further. Do the honors here. | 1957 | child.ParentGroup.HasGroupChanged = true; |
1798 | child.ParentGroup.HasGroupChanged = true; | 1958 | child.ParentGroup.ScheduleGroupForFullUpdate(); |
1799 | child.ParentGroup.ScheduleGroupForFullUpdate(); | 1959 | } |
1800 | } | 1960 | } |
1801 | 1961 | ||
1802 | foreach (SceneObjectPart root in rootParts) | 1962 | foreach (SceneObjectPart root in rootParts) |
@@ -1806,63 +1966,54 @@ namespace OpenSim.Region.Framework.Scenes | |||
1806 | // However, editing linked parts and unlinking may be different | 1966 | // However, editing linked parts and unlinking may be different |
1807 | // | 1967 | // |
1808 | SceneObjectGroup group = root.ParentGroup; | 1968 | SceneObjectGroup group = root.ParentGroup; |
1809 | 1969 | ||
1810 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); | 1970 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); |
1971 | |||
1972 | newSet.Remove(root); | ||
1811 | int numChildren = newSet.Count; | 1973 | int numChildren = newSet.Count; |
1974 | if(numChildren == 0) | ||
1975 | break; | ||
1976 | |||
1977 | foreach (SceneObjectPart p in newSet) | ||
1978 | group.DelinkFromGroup(p, false); | ||
1979 | |||
1980 | SceneObjectPart newRoot = newSet[0]; | ||
1812 | 1981 | ||
1813 | // If there are prims left in a link set, but the root is | 1982 | // If there is more than one prim remaining, we |
1814 | // slated for unlink, we need to do this | 1983 | // need to re-link |
1815 | // | 1984 | // |
1816 | if (numChildren != 1) | 1985 | if (numChildren > 1) |
1817 | { | 1986 | { |
1818 | // Unlink the remaining set | 1987 | // Determine new root |
1819 | // | 1988 | // |
1820 | bool sendEventsToRemainder = true; | 1989 | newSet.RemoveAt(0); |
1821 | if (numChildren > 1) | 1990 | foreach (SceneObjectPart newChild in newSet) |
1822 | sendEventsToRemainder = false; | 1991 | newChild.ClearUpdateSchedule(); |
1823 | 1992 | ||
1824 | foreach (SceneObjectPart p in newSet) | 1993 | LinkObjects(newRoot, newSet); |
1825 | { | 1994 | } |
1826 | if (p != group.RootPart) | 1995 | else |
1827 | group.DelinkFromGroup(p, sendEventsToRemainder); | 1996 | { |
1828 | } | 1997 | newRoot.TriggerScriptChangedEvent(Changed.LINK); |
1829 | 1998 | newRoot.ParentGroup.HasGroupChanged = true; | |
1830 | // If there is more than one prim remaining, we | 1999 | newRoot.ParentGroup.InvalidatePartsLinkMaps(); |
1831 | // need to re-link | 2000 | newRoot.ParentGroup.ScheduleGroupForFullUpdate(); |
1832 | // | ||
1833 | if (numChildren > 2) | ||
1834 | { | ||
1835 | // Remove old root | ||
1836 | // | ||
1837 | if (newSet.Contains(root)) | ||
1838 | newSet.Remove(root); | ||
1839 | |||
1840 | // Preserve link ordering | ||
1841 | // | ||
1842 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1843 | { | ||
1844 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1845 | }); | ||
1846 | |||
1847 | // Determine new root | ||
1848 | // | ||
1849 | SceneObjectPart newRoot = newSet[0]; | ||
1850 | newSet.RemoveAt(0); | ||
1851 | |||
1852 | foreach (SceneObjectPart newChild in newSet) | ||
1853 | newChild.ClearUpdateSchedule(); | ||
1854 | |||
1855 | LinkObjects(newRoot, newSet); | ||
1856 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | ||
1857 | affectedGroups.Add(newRoot.ParentGroup); | ||
1858 | } | ||
1859 | } | 2001 | } |
1860 | } | 2002 | } |
1861 | 2003 | ||
1862 | // Finally, trigger events in the roots | 2004 | // trigger events in the roots |
1863 | // | 2005 | // |
1864 | foreach (SceneObjectGroup g in affectedGroups) | 2006 | foreach (SceneObjectGroup g in affectedGroups) |
1865 | { | 2007 | { |
2008 | if(g.RootPart.PhysActor != null) | ||
2009 | g.RootPart.PhysActor.Building = false; | ||
2010 | g.AdjustChildPrimPermissions(false); | ||
2011 | // Child prims that have been unlinked and deleted will | ||
2012 | // return unless the root is deleted. This will remove them | ||
2013 | // from the database. They will be rewritten immediately, | ||
2014 | // minus the rows for the unlinked child prims. | ||
2015 | m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); | ||
2016 | g.InvalidatePartsLinkMaps(); | ||
1866 | g.TriggerScriptChangedEvent(Changed.LINK); | 2017 | g.TriggerScriptChangedEvent(Changed.LINK); |
1867 | g.HasGroupChanged = true; // Persist | 2018 | g.HasGroupChanged = true; // Persist |
1868 | g.ScheduleGroupForFullUpdate(); | 2019 | g.ScheduleGroupForFullUpdate(); |
@@ -1876,27 +2027,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1876 | 2027 | ||
1877 | protected internal void MakeObjectSearchable(IClientAPI remoteClient, bool IncludeInSearch, uint localID) | 2028 | protected internal void MakeObjectSearchable(IClientAPI remoteClient, bool IncludeInSearch, uint localID) |
1878 | { | 2029 | { |
1879 | UUID user = remoteClient.AgentId; | 2030 | SceneObjectGroup sog = GetGroupByPrim(localID); |
1880 | UUID objid = UUID.Zero; | 2031 | if(sog == null) |
1881 | SceneObjectPart obj = null; | 2032 | return; |
1882 | |||
1883 | EntityBase[] entityList = GetEntities(); | ||
1884 | foreach (EntityBase ent in entityList) | ||
1885 | { | ||
1886 | if (ent is SceneObjectGroup) | ||
1887 | { | ||
1888 | SceneObjectGroup sog = ent as SceneObjectGroup; | ||
1889 | |||
1890 | foreach (SceneObjectPart part in sog.Parts) | ||
1891 | { | ||
1892 | if (part.LocalId == localID) | ||
1893 | { | ||
1894 | objid = part.UUID; | ||
1895 | obj = part; | ||
1896 | } | ||
1897 | } | ||
1898 | } | ||
1899 | } | ||
1900 | 2033 | ||
1901 | //Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints | 2034 | //Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints |
1902 | //aka ObjectFlags.JointWheel = IncludeInSearch | 2035 | //aka ObjectFlags.JointWheel = IncludeInSearch |
@@ -1913,15 +2046,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
1913 | // libomv will complain about PrimFlags.JointWheel being | 2046 | // libomv will complain about PrimFlags.JointWheel being |
1914 | // deprecated, so we | 2047 | // deprecated, so we |
1915 | #pragma warning disable 0612 | 2048 | #pragma warning disable 0612 |
1916 | if (IncludeInSearch && m_parentScene.Permissions.CanEditObject(objid, user)) | 2049 | if (IncludeInSearch && m_parentScene.Permissions.CanEditObject(sog, remoteClient)) |
1917 | { | 2050 | { |
1918 | obj.ParentGroup.RootPart.AddFlag(PrimFlags.JointWheel); | 2051 | sog.RootPart.AddFlag(PrimFlags.JointWheel); |
1919 | obj.ParentGroup.HasGroupChanged = true; | 2052 | sog.HasGroupChanged = true; |
1920 | } | 2053 | } |
1921 | else if (!IncludeInSearch && m_parentScene.Permissions.CanMoveObject(objid,user)) | 2054 | else if (!IncludeInSearch && m_parentScene.Permissions.CanMoveObject(sog, remoteClient)) |
1922 | { | 2055 | { |
1923 | obj.ParentGroup.RootPart.RemFlag(PrimFlags.JointWheel); | 2056 | sog.RootPart.RemFlag(PrimFlags.JointWheel); |
1924 | obj.ParentGroup.HasGroupChanged = true; | 2057 | sog.HasGroupChanged = true; |
1925 | } | 2058 | } |
1926 | #pragma warning restore 0612 | 2059 | #pragma warning restore 0612 |
1927 | } | 2060 | } |
@@ -1936,120 +2069,86 @@ namespace OpenSim.Region.Framework.Scenes | |||
1936 | /// <param name="GroupID"></param> | 2069 | /// <param name="GroupID"></param> |
1937 | /// <param name="rot"></param> | 2070 | /// <param name="rot"></param> |
1938 | /// <returns>null if duplication fails, otherwise the duplicated object</returns> | 2071 | /// <returns>null if duplication fails, otherwise the duplicated object</returns> |
1939 | public SceneObjectGroup DuplicateObject( | 2072 | /// <summary> |
1940 | uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) | 2073 | public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, UUID AgentID, UUID GroupID, Quaternion rot, bool createSelected) |
1941 | { | 2074 | { |
1942 | Monitor.Enter(m_updateLock); | 2075 | // m_log.DebugFormat( |
2076 | // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", | ||
2077 | // originalPrimID, offset, AgentID); | ||
1943 | 2078 | ||
1944 | try | 2079 | SceneObjectGroup original = GetGroupByPrim(originalPrimID); |
2080 | if (original != null) | ||
1945 | { | 2081 | { |
1946 | // m_log.DebugFormat( | 2082 | if (m_parentScene.Permissions.CanDuplicateObject(original, AgentID)) |
1947 | // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", | ||
1948 | // originalPrimID, offset, AgentID); | ||
1949 | |||
1950 | SceneObjectGroup original = GetGroupByPrim(originalPrimID); | ||
1951 | if (original == null) | ||
1952 | { | 2083 | { |
1953 | m_log.WarnFormat( | 2084 | SceneObjectGroup copy = original.Copy(true); |
1954 | "[SCENEGRAPH]: Attempt to duplicate nonexistent prim id {0} by {1}", originalPrimID, AgentID); | 2085 | copy.AbsolutePosition = copy.AbsolutePosition + offset; |
1955 | 2086 | ||
1956 | return null; | 2087 | SceneObjectPart[] parts = copy.Parts; |
1957 | } | ||
1958 | |||
1959 | if (!m_parentScene.Permissions.CanDuplicateObject( | ||
1960 | original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) | ||
1961 | return null; | ||
1962 | |||
1963 | SceneObjectGroup copy = original.Copy(true); | ||
1964 | copy.AbsolutePosition = copy.AbsolutePosition + offset; | ||
1965 | |||
1966 | if (original.OwnerID != AgentID) | ||
1967 | { | ||
1968 | copy.SetOwnerId(AgentID); | ||
1969 | copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); | ||
1970 | 2088 | ||
1971 | SceneObjectPart[] partList = copy.Parts; | 2089 | m_numTotalPrim += parts.Length; |
1972 | 2090 | ||
1973 | if (m_parentScene.Permissions.PropagatePermissions()) | 2091 | if (original.OwnerID != AgentID) |
1974 | { | 2092 | { |
1975 | foreach (SceneObjectPart child in partList) | 2093 | copy.SetOwner(AgentID, GroupID); |
2094 | |||
2095 | if (m_parentScene.Permissions.PropagatePermissions()) | ||
1976 | { | 2096 | { |
1977 | child.Inventory.ChangeInventoryOwner(AgentID); | 2097 | foreach (SceneObjectPart child in parts) |
1978 | child.TriggerScriptChangedEvent(Changed.OWNER); | 2098 | { |
1979 | child.ApplyNextOwnerPermissions(); | 2099 | child.Inventory.ChangeInventoryOwner(AgentID); |
2100 | child.TriggerScriptChangedEvent(Changed.OWNER); | ||
2101 | child.ApplyNextOwnerPermissions(); | ||
2102 | } | ||
2103 | copy.InvalidateEffectivePerms(); | ||
1980 | } | 2104 | } |
1981 | } | 2105 | } |
1982 | 2106 | ||
1983 | copy.RootPart.ObjectSaleType = 0; | 2107 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() |
1984 | copy.RootPart.SalePrice = 10; | 2108 | Entities.Add(copy); |
1985 | } | ||
1986 | 2109 | ||
1987 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() | 2110 | lock (SceneObjectGroupsByFullID) |
1988 | Entities.Add(copy); | 2111 | SceneObjectGroupsByFullID[copy.UUID] = copy; |
1989 | |||
1990 | lock (SceneObjectGroupsByFullID) | ||
1991 | SceneObjectGroupsByFullID[copy.UUID] = copy; | ||
1992 | |||
1993 | SceneObjectPart[] children = copy.Parts; | ||
1994 | |||
1995 | lock (SceneObjectGroupsByFullPartID) | ||
1996 | { | ||
1997 | SceneObjectGroupsByFullPartID[copy.UUID] = copy; | ||
1998 | foreach (SceneObjectPart part in children) | ||
1999 | SceneObjectGroupsByFullPartID[part.UUID] = copy; | ||
2000 | } | ||
2001 | |||
2002 | lock (SceneObjectGroupsByLocalPartID) | ||
2003 | { | ||
2004 | SceneObjectGroupsByLocalPartID[copy.LocalId] = copy; | ||
2005 | foreach (SceneObjectPart part in children) | ||
2006 | SceneObjectGroupsByLocalPartID[part.LocalId] = copy; | ||
2007 | } | ||
2008 | // PROBABLE END OF FIXME | ||
2009 | 2112 | ||
2010 | // Since we copy from a source group that is in selected | 2113 | foreach (SceneObjectPart part in parts) |
2011 | // state, but the copy is shown deselected in the viewer, | 2114 | { |
2012 | // We need to clear the selection flag here, else that | 2115 | if (part.GetPrimType() == PrimType.SCULPT) |
2013 | // prim never gets persisted at all. The client doesn't | 2116 | m_numMesh++; |
2014 | // think it's selected, so it will never send a deselect... | 2117 | else |
2015 | copy.IsSelected = false; | 2118 | m_numPrim++; |
2016 | 2119 | ||
2017 | m_numTotalPrim += copy.Parts.Length; | 2120 | lock (SceneObjectGroupsByFullPartID) |
2121 | SceneObjectGroupsByFullPartID[part.UUID] = copy; | ||
2122 | lock (SceneObjectGroupsByLocalPartID) | ||
2123 | SceneObjectGroupsByLocalPartID[part.LocalId] = copy; | ||
2124 | } | ||
2018 | 2125 | ||
2019 | // Go through all parts (primitives and meshes) of this Scene Object | 2126 | // PROBABLE END OF FIXME |
2020 | foreach (SceneObjectPart part in copy.Parts) | ||
2021 | { | ||
2022 | // Keep track of the total number of meshes or geometric primitives now in the scene; | ||
2023 | // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to | ||
2024 | // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives | ||
2025 | if (part.GetPrimType() == PrimType.SCULPT) | ||
2026 | m_numMesh++; | ||
2027 | else | ||
2028 | m_numPrim++; | ||
2029 | } | ||
2030 | 2127 | ||
2031 | if (rot != Quaternion.Identity) | 2128 | copy.IsSelected = createSelected; |
2032 | { | 2129 | |
2033 | copy.UpdateGroupRotationR(rot); | 2130 | if (rot != Quaternion.Identity) |
2034 | } | 2131 | copy.UpdateGroupRotationR(rot); |
2035 | 2132 | ||
2036 | copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); | 2133 | // required for physics to update it's position |
2037 | copy.HasGroupChanged = true; | 2134 | copy.ResetChildPrimPhysicsPositions(); |
2038 | copy.ScheduleGroupForFullUpdate(); | ||
2039 | copy.ResumeScripts(); | ||
2040 | 2135 | ||
2041 | // required for physics to update it's position | 2136 | copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); |
2042 | copy.AbsolutePosition = copy.AbsolutePosition; | 2137 | copy.ResumeScripts(); |
2043 | 2138 | ||
2044 | return copy; | 2139 | copy.HasGroupChanged = true; |
2140 | copy.ScheduleGroupForFullUpdate(); | ||
2141 | return copy; | ||
2142 | } | ||
2045 | } | 2143 | } |
2046 | finally | 2144 | else |
2047 | { | 2145 | { |
2048 | Monitor.Exit(m_updateLock); | 2146 | m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID); |
2049 | } | 2147 | } |
2148 | |||
2149 | return null; | ||
2050 | } | 2150 | } |
2051 | 2151 | ||
2052 | /// <summary> | ||
2053 | /// Calculates the distance between two Vector3s | 2152 | /// Calculates the distance between two Vector3s |
2054 | /// </summary> | 2153 | /// </summary> |
2055 | /// <param name="v1"></param> | 2154 | /// <param name="v1"></param> |
@@ -2067,6 +2166,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
2067 | 2166 | ||
2068 | #endregion | 2167 | #endregion |
2069 | 2168 | ||
2070 | 2169 | ||
2071 | } | 2170 | } |
2072 | } | 2171 | } |