diff --git a/Content/TangibleActor.uasset b/Content/TangibleActor.uasset index 24cba782..781f917d 100644 --- a/Content/TangibleActor.uasset +++ b/Content/TangibleActor.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:90b49cd7987f58dbe07e6c7af9896ce38633e1212eef5fe3b7132b12e13df4d7 -size 160465 +oid sha256:e25fe70233549efcc19085e8c000dae416a86ae171cb3526039a07a50af1e1a5 +size 290458 diff --git a/Source/Integration/AnimQueue.cpp b/Source/Integration/AnimQueue.cpp index 2fca5ce0..78ce2563 100644 --- a/Source/Integration/AnimQueue.cpp +++ b/Source/Integration/AnimQueue.cpp @@ -29,9 +29,12 @@ static bool ClearProperties(const FString& prefix, UObject* obj) { return true; } -static bool SetProperty(const FString& name, UObject* obj, const FlxAnimationField& field) { +#pragma optimize("", off) + +static bool SetProperty(const FString& prefix, UObject* obj, const FlxAnimationField& field) { UClass* uclass = obj->GetClass(); - FName nname(name); + FString sname(field.Name.size(), (const UTF8CHAR*)field.Name.data()); + FName nname(prefix + sname); switch (field.Type) { case ElxAnimValueType::STRING: { FStrProperty* fprop = FindFProperty(uclass, nname); @@ -66,29 +69,35 @@ static bool SetProperty(const FString& name, UObject* obj, const FlxAnimationFie return false; } -bool FlxAnimationStep::Unpack(const FString& prefix, UObject* into, bool preclear) const { +#pragma optimize("", off) +bool FlxAnimationStep::Unpack(const FString& prefix, UObject* into) const { UClass* uclass = into->GetClass(); std::string_view body((const char*)(Body.GetData()), Body.Num()); FlxAnimationStepDecoder decoder(body); - bool ok = true; - if (preclear) { - ok &= ClearProperties(prefix, into); - } + bool ok = ClearProperties(prefix, into); while (!decoder.AtEOF()) { FlxAnimationField field = decoder.ReadField(); - FString sname(field.Name.size(), (const UTF8CHAR*)field.Name.data()); - ok &= SetProperty(prefix + sname, into, field); + if (Finished && !field.Persistent) continue; + ok &= SetProperty(prefix, into, field); + } + if (Finished) { + FlxAnimationField field; + field.Name = "action"; + field.Persistent = false; + field.Type = ElxAnimValueType::STRING; + field.S = "idle"; + ok &= SetProperty(prefix, into, field); } return ok; } FString UlxAnimationStepLibrary::AnimationStepDebugString(const FlxAnimationStep& step) { std::string_view body((const char*)(step.Body.GetData()), step.Body.Num()); - return FlxAnimationStepDecoder::DebugString(step.Hash, body); + return FlxAnimationStepDecoder::DebugString(step.Finished, step.Finished, step.Hash, body); } void UlxAnimationStepLibrary::UnpackAnimationStep(UObject* into, const FlxAnimationStep& step, const FString& prefix) { - step.Unpack(prefix, into, true); + step.Unpack(prefix, into); } static FlxAnimationField FindAnimationFieldLL(const FlxAnimationStep& step, std::string_view name) { @@ -133,6 +142,10 @@ void FlxAnimationStep::AutoUpdatePlane(FName *planep) const { } } +bool UlxAnimationStepLibrary::AnimationStepEqual(const FlxAnimationStep &stepa, const FlxAnimationStep &stepb) { + return (stepa.Finished == stepb.Finished) && (stepa.Hash == stepb.Hash); +} + bool UlxAnimationStepLibrary::AnimationStepIsIdle(const FlxAnimationStep &step) { return step.Finished; } @@ -149,8 +162,10 @@ double UlxAnimationStepLibrary::AnimationStepGetFloat(const FlxAnimationStep& st return field.X; } -#pragma optimize("", off) FString UlxAnimationStepLibrary::AnimationStepGetString(const FlxAnimationStep& step, const FString& name) { + if (step.Finished && (name == TEXT("action"))) { + return TEXT("idle"); + } FlxAnimationField field = FindAnimationField(step, name); if (field.Type != ElxAnimValueType::STRING) return TEXT(""); return FString(field.S.size(), (const UTF8CHAR*)(field.S.data())); @@ -210,12 +225,16 @@ FlxAnimationField FlxAnimationStepDecoder::ReadField() { return result; } -FString FlxAnimationStepDecoder::DebugString(uint64 hash, std::string_view body) { +FString FlxAnimationStepDecoder::DebugString(bool injectidle, bool persistentonly, uint64 hash, std::string_view body) { FString result; FlxAnimationStepDecoder decoder(body); result.Appendf(TEXT("Hash=%016llx"), hash); + if (injectidle) { + result.Appendf(TEXT(" action=idle")); + } while (!decoder.AtEOF()) { FlxAnimationField field = decoder.ReadField(); + if (persistentonly && !field.Persistent) continue; result.Append(TEXT(" ")); result.Append(FString(field.Name.size(), (const UTF8CHAR*)field.Name.data())); result.Append(field.Persistent ? TEXT("=") : TEXT(":")); @@ -247,7 +266,7 @@ FString FlxAnimQueueDecoder::DebugString(std::string_view queue) { FlxAnimQueueDecoder decoder(queue); while (!decoder.AtEOF()) { FlxAnimationStepView step = decoder.ReadStep(); - FString stepdebug = FlxAnimationStepDecoder::DebugString(step.Hash, step.Body); + FString stepdebug = FlxAnimationStepDecoder::DebugString(false, false, step.Hash, step.Body); result.Appendf(TEXT("%s\n"), *stepdebug); } return result; @@ -339,6 +358,7 @@ void FlxAnimTracker::Update(std::string_view encqueue) { while (!newsteps.IsEmpty()) { FlxAnimationStepView step = newsteps.Pop(); AQ.EmplaceLast(step.Hash, step.Body); + } // If there are too many animations in AQ, discard @@ -357,10 +377,13 @@ void FlxAnimTracker::Update(std::string_view encqueue) { } FlxAnimationStep FlxAnimTracker::GetCurrentAnimation() { + FlxAnimationStep result; for (int i = 0; i < AQ.Num(); i++) { if (!AQ[i].Finished) { return AQ[i]; } } - return AQ.Last(); + result = AQ.Last(); + result.Hash = 0; + return result; } diff --git a/Source/Integration/AnimQueue.h b/Source/Integration/AnimQueue.h index 02ab3300..ff576088 100644 --- a/Source/Integration/AnimQueue.h +++ b/Source/Integration/AnimQueue.h @@ -58,6 +58,14 @@ public: // routine tries to find a string property "color" in the // UObject, and then it sets that property to "blue." // + // The prefix is prepended to the key names. For example, + // if one of the key-value pairs is "color=blue", and the + // prefix is "aq", then the property "aqColor=blue" will be + // stored in the UObject. + // + // All properties of the UObject starting with the specified + // prefix are cleared before unpacking the animation step. + // // Returns true if all of the key-value pairs in the // animation step could be unpacked into fields of the UObject. // This could fail, for instance, if the UObject just doesn't @@ -65,16 +73,10 @@ public: // fail if there's a type mismatch. For example, "color=blue" // cannot be stored in a property "color" of type int. // - // The prefix is prepended to the key names. For example, - // if one of the key-value pairs is "color=blue", and the - // prefix is "aq", then the property "aqColor=blue" will be - // stored in the UObject. + // Automatically injects a boolean property "idle" representing + // whether the property's finished flag is set. // - // If pre-clear is true, then all properties of the UObject - // starting with the specified prefix are cleared before - // unpacking the animation step. - // - bool Unpack(const FString& prefix, UObject* into, bool preclear = true) const; + bool Unpack(const FString& prefix, UObject* into) const; // Auto-Execute // @@ -108,7 +110,10 @@ public: static FString AnimationStepDebugString(const FlxAnimationStep& step); UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "into"), Category = Luprex) - static void UnpackAnimationStep(UObject* into, const FlxAnimationStep& step, const FString& VariableNamePrefix); + static void UnpackAnimationStep(UObject* into, const FlxAnimationStep& step, const FString& VariableNamePrefix = TEXT("aq")); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = Luprex) + static bool AnimationStepEqual(const FlxAnimationStep &StepA, const FlxAnimationStep &StepB); UFUNCTION(BlueprintCallable, BlueprintPure, Category = Luprex) static bool AnimationStepIsIdle(const FlxAnimationStep &step); @@ -241,7 +246,7 @@ public: // Convert an AnimStep to an FString. // - static FString DebugString(uint64 hash, std::string_view body); + static FString DebugString(bool injectidle, bool persistentonly, uint64 hash, std::string_view body); }; ////////////////////////////////////////////////