private void LinkNonRootPart(SceneObjectPart part, Vector3 oldGroupPosition, Quaternion oldGroupRotation, int linkNum) { Quaternion oldRot = part.RotationOffset; // first fix from old local to world // position Vector3 axPos = part.OffsetPosition; axPos *= oldGroupRotation; part.SetGroupPosition(oldGroupPosition + axPos); //offset part.SetRotationOffset(false, oldGroupRotation * oldRot ,false); // have it in world coords lets fix other things m_scene.SceneGraph.LinkPartToSOG(this, part, linkNum); part.CreateSelected = true; // now lets move to the new parent frame Quaternion rootRotation = m_rootPart.RotationOffset; Vector3 pos = part.GroupPosition - AbsolutePosition; pos *= Quaternion.Inverse(rootRotation); part.SetOffsetPosition(pos); Quaternion newRot = Quaternion.Inverse(rootRotation) * oldRot; part.SetRotationOffset(false,newRot,false); // caller will tell the rest about this position changes.. }
/// <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; }