mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-04-19 13:59:22 -04:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
309 lines
7.8 KiB
C#
309 lines
7.8 KiB
C#
namespace Editor.GraphicsItems;
|
|
|
|
/// <summary>
|
|
/// Represents a keyframe on an EditableCurve
|
|
/// </summary>
|
|
public partial class EditableCurve
|
|
{
|
|
public class Handle : GraphicsItem
|
|
{
|
|
public Curve.Frame Frame;
|
|
public EditableCurve EditableCurve;
|
|
public Tangent In;
|
|
public Tangent Out;
|
|
public Vector2 RealPosition;
|
|
|
|
public Handle( EditableCurve parent, in Curve.Frame k ) : base( parent )
|
|
{
|
|
Frame = k;
|
|
EditableCurve = parent;
|
|
|
|
HoverEvents = true;
|
|
HandlePosition = 0.5f;
|
|
Size = 32.0f;
|
|
Cursor = CursorShape.Finger;
|
|
Movable = true;
|
|
Focusable = true;
|
|
Selectable = true;
|
|
|
|
In = new Tangent( this, true, k.In );
|
|
Out = new Tangent( this, false, k.Out );
|
|
|
|
UpdatePositionFromValue();
|
|
}
|
|
|
|
internal void UpdatePositionFromValue()
|
|
{
|
|
var val = new Vector2( Frame.Time, Frame.Value );
|
|
Position = ValueToPosition( val );
|
|
}
|
|
|
|
Vector2 ValueToPosition( Vector2 pos )
|
|
{
|
|
var x = pos.x.Remap( 0, 1, EditableCurve.TimeRange.x, EditableCurve.TimeRange.y, false );
|
|
var y = pos.y.Remap( 0, 1, EditableCurve.ValueRange.x, EditableCurve.ValueRange.y, false );
|
|
var drawnX = x.Remap( EditableCurve.ViewportRangeX.x, EditableCurve.ViewportRangeX.y, 0, 1, false );
|
|
var drawnY = y.Remap( EditableCurve.ViewportRangeY.x, EditableCurve.ViewportRangeY.y, 0, 1, false );
|
|
RealPosition = new Vector2( drawnX, 1f - drawnY ) * EditableCurve.Size;
|
|
return RealPosition;
|
|
}
|
|
|
|
Vector2 PositionToValue( Vector2 pos )
|
|
{
|
|
// Map the position to the viewport range
|
|
var x = pos.x.Remap( 0, EditableCurve.Size.x, EditableCurve.ViewportRangeX.x, EditableCurve.ViewportRangeX.y, false );
|
|
var y = pos.y.Remap( 0, EditableCurve.Size.y, EditableCurve.ViewportRangeY.y, EditableCurve.ViewportRangeY.x, false );
|
|
// Now remap the viewport range to the actual range
|
|
if ( EditableCurve.Value.Length > 1 )
|
|
{
|
|
x = x.Remap( EditableCurve.TimeRange.x, EditableCurve.TimeRange.y, 0, 1, false );
|
|
y = y.Remap( EditableCurve.ValueRange.x, EditableCurve.ValueRange.y, 0, 1, false );
|
|
}
|
|
return new Vector2( x, y );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the value from range scaled values
|
|
/// </summary>
|
|
public void SetValue( float x, float y )
|
|
{
|
|
x = x.Remap( EditableCurve.TimeRange.x, EditableCurve.TimeRange.y, 0, 1, false );
|
|
y = y.Remap( EditableCurve.ValueRange.x, EditableCurve.ValueRange.y, 0, 1, false );
|
|
|
|
Position = ValueToPosition( new Vector2( x, y ) );
|
|
EditableCurve?.OnHandleMoved();
|
|
OnMoved();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert this point into a keyframe, appropriate for saving into a curve
|
|
/// </summary>
|
|
internal Curve.Frame GetKeyFrame()
|
|
{
|
|
var kf = new Curve.Frame();
|
|
|
|
var value = PositionToValue( RealPosition );
|
|
|
|
kf.Time = value.x;
|
|
kf.Value = value.y;
|
|
|
|
kf.In = In?.Value ?? 0;
|
|
kf.Out = Out?.Value ?? 0;
|
|
|
|
kf.Mode = Frame.Mode;
|
|
|
|
return kf;
|
|
}
|
|
|
|
protected override void OnPaint()
|
|
{
|
|
if ( !EditableCurve.BoundingRect.IsInside( Position ) )
|
|
return;
|
|
|
|
var size = 4.0f;
|
|
|
|
Paint.SetBrush( EditableCurve.CurveColor );
|
|
Paint.ClearPen();
|
|
|
|
if ( Paint.HasMouseOver ) // todo - don't do this if over a child and not us
|
|
{
|
|
Paint.SetPen( EditableCurve.SelectionColor, 2 );
|
|
size += 2;
|
|
}
|
|
|
|
if ( Paint.HasSelected )
|
|
{
|
|
Paint.SetBrush( EditableCurve.SelectionColor );
|
|
size += 3;
|
|
}
|
|
|
|
Paint.DrawCircle( Size * 0.5f, size );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Paint extra background stuff
|
|
/// </summary>
|
|
public void PaintExtras()
|
|
{
|
|
if ( Hovered )
|
|
{
|
|
Paint.ClearBrush();
|
|
|
|
if ( (In?.Hovered ?? false) || (Out?.Hovered ?? false) )
|
|
{
|
|
Paint.SetPen( EditableCurve.CurveColor.WithAlpha( 0.1f ), 1, PenStyle.Dot );
|
|
Paint.DrawCircle( 0, EditableCurve.HandleDistance * 2.0f );
|
|
}
|
|
|
|
var maxLineSize = EditableCurve.Size.Length;
|
|
|
|
// Guide Lines
|
|
Paint.SetPen( EditableCurve.CurveColor.WithAlpha( 0.3f ), 1, PenStyle.Dot );
|
|
//Paint.DrawLine( TangentIn.Position * maxLineSize, TangentIn.Position );
|
|
//Paint.DrawLine( TangentOut.Position * maxLineSize, TangentOut.Position );
|
|
Paint.DrawLine( new Vector2( -maxLineSize, 0 ), new Vector2( maxLineSize, 0 ) );
|
|
|
|
}
|
|
|
|
Paint.SetPen( Hovered ? EditableCurve.SelectionColor.WithAlpha( 0.5f ) : EditableCurve.CurveColor.WithAlpha( 0.1f ), 1, PenStyle.Dot );
|
|
Paint.ClearBrush();
|
|
|
|
if ( In.IsValid() && Out.IsValid() )
|
|
{
|
|
Paint.DrawLine( 0, In.Position );
|
|
Paint.DrawLine( 0, Out.Position );
|
|
}
|
|
|
|
if ( Hovered )
|
|
{
|
|
//Paint.RenderMode = RenderMode.HardLight;
|
|
//Paint.ClearPen();
|
|
|
|
//Paint.SetBrushRadial( 0, 100, Curve.CurveColor.WithAlpha( 0.2f ), Curve.CurveColor.WithAlpha( 0 ) );
|
|
//Paint.DrawCircle( 0, 200 );
|
|
}
|
|
}
|
|
|
|
protected override void OnMoved()
|
|
{
|
|
RealPosition = Position;
|
|
var value = PositionToValue( Position );
|
|
if ( Application.KeyboardModifiers.HasFlag( KeyboardModifiers.Ctrl ) )
|
|
{
|
|
var _xInc = EditableCurve.editor.GetBackgroundIncrementX();
|
|
var _yInc = EditableCurve.editor.GetBackgroundIncrementY();
|
|
value.x = value.x
|
|
.Remap( 0, 1, EditableCurve.TimeRange.x, EditableCurve.TimeRange.y, false )
|
|
.SnapToGrid( _xInc )
|
|
.Remap( EditableCurve.TimeRange.x, EditableCurve.TimeRange.y, 0, 1, false );
|
|
value.y = value.y
|
|
.Remap( 0, 1, EditableCurve.ValueRange.x, EditableCurve.ValueRange.y, false )
|
|
.SnapToGrid( _yInc )
|
|
.Remap( EditableCurve.ValueRange.x, EditableCurve.ValueRange.y, 0, 1, false );
|
|
Position = ValueToPosition( value );
|
|
}
|
|
|
|
Frame.Time = value.x;
|
|
Frame.Value = value.y;
|
|
|
|
EditableCurve?.OnHandleMoved();
|
|
}
|
|
|
|
protected override void OnPositionChanged()
|
|
{
|
|
base.OnPositionChanged();
|
|
|
|
Position = Position.Clamp( 0, EditableCurve.Size );
|
|
|
|
In?.UpdatePositionFromValue();
|
|
Out?.UpdatePositionFromValue();
|
|
}
|
|
|
|
protected override void OnHoverEnter( GraphicsHoverEvent e )
|
|
{
|
|
EditableCurve?.Update();
|
|
EditableCurve?.UpdateTooltip();
|
|
}
|
|
protected override void OnHoverLeave( GraphicsHoverEvent e )
|
|
{
|
|
EditableCurve?.Update();
|
|
EditableCurve?.UpdateTooltip();
|
|
}
|
|
|
|
protected override void OnMousePressed( GraphicsMouseEvent e )
|
|
{
|
|
base.OnMousePressed( e );
|
|
|
|
if ( e.RightMouseButton )
|
|
OpenContextMenu( e.ScreenPosition );
|
|
}
|
|
|
|
public virtual void OpenContextMenu( Vector2 pos )
|
|
{
|
|
var m = new ContextMenu( null );
|
|
|
|
var enums = DisplayInfo.ForEnumValues( typeof( Curve.HandleMode ) );
|
|
var values = System.Enum.GetValues<Curve.HandleMode>();
|
|
|
|
foreach ( var e in DisplayInfo.ForEnumValues<Curve.HandleMode>() )
|
|
{
|
|
var o = m.AddOption( e.info.Name, e.info.Icon, () => SetHandleMode( e.value ) );
|
|
o.Enabled = Frame.Mode != e.value;
|
|
}
|
|
|
|
m.AddSeparator();
|
|
m.AddOption( "Delete", "delete", DeleteHandle );
|
|
|
|
m.OpenAt( pos, false );
|
|
}
|
|
|
|
public void SetHandleMode( Curve.HandleMode mode )
|
|
{
|
|
if ( Frame.Mode == mode )
|
|
return;
|
|
|
|
Frame.Mode = mode;
|
|
OnHandleModeChanged();
|
|
EditableCurve.SaveCurve();
|
|
EditableCurve.UpdateTooltip();
|
|
}
|
|
|
|
public void OnHandleModeChanged()
|
|
{
|
|
In ??= new Tangent( this, true, Frame.In );
|
|
Out ??= new Tangent( this, false, Frame.Out );
|
|
|
|
OnTangentChanged( true );
|
|
|
|
if ( Frame.Mode == Curve.HandleMode.Mirrored ) return;
|
|
if ( Frame.Mode == Curve.HandleMode.Split ) return;
|
|
|
|
In?.Destroy();
|
|
In = null;
|
|
|
|
Out?.Destroy();
|
|
Out = null;
|
|
}
|
|
|
|
public void DeleteHandle()
|
|
{
|
|
EditableCurve.Delete( this );
|
|
}
|
|
|
|
protected override void OnKeyPress( KeyEvent e )
|
|
{
|
|
base.OnKeyPress( e );
|
|
|
|
// Forward keypresses onto the curve,
|
|
// so it can apply them to all selected
|
|
EditableCurve?.FocusedHandleKeyPress( e );
|
|
}
|
|
|
|
internal void OnTangentChanged( bool isIncoming )
|
|
{
|
|
var i = In;
|
|
var o = Out;
|
|
|
|
if ( !isIncoming )
|
|
{
|
|
i = o;
|
|
o = In;
|
|
}
|
|
|
|
if ( Frame.Mode == Curve.HandleMode.Mirrored )
|
|
{
|
|
o.Value = -i.Value;
|
|
o.UpdatePositionFromValue();
|
|
}
|
|
}
|
|
|
|
protected override void OnSelectionChanged()
|
|
{
|
|
base.OnSelectionChanged();
|
|
|
|
EditableCurve?.HandleSelectionChanged();
|
|
}
|
|
}
|
|
|
|
}
|