public void OnPostprocessBuild(BuildReport report) { if (!brickBuildingWasOn) { return; } ProcessHelper.ProcessAssets((go) => { Brick[] bricks = go.GetComponentsInChildren <Brick>(true); bool hasComponents = false; // Remove all of them foreach (var brick in bricks) { if (brick.colliding) { hasComponents = true; brick.SetMaterial(brick.colliding, false); } } // Flag as dirty if (hasComponents) { EditorUtility.SetDirty(go); return(true); } return(false); }); SceneBrickBuilder.ToggleBrickBuilding(); }
public void EnableSingleBrickSelectionTool() { bool singleBrickSelectionIsEnabled = !SceneBrickBuilder.GetSelectConnectedBricks(); if (singleBrickSelectionIsEnabled) { return; } SceneBrickBuilder.ToggleSelectConnectedBricks(); }
public void DisableBrickBuildingTool() { bool brickBuildingActive = SceneBrickBuilder.GetToggleBrickBuildingStatus(); if (!brickBuildingActive) { return; } SceneBrickBuilder.ToggleBrickBuilding(); }
private void OnGUI() { var snapDistance = EditorGUILayout.FloatField("Sticky Snap Distance", SceneBrickBuilder.GetStickySnapDistance()); SceneBrickBuilder.SetStickySnapDistance(snapDistance); var maxTries = EditorGUILayout.IntSlider("Max Tries Per Brick", SceneBrickBuilder.GetMaxTriesPerBrick(), 1, 20); SceneBrickBuilder.SetMaxTriesPerBrick(maxTries); }
public void OnPreprocessBuild(BuildReport report) { brickBuildingWasOn = SceneBrickBuilder.GetToggleBrickBuildingStatus(); if (brickBuildingWasOn) { SceneBrickBuilder.ToggleBrickBuilding(); } var activeScene = EditorSceneManager.GetActiveScene(); if (activeScene != null && activeScene.path != "") { activeScenePath = activeScene.path; } ProcessHelper.ProcessAssets((go) => { Brick[] bricks = go.GetComponentsInChildren <Brick>(true); bool hasComponents = false; // Remove all of them foreach (var brick in bricks) { if (brick.colliding) { hasComponents = true; brick.SetMaterial(false, false); } } // Flag as dirty if (hasComponents) { EditorUtility.SetDirty(go); return(true); } return(false); }); }
static void ConnectivityUIWindow(int windowId) { bool brickBuildingActive = SceneBrickBuilder.GetToggleBrickBuildingStatus(); bool selectConnectedActive = SceneBrickBuilder.GetSelectConnectedBricks(); GUILayout.BeginHorizontal(); // Toggle brick building string toggleBrickBuildingShortcut = ShortcutManager.instance.GetShortcutBinding("Main Menu/" + SceneBrickBuilder.brickBuildingMenuPath).ToString(); GUIContent toggleBrickBuildingContent = new GUIContent("", "Brick Building " + toggleBrickBuildingShortcut); brickBuildingStyle.normal.background = brickBuildingActive ? brickBuildingOnImage : brickBuildingOffImage; brickBuildingStyle.active.background = brickBuildingActive ? brickBuildingOffImage : brickBuildingOnImage; if (GUILayout.Button(toggleBrickBuildingContent, brickBuildingStyle)) { SceneBrickBuilder.ToggleBrickBuilding(); } // Toggle select connected string toggleSelectConnectedShortcut = ShortcutManager.instance.GetShortcutBinding("Main Menu/" + SceneBrickBuilder.editorSelectConnectedMenuPath).ToString(); GUIContent toggleSelectConnectedContent = selectConnectedActive ? new GUIContent("", "Connected Brick Selection " + toggleSelectConnectedShortcut) : new GUIContent("", "Single Brick Selection " + toggleSelectConnectedShortcut); selectConnectedStyle.normal.background = selectConnectedActive ? selectConnectedOnImage : selectConnectedOffImage; selectConnectedStyle.active.background = selectConnectedActive ? selectConnectedOffImage : selectConnectedOnImage; GUI.enabled = SceneBrickBuilder.ValidateSelectConnectedBricks(); if (GUILayout.Button(toggleSelectConnectedContent, selectConnectedStyle)) { SceneBrickBuilder.ToggleSelectConnectedBricks(); } GUILayout.EndHorizontal(); GUI.enabled = true; GUI.DragWindow(); }
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(); }
/// <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); }
private void OnGUI() { // Find max label width. var maxLabelWidth = 110.0f; for (int i = 0; i < lxfml.groups.Length; i++) { var size = EditorStyles.boldLabel.CalcSize(new GUIContent(lxfml.groups[i].name)); maxLabelWidth = Mathf.Max(maxLabelWidth, size.x); } minSize = new Vector2(leftMargin + maxLabelWidth + 360, 226); maxSize = new Vector2(leftMargin + maxLabelWidth + 360, 2000); scrollPosition = GUILayout.BeginScrollView(scrollPosition, false, false); GUI.Box(new Rect(20, 20, 100, 100), logoTexture); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 20.0f, 100.0f), "Colliders", "Add colliders to bricks."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 50.0f, 100.0f), "Connectivity", "Add connectivity to bricks. Connectivity requires colliders."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 100.0f, 100.0f), "Static", "Make bricks static."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 130.0f, 100.0f), "Lightmapped", "Add lightmap UVs to bricks. Bricks must be static to be lightmapped."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 180.0f, 100.0f), "Randomize Rotation", "Slightly rotate bricks to improve realism."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 230.0f, 100.0f), "Prefer Legacy", "Prefer legacy geometry over new geometry."); CreateHeaderUI(new Vector2(leftMargin + maxLabelWidth + 280.0f, 100.0f), "LOD", "LOD 0 includes chamfered edges.\nLOD 1 does not.\nLOD 2 simplifies knobs."); // Reserve the space for the GUILayout scroll view. GUILayout.Space(135.0f); var nextY = 135.0f; var showAllBoolsUI = model == null && group == null && lxfml.groups.Length > 1; // When importing a new model, just check if there is more than one lxfml group. showAllBoolsUI |= model != null && importSettings.Count > 1; // When reimporting an entire model, check if the existing model has more than one group. if (showAllBoolsUI) { CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 15.0f, nextY), importSettings, "colliders", "connectivity", null); CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 45.0f, nextY), importSettings, "connectivity", null, "colliders"); CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 95.0f, nextY), importSettings, "isStatic", "lightmapped", null); CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 125.0f, nextY), importSettings, "lightmapped", null, "isStatic"); CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 175.0f, nextY), importSettings, "randomizeRotation"); CreateAllBoolsUI(new Vector2(leftMargin + maxLabelWidth + 225.0f, nextY), importSettings, "preferLegacy"); CreateAllLODsUI(new Vector2(leftMargin + maxLabelWidth + 275.0f, nextY), importSettings); // Reserve the space for the GUILayout scroll view. GUILayout.Space(25.0f); nextY += 25.0f; } var collidersOrConnectivityWhilePreferringLegacy = false; for (int i = 0; i < lxfml.groups.Length; i++) { var showGroup = group == null && model == null; // When importing a new model, show all groups. showGroup |= model != null && importSettings.ContainsKey(i); // When reimporting an entire model, only show groups already in the existing model. showGroup |= group != null && i == group.number; // When reimporting a model group, only show that group. if (showGroup) { GUI.Label(new Rect(leftMargin, nextY, maxLabelWidth, 20.0f), lxfml.groups[i].name); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 15.0f, nextY), importSettings, "colliders", i, "connectivity", null); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 45.0f, nextY), importSettings, "connectivity", i, null, "colliders"); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 95.0f, nextY), importSettings, "isStatic", i, "lightmapped", null); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 125.0f, nextY), importSettings, "lightmapped", i, null, "isStatic"); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 175.0f, nextY), importSettings, "randomizeRotation", i); CreateBoolUI(new Vector2(leftMargin + maxLabelWidth + 225.0f, nextY), importSettings, "preferLegacy", i); CreateLODUI(new Vector2(leftMargin + maxLabelWidth + 275.0f, nextY), importSettings, i); if ((importSettings[i].colliders || importSettings[i].connectivity) && importSettings[i].preferLegacy) { collidersOrConnectivityWhilePreferringLegacy = true; } // Reserve the space for the GUILayout scroll view. GUILayout.Space(20.0f); nextY += 20.0f; } } if (collidersOrConnectivityWhilePreferringLegacy) { EditorGUI.HelpBox(new Rect(leftMargin, nextY, position.width - leftMargin - 20.0f, 38.0f), "Legacy parts might not contain colliders or connectivity information.", MessageType.Warning); // Reserve the space for the GUILayout scroll view. GUILayout.Space(42.0f); nextY += 42.0f; } // Reserve the space for the GUILayout scroll view. GUILayout.Space(5.0f); nextY += 5.0f; // Only show pivot option when not reimporting group. if (group == null) { GUI.Label(new Rect(leftMargin, nextY, maxLabelWidth, 20.0f), "Pivot"); pivot = (Model.Pivot)EditorGUI.EnumPopup(new Rect(leftMargin + maxLabelWidth + 15.0f, nextY, 126.0f, 16.0f), pivot); // Reserve the space for the GUILayout scroll view. GUILayout.Space(25.0f); nextY += 25.0f; } // Create the right import/reimport button and handle the import/reimport based on the three cases: // - Reimport model // - Reimport model group // - Import model bool importPressed; if (model) { // ---------------------- // Reimport entire model. // ---------------------- importPressed = GUI.Button(new Rect(leftMargin, nextY, maxLabelWidth + 15.0f + 126.0f, 32.0f), "Reimport Model"); if (importPressed) { // Register undo. Undo.RegisterFullObjectHierarchyUndo(model.gameObject, "Reimport"); var oldPivot = model.pivot; model.pivot = pivot; // Update the path if it is new. if (filePath != null) { model.absoluteFilePath = filePath; model.relativeFilePath = PathUtils.GetRelativePath(Directory.GetCurrentDirectory(), filePath); } ModelImporter.ReimportModel(lxfml, model, oldPivot, importSettings); var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { EditorSceneManager.MarkSceneDirty(prefabStage.scene); } SceneBrickBuilder.MarkSceneDirty(); } } else if (group) { // --------------------- // Reimport model group. // --------------------- importPressed = GUI.Button(new Rect(leftMargin, nextY, maxLabelWidth + 15.0f + 126.0f, 32.0f), "Reimport Model Group"); if (importPressed) { // Register undo. Undo.RegisterFullObjectHierarchyUndo(group.gameObject, "Reimport"); ModelImporter.ReimportModelGroup(lxfml, group, importSettings[group.number], true); var prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (prefabStage != null) { EditorSceneManager.MarkSceneDirty(prefabStage.scene); } SceneBrickBuilder.MarkSceneDirty(); } } else { // ---------------------- // Import model. // ---------------------- importPressed = GUI.Button(new Rect(leftMargin, nextY, maxLabelWidth + 15.0f + 126.0f, 32.0f), "Import Model"); if (importPressed) { // Check for connectivity updates. ConnectivityVersionChecker.CheckForUpdates(); model = ModelImporter.InstantiateModel(lxfml, filePath, pivot, importSettings).GetComponent <Model>(); var camera = SceneView.lastActiveSceneView.camera; if (camera) { var cameraRay = new Ray(camera.transform.position, camera.transform.forward); var bricksInModel = model.GetComponentsInChildren <Brick>(); var bricks = new HashSet <Brick>(bricksInModel); var sourceBrick = bricks.First(); BrickBuildingUtility.AlignBricks(sourceBrick, bricks, BrickBuildingUtility.ComputeBounds(bricks), sourceBrick.transform.position, Vector3.zero, cameraRay, new Plane(Vector3.up, Vector3.zero), 100.0f, out Vector3 offset, out Vector3 alignedOffset, out _, out _); var offsetPosition = model.transform.position + alignedOffset; model.transform.position = offsetPosition; Selection.activeGameObject = model.gameObject; Physics.SyncTransforms(); } SceneBrickBuilder.SyncAndUpdateBrickCollision(true); } } // Reserve the space for the GUILayout scroll view. GUILayout.Space(36.0f); nextY += 36.0f; // List tracked errors. foreach (var trackedError in trackedErrors) { EditorGUI.HelpBox(new Rect(leftMargin, nextY, maxLabelWidth + 340.0f, 38.0f), trackedError.Key, MessageType.Warning); // Reserve the space for the GUILayout scroll view. GUILayout.Space(42.0f); nextY += 42.0f; foreach (var id in trackedError.Value) { GUI.Label(new Rect(leftMargin, nextY, maxLabelWidth + 340.0f, 16.0f), id); // Reserve the space for the GUILayout scroll view. GUILayout.Space(20.0f); nextY += 20.0f; } } GUILayout.EndScrollView(); if (importPressed) { this.Close(); } }
public bool IsBrickBuildingEnabled() { return(SceneBrickBuilder.GetToggleBrickBuildingStatus()); }
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(); }