More work on AnimQueueDecoder
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
|
||||
#include "AnimQueue.h"
|
||||
|
||||
FAnimStep FAnimQueueDecoder::ReadStep() {
|
||||
FAnimStep result;
|
||||
result.Hash = Decoder.read_uint64();
|
||||
result.Body = Decoder.read_string_view();
|
||||
return result;
|
||||
}
|
||||
|
||||
FAnimField FAnimStepDecoder::ReadField() {
|
||||
FAnimField result;
|
||||
result.Name = Decoder.read_string_view();
|
||||
result.Persistent = Decoder.read_bool();
|
||||
result.Type = (EAnimValueType)Decoder.read_uint8();
|
||||
switch (result.Type) {
|
||||
case T_STRING: {
|
||||
result.S = Decoder.read_string_view();
|
||||
break;
|
||||
}
|
||||
case T_NUMBER: {
|
||||
result.X = Decoder.read_double();
|
||||
break;
|
||||
}
|
||||
case T_BOOLEAN: {
|
||||
result.X = Decoder.read_bool() ? 1.0 : 0.0;
|
||||
break;
|
||||
}
|
||||
case T_XYZ: {
|
||||
result.X = Decoder.read_double();
|
||||
result.Y = Decoder.read_double();
|
||||
result.Z = Decoder.read_double();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Decoder.set_at_eof();
|
||||
result.Type = T_BOOLEAN;
|
||||
result.X = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FString FAnimQueueDecoder::DebugString(std::string_view queue) {
|
||||
// IMPLEMENT ME
|
||||
return FString();
|
||||
}
|
||||
|
||||
FString FAnimStepDecoder::DebugString(const FAnimStep& step) {
|
||||
// IMPLEMENT ME
|
||||
return FString();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "StringDecoder.h"
|
||||
|
||||
////////////////////////////////////////////////
|
||||
//
|
||||
// This is copied over from Luprex source. Not ideal.
|
||||
//
|
||||
////////////////////////////////////////////////
|
||||
|
||||
enum EAnimValueType {
|
||||
T_STRING,
|
||||
T_NUMBER,
|
||||
T_BOOLEAN,
|
||||
T_XYZ,
|
||||
T_UNINITIALIZED
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////
|
||||
//
|
||||
// An single animation step.
|
||||
//
|
||||
// The body consists of a sequence of FAnimField
|
||||
// records. The body is encoded, to read the
|
||||
// FAnimField records you need an FAnimStepDecoder.
|
||||
//
|
||||
////////////////////////////////////////////////
|
||||
|
||||
struct FAnimStep {
|
||||
uint32 Hash;
|
||||
std::string_view Body;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////
|
||||
//
|
||||
// A single animation field.
|
||||
//
|
||||
// A field consists of a variable name,
|
||||
// a persistent flag, a type, and some fields
|
||||
// to hold the values.
|
||||
//
|
||||
// If the value is boolean, it is stored in
|
||||
// X, as either 1 or 0. If the value is double,
|
||||
// it is stored in X.
|
||||
//
|
||||
////////////////////////////////////////////////
|
||||
|
||||
struct FAnimField {
|
||||
std::string_view Name;
|
||||
bool Persistent;
|
||||
EAnimValueType Type;
|
||||
double X, Y, Z;
|
||||
std::string_view S;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////
|
||||
//
|
||||
// An Animation Queue Decoder.
|
||||
//
|
||||
// This acts a lot like a stream reader,
|
||||
// it reads one AnimEntry at a time from
|
||||
// the animation queue until you reach
|
||||
// 'end-of-file'.
|
||||
//
|
||||
////////////////////////////////////////////////
|
||||
|
||||
class FAnimQueueDecoder {
|
||||
private:
|
||||
FStringDecoder Decoder;
|
||||
|
||||
public:
|
||||
// Initialize the FAnimQueueDecoder with the encoded animation queue.
|
||||
//
|
||||
FAnimQueueDecoder(std::string_view s) : Decoder(s) {}
|
||||
|
||||
// Return true if the parser has reached the end of the string.
|
||||
//
|
||||
bool AtEOF() { return Decoder.at_eof(); }
|
||||
|
||||
// Read one animation step.
|
||||
//
|
||||
FAnimStep ReadStep();
|
||||
|
||||
// Convert an AnimQueue to an FString.
|
||||
//
|
||||
static FString DebugString(std::string_view s);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////
|
||||
//
|
||||
// An Animation Step Decoder.
|
||||
//
|
||||
// This acts a lot like a stream reader,
|
||||
// it reads one FAnimField at a time from
|
||||
// the animation queue until you reach
|
||||
// 'end-of-file'.
|
||||
//
|
||||
////////////////////////////////////////////////
|
||||
|
||||
class FAnimStepDecoder {
|
||||
private:
|
||||
FStringDecoder Decoder;
|
||||
|
||||
public:
|
||||
// Initialize the FAnimStepDecoder from the FAnimStep.
|
||||
//
|
||||
FAnimStepDecoder(const FAnimStep &step) : Decoder(step.Body) {}
|
||||
|
||||
// Return true if the parser has reached the end of the string.
|
||||
//
|
||||
bool AtEOF() { return Decoder.at_eof(); }
|
||||
|
||||
// Read one field.
|
||||
//
|
||||
FAnimField ReadField();
|
||||
|
||||
// Convert an AnimStep to an FString.
|
||||
//
|
||||
static FString DebugString(const FAnimStep &step);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#include "StringDecoder.h"
|
||||
|
||||
std::string_view StringDecoder::read_string_view() {
|
||||
FStringDecoder::FStringDecoder(std::string_view s) {
|
||||
Text = s.data();
|
||||
Size = s.size();
|
||||
ErrBeyondEOF = false;
|
||||
ErrStringTooLong = false;
|
||||
}
|
||||
|
||||
std::string_view FStringDecoder::read_string_view() {
|
||||
size_t length = read_length();
|
||||
if (length > Size) {
|
||||
ErrBeyondEOF = true;
|
||||
@@ -11,3 +18,9 @@ std::string_view StringDecoder::read_string_view() {
|
||||
Size -= length;
|
||||
return result;
|
||||
}
|
||||
|
||||
void FStringDecoder::set_at_eof() {
|
||||
Text += Size;
|
||||
Size = 0;
|
||||
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "lpx-basewriter.hpp"
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//
|
||||
// StringDecoder
|
||||
// FStringDecoder
|
||||
//
|
||||
// This class is used to decipher 8-bit strings that
|
||||
// contain packed ints, strings, and other data.
|
||||
// The typical example of usage is to decipher the
|
||||
// serialized animation queues fed to us by Luprex.
|
||||
//
|
||||
// The StringDecoder doesn't make a copy of the string
|
||||
// The FStringDecoder doesn't make a copy of the string
|
||||
// you pass in, instead, it stores a pointer to it.
|
||||
// So be sure not to free the string until you're
|
||||
// done analyzing it.
|
||||
@@ -25,7 +26,7 @@
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
|
||||
class StringDecoder : public BaseReader<StringDecoder> {
|
||||
class FStringDecoder : public BaseReader<FStringDecoder> {
|
||||
private:
|
||||
const char* Text;
|
||||
size_t Size;
|
||||
@@ -42,10 +43,9 @@ public:
|
||||
//
|
||||
void read_bytes_into(char* buffer, size_t size) {
|
||||
if (size > Size) {
|
||||
ErrBeyondEOF = true;
|
||||
memset(buffer, 0, size);
|
||||
Text += Size;
|
||||
Size = 0;
|
||||
ErrBeyondEOF = true;
|
||||
set_at_eof();
|
||||
}
|
||||
else {
|
||||
memcpy(buffer, Text, size);
|
||||
@@ -68,20 +68,19 @@ public:
|
||||
|
||||
// Initialize the string decoder with a text to analyze.
|
||||
//
|
||||
StringDecoder(const char* text, int size) {
|
||||
Text = text;
|
||||
Size = size;
|
||||
ErrBeyondEOF = false;
|
||||
ErrStringTooLong = false;
|
||||
}
|
||||
FStringDecoder(std::string_view s);
|
||||
|
||||
// Get the size of the remaining text.
|
||||
//
|
||||
size_t GetSize() { return Size; }
|
||||
size_t get_size() { return Size; }
|
||||
|
||||
// Return true if the remaining text is empty.
|
||||
//
|
||||
bool AtEOF() { return Size == 0; }
|
||||
bool at_eof() { return Size == 0; }
|
||||
|
||||
// Move the cursor to EOF.
|
||||
//
|
||||
void set_at_eof();
|
||||
|
||||
// Read a string as a string_view
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user