private static void CreateBoolUI(Vector2 position, DictionaryIntToModelGroupImportSettings importSettings, string valueName, int index, string onFalseName = null, string onTrueName = null) { var type = typeof(ModelGroupImportSettings); var valueField = type.GetField(valueName); var onFalseField = onFalseName != null?type.GetField(onFalseName) : null; var onTrueField = onTrueName != null?type.GetField(onTrueName) : null; var newValue = EditorGUI.Toggle(new Rect(position, new Vector2(16, 16)), (bool)valueField.GetValue(importSettings[index])); valueField.SetValue(importSettings[index], newValue); if (onFalseField != null && !newValue) { onFalseField.SetValue(importSettings[index], false); } if (onTrueField != null && newValue) { onTrueField.SetValue(importSettings[index], true); } }
private static void CreateAllLODsUI(Vector2 position, DictionaryIntToModelGroupImportSettings importSettings) { var lodSet = new HashSet <int>(); foreach (var key in new List <int>(importSettings.Keys)) { lodSet.Add(importSettings[key].lod); } EditorGUI.showMixedValue = lodSet.Count > 1; EditorGUI.BeginChangeCheck(); var newValue = EditorGUI.Popup(new Rect(position, new Vector2(64, 16)), importSettings[0].lod, lodOptions); if (EditorGUI.EndChangeCheck()) { foreach (var key in new List <int>(importSettings.Keys)) { importSettings[key].lod = newValue; } } EditorGUI.showMixedValue = false; }
private static void CreateAllBoolsUI(Vector2 position, DictionaryIntToModelGroupImportSettings importSettings, string valueName, string onFalseName = null, string onTrueName = null) { var type = typeof(ModelGroupImportSettings); var valueField = type.GetField(valueName); var onFalseField = onFalseName != null?type.GetField(onFalseName) : null; var onTrueField = onTrueName != null?type.GetField(onTrueName) : null; EditorGUI.showMixedValue = importSettings.Values.Any(setting => (bool)valueField.GetValue(setting)) && importSettings.Values.Any(setting => !(bool)valueField.GetValue(setting)); EditorGUI.BeginChangeCheck(); var newValue = EditorGUI.Toggle(new Rect(position, new Vector2(16, 16)), (bool)valueField.GetValue(importSettings[0])); if (EditorGUI.EndChangeCheck()) { foreach (var key in new List <int>(importSettings.Keys)) { valueField.SetValue(importSettings[key], newValue); } if (onFalseField != null && !newValue) { foreach (var key in new List <int>(importSettings.Keys)) { onFalseField.SetValue(importSettings[key], false); } } if (onTrueField != null && newValue) { foreach (var key in new List <int>(importSettings.Keys)) { onTrueField.SetValue(importSettings[key], true); } } } EditorGUI.showMixedValue = false; }
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(); }
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); }
/// <summary> /// Instantiate game objects for each brick in an LXFML-file /// </summary> /// <param name="lxfml">The LXFML-file</param> /// <param name="colliders">Add colliders to part</param> /// <param name="connectivity">Add connectivity to part</param> /// <param name="isStatic">Make the part static</param> /// <param name="lightmapped">Instantiate meshes with or without lightmap UVs</param> /// <param name="randomizeRotation">Slightly rotate rotation of part</param> /// <param name="preferLegacy">Choose legacy meshes if available</param> /// <param name="lod">Instantiate meshes of a certain LOD</param> /// <param name="resultBricks">Dictionary that contains brick component, using refID as key</param> /// <param name="groupNumber">If non-negative, only instantiate bricks from the specified group number</param> public static void InstantiateModelBricks(LXFMLDoc lxfml, DictionaryIntToModelGroupImportSettings importSettings, ref Dictionary <int, Brick> resultBricks, int groupNumber = -1) { for (var i = 0; i < lxfml.bricks.Count; ++i) { if (i % 200 == 0) { EditorUtility.DisplayProgressBar("Importing", "Creating bricks.", ((float)i / lxfml.bricks.Count) * 0.7f); } var brick = lxfml.bricks[i]; var group = FindGroup(lxfml, brick); // Discard bricks from other groups if group number is specified. if (groupNumber >= 0 && group != null && group.number != groupNumber) { continue; } // Determine whether or not to be static and to generate light map UVs. var brickStatic = (group != null ? importSettings[group.number].isStatic : false); var brickLightmapped = brickStatic && (group != null ? importSettings[group.number].lightmapped : false); var brickLod = (group != null ? importSettings[group.number].lod : 0); var brickGO = new GameObject(brick.designId, typeof(Brick)); var brickComp = brickGO.GetComponent <Brick>(); Undo.RegisterCreatedObjectUndo(brickGO, "Brick"); foreach (var part in brick.parts) { GameObject partToInstantiate = null; var partExistenceResult = PartUtility.UnpackPart(part.partDesignId, brickLightmapped, group != null ? importSettings[group.number].preferLegacy : false, brickLod); if (partExistenceResult.existence != PartUtility.PartExistence.None) { // FIXME Make a note of changed design ids. partToInstantiate = PartUtility.LoadPart(partExistenceResult.designID, brickLightmapped, partExistenceResult.existence == PartUtility.PartExistence.Legacy, brickLod); } if (partToInstantiate == null) { Debug.LogError("Missing part FBX -> " + partExistenceResult.designID); continue; } var partGO = Object.Instantiate(partToInstantiate); partGO.name = partToInstantiate.name; // Assign legacy, material IDs and set up references. var partComp = partGO.AddComponent <Part>(); partComp.designID = Convert.ToInt32(part.partDesignId); partComp.legacy = partExistenceResult.existence == PartUtility.PartExistence.Legacy; foreach (var material in part.materials) { partComp.materialIDs.Add(material.colorId); } partComp.brick = brickComp; brickComp.parts.Add(partComp); if (partExistenceResult.existence == PartUtility.PartExistence.New) { // FIXME Handle normal mapped model. InstantiateKnobsAndTubes(partComp, brickLightmapped, brickLod); } // Create collider and connectivity information. var brickColliders = (group != null ? importSettings[group.number].colliders : false); var brickConnectivity = brickColliders && (group != null ? importSettings[group.number].connectivity : false); if (brickColliders) { GameObject collidersToInstantiate = null; var collidersAvailable = PartUtility.UnpackCollidersForPart(partExistenceResult.designID); if (collidersAvailable) { collidersToInstantiate = PartUtility.LoadCollidersPrefab(partExistenceResult.designID); } if (collidersToInstantiate == null && partExistenceResult.existence != PartUtility.PartExistence.Legacy) { Debug.LogError("Missing part collider information -> " + partExistenceResult.designID); } if (collidersToInstantiate) { var collidersGO = Object.Instantiate(collidersToInstantiate); collidersGO.name = "Colliders"; collidersGO.transform.SetParent(partGO.transform, false); var colliderComps = collidersGO.GetComponentsInChildren <Collider>(); partComp.colliders.AddRange(colliderComps); } } if (brickConnectivity) { GameObject connectivityToInstantiate = null; var connectivityAvailable = PartUtility.UnpackConnectivityForPart(partExistenceResult.designID); if (connectivityAvailable) { connectivityToInstantiate = PartUtility.LoadConnectivityPrefab(partExistenceResult.designID); } if (connectivityToInstantiate == null && partExistenceResult.existence != PartUtility.PartExistence.Legacy) { Debug.LogError("Missing part connectivity information -> " + partExistenceResult.designID); } if (connectivityToInstantiate) { var connectivityGO = Object.Instantiate(connectivityToInstantiate); connectivityGO.name = "Connectivity"; connectivityGO.transform.SetParent(partGO.transform, false); var connectivityComp = connectivityGO.GetComponent <Connectivity>(); partComp.connectivity = connectivityComp; brickComp.totalBounds.Encapsulate(connectivityComp.extents); connectivityComp.part = partComp; foreach (var field in connectivityComp.connectionFields) { foreach (var connection in field.connections) { MatchConnectionWithKnob(connection, partComp.knobs); MatchConnectionWithTubes(connection, partComp.tubes); } } } } SetMaterials(partComp, part.materials, partExistenceResult.existence == PartUtility.PartExistence.Legacy); SetDecorations(partComp, part.decorations, partExistenceResult.existence == PartUtility.PartExistence.Legacy); SetStaticAndGIParams(partGO, brickStatic, brickLightmapped, true); // Set Position & Rotation SetPositionRotation(partGO, part); if (group != null ? importSettings[group.number].randomizeRotation : false) { RandomizeRotation(partComp, brickConnectivity); } // If first part, place brick at same position. if (brickGO.transform.childCount == 0) { brickGO.transform.position = partGO.transform.position; brickGO.transform.rotation = partGO.transform.rotation; brickGO.transform.localScale = Vector3.one; } partGO.transform.SetParent(brickGO.transform, true); if (!brickConnectivity) { var worldBounds = ComputeBounds(partGO.transform); worldBounds.SetMinMax(brickComp.transform.InverseTransformPoint(worldBounds.min), brickComp.transform.InverseTransformPoint(worldBounds.max)); brickComp.totalBounds.Encapsulate(worldBounds); } } // If all parts were missing, discard brick. if (brickGO.transform.childCount == 0) { Undo.DestroyObjectImmediate(brickGO); continue; } SetStaticAndGIParams(brickGO, brickStatic, brickLightmapped); // Assign uuid brickComp.designID = Convert.ToInt32(brick.designId); brickComp.uuid = brick.uuid; // Add LEGOAsset component. brickGO.AddComponent <LEGOAsset>(); resultBricks[brick.refId] = brickComp; } }
private static void CreateLODUI(Vector2 position, DictionaryIntToModelGroupImportSettings importSettings, int index) { importSettings[index].lod = EditorGUI.Popup(new Rect(position, new Vector2(64, 16)), importSettings[index].lod, lodOptions); }
public DictionaryIntToModelGroupImportSettings(DictionaryIntToModelGroupImportSettings dictionary) : base(dictionary) { }
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 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); // Assign bricks to group. foreach (var brick in resultBricks.Values) { brick.transform.SetParent(group.transform); } // 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(); }
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(); }