public override void OnInspectorGUI() { if (!isVisible) { return; } bool forceUpdate = false; Material targetMat = target as Material; string[] originalKeywords = targetMat.shaderKeywords; //Set default values when the material is newly created if (originalKeywords.Length == 0) { originalKeywords = defaultKeywords; targetMat.shaderKeywords = defaultKeywords; EditorUtility.SetDirty(targetMat); } //Grass type int grassType = -1; for (int i = 0; i < grassTypeLabels.Length; i++) { if (originalKeywords.Contains(grassTypeString[i])) { grassType = i; break; } } if (grassType < 0) { grassType = defaultGrassType; forceUpdate = true; } //Lighting mode int lightingMode = -1; for (int i = 0; i < lightingModeLabels.Length; i++) { if (originalKeywords.Contains(lightingModes[i])) { lightingMode = i; break; } } if (lightingMode < 0) { lightingMode = defaultLightingMode; forceUpdate = true; } //Density mode var densityMode = GrassEditorUtility.GetDensityMode(targetMat); bool ignoreGISpecular = originalKeywords.Contains("GRASS_IGNORE_GI_SPECULAR"); bool widthSmoothing = originalKeywords.Contains("GRASS_WIDTH_SMOOTHING"); bool heightSmoothing = originalKeywords.Contains("GRASS_HEIGHT_SMOOTHING"); bool objectMode = originalKeywords.Contains("GRASS_OBJECT_MODE"); bool topViewCompensation = originalKeywords.Contains("GRASS_TOP_VIEW_COMPENSATION"); bool surfaceNormal = originalKeywords.Contains("GRASS_FOLLOW_SURFACE_NORMAL"); bool useTextureAtlas = originalKeywords.Contains("GRASS_USE_TEXTURE_ATLAS"); bool grassRandomDirection = originalKeywords.Contains("GRASS_RANDOM_DIR"); bool calcGlobalWind = originalKeywords.Contains("GRASS_CALC_GLOBAL_WIND"); //Grass painter if (Selection.activeObject == null || AssetDatabase.Contains(Selection.activeObject)) { EditorGUILayout.LabelField("To open the grass painter, select a scene object with a grass material."); EditorGUILayout.LabelField("For Unity Terrain you can open it from Window > Stix Games > GrassPainter"); } else { if (GUILayout.Button("Open Grass Painter")) { GrassPainterWindow.OpenWindow(); } } EditorGUILayout.Space(); EditorGUI.BeginChangeCheck(); EditorGUILayout.LabelField("Shader Variants", EditorStyles.boldLabel); EditorGUILayout.LabelField("Grass Modes", EditorStyles.boldLabel); grassType = EditorGUILayout.Popup("Grass type:", grassType, grassTypeLabels); densityMode = (DensityMode)EditorGUILayout.Popup("Density mode:", (int)densityMode, densityModeLabels); grassRandomDirection = GUILayout.Toggle(grassRandomDirection, "Randomize grass orientation"); EditorGUILayout.Separator(); EditorGUILayout.LabelField("Grass Lighting", EditorStyles.boldLabel); lightingMode = EditorGUILayout.Popup("Lighting mode:", lightingMode, lightingModeLabels); ignoreGISpecular = GUILayout.Toggle(ignoreGISpecular, new GUIContent("Ignore global specular lighting", "If checked, the specular lighting from the " + "global illumination engine will be ignored. " + "Skyboxes will no longer reflect on the grass.")); EditorGUILayout.Separator(); EditorGUILayout.LabelField("Level of Detail Interpolation", EditorStyles.boldLabel); widthSmoothing = GUILayout.Toggle(widthSmoothing, "Smooth grass width"); heightSmoothing = GUILayout.Toggle(heightSmoothing, "Smooth grass height"); EditorGUILayout.Separator(); EditorGUILayout.LabelField("Object / World Space Modes", EditorStyles.boldLabel); objectMode = GUILayout.Toggle(objectMode, "Object space mode"); surfaceNormal = GUILayout.Toggle(surfaceNormal, "Follow surface normals"); EditorGUILayout.Separator(); EditorGUILayout.LabelField("Other Shader Variants", EditorStyles.boldLabel); topViewCompensation = GUILayout.Toggle(topViewCompensation, "Improve viewing grass from above"); calcGlobalWind = GUILayout.Toggle(calcGlobalWind, "Use global wind"); EditorGUILayout.Separator(); useTextureAtlas = grassType >= 2 && GUILayout.Toggle(useTextureAtlas, "Use texture atlas"); EditorGUILayout.Separator(); if (EditorGUI.EndChangeCheck() || forceUpdate) { Undo.RecordObject(targetMat, "Changed grass shader keywords"); var keywords = new List <string>(); keywords.Add(grassTypeString[grassType]); keywords.Add(lightingModes[lightingMode]); keywords.Add(GrassEditorUtility.DensityModes[(int)densityMode]); if (ignoreGISpecular) { keywords.Add("GRASS_IGNORE_GI_SPECULAR"); } if (widthSmoothing) { keywords.Add("GRASS_WIDTH_SMOOTHING"); } if (heightSmoothing) { keywords.Add("GRASS_HEIGHT_SMOOTHING"); } if (objectMode) { keywords.Add("GRASS_OBJECT_MODE"); } if (topViewCompensation) { keywords.Add("GRASS_TOP_VIEW_COMPENSATION"); } if (surfaceNormal) { keywords.Add("GRASS_FOLLOW_SURFACE_NORMAL"); } if (useTextureAtlas) { keywords.Add("GRASS_USE_TEXTURE_ATLAS"); } if (grassRandomDirection) { keywords.Add("GRASS_RANDOM_DIR"); } if (calcGlobalWind) { keywords.Add("GRASS_CALC_GLOBAL_WIND"); } targetMat.shaderKeywords = keywords.ToArray(); EditorUtility.SetDirty(targetMat); } EditorGUILayout.LabelField("Shader Settings", EditorStyles.boldLabel); serializedObject.Update(); var theShader = serializedObject.FindProperty("m_Shader"); if (isVisible && !theShader.hasMultipleDifferentValues && theShader.objectReferenceValue != null) { EditorGUIUtility.fieldWidth = 64; EditorGUI.BeginChangeCheck(); int grassLabel = 1; var properties = GetMaterialProperties(new Object[] { targetMat }); foreach (var property in properties) { //Ignore unused grass types if ((grassType < 3 && property.name.Contains("01")) || (grassType < 4 && property.name.Contains("02")) || (grassType < 5 && property.name.Contains("03"))) { break; } // =========== Labels ================== if (property.name == "_EdgeLength") { EditorGUILayout.LabelField("Performance Settings", EditorStyles.boldLabel); } if (property.name == "_GrassFadeStart") { EditorGUILayout.Space(); EditorGUILayout.LabelField("Visual Settings", EditorStyles.boldLabel); } if (property.name == "_ColorMap") { EditorGUILayout.Space(); EditorGUILayout.LabelField("Base Textures", EditorStyles.boldLabel); } if (property.name == "_WindParams") { EditorGUILayout.Space(); EditorGUILayout.LabelField("Wind Settings", EditorStyles.boldLabel); } //Grass type label if (property.name.Contains("_GrassTex")) { EditorGUILayout.Space(); EditorGUILayout.LabelField("Grass Type Nr. " + grassLabel, EditorStyles.boldLabel); grassLabel++; } // ============ Non standard settings ============= if (property.name == "_CullMode") { //Cull Mode is only set by the editor, don't show it in the inspector property.floatValue = grassRandomDirection ? 2 : 0; continue; } //Max tessellation can only be a int between 1 and 6 if (property.name == "_MaxTessellation") { property.floatValue = EditorGUILayout.IntSlider(property.displayName, (int)property.floatValue, (int)property.rangeLimits.x, (int)property.rangeLimits.y); continue; } //Max tessellation can only be a int between 1 and 6 if (property.name == "_LODMax") { property.floatValue = EditorGUILayout.IntSlider(property.displayName, (int)property.floatValue, (int)property.rangeLimits.x, (int)property.rangeLimits.y); continue; } //Hide texture atlas settings if not active if (property.name.Contains("_TextureAtlas")) { if (useTextureAtlas) { property.floatValue = Math.Max(EditorGUILayout.IntField(property.displayName, (int)property.floatValue), 1); } continue; } //Wind should only be active when activated if (property.name.StartsWith("_Wind")) { EditorGUI.BeginDisabledGroup(!calcGlobalWind); DrawProperty(property); EditorGUI.EndDisabledGroup(); continue; } // ============ Standard settings ============= //Density if (property.name.Contains("_Density")) { //Vertex density if (densityMode == DensityMode.Vertex || grassType == 0) { continue; } //Texture density if (densityMode == DensityMode.Texture && property.name == "_DensityValues") { continue; } //Density value if (densityMode == DensityMode.Value && property.name == "_Density") { continue; } } //In simple grass, ignore grass texture if ((grassType == 0 || grassType == 1) && property.name.Contains("_GrassTex")) { continue; } //For billboard grass (not randomized direction grass) the subsurface scattering setting is not in use (yet?) if (!grassRandomDirection && property.name.Contains("Subsurface")) { continue; } DrawProperty(property); } if (EditorGUI.EndChangeCheck()) { PropertiesChanged(); } } }
private void TextureSettings() { if (grassObject == null) { EditorGUILayout.LabelField("No grass object selected. Select a grass object in the scene Hierarchy."); return; } EditorGUILayout.LabelField("Current object: " + grassObject.name); EditorGUILayout.Space(); if (GrassEditorUtility.GetDensityMode(grassMaterial) != DensityMode.Texture) { EditorGUILayout.LabelField("The grass material is not in texture density mode.", EditorStyles.boldLabel); if (GUILayout.Button("Change material to texture density")) { GrassEditorUtility.SetDensityMode(grassMaterial, DensityMode.Texture); } EditorGUILayout.Space(); } if (grassMaterial.GetTexture("_Density") == null) { EditorGUILayout.LabelField("Create new texture", EditorStyles.boldLabel); EditorGUILayout.Space(); textureSize = EditorGUILayout.IntField("Texture Size", textureSize); if (GUILayout.Button("Create texture")) { //Select the path and return on cancel string path = EditorUtility.SaveFilePanelInProject("Create density texture", "newDensityTexture", "png", "Choose where to save the new density texture"); if (path == null) { return; } //Create the new texture and save it at the selected path GrassPainter.Texture = new Texture2D(textureSize, textureSize, TextureFormat.ARGB32, false, true); Color[] colors = new Color[textureSize * textureSize]; for (int i = 0; i < colors.Length; i++) { colors[i] = new Color(0, 0, 0, 0); } GrassPainter.Texture.SetPixels(colors); GrassPainter.Texture.Apply(); File.WriteAllBytes(path, GrassPainter.Texture.EncodeToPNG()); //Import and load the new texture AssetDatabase.ImportAsset(path); var importer = (TextureImporter)AssetImporter.GetAtPath(path); importer.wrapMode = TextureWrapMode.Clamp; importer.isReadable = true; importer.maxTextureSize = textureSize; #if UNITY_5_5_OR_NEWER importer.sRGBTexture = false; importer.textureCompression = TextureImporterCompression.Uncompressed; importer.SetPlatformTextureSettings(new TextureImporterPlatformSettings { format = TextureImporterFormat.ARGB32, overridden = true, }); #else importer.linearTexture = true; importer.textureFormat = TextureImporterFormat.ARGB32; #endif AssetDatabase.ImportAsset(path); GrassPainter.Texture = AssetDatabase.LoadAssetAtPath(path, typeof(Texture2D)) as Texture2D; //Set texture to material grassMaterial.SetTexture("_Density", GrassPainter.Texture); } EditorGUILayout.Space(); } }