Editor/Widgets/AltCurveEditorToolbar.cs
using AltCurves.GraphicsItems;
using Editor;
namespace AltCurves.Widgets;
/// <summary>
/// Collection of curve editor toolbar buttons
/// </summary>
internal class AltCurveEditorToolbar : Widget
{
private readonly Button _visibilityOptions;
private readonly Button _zoomButton;
private readonly SnapButtonTime _snapTimeButton;
private readonly SnapButtonValue _snapValueButton;
//private readonly EnumProperty<AltCurve.Extrapolation> _preInfinity;
//private readonly EnumProperty<AltCurve.Extrapolation> _postInfinity;
private readonly CurveCoordinateProperty _timeCoord;
private readonly CurveCoordinateProperty _valueCoord;
private readonly InterpolationControl _interpolation;
private readonly Button _flattenButton;
public AltCurveEditorToolbar( Widget parent, int HEADER_HEIGHT = 30 ) : base( parent )
{
Layout = Layout.Row();
Layout.Margin = 0;
Layout.Spacing = 5.0f;
_visibilityOptions = Layout.Add(new Button("View", "visibility", this )
{
ToolTip = "Toggle visibility of the curve",
Enabled = true,
VerticalSizeMode = SizeMode.CanGrow,
} );
_zoomButton = Layout.Add( new Button( "Zoom to Fit", "search", this )
{
ToolTip = "Zoom to Fit (Shortcut: F)",
Enabled = true,
VerticalSizeMode = SizeMode.CanGrow,
} );
const float coordWidth = 90.0f;
_timeCoord = Layout.Add( new CurveCoordinateProperty( "X", this )
{
FixedWidth = coordWidth,
HighlightColor = Theme.Red
} );
_valueCoord = Layout.Add( new CurveCoordinateProperty( "Y", this )
{
FixedWidth = coordWidth,
HighlightColor = Theme.Green
} );
_snapTimeButton = Layout.Add( new SnapButtonTime( this, TimeSnapOptions.Tenths )
{
VerticalSizeMode = SizeMode.CanGrow,
} );
_snapValueButton = Layout.Add( new SnapButtonValue( this, ValueSnapOptions.Gridlines )
{
VerticalSizeMode = SizeMode.CanGrow,
} );
////Layout.Add( new Label( "Pre-Infinity Extrapolation:", this ) );
//_preInfinity = Layout.Add( new EnumProperty<AltCurve.Extrapolation>( this )
//{
// Position = new( 150, 0 ),
// Size = new( 100, HEADER_HEIGHT ),
// MinimumWidth = 100
//} );
//
////Layout.Add( new Label( "Post-Infinity Extrapolation:", this ) );
//_postInfinity = Layout.Add( new EnumProperty<AltCurve.Extrapolation>( this )
//{
// Position = new( 150, 0 ),
// Size = new( 100, HEADER_HEIGHT ),
// MinimumWidth = 100
//} );
_interpolation = Layout.Add( new InterpolationControl( this ) );
_flattenButton = Layout.Add( new Button( "Flatten", "horizontal_rule", this )
{
ToolTip = "Flatten (Shortcut: 6): Flatten the selected curve tangents.",
VerticalSizeMode = SizeMode.CanGrow,
} );
Layout.AddStretchCell(); // Pad remaining width
}
/// <summary>
/// Hook these toolbar controls onto the given curve widget properties
/// </summary>
internal void BindCurveControls( AltCurveEditor editor, EditableAltCurve curveWidget )
{
// Visiblity dropdown/binding
_visibilityOptions.Pressed += () =>
{
var m = new Menu()
{
DeleteOnClose = true
};
m.AddHeading( "View Options" );
{
m.AddHeading( "Tangent Visibility" );
var always = m.AddOption( "Always", null, () => curveWidget.ViewConfig = curveWidget.ViewConfig with { TangentMode = TangentViewMode.All } );
always.Checkable = true;
always.Checked = curveWidget.ViewConfig.TangentMode == TangentViewMode.All;
var selected = m.AddOption( "Selected", null, () => curveWidget.ViewConfig = curveWidget.ViewConfig with { TangentMode = TangentViewMode.Selected } );
selected.Checkable = true;
selected.Checked = curveWidget.ViewConfig.TangentMode == TangentViewMode.Selected;
var none = m.AddOption( "None", null, () => curveWidget.ViewConfig = curveWidget.ViewConfig with { TangentMode = TangentViewMode.None } );
none.Checkable = true;
none.Checked = curveWidget.ViewConfig.TangentMode == TangentViewMode.None;
}
m.AddSeparator();
var showTooltip = new Option( "Show Curve Tooltip", null, () => curveWidget.ViewConfig = curveWidget.ViewConfig with { ShowCurveTooltip = !curveWidget.ViewConfig.ShowCurveTooltip } )
{
Checkable = true,
Checked = curveWidget.ViewConfig.ShowCurveTooltip
};
m.AddOption( showTooltip );
m.OpenAtCursor();
};
// Zoom to focus
_zoomButton.Pressed += () => editor.ZoomToFit();
// Time snap
curveWidget.Bind( "SnapTimeEnabled" ).From( _snapTimeButton, "SnapEnabled" );
curveWidget.Bind( "SnapTimeMode" ).From( _snapTimeButton, "CurrentSnapMode" );
curveWidget.Bind( "SnapTimeCustom" ).From( _snapTimeButton, "CustomSnapValue" );
_snapTimeButton.Bind( "ForcefullyDisabled" ).ReadOnly().From( curveWidget, "ForceDisableSnap" ); // Read-only reverse bind for alt-hold override feedback
// Value snap
curveWidget.Bind( "SnapValueEnabled" ).From( _snapValueButton, "SnapEnabled" );
curveWidget.Bind( "SnapValueMode" ).From( _snapValueButton, "CurrentSnapMode" );
curveWidget.Bind( "SnapValueCustom" ).From( _snapValueButton, "CustomSnapValue" );
_snapValueButton.Bind( "ForcefullyDisabled" ).ReadOnly().From( curveWidget, "ForceDisableSnap" ); // Read-only reverse bind for alt-hold override feedback
// // Pre-infinity
// _preInfinity.Bind( "Value" ).From( () => curveWidget.RawCurve.PreInfinity, v => curveWidget.RawCurve = curveWidget.RawCurve with { PreInfinity = v } );
//
// // Post-infinity
// _postInfinity.Bind( "Value" ).From( () => curveWidget.RawCurve.PostInfinity, v => curveWidget.RawCurve = curveWidget.RawCurve with { PostInfinity = v });
// Time coord
_timeCoord.Bind( "SelectedKeyframes" ).ReadOnly().From( () => curveWidget.SelectionState.SelectedKeyframes, x => { } );
_timeCoord.Bind( "SelectedValue" ).ReadOnly().From( () => curveWidget.SelectionState.SelectedTime, x => { } );
_timeCoord.OnDraggingStart = () => curveWidget.PushUndoState( $"Translate {curveWidget.SelectionState.SelectedKeyframes} keyframe{(curveWidget.SelectionState.SelectedKeyframes > 1 ? "s" : "")}" );
_timeCoord.OnDragging += ( amt ) => curveWidget.TranslateSelection( amt, 0.0f );
_timeCoord.OnManualInput += ( val ) => curveWidget.SetSelectionTime( val );
// Value coord
_valueCoord.Bind( "SelectedKeyframes" ).ReadOnly().From( () => curveWidget.SelectionState.SelectedKeyframes, x => { } );
_valueCoord.Bind( "SelectedValue" ).ReadOnly().From( () => curveWidget.SelectionState.SelectedValue, x => { } );
_valueCoord.OnDraggingStart = () => curveWidget.PushUndoState( $"Translate {curveWidget.SelectionState.SelectedKeyframes} keyframe{(curveWidget.SelectionState.SelectedKeyframes > 1 ? "s" : "")}" );
_valueCoord.OnDragging += ( amt ) => curveWidget.TranslateSelection( 0.0f, amt );
_valueCoord.OnManualInput += ( val ) => curveWidget.SetSelectionValue( val );
// Selected keyframe interpolation
_interpolation.Bind( "HighlightedInterpolation" ).ReadOnly().From( curveWidget, "SelectedInterpolation" );
_interpolation.Bind( "HasSelectedKeyframe" ).ReadOnly().From( curveWidget, "HasSelectedKeyframe" );
_interpolation.SelectedInterp = (newTangentMode) => curveWidget.SetSelectionInterpolation( newTangentMode );
// Flatten button
//_flattenButton.Bind( "Enabled" ).ReadOnly().From( () =>
// curveWidget.SelectedInterpolation.HasValue && curveWidget.SelectedInterpolation.Value.Interp == AltCurve.Interpolation.Cubic,
// x => { } ); // Disable for now, allow flattening tangents even if we don't share an interpolation type
_flattenButton.Bind( "Enabled" ).ReadOnly().From( curveWidget, "HasSelectedKeyframe" );
_flattenButton.Pressed = () => curveWidget.SetSelectionTangentFlat();
}
}