More work on anim queues

This commit is contained in:
2023-10-12 18:15:56 -04:00
parent 334a95481d
commit f7249e4d29
3 changed files with 56 additions and 28 deletions

Binary file not shown.

View File

@@ -29,9 +29,12 @@ static bool ClearProperties(const FString& prefix, UObject* obj) {
return true; 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(); UClass* uclass = obj->GetClass();
FName nname(name); FString sname(field.Name.size(), (const UTF8CHAR*)field.Name.data());
FName nname(prefix + sname);
switch (field.Type) { switch (field.Type) {
case ElxAnimValueType::STRING: { case ElxAnimValueType::STRING: {
FStrProperty* fprop = FindFProperty<FStrProperty>(uclass, nname); FStrProperty* fprop = FindFProperty<FStrProperty>(uclass, nname);
@@ -66,29 +69,35 @@ static bool SetProperty(const FString& name, UObject* obj, const FlxAnimationFie
return false; 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(); UClass* uclass = into->GetClass();
std::string_view body((const char*)(Body.GetData()), Body.Num()); std::string_view body((const char*)(Body.GetData()), Body.Num());
FlxAnimationStepDecoder decoder(body); FlxAnimationStepDecoder decoder(body);
bool ok = true; bool ok = ClearProperties(prefix, into);
if (preclear) {
ok &= ClearProperties(prefix, into);
}
while (!decoder.AtEOF()) { while (!decoder.AtEOF()) {
FlxAnimationField field = decoder.ReadField(); FlxAnimationField field = decoder.ReadField();
FString sname(field.Name.size(), (const UTF8CHAR*)field.Name.data()); if (Finished && !field.Persistent) continue;
ok &= SetProperty(prefix + sname, into, field); 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; return ok;
} }
FString UlxAnimationStepLibrary::AnimationStepDebugString(const FlxAnimationStep& step) { FString UlxAnimationStepLibrary::AnimationStepDebugString(const FlxAnimationStep& step) {
std::string_view body((const char*)(step.Body.GetData()), step.Body.Num()); 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) { 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) { 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) { bool UlxAnimationStepLibrary::AnimationStepIsIdle(const FlxAnimationStep &step) {
return step.Finished; return step.Finished;
} }
@@ -149,8 +162,10 @@ double UlxAnimationStepLibrary::AnimationStepGetFloat(const FlxAnimationStep& st
return field.X; return field.X;
} }
#pragma optimize("", off)
FString UlxAnimationStepLibrary::AnimationStepGetString(const FlxAnimationStep& step, const FString& name) { FString UlxAnimationStepLibrary::AnimationStepGetString(const FlxAnimationStep& step, const FString& name) {
if (step.Finished && (name == TEXT("action"))) {
return TEXT("idle");
}
FlxAnimationField field = FindAnimationField(step, name); FlxAnimationField field = FindAnimationField(step, name);
if (field.Type != ElxAnimValueType::STRING) return TEXT(""); if (field.Type != ElxAnimValueType::STRING) return TEXT("");
return FString(field.S.size(), (const UTF8CHAR*)(field.S.data())); return FString(field.S.size(), (const UTF8CHAR*)(field.S.data()));
@@ -210,12 +225,16 @@ FlxAnimationField FlxAnimationStepDecoder::ReadField() {
return result; 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; FString result;
FlxAnimationStepDecoder decoder(body); FlxAnimationStepDecoder decoder(body);
result.Appendf(TEXT("Hash=%016llx"), hash); result.Appendf(TEXT("Hash=%016llx"), hash);
if (injectidle) {
result.Appendf(TEXT(" action=idle"));
}
while (!decoder.AtEOF()) { while (!decoder.AtEOF()) {
FlxAnimationField field = decoder.ReadField(); FlxAnimationField field = decoder.ReadField();
if (persistentonly && !field.Persistent) continue;
result.Append(TEXT(" ")); result.Append(TEXT(" "));
result.Append(FString(field.Name.size(), (const UTF8CHAR*)field.Name.data())); result.Append(FString(field.Name.size(), (const UTF8CHAR*)field.Name.data()));
result.Append(field.Persistent ? TEXT("=") : TEXT(":")); result.Append(field.Persistent ? TEXT("=") : TEXT(":"));
@@ -247,7 +266,7 @@ FString FlxAnimQueueDecoder::DebugString(std::string_view queue) {
FlxAnimQueueDecoder decoder(queue); FlxAnimQueueDecoder decoder(queue);
while (!decoder.AtEOF()) { while (!decoder.AtEOF()) {
FlxAnimationStepView step = decoder.ReadStep(); 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); result.Appendf(TEXT("%s\n"), *stepdebug);
} }
return result; return result;
@@ -339,6 +358,7 @@ void FlxAnimTracker::Update(std::string_view encqueue) {
while (!newsteps.IsEmpty()) { while (!newsteps.IsEmpty()) {
FlxAnimationStepView step = newsteps.Pop(); FlxAnimationStepView step = newsteps.Pop();
AQ.EmplaceLast(step.Hash, step.Body); AQ.EmplaceLast(step.Hash, step.Body);
} }
// If there are too many animations in AQ, discard // If there are too many animations in AQ, discard
@@ -357,10 +377,13 @@ void FlxAnimTracker::Update(std::string_view encqueue) {
} }
FlxAnimationStep FlxAnimTracker::GetCurrentAnimation() { FlxAnimationStep FlxAnimTracker::GetCurrentAnimation() {
FlxAnimationStep result;
for (int i = 0; i < AQ.Num(); i++) { for (int i = 0; i < AQ.Num(); i++) {
if (!AQ[i].Finished) { if (!AQ[i].Finished) {
return AQ[i]; return AQ[i];
} }
} }
return AQ.Last(); result = AQ.Last();
result.Hash = 0;
return result;
} }

View File

@@ -58,6 +58,14 @@ public:
// routine tries to find a string property "color" in the // routine tries to find a string property "color" in the
// UObject, and then it sets that property to "blue." // 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 // Returns true if all of the key-value pairs in the
// animation step could be unpacked into fields of the UObject. // animation step could be unpacked into fields of the UObject.
// This could fail, for instance, if the UObject just doesn't // 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" // fail if there's a type mismatch. For example, "color=blue"
// cannot be stored in a property "color" of type int. // cannot be stored in a property "color" of type int.
// //
// The prefix is prepended to the key names. For example, // Automatically injects a boolean property "idle" representing
// if one of the key-value pairs is "color=blue", and the // whether the property's finished flag is set.
// prefix is "aq", then the property "aqColor=blue" will be
// stored in the UObject.
// //
// If pre-clear is true, then all properties of the UObject bool Unpack(const FString& prefix, UObject* into) const;
// starting with the specified prefix are cleared before
// unpacking the animation step.
//
bool Unpack(const FString& prefix, UObject* into, bool preclear = true) const;
// Auto-Execute // Auto-Execute
// //
@@ -108,7 +110,10 @@ public:
static FString AnimationStepDebugString(const FlxAnimationStep& step); static FString AnimationStepDebugString(const FlxAnimationStep& step);
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "into"), Category = Luprex) 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) UFUNCTION(BlueprintCallable, BlueprintPure, Category = Luprex)
static bool AnimationStepIsIdle(const FlxAnimationStep &step); static bool AnimationStepIsIdle(const FlxAnimationStep &step);
@@ -241,7 +246,7 @@ public:
// Convert an AnimStep to an FString. // 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);
}; };
//////////////////////////////////////////////// ////////////////////////////////////////////////