Improved Docs, AnimationStepApplyMesh+Materials, some other minor tweaks

This commit is contained in:
2026-02-06 17:34:26 -05:00
parent a2e179e15b
commit 56765fdc16
28 changed files with 731 additions and 165 deletions

View File

@@ -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)) {