BITFALL/Assets/Polaris - Low Poly Ecosystem/Polaris - Low Poly Terrain .../Editor/Scripts/SplineTool/GPathPainterInspector.cs

373 lines
16 KiB
C#
Raw Normal View History

2024-03-05 17:34:41 +08:00
#if GRIFFIN
2023-12-30 17:37:48 +08:00
using Pinwheel.Griffin.BackupTool;
2024-03-05 17:34:41 +08:00
using System.Collections;
2023-12-30 17:37:48 +08:00
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
2024-03-05 17:34:41 +08:00
using UnityEngine.Rendering;
using Unity.EditorCoroutines.Editor;
2023-12-30 17:37:48 +08:00
namespace Pinwheel.Griffin.SplineTool
{
[CustomEditor(typeof(GPathPainter))]
public class GPathPainterInspector : Editor
{
private GPathPainter instance;
private Dictionary<string, RenderTexture> previewTextures;
2024-03-05 17:34:41 +08:00
private bool isUrp;
private ScriptableRenderContext urpContext;
2023-12-30 17:37:48 +08:00
private static readonly string HISTORY_PREFIX_ALBEDO_METALLIC = "Make Path Albedo Metallic";
private static readonly string HISTORY_PREFIX_SPLAT = "Make Path Splat";
public void OnEnable()
{
Undo.undoRedoPerformed += OnUndoRedo;
instance = (GPathPainter)target;
instance.Internal_UpdateFalloffTexture();
GCommon.RegisterBeginRender(OnCameraRender);
GCommon.RegisterBeginRenderSRP(OnCameraRenderSRP);
GCommon.UpdateMaterials(instance.SplineCreator.GroupId);
}
private void OnDisable()
{
Undo.undoRedoPerformed -= OnUndoRedo;
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);
}
2024-03-05 17:34:41 +08:00
public override void OnInspectorGUI()
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
DrawBaseGUI();
if (instance.SplineCreator == null)
return;
DrawFalloffGUI();
DrawPathGUI();
DrawActionGUI();
2023-12-30 17:37:48 +08:00
}
2024-03-05 17:34:41 +08:00
private class GBaseGUI
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
public static readonly GUIContent SPLINE_CREATOR = new GUIContent("Spline Creator", "The Spline Creator component this modifier belongs to");
public static readonly GUIContent LIVE_PREVIEW = new GUIContent("Live Preview", "Draw a preview over the terrain");
2023-12-30 17:37:48 +08:00
}
2024-03-05 17:34:41 +08:00
private void DrawBaseGUI()
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
instance.SplineCreator = EditorGUILayout.ObjectField(GBaseGUI.SPLINE_CREATOR, instance.SplineCreator, typeof(GSplineCreator), true) as GSplineCreator;
2023-12-30 17:37:48 +08:00
EditorGUI.BeginChangeCheck();
2024-03-05 17:34:41 +08:00
GEditorSettings.Instance.splineTools.livePreview.pathPainter = EditorGUILayout.Toggle(GBaseGUI.LIVE_PREVIEW, GEditorSettings.Instance.splineTools.livePreview.pathPainter);
2023-12-30 17:37:48 +08:00
if (EditorGUI.EndChangeCheck())
{
2024-03-05 17:34:41 +08:00
EditorUtility.SetDirty(GEditorSettings.Instance);
2023-12-30 17:37:48 +08:00
}
2024-03-05 17:34:41 +08:00
}
2023-12-30 17:37:48 +08:00
2024-03-05 17:34:41 +08:00
private class GFalloffGUI
{
public static readonly string LABEL = "Falloff";
public static readonly string ID = "spline-path-painter-falloff";
2023-12-30 17:37:48 +08:00
2024-03-05 17:34:41 +08:00
public static readonly GUIContent FALL_OFF = new GUIContent("Falloff", "Falloff factor of the spline effect, from the center to the edge");
public static readonly GUIContent FALL_OFF_NOISE = new GUIContent("Falloff Noise", "Noise map in world space to blend with the falloff curve");
public static readonly GUIContent FALL_OFF_NOISE_SIZE = new GUIContent("Falloff Noise Size", "Size of the falloff noise in world space");
}
private void DrawFalloffGUI()
{
GEditorCommon.Foldout(GFalloffGUI.LABEL, false, GFalloffGUI.ID, () =>
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
EditorGUI.BeginChangeCheck();
instance.Falloff = EditorGUILayout.CurveField(GFalloffGUI.FALL_OFF, instance.Falloff, Color.red, new Rect(0, 0, 1, 1));
if (EditorGUI.EndChangeCheck())
{
instance.Internal_UpdateFalloffTexture();
}
instance.FalloffNoise = EditorGUILayout.ObjectField(GFalloffGUI.FALL_OFF_NOISE, instance.FalloffNoise, typeof(Texture2D), false) as Texture2D;
if (instance.FalloffNoise != null)
instance.FalloffNoiseSize = GEditorCommon.InlineVector2Field(GFalloffGUI.FALL_OFF_NOISE_SIZE, instance.FalloffNoiseSize);
});
}
private class GPathGUI
{
public static readonly string LABEL = "Path";
public static readonly string ID = "spline-path-painter-path";
public static readonly GUIContent CHANNEL = new GUIContent("Channel", "The target texture to paint the path on");
public static readonly GUIContent COLOR = new GUIContent("Color", "Color of the path");
public static readonly GUIContent METALLIC = new GUIContent("Metallic", "Metallic value of the path");
public static readonly GUIContent SMOOTHNESS = new GUIContent("Smoothness", "Smoothness value of the path");
public static readonly GUIContent AMS_NOTE = new GUIContent("Use a material that utilizes Albedo & Metallic map to see the result!");
public static readonly GUIContent SPLAT_PROTOTYPE = new GUIContent("Prototype");
public static readonly GUIContent SPLAT_NOTE = new GUIContent("Use a material that utilizes Splat map to see the result!");
}
private void DrawPathGUI()
{
GEditorCommon.Foldout(GPathGUI.LABEL, false, GPathGUI.ID, () =>
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
instance.Channel = (GPathPainter.PaintChannel)EditorGUILayout.EnumPopup(GPathGUI.CHANNEL, instance.Channel);
if (instance.Channel == GPathPainter.PaintChannel.AlbedoAndMetallic)
{
instance.Color = EditorGUILayout.ColorField(GPathGUI.COLOR, instance.Color);
instance.Metallic = EditorGUILayout.Slider(GPathGUI.METALLIC, instance.Metallic, 0f, 1f);
instance.Smoothness = EditorGUILayout.Slider(GPathGUI.SMOOTHNESS, instance.Smoothness, 0f, 1f);
EditorGUILayout.Space();
EditorGUILayout.LabelField(GPathGUI.AMS_NOTE, GEditorCommon.WordWrapItalicLabel);
}
else if (instance.Channel == GPathPainter.PaintChannel.Splat)
{
EditorGUILayout.LabelField(GPathGUI.SPLAT_PROTOTYPE);
instance.SplatIndex = GEditorCommon.SplatSetSelectionGrid(instance.SplineCreator.GroupId, instance.SplatIndex);
EditorGUILayout.Space();
EditorGUILayout.LabelField(GPathGUI.SPLAT_NOTE, GEditorCommon.WordWrapItalicLabel);
}
});
}
private class GActionGUI
{
public static readonly string LABEL = "Action";
public static readonly string ID = "spline-path-painter-action";
public static readonly GUIContent APPLY_BTN = new GUIContent("Apply");
}
private void DrawActionGUI()
{
GEditorCommon.ExpandFoldout(GActionGUI.ID);
GEditorCommon.Foldout(GActionGUI.LABEL, true, GActionGUI.ID, () =>
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
if (GUILayout.Button(GActionGUI.APPLY_BTN))
{
List<GStylizedTerrain> terrains = GUtilities.ExtractTerrainsFromOverlapTest(instance.SplineCreator.SweepTest());
CreateInitialBackup(terrains);
ApplyPath();
CreateBackupAfterApplyPath(terrains);
}
});
2023-12-30 17:37:48 +08:00
}
2024-03-05 17:34:41 +08:00
private void CreateInitialBackup(List<GStylizedTerrain> terrains)
2023-12-30 17:37:48 +08:00
{
string historyPrefix =
instance.Channel == GPathPainter.PaintChannel.AlbedoAndMetallic ? HISTORY_PREFIX_ALBEDO_METALLIC :
instance.Channel == GPathPainter.PaintChannel.Splat ? HISTORY_PREFIX_SPLAT : "Unknown Action";
List<GTerrainResourceFlag> resourceFlag = new List<GTerrainResourceFlag>();
if (instance.Channel == GPathPainter.PaintChannel.AlbedoAndMetallic)
{
resourceFlag.Add(GTerrainResourceFlag.AlbedoMap);
resourceFlag.Add(GTerrainResourceFlag.MetallicMap);
}
else if (instance.Channel == GPathPainter.PaintChannel.Splat)
{
resourceFlag.Add(GTerrainResourceFlag.SplatControlMaps);
}
GBackupInternal.TryCreateAndMergeInitialBackup(historyPrefix, terrains, resourceFlag, true);
}
private void ApplyPath()
{
EditorUtility.DisplayProgressBar("Applying", "Creating path...", 1f);
try
{
instance.Apply();
}
catch (System.Exception e)
{
Debug.LogError(e.ToString());
}
EditorUtility.ClearProgressBar();
}
2024-03-05 17:34:41 +08:00
private void CreateBackupAfterApplyPath(List<GStylizedTerrain> terrains)
2023-12-30 17:37:48 +08:00
{
string historyPrefix =
instance.Channel == GPathPainter.PaintChannel.AlbedoAndMetallic ? HISTORY_PREFIX_ALBEDO_METALLIC :
instance.Channel == GPathPainter.PaintChannel.Splat ? HISTORY_PREFIX_SPLAT : "Unknown Action";
List<GTerrainResourceFlag> resourceFlag = new List<GTerrainResourceFlag>();
if (instance.Channel == GPathPainter.PaintChannel.AlbedoAndMetallic)
{
resourceFlag.Add(GTerrainResourceFlag.AlbedoMap);
resourceFlag.Add(GTerrainResourceFlag.MetallicMap);
}
else if (instance.Channel == GPathPainter.PaintChannel.Splat)
{
resourceFlag.Add(GTerrainResourceFlag.SplatControlMaps);
}
GBackupInternal.TryCreateAndMergeBackup(historyPrefix, terrains, resourceFlag, true);
}
2024-03-05 17:34:41 +08:00
private void OnCameraRender(Camera cam)
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
isUrp = false;
urpContext = default;
if (cam.cameraType != CameraType.SceneView)
return;
if (GEditorSettings.Instance.splineTools.livePreview.pathPainter)
DrawLivePreview(cam);
2023-12-30 17:37:48 +08:00
}
2024-03-05 17:34:41 +08:00
private void OnCameraRenderSRP(UnityEngine.Rendering.ScriptableRenderContext context, Camera cam)
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
isUrp = true;
urpContext = context;
if (cam.cameraType != CameraType.SceneView)
return;
if (GEditorSettings.Instance.splineTools.livePreview.pathPainter)
{
EditorCoroutineUtility.StartCoroutine(IDrawLivePreviewEndOfFrameURP(cam), this);
}
2023-12-30 17:37:48 +08:00
}
2024-03-05 17:34:41 +08:00
private IEnumerator IDrawLivePreviewEndOfFrameURP(Camera cam)
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
yield return new WaitForEndOfFrame();
if (cam != null)
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
DrawLivePreview(cam);
2023-12-30 17:37:48 +08:00
}
}
2024-03-05 17:34:41 +08:00
private void DrawLivePreview(Camera cam)
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
List<GOverlapTestResult> sweepTest = instance.SplineCreator.SweepTest();
for (int i = 0; i < sweepTest.Count; ++i)
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
GOverlapTestResult st = sweepTest[i];
if (!st.IsOverlapped)
continue;
DrawLivePreview(st.Terrain, cam, st.IsChunkOverlapped);
2023-12-30 17:37:48 +08:00
}
2024-03-05 17:34:41 +08:00
}
2023-12-30 17:37:48 +08:00
2024-03-05 17:34:41 +08:00
private void DrawLivePreview(GStylizedTerrain t, Camera cam, bool[] chunkCulling)
{
2023-12-30 17:37:48 +08:00
if (instance.Channel == GPathPainter.PaintChannel.AlbedoAndMetallic)
{
2024-03-05 17:34:41 +08:00
SetupAlbedoMetallicPreview(t, cam, chunkCulling);
2023-12-30 17:37:48 +08:00
}
else if (instance.Channel == GPathPainter.PaintChannel.Splat)
{
2024-03-05 17:34:41 +08:00
SetupSplatPreview(t, cam, chunkCulling);
2023-12-30 17:37:48 +08:00
}
}
2024-03-05 17:34:41 +08:00
private void SetupAlbedoMetallicPreview(GStylizedTerrain t, Camera cam, bool[] chunkCulling)
2023-12-30 17:37:48 +08:00
{
Material mat = t.TerrainData.Shading.MaterialToRender;
if (mat == null)
return;
int albedoResolution = t.TerrainData.Shading.AlbedoMapResolution;
FilterMode albedoFilter = t.TerrainData.Shading.AlbedoMapOrDefault.filterMode;
RenderTexture rtAlbedo = GetPreviewTexture(t, "albedo", albedoResolution, albedoFilter);
2024-03-05 17:34:41 +08:00
if (isUrp)
{
instance.Internal_ApplyAlbedo(t, rtAlbedo, urpContext);
}
else
{
instance.Internal_ApplyAlbedo(t, rtAlbedo);
}
2023-12-30 17:37:48 +08:00
int metallicResolution = t.TerrainData.Shading.MetallicMapResolution;
FilterMode metallicFilter = t.TerrainData.Shading.MetallicMapOrDefault.filterMode;
RenderTexture rtMetallic = GetPreviewTexture(t, "metallic", metallicResolution, metallicFilter);
2024-03-05 17:34:41 +08:00
if (isUrp)
{
instance.Internal_ApplyMetallic(t, rtMetallic, urpContext);
}
else
{
instance.Internal_ApplyMetallic(t, rtMetallic);
}
2023-12-30 17:37:48 +08:00
2024-03-05 17:34:41 +08:00
GLivePreviewDrawer.DrawAMSLivePreview(t, cam, rtAlbedo, rtMetallic, chunkCulling);
2023-12-30 17:37:48 +08:00
}
2024-03-05 17:34:41 +08:00
private void SetupSplatPreview(GStylizedTerrain t, Camera cam, bool[] chunkCulling)
2023-12-30 17:37:48 +08:00
{
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)
{
rtControls[i] = GetPreviewTexture(t, "splatControl" + i, controlMapResolution, t.TerrainData.Shading.GetSplatControlOrDefault(i).filterMode);
}
2024-03-05 17:34:41 +08:00
if (isUrp)
2023-12-30 17:37:48 +08:00
{
2024-03-05 17:34:41 +08:00
instance.Internal_ApplySplat(t, rtControls, urpContext);
}
else
{
instance.Internal_ApplySplat(t, rtControls);
2023-12-30 17:37:48 +08:00
}
2024-03-05 17:34:41 +08:00
GLivePreviewDrawer.DrawSplatLivePreview(t, cam, rtControls, chunkCulling);
2023-12-30 17:37:48 +08:00
}
private RenderTexture GetPreviewTexture(GStylizedTerrain t, string mapName, int resolution, FilterMode filter)
{
if (previewTextures == null)
{
previewTextures = new Dictionary<string, RenderTexture>();
}
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];
}
}
}
2024-03-05 17:34:41 +08:00
#endif