Overhaul animation queues so the queue is stored as a single encoded string.

This commit is contained in:
2023-07-26 17:40:20 -04:00
parent 2dff145885
commit b459eedc82
10 changed files with 239 additions and 242 deletions

View File

@@ -18,14 +18,63 @@
// Persistent values are retained from one animation step to the next,
// nonpersistent values exist for one animation step only.
//
// Animation steps are stored encoded as strings, which is convenient for
// passing the data to unreal, but it means that the animation step has to be
// decoded whenever you want access to the key-value pairs.
//
// Each animation step has a hash value. The hash value is generated
// by mixing the hash value of the previous step with the hash value
// of the encoded string of key-value pairs.
//
//
///////////////////////////////////////////////////////////////////
//
// SERIALIZED STORAGE
//
// The entired animation queue is stored in a serialized format,
// as a shared string. This means that the animation queue can be
// passed to the graphics engine as a single string. This vastly
// simplifies the API for passing the animation queue to the
// graphics engine. It also vastly reduces the amount of computation
// done during the graphics engine probe: all we have to do is get
// the already existing string and pass a reference to it.
//
// However, that means that when manipulating the animation queue,
// we have to decode it, manipulate it, and then reencode it. This
// is a good tradeoff: we update animation queues rarely, compared
// to how often we pass them to the graphics engine.
//
// So first, you need to know how to serialize a single animation
// step. Remember, an animation step consists of a list of key-value
// pairs (see above). The key-value pairs are serialized as follows:
//
// for all key-value pairs do:
// write_string(key)
// write_bool(persistent)
// write_uint8(type) // T_STRING, T_NUMBER, T_BOOL, or T_XYZ
// switch type:
// T_STRING: write_string(value)
// T_NUMBER: write_double(value)
// T_BOOL: write_bool(value)
// T_XYZ: write_xyz(value)
//
// The encoded string produced by the loop above is called an "encstep".
// That's short for "encoded animation step". The encstep has a hash
// value, which is a function that accepts the encstep and also the hash
// of the previous encstep. Note that the hash is not part of the encstep.
//
// An animation queue consists of a list of steps. Each step has a hash
// and an encstep. An animation queue is serialized as follows:
//
// for all animation steps, starting with the most recent, do:
// write_uint64(hash)
// write_string(encstep)
//
// The encoded string produced by the loop above is called an "encqueue",
// because it encodes everything in the animation queue (except for the
// size limit, which is separate).
//
// Since the steps in an encqueue are stored most-recent first, if you
// want some information about the most recent animation entry, you
// don't need to decode the entire encqueue. You only need to
// decode the first step.
//
///////////////////////////////////////////////////////////////////
#ifndef ANIMQUEUE_HPP
@@ -40,7 +89,6 @@
#include "streambuffer.hpp"
#include "debugcollector.hpp"
#include "util.hpp"
#include "enginewrapper.hpp"
#include <cassert>
#include <ostream>
@@ -190,14 +238,6 @@ struct AnimCoreState
};
class AnimQueue : public eng::nevernew {
private:
struct Step {
Step() { hash=0; }
Step(const eng::string &e, uint64_t h) : encoding(e), hash(h) {}
eng::string encoding;
uint64_t hash;
};
public:
// Construct an empty animation queue.
// clears the state to a valid state.
@@ -250,10 +290,6 @@ public:
eng::string steps_debug_string() const;
eng::string full_debug_string() const;
// Get the final hash value.
//
uint64_t get_final_hash() const { return steps_.back().hash; }
// Get the final entry, xyz and plane only.
//
AnimCoreState get_final_core_state() const;
@@ -266,17 +302,22 @@ public:
//
AnimState get_final_everything() const;
// Get the contents of the animation queue for export to the engine wrapper.
// Get a serialized representation of the animation queue.
//
// Caution: this exports pointers into existing allocated strings.
// The pointers in this array are only valid until you modify the
// animation queue.
// Get the entire animation queue in a serialized format (encqueue).
// The string returned is a shared string. No string copy
// is made during this process.
//
void get_for_engine_wrapper(std::vector<EngineWrapper::AnimEntry> *into) const;
util::SharedStdString get_encoded_queue() const { return encqueue_; }
private:
int size_limit_;
eng::deque<Step> steps_;
// Note: this is stored as a std::string, not an eng::string, because the
// ownership ends up being shared between us and the graphics engine. We
// can't have the graphics engine affecting the behavior of the engine heap.
//
util::SharedStdString encqueue_;
};
#endif // ANIMQUEUE_HPP