Skip to content

Commit

Permalink
feat: animation curve copy and paste support
Browse files Browse the repository at this point in the history
  • Loading branch information
witalosk committed Feb 13, 2025
1 parent a3e20e3 commit e4883a7
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,10 @@
{
flex-direction: row;
flex-wrap: wrap;
flex-basis: 33%;
}

.rosettaui-animation-curve-editor__time-value-row > FloatField {
.rosettaui-animation-curve-editor__time-value-row > FloatField
{
flex-basis: 100px;
}

Expand All @@ -120,7 +120,8 @@
min-width: 50px;
}

.rosettaui-animation-curve-editor__time-value-row > EnumField {
.rosettaui-animation-curve-editor__time-value-row > EnumField
{
min-width: 189.5px;
max-width: 100%;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ private void InitControlPoints()
var key = _curve.keys[i];
var controlPoint = new ControlPoint(this, OnControlPointSelected, OnControlPointMoved, RemoveControlPoint);
_controlPoints.Add(controlPoint);
_curvePreviewElement.Add(controlPoint);
_curvePreviewElement.Insert(0, controlPoint);
controlPoint.SetKeyframe(_curve, i);
controlPoint.SetPointMode(key.GetPointMode());
controlPoint.SetTangentMode(_curve.GetInTangentMode(i), _curve.GetOutTangentMode(i));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,14 +222,14 @@ public void SetKeyframe(in AnimationCurve curve, int idx)

float? inWeight = _keyframeCopy.weightedMode is WeightedMode.In or WeightedMode.Both ? _keyframeCopy.inWeight : null;
float? outWeight = _keyframeCopy.weightedMode is WeightedMode.Out or WeightedMode.Both ? _keyframeCopy.outWeight : null;
_leftHandle.SetWeight(inWeight, GetXDistInScreen(curve, idx, idx - 1));
_rightHandle.SetWeight(outWeight, GetXDistInScreen(curve, idx + 1, idx));
_leftHandle.SetWeight(inWeight, GetXDistInScreen(curve, idx - 1, idx));
_rightHandle.SetWeight(outWeight, GetXDistInScreen(curve, idx, idx + 1));
return;

float GetXDistInScreen(in AnimationCurve curve, int leftIdx, int rightIdx)
{
if (rightIdx <= 0 || curve.length <= leftIdx) return 0f;
return _coordinateConverter.GetScreenPosFromCurvePos(curve[leftIdx].GetPosition()).x - _coordinateConverter.GetScreenPosFromCurvePos(curve[rightIdx].GetPosition()).x;
if (leftIdx < 0 || curve.length <= rightIdx) return 0f;
return _coordinateConverter.GetScreenPosFromCurvePos(curve[rightIdx].GetPosition()).x - _coordinateConverter.GetScreenPosFromCurvePos(curve[leftIdx].GetPosition()).x;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@
bool2 isSubGrid = IsGrid(uv, _GridParams.zw * 0.1, 1.0) && frac(_GridParams) > 0.0;
bool isGrid = any(IsGrid(uv, _GridParams.zw, 1.0));
bool2 isMainGrid = IsGrid(uv, _GridParams.zw, 2.0 * cos(frac(_GridParams - EPSILON) * UNITY_PI * 0.5));
col = isSubGrid.x ? float4(GridColor.rgb, 1.0 - frac(_GridParams.x - EPSILON)) : col;
col = isSubGrid.y ? float4(GridColor.rgb, 1.0 - frac(_GridParams.y - EPSILON)) : col;
col = isSubGrid.x ? float4(GridColor.rgb, 1.0 - frac(_GridParams.x)) : col;
col = isSubGrid.y ? float4(GridColor.rgb, 1.0 - frac(_GridParams.y)) : col;
col = isGrid ? GridColor : col;
col = isMainGrid.x ? MainGridColor : col;
col = isMainGrid.y ? MainGridColor : col;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,29 @@ public static void Copy(AnimationCurve src, AnimationCurve dst)
public static Rect GetCurveRect(this AnimationCurve curve, int stepNum = 64)
{
var rect = new Rect();
foreach (var keyframe in curve.keys)
if (curve.keys.Length <= 0) return rect;
for (var i = 0; i < curve.keys.Length; i++)
{
var keyframe = curve.keys[i];
if (i == 0)
{
rect.xMin = keyframe.time;
rect.xMax = keyframe.time;
continue;
}
rect.xMin = Mathf.Min(rect.xMin, keyframe.time);
rect.xMax = Mathf.Max(rect.xMax, keyframe.time);
}

for (int i = 0; i < stepNum; i++)
{
float y = curve.Evaluate(i / (stepNum - 1f));
float y = curve.Evaluate(rect.xMin + i / (stepNum - 1f) * rect.width);
if (i == 0)
{
rect.yMin = y;
rect.yMax = y;
continue;
}
rect.yMin = Mathf.Min(rect.yMin, y);
rect.yMax = Mathf.Max(rect.yMax, y);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ public static Dictionary<string, object> ObjectToDictionary(object obj, string f
#if UNITY_6000_0_OR_NEWER
SerializedPropertyTypeRuntime.RenderingLayerMask => ((RenderingLayerMask)obj).value,
#endif
// SerializedPropertyTypeRuntime.AnimationCurve:
SerializedPropertyTypeRuntime.Enum => SerializeEnum(obj),
SerializedPropertyTypeRuntime.AnimationCurve => SerializeAnimationCurve((AnimationCurve)obj),
SerializedPropertyTypeRuntime.Bounds => SerializeBounds((Bounds)obj),
SerializedPropertyTypeRuntime.Gradient => SerializeGradient((Gradient)obj),
SerializedPropertyTypeRuntime.Quaternion => SerializeQuaternion((Quaternion)obj),
Expand Down Expand Up @@ -200,7 +200,7 @@ private static (bool success, object value) DictionaryToObject_Primitive(Type ty
nameof(RenderingLayerMask) => ToSuccessTuple(new RenderingLayerMask { value =
Convert.ToUInt32(val) }),
#endif
// nameof(AnimationCurve) => { /* res["val"] = WriteCustom(new AnimationCurveWrapper(p.animationCurveValue)); */ },
nameof(AnimationCurve) => ToResultTuple<AnimationCurve>(DeserializeAnimationCurve, val),
nameof(Bounds) => ToResultTuple<Bounds>(DeserializeBounds, val),
nameof(Gradient) => ToResultTuple<Gradient>(DeserializeGradient, val),
nameof(Quaternion) => ToResultTuple<Quaternion>(DeserializeQuaternion, val),
Expand Down
43 changes: 43 additions & 0 deletions Packages/ga.fuquna.rosettaui/Runtime/Clipboard/ClipboardParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public static partial class ClipboardParser
{
public const string PrefixEnum = "Enum:";
public const string PrefixGradient = nameof(UnityEditor) + ".GradientWrapperJSON:";
public const string PrefixAnimationCurve = nameof(UnityEditor) + ".AnimationCurveWrapperJSON:";
public const string PrefixGeneric = "GenericPropertyJSON:";

private delegate bool DeserializeFunc<T>(string text, out T value);
Expand Down Expand Up @@ -47,6 +48,8 @@ public static string Serialize<T>(T value)
nameof(Quaternion) => SerializeQuaternion(To<Quaternion>(ref value)),
nameof(Color) => SerializeColor(To<Color>(ref value)),
nameof(Gradient) => SerializeGradient(To<Gradient>(ref value)),
nameof(AnimationCurve) => SerializeAnimationCurve(To<AnimationCurve>(ref value)),

_ when type.IsEnum => SerializeEnum(value),
_ => SerializeGeneric(in value)
};
Expand Down Expand Up @@ -77,6 +80,7 @@ public static (bool success, T value) Deserialize<T>(string text)
nameof(Quaternion) => (DeserializeQuaternion(text, out var v), From(ref v)),
nameof(Color) => (DeserializeColor(text, out var v), From(ref v)),
nameof(Gradient) => (DeserializeGradient(text, out var v), From(ref v)),
nameof(AnimationCurve) => (DeserializeAnimationCurve(text, out var v), From(ref v)),
_ when type.IsEnum => (DeserializeEnum<T>(text, out var v), v),
_ => (DeserializeGeneric<T>(text, out var v), v)
};
Expand Down Expand Up @@ -309,6 +313,17 @@ public static string SerializeGradient(Gradient gradient)
return $"{PrefixGradient}{JsonUtility.ToJson(wrapper)}";
}

// Gradient
// インスペクタはCustomPrefix付きでEditorJsonUtilityでシリアライズしている
// https://github.com/Unity-Technologies/UnityCsReference/blob/5406f17521a16bb37880960352990229987aa676/Editor/Mono/Clipboard/ClipboardParser.cs#L353
//
// さらにGradientWrapperでかぶせている
public static string SerializeAnimationCurve(AnimationCurve curve)
{
var wrapper = new AnimationCurveWrapper() { curve = curve};
return $"{PrefixAnimationCurve}{JsonUtility.ToJson(wrapper)}";
}

public static bool DeserializeGradient(string text, out Gradient gradient)
{
gradient = new Gradient();
Expand All @@ -331,6 +346,28 @@ public static bool DeserializeGradient(string text, out Gradient gradient)

return true;
}

public static bool DeserializeAnimationCurve(string text, out AnimationCurve curve)
{
curve = new AnimationCurve();
if (string.IsNullOrEmpty(text)) return false;

if (!text.StartsWith(PrefixAnimationCurve, StringComparison.OrdinalIgnoreCase)) return false;

try
{
var wrapper = new AnimationCurveWrapper();
JsonUtility.FromJsonOverwrite(text.Remove(0, PrefixAnimationCurve.Length), wrapper);
curve = wrapper.curve;
}
catch (Exception e)
{
Debug.LogException(e);
return false;
}

return true;
}


[Serializable]
Expand All @@ -339,6 +376,12 @@ private class GradientWrapper
public Gradient gradient;
}

[Serializable]
private class AnimationCurveWrapper
{
public AnimationCurve curve;
}


public static string SerializeGeneric<T>(in T value)
{
Expand Down

0 comments on commit e4883a7

Please sign in to comment.