aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneGraph.cs
diff options
context:
space:
mode:
authoronefang2019-05-19 21:24:15 +1000
committeronefang2019-05-19 21:24:15 +1000
commit5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch)
treea9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Region/Framework/Scenes/SceneGraph.cs
parentAdd a build script. (diff)
downloadopensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to '')
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/Framework/Scenes/SceneGraph.cs833
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..100755
--- 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}