Re-implement gradient selections
Uncomments and makes available selection.gradient in Lua. (The backend C code for this still existed, it just wasn't used.) The only valid way to specify a gradient is with a table. I considered adding non-table versions, but decided that there are too many independent variables that can be optional. A non-table version, without named parameters, would be confusing to read, especially since most of the arguments are ints. Also adds an impossible in the (possibly unreachable) case that selection_do_gradient gets called with a bad gradient type.
This commit is contained in:
committed by
Pasi Kallinen
parent
407f65aa8a
commit
0befdbfd02
@@ -2514,6 +2514,8 @@ E struct selectionvar *FDECL(selection_filter_mapchar, (struct selectionvar *,
|
||||
E void FDECL(set_floodfillchk_match_under, (XCHAR_P));
|
||||
E void FDECL(selection_do_ellipse, (struct selectionvar *,
|
||||
int, int, int, int, int));
|
||||
E void FDECL(selection_do_gradient, (struct selectionvar *, long, long,
|
||||
long, long, long, long, long, long));
|
||||
E void NDECL(update_croom);
|
||||
E const char *FDECL(get_trapname_bytype, (int));
|
||||
E void FDECL(l_register_des, (lua_State *));
|
||||
|
||||
70
src/nhlsel.c
70
src/nhlsel.c
@@ -25,6 +25,7 @@ static int FDECL(l_selection_match, (lua_State *));
|
||||
static int FDECL(l_selection_flood, (lua_State *));
|
||||
static int FDECL(l_selection_circle, (lua_State *));
|
||||
static int FDECL(l_selection_ellipse, (lua_State *));
|
||||
static int FDECL(l_selection_gradient, (lua_State *));
|
||||
static int FDECL(l_selection_iterate, (lua_State *));
|
||||
static int FDECL(l_selection_gc, (lua_State *));
|
||||
static int FDECL(l_selection_not, (lua_State *));
|
||||
@@ -39,7 +40,6 @@ static int FDECL(l_selection_not, (lua_State *));
|
||||
if ifdef'd out the prototype here and the
|
||||
function body below.
|
||||
*/
|
||||
static int FDECL(l_selection_gradient, (lua_State *));
|
||||
static int FDECL(l_selection_add, (lua_State *));
|
||||
static int FDECL(l_selection_sub, (lua_State *));
|
||||
static int FDECL(l_selection_ipairs, (lua_State *));
|
||||
@@ -736,6 +736,70 @@ lua_State *L;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Gradients are versatile enough, with so many independently optional
|
||||
* arguments, that it doesn't seem helpful to provide a non-table form with
|
||||
* non-obvious argument order. */
|
||||
/* selection.gradient({ type = "radial", x = 3, y = 5, x2 = 10, y2 = 12,
|
||||
* mindist = 4, maxdist = 10, limited = false }); */
|
||||
static int
|
||||
l_selection_gradient(L)
|
||||
lua_State *L;
|
||||
{
|
||||
int argc = lua_gettop(L);
|
||||
struct selectionvar *sel = (struct selectionvar *) 0;
|
||||
/* if x2 and y2 aren't set, the gradient has a single center point of x,y;
|
||||
* if they are set, the gradient is centered on a (x,y) to (x2,y2) line */
|
||||
schar x = 0, y = 0, x2 = -1, y2 = -1;
|
||||
/* points will not be added within mindist of the center; the chance for a
|
||||
* point between mindist and maxdist to be added to the selection starts at
|
||||
* 0% at mindist and increases linearly to 100% at maxdist */
|
||||
xchar mindist = 0, maxdist = 0;
|
||||
/* if limited is true, no points farther than maxdist will be added; if
|
||||
* false, all points farther than maxdist will be added */
|
||||
boolean limited = FALSE;
|
||||
long type;
|
||||
static const char *const gradtypes[] = {
|
||||
"radial", "square", NULL
|
||||
};
|
||||
static const int gradtypes2i[] = {
|
||||
SEL_GRADIENT_RADIAL, SEL_GRADIENT_SQUARE, -1
|
||||
};
|
||||
|
||||
if (argc == 1 && lua_type(L, 1) == LUA_TTABLE) {
|
||||
lcheck_param_table(L);
|
||||
type = gradtypes2i[get_table_option(L, "type", "radial", gradtypes)];
|
||||
x = (schar) get_table_int(L, "x");
|
||||
y = (schar) get_table_int(L, "y");
|
||||
x2 = (schar) get_table_int_opt(L, "x2", -1);
|
||||
y2 = (schar) get_table_int_opt(L, "y2", -1);
|
||||
/* maxdist is required because there's no obvious default value for it,
|
||||
* whereas mindist has an obvious defalt of 0 */
|
||||
maxdist = get_table_int(L, "maxdist");
|
||||
mindist = get_table_int_opt(L, "mindist", 0);
|
||||
limited = get_table_boolean_opt(L, "limited", FALSE);
|
||||
|
||||
lua_pop(L, 1);
|
||||
(void) l_selection_new(L);
|
||||
sel = l_selection_check(L, 1);
|
||||
} else {
|
||||
nhl_error(L, "wrong parameters");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* someone might conceivably want to draw a gradient somewhere off-map. So
|
||||
* the only coordinate that's "illegal" for that is (-1,-1).
|
||||
* If a level designer really needs to draw a gradient line using that
|
||||
* coordinate, they can do so by setting regular x and y to -1. */
|
||||
if (x2 == -1 && y2 == -1) {
|
||||
x2 = x;
|
||||
y2 = y;
|
||||
}
|
||||
|
||||
selection_do_gradient(sel, x, y, x2, y2, type, mindist, maxdist, limited);
|
||||
lua_settop(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* sel:iterate(function(x,y) ... end); */
|
||||
static int
|
||||
l_selection_iterate(L)
|
||||
@@ -782,10 +846,8 @@ static const struct luaL_Reg l_selection_methods[] = {
|
||||
{ "floodfill", l_selection_flood },
|
||||
{ "circle", l_selection_circle },
|
||||
{ "ellipse", l_selection_ellipse },
|
||||
{ "gradient", l_selection_gradient },
|
||||
{ "iterate", l_selection_iterate },
|
||||
/* TODO:
|
||||
{ "gradient", l_selection_gradient },
|
||||
*/
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
@@ -4683,6 +4683,8 @@ long x, y, x2, y2, gtyp, mind, maxd, limit;
|
||||
|
||||
switch (gtyp) {
|
||||
default:
|
||||
impossible("Unrecognized gradient type! Defaulting to radial...");
|
||||
/* FALLTHRU */
|
||||
case SEL_GRADIENT_RADIAL: {
|
||||
for (dx = 0; dx < COLNO; dx++)
|
||||
for (dy = 0; dy < ROWNO; dy++) {
|
||||
|
||||
Reference in New Issue
Block a user