// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using System; using System.Collections.Generic; using FlaxEngine; using FlaxEngine.GUI; namespace FlaxEditor.GUI { /// /// The base class for editors. Allows to use generic curve editor without type information at compile-time. /// [HideInEditor] public abstract class CurveEditorBase : ContainerControl, IKeyframesEditor { /// /// The UI use mode flags. /// [Flags] public enum UseMode { /// /// Disable usage. /// Off = 0, /// /// Allow only vertical usage. /// Vertical = 1, /// /// Allow only horizontal usage. /// Horizontal = 2, /// /// Allow both vertical and horizontal usage. /// On = Vertical | Horizontal, } /// /// Occurs when curve gets edited. /// public event Action Edited; /// /// Occurs when curve data editing starts (via UI). /// public event Action EditingStart; /// /// Occurs when curve data editing ends (via UI). /// public event Action EditingEnd; /// /// The function for custom view panning. Gets input movement delta (in curve control space) and returns the renaming input delta to process by curve editor itself. /// public Func CustomViewPanning; /// /// The maximum amount of keyframes to use in a single curve. /// public int MaxKeyframes = ushort.MaxValue; /// /// True if enable view zooming. Otherwise user won't be able to zoom in or out. /// public UseMode EnableZoom = UseMode.On; /// /// True if enable view panning. Otherwise user won't be able to move the view area. /// public UseMode EnablePanning = UseMode.On; /// /// Gets or sets the scroll bars usage. /// public abstract ScrollBars ScrollBars { get; set; } /// /// Enables drawing start/end values continuous lines. /// public bool ShowStartEndLines; /// /// Enables drawing background. /// public bool ShowBackground = true; /// /// Enables drawing time and values axes (lines and labels). /// public UseMode ShowAxes = UseMode.On; /// /// Gets the type of the curves keyframes value. /// public abstract Type ValueType { get; } /// /// The amount of frames per second of the curve animation (optional). Can be used to restrict the keyframes time values to the given time quantization rate. /// public abstract float? FPS { get; set; } /// /// Gets or sets a value indicating whether show curve collapsed as a list of keyframe points rather than a full curve. /// public abstract bool ShowCollapsed { get; set; } /// /// Gets or sets the view offset (via scroll bars). /// public abstract Float2 ViewOffset { get; set; } /// /// Gets or sets the view scale. /// public abstract Float2 ViewScale { get; set; } /// /// Gets the amount of keyframes added to the curve. /// public abstract int KeyframesCount { get; } /// /// Clears the selection. /// public abstract void ClearSelection(); /// /// Called when curve gets edited. /// public void OnEdited() { Edited?.Invoke(); } /// /// Called when curve data editing starts (via UI). /// public void OnEditingStart() { EditingStart?.Invoke(); } /// /// Called when curve data editing ends (via UI). /// public void OnEditingEnd() { EditingEnd?.Invoke(); } /// /// Updates the keyframes positioning. /// public abstract void UpdateKeyframes(); /// /// Updates the tangents positioning. /// public abstract void UpdateTangents(); /// /// Shows the whole curve. /// public abstract void ShowWholeCurve(); /// /// Resets the view. /// public void ResetView() { ViewScale = ApplyUseModeMask(EnableZoom, Float2.One, ViewScale); ViewOffset = ApplyUseModeMask(EnablePanning, Float2.Zero, ViewOffset); UpdateKeyframes(); } /// /// Evaluates the animation curve value at the specified time. /// /// The interpolated value from the curve at provided time. /// The time to evaluate the curve at. /// If true the curve will loop when it goes past the end or beginning. Otherwise the curve value will be clamped. public abstract void Evaluate(out object result, float time, bool loop = false); /// /// Gets the keyframes collection (as boxed objects). /// /// The array of boxed keyframe values of type or . public abstract object[] GetKeyframes(); /// /// Sets the keyframes collection (as boxed objects). /// /// The array of boxed keyframe values of type or . public abstract void SetKeyframes(object[] keyframes); /// /// Adds the new keyframe (as boxed object). /// /// The keyframe time. /// The keyframe value (boxed). /// The index of the keyframe. public abstract int AddKeyframe(float time, object value); /// /// Adds the new keyframe (as boxed object). /// /// The keyframe time. /// The keyframe value (boxed). /// The keyframe 'In' tangent value (boxed). /// The keyframe 'Out' tangent value (boxed). /// The index of the keyframe. public abstract int AddKeyframe(float time, object value, object tangentIn, object tangentOut); /// /// Gets the keyframe data (as boxed objects). /// /// The keyframe index. /// The keyframe time. /// The keyframe value (boxed). /// The keyframe 'In' tangent value (boxed). /// The keyframe 'Out' tangent value (boxed). public abstract void GetKeyframe(int index, out float time, out object value, out object tangentIn, out object tangentOut); /// /// Gets the existing keyframe value (as boxed object). /// /// The keyframe index. /// The keyframe value. public abstract object GetKeyframe(int index); /// /// Sets the existing keyframe value (as boxed object). /// /// The keyframe index. /// The keyframe value. public abstract void SetKeyframeValue(int index, object value); /// /// Gets the keyframe point (in keyframes space). /// /// The keyframe index. /// The keyframe value component index. /// The point in time/value space. public abstract Float2 GetKeyframePoint(int index, int component); /// /// Converts the into the mask. /// /// The mode. /// The mask. protected static Float2 GetUseModeMask(UseMode mode) { return new Float2((mode & UseMode.Horizontal) == UseMode.Horizontal ? 1.0f : 0.0f, (mode & UseMode.Vertical) == UseMode.Vertical ? 1.0f : 0.0f); } /// /// Filters the given value using the . /// /// The mode. /// The value to process. /// The default value. /// The combined value. protected static Float2 ApplyUseModeMask(UseMode mode, Float2 value, Float2 defaultValue) { return new Float2( (mode & UseMode.Horizontal) == UseMode.Horizontal ? value.X : defaultValue.X, (mode & UseMode.Vertical) == UseMode.Vertical ? value.Y : defaultValue.Y ); } /// public IKeyframesEditorContext KeyframesEditorContext { get; set; } /// public abstract void OnKeyframesDeselect(IKeyframesEditor editor); /// public abstract void OnKeyframesSelection(IKeyframesEditor editor, ContainerControl control, Rectangle selection); /// public abstract int OnKeyframesSelectionCount(); /// public abstract void OnKeyframesDelete(IKeyframesEditor editor); /// public abstract void OnKeyframesMove(IKeyframesEditor editor, ContainerControl control, Float2 location, bool start, bool end); /// public abstract void OnKeyframesCopy(IKeyframesEditor editor, float? timeOffset, System.Text.StringBuilder data); /// public abstract void OnKeyframesPaste(IKeyframesEditor editor, float? timeOffset, string[] datas, ref int index); /// public abstract void OnKeyframesGet(string trackName, Action get); /// public abstract void OnKeyframesSet(List> keyframes); } }