public static void DrawTextureField(MicroSplatObject t, GUIContent content, ref Texture2D tex, string keyword, string keyword2 = null, string keyword3 = null, string keyword4 = null, bool allKeywordsRequired = true) { if (allKeywordsRequired) { if (keyword != null && !t.keywordSO.IsKeywordEnabled(keyword)) { return; } if (keyword2 != null && !t.keywordSO.IsKeywordEnabled(keyword2)) { return; } if (keyword3 != null && !t.keywordSO.IsKeywordEnabled(keyword3)) { return; } if (keyword4 != null && !t.keywordSO.IsKeywordEnabled(keyword4)) { return; } } else { bool pass = false; if (keyword != null && t.keywordSO.IsKeywordEnabled(keyword)) { pass = true; } if (keyword2 != null && t.keywordSO.IsKeywordEnabled(keyword2)) { pass = true; } if (keyword3 != null && t.keywordSO.IsKeywordEnabled(keyword3)) { pass = true; } if (keyword4 != null && t.keywordSO.IsKeywordEnabled(keyword4)) { pass = true; } if (!pass) { return; } } EditorGUI.BeginChangeCheck(); Rect r = EditorGUILayout.GetControlRect(GUILayout.Height(18)); r.width -= 18; // shrik for boxed contents.. which unity doesn't seem to handle right.. tex = EditorGUI.ObjectField(r, content, tex, typeof(Texture2D), false) as Texture2D; if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(t); MicroSplatObject.SyncAll(); } }
public void Compile(Material m, string shaderName = null) { int hash = 0; MicroSplatKeywords keywords = MicroSplatUtilities.FindOrCreateKeywords(m); for (int i = 0; i < keywords.keywords.Count; ++i) { hash += 31 + keywords.keywords [i].GetHashCode(); } var path = AssetDatabase.GetAssetPath(m.shader); string nm = m.shader.name; if (!string.IsNullOrEmpty(shaderName)) { nm = shaderName; } string baseName = "Hidden/" + nm + "_Base" + hash.ToString(); string terrainShader = Compile(keywords.keywords.ToArray(), nm, baseName); if (renderLoop != null) { keywords.EnableKeyword(renderLoop.GetRenderLoopKeyword()); } GenerateAuxShaders(nm, path, keywords.keywords); MicroSplatUtilities.Checkout(path); System.IO.File.WriteAllText(path, terrainShader); if (!keywords.IsKeywordEnabled("_MICROMESH") && !keywords.IsKeywordEnabled("_MICROVERTEXMESH") && !keywords.IsKeywordEnabled("_MEGASPLAT") && !keywords.IsKeywordEnabled("_MICROTERRAINMESH")) { // generate fallback string[] oldKeywords = new string[keywords.keywords.Count]; System.Array.Copy(keywords.keywords.ToArray(), oldKeywords, keywords.keywords.Count); keywords.DisableKeyword("_TESSDISTANCE"); keywords.DisableKeyword("_PARALLAX"); keywords.DisableKeyword("_DETAILNOISE"); keywords.EnableKeyword("_MICROSPLATBASEMAP"); string fallback = Compile(keywords.keywords.ToArray(), baseName); keywords.keywords = new List <string> (oldKeywords); string fallbackPath = path.Replace(".shader", "_Base.shader"); MicroSplatUtilities.Checkout(fallbackPath); System.IO.File.WriteAllText(fallbackPath, fallback); } EditorUtility.SetDirty(m); AssetDatabase.Refresh(); #if __MICROSPLAT_MESH__ MicroSplatMesh.ClearMaterialCache(); #endif MicroSplatObject.SyncAll(); }
public static void DrawGUI(MicroSplatObject mso, Options o) { if (MicroSplatUtilities.DrawRollup("Compressor", false)) { EditorGUILayout.HelpBox("You can use this section to automatically covert various maps to compressed formats before a build. Please note, that once compressed, external files will be used for things like the terrain splat maps, and changing the terrain through Unity's tools will have no effect", MessageType.Info); EditorGUILayout.LabelField("Compression Options"); o.splatMaps = EditorGUILayout.Toggle(CCompSplatMaps, o.splatMaps); if (o.splatMaps) { EditorGUILayout.HelpBox("This will remove the terrain painting from your terrain file to save memory! The Uncompress button will restore this from the output textures, but if you delete or unhook them your painting may be lost.", MessageType.Error); } o.streamMaps = EditorGUILayout.Toggle(CCompStreamMap, o.streamMaps); o.snowMask = EditorGUILayout.Toggle(CCompSnowMaps, o.snowMask); o.biomeMask = EditorGUILayout.Toggle(CCompBiomeMaps, o.biomeMask); o.tintMap = EditorGUILayout.Toggle(CCompTintMaps, o.tintMap); EditorGUILayout.BeginHorizontal(); EditorGUILayout.Space(); if (GUILayout.Button("Compress")) { MicroSplatCompressor comp = new MicroSplatCompressor(); comp.Compress(mso, o); } if (GUILayout.Button("Uncompress")) { MicroSplatCompressor comp = new MicroSplatCompressor(); comp.Revert(mso); } EditorGUILayout.Space(); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.Space(); if (GUILayout.Button("Compress Scene")) { MicroSplatCompressor comp = new MicroSplatCompressor(); MicroSplatObject [] objs = GameObject.FindObjectsOfType <MicroSplatObject> (); foreach (var obj in objs) { comp.Compress(obj, o); } } if (GUILayout.Button("Uncompress Scene")) { MicroSplatCompressor comp = new MicroSplatCompressor(); MicroSplatObject [] objs = GameObject.FindObjectsOfType <MicroSplatObject> (); foreach (var obj in objs) { comp.Revert(obj); } } EditorGUILayout.Space(); EditorGUILayout.EndHorizontal(); } }
static Vector2 WorldToTerrain(MicroSplatObject ter, Vector3 point, int width, int height) { Bounds b = ter.GetBounds(); point = ter.transform.worldToLocalMatrix.MultiplyPoint(point); float x = (point.x / b.size.x) * width; float z = (point.z / b.size.z) * height; return(new Vector2(x, z)); }
public void Revert(MicroSplatObject mso) { MicroSplatTerrain t = mso as MicroSplatTerrain; if (t != null) { if (t.templateMaterial == null) { Debug.LogError("MicroSplatTerrain " + mso.gameObject.name + " does not have template material"); } else { RevertTerrainSplats(t); } } #if __MICROSPLAT_MESH__ MicroSplatMesh msm = mso as MicroSplatMesh; if (msm != null) { foreach (var subMesh in msm.subMeshEntries) { foreach (var tex in subMesh.subMeshOverride.controlTextures) { UncompressTexture(tex); } } } #endif #if __MICROSPLAT_PROCTEX__ UncompressTexture(mso.procBiomeMask); UncompressTexture(mso.procBiomeMask2); UncompressTexture(mso.templateMaterial, "_ProcTexBiomeMask"); UncompressTexture(mso.templateMaterial, "_ProcTexBiomeMask2"); #endif #if __MICROSPLAT_SNOW__ UncompressTexture(mso.snowMaskOverride); UncompressTexture(mso.templateMaterial, "_SnowMask"); #endif #if __MICROSPLAT_STREAMS__ UncompressTexture(mso.streamTexture); UncompressTexture(mso.templateMaterial, "_StreamControl"); #endif #if __MICROSPLAT_GLOBALTEXTURE__ UncompressTexture(mso.streamTexture); UncompressTexture(mso.templateMaterial, "_GlobalTintTex"); #endif }
bool VerifyData() { if (rawTerrains == null || rawTerrains.Count == 0) { return(false); } for (int i = 0; i < rawTerrains.Count; ++i) { Terrain t = rawTerrains [i]; MicroSplatObject mso = t.GetComponent <MicroSplatObject> (); if (t.materialTemplate == null || mso == null || !mso.keywordSO.IsKeywordEnabled("_MICROSPLAT")) { EditorGUILayout.HelpBox("Terrain(s) are not setup for MicroSplat, please set them up", MessageType.Error); return(false); } } return(true); }
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) { Undo.undoRedoPerformed -= Undo_UndoRedoPerformed; Undo.undoRedoPerformed += Undo_UndoRedoPerformed; Material targetMat = materialEditor.target as Material; if (cachedTitle == null) { cachedTitle = "Shader Generator v:" + MicroSplatVersion; } if (moduleLabelStyle == null) { moduleLabelStyle = new GUIStyle(EditorStyles.foldout); moduleLabelStyle.fontStyle = FontStyle.Bold; } if (GUI.enabled == false || string.IsNullOrEmpty(AssetDatabase.GetAssetPath(targetMat))) { EditorGUILayout.HelpBox("You must edit the template material, not the instance being used. You can find this in the MicroSplatData directory, or assigned on your MicroSplatTerrain component", MessageType.Info); return; } EditorGUI.BeginChangeCheck(); // sync materials var keywordSO = MicroSplatUtilities.FindOrCreateKeywords(targetMat); cachedKeywordCount = keywordSO.keywords.Count; // for undo cachedMaterial = targetMat; compiler.Init(); // must unpack everything before the generator draws- otherwise we get IMGUI errors for (int i = 0; i < compiler.extensions.Count; ++i) { var ext = compiler.extensions[i]; ext.Unpack(keywordSO.keywords.ToArray()); } string shaderName = targetMat.shader.name; DrawModules(); EditorGUI.BeginChangeCheck(); // needs compile var propTex = FindOrCreatePropTex(targetMat); Undo.RecordObjects(new Object[3] { targetMat, keywordSO, propTex }, "MicroSplat Material Edit"); using (new GUILayout.VerticalScope(MicroSplatUtilities.boxStyle)) { if (MicroSplatUtilities.DrawRollup(cachedTitle)) { GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (bulkEditMode) { if (GUILayout.Button("Exit Bulk Shader Feature Edit Mode", GUILayout.Width(230))) { bulkEditMode = false; needsCompile = true; } } else { if (GUILayout.Button("Enter Bulk Shader Feature Edit Mode", GUILayout.Width(230))) { bulkEditMode = true; } } GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); if (bulkEditMode) { EditorGUILayout.HelpBox("Shader is in bulk edit mode, allowing you to change many options without recompiling the shader. No material properties will be shown during bulk editing, and the shader will be recompiled and properties shown once you exit this mode", MessageType.Warning); } shaderName = EditorGUILayout.DelayedTextField(CShaderName, shaderName); if (DrawRenderLoopGUI(keywordSO, targetMat)) { needsCompile = true; } for (int i = 0; i < compiler.extensions.Count; ++i) { var e = compiler.extensions [i]; if (e.GetVersion() == MicroSplatVersion) { needsCompile = EditorGUI.EndChangeCheck() || needsCompile; if (!moduleFoldoutState.ContainsKey(e.ModuleName())) { moduleFoldoutState [e.ModuleName()] = true; } // hack for invisible modules- need to make this more formal somehow? bool empty = (e.ModuleName() == "Mesh" && (!keywordSO.IsKeywordEnabled("_MICROMESH") && !keywordSO.IsKeywordEnabled("_MICROVERTEXMESH")) || (e.ModuleName() == "MeshTerrain" && !keywordSO.IsKeywordEnabled("_MICROMESHTERRAIN"))); if (!empty) { using (new GUILayout.VerticalScope(MicroSplatUtilities.boxStyle)) { EditorGUI.indentLevel++; moduleFoldoutState [e.ModuleName()] = EditorGUILayout.Foldout(moduleFoldoutState [e.ModuleName()], e.ModuleName(), moduleLabelStyle); //EditorGUILayout.LabelField (e.ModuleName (), moduleLabelStyle); EditorGUI.BeginChangeCheck(); if (moduleFoldoutState [e.ModuleName()]) { //EditorGUI.indentLevel++; e.DrawFeatureGUI(keywordSO); //EditorGUI.indentLevel--; } EditorGUI.indentLevel--; } } else { EditorGUI.BeginChangeCheck(); } } else { EditorGUILayout.HelpBox("Extension : " + e.ModuleName() + " is version " + e.GetVersion() + " and MicroSplat is version " + MicroSplatVersion + ", please update", MessageType.Error); } } for (int i = 0; i < availableRenderLoops.Count; ++i) { var rl = availableRenderLoops [i]; if (rl.GetVersion() != MicroSplatVersion) { EditorGUILayout.HelpBox("Render Loop : " + rl.GetDisplayName() + " is version " + rl.GetVersion() + " and MicroSplat is version " + MicroSplatVersion + ", please update", MessageType.Error); } } } if (bulkEditMode) { if (!keywordSO.IsKeywordEnabled("_DISABLESPLATMAPS")) { Texture2DArray diff = targetMat.GetTexture("_Diffuse") as Texture2DArray; if (diff != null && MicroSplatUtilities.DrawRollup("Per Texture Properties")) { perTexIndex = MicroSplatUtilities.DrawTextureSelector(perTexIndex, diff); for (int i = 0; i < compiler.extensions.Count; ++i) { var ext = compiler.extensions [i]; if (ext.GetVersion() == MicroSplatVersion) { ext.DrawPerTextureGUI(perTexIndex, keywordSO, targetMat, propTex); } } } } needsCompile = needsCompile || EditorGUI.EndChangeCheck(); if (needsCompile) { keywordSO.keywords.Clear(); for (int i = 0; i < compiler.extensions.Count; ++i) { compiler.extensions [i].Pack(keywordSO); } if (compiler.renderLoop != null) { keywordSO.EnableKeyword(compiler.renderLoop.GetRenderLoopKeyword()); } needsCompile = false; } return; // Don't draw rest of GUI } } needsCompile = needsCompile || EditorGUI.EndChangeCheck(); int featureCount = keywordSO.keywords.Count; // note, ideally we wouldn't draw the GUI for the rest of stuff if we need to compile. // But we can't really do that without causing IMGUI to split warnings about // mismatched GUILayout blocks if (!needsCompile) { for (int i = 0; i < compiler.extensions.Count; ++i) { var ext = compiler.extensions [i]; if (ext.GetVersion() == MicroSplatVersion) { ext.DrawShaderGUI(this, keywordSO, targetMat, materialEditor, props); } else { EditorGUILayout.HelpBox("Extension : " + ext.ModuleName() + " is version " + ext.GetVersion() + " and MicroSplat is version " + MicroSplatVersion + ", please update so that all modules are using the same version.", MessageType.Error); } } if (!keywordSO.IsKeywordEnabled("_DISABLESPLATMAPS")) { Texture2DArray diff = targetMat.GetTexture("_Diffuse") as Texture2DArray; if (diff != null && MicroSplatUtilities.DrawRollup("Per Texture Properties")) { perTexIndex = MicroSplatUtilities.DrawTextureSelector(perTexIndex, diff); for (int i = 0; i < compiler.extensions.Count; ++i) { var ext = compiler.extensions [i]; if (ext.GetVersion() == MicroSplatVersion) { ext.DrawPerTextureGUI(perTexIndex, keywordSO, targetMat, propTex); } } } } } if (!needsCompile) { if (featureCount != keywordSO.keywords.Count) { needsCompile = true; } } int arraySampleCount = 0; int textureSampleCount = 0; int maxSamples = 0; int tessSamples = 0; int depTexReadLevel = 0; builder.Length = 0; for (int i = 0; i < compiler.extensions.Count; ++i) { var ext = compiler.extensions [i]; if (ext.GetVersion() == MicroSplatVersion) { ext.ComputeSampleCounts(keywordSO.keywords.ToArray(), ref arraySampleCount, ref textureSampleCount, ref maxSamples, ref tessSamples, ref depTexReadLevel); } } if (MicroSplatUtilities.DrawRollup("Debug")) { string shaderModel = compiler.GetShaderModel(keywordSO.keywords.ToArray()); builder.Append("Shader Model : "); builder.AppendLine(shaderModel); if (maxSamples != arraySampleCount) { builder.Append("Texture Array Samples : "); builder.AppendLine(arraySampleCount.ToString()); builder.Append("Regular Samples : "); builder.AppendLine(textureSampleCount.ToString()); } else { builder.Append("Texture Array Samples : "); builder.AppendLine(arraySampleCount.ToString()); builder.Append("Regular Samples : "); builder.AppendLine(textureSampleCount.ToString()); } if (tessSamples > 0) { builder.Append("Tessellation Samples : "); builder.AppendLine(tessSamples.ToString()); } if (depTexReadLevel > 0) { builder.Append(depTexReadLevel.ToString()); builder.AppendLine(" areas with dependent texture reads"); } EditorGUILayout.HelpBox(builder.ToString(), MessageType.Info); } if (EditorGUI.EndChangeCheck() && !needsCompile) { MicroSplatObject.SyncAll(); } if (needsCompile) { needsCompile = false; keywordSO.keywords.Clear(); for (int i = 0; i < compiler.extensions.Count; ++i) { compiler.extensions [i].Pack(keywordSO); } if (compiler.renderLoop != null) { keywordSO.EnableKeyword(compiler.renderLoop.GetRenderLoopKeyword()); } // horrible workaround to GUI warning issues compileMat = targetMat; compileName = shaderName; targetCompiler = compiler; EditorApplication.delayCall += TriggerCompile; } }
public override void OnInspectorGUI() { StreamManager sm = target as StreamManager; MicroSplatObject mso = sm.GetComponent <MicroSplatObject>(); if (mso == null) { EditorGUILayout.HelpBox("Must be on a MicroSplatObject (terrain, mesh terrain, etc)", MessageType.Error); return; } if (mso.keywordSO == null) { EditorGUILayout.HelpBox("MicroSplat Terrain is missing keywords", MessageType.Error); return; } if (!mso.keywordSO.IsKeywordEnabled("_DYNAMICFLOWS")) { EditorGUILayout.HelpBox("Must have Dynamic Flows ON in your terrain material", MessageType.Error); return; } EditorGUI.BeginChangeCheck(); if (MicroSplatUtilities.DrawRollup("Streams", true, false)) { sm.strength.x = EditorGUILayout.Slider(CStrength, sm.strength.x, 0, 1); sm.evaporation.x = EditorGUILayout.Slider(CEvaporation, sm.evaporation.x, 0, 0.5f); sm.speed.x = EditorGUILayout.Slider(CSpeed, sm.speed.x, 0, 10); sm.resistance.x = EditorGUILayout.Slider(CResistance, sm.resistance.x, 0.005f, 0.75f); sm.wetnessEvaporation = EditorGUILayout.Slider(CWetnessEvap, sm.wetnessEvaporation, 0.0f, 0.5f); if (Application.isPlaying) { GUILayout.BeginHorizontal(); GUILayout.Space(5); if (GUILayout.Button("Save State")) { SaveStream(sm); } GUILayout.Space(5); GUILayout.EndHorizontal(); } } if (MicroSplatUtilities.DrawRollup("Lava", true, false)) { sm.strength.y = EditorGUILayout.Slider(CStrength, sm.strength.y, 0, 1); sm.evaporation.y = EditorGUILayout.Slider(CEvaporation, sm.evaporation.y, 0, 0.5f); sm.speed.y = EditorGUILayout.Slider(CSpeed, sm.speed.y, 0, 10); sm.resistance.y = EditorGUILayout.Slider(CResistance, sm.resistance.y, 0.005f, 0.75f); sm.burnEvaporation = EditorGUILayout.Slider(CBurnEvap, sm.burnEvaporation, 0.0f, 0.5f); if (Application.isPlaying) { GUILayout.BeginHorizontal(); GUILayout.Space(5); if (GUILayout.Button("Save State")) { SaveLava(sm); } GUILayout.Space(5); GUILayout.EndHorizontal(); } } if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(sm); } if (sm.updateBuffer != null) { if (sm.updateBuffer.GetCurrent() != null) { EditorGUILayout.BeginHorizontal(); GUILayout.Label("Dynamic Buffer"); int mem = sm.updateBuffer.width * sm.updateBuffer.height * 2; mem /= 128; EditorGUILayout.LabelField("Buffer Memory: " + mem.ToString() + "kb"); EditorGUILayout.EndHorizontal(); GUILayout.Box(sm.updateBuffer.GetCurrent(), GUILayout.Width(256), GUILayout.Height(256)); } } }
private void OnSceneSave(Scene scene) { MicroSplatObject.SyncAll(); }
private static void OnScriptsReloaded() { MicroSplatObject.SyncAll(); }
public static float GetSnowCoverage(Terrain t, Vector3 worldPos, int maxDistance = 2) { MicroSplatObject mso = t.GetComponent <MicroSplatTerrain>(); if (mso != null) { if (mso.keywordSO.IsKeywordEnabled("_SNOW")) { var terrainLocalPos = worldPos - t.transform.position; var normalizedPos = new Vector2(Mathf.InverseLerp(0.0f, t.terrainData.size.x, terrainLocalPos.x), Mathf.InverseLerp(0.0f, t.terrainData.size.z, terrainLocalPos.z)); Vector3 worldNormal = t.terrainData.GetInterpolatedNormal(normalizedPos.x, normalizedPos.y); float worldheight = t.terrainData.GetInterpolatedHeight(normalizedPos.x, normalizedPos.y); float snowLevel; var mat = mso.templateMaterial; float snowMin; float snowMax; float angleRangeW; float angleRangeZ; if (mso.keywordSO.IsKeywordEnabled("_USEGLOBALSNOWLEVEL")) { snowLevel = Shader.GetGlobalFloat("_Global_SnowLevel"); } else { snowLevel = mat.GetFloat("_SnowAmount"); } if (mso.keywordSO.IsKeywordEnabled("_USEGLOBALSNOWHEIGHT")) { var g = Shader.GetGlobalVector("_Global_SnowMinMaxHeight"); snowMin = g.x; snowMax = g.y; angleRangeZ = g.z; angleRangeW = g.w; } else { var g = mat.GetVector("_SnowHeightAngleRange"); snowMin = g.x; snowMax = g.y; angleRangeZ = g.z; angleRangeW = g.w; } Vector4 _SnowParams = mat.GetVector("_SnowParams"); Vector3 snowUpVector = mat.GetVector("_SnowUpVector"); float snowDot = Mathf.Max(snowLevel / 2, Vector3.Dot(worldNormal, snowUpVector)); float snowDotVertex = snowDot; float ao = 1; float oheight = 0; float snowFade = SnowFade(worldheight, snowMin, snowMax, snowDot, snowDotVertex, snowLevel, angleRangeZ, angleRangeW); float height = Mathf.Clamp01(oheight - (1.0f - _SnowParams.x)); float erosion = Mathf.Clamp01(ao * _SnowParams.y); erosion *= erosion; float snowMask = Mathf.Clamp01(snowFade - erosion - height); snowMask = snowMask * snowMask * snowMask; float snowAmount = snowMask * Mathf.Clamp01(snowDot - (height + erosion) * 0.5f); // up snowAmount = Mathf.Clamp01(snowAmount * 8); return(snowAmount); } } return(0); }
public void Sync() { #if UNITY_EDITOR // If we have a terrain, we might be moved over another terrain. So lets see if we're in the bounds of our current terrain // and if not, clear it and try to get a new one.. bool testForNewTerrain = false; if (msObject != null) { var tbounds = TransformBounds(msObject.GetBounds()); Renderer rend = GetComponent <Renderer>(); if (!tbounds.Intersects(rend.bounds)) { testForNewTerrain = true; } } if (msObject == null || testForNewTerrain) { RaycastHit[] hits = Physics.RaycastAll(this.transform.position + Vector3.up * 100, Vector3.down, 500); for (int i = 0; i < hits.Length; ++i) { var h = hits[i]; var t = h.collider.GetComponent <Terrain>(); if (t != null) { var nt = t.GetComponent <MicroSplatTerrain>(); if (nt != null) { msObject = nt; break; } } #if __MICROSPLAT_MESH__ var m = h.collider.GetComponent <MicroSplatMesh>(); if (m != null) { msObject = m; break; } #endif } } #endif Material bmInstance = msObject.GetBlendMatInstance(); if (msObject == null && bmInstance) { return; } Renderer r = GetComponent <Renderer>(); var materials = r.sharedMaterials; bool hasBlendMat = false; for (int i = 0; i < materials.Length; ++i) { if (materials[i] == bmInstance && bmInstance != null) { hasBlendMat = true; } else if (materials[i] == null || materials[i].IsKeywordEnabled("_TERRAINBLENDING")) { hasBlendMat = true; materials[i] = bmInstance; r.sharedMaterials = materials; } } if (!hasBlendMat) { System.Array.Resize <Material>(ref materials, materials.Length + 1); materials[materials.Length - 1] = bmInstance; r.sharedMaterials = materials; } if (props == null) { props = new MaterialPropertyBlock(); } props.Clear(); props.SetVector("_TerrainBlendParams", new Vector4(blendDistance, blendContrast, msObject.transform.position.y, blendCurve)); props.SetVector("_SlopeBlendParams", new Vector4(slopeFilter, slopeContrast, slopeNoise, normalBlendDistance)); props.SetVector("_SnowBlendParams", new Vector4(snowWidth, 0, 0, 0)); props.SetVector("_FeatureFilters", new Vector4(doTerrainBlend ? 0.0f : 1.0f, doSnow ? 0.0f : 1.0f, 0, 0)); if (normalFromObject != null) { props.SetTexture("_NormalOriginal", normalFromObject); } r.SetPropertyBlock(props); }
void Awake() { msObject = GetComponent <MicroSplatObject>(); }
void DrawScatterGUI() { if (MicroSplatUtilities.DrawRollup("Brush Settings")) { brushSize = EditorGUILayout.Slider("Brush Size", brushSize, 0.01f, 30.0f); brushFlow = EditorGUILayout.Slider("Brush Flow", brushFlow, 0.1f, 128.0f); brushFalloff = EditorGUILayout.Slider("Brush Falloff", brushFalloff, 0.1f, 3.5f); Material tempMat = null; for (int i = 0; i < rawTerrains.Count; ++i) { Terrain t = rawTerrains [i]; MicroSplatTerrain mst = t.GetComponent <MicroSplatTerrain> (); if (mst != null) { if (mst.templateMaterial != null && mst.templateMaterial.HasProperty("_ScatterDiffuse")) { Texture2DArray diff = mst.templateMaterial.GetTexture("_ScatterDiffuse") as Texture2DArray; scatterIndex = MicroSplatUtilities.DrawTextureSelector(scatterIndex, diff, false); tempMat = mst.templateMaterial; } else { scatterIndex = EditorGUILayout.IntField("Scatter Index", scatterIndex); } } else { scatterIndex = EditorGUILayout.IntField("Scatter Index", scatterIndex); } } //EditorGUILayout.MinMaxSlider (CSlopeRange, ref slopeRange.x, ref slopeRange.y, 0.0f, 1.0f); paintValue = EditorGUILayout.Slider("Target Opacity", paintValue, 0.0f, 1.0f); #if __MICROSPLAT_SCATTER__ if (tempMat != null) { scatterLayer = (ScatterLayer)EditorGUILayout.EnumPopup(CScatterLayer, scatterLayer); EditorGUILayout.Separator(); using (new GUILayout.VerticalScope(GUI.skin.box)) { EditorGUI.BeginChangeCheck(); EditorGUILayout.LabelField("Per Texture Properties"); bool changed = MicroSplatScatter.DrawPerTexExternal(tempMat, scatterIndex); EditorGUILayout.Separator(); // sync compile changes if (changed) { MicroSplatShaderGUI.MicroSplatCompiler comp = new MicroSplatShaderGUI.MicroSplatCompiler(); comp.Init(); comp.Compile(tempMat); } // sync property changes if (EditorGUI.EndChangeCheck()) { MicroSplatObject.SyncAll(); } } } #endif GUILayout.Box("", new GUILayoutOption [] { GUILayout.ExpandWidth(true), GUILayout.Height(1) }); EditorGUILayout.Separator(); } DrawFillGUI(); }
public void Compress(MicroSplatObject mso, Options opt) { MicroSplatTerrain t = mso as MicroSplatTerrain; if (t != null) { if (t.templateMaterial == null) { Debug.LogError("MicroSplatTerrain " + mso.gameObject.name + " does not have template material"); } else { if (opt.splatMaps) { CompressTerrainSplats(t); } } } #if __MICROSPLAT_MESH__ MicroSplatMesh msm = mso as MicroSplatMesh; if (msm != null) { foreach (var subMesh in msm.subMeshEntries) { foreach (var tex in subMesh.subMeshOverride.controlTextures) { CompressTexture(tex, false); } } } #endif #if __MICROSPLAT_PROCTEX__ if (opt.biomeMask) { CompressTexture(mso.procBiomeMask, false); CompressTexture(mso.procBiomeMask2, false); CompressTexture(mso.templateMaterial, "_ProcTexBiomeMask", false); CompressTexture(mso.templateMaterial, "_ProcTexBiomeMask2", false); } #endif #if __MICROSPLAT_SNOW__ if (opt.snowMask) { CompressTexture(mso.snowMaskOverride, false); CompressTexture(mso.templateMaterial, "_SnowMask", false); } #endif #if __MICROSPLAT_STREAMS__ if (opt.streamMaps) { CompressTexture(mso.streamTexture, false); CompressTexture(mso.templateMaterial, "_StreamControl", false); } #endif #if __MICROSPLAT_GLOBALTEXTURE__ if (opt.tintMap) { CompressTexture(mso.streamTexture, true); CompressTexture(mso.templateMaterial, "_GlobalTintTex", true); } #endif }
public void Sync() { #if UNITY_EDITOR // If we have a terrain, we might be moved over another terrain. So lets see if we're in the bounds of our current terrain // and if not, clear it and try to get a new one.. bool testForNewTerrain = false; // check bounds of existing terrain if (msObject != null && testForNewTerrain) { var tbounds = TransformBounds(msObject.GetBounds()); Renderer rend = GetComponent <Renderer>(); if (!tbounds.Intersects(rend.bounds)) { testForNewTerrain = true; } } // see if we have override, if we do, skip terrain testing if (msOverrideObject != null) { if (msOverrideObject is MicroSplatTerrain #if __MICROSPLAT_MESHTERRAIN__ || msOverrideObject is MicroSplatMeshTerrain #endif ) { msObject = msOverrideObject; testForNewTerrain = false; } } if (testForNewTerrain) { RaycastHit[] hits = Physics.RaycastAll(this.transform.position + Vector3.up * 100, Vector3.down, 500); for (int i = 0; i < hits.Length; ++i) { var h = hits[i]; var t = h.collider.GetComponent <Terrain>(); if (t != null) { var nt = t.GetComponent <MicroSplatTerrain>(); if (nt != null) { msObject = nt; break; } } } #if __MICROSPLAT_MESHTERRAIN__ if (msObject == null) { for (int i = 0; i < hits.Length; ++i) { var h = hits [i]; var m = h.collider.GetComponent <MicroSplatMeshTerrain> (); if (m != null) { msObject = m; break; } if (h.collider.transform.parent != null) { m = h.collider.transform.parent.GetComponent <MicroSplatMeshTerrain> (); if (m != null) { msObject = m; break; } } } } #endif //__MICROSPLAT_MESHTERRAIN__ } #endif //UNITY_EDITOR if (msObject == null) { Debug.LogWarning("Terrain Blending: No Terrain Found"); return; } Material bmInstance = msObject.GetBlendMatInstance(); if (bmInstance == null) { Debug.LogWarning("Terrain Blending: No blend instance found from " + msObject.name); return; } Renderer r = GetComponent <Renderer>(); var materials = r.sharedMaterials; bool hasBlendMat = false; for (int i = 0; i < materials.Length; ++i) { if (materials[i] == bmInstance && bmInstance != null) { hasBlendMat = true; } else if (materials[i] == null || materials[i].shader == null || materials[i].shader.name.Contains("_TerrainObjectBlend")) { hasBlendMat = true; materials[i] = bmInstance; r.sharedMaterials = materials; } } if (!hasBlendMat) { System.Array.Resize <Material>(ref materials, materials.Length + 1); materials[materials.Length - 1] = bmInstance; r.sharedMaterials = materials; } if (props == null) { props = new MaterialPropertyBlock(); } props.Clear(); props.SetVector("_TerrainBlendParams", new Vector4(blendDistance, blendContrast, msObject.transform.position.y, blendCurve)); props.SetVector("_SlopeBlendParams", new Vector4(slopeFilter, slopeContrast, slopeNoise, normalBlendDistance)); props.SetVector("_SnowBlendParams", new Vector4(snowWidth, 0, 0, 0)); props.SetFloat("_TBNoiseScale", noiseScale); props.SetVector("_FeatureFilters", new Vector4(doTerrainBlend ? 0.0f : 1.0f, doSnow ? 0.0f : 1.0f, 0, 0)); if (normalFromObject != null) { props.SetTexture("_NormalOriginal", normalFromObject); } r.SetPropertyBlock(props); }
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) { Undo.undoRedoPerformed -= Undo_UndoRedoPerformed; Undo.undoRedoPerformed += Undo_UndoRedoPerformed; Material targetMat = materialEditor.target as Material; if (cachedTitle == null) { cachedTitle = "Shader Generator v:" + MicroSplatVersion; } if (GUI.enabled == false || string.IsNullOrEmpty(AssetDatabase.GetAssetPath(targetMat))) { EditorGUILayout.HelpBox("You must edit the template material, not the instance being used. You can find this in the MicroSplatData directory, or assigned on your MicroSplatTerrain component", MessageType.Info); return; } EditorGUI.BeginChangeCheck(); // sync materials var keywordSO = MicroSplatUtilities.FindOrCreateKeywords(targetMat); cachedKeywordCount = keywordSO.keywords.Count; // for undo cachedMaterial = targetMat; compiler.Init(); // must unpack everything before the generator draws- otherwise we get IMGUI errors for (int i = 0; i < compiler.extensions.Count; ++i) { var ext = compiler.extensions[i]; ext.Unpack(keywordSO.keywords.ToArray()); } string shaderName = targetMat.shader.name; DrawModules(); EditorGUI.BeginChangeCheck(); // needs compile var propTex = FindOrCreatePropTex(targetMat); Undo.RecordObjects(new Object[3] { targetMat, keywordSO, propTex }, "MicroSplat Material Edit"); if (MicroSplatUtilities.DrawRollup(cachedTitle)) { shaderName = EditorGUILayout.DelayedTextField(CShaderName, shaderName); if (DrawRenderLoopGUI(keywordSO, targetMat)) { needsCompile = true; } for (int i = 0; i < compiler.extensions.Count; ++i) { var e = compiler.extensions[i]; if (e.GetVersion() == MicroSplatVersion) { //using (new GUILayout.VerticalScope(GUI.skin.box)) { e.DrawFeatureGUI(keywordSO); } } else { EditorGUILayout.HelpBox("Extension : " + e + " is version " + e.GetVersion() + " and MicroSplat is version " + MicroSplatVersion + ", please update", MessageType.Error); } } for (int i = 0; i < availableRenderLoops.Count; ++i) { var rl = availableRenderLoops[i]; if (rl.GetVersion() != MicroSplatVersion) { EditorGUILayout.HelpBox("Render Loop : " + rl.GetDisplayName() + " is version " + rl.GetVersion() + " and MicroSplat is version " + MicroSplatVersion + ", please update", MessageType.Error); } } } needsCompile = needsCompile || EditorGUI.EndChangeCheck(); int featureCount = keywordSO.keywords.Count; // note, ideally we wouldn't draw the GUI for the rest of stuff if we need to compile. // But we can't really do that without causing IMGUI to split warnings about // mismatched GUILayout blocks if (!needsCompile) { for (int i = 0; i < compiler.extensions.Count; ++i) { var ext = compiler.extensions[i]; if (ext.GetVersion() == MicroSplatVersion) { ext.DrawShaderGUI(this, keywordSO, targetMat, materialEditor, props); } else { EditorGUILayout.HelpBox("Extension : " + ext + " is version " + ext.GetVersion() + " and MicroSplat is version " + MicroSplatVersion + ", please update so that all modules are using the same version.", MessageType.Error); } } if (!keywordSO.IsKeywordEnabled("_DISABLESPLATMAPS")) { Texture2DArray diff = targetMat.GetTexture("_Diffuse") as Texture2DArray; if (diff != null && MicroSplatUtilities.DrawRollup("Per Texture Properties")) { perTexIndex = MicroSplatUtilities.DrawTextureSelector(perTexIndex, diff); for (int i = 0; i < compiler.extensions.Count; ++i) { var ext = compiler.extensions [i]; if (ext.GetVersion() == MicroSplatVersion) { ext.DrawPerTextureGUI(perTexIndex, keywordSO, targetMat, propTex); } } } } } if (!needsCompile) { if (featureCount != keywordSO.keywords.Count) { needsCompile = true; } } int arraySampleCount = 0; int textureSampleCount = 0; int maxSamples = 0; int tessSamples = 0; int depTexReadLevel = 0; builder.Length = 0; for (int i = 0; i < compiler.extensions.Count; ++i) { var ext = compiler.extensions[i]; if (ext.GetVersion() == MicroSplatVersion) { ext.ComputeSampleCounts(keywordSO.keywords.ToArray(), ref arraySampleCount, ref textureSampleCount, ref maxSamples, ref tessSamples, ref depTexReadLevel); } } if (MicroSplatUtilities.DrawRollup("Debug")) { string shaderModel = compiler.GetShaderModel(keywordSO.keywords.ToArray()); builder.Append("Shader Model : "); builder.AppendLine(shaderModel); if (maxSamples != arraySampleCount) { builder.Append("Texture Array Samples : "); builder.AppendLine(arraySampleCount.ToString()); builder.Append("Regular Samples : "); builder.AppendLine(textureSampleCount.ToString()); } else { builder.Append("Texture Array Samples : "); builder.AppendLine(arraySampleCount.ToString()); builder.Append("Regular Samples : "); builder.AppendLine(textureSampleCount.ToString()); } if (tessSamples > 0) { builder.Append("Tessellation Samples : "); builder.AppendLine(tessSamples.ToString()); } if (depTexReadLevel > 0) { builder.Append(depTexReadLevel.ToString()); builder.AppendLine(" areas with dependent texture reads"); } EditorGUILayout.HelpBox(builder.ToString(), MessageType.Info); } if (EditorGUI.EndChangeCheck() && !needsCompile) { MicroSplatObject.SyncAll(); } if (needsCompile) { needsCompile = false; keywordSO.keywords.Clear(); for (int i = 0; i < compiler.extensions.Count; ++i) { compiler.extensions[i].Pack(keywordSO); } if (compiler.renderLoop != null) { keywordSO.EnableKeyword(compiler.renderLoop.GetRenderLoopKeyword()); } // horrible workaround to GUI warning issues compileMat = targetMat; compileName = shaderName; targetCompiler = compiler; EditorApplication.delayCall += TriggerCompile; } }
public void Compile(Material m, string shaderName = null) { int hash = 0; MicroSplatKeywords keywords = MicroSplatUtilities.FindOrCreateKeywords(m); for (int i = 0; i < keywords.keywords.Count; ++i) { hash += 31 + keywords.keywords [i].GetHashCode(); } var path = AssetDatabase.GetAssetPath(m.shader); string nm = m.shader.name; if (!string.IsNullOrEmpty(shaderName)) { nm = shaderName; } string baseName = "Hidden/" + nm + "_Base" + hash.ToString(); string terrainShader = Compile(keywords.keywords.ToArray(), nm, baseName); if (renderLoop != null) { keywords.EnableKeyword(renderLoop.GetRenderLoopKeyword()); } string blendShader = null; // strip extra feature from terrain blending to make it cheaper if (keywords.IsKeywordEnabled("_TERRAINBLENDING")) { List <string> blendKeywords = new List <string> (keywords.keywords); if (keywords.IsKeywordEnabled("_TBDISABLE_DETAILNOISE") && blendKeywords.Contains("_DETAILNOISE")) { blendKeywords.Remove("_DETAILNOISE"); } if (keywords.IsKeywordEnabled("_TBDISABLE_DETAILNOISE") && blendKeywords.Contains("_ANTITILEARRAYDETAIL")) { blendKeywords.Remove("_ANTITILEARRAYDETAIL"); } if (keywords.IsKeywordEnabled("_TBDISABLE_DISTANCENOISE") && blendKeywords.Contains("_DISTANCENOISE")) { blendKeywords.Remove("_DISTANCENOISE"); } if (keywords.IsKeywordEnabled("_TBDISABLE_DISTANCENOISE") && blendKeywords.Contains("_ANTITILEARRAYDISTANCE")) { blendKeywords.Remove("_ANTITILEARRAYDISTANCE"); } if (keywords.IsKeywordEnabled("_TBDISABLE_DISTANCERESAMPLE") && blendKeywords.Contains("_DISTANCERESAMPLE")) { blendKeywords.Remove("_DISTANCERESAMPLE"); } blendShader = Compile(blendKeywords.ToArray(), nm, null, true); } string meshBlendShader = null; if (keywords.IsKeywordEnabled("_MESHOVERLAYSPLATS")) { List <string> blendKeywords = new List <string> (keywords.keywords); if (blendKeywords.Contains("_TESSDISTANCE")) { blendKeywords.Remove("_TESSDISTANCE"); } meshBlendShader = Compile(blendKeywords.ToArray(), nm, null, true); } MicroSplatUtilities.Checkout(path); System.IO.File.WriteAllText(path, terrainShader); if (!keywords.IsKeywordEnabled("_MICROMESH")) { // generate fallback string[] oldKeywords = new string[keywords.keywords.Count]; System.Array.Copy(keywords.keywords.ToArray(), oldKeywords, keywords.keywords.Count); keywords.DisableKeyword("_TESSDISTANCE"); keywords.DisableKeyword("_PARALLAX"); keywords.DisableKeyword("_DETAILNOISE"); keywords.EnableKeyword("_MICROSPLATBASEMAP"); string fallback = Compile(keywords.keywords.ToArray(), baseName); keywords.keywords = new List <string> (oldKeywords); string fallbackPath = path.Replace(".shader", "_Base.shader"); MicroSplatUtilities.Checkout(fallbackPath); System.IO.File.WriteAllText(fallbackPath, fallback); } string terrainBlendPath = path.Replace(".shader", "_TerrainObjectBlend.shader"); string meshBlendPath = path.Replace(".shader", "_MeshOverlay.shader"); if (blendShader != null) { MicroSplatUtilities.Checkout(terrainBlendPath); System.IO.File.WriteAllText(terrainBlendPath, blendShader); } if (meshBlendShader != null) { MicroSplatUtilities.Checkout(meshBlendPath); System.IO.File.WriteAllText(meshBlendPath, meshBlendShader); } EditorUtility.SetDirty(m); AssetDatabase.Refresh(); MicroSplatObject.SyncAll(); }
public override void OnInspectorGUI() { MicroSplatTerrain t = target as MicroSplatTerrain; if (t == null) { EditorGUILayout.HelpBox("No Terrain Present, please put this component on a terrain", MessageType.Error); return; } EditorGUI.BeginChangeCheck(); t.templateMaterial = EditorGUILayout.ObjectField(CTemplateMaterial, t.templateMaterial, typeof(Material), false) as Material; if (EditorGUI.EndChangeCheck()) { MicroSplatTerrain.SyncAll(); } EditorGUI.BeginChangeCheck(); if (DoConvertGUI(t)) { return; } if (t.templateMaterial == null) { return; } if (t.propData == null) { t.propData = MicroSplatShaderGUI.FindOrCreatePropTex(t.templateMaterial); EditorUtility.SetDirty(t); MicroSplatObject.SyncAll(); } if (t.keywordSO == null) { t.keywordSO = MicroSplatUtilities.FindOrCreateKeywords(t.templateMaterial); EditorUtility.SetDirty(t); } EditorGUI.BeginChangeCheck(); #if __MICROSPLAT_PROCTEX__ if (t.keywordSO.IsKeywordEnabled("_PROCEDURALTEXTURE") || t.keywordSO.IsKeywordEnabled("_PCHEIGHTGRADIENT") || t.keywordSO.IsKeywordEnabled("_PCHEIGHTHSV")) { var old = t.procTexCfg; t.procTexCfg = MicroSplatProceduralTexture.FindOrCreateProceduralConfig(t.templateMaterial); if (old != t.procTexCfg) { EditorUtility.SetDirty(t); MicroSplatObject.SyncAll(); } } #endif #if __MICROSPLAT_TERRAINBLEND__ || __MICROSPLAT_STREAMS__ DoTerrainDescGUI(); #endif DoPerPixelNormalGUI(); #if __MICROSPLAT_PROCTEX__ if (t.keywordSO.IsKeywordEnabled(MicroSplatProceduralTexture.GetFeatureName(MicroSplatProceduralTexture.DefineFeature._PCCAVITY)) || t.keywordSO.IsKeywordEnabled(MicroSplatProceduralTexture.GetFeatureName(MicroSplatProceduralTexture.DefineFeature._PCFLOW))) { DoCavityMapGUI(); } #endif // could move this to some type of interfaced component created by the module if this becomes a thing, // but I think this will be most of the cases? MicroSplatUtilities.DrawTextureField(t, CCustomSplat0, ref t.customControl0, "_CUSTOMSPLATTEXTURES"); MicroSplatUtilities.DrawTextureField(t, CCustomSplat1, ref t.customControl1, "_CUSTOMSPLATTEXTURES"); MicroSplatUtilities.DrawTextureField(t, CCustomSplat2, ref t.customControl2, "_CUSTOMSPLATTEXTURES"); MicroSplatUtilities.DrawTextureField(t, CCustomSplat3, ref t.customControl3, "_CUSTOMSPLATTEXTURES"); MicroSplatUtilities.DrawTextureField(t, CCustomSplat4, ref t.customControl4, "_CUSTOMSPLATTEXTURES"); MicroSplatUtilities.DrawTextureField(t, CCustomSplat5, ref t.customControl5, "_CUSTOMSPLATTEXTURES"); MicroSplatUtilities.DrawTextureField(t, CCustomSplat6, ref t.customControl6, "_CUSTOMSPLATTEXTURES"); MicroSplatUtilities.DrawTextureField(t, CCustomSplat7, ref t.customControl7, "_CUSTOMSPLATTEXTURES"); // perpixel normal MicroSplatUtilities.DrawTextureField(t, perPixelNormal, ref t.perPixelNormal, "_PERPIXELNORMAL"); // global texture overrides #if __MICROSPLAT_GLOBALTEXTURE__ MicroSplatUtilities.DrawTextureField(t, geoTexOverride, ref t.geoTextureOverride, "_GEOMAP"); MicroSplatUtilities.DrawTextureField(t, geoTintOverride, ref t.tintMapOverride, "_GLOBALTINT"); MicroSplatUtilities.DrawTextureField(t, geoNormalOverride, ref t.globalNormalOverride, "_GLOBALNORMALS"); MicroSplatUtilities.DrawTextureField(t, geoSAOMOverride, ref t.globalSAOMOverride, "_GLOBALSMOOTHAOMETAL"); MicroSplatUtilities.DrawTextureField(t, geoEmisOverride, ref t.globalEmisOverride, "_GLOBALEMIS"); #endif #if __MICROSPLAT_SNOW__ MicroSplatUtilities.DrawTextureField(t, snowMaskOverride, ref t.snowMaskOverride, "_SNOWMASK"); #endif #if __MICROSPLAT_ALPHAHOLE__ // alpha hole override MicroSplatUtilities.DrawTextureField(t, clipMapOverride, ref t.clipMap, "_ALPHAHOLETEXTURE"); #endif #if (VEGETATION_STUDIO || VEGETATION_STUDIO_PRO) // vsstudio overrides MicroSplatUtilities.DrawTextureField(t, CVSGrassMap, ref t.vsGrassMap, "_VSGRASSMAP"); MicroSplatUtilities.DrawTextureField(t, CVSShadowMap, ref t.vsShadowMap, "_VSSHADOWMAP"); #endif #if __MICROSPLAT_PROCTEX__ MicroSplatUtilities.DrawTextureField(t, biomeOverride, ref t.procBiomeMask, "_PROCEDURALTEXTURE"); #endif #if __MICROSPLAT_STREAMS__ MicroSplatUtilities.DrawTextureField(t, streamOverride, ref t.streamTexture, "_WETNESS", "_PUDDLES", "_STREAMS", "_LAVA", false); #endif #if __MICROSPLAT_ADVANCED_DETAIL__ DrawAdvancedModuleDetailGUI(t); #endif if (t.propData == null && t.templateMaterial != null) { t.propData = MicroSplatShaderGUI.FindOrCreatePropTex(t.templateMaterial); if (t.propData == null) { // this should really never happen, but users seem to have issues with unassigned propData's a lot. I think // this is from external tools like MapMagic not creating it, but the above call should create it. EditorGUILayout.HelpBox("PropData is null, please assign", MessageType.Error); t.propData = EditorGUILayout.ObjectField("Per Texture Data", t.propData, typeof(MicroSplatPropData), false) as MicroSplatPropData; } } if (EditorGUI.EndChangeCheck()) { MicroSplatTerrain.SyncAll(); } EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Sync")) { var mgr = target as MicroSplatTerrain; mgr.Sync(); } if (GUILayout.Button("Sync All")) { MicroSplatTerrain.SyncAll(); } EditorGUILayout.EndHorizontal(); BakingGUI(t); WeightLimitingGUI(t); ImportExportGUI(); #if __MICROSPLAT_ADVANCED_DETAIL__ DrawAdvancedModuleDetailTooset(t); #endif if (MicroSplatUtilities.DrawRollup("Debug", false, true)) { EditorGUI.indentLevel += 2; EditorGUILayout.HelpBox("These should not need to be edited unless something funky has happened. They are automatically managed by MicroSplat.", MessageType.Info); t.propData = EditorGUILayout.ObjectField("Per Texture Data", t.propData, typeof(MicroSplatPropData), false) as MicroSplatPropData; #if __MICROSPLAT_PROCTEX__ t.procTexCfg = EditorGUILayout.ObjectField("Procedural Config", t.procTexCfg, typeof(MicroSplatProceduralTextureConfig), false) as MicroSplatProceduralTextureConfig; #endif t.keywordSO = EditorGUILayout.ObjectField("Keywords", t.keywordSO, typeof(MicroSplatKeywords), false) as MicroSplatKeywords; t.blendMat = EditorGUILayout.ObjectField(CBlendMat, t.blendMat, typeof(Material), false) as Material; t.addPass = EditorGUILayout.ObjectField("Add Pass", t.addPass, typeof(Shader), false) as Shader; EditorGUI.indentLevel -= 2; } if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(t); } }