Change directory structure
This commit is contained in:
241
luprex/cpp/core/animqueue.hpp
Normal file
241
luprex/cpp/core/animqueue.hpp
Normal file
@@ -0,0 +1,241 @@
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ANIMATION QUEUES
|
||||
//
|
||||
// An animation queue is a fifo queue of animation steps. New animations are
|
||||
// pushed on the back, and old ones are popped from the front.
|
||||
//
|
||||
// An animation step has an "action" which is usually the name of an animation,
|
||||
// or it's a special token like "walk" or "warp." Each animation step shows the
|
||||
// resulting AnimState that the player finds himself in after executing the
|
||||
// action.
|
||||
//
|
||||
// The first step in an animation queue always has id=0 and action="". This step
|
||||
// represents the initial state of the sprite before any animations or
|
||||
// movements.
|
||||
//
|
||||
// To add new items to the AnimQueue, use this process: first, call add(id,
|
||||
// action). This adds a new step to the queue. Then, call set_xyz, set_facing,
|
||||
// set_plane, or an other setter. These setters are meant to only be used
|
||||
// immediately after calling 'add' to populate the new step.
|
||||
//
|
||||
// VERSION NUMBERS
|
||||
//
|
||||
// The version number field: if the version number in the synchronous model is
|
||||
// equal to the version number in the master model, then the two animqueues are
|
||||
// guaranteed to be equal. Here's how we achieve that invariant:
|
||||
//
|
||||
// * In the master model, the version number starts at 1 and is auto-incremented
|
||||
// every time the animation queue is mutated.
|
||||
//
|
||||
// * In the synchronous model, the version number is set to zero every time the
|
||||
// animation queue is mutated. Note that master version numbers are never
|
||||
// zero. Applying a patch also sets the version number to zero.
|
||||
//
|
||||
// * Serializing and deserializing causes the version number to be saved and
|
||||
// restored in both master and synchronous models.
|
||||
//
|
||||
// * The routine 'update_version' should be called after difference
|
||||
// transmission. This copies the version number from the master to the
|
||||
// synchronous model. This is guaranteed to be safe because we just finished
|
||||
// difference transmission, therefore, the queues should match.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ANIMQUEUE_HPP
|
||||
#define ANIMQUEUE_HPP
|
||||
|
||||
#include "wrap-set.hpp"
|
||||
#include "wrap-string.hpp"
|
||||
#include "wrap-deque.hpp"
|
||||
#include "wrap-unordered-map.hpp"
|
||||
|
||||
#include "streambuffer.hpp"
|
||||
#include "debugcollector.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <ostream>
|
||||
|
||||
class AnimStep : public eng::nevernew {
|
||||
friend class AnimQueue;
|
||||
public:
|
||||
enum {
|
||||
HAS_FACING = 1,
|
||||
HAS_X = 2,
|
||||
HAS_Y = 4,
|
||||
HAS_Z = 8,
|
||||
HAS_XYZ = 14,
|
||||
HAS_GRAPHIC = 16,
|
||||
HAS_PLANE = 32,
|
||||
HAS_EVERYTHING = 63,
|
||||
};
|
||||
|
||||
AnimStep();
|
||||
~AnimStep();
|
||||
|
||||
int64_t id() const { return id_; }
|
||||
int bits() const { return bits_; }
|
||||
|
||||
const eng::string &action() const { return action_; }
|
||||
double facing() const { return facing_; }
|
||||
float x() const { return xyz_.x; }
|
||||
float y() const { return xyz_.y; }
|
||||
float z() const { return xyz_.z; }
|
||||
const util::XYZ &xyz() const { return xyz_; }
|
||||
const eng::string &graphic() const { return graphic_; }
|
||||
const eng::string &plane() const { return plane_; }
|
||||
|
||||
bool has_facing() const { return bits_ & HAS_FACING; }
|
||||
bool has_x() const { return bits_ & HAS_X; }
|
||||
bool has_y() const { return bits_ & HAS_Y; }
|
||||
bool has_z() const { return bits_ & HAS_Z; }
|
||||
bool has_xyz() const { return (bits_ & HAS_XYZ) == HAS_XYZ; }
|
||||
bool has_graphic() const { return bits_ & AnimStep::HAS_GRAPHIC; }
|
||||
bool has_plane() const { return bits_ & AnimStep::HAS_PLANE; }
|
||||
|
||||
void set_action(const eng::string &action);
|
||||
void set_facing(float f);
|
||||
void set_x(float f);
|
||||
void set_y(float f);
|
||||
void set_z(float z);
|
||||
void set_xyz(const util::XYZ &xyz);
|
||||
void set_graphic(const eng::string &g);
|
||||
void set_plane(const eng::string &p);
|
||||
|
||||
void clear();
|
||||
|
||||
// ExactlyEqual compares all fields.
|
||||
bool exactly_equal(const AnimStep &other) const;
|
||||
|
||||
// LogicallyEqual only compares fields whose HAS_XXX bits are set.
|
||||
bool logically_equal(const AnimStep &other) const;
|
||||
|
||||
// StateEqual is true if the plane, graphic, facing, and xyz match.
|
||||
bool state_equal(const AnimStep &other) const;
|
||||
|
||||
// read/write the step using a stream buffer.
|
||||
//
|
||||
void write_into(StreamBuffer *sb) const;
|
||||
void read_from(StreamBuffer *sb);
|
||||
|
||||
// Create an AnimStep from a lua table.
|
||||
//
|
||||
// Lua stack must contain a table, which may contain:
|
||||
// action: "action"
|
||||
// facing: 0.0 - 360.0
|
||||
// x: x-coordinate
|
||||
// y: y-coordinate
|
||||
// z: z-coordinate
|
||||
// graphic: "graphic"
|
||||
// plane: "plane"
|
||||
//
|
||||
// aqback: the animation queue back, from which relative
|
||||
// moves are computed.
|
||||
//
|
||||
void configure(LuaKeywordParser &kp, const AnimStep &aqback);
|
||||
|
||||
// Make this step into a first-step of an anim queue.
|
||||
void keep_state_only();
|
||||
|
||||
// For any values that are unchanged in this step,
|
||||
// echo the values of the previous step.
|
||||
void echo(const AnimStep &prev);
|
||||
|
||||
// Verify that this step echoes the previous step.
|
||||
bool echoes(const AnimStep &prev) const;
|
||||
|
||||
// Convert to a string for debugging purposes.
|
||||
eng::string debug_string() const;
|
||||
|
||||
// Convert a string to an animstep (for testing only).
|
||||
bool from_string(const eng::string &s);
|
||||
|
||||
private:
|
||||
int64_t id_;
|
||||
int16_t bits_;
|
||||
eng::string action_;
|
||||
|
||||
float facing_;
|
||||
util::XYZ xyz_;
|
||||
eng::string graphic_;
|
||||
eng::string plane_;
|
||||
|
||||
void config_store_string(lua_State *L, int idx, eng::string *target, int16_t bits, const char *name);
|
||||
void config_store_number(lua_State *L, int idx, float *target, float offset, int16_t bits, const char *name);
|
||||
};
|
||||
|
||||
|
||||
class AnimQueue : public eng::nevernew {
|
||||
public:
|
||||
// World type determines whether versions increment or autozero
|
||||
AnimQueue(util::WorldType wt);
|
||||
|
||||
// Simple getters.
|
||||
const AnimStep &nth(int n) const { return steps_[n]; }
|
||||
size_t size() const { return steps_.size(); }
|
||||
int32_t size_limit() const { return size_limit_; }
|
||||
int64_t version_number() const { return version_number_; }
|
||||
bool version_identical(const AnimQueue &aq) const;
|
||||
|
||||
// Return true if the size limit and steps are identical.
|
||||
bool size_and_steps_equal(const AnimQueue &aq) const;
|
||||
|
||||
// Mutator to create a new step.
|
||||
void add(int64_t id, const AnimStep &step);
|
||||
|
||||
// Clear and set the plane.
|
||||
void clear(const eng::string &plane);
|
||||
|
||||
// Serialize or deserialize to a StreamBuffer
|
||||
//
|
||||
// Caution: version numbers are not stored. On deserialize,
|
||||
// version number is set to zero.
|
||||
//
|
||||
void serialize(StreamBuffer *sb) const;
|
||||
void deserialize(StreamBuffer *sb);
|
||||
|
||||
// Difference transmission
|
||||
bool diff(const AnimQueue &auth, StreamBuffer *sb) const;
|
||||
void patch(StreamBuffer *sb, DebugCollector *dbc);
|
||||
void update_version(const AnimQueue &auth);
|
||||
|
||||
// Get the final resting place after all animations are complete.
|
||||
const AnimStep &back() const;
|
||||
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TESTING SUPPORT
|
||||
//
|
||||
// The following functions are not designed to be useful for production
|
||||
// code, they're designed to be helpful for unit testing.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Change the size limit.
|
||||
void full_clear_and_set_limit(int szl);
|
||||
void set_limit(int szl);
|
||||
|
||||
// Make sure the invariants are preserved.
|
||||
bool valid() const;
|
||||
|
||||
// Convert to a string for debugging purposes.
|
||||
eng::string steps_debug_string() const;
|
||||
eng::string full_debug_string() const;
|
||||
|
||||
// Convert to a
|
||||
|
||||
private:
|
||||
bool version_autoinc_;
|
||||
int32_t size_limit_;
|
||||
eng::deque<AnimStep> steps_;
|
||||
int64_t version_number_;
|
||||
|
||||
// Called whenever the animation queue is mutated.
|
||||
// serialization and deserialization
|
||||
void mutated();
|
||||
};
|
||||
|
||||
#endif // ANIMQUEUE_HPP
|
||||
|
||||
Reference in New Issue
Block a user