From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001 From: onefang Date: Sun, 19 May 2019 21:24:15 +1000 Subject: Dump OpenSim 0.9.0.1 into it's own branch. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 833 ++++++++++++++------------ 1 file changed, 466 insertions(+), 367 deletions(-) mode change 100644 => 100755 OpenSim/Region/Framework/Scenes/SceneGraph.cs (limited to 'OpenSim/Region/Framework/Scenes/SceneGraph.cs') diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs old mode 100644 new mode 100755 index e0080f2..61a243d --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes { public delegate void PhysicsCrash(); + public delegate void AttachToBackupDelegate(SceneObjectGroup sog); + + public delegate void DetachFromBackupDelegate(SceneObjectGroup sog); + + public delegate void ChangedBackupDelegate(SceneObjectGroup sog); + /// /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components /// should be migrated out over time. @@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes protected internal event PhysicsCrash UnRecoverableError; private PhysicsCrash handlerPhysicsCrash = null; + public event AttachToBackupDelegate OnAttachToBackup; + public event DetachFromBackupDelegate OnDetachFromBackup; + public event ChangedBackupDelegate OnChangeBackup; + #endregion #region Fields - protected object m_presenceLock = new object(); + protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); protected Dictionary m_scenePresenceMap = new Dictionary(); protected List m_scenePresenceArray = new List(); @@ -77,21 +87,21 @@ namespace OpenSim.Region.Framework.Scenes protected int m_scriptLPS = 0; protected internal PhysicsScene _PhyScene; - + /// /// Index the SceneObjectGroup for each part by the root part's UUID. /// protected internal Dictionary SceneObjectGroupsByFullID = new Dictionary(); - + /// /// Index the SceneObjectGroup for each part by that part's UUID. /// protected internal Dictionary SceneObjectGroupsByFullPartID = new Dictionary(); - + /// /// Index the SceneObjectGroup for each part by that part's local ID. /// - protected internal Dictionary SceneObjectGroupsByLocalPartID = new Dictionary(); + protected internal Dictionary SceneObjectGroupsByLocalPartID = new Dictionary(); /// /// Lock to prevent object group update, linking, delinking and duplication operations from running concurrently. @@ -111,11 +121,11 @@ namespace OpenSim.Region.Framework.Scenes public PhysicsScene PhysicsScene { - get + get { if (_PhyScene == null) _PhyScene = m_parentScene.RequestModuleInterface(); - return _PhyScene; + return _PhyScene; } set { @@ -134,13 +144,18 @@ namespace OpenSim.Region.Framework.Scenes protected internal void Close() { - lock (m_presenceLock) + m_scenePresencesLock.EnterWriteLock(); + try { Dictionary newmap = new Dictionary(); List newlist = new List(); m_scenePresenceMap = newmap; m_scenePresenceArray = newlist; } + finally + { + m_scenePresencesLock.ExitWriteLock(); + } lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID.Clear(); @@ -200,13 +215,20 @@ namespace OpenSim.Region.Framework.Scenes // the joint in the Scene does not exist in the PhysicsScene. // // To solve this, we have an event in the PhysicsScene that is fired when a joint - // has changed position (because one of its associated PhysicsActors has changed + // has changed position (because one of its associated PhysicsActors has changed // position). // // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate(). + return PhysicsScene.Simulate((float)elapsed); } + protected internal void ProcessPhysicsPreSimulation() + { + if(PhysicsScene != null) + PhysicsScene.ProcessPreSimulation(); + } + protected internal void UpdateScenePresenceMovement() { ForEachScenePresence(delegate(ScenePresence presence) @@ -220,17 +242,32 @@ namespace OpenSim.Region.Framework.Scenes coarseLocations = new List(); avatarUUIDs = new List(); + // coarse locations are sent as BYTE, so limited to the 255m max of normal regions + // try to work around that scale down X and Y acording to region size, so reducing the resolution + // + // viewers need to scale up + float scaleX = (float)m_parentScene.RegionInfo.RegionSizeX / (float)Constants.RegionSize; + if (scaleX == 0) + scaleX = 1.0f; + scaleX = 1.0f / scaleX; + float scaleY = (float)m_parentScene.RegionInfo.RegionSizeY / (float)Constants.RegionSize; + if (scaleY == 0) + scaleY = 1.0f; + scaleY = 1.0f / scaleY; + List presences = GetScenePresences(); for (int i = 0; i < Math.Min(presences.Count, maxLocations); ++i) { ScenePresence sp = presences[i]; - + // If this presence is a child agent, we don't want its coarse locations if (sp.IsChildAgent) continue; + Vector3 pos = sp.AbsolutePosition; + pos.X *= scaleX; + pos.Y *= scaleY; - coarseLocations.Add(sp.AbsolutePosition); - + coarseLocations.Add(pos); avatarUUIDs.Add(sp.UUID); } } @@ -261,15 +298,55 @@ namespace OpenSim.Region.Framework.Scenes protected internal bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) { + // temporary checks to remove after varsize suport + float regionSizeX = m_parentScene.RegionInfo.RegionSizeX; + if (regionSizeX == 0) + regionSizeX = Constants.RegionSize; + float regionSizeY = m_parentScene.RegionInfo.RegionSizeY; + if (regionSizeY == 0) + regionSizeY = Constants.RegionSize; + + // KF: Check for out-of-region, move inside and make static. + Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, + sceneObject.RootPart.GroupPosition.Y, + sceneObject.RootPart.GroupPosition.Z); + bool clampZ = m_parentScene.ClampNegativeZ; + + 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) || + npos.X > regionSizeX || + npos.Y > regionSizeY)) + { + if (npos.X < 0.0) npos.X = 1.0f; + if (npos.Y < 0.0) npos.Y = 1.0f; + if (npos.Z < 0.0 && clampZ) npos.Z = 0.0f; + if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f; + if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f; + + SceneObjectPart rootpart = sceneObject.RootPart; + rootpart.GroupPosition = npos; + + foreach (SceneObjectPart part in sceneObject.Parts) + { + if (part == rootpart) + continue; + part.GroupPosition = npos; + } + rootpart.Velocity = Vector3.Zero; + rootpart.AngularVelocity = Vector3.Zero; + rootpart.Acceleration = Vector3.Zero; + } + + bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); + if (attachToBackup && (!alreadyPersisted)) { sceneObject.ForceInventoryPersistence(); sceneObject.HasGroupChanged = true; } - - return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); + sceneObject.InvalidateDeepEffectivePerms(); + return ret; } - + /// /// Add a newly created object to the scene. This will both update the scene, and send information about the /// new object to all clients interested in the scene. @@ -284,18 +361,22 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { - // Ensure that we persist this new scene object if it's not an + + bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); + + // Ensure that we persist this new scene object if it's not an // attachment + if (attachToBackup) sceneObject.HasGroupChanged = true; - return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); + return ret; } - + /// /// Add a newly created object to the scene. /// - /// + /// /// This method does not send updates to the client - callers need to handle this themselves. /// Caller should also trigger EventManager.TriggerObjectAddedToScene /// @@ -307,26 +388,25 @@ namespace OpenSim.Region.Framework.Scenes public bool AddNewSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) { - AddNewSceneObject(sceneObject, attachToBackup, false); - if (pos != null) sceneObject.AbsolutePosition = (Vector3)pos; + if (rot != null) + sceneObject.UpdateGroupRotationR((Quaternion)rot); + + AddNewSceneObject(sceneObject, attachToBackup, false); + if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) { sceneObject.ClearPartAttachmentData(); } - if (rot != null) - sceneObject.UpdateGroupRotationR((Quaternion)rot); - PhysicsActor pa = sceneObject.RootPart.PhysActor; if (pa != null && pa.IsPhysical && vel != Vector3.Zero) { sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); - sceneObject.Velocity = vel; } - + return true; } @@ -351,6 +431,11 @@ namespace OpenSim.Region.Framework.Scenes /// protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { + if (sceneObject == null) + { + m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object"); + return false; + } if (sceneObject.UUID == UUID.Zero) { m_log.ErrorFormat( @@ -383,9 +468,9 @@ namespace OpenSim.Region.Framework.Scenes { Vector3 scale = part.Shape.Scale; - scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); - scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); - scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); + scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); + scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); + scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys); part.Shape.Scale = scale; } @@ -406,36 +491,39 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.AttachToScene(m_parentScene); - if (sendClientUpdates) - sceneObject.ScheduleGroupForFullUpdate(); - Entities.Add(sceneObject); - if (attachToBackup) - sceneObject.AttachToBackup(); - lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; - lock (SceneObjectGroupsByFullPartID) + foreach (SceneObjectPart part in parts) { - foreach (SceneObjectPart part in parts) + lock (SceneObjectGroupsByFullPartID) SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; - } - lock (SceneObjectGroupsByLocalPartID) - { -// m_log.DebugFormat( -// "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}", -// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName); - - foreach (SceneObjectPart part in parts) + lock (SceneObjectGroupsByLocalPartID) SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; } + if (sendClientUpdates) + sceneObject.ScheduleGroupForFullUpdate(); + + if (attachToBackup) + sceneObject.AttachToBackup(); + return true; } + public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp) + { + // no tests, caller has responsability... + lock (SceneObjectGroupsByFullPartID) + SceneObjectGroupsByFullPartID[part.UUID] = grp; + + lock (SceneObjectGroupsByLocalPartID) + SceneObjectGroupsByLocalPartID[part.LocalId] = grp; + } + /// /// Delete an object from the scene /// @@ -461,6 +549,8 @@ namespace OpenSim.Region.Framework.Scenes // that are part of the Scene Object being removed m_numTotalPrim -= grp.PrimCount; + bool isPh = (grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics; + int nphysparts = 0; // Go through all parts (primitives and meshes) of this Scene Object foreach (SceneObjectPart part in grp.Parts) { @@ -471,30 +561,31 @@ namespace OpenSim.Region.Framework.Scenes m_numMesh--; else m_numPrim--; + + if(isPh && part.PhysicsShapeType != (byte)PhysShapeType.none) + nphysparts++; } - if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) - RemovePhysicalPrim(grp.PrimCount); + if (nphysparts > 0 ) + RemovePhysicalPrim(nphysparts); } - + + bool ret = Entities.Remove(uuid); + lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID.Remove(grp.UUID); - lock (SceneObjectGroupsByFullPartID) + SceneObjectPart[] parts = grp.Parts; + for (int i = 0; i < parts.Length; i++) { - SceneObjectPart[] parts = grp.Parts; - for (int i = 0; i < parts.Length; i++) + lock (SceneObjectGroupsByFullPartID) SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); - } - lock (SceneObjectGroupsByLocalPartID) - { - SceneObjectPart[] parts = grp.Parts; - for (int i = 0; i < parts.Length; i++) + lock (SceneObjectGroupsByLocalPartID) SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); } - return Entities.Remove(uuid); + return ret; } /// @@ -509,6 +600,30 @@ namespace OpenSim.Region.Framework.Scenes m_updateList[obj.UUID] = obj; } + public void FireAttachToBackup(SceneObjectGroup obj) + { + if (OnAttachToBackup != null) + { + OnAttachToBackup(obj); + } + } + + public void FireDetachFromBackup(SceneObjectGroup obj) + { + if (OnDetachFromBackup != null) + { + OnDetachFromBackup(obj); + } + } + + public void FireChangeBackup(SceneObjectGroup obj) + { + if (OnChangeBackup != null) + { + OnChangeBackup(obj); + } + } + /// /// Process all pending updates /// @@ -520,7 +635,7 @@ namespace OpenSim.Region.Framework.Scenes { List updates; - // Some updates add more updates to the updateList. + // Some updates add more updates to the updateList. // Get the current list of updates and clear the list before iterating lock (m_updateList) { @@ -600,7 +715,8 @@ namespace OpenSim.Region.Framework.Scenes Entities[presence.UUID] = presence; - lock (m_presenceLock) + m_scenePresencesLock.EnterWriteLock(); + try { m_numChildAgents++; @@ -626,6 +742,10 @@ namespace OpenSim.Region.Framework.Scenes m_scenePresenceMap = newmap; m_scenePresenceArray = newlist; } + finally + { + m_scenePresencesLock.ExitWriteLock(); + } return presence; } @@ -642,11 +762,12 @@ namespace OpenSim.Region.Framework.Scenes agentID); } - lock (m_presenceLock) + m_scenePresencesLock.EnterWriteLock(); + try { Dictionary newmap = new Dictionary(m_scenePresenceMap); List newlist = new List(m_scenePresenceArray); - + // Remove the presence reference from the dictionary if (newmap.ContainsKey(agentID)) { @@ -664,6 +785,10 @@ namespace OpenSim.Region.Framework.Scenes m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); } } + finally + { + m_scenePresencesLock.ExitWriteLock(); + } } protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) @@ -754,7 +879,7 @@ namespace OpenSim.Region.Framework.Scenes #endregion #region Get Methods - + /// /// Get the controlling client for the given avatar, if there is one. /// @@ -892,7 +1017,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.WarnFormat( "[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}.", sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); - + m_log.WarnFormat("stack: {0}", Environment.StackTrace); SceneObjectGroupsByLocalPartID.Remove(localID); } } @@ -1066,11 +1191,11 @@ namespace OpenSim.Region.Framework.Scenes protected internal SceneObjectPart GetSceneObjectPart(uint localID) { SceneObjectGroup group = GetGroupByPrim(localID); - if (group == null) + if (group == null || group.IsDeleted) return null; return group.GetPart(localID); } - + /// /// Get a prim by name from the scene (will return the first /// found, if there are more than one prim with the same name) @@ -1089,7 +1214,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts) { // m_log.DebugFormat("[SCENE GRAPH]: Part {0} has name {1}", p.UUID, p.Name); - + if (p.Name == name) { sop = p; @@ -1188,7 +1313,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Performs action on all scene presences. This can ultimately run the actions in parallel but /// any delegates passed in will need to implement their own locking on data they reference and - /// modify outside of the scope of the delegate. + /// modify outside of the scope of the delegate. /// /// public void ForEachScenePresence(Action action) @@ -1223,11 +1348,57 @@ namespace OpenSim.Region.Framework.Scenes } } } - + #endregion #region Client Event handlers + protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient) + { + SceneObjectPart part = GetSceneObjectPart(localID); + ObjectChangeData data = (ObjectChangeData)odata; + + if (part != null) + { + SceneObjectGroup grp = part.ParentGroup; + if (grp != null) + { + if (m_parentScene.Permissions.CanEditObject(grp, remoteClient)) + { + // These two are exceptions SL makes in the interpretation + // of the change flags. Must check them here because otherwise + // the group flag (see below) would be lost + if (data.change == ObjectChangeType.groupS) + data.change = ObjectChangeType.primS; + if (data.change == ObjectChangeType.groupPS) + data.change = ObjectChangeType.primPS; + part.StoreUndoState(data.change); // lets test only saving what we changed + grp.doChangeObject(part, (ObjectChangeData)data); + } + else + { + // Is this any kind of group operation? + if ((data.change & ObjectChangeType.Group) != 0) + { + // Is a move and/or rotation requested? + if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0) + { + // Are we allowed to move it? + if (m_parentScene.Permissions.CanMoveObject(grp, remoteClient)) + { + // Strip all but move and rotation from request + data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation); + + part.StoreUndoState(data.change); + grp.doChangeObject(part, (ObjectChangeData)data); + } + } + } + } + } + } + } + /// /// Update the scale of an individual prim. /// @@ -1240,9 +1411,19 @@ namespace OpenSim.Region.Framework.Scenes if (part != null) { - if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(part.ParentGroup, remoteClient)) { + bool physbuild = false; + if (part.ParentGroup.RootPart.PhysActor != null) + { + part.ParentGroup.RootPart.PhysActor.Building = true; + physbuild = true; + } + part.Resize(scale); + + if (physbuild) + part.ParentGroup.RootPart.PhysActor.Building = false; } } } @@ -1252,9 +1433,19 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { + bool physbuild = false; + if (group.RootPart.PhysActor != null) + { + group.RootPart.PhysActor.Building = true; + physbuild = true; + } + group.GroupResize(scale); + + if (physbuild) + group.RootPart.PhysActor.Building = false; } } } @@ -1288,7 +1479,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) { group.UpdateSingleRotation(rot, localID); } @@ -1306,7 +1497,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) { group.UpdateSingleRotation(rot, pos, localID); } @@ -1324,7 +1515,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) { group.UpdateGroupRotationR(rot); } @@ -1343,7 +1534,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) { group.UpdateGroupRotationPR(pos, rot); } @@ -1361,7 +1552,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId) || group.IsAttachment) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient) || group.IsAttachment) { group.UpdateSinglePosition(pos, localID); } @@ -1376,30 +1567,24 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdatePrimGroupPosition(uint localId, Vector3 pos, IClientAPI remoteClient) { - UpdatePrimGroupPosition(localId, pos, remoteClient.AgentId); - } - - /// - /// Update the position of the given group. - /// - /// - /// - /// - public void UpdatePrimGroupPosition(uint localId, Vector3 pos, UUID updatingAgentId) - { SceneObjectGroup group = GetGroupByPrim(localId); - + if (group != null) { if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) { - if (m_parentScene.AttachmentsModule != null) - m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); + // Set the new attachment point data in the object + byte attachmentPoint = (byte)group.AttachmentPoint; + group.UpdateGroupPosition(pos); + group.IsAttachment = false; + group.AbsolutePosition = group.RootPart.AttachedPos; + group.AttachmentPoint = attachmentPoint; + group.HasGroupChanged = true; } else { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, updatingAgentId) - && m_parentScene.Permissions.CanObjectEntry(group.UUID, false, pos)) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient) + && m_parentScene.Permissions.CanObjectEntry(group, false, pos)) { group.UpdateGroupPosition(pos); } @@ -1419,13 +1604,16 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient) { - SceneObjectGroup group = GetGroupByPrim(localID); - - if (group != null) + SceneObjectPart part = GetSceneObjectPart(localID); + if(part == null) + return; + + SceneObjectGroup group = part.ParentGroup; + if (group != null && !group.IsDeleted) { - if (m_parentScene.Permissions.CanEditObject(group.UUID,remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { - group.UpdateTextureEntry(localID, texture); + part.UpdateTextureEntry(texture); } } } @@ -1447,11 +1635,12 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { // VolumeDetect can't be set via UI and will always be off when a change is made there // now only change volume dtc if phantom off + bool wantedPhys = UsePhysics; if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data { bool vdtc; @@ -1460,7 +1649,7 @@ namespace OpenSim.Region.Framework.Scenes else // else turn it off vdtc = false; - group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, vdtc); + group.UpdateFlags(UsePhysics, SetTemporary, SetPhantom, vdtc); } else { @@ -1468,77 +1657,21 @@ namespace OpenSim.Region.Framework.Scenes if (part != null) { part.UpdateExtraPhysics(PhysData); - if (part.UpdatePhysRequired) + if (remoteClient != null) remoteClient.SendPartPhysicsProprieties(part); } } - } - } - } - - /// - /// Move the given object - /// - /// - /// - /// - /// - protected internal void MoveObject(UUID objectID, Vector3 offset, Vector3 pos, IClientAPI remoteClient, List surfaceArgs) - { - SceneObjectGroup group = GetGroupByPrim(objectID); - if (group != null) - { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) - { - group.GrabMovement(objectID, offset, pos, remoteClient); - } - // This is outside the above permissions condition - // so that if the object is locked the client moving the object - // get's it's position on the simulator even if it was the same as before - // This keeps the moving user's client in sync with the rest of the world. - group.SendGroupTerseUpdate(); - } - } - - /// - /// Start spinning the given object - /// - /// - /// - /// - protected internal void SpinStart(UUID objectID, IClientAPI remoteClient) - { - SceneObjectGroup group = GetGroupByPrim(objectID); - if (group != null) - { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) - { - group.SpinStart(remoteClient); - } - } - } - - /// - /// Spin the given object - /// - /// - /// - /// - protected internal void SpinObject(UUID objectID, Quaternion rotation, IClientAPI remoteClient) - { - SceneObjectGroup group = GetGroupByPrim(objectID); - if (group != null) - { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) - { - group.SpinMovement(rotation, remoteClient); + if (wantedPhys != group.UsesPhysics && remoteClient != null) + { + if(m_parentScene.m_linksetPhysCapacity != 0) + remoteClient.SendAlertMessage("Object physics cancelled because it exceeds limits for physical prims, either size or number of primswith shape type not set to None"); + else + remoteClient.SendAlertMessage("Object physics cancelled because it exceeds size limits for physical prims"); + + group.RootPart.ScheduleFullUpdate(); + } } - // This is outside the above permissions condition - // so that if the object is locked the client moving the object - // get's it's position on the simulator even if it was the same as before - // This keeps the moving user's client in sync with the rest of the world. - group.SendGroupTerseUpdate(); } } @@ -1552,7 +1685,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { group.SetPartName(Util.CleanString(name), primLocalID); group.HasGroupChanged = true; @@ -1570,7 +1703,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { group.SetPartDescription(Util.CleanString(description), primLocalID); group.HasGroupChanged = true; @@ -1592,13 +1725,13 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID); if (part != null) { - part.ClickAction = Convert.ToByte(clickAction); - group.HasGroupChanged = true; + part.ClickAction = Convert.ToByte(clickAction); + group.HasGroupChanged = true; } } } @@ -1609,13 +1742,14 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID); if (part != null) { part.Material = Convert.ToByte(material); group.HasGroupChanged = true; + remoteClient.SendPartPhysicsProprieties(part); } } } @@ -1694,12 +1828,14 @@ namespace OpenSim.Region.Framework.Scenes return; Monitor.Enter(m_updateLock); + try { + List childGroups = new List(); // We do this in reverse to get the link order of the prims correct - for (int i = 0 ; i < children.Count ; i++) + for (int i = 0; i < children.Count; i++) { SceneObjectGroup child = children[i].ParentGroup; @@ -1710,9 +1846,13 @@ namespace OpenSim.Region.Framework.Scenes // Make sure no child prim is set for sale // So that, on delink, no prims are unwittingly // left for sale and sold off - child.RootPart.ObjectSaleType = 0; - child.RootPart.SalePrice = 10; - childGroups.Add(child); + + if (child != null) + { + child.RootPart.ObjectSaleType = 0; + child.RootPart.SalePrice = 10; + childGroups.Add(child); + } } foreach (SceneObjectGroup child in childGroups) @@ -1725,7 +1865,8 @@ namespace OpenSim.Region.Framework.Scenes // this is here so physics gets updated! // Don't remove! Bad juju! Stay away! or fix physics! - child.AbsolutePosition = child.AbsolutePosition; + // already done in LinkToGroup +// child.AbsolutePosition = child.AbsolutePosition; } } @@ -1741,6 +1882,17 @@ namespace OpenSim.Region.Framework.Scenes } finally { +/* + lock (SceneObjectGroupsByLocalPartID) + { + foreach (SceneObjectPart part in parentGroup.Parts) + SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; + } +*/ + parentGroup.AdjustChildPrimPermissions(false); + parentGroup.HasGroupChanged = true; + parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); + parentGroup.ScheduleGroupForFullUpdate(); Monitor.Exit(m_updateLock); } } @@ -1761,42 +1913,50 @@ namespace OpenSim.Region.Framework.Scenes // foreach (SceneObjectPart part in prims) { - if (part != null) + if(part == null) + continue; + SceneObjectGroup parentSOG = part.ParentGroup; + if(parentSOG == null || + parentSOG.IsDeleted || + parentSOG.inTransit || + parentSOG.PrimCount == 1) + continue; + + if (!affectedGroups.Contains(parentSOG)) { - if (part.KeyframeMotion != null) - { - part.KeyframeMotion.Stop(); - part.KeyframeMotion = null; - } - if (part.ParentGroup.PrimCount != 1) // Skip single - { - if (part.LinkNum < 2) // Root - { - rootParts.Add(part); - } - else - { - part.LastOwnerID = part.ParentGroup.RootPart.LastOwnerID; - childParts.Add(part); - } + affectedGroups.Add(parentSOG); + if(parentSOG.RootPart.PhysActor != null) + parentSOG.RootPart.PhysActor.Building = true; + } - SceneObjectGroup group = part.ParentGroup; - if (!affectedGroups.Contains(group)) - affectedGroups.Add(group); - } + if (part.KeyframeMotion != null) + { + part.KeyframeMotion.Stop(); + part.KeyframeMotion = null; + } + + if (part.LinkNum < 2) // Root + { + rootParts.Add(part); + } + else + { + part.LastOwnerID = part.ParentGroup.RootPart.LastOwnerID; + part.RezzerID = part.ParentGroup.RootPart.RezzerID; + childParts.Add(part); } } - foreach (SceneObjectPart child in childParts) + if (childParts.Count > 0) { - // Unlink all child parts from their groups - // - child.ParentGroup.DelinkFromGroup(child, true); - - // These are not in affected groups and will not be - // handled further. Do the honors here. - child.ParentGroup.HasGroupChanged = true; - child.ParentGroup.ScheduleGroupForFullUpdate(); + foreach (SceneObjectPart child in childParts) + { + // Unlink all child parts from their groups + child.ParentGroup.DelinkFromGroup(child, true); + //child.ParentGroup is now other + child.ParentGroup.HasGroupChanged = true; + child.ParentGroup.ScheduleGroupForFullUpdate(); + } } foreach (SceneObjectPart root in rootParts) @@ -1806,63 +1966,54 @@ namespace OpenSim.Region.Framework.Scenes // However, editing linked parts and unlinking may be different // SceneObjectGroup group = root.ParentGroup; - + List newSet = new List(group.Parts); + + newSet.Remove(root); int numChildren = newSet.Count; + if(numChildren == 0) + break; + + foreach (SceneObjectPart p in newSet) + group.DelinkFromGroup(p, false); + + SceneObjectPart newRoot = newSet[0]; - // If there are prims left in a link set, but the root is - // slated for unlink, we need to do this + // If there is more than one prim remaining, we + // need to re-link // - if (numChildren != 1) + if (numChildren > 1) { - // Unlink the remaining set + // Determine new root // - bool sendEventsToRemainder = true; - if (numChildren > 1) - sendEventsToRemainder = false; + newSet.RemoveAt(0); + foreach (SceneObjectPart newChild in newSet) + newChild.ClearUpdateSchedule(); - foreach (SceneObjectPart p in newSet) - { - if (p != group.RootPart) - group.DelinkFromGroup(p, sendEventsToRemainder); - } - - // If there is more than one prim remaining, we - // need to re-link - // - if (numChildren > 2) - { - // Remove old root - // - if (newSet.Contains(root)) - newSet.Remove(root); - - // Preserve link ordering - // - newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) - { - return a.LinkNum.CompareTo(b.LinkNum); - }); - - // Determine new root - // - SceneObjectPart newRoot = newSet[0]; - newSet.RemoveAt(0); - - foreach (SceneObjectPart newChild in newSet) - newChild.ClearUpdateSchedule(); - - LinkObjects(newRoot, newSet); - if (!affectedGroups.Contains(newRoot.ParentGroup)) - affectedGroups.Add(newRoot.ParentGroup); - } + LinkObjects(newRoot, newSet); + } + else + { + newRoot.TriggerScriptChangedEvent(Changed.LINK); + newRoot.ParentGroup.HasGroupChanged = true; + newRoot.ParentGroup.InvalidatePartsLinkMaps(); + newRoot.ParentGroup.ScheduleGroupForFullUpdate(); } } - // Finally, trigger events in the roots + // trigger events in the roots // foreach (SceneObjectGroup g in affectedGroups) { + if(g.RootPart.PhysActor != null) + g.RootPart.PhysActor.Building = false; + g.AdjustChildPrimPermissions(false); + // Child prims that have been unlinked and deleted will + // return unless the root is deleted. This will remove them + // from the database. They will be rewritten immediately, + // minus the rows for the unlinked child prims. + m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); + g.InvalidatePartsLinkMaps(); g.TriggerScriptChangedEvent(Changed.LINK); g.HasGroupChanged = true; // Persist g.ScheduleGroupForFullUpdate(); @@ -1876,27 +2027,9 @@ namespace OpenSim.Region.Framework.Scenes protected internal void MakeObjectSearchable(IClientAPI remoteClient, bool IncludeInSearch, uint localID) { - UUID user = remoteClient.AgentId; - UUID objid = UUID.Zero; - SceneObjectPart obj = null; - - EntityBase[] entityList = GetEntities(); - foreach (EntityBase ent in entityList) - { - if (ent is SceneObjectGroup) - { - SceneObjectGroup sog = ent as SceneObjectGroup; - - foreach (SceneObjectPart part in sog.Parts) - { - if (part.LocalId == localID) - { - objid = part.UUID; - obj = part; - } - } - } - } + SceneObjectGroup sog = GetGroupByPrim(localID); + if(sog == null) + return; //Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints //aka ObjectFlags.JointWheel = IncludeInSearch @@ -1913,15 +2046,15 @@ namespace OpenSim.Region.Framework.Scenes // libomv will complain about PrimFlags.JointWheel being // deprecated, so we #pragma warning disable 0612 - if (IncludeInSearch && m_parentScene.Permissions.CanEditObject(objid, user)) + if (IncludeInSearch && m_parentScene.Permissions.CanEditObject(sog, remoteClient)) { - obj.ParentGroup.RootPart.AddFlag(PrimFlags.JointWheel); - obj.ParentGroup.HasGroupChanged = true; + sog.RootPart.AddFlag(PrimFlags.JointWheel); + sog.HasGroupChanged = true; } - else if (!IncludeInSearch && m_parentScene.Permissions.CanMoveObject(objid,user)) + else if (!IncludeInSearch && m_parentScene.Permissions.CanMoveObject(sog, remoteClient)) { - obj.ParentGroup.RootPart.RemFlag(PrimFlags.JointWheel); - obj.ParentGroup.HasGroupChanged = true; + sog.RootPart.RemFlag(PrimFlags.JointWheel); + sog.HasGroupChanged = true; } #pragma warning restore 0612 } @@ -1936,120 +2069,86 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// null if duplication fails, otherwise the duplicated object - public SceneObjectGroup DuplicateObject( - uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) + /// + public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, UUID AgentID, UUID GroupID, Quaternion rot, bool createSelected) { - Monitor.Enter(m_updateLock); +// m_log.DebugFormat( +// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", +// originalPrimID, offset, AgentID); - try + SceneObjectGroup original = GetGroupByPrim(originalPrimID); + if (original != null) { - // m_log.DebugFormat( - // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", - // originalPrimID, offset, AgentID); - - SceneObjectGroup original = GetGroupByPrim(originalPrimID); - if (original == null) + if (m_parentScene.Permissions.CanDuplicateObject(original, AgentID)) { - m_log.WarnFormat( - "[SCENEGRAPH]: Attempt to duplicate nonexistent prim id {0} by {1}", originalPrimID, AgentID); + SceneObjectGroup copy = original.Copy(true); + copy.AbsolutePosition = copy.AbsolutePosition + offset; - return null; - } - - if (!m_parentScene.Permissions.CanDuplicateObject( - original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) - return null; - - SceneObjectGroup copy = original.Copy(true); - copy.AbsolutePosition = copy.AbsolutePosition + offset; - - if (original.OwnerID != AgentID) - { - copy.SetOwnerId(AgentID); - copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); + SceneObjectPart[] parts = copy.Parts; - SceneObjectPart[] partList = copy.Parts; + m_numTotalPrim += parts.Length; - if (m_parentScene.Permissions.PropagatePermissions()) + if (original.OwnerID != AgentID) { - foreach (SceneObjectPart child in partList) + copy.SetOwner(AgentID, GroupID); + + if (m_parentScene.Permissions.PropagatePermissions()) { - child.Inventory.ChangeInventoryOwner(AgentID); - child.TriggerScriptChangedEvent(Changed.OWNER); - child.ApplyNextOwnerPermissions(); + foreach (SceneObjectPart child in parts) + { + child.Inventory.ChangeInventoryOwner(AgentID); + child.TriggerScriptChangedEvent(Changed.OWNER); + child.ApplyNextOwnerPermissions(); + } + copy.InvalidateEffectivePerms(); } } - copy.RootPart.ObjectSaleType = 0; - copy.RootPart.SalePrice = 10; - } + // FIXME: This section needs to be refactored so that it just calls AddSceneObject() + Entities.Add(copy); - // FIXME: This section needs to be refactored so that it just calls AddSceneObject() - Entities.Add(copy); - - lock (SceneObjectGroupsByFullID) - SceneObjectGroupsByFullID[copy.UUID] = copy; - - SceneObjectPart[] children = copy.Parts; - - lock (SceneObjectGroupsByFullPartID) - { - SceneObjectGroupsByFullPartID[copy.UUID] = copy; - foreach (SceneObjectPart part in children) - SceneObjectGroupsByFullPartID[part.UUID] = copy; - } - - lock (SceneObjectGroupsByLocalPartID) - { - SceneObjectGroupsByLocalPartID[copy.LocalId] = copy; - foreach (SceneObjectPart part in children) - SceneObjectGroupsByLocalPartID[part.LocalId] = copy; - } - // PROBABLE END OF FIXME + lock (SceneObjectGroupsByFullID) + SceneObjectGroupsByFullID[copy.UUID] = copy; - // Since we copy from a source group that is in selected - // state, but the copy is shown deselected in the viewer, - // We need to clear the selection flag here, else that - // prim never gets persisted at all. The client doesn't - // think it's selected, so it will never send a deselect... - copy.IsSelected = false; + foreach (SceneObjectPart part in parts) + { + if (part.GetPrimType() == PrimType.SCULPT) + m_numMesh++; + else + m_numPrim++; - m_numTotalPrim += copy.Parts.Length; + lock (SceneObjectGroupsByFullPartID) + SceneObjectGroupsByFullPartID[part.UUID] = copy; + lock (SceneObjectGroupsByLocalPartID) + SceneObjectGroupsByLocalPartID[part.LocalId] = copy; + } - // Go through all parts (primitives and meshes) of this Scene Object - foreach (SceneObjectPart part in copy.Parts) - { - // Keep track of the total number of meshes or geometric primitives now in the scene; - // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to - // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives - if (part.GetPrimType() == PrimType.SCULPT) - m_numMesh++; - else - m_numPrim++; - } + // PROBABLE END OF FIXME - if (rot != Quaternion.Identity) - { - copy.UpdateGroupRotationR(rot); - } + copy.IsSelected = createSelected; + + if (rot != Quaternion.Identity) + copy.UpdateGroupRotationR(rot); - copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); - copy.HasGroupChanged = true; - copy.ScheduleGroupForFullUpdate(); - copy.ResumeScripts(); + // required for physics to update it's position + copy.ResetChildPrimPhysicsPositions(); - // required for physics to update it's position - copy.AbsolutePosition = copy.AbsolutePosition; + copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); + copy.ResumeScripts(); - return copy; + copy.HasGroupChanged = true; + copy.ScheduleGroupForFullUpdate(); + return copy; + } } - finally + else { - Monitor.Exit(m_updateLock); + m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID); } + + return null; } - - /// + /// Calculates the distance between two Vector3s /// /// @@ -2067,6 +2166,6 @@ namespace OpenSim.Region.Framework.Scenes #endregion - + } } -- cgit v1.1