Example #1
0
        public static void ReimportModelGroup(LXFMLDoc lxfml, ModelGroup group, ModelGroupImportSettings importSettings, bool detectConnectivity = false)
        {
            // Assign the new group import settings to the group.
            group.importSettings = importSettings;

            // We assume that the group can be found, so reimport it.
            if (group.processed)
            {
                // Remove all processed meshes.
                var renderers = group.GetComponentsInChildren <MeshRenderer>();
                foreach (var renderer in renderers)
                {
                    // FIXME Destroy the mesh? Prevents undo..
                    var filter = renderer.GetComponent <MeshFilter>();
                    //Undo.DestroyObjectImmediate(filter.sharedMesh);

                    if (renderer.GetComponent <ModelGroup>() == null)
                    {
                        // Destroy submesh game objects entirely.
                        Undo.DestroyObjectImmediate(renderer.gameObject);
                    }
                    else
                    {
                        // Destroy mesh related components on group game object.
                        Object.DestroyImmediate(filter);
                        Object.DestroyImmediate(renderer);
                    }
                }
            }

            // FIXME Check if bricks are referenced.
            // FIXME Check if bricks have custom components attached.

            // Remove group bricks.
            var existingBricks = group.GetComponentsInChildren <Brick>();

            foreach (var brick in existingBricks)
            {
                Undo.DestroyObjectImmediate(brick.gameObject);
            }

            var groupLightMapped = group.importSettings.isStatic && group.importSettings.lightmapped;

            SetStaticAndGIParams(group.gameObject, group.importSettings.isStatic, groupLightMapped);

            // Move group to origo to ensure that bricks are instantiated in the correct positions.
            var originalGroupLocalPosition = group.transform.localPosition;
            var originalGroupLocalRotation = group.transform.localRotation;
            var originalGroupLocalScale    = group.transform.localScale;
            var originalGroupParent        = group.transform.parent;
            var originalGroupSiblingIndex  = group.transform.GetSiblingIndex();

            group.transform.SetParent(null);
            group.transform.localPosition = Vector3.zero;
            group.transform.localRotation = Quaternion.identity;
            group.transform.localScale    = Vector3.one;

            // Create dictionary with just this group.
            var modelGroupImportSettingsDictionary = new DictionaryIntToModelGroupImportSettings();

            modelGroupImportSettingsDictionary.Add(group.number, group.importSettings);

            // Instantiate group bricks.
            var resultBricks = new Dictionary <int, Brick>(lxfml.bricks.Count);

            InstantiateModelBricks(lxfml, modelGroupImportSettingsDictionary, ref resultBricks, group.number);

            // Assign bricks to group.
            foreach (var brick in resultBricks.Values)
            {
                brick.transform.SetParent(group.transform);
            }
            ModelGroupUtility.RecomputePivot(group, false, ModelGroupUtility.UndoBehavior.withoutUndo);

            // Move group back to original location.
            group.transform.SetParent(originalGroupParent);
            group.transform.SetSiblingIndex(originalGroupSiblingIndex);
            group.transform.localPosition = originalGroupLocalPosition;
            group.transform.localRotation = originalGroupLocalRotation;
            group.transform.localScale    = originalGroupLocalScale;

            /*if (group.processed)
             * {
             *  // Process the group again.
             *  // FIXME Is this even a good idea?
             *  if (group.type == GroupType.Environment || group.type == GroupType.Static)
             *  {
             *      Vector2Int vertCount = Vector2Int.zero;
             *      Vector2Int triCount = Vector2Int.zero;
             *      Vector2Int meshCount = Vector2Int.zero;
             *      Vector2Int colliderCount = Vector2Int.zero;
             *      ModelProcessor.ProcessModelGroup(group, ref vertCount, ref triCount, ref meshCount, ref colliderCount);
             *
             *      Debug.Log($"Process result (before/after):\nVerts {vertCount.x}/{vertCount.y}, tris {triCount.x}/{triCount.y}, meshes {meshCount.x}/{meshCount.y}, colliders {colliderCount.x}/{colliderCount.y}");
             *  }
             * }*/

            if (detectConnectivity && group.importSettings.connectivity)
            {
                var sceneBricks = new HashSet <Brick>(StageUtility.GetCurrentStageHandle().FindComponentsOfType <Brick>());
                DetectConnectivity(new HashSet <Brick>(resultBricks.Values), sceneBricks);
            }

            EditorUtility.ClearProgressBar();
        }
Example #2
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();
        }
        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();
        }
Example #4
0
        /// <summary>
        /// Instantiate all bricks and groups in an LXFML document
        /// </summary>
        /// <param name="lxfml">The LXFML document</param>
        /// <param name="nameOfObject">Path of the LXFML document</param>
        public static GameObject InstantiateModel(LXFMLDoc lxfml, string filePath, Model.Pivot pivot, DictionaryIntToModelGroupImportSettings importSettings)
        {
            //Create "root" LXFML gameobject
            GameObject parent = new GameObject(Path.GetFileNameWithoutExtension(filePath));

            Undo.RegisterCreatedObjectUndo(parent, "Model");
            parent.transform.position = Vector3.zero;

            var model = parent.AddComponent <Model>();

            model.absoluteFilePath = filePath;
            model.relativeFilePath = PathUtils.GetRelativePath(Directory.GetCurrentDirectory(), filePath);
            model.pivot            = pivot;
            model.importSettings   = new DictionaryIntToModelGroupImportSettings(importSettings);

            EditorUtility.DisplayProgressBar("Importing", "Creating bricks.", 0.0f);

            var resultBricks = new Dictionary <int, Brick>(lxfml.bricks.Count);

            InstantiateModelBricks(lxfml, importSettings, ref resultBricks);

            EditorUtility.DisplayProgressBar("Importing", "Creating groups.", 0.8f);

            if (resultBricks.Count > 0)
            {
                var bricksWithConnectivity = new HashSet <Brick>();
                var groups = lxfml.groups;

                for (int i = 0; i < groups.Length; i++)
                {
                    var        number      = groups[i].number;
                    GameObject groupParent = InstantiateModelGroup(groups[i], i, parent, filePath, model.relativeFilePath, ref resultBricks, false, importSettings[number]);
                    if (importSettings[number].connectivity)
                    {
                        bricksWithConnectivity.UnionWith(groupParent.GetComponentsInChildren <Brick>());
                    }
                }

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


                if (SceneBrickBuilder.GetAutoUpdateHierarchy())
                {
                    var bricks = new HashSet <Brick>();
                    foreach (var pair in resultBricks)
                    {
                        foreach (var part in pair.Value.parts)
                        {
                            if (part.connectivity)
                            {
                                bricks.Add(pair.Value);
                                break;
                            }
                        }
                    }

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

            // Change the pivot.
            if (pivot != Model.Pivot.Original)
            {
                EditorUtility.DisplayProgressBar("Importing", "Computing bounds.", 0.9f);

                var bounds   = ComputeBounds(parent.transform);
                var newPivot = bounds.center;
                switch (pivot)
                {
                case Model.Pivot.BottomCenter:
                {
                    newPivot += -parent.transform.up * bounds.extents.y;
                    break;
                }
                }

                foreach (Transform child in parent.transform)
                {
                    child.position -= newPivot;
                }
                parent.transform.position += newPivot;
            }

            // Add LEGOModelAsset component.
            parent.AddComponent <LEGOModelAsset>();

            EditorUtility.ClearProgressBar();

            return(parent);
        }
Example #5
0
        public static void ReimportModelGroup(LXFMLDoc lxfml, ModelGroup group, ModelGroupImportSettings importSettings, bool detectConnectivity = false)
        {
            // Assign the new group import settings to the group.
            group.importSettings = importSettings;

            // We assume that the group can be found, so reimport it.
            if (group.processed)
            {
                // Remove processed decoration surfaces.
                var decorationSurfaces = group.transform.Find("DecorationSurfaces");
                if (decorationSurfaces)
                {
                    Undo.DestroyObjectImmediate(decorationSurfaces.gameObject);
                }

                // Remove processed colliders.
                var colliders = group.transform.Find("Colliders");
                if (colliders)
                {
                    Undo.DestroyObjectImmediate(colliders.gameObject);
                }

                // Remove all processed meshes.
                var renderers = group.GetComponentsInChildren <MeshRenderer>();
                foreach (var renderer in renderers)
                {
                    // FIXME Destroy the mesh? Prevents undo..
                    var filter = renderer.GetComponent <MeshFilter>();
                    //Undo.DestroyObjectImmediate(filter.sharedMesh);

                    if (renderer.GetComponent <ModelGroup>() == null)
                    {
                        // Destroy submesh game objects entirely.
                        Undo.DestroyObjectImmediate(renderer.gameObject);
                    }
                    else
                    {
                        // Destroy mesh related components on group game object.
                        Object.DestroyImmediate(filter);
                        Object.DestroyImmediate(renderer);
                    }
                }
            }

            group.processed = false;

            // FIXME Check if bricks are referenced.
            // FIXME Check if bricks have custom components attached.

            // Remove group bricks.
            var existingBricks = group.GetComponentsInChildren <Brick>();

            foreach (var brick in existingBricks)
            {
                Undo.DestroyObjectImmediate(brick.gameObject);
            }

            var groupLightMapped = group.importSettings.isStatic && group.importSettings.lightmapped;

            SetStaticAndGIParams(group.gameObject, group.importSettings.isStatic, groupLightMapped);

            // Move group to origo to ensure that bricks are instantiated in the correct positions.
            var originalGroupParent       = group.transform.parent;
            var originalGroupSiblingIndex = group.transform.GetSiblingIndex();

            group.transform.parent        = null;
            group.transform.localPosition = Vector3.zero;
            group.transform.localRotation = Quaternion.identity;
            group.transform.localScale    = Vector3.one;

            // Create dictionary with just this group.
            var modelGroupImportSettingsDictionary = new DictionaryIntToModelGroupImportSettings();

            modelGroupImportSettingsDictionary.Add(group.number, group.importSettings);

            // Instantiate group bricks.
            var resultBricks = new Dictionary <int, Brick>(lxfml.bricks.Count);

            InstantiateModelBricks(lxfml, modelGroupImportSettingsDictionary, ref resultBricks, group.number, true);

            // Assign bricks to group.
            foreach (var brick in resultBricks.Values)
            {
                brick.transform.SetParent(group.transform, true);
            }

            ModelGroupUtility.RecomputePivot(group, true, ModelGroupUtility.UndoBehavior.withoutUndo);

            // Set parent of group back to original.
            group.transform.parent = originalGroupParent;
            group.transform.SetSiblingIndex(originalGroupSiblingIndex);

            if (detectConnectivity && group.importSettings.connectivity)
            {
                var sceneBricks = new HashSet <Brick>(StageUtility.GetCurrentStageHandle().FindComponentsOfType <Brick>());
                DetectConnectivity(new HashSet <Brick>(resultBricks.Values), sceneBricks);
            }

            EditorUtility.ClearProgressBar();
        }