2023-10-05 13:13:03 -04:00

312 lines
15 KiB
C++

// ©2023 Batty Bovine Productions, LLC. All Rights Reserved.
#include "ComboInputEditor.h"
#include "ComboActionGraph.h"
#include "ComboInputAssets.h"
#include "ToolMenuSection.h"
#include "AssetTypeActions/AssetTypeActions_DataAsset.h"
#include "Ed/AssetEditor_ComboActionGraph.h"
#include "Ed/EdComboActionGraphEdge.h"
#include "Ed/EdComboActionGraphNode.h"
#include "Ed/FComboActionGraphEditorCommands.h"
#include "Ed/SEdComboActionGraphEdge.h"
#include "Ed/SEdComboActionGraphNode.h"
#include "Interfaces/IPluginManager.h"
#include "Styling/SlateStyle.h"
#include "Styling/SlateStyleMacros.h"
#include "Styling/SlateStyleRegistry.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(ComboInputEditor)
#define LOCTEXT_NAMESPACE "FComboInputEditorModule"
EAssetTypeCategories::Type FComboInputEditorModule::ComboAssetsCategory;
EAssetTypeCategories::Type FComboInputEditorModule::ComboActionGraphCategory;
class FAssetTypeActions_ComboAction : public FAssetTypeActions_DataAsset
{
public:
virtual FText GetName() const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_ComboAction", "Combo Action"); }
virtual uint32 GetCategories() override { return FComboInputEditorModule::GetInputAssetsCategory(); }
virtual FColor GetTypeColor() const override { return FColor(255, 127, 255); }
virtual FText GetAssetDescription(const FAssetData &AssetData) const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_ComboActionDesc", "An action that can be executed as part of a combo sequence. This is essentially a representation of an attack, and can be sent to the Animation Graph to play an attack animation and the like."); }
virtual UClass *GetSupportedClass() const override { return UComboAction::StaticClass(); }
};
class FAssetTypeActions_ComboInputAsset : public FAssetTypeActions_DataAsset
{
public:
virtual FText GetName() const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_ComboInputAsset", "Combo Input Asset"); }
virtual uint32 GetCategories() override { return FComboInputEditorModule::GetInputAssetsCategory(); }
virtual FColor GetTypeColor() const override { return FColor(255, 127, 255); }
virtual FText GetAssetDescription(const FAssetData &AssetData) const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_ComboInputAssetDesc", "This maps a sequence of button inputs from EnhancedInput to a combo action that can be used to execute a sequence of moves. This gets sent from the input buffer subsystem to the player controller's ComboManagerComponent, which executes the associated action in the current ComboActionGraph."); }
virtual UClass *GetSupportedClass() const override { return UComboInputAsset::StaticClass(); }
};
class FAssetTypeActions_ComboActionGraph : public FAssetTypeActions_Base
{
public:
virtual FText GetName() const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_ComboActionGraph", "Combo Action Graph"); }
virtual uint32 GetCategories() override { return FComboInputEditorModule::GetInputAssetsCategory(); }
virtual FColor GetTypeColor() const override { return FColor(255, 127, 255); }
virtual FText GetAssetDescription(const FAssetData &AssetData) const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_ComboActionGraphDesc", "A node graph containing a sequence of combo actions. Each node can respond to any number of combo inputs, and when activated will execute the associated event."); }
virtual UClass *GetSupportedClass() const override { return UComboActionGraph::StaticClass(); }
virtual void OpenAssetEditor(const TArray<UObject*> &InObjects, TSharedPtr<class IToolkitHost> EditWithinLevelEditor = TSharedPtr<IToolkitHost>()) override
{
const EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone;
for (auto ObjIt = InObjects.CreateConstIterator(); ObjIt; ObjIt++)
{
if (UComboActionGraph *Graph = Cast<UComboActionGraph>(*ObjIt))
{
TSharedRef<FAssetEditor_ComboActionGraph> NewGraphEditor(new FAssetEditor_ComboActionGraph());
NewGraphEditor->InitComboActionGraphAssetEditor(Mode, EditWithinLevelEditor, Graph);
}
}
}
};
class FComboActionGraphPanelNodeFactory : public FGraphPanelNodeFactory
{
public:
virtual TSharedPtr<class SGraphNode> CreateNode(UEdGraphNode *Node) const override
{
if (UEdComboActionGraphNode *EdGraphNode = Cast<UEdComboActionGraphNode>(Node))
{
return SNew(SEdComboActionGraphNode, EdGraphNode);
}
else if (UEdComboActionGraphEdge *EdGraphEdge = Cast<UEdComboActionGraphEdge>(Node))
{
return SNew(SEdComboActionGraphEdge, EdGraphEdge);
}
return nullptr;
}
};
UComboAction_Factory::UComboAction_Factory(const FObjectInitializer &ObjectInitializer)
: Super(ObjectInitializer)
{
this->SupportedClass = UComboAction::StaticClass();
this->bEditAfterNew = true;
this->bCreateNew = true;
}
UObject *UComboAction_Factory::FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn)
{
if (this->ComboActionClass != nullptr)
{
return NewObject<UComboAction>(InParent, this->ComboActionClass, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
else
{
check(Class->IsChildOf(UComboAction::StaticClass()));
return NewObject<UComboAction>(InParent, Class, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
}
UComboInputAsset_Factory::UComboInputAsset_Factory(const FObjectInitializer &ObjectInitializer)
: Super(ObjectInitializer)
{
this->SupportedClass = UComboInputAsset::StaticClass();
this->bEditAfterNew = true;
this->bCreateNew = true;
}
UObject *UComboInputAsset_Factory::FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn)
{
if (this->ComboInputAssetClass != nullptr)
{
return NewObject<UComboInputAsset>(InParent, this->ComboInputAssetClass, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
else
{
check(Class->IsChildOf(UComboInputAsset::StaticClass()));
return NewObject<UComboInputAsset>(InParent, Class, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
}
UComboActionGraph_Factory::UComboActionGraph_Factory(const FObjectInitializer &ObjectInitializer)
: Super(ObjectInitializer)
{
this->SupportedClass = UComboActionGraph::StaticClass();
this->bEditAfterNew = true;
this->bCreateNew = true;
}
UObject *UComboActionGraph_Factory::FactoryCreateNew(UClass *Class, UObject *InParent, FName Name, EObjectFlags Flags, UObject *Context, FFeedbackContext *Warn)
{
if (this->ComboActionGraphClass != nullptr)
{
return NewObject<UComboActionGraph>(InParent, this->ComboActionGraphClass, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
else
{
check(Class->IsChildOf(UComboActionGraph::StaticClass()));
return NewObject<UComboActionGraph>(InParent, Class, Name, Flags | EObjectFlags::RF_Transactional, Context);
}
}
FComboInputSlateStyle::FComboInputSlateStyle() : FSlateStyleSet("ComboInputEditor")
{
this->SetParentStyleName(FAppStyle::GetAppStyleSetName());
const FString &PluginSlateDir = IPluginManager::Get().FindPlugin("ComboInput")->GetBaseDir();
this->SetContentRoot(PluginSlateDir / TEXT("Resources/Slate"));
this->SetCoreContentRoot(FPaths::EngineContentDir() / TEXT("Slate"));
// Combo Input Editor icons
static const FVector2D Icon12(12.0f, 12.0f);
static const FVector2D Icon16(16.0f, 16.0f);
static const FVector2D Icon40(40.0f, 40.0f);
static const FVector2D Icon64(64.0f, 64.0f);
this->Set("ComboInputIcon_Small", new IMAGE_BRUSH_SVG("Icons/ComboInput_16", Icon16));
this->Set("ComboInputIcon_Large", new IMAGE_BRUSH_SVG("Icons/ComboInput_64", Icon64));
this->Set("ClassIcon.ComboAction", new IMAGE_BRUSH_SVG("Icons/ComboAction_16", Icon16));
this->Set("ClassThumbnail.ComboAction", new IMAGE_BRUSH_SVG("Icons/ComboAction_64", Icon64));
this->Set("ClassIcon.ComboSequenceNode", new IMAGE_BRUSH_SVG("Icons/ComboSequenceNode_16", Icon16));
this->Set("ClassThumbnail.ComboSequenceNode", new IMAGE_BRUSH_SVG("Icons/ComboSequenceNode_64", Icon64));
this->Set("ClassIcon.ComboInputAsset", new IMAGE_BRUSH_SVG("Icons/ComboInputAsset_16", Icon16));
this->Set("ClassThumbnail.ComboInputAsset", new IMAGE_BRUSH_SVG("Icons/ComboInputAsset_64", Icon64));
this->Set("ClassIcon.ComboActionGraph", new IMAGE_BRUSH_SVG("Icons/ComboSequenceNode_16", Icon16));
this->Set("ClassThumbnail.ComboActionGraph", new IMAGE_BRUSH_SVG("Icons/ComboSequenceNode_64", Icon64));
// Combo Action Graph editor brushes
{
this->SetContentRoot(PluginSlateDir / TEXT("Resources/Slate/Editor"));
this->SetCoreContentRoot(FPaths::EngineContentDir() / TEXT("Slate/Editor"));
this->Set("MDSStyleSet.AutoArrange.small", new IMAGE_BRUSH(TEXT("AutoArrangeIcon"), Icon16));
this->Set("MDSStyleSet.AutoArrange", new IMAGE_BRUSH(TEXT("AutoArrangeIcon"), Icon40));
this->Set("MDSStyleSet.AutoArrange.large", new IMAGE_BRUSH(TEXT("AutoArrangeIcon"), Icon64));
this->Set("MDSStyleSet.GraphSettings.small", new IMAGE_BRUSH(TEXT("GraphSettings"), Icon16));
this->Set("MDSStyleSet.GraphSettings", new IMAGE_BRUSH(TEXT("GraphSettings"), Icon40));
this->Set("MDSStyleSet.GraphSettings.large", new IMAGE_BRUSH(TEXT("GraphSettings"), Icon64));
this->Set("MDSStyleSet.ValidateGraph.small", new IMAGE_BRUSH(TEXT("ValidateGraph"), Icon16));
this->Set("MDSStyleSet.ValidateGraph", new IMAGE_BRUSH(TEXT("ValidateGraph"), Icon40));
this->Set("MDSStyleSet.ValidateGraph.large", new IMAGE_BRUSH(TEXT("ValidateGraph"), Icon64));
this->Set("MDSStyleSet.Graph.NodeOverlay", new BOX_BRUSH(TEXT("NodeOverlay"), FMargin(8.0f / 64.0f, 3.0f / 32.0f, 0, 0)));
this->Set("MDSStyleSet.Graph.PinDocksOverlay", new BOX_BRUSH(TEXT("PinDocksOverlay"), FMargin(8.0f / 64.0f, 3.0f / 32.0f, 0, 0)));
this->Set("MDSStyleSet.Graph.SimpleArrow", new IMAGE_BRUSH(TEXT("SimpleArrow"), Icon16));
this->Set("MDSStyleSet.Graph.HollowArrow", new IMAGE_BRUSH(TEXT("HollowArrow"), Icon16));
this->Set("MDSStyleSet.Graph.FancyArrow", new IMAGE_BRUSH(TEXT("FancyArrow"), Icon16));
this->Set("MDSStyleSet.Graph.Bubble", new IMAGE_BRUSH(TEXT("Bubble"), Icon16));
this->Set("MDSStyleSet.Node.SoftEdges", new BOX_BRUSH(TEXT("NodeSoftCorners"), FMargin(16.f / 64.f, 25.f / 64.f, 16.f / 64.f, 16.f / 64.f)));
this->Set("MDSStyleSet.Node.HardEdges", new BOX_BRUSH(TEXT("NodeHardCorners"), FMargin(16.f / 64.f, 25.f / 64.f, 16.f / 64.f, 16.f / 64.f)));
this->Set("MDSStyleSet.Node.TextSoftEdges", new BOX_BRUSH(TEXT("TextSoftCorners"), FMargin(16.f / 64.f, 25.f / 64.f, 16.f / 64.f, 16.f / 64.f)));
this->Set("MDSStyleSet.Node.TextHardEdges", new BOX_BRUSH(TEXT("TextHardCorners"), FMargin(16.f / 64.f, 25.f / 64.f, 16.f / 64.f, 16.f / 64.f)));
this->Set("MDSStyleSet.Node.IndexCircle", new IMAGE_BRUSH(TEXT("IndexIcon"), Icon16));
this->Set("MDSStyleSet.Icon.OK", new IMAGE_BRUSH(TEXT("OKIcon"), Icon16));
this->Set("MDSStyleSet.Icon.Error", new IMAGE_BRUSH(TEXT("ErroIcon"), Icon16));
this->Set("MDSStyleSet.Icon.BulletPoint", new IMAGE_BRUSH(TEXT("CircleBox"), Icon16));
this->Set("MDSStyleSet.Graph.CornerImage", new IMAGE_BRUSH(TEXT("Icon128"), FVector2D(128.0f, 128.0f)));
this->Set("MDSStyleSet.Icon.Browse", new IMAGE_BRUSH(TEXT("BrowseIcon"), Icon12));
this->Set("MDSStyleSet.Icon.Edit", new IMAGE_BRUSH(TEXT("EditIcon"), Icon12));
this->Set("MDSStyleSet.Buttons.Documentation", new IMAGE_BRUSH(TEXT("Documentation"), FVector2D(200.0f, 70.0f)));
this->Set("MDSStyleSet.Buttons.Documentation.small", new IMAGE_BRUSH(TEXT("DocumentationIcon"), Icon12));
this->Set("MDSStyleSet.Node.Icon.large", new IMAGE_BRUSH(TEXT("DialogueNodeIcon"), Icon64));
this->Set("MDSStyleSet.Node.Icon", new IMAGE_BRUSH(TEXT("DialogueNodeIcon"), Icon16));
this->Set("MDSStyleSet.Node.Icon.small", new IMAGE_BRUSH(TEXT("DialogueNodeIcon"), Icon12));
this->Set("MDSStyleSet.Icon.Close", new IMAGE_BRUSH(TEXT("CloseIcon"), Icon12));
this->Set("MDSStyleSet.Icon.HeartIcon", new IMAGE_BRUSH(TEXT("HeartIcon"), Icon12));
this->Set("MDSStyleSet.Icon.UBIcon", new IMAGE_BRUSH(TEXT("UnrealBucketIcon"), Icon12));
this->Set("MDSStyleSet.Icon.MoneyIcon", new IMAGE_BRUSH(TEXT("MoneyIcon"), Icon12));
this->Set("MDSStyleSet.Buttons.Style", FButtonStyle()
.SetNormal(BOX_BRUSH("RoundedSelection_16x", 4.0f / 16.0f, FLinearColor(1, 1, 1, 0.1f)))
.SetHovered(BOX_BRUSH("RoundedSelection_16x", 4.0f / 16.0f, FLinearColor(1, .55f, 0, 0.2f)))
.SetPressed(BOX_BRUSH("RoundedSelection_16x", 4.0f / 16.0f, FLinearColor(1, .55f, 0, 0.4f))));
const FScrollBarStyle ScrollBar = GetWidgetStyle<FScrollBarStyle>("ScrollBar");
FTextBlockStyle NormalText = FTextBlockStyle()
.SetFont(DEFAULT_FONT("Regular", FCoreStyle::RegularTextSize))
.SetColorAndOpacity(FSlateColor::UseForeground())
.SetShadowOffset(FVector2D::ZeroVector)
.SetShadowColorAndOpacity(FLinearColor::Black)
.SetHighlightColor(FLinearColor(0.02f, 0.3f, 0.0f))
.SetHighlightShape(BOX_BRUSH("TextBlockHighlightShape", FMargin(3.f / 8.f)));
FTextBlockStyle NodeTitle = FTextBlockStyle(NormalText)
.SetFont(DEFAULT_FONT("Bold", 14))
.SetColorAndOpacity(FLinearColor(230.0f / 255.0f, 230.0f / 255.0f, 230.0f / 255.0f))
.SetShadowOffset(FVector2D(2, 2))
.SetShadowColorAndOpacity(FLinearColor(0.f, 0.f, 0.f, 0.7f));
this->Set("MDSStyleSet.NodeTitle", NodeTitle);
FEditableTextBoxStyle NodeTitleEditableText = FEditableTextBoxStyle()
.SetFont(NormalText.Font)
.SetBackgroundImageNormal(BOX_BRUSH("TextBox", FMargin(4.0f / 16.0f)))
.SetBackgroundImageHovered(BOX_BRUSH("TextBox_Hovered", FMargin(4.0f / 16.0f)))
.SetBackgroundImageFocused(BOX_BRUSH("TextBox_Hovered", FMargin(4.0f / 16.0f)))
.SetBackgroundImageReadOnly(BOX_BRUSH("TextBox_ReadOnly", FMargin(4.0f / 16.0f)))
.SetScrollBarStyle(ScrollBar);
this->Set("MDSStyleSet.NodeTitleEditableText", NodeTitleEditableText);
this->Set("MDSStyleSet.NodeTitleInlineEditableText", FInlineEditableTextBlockStyle()
.SetTextStyle(NodeTitle)
.SetEditableTextBoxStyle(NodeTitleEditableText)
);
}
}
void FComboInputEditorModule::StartupModule()
{
// Register combo action asset
IAssetTools &AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
FComboInputEditorModule::ComboAssetsCategory = AssetTools.RegisterAdvancedAssetCategory(FName(TEXT("Combo Input")), LOCTEXT("ComboInputAssetsCategory", "Combo Input"));
this->RegisterAssetTypeActions(AssetTools, MakeShareable(new FAssetTypeActions_ComboAction));
this->RegisterAssetTypeActions(AssetTools, MakeShareable(new FAssetTypeActions_ComboInputAsset));
// Make a new style set for Combo Input, which will register any custom icons for the types in this plugin
this->ComboInputEditorStyleSet = MakeShared<FComboInputSlateStyle>();
FSlateStyleRegistry::RegisterSlateStyle(*this->ComboInputEditorStyleSet.Get());
// Combo Action Graph
{
this->ComboActionGraphPanelNodeFactory = MakeShareable(new FComboActionGraphPanelNodeFactory());
FEdGraphUtilities::RegisterVisualNodeFactory(this->ComboActionGraphPanelNodeFactory);
// Register asset actions
this->ComboActionGraphAssetActions = MakeShared<FAssetTypeActions_ComboActionGraph>();
this->RegisterAssetTypeActions(AssetTools, this->ComboActionGraphAssetActions.ToSharedRef());
}
FComboActionGraphEditorCommands::Register();
}
void FComboInputEditorModule::ShutdownModule()
{
FComboActionGraphEditorCommands::Unregister();
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FComboInputEditorModule, ComboInputEditorModule)