public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me) { CheckFaceParam(part, face); if (null == part.Shape.Media) part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]); lock (part.Shape.Media) part.Shape.Media[face] = me; UpdateMediaUrl(part, UUID.Zero); part.ScheduleFullUpdate(PrimUpdateFlags.FullUpdate); part.TriggerScriptChangedEvent(Changed.MEDIA); }
/// <summary> /// Delink the given prim from this group. The delinked prim is established as /// an independent SceneObjectGroup. /// </summary> /// <param name="partID"></param> /// <param name="sendEvents"></param> /// <returns>The object group of the newly delinked prim.</returns> public SceneObjectGroup DelinkFromGroup(SceneObjectPart linkPart, bool sendEvents) { // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object m_scene.SceneGraph.DeLinkPartFromEntity(this, linkPart); /* this is already done in DeLinkPartFromEntity if (m_partsList.Count == 1 && RootPart != null) //Single prim is left RootPart.LinkNum = 0; else { lock (m_partsLock) { foreach (SceneObjectPart p in m_partsList) { if (p.LinkNum > linkPart.LinkNum) p.LinkNum--; } } } */ linkPart.SetParentLocalId(0); linkPart.LinkNum = 0; if (linkPart.PhysActor != null) { m_scene.SceneGraph.PhysicsScene.RemovePrim(linkPart.PhysActor); // linkPart.PhysActor.delink(); } // We need to reset the child part's position // ready for life as a separate object after being a part of another object Quaternion parentRot = m_rootPart.RotationOffset; Vector3 axPos = linkPart.OffsetPosition; axPos *= parentRot; linkPart.SetOffsetPosition(axPos); linkPart.FixGroupPosition(AbsolutePosition + linkPart.OffsetPosition,false); linkPart.FixOffsetPosition(Vector3.Zero, false); linkPart.RotationOffset = worldRot; SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart, Scene); m_scene.SceneGraph.DelinkPartToScene(objectGroup); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); linkPart.Rezzed = RootPart.Rezzed; //This is already set multiple places, no need to do it again //HasGroupChanged = true; //We need to send this so that we don't have issues with the client not realizing that the prims were unlinked ScheduleGroupUpdate(PrimUpdateFlags.FullUpdate); return objectGroup; }
/// <summary> /// Set the media entry on the face of the given part. /// </summary> /// <param name="part">/param> /// <param name="face"></param> /// <param name="me">If null, then the media entry is cleared.</param> public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me) { // m_log.DebugFormat("[MOAP]: SetMediaEntry for {0}, face {1}", part.Name, face); int numFaces = part.GetNumberOfSides(); if (part.Shape.Media == null) part.Shape.Media = new PrimitiveBaseShape.PrimMedia(numFaces); else part.Shape.Media.Resize(numFaces); if (!CheckFaceParam(part, face)) return; // ClearMediaEntry passes null for me so it must not be ignored! lock (part.Shape.Media) part.Shape.Media[face] = me; UpdateMediaUrl(part, UUID.Zero); SetPartMediaFlags(part, face, me != null); part.ScheduleFullUpdate(PrimUpdateFlags.FindBest); part.TriggerScriptChangedEvent(Changed.MEDIA); }
/// <summary> /// Delink the given prim from this group. The delinked prim is established as /// an independent SceneObjectGroup. /// </summary> /// <remarks> /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race /// condition. But currently there is no /// alternative method that does take a lock to delink a single prim. /// </remarks> /// <param name="partID"></param> /// <param name="sendEvents"></param> /// <returns>The object group of the newly delinked prim.</returns> public SceneObjectGroup DelinkFromGroup(SceneObjectPart linkPart, bool sendEvents) { // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); linkPart.ClearUndoState(); Vector3 worldPos = linkPart.GetWorldPosition(); Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object lock (m_parts.SyncRoot) { m_parts.Remove(linkPart.UUID); SceneObjectPart[] parts = m_parts.GetArray(); // Rejigger the linknum's of the remaining SOP's to fill any gap if (parts.Length == 1 && RootPart != null) { // Single prim left RootPart.LinkNum = 0; } else { for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part.LinkNum > linkPart.LinkNum) part.LinkNum--; } } } linkPart.ParentID = 0; linkPart.LinkNum = 0; PhysicsActor linkPartPa = linkPart.PhysActor; // Remove the SOP from the physical scene. // If the new SOG is physical, it is re-created later. // (There is a problem here in that we have not yet told the physics // engine about the delink. Someday, linksets should be made first // class objects in the physics engine interface). if (linkPartPa != null) m_scene.PhysicsScene.RemovePrim(linkPartPa); // We need to reset the child part's position // ready for life as a separate object after being a part of another object /* This commented out code seems to recompute what GetWorldPosition already does. * Replace with a call to GetWorldPosition (before unlinking) Quaternion parentRot = m_rootPart.RotationOffset; Vector3 axPos = linkPart.OffsetPosition; axPos *= parentRot; linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z); linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; linkPart.OffsetPosition = new Vector3(0, 0, 0); */ linkPart.GroupPosition = worldPos; linkPart.OffsetPosition = Vector3.Zero; linkPart.RotationOffset = worldRot; // Create a new SOG to go around this unlinked and unattached SOP SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); m_scene.AddNewSceneObject(objectGroup, true); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); linkPart.Rezzed = RootPart.Rezzed; // When we delete a group, we currently have to force persist to the database if the object id has changed // (since delete works by deleting all rows which have a given object id) objectGroup.HasGroupChangedDueToDelink = true; return objectGroup; }
/// <summary> /// Delink the given prim from this group. The delinked prim is established as /// an independent SceneObjectGroup. /// </summary> /// <param name="partID"></param> /// <param name="sendEvents"></param> /// <returns>The object group of the newly delinked prim.</returns> public SceneObjectGroup DelinkFromGroup(SceneObjectPart linkPart, bool sendEvents) { // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); linkPart.ClearUndoState(); Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object lock (m_parts.SyncRoot) { m_parts.Remove(linkPart.UUID); SceneObjectPart[] parts = m_parts.GetArray(); if (parts.Length == 1 && RootPart != null) { // Single prim left RootPart.LinkNum = 0; } else { for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part.LinkNum > linkPart.LinkNum) part.LinkNum--; } } } linkPart.ParentID = 0; linkPart.LinkNum = 0; if (linkPart.PhysActor != null) { m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); } // We need to reset the child part's position // ready for life as a separate object after being a part of another object Quaternion parentRot = m_rootPart.RotationOffset; Vector3 axPos = linkPart.OffsetPosition; axPos *= parentRot; linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z); linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; linkPart.OffsetPosition = new Vector3(0, 0, 0); linkPart.RotationOffset = worldRot; SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); m_scene.AddNewSceneObject(objectGroup, true); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); linkPart.Rezzed = RootPart.Rezzed; // When we delete a group, we currently have to force persist to the database if the object id has changed // (since delete works by deleting all rows which have a given object id) objectGroup.HasGroupChangedDueToDelink = true; return objectGroup; }
/// <summary> /// Delink the given prim from this group. The delinked prim is established as /// an independent SceneObjectGroup. /// </summary> /// <param name="partID"></param> /// <param name="sendEvents"></param> /// <returns>The object group of the newly delinked prim.</returns> public SceneObjectGroup DelinkFromGroup(SceneObjectPart linkPart, bool sendEvents) { // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); linkPart.ClearUndoState(); Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object lock (m_parts) { m_parts.Remove(linkPart.UUID); } if (m_parts.Count == 1 && RootPart != null) //Single prim is left RootPart.LinkNum = 0; else { foreach (SceneObjectPart p in m_parts.Values) { if (p.LinkNum > linkPart.LinkNum) p.LinkNum--; } } linkPart.ParentID = 0; linkPart.LinkNum = 0; if (linkPart.PhysActor != null) { m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); } // We need to reset the child part's position // ready for life as a separate object after being a part of another object Quaternion parentRot = m_rootPart.RotationOffset; Vector3 axPos = linkPart.OffsetPosition; axPos *= parentRot; linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z); linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; linkPart.OffsetPosition = new Vector3(0, 0, 0); linkPart.RotationOffset = worldRot; SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); m_scene.AddNewSceneObject(objectGroup, true); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); linkPart.Rezzed = RootPart.Rezzed; //HasGroupChanged = true; //ScheduleGroupForFullUpdate(); return objectGroup; }
/// <summary> /// Delink the given prim from this group. The delinked prim is established as /// an independent SceneObjectGroup. /// </summary> /// <remarks> /// FIXME: This method should not be called directly since it bypasses update locking, allowing a potential race /// condition. But currently there is no /// alternative method that does take a lock to delink a single prim. /// </remarks> /// <param name="partID"></param> /// <param name="sendEvents"></param> /// <returns>The object group of the newly delinked prim.</returns> public SceneObjectGroup DelinkFromGroup(SceneObjectPart linkPart, bool sendEvents) { // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); linkPart.ClearUndoState(); Vector3 worldPos = linkPart.GetWorldPosition(); Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object lock (m_parts.SyncRoot) { m_parts.Remove(linkPart.UUID); SceneObjectPart[] parts = m_parts.GetArray(); // Rejigger the linknum's of the remaining SOP's to fill any gap if (parts.Length == 1 && RootPart != null) { // Single prim left RootPart.LinkNum = 0; } else { for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; if (part.LinkNum > linkPart.LinkNum) part.LinkNum--; } } } linkPart.ParentID = 0; linkPart.LinkNum = 0; PhysicsActor linkPartPa = linkPart.PhysActor; // Remove the SOP from the physical scene. // If the new SOG is physical, it is re-created later. // (There is a problem here in that we have not yet told the physics // engine about the delink. Someday, linksets should be made first // class objects in the physics engine interface). if (linkPartPa != null) m_scene.PhysicsScene.RemovePrim(linkPartPa); // We need to reset the child part's position // ready for life as a separate object after being a part of another object /* This commented out code seems to recompute what GetWorldPosition already does. * Replace with a call to GetWorldPosition (before unlinking) Quaternion parentRot = m_rootPart.RotationOffset; Vector3 axPos = linkPart.OffsetPosition; axPos *= parentRot; linkPart.OffsetPosition = new Vector3(axPos.X, axPos.Y, axPos.Z); linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; linkPart.OffsetPosition = new Vector3(0, 0, 0); */ linkPart.GroupPosition = worldPos; linkPart.OffsetPosition = Vector3.Zero; linkPart.RotationOffset = worldRot; // Create a new SOG to go around this unlinked and unattached SOP SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); m_scene.AddNewSceneObject(objectGroup, true); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); linkPart.Rezzed = RootPart.Rezzed; // We must persist the delinked group to the database immediately, for safety. The problem // is that although in memory the new group has a new SceneGroupID, in the database it // still has the parent group's SceneGroupID (until the next backup). This means that if the // parent group is deleted then the delinked group will also be deleted from the database. // This problem will disappear if the region remains alive long enough for another backup, // since at that time the delinked group's new SceneGroupID will be written to the database. // But if the region crashes before that then the prims will be permanently gone, and this must // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case // because the delinked group doesn't know when the source group is deleted.) m_scene.ForceSceneObjectBackup(objectGroup); return objectGroup; }
public void DelinkFromGroup(SceneObjectPart linkPart, bool sendEvents, bool sendGroupUpdate) { linkPart.ClearUndoState(); // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object lock (m_parts) { m_parts.Remove(linkPart.UUID); _partsByLocalId.Remove(linkPart.LocalId); if (m_parts.Count == 1 && RootPart != null) //Single prim is left { RootPart.LinkNum = 0; } else { foreach (SceneObjectPart p in m_parts.Values) { if (p.LinkNum > linkPart.LinkNum) p.LinkNum--; } } } linkPart.ParentID = 0; linkPart.LinkNum = 0; // We need to reset the child part's position // ready for life as a separate object after being a part of another object Quaternion parentRot = m_rootPart.RotationOffset; Vector3 axPos = linkPart.OffsetPosition; axPos *= parentRot; Vector3 groupPosition = AbsolutePosition + axPos; linkPart.SetGroupPositionDirect(groupPosition); linkPart.SetOffsetPositionDirect(Vector3.Zero); linkPart.SetRotationOffsetDirect(worldRot); SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); PhysicsActor partActor = linkPart.PhysActor; if (partActor != null) { partActor.DelinkFromParent(groupPosition, worldRot); } m_scene.AddNewSceneObject(objectGroup, true); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); linkPart.Rezzed = RootPart.Rezzed; //Rebuild the bounding box ClearBoundingBoxCache(); // Update the ServerWeight/LandImpact and StreamingCost RecalcPrimWeights(); if (sendGroupUpdate) { HasGroupChanged = true; ScheduleGroupForFullUpdate(); objectGroup.ScheduleGroupForFullUpdate(); } }
/// <summary> /// Set the media entry on the face of the given part. /// </summary> /// <param name="part">/param> /// <param name="face"></param> /// <param name="me">If null, then the media entry is cleared.</param> public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me) { // m_log.DebugFormat("[MOAP]: SetMediaEntry for {0}, face {1}", part.Name, face); CheckFaceParam(part, face); if (null == part.Shape.Media) { if (me == null) return; else part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]); } lock (part.Shape.Media) part.Shape.Media[face] = me; UpdateMediaUrl(part, UUID.Zero); SetPartMediaFlags(part, face, me != null); part.ScheduleFullUpdate(); part.TriggerScriptChangedEvent(Changed.MEDIA); }