Files
UnrealEngineUWP/Engine/Source/Editor/CurveEditor/Private/CurveEditorContextMenu.cpp
max chen 16d8af48fe Curve Editor: Buffered curve features
Buffered curves now can only operate on themselves, matching by LongDisplayName. The operations are also restricted to the selected curves (either selected in the tree or selected by way of selected keys). There is a new option to Swap Buffered Curves which stores the current curve to the buffer and restores the buffer to the current curve. The Store/Swap/Apply menus are now visible for all the context menus (keys, hovered curve, all curves). There is also a new toggle to show/hide buffered curves and they are also only visible when the curve is selected.

#jira UE-143895
#preflight 62294f800d5a90e98ed4ae68
#rb mike.zyracki

#ROBOMERGE-AUTHOR: max.chen
#ROBOMERGE-SOURCE: CL 19344793 via CL 19346614 via CL 19351363 via CL 19351424
#ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v926-19321884)

[CL 19351984 by max chen in ue5-main branch]
2022-03-11 04:29:44 -05:00

213 lines
8.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "CurveEditorContextMenu.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "Framework/Commands/GenericCommands.h"
#include "CurveEditor.h"
#include "CurveEditorCommands.h"
#define LOCTEXT_NAMESPACE "CurveEditorContextMenu"
void FCurveEditorContextMenu::BuildMenu(FMenuBuilder& MenuBuilder, TSharedRef<FCurveEditor> CurveEditor, TOptional<FCurvePointHandle> ClickedPoint, TOptional<FCurveModelID> HoveredCurveID)
{
int32 NumSelectedKeys = CurveEditor->GetSelection().Count();
TSharedPtr<FCurveEditor> LocalCurveEditor = CurveEditor->AsShared();
int32 NumActiveCurves = LocalCurveEditor->GetCurvesForBufferedCurves().Num();
int32 NumBufferedCurves = 0;
for (const TUniquePtr<IBufferedCurveModel>& BufferedCurve : LocalCurveEditor->GetBufferedCurves())
{
if (LocalCurveEditor->IsActiveBufferedCurve(BufferedCurve))
{
++NumBufferedCurves;
}
}
// We change the name to reflect the current number of curves selected.
TAttribute<FText> BufferedCurvesText = FText::Format(LOCTEXT("StoreCurvesContextMenu", "Store {0} Curves"), NumActiveCurves);
TAttribute<FText> SwapBufferedCurvesText = FText::Format(LOCTEXT("SwapStoredCurvesContextMenu", "Swap {0} Stored Curves onto {1} Selected Curves"), NumBufferedCurves, NumActiveCurves);
TAttribute<FText> ApplyBufferedCurvesText = FText::Format(LOCTEXT("ApplyStoredCurvesContextMenu", "Apply {0} Stored Curves onto {1} Selected Curves"), NumBufferedCurves, NumActiveCurves);
const FCurveModel* HoveredCurve = HoveredCurveID.IsSet() ? CurveEditor->FindCurve(HoveredCurveID.GetValue()) : nullptr;
// We prioritize key selections over curve selections to reduce the pixel-perfectness needed
// to edit the keys (which is more common than curves). Right clicking on a key or an empty space
// should show the key menu, otherwise we show the curve menu (ie: right clicking on a curve, not
// directly over a key).
if (NumSelectedKeys > 0 && (!HoveredCurveID.IsSet() || ClickedPoint.IsSet()))
{
MenuBuilder.BeginSection("CurveEditorKeySection", FText::Format(LOCTEXT("CurveEditorKeySection", "{0} Selected {0}|plural(one=Key,other=Keys)"), NumSelectedKeys));
{
bool bIsReadOnly = false;
if (HoveredCurve)
{
bIsReadOnly = HoveredCurve->IsReadOnly();
}
else
{
if (ClickedPoint.IsSet())
{
if (FCurveModel* ClickedPointCurve = CurveEditor->FindCurve(ClickedPoint->CurveID))
{
bIsReadOnly = ClickedPointCurve->IsReadOnly();
}
}
}
if (!bIsReadOnly)
{
// Modify Data
MenuBuilder.AddMenuEntry(FGenericCommands::Get().Cut);
MenuBuilder.AddMenuEntry(FGenericCommands::Get().Paste);
MenuBuilder.AddMenuEntry(FGenericCommands::Get().Copy);
MenuBuilder.AddMenuEntry(FGenericCommands::Get().Delete);
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().FlattenTangents);
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().StraightenTangents);
MenuBuilder.AddMenuSeparator();
// Tangent Types
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().InterpolationCubicAuto);
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().InterpolationCubicUser);
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().InterpolationCubicBreak);
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().InterpolationLinear);
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().InterpolationConstant);
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().InterpolationToggleWeighted);
MenuBuilder.AddMenuSeparator();
}
// Buffer Curves
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().BufferVisibleCurves, NAME_None, BufferedCurvesText);
if (!bIsReadOnly)
{
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().SwapBufferedCurves, NAME_None, SwapBufferedCurvesText);
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().ApplyBufferedCurves, NAME_None, ApplyBufferedCurvesText);
}
MenuBuilder.AddSeparator();
// Select
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().SelectAllKeys);
// Filters
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().OpenUserImplementableFilterWindow);
// View
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().ZoomToFit);
}
MenuBuilder.EndSection();
}
else
{
// Test if at least one curve is editable
bool bIsReadOnly = true;
TSet<FCurveModelID> CurvesToAddTo;
for(const FCurveModelID& CurveModelID : CurveEditor->GetEditedCurves())
{
if (const FCurveModel* CurveModel = CurveEditor->FindCurve(CurveModelID))
{
if (!CurveModel->IsReadOnly())
{
bIsReadOnly = false;
break;
}
}
}
if (HoveredCurve)
{
MenuBuilder.BeginSection("CurveEditorCurveSection", FText::Format(LOCTEXT("CurveNameFormat", "Curve '{0}'"), HoveredCurve->GetLongDisplayName()));
{
// Modify Curve
if (!HoveredCurve->IsReadOnly())
{
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().AddKeyHovered);
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().PasteKeysHovered);
MenuBuilder.AddMenuSeparator();
MenuBuilder.AddSubMenu(LOCTEXT("PreInfinityText", "Pre-Infinity"), FText(), FNewMenuDelegate::CreateLambda(
[](FMenuBuilder& SubMenu)
{
SubMenu.AddMenuEntry(FCurveEditorCommands::Get().SetPreInfinityExtrapCycle);
SubMenu.AddMenuEntry(FCurveEditorCommands::Get().SetPreInfinityExtrapCycleWithOffset);
SubMenu.AddMenuEntry(FCurveEditorCommands::Get().SetPreInfinityExtrapOscillate);
SubMenu.AddMenuEntry(FCurveEditorCommands::Get().SetPreInfinityExtrapLinear);
SubMenu.AddMenuEntry(FCurveEditorCommands::Get().SetPreInfinityExtrapConstant);
})
);
MenuBuilder.AddSubMenu(LOCTEXT("PostInfinityText", "Post-Infinity"), FText(), FNewMenuDelegate::CreateLambda(
[](FMenuBuilder& SubMenu)
{
SubMenu.AddMenuEntry(FCurveEditorCommands::Get().SetPostInfinityExtrapCycle);
SubMenu.AddMenuEntry(FCurveEditorCommands::Get().SetPostInfinityExtrapCycleWithOffset);
SubMenu.AddMenuEntry(FCurveEditorCommands::Get().SetPostInfinityExtrapOscillate);
SubMenu.AddMenuEntry(FCurveEditorCommands::Get().SetPostInfinityExtrapLinear);
SubMenu.AddMenuEntry(FCurveEditorCommands::Get().SetPostInfinityExtrapConstant);
})
);
MenuBuilder.AddMenuSeparator();
// Buffer Curves
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().BufferVisibleCurves, NAME_None, BufferedCurvesText);
if (!bIsReadOnly)
{
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().SwapBufferedCurves, NAME_None, SwapBufferedCurvesText);
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().ApplyBufferedCurves, NAME_None, ApplyBufferedCurvesText);
}
MenuBuilder.AddSeparator();
}
// Select
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().SelectAllKeys);
// Filters
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().OpenUserImplementableFilterWindow);
// View
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().ZoomToFit);
}
MenuBuilder.EndSection();
}
else
{
MenuBuilder.BeginSection("CurveEditorAllCurveSections", LOCTEXT("CurveEditorAllCurveSections", "All Curves"));
{
if (!bIsReadOnly)
{
// Modify Curves
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().AddKeyToAllCurves);
MenuBuilder.AddSeparator();
// Buffer Curves
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().BufferVisibleCurves, NAME_None, BufferedCurvesText);
if (!bIsReadOnly)
{
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().SwapBufferedCurves, NAME_None, SwapBufferedCurvesText);
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().ApplyBufferedCurves, NAME_None, ApplyBufferedCurvesText);
}
MenuBuilder.AddSeparator();
}
// Select
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().SelectAllKeys);
// Filters
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().OpenUserImplementableFilterWindow);
// View
MenuBuilder.AddMenuEntry(FCurveEditorCommands::Get().ZoomToFit);
}
MenuBuilder.EndSection();
}
}
}
#undef LOCTEXT_NAMESPACE