protected static void applyBrush(Vox.VoxelEditor editor, Ray mouseLocation) { byte opacity = byte.MaxValue; if (UnityEngine.Event.current.shift) { opacity = byte.MinValue; } Vector3 point = editor.getBrushPoint(mouseLocation); switch (editor.selectedBrush) { case 0: Vox.SphereModifier sphereMod = new Vox.SphereModifier(editor, point, editor.sphereBrushSize, new Vox.Voxel(editor.sphereBrushSubstance, opacity), true); sphereMod.overwriteShape = !editor.sphereSubstanceOnly; sphereMod.apply(); break; case 1: Vox.CubeModifier cubeMod = new Vox.CubeModifier(editor, point, editor.cubeBrushDimensions, new Vox.Voxel(editor.cubeBrushSubstance, opacity), true); cubeMod.overwriteShape = !editor.cubeSubstanceOnly; cubeMod.apply(); break; case 2: Vox.BlurModifier blur = new Vox.BlurModifier(editor, point, editor.smoothBrushSize, editor.smoothBrushStrength, true); blur.blurRadius = editor.smoothBrushBlurRadius; blur.apply(); break; } }
public void generateVoxels(Vox.VoxelEditor editor) { editor.wipe(); generationParameters.setTo(editor); editor.initialize(); switch (selectedGenerationMode) { case 0: editor.setToHeight(); break; case 1: editor.setToSphere(); break; case 2: editor.setToProcedural(); break; case 3: editor.heightmaps = generationParameters.heightmaps; editor.heightmapSubstances = generationParameters.heightmapSubstances; editor.setToHeightmap(); break; } editor.generateRenderers(); setupGeneration = false; }
public void OnSceneGUI() { Vox.VoxelEditor editor = (Vox.VoxelEditor)target; if (editor.selectedMode != 1) { return; } int controlId = GUIUtility.GetControlID(FocusType.Passive); switch (UnityEngine.Event.current.GetTypeForControl(controlId)) { case EventType.MouseDown: if (UnityEngine.Event.current.button == 0) { GUIUtility.hotControl = controlId; applyBrush(editor, HandleUtility.GUIPointToWorldRay(UnityEngine.Event.current.mousePosition)); UnityEngine.Event.current.Use(); } break; case EventType.MouseUp: if (UnityEngine.Event.current.button == 0) { GUIUtility.hotControl = 0; UnityEngine.Event.current.Use(); } break; case EventType.MouseMove: SceneView.RepaintAll(); break; } }
protected Vox.Mutator buildMutator(Vox.VoxelEditor editor, Vector3 point) { // check for subtraction mode byte opacity = byte.MaxValue; if (editor.isSubtracting()) { opacity = byte.MinValue; } // create mutator (and maybe apply) switch (editor.selectedBrush) { case 0: Vox.SphereMutator sphereMod = new Vox.SphereMutator(point, editor.sphereBrushSize, new Vox.Voxel(editor.sphereBrushSubstance, opacity)); sphereMod.overwriteShape = !editor.sphereSubstanceOnly; return(sphereMod); case 1: Vox.CubeMutator cubeMod = new Vox.CubeMutator(editor, point, editor.cubeBrushDimensions, new Vox.Voxel(editor.cubeBrushSubstance, opacity), true); cubeMod.overwriteShape = !editor.cubeSubstanceOnly; return(cubeMod); default: Vox.BlurMutator blurMod = new Vox.BlurMutator(editor, point, editor.smoothBrushSize, editor.smoothBrushStrength); blurMod.blurRadius = editor.smoothBrushBlurRadius; return(blurMod); } }
public override void OnInspectorGUI() { labelBigFont = new GUIStyle(GUI.skin.label); labelBigFont.margin = new RectOffset(labelBigFont.margin.left, labelBigFont.margin.right, labelBigFont.margin.top + 10, labelBigFont.margin.bottom); labelBigFont.fontSize = 16; foldoutBigFont = new GUIStyle(EditorStyles.foldout); foldoutBigFont.margin = new RectOffset(foldoutBigFont.margin.left, foldoutBigFont.margin.right, foldoutBigFont.margin.top + 10, foldoutBigFont.margin.bottom); foldoutBigFont.fontSize = 16; foldoutBigFont.alignment = TextAnchor.LowerLeft; buttonBigFont = new GUIStyle(GUI.skin.button); buttonBigFont.fontSize = 14; tabsBigFont = new GUIStyle(GUI.skin.button); tabsBigFont.fixedHeight = 30; Vox.VoxelEditor editor = (Vox.VoxelEditor)target; if (editor.generating()) { string label = "Generating Skin..."; EditorGUI.ProgressBar(GUILayoutUtility.GetRect(new GUIContent(label), GUI.skin.button), VoxelEditorProgressController.getGenerationProgress(editor), label); Repaint(); return; } serializedObject.Update(); if (setupGeneration) { doGenerationGUI(editor); return; } else { if (!editor.hasVoxelData()) { GUI.enabled = false; } editor.selectedMode = GUILayout.Toolbar(editor.selectedMode, modes, tabsBigFont, GUILayout.Height(30)); GUI.enabled = true; switch (editor.selectedMode) { case 0: doManageGUI(editor); break; case 1: doSculptGUI(editor); break; case 2: doMaskGUI(editor); break; } } // finally, apply the changes serializedObject.ApplyModifiedProperties(); }
public void setTo(Vox.VoxelEditor editor) { editor.baseSize = baseSize; editor.maxDetail = maxDetail; editor.createColliders = createColliders; editor.useStaticMeshes = useStaticMeshes; editor.saveMeshes = saveMeshes; editor.reduceMeshes = reduceMeshes; editor.reductionAmount = reductionAmount; editor.heightPercentage = heightPercentage; editor.spherePercentage = spherePercentage; }
protected void doMaskGUI(Vox.VoxelEditor editor) { editor.maskDisplayAlpha = doSliderFloatField("Mask Display Transparency", editor.maskDisplayAlpha, 0, 1); // mask list showMasks = doBigFoldout(showMasks, "Masks"); if (showMasks) { SerializedProperty voxelMasks = serializedObject.FindProperty("masks"); // EditorGUILayout.PropertyField(voxelMasks, new GUIContent("Sculpting Masks"), true); InspectorList.doArrayGUISimple(ref voxelMasks); } }
public void setFrom(Vox.VoxelEditor editor) { baseSize = editor.baseSize; maxDetail = editor.maxDetail; maxChange = editor.maxChange; proceduralSeed = editor.proceduralSeed; createColliders = editor.createColliders; useStaticMeshes = editor.useStaticMeshes; saveMeshes = editor.saveMeshes; reduceMeshes = editor.reduceMeshes; reductionAmount = editor.reductionAmount; heightPercentage = editor.heightPercentage; spherePercentage = editor.spherePercentage; }
public void OnSceneGUI() { Vox.VoxelEditor editor = (Vox.VoxelEditor)target; if (editor.selectedMode != 1) { return; } if (editor.pathPoints != null && editor.pathPoints.Length > 0 && editor.isSelectedBrushPathable() && editor.showPositionHandles) { for (int i = 0; i < editor.pathPoints.Length; ++i) { editor.pathPoints[i] = UnityEditor.Handles.PositionHandle(editor.pathPoints[i], Quaternion.identity); } } int controlId = GUIUtility.GetControlID(FocusType.Passive); switch (UnityEngine.Event.current.GetTypeForControl(controlId)) { case EventType.MouseDown: if (UnityEngine.Event.current.button == 0) { GUIUtility.hotControl = controlId; applyBrush(editor, HandleUtility.GUIPointToWorldRay(UnityEngine.Event.current.mousePosition)); UnityEngine.Event.current.Use(); } break; case EventType.MouseUp: if (UnityEngine.Event.current.button == 0) { GUIUtility.hotControl = 0; UnityEngine.Event.current.Use(); } break; case EventType.MouseMove: SceneView.RepaintAll(); break; case EventType.KeyDown: if (UnityEngine.Event.current.keyCode == KeyCode.Escape) { editor.pathPoints = null; } break; } }
protected void doGenerationGUI(Vox.VoxelEditor editor) { GUILayout.Label("Properties", labelBigFont); doTreeSizeGUI(generationParameters); // general properties doGeneralPropertiesGUI(generationParameters); // substances doSubstancesGUI(serializedObject); // generation mode GUILayout.Label("Generation Mode", labelBigFont); selectedGenerationMode = GUILayout.Toolbar(selectedGenerationMode, generationModes); switch (selectedGenerationMode) { case 0: doFlatGenerationGUI(); break; case 1: doSphereGenerationGUI(); break; case 2: doProceduralGenerationGUI(); break; case 3: doHeightmapGenerationGUI(); break; } // confirmation GUILayout.Label("Confirmation", labelBigFont); if (GUILayout.Button("Generate", buttonBigFont) && validateSubstances(editor)) { if (EditorUtility.DisplayDialog("Generate Voxels?", "Are you sure you want to generate the voxel terain from scratch? Any previous work will be overriden.", "Generate", "Cancel")) { generateVoxels(editor); } } if (GUILayout.Button("Cancel Generation", buttonBigFont)) { setupGeneration = false; } EditorGUILayout.Separator(); }
public static VoxelEditor createEmpty() { GameObject ob = new GameObject(); ob.name = "Voxel Object"; VoxelEditor editor = ob.AddComponent <VoxelEditor>(); editor.voxelSubstances = new VoxelSubstance[1]; VoxelSubstance sub = new VoxelSubstance("Base", UnityEditor.AssetDatabase.LoadAssetAtPath <Material>(DEFAULT_MATERIAL_PATH), UnityEditor.AssetDatabase.LoadAssetAtPath <Material>(DEFAULT_BLEND_MATERIAL_PATH), UnityEditor.AssetDatabase.LoadAssetAtPath <PhysicMaterial>(DEFAULT_PHYSICS_MATERIAL_PATH)); editor.voxelSubstances[0] = sub; return(editor); }
protected void doGeneralPropertiesGUI(Vox.VoxelEditor editor) { editor.createColliders = EditorGUILayout.Toggle(new GUIContent("Generate Colliders"), editor.createColliders); editor.useStaticMeshes = EditorGUILayout.Toggle(new GUIContent("Use Static Meshes"), editor.useStaticMeshes); editor.saveMeshes = EditorGUILayout.Toggle(new GUIContent("Save Meshes To Scene"), editor.saveMeshes); editor.reduceMeshes = EditorGUILayout.Toggle(new GUIContent("Reduce Meshes"), editor.reduceMeshes); if (editor.reduceMeshes) { editor.reductionAmount = doSliderFloatField("Mesh Reduction Level", editor.reductionAmount, 0, 0.5f); } //editor.maxDetail = (byte)EditorGUILayout.IntField(new GUIContent("Voxel Power"), editor.maxDetail); // if (createColliders != editor.createColliders || useStaticMeshes != editor.useStaticMeshes) { // editor.createColliders = createColliders; // editor.useStaticMeshes = useStaticMeshes; // editor.generateRenderers(); // } }
protected bool validateSubstances(Vox.VoxelEditor editor) { if (editor.voxelSubstances == null || editor.voxelSubstances.Length < 1) { EditorUtility.DisplayDialog("Invalid Substances", "There must be at least one voxel substance defined to generate the voxel object.", "OK"); return(false); } int i = 1; foreach (Vox.VoxelSubstance sub in editor.voxelSubstances) { if (sub.renderMaterial == null || sub.blendMaterial == null) { EditorUtility.DisplayDialog("Invalid Substance", "Substance " + i + ", " + sub.name + ", must have a render material and a blend material set.", "OK"); return(false); } ++i; } return(true); }
protected void applyBrush(Vox.VoxelEditor editor, Ray mouseLocation) { // get point clicked on System.Nullable <Vector3> point = editor.getBrushPoint(mouseLocation); if (point == null) { return; } // check if control pressed. If so, add point to pathList if (editor.isPathing()) { editor.addPathPoint(point.Value); return; } // check for showPositionHandles if (editor.showPositionHandles && editor.isSelectedBrushPathable() && editor.pathPoints != null && editor.pathPoints.Length > 0) { return; } // create mutator Vox.Mutator mutator = buildMutator(editor, point.Value); // apply mutator if (mutator == null) { return; } Vox.LocalMutator localMutator = mutator as Vox.LocalMutator; if (localMutator != null && editor.pathPoints != null && editor.pathPoints.Length > 0) { editor.addPathPoint(point.Value); mutator = new Vox.LineMutator(editor.pathPoints, localMutator); editor.pathPoints = null; } mutator.apply(editor); }
protected void doTreeSizeGUI(Vox.VoxelEditor editor) { // world detail EditorGUILayout.LabelField("Voxel Power", editor.maxDetail.ToString()); long dimension = 1 << editor.maxDetail; ++EditorGUI.indentLevel; EditorGUILayout.LabelField("Voxels Per Side", dimension.ToString(numFormInt)); EditorGUILayout.LabelField("Max Voxel Count", Mathf.Pow(dimension, 3).ToString(numFormInt)); --EditorGUI.indentLevel; EditorGUILayout.Separator(); // world dimension EditorGUILayout.LabelField("World Size (m)", editor.baseSize.ToString()); ++EditorGUI.indentLevel; EditorGUILayout.LabelField("World Area", Mathf.Pow(editor.baseSize / 1000, 2).ToString(numForm) + " square km"); EditorGUILayout.LabelField("World Volume", Mathf.Pow(editor.baseSize / 1000, 3).ToString(numForm) + " cubic km"); --EditorGUI.indentLevel; EditorGUILayout.Separator(); EditorGUILayout.LabelField("Voxel Size", (editor.baseSize / dimension).ToString(numForm) + " m"); EditorGUILayout.Separator(); }
protected static float maxBrushSize(Vox.VoxelEditor editor) { return(Mathf.Max(editor.voxelSize() * 20, 50)); }
protected void doSculptGUI(Vox.VoxelEditor editor) { // brush ghost editor.ghostBrushAlpha = doSliderFloatField("Brush Ghost Opacity", editor.ghostBrushAlpha, 0, 1); editor.gridEnabled = EditorGUILayout.Toggle("Snap to Grid", editor.gridEnabled); if (editor.gridEnabled) { ++EditorGUI.indentLevel; editor.gridUseVoxelUnits = EditorGUILayout.Toggle("Use Voxel Units", editor.gridUseVoxelUnits); if (editor.gridUseVoxelUnits) { float voxelSize = editor.baseSize / (1 << editor.maxDetail); editor.gridSize = EditorGUILayout.FloatField("Grid Spacing (Voxels)", editor.gridSize / voxelSize) * voxelSize; } else { editor.gridSize = EditorGUILayout.FloatField("Grid Spacing (Meters)", editor.gridSize); } --EditorGUI.indentLevel; } // brush list GUILayout.Label("Brush", labelBigFont); editor.selectedBrush = GUILayout.Toolbar(editor.selectedBrush, brushes, GUILayout.MinHeight(20)); // brush substance type string[] substances = new string[editor.voxelSubstances.Length]; for (int i = 0; i < substances.Length; ++i) { substances[i] = editor.voxelSubstances[i].name; } // brush size switch (editor.selectedBrush) { case 0: GUILayout.Label("Hold 'Shift' to subtract."); editor.sphereBrushSize = doSliderFloatField("Sphere Radius (m)", editor.sphereBrushSize, 0, 100); editor.sphereSubstanceOnly = GUILayout.Toggle(editor.sphereSubstanceOnly, "Change Substance Only"); GUILayout.Label("Substance", labelBigFont); editor.sphereBrushSubstance = (byte)GUILayout.SelectionGrid(editor.sphereBrushSubstance, substances, 1); break; case 1: GUILayout.Label("Hold 'Shift' to subtract."); GUILayout.BeginHorizontal(); GUILayout.Label("Dimensions (m)"); editor.cubeBrushDimensions.x = EditorGUILayout.FloatField(editor.cubeBrushDimensions.x); editor.cubeBrushDimensions.y = EditorGUILayout.FloatField(editor.cubeBrushDimensions.y); editor.cubeBrushDimensions.z = EditorGUILayout.FloatField(editor.cubeBrushDimensions.z); // SerializedProperty cubeBrushDimensions = ob.FindProperty("cubeBrushDimensions"); // EditorGUILayout.PropertyField(cubeBrushDimensions, new GUIContent("Rectangle Brush Dimensions"), true); GUILayout.EndHorizontal(); editor.cubeSubstanceOnly = GUILayout.Toggle(editor.cubeSubstanceOnly, "Change Substance Only"); GUILayout.Label("Substance", labelBigFont); editor.cubeBrushSubstance = (byte)GUILayout.SelectionGrid(editor.cubeBrushSubstance, substances, 1); break; case 2: editor.smoothBrushSize = doSliderFloatField("Radius (m)", editor.smoothBrushSize, 0, 100); editor.smoothBrushStrength = doSliderFloatField("Strength", editor.smoothBrushStrength, 0, 5); editor.smoothBrushBlurRadius = EditorGUILayout.IntField("Blur Radius", editor.smoothBrushBlurRadius); break; } }
protected void doManageGUI(Vox.VoxelEditor editor) { // actions GUILayout.Label("Actions", labelBigFont); if (GUILayout.Button("Generate New")) { setupGeneration = true; generationParameters = new VoxelEditorParameters(); generationParameters.setFrom(editor); } if (editor.hasVoxelData()) { if (GUILayout.Button("Erase")) { if (EditorUtility.DisplayDialog("Erase Voxels?", "Are you sure you want to erase all voxel data?", "Erase", "Cancel")) { editor.wipe(); } } if (GUILayout.Button(editor.hasRenderers()? "Reskin": "Skin", buttonBigFont) && validateSubstances(editor)) { editor.generateRenderers(); } if (editor.hasRenderers() && GUILayout.Button("Clear Skin") && validateSubstances(editor)) { editor.clearRenderers(); } if (GUILayout.Button("Export")) { editor.export(EditorUtility.SaveFilePanel("Choose File to Export To", "", "Voxels", "vox")); } } if (GUILayout.Button("Import")) { if (!editor.import(EditorUtility.OpenFilePanel("Choose File to Import From", "", "vox"))) { EditorUtility.DisplayDialog("Wrong Voxel Format", "The file you chose was an unknown or incompatible voxel format version.", "OK"); } } if (!editor.hasVoxelData()) { return; } GUILayout.Label("Properties", labelBigFont); doGeneralPropertiesGUI(editor); // TODO: implement LOD and uncomment this // // LOD // SerializedProperty useLod = ob.FindProperty("useLod"); // EditorGUILayout.PropertyField(useLod, new GUIContent("Use Level of Detail")); // if (useLod.boolValue) { // ++EditorGUI.indentLevel; // SerializedProperty lodDetail = ob.FindProperty("lodDetail"); // EditorGUILayout.PropertyField(lodDetail, new GUIContent("Target Level of Detail")); // if (lodDetail.floatValue > 1000) // lodDetail.floatValue = 1000; // else if (lodDetail.floatValue < 0.1f) // lodDetail.floatValue = 0.1f; // // SerializedProperty curLodDetail = ob.FindProperty("curLodDetail"); // if (Application.isPlaying) { // EditorGUILayout.PropertyField(curLodDetail, new GUIContent("Current Level of Detail")); // } else { // EditorGUILayout.PropertyField(curLodDetail, new GUIContent("Starting Level of Detail")); // } // // if (curLodDetail.floatValue > 1000) // curLodDetail.floatValue = 1000; // else if (curLodDetail.floatValue < 0.1f) // curLodDetail.floatValue = 0.1f; // --EditorGUI.indentLevel; // } // do substances doSubstancesGUI(serializedObject); // show statistics showStatistics = doBigFoldout(showStatistics, "Statistics"); if (showStatistics) { EditorGUILayout.LabelField("Chunk Count: " + editor.renderers.Count); doTreeSizeGUI(editor); EditorGUILayout.LabelField("Vertex Count: " + editor.vertexCount); EditorGUILayout.LabelField("Triangle Count: " + editor.triangleCount); } }
protected void doSculptGUI(Vox.VoxelEditor editor) { // brush ghost editor.ghostBrushAlpha = doSliderFloatField("Brush Ghost Opacity", editor.ghostBrushAlpha, 0, 1); editor.gridEnabled = EditorGUILayout.Toggle("Snap to Grid", editor.gridEnabled); if (editor.gridEnabled) { ++EditorGUI.indentLevel; editor.gridUseVoxelUnits = EditorGUILayout.Toggle("Use Voxel Units", editor.gridUseVoxelUnits); if (editor.gridUseVoxelUnits) { float voxelSize = editor.baseSize / (1 << editor.maxDetail); editor.gridSize = EditorGUILayout.FloatField("Grid Spacing (Voxels)", editor.gridSize / voxelSize) * voxelSize; } else { editor.gridSize = EditorGUILayout.FloatField("Grid Spacing (Meters)", editor.gridSize); } --EditorGUI.indentLevel; } // brush list GUILayout.Label("Brush", labelBigFont); editor.selectedBrush = GUILayout.Toolbar(editor.selectedBrush, brushes, GUILayout.MinHeight(20)); // brush substance type string[] substances = new string[editor.voxelSubstances.Length]; for (int i = 0; i < substances.Length; ++i) { substances[i] = editor.voxelSubstances[i].name; } // brush size switch (editor.selectedBrush) { case 0: GUILayout.Label("Hold 'Shift' to subtract."); editor.sphereBrushSize = doSliderFloatField("Sphere Radius (m)", editor.sphereBrushSize, 0, maxBrushSize(editor)); editor.sphereSubstanceOnly = GUILayout.Toggle(editor.sphereSubstanceOnly, "Change Substance Only"); GUILayout.Label("Substance", labelBigFont); editor.sphereBrushSubstance = (byte)GUILayout.SelectionGrid(editor.sphereBrushSubstance, substances, 1); break; case 1: GUILayout.Label("Hold 'Shift' to subtract."); GUILayout.BeginHorizontal(); GUILayout.Label("Dimensions (m)"); editor.cubeBrushDimensions.x = EditorGUILayout.FloatField(editor.cubeBrushDimensions.x); editor.cubeBrushDimensions.y = EditorGUILayout.FloatField(editor.cubeBrushDimensions.y); editor.cubeBrushDimensions.z = EditorGUILayout.FloatField(editor.cubeBrushDimensions.z); GUILayout.EndHorizontal(); editor.cubeSubstanceOnly = GUILayout.Toggle(editor.cubeSubstanceOnly, "Change Substance Only"); GUILayout.Label("Substance", labelBigFont); editor.cubeBrushSubstance = (byte)GUILayout.SelectionGrid(editor.cubeBrushSubstance, substances, 1); break; case 2: editor.smoothBrushSize = doSliderFloatField("Radius (m)", editor.smoothBrushSize, 0, maxBrushSize(editor)); editor.smoothBrushStrength = doSliderFloatField("Strength", editor.smoothBrushStrength, 0, 5); editor.smoothBrushBlurRadius = EditorGUILayout.IntField("Blur Radius", editor.smoothBrushBlurRadius); break; } // PATH GUI if (editor.selectedBrush != 0 && editor.selectedBrush != 1) { return; } GUILayout.Label("Path Tool", labelBigFont); if (editor.pathPoints != null && editor.pathPoints.Length > 0) { GUILayout.Label("Hold 'Control' to place another point."); editor.showPositionHandles = GUILayout.Toggle(editor.showPositionHandles, "Show drag handles (disable click to complete)."); SerializedProperty prop = serializedObject.FindProperty("pathPoints"); InspectorList.doArrayGUISimple(ref prop); serializedObject.ApplyModifiedProperties(); if (GUILayout.Button("Clear Path")) { editor.pathPoints = null; } else if (GUILayout.Button("Apply Path")) { Vox.LocalMutator mut = (Vox.LocalMutator)buildMutator(editor, editor.pathPoints[0]); if (editor.pathPoints.Length > 1) { new Vox.LineMutator(editor.pathPoints, mut).apply(editor); } else { mut.apply(editor); } } } else { GUILayout.Label("Hold 'Control' to start a path."); if (GUILayout.Button("Start Path")) { editor.addPathPoint(editor.transform.position); } } }