From f5f9f76ee1e03fdabd68ba28d0ca573eb1945f66 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 29 Oct 2023 14:09:42 -0700 Subject: [PATCH] implement box select from the UI --- plugins/burrow.cpp | 62 +++++++++++++++++++++++++++++++++++------- plugins/lua/burrow.lua | 22 +++++++-------- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/plugins/burrow.cpp b/plugins/burrow.cpp index 4a6d8ee8b..33b7cb719 100644 --- a/plugins/burrow.cpp +++ b/plugins/burrow.cpp @@ -182,12 +182,41 @@ static void do_cycle(color_ostream &out) // Lua API // -static void get_opts(lua_State *L, int idx, bool &dry_run, bool &cur_zlevel) { - // TODO +static void get_bool_field(lua_State *L, int idx, const char *name, bool *dest) { + lua_getfield(L, idx, name); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + return; + } + *dest = lua_toboolean(L, -1); + lua_pop(L, 1); } -static void get_bounds(lua_State *L, int idx, df::coord &pos1, df::coord &pos2) { - // TODO +static void get_opts(lua_State *L, int idx, bool &dry_run, bool &zlevel) { + if (lua_gettop(L) < idx) + return; + get_bool_field(L, idx, "dry_run", &dry_run); + get_bool_field(L, idx, "zlevel", &zlevel); +} + +static bool get_int_field(lua_State *L, int idx, const char *name, int16_t *dest) { + lua_getfield(L, idx, name); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + return false; + } + *dest = lua_tointeger(L, -1); + lua_pop(L, 1); + return true; +} + +static bool get_bounds(lua_State *L, int idx, df::coord &pos1, df::coord &pos2) { + return get_int_field(L, idx, "x1", &pos1.x) && + get_int_field(L, idx, "y1", &pos1.y) && + get_int_field(L, idx, "z1", &pos1.z) && + get_int_field(L, idx, "x2", &pos2.x) && + get_int_field(L, idx, "y2", &pos2.y) && + get_int_field(L, idx, "z2", &pos2.z); } static int burrow_tiles_clear(lua_State *L) { @@ -195,6 +224,7 @@ static int burrow_tiles_clear(lua_State *L) { if (!out) out = &Core::getInstance().getConsole(); DEBUG(status,*out).print("entering burrow_tiles_clear\n"); + // TODO return 0; } @@ -203,6 +233,7 @@ static int burrow_tiles_set(lua_State *L) { if (!out) out = &Core::getInstance().getConsole(); DEBUG(status,*out).print("entering burrow_tiles_set\n"); + // TODO return 0; } @@ -211,6 +242,7 @@ static int burrow_tiles_add(lua_State *L) { if (!out) out = &Core::getInstance().getConsole(); DEBUG(status,*out).print("entering burrow_tiles_add\n"); + // TODO return 0; } @@ -219,12 +251,13 @@ static int burrow_tiles_remove(lua_State *L) { if (!out) out = &Core::getInstance().getConsole(); DEBUG(status,*out).print("entering burrow_tiles_remove\n"); + // TODO return 0; } static int box_fill(lua_State *L, bool enable) { df::coord pos_start, pos_end; - bool dry_run = false, cur_zlevel = false; + bool dry_run = false, zlevel = false; df::burrow *burrow = NULL; if (lua_isuserdata(L, 1)) @@ -239,10 +272,13 @@ static int box_fill(lua_State *L, bool enable) { return 0; } - get_bounds(L, 2, pos_start, pos_end); - get_opts(L, 3, dry_run, cur_zlevel); + if (!get_bounds(L, 2, pos_start, pos_end)) { + luaL_argerror(L, 2, "invalid box bounds"); + return 0; + } + get_opts(L, 3, dry_run, zlevel); - if (cur_zlevel) { + if (zlevel) { pos_start.z = *window_z; pos_end.z = *window_z; } @@ -252,10 +288,10 @@ static int box_fill(lua_State *L, bool enable) { for (int32_t y = pos_start.y; y <= pos_end.y; ++y) { for (int32_t x = pos_start.x; x <= pos_end.x; ++x) { df::coord pos(x, y, z); - if (!Burrows::isAssignedTile(burrow, pos)) + if (enable != Burrows::isAssignedTile(burrow, pos)) ++count; if (!dry_run) - Burrows::setAssignedTile(burrow, pos, true); + Burrows::setAssignedTile(burrow, pos, enable); } } } @@ -285,6 +321,7 @@ static int burrow_tiles_flood_add(lua_State *L) { if (!out) out = &Core::getInstance().getConsole(); DEBUG(status,*out).print("entering burrow_tiles_flood_add\n"); + // TODO return 0; } @@ -293,6 +330,7 @@ static int burrow_tiles_flood_remove(lua_State *L) { if (!out) out = &Core::getInstance().getConsole(); DEBUG(status,*out).print("entering burrow_tiles_flood_remove\n"); + // TODO return 0; } @@ -301,6 +339,7 @@ static int burrow_units_clear(lua_State *L) { if (!out) out = &Core::getInstance().getConsole(); DEBUG(status,*out).print("entering burrow_units_clear\n"); + // TODO return 0; } @@ -309,6 +348,7 @@ static int burrow_units_set(lua_State *L) { if (!out) out = &Core::getInstance().getConsole(); DEBUG(status,*out).print("entering burrow_units_set\n"); + // TODO return 0; } @@ -317,6 +357,7 @@ static int burrow_units_add(lua_State *L) { if (!out) out = &Core::getInstance().getConsole(); DEBUG(status,*out).print("entering burrow_units_add\n"); + // TODO return 0; } @@ -325,6 +366,7 @@ static int burrow_units_remove(lua_State *L) { if (!out) out = &Core::getInstance().getConsole(); DEBUG(status,*out).print("entering burrow_units_remove\n"); + // TODO return 0; } diff --git a/plugins/lua/burrow.lua b/plugins/lua/burrow.lua index 536372fae..2668cc5e7 100644 --- a/plugins/lua/burrow.lua +++ b/plugins/lua/burrow.lua @@ -87,14 +87,15 @@ function BurrowDesignationOverlay:init() subviews={ widgets.Label{ frame={t=0, l=1}, - text='Double-click to fill.', + text='Double-click to fill. Shift double-click to 3D fill.', auto_width=true, + visible=function() return not is_choosing_area() end, }, widgets.Label{ - frame={t=0, l=25}, + frame={t=0, l=1}, text_pen=COLOR_DARKGREY, text={ - 'Selected area: ', + '3D box select enabled: ', {text=function() return ('%dx%dx%d'):format(get_cur_area_dims()) end}, }, visible=is_choosing_area, @@ -104,23 +105,22 @@ function BurrowDesignationOverlay:init() } end -local function flood_fill(pos, erasing, painting_burrow) +local function flood_fill(pos, erasing, do_3d, painting_burrow) + local opts = {zlevel=not do_3d} if erasing then - burrow_tiles_flood_remove(painting_burrow, pos) + burrow_tiles_flood_remove(painting_burrow, pos, opts) else - burrow_tiles_flood_add(painting_burrow, pos) + burrow_tiles_flood_add(painting_burrow, pos, opts) end reset_selection_rect() end local function box_fill(bounds, erasing, painting_burrow) if bounds.z1 == bounds.z2 then return end - local pos1 = xyz2pos(bounds.x1, bounds.y1, bounds.z1) - local pos2 = xyz2pos(bounds.x2, bounds.y2, bounds.z2) if erasing then - burrow_tiles_box_remove(painting_burrow, pos1, pos2) + burrow_tiles_box_remove(painting_burrow, bounds) else - burrow_tiles_box_add(painting_burrow, pos1, pos2) + burrow_tiles_box_add(painting_burrow, bounds) end end @@ -140,7 +140,7 @@ function BurrowDesignationOverlay:onInput(keys) else if now_ms - self.last_click_ms <= widgets.DOUBLE_CLICK_MS then self.last_click_ms = 0 - self.pending_fn = curry(flood_fill, pos, if_burrow.erasing) + self.pending_fn = curry(flood_fill, pos, if_burrow.erasing, dfhack.internal.getModifiers().shift) return else self.last_click_ms = now_ms