470 lines
16 KiB
C++
470 lines
16 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "Containers/ArrayView.h"
|
|
#include "Containers/Map.h"
|
|
#include "Containers/Set.h"
|
|
#include "CurveDataAbstraction.h"
|
|
#include "CurveDrawInfo.h"
|
|
#include "CurveEditor.h"
|
|
#include "CurveEditorTypes.h"
|
|
#include "WidgetFocusUtils.h"
|
|
#include "Curves/RealCurve.h"
|
|
#include "Curves/RichCurve.h"
|
|
#include "Filters/PromotedFilterCommandBinder.h"
|
|
#include "HAL/Platform.h"
|
|
#include "Input/Reply.h"
|
|
#include "Internationalization/Text.h"
|
|
#include "Layout/Geometry.h"
|
|
#include "Layout/Visibility.h"
|
|
#include "Math/Axis.h"
|
|
#include "Math/Color.h"
|
|
#include "Misc/Attribute.h"
|
|
#include "Misc/Optional.h"
|
|
#include "Templates/SharedPointer.h"
|
|
#include "Templates/SubclassOf.h"
|
|
#include "Templates/UniquePtr.h"
|
|
#include "Textures/SlateIcon.h"
|
|
#include "Widgets/DeclarativeSyntaxSupport.h"
|
|
#include "Widgets/SCompoundWidget.h"
|
|
|
|
class FCurveEditor;
|
|
class FExtender;
|
|
class FTabManager;
|
|
class FToolBarBuilder;
|
|
class FMenuBuilder;
|
|
class FUICommandList;
|
|
class IDetailsView;
|
|
class IGraphEditorView;
|
|
class ITimeSliderController;
|
|
class SCurveEditorToolProperties;
|
|
class SCurveEditorView;
|
|
class SCurveEditorViewContainer;
|
|
class SCurveEditorFilterPanel;
|
|
class SCurveKeyDetailPanel;
|
|
class SScrollBox;
|
|
class SWidget;
|
|
class UCurveEditorFilterBase;
|
|
struct FCurveEditorDelayedDrag;
|
|
struct FCurveEditorEditObjectContainer;
|
|
struct FCurveEditorToolID;
|
|
struct FKeyEvent;
|
|
namespace UE::CurveEditor { class FPromotedFilterContainer; }
|
|
|
|
/**
|
|
* Curve editor widget that reflects the state of an FCurveEditor
|
|
*/
|
|
class CURVEEDITOR_API SCurveEditorPanel : public SCompoundWidget
|
|
{
|
|
SLATE_BEGIN_ARGS(SCurveEditorPanel)
|
|
: _GridLineTint(FLinearColor(0.1f, 0.1f, 0.1f, 1.f))
|
|
, _MinimumViewPanelHeight(300.0f)
|
|
{}
|
|
|
|
/** Color to draw grid lines */
|
|
SLATE_ATTRIBUTE(FLinearColor, GridLineTint)
|
|
|
|
/** Tab Manager which owns this panel. */
|
|
SLATE_ARGUMENT(TSharedPtr<FTabManager>, TabManager)
|
|
|
|
/** Optional Time Slider Controller which allows us to synchronize with an externally controlled Time Slider */
|
|
SLATE_ARGUMENT(TSharedPtr<ITimeSliderController>, ExternalTimeSliderController)
|
|
|
|
/** If specified, causes the time snap adjustment UI controls to be disabled and specifies the tooltip to be used. Can be used to disable time snap controls when externally controlled. */
|
|
SLATE_ATTRIBUTE(FText, DisabledTimeSnapTooltip)
|
|
|
|
/** Widget slot for the tree content */
|
|
SLATE_NAMED_SLOT(FArguments, TreeContent)
|
|
|
|
/** The minimum height for the panel which contains the curve editor views. */
|
|
SLATE_ARGUMENT(float, MinimumViewPanelHeight)
|
|
|
|
SLATE_END_ARGS()
|
|
|
|
SCurveEditorPanel();
|
|
~SCurveEditorPanel();
|
|
|
|
/**
|
|
* Construct a new curve editor panel widget
|
|
*/
|
|
void Construct(const FArguments& InArgs, TSharedRef<FCurveEditor> InCurveEditor);
|
|
|
|
/**
|
|
* Access the combined command list for this curve editor and panel widget
|
|
*/
|
|
TSharedPtr<FUICommandList> GetCommands() const
|
|
{
|
|
return CommandList;
|
|
}
|
|
|
|
/**
|
|
* Access the details view used for editing selected keys
|
|
*/
|
|
TSharedPtr<class SCurveKeyDetailPanel> GetKeyDetailsView() const
|
|
{
|
|
return KeyDetailsView;
|
|
}
|
|
|
|
/**
|
|
* Access the filter panel
|
|
*/
|
|
TSharedPtr<class SCurveEditorFilterPanel> GetFilterPanel() const
|
|
{
|
|
return FilterPanel;
|
|
}
|
|
|
|
/**
|
|
* Access the tool properties panel
|
|
*/
|
|
TSharedPtr<class SCurveEditorToolProperties> GetToolPropertiesPanel() const
|
|
{
|
|
return ToolPropertiesPanel;
|
|
}
|
|
|
|
void AddView(TSharedRef<SCurveEditorView> ViewToAdd);
|
|
|
|
void RemoveView(TSharedRef<SCurveEditorView> ViewToRemove);
|
|
|
|
/** This returns an extender which is pre-configured with the standard set of Toolbar Icons. Implementers of SCurveEditorPanel should use this
|
|
* to generate the icons and then add any additional context-specific icons (such as save buttons in the Asset Editor) to ensure that the Curve
|
|
* Editor has a consistent set (and order) of icons across all usages.
|
|
*/
|
|
TSharedPtr<FExtender> GetToolbarExtender();
|
|
|
|
/** Access the cached geometry of the outer scroll panel that contains this panel's views */
|
|
const FGeometry& GetScrollPanelGeometry() const;
|
|
|
|
/** Access the cached geometry of container housing all this panel's views */
|
|
const FGeometry& GetViewContainerGeometry() const;
|
|
|
|
/** Get all the views stored in this panel. */
|
|
TArrayView<const TSharedPtr<SCurveEditorView>> GetViews() const;
|
|
|
|
/** Get the grid line tint to be used for views on panel */
|
|
FLinearColor GetGridLineTint() const { return GridLineTintAttribute.Get(); }
|
|
|
|
/** Scroll this panel's view scroll box vertically by the specified amount */
|
|
void ScrollBy(float Amount);
|
|
|
|
/**
|
|
* Find all the views that the specified curve is being displayed on
|
|
* @note: Returns an in-place iterator to this curve's view mapping. Adding or removing curves from views *will* invalidate this iterator.
|
|
*
|
|
* @param InCurveID The identifier of the curve to find views for
|
|
* @return An iterator to all the views that this cuvrve is displayed within.
|
|
*/
|
|
TMultiMap<FCurveModelID, TSharedRef<SCurveEditorView>>::TConstKeyIterator FindViews(TRetainedRef<FCurveModelID> InCurveID)
|
|
{
|
|
return CurveViews.CreateConstKeyIterator(InCurveID.Get());
|
|
}
|
|
|
|
/**
|
|
* Remove the specified curve from all views it is currently displayed on.
|
|
*/
|
|
void RemoveCurveFromViews(FCurveModelID InCurveID);
|
|
|
|
/** Get the last set View Mode for this UI. Utility function for the UI. */
|
|
ECurveEditorViewID GetViewMode() const { return DefaultViewID; }
|
|
|
|
/** Undo occurred, invalidate or update internal structures */
|
|
void PostUndo();
|
|
|
|
/** Reset Stored Min/Max's*/
|
|
void ResetMinMaxes();
|
|
|
|
/** Update the axis snapping based on the settings. */
|
|
void UpdateAxisSnapping();
|
|
|
|
/** Delegate for when the chosen filter class has changed */
|
|
FSimpleDelegate OnFilterClassChanged;
|
|
void FilterClassChanged();
|
|
|
|
/** Enable/disable pending focus */
|
|
void EnablePendingFocusOnHovering(const bool InEnabled);
|
|
|
|
/** Broadcasts after the curve views have been rebuilt (by RebuildCurveViews). */
|
|
FSimpleMulticastDelegate& OnPostRebuildCurveViews() { return OnPostRebuildCurveViewsDelegate; }
|
|
|
|
private:
|
|
// SWidget Interface
|
|
virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override;
|
|
// ~SWidget Interface
|
|
|
|
/*~ Keyboard interaction */
|
|
virtual bool SupportsKeyboardFocus() const override { return true; }
|
|
virtual FReply OnKeyDown(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent) override;
|
|
virtual void OnMouseEnter(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
|
|
virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override;
|
|
|
|
/** @return Extender combining all ICurveEditorModule::GetAllToolBarMenuExtenders and the owning FCurveEditor's ICurveEditorExtensions. */
|
|
TSharedPtr<FExtender> CombineEditorExtensions() const;
|
|
/** Adds all base curve editor UI elements to ToolbarBuilder. */
|
|
void BuildToolbar(FToolBarBuilder& InToolBarBuilder, TSharedPtr<FExtender> InBaseExtender);
|
|
|
|
TSharedRef<SWidget> MakeTimeSnapMenu();
|
|
FText GetTimeSnapMenuTooltip() const;
|
|
|
|
TSharedRef<SWidget> MakeGridSpacingMenu();
|
|
TSharedRef<SWidget> MakeAxisSnapMenu();
|
|
|
|
/* Curve Flip make menu function and settings */
|
|
TSharedRef<SWidget> MakeFlipCurveMenu(FCurveEditor::ECurveFlipDirection Direction);
|
|
|
|
bool IsInlineEditPanelEditable() const;
|
|
EVisibility ShouldInstructionOverlayBeVisible() const;
|
|
|
|
private:
|
|
|
|
TSharedRef<SWidget> MakeToolsComboMenu(TSharedPtr<FExtender> InExtender);
|
|
FText GetCurrentToolLabel() const;
|
|
FText GetCurrentToolDescription() const;
|
|
FSlateIcon GetCurrentToolIcon() const;
|
|
|
|
private:
|
|
|
|
// Tangent mode toolbar combo button
|
|
TSharedRef<SWidget> MakeTangentModeMenu();
|
|
FText GetTangentModeLabel() const;
|
|
FText GetTangentModeTooltip() const;
|
|
FSlateIcon GetTangentModeIcon() const;
|
|
bool IsTangentModeComboEnabled() const;
|
|
|
|
enum class ETangentModeComboState : uint8
|
|
{
|
|
NoSelection,
|
|
|
|
// All keys in selection share the following mode:
|
|
Constant,
|
|
Linear,
|
|
CubicAuto,
|
|
CubicSmartAuto,
|
|
CubicUser,
|
|
CubicBreak,
|
|
|
|
// The keys are mixed
|
|
Mixed
|
|
};
|
|
ETangentModeComboState DetermineTangentMode() const;
|
|
|
|
private:
|
|
|
|
/**
|
|
* Get the visibility for the value splitter control
|
|
*/
|
|
EVisibility GetSplitterVisibility() const;
|
|
|
|
/*~ Event bindings */
|
|
void UpdateTime();
|
|
void UpdateEditBox();
|
|
void UpdateCommonCurveInfo();
|
|
|
|
/** Creates the drop-down list you see when changing Curve View options. */
|
|
TSharedRef<SWidget> MakeCurveEditorCurveViewOptionsMenu(TSharedPtr<FExtender> InExtender);
|
|
/** Creates the drop-down for changing curves on a whole. */
|
|
TSharedRef<SWidget> MakeCurvesMenu(TSharedPtr<FExtender> InExtender);
|
|
void AddPreInfinityToMenu(FMenuBuilder& InMenuBuilder);
|
|
void AddPostInfinityToMenu(FMenuBuilder& InMenuBuilder);
|
|
FSlateIcon GetCurveExtrapolationPreIcon() const;
|
|
FSlateIcon GetCurveExtrapolationPostIcon() const;
|
|
|
|
/** Creates the Curve Editor Filter UI and pre-populates it with the specified class. */
|
|
void ShowCurveFilterUI(TSubclassOf<UCurveEditorFilterBase> FilterClass);
|
|
|
|
private:
|
|
|
|
/**
|
|
* Bind command mappings for this widget
|
|
*/
|
|
void BindCommands();
|
|
|
|
/**
|
|
* Assign new attributes to the currently selected keys
|
|
*/
|
|
void SetKeyAttributes(FKeyAttributes KeyAttributes, FText Description);
|
|
|
|
/**
|
|
* Assign new curve attributes to all visible curves
|
|
*/
|
|
void SetCurveAttributes(FCurveAttributes CurveAttributes, FText Description);
|
|
|
|
/** Compare all the currently selected keys' interp modes against the specified interp mode */
|
|
bool CompareCommonInterpolationMode(ERichCurveInterpMode InterpMode) const
|
|
{
|
|
return CachedCommonKeyAttributes.HasInterpMode() && CachedCommonKeyAttributes.GetInterpMode() == InterpMode;
|
|
}
|
|
|
|
/** Compare all the currently selected keys' tangent modes against the specified tangent mode */
|
|
bool CompareCommonTangentMode(ERichCurveInterpMode InterpMode, ERichCurveTangentMode TangentMode) const
|
|
{
|
|
return CompareCommonInterpolationMode(InterpMode) && CachedCommonKeyAttributes.HasTangentMode() && CachedCommonKeyAttributes.GetTangentMode() == TangentMode;
|
|
}
|
|
|
|
/** Compare all the currently selected keys' tangent modes against the specified tangent mode */
|
|
bool CompareCommonTangentWeightMode(ERichCurveInterpMode InterpMode, ERichCurveTangentWeightMode TangentWeightMode) const
|
|
{
|
|
return CompareCommonInterpolationMode(InterpMode) && CachedCommonKeyAttributes.HasTangentWeightMode() && CachedCommonKeyAttributes.GetTangentWeightMode() == TangentWeightMode;
|
|
}
|
|
|
|
/** Compare all the visible curves' pre-extrapolation modes against the specified extrapolation mode */
|
|
bool CompareCommonPreExtrapolationMode(ERichCurveExtrapolation PreExtrapolationMode) const
|
|
{
|
|
return CachedCommonCurveAttributes.HasPreExtrapolation() && CachedCommonCurveAttributes.GetPreExtrapolation() == PreExtrapolationMode;
|
|
}
|
|
|
|
/** Compare all the visible curves' post-extrapolation modes against the specified extrapolation mode */
|
|
bool CompareCommonPostExtrapolationMode(ERichCurveExtrapolation PostExtrapolationMode) const
|
|
{
|
|
return CachedCommonCurveAttributes.HasPostExtrapolation() && CachedCommonCurveAttributes.GetPostExtrapolation() == PostExtrapolationMode;
|
|
}
|
|
|
|
/**
|
|
* Toggle weighted tangents on the current selection
|
|
*/
|
|
void ToggleWeightedTangents();
|
|
|
|
/**
|
|
* Check whether we can toggle weighted tangents on the current selection
|
|
*/
|
|
bool CanToggleWeightedTangents() const;
|
|
|
|
/**
|
|
* Check whether or not we can set a key interpolation on the current selection. If no keys are selected, you can't set an interpolation!
|
|
*/
|
|
bool CanSetKeyInterpolation() const;
|
|
|
|
/** Sets the axis snapping to the specified value. Only supports X, Y and None. */
|
|
void SetAxisSnapping(ECurveEditorSnapAxis);
|
|
|
|
/** Get a reference to the curve editor this panel represents. */
|
|
TSharedPtr<FCurveEditor> GetCurveEditor() const { return CurveEditor; }
|
|
|
|
float GetColumnFillCoefficient(int32 ColumnIndex) const
|
|
{
|
|
ensure(ColumnIndex == 0 || ColumnIndex == 1);
|
|
return ColumnFillCoefficients[ColumnIndex];
|
|
}
|
|
|
|
/** Called when a column fill percentage is changed by a splitter slot. */
|
|
void OnColumnFillCoefficientChanged(float FillCoefficient, int32 ColumnIndex);
|
|
|
|
void OnSplitterFinishedResizing();
|
|
|
|
private:
|
|
|
|
/**
|
|
* Create a new view for a model of the specified type, and add the curve to the view
|
|
*
|
|
* @param CurveModelID The ID of the curve we're creating a view for
|
|
* @param ViewTypeID The ID of the view we'd like to create
|
|
* @param bPinned Whether the view should be pinned or not
|
|
* @return A new view or nullptr if one could not be created
|
|
*/
|
|
TSharedPtr<SCurveEditorView> CreateViewOfType(FCurveModelID CurveModelID, ECurveEditorViewID ViewTypeID, bool bPinned);
|
|
|
|
private:
|
|
|
|
/** The curve editor pointer */
|
|
TSharedPtr<FCurveEditor> CurveEditor;
|
|
|
|
/** Map from curve model ID to the views that it is on */
|
|
TMultiMap<FCurveModelID, TSharedRef<SCurveEditorView>> CurveViews;
|
|
|
|
/** Set of externally added views */
|
|
TSet<TSharedRef<SCurveEditorView>> ExternalViews;
|
|
|
|
/** (Optional) the current drag operation */
|
|
TOptional<FCurveEditorDelayedDrag> DragOperation;
|
|
|
|
/** Cached curve attributes that are common to all visible curves */
|
|
FCurveAttributes CachedCommonCurveAttributes;
|
|
|
|
/** Cached key attributes that are common to all selected keys */
|
|
FKeyAttributes CachedCommonKeyAttributes;
|
|
|
|
/** True if the current selection supports weighted tangents, false otherwise */
|
|
bool bSelectionSupportsWeightedTangents;
|
|
|
|
/** Attribute used for retrieving the desired grid line color */
|
|
TAttribute<FLinearColor> GridLineTintAttribute;
|
|
|
|
/** Attribute used for retrieving the tooltip for when the Time Snap control is disabled. Specifying this causes the Time Snap Adjustment to be disabled. */
|
|
TAttribute<FText> DisabledTimeSnapTooltipAttribute;
|
|
|
|
/** Edit panel */
|
|
TSharedPtr<SCurveKeyDetailPanel> KeyDetailsView;
|
|
|
|
/* Filter panel */
|
|
TSharedPtr<SCurveEditorFilterPanel> FilterPanel;
|
|
|
|
/** Tool options panel */
|
|
TSharedPtr<SCurveEditorToolProperties> ToolPropertiesPanel;
|
|
|
|
/** Map of edit UI widgets for each curve in the current selection set */
|
|
TMap<FCurveModelID, TSharedPtr<SWidget>> CurveToEditUI;
|
|
|
|
/** Command list for widget specific command bindings */
|
|
TSharedPtr<FUICommandList> CommandList;
|
|
|
|
/** Binds commands from FPromotedFilterContainer so the filters surfaced from SCurveEditorFilterPanel show up in the toolbar. */
|
|
TUniquePtr<UE::CurveEditor::FPromotedFilterCommandBinder> ToolbarPromotedFilterBinder;
|
|
|
|
/** Cached serial number from the curve editor selection. Used to update edit UIs when the selection changes. */
|
|
uint32 CachedSelectionSerialNumber;
|
|
|
|
private:
|
|
|
|
/** Sets the View Mode for the UI to the specified mode. This will destroy and re-create all views, but leave additional pinned views unmodified. */
|
|
void SetViewMode(const ECurveEditorViewID NewViewMode);
|
|
|
|
/** Compare if our current view mode matches the specified one. Utility function for the UI. */
|
|
bool CompareViewMode(const ECurveEditorViewID InViewMode) const;
|
|
|
|
/** Rebuild the Curve Views layout to match the currently specified View Mode. */
|
|
void RebuildCurveViews();
|
|
|
|
/** Reconstructs the properties widget on tool switch */
|
|
void OnCurveEditorToolChanged(FCurveEditorToolID InToolId);
|
|
|
|
/** Last Output Min and Max values for the views*/
|
|
double LastOutputMin = DBL_MAX;
|
|
double LastOutputMax = DBL_MIN;
|
|
|
|
/** The last set View Mode for this UI. */
|
|
ECurveEditorViewID DefaultViewID;
|
|
|
|
/** Broadcasts after the curve views have been rebuilt (by RebuildCurveViews). */
|
|
FSimpleMulticastDelegate OnPostRebuildCurveViewsDelegate;
|
|
|
|
TMultiMap<ECurveEditorViewID, TSharedRef<SCurveEditorView>> FreeViewsByType;
|
|
|
|
/** The scrool box that all curve views live inside */
|
|
TSharedPtr<SScrollBox> ScrollBox;
|
|
|
|
/** The container for all our vertically laid out curve views. */
|
|
TSharedPtr<SCurveEditorViewContainer> CurveViewsContainer;
|
|
|
|
private:
|
|
|
|
/** Pending focus handler */
|
|
FPendingWidgetFocus PendingFocus;
|
|
|
|
/** Whether to explicitly refresh the views for this panel */
|
|
bool bNeedsRefresh;
|
|
|
|
/** Serial number cached from FCurveEditor::GetActiveCurvesSerialNumber() on tick */
|
|
uint32 CachedActiveCurvesSerialNumber;
|
|
|
|
/** A copy of the View Geometry used to represent the View portion of the Curve Editor. */
|
|
FGeometry CachedViewGeometry;
|
|
|
|
/** The fill coefficients of each column in the grid. */
|
|
float ColumnFillCoefficients[2];
|
|
|
|
TSharedPtr<class SSplitter> TreeViewSplitter;
|
|
|
|
/** Container of objects that are being used to edit keys on the curve editor */
|
|
TUniquePtr<FCurveEditorEditObjectContainer> EditObjects;
|
|
|
|
TWeakPtr<FTabManager> WeakTabManager;
|
|
}; |