Implement code to unpack anim steps into UObject
This commit is contained in:
BIN
Content/TangibleActor.uasset
LFS
BIN
Content/TangibleActor.uasset
LFS
Binary file not shown.
@@ -47,15 +47,15 @@ FString FlxAnimQueueDecoder::DebugString(std::string_view queue) {
|
|||||||
FlxAnimQueueDecoder decoder(queue);
|
FlxAnimQueueDecoder decoder(queue);
|
||||||
while (!decoder.AtEOF()) {
|
while (!decoder.AtEOF()) {
|
||||||
FlxAnimStep step = decoder.ReadStep();
|
FlxAnimStep step = decoder.ReadStep();
|
||||||
FString stepdebug = FlxAnimStepDecoder::DebugString(step);
|
FString stepdebug = FlxAnimStepDecoder::DebugString(step.Body);
|
||||||
result.Appendf(TEXT("%s\n"), *stepdebug);
|
result.Appendf(TEXT("%s\n"), *stepdebug);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
FString FlxAnimStepDecoder::DebugString(const FlxAnimStep& step) {
|
FString FlxAnimStepDecoder::DebugString(std::string_view body) {
|
||||||
FString result;
|
FString result;
|
||||||
FlxAnimStepDecoder decoder(step);
|
FlxAnimStepDecoder decoder(body);
|
||||||
bool first = true;
|
bool first = true;
|
||||||
while (!decoder.AtEOF()) {
|
while (!decoder.AtEOF()) {
|
||||||
FlxAnimField field = decoder.ReadField();
|
FlxAnimField field = decoder.ReadField();
|
||||||
@@ -83,6 +83,78 @@ FString FlxAnimStepDecoder::DebugString(const FlxAnimStep& step) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FlxAnimStepDecoder::ClearProperties(const FString& prefix, UObject* obj) {
|
||||||
|
UClass* uclass = obj->GetClass();
|
||||||
|
if (prefix.IsEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FName prefixlo(prefix);
|
||||||
|
FName prefixhi(prefix + TEXT("\xFFFF"));
|
||||||
|
for (TFieldIterator<FProperty> It(uclass); It; ++It)
|
||||||
|
{
|
||||||
|
FProperty* fprop = *It;
|
||||||
|
bool match1 = (fprop->GetFName().Compare(prefixlo) > 0);
|
||||||
|
bool match2 = (fprop->GetFName().Compare(prefixhi) < 0);
|
||||||
|
if (match1 && match2) {
|
||||||
|
uint8* pptr = fprop->ContainerPtrToValuePtr<uint8>(obj);
|
||||||
|
fprop->ClearValue(pptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FlxAnimStepDecoder::SetProperty(const FString& name, UObject* obj, const FlxAnimField& field) {
|
||||||
|
UClass* uclass = obj->GetClass();
|
||||||
|
FName nname(name);
|
||||||
|
switch (field.Type) {
|
||||||
|
case ElxAnimValueType::STRING: {
|
||||||
|
FStrProperty* fprop = FindFProperty<FStrProperty>(uclass, nname);
|
||||||
|
if (fprop == nullptr) return false;
|
||||||
|
FString* pptr = fprop->ContainerPtrToValuePtr<FString>(obj);
|
||||||
|
*pptr = FString(field.S.size(), (const UTF8CHAR*)field.S.data());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case ElxAnimValueType::NUMBER: {
|
||||||
|
FDoubleProperty* fprop = FindFProperty<FDoubleProperty>(uclass, nname);
|
||||||
|
if (fprop == nullptr) return false;
|
||||||
|
double* pptr = fprop->ContainerPtrToValuePtr<double>(obj);
|
||||||
|
fprop->SetPropertyValue(pptr, field.X);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case ElxAnimValueType::BOOLEAN: {
|
||||||
|
FBoolProperty* fprop = FindFProperty<FBoolProperty>(uclass, nname);
|
||||||
|
if (fprop == nullptr) return false;
|
||||||
|
uint8* pptr = fprop->ContainerPtrToValuePtr<uint8>(obj);
|
||||||
|
fprop->SetPropertyValue(pptr, (field.X == 1.0));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case ElxAnimValueType::XYZ: {
|
||||||
|
FStructProperty* fprop = FindFProperty<FStructProperty>(uclass, nname);
|
||||||
|
if (fprop == nullptr) return false;
|
||||||
|
if (fprop->Struct != TBaseStructure<FVector>::Get()) return false;
|
||||||
|
FVector* pptr = fprop->ContainerPtrToValuePtr<FVector>(obj);
|
||||||
|
*pptr = FVector(field.X, field.Y, field.Z);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma optimize("", off)
|
||||||
|
bool FlxAnimStepDecoder::UnpackInto(std::string_view body, const FString& prefix, bool preclear, UObject* obj) {
|
||||||
|
UClass* uclass = obj->GetClass();
|
||||||
|
FlxAnimStepDecoder decoder(body);
|
||||||
|
bool ok = true;
|
||||||
|
if (preclear) {
|
||||||
|
ok &= ClearProperties(prefix, obj);
|
||||||
|
}
|
||||||
|
while (!decoder.AtEOF()) {
|
||||||
|
FlxAnimField field = decoder.ReadField();
|
||||||
|
FString sname(field.Name.size(), (const UTF8CHAR*)field.Name.data());
|
||||||
|
ok &= SetProperty(prefix + sname, obj, field);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
FlxAnimTracker::FlxAnimTracker() {
|
FlxAnimTracker::FlxAnimTracker() {
|
||||||
AQ.Empty();
|
AQ.Empty();
|
||||||
|
|||||||
@@ -141,11 +141,12 @@ class FlxAnimStepDecoder {
|
|||||||
private:
|
private:
|
||||||
FlxStringDecoder Decoder;
|
FlxStringDecoder Decoder;
|
||||||
|
|
||||||
|
static bool ClearProperties(const FString& prefix, UObject* obj);
|
||||||
|
static bool SetProperty(const FString& name, UObject *obj, const FlxAnimField& value);
|
||||||
public:
|
public:
|
||||||
// Initialize the FlxAnimStepDecoder from the FlxAnimStep.
|
// Initialize the FlxAnimStepDecoder from the FlxAnimStep.
|
||||||
//
|
//
|
||||||
FlxAnimStepDecoder(const FlxAnimStep &step) : Decoder(step.Body) {}
|
FlxAnimStepDecoder(std::string_view body) : Decoder(body) {}
|
||||||
FlxAnimStepDecoder(const FlxAnimStoredStep& step) : Decoder(step.Body) {}
|
|
||||||
|
|
||||||
// Return true if the parser has reached the end of the string.
|
// Return true if the parser has reached the end of the string.
|
||||||
//
|
//
|
||||||
@@ -157,7 +158,33 @@ public:
|
|||||||
|
|
||||||
// Convert an AnimStep to an FString.
|
// Convert an AnimStep to an FString.
|
||||||
//
|
//
|
||||||
static FString DebugString(const FlxAnimStep &step);
|
static FString DebugString(std::string_view body);
|
||||||
|
|
||||||
|
// Unpack an AnimStep into a UObject
|
||||||
|
//
|
||||||
|
// Stores the key-value pairs of the animation step into
|
||||||
|
// properties of a UObject. For example, if the key-value
|
||||||
|
// pair "color=blue" is present in the AnimStep, then this
|
||||||
|
// routine tries to find a string property "color" in the
|
||||||
|
// UObject, and then it sets that property to "blue."
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
// contain one of the necessary properties. It can also
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// If pre-clear is true, then all properties of the UObject
|
||||||
|
// starting with the specified prefix are cleared before
|
||||||
|
// unpacking the animation step.
|
||||||
|
//
|
||||||
|
static bool UnpackInto(std::string_view body, const FString &prefix, bool preclear, UObject* obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -104,6 +104,15 @@ void AIntegrationGameModeBase::MaybeTriggerUpdateTask(float deltaseconds) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#pragma optimize( "", off )
|
||||||
|
//void SetLocal(UObject* obj, const char *name, int value) {
|
||||||
|
// FString sname((const UTF8CHAR *)name);
|
||||||
|
// FName nname(sname);
|
||||||
|
// UClass* uclass = obj->GetClass();
|
||||||
|
// FProperty* fprop = FindFProperty<FProperty>(uclass, nname);
|
||||||
|
// FStructProperty* sprop = FindFProperty<FStructProperty>(uclass, nname);
|
||||||
|
//}
|
||||||
|
|
||||||
void AIntegrationGameModeBase::UpdateTangibles() {
|
void AIntegrationGameModeBase::UpdateTangibles() {
|
||||||
if (!Playing) return;
|
if (!Playing) return;
|
||||||
FlxLockedWrapper w(LockableWrapper);
|
FlxLockedWrapper w(LockableWrapper);
|
||||||
@@ -130,6 +139,9 @@ void AIntegrationGameModeBase::UpdateTangibles() {
|
|||||||
FlxAnimStoredStep step;
|
FlxAnimStoredStep step;
|
||||||
ElxAnimPlaybackMode mode = t->AnimTracker.GetNextStep(step);
|
ElxAnimPlaybackMode mode = t->AnimTracker.GetNextStep(step);
|
||||||
bool started = false;
|
bool started = false;
|
||||||
|
if (mode != ElxAnimPlaybackMode::INVALID) {
|
||||||
|
FlxAnimStepDecoder::UnpackInto(step.Body, TEXT("aq"), true, t->Actor);
|
||||||
|
}
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case ElxAnimPlaybackMode::INVALID:
|
case ElxAnimPlaybackMode::INVALID:
|
||||||
started = false; // Nothing to do.
|
started = false; // Nothing to do.
|
||||||
|
|||||||
Reference in New Issue
Block a user