Files
Fishing2/Packages/com.waveharmonic.crest/Editor/Scripts/Utility/Shared/TexturePreview.cs
2025-05-10 12:49:47 +08:00

132 lines
4.4 KiB
C#

// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEditor;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using WaveHarmonic.Crest.Internal;
namespace WaveHarmonic.Crest.Editor
{
abstract class TexturePreview : ObjectPreview
{
public static bool AnyActivePreviews { get; private set; }
UnityEditor.Editor _Editor;
RenderTexture _RenderTexture;
RenderTextureDescriptor _OriginalDescriptor = new();
Texture _Current;
protected int _Slice;
bool _First = true;
protected abstract Texture OriginalTexture { get; }
protected virtual Texture ModifiedTexture { get; }
Texture Texture => ModifiedTexture != null ? ModifiedTexture : OriginalTexture;
protected virtual bool Flipped => false;
// Preview complains if not a certain set of formats.
bool Incompatible => !(GraphicsFormatUtility.IsIEEE754Format(Texture.graphicsFormat)
|| GraphicsFormatUtility.IsNormFormat(Texture.graphicsFormat));
public TexturePreview() { }
public override bool HasPreviewGUI()
{
AnyActivePreviews = false;
return OriginalTexture;
}
public override void Cleanup()
{
base.Cleanup();
Object.DestroyImmediate(_Editor);
if (_RenderTexture != null) _RenderTexture.Release();
Object.DestroyImmediate(_RenderTexture);
}
public override void OnPreviewSettings()
{
if (_First && Event.current.type == EventType.Repaint && !Application.isPlaying)
{
// Solves on enter edit mode:
// ArgumentException: Getting control 2's position in a group with only 2 controls when doing repaint
_First = false;
return;
}
if (_Editor != null) _Editor.OnPreviewSettings();
}
public override void OnPreviewGUI(Rect rect, GUIStyle background)
{
AnyActivePreviews = true;
// This check is in original.
if (Event.current.type == EventType.Repaint)
{
background.Draw(rect, false, false, false, false);
}
var descriptor = Texture.GetDescriptor();
if (Helpers.RenderTextureNeedsUpdating(descriptor, _OriginalDescriptor))
{
_OriginalDescriptor = descriptor;
if (Incompatible)
{
descriptor.graphicsFormat = GraphicsFormat.R32G32B32A32_SFloat;
}
Helpers.SafeCreateRenderTexture(ref _RenderTexture, descriptor);
_RenderTexture.Create();
Object.DestroyImmediate(_Editor);
_Editor = UnityEditor.Editor.CreateEditor(_RenderTexture);
// Reset for incompatible copy.
descriptor = _OriginalDescriptor;
}
// Name may change without texture changing (see SWS).
_RenderTexture.name = Texture.name + " (Preview)";
if (Incompatible)
{
var temporary = RenderTexture.GetTemporary(descriptor);
Graphics.CopyTexture(Texture, temporary);
Helpers.Blit(temporary, _RenderTexture);
RenderTexture.ReleaseTemporary(temporary);
}
else
{
Graphics.CopyTexture(Texture, _RenderTexture);
}
_Editor.DrawPreview(rect);
}
#if CREST_DEBUG
public override void OnInteractivePreviewGUI(Rect rect, GUIStyle background)
{
OnPreviewGUI(rect, background);
// Show pixel value in preview.
_Slice = Development.Utility.GetPreviewSlice(_Editor, Texture);
var color = Development.Utility.InspectPixel(rect, OriginalTexture, Flipped, _Slice);
var text = Development.Utility.GetInspectPixelString(color, OriginalTexture);
EditorGUI.DropShadowLabel(new Rect(rect.x, rect.y, rect.width, 40), text);
}
#endif
void Allocate(Texture texture)
{
// LOD with buffered data like foam will recreate every frame freezing controls.
if (_Editor != null && _Current == Texture) return;
_Current = texture;
Object.DestroyImmediate(_Editor);
_Editor = UnityEditor.Editor.CreateEditor(texture);
}
}
}