/// <summary> /// Link the prims in a given group to this group /// </summary> /// <param name = "grp">The group of prims which should be linked to this group</param> public void LinkToGroup(ISceneEntity grp) { //MainConsole.Instance.DebugFormat( // "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", // objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); if (!(grp is SceneObjectGroup)) return; SceneObjectGroup objectGroup = (SceneObjectGroup) grp; if (m_rootPart.PhysActor != null) m_rootPart.PhysActor.BlockPhysicalReconstruction = true; SceneObjectPart linkPart = objectGroup.m_rootPart; Vector3 oldGroupPosition = linkPart.GroupPosition; Quaternion oldRootRotation = linkPart.RotationOffset; Quaternion parentRot = m_rootPart.RotationOffset; linkPart.SetGroupPosition(AbsolutePosition); // just change it without doing anything else Vector3 axPos = oldGroupPosition - AbsolutePosition; axPos *= Quaternion.Inverse(parentRot); linkPart.SetOffsetPosition(axPos); Quaternion newRot = Quaternion.Inverse(parentRot)*oldRootRotation; linkPart.SetRotationOffset(false, newRot, false); //Fix the link number for the root if (m_rootPart.LinkNum == 0) m_rootPart.LinkNum = 1; SceneObjectPart[] objectGroupChildren = new SceneObjectPart[objectGroup.ChildrenList.Count]; objectGroup.ChildrenList.CopyTo(objectGroupChildren, 0); //Destroy the old group m_scene.SceneGraph.DeleteEntity(objectGroup); objectGroup.IsDeleted = true; objectGroup.ClearChildren(); lock (m_partsLock) { int linkNum = 2; //Add the root part to our group! m_scene.SceneGraph.LinkPartToSOG(this, linkPart, linkNum++); linkPart.CreateSelected = true; linkPart.FixOffsetPosition(linkPart.OffsetPosition, true); // nasty let all know about where this is // let physics link it if (linkPart.PhysActor != null && m_rootPart.PhysActor != null) { if (linkPart.PhysicsType != (byte) PhysicsShapeType.None) { linkPart.PhysActor.link(m_rootPart.PhysActor); Scene.PhysicsScene.AddPhysicsActorTaint(linkPart.PhysActor); } } //rest of parts #if (!ISWIN) foreach (SceneObjectPart part in objectGroupChildren) { if (part.UUID != objectGroup.m_rootPart.UUID) { LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); part.FixOffsetPosition(part.OffsetPosition, true); if (part.PhysActor != null && m_rootPart.PhysActor != null) { part.PhysActor.link(m_rootPart.PhysActor); Scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); } } } #else foreach (SceneObjectPart part in objectGroupChildren.Where(part => part.UUID != objectGroup.m_rootPart.UUID)) { LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); part.FixOffsetPosition(part.OffsetPosition, true); if (part.PhysActor != null && m_rootPart.PhysActor != null) { part.PhysActor.link(m_rootPart.PhysActor); Scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); } } #endif } // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the // position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and // unmoved prims! m_ValidgrpOOB = false; ResetChildPrimPhysicsPositions(); if (m_rootPart.PhysActor != null) m_rootPart.PhysActor.BlockPhysicalReconstruction = false; }