Improved Docs, AnimationStepApplyMesh+Materials, some other minor tweaks
This commit is contained in:
@@ -85,11 +85,11 @@ static AnimValue parse_anim_value(LuaCoreStack &LS, LuaSlot val) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void AnimState::set_persistent(const eng::string &name) {
|
||||
void AnimStepEditor::set_persistent(const eng::string &name) {
|
||||
map_[name].persistent = true;
|
||||
}
|
||||
|
||||
void AnimState::print_debug_string(eng::ostringstream &oss) {
|
||||
void AnimStepEditor::print_debug_string(eng::ostringstream &oss) {
|
||||
bool first = true;
|
||||
if (map_.empty()) {
|
||||
oss << "[empty]";
|
||||
@@ -117,13 +117,13 @@ void AnimState::print_debug_string(eng::ostringstream &oss) {
|
||||
}
|
||||
}
|
||||
|
||||
eng::string AnimState::debug_string() {
|
||||
eng::string AnimStepEditor::debug_string() {
|
||||
eng::ostringstream oss;
|
||||
print_debug_string(oss);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
eng::string AnimState::encode() const {
|
||||
eng::string AnimStepEditor::encode() const {
|
||||
StreamBuffer sb;
|
||||
for (const auto &pair : map_) {
|
||||
const eng::string &name = pair.first;
|
||||
@@ -135,7 +135,7 @@ eng::string AnimState::encode() const {
|
||||
return eng::string(sb.view());
|
||||
}
|
||||
|
||||
void AnimState::decode(std::string_view s) {
|
||||
void AnimStepEditor::decode(std::string_view s) {
|
||||
map_.clear();
|
||||
StreamBuffer sb(s);
|
||||
while (!sb.empty()) {
|
||||
@@ -146,7 +146,7 @@ void AnimState::decode(std::string_view s) {
|
||||
}
|
||||
}
|
||||
|
||||
void AnimState::decode_persistent(std::string_view s) {
|
||||
void AnimStepEditor::decode_persistent(std::string_view s) {
|
||||
map_.clear();
|
||||
StreamBuffer sb(s);
|
||||
AnimValue dummy;
|
||||
@@ -163,7 +163,7 @@ void AnimState::decode_persistent(std::string_view s) {
|
||||
}
|
||||
}
|
||||
|
||||
eng::string AnimState::add_default(const eng::string &name, const AnimValue &def, const AnimState *other) {
|
||||
eng::string AnimStepEditor::add_default(const eng::string &name, const AnimValue &def, const AnimStepEditor *other) {
|
||||
AnimValue &value = map_[name];
|
||||
value.persistent = true;
|
||||
if (value.type == SimpleDynamicTag::UNINITIALIZED) {
|
||||
@@ -185,7 +185,7 @@ eng::string AnimState::add_default(const eng::string &name, const AnimValue &def
|
||||
return "";
|
||||
}
|
||||
|
||||
eng::string AnimState::add_defaults(const AnimState *other) {
|
||||
eng::string AnimStepEditor::add_defaults(const AnimStepEditor *other) {
|
||||
eng::string err;
|
||||
AnimValue defval;
|
||||
|
||||
@@ -209,7 +209,7 @@ eng::string AnimState::add_defaults(const AnimState *other) {
|
||||
}
|
||||
|
||||
|
||||
eng::string AnimState::from_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent, bool allowauto) {
|
||||
eng::string AnimStepEditor::from_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent, bool allowauto) {
|
||||
LuaVar key, val;
|
||||
LuaExtStack LS(LS0.state(), key, val);
|
||||
util::DXYZ xyz;
|
||||
@@ -241,7 +241,7 @@ eng::string AnimState::from_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent,
|
||||
return "";
|
||||
}
|
||||
|
||||
eng::string AnimState::merge(const AnimState &previous, const AnimState &update) {
|
||||
eng::string AnimStepEditor::merge(const AnimStepEditor &previous, const AnimStepEditor &update) {
|
||||
// Copy everything over from the previous entry.
|
||||
map_ = previous.map_;
|
||||
|
||||
@@ -286,7 +286,7 @@ eng::string AnimState::merge(const AnimState &previous, const AnimState &update)
|
||||
}
|
||||
|
||||
|
||||
void AnimState::to_lua(LuaCoreStack &LS0, LuaSlot tab, bool transient, bool persistent) {
|
||||
void AnimStepEditor::to_lua(LuaCoreStack &LS0, LuaSlot tab, bool transient, bool persistent) {
|
||||
LuaVar name, val;
|
||||
LuaExtStack LS(LS0.state(), name, val);
|
||||
LS.newtable(tab);
|
||||
@@ -319,7 +319,7 @@ void AnimState::to_lua(LuaCoreStack &LS0, LuaSlot tab, bool transient, bool pers
|
||||
|
||||
// The syntax used by this parser is not general enough to represent all
|
||||
// possible strings. That's OK, though, since it's just for unit testing.
|
||||
void AnimState::parse(std::string_view config) {
|
||||
void AnimStepEditor::parse(std::string_view config) {
|
||||
while (true) {
|
||||
config = sv::ltrim(config);
|
||||
if (config.empty()) break;
|
||||
@@ -336,7 +336,7 @@ void AnimState::parse(std::string_view config) {
|
||||
}
|
||||
}
|
||||
|
||||
void AnimState::clear_and_parse(std::string_view config) {
|
||||
void AnimStepEditor::clear_and_parse(std::string_view config) {
|
||||
map_.clear();
|
||||
parse(config);
|
||||
}
|
||||
@@ -442,15 +442,15 @@ void AnimQueue::update_encqueue(int limit, bool add, std::string_view add_enc, i
|
||||
}
|
||||
|
||||
AnimQueue::AnimQueue() {
|
||||
update_encqueue(10, true, AnimState().encode(), 0, 0);
|
||||
update_encqueue(10, true, AnimStepEditor().encode(), 0, 0);
|
||||
}
|
||||
|
||||
void AnimQueue::clear(const AnimState &state) {
|
||||
void AnimQueue::clear(const AnimStepEditor &state) {
|
||||
update_encqueue(get_size_limit(), true, state.encode(), 0, 0);
|
||||
}
|
||||
|
||||
void AnimQueue::clear() {
|
||||
update_encqueue(get_size_limit(), true, AnimState().encode(), 0, 0);
|
||||
update_encqueue(get_size_limit(), true, AnimStepEditor().encode(), 0, 0);
|
||||
}
|
||||
|
||||
void AnimQueue::set_limit(int limit) {
|
||||
@@ -458,12 +458,12 @@ void AnimQueue::set_limit(int limit) {
|
||||
update_encqueue(limit, false, std::string_view(), 0, limit);
|
||||
}
|
||||
|
||||
void AnimQueue::add(const AnimState &state) {
|
||||
void AnimQueue::add(const AnimStepEditor &state) {
|
||||
int limit = get_size_limit();
|
||||
update_encqueue(limit, true, state.encode(), 0, limit - 1);
|
||||
}
|
||||
|
||||
void AnimQueue::replace(const AnimState &state) {
|
||||
void AnimQueue::replace(const AnimStepEditor &state) {
|
||||
int limit = get_size_limit();
|
||||
update_encqueue(limit, true, state.encode(), 1, limit);
|
||||
}
|
||||
@@ -528,7 +528,7 @@ void AnimQueue::print_debug_string(eng::ostringstream &oss, bool full) const {
|
||||
assert(sb.empty());
|
||||
for (int i = encsteps.size() - 1; i >= 0; i --) {
|
||||
if (!first) oss << "; ";
|
||||
AnimState state(encsteps[i]);
|
||||
AnimStepEditor state(encsteps[i]);
|
||||
state.print_debug_string(oss);
|
||||
first = false;
|
||||
}
|
||||
@@ -553,16 +553,16 @@ AnimCoreState AnimQueue::get_final_core_state() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
AnimState AnimQueue::get_final_persistent() const {
|
||||
AnimStepEditor AnimQueue::get_final_persistent() const {
|
||||
std::string_view encstep = get_final_encstep();
|
||||
AnimState result;
|
||||
AnimStepEditor result;
|
||||
result.decode_persistent(encstep);
|
||||
return result;
|
||||
}
|
||||
|
||||
AnimState AnimQueue::get_final_everything() const {
|
||||
AnimStepEditor AnimQueue::get_final_everything() const {
|
||||
std::string_view encstep = get_final_encstep();
|
||||
AnimState result;
|
||||
AnimStepEditor result;
|
||||
result.decode(encstep);
|
||||
return result;
|
||||
}
|
||||
@@ -571,44 +571,44 @@ LuaDefine(unittests_animqueue, "", "some unit tests") {
|
||||
// Useful objects.
|
||||
AnimQueue aq, aqs;
|
||||
StreamBuffer sb;
|
||||
AnimState astate;
|
||||
AnimStepEditor astate;
|
||||
eng::string enc;
|
||||
AnimCoreState core;
|
||||
|
||||
// Debug string of a newly initialized queue
|
||||
LuaAssertStrEq(L, aq.full_debug_string(), "limit=10; [empty]");
|
||||
|
||||
// Test AnimState simple setters.
|
||||
// Test AnimStepEditor simple setters.
|
||||
astate.set_string("color", "blue");
|
||||
astate.set_dxyz("xyz", util::DXYZ(1,2,3));
|
||||
astate.set_number("half", 0.5);
|
||||
astate.set_boolean("nice", true);
|
||||
LuaAssertStrEq(L, astate.debug_string(), "color:blue half:0.5 nice:true xyz:1,2,3");
|
||||
|
||||
// // Test AnimState simple getters.
|
||||
// // Test AnimStepEditor simple getters.
|
||||
// LuaAssert(L, astate.get_string("color") == "blue");
|
||||
// LuaAssert(L, astate.get_xyz("xyz") == util::DXYZ(1,2,3));
|
||||
// LuaAssert(L, astate.get_number("half") == 0.5);
|
||||
// LuaAssert(L, astate.get_boolean("nice") == true);
|
||||
|
||||
// // Test AnimState simple getters on nonexistent data.
|
||||
// // Test AnimStepEditor simple getters on nonexistent data.
|
||||
// LuaAssert(L, astate.get_string("q") == "");
|
||||
// LuaAssert(L, astate.get_xyz("q") == util::DXYZ(0,0,0));
|
||||
// LuaAssert(L, astate.get_number("q") == 0.0);
|
||||
// LuaAssert(L, astate.get_boolean("q") == false);
|
||||
|
||||
// // Test AnimState simple getters on wrong-type data.
|
||||
// // Test AnimStepEditor simple getters on wrong-type data.
|
||||
// LuaAssert(L, astate.get_string("half") == "");
|
||||
// LuaAssert(L, astate.get_xyz("half") == util::DXYZ(0,0,0));
|
||||
// LuaAssert(L, astate.get_number("color") == 0.0);
|
||||
// LuaAssert(L, astate.get_boolean("color") == false);
|
||||
|
||||
// Test AnimState persistence manipulation.
|
||||
// Test AnimStepEditor persistence manipulation.
|
||||
astate.set_persistent("color");
|
||||
astate.set_persistent("nice");
|
||||
LuaAssertStrEq(L, astate.debug_string(), "color=blue half:0.5 nice=true xyz:1,2,3");
|
||||
|
||||
// Test AnimState parser.
|
||||
// Test AnimStepEditor parser.
|
||||
astate.clear_and_parse("color:green mean=true pos=3,4,5 ok:false");
|
||||
LuaAssertStrEq(L, astate.debug_string(), "color:green mean=true ok:false pos=3,4,5");
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ANIMATION QUEUES
|
||||
// ANIMATION QUEUES AND ANIMATION STEPS
|
||||
//
|
||||
// See "Animation Queues and Tangible Actors.md" for an overview.
|
||||
//
|
||||
// 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 is a set of key-value pairs, where each key is an
|
||||
// identifier, and each value is either a number, a boolean, an XYZ coordinate,
|
||||
// or a string. A key-value pair can be either persistent or nonpersistent.
|
||||
// identifier, and each value is either a number, boolean, vector,
|
||||
// token, or string. A key-value pair can be either persistent or nonpersistent.
|
||||
// So a typical animation step might be:
|
||||
//
|
||||
// action=walk [nonpersistent]
|
||||
@@ -22,9 +24,34 @@
|
||||
// by mixing the hash value of the previous step with the hash value
|
||||
// of the encoded string of key-value pairs.
|
||||
//
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// SERIALIZED STORAGE
|
||||
// Class AnimStepEditor is used to read+write animation steps.
|
||||
//
|
||||
// Note: this class is not used for storage of animation steps.
|
||||
// Animation steps are stored in class AnimQueue. AnimStepEditor
|
||||
// is only used when you want to extract animation steps from
|
||||
// an AnimQueue, or insert new animation steps into an AnimQueue.
|
||||
//
|
||||
// Class AnimStepEditor is quite simple: it's a map from Key to
|
||||
// AnimValue. AnimValue is a container that can hold a number,
|
||||
// string, vector, token, or boolean. Class AnimStepEditor provides
|
||||
// a variety of accessors to set key-value pairs.
|
||||
//
|
||||
// For example, you can populate an animation step by setting
|
||||
// key-value pairs directly. You can import key-value pairs
|
||||
// from a lua table. You can also merge key-value pairs from
|
||||
// a different AnimStepEditor.
|
||||
//
|
||||
// When importing from a lua_table or a from another AnimStepEditor,
|
||||
// there are rules for resolving conflicts between any key-value
|
||||
// pairs that are already in the builder with those being imported.
|
||||
// See the documentation for those functions for more information.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Class AnimQueue stores animation queues.
|
||||
//
|
||||
// The entired animation queue is stored in a serialized format,
|
||||
// as a shared string. This means that the animation queue can be
|
||||
@@ -118,7 +145,7 @@ struct AnimValue : public SimpleDynamicValue {
|
||||
};
|
||||
|
||||
|
||||
class AnimState
|
||||
class AnimStepEditor
|
||||
{
|
||||
private:
|
||||
using Map = eng::map<eng::string, AnimValue>;
|
||||
@@ -126,7 +153,7 @@ private:
|
||||
|
||||
// Set the default value, internal
|
||||
//
|
||||
eng::string add_default(const eng::string &name, const AnimValue &v, const AnimState *other);
|
||||
eng::string add_default(const eng::string &name, const AnimValue &v, const AnimStepEditor *other);
|
||||
|
||||
public:
|
||||
// Clear everything
|
||||
@@ -160,7 +187,7 @@ public:
|
||||
|
||||
// Constructs an empty state.
|
||||
//
|
||||
AnimState() {}
|
||||
AnimStepEditor() {}
|
||||
|
||||
// Convert to an encoded string.
|
||||
//
|
||||
@@ -188,7 +215,7 @@ public:
|
||||
// - If no default value can be found in 'other', then a hardwired
|
||||
// default value is provided.
|
||||
//
|
||||
eng::string add_defaults(const AnimState *other);
|
||||
eng::string add_defaults(const AnimStepEditor *other);
|
||||
|
||||
// Parse an animstate from a Lua Table.
|
||||
//
|
||||
@@ -199,7 +226,7 @@ public:
|
||||
//
|
||||
// If 'allowauto' is true, then the lua table may contain a key-value
|
||||
// pair of the form (key, math.auto). These keys will be stored in the
|
||||
// AnimState map with mapentry.type == SimpleDynamicTag::AUTO.
|
||||
// AnimStepEditor map with mapentry.type == SimpleDynamicTag::AUTO.
|
||||
// This is done to express an intent that the value should be
|
||||
// automatically computer later.
|
||||
//
|
||||
@@ -207,7 +234,7 @@ public:
|
||||
|
||||
// Generate a merged animstate using a previous state and an update.
|
||||
//
|
||||
// Keys from both previous and update are combined to create this AnimState.
|
||||
// Keys from both previous and update are combined to create this AnimStepEditor.
|
||||
// Values from 'update' override values from 'previous'. Persistent flags
|
||||
// are taken from 'previous'. If a key exists in both previous and update,
|
||||
// and the key is persistent in 'previous', then the types must match,
|
||||
@@ -218,7 +245,7 @@ public:
|
||||
// a rule to compute that value automatically. Failure to find a rule
|
||||
// results in an error.
|
||||
//
|
||||
eng::string merge(const AnimState &previous, const AnimState &update);
|
||||
eng::string merge(const AnimStepEditor &previous, const AnimStepEditor &update);
|
||||
|
||||
// Convert an animstate to a lua table.
|
||||
//
|
||||
@@ -250,7 +277,7 @@ public:
|
||||
|
||||
// Constructor from an encoded string.
|
||||
//
|
||||
AnimState(std::string_view s) { decode(s); }
|
||||
AnimStepEditor(std::string_view s) { decode(s); }
|
||||
};
|
||||
|
||||
struct AnimCoreState
|
||||
@@ -271,7 +298,7 @@ public:
|
||||
// Clear the steps to an initial state.
|
||||
//
|
||||
void clear();
|
||||
void clear(const AnimState &initial);
|
||||
void clear(const AnimStepEditor &initial);
|
||||
|
||||
// Change the size limit.
|
||||
//
|
||||
@@ -282,14 +309,14 @@ public:
|
||||
// Note: add does not automatically compose the step with the previous
|
||||
// step, you have to do that yourself.
|
||||
//
|
||||
void add(const AnimState &state);
|
||||
void add(const AnimStepEditor &state);
|
||||
|
||||
// Replace the most recent animation step.
|
||||
//
|
||||
// Note: replace does not automatically compose the step with the previous
|
||||
// step, you have to do that yourself.
|
||||
//
|
||||
void replace(const AnimState &state);
|
||||
void replace(const AnimStepEditor &state);
|
||||
|
||||
// Serialize or deserialize to a StreamBuffer
|
||||
//
|
||||
@@ -324,11 +351,11 @@ public:
|
||||
|
||||
// Get the final entry, all persistent variables.
|
||||
//
|
||||
AnimState get_final_persistent() const;
|
||||
AnimStepEditor get_final_persistent() const;
|
||||
|
||||
// Get the final entry, everything persistent and non-persistent.
|
||||
//
|
||||
AnimState get_final_everything() const;
|
||||
AnimStepEditor get_final_everything() const;
|
||||
|
||||
// Get a serialized representation of the animation queue.
|
||||
//
|
||||
|
||||
@@ -256,22 +256,22 @@
|
||||
// either.
|
||||
//
|
||||
// Lua has a datatype called 'lightuserdata'. A lightuserdata holds an
|
||||
// int64. That gives me an option: I can store json null as
|
||||
// lightuserdata(0x6E756C6C00000000). When we see this lightuserdata
|
||||
// value, we would know we have a json null. Why 0x6E756C6C00000000?
|
||||
// Because if you interpret those 8 bytes as 8 ascii characters, it's the
|
||||
// string "null".
|
||||
// int64. That gives me an option: I can store json null as a
|
||||
// lightuserdata. When we see this lightuserdata value, we would know
|
||||
// we have a json null.
|
||||
//
|
||||
// So that finally brings me to what a "token" is. A token is a lightuserdata
|
||||
// containing up to 8 ascii characters. So in effect, it's a short string,
|
||||
// but it's a string that's distinguishable from a normal lua string. It
|
||||
// doesn't have the same type as a lua string (it shows up as a lightuserdata).
|
||||
// containing a short string encoded as a base36 number. Tokens may only
|
||||
// contain the characters a-z and 0-9, and can be up to 12 characters long
|
||||
// (since 36^12 fits in 64 bits). In effect, it's a short string, but it's
|
||||
// a string that's distinguishable from a normal lua string. It doesn't have
|
||||
// the same type as a lua string (it shows up as a lightuserdata).
|
||||
// The purpose of tokens is to represent special unique values, like json null.
|
||||
//
|
||||
// To make working with tokens easy, I've created a C++ class 'LuaToken'.
|
||||
// To make working with tokens easy, I've created a C++ struct 'LuaToken'.
|
||||
// It stores an int64. You can construct a LuaToken in two different ways:
|
||||
//
|
||||
// LuaToken(0x6E756C6C00000000)
|
||||
// LuaToken(0x10FAA9)
|
||||
// LuaToken("null")
|
||||
//
|
||||
// Those are equivalent. The second form is just as fast as the first,
|
||||
|
||||
@@ -74,14 +74,19 @@ LuaDefine(tangible_animfinal, "tan",
|
||||
LuaDefStack LS(L, tanobj, result);
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
Tangible *tan = w->tangible_get(LS, tanobj, false);
|
||||
AnimState state = tan->anim_queue_.get_final_everything();
|
||||
state.to_lua(LS, result, true, true);
|
||||
AnimStepEditor step = tan->anim_queue_.get_final_everything();
|
||||
step.to_lua(LS, result, true, true);
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
LuaDefine(tangible_animinit, "tan,config",
|
||||
LuaDefine(tangible_animinit, "config",
|
||||
"|Reinitialize the animation queue and specify persistent state."
|
||||
"|"
|
||||
"|The configuration table must contain the following keywords:"
|
||||
"|"
|
||||
"| tan: the tangible to reinitialize."
|
||||
"| anim: a table of key-value pairs for the initial animation state."
|
||||
"|"
|
||||
"|Every tangible has an animation queue. The queue consists of a"
|
||||
"|sequence of animation steps. Each step consists of a list of"
|
||||
"|key-value pairs. For example, if you want a human person to jump"
|
||||
@@ -102,7 +107,7 @@ LuaDefine(tangible_animinit, "tan,config",
|
||||
"|When you add an animation step to the animation queue, you do not have"
|
||||
"|to always specify xyz and plane. For example, you can legally say:"
|
||||
"|"
|
||||
"| tangible.animate(a, nil, {action='jump', height=3.0}))"
|
||||
"| tangible.animate{tan=a, anim={action='jump', height=3.0}}"
|
||||
"|"
|
||||
"|This adds a step to the animation queue. That step contains"
|
||||
"|xyz and plane, even though we didn't specify xyz and plane in"
|
||||
@@ -125,39 +130,51 @@ LuaDefine(tangible_animinit, "tan,config",
|
||||
"|"
|
||||
"|This function, tangible.animinit, is used to reconfigure the set of"
|
||||
"|persistent state variables that are retained by the tangible's"
|
||||
"|animation queue. You must provide a table containing all the"
|
||||
"|animation queue. You must provide an anim table containing all the"
|
||||
"|persistent values you want, and their initial values."
|
||||
"|") {
|
||||
LuaArg tanobj, config;
|
||||
LuaDefStack LS(L, tanobj, config);
|
||||
LuaArg config;
|
||||
LuaVar tanobj, animtab;
|
||||
LuaDefStack LS(L, config, tanobj, animtab);
|
||||
|
||||
LuaKeywordParser kp(LS, config);
|
||||
kp.required(tanobj, "tan");
|
||||
kp.required(animtab, "anim");
|
||||
kp.check_throw();
|
||||
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
Tangible *tan = w->tangible_get(LS, tanobj, false);
|
||||
AnimState state;
|
||||
eng::string error = state.from_lua(LS, config, true, false);
|
||||
AnimStepEditor step;
|
||||
eng::string error = step.from_lua(LS, animtab, true, false);
|
||||
if (!error.empty()) {
|
||||
luaL_error(L, "%s", error.c_str());
|
||||
}
|
||||
AnimState defsource = tan->anim_queue_.get_final_persistent();
|
||||
error = state.add_defaults(&defsource);
|
||||
AnimStepEditor defsource = tan->anim_queue_.get_final_persistent();
|
||||
error = step.add_defaults(&defsource);
|
||||
if (!error.empty()) {
|
||||
luaL_error(L, "%s", error.c_str());
|
||||
}
|
||||
tan->anim_queue_.clear(state);
|
||||
tan->anim_queue_.clear(step);
|
||||
tan->update_plane_item();
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
LuaDefine(tangible_animate, "tan,options,config",
|
||||
LuaDefine(tangible_animate, "config",
|
||||
"|Add an animation step to the tangible."
|
||||
"|"
|
||||
"|The animation queue stores animation steps. This function, "
|
||||
"|tangible.animate, adds one new animation step to the queue."
|
||||
"|The configuration table must contain the following keywords:"
|
||||
"|"
|
||||
"| tan: the tangible to animate."
|
||||
"| anim: a table of key-value pairs for the animation step."
|
||||
"| replace: (optional) if true, the last step in the queue is"
|
||||
"| removed, and the new animation replaces it. Persistent"
|
||||
"| state is carried over from the step that was replaced."
|
||||
"|"
|
||||
"|It might be useful to read doc(tangible.animinit) before reading"
|
||||
"|more."
|
||||
"|"
|
||||
"|An animation step is just a list of key-value pairs. Therefore,"
|
||||
"|the config table must be key-value pairs. Keys must be simple"
|
||||
"|the anim table must be key-value pairs. Keys must be simple"
|
||||
"|identifiers. Values can be numbers, strings, booleans, or"
|
||||
"|coordinates."
|
||||
"|"
|
||||
@@ -171,34 +188,29 @@ LuaDefine(tangible_animate, "tan,options,config",
|
||||
"|animation step, but nothing is propagated forward to future animation"
|
||||
"|steps."
|
||||
"|"
|
||||
"|The options can be nil, or options can be a table containing"
|
||||
"|the following flags:"
|
||||
"|"
|
||||
"| replace: if true, then the last step in the queue is removed,"
|
||||
"| and the new animation replaces it. Persistent state is carried"
|
||||
"| over from the step that was replaced."
|
||||
"|"
|
||||
"|") {
|
||||
LuaArg tanobj, options, steptab;
|
||||
LuaVar option;
|
||||
LuaDefStack LS(L, option, tanobj, options, steptab);
|
||||
LuaArg config;
|
||||
LuaVar tanobj, animtab, option;
|
||||
LuaDefStack LS(L, config, tanobj, animtab, option);
|
||||
|
||||
LuaKeywordParser kp(LS, config);
|
||||
kp.required(tanobj, "tan");
|
||||
kp.required(animtab, "anim");
|
||||
bool replace = false;
|
||||
if (!LS.isnil(options)) {
|
||||
LuaKeywordParser kp(LS, options);
|
||||
if (kp.optional(option, "replace")) {
|
||||
replace = LS.ckboolean(option);
|
||||
}
|
||||
kp.final_check_throw();
|
||||
if (kp.optional(option, "replace")) {
|
||||
replace = LS.ckboolean(option);
|
||||
}
|
||||
kp.check_throw();
|
||||
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
Tangible *tan = w->tangible_get(LS, tanobj, false);
|
||||
AnimState previous = tan->anim_queue_.get_final_persistent();
|
||||
AnimState update;
|
||||
eng::string error = update.from_lua(LS, steptab, false, true);
|
||||
AnimStepEditor previous = tan->anim_queue_.get_final_persistent();
|
||||
AnimStepEditor update;
|
||||
eng::string error = update.from_lua(LS, animtab, false, true);
|
||||
if (!error.empty()) {
|
||||
luaL_error(L, "%s", error.c_str());
|
||||
}
|
||||
AnimState merge;
|
||||
AnimStepEditor merge;
|
||||
error = merge.merge(previous, update);
|
||||
if (!error.empty()) {
|
||||
luaL_error(L, "%s", error.c_str());
|
||||
@@ -291,16 +303,13 @@ LuaDefine(tangible_build, "config",
|
||||
"|Build a new tangible object."
|
||||
"|"
|
||||
"|The configuration table must contain the keyword 'class', which"
|
||||
"|must be the name of a class created with 'makeclass'. It may also"
|
||||
"|contain the following values:"
|
||||
"|"
|
||||
"| bp - the unreal blueprint, defaults to class name."
|
||||
"| plane - the plane, defaults to actor.plane"
|
||||
"| xyz - the xyz coordinate, defaults to actor.xyz"
|
||||
"| facing - the rotation, defaults to actor.facing"
|
||||
"|"
|
||||
"|Tangible.build will create an initial animstate containing only"
|
||||
"|bp, plane, xyz, and facing."
|
||||
"|must be the name of a class created with 'makeclass'. It may"
|
||||
"|optionally contain the keyword 'anim', which is a table of"
|
||||
"|key-value pairs for the initial animation step. The anim table"
|
||||
"|may contain any key-value pairs that tangible.animate accepts."
|
||||
"|The mandatory keys (bp, plane, xyz, facing) will be defaulted"
|
||||
"|from the actor if not specified. If bp is not specified, it"
|
||||
"|defaults to the class name."
|
||||
"|"
|
||||
"|After creating the tangible and setting up the initial animation"
|
||||
"|state, build will call the constructor for the tangible."
|
||||
@@ -315,17 +324,14 @@ LuaDefine(tangible_build, "config",
|
||||
"|The constructor is not allowed to block."
|
||||
){
|
||||
LuaArg config;
|
||||
LuaVar classname, classtab, bp, plane, xyz, facing, mt, func;
|
||||
LuaVar classname, classtab, animtab, mt, func;
|
||||
LuaRet database;
|
||||
LuaDefStack LS(L, config, classname, classtab, bp, plane, xyz, facing, mt, func, database);
|
||||
LuaDefStack LS(L, config, classname, classtab, animtab, mt, func, database);
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
|
||||
LuaKeywordParser kp(LS, config);
|
||||
kp.required(classname, "class");
|
||||
kp.optional(bp, "bp");
|
||||
kp.optional(plane, "plane");
|
||||
kp.optional(xyz, "xyz");
|
||||
kp.optional(facing, "facing");
|
||||
kp.optional(animtab, "anim");
|
||||
kp.check_throw();
|
||||
|
||||
// Verify the class.
|
||||
@@ -335,41 +341,38 @@ LuaDefine(tangible_build, "config",
|
||||
}
|
||||
|
||||
// Calculate the initial animation state.
|
||||
AnimState state;
|
||||
if (!LS.isnil(bp)) {
|
||||
state.set_string("bp", LS.ckstring(bp));
|
||||
} else {
|
||||
state.set_string("bp", LS.classname(classtab));
|
||||
AnimStepEditor step;
|
||||
if (!LS.isnil(animtab)) {
|
||||
err = step.from_lua(LS, animtab, true, false);
|
||||
if (err != "") {
|
||||
luaL_error(L, "%s", err.c_str());
|
||||
}
|
||||
}
|
||||
if (!LS.isnil(plane)) {
|
||||
state.set_string("plane", LS.ckstring(plane));
|
||||
}
|
||||
if (!LS.isnil(xyz)) {
|
||||
state.set_dxyz("xyz", LS.ckxyz(xyz));
|
||||
}
|
||||
if (!LS.isnil(facing)) {
|
||||
state.set_number("facing", LS.cknumber(facing));
|
||||
|
||||
// Default bp to the class name if not specified.
|
||||
if (!step.contains("bp")) {
|
||||
step.set_string("bp", LS.classname(classtab));
|
||||
}
|
||||
|
||||
// Add default values from the actor. Set persistent flags.
|
||||
Tangible *actor = w->tangible_get(w->lthread_actor_id_);
|
||||
AnimState actorstate = actor->anim_queue_.get_final_persistent();
|
||||
err = state.add_defaults(&actorstate);
|
||||
AnimStepEditor actorstate = actor->anim_queue_.get_final_persistent();
|
||||
err = step.add_defaults(&actorstate);
|
||||
if (err != "") {
|
||||
luaL_error(L, "%s", err.c_str());
|
||||
}
|
||||
|
||||
|
||||
int64_t new_id = w->alloc_id_predictable();
|
||||
Tangible *tan = w->tangible_make(LS, database, new_id);
|
||||
|
||||
// Update the class of the new tangible.
|
||||
LS.getmetatable(mt, database);
|
||||
LS.rawset(mt, "__index", classtab);
|
||||
|
||||
|
||||
// Initialize the animstate of the new tangible.
|
||||
tan->anim_queue_.clear(state);
|
||||
tan->anim_queue_.clear(step);
|
||||
tan->update_plane_item();
|
||||
|
||||
|
||||
// Call the constructor and finish.
|
||||
LS.rawget(func, classtab, "init");
|
||||
if (!LS.isfunction(func)) {
|
||||
|
||||
@@ -227,7 +227,7 @@ Tangible *World::tangible_make(const LuaCoreStack &LS0, LuaSlot database, int64_
|
||||
t->delete_on_disconnect_ = false;
|
||||
|
||||
// AnimQueue initializes itself to a valid default state.
|
||||
AnimState state;
|
||||
AnimStepEditor state;
|
||||
state.add_defaults(nullptr);
|
||||
t->anim_queue_.clear(state);
|
||||
t->update_plane_item();
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
void World::tangible_clear_anim_queue_to_empty(int64_t id) {
|
||||
Tangible *t = tangible_get(id);
|
||||
assert(t != nullptr);
|
||||
AnimState state;
|
||||
AnimStepEditor state;
|
||||
t->anim_queue_.clear(state);
|
||||
t->update_plane_item();
|
||||
}
|
||||
@@ -16,7 +16,7 @@ void World::tangible_clear_anim_queue_to_empty(int64_t id) {
|
||||
void World::tangible_clear_plane_and_xyz(int64_t id, const eng::string &plane, const util::DXYZ &xyz) {
|
||||
Tangible *t = tangible_get(id);
|
||||
assert(t != nullptr);
|
||||
AnimState state;
|
||||
AnimStepEditor state;
|
||||
state.set_string("plane", plane);
|
||||
state.set_dxyz("xyz", xyz);
|
||||
state.set_persistent("plane");
|
||||
@@ -28,7 +28,7 @@ void World::tangible_clear_plane_and_xyz(int64_t id, const eng::string &plane, c
|
||||
void World::tangible_walkto(int64_t id, float x, float y) {
|
||||
Tangible *t = tangible_get(id);
|
||||
assert(t != nullptr);
|
||||
AnimState state = t->anim_queue_.get_final_persistent();
|
||||
AnimStepEditor state = t->anim_queue_.get_final_persistent();
|
||||
state.set_string("action", "walkto");
|
||||
state.set_dxyz("xyz", util::DXYZ(x,y,0.0));
|
||||
t->anim_queue_.add(state);
|
||||
@@ -71,7 +71,7 @@ eng::string World::tangibles_near_debug_string(int64_t actor, int64_t distance)
|
||||
LS.rawget(tanobj, tangibles, id);
|
||||
LS.tangetclass(classtab, tanobj);
|
||||
eng::string cname = LS.classname(classtab);
|
||||
AnimState state = tan->anim_queue_.get_final_persistent();
|
||||
AnimStepEditor state = tan->anim_queue_.get_final_persistent();
|
||||
result << id << " (" << cname << "): " << state.debug_string() << std::endl;
|
||||
}
|
||||
return result.str();
|
||||
|
||||
Reference in New Issue
Block a user