#pragma once #include "CoreMinimal.h" #include "WingServer.h" #include "WingHandler.h" #include "WingFetcher.h" #include "WingJson.h" #include "WingUtils.h" #include "Animation/AnimSequence.h" #include "Animation/BlendSpace.h" #include "AnimBlueprint_SetBlendSpaceSamples.generated.h" // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- USTRUCT() struct FBlendSpaceSampleEntry { GENERATED_BODY() UPROPERTY() FString AnimationAsset; UPROPERTY() float X = 0.0f; UPROPERTY() float Y = 0.0f; }; UCLASS() class UWing_AnimBlueprint_SetBlendSpaceSamples : public UObject, public IWingHandler { GENERATED_BODY() public: UPROPERTY(meta=(Description="Blend Space package path")) FString BlendSpace; UPROPERTY(meta=(Optional, Description="Display name for the X axis")) FString AxisXName; UPROPERTY(meta=(Optional, Description="Display name for the Y axis")) FString AxisYName; UPROPERTY(meta=(Optional, Description="Minimum value for X axis")) float AxisXMin = 0.0f; UPROPERTY(meta=(Optional, Description="Maximum value for X axis")) float AxisXMax = 0.0f; UPROPERTY(meta=(Optional, Description="Minimum value for Y axis")) float AxisYMin = 0.0f; UPROPERTY(meta=(Optional, Description="Maximum value for Y axis")) float AxisYMax = 0.0f; UPROPERTY(meta=(Optional, Description="Array of sample points, each with animationAsset, x, y")) FWingJsonArray Samples; virtual FString GetDescription() const override { return TEXT("Set axis parameters and animation sample points on a Blend Space. " "Replaces all existing samples."); } virtual void Handle() override { // Load the blend space WingFetcher F; UBlendSpace* BS = F.Asset(BlendSpace).Cast(); if (!BS) return; // Set axis parameters const FBlendParameter& ParamX = BS->GetBlendParameter(0); const FBlendParameter& ParamY = BS->GetBlendParameter(1); // We need to modify BlendParameters directly — use const_cast since there's no setter API FBlendParameter& MutableParamX = const_cast(ParamX); FBlendParameter& MutableParamY = const_cast(ParamY); if (!AxisXName.IsEmpty()) MutableParamX.DisplayName = AxisXName; if (AxisXMin != 0.0f) MutableParamX.Min = AxisXMin; if (AxisXMax != 0.0f) MutableParamX.Max = AxisXMax; if (!AxisYName.IsEmpty()) MutableParamY.DisplayName = AxisYName; if (AxisYMin != 0.0f) MutableParamY.Min = AxisYMin; if (AxisYMax != 0.0f) MutableParamY.Max = AxisYMax; // Clear existing samples (delete from end to start) int32 NumExisting = BS->GetNumberOfBlendSamples(); for (int32 i = NumExisting - 1; i >= 0; --i) { BS->DeleteSample(i); } // Add new samples int32 SamplesSet = 0; for (const TSharedPtr& SampleVal : Samples.Array) { FBlendSpaceSampleEntry Entry; if (!WingJson::PopulateFromJson(FBlendSpaceSampleEntry::StaticStruct(), &Entry, SampleVal)) return; UAnimSequence* AnimSeq = nullptr; if (!Entry.AnimationAsset.IsEmpty()) { WingFetcher F2; AnimSeq = F2.Asset(Entry.AnimationAsset).Cast(); if (!AnimSeq) return; } FVector SampleValue(Entry.X, Entry.Y, 0.0f); if (AnimSeq) { BS->AddSample(AnimSeq, SampleValue); } else { BS->AddSample(SampleValue); } SamplesSet++; } BS->ValidateSampleData(); UWingServer::Printf(TEXT("Set %d samples on %s\n"), SamplesSet, *WingUtils::FormatName(BS)); } };