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(); } }
private void DrawMouldingColour(int colourID, int listIndex, bool multipleValues) { var position = EditorGUILayout.GetControlRect(); // Draw label position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), new GUIContent("Moulding Colour " + listIndex)); if (multipleValues) { // Create box and tooltip. GUI.Box(position, new GUIContent("", "Multiple colours selected")); var colorRect = new Rect(position.x + 1.0f, position.y + 1.0f, position.width - 2.0f, position.height - 2.0f); var lineRect = new Rect(position.x + 1.0f, position.y + 1.0f + colorRect.height / 2.0f, 10.0f, 1.0f); EditorGUI.DrawRect(colorRect, new Color32(209, 209, 209, 255)); EditorGUI.DrawRect(lineRect, Color.grey); } else { var mouldingColourID = (MouldingColour.Id)colourID; var colour = MouldingColour.GetColour(mouldingColourID); // Create box and tooltip. GUI.Box(position, new GUIContent("", ObjectNames.NicifyVariableName((int)mouldingColourID + " - " + mouldingColourID.ToString()))); // Draw rects with colour. var colorRect = new Rect(position.x + 1.0f, position.y + 1.0f, position.width - 2.0f, position.height - 2.0f - alphaBarHeight); var alphaRect = new Rect(position.x + 1.0f, position.y + 1.0f + colorRect.height, Mathf.Round((position.width - 2.0f) * colour.a), alphaBarHeight); var blackRect = new Rect(position.x + 1.0f + alphaRect.width, position.y + 1.0f + colorRect.height, position.width - 2.0f - alphaRect.width, alphaBarHeight); EditorGUI.DrawRect(colorRect, new Color(colour.r, colour.g, colour.b)); EditorGUI.DrawRect(alphaRect, Color.white); EditorGUI.DrawRect(blackRect, Color.black); } // Detect click. if (Event.current.type == EventType.MouseDown) { if (position.Contains(Event.current.mousePosition)) { MouldingColourPicker.Show((c) => { // Collect all parts to record for undo. foreach (var target in targets) { var brickTarget = (Brick)target; Undo.RegisterFullObjectHierarchyUndo(brickTarget.gameObject, "Changed Material"); int indexOffset = 0; foreach (var partTarget in brickTarget.parts) { if (indexOffset <= listIndex && listIndex < indexOffset + partTarget.materialIDs.Count) { Undo.RegisterFullObjectHierarchyUndo(partTarget.gameObject, "Changed Material"); break; } indexOffset += partTarget.materialIDs.Count; } } // Collect all parts to change the material. foreach (var target in targets) { var brickTarget = (Brick)target; int indexOffset = 0; foreach (var partTarget in brickTarget.parts) { if (indexOffset <= listIndex && listIndex < indexOffset + partTarget.materialIDs.Count) { // Update material ID. partTarget.materialIDs[listIndex - indexOffset] = (int)MouldingColour.GetId(c); // Collect all materials. LXFMLDoc.Brick.Part.Material[] materials = new LXFMLDoc.Brick.Part.Material[partTarget.materialIDs.Count]; for (var i = 0; i < partTarget.materialIDs.Count; ++i) { materials[i] = new LXFMLDoc.Brick.Part.Material() { colorId = partTarget.materialIDs[i], shaderId = 0 }; } // Update the part materials. ModelImporter.SetMaterials(partTarget, materials, partTarget.legacy); // Update knobs and tubes of this brick and the bricks it is connected to directly. var connectedBricks = partTarget.brick.GetConnectedBricks(false); connectedBricks.Add(partTarget.brick); foreach (var brick in connectedBricks) { foreach (var part in brick.parts) { if (!part.legacy && part.connectivity) { foreach (var connectionField in part.connectivity.connectionFields) { foreach (var connection in connectionField.connections) { connection.UpdateKnobsAndTubes(); } } } } } break; } indexOffset += partTarget.materialIDs.Count; } } // Collect all parts to record prefab instance modifications. foreach (var target in targets) { var brickTarget = (Brick)target; if (PrefabUtility.IsPartOfAnyPrefab(brickTarget.gameObject)) { PrefabUtility.RecordPrefabInstancePropertyModifications(brickTarget.gameObject); } int indexOffset = 0; foreach (var partTarget in brickTarget.parts) { if (indexOffset <= listIndex && listIndex < indexOffset + partTarget.materialIDs.Count) { if (PrefabUtility.IsPartOfAnyPrefab(partTarget.gameObject)) { PrefabUtility.RecordPrefabInstancePropertyModifications(partTarget.gameObject); } break; } indexOffset += partTarget.materialIDs.Count; } } }, false, false, true ); } } }
private static bool UpdateConnections(Brick[] bricks) { var updated = false; foreach (var brick in bricks) { if (PrefabUtility.IsPartOfPrefabInstance(brick)) { continue; } foreach (var part in brick.parts) { var designID = part.designID.ToString(); if (!PartUtility.CheckIfConnectivityForPartIsUnpacked(designID)) { PartUtility.UnpackConnectivityForPart(designID); } var connectivity = part.connectivity; if (!connectivity) { // Unsupported or legacy. continue; } if (connectivity.version == currentVersion) { // Already up to date. continue; } var connectivityToInstantiate = PartUtility.LoadConnectivityPrefab(designID); if (connectivityToInstantiate) { GameObject.DestroyImmediate(connectivity.gameObject, true); var connectivityGO = UnityEngine.Object.Instantiate(connectivityToInstantiate); connectivityGO.name = "Connectivity"; connectivityGO.transform.SetParent(part.transform, false); var connectivityComp = connectivityGO.GetComponent <Connectivity>(); part.connectivity = connectivityComp; part.brick.totalBounds.Encapsulate(connectivityComp.extents); connectivityComp.part = part; updated = true; foreach (var tube in part.tubes) { tube.connections.Clear(); tube.field = null; } foreach (var knob in part.knobs) { knob.field = null; knob.connectionIndex = -1; } foreach (var field in connectivityComp.connectionFields) { foreach (var connection in field.connections) { ModelImporter.MatchConnectionWithKnob(connection, part.knobs); ModelImporter.MatchConnectionWithTubes(connection, part.tubes); } } } } } return(updated); }
private void DrawMouldingColour(SerializedProperty property, GUIContent label) { var position = EditorGUILayout.GetControlRect(); // Draw label position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); if (property.hasMultipleDifferentValues) { // Create box and tooltip. GUI.Box(position, new GUIContent("", "Multiple colours selected")); var colorRect = new Rect(position.x + 1.0f, position.y + 1.0f, position.width - 2.0f, position.height - 2.0f); var lineRect = new Rect(position.x + 1.0f, position.y + 1.0f + colorRect.height / 2.0f, 10.0f, 1.0f); EditorGUI.DrawRect(colorRect, new Color32(209, 209, 209, 255)); EditorGUI.DrawRect(lineRect, Color.grey); } else { var mouldingColourId = (MouldingColour.Id)property.intValue; var colour = MouldingColour.GetColour(mouldingColourId); // Create box and tooltip. GUI.Box(position, new GUIContent("", ObjectNames.NicifyVariableName((int)mouldingColourId + " - " + mouldingColourId.ToString()))); // Draw rects with colour. var colorRect = new Rect(position.x + 1.0f, position.y + 1.0f, position.width - 2.0f, position.height - 2.0f - alphaBarHeight); var alphaRect = new Rect(position.x + 1.0f, position.y + 1.0f + colorRect.height, Mathf.Round((position.width - 2.0f) * colour.a), alphaBarHeight); var blackRect = new Rect(position.x + 1.0f + alphaRect.width, position.y + 1.0f + colorRect.height, position.width - 2.0f - alphaRect.width, alphaBarHeight); EditorGUI.DrawRect(colorRect, new Color(colour.r, colour.g, colour.b)); EditorGUI.DrawRect(alphaRect, Color.white); EditorGUI.DrawRect(blackRect, Color.black); } // Detect click. if (Event.current.type == EventType.MouseDown) { if (position.Contains(Event.current.mousePosition)) { MouldingColourPicker.Show((c) => { property.intValue = (int)MouldingColour.GetId(c); // Collect all materials. LXFMLDoc.Brick.Part.Material[] materials = new LXFMLDoc.Brick.Part.Material[materialIDsProp.arraySize]; for (var i = 0; i < materialIDsProp.arraySize; ++i) { materials[i] = new LXFMLDoc.Brick.Part.Material() { colorId = materialIDsProp.GetArrayElementAtIndex(i).intValue, shaderId = 0 }; } // Run through all targeted parts and record them for undo. foreach (var target in targets) { var partTarget = (Part)target; // Register state before updating materials. Undo.RegisterFullObjectHierarchyUndo(partTarget.gameObject, "Changed Material"); } // Run through all targeted parts and update them. foreach (var target in targets) { var partTarget = (Part)target; // Update the part materials. ModelImporter.SetMaterials(partTarget, materials, legacyProp.boolValue); // Apply the new colour to the serialized property. property.serializedObject.ApplyModifiedProperties(); // Update knobs and tubes of this brick and the bricks it is connected to directly. var connectedBricks = partTarget.brick.GetConnectedBricks(false); connectedBricks.Add(partTarget.brick); foreach (var brick in connectedBricks) { foreach (var part in brick.parts) { if (!part.legacy) { foreach (var connectionField in part.connectivity.connectionFields) { foreach (var connection in connectionField.connections) { connection.UpdateKnobsAndTubes(); } } } } } } }, false, false, true ); } } }