private bool TryUnlinkRoot(out ObjectPart part, bool sendEvent = true) { part = null; int primCount = Count; part = this[LINK_ROOT]; var rootPos = part.GlobalPosition; var rootRot = part.GlobalRotation; ObjectPart newRoot; if (!TryGetValue(2, out newRoot)) { part = null; return(false); } var offsetPos = newRoot.Position; var offsetRot = newRoot.Rotation; foreach (var linkpart in ValuesByKey1) { linkpart.Inventory.SuspendScripts(); } part.Inventory.SuspendScripts(); part.ObjectGroup.StopKeyframedMotion(); if (!Remove(part.ID)) { foreach (var linkpart in ValuesByKey1) { linkpart.Inventory.ResumeScripts(); } part = null; return(false); } newRoot.LocalPosition += rootPos; newRoot.LocalRotation *= rootRot; ChangeKey(LINK_ROOT, 2); int i; for (i = 3; i < primCount; ++i) { ChangeKey(i - 1, i); var linkPart = this[i - 1]; linkPart.Position -= offsetPos; linkPart.Rotation /= offsetRot; } foreach (var linkpart in ValuesByKey1) { linkpart.Inventory.ResumeScripts(); linkpart.TriggerOnUpdate(UpdateChangedFlags.Link); } if (sendEvent) { PostEvent(new ChangedEvent(ChangedEvent.ChangedFlags.Link)); } return(true); }
private static ObjectPart ParseRootPart(XmlTextReader reader, ObjectGroup group, UGUI currentOwner, XmlDeserializationOptions options) { ObjectPart rootPart = null; if (reader.IsEmptyElement) { throw new InvalidObjectXmlException(); } for (; ;) { if (!reader.Read()) { throw new InvalidObjectXmlException(); } string nodeName = reader.Name; bool isEmptyElement = reader.IsEmptyElement; switch (reader.NodeType) { case XmlNodeType.Element: switch (nodeName) { case "SceneObjectPart": if (rootPart != null) { throw new InvalidObjectXmlException(); } if (isEmptyElement) { throw new InvalidObjectXmlException(); } if (rootPart != null) { throw new InvalidObjectXmlException(); } rootPart = ObjectPart.FromXml(reader, group, currentOwner, options); group.Add(LINK_ROOT, rootPart.ID, rootPart); break; default: reader.ReadToEndElement(); break; } break; case XmlNodeType.EndElement: if (nodeName != "RootPart") { throw new InvalidObjectXmlException(); } return(rootPart); default: break; } } }
public void AddLink(ObjectPart part) { lock (m_LinkUnlinkLock) { part.ObjectGroup = this; Add(Count + 1, part.ID, part); } part.IncSerialNumber(); Scene?.ScheduleUpdate(part.UpdateInfo); }
private bool TryUnlink(UUID primID, out ObjectPart part) { part = null; lock (m_LinkUnlinkLock) { if (TryGetValue(primID, out part)) { if (Count == 1) { return(false); } if (part.LinkNumber == LINK_ROOT) { #if DEBUG m_Log.DebugFormat("Unlinking root prim {0} from object", primID); #endif return(TryUnlinkRoot(out part)); } else { /* separate single prim */ int linkno = part.LinkNumber; Vector3 rootPos = part.GlobalPosition; Quaternion rootRot = part.GlobalRotation; #if DEBUG m_Log.DebugFormat("Unlinking child prim {0} (link {3}) from object (New location {1} / {2})", primID, rootPos, rootRot, linkno); #endif part.Inventory.SuspendScripts(); if (!Remove(primID)) { part.Inventory.ResumeScripts(); return(false); } part.LocalPosition = rootPos; part.LocalRotation = rootRot; for (++linkno; linkno <= Count; ++linkno) { ChangeKey(linkno - 1, linkno); } PostEvent(new ChangedEvent(ChangedEvent.ChangedFlags.Link)); return(true); } } } return(false); }
public void FinalizeObject() { ObjectPart rootPart = RootPart; foreach (ObjectPart part in Values) { /* make those parameters align well */ part.IsPhantom = rootPart.IsPhantom; part.IsPhysics = rootPart.IsPhysics; part.IsVolumeDetect = rootPart.IsVolumeDetect; part.ObjectGroup = this; part.UpdateData(ObjectPartLocalizedInfo.UpdateDataFlags.All); } }
public void InsertLinks(int linkno, ObjectPart[] parts) { if (linkno < 2) { throw new ArgumentOutOfRangeException(nameof(linkno)); } if (parts == null) { throw new ArgumentNullException(nameof(parts)); } if (parts.Length == 0) { throw new ArgumentOutOfRangeException(nameof(parts)); } foreach (ObjectPart part in parts) { if (part == null) { throw new ArgumentOutOfRangeException(nameof(parts)); } } lock (m_LinkUnlinkLock) { for (int startlink = Count + 1; startlink-- > linkno;) { ChangeKey(startlink + parts.Length, startlink); } for (int link = 0; link < parts.Length; ++link) { ObjectPart part = parts[link]; Add(link + 2, part.ID, part); part.ObjectGroup = this; } } /* we have to update all */ foreach (ObjectPart part in ValuesByKey1) { if (part != RootPart) { part.IncSerialNumber(); Scene?.ScheduleUpdate(part.UpdateInfo); } } }
public void FillFromXml(XmlTextReader reader, UGUI currentOwner, XmlDeserializationOptions options) { var part = new ObjectPart { Owner = currentOwner }; if (reader.IsEmptyElement) { throw new InvalidObjectXmlException(); } for (; ;) { if (!reader.Read()) { throw new InvalidObjectXmlException(); } switch (reader.NodeType) { case XmlNodeType.Element: if (reader.IsEmptyElement) { break; } switch (reader.Name) { case "TaskInventoryItem": UUID origid; ObjectPartInventoryItem item = FromXML(reader, currentOwner, options, out origid); if (ContainsKey(item.ID)) { /* skip duplicate ids. There seems to be at least one OpenSim version generating bogus task inventory */ break; } try { Add(item, true); } catch { throw new InvalidObjectXmlException(string.Format("Duplicate task inventory name {0} ({1})", item.Name, origid)); } break; default: reader.ReadToEndElement(); break; } break; case XmlNodeType.EndElement: if (reader.Name != "TaskInventory") { throw new InvalidObjectXmlException(); } return; default: break; } } }
public static ObjectGroup FromXml(XmlTextReader reader, UGUI currentOwner, bool inRootPart = false, XmlDeserializationOptions options = XmlDeserializationOptions.None) { var group = new ObjectGroup(); ObjectPart rootPart = null; if (reader.IsEmptyElement) { throw new InvalidObjectXmlException(); } for (; ;) { if (inRootPart) { inRootPart = false; } else if (!reader.Read()) { throw new InvalidObjectXmlException(); } bool isEmptyElement = reader.IsEmptyElement; string nodeName = reader.Name; switch (reader.NodeType) { case XmlNodeType.Element: switch (nodeName) { case "RootPart": if (isEmptyElement) { throw new InvalidObjectXmlException(); } if (rootPart != null) { throw new InvalidObjectXmlException(); } rootPart = ParseRootPart(reader, group, currentOwner, options); break; case "SceneObjectPart": if (rootPart != null) { throw new InvalidObjectXmlException(); } if (isEmptyElement) { throw new InvalidObjectXmlException(); } if (rootPart != null) { throw new InvalidObjectXmlException(); } rootPart = ObjectPart.FromXml(reader, group, currentOwner, options); group.Add(LINK_ROOT, rootPart.ID, rootPart); break; case "OtherParts": if (isEmptyElement) { break; } FromXmlOtherParts(reader, group, currentOwner, options); break; case "GroupScriptStates": if (isEmptyElement) { break; } FromXmlGroupScriptStates(reader, group); break; case "KeyframeMotion": if (isEmptyElement) { break; } reader.ReadToEndElement(); break; default: reader.ReadToEndElement(); break; } break; case XmlNodeType.EndElement: if (nodeName != "SceneObjectGroup") { throw new InvalidObjectXmlException(); } foreach (ObjectPart part in group.Values) { part.Owner = currentOwner; if ((options & XmlDeserializationOptions.RestoreIDs) == 0) { foreach (UUID key in part.Inventory.Keys1) { UUID newid = UUID.Random; part.Inventory[key].SetNewID(newid); part.Inventory.ChangeKey(newid, key); } } } group.FinalizeObject(); return(group); default: break; } } }
private static void FromXmlOtherParts(XmlTextReader reader, ObjectGroup group, UGUI currentOwner, XmlDeserializationOptions options) { ObjectPart part; var links = new SortedDictionary <int, ObjectPart>(); if (reader.IsEmptyElement) { throw new InvalidObjectXmlException(); } for (; ;) { if (!reader.Read()) { throw new InvalidObjectXmlException(); } bool isEmptyElement = reader.IsEmptyElement; string nodeName = reader.Name; switch (reader.NodeType) { case XmlNodeType.Element: switch (nodeName) { case "Part": if (isEmptyElement) { throw new InvalidObjectXmlException(); } part = ParseOtherPart(reader, group, currentOwner, options); links.Add(part.LoadedLinkNumber, part); break; case "SceneObjectPart": if (isEmptyElement) { throw new InvalidObjectXmlException(); } part = ObjectPart.FromXml(reader, null, currentOwner, options); try { part.LoadedLinkNumber = links.Count + 2; links.Add(part.LoadedLinkNumber, part); } catch { throw new ObjectDeserializationFailedDueKeyException(); } break; default: reader.ReadToEndElement(); break; } break; case XmlNodeType.EndElement: if (nodeName != "OtherParts") { throw new InvalidObjectXmlException(); } foreach (KeyValuePair <int, ObjectPart> kvp in links) { group.Add(kvp.Key, kvp.Value.ID, kvp.Value); } return; default: break; } } }
public ObjectAnimationController(ObjectPart part) { m_Part = part; m_NextAnimSeqNumber = 1; }
public bool TryUnlink(List <UUID> uuids, List <ObjectGroup> unlinkedPrims) { lock (m_LinkUnlinkLock) { if (Count == 1) { return(false); } bool rootPrimRemoved = false; Dictionary <UUID, Vector3> newChildPos = new Dictionary <UUID, Vector3>(); Dictionary <UUID, Quaternion> newChildRot = new Dictionary <UUID, Quaternion>(); foreach (UUID id in uuids) { ObjectPart part; if (TryGetValue(id, out part)) { /* is any of those our root prim? */ if (part == RootPart) { rootPrimRemoved = true; } newChildPos[part.ID] = part.GlobalPosition; newChildRot[part.ID] = part.GlobalRotation; } else { return(false); } } SortedDictionary <int, int> reorderLinkSet = new SortedDictionary <int, int>(); int newlink = LINK_ROOT; if (rootPrimRemoved) { Vector3 rootPos = RootPart.GlobalPosition; Quaternion rootRot = RootPart.GlobalRotation; Vector3 offsetPos = Vector3.Zero; Quaternion offsetRot = Quaternion.Identity; ObjectGroup newLinkSet = new ObjectGroup(this); /* we are extracting the remaining linkset into new ObjectGroup */ for (int i = LINK_ROOT; i <= Count; ++i) { ObjectPart linkpart = this[i]; linkpart.Inventory.SuspendScripts(); if (!uuids.Contains(linkpart.ID)) { if (newlink == 1) { Vector3 newRootPos = linkpart.GlobalPosition; Quaternion newRootRot = linkpart.GlobalRotation; offsetRot = linkpart.LocalRotation; offsetPos = linkpart.LocalPosition / offsetRot; linkpart.LocalPosition = newRootPos; linkpart.LocalRotation = newRootRot; linkpart.IsSandbox = false; newLinkSet.Add(LINK_ROOT, linkpart.ID, linkpart); linkpart.ObjectGroup = newLinkSet; } else { linkpart.LocalPosition += offsetPos; linkpart.LocalRotation /= offsetRot; newLinkSet.AddLink(linkpart); linkpart.ObjectGroup = newLinkSet; } Remove(linkpart.ID); } } /* root prim always remains in original group */ uuids.Remove(RootPart.ID); if (newLinkSet.Count != 0) { newLinkSet.PostEvent(new ChangedEvent(ChangedEvent.ChangedFlags.Link)); unlinkedPrims.Add(newLinkSet); } } newlink = LINK_ROOT + 1; for (int i = LINK_ROOT + 1; i <= Count; ++i) { ObjectPart linkpart = this[i]; if (!uuids.Contains(linkpart.ID)) { if (i != newlink) { reorderLinkSet.Add(i, newlink); } ++newlink; } } /* remove child prims */ foreach (UUID id in uuids) { ObjectPart part; if (Remove(id, out part)) { var newGrp = new ObjectGroup(this); newGrp.Add(LINK_ROOT, part.ID, part); part.ObjectGroup = newGrp; part.LocalPosition = newChildPos[id]; part.LocalRotation = newChildRot[id]; part.IsSandbox = false; /* re-trigger update */ part.IncSerialNumber(); newGrp.PostEvent(new ChangedEvent(ChangedEvent.ChangedFlags.Link)); unlinkedPrims.Add(newGrp); } } foreach (KeyValuePair <int, int> kvp in reorderLinkSet) { ChangeKey(kvp.Value, kvp.Key); } foreach (ObjectPart part in ValuesByKey1) { part.TriggerOnUpdate(UpdateChangedFlags.Link); part.Inventory.ResumeScripts(); } return(true); } }
internal ObjectUpdateInfo(ObjectPart part) { Part = part; ID = part.ID; }