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);
        }
Example #2
0
        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);
        }
Example #5
0
        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);
                }
            }
        }
Example #7
0
        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;
                }
            }
        }
Example #8
0
        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;
                }
            }
        }
Example #9
0
        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;
                }
            }
        }
Example #10
0
 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);
            }
        }
Example #12
0
 internal ObjectUpdateInfo(ObjectPart part)
 {
     Part = part;
     ID   = part.ID;
 }