/// <summary> /// Generates the surfaces which in turn create the meshes /// </summary> /// <param name='OnIteration'> /// Delegate for showing progress bar on each iteration in the editor /// </param> public void Generate(Action OnIteration, bool loadModule) { if (loadModule) { LoadModule(); } if (terrain != null) { // global maps if (textureNodeInstances == null) { textureNodeInstances = new Planet.TextureNodeInstance[0]; } if (textureNodeInstances.Length != terrain.textureNodes.Count) { Planet.TextureNodeInstance[] newInstances = new Planet.TextureNodeInstance[terrain.textureNodes.Count]; for (int i = 0; i < terrain.textureNodes.Count; i++) { bool createNewInstance = true; if (i < textureNodeInstances.Length) { if (textureNodeInstances[i] != null) { newInstances[i] = textureNodeInstances[i]; createNewInstance = false; } } if (createNewInstance) { newInstances[i] = new Planet.TextureNodeInstance(terrain.textureNodes[i]); } } textureNodeInstances = newInstances; } for (int i = 0; i < textureNodeInstances.Length; i++) { textureNodeInstances[i].node = terrain.textureNodes[i]; if (textureNodeInstances[i].generateGlobalMap) { GenerateGlobalMaps(textureNodeInstances[i]); } } // initialize modifiers if not existing already if (!modifiersInitialized) { modifiersInitialized = true; ClearModifiers(); } // destroy already existing surfaces before creating new ones ClearSurfaces(); // plot vertex positions for all surfaces float step = 2f / subdivisions; float half = subdivisions / 2f * step; id = 0; if (subdivisions > 0) { for (int sY = 0; sY < subdivisions; sY++) { float y = sY * step; float ny = (sY + 1) * step; for (int sX = 0; sX < subdivisions; sX++) { float x = sX * step; float nx = (sX + 1) * step; for (int i = 0; i < 6; i++) { CreateSurface(x, half, y, nx, ny, (SurfacePosition)i, sX, sY); if (OnIteration != null) { OnIteration(); } } } } } } }
override public void OnInspectorGUI() { serializedObject.Update(); // toolbar EditorGUILayout.Space(); currentTab = (Tab)GUILayout.Toolbar((int)currentTab, tabTexts, EditorStyles.toolbarButton); switch (currentTab) { case Tab.GENERATION: EditorGUILayout.Space(); EditorGUILayout.LabelField("Terrain Module:", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); terrainAsset.objectReferenceValue = EditorGUILayout.ObjectField(terrainAsset.objectReferenceValue, typeof(TextAsset), false); if (GUILayout.Button("Edit Module", GUILayout.Width(90f))) { ModuleEditorWindow.Init(); ((ModuleEditorWindow)ModuleEditorWindow.window).Load((TextAsset)terrainAsset.objectReferenceValue, planet); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Frequency scale:"); frequencyScale.floatValue = EditorGUILayout.FloatField(frequencyScale.floatValue); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUILayout.LabelField("Mesh Settings", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Radius:"); radius.floatValue = EditorGUILayout.FloatField(radius.floatValue); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Height variation:"); heightVariation.floatValue = EditorGUILayout.FloatField(heightVariation.floatValue); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Mesh resolution:"); meshResolution.intValue = EditorGUILayout.IntField(meshResolution.intValue); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Subdivisions:"); subdivisions.intValue = EditorGUILayout.IntField(subdivisions.intValue); EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); generateOnStart.boolValue = EditorGUILayout.Toggle("Generate on start", generateOnStart.boolValue); if (generateOnStart.boolValue) { randomizeSeeds.boolValue = EditorGUILayout.Toggle("Randomize seeds", randomizeSeeds.boolValue); } else { randomizeSeeds.boolValue = false; } EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Random seed:"); seed.floatValue = EditorGUILayout.FloatField(seed.floatValue); if (GUILayout.Button("Rnd", GUILayout.Width(90f))) { seed.floatValue = (float)UnityEngine.Random.Range(-1000f, 1000f); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Generate now")) { //Undo.RegisterFullObjectHierarchyUndo(planet.gameObject);//, "Generate planet"); Generate(planet); } if (GUILayout.Button("Clear")) { //Undo.RegisterFullObjectHierarchyUndo(planet.gameObject);//, "Clear surfaces"); planet.ClearSurfaces(); } // COLLIDERS EditorGUILayout.Space(); EditorGUILayout.LabelField("Colliders", EditorStyles.boldLabel); EditorGUILayout.HelpBox("Lower level colliders are automatically disabled when a higher level collider is generated.", MessageType.Info); showColliderTab = EditorGUILayout.Foldout(showColliderTab, "Show"); if (showColliderTab) { EditorGUILayout.LabelField("Level 0:"); planet.generateColliders[0] = EditorGUILayout.Toggle("Generate colliders", planet.generateColliders[0]); //planet.disableCollidersOnSubdivision[0] = EditorGUILayout.Toggle("Disable when subdividing", planet.disableCollidersOnSubdivision[0]); if (planet.useLod) { for (int i = 0; i < planet.lodDistances.Length; i++) { EditorGUILayout.LabelField("Level " + (i + 1).ToString() + ":"); planet.generateColliders[i + 1] = EditorGUILayout.Toggle("Generate colliders", planet.generateColliders[i + 1]); //planet.disableCollidersOnSubdivision[i+1] = EditorGUILayout.Toggle("Disable when subdividing", planet.disableCollidersOnSubdivision[i+1]); } } } // EXPORT EditorGUILayout.Space(); EditorGUILayout.LabelField("Export", EditorStyles.boldLabel); EditorGUILayout.HelpBox("Creates a prefab with current settings. Also saves meshes and material to disc if they have been generated.", MessageType.Info); if (GUILayout.Button("Save to Assets")) { string path = EditorUtility.SaveFilePanelInProject("Select Folder", "", "", ""); if (path != "") { Material mat = null; Surface[] surfaces = planet.GetComponentsInChildren <Surface>(true); for (int i = 0; i < surfaces.Length; i++) { if (surfaces[i].mesh != null) { AssetDatabase.CreateAsset(surfaces[i].mesh, path + surfaces[i].name.ToString() + "_" + i.ToString() + ".asset"); if (mat == null) { mat = surfaces[i].renderer.sharedMaterial; AssetDatabase.CreateAsset(mat, path + surfaces[i].name.ToString() + "Material.mat"); } } } PrefabUtility.CreatePrefab(path + ".prefab", planet.gameObject); AssetDatabase.SaveAssets(); } } break; case Tab.LOD: // LOD EditorGUILayout.Space(); EditorGUILayout.LabelField("LOD", EditorStyles.boldLabel); planet.useLod = EditorGUILayout.Toggle("Use LOD", planet.useLod); if (planet.useLod) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("LOD target:"); lodTarget.objectReferenceValue = EditorGUILayout.ObjectField(lodTarget.objectReferenceValue, typeof(Transform), true); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("LOD levels:"); planet.maxLodLevel = EditorGUILayout.IntField(planet.maxLodLevel); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Level loading distances:"); EditorGUILayout.EndHorizontal(); for (int i = 0; i < planet.lodDistances.Length; i++) { planet.lodDistances[i] = EditorGUILayout.FloatField("Level " + (i + 1).ToString() + ":", planet.lodDistances[i]); } EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Minimum angle (planet-viewer dot planet-surface):"); EditorGUILayout.EndHorizontal(); for (int i = 0; i < planet.lodDots.Length; i++) { planet.lodDots[i] = EditorGUILayout.FloatField("Dot angle " + (i + 1).ToString() + ":", planet.lodDots[i]); } EditorGUILayout.Space(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField("Performance:", EditorStyles.boldLabel); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("LOD update interval:"); lodUpdateInterval.floatValue = EditorGUILayout.FloatField(lodUpdateInterval.floatValue); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Simultaneous subdivisions:"); simultaneousSubdivisions.intValue = EditorGUILayout.IntField(simultaneousSubdivisions.intValue); EditorGUILayout.EndHorizontal(); useAngleCulling.boolValue = EditorGUILayout.Toggle("Use angle culling:", useAngleCulling.boolValue); if (useAngleCulling.boolValue) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Renderer culling angle:"); rendererCullingAngle.floatValue = EditorGUILayout.FloatField(rendererCullingAngle.floatValue); EditorGUILayout.EndHorizontal(); } createBorders.boolValue = EditorGUILayout.Toggle("Create surface skirts", createBorders.boolValue); logGenerationTimes.boolValue = EditorGUILayout.Toggle("Log generation times", logGenerationTimes.boolValue); showDebug.boolValue = EditorGUILayout.Toggle("Show LOD debug", showDebug.boolValue); } break; case Tab.PAINTING: if (planet.uv1type != Planet.UV.CONTINUOUS) { EditorGUILayout.HelpBox("Terrain painting requires UV1 type to be Continuous in the SHADER tab during painting, switch to it and regenerate.", MessageType.Warning); } EditorGUILayout.LabelField("Brush settings", EditorStyles.boldLabel); planet.useBrushTexture = EditorGUILayout.Toggle("Use brush texture:", planet.useBrushTexture); if (planet.useBrushTexture) { planet.brushTexture = (Texture2D)EditorGUILayout.ObjectField(planet.brushTexture, typeof(Texture2D), false, GUILayout.Width(64), GUILayout.Height(64)); planet.useBrushAlpha = EditorGUILayout.Toggle("Use alpha value:", planet.useBrushAlpha); EditorGUILayout.HelpBox("Brush texture must be Read/Write enabled in the texture import settings", MessageType.Info); } EditorGUILayout.LabelField("Brush mode:"); planet.brushMode = (Planet.BrushMode)GUILayout.Toolbar((int)planet.brushMode, brushTexts, EditorStyles.toolbarButton); planet.brushSize = EditorGUILayout.Slider("Brush size", planet.brushSize, 0.001f, .5f); planet.brushStrength = EditorGUILayout.Slider("Brush strength", planet.brushStrength, 0f, 1f); switch (planet.brushMode) { case Planet.BrushMode.SET: planet.brushSetValue = EditorGUILayout.Slider("Set to", planet.brushSetValue, planet.lowLimit, planet.highLimit); break; } planet.brushFalloff = EditorGUILayout.Toggle("Use fall off:", planet.brushFalloff); if (planet.brushFalloff) { planet.falloff = EditorGUILayout.CurveField("Brush falloff", planet.falloff); } planet.lowLimit = EditorGUILayout.FloatField("Low limit", planet.lowLimit); planet.highLimit = EditorGUILayout.FloatField("High limit", planet.highLimit); EditorGUILayout.Space(); EditorGUILayout.LabelField("Options", EditorStyles.boldLabel); planet.modifierResolution = EditorGUILayout.IntField("Painting resolution", planet.modifierResolution); planet.useBicubicInterpolation = EditorGUILayout.Toggle("Use bicubic interpolation:", planet.useBicubicInterpolation); if (GUILayout.Button("Clear all")) { planet.ClearModifiers(); Generate(planet); } break; case Tab.SHADER: EditorGUILayout.LabelField("Terrain material:"); planet.terrainMaterial = (Material)EditorGUILayout.ObjectField(planet.terrainMaterial, typeof(Material), false); EditorGUILayout.Space(); EditorGUILayout.LabelField("UVs", EditorStyles.boldLabel); planet.uv1type = (Planet.UV)EditorGUILayout.EnumPopup("UV1 type:", planet.uv1type); planet.uv2 = EditorGUILayout.Toggle("Generate UV2:", planet.uv2); if (planet.uv2) { planet.uv2type = (Planet.UV)EditorGUILayout.EnumPopup("UV2 type:", planet.uv2type); } EditorGUILayout.HelpBox("Default shaders use Continuous UV1 for splat texturing. Global maps use Spherical UV2 and Surface textures use Surface UV2.", MessageType.Info); EditorGUILayout.Space(); EditorGUILayout.LabelField("Texture generation", EditorStyles.boldLabel); EditorGUILayout.HelpBox("Texture nodes from the module file will appear here.", MessageType.Info); if (planet.Terrain != null) { if (planet.textureNodeInstances == null) { planet.textureNodeInstances = new Planet.TextureNodeInstance[0]; } if (planet.textureNodeInstances.Length != planet.Terrain.textureNodes.Count) { Planet.TextureNodeInstance[] newInstances = new Planet.TextureNodeInstance[planet.Terrain.textureNodes.Count]; for (int i = 0; i < planet.Terrain.textureNodes.Count; i++) { bool createNewInstance = true; if (i < planet.textureNodeInstances.Length) { if (planet.textureNodeInstances[i] != null) { newInstances[i] = planet.textureNodeInstances[i]; createNewInstance = false; } } if (createNewInstance) { newInstances[i] = new Planet.TextureNodeInstance(planet.Terrain.textureNodes[i]); } } planet.textureNodeInstances = newInstances; } for (int i = 0; i < planet.textureNodeInstances.Length; i++) { Planet.TextureNodeInstance tni = planet.textureNodeInstances[i]; EditorGUILayout.LabelField(tni.node.textureId, EditorStyles.boldLabel); EditorGUILayout.LabelField("Material property name:"); tni.materialPropertyName = EditorGUILayout.TextField(tni.materialPropertyName); tni.generateSurfaceTextures = EditorGUILayout.Toggle("Generate surface textures:", tni.generateSurfaceTextures); if (tni.generateSurfaceTextures) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Texture resolution:"); planet.textureResolution = EditorGUILayout.IntField(planet.textureResolution); EditorGUILayout.EndHorizontal(); } tni.generateGlobalMap = EditorGUILayout.Toggle("Generate global map:", tni.generateGlobalMap); if (tni.generateGlobalMap) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Global map width:"); tni.globalMapSize = EditorGUILayout.IntField(tni.globalMapSize); EditorGUILayout.EndHorizontal(); } if (GUILayout.Button("Save GlobalMap")) { for (int ii = 0; ii < planet.textureNodeInstances.Length; ii++) { planet.textureNodeInstances[ii].node = planet.Terrain.textureNodes[ii]; } string savepath = EditorUtility.SaveFilePanel("Export texture", Application.dataPath, tni.materialPropertyName, ""); if (savepath.Length != 0) { float progress = 1; float total = 2; EditorUtility.DisplayProgressBar("Planet generator", "Generating texture...", progress / total); Texture2D texture = GlobalMapUtility.Generate(tni.globalMapSize, tni.node.GetModule()); progress++; EditorUtility.DisplayProgressBar("Planet generator", "Saving texture...", progress / total); File.WriteAllBytes(savepath + ".png", texture.EncodeToPNG()); EditorUtility.ClearProgressBar(); AssetDatabase.Refresh(); } } EditorGUILayout.Space(); } if (planet.Terrain.textureNodes.Count == 0) { EditorGUILayout.LabelField("Module has no texture outputs defined.", EditorStyles.label); } } EditorGUILayout.HelpBox("Surface textures are generated for each surface. Global maps are generated once during start.", MessageType.Info); break; } EditorGUILayout.Space(); serializedObject.ApplyModifiedProperties(); }