Ejemplo n.º 1
0
        /// <summary>
        /// Parses a 3d World from an ArrayEntry
        /// </summary>
        /// <param name="objectEntry"></param>
        /// <param name="zone"></param>
        /// <param name="objectsByReference"></param>
        /// <returns></returns>
        public static I3dWorldObject ParseObject(ArrayEntry objectEntry, SM3DWorldZone zone, Dictionary <long, I3dWorldObject> objectsByReference, out bool alreadyInLinks, Dictionary <string, I3dWorldObject> linkedObjsByID, bool isLinked = false)
        {
            ObjectInfo info = GetObjectInfo(ref objectEntry, zone);

            I3dWorldObject obj;
            bool           loadLinks;

            if ((info.ClassName == "Area") || info.ObjectName.Contains("Area") && AreaModelNames.Contains(info.ModelName))
            {
                obj = new AreaObject(in info, zone, out loadLinks);
            }
            else if (info.PropertyEntries.TryGetValue("RailPoints", out DictionaryEntry railPointEntry) && railPointEntry.NodeType == ByamlFile.ByamlNodeType.Array) //at this point we can be sure it's a rail
            {
                obj = new Rail(in info, zone, out loadLinks);
            }
            else
            {
                obj = new General3dWorldObject(in info, zone, out loadLinks);
            }

            if (isLinked && linkedObjsByID != null && !(obj is Rail))
            {
                if (!linkedObjsByID.ContainsKey(info.ID))
                {
                    linkedObjsByID.Add(info.ID, obj);
                }
                else
                {
                    alreadyInLinks = true;

                    obj = linkedObjsByID[info.ID];

                    if (!isLinked)
                    {
                        alreadyInLinks = !zone.LinkedObjects.Remove(obj);
                    }

                    //in case this object was already read in another file
                    if (!objectsByReference.ContainsKey(objectEntry.Position))
                    {
                        objectsByReference.Add(objectEntry.Position, obj);
                    }

                    return(obj);
                }
            }

            alreadyInLinks = false;

            if (!objectsByReference.ContainsKey(objectEntry.Position))
            {
                objectsByReference.Add(objectEntry.Position, obj);
            }
            else if (!isLinked)
            {
                obj = objectsByReference[objectEntry.Position];
                zone.LinkedObjects.Remove(obj);
                return(obj);
            }

            if (loadLinks)
            {
                var links = new Dictionary <string, List <I3dWorldObject> >();
                foreach (DictionaryEntry link in info.LinkEntries.Values)
                {
                    links.Add(link.Key, new List <I3dWorldObject>());
                    foreach (ArrayEntry linked in link.IterArray())
                    {
                        if (objectsByReference.ContainsKey(linked.Position))
                        {
                            links[link.Key].Add(objectsByReference[linked.Position]);
                            objectsByReference[linked.Position].AddLinkDestination(link.Key, obj);
                        }
                        else
                        {
                            I3dWorldObject _obj = ParseObject(linked, zone, objectsByReference, out bool linkedAlreadyReferenced, linkedObjsByID, true);
                            _obj.AddLinkDestination(link.Key, obj);
                            links[link.Key].Add(_obj);
                            if (zone != null && !linkedAlreadyReferenced)
                            {
                                zone.LinkedObjects.Add(_obj);
                            }
                        }
                    }
                }
                if (links.Count > 0)
                {
                    obj.Links = links;
                }
            }

            return(obj);
        }
Ejemplo n.º 2
0
        private static ObjectInfo GetObjectInfo(ref ArrayEntry objectEntry, SM3DWorldZone zone)
        {
            Dictionary <string, DictionaryEntry> properties = new Dictionary <string, DictionaryEntry>();
            Dictionary <string, DictionaryEntry> links      = new Dictionary <string, DictionaryEntry>();

            ObjectInfo info = new ObjectInfo();

            foreach (DictionaryEntry entry in objectEntry.IterDictionary())
            {
                switch (entry.Key)
                {
                case "comment":
                case "Comment":
                    info.Comment = entry.Parse();
                    break;

                case "IsLinkDest":
#if ODYSSEY
                case "SrcUnitLayerList":
                case "PlacementFileName":
#endif
                    break;     //ignore these

                case "Id":
                    info.ID = entry.Parse();
                    break;

                case "LayerConfigName":
                    info.Layer = entry.Parse();
                    break;

                case "Links":
                    foreach (DictionaryEntry linkEntry in entry.IterDictionary())
                    {
                        links.Add(linkEntry.Key, linkEntry);
                    }
                    break;

                case "ModelName":
                    info.ModelName = entry.Parse() ?? "";
                    break;

                case "Rotate":
                    dynamic _data = entry.Parse();
                    info.Rotation = new Vector3(
                        _data["X"],
                        _data["Y"],
                        _data["Z"]
                        );
                    break;

                case "Scale":
                    _data      = entry.Parse();
                    info.Scale = new Vector3(
                        _data["X"],
                        _data["Y"],
                        _data["Z"]
                        );
                    break;

                case "Translate":
                    _data         = entry.Parse();
                    info.Position = new Vector3(
                        _data["X"] / 100f,
                        _data["Y"] / 100f,
                        _data["Z"] / 100f
                        );
                    break;

                case "UnitConfigName":
                    info.ObjectName = entry.Parse();
                    break;

                case "UnitConfig":
                    _data = entry.Parse();

                    info.DisplayTranslation = new Vector3(
                        _data["DisplayTranslate"]["X"] / 100f,
                        _data["DisplayTranslate"]["Y"] / 100f,
                        _data["DisplayTranslate"]["Z"] / 100f
                        );
                    info.DisplayName = _data["DisplayName"];
                    info.ClassName   = _data["ParameterConfigName"];
                    break;

                default:
                    if (!properties.ContainsKey(entry.Key))
                    {
                        properties.Add(entry.Key, entry);
                    }
                    break;
                }
            }

            info.PropertyEntries = properties;
            info.LinkEntries     = links;
            return(info);
        }