public static void SOPToXml2(XmlTextWriter writer, SceneObjectPart sop, Dictionary<string, object> options) { writer.WriteStartElement("SceneObjectPart"); writer.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); writer.WriteAttributeString("xmlns:xsd", "http://www.w3.org/2001/XMLSchema"); writer.WriteElementString("AllowedDrop", sop.AllowedDrop.ToString().ToLower()); WriteUUID(writer, "CreatorID", sop.CreatorID, options); if (!string.IsNullOrEmpty(sop.CreatorData)) writer.WriteElementString("CreatorData", sop.CreatorData); else if (options.ContainsKey("home")) { if (m_UserManagement == null) m_UserManagement = sop.ParentGroup.Scene.RequestModuleInterface<IUserManagement>(); string name = m_UserManagement.GetUserName(sop.CreatorID); writer.WriteElementString("CreatorData", (string)options["home"] + ";" + name); } WriteUUID(writer, "FolderID", sop.FolderID, options); writer.WriteElementString("InventorySerial", sop.InventorySerial.ToString()); WriteTaskInventory(writer, sop.TaskInventory, options, sop.ParentGroup.Scene); WriteUUID(writer, "UUID", sop.UUID, options); writer.WriteElementString("LocalId", sop.LocalId.ToString()); writer.WriteElementString("Name", sop.Name); writer.WriteElementString("Material", sop.Material.ToString()); writer.WriteElementString("PassTouches", sop.PassTouches.ToString().ToLower()); writer.WriteElementString("PassCollisions", sop.PassCollisions.ToString().ToLower()); writer.WriteElementString("RegionHandle", sop.RegionHandle.ToString()); writer.WriteElementString("ScriptAccessPin", sop.ScriptAccessPin.ToString()); WriteVector(writer, "GroupPosition", sop.GroupPosition); WriteVector(writer, "OffsetPosition", sop.OffsetPosition); WriteQuaternion(writer, "RotationOffset", sop.RotationOffset); WriteVector(writer, "Velocity", sop.Velocity); WriteVector(writer, "AngularVelocity", sop.AngularVelocity); WriteVector(writer, "Acceleration", sop.Acceleration); writer.WriteElementString("Description", sop.Description); writer.WriteStartElement("Color"); writer.WriteElementString("R", sop.Color.R.ToString(Utils.EnUsCulture)); writer.WriteElementString("G", sop.Color.G.ToString(Utils.EnUsCulture)); writer.WriteElementString("B", sop.Color.B.ToString(Utils.EnUsCulture)); writer.WriteElementString("A", sop.Color.A.ToString(Utils.EnUsCulture)); writer.WriteEndElement(); writer.WriteElementString("Text", sop.Text); writer.WriteElementString("SitName", sop.SitName); writer.WriteElementString("TouchName", sop.TouchName); writer.WriteElementString("LinkNum", sop.LinkNum.ToString()); writer.WriteElementString("ClickAction", sop.ClickAction.ToString()); WriteShape(writer, sop.Shape, options); WriteVector(writer, "Scale", sop.Scale); WriteQuaternion(writer, "SitTargetOrientation", sop.SitTargetOrientation); WriteVector(writer, "SitTargetPosition", sop.SitTargetPosition); WriteVector(writer, "SitTargetPositionLL", sop.SitTargetPositionLL); WriteQuaternion(writer, "SitTargetOrientationLL", sop.SitTargetOrientationLL); writer.WriteElementString("ParentID", sop.ParentID.ToString()); writer.WriteElementString("CreationDate", sop.CreationDate.ToString()); writer.WriteElementString("Category", sop.Category.ToString()); writer.WriteElementString("SalePrice", sop.SalePrice.ToString()); writer.WriteElementString("ObjectSaleType", sop.ObjectSaleType.ToString()); writer.WriteElementString("OwnershipCost", sop.OwnershipCost.ToString()); WriteUUID(writer, "GroupID", sop.GroupID, options); UUID ownerID = options.ContainsKey("wipe-owners") ? UUID.Zero : sop.OwnerID; WriteUUID(writer, "OwnerID", ownerID, options); UUID lastOwnerID = options.ContainsKey("wipe-owners") ? UUID.Zero : sop.LastOwnerID; WriteUUID(writer, "LastOwnerID", lastOwnerID, options); writer.WriteElementString("BaseMask", sop.BaseMask.ToString()); writer.WriteElementString("OwnerMask", sop.OwnerMask.ToString()); writer.WriteElementString("GroupMask", sop.GroupMask.ToString()); writer.WriteElementString("EveryoneMask", sop.EveryoneMask.ToString()); writer.WriteElementString("NextOwnerMask", sop.NextOwnerMask.ToString()); WriteFlags(writer, "Flags", sop.Flags.ToString(), options); WriteUUID(writer, "CollisionSound", sop.CollisionSound, options); writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); if (sop.MediaUrl != null) writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); WriteVector(writer, "AttachedPos", sop.AttachedPos); if (sop.DynAttrs.CountNamespaces > 0) { writer.WriteStartElement("DynAttrs"); sop.DynAttrs.WriteXml(writer); writer.WriteEndElement(); } WriteBytes(writer, "TextureAnimation", sop.TextureAnimation); WriteBytes(writer, "ParticleSystem", sop.ParticleSystem); writer.WriteElementString("PayPrice0", sop.PayPrice[0].ToString()); writer.WriteElementString("PayPrice1", sop.PayPrice[1].ToString()); writer.WriteElementString("PayPrice2", sop.PayPrice[2].ToString()); writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType()) writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower()); if (sop.Density != 1000.0f) writer.WriteElementString("Density", sop.Density.ToString().ToLower()); if (sop.Friction != 0.6f) writer.WriteElementString("Friction", sop.Friction.ToString().ToLower()); if (sop.Restitution != 0.5f) writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower()); if (sop.GravityModifier != 1.0f) writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower()); writer.WriteEndElement(); }
/// <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); if (m_rootPart.PhysActor != null) m_rootPart.PhysActor.Building = true; 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.setGroupPosition(worldPos); linkPart.setOffsetPosition(Vector3.Zero); linkPart.setRotationOffset(worldRot); // Create a new SOG to go around this unlinked and unattached SOP SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); m_scene.AddNewSceneObject(objectGroup, true); 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) // this is as it seems to be in sl now if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none) linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now if (m_rootPart.PhysActor != null) m_rootPart.PhysActor.Building = false; objectGroup.HasGroupChangedDueToDelink = true; InvalidBoundsRadius(); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); return objectGroup; }