diff options
Diffstat (limited to '')
-rwxr-xr-x | OpenSim/Region/Framework/Scenes/SceneGraph.cs | 496 |
1 files changed, 366 insertions, 130 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index c2e9b61..3f6a7f8 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 | ||
@@ -129,13 +139,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
129 | 139 | ||
130 | protected internal void Close() | 140 | protected internal void Close() |
131 | { | 141 | { |
132 | lock (m_presenceLock) | 142 | m_scenePresencesLock.EnterWriteLock(); |
143 | try | ||
133 | { | 144 | { |
134 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); | 145 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); |
135 | List<ScenePresence> newlist = new List<ScenePresence>(); | 146 | List<ScenePresence> newlist = new List<ScenePresence>(); |
136 | m_scenePresenceMap = newmap; | 147 | m_scenePresenceMap = newmap; |
137 | m_scenePresenceArray = newlist; | 148 | m_scenePresenceArray = newlist; |
138 | } | 149 | } |
150 | finally | ||
151 | { | ||
152 | m_scenePresencesLock.ExitWriteLock(); | ||
153 | } | ||
139 | 154 | ||
140 | lock (SceneObjectGroupsByFullID) | 155 | lock (SceneObjectGroupsByFullID) |
141 | SceneObjectGroupsByFullID.Clear(); | 156 | SceneObjectGroupsByFullID.Clear(); |
@@ -256,13 +271,54 @@ namespace OpenSim.Region.Framework.Scenes | |||
256 | protected internal bool AddRestoredSceneObject( | 271 | protected internal bool AddRestoredSceneObject( |
257 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) | 272 | SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) |
258 | { | 273 | { |
274 | if (!m_parentScene.CombineRegions) | ||
275 | { | ||
276 | // temporary checks to remove after varsize suport | ||
277 | float regionSizeX = m_parentScene.RegionInfo.RegionSizeX; | ||
278 | if (regionSizeX == 0) | ||
279 | regionSizeX = Constants.RegionSize; | ||
280 | float regionSizeY = m_parentScene.RegionInfo.RegionSizeY; | ||
281 | if (regionSizeY == 0) | ||
282 | regionSizeY = Constants.RegionSize; | ||
283 | |||
284 | // KF: Check for out-of-region, move inside and make static. | ||
285 | Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, | ||
286 | sceneObject.RootPart.GroupPosition.Y, | ||
287 | sceneObject.RootPart.GroupPosition.Z); | ||
288 | 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 || | ||
289 | npos.X > regionSizeX || | ||
290 | npos.Y > regionSizeY)) | ||
291 | { | ||
292 | if (npos.X < 0.0) npos.X = 1.0f; | ||
293 | if (npos.Y < 0.0) npos.Y = 1.0f; | ||
294 | if (npos.Z < 0.0) npos.Z = 0.0f; | ||
295 | if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f; | ||
296 | if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f; | ||
297 | |||
298 | SceneObjectPart rootpart = sceneObject.RootPart; | ||
299 | rootpart.GroupPosition = npos; | ||
300 | |||
301 | foreach (SceneObjectPart part in sceneObject.Parts) | ||
302 | { | ||
303 | if (part == rootpart) | ||
304 | continue; | ||
305 | part.GroupPosition = npos; | ||
306 | } | ||
307 | rootpart.Velocity = Vector3.Zero; | ||
308 | rootpart.AngularVelocity = Vector3.Zero; | ||
309 | rootpart.Acceleration = Vector3.Zero; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | ||
314 | |||
259 | if (attachToBackup && (!alreadyPersisted)) | 315 | if (attachToBackup && (!alreadyPersisted)) |
260 | { | 316 | { |
261 | sceneObject.ForceInventoryPersistence(); | 317 | sceneObject.ForceInventoryPersistence(); |
262 | sceneObject.HasGroupChanged = true; | 318 | sceneObject.HasGroupChanged = true; |
263 | } | 319 | } |
264 | 320 | ||
265 | return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | 321 | return ret; |
266 | } | 322 | } |
267 | 323 | ||
268 | /// <summary> | 324 | /// <summary> |
@@ -279,12 +335,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
279 | /// </returns> | 335 | /// </returns> |
280 | protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) | 336 | protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) |
281 | { | 337 | { |
282 | // Ensure that we persist this new scene object if it's not an | 338 | |
339 | bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | ||
340 | |||
341 | // Ensure that we persist this new scene object if it's not an | ||
283 | // attachment | 342 | // attachment |
343 | |||
284 | if (attachToBackup) | 344 | if (attachToBackup) |
285 | sceneObject.HasGroupChanged = true; | 345 | sceneObject.HasGroupChanged = true; |
286 | 346 | ||
287 | return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); | 347 | return ret; |
288 | } | 348 | } |
289 | 349 | ||
290 | /// <summary> | 350 | /// <summary> |
@@ -319,9 +379,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
319 | if (pa != null && pa.IsPhysical && vel != Vector3.Zero) | 379 | if (pa != null && pa.IsPhysical && vel != Vector3.Zero) |
320 | { | 380 | { |
321 | sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); | 381 | sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); |
322 | sceneObject.Velocity = vel; | ||
323 | } | 382 | } |
324 | 383 | ||
325 | return true; | 384 | return true; |
326 | } | 385 | } |
327 | 386 | ||
@@ -346,6 +405,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
346 | /// </returns> | 405 | /// </returns> |
347 | protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) | 406 | protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) |
348 | { | 407 | { |
408 | if (sceneObject == null) | ||
409 | { | ||
410 | m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object"); | ||
411 | return false; | ||
412 | } | ||
349 | if (sceneObject.UUID == UUID.Zero) | 413 | if (sceneObject.UUID == UUID.Zero) |
350 | { | 414 | { |
351 | m_log.ErrorFormat( | 415 | m_log.ErrorFormat( |
@@ -378,9 +442,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
378 | { | 442 | { |
379 | Vector3 scale = part.Shape.Scale; | 443 | Vector3 scale = part.Shape.Scale; |
380 | 444 | ||
381 | scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); | 445 | scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); |
382 | scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); | 446 | scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); |
383 | scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); | 447 | scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); |
384 | 448 | ||
385 | part.Shape.Scale = scale; | 449 | part.Shape.Scale = scale; |
386 | } | 450 | } |
@@ -401,36 +465,39 @@ namespace OpenSim.Region.Framework.Scenes | |||
401 | 465 | ||
402 | sceneObject.AttachToScene(m_parentScene); | 466 | sceneObject.AttachToScene(m_parentScene); |
403 | 467 | ||
404 | if (sendClientUpdates) | ||
405 | sceneObject.ScheduleGroupForFullUpdate(); | ||
406 | |||
407 | Entities.Add(sceneObject); | 468 | Entities.Add(sceneObject); |
408 | 469 | ||
409 | if (attachToBackup) | ||
410 | sceneObject.AttachToBackup(); | ||
411 | |||
412 | lock (SceneObjectGroupsByFullID) | 470 | lock (SceneObjectGroupsByFullID) |
413 | SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; | 471 | SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; |
414 | 472 | ||
415 | lock (SceneObjectGroupsByFullPartID) | 473 | foreach (SceneObjectPart part in parts) |
416 | { | 474 | { |
417 | foreach (SceneObjectPart part in parts) | 475 | lock (SceneObjectGroupsByFullPartID) |
418 | SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; | 476 | SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; |
419 | } | ||
420 | |||
421 | lock (SceneObjectGroupsByLocalPartID) | ||
422 | { | ||
423 | // m_log.DebugFormat( | ||
424 | // "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}", | ||
425 | // sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName); | ||
426 | 477 | ||
427 | foreach (SceneObjectPart part in parts) | 478 | lock (SceneObjectGroupsByLocalPartID) |
428 | SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; | 479 | SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; |
429 | } | 480 | } |
430 | 481 | ||
482 | if (sendClientUpdates) | ||
483 | sceneObject.ScheduleGroupForFullUpdate(); | ||
484 | |||
485 | if (attachToBackup) | ||
486 | sceneObject.AttachToBackup(); | ||
487 | |||
431 | return true; | 488 | return true; |
432 | } | 489 | } |
433 | 490 | ||
491 | public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp) | ||
492 | { | ||
493 | // no tests, caller has responsability... | ||
494 | lock (SceneObjectGroupsByFullPartID) | ||
495 | SceneObjectGroupsByFullPartID[part.UUID] = grp; | ||
496 | |||
497 | lock (SceneObjectGroupsByLocalPartID) | ||
498 | SceneObjectGroupsByLocalPartID[part.LocalId] = grp; | ||
499 | } | ||
500 | |||
434 | /// <summary> | 501 | /// <summary> |
435 | /// Delete an object from the scene | 502 | /// Delete an object from the scene |
436 | /// </summary> | 503 | /// </summary> |
@@ -471,25 +538,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
471 | if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) | 538 | if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) |
472 | RemovePhysicalPrim(grp.PrimCount); | 539 | RemovePhysicalPrim(grp.PrimCount); |
473 | } | 540 | } |
474 | 541 | ||
542 | bool ret = Entities.Remove(uuid); | ||
543 | |||
475 | lock (SceneObjectGroupsByFullID) | 544 | lock (SceneObjectGroupsByFullID) |
476 | SceneObjectGroupsByFullID.Remove(grp.UUID); | 545 | SceneObjectGroupsByFullID.Remove(grp.UUID); |
477 | 546 | ||
478 | lock (SceneObjectGroupsByFullPartID) | 547 | SceneObjectPart[] parts = grp.Parts; |
548 | for (int i = 0; i < parts.Length; i++) | ||
479 | { | 549 | { |
480 | SceneObjectPart[] parts = grp.Parts; | 550 | lock (SceneObjectGroupsByFullPartID) |
481 | for (int i = 0; i < parts.Length; i++) | ||
482 | SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); | 551 | SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); |
483 | } | ||
484 | 552 | ||
485 | lock (SceneObjectGroupsByLocalPartID) | 553 | lock (SceneObjectGroupsByLocalPartID) |
486 | { | ||
487 | SceneObjectPart[] parts = grp.Parts; | ||
488 | for (int i = 0; i < parts.Length; i++) | ||
489 | SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); | 554 | SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); |
490 | } | 555 | } |
491 | 556 | ||
492 | return Entities.Remove(uuid); | 557 | return ret; |
493 | } | 558 | } |
494 | 559 | ||
495 | /// <summary> | 560 | /// <summary> |
@@ -504,6 +569,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
504 | m_updateList[obj.UUID] = obj; | 569 | m_updateList[obj.UUID] = obj; |
505 | } | 570 | } |
506 | 571 | ||
572 | public void FireAttachToBackup(SceneObjectGroup obj) | ||
573 | { | ||
574 | if (OnAttachToBackup != null) | ||
575 | { | ||
576 | OnAttachToBackup(obj); | ||
577 | } | ||
578 | } | ||
579 | |||
580 | public void FireDetachFromBackup(SceneObjectGroup obj) | ||
581 | { | ||
582 | if (OnDetachFromBackup != null) | ||
583 | { | ||
584 | OnDetachFromBackup(obj); | ||
585 | } | ||
586 | } | ||
587 | |||
588 | public void FireChangeBackup(SceneObjectGroup obj) | ||
589 | { | ||
590 | if (OnChangeBackup != null) | ||
591 | { | ||
592 | OnChangeBackup(obj); | ||
593 | } | ||
594 | } | ||
595 | |||
507 | /// <summary> | 596 | /// <summary> |
508 | /// Process all pending updates | 597 | /// Process all pending updates |
509 | /// </summary> | 598 | /// </summary> |
@@ -595,7 +684,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
595 | 684 | ||
596 | Entities[presence.UUID] = presence; | 685 | Entities[presence.UUID] = presence; |
597 | 686 | ||
598 | lock (m_presenceLock) | 687 | m_scenePresencesLock.EnterWriteLock(); |
688 | try | ||
599 | { | 689 | { |
600 | m_numChildAgents++; | 690 | m_numChildAgents++; |
601 | 691 | ||
@@ -621,6 +711,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
621 | m_scenePresenceMap = newmap; | 711 | m_scenePresenceMap = newmap; |
622 | m_scenePresenceArray = newlist; | 712 | m_scenePresenceArray = newlist; |
623 | } | 713 | } |
714 | finally | ||
715 | { | ||
716 | m_scenePresencesLock.ExitWriteLock(); | ||
717 | } | ||
624 | 718 | ||
625 | return presence; | 719 | return presence; |
626 | } | 720 | } |
@@ -637,7 +731,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
637 | agentID); | 731 | agentID); |
638 | } | 732 | } |
639 | 733 | ||
640 | lock (m_presenceLock) | 734 | m_scenePresencesLock.EnterWriteLock(); |
735 | try | ||
641 | { | 736 | { |
642 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); | 737 | Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); |
643 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); | 738 | List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); |
@@ -659,6 +754,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
659 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); | 754 | m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); |
660 | } | 755 | } |
661 | } | 756 | } |
757 | finally | ||
758 | { | ||
759 | m_scenePresencesLock.ExitWriteLock(); | ||
760 | } | ||
662 | } | 761 | } |
663 | 762 | ||
664 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) | 763 | protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) |
@@ -887,7 +986,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
887 | m_log.WarnFormat( | 986 | m_log.WarnFormat( |
888 | "[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}.", | 987 | "[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}.", |
889 | sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); | 988 | sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); |
890 | 989 | m_log.WarnFormat("stack: {0}", Environment.StackTrace); | |
891 | SceneObjectGroupsByLocalPartID.Remove(localID); | 990 | SceneObjectGroupsByLocalPartID.Remove(localID); |
892 | } | 991 | } |
893 | } | 992 | } |
@@ -1223,6 +1322,52 @@ namespace OpenSim.Region.Framework.Scenes | |||
1223 | 1322 | ||
1224 | #region Client Event handlers | 1323 | #region Client Event handlers |
1225 | 1324 | ||
1325 | protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient) | ||
1326 | { | ||
1327 | SceneObjectPart part = GetSceneObjectPart(localID); | ||
1328 | ObjectChangeData data = (ObjectChangeData)odata; | ||
1329 | |||
1330 | if (part != null) | ||
1331 | { | ||
1332 | SceneObjectGroup grp = part.ParentGroup; | ||
1333 | if (grp != null) | ||
1334 | { | ||
1335 | if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId)) | ||
1336 | { | ||
1337 | // These two are exceptions SL makes in the interpretation | ||
1338 | // of the change flags. Must check them here because otherwise | ||
1339 | // the group flag (see below) would be lost | ||
1340 | if (data.change == ObjectChangeType.groupS) | ||
1341 | data.change = ObjectChangeType.primS; | ||
1342 | if (data.change == ObjectChangeType.groupPS) | ||
1343 | data.change = ObjectChangeType.primPS; | ||
1344 | part.StoreUndoState(data.change); // lets test only saving what we changed | ||
1345 | grp.doChangeObject(part, (ObjectChangeData)data); | ||
1346 | } | ||
1347 | else | ||
1348 | { | ||
1349 | // Is this any kind of group operation? | ||
1350 | if ((data.change & ObjectChangeType.Group) != 0) | ||
1351 | { | ||
1352 | // Is a move and/or rotation requested? | ||
1353 | if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0) | ||
1354 | { | ||
1355 | // Are we allowed to move it? | ||
1356 | if (m_parentScene.Permissions.CanMoveObject(grp.UUID, remoteClient.AgentId)) | ||
1357 | { | ||
1358 | // Strip all but move and rotation from request | ||
1359 | data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation); | ||
1360 | |||
1361 | part.StoreUndoState(data.change); | ||
1362 | grp.doChangeObject(part, (ObjectChangeData)data); | ||
1363 | } | ||
1364 | } | ||
1365 | } | ||
1366 | } | ||
1367 | } | ||
1368 | } | ||
1369 | } | ||
1370 | |||
1226 | /// <summary> | 1371 | /// <summary> |
1227 | /// Update the scale of an individual prim. | 1372 | /// Update the scale of an individual prim. |
1228 | /// </summary> | 1373 | /// </summary> |
@@ -1237,7 +1382,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1237 | { | 1382 | { |
1238 | if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) | 1383 | if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) |
1239 | { | 1384 | { |
1385 | bool physbuild = false; | ||
1386 | if (part.ParentGroup.RootPart.PhysActor != null) | ||
1387 | { | ||
1388 | part.ParentGroup.RootPart.PhysActor.Building = true; | ||
1389 | physbuild = true; | ||
1390 | } | ||
1391 | |||
1240 | part.Resize(scale); | 1392 | part.Resize(scale); |
1393 | |||
1394 | if (physbuild) | ||
1395 | part.ParentGroup.RootPart.PhysActor.Building = false; | ||
1241 | } | 1396 | } |
1242 | } | 1397 | } |
1243 | } | 1398 | } |
@@ -1249,7 +1404,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1249 | { | 1404 | { |
1250 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) | 1405 | if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) |
1251 | { | 1406 | { |
1407 | bool physbuild = false; | ||
1408 | if (group.RootPart.PhysActor != null) | ||
1409 | { | ||
1410 | group.RootPart.PhysActor.Building = true; | ||
1411 | physbuild = true; | ||
1412 | } | ||
1413 | |||
1252 | group.GroupResize(scale); | 1414 | group.GroupResize(scale); |
1415 | |||
1416 | if (physbuild) | ||
1417 | group.RootPart.PhysActor.Building = false; | ||
1253 | } | 1418 | } |
1254 | } | 1419 | } |
1255 | } | 1420 | } |
@@ -1388,8 +1553,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1388 | { | 1553 | { |
1389 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) | 1554 | if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) |
1390 | { | 1555 | { |
1391 | if (m_parentScene.AttachmentsModule != null) | 1556 | // Set the new attachment point data in the object |
1392 | m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); | 1557 | byte attachmentPoint = group.GetAttachmentPoint(); |
1558 | group.UpdateGroupPosition(pos); | ||
1559 | group.IsAttachment = false; | ||
1560 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
1561 | group.AttachmentPoint = attachmentPoint; | ||
1562 | group.HasGroupChanged = true; | ||
1393 | } | 1563 | } |
1394 | else | 1564 | else |
1395 | { | 1565 | { |
@@ -1447,6 +1617,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1447 | // VolumeDetect can't be set via UI and will always be off when a change is made there | 1617 | // VolumeDetect can't be set via UI and will always be off when a change is made there |
1448 | // now only change volume dtc if phantom off | 1618 | // now only change volume dtc if phantom off |
1449 | 1619 | ||
1620 | bool wantedPhys = UsePhysics; | ||
1450 | if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data | 1621 | if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data |
1451 | { | 1622 | { |
1452 | bool vdtc; | 1623 | bool vdtc; |
@@ -1463,10 +1634,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1463 | if (part != null) | 1634 | if (part != null) |
1464 | { | 1635 | { |
1465 | part.UpdateExtraPhysics(PhysData); | 1636 | part.UpdateExtraPhysics(PhysData); |
1466 | if (part.UpdatePhysRequired) | 1637 | if (part.UpdatePhysRequired && remoteClient != null) |
1467 | remoteClient.SendPartPhysicsProprieties(part); | 1638 | remoteClient.SendPartPhysicsProprieties(part); |
1468 | } | 1639 | } |
1469 | } | 1640 | } |
1641 | |||
1642 | if (wantedPhys != group.UsesPhysics && remoteClient != null) | ||
1643 | { | ||
1644 | remoteClient.SendAlertMessage("Object physics canceled because exceeds the limit of " + | ||
1645 | m_parentScene.m_linksetPhysCapacity + " physical prims with shape type not set to None"); | ||
1646 | group.RootPart.ScheduleFullUpdate(); | ||
1647 | } | ||
1470 | } | 1648 | } |
1471 | } | 1649 | } |
1472 | } | 1650 | } |
@@ -1611,6 +1789,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1611 | { | 1789 | { |
1612 | part.Material = Convert.ToByte(material); | 1790 | part.Material = Convert.ToByte(material); |
1613 | group.HasGroupChanged = true; | 1791 | group.HasGroupChanged = true; |
1792 | remoteClient.SendPartPhysicsProprieties(part); | ||
1614 | } | 1793 | } |
1615 | } | 1794 | } |
1616 | } | 1795 | } |
@@ -1689,12 +1868,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1689 | return; | 1868 | return; |
1690 | 1869 | ||
1691 | Monitor.Enter(m_updateLock); | 1870 | Monitor.Enter(m_updateLock); |
1871 | |||
1692 | try | 1872 | try |
1693 | { | 1873 | { |
1874 | |||
1694 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); | 1875 | List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); |
1695 | 1876 | ||
1696 | // We do this in reverse to get the link order of the prims correct | 1877 | // We do this in reverse to get the link order of the prims correct |
1697 | for (int i = 0 ; i < children.Count ; i++) | 1878 | for (int i = 0; i < children.Count; i++) |
1698 | { | 1879 | { |
1699 | SceneObjectGroup child = children[i].ParentGroup; | 1880 | SceneObjectGroup child = children[i].ParentGroup; |
1700 | 1881 | ||
@@ -1705,9 +1886,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1705 | // Make sure no child prim is set for sale | 1886 | // Make sure no child prim is set for sale |
1706 | // So that, on delink, no prims are unwittingly | 1887 | // So that, on delink, no prims are unwittingly |
1707 | // left for sale and sold off | 1888 | // left for sale and sold off |
1708 | child.RootPart.ObjectSaleType = 0; | 1889 | |
1709 | child.RootPart.SalePrice = 10; | 1890 | if (child != null) |
1710 | childGroups.Add(child); | 1891 | { |
1892 | child.RootPart.ObjectSaleType = 0; | ||
1893 | child.RootPart.SalePrice = 10; | ||
1894 | childGroups.Add(child); | ||
1895 | } | ||
1711 | } | 1896 | } |
1712 | 1897 | ||
1713 | foreach (SceneObjectGroup child in childGroups) | 1898 | foreach (SceneObjectGroup child in childGroups) |
@@ -1736,6 +1921,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1736 | } | 1921 | } |
1737 | finally | 1922 | finally |
1738 | { | 1923 | { |
1924 | /* | ||
1925 | lock (SceneObjectGroupsByLocalPartID) | ||
1926 | { | ||
1927 | foreach (SceneObjectPart part in parentGroup.Parts) | ||
1928 | SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; | ||
1929 | } | ||
1930 | */ | ||
1931 | parentGroup.AdjustChildPrimPermissions(); | ||
1932 | parentGroup.HasGroupChanged = true; | ||
1933 | parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); | ||
1934 | parentGroup.ScheduleGroupForFullUpdate(); | ||
1739 | Monitor.Exit(m_updateLock); | 1935 | Monitor.Exit(m_updateLock); |
1740 | } | 1936 | } |
1741 | } | 1937 | } |
@@ -1777,21 +1973,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
1777 | 1973 | ||
1778 | SceneObjectGroup group = part.ParentGroup; | 1974 | SceneObjectGroup group = part.ParentGroup; |
1779 | if (!affectedGroups.Contains(group)) | 1975 | if (!affectedGroups.Contains(group)) |
1976 | { | ||
1780 | affectedGroups.Add(group); | 1977 | affectedGroups.Add(group); |
1978 | } | ||
1781 | } | 1979 | } |
1782 | } | 1980 | } |
1783 | } | 1981 | } |
1784 | 1982 | ||
1785 | foreach (SceneObjectPart child in childParts) | 1983 | if (childParts.Count > 0) |
1786 | { | 1984 | { |
1787 | // Unlink all child parts from their groups | 1985 | foreach (SceneObjectPart child in childParts) |
1788 | // | 1986 | { |
1789 | child.ParentGroup.DelinkFromGroup(child, true); | 1987 | // Unlink all child parts from their groups |
1790 | 1988 | // | |
1791 | // These are not in affected groups and will not be | 1989 | child.ParentGroup.DelinkFromGroup(child, true); |
1792 | // handled further. Do the honors here. | 1990 | child.ParentGroup.HasGroupChanged = true; |
1793 | child.ParentGroup.HasGroupChanged = true; | 1991 | child.ParentGroup.ScheduleGroupForFullUpdate(); |
1794 | child.ParentGroup.ScheduleGroupForFullUpdate(); | 1992 | } |
1795 | } | 1993 | } |
1796 | 1994 | ||
1797 | foreach (SceneObjectPart root in rootParts) | 1995 | foreach (SceneObjectPart root in rootParts) |
@@ -1805,52 +2003,58 @@ namespace OpenSim.Region.Framework.Scenes | |||
1805 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); | 2003 | List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); |
1806 | int numChildren = newSet.Count; | 2004 | int numChildren = newSet.Count; |
1807 | 2005 | ||
2006 | if (numChildren == 1) | ||
2007 | break; | ||
2008 | |||
1808 | // If there are prims left in a link set, but the root is | 2009 | // If there are prims left in a link set, but the root is |
1809 | // slated for unlink, we need to do this | 2010 | // slated for unlink, we need to do this |
2011 | // Unlink the remaining set | ||
1810 | // | 2012 | // |
1811 | if (numChildren != 1) | 2013 | bool sendEventsToRemainder = false; |
1812 | { | 2014 | if (numChildren == 2) // only one child prim no re-link needed |
1813 | // Unlink the remaining set | 2015 | sendEventsToRemainder = true; |
1814 | // | ||
1815 | bool sendEventsToRemainder = true; | ||
1816 | if (numChildren > 1) | ||
1817 | sendEventsToRemainder = false; | ||
1818 | 2016 | ||
1819 | foreach (SceneObjectPart p in newSet) | 2017 | foreach (SceneObjectPart p in newSet) |
2018 | { | ||
2019 | if (p != group.RootPart) | ||
1820 | { | 2020 | { |
1821 | if (p != group.RootPart) | 2021 | group.DelinkFromGroup(p, sendEventsToRemainder); |
1822 | group.DelinkFromGroup(p, sendEventsToRemainder); | 2022 | if (sendEventsToRemainder) // finish single child prim now |
2023 | { | ||
2024 | p.ParentGroup.HasGroupChanged = true; | ||
2025 | p.ParentGroup.ScheduleGroupForFullUpdate(); | ||
2026 | } | ||
1823 | } | 2027 | } |
2028 | } | ||
1824 | 2029 | ||
1825 | // If there is more than one prim remaining, we | 2030 | // If there is more than one prim remaining, we |
1826 | // need to re-link | 2031 | // need to re-link |
2032 | // | ||
2033 | if (numChildren > 2) | ||
2034 | { | ||
2035 | // Remove old root | ||
1827 | // | 2036 | // |
1828 | if (numChildren > 2) | 2037 | if (newSet.Contains(root)) |
2038 | newSet.Remove(root); | ||
2039 | |||
2040 | // Preserve link ordering | ||
2041 | // | ||
2042 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1829 | { | 2043 | { |
1830 | // Remove old root | 2044 | return a.LinkNum.CompareTo(b.LinkNum); |
1831 | // | 2045 | }); |
1832 | if (newSet.Contains(root)) | ||
1833 | newSet.Remove(root); | ||
1834 | |||
1835 | // Preserve link ordering | ||
1836 | // | ||
1837 | newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) | ||
1838 | { | ||
1839 | return a.LinkNum.CompareTo(b.LinkNum); | ||
1840 | }); | ||
1841 | 2046 | ||
1842 | // Determine new root | 2047 | // Determine new root |
1843 | // | 2048 | // |
1844 | SceneObjectPart newRoot = newSet[0]; | 2049 | SceneObjectPart newRoot = newSet[0]; |
1845 | newSet.RemoveAt(0); | 2050 | newSet.RemoveAt(0); |
1846 | 2051 | ||
1847 | foreach (SceneObjectPart newChild in newSet) | 2052 | foreach (SceneObjectPart newChild in newSet) |
1848 | newChild.ClearUpdateSchedule(); | 2053 | newChild.ClearUpdateSchedule(); |
1849 | 2054 | ||
1850 | LinkObjects(newRoot, newSet); | 2055 | LinkObjects(newRoot, newSet); |
1851 | if (!affectedGroups.Contains(newRoot.ParentGroup)) | 2056 | // if (!affectedGroups.Contains(newRoot.ParentGroup)) |
1852 | affectedGroups.Add(newRoot.ParentGroup); | 2057 | // affectedGroups.Add(newRoot.ParentGroup); |
1853 | } | ||
1854 | } | 2058 | } |
1855 | } | 2059 | } |
1856 | 2060 | ||
@@ -1858,6 +2062,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
1858 | // | 2062 | // |
1859 | foreach (SceneObjectGroup g in affectedGroups) | 2063 | foreach (SceneObjectGroup g in affectedGroups) |
1860 | { | 2064 | { |
2065 | // Child prims that have been unlinked and deleted will | ||
2066 | // return unless the root is deleted. This will remove them | ||
2067 | // from the database. They will be rewritten immediately, | ||
2068 | // minus the rows for the unlinked child prims. | ||
2069 | g.AdjustChildPrimPermissions(); | ||
2070 | m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); | ||
1861 | g.TriggerScriptChangedEvent(Changed.LINK); | 2071 | g.TriggerScriptChangedEvent(Changed.LINK); |
1862 | g.HasGroupChanged = true; // Persist | 2072 | g.HasGroupChanged = true; // Persist |
1863 | g.ScheduleGroupForFullUpdate(); | 2073 | g.ScheduleGroupForFullUpdate(); |
@@ -1931,54 +2141,63 @@ namespace OpenSim.Region.Framework.Scenes | |||
1931 | /// <param name="GroupID"></param> | 2141 | /// <param name="GroupID"></param> |
1932 | /// <param name="rot"></param> | 2142 | /// <param name="rot"></param> |
1933 | /// <returns>null if duplication fails, otherwise the duplicated object</returns> | 2143 | /// <returns>null if duplication fails, otherwise the duplicated object</returns> |
1934 | public SceneObjectGroup DuplicateObject( | 2144 | /// <summary> |
1935 | uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) | 2145 | public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) |
1936 | { | 2146 | { |
1937 | Monitor.Enter(m_updateLock); | 2147 | // m_log.DebugFormat( |
2148 | // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", | ||
2149 | // originalPrimID, offset, AgentID); | ||
1938 | 2150 | ||
1939 | try | 2151 | SceneObjectGroup original = GetGroupByPrim(originalPrimID); |
2152 | if (original != null) | ||
1940 | { | 2153 | { |
1941 | // m_log.DebugFormat( | 2154 | if (m_parentScene.Permissions.CanDuplicateObject( |
1942 | // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", | 2155 | original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) |
1943 | // originalPrimID, offset, AgentID); | ||
1944 | |||
1945 | SceneObjectGroup original = GetGroupByPrim(originalPrimID); | ||
1946 | if (original == null) | ||
1947 | { | 2156 | { |
2157 | <<<<<<< HEAD | ||
1948 | m_log.WarnFormat( | 2158 | m_log.WarnFormat( |
1949 | "[SCENEGRAPH]: Attempt to duplicate nonexistent prim id {0} by {1}", originalPrimID, AgentID); | 2159 | "[SCENEGRAPH]: Attempt to duplicate nonexistent prim id {0} by {1}", originalPrimID, AgentID); |
2160 | ======= | ||
2161 | SceneObjectGroup copy = original.Copy(true); | ||
2162 | copy.AbsolutePosition = copy.AbsolutePosition + offset; | ||
2163 | >>>>>>> avn/ubitvar | ||
1950 | 2164 | ||
1951 | return null; | 2165 | if (original.OwnerID != AgentID) |
1952 | } | 2166 | { |
2167 | copy.SetOwnerId(AgentID); | ||
2168 | copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); | ||
1953 | 2169 | ||
1954 | if (!m_parentScene.Permissions.CanDuplicateObject( | 2170 | SceneObjectPart[] partList = copy.Parts; |
1955 | original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) | ||
1956 | return null; | ||
1957 | 2171 | ||
1958 | SceneObjectGroup copy = original.Copy(true); | 2172 | if (m_parentScene.Permissions.PropagatePermissions()) |
1959 | copy.AbsolutePosition = copy.AbsolutePosition + offset; | 2173 | { |
2174 | foreach (SceneObjectPart child in partList) | ||
2175 | { | ||
2176 | child.Inventory.ChangeInventoryOwner(AgentID); | ||
2177 | child.TriggerScriptChangedEvent(Changed.OWNER); | ||
2178 | child.ApplyNextOwnerPermissions(); | ||
2179 | } | ||
2180 | } | ||
2181 | } | ||
1960 | 2182 | ||
1961 | if (original.OwnerID != AgentID) | 2183 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() |
1962 | { | 2184 | Entities.Add(copy); |
1963 | copy.SetOwnerId(AgentID); | ||
1964 | copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); | ||
1965 | 2185 | ||
1966 | SceneObjectPart[] partList = copy.Parts; | 2186 | lock (SceneObjectGroupsByFullID) |
2187 | SceneObjectGroupsByFullID[copy.UUID] = copy; | ||
1967 | 2188 | ||
1968 | if (m_parentScene.Permissions.PropagatePermissions()) | 2189 | SceneObjectPart[] parts = copy.Parts; |
2190 | foreach (SceneObjectPart part in parts) | ||
1969 | { | 2191 | { |
1970 | foreach (SceneObjectPart child in partList) | 2192 | lock (SceneObjectGroupsByFullPartID) |
1971 | { | 2193 | SceneObjectGroupsByFullPartID[part.UUID] = copy; |
1972 | child.Inventory.ChangeInventoryOwner(AgentID); | 2194 | lock (SceneObjectGroupsByLocalPartID) |
1973 | child.TriggerScriptChangedEvent(Changed.OWNER); | 2195 | SceneObjectGroupsByLocalPartID[part.LocalId] = copy; |
1974 | child.ApplyNextOwnerPermissions(); | ||
1975 | } | ||
1976 | } | 2196 | } |
1977 | 2197 | ||
1978 | copy.RootPart.ObjectSaleType = 0; | 2198 | // PROBABLE END OF FIXME |
1979 | copy.RootPart.SalePrice = 10; | ||
1980 | } | ||
1981 | 2199 | ||
2200 | <<<<<<< HEAD | ||
1982 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() | 2201 | // FIXME: This section needs to be refactored so that it just calls AddSceneObject() |
1983 | Entities.Add(copy); | 2202 | Entities.Add(copy); |
1984 | 2203 | ||
@@ -2027,24 +2246,41 @@ namespace OpenSim.Region.Framework.Scenes | |||
2027 | { | 2246 | { |
2028 | copy.UpdateGroupRotationR(rot); | 2247 | copy.UpdateGroupRotationR(rot); |
2029 | } | 2248 | } |
2249 | ======= | ||
2250 | // Since we copy from a source group that is in selected | ||
2251 | // state, but the copy is shown deselected in the viewer, | ||
2252 | // We need to clear the selection flag here, else that | ||
2253 | // prim never gets persisted at all. The client doesn't | ||
2254 | // think it's selected, so it will never send a deselect... | ||
2255 | copy.IsSelected = false; | ||
2256 | >>>>>>> avn/ubitvar | ||
2257 | |||
2258 | m_numPrim += copy.Parts.Length; | ||
2259 | |||
2260 | if (rot != Quaternion.Identity) | ||
2261 | { | ||
2262 | copy.UpdateGroupRotationR(rot); | ||
2263 | } | ||
2030 | 2264 | ||
2031 | copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); | 2265 | copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); |
2032 | copy.HasGroupChanged = true; | 2266 | copy.HasGroupChanged = true; |
2033 | copy.ScheduleGroupForFullUpdate(); | 2267 | copy.ScheduleGroupForFullUpdate(); |
2034 | copy.ResumeScripts(); | 2268 | copy.ResumeScripts(); |
2035 | 2269 | ||
2036 | // required for physics to update it's position | 2270 | // required for physics to update it's position |
2037 | copy.AbsolutePosition = copy.AbsolutePosition; | 2271 | copy.AbsolutePosition = copy.AbsolutePosition; |
2038 | 2272 | ||
2039 | return copy; | 2273 | return copy; |
2274 | } | ||
2040 | } | 2275 | } |
2041 | finally | 2276 | else |
2042 | { | 2277 | { |
2043 | Monitor.Exit(m_updateLock); | 2278 | m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID); |
2044 | } | 2279 | } |
2280 | |||
2281 | return null; | ||
2045 | } | 2282 | } |
2046 | 2283 | ||
2047 | /// <summary> | ||
2048 | /// Calculates the distance between two Vector3s | 2284 | /// Calculates the distance between two Vector3s |
2049 | /// </summary> | 2285 | /// </summary> |
2050 | /// <param name="v1"></param> | 2286 | /// <param name="v1"></param> |