Skip to content

Commit

Permalink
feat: animation curve handle
Browse files Browse the repository at this point in the history
  • Loading branch information
witalosk committed Jan 31, 2025
1 parent a4e4727 commit c82c587
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UIElements;

Expand Down Expand Up @@ -182,6 +181,8 @@ private void InitUI()
UpdateView();
onCurveChanged?.Invoke(_curve);
});

UpdateFields();
}

/// <summary>
Expand All @@ -192,6 +193,7 @@ public void SetCurve(AnimationCurve curve)
{
_curve = curve;
UpdateView();

}

/// <summary>
Expand Down Expand Up @@ -237,6 +239,10 @@ private void UpdateControlPoints()
{
_selectedControlPointIndex = _controlPoints.IndexOf(cp);
UpdateFields();
foreach (var c in _controlPoints)
{
c.SetActive(c == cp);
}
},
(newPos, it, ot) =>
{
Expand Down Expand Up @@ -310,6 +316,14 @@ private void MoveKey(Keyframe key)

private void UpdateFields()
{
if (_selectedControlPointIndex < 0)
{
_timeField.style.visibility = Visibility.Hidden;
_valueField.style.visibility = Visibility.Hidden;
return;
}
_timeField.style.visibility = Visibility.Visible;
_valueField.style.visibility = Visibility.Visible;
_timeField.SetValueWithoutNotify(_curve.keys[_selectedControlPointIndex].time);
_valueField.SetValueWithoutNotify(_curve.keys[_selectedControlPointIndex].value);
}
Expand All @@ -327,6 +341,15 @@ private void OnMouseDown(MouseDownEvent evt)

evt.StopPropagation();
}
else if (_mouseButton == 0)
{
_selectedControlPointIndex = -1;
UpdateFields();
foreach (var c in _controlPoints)
{
c.SetActive(false);
}
}
}

private void OnMouseMove(MouseMoveEvent evt)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class AnimationCurveEditorControlPoint : VisualElement
private AnimationCurveEditorControlPointHandle _leftHandle;
private AnimationCurveEditorControlPointHandle _rightHandle;

private Vector2 _position;
private float _inTangent;
private float _outTangent;

Expand All @@ -31,9 +32,38 @@ public AnimationCurveEditorControlPoint(Action<AnimationCurveEditorControlPoint>
_onPointMoved = onPointMoved;

// Handles
_leftHandle = new AnimationCurveEditorControlPointHandle(0f);
_leftHandle = new AnimationCurveEditorControlPointHandle(180f, () => _onPointSelected(this), angle =>
{
angle = Mathf.Clamp(Mathf.Abs(angle), 90f, 180f) * Mathf.Sign(angle);
_inTangent = angle switch
{
90f => float.PositiveInfinity,
-90f => float.NegativeInfinity,
_ => Mathf.Tan(angle * Mathf.Deg2Rad)
};

_onPointMoved.Invoke(
_position,
_inTangent,
_outTangent
);
});
Add(_leftHandle);
_rightHandle = new AnimationCurveEditorControlPointHandle(180f);
_rightHandle = new AnimationCurveEditorControlPointHandle(0f, () => _onPointSelected(this), angle =>
{
angle = Mathf.Clamp(angle, -90f, 90f);
_outTangent = angle switch
{
90f => float.PositiveInfinity,
-90f => float.NegativeInfinity,
_ => Mathf.Tan(angle * Mathf.Deg2Rad)
};
_onPointMoved.Invoke(
_position,
_inTangent,
_outTangent
);
});
Add(_rightHandle);

// Control point
Expand All @@ -47,10 +77,28 @@ public AnimationCurveEditorControlPoint(Action<AnimationCurveEditorControlPoint>
_controlPoint.style.height = ControlPointSize;
}

public void SetActive(bool active)
{
if (active)
{
_controlPoint.style.backgroundColor = new StyleColor(Color.white);
_leftHandle.style.visibility = Visibility.Visible;
_rightHandle.style.visibility = Visibility.Visible;
}
else
{
_controlPoint.style.backgroundColor = new StyleColor(Color.green);
_leftHandle.style.visibility = Visibility.Hidden;
_rightHandle.style.visibility = Visibility.Hidden;
}
}

public void SetPosition(float x, float y, float leftTan, float rightTan)
{

style.left = x - ControlPointSize * 0.5f;
style.top = y - ControlPointSize * 0.5f;
_position = Vector2.up + new Vector2(x, -y) / parent.layout.size;
_leftHandle.SetAngle(Mathf.Atan(leftTan) * Mathf.Rad2Deg);
_rightHandle.SetAngle(180f + Mathf.Atan(rightTan) * Mathf.Rad2Deg);
_inTangent = leftTan;
Expand Down Expand Up @@ -84,9 +132,9 @@ private void SetMousePosition(Vector2 mousePosition)
{
style.left = _elementPositionOnDown.x + (mousePosition.x - _mouseDownPosition.x);
style.top = _elementPositionOnDown.y + (mousePosition.y - _mouseDownPosition.y);
_position = Vector2.up + new Vector2(style.left.value.value, -style.top.value.value) / parent.layout.size;
_onPointMoved.Invoke(
Vector2.up + new Vector2(style.left.value.value,
-style.top.value.value) / parent.layout.size,
_position,
_inTangent,
_outTangent
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using UnityEngine;
using System;
using UnityEngine;
using UnityEngine.UIElements;

namespace RosettaUI.UIToolkit
Expand All @@ -9,9 +10,13 @@ public class AnimationCurveEditorControlPointHandle : VisualElement
private VisualElement _handleElement;

private Vector2 _mouseDownPosition;
private Action _onHandleSelected;
private Action<float> _onAngleChanged;

public AnimationCurveEditorControlPointHandle(float angle)
public AnimationCurveEditorControlPointHandle(float angle, Action onHandleSelected, Action<float> onAngleChanged)
{
_onHandleSelected = onHandleSelected;
_onAngleChanged = onAngleChanged;
AddToClassList("rosettaui-animation-curve-editor__control-point-handle");
InitUI();
SetAngle(angle);
Expand All @@ -26,18 +31,19 @@ private void InitUI()
_handleElement = new VisualElement();
_handleElement.AddToClassList("rosettaui-animation-curve-editor__control-point-handle__handle");
_lineElement.Add(_handleElement);
_handleElement.RegisterCallback<MouseDownEvent>(OnMouseDown);
_handleElement.RegisterCallback<PointerDownEvent>(OnPointerDown);
}

public void SetAngle(float angle)
{
_lineElement.style.rotate = new StyleRotate(new Rotate(Angle.Degrees(180f - angle)));
if (Mathf.Approximately(Mathf.Abs(angle), 90f)) angle *= -1f;
_lineElement.transform.rotation = Quaternion.AngleAxis(angle + 180f, Vector3.back);
}

private void OnMouseDown(MouseDownEvent evt)
private void OnPointerDown(PointerDownEvent evt)
{
if (evt.button != 0) return;
_mouseDownPosition = evt.mousePosition;
_onHandleSelected?.Invoke();
_handleElement.CaptureMouse();
_handleElement.RegisterCallback<PointerMoveEvent>(OnPointerMove);
_handleElement.RegisterCallback<PointerLeaveEvent>(OnPointerLeave);
Expand All @@ -49,8 +55,11 @@ private void OnPointerMove(PointerMoveEvent evt)
{
var centerPoint = parent.LocalToWorld(Vector2.one * 0.5f);
var mousePoint = evt.position;
var angle = Mathf.Atan2(mousePoint.y - centerPoint.y, mousePoint.x - centerPoint.x) * Mathf.Rad2Deg;
SetAngle(180f - angle);
var angle = Mathf.Atan2(-mousePoint.y + centerPoint.y, mousePoint.x - centerPoint.x) * Mathf.Rad2Deg;

Debug.Log(angle);
SetAngle(angle);
_onAngleChanged?.Invoke(angle);
evt.StopPropagation();
}

Expand Down

0 comments on commit c82c587

Please sign in to comment.