#if GRIFFIN using Pinwheel.Griffin.BackupTool; using Pinwheel.Griffin.TextureTool; using System.Collections.Generic; using UnityEditor; using UnityEngine; namespace Pinwheel.Griffin.StampTool { [CustomEditor(typeof(GTextureStamper))] public class GTextureStamperInspector : Editor { private GTextureStamper instance; private Dictionary previewTextures; private MaterialPropertyBlock previewPropertyBlock; private const string HISTORY_PREFIX_COLOR = "Stamp AMS"; private const string HISTORY_PREFIX_TEXTURE = "Stamp Splat"; private readonly Vector3[] worldPoints = new Vector3[4]; private readonly Vector2[] normalizedPoints = new Vector2[4]; private readonly Vector3[] worldBox = new Vector3[8]; private void OnEnable() { Undo.undoRedoPerformed += OnUndoRedo; SceneView.duringSceneGui += DuringSceneGUI; instance = target as GTextureStamper; Tools.hidden = true; instance.Internal_UpdateFalloffTexture(); instance.Internal_UpdateLayerTransitionTextures(); previewPropertyBlock = new MaterialPropertyBlock(); GCommon.RegisterBeginRender(OnCameraRender); GCommon.RegisterBeginRenderSRP(OnCameraRenderSRP); GCommon.UpdateMaterials(instance.GroupId); UpdatePreview(); } private void OnDisable() { Undo.undoRedoPerformed -= OnUndoRedo; SceneView.duringSceneGui -= DuringSceneGUI; Tools.hidden = false; GCommon.UnregisterBeginRender(OnCameraRender); GCommon.UnregisterBeginRenderSRP(OnCameraRenderSRP); if (previewTextures != null) { foreach (string k in previewTextures.Keys) { RenderTexture rt = previewTextures[k]; if (rt == null) continue; rt.Release(); Object.DestroyImmediate(rt); } } } private void OnUndoRedo() { if (Selection.activeGameObject != instance.gameObject) return; if (string.IsNullOrEmpty(GUndoCompatibleBuffer.Instance.CurrentBackupName)) return; GBackup.Restore(GUndoCompatibleBuffer.Instance.CurrentBackupName); UpdatePreview(); } private class GBaseGUI { public static readonly GUIContent GROUP_ID = new GUIContent("Group Id", "Id of the terrain group which is edited by this tool"); public static readonly GUIContent ENABLE_TERRAIN_MASK = new GUIContent("Enable Terrain Mask", "Use terrain mask (R) to lock a particular region from editing"); public static readonly GUIContent SHOW_TERRAIN_MASK = new GUIContent("Show Terrain Mask", "Draw an overlay of the terrain mask in the scene view"); } public override void OnInspectorGUI() { EditorGUI.BeginChangeCheck(); instance.GroupId = GEditorCommon.ActiveTerrainGroupPopupWithAllOption(GBaseGUI.GROUP_ID, instance.GroupId); instance.EnableTerrainMask = EditorGUILayout.Toggle(GBaseGUI.ENABLE_TERRAIN_MASK, instance.EnableTerrainMask); if (instance.EnableTerrainMask) { GEditorSettings.Instance.stampTools.showTerrainMask = EditorGUILayout.Toggle(GBaseGUI.SHOW_TERRAIN_MASK, GEditorSettings.Instance.stampTools.showTerrainMask); } DrawInstructionGUI(); DrawTransformGUI(); DrawStampGUI(); DrawStampLayersGUI(); DrawGizmosGUI(); DrawActionGUI(); GEditorCommon.DrawBackupHelpBox(); if (EditorGUI.EndChangeCheck()) { UpdatePreview(); } } public override bool RequiresConstantRepaint() { return false; } private class GInstructionGUI { public static readonly string LABEL = "Instruction"; public static readonly string ID = "texture-stamper-instruction"; public static readonly string INSTRUCTION = "Stamp texture or color onto the terrain surface."; } private void DrawInstructionGUI() { GEditorCommon.Foldout(GInstructionGUI.LABEL, true, GInstructionGUI.ID, () => { EditorGUILayout.LabelField(GInstructionGUI.INSTRUCTION, GEditorCommon.WordWrapItalicLabel); }); } private class GTransformGUI { public static readonly string LABEL = "Transform"; public static readonly string ID = "texture-stamper-transform"; public static readonly GUIContent POSITION = new GUIContent("Position", "Position of the stamper"); public static readonly GUIContent ROTATION = new GUIContent("Rotation", "Rotation of the stamper"); public static readonly GUIContent SCALE = new GUIContent("Scale", "Scale of the stamper"); } private void DrawTransformGUI() { GEditorCommon.Foldout(GTransformGUI.LABEL, true, GTransformGUI.ID, () => { instance.Position = GEditorCommon.InlineVector3Field(GTransformGUI.POSITION, instance.Position); instance.Rotation = Quaternion.Euler(GEditorCommon.InlineVector3Field(GTransformGUI.ROTATION, instance.Rotation.eulerAngles)); instance.Scale = GEditorCommon.InlineVector3Field(GTransformGUI.SCALE, instance.Scale); Vector3 euler = instance.Rotation.eulerAngles; euler = new Vector3(0, euler.y, 0); instance.Rotation = Quaternion.Euler(euler); }); } private class GStampGUI { public static readonly string LABEL = "Stamp"; public static readonly string ID = "texture-stamper-stamp"; public static readonly GUIContent MASK = new GUIContent("Mask", "A texture defines the opacity of the stamper"); public static readonly GUIContent FALLOFF = new GUIContent("Falloff", "Gradually decrease the mask intensity over its edge"); public static readonly GUIContent CHANNEL = new GUIContent("Channel", "Choose the texture to stamp on, Albedo Metallic or Splat Controls"); } private void DrawStampGUI() { GEditorCommon.Foldout(GStampGUI.LABEL, true, GStampGUI.ID, () => { instance.Mask = EditorGUILayout.ObjectField(GStampGUI.MASK, instance.Mask, typeof(Texture2D), false) as Texture2D; EditorGUI.BeginChangeCheck(); instance.Falloff = EditorGUILayout.CurveField(GStampGUI.FALLOFF, instance.Falloff, Color.red, new Rect(0, 0, 1, 1)); if (EditorGUI.EndChangeCheck()) { instance.Internal_UpdateFalloffTexture(); } instance.Channel = (GTextureStampChannel)EditorGUILayout.EnumPopup(GStampGUI.CHANNEL, instance.Channel); }); } private class GLayerGUI { public static readonly string LABEL = "Layers"; public static readonly string ID = "texture-stamper-layer"; public static readonly string LAYER_ID_PREFIX = "texture-stamp-layer"; public static readonly GUIContent ADD_LAYER = new GUIContent("Add Layer"); public static readonly GUIContent MOVE_LAYER_UP = new GUIContent("Move Up"); public static readonly GUIContent MOVE_LAYER_DOWN = new GUIContent("Move Down"); public static readonly GUIContent REMOVE = new GUIContent("Remove"); public static readonly string HEADER_GENERAL = "General"; public static readonly GUIContent IGNORE = new GUIContent("Ignore", "Ignore this layer"); public static readonly GUIContent NAME = new GUIContent("Name", "Display name of this layer"); public static readonly GUIContent VISUALIZE_COLOR = new GUIContent("Visualize Color", "Color to draw a visualize mask in the scene view"); public static readonly string HEADER_ALBEDO_METALLIC_SMOOTHNESS = "AMS"; public static readonly GUIContent COLOR = new GUIContent("Color", "The albedo color to stamp"); public static readonly GUIContent METALLIC = new GUIContent("Metallic", "The metallic value"); public static readonly GUIContent SMOOTHNESS = new GUIContent("Smoothness", "The smoothness value"); public static readonly string HEADER_SPLAT = "Splats"; public static readonly string HEADER_HEIGHT_RULE = "Height Rule"; public static readonly GUIContent BLEND_HEIGHT = new GUIContent("Enable", "Toggle terrain height rule"); public static readonly GUIContent MIN_HEIGHT = new GUIContent("Min", "The minimum height to satisfy the rule"); public static readonly GUIContent MAX_HEIGHT = new GUIContent("Max", "The maximum height to satisfy the rule"); public static readonly GUIContent HEIGHT_TRANSITION = new GUIContent("Transition", "Fade factor for height rule"); public static readonly string HEADER_SLOPE_RULE = "Slope Rule"; public static readonly GUIContent BLEND_SLOPE = new GUIContent("Enable", "Toggle slope/steepness rule"); public static readonly GUIContent NORMAL_MAP_MODE = new GUIContent("Mode", "Choose which normal map to read slope data from"); public static readonly GUIContent MIN_SLOPE = new GUIContent("Min", "Minimum angle between surface normal and the up vector to satisfy the rule"); public static readonly GUIContent MAX_SLOPE = new GUIContent("Max", "Maximum angle between surface normal and the up vector to satisfy the rule"); public static readonly GUIContent SLOPE_TRANSITION = new GUIContent("Transition", "Fade factor for slope rule"); public static readonly string HEADER_NOISE_RULE = "Noise Rule"; public static readonly GUIContent BLEND_NOISE = new GUIContent("Enable", "Toggle noise rule"); public static readonly GUIContent NOISE_ORIGIN = new GUIContent("Origin", "The origin point of the noise map"); public static readonly GUIContent NOISE_FREQUENCY = new GUIContent("Frequency", "Frequency of the noise pattern, higher value gives thicker noise"); public static readonly GUIContent NOISE_OCTAVES = new GUIContent("Octaves", "The number of noise layers to stack on top of each others"); public static readonly GUIContent NOISE_LACUNARITY = new GUIContent("Lacunarity", "The change in frequency of each noise layer"); public static readonly GUIContent NOISE_PERSISTENCE = new GUIContent("Persistence", "The change in amplitude of each noise layer"); public static readonly GUIContent NOISE_REMAP = new GUIContent("Remap", "Remap the generated noise value"); } private void DrawStampLayersGUI() { GEditorCommon.Foldout(GLayerGUI.LABEL, true, GLayerGUI.ID, () => { List layers = instance.Layers; for (int i = 0; i < layers.Count; ++i) { DrawLayer(layers[i], i); } if (layers.Count > 0) { GEditorCommon.Separator(); } if (GUILayout.Button(GLayerGUI.ADD_LAYER)) { GTextureStampLayer layer = GTextureStampLayer.Create(); layers.Add(layer); } }); } private void DrawLayer(GTextureStampLayer layer, int index) { string label = string.Format("Layer: {0} {1}", !string.IsNullOrEmpty(layer.Name) ? layer.Name : index.ToString(), layer.Ignore ? "[Ignored]" : string.Empty); string id = GLayerGUI.LAYER_ID_PREFIX + index; GenericMenu menu = new GenericMenu(); menu.AddItem( GLayerGUI.MOVE_LAYER_UP, false, () => { int layerCount = instance.Layers.Count; int swapIndex = Mathf.Clamp(index - 1, 0, layerCount - 1); bool expand0 = GEditorCommon.GetFoldoutState(GLayerGUI.LAYER_ID_PREFIX + index); bool expand1 = GEditorCommon.GetFoldoutState(GLayerGUI.LAYER_ID_PREFIX + swapIndex); GEditorCommon.SetFoldoutState(GLayerGUI.LAYER_ID_PREFIX + swapIndex, expand0); GEditorCommon.SetFoldoutState(GLayerGUI.LAYER_ID_PREFIX + index, expand1); GUtilities.Swap(instance.Layers, index, swapIndex); UpdatePreview(); }); menu.AddItem( GLayerGUI.MOVE_LAYER_DOWN, false, () => { int layerCount = instance.Layers.Count; int swapIndex = Mathf.Clamp(index + 1, 0, layerCount - 1); bool expand0 = GEditorCommon.GetFoldoutState(GLayerGUI.LAYER_ID_PREFIX + index); bool expand1 = GEditorCommon.GetFoldoutState(GLayerGUI.LAYER_ID_PREFIX + swapIndex); GEditorCommon.SetFoldoutState(GLayerGUI.LAYER_ID_PREFIX + swapIndex, expand0); GEditorCommon.SetFoldoutState(GLayerGUI.LAYER_ID_PREFIX + index, expand1); GUtilities.Swap(instance.Layers, index, swapIndex); UpdatePreview(); }); menu.AddSeparator(null); menu.AddItem( GLayerGUI.REMOVE, false, () => { ConfirmAndRemoveLayerAt(index); }); GEditorCommon.Foldout(label, false, id, () => { EditorGUI.indentLevel -= 1; GEditorCommon.Header(GLayerGUI.HEADER_GENERAL); layer.Ignore = EditorGUILayout.Toggle(GLayerGUI.IGNORE, layer.Ignore); layer.Name = EditorGUILayout.TextField(GLayerGUI.NAME, layer.Name); if (instance.Channel == GTextureStampChannel.AlbedoMetallicSmoothness) { GEditorCommon.Header(GLayerGUI.HEADER_ALBEDO_METALLIC_SMOOTHNESS); layer.Color = EditorGUILayout.ColorField(GLayerGUI.COLOR, layer.Color); layer.Metallic = EditorGUILayout.Slider(GLayerGUI.METALLIC, layer.Metallic, 0f, 1f); layer.Smoothness = EditorGUILayout.Slider(GLayerGUI.SMOOTHNESS, layer.Smoothness, 0f, 1f); } else if (instance.Channel == GTextureStampChannel.Splat) { GEditorCommon.Header(GLayerGUI.HEADER_SPLAT); layer.SplatIndex = GEditorCommon.SplatSetSelectionGrid(instance.GroupId, layer.SplatIndex); } GEditorCommon.Header(GLayerGUI.HEADER_HEIGHT_RULE); layer.BlendHeight = EditorGUILayout.Toggle("Blend Height", layer.BlendHeight); if (layer.BlendHeight) { EditorGUI.indentLevel += 1; layer.MinHeight = EditorGUILayout.FloatField(GLayerGUI.MIN_HEIGHT, layer.MinHeight); layer.MaxHeight = EditorGUILayout.FloatField(GLayerGUI.MAX_HEIGHT, layer.MaxHeight); EditorGUI.BeginChangeCheck(); layer.HeightTransition = EditorGUILayout.CurveField(GLayerGUI.HEIGHT_TRANSITION, layer.HeightTransition, Color.red, new Rect(0, 0, 1, 1)); if (EditorGUI.EndChangeCheck()) { layer.UpdateCurveTextures(); } EditorGUI.indentLevel -= 1; } GEditorCommon.Header(GLayerGUI.HEADER_SLOPE_RULE); layer.BlendSlope = EditorGUILayout.Toggle(GLayerGUI.BLEND_SLOPE, layer.BlendSlope); if (layer.BlendSlope) { EditorGUI.indentLevel += 1; layer.NormalMapMode = (GNormalMapMode)EditorGUILayout.EnumPopup(GLayerGUI.NORMAL_MAP_MODE, layer.NormalMapMode); layer.MinSlope = EditorGUILayout.FloatField(GLayerGUI.MIN_SLOPE, layer.MinSlope); layer.MaxSlope = EditorGUILayout.FloatField(GLayerGUI.MAX_SLOPE, layer.MaxSlope); EditorGUI.BeginChangeCheck(); layer.SlopeTransition = EditorGUILayout.CurveField(GLayerGUI.SLOPE_TRANSITION, layer.SlopeTransition, Color.red, new Rect(0, 0, 1, 1)); if (EditorGUI.EndChangeCheck()) { layer.UpdateCurveTextures(); } EditorGUI.indentLevel -= 1; } GEditorCommon.Header(GLayerGUI.HEADER_NOISE_RULE); layer.BlendNoise = EditorGUILayout.Toggle(GLayerGUI.BLEND_NOISE, layer.BlendNoise); if (layer.BlendNoise) { EditorGUI.indentLevel += 1; layer.NoiseOrigin = GEditorCommon.InlineVector2Field(GLayerGUI.NOISE_ORIGIN, layer.NoiseOrigin); layer.NoiseFrequency = EditorGUILayout.FloatField(GLayerGUI.NOISE_FREQUENCY, layer.NoiseFrequency); layer.NoiseLacunarity = EditorGUILayout.FloatField(GLayerGUI.NOISE_LACUNARITY, layer.NoiseLacunarity); layer.NoisePersistence = EditorGUILayout.Slider(GLayerGUI.NOISE_PERSISTENCE, layer.NoisePersistence, 0.01f, 1f); layer.NoiseOctaves = EditorGUILayout.IntSlider(GLayerGUI.NOISE_OCTAVES, layer.NoiseOctaves, 1, 4); EditorGUI.BeginChangeCheck(); layer.NoiseRemap = EditorGUILayout.CurveField(GLayerGUI.NOISE_REMAP, layer.NoiseRemap, Color.red, new Rect(0, 0, 1, 1)); if (EditorGUI.EndChangeCheck()) { layer.UpdateCurveTextures(); } EditorGUI.indentLevel -= 1; } EditorGUI.indentLevel += 1; }, menu); } private class GRemoveLayerDialogGUI { public static readonly string CONFIRM = "Confirm"; public static readonly string OK = "OK"; public static readonly string CANCEL = "Cancel"; } private void ConfirmAndRemoveLayerAt(int index) { GTextureStampLayer layer = instance.Layers[index]; string layerName = string.IsNullOrEmpty(layer.Name) ? ("Layer " + index) : ("Layer " + layer.Name); if (EditorUtility.DisplayDialog( GRemoveLayerDialogGUI.CONFIRM, "Remove " + layerName + "?", GRemoveLayerDialogGUI.OK, GRemoveLayerDialogGUI.CANCEL)) { instance.Layers.RemoveAt(index); } } private class GGizmosGUI { public static readonly string LABEL = "Gizmos"; public static readonly string ID = "texture-stamper-gizmos"; public static readonly GUIContent LIVE_PREVIEW = new GUIContent("Live Preview", "Draw a preview in the scene view"); public static readonly GUIContent BOUNDS = new GUIContent("Bounds", "Show the stamper bounds in the scene view"); } private void DrawGizmosGUI() { GEditorCommon.Foldout(GGizmosGUI.LABEL, true, GGizmosGUI.ID, () => { GEditorSettings.Instance.stampTools.showLivePreview = EditorGUILayout.Toggle(GGizmosGUI.LIVE_PREVIEW, GEditorSettings.Instance.stampTools.showLivePreview); GEditorSettings.Instance.stampTools.showBounds = EditorGUILayout.Toggle(GGizmosGUI.BOUNDS, GEditorSettings.Instance.stampTools.showBounds); }); } private class GActionGUI { public static readonly string LABEL = "Action"; public static readonly string ID = "texture-stamper-action"; public static readonly GUIContent SNAP_TO_TERRAIN = new GUIContent("Snap To Terrain", "Fit the stamper to the underneath terrain"); public static readonly GUIContent SNAP_TO_LEVEL_BOUNDS = new GUIContent("Snap To Level Bounds", "Fit the stamper to cover all terrains in the level"); public static readonly GUIContent APPLY = new GUIContent("Apply", "Stamp on the terrains"); } private void DrawActionGUI() { GEditorCommon.Foldout(GActionGUI.LABEL, true, GActionGUI.ID, () => { EditorGUILayout.BeginHorizontal(); if (GUILayout.Button(GActionGUI.SNAP_TO_TERRAIN)) { IEnumerator terrains = GStylizedTerrain.ActiveTerrains.GetEnumerator(); while (terrains.MoveNext()) { GStylizedTerrain t = terrains.Current; Bounds b = t.Bounds; Rect r = new Rect(new Vector2(b.min.x, b.min.z), new Vector2(b.size.x, b.size.z)); Vector2 p = new Vector2(instance.Position.x, instance.Position.z); if (r.Contains(p)) { instance.Position = new Vector3(r.center.x, b.min.y, r.center.y); instance.Rotation = Quaternion.identity; instance.Scale = new Vector3(b.size.x, b.size.y, b.size.z); break; } } } if (GUILayout.Button(GActionGUI.SNAP_TO_LEVEL_BOUNDS)) { Bounds b = GCommon.GetLevelBounds(); instance.Position = new Vector3(b.center.x, b.min.y, b.center.z); instance.Rotation = Quaternion.identity; instance.Scale = new Vector3(b.size.x, b.size.y, b.size.z); } EditorGUILayout.EndHorizontal(); if (GUILayout.Button(GActionGUI.APPLY)) { List terrains = GUtilities.ExtractTerrainsFromOverlapTest(GCommon.OverlapTest(instance.GroupId, instance.GetQuad())); CreateInitialBackup(terrains); ApplyStamp(); CreateAfterStampBackup(terrains); } }); } private void CreateInitialBackup(List terrains) { string historyPrefix = instance.Channel == GTextureStampChannel.AlbedoMetallicSmoothness ? HISTORY_PREFIX_COLOR : instance.Channel == GTextureStampChannel.Splat ? HISTORY_PREFIX_TEXTURE : "Unknown Action"; List resourcesFlag = new List(); if (instance.Channel == GTextureStampChannel.AlbedoMetallicSmoothness) { resourcesFlag.Add(GTerrainResourceFlag.AlbedoMap); resourcesFlag.Add(GTerrainResourceFlag.MetallicMap); } else if (instance.Channel == GTextureStampChannel.Splat) { resourcesFlag.Add(GTerrainResourceFlag.SplatControlMaps); } GBackupInternal.TryCreateAndMergeInitialBackup(historyPrefix, terrains, resourcesFlag, true); } private class GStampDialogGUI { public static readonly string TITLE = "Applying"; public static readonly string INFO = "Stamping terrain geometry..."; } private void ApplyStamp() { EditorUtility.DisplayProgressBar(GStampDialogGUI.TITLE, GStampDialogGUI.INFO, 1f); try { instance.Apply(); } catch (System.Exception e) { Debug.LogError(e.ToString()); } EditorUtility.ClearProgressBar(); } private void CreateAfterStampBackup(List terrains) { string historyPrefix = instance.Channel == GTextureStampChannel.AlbedoMetallicSmoothness ? HISTORY_PREFIX_COLOR : instance.Channel == GTextureStampChannel.Splat ? HISTORY_PREFIX_TEXTURE : "Unknown Action"; List resourcesFlag = new List(); if (instance.Channel == GTextureStampChannel.AlbedoMetallicSmoothness) { resourcesFlag.Add(GTerrainResourceFlag.AlbedoMap); resourcesFlag.Add(GTerrainResourceFlag.MetallicMap); } else if (instance.Channel == GTextureStampChannel.Splat) { resourcesFlag.Add(GTerrainResourceFlag.SplatControlMaps); } GBackupInternal.TryCreateAndMergeBackup(historyPrefix, terrains, resourcesFlag, true); } private void DuringSceneGUI(SceneView sv) { EditorGUI.BeginChangeCheck(); HandleEditingTransform(); DrawStampBounds(); if (EditorGUI.EndChangeCheck()) { UpdatePreview(); } } private void HandleEditingTransform() { if (Tools.current == Tool.Move) { instance.Position = Handles.PositionHandle(instance.Position, instance.Rotation); } else if (Tools.current == Tool.Rotate) { instance.Rotation = Handles.RotationHandle(instance.Rotation, instance.Position); Vector3 euler = instance.Rotation.eulerAngles; euler = new Vector3(0, euler.y, 0); instance.Rotation = Quaternion.Euler(euler); } else if (Tools.current == Tool.Scale) { instance.Scale = Handles.ScaleHandle(instance.Scale, instance.Position, instance.Rotation, HandleUtility.GetHandleSize(instance.Position)); } } private void OnCameraRender(Camera cam) { if (instance.Editor_ShowLivePreview) DrawLivePreview(cam); if (instance.EnableTerrainMask) DrawTerrainMask(cam); } private void DrawTerrainMask(Camera cam) { GCommon.ForEachTerrain(instance.GroupId, (t) => { GLivePreviewDrawer.DrawTerrainMask(t, cam); }); } private void OnCameraRenderSRP(UnityEngine.Rendering.ScriptableRenderContext context, Camera cam) { OnCameraRender(cam); } private void DrawLivePreview(Camera cam) { IEnumerator terrains = GStylizedTerrain.ActiveTerrains.GetEnumerator(); while (terrains.MoveNext()) { GStylizedTerrain t = terrains.Current; if (t.TerrainData == null) continue; if (instance.GroupId >= 0 && instance.GroupId != t.GroupId) continue; DrawLivePreview(t, cam); } } private void DrawLivePreview(GStylizedTerrain t, Camera cam) { if (t.transform.rotation != Quaternion.identity || t.transform.lossyScale != Vector3.one) return; instance.GetQuad(worldPoints); for (int i = 0; i < normalizedPoints.Length; ++i) { normalizedPoints[i] = t.WorldPointToUV(worldPoints[i]); } Rect dirtyRect = GUtilities.GetRectContainsPoints(normalizedPoints); if (instance.Channel == GTextureStampChannel.AlbedoMetallicSmoothness) { int albedoResolution = t.TerrainData.Shading.AlbedoMapResolution; FilterMode albedoFilter = t.TerrainData.Shading.AlbedoMapOrDefault.filterMode; int metallicResolution = t.TerrainData.Shading.MetallicMapResolution; FilterMode metallicFilter = t.TerrainData.Shading.MetallicMapOrDefault.filterMode; Texture albedo = GetPreviewTexture(t, "albedo", albedoResolution, albedoFilter); Texture metallic = GetPreviewTexture(t, "metallic", metallicResolution, metallicFilter); GLivePreviewDrawer.DrawAMSLivePreview(t, cam, albedo, metallic, dirtyRect); } else if (instance.Channel == GTextureStampChannel.Splat) { int controlMapResolution = t.TerrainData.Shading.SplatControlResolution; Texture[] controls = new Texture[t.TerrainData.Shading.SplatControlMapCount]; for (int i = 0; i < controls.Length; ++i) { Texture currentControl = t.TerrainData.Shading.GetSplatControlOrDefault(i); controls[i] = GetPreviewTexture(t, "splatControl" + i, controlMapResolution, currentControl.filterMode); } GLivePreviewDrawer.DrawSplatLivePreview(t, cam, controls, dirtyRect); } } private void UpdatePreview() { IEnumerator terrains = GStylizedTerrain.ActiveTerrains.GetEnumerator(); while (terrains.MoveNext()) { GStylizedTerrain t = terrains.Current; if (t.TerrainData == null) continue; if (instance.GroupId >= 0 && instance.GroupId != t.GroupId) continue; if (instance.Channel == GTextureStampChannel.AlbedoMetallicSmoothness) { SetupAlbedoMetallicSmoothnessPreview(t); } else if (instance.Channel == GTextureStampChannel.Splat) { SetupSplatPreview(t); } } } private void SetupSplatPreview(GStylizedTerrain t) { Material mat = t.TerrainData.Shading.MaterialToRender; if (mat == null) return; int controlMapResolution = t.TerrainData.Shading.SplatControlResolution; int controlMapCount = t.TerrainData.Shading.SplatControlMapCount; if (controlMapCount == 0) return; RenderTexture[] rtControls = new RenderTexture[controlMapCount]; for (int i = 0; i < controlMapCount; ++i) { Texture2D splatControl = t.TerrainData.Shading.GetSplatControlOrDefault(i); rtControls[i] = GetPreviewTexture(t, "splatControl" + i, controlMapResolution, splatControl.filterMode); GCommon.ClearRT(rtControls[i]); } instance.Internal_ApplySplat(t, rtControls); previewPropertyBlock.Clear(); } private void SetupAlbedoMetallicSmoothnessPreview(GStylizedTerrain t) { Material mat = t.TerrainData.Shading.MaterialToRender; if (mat == null) return; int albedoResolution = t.TerrainData.Shading.AlbedoMapResolution; RenderTexture previewAlbedo = GetPreviewTexture(t, "albedo", albedoResolution, t.TerrainData.Shading.AlbedoMapOrDefault.filterMode); GCommon.ClearRT(previewAlbedo); int metallicResolution = t.TerrainData.Shading.MetallicMapResolution; RenderTexture previewMetallic = GetPreviewTexture(t, "metallic", metallicResolution, t.TerrainData.Shading.MetallicMapOrDefault.filterMode); GCommon.ClearRT(previewMetallic); instance.Internal_ApplyAlbedoMetallicSmoothness(t, previewAlbedo, previewMetallic); } private RenderTexture GetPreviewTexture(GStylizedTerrain t, string mapName, int resolution, FilterMode filter) { if (previewTextures == null) { previewTextures = new Dictionary(); } string key = string.Format("{0}_{1}", t.GetInstanceID(), mapName); if (!previewTextures.ContainsKey(key) || previewTextures[key] == null) { RenderTexture rt = new RenderTexture(resolution, resolution, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear); rt.wrapMode = TextureWrapMode.Clamp; previewTextures[key] = rt; } else if (previewTextures[key].width != resolution || previewTextures[key].height != resolution) { previewTextures[key].Release(); Object.DestroyImmediate(previewTextures[key]); RenderTexture rt = new RenderTexture(resolution, resolution, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear); rt.wrapMode = TextureWrapMode.Clamp; previewTextures[key] = rt; } previewTextures[key].filterMode = filter; return previewTextures[key]; } private void DrawStampBounds() { if (!instance.Editor_ShowBounds) return; instance.GetBox(worldBox); Vector3[] b = worldBox; Handles.color = Color.yellow; Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual; Handles.DrawLines(new Vector3[] { //bottom quad b[0], b[1], b[1], b[2], b[2], b[3], b[3], b[0], //top quad b[4], b[5], b[5], b[6], b[6], b[7], b[7], b[4], //vertical lines b[0], b[4], b[1], b[5], b[2], b[6], b[3], b[7] }); Handles.zTest = UnityEngine.Rendering.CompareFunction.Always; } } } #endif