Skip to content

Commit

Permalink
Fix Ramp Editor Undo/Redo
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonMa0012 committed Jul 16, 2024
1 parent b5bded8 commit 2e3af6c
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 73 deletions.
70 changes: 42 additions & 28 deletions Editor/Helper/RampHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using LWGUI.Runtime.LwguiGradient;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;

namespace LWGUI
{
Expand Down Expand Up @@ -33,42 +34,49 @@ public static bool RampEditor(
string rootPath,
int defaultWidth,
int defaultHeight,
out bool doRegisterUndo,
out Texture2D newTexture,
out bool doSave,
out bool doDiscard)
out bool doDiscard
)
{
newTexture = null;
var hasChange = false;
var shouldCreate = false;
var doOpenWindow = false;
var singleButtonWidth = buttonRect.width * 0.25f;
var editRect = new Rect(buttonRect.x + singleButtonWidth * 0, buttonRect.y, singleButtonWidth, buttonRect.height);
var saveRect = new Rect(buttonRect.x + singleButtonWidth * 1, buttonRect.y, singleButtonWidth, buttonRect.height);
var addRect = new Rect(buttonRect.x + singleButtonWidth * 2, buttonRect.y, singleButtonWidth, buttonRect.height);
var discardRect = new Rect(buttonRect.x + singleButtonWidth * 3, buttonRect.y, singleButtonWidth, buttonRect.height);

// Edit button event
EditorGUI.BeginChangeCheck();
LwguiGradientEditorHelper.GradientEditButton(editRect, _iconEdit, gradient, colorSpace, viewChannelMask, timeRange, () =>
{
// if the current edited texture is null, create new one
if (prop.textureValue == null)
EditorGUI.BeginChangeCheck();
LwguiGradientEditorHelper.GradientEditButton(editRect, _iconEdit, gradient, colorSpace, viewChannelMask, timeRange, () =>
{
shouldCreate = true;
Event.current.Use();
}
else
// if the current edited texture is null, create new one
if (prop.textureValue == null)
{
shouldCreate = true;
Event.current.Use();
return false;
}
else
{
doOpenWindow = true;
return true;
}
});
if (EditorGUI.EndChangeCheck())
{
// Undo.RecordObject(prop.textureValue, "Edit Gradient");
hasChange = true;
gradient = LwguiGradientWindow.instance.lwguiGradient;
}

return prop.textureValue != null;
});
if (EditorGUI.EndChangeCheck())
{
hasChange = true;
gradient = LwguiGradientWindow.instance.lwguiGradient;
doRegisterUndo = doOpenWindow;
}

// Create button
if (GUI.Button(addRect, _iconAdd) || shouldCreate)
{
Expand Down Expand Up @@ -102,11 +110,13 @@ public static bool RampEditor(
}

// Save button
var color = GUI.color;
if (isDirty) GUI.color = Color.yellow;
doSave = GUI.Button(saveRect, _iconSave);
GUI.color = color;

{
var color = GUI.color;
if (isDirty) GUI.color = Color.yellow;
doSave = GUI.Button(saveRect, _iconSave);
GUI.color = color;
}

// Discard button
doDiscard = GUI.Button(discardRect, _iconDiscard);

Expand All @@ -115,12 +125,16 @@ public static bool RampEditor(

public static bool HasGradient(AssetImporter assetImporter) { return assetImporter.userData.Contains("#");}

public static LwguiGradient GetGradientFromTexture(Texture texture, out bool isDirty, bool doDiscard = false)
public static LwguiGradient GetGradientFromTexture(Texture texture, out bool isDirty, bool doDiscard = false, bool doRegisterUndo = false)
{
isDirty = false;
if (texture == null) return null;

var assetImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(texture));
if (doRegisterUndo)
{
LwguiGradientWindow.RegisterRampMapUndo(texture, assetImporter);
}
if (assetImporter != null && HasGradient(assetImporter))
{
isDirty = DecodeGradientFromJSON(assetImporter.userData, out var savedGradient, out var editingGradient);
Expand All @@ -142,19 +156,19 @@ public static void SetGradientToTexture(Texture texture, LwguiGradient gradient,
if (texture == null || gradient == null) return;

var texture2D = (Texture2D)texture;
var path = AssetDatabase.GetAssetPath(texture);
var assetImporter = AssetImporter.GetAtPath(path);
VersionControlHelper.Checkout(texture2D);
Undo.RecordObject(texture2D, "LWGUI: Set Gradient To Texture");

LwguiGradientWindow.RegisterRampMapUndo(texture2D, assetImporter);

// Save to texture
var path = AssetDatabase.GetAssetPath(texture);
var pixels = gradient.GetPixels(texture.width, texture.height);
texture2D.SetPixels(pixels);
texture2D.Apply();

// Save gradient JSON to userData
var assetImporter = AssetImporter.GetAtPath(path);
LwguiGradient savedGradient, editingGradient;
DecodeGradientFromJSON(assetImporter.userData, out savedGradient, out editingGradient);
DecodeGradientFromJSON(assetImporter.userData, out var savedGradient, out _);
assetImporter.userData = EncodeGradientToJSON(doSaveToDisk ? gradient : savedGradient, gradient);

// Save texture to disk
Expand Down
5 changes: 3 additions & 2 deletions Editor/ShaderDrawer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,7 @@ public class RampDrawer : SubDrawer
protected ColorSpace _colorSpace;
protected LwguiGradient.ChannelMask _viewChannelMask;
protected LwguiGradient.GradientTimeRange _timeRange;
protected bool _doRegisterUndo;

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

Expand Down Expand Up @@ -988,7 +989,7 @@ public override void DrawProp(Rect position, MaterialProperty prop, GUIContent l
var labelWidth = EditorGUIUtility.labelWidth;
var indentLevel = EditorGUI.indentLevel;

var gradient = RampHelper.GetGradientFromTexture(prop.textureValue, out var isDirty) ?? new LwguiGradient();
var gradient = RampHelper.GetGradientFromTexture(prop.textureValue, out var isDirty, false, _doRegisterUndo) ?? new LwguiGradient();

OnRampPropUpdate(position, prop, label, editor);

Expand All @@ -1011,7 +1012,7 @@ public override void DrawProp(Rect position, MaterialProperty prop, GUIContent l

// Draw Ramp Editor
var hasGradientChanges = RampHelper.RampEditor(buttonRect, prop, ref gradient, _colorSpace, _viewChannelMask, _timeRange,
isDirty, _defaultFileName, _rootPath, (int)_defaultWidth, (int)_defaultHeight,
isDirty, _defaultFileName, _rootPath, (int)_defaultWidth, (int)_defaultHeight, out _doRegisterUndo,
out var newCreatedTexture, out var doSaveGradient, out var doDiscardGradient);

if (newCreatedTexture != null)
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Having been validated through numerous large-scale commercial projects, employin
* [Contribution](#contribution)

<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
<!-- Added by: runner, at: Thu Jul 11 09:14:46 UTC 2024 -->
<!-- Added by: runner, at: Fri May 24 11:12:50 UTC 2024 -->

<!--te-->

Expand All @@ -81,6 +81,8 @@ Having been validated through numerous large-scale commercial projects, employin
- LWGUI 1.x: **Unity 2017.4+**

- LWGUI 2.x: **Unity 2021.3+**
- **Recommended minimum version: Unity 2022.2+, lower versions can be used but may have bugs**

2. Open your project
3. `Window > Package Manager > Add > Add package from git URL` , enter: `https://github.com/JasonMa0012/LWGUI.git`

Expand Down
3 changes: 2 additions & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
* [Contribution](#contribution)

<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
<!-- Added by: runner, at: Thu Jul 11 09:14:46 UTC 2024 -->
<!-- Added by: runner, at: Fri May 24 11:12:51 UTC 2024 -->

<!--te-->

Expand All @@ -78,6 +78,7 @@
1. 确保你的Unity版本兼容LWGUI
- LWGUI 1.x: **Unity 2017.4+**
- LWGUI 2.x: **Unity 2021.3+**
- **推荐的最低版本: Unity 2022.2+, 更低版本虽然能使用但可能有BUG**

2. 打开已有工程
3. (可能需要全局代理)`Window > Package Manager > Add > Add package from git URL` 输入`https://github.com/JasonMa0012/LWGUI.git`
Expand Down
29 changes: 17 additions & 12 deletions Runtime/LwguiGradient/LwguiGradient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,7 @@ public LwguiGradient()

public LwguiGradient(LwguiGradient src)
{
_curves = new List<AnimationCurve>();
for (int c = 0; c < (int)Channel.Num; c++)
_curves.Add(new AnimationCurve());

for (int c = 0; c < src._curves.Count; c++)
{
foreach (var key in src._curves[c].keys)
{
_curves[c].AddKey(key);
}
}
DeepCopyFrom(src);
}

public LwguiGradient(params Keyframe[] keys)
Expand All @@ -108,10 +98,25 @@ public void Clear(ChannelMask channelMask = ChannelMask.All)
{
if (!IsChannelIndexInMask(c, channelMask)) continue;

if (_curves.Count > c) _curves[c].keys = new Keyframe[0];
if (_curves.Count > c) _curves[c].keys = Array.Empty<Keyframe>();
else _curves.Add(new AnimationCurve());
}
}

public void DeepCopyFrom(LwguiGradient src)
{
_curves = new List<AnimationCurve>();
for (int c = 0; c < (int)Channel.Num; c++)
_curves.Add(new AnimationCurve());

for (int c = 0; c < src._curves.Count; c++)
{
foreach (var key in src._curves[c].keys)
{
_curves[c].AddKey(key);
}
}
}

public void SetCurve(AnimationCurve curve, ChannelMask channelMask)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ public override void OnGUI(Rect position, SerializedProperty property, GUIConten
LwguiGradientEditorHelper.GradientField(position, label, property, gradient, colorSpace, viewChannelMask, timeRange);
if (EditorGUI.EndChangeCheck())
{
// Debug.Log(11111111111);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ public static void DrawGradientWithBackground(Rect position, LwguiGradient gradi
public static void GradientField(Rect position, GUIContent label, LwguiGradient gradient,
ColorSpace colorSpace = ColorSpace.Gamma,
LwguiGradient.ChannelMask viewChannelMask = LwguiGradient.ChannelMask.All,
LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One)
LwguiGradient.GradientTimeRange timeRange = LwguiGradient.GradientTimeRange.One,
Action onOpenWindow = null)
{
int id = GUIUtility.GetControlID(s_LwguiGradientHash, FocusType.Keyboard, position);
var rect = EditorGUI.PrefixLabel(position, id, label);
Expand All @@ -60,6 +61,7 @@ public static void GradientField(Rect position, GUIContent label, LwguiGradient
s_LwguiGradientID = id;
GUIUtility.keyboardControl = id;
LwguiGradientWindow.Show(gradient, colorSpace, viewChannelMask, timeRange, GUIView.current);
onOpenWindow?.Invoke();
GUIUtility.ExitGUI();
}
else if (evt.button == 1)
Expand All @@ -75,27 +77,30 @@ public static void GradientField(Rect position, GUIContent label, LwguiGradient
{
evt.Use();
LwguiGradientWindow.Show(gradient, colorSpace, viewChannelMask, timeRange, GUIView.current);
onOpenWindow?.Invoke();
GUIUtility.ExitGUI();
}

break;
case EventType.Repaint:
DrawGradientWithBackground(rect, gradient, colorSpace, viewChannelMask);
// var previewRect = new Rect(rect.x + 2.5f, rect.y + 2.5f, rect.width - 5.0f, rect.height - 5.0f);
// EditorGUI.DrawPreviewTexture(previewRect, gradient.GetPreviewRampTexture(256, 1, colorSpace, viewChannelMask));
// var outlineRect = new Rect(rect.x + 0.5f, rect.y + 0.5f, rect.width - 1.0f, rect.height - 1.0f);
// EditorStyles.colorPickerBox.Draw(outlineRect, GUIContent.none, id);
break;
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.Use();
GUI.changed = true;
HandleUtility.Repaint();
}
break;
case EventType.ValidateCommand:
// Sync Undo/Redo result to editor window
if (s_LwguiGradientID == id && evt.commandName == "UndoRedoPerformed")
{
LwguiGradientWindow.UpdateCurrentGradient(gradient);
}
break;
}
}

Expand All @@ -108,14 +113,13 @@ public static void GradientField(Rect position, GUIContent label, SerializedProp
label = EditorGUI.BeginProperty(position, label, property);
EditorGUI.BeginChangeCheck();

GradientField(position, label, gradient, colorSpace, viewChannelMask, timeRange);
GradientField(position, label, gradient, colorSpace, viewChannelMask, timeRange,
() => LwguiGradientWindow.RegisterSerializedObjectUndo(property.serializedObject.targetObject));

if (EditorGUI.EndChangeCheck())
{
GUI.changed = true;
// TODO: Undo/Redo
// Undo.RecordObject(property.serializedObject.targetObject, "Editing Lwgui Gradient");
property.serializedObject.UpdateIfRequiredOrScript();
LwguiGradientWindow.RegisterSerializedObjectUndo(property.serializedObject.targetObject);
}
EditorGUI.EndProperty();
}
Expand All @@ -138,6 +142,14 @@ public static bool GradientEditButton(Rect position, GUIContent icon, LwguiGradi
HandleUtility.Repaint();
}

// Sync Undo/Redo result to editor window
if (s_LwguiGradientID == id
&& evt.commandName == "UndoRedoPerformed")
{
LwguiGradientWindow.UpdateCurrentGradient(gradient);
}

// Open editor window
var clicked = ReflectionHelper.GUI_Button(position, id, icon, GUI.skin.button);
if (clicked)
{
Expand Down
Loading

0 comments on commit 2e3af6c

Please sign in to comment.