// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. #include "Nodes/AnimGraphNode_OLSMask.h" #include "Kismet2/BlueprintEditorUtils.h" #define LOCTEXT_NAMESPACE "OLSNodes" UAnimGraphNode_OLSMask::UAnimGraphNode_OLSMask(const FObjectInitializer& objectInitializer) : Super(objectInitializer) { Node.BlendMasks.Reserve(1); Node.MaskBlendWeights.Reserve(1); Node.AllBoneBlendWeights.Reserve(1); } FLinearColor UAnimGraphNode_OLSMask::GetNodeTitleColor() const { return FLinearColor(0.0f, 204.0f, 204.0f); } FText UAnimGraphNode_OLSMask::GetTooltipText() const { return LOCTEXT("AnimGraphNode_OLSMask_Tooltip", "OLS Mask Node"); } FText UAnimGraphNode_OLSMask::GetNodeTitle(ENodeTitleType::Type TitleType) const { return LOCTEXT("AnimGraphNode_OLSMaskBlend_Title", "Per Body Part Mask"); } void UAnimGraphNode_OLSMask::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) { const FName PropertyName = (PropertyChangedEvent.Property ? PropertyChangedEvent.Property->GetFName() : NAME_None); if (PropertyName == GET_MEMBER_NAME_STRING_CHECKED(FAnimNode_OLSMask, BlendMasks)) { FScopedTransaction Transaction(LOCTEXT("AddedBlendMask", "Add Blend Mask")); Modify(); const int32 NumMasks = Node.BlendMasks.Num(); Node.MaskBlendWeights.SetNum(NumMasks); Node.AllBoneBlendWeights.SetNum(NumMasks); FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(GetBlueprint()); ReconstructNode(); } Super::PostEditChangeProperty(PropertyChangedEvent); } FString UAnimGraphNode_OLSMask::GetNodeCategory() const { return TEXT("Blends|OLS Nodes"); } void UAnimGraphNode_OLSMask::PreloadRequiredAssets() { const TObjectPtr animBlueprint = GetAnimBlueprint(); if (animBlueprint && !GIsCookerLoadingPackage && animBlueprint->TargetSkeleton) { const int32 numBlendMasks = Node.BlendMasks.Num(); if (numBlendMasks > 0) { for (int32 maskIndex = 0; maskIndex < numBlendMasks; ++maskIndex) { const FName blendProfileName = Node.BlendMasks[maskIndex].BlendProfileName; if (const TObjectPtr blendProfile = animBlueprint->TargetSkeleton->GetBlendProfile( blendProfileName)) { Node.BlendMasks[maskIndex].BlendProfile = blendProfile; } const TObjectPtr blendMask = Node.BlendMasks[maskIndex].BlendProfile; PreloadObject(blendMask); } } } Super::PreloadRequiredAssets(); } void UAnimGraphNode_OLSMask::BakeDataDuringCompilation(FCompilerResultsLog& MessageLog) { const TObjectPtr animBlueprint = GetAnimBlueprint(); if (!GIsCookerLoadingPackage && animBlueprint->TargetSkeleton) { const int32 numBlendMasks = Node.BlendMasks.Num(); for (int32 maskIndex = 0; maskIndex < numBlendMasks; ++maskIndex) { const FOLSMaskSettings& currentMask = Node.BlendMasks[maskIndex]; const FName& blendProfileName = Node.BlendMasks[maskIndex].BlendProfileName; if (const TObjectPtr bendProfile = animBlueprint->TargetSkeleton->GetBlendProfile( blendProfileName)) { Node.BlendMasks[maskIndex].BlendProfile = bendProfile; } if (currentMask.bShouldAddSlot) { animBlueprint->TargetSkeleton->RegisterSlotNode(currentMask.SlotName); } } } } void UAnimGraphNode_OLSMask::ValidateAnimNodeDuringCompilation(USkeleton* skeleton, FCompilerResultsLog& MessageLog) { if (skeleton) { // ensure to cache the per-bone blend weights if (!Node.ArePerBoneBlendWeightsValid(skeleton)) { Node.RebuildPerBoneBlendWeights(skeleton); } if (Node.BlendMasks.Num() > 0) { const int32 numBlendMasks = Node.BlendMasks.Num(); for (int32 maskIndex = 0; maskIndex < numBlendMasks; ++maskIndex) { const FName& blendProfileName = Node.BlendMasks[maskIndex].BlendProfileName; const TObjectPtr blendProfile = skeleton->GetBlendProfile(blendProfileName); if (blendProfile) { Node.BlendMasks[maskIndex].BlendProfile = blendProfile; } if (!blendProfile) { MessageLog.Error( *FText::Format( LOCTEXT("BlendProfileIsNull", "@@ has null BlendMask In Index {0}. "), FText::AsNumber(maskIndex)).ToString(), this, blendProfile); continue; } if (!blendProfile->IsBlendMask()) { MessageLog.Error( *FText::Format(LOCTEXT("BlendProfileModeError", "@@ is using a BlendProfile(@@) without a BlendMask mode In Index {0}. "), FText::AsNumber( maskIndex)).ToString(), this, blendProfile); } } } } Super::ValidateAnimNodeDuringCompilation(skeleton, MessageLog); } #undef LOCTEXT_NAMESPACE