第一次提交
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class GenericMovementEditor : ModuleRules
|
||||
{
|
||||
public GenericMovementEditor(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
|
||||
CppCompileWarningSettings.NonInlinedGenCppWarningLevel = WarningLevel.Warning;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core", "CoreUObject", "Engine", "AnimGraphRuntime", "AnimationModifiers", "AnimationBlueprintLibrary",
|
||||
"SlateCore",
|
||||
"GenericMovementSystem",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(new[]
|
||||
{
|
||||
"UnrealEd",
|
||||
"AnimGraph",
|
||||
"BlueprintGraph",
|
||||
"ToolMenus",
|
||||
"Blutility",
|
||||
"AssetTools",
|
||||
"GameplayTags",
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
|
||||
#include "Blutility/GMS_EditorUtilityLibrary.h"
|
||||
#include "AnimationModifier.h"
|
||||
#include "AnimationModifiersAssetUserData.h"
|
||||
#include "EditorUtilityLibrary.h"
|
||||
|
||||
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_EditorUtilityLibrary)
|
||||
|
||||
void UGMS_EditorUtilityLibrary::RevertAnimModifierOfClass(TSubclassOf<UAnimationModifier> ModifierClass)
|
||||
{
|
||||
if (!IsValid(ModifierClass))
|
||||
{
|
||||
return;
|
||||
}
|
||||
TArray<UObject*> Anims = UEditorUtilityLibrary::GetSelectedAssetsOfClass(UAnimSequence::StaticClass());
|
||||
|
||||
for (int32 i = 0; i < Anims.Num(); i++)
|
||||
{
|
||||
if (UAnimSequence* AnimSequence = Cast<UAnimSequence>(Anims[i]))
|
||||
{
|
||||
if (UAnimationModifiersAssetUserData* UserData = AnimSequence->GetAssetUserData<UAnimationModifiersAssetUserData>())
|
||||
{
|
||||
const TArray<UAnimationModifier*>& Modifiers = UserData->GetAnimationModifierInstances().FilterByPredicate([&](const UAnimationModifier* Instance)
|
||||
{
|
||||
return Instance && Instance->GetClass()->IsChildOf(ModifierClass);
|
||||
});
|
||||
|
||||
for (const UAnimationModifier* Modifier : Modifiers)
|
||||
{
|
||||
if (Modifier)
|
||||
{
|
||||
Modifier->RevertFromAnimationSequence(AnimSequence);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float UGMS_EditorUtilityLibrary::GetSamplingFrameRate(const UAnimSequence* AnimSequence)
|
||||
{
|
||||
if (AnimSequence)
|
||||
{
|
||||
return AnimSequence->GetSamplingFrameRate().AsDecimal();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
TArray<FName> UGMS_EditorUtilityLibrary::GetAllCurveNames(const UAnimSequence* AnimSequence)
|
||||
{
|
||||
TArray<FName> Names;
|
||||
if (IsValid(AnimSequence))
|
||||
{
|
||||
for (const FFloatCurve& FloatCurve : AnimSequence->GetCurveData().FloatCurves)
|
||||
{
|
||||
Names.Add(FloatCurve.GetName());
|
||||
}
|
||||
}
|
||||
|
||||
return Names;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
|
||||
#include "Factories/GMS_AssetTypeActions.h"
|
||||
#include "GenericMovementEditor.h"
|
||||
#include "Locomotions/GMS_AnimLayer_Overlay_PoseStack.h"
|
||||
#include "Locomotions/GMS_AnimLayer_Overlay_SequenceStack.h"
|
||||
#include "Locomotions/GMS_AnimLayer_States_DefaultLocomotion.h"
|
||||
#include "Settings/GMS_SettingObjectLibrary.h"
|
||||
|
||||
|
||||
uint32 FGMS_AssetTypeAction::GetCategories()
|
||||
{
|
||||
return FGenericMovementEditorModule::GetAssetsCategory();
|
||||
}
|
||||
|
||||
FColor FGMS_AssetTypeAction::GetTypeColor() const
|
||||
{
|
||||
return FColor(114, 40, 199);
|
||||
}
|
||||
|
||||
#define IMPLEMENT_GMS_ASSET_ACTION(ActionName, NameText, DescText) \
|
||||
FText FGMS_AssetTypeAction_##ActionName::GetName() const \
|
||||
{ \
|
||||
return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_" #ActionName "_Name", NameText); \
|
||||
} \
|
||||
FText FGMS_AssetTypeAction_##ActionName::GetAssetDescription(const FAssetData& AssetData) const \
|
||||
{ \
|
||||
return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_" #ActionName "_Description", DescText); \
|
||||
} \
|
||||
UClass* FGMS_AssetTypeAction_##ActionName::GetSupportedClass() const \
|
||||
{ \
|
||||
return UGMS_##ActionName::StaticClass(); \
|
||||
}
|
||||
|
||||
IMPLEMENT_GMS_ASSET_ACTION(MovementDefinition, "Movement Definition",
|
||||
"Data Asset that defines multiple movement set settings together.")
|
||||
IMPLEMENT_GMS_ASSET_ACTION(MovementControlSetting_Default, "Movement Control Setting",
|
||||
"Data Asset that defines movement control settings")
|
||||
IMPLEMENT_GMS_ASSET_ACTION(AnimGraphSetting, "Anim Graph Setting",
|
||||
"Data Asset that stores animation graph-specific settings, one per unique skeleton.")
|
||||
IMPLEMENT_GMS_ASSET_ACTION(AnimLayerSetting_States_Default, "States Anim Layer Setting(Basic Locomotion)",
|
||||
"Data Asset that stores basic locomotion(default states animation layer settings.)")
|
||||
IMPLEMENT_GMS_ASSET_ACTION(AnimLayerSetting_Overlay_PoseStack, "Overlay Anim Layer Setting(Pose Stack)",
|
||||
"Data Asset that stores pose stack overlay settings")
|
||||
IMPLEMENT_GMS_ASSET_ACTION(AnimLayerSetting_Overlay_SequenceStack, "Overlay Anim Layer Setting(Sequence Stack)",
|
||||
"Data Asset that stores sequence stack overlay settings")
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
|
||||
#include "Factories/GMS_DataAssetsFactories.h"
|
||||
|
||||
#include "Locomotions/GMS_AnimLayer_Overlay_PoseStack.h"
|
||||
#include "Locomotions/GMS_AnimLayer_Overlay_SequenceStack.h"
|
||||
#include "Locomotions/GMS_AnimLayer_States_DefaultLocomotion.h"
|
||||
#include "Settings/GMS_SettingObjectLibrary.h"
|
||||
|
||||
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_DataAssetsFactories)
|
||||
|
||||
|
||||
UGMS_Factory::UGMS_Factory(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
|
||||
{
|
||||
bEditAfterNew = true;
|
||||
bCreateNew = true;
|
||||
}
|
||||
|
||||
uint32 UGMS_Factory::GetMenuCategories() const
|
||||
{
|
||||
return Super::GetMenuCategories();
|
||||
}
|
||||
|
||||
const TArray<FText>& UGMS_Factory::GetMenuCategorySubMenus() const
|
||||
{
|
||||
return Super::GetMenuCategorySubMenus();
|
||||
}
|
||||
|
||||
#define IMPLEMENT_GMS_FACTORY(FactoryName) \
|
||||
UGMS_Factory_##FactoryName::UGMS_Factory_##FactoryName(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) \
|
||||
{ \
|
||||
SupportedClass = UGMS_##FactoryName::StaticClass(); \
|
||||
} \
|
||||
UObject* UGMS_Factory_##FactoryName::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) \
|
||||
{ \
|
||||
check(Class->IsChildOf(UGMS_##FactoryName::StaticClass())); \
|
||||
return NewObject<UGMS_##FactoryName>(InParent, Class, Name, Flags | RF_Transactional, Context); \
|
||||
}
|
||||
|
||||
IMPLEMENT_GMS_FACTORY(MovementDefinition)
|
||||
IMPLEMENT_GMS_FACTORY(MovementControlSetting_Default)
|
||||
IMPLEMENT_GMS_FACTORY(AnimGraphSetting)
|
||||
IMPLEMENT_GMS_FACTORY(AnimLayerSetting_States_Default)
|
||||
IMPLEMENT_GMS_FACTORY(AnimLayerSetting_Overlay_PoseStack)
|
||||
IMPLEMENT_GMS_FACTORY(AnimLayerSetting_Overlay_SequenceStack)
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
#include "GenericMovementEditor.h"
|
||||
#include "AssetToolsModule.h"
|
||||
#include "Factories/GMS_AssetTypeActions.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FGenericMovementEditorModule"
|
||||
|
||||
TArray<TSharedPtr<IAssetTypeActions>> FGenericMovementEditorModule::AssetTypeActions = {
|
||||
MakeShared<FGMS_AssetTypeAction_MovementDefinition>(),
|
||||
MakeShared<FGMS_AssetTypeAction_AnimGraphSetting>(),
|
||||
MakeShared<FGMS_AssetTypeAction_MovementControlSetting_Default>(),
|
||||
MakeShared<FGMS_AssetTypeAction_AnimLayerSetting_States_Default>(),
|
||||
MakeShared<FGMS_AssetTypeAction_AnimLayerSetting_Overlay_PoseStack>(),
|
||||
MakeShared<FGMS_AssetTypeAction_AnimLayerSetting_Overlay_SequenceStack>()
|
||||
};
|
||||
|
||||
EAssetTypeCategories::Type FGenericMovementEditorModule::AssetsCategory;
|
||||
|
||||
|
||||
void FGenericMovementEditorModule::StartupModule()
|
||||
{
|
||||
IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();
|
||||
AssetsCategory = AssetTools.RegisterAdvancedAssetCategory(FName(TEXT("GenericMovementSystem")), LOCTEXT("GMS_AssetsCategory", "Generic Movement System"));
|
||||
for (TSharedPtr<IAssetTypeActions>& Action : AssetTypeActions)
|
||||
{
|
||||
AssetTools.RegisterAssetTypeActions(Action.ToSharedRef());
|
||||
}
|
||||
}
|
||||
|
||||
void FGenericMovementEditorModule::ShutdownModule()
|
||||
{
|
||||
if (const FAssetToolsModule* AssetTools = FModuleManager::GetModulePtr<FAssetToolsModule>("AssetTools"))
|
||||
{
|
||||
for (TSharedPtr<IAssetTypeActions>& Action : AssetTypeActions)
|
||||
{
|
||||
AssetTools->Get().UnregisterAssetTypeActions(Action.ToSharedRef());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FGenericMovementEditorModule, GenericMovementEditor)
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AssetTypeCategories.h"
|
||||
#include "IAssetTools.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
class FGenericMovementEditorModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
static EAssetTypeCategories::Type GetAssetsCategory()
|
||||
{
|
||||
return AssetsCategory;
|
||||
}
|
||||
|
||||
private:
|
||||
static TArray<TSharedPtr<IAssetTypeActions>> AssetTypeActions;
|
||||
static EAssetTypeCategories::Type AssetsCategory;
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
|
||||
#include "Nodes/GMS_AnimGraphNode_CurvesBlend.h"
|
||||
|
||||
|
||||
#define LOCTEXT_NAMESPACE "GMS_CurvesBlendAnimationGraphNode"
|
||||
|
||||
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_AnimGraphNode_CurvesBlend)
|
||||
|
||||
FText UGMS_AnimGraphNode_CurvesBlend::GetNodeTitle(const ENodeTitleType::Type TitleType) const
|
||||
{
|
||||
return LOCTEXT("Title", "Blend Curves");
|
||||
}
|
||||
|
||||
FText UGMS_AnimGraphNode_CurvesBlend::GetTooltipText() const
|
||||
{
|
||||
return LOCTEXT("Tooltip", "Blend Curves");
|
||||
}
|
||||
|
||||
FString UGMS_AnimGraphNode_CurvesBlend::GetNodeCategory() const
|
||||
{
|
||||
return FString{TEXTVIEW("GMS|Blends")};
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,106 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
|
||||
#include "Nodes/GMS_AnimGraphNode_GameplayTagsBlend.h"
|
||||
|
||||
#include "GameplayTagsManager.h"
|
||||
|
||||
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_AnimGraphNode_GameplayTagsBlend)
|
||||
|
||||
#define LOCTEXT_NAMESPACE "GMS_AnimGraphNode_GameplayTagsBlend"
|
||||
|
||||
UGMS_AnimGraphNode_GameplayTagsBlend::UGMS_AnimGraphNode_GameplayTagsBlend()
|
||||
{
|
||||
Node.AddPose();
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_GameplayTagsBlend::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
if (PropertyChangedEvent.GetPropertyName() == GET_MEMBER_NAME_CHECKED(FGMS_AnimNode_GameplayTagsBlend, Tags))
|
||||
{
|
||||
ReconstructNode();
|
||||
}
|
||||
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
}
|
||||
|
||||
FText UGMS_AnimGraphNode_GameplayTagsBlend::GetNodeTitle(const ENodeTitleType::Type TitleType) const
|
||||
{
|
||||
return LOCTEXT("Title", "Blend Poses by Gameplay Tag");
|
||||
}
|
||||
|
||||
FText UGMS_AnimGraphNode_GameplayTagsBlend::GetTooltipText() const
|
||||
{
|
||||
return LOCTEXT("Tooltip", "Blend Poses by Gameplay Tag");
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_GameplayTagsBlend::ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& PreviousPins)
|
||||
{
|
||||
Node.RefreshPoses();
|
||||
|
||||
Super::ReallocatePinsDuringReconstruction(PreviousPins);
|
||||
}
|
||||
|
||||
FString UGMS_AnimGraphNode_GameplayTagsBlend::GetNodeCategory() const
|
||||
{
|
||||
return FString{TEXTVIEW("GMS|Blends")};
|
||||
}
|
||||
|
||||
FName GetSimpleTagName(const FGameplayTag& Tag)
|
||||
{
|
||||
const auto TagNode{UGameplayTagsManager::Get().FindTagNode(Tag)};
|
||||
|
||||
return TagNode.IsValid() ? TagNode->GetSimpleTagName() : NAME_None;
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_GameplayTagsBlend::CustomizePinData(UEdGraphPin* Pin, const FName SourcePropertyName, const int32 PinIndex) const
|
||||
{
|
||||
Super::CustomizePinData(Pin, SourcePropertyName, PinIndex);
|
||||
|
||||
bool bBlendPosePin;
|
||||
bool bBlendTimePin;
|
||||
GetBlendPinProperties(Pin, bBlendPosePin, bBlendTimePin);
|
||||
|
||||
if (!bBlendPosePin && !bBlendTimePin)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Pin->PinFriendlyName = PinIndex <= 0
|
||||
? LOCTEXT("Default", "Default")
|
||||
: PinIndex > Node.Tags.Num()
|
||||
? LOCTEXT("Invalid", "Invalid")
|
||||
: FText::AsCultureInvariant(GetSimpleTagName(Node.Tags[PinIndex - 1]).ToString());
|
||||
|
||||
if (bBlendPosePin)
|
||||
{
|
||||
static const FTextFormat BlendPosePinFormat{LOCTEXT("Pose", "{PinName} Pose")};
|
||||
|
||||
Pin->PinFriendlyName = FText::Format(BlendPosePinFormat, {{FString{TEXTVIEW("PinName")}, Pin->PinFriendlyName}});
|
||||
}
|
||||
else if (bBlendTimePin)
|
||||
{
|
||||
static const FTextFormat BlendTimePinFormat{LOCTEXT("BlendTime", "{PinName} Blend Time")};
|
||||
|
||||
Pin->PinFriendlyName = FText::Format(BlendTimePinFormat, {{FString{TEXTVIEW("PinName")}, Pin->PinFriendlyName}});
|
||||
}
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_GameplayTagsBlend::GetBlendPinProperties(const UEdGraphPin* Pin, bool& bBlendPosePin, bool& bBlendTimePin)
|
||||
{
|
||||
const auto PinFullName{Pin->PinName.ToString()};
|
||||
const auto SeparatorIndex{PinFullName.Find(TEXT("_"), ESearchCase::CaseSensitive)};
|
||||
|
||||
if (SeparatorIndex <= 0)
|
||||
{
|
||||
bBlendPosePin = false;
|
||||
bBlendTimePin = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PinName{PinFullName.Left(SeparatorIndex)};
|
||||
bBlendPosePin = PinName == TEXTVIEW("BlendPose");
|
||||
bBlendTimePin = PinName == TEXTVIEW("BlendTime");
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,111 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
#include "Nodes/GMS_AnimGraphNode_LayeredBoneBlend.h"
|
||||
#include "ToolMenus.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
|
||||
#include "AnimGraphCommands.h"
|
||||
#include "ScopedTransaction.h"
|
||||
|
||||
#include "Kismet2/CompilerResultsLog.h"
|
||||
#include "UObject/UE5ReleaseStreamObjectVersion.h"
|
||||
|
||||
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_AnimGraphNode_LayeredBoneBlend)
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// UGMS_AnimGraphNode_LayeredBoneBlend
|
||||
|
||||
#define LOCTEXT_NAMESPACE "A3Nodes"
|
||||
|
||||
UGMS_AnimGraphNode_LayeredBoneBlend::UGMS_AnimGraphNode_LayeredBoneBlend(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
Node.AddPose();
|
||||
}
|
||||
|
||||
FLinearColor UGMS_AnimGraphNode_LayeredBoneBlend::GetNodeTitleColor() const
|
||||
{
|
||||
return FLinearColor(0.2f, 0.8f, 0.3f);
|
||||
}
|
||||
|
||||
FText UGMS_AnimGraphNode_LayeredBoneBlend::GetTooltipText() const
|
||||
{
|
||||
return LOCTEXT("AnimGraphNode_LayeredBoneBlend_Tooltip", "Generic Layered blend per bone");
|
||||
}
|
||||
|
||||
FText UGMS_AnimGraphNode_LayeredBoneBlend::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
||||
{
|
||||
return LOCTEXT("AnimGraphNode_LayeredBoneBlend_Title", "Generic Layered blend per bone");
|
||||
}
|
||||
|
||||
FString UGMS_AnimGraphNode_LayeredBoneBlend::GetNodeCategory() const
|
||||
{
|
||||
return TEXT("Animation|Blends");
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_LayeredBoneBlend::AddPinToBlendByFilter()
|
||||
{
|
||||
FScopedTransaction Transaction( LOCTEXT("AddPinToBlend", "AddPinToBlendByFilter") );
|
||||
Modify();
|
||||
|
||||
Node.AddPose();
|
||||
ReconstructNode();
|
||||
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint());
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_LayeredBoneBlend::RemovePinFromBlendByFilter(UEdGraphPin* Pin)
|
||||
{
|
||||
FScopedTransaction Transaction( LOCTEXT("RemovePinFromBlend", "RemovePinFromBlendByFilter") );
|
||||
Modify();
|
||||
|
||||
FProperty* AssociatedProperty;
|
||||
int32 ArrayIndex;
|
||||
GetPinAssociatedProperty(GetFNodeType(), Pin, /*out*/ AssociatedProperty, /*out*/ ArrayIndex);
|
||||
|
||||
if (ArrayIndex != INDEX_NONE)
|
||||
{
|
||||
//@TODO: ANIMREFACTOR: Need to handle moving pins below up correctly
|
||||
// setting up removed pins info
|
||||
RemovedPinArrayIndex = ArrayIndex;
|
||||
Node.RemovePose(ArrayIndex);
|
||||
ReconstructNode();
|
||||
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint());
|
||||
}
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_LayeredBoneBlend::GetNodeContextMenuActions(UToolMenu* Menu, UGraphNodeContextMenuContext* Context) const
|
||||
{
|
||||
if (!Context->bIsDebugging)
|
||||
{
|
||||
{
|
||||
FToolMenuSection& Section = Menu->AddSection("AnimGraphNodeLayeredBoneblend", LOCTEXT("LayeredBoneBlend", "Generic Layered Bone Blend"));
|
||||
if (Context->Pin != NULL)
|
||||
{
|
||||
// we only do this for normal BlendList/BlendList by enum, BlendList by Bool doesn't support add/remove pins
|
||||
if (Context->Pin->Direction == EGPD_Input)
|
||||
{
|
||||
//@TODO: Only offer this option on arrayed pins
|
||||
Section.AddMenuEntry(FAnimGraphCommands::Get().RemoveBlendListPin);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Section.AddMenuEntry(FAnimGraphCommands::Get().AddBlendListPin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_LayeredBoneBlend::ValidateAnimNodeDuringCompilation(class USkeleton* ForSkeleton, class FCompilerResultsLog& MessageLog)
|
||||
{
|
||||
UAnimGraphNode_Base::ValidateAnimNodeDuringCompilation(ForSkeleton, MessageLog);
|
||||
|
||||
// ensure to cache the per-bone blend weights
|
||||
if (!Node.ArePerBoneBlendWeightsValid(ForSkeleton))
|
||||
{
|
||||
Node.RebuildPerBoneBlendWeights(ForSkeleton);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,287 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
#include "Nodes/GMS_AnimGraphNode_OrientationWarping.h"
|
||||
#include "Animation/AnimRootMotionProvider.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
#include "Kismet2/CompilerResultsLog.h"
|
||||
#include "DetailCategoryBuilder.h"
|
||||
#include "DetailLayoutBuilder.h"
|
||||
#include "PropertyHandle.h"
|
||||
#include "ScopedTransaction.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "GMS_AnimGraphNode_OrientationWarping"
|
||||
#include UE_INLINE_GENERATED_CPP_BY_NAME(GMS_AnimGraphNode_OrientationWarping)
|
||||
|
||||
UGMS_AnimGraphNode_OrientationWarping::UGMS_AnimGraphNode_OrientationWarping(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
|
||||
{
|
||||
}
|
||||
|
||||
FText UGMS_AnimGraphNode_OrientationWarping::GetControllerDescription() const
|
||||
{
|
||||
return LOCTEXT("OrientationWarping", "Generic Orientation Warping");
|
||||
}
|
||||
|
||||
FText UGMS_AnimGraphNode_OrientationWarping::GetTooltipText() const
|
||||
{
|
||||
return LOCTEXT("OrientationWarpingTooltip", "Rotates the root and lower body by the specified angle, while counter rotating the upper body to maintain the forward facing direction.");
|
||||
}
|
||||
|
||||
FText UGMS_AnimGraphNode_OrientationWarping::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
||||
{
|
||||
return GetControllerDescription();
|
||||
}
|
||||
|
||||
FLinearColor UGMS_AnimGraphNode_OrientationWarping::GetNodeTitleColor() const
|
||||
{
|
||||
return FLinearColor(FColor(0.f, 255.f, 0.f));
|
||||
}
|
||||
|
||||
FString UGMS_AnimGraphNode_OrientationWarping::GetNodeCategory() const
|
||||
{
|
||||
return TEXT("GMS|Animation Warping");
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_OrientationWarping::CustomizePinData(UEdGraphPin* Pin, FName SourcePropertyName, int32 ArrayIndex) const
|
||||
{
|
||||
Super::CustomizePinData(Pin, SourcePropertyName, ArrayIndex);
|
||||
|
||||
return; //直接返回,编辑器模式下不根据配置情况动态隐藏/显示属性
|
||||
|
||||
// if (Pin->PinName == GET_MEMBER_NAME_STRING_CHECKED(FGMS_AnimNode_OrientationWarping, OrientationAngle))
|
||||
// {
|
||||
// Pin->bHidden = (Node.Mode == EWarpingEvaluationMode::Graph);
|
||||
// }
|
||||
//
|
||||
// if (Pin->PinName == GET_MEMBER_NAME_STRING_CHECKED(FGMS_AnimNode_OrientationWarping, LocomotionAngle))
|
||||
// {
|
||||
// Pin->bHidden = (Node.Mode == EWarpingEvaluationMode::Manual);
|
||||
// }
|
||||
//
|
||||
// if (Pin->PinName == GET_MEMBER_NAME_STRING_CHECKED(FGMS_AnimNode_OrientationWarping, LocomotionAngleDeltaThreshold))
|
||||
// {
|
||||
// Pin->bHidden = (Node.Mode == EWarpingEvaluationMode::Manual);
|
||||
// }
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_OrientationWarping::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder)
|
||||
{
|
||||
DECLARE_SCOPE_HIERARCHICAL_COUNTER_FUNC()
|
||||
Super::CustomizeDetails(DetailBuilder);
|
||||
|
||||
return; //直接返回,编辑器模式下不根据配置情况动态隐藏/显示属性
|
||||
|
||||
// DetailBuilder.SortCategories([](const TMap<FName, IDetailCategoryBuilder*>& CategoryMap)
|
||||
// {
|
||||
// for (const TPair<FName, IDetailCategoryBuilder*>& Pair : CategoryMap)
|
||||
// {
|
||||
// int32 SortOrder = Pair.Value->GetSortOrder();
|
||||
// const FName CategoryName = Pair.Key;
|
||||
//
|
||||
// if (CategoryName == "Evaluation")
|
||||
// {
|
||||
// SortOrder += 1;
|
||||
// }
|
||||
// else if (CategoryName == "Settings")
|
||||
// {
|
||||
// SortOrder += 2;
|
||||
// }
|
||||
// else if (CategoryName == "Debug")
|
||||
// {
|
||||
// SortOrder += 3;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// const int32 ValueSortOrder = Pair.Value->GetSortOrder();
|
||||
// if (ValueSortOrder >= SortOrder && ValueSortOrder < SortOrder + 10)
|
||||
// {
|
||||
// SortOrder += 10;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Pair.Value->SetSortOrder(SortOrder);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// TSharedRef<IPropertyHandle> NodeHandle = DetailBuilder.GetProperty(FName(TEXT("Node")), GetClass());
|
||||
//
|
||||
// if (Node.Mode == EWarpingEvaluationMode::Graph)
|
||||
// {
|
||||
// DetailBuilder.HideProperty(NodeHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FGMS_AnimNode_OrientationWarping, OrientationAngle)));
|
||||
// }
|
||||
//
|
||||
// if (Node.Mode == EWarpingEvaluationMode::Manual)
|
||||
// {
|
||||
// DetailBuilder.HideProperty(NodeHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FGMS_AnimNode_OrientationWarping, LocomotionAngle)));
|
||||
// DetailBuilder.HideProperty(NodeHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FGMS_AnimNode_OrientationWarping, LocomotionAngleDeltaThreshold)));
|
||||
// DetailBuilder.HideProperty(NodeHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FGMS_AnimNode_OrientationWarping, MinRootMotionSpeedThreshold)));
|
||||
// }
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_OrientationWarping::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent)
|
||||
{
|
||||
DECLARE_SCOPE_HIERARCHICAL_COUNTER_FUNC()
|
||||
Super::PostEditChangeProperty(PropertyChangedEvent);
|
||||
|
||||
return; //直接返回,编辑器模式下不根据配置情况动态隐藏/显示属性
|
||||
|
||||
// bool bRequiresNodeReconstruct = false;
|
||||
// FProperty* ChangedProperty = PropertyChangedEvent.Property;
|
||||
//
|
||||
// if (ChangedProperty)
|
||||
// {
|
||||
// // Evaluation mode
|
||||
// if (ChangedProperty->GetFName() == GET_MEMBER_NAME_STRING_CHECKED(FGMS_AnimNode_OrientationWarping, Mode))
|
||||
// {
|
||||
// FScopedTransaction Transaction(LOCTEXT("ChangeEvaluationMode", "Change Evaluation Mode"));
|
||||
// Modify();
|
||||
//
|
||||
// // Break links to pins going away
|
||||
// for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex)
|
||||
// {
|
||||
// UEdGraphPin* Pin = Pins[PinIndex];
|
||||
// if (Pin->PinName == GET_MEMBER_NAME_STRING_CHECKED(FGMS_AnimNode_OrientationWarping, OrientationAngle))
|
||||
// {
|
||||
// if (Node.Mode == EWarpingEvaluationMode::Graph)
|
||||
// {
|
||||
// Pin->BreakAllPinLinks();
|
||||
// }
|
||||
// }
|
||||
// else if (Pin->PinName == GET_MEMBER_NAME_STRING_CHECKED(FGMS_AnimNode_OrientationWarping, LocomotionAngle))
|
||||
// {
|
||||
// if (Node.Mode == EWarpingEvaluationMode::Manual)
|
||||
// {
|
||||
// Pin->BreakAllPinLinks();
|
||||
// }
|
||||
// }
|
||||
// else if (Pin->PinName == GET_MEMBER_NAME_STRING_CHECKED(FGMS_AnimNode_OrientationWarping, LocomotionAngleDeltaThreshold))
|
||||
// {
|
||||
// if (Node.Mode == EWarpingEvaluationMode::Manual)
|
||||
// {
|
||||
// Pin->BreakAllPinLinks();
|
||||
// }
|
||||
// }
|
||||
// else if (Pin->PinName == GET_MEMBER_NAME_STRING_CHECKED(FGMS_AnimNode_OrientationWarping, MinRootMotionSpeedThreshold))
|
||||
// {
|
||||
// if (Node.Mode == EWarpingEvaluationMode::Manual)
|
||||
// {
|
||||
// Pin->BreakAllPinLinks();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// bRequiresNodeReconstruct = true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (bRequiresNodeReconstruct)
|
||||
// {
|
||||
// ReconstructNode();
|
||||
// FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint());
|
||||
// }
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_OrientationWarping::GetInputLinkAttributes(FNodeAttributeArray& OutAttributes) const
|
||||
{
|
||||
if (Node.Mode == EWarpingEvaluationMode::Graph)
|
||||
{
|
||||
OutAttributes.Add(UE::Anim::IAnimRootMotionProvider::AttributeName);
|
||||
}
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_OrientationWarping::GetOutputLinkAttributes(FNodeAttributeArray& OutAttributes) const
|
||||
{
|
||||
if (Node.Mode == EWarpingEvaluationMode::Graph)
|
||||
{
|
||||
OutAttributes.Add(UE::Anim::IAnimRootMotionProvider::AttributeName);
|
||||
}
|
||||
}
|
||||
|
||||
void UGMS_AnimGraphNode_OrientationWarping::ValidateAnimNodeDuringCompilation(USkeleton* ForSkeleton, FCompilerResultsLog& MessageLog)
|
||||
{
|
||||
return Super::ValidateAnimNodeDuringCompilation(ForSkeleton, MessageLog); //直接返回,编辑器模式下不做任何校验。
|
||||
// auto HasInvalidBoneName = [](const FName& BoneName)
|
||||
// {
|
||||
// return BoneName == NAME_None;
|
||||
// };
|
||||
//
|
||||
// auto HasInvalidBoneIndex = [&](const FName& BoneName)
|
||||
// {
|
||||
// return ForSkeleton && ForSkeleton->GetReferenceSkeleton().FindBoneIndex(BoneName) == INDEX_NONE;
|
||||
// };
|
||||
//
|
||||
// auto InvalidBoneNameMessage = [&](const FName& BoneName)
|
||||
// {
|
||||
// FFormatNamedArguments Args;
|
||||
// Args.Add(TEXT("BoneName"), FText::FromName(BoneName));
|
||||
// const FText Message = FText::Format(NSLOCTEXT("OrientationWarping", "Invalid{BoneName}BoneName", "@@ - {BoneName} bone not found in Skeleton"), Args);
|
||||
// MessageLog.Warning(*Message.ToString(), this);
|
||||
// };
|
||||
//
|
||||
// auto InvalidBoneIndexMessage = [&](const FName& BoneName)
|
||||
// {
|
||||
// FFormatNamedArguments Args;
|
||||
// Args.Add(TEXT("BoneName"), FText::FromName(BoneName));
|
||||
// const FText Message = FText::Format(NSLOCTEXT("OrientationWarping", "Invalid{BoneName}BoneInSkeleton", "@@ - {BoneName} bone definition is required"), Args);
|
||||
// MessageLog.Warning(*Message.ToString(), this);
|
||||
// };
|
||||
//
|
||||
// if (Node.RotationAxis == EAxis::None)
|
||||
// {
|
||||
// MessageLog.Warning(*NSLOCTEXT("OrientationWarping", "InvalidRotationAxis", "@@ - Rotation Axis choice of X, Y, or Z is required").ToString(), this);
|
||||
// }
|
||||
//
|
||||
// if (Node.SpineBones.IsEmpty())
|
||||
// {
|
||||
// MessageLog.Warning(*NSLOCTEXT("OrientationWarping", "InvalidSpineBones", "@@ - Spine bone definitions are required").ToString(), this);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// for (const auto& Bone : Node.SpineBones)
|
||||
// {
|
||||
// if (HasInvalidBoneName(Bone.BoneName))
|
||||
// {
|
||||
// InvalidBoneIndexMessage("Spine");
|
||||
// }
|
||||
// else if (HasInvalidBoneIndex(Bone.BoneName))
|
||||
// {
|
||||
// InvalidBoneNameMessage(Bone.BoneName);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (HasInvalidBoneName(Node.IKFootRootBone.BoneName))
|
||||
// {
|
||||
// InvalidBoneIndexMessage("IK Foot Root");
|
||||
// }
|
||||
// else if (HasInvalidBoneIndex(Node.IKFootRootBone.BoneName))
|
||||
// {
|
||||
// InvalidBoneNameMessage(Node.IKFootRootBone.BoneName);
|
||||
// }
|
||||
//
|
||||
// if (Node.SpineBones.IsEmpty())
|
||||
// {
|
||||
// MessageLog.Warning(*NSLOCTEXT("OrientationWarping", "InvalidIKFootBones", "@@ - IK Foot bone definitions are required").ToString(), this);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// for (const auto& Bone : Node.IKFootBones)
|
||||
// {
|
||||
// if (HasInvalidBoneName(Bone.BoneName))
|
||||
// {
|
||||
// InvalidBoneIndexMessage("IK Foot");
|
||||
// }
|
||||
// else if (HasInvalidBoneIndex(Bone.BoneName))
|
||||
// {
|
||||
// InvalidBoneNameMessage(Bone.BoneName);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Super::ValidateAnimNodeDuringCompilation(ForSkeleton, MessageLog);
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "GMS_EditorUtilityLibrary.generated.h"
|
||||
|
||||
class UAnimationModifier;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(Blueprintable)
|
||||
class GENERICMOVEMENTEDITOR_API UGMS_EditorUtilityLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
#if WITH_EDITOR
|
||||
UFUNCTION(BlueprintCallable, Category="GMS|Development|Editor")
|
||||
static void RevertAnimModifierOfClass(TSubclassOf<UAnimationModifier> ModifierClass);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="GMS|Development|Editor")
|
||||
static float GetSamplingFrameRate(const UAnimSequence* AnimSequence);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="GMS|Development|Editor")
|
||||
static TArray<FName> GetAllCurveNames(const UAnimSequence* AnimSequence);
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AssetTypeActions/AssetTypeActions_DataAsset.h"
|
||||
|
||||
class FGMS_AssetTypeAction : public FAssetTypeActions_DataAsset
|
||||
{
|
||||
public:
|
||||
virtual uint32 GetCategories() override;
|
||||
virtual FColor GetTypeColor() const override;
|
||||
};
|
||||
|
||||
#define DEFINE_GMS_ASSET_ACTION(ActionName) \
|
||||
class FGMS_AssetTypeAction_##ActionName final : public FGMS_AssetTypeAction \
|
||||
{ \
|
||||
public: \
|
||||
virtual FText GetName() const override; \
|
||||
virtual FText GetAssetDescription(const FAssetData& AssetData) const override; \
|
||||
virtual UClass* GetSupportedClass() const override; \
|
||||
};
|
||||
|
||||
DEFINE_GMS_ASSET_ACTION(MovementDefinition)
|
||||
|
||||
DEFINE_GMS_ASSET_ACTION(MovementControlSetting_Default)
|
||||
|
||||
DEFINE_GMS_ASSET_ACTION(AnimGraphSetting)
|
||||
|
||||
DEFINE_GMS_ASSET_ACTION(AnimLayerSetting_States_Default)
|
||||
|
||||
DEFINE_GMS_ASSET_ACTION(AnimLayerSetting_Overlay_PoseStack)
|
||||
|
||||
DEFINE_GMS_ASSET_ACTION(AnimLayerSetting_Overlay_SequenceStack)
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "Templates/SubclassOf.h"
|
||||
#include "Factories/Factory.h"
|
||||
#include "GMS_DataAssetsFactories.generated.h"
|
||||
|
||||
UCLASS(Abstract)
|
||||
class UGMS_Factory : public UFactory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGMS_Factory(const FObjectInitializer& ObjectInitializer);
|
||||
virtual uint32 GetMenuCategories() const override;
|
||||
virtual const TArray<FText>& GetMenuCategorySubMenus() const override;
|
||||
};
|
||||
|
||||
#define DEFINE_GMS_FACTORY(FactoryName) \
|
||||
UCLASS() \
|
||||
class UGMS_Factory_##FactoryName : public UGMS_Factory \
|
||||
{ \
|
||||
GENERATED_BODY() \
|
||||
public: \
|
||||
UGMS_Factory_##FactoryName(const FObjectInitializer& ObjectInitializer); \
|
||||
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override; \
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UGMS_Factory_MovementDefinition : public UGMS_Factory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGMS_Factory_MovementDefinition(const FObjectInitializer& ObjectInitializer);
|
||||
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UGMS_Factory_MovementControlSetting_Default : public UGMS_Factory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGMS_Factory_MovementControlSetting_Default(const FObjectInitializer& ObjectInitializer);
|
||||
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UGMS_Factory_AnimGraphSetting : public UGMS_Factory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGMS_Factory_AnimGraphSetting(const FObjectInitializer& ObjectInitializer);
|
||||
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UGMS_Factory_AnimLayerSetting_States_Default : public UGMS_Factory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGMS_Factory_AnimLayerSetting_States_Default(const FObjectInitializer& ObjectInitializer);
|
||||
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UGMS_Factory_AnimLayerSetting_Overlay_PoseStack : public UGMS_Factory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGMS_Factory_AnimLayerSetting_Overlay_PoseStack(const FObjectInitializer& ObjectInitializer);
|
||||
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UGMS_Factory_AnimLayerSetting_Overlay_SequenceStack : public UGMS_Factory
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGMS_Factory_AnimLayerSetting_Overlay_SequenceStack(const FObjectInitializer& ObjectInitializer);
|
||||
virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override;
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "AnimGraphNode_Base.h"
|
||||
#include "Nodes/GMS_AnimNode_CurvesBlend.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "GMS_AnimGraphNode_CurvesBlend.generated.h"
|
||||
|
||||
|
||||
UCLASS()
|
||||
class GENERICMOVEMENTEDITOR_API UGMS_AnimGraphNode_CurvesBlend : public UAnimGraphNode_Base
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Settings")
|
||||
FGMS_AnimNode_CurvesBlend Node;
|
||||
|
||||
public:
|
||||
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
|
||||
|
||||
virtual FText GetTooltipText() const override;
|
||||
|
||||
virtual FString GetNodeCategory() const override;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AnimGraphNode_BlendListBase.h"
|
||||
#include "Nodes/GMS_AnimNode_GameplayTagsBlend.h"
|
||||
#include "GMS_AnimGraphNode_GameplayTagsBlend.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class GENERICMOVEMENTEDITOR_API UGMS_AnimGraphNode_GameplayTagsBlend : public UAnimGraphNode_BlendListBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Settings")
|
||||
FGMS_AnimNode_GameplayTagsBlend Node;
|
||||
|
||||
public:
|
||||
UGMS_AnimGraphNode_GameplayTagsBlend();
|
||||
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent &PropertyChangedEvent) override;
|
||||
|
||||
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
|
||||
|
||||
virtual FText GetTooltipText() const override;
|
||||
|
||||
virtual void ReallocatePinsDuringReconstruction(TArray<UEdGraphPin *> &PreviousPins) override;
|
||||
|
||||
virtual FString GetNodeCategory() const override;
|
||||
|
||||
virtual void CustomizePinData(UEdGraphPin *Pin, FName SourcePropertyName, int32 PinIndex) const override;
|
||||
|
||||
protected:
|
||||
static void GetBlendPinProperties(const UEdGraphPin *Pin, bool &bBlendPosePin, bool &bBlendTimePin);
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "AnimGraphNode_BlendListBase.h"
|
||||
#include "Nodes/GMS_AnimNode_LayeredBoneBlend.h"
|
||||
#include "GMS_AnimGraphNode_LayeredBoneBlend.generated.h"
|
||||
|
||||
UCLASS(MinimalAPI)
|
||||
class UGMS_AnimGraphNode_LayeredBoneBlend : public UAnimGraphNode_BlendListBase
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
UPROPERTY(EditAnywhere, Category=Settings)
|
||||
FGMS_AnimNode_LayeredBoneBlend Node;
|
||||
|
||||
// Adds a new pose pin
|
||||
//@TODO: Generalize this behavior (returning a list of actions/delegates maybe?)
|
||||
GENERICMOVEMENTEDITOR_API virtual void AddPinToBlendByFilter();
|
||||
GENERICMOVEMENTEDITOR_API virtual void RemovePinFromBlendByFilter(UEdGraphPin* Pin);
|
||||
|
||||
// UObject interface
|
||||
// End of UObject interface
|
||||
|
||||
// UEdGraphNode interface
|
||||
virtual FLinearColor GetNodeTitleColor() const override;
|
||||
virtual FText GetTooltipText() const override;
|
||||
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
|
||||
// End of UEdGraphNode interface
|
||||
|
||||
// UK2Node interface
|
||||
virtual void GetNodeContextMenuActions(class UToolMenu* Menu, class UGraphNodeContextMenuContext* Context) const override;
|
||||
// End of UK2Node interface
|
||||
|
||||
// UAnimGraphNode_Base interface
|
||||
virtual FString GetNodeCategory() const override;
|
||||
// End of UAnimGraphNode_Base interface
|
||||
|
||||
|
||||
// Gives each visual node a chance to validate that they are still valid in the context of the compiled class, giving a last shot at error or warning generation after primary compilation is finished
|
||||
virtual void ValidateAnimNodeDuringCompilation(class USkeleton* ForSkeleton, class FCompilerResultsLog& MessageLog) override;
|
||||
// End of UAnimGraphNode_Base interface
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
#include "AnimGraphNode_SkeletalControlBase.h"
|
||||
#include "Nodes/GMS_AnimNode_OrientationWarping.h"
|
||||
#include "GMS_AnimGraphNode_OrientationWarping.generated.h"
|
||||
|
||||
UCLASS()
|
||||
class UGMS_AnimGraphNode_OrientationWarping : public UAnimGraphNode_SkeletalControlBase
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="Settings")
|
||||
FGMS_AnimNode_OrientationWarping Node;
|
||||
|
||||
public:
|
||||
// UEdGraphNode interface
|
||||
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
|
||||
virtual FLinearColor GetNodeTitleColor() const override;
|
||||
virtual FText GetTooltipText() const override;
|
||||
virtual FString GetNodeCategory() const override;
|
||||
virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override;
|
||||
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
virtual void GetInputLinkAttributes(FNodeAttributeArray& OutAttributes) const override;
|
||||
virtual void GetOutputLinkAttributes(FNodeAttributeArray& OutAttributes) const override;
|
||||
virtual void ValidateAnimNodeDuringCompilation(USkeleton* ForSkeleton, FCompilerResultsLog& MessageLog) override;
|
||||
// End of UEdGraphNode interface
|
||||
|
||||
protected:
|
||||
// UAnimGraphNode_Base interface
|
||||
virtual void CustomizePinData(UEdGraphPin* Pin, FName SourcePropertyName, int32 ArrayIndex) const override;
|
||||
// End of UAnimGraphNode_Base interface
|
||||
|
||||
// UAnimGraphNode_SkeletalControlBase interface
|
||||
virtual FText GetControllerDescription() const override;
|
||||
virtual const FAnimNode_SkeletalControlBase* GetNode() const override { return &Node; }
|
||||
// End of UAnimGraphNode_SkeletalControlBase interface
|
||||
};
|
||||
Reference in New Issue
Block a user