Skip to content

Commit

Permalink
Merge pull request #61 from JasonMa0012/2.x
Browse files Browse the repository at this point in the history
Add LwguiGradient preview caches
  • Loading branch information
JasonMa0012 authored Aug 27, 2024
2 parents 2438c8b + e182fb8 commit 8c0dbef
Show file tree
Hide file tree
Showing 7 changed files with 154 additions and 31 deletions.
13 changes: 8 additions & 5 deletions Editor/ShaderDrawer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,10 @@ public class RampDrawer : SubDrawer

private static readonly GUIContent _iconMixImage = EditorGUIUtility.IconContent("darkviewbackground");

protected override float GetVisibleHeight(MaterialProperty prop) { return EditorGUIUtility.singleLineHeight * 2f; }
private static readonly float _rampPreviewHeight = EditorGUIUtility.singleLineHeight;
private static readonly float _rampButtonsHeight = EditorGUIUtility.singleLineHeight;

protected override float GetVisibleHeight(MaterialProperty prop) { return _rampPreviewHeight + _rampButtonsHeight; }

public RampDrawer() : this(String.Empty) { }

Expand Down Expand Up @@ -994,7 +997,7 @@ public override void DrawProp(Rect position, MaterialProperty prop, GUIContent l
// Draw Label
var labelRect = new Rect(position); //EditorGUILayout.GetControlRect();
{
labelRect.yMax -= position.height * 0.5f;
labelRect.height = _rampPreviewHeight;
EditorGUI.PrefixLabel(labelRect, label);
}

Expand All @@ -1003,7 +1006,7 @@ public override void DrawProp(Rect position, MaterialProperty prop, GUIContent l
{
EditorGUIUtility.labelWidth = 0;
EditorGUI.indentLevel = 0;
buttonRect.yMin += position.height * 0.5f;
buttonRect.yMin = buttonRect.yMax - _rampPreviewHeight;
buttonRect = MaterialEditor.GetRectAfterLabelWidth(buttonRect);
if (buttonRect.width < 50f) return;
}
Expand Down Expand Up @@ -1043,7 +1046,7 @@ public override void DrawProp(Rect position, MaterialProperty prop, GUIContent l

// Texture object field, handle switch texture event
var rampFieldRect = MaterialEditor.GetRectAfterLabelWidth(labelRect);
var previewRect = new Rect(rampFieldRect.x + 1, rampFieldRect.y + 1, rampFieldRect.width - 19, rampFieldRect.height - 2);
var previewRect = new Rect(rampFieldRect.x + 0.5f, rampFieldRect.y + 0.5f, rampFieldRect.width - 18, rampFieldRect.height - 0.5f);
{
var selectButtonRect = new Rect(previewRect.xMax, rampFieldRect.y, rampFieldRect.width - previewRect.width, rampFieldRect.height);
RampHelper.RampSelector(selectButtonRect, _rootPath, OnSwitchRampMapEvent);
Expand All @@ -1068,7 +1071,7 @@ public override void DrawProp(Rect position, MaterialProperty prop, GUIContent l
GUI.Label(new Rect(previewRect.x + previewRect.width * 0.5f - 10, previewRect.y, previewRect.width * 0.5f, previewRect.height), "");
}
else if (prop.textureValue != null)
EditorGUI.DrawPreviewTexture(previewRect, prop.textureValue);
LwguiGradientEditorHelper.DrawGradientWithSeparateAlphaChannel(previewRect, gradient, _colorSpace, _viewChannelMask);
}

EditorGUIUtility.labelWidth = labelWidth;
Expand Down
52 changes: 43 additions & 9 deletions Runtime/LwguiGradient/LwguiGradient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace LWGUI.Runtime.LwguiGradient
{
[Serializable]
public class LwguiGradient
public class LwguiGradient : IDisposable
{
#region Channel Enum

Expand Down Expand Up @@ -113,6 +113,29 @@ public LwguiGradient(Color[] colors, float[] times)

#endregion

public int GetValueBasedHashCode()
{
var hash = 17;

if (_curves != null)
{
foreach (var curve in _curves)
{
if (curve != null)
{
hash = hash * 23 + curve.GetHashCode();
}
}
}

return hash;
}

public void Dispose()
{
_curves?.Clear();
}

public void Clear(ChannelMask channelMask = ChannelMask.All)
{
_curves ??= new List<AnimationCurve>();
Expand All @@ -133,7 +156,7 @@ public void DeepCopyFrom(LwguiGradient src)
if (_curves.Count == c)
_curves.Add(new AnimationCurve());

_curves[c].keys = new Keyframe[0];
_curves[c].keys = Array.Empty<Keyframe>();
}

for (int c = 0; c < src._curves.Count; c++)
Expand Down Expand Up @@ -270,12 +293,18 @@ public Color[] GetPixels(int width, int height, ChannelMask channelMask = Channe

public Texture2D GetPreviewRampTexture(int width = 256, int height = 1, ColorSpace colorSpace = ColorSpace.Gamma, ChannelMask channelMask = ChannelMask.All)
{
var ramp = new Texture2D(width, height, TextureFormat.RGBA32, false, colorSpace == ColorSpace.Linear);
if (LwguiGradientHelper.TryGetRampPreview(this, width, height, colorSpace, channelMask, out var cachedPreview))
return cachedPreview;

var rampPreview = new Texture2D(width, height, TextureFormat.RGBA32, false, colorSpace == ColorSpace.Linear);
var pixels = GetPixels(width, height, channelMask);
ramp.SetPixels(pixels);
ramp.wrapMode = TextureWrapMode.Clamp;
ramp.Apply();
return ramp;
rampPreview.SetPixels(pixels);
rampPreview.wrapMode = TextureWrapMode.Clamp;
rampPreview.name = "LWGUI Gradient Preview";
rampPreview.Apply();

LwguiGradientHelper.SetRampPreview(this, width, height, colorSpace, channelMask, rampPreview);
return rampPreview;
}

#endregion
Expand All @@ -296,7 +325,7 @@ public LwguiKeyframe(float time, float value, int index)
}
}

public class LwguiMergedColorCurves
public class LwguiMergedColorCurves : IDisposable
{
public List<List<LwguiKeyframe>> curves = new ();

Expand Down Expand Up @@ -403,7 +432,12 @@ public List<AnimationCurve> ToAnimationCurves()
public LwguiGradient ToLwguiGradient()
{
return new LwguiGradient(ToAnimationCurves());
}
}

public void Dispose()
{
curves?.Clear();
}
}

public static LwguiGradient FromGradient(Gradient gradient)
Expand Down
58 changes: 58 additions & 0 deletions Runtime/LwguiGradient/LwguiGradientHelper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright (c) Jason Ma

using System.Collections.Generic;
using System.Linq;
using UnityEngine;

// Disable Keyframe.tangentMode obsolete warning
Expand All @@ -10,6 +12,8 @@ namespace LWGUI.Runtime.LwguiGradient
{
public static class LwguiGradientHelper
{
#region Extended Methods

public static Keyframe SetLinearTangentMode(this Keyframe key)
{
key.tangentMode = 69;
Expand All @@ -29,5 +33,59 @@ public static void SetLinearTangents(this AnimationCurve curve)
curve.MoveKey(i, keyEnd);
}
}

public static void DestroyInEditorOrRuntime(this UnityEngine.Object obj)
{
#if UNITY_EDITOR
Object.DestroyImmediate(obj);
#else
Object.Destroy(obj);
#endif
}

#endregion

#region Ramp Preview Caches

private static Dictionary<int/* LwguiGradient Value Based Hash */,
Dictionary<(int, int, ColorSpace, LwguiGradient.ChannelMask), Texture2D>> _gradientToPreviewDic;

public static bool TryGetRampPreview(LwguiGradient gradient, int width, int height, ColorSpace colorSpace, LwguiGradient.ChannelMask channelMask,
out Texture2D cachedPreview)
{
cachedPreview = _gradientToPreviewDic?.GetValueOrDefault(gradient.GetValueBasedHashCode())?.GetValueOrDefault((width, height, colorSpace, channelMask));
return cachedPreview;
}

public static void SetRampPreview(LwguiGradient gradient, int width, int height, ColorSpace colorSpace, LwguiGradient.ChannelMask channelMask, Texture2D newPreviewTex)
{
_gradientToPreviewDic ??= new Dictionary<int, Dictionary<(int, int, ColorSpace, LwguiGradient.ChannelMask), Texture2D>>();
var hash = gradient.GetValueBasedHashCode();

if (!_gradientToPreviewDic.ContainsKey(hash))
{
_gradientToPreviewDic[hash] = new Dictionary<(int, int, ColorSpace, LwguiGradient.ChannelMask), Texture2D>();
}

if (_gradientToPreviewDic[hash].ContainsKey((width, height, colorSpace, channelMask)))
{
_gradientToPreviewDic[hash][(width, height, colorSpace, channelMask)].DestroyInEditorOrRuntime();
}

_gradientToPreviewDic[hash][(width, height, colorSpace, channelMask)] = newPreviewTex;
}

public static void ClearRampPreviewCaches()
{
if (_gradientToPreviewDic == null) return;

foreach (var paramsToPreviewTexDic in _gradientToPreviewDic.Values)
{
paramsToPreviewTexDic.Values.ToList().ForEach(previewTex => previewTex.DestroyInEditorOrRuntime());
}
_gradientToPreviewDic.Clear();
}

#endregion
}
}
51 changes: 36 additions & 15 deletions UnityEditorExtension/LwguiGradientEditor/LwguiGradientEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ private void OnGradientEditorGUI()
ApplyGradientChangesToCurve();
}

SyncSelectionFromGradientToCurve();
SyncSelectionFromGradientToCurveWithoutChanges();
}
}

Expand Down Expand Up @@ -503,20 +503,23 @@ private void ApplyGradientChangesToCurve()
foreach (var curveSelection in _selectedCurves.Where(selection => LwguiGradient.IsChannelIndexInMask(selection.curveID, viewChannelMask)))
{
var cw = _curveEditor.animationCurves[curveSelection.curveID];
var key = cw.curve.keys[curveSelection.key];
var selectedKey = cw.curve.keys[curveSelection.key];
if (rgbKeyCountEqual && alphaKeyCountEqual)
{
{
var newKey = selectedKey;

// Change a key time
if (_selectedGradientKey.m_Time != _lastSelectedGradientKey.m_Time)
{
key.time = _selectedGradientKey.m_Time;
newKey.time = _selectedGradientKey.m_Time;
}
// Change a key value
else if (_selectedGradientKey.m_Value != _lastSelectedGradientKey.m_Value)
{
key.value = _selectedGradientKey.m_IsAlpha ? _selectedGradientKey.m_Value.r : _selectedGradientKey.m_Value[curveSelection.curveID];
newKey.value = _selectedGradientKey.m_IsAlpha ? _selectedGradientKey.m_Value.r : _selectedGradientKey.m_Value[curveSelection.curveID];
}
curveSelection.key = cw.MoveKey(curveSelection.key, ref key);
newKey = CheckNewKeyTime(cw, newKey, selectedKey.time);
curveSelection.key = cw.MoveKey(curveSelection.key, ref newKey);
}
else
{
Expand All @@ -525,7 +528,7 @@ private void ApplyGradientChangesToCurve()
{
_deletedGradientKey = new GradientEditor.Swatch(_selectedGradientKey.m_Time, _selectedGradientKey.m_Value, _selectedGradientKey.m_IsAlpha);
_deletedCurveKeys ??= new List<Keyframe>(new Keyframe[(int)LwguiGradient.Channel.Num]);
_deletedCurveKeys[curveSelection.curveID] = key;
_deletedCurveKeys[curveSelection.curveID] = selectedKey;
}

// Del a key
Expand Down Expand Up @@ -559,16 +562,18 @@ private void ApplyGradientChangesToCurve()
&& _selectedGradientKey?.m_Value == _deletedGradientKey?.m_Value
&& _selectedGradientKey?.m_IsAlpha == _deletedGradientKey?.m_IsAlpha)
{
var key = _deletedCurveKeys[c];
key.time = _selectedGradientKey.m_Time;
curveSelections.Add(new CurveSelection(c, cw.AddKey(key), CurveSelection.SelectionType.Key));
var deletedKey = _deletedCurveKeys[c];
var newKey = deletedKey;
newKey.time = _selectedGradientKey.m_Time;
newKey = CheckNewKeyTime(cw, newKey, deletedKey.time);
var addedKeyIndex = cw.AddKey(newKey);
curveSelections.Add(new CurveSelection(c, addedKeyIndex, CurveSelection.SelectionType.Key));
}
// Add a new key
else
{
var curveSelection = _curveEditor.AddKeyAtTime(cw, _selectedGradientKey.m_Time);
curveSelections.Add(curveSelection);
// _curveMenuManager.SetBothLinear(new List<KeyIdentifier>(){ new KeyIdentifier(_curveEditor.animationCurves[curveSelection.curveID].curve, curveSelection.curveID, curveSelection.key) });
}

cw.selected = CurveWrapper.SelectionMode.Selected;
Expand All @@ -585,6 +590,22 @@ private void ApplyGradientChangesToCurve()

_curveEditor.InvalidateSelectionBounds();
InitCurveEditor(true);

// Cannot overlap with the Time of an existing Key when adding or moving Keys
Keyframe CheckNewKeyTime(CurveWrapper cw, Keyframe newKey, float oldKeyTime = 0)
{
try
{
var sameTimeKey = cw.curve.keys.First(keyframe => keyframe.time == newKey.time);
if (newKey.time > oldKeyTime)
newKey.time += 0.00001f;
else
newKey.time -= 0.00001f;
}
catch (InvalidOperationException ex) { }

return newKey;
}
}

private void PrepareSyncSelectionFromGradientToCurve()
Expand All @@ -594,7 +615,7 @@ private void PrepareSyncSelectionFromGradientToCurve()
_lastGradientAlphaSwatchesCount = _gradientAlphaSwatches.Count;
}

private void SyncSelectionFromGradientToCurve()
private void SyncSelectionFromGradientToCurveWithoutChanges()
{
// Only detect when switching selected Key without modifying it
if (!_gradientEditorRect.Contains(Event.current.mousePosition)
Expand All @@ -606,7 +627,7 @@ private void SyncSelectionFromGradientToCurve()

if (_selectedGradientKey == null)
{
_selectedCurves = null;
_curveEditor.SelectNone();
return;
}

Expand All @@ -626,7 +647,7 @@ private void SyncSelectionFromGradientToCurve()
}

// Get curve key index
_selectedCurves.Clear();
_curveEditor.SelectNone();
var lwguiMergedCurves = new LwguiGradient.LwguiMergedColorCurves(lwguiGradient.rawCurves);
for (int c = 0; c < (int)LwguiGradient.Channel.Num; c++)
{
Expand Down Expand Up @@ -678,7 +699,7 @@ private void InitCurveEditor(bool force = false)
if (firstOpenWindow)
{
_curveEditor.Frame(new Bounds(new Vector2(0.5f, 0.5f), Vector2.one), true, true);
_selectedCurves = null;
_curveEditor.SelectNone();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public static void GradientField(Rect position, GUIContent label, LwguiGradient
int id = GUIUtility.GetControlID(s_LwguiGradientHash, FocusType.Keyboard, position);
var rect = EditorGUI.PrefixLabel(position, id, label);
var evt = Event.current;


// internal static Gradient DoGradientField(Rect position, int id, Gradient value, SerializedProperty property, bool hdr, ColorSpace space)
switch (evt.GetTypeForControl(id))
Expand Down Expand Up @@ -113,9 +114,10 @@ public static void GradientField(Rect position, GUIContent label, LwguiGradient
case EventType.ExecuteCommand:
// When drawing the modifying Gradient Field and it has changed
if ((GUIUtility.keyboardControl == id || s_LwguiGradientID == id)
&& evt.commandName == LwguiGradientWindow.LwguiGradientChangedCommand)
&& (evt.commandName is LwguiGradientWindow.LwguiGradientChangedCommand))
{
GUI.changed = true;
LwguiGradientHelper.ClearRampPreviewCaches();
HandleUtility.Repaint();
}
break;
Expand Down
Loading

0 comments on commit 8c0dbef

Please sign in to comment.