Redesign of animation queue for unreal, add get_tangibles_near to drivenengine
This commit is contained in:
@@ -17,56 +17,169 @@ static void tangible_getall(LuaCoreStack &LS0, LuaSlot list, const util::IdVecto
|
||||
}
|
||||
}
|
||||
|
||||
LuaDefine(tangible_animstate, "tan",
|
||||
"|Get the entire animation state of the tangible."
|
||||
"|Returns six values: graphic,plane,x,y,z,facing.") {
|
||||
LuaArg tanobj;
|
||||
LuaRet graphic, plane, x, y, z, facing;
|
||||
LuaDefStack LS(L, tanobj, graphic, plane, x, y, z, facing);
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
Tangible *tan = w->tangible_get(LS, tanobj, false);
|
||||
const AnimStep &aqback = tan->anim_queue_.back();
|
||||
LS.set(graphic, aqback.graphic());
|
||||
LS.set(plane, aqback.plane());
|
||||
LS.set(x, aqback.xyz().x);
|
||||
LS.set(y, aqback.xyz().y);
|
||||
LS.set(z, aqback.xyz().z);
|
||||
LS.set(facing, aqback.facing());
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
LuaDefine(tangible_xyz, "tan",
|
||||
"|Get the current coordinates of the tangible."
|
||||
"|Returns three values: x, y, z") {
|
||||
"|Get the current coordinates of the tangible and the plane."
|
||||
"|Returns four values: x, y, z, plane") {
|
||||
LuaArg tanobj;
|
||||
LuaRet x, y, z;
|
||||
LuaRet x, y, z, plane;
|
||||
LuaDefStack LS(L, tanobj, x, y, z);
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
Tangible *tan = w->tangible_get(LS, tanobj, false);
|
||||
const AnimStep &aqback = tan->anim_queue_.back();
|
||||
LS.set(x, aqback.xyz().x);
|
||||
LS.set(y, aqback.xyz().y);
|
||||
LS.set(z, aqback.xyz().z);
|
||||
AnimCoreState pos = tan->anim_queue_.get_final_core_state();
|
||||
LS.set(x, pos.xyz.x);
|
||||
LS.set(y, pos.xyz.y);
|
||||
LS.set(z, pos.xyz.z);
|
||||
LS.set(plane, pos.plane);
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
LuaDefine(tangible_animate, "tan,configtable",
|
||||
"|Add an animation step to the tangible."
|
||||
"|The configtable is a table containing any of the following:"
|
||||
"|action,graphic,plane,x,y,z,facing") {
|
||||
LuaArg tanobj, config;
|
||||
LuaDefStack LS(L, tanobj, config);
|
||||
LuaKeywordParser kp(LS, config);
|
||||
LuaDefine(tangible_animdebug, "tan",
|
||||
"|Return a debug string showing the entire animation queue"
|
||||
"|") {
|
||||
LuaArg tanobj;
|
||||
LuaRet result;
|
||||
LuaDefStack LS(L, tanobj, result);
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
Tangible *tan = w->tangible_get(LS, tanobj, false);
|
||||
int64_t id = w->alloc_id_predictable();
|
||||
AnimStep step;
|
||||
step.configure(kp, tan->anim_queue_.back());
|
||||
kp.final_check_throw();
|
||||
if (step.action() == "") {
|
||||
luaL_error(L, "animation action must be specified");
|
||||
LS.set(result, tan->anim_queue_.steps_debug_string());
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
LuaDefine(tangible_animstate, "tan",
|
||||
"|Return the animation state variables of the tangible as a table."
|
||||
"|"
|
||||
"|The animation system stores 'animation state variables. "
|
||||
"|There are several builtin animation state variables. The"
|
||||
"|following is a list, along with some example values that"
|
||||
"|might be used if the object were a pirate treasure chest."
|
||||
"|"
|
||||
"| xyz={1,2,3} # xyz coordinate"
|
||||
"| plane='earth' # plane where the chest is located"
|
||||
"| facing=0 # rotation of the chest"
|
||||
"| bp='BP_piratechest' # name of an unreal blueprint"
|
||||
"| model='SM_piratechest' # name of an unreal mesh"
|
||||
"|"
|
||||
"|There can also be user-defined animation state variables."
|
||||
"|For example, for a pirate chest, you might want to add two"
|
||||
"|more state variables:"
|
||||
"|"
|
||||
"| open=true # chest can be open or closed"
|
||||
"| fullness=0.8 # how big the heap of coins is"
|
||||
"|"
|
||||
"|All state variables must be one of four types: number, string,"
|
||||
"|boolean, or coordinate. All state variables must have simple"
|
||||
"|identifiers for names."
|
||||
"|"
|
||||
"|Animation state variables are updated when you use"
|
||||
"|tangible.animate to create an animation record. For example,"
|
||||
"|suppose your character is initialized at xyz={1,1,1}. Then"
|
||||
"|he walks to xyz={2,2,2}, then he walks to xyz={3,3,3}."
|
||||
"|The animation queue now contains three animation steps:"
|
||||
"|"
|
||||
"|Animation Queue:"
|
||||
"| Step 1: action:initialize xyz={1,1,1} ..."
|
||||
"| Step 2: action:walkto xyz={2,2,2} ..."
|
||||
"| Step 3: action:walkto xyz={3,3,3} ..."
|
||||
"|"
|
||||
"|Notice that the state variable xyz is stored three times, once"
|
||||
"|in each animation step. All animation state variables are stored"
|
||||
"|in every animation step. When you use tangible.animstate to fetch"
|
||||
"|the current value of the animation state variables, you're"
|
||||
"|actually fetching the state variables from the last step in"
|
||||
"|the animation queue."
|
||||
"|"
|
||||
"|You can use this function, tangible.animstate, to view the"
|
||||
"|current set of state variables. You can use tangible.animinit"
|
||||
"|to reconfigure the set of user-defined state variables. You"
|
||||
"|can use tangible.animate to create animation steps, which can"
|
||||
"|alter any of the state variables."
|
||||
"|") {
|
||||
LuaArg tanobj;
|
||||
LuaRet result;
|
||||
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_persistent();
|
||||
state.to_lua(LS, result, true);
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
LuaDefine(tangible_animinit, "tan,config",
|
||||
"|Reinitialize the animation queue."
|
||||
"|"
|
||||
"|The animation queue stores certain animation state variables."
|
||||
"|See doc(tangible.animstate) for more information about animation"
|
||||
"|state variables."
|
||||
"|"
|
||||
"|This function, tangible.animinit, is used to reconfigure the set of"
|
||||
"|user-defined state variables. The config table that you pass in must"
|
||||
"|be key-value pairs. Keys must be simple identifiers. Values can be"
|
||||
"|numbers, strings, booleans, or coordinates."
|
||||
"|"
|
||||
"|After tangible.animinit, the tangible's animation state variables will"
|
||||
"|consist of the user-defined variables listed in the config table,"
|
||||
"|plus all the builtin animation state variables."
|
||||
"|"
|
||||
"|Optionally, the config table can also supply values for some or all"
|
||||
"|of the builtin state variables. For example, you could supply xyz"
|
||||
"|in the config table. If you do, the tangible will move to a new xyz"
|
||||
"|coordinate. If not, the tangible will retain its old xyz coordinate."
|
||||
"|") {
|
||||
LuaArg tanobj, config;
|
||||
LuaDefStack LS(L, tanobj, config);
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
Tangible *tan = w->tangible_get(LS, tanobj, false);
|
||||
AnimState state;
|
||||
eng::string error = state.apply_lua(LS, config, true);
|
||||
if (!error.empty()) {
|
||||
luaL_error(L, "%s", error.c_str());
|
||||
}
|
||||
tan->anim_queue_.add(id, step);
|
||||
AnimState defsource = tan->anim_queue_.get_final_persistent();
|
||||
error = state.add_defaults(&defsource);
|
||||
if (!error.empty()) {
|
||||
luaL_error(L, "%s", error.c_str());
|
||||
}
|
||||
tan->anim_queue_.clear(state);
|
||||
tan->update_plane_item();
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
|
||||
LuaDefine(tangible_animate, "tan,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."
|
||||
"|"
|
||||
"|It might be useful to read about 'animation state variables' before"
|
||||
"|reading this explanation. See doc(tangible.animstate)."
|
||||
"|"
|
||||
"|An animation step is just a list of key-value pairs. Therefore,"
|
||||
"|the config table must be key-value pairs. Keys must be simple"
|
||||
"|identifiers. Values can be numbers, strings, booleans, or"
|
||||
"|coordinates."
|
||||
"|"
|
||||
"|Some of the key-value pairs may match the name of an animation state"
|
||||
"|variable. If so, that key-value pair permanently changes the"
|
||||
"|value of that animation state variable. The new value will"
|
||||
"|be retained for all future animation steps."
|
||||
"|"
|
||||
"|Some of the key-value pairs may NOT match the name of any animation"
|
||||
"|state variable. If so, that key-value pair is part of the"
|
||||
"|animation step, but nothing is propagated forward to future animation"
|
||||
"|steps."
|
||||
"|"
|
||||
"|") {
|
||||
LuaArg tanobj, config;
|
||||
LuaDefStack LS(L, tanobj, config);
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
Tangible *tan = w->tangible_get(LS, tanobj, false);
|
||||
AnimState state = tan->anim_queue_.get_final_persistent();
|
||||
eng::string error = state.apply_lua(LS, config, false);
|
||||
if (!error.empty()) {
|
||||
luaL_error(L, "%s", error.c_str());
|
||||
}
|
||||
tan->anim_queue_.add(state);
|
||||
tan->update_plane_item();
|
||||
return LS.result();
|
||||
}
|
||||
@@ -132,51 +245,53 @@ LuaDefine(tangible_delete, "tan",
|
||||
|
||||
LuaDefine(tangible_build, "config",
|
||||
"|Build a new tangible object."
|
||||
"|The config table must contain: class,x,y,z,plane,graphic."
|
||||
"|The config table can optionally contain: facing.") {
|
||||
"|"
|
||||
"|The config table must contain: class,animstate."
|
||||
"|" ){
|
||||
LuaArg config;
|
||||
LuaVar classname, classtab, mt;
|
||||
LuaVar classname, classtab, mt, animstate;
|
||||
LuaRet database;
|
||||
LuaDefStack LS(L, config, classname, classtab, database, mt);
|
||||
LuaDefStack LS(L, config, classname, classtab, database, mt, animstate);
|
||||
LuaKeywordParser kp(LS, config);
|
||||
|
||||
// Get the class of the new tangible.
|
||||
// Get the keyword arguments.
|
||||
if (!kp.parse(classname, "class")) {
|
||||
luaL_error(L, "You must specify a class for the tangible");
|
||||
}
|
||||
if (!kp.parse(animstate, "animstate")) {
|
||||
luaL_error(L, "You must specify an animstate table");
|
||||
}
|
||||
kp.final_check_throw();
|
||||
|
||||
// Find the class.
|
||||
eng::string err = LS.getclass(classtab, classname);
|
||||
if (err != "") {
|
||||
luaL_error(L, "%s", err.c_str());
|
||||
}
|
||||
|
||||
// Parse the initial animation step.
|
||||
AnimStep initstep, blank;
|
||||
initstep.configure(kp, blank);
|
||||
kp.final_check_throw();
|
||||
if (!initstep.has_xyz()) {
|
||||
luaL_error(L, "You must specify (X,Y,Z) for new tangible");
|
||||
// Calculate the initial animation state.
|
||||
AnimState state;
|
||||
err = state.apply_lua(LS, animstate, true);
|
||||
if (err != "") {
|
||||
luaL_error(L, "%s", err.c_str());
|
||||
}
|
||||
if (!initstep.has_plane()) {
|
||||
luaL_error(L, "You must specify plane for new tangible");
|
||||
if (!state.contains("xyz") || !state.contains("plane")) {
|
||||
luaL_error(L, "You must specify both xyz and plane in animstate");
|
||||
}
|
||||
if (!initstep.has_graphic()) {
|
||||
luaL_error(L, "You must specify graphic for new tangible");
|
||||
err = state.add_defaults(nullptr);
|
||||
if (err != "") {
|
||||
luaL_error(L, "%s", err.c_str());
|
||||
}
|
||||
|
||||
// TODO: generate error if there's extra crap in the config table.
|
||||
|
||||
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
int64_t new_id = w->alloc_id_predictable();
|
||||
Tangible *tan = w->tangible_make(LS, database, new_id, "nowhere");
|
||||
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);
|
||||
|
||||
// Update the animation queue and planemap of the new tangible.
|
||||
int64_t stepid = w->alloc_id_predictable();
|
||||
tan->anim_queue_.add(stepid, initstep);
|
||||
tan->update_plane_item();
|
||||
|
||||
tan->anim_queue_.clear(state);
|
||||
|
||||
return LS.result();
|
||||
}
|
||||
@@ -259,34 +374,27 @@ LuaDefine(tangible_place, "",
|
||||
}
|
||||
|
||||
LuaDefine(tangible_near, "tan,radius,omit_nowhere,omit_self",
|
||||
"|Scan near the specified tangible."
|
||||
"|If omit_nowhere is true, and the tangible is on the nowhere plane,"
|
||||
"|then the scan returns empty. If omit_self is true, then the "
|
||||
"|tangible passed in is omitted from the results.") {
|
||||
"|Deprecated. Use tangible.find instead.") {
|
||||
LuaArg ltan, lradius, lomit_nowhere, lomit_self;
|
||||
LuaRet list;
|
||||
LuaDefStack LS(L, ltan, lradius, lomit_nowhere, lomit_self, list);
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
Tangible *tan = w->tangible_get(LS, ltan, false);
|
||||
const AnimStep &aqback = tan->anim_queue_.back();
|
||||
|
||||
PlaneScan scan;
|
||||
scan.set_plane(aqback.plane());
|
||||
scan.set_bbox_given_center_radius(aqback.xyz(), LS.cknumber(lradius));
|
||||
scan.set_radius(LS.cknumber(lradius));
|
||||
scan.set_shape(PlaneScan::SPHERE);
|
||||
scan.set_sorted(true);
|
||||
scan.set_near(tan->id(), !LS.ckboolean(lomit_self));
|
||||
scan.set_omit_nowhere(LS.ckboolean(lomit_nowhere));
|
||||
|
||||
util::IdVector idv = w->plane_map_.scan(scan);
|
||||
util::IdVector idv;
|
||||
w->get_near(scan, &idv);
|
||||
tangible_getall(LS, list, idv);
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
LuaDefine(tangible_scan, "plane,x,y,radius,omit_nowhere",
|
||||
"|Scan the specified plane."
|
||||
"|If omit_nowhere is true, and the plane is 'nowhere', then"
|
||||
"|the scan returns empty.") {
|
||||
"|Deprecated. Use tangible.find instead.") {
|
||||
LuaArg lplane, lx, ly, lradius, lomit_nowhere;
|
||||
LuaRet list;
|
||||
LuaDefStack LS(L, lplane, lx, ly, lradius, lomit_nowhere, list);
|
||||
@@ -294,12 +402,13 @@ LuaDefine(tangible_scan, "plane,x,y,radius,omit_nowhere",
|
||||
|
||||
PlaneScan scan;
|
||||
scan.set_plane(LS.ckstring(lplane));
|
||||
scan.set_bbox_given_center_radius(util::XYZ(LS.cknumber(lx), LS.cknumber(ly), 0), LS.cknumber(lradius));
|
||||
scan.set_center_and_radius(util::XYZ(LS.cknumber(lx), LS.cknumber(ly), 0), LS.cknumber(lradius));
|
||||
scan.set_shape(PlaneScan::SPHERE);
|
||||
scan.set_sorted(true);
|
||||
scan.set_omit_nowhere(LS.ckboolean(lomit_nowhere));
|
||||
|
||||
util::IdVector idv = w->plane_map_.scan(scan);
|
||||
util::IdVector idv;
|
||||
w->get_near(scan, &idv);
|
||||
tangible_getall(LS, list, idv);
|
||||
return LS.result();
|
||||
}
|
||||
@@ -369,21 +478,9 @@ LuaDefine(tangible_find, "config",
|
||||
scan.configure(kw);
|
||||
kw.final_check_throw();
|
||||
|
||||
// When the configure routine sees the 'near' flag, it stores the tangible
|
||||
// ID, but not the center and plane, because doing so would require it to
|
||||
// know about world models. We have to handle center and plane for 'near'
|
||||
// separately.
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
int64_t near = scan.near();
|
||||
if (near != 0) {
|
||||
Tangible *t = w->tangible_get(near);
|
||||
assert(t != nullptr); // Should never happen.
|
||||
const AnimStep &aqback = t->anim_queue_.back();
|
||||
scan.set_plane(aqback.plane());
|
||||
scan.set_center(aqback.xyz());
|
||||
}
|
||||
// Do the scan.
|
||||
util::IdVector idv = w->plane_map_.scan(scan);
|
||||
util::IdVector idv;
|
||||
w->get_near(scan, &idv);
|
||||
tangible_getall(LS, result, idv);
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user