/// <summary>
        ///
        /// </summary>
        /// <param name="masterParent"></param>
        /// <param name="parent"></param>
        /// <param name="parentNode"></param>
        private static void ReadGroupTreeRecursively(LXFMLDoc.BrickGroup masterParent, LXFMLDoc.BrickGroup parent, XmlNode parentNode)
        {
            parent.brickRefs = ParseUtils.StringToIntArray(parentNode.Attributes["brickRefs"].Value);

            if (masterParent != parent)
            {
                var current = new List <int>(masterParent.brickRefs);
                current.AddRange(parent.brickRefs);
                masterParent.brickRefs = current.ToArray();
            }

            var childNodes = parentNode.SelectNodes("Group");

            if (childNodes.Count > 0)
            {
                var groupCount = 0;
                parent.children = new LXFMLDoc.BrickGroup[childNodes.Count];

                foreach (XmlNode childNode in childNodes)
                {
                    var group = new LXFMLDoc.BrickGroup();
                    parent.children[groupCount++] = group;
                    group.parent = parent;
                    ReadGroupTreeRecursively(masterParent, group, childNode);
                }
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="lxfmlDoc"></param>
        /// <param name="lxfml"></param>
        /// <returns></returns>
        public static bool ReadLxfml(XmlDocument lxfmlDoc, ref LXFMLDoc lxfml)
        {
            var success = false;

            if (lxfmlDoc != null)
            {
                try
                {
                    success = true;

                    var lxfmlNode  = lxfmlDoc.SelectSingleNode("LXFML");
                    var cameraNode = lxfmlNode.SelectSingleNode("Cameras/Camera");

                    if (cameraNode != null)
                    {
                        var lxfmlCamera = new LXFMLDoc.LxfmlCamera();
                        lxfmlCamera.fov            = float.Parse(cameraNode.Attributes["fieldOfView"].Value, CultureInfo.InvariantCulture);
                        lxfmlCamera.distance       = float.Parse(cameraNode.Attributes["distance"].Value, CultureInfo.InvariantCulture);
                        lxfmlCamera.transformation = ParseUtils.StringToFloatArray(cameraNode.Attributes["transformation"].Value);
                        var transformation = new Matrix4x4();
                        var mArr           = ParseUtils.StringToFloatArray(cameraNode.Attributes["transformation"].Value);

                        for (var i = 0; i < 4; ++i)
                        {
                            transformation.SetRow(i, new Vector4(mArr[i * 3], mArr[i * 3 + 1], mArr[i * 3 + 2], 0));
                        }

                        lxfmlCamera.position = GetPosition(transformation);
                        lxfmlCamera.rotation = GetRotation(transformation);
                        lxfml.camera         = lxfmlCamera;
                    }

                    var lxfmlNameAttrib = lxfmlNode.Attributes["name"];
                    if (lxfmlNameAttrib != null)
                    {
                        lxfml.name = lxfmlNameAttrib.Value;
                    }

                    var bricksNode = lxfmlNode.SelectSingleNode("Bricks");
                    var brickNodes = bricksNode.SelectNodes("Brick");

                    foreach (XmlNode brickNode in brickNodes)
                    {
                        var brick = PopulateBrick(brickNode);
                        lxfml.bricks.Add(brick);
                    }

                    var groupsNode = lxfmlNode.SelectSingleNode("GroupSystems");

                    if (groupsNode != null)
                    {
                        var brickGroupSystemNode = groupsNode.SelectSingleNode("BrickGroupSystem"); // TODO: Handle PartGroupSystem.
                        if (brickGroupSystemNode != null)
                        {
                            var rootGroupNodes = brickGroupSystemNode.SelectNodes("Group");

                            if (rootGroupNodes.Count > 0)
                            {
                                lxfml.groups = new LXFMLDoc.BrickGroup[rootGroupNodes.Count];
                                var groupCount = 0;

                                foreach (XmlNode rootGroupNode in rootGroupNodes)
                                {
                                    var group         = new LXFMLDoc.BrickGroup();
                                    var nameAttribute = rootGroupNode.Attributes["name"];
                                    if (nameAttribute != null)
                                    {
                                        group.name = nameAttribute.Value;
                                    }
                                    group.number = groupCount;

                                    lxfml.groups[groupCount++] = group;

                                    //Sub groups!
                                    if (rootGroupNode.SelectNodes("Group").Count > 0)
                                    {
                                        ReadGroupTreeRecursively(group, group, rootGroupNode);
                                    }
                                    else
                                    {
                                        var brickRefsAttribute = rootGroupNode.Attributes["brickRefs"];

                                        if (brickRefsAttribute != null)
                                        {
                                            group.brickRefs = ParseUtils.StringToIntArray(brickRefsAttribute.Value);
                                            SetGroupBricksFromBrickRefs(lxfml.bricks, group);
                                        }
                                        else
                                        {
                                            group.brickRefs = new int[0];
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    Debug.LogWarning(e + "\t" + e.StackTrace);
                    success = false;
                }
            }

            return(success);
        }
 private static void SetGroupBricksFromBrickRefs(List <LXFMLDoc.Brick> bricks, LXFMLDoc.BrickGroup group)
 {
     for (int i = 0; i < group.brickRefs.Length; ++i)
     {
         group.bricks.Add(bricks.Find((obj) => obj.refId == group.brickRefs[i]));
     }
 }
示例#4
0
        public static void ReimportModel(LXFMLDoc lxfml, Model model, DictionaryIntToModelGroupImportSettings importSettings)
        {
            var brickBuilding = SceneBrickBuilder.GetToggleBrickBuildingStatus();

            if (brickBuilding)
            {
                SceneBrickBuilder.ToggleBrickBuilding();
            }

            // FIXME Next version could include option to match groups up manually.

            var groups = model.GetComponentsInChildren <ModelGroup>();

            for (var i = groups.Length - 1; i >= 0; i--)
            {
                var group = groups[i];
                if (group.autoGenerated)
                {
                    Undo.DestroyObjectImmediate(group.gameObject);
                }
                else if (group.number >= lxfml.groups.Length)
                {
                    Debug.LogWarning("Group " + group.number + " " + group.groupName + " does not match up with files. Wiping.");
                    Undo.DestroyObjectImmediate(group.gameObject);
                }
            }

            groups = model.GetComponentsInChildren <ModelGroup>();

            var removedGroups = new List <LXFMLDoc.BrickGroup>();

            for (var i = 0; i < lxfml.groups.Length; i++)
            {
                LXFMLDoc.BrickGroup group = lxfml.groups[i];
                bool exists = false;
                for (var j = 0; j < groups.Length; j++)
                {
                    if (groups[j].number == group.number)
                    {
                        exists = true;
                        break;
                    }
                }

                if (!exists)
                {
                    removedGroups.Add(group);
                }
            }

            // Assign the new model import settings to the model.
            model.importSettings = new DictionaryIntToModelGroupImportSettings(importSettings);
            var bricksWithConnectivity = new HashSet <Brick>();

            if (removedGroups.Count > 0)
            {
                var resultBricks = new Dictionary <int, Brick>(lxfml.bricks.Count);
                foreach (var group in removedGroups)
                {
                    var number = group.number;
                    InstantiateModelBricks(lxfml, model.importSettings, ref resultBricks, number);
                    var groupGO = InstantiateModelGroup(group, number, model.gameObject, model.absoluteFilePath, model.relativeFilePath, ref resultBricks, false, importSettings[number]);
                    groupGO.transform.position = model.transform.position;
                    Undo.RegisterCreatedObjectUndo(groupGO, "Re-creating model group");
                    if (importSettings[number].connectivity)
                    {
                        bricksWithConnectivity.UnionWith(groupGO.GetComponentsInChildren <Brick>());
                    }
                }
            }

            foreach (var group in groups)
            {
                group.absoluteFilePath = model.absoluteFilePath;
                group.relativeFilePath = model.relativeFilePath;
                ReimportModelGroup(lxfml, group, importSettings[group.number]);
                if (group.importSettings.connectivity)
                {
                    bricksWithConnectivity.UnionWith(group.GetComponentsInChildren <Brick>());
                }
            }

            if (bricksWithConnectivity.Count > 0)
            {
                var sceneBricks = new HashSet <Brick>(StageUtility.GetCurrentStageHandle().FindComponentsOfType <Brick>());
                DetectConnectivity(bricksWithConnectivity, sceneBricks);
            }

            if (brickBuilding)
            {
                SceneBrickBuilder.ToggleBrickBuilding();
            }

            if (SceneBrickBuilder.GetAutoUpdateHierarchy())
            {
                groups = model.GetComponentsInChildren <ModelGroup>();
                var bricks = new HashSet <Brick>();
                foreach (var group in groups)
                {
                    if (group.importSettings.connectivity)
                    {
                        var groupBricks = group.GetComponentsInChildren <Brick>();
                        foreach (var brick in groupBricks)
                        {
                            bricks.Add(brick);
                        }
                    }
                }

                // On reimport, the model will be positioned weirdly compared to the rest of the scene, so we just ignore all other bricks
                ModelGroupUtility.RecomputeModelGroups(bricks);
            }

            EditorUtility.ClearProgressBar();
        }
示例#5
0
        //private static readonly string decorationMaterialsPath = "Assets/LEGOIntegrationHub/Internal/LXFML/Resources/Materials";
        //public static Material decoCutoutMaterial = Resources.Load<Material>("LXFMLMaterials/transpcutoutMinifigure");

        /// <summary>
        /// Translate the bricks in a given LXFML-group to interactable objects
        /// </summary>
        /// <param name="group">The LXFML-group</param>
        /// <param name="index">Index of the group</param>
        /// <param name="parent">The imported asset</param>
        /// <param name="absoluteFilePath">Path of the imported asset</param>
        /// <param name="relativeFilePath">Path of the imported asset</param>
        /// <param name="resultBricks">Dictionary containing the simple bricks</param>
        /// <param name="isSubGroup">Whether it is a subgroup or not</param>
        /// <param name="lightmapped">Whether it is lightmapped or not</param>
        /// <param name="missingGroups">List of groups containing missing elements</param>
        public static GameObject InstantiateModelGroup(LXFMLDoc.BrickGroup group, int index, GameObject parent, string absoluteFilePath, string relativeFilePath, ref Dictionary <int, Brick> resultBricks, bool isSubGroup, ModelGroupImportSettings importSettings)
        {
            ModelGroup groupComp;
            GameObject groupParent;

            if (isSubGroup)
            {
                groupParent = new GameObject("SubGroup " + index + " - " + group.name);
            }
            else
            {
                groupParent = new GameObject(group.name);
            }

            // FIXME Handle subgroups properly.
            //Recursively check subgroups
            if (group.children != null)
            {
                foreach (var subGroup in group.children)
                {
                    foreach (var part in group.brickRefs)
                    {
                        //Apparently supergroups contain elements from subgroups. Duplicates are removed from supergroups.
                        if (subGroup.brickRefs.Contains(part))
                        {
                            group.brickRefs[Array.IndexOf(group.brickRefs, part)] = -1;
                        }
                    }
                    InstantiateModelGroup(subGroup, Array.IndexOf(group.children, subGroup), groupParent, absoluteFilePath, relativeFilePath, ref resultBricks, true, importSettings);
                }
            }

            importSettings.lightmapped &= importSettings.isStatic;

            SetStaticAndGIParams(groupParent, importSettings.isStatic, importSettings.lightmapped);

            groupParent.transform.parent = parent.transform;
            groupParent.transform.SetSiblingIndex(index);
            if (!isSubGroup)
            {
                groupComp = groupParent.AddComponent <ModelGroup>();
                groupComp.absoluteFilePath = absoluteFilePath;
                groupComp.relativeFilePath = relativeFilePath;

                groupComp.importSettings = importSettings;

                groupComp.groupName  = group.name;
                groupComp.number     = index;
                groupComp.parentName = parent.name;

                groupComp.optimizations = ModelGroup.Optimizations.Everything;

                // Add LEGOModelGroupAsset component.
                groupParent.AddComponent <LEGOModelGroupAsset>();
            }

            var groupBricks = new HashSet <Brick>();

            foreach (int id in group.brickRefs)
            {
                if (id == -1)
                {
                    continue;
                }
                if (resultBricks.ContainsKey(id))
                {
                    groupBricks.Add(resultBricks[id]);
                    resultBricks[id].transform.SetParent(groupParent.transform);
                }
            }

            return(groupParent);
        }
        public static void ReimportModel(LXFMLDoc lxfml, Model model, Model.Pivot previousPivot, DictionaryIntToModelGroupImportSettings importSettings)
        {
            var brickBuilding = SceneBrickBuilder.GetToggleBrickBuildingStatus();

            if (brickBuilding)
            {
                SceneBrickBuilder.ToggleBrickBuilding();
            }

            // FIXME Next version could include option to match groups up manually.

            var oldPosition = model.transform.position;
            var oldRotation = model.transform.rotation;

            model.transform.position = Vector3.zero;
            model.transform.rotation = Quaternion.identity;

            var groups = model.GetComponentsInChildren <ModelGroup>();

            for (var i = groups.Length - 1; i >= 0; i--)
            {
                var group = groups[i];
                if (group.autoGenerated)
                {
                    Undo.DestroyObjectImmediate(group.gameObject);
                }
                else if (group.number >= lxfml.groups.Length)
                {
                    Debug.LogWarning("Group " + group.number + " " + group.groupName + " does not match up with files. Wiping.");
                    Undo.DestroyObjectImmediate(group.gameObject);
                }
            }

            groups = model.GetComponentsInChildren <ModelGroup>();

            var removedGroups = new List <LXFMLDoc.BrickGroup>();

            for (var i = 0; i < lxfml.groups.Length; i++)
            {
                LXFMLDoc.BrickGroup group = lxfml.groups[i];
                bool exists = false;
                for (var j = 0; j < groups.Length; j++)
                {
                    if (groups[j].number == group.number)
                    {
                        exists = true;
                        break;
                    }
                }

                if (!exists)
                {
                    removedGroups.Add(group);
                }
            }

            // Assign the new model import settings to the model.
            model.importSettings = new DictionaryIntToModelGroupImportSettings(importSettings);
            var bricksWithConnectivity = new HashSet <Brick>();

            if (removedGroups.Count > 0)
            {
                var resultBricks = new Dictionary <int, Brick>(lxfml.bricks.Count);
                foreach (var group in removedGroups)
                {
                    var number = group.number;
                    InstantiateModelBricks(lxfml, model.importSettings, ref resultBricks, number);
                    var groupGO = InstantiateModelGroup(group, number, model.gameObject, model.absoluteFilePath, model.relativeFilePath, ref resultBricks, false, importSettings[number]);
                    groupGO.transform.position = model.transform.position;
                    Undo.RegisterCreatedObjectUndo(groupGO, "Re-creating model group");
                    if (importSettings[number].connectivity)
                    {
                        bricksWithConnectivity.UnionWith(groupGO.GetComponentsInChildren <Brick>());
                    }
                }
            }

            foreach (var group in groups)
            {
                group.absoluteFilePath = model.absoluteFilePath;
                group.relativeFilePath = model.relativeFilePath;
                ReimportModelGroup(lxfml, group, importSettings[group.number]);
                if (group.importSettings.connectivity)
                {
                    bricksWithConnectivity.UnionWith(group.GetComponentsInChildren <Brick>());
                }
            }

            if (bricksWithConnectivity.Count > 0)
            {
                var sceneBricks = new HashSet <Brick>(StageUtility.GetCurrentStageHandle().FindComponentsOfType <Brick>());
                DetectConnectivity(bricksWithConnectivity, sceneBricks);
            }

            if (SceneBrickBuilder.GetAutoUpdateHierarchy())
            {
                groups = model.GetComponentsInChildren <ModelGroup>();
                var bricks = new HashSet <Brick>();
                foreach (var group in groups)
                {
                    if (group.importSettings.connectivity)
                    {
                        var groupBricks = group.GetComponentsInChildren <Brick>();
                        foreach (var brick in groupBricks)
                        {
                            bricks.Add(brick);
                        }
                    }
                }
                ModelGroupUtility.RecomputeHierarchy(bricks, false, ModelGroupUtility.UndoBehavior.withUndo);

                var oldToNew = model.transform.position;
                model.transform.rotation = oldRotation;
                model.transform.position = oldPosition;
                oldToNew = model.transform.TransformVector(oldToNew);

                if ((previousPivot == Model.Pivot.Center || previousPivot == Model.Pivot.BottomCenter) && model.pivot == Model.Pivot.Original)
                {
                    ModelGroupUtility.RecomputePivot(model.transform, previousPivot, true, ModelGroupUtility.UndoBehavior.withoutUndo);
                    var oldPivotPos = model.transform.position;
                    model.transform.position = oldPosition;
                    var diff = model.transform.position - oldPivotPos;
                    model.transform.position += diff;
                    foreach (var brick in model.GetComponentsInChildren <Brick>())
                    {
                        brick.transform.position -= diff;
                    }
                    model.transform.rotation = oldRotation;
                }

                if (model.pivot != Model.Pivot.Original && previousPivot == Model.Pivot.Original)
                {
                    model.transform.position += oldToNew;
                    model.transform.rotation  = oldRotation;
                }

                if (model.pivot != Model.Pivot.Original && previousPivot != Model.Pivot.Original)
                {
                    if (model.pivot != previousPivot)
                    {
                        ModelGroupUtility.RecomputePivot(model.transform, previousPivot, true, ModelGroupUtility.UndoBehavior.withoutUndo);
                        model.transform.position = oldPosition;
                        ModelGroupUtility.RecomputePivot(model, false, ModelGroupUtility.UndoBehavior.withoutUndo);
                        model.transform.rotation = oldRotation;
                    }
                }
            }

            if (brickBuilding)
            {
                SceneBrickBuilder.ToggleBrickBuilding();
            }

            EditorUtility.ClearProgressBar();
        }