From a0919ec316aa6fb5c11890d86873f252f0834c9e Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 10 Sep 2023 05:29:55 -0700 Subject: [PATCH] add ASCII-mode highlight for smoothing and carving designations --- docs/changelog.txt | 1 + docs/plugins/dig.rst | 19 ++++++-- library/include/modules/Maps.h | 6 +-- plugins/lua/dig.lua | 24 +++++++++- plugins/pathable.cpp | 80 ++++++++++++++++++++++++++++++++++ 5 files changed, 121 insertions(+), 9 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 0465609e9..3ac2e3c48 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -54,6 +54,7 @@ Template for new versions: ## New Tools ## New Features +- `dig`: new overlay for ASCII mode that visualizes designations for smoothing, engraving, carving tracks, and carving fortifications ## Fixes - `buildingplan`: make the construction dimensions readout visible again diff --git a/docs/plugins/dig.rst b/docs/plugins/dig.rst index 310bd1647..77b3137ae 100644 --- a/docs/plugins/dig.rst +++ b/docs/plugins/dig.rst @@ -183,8 +183,19 @@ After you have a pattern set, you can use ``expdig`` to apply it again. Overlay ------- -This tool also provides an overlay that is managed by the `overlay` framework. -When the ``dig.asciiwarmdamp`` overlay is enabled and you are in non-graphics -(ASCII) mode, warm tiles will be highlighted in red and damp tiles will be -highlighted in blue. Box selection characters and the keyboard cursor will also +This tool also provides two overlays that are managed by the `overlay` +framework. Both have no effect when in graphics mode, but when in ASCII mode, +they display useful highlights that are otherwise missing from the ASCII mode +interface. + +The ``dig.asciiwarmdamp`` overlay highlights warm tiles red and damp tiles in +blue. Box selection characters and the keyboard cursor will also change color as appropriate when over the warm or damp tile. + +The ``dig.asciicarve`` overlay highlights tiles that are designated for +smoothing, engraving, track carving, or fortification carving. The designations +blink so you can still see what is underneath them. + +Note that due to the limitations of the ASCII mode screen buffer, the +designation highlights may show through other interface elements that overlap +the designated area. diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index e468dcf9c..2b7d768d0 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -293,13 +293,13 @@ extern DFHACK_EXPORT df::tiletype *getTileType(int32_t x, int32_t y, int32_t z); extern DFHACK_EXPORT df::tile_designation *getTileDesignation(int32_t x, int32_t y, int32_t z); extern DFHACK_EXPORT df::tile_occupancy *getTileOccupancy(int32_t x, int32_t y, int32_t z); -inline df::tiletype *getTileType(df::coord pos) { +inline df::tiletype *getTileType(const df::coord &pos) { return getTileType(pos.x, pos.y, pos.z); } -inline df::tile_designation *getTileDesignation(df::coord pos) { +inline df::tile_designation *getTileDesignation(const df::coord &pos) { return getTileDesignation(pos.x, pos.y, pos.z); } -inline df::tile_occupancy *getTileOccupancy(df::coord pos) { +inline df::tile_occupancy *getTileOccupancy(const df::coord &pos) { return getTileOccupancy(pos.x, pos.y, pos.z); } diff --git a/plugins/lua/dig.lua b/plugins/lua/dig.lua index 43012d5d2..e24885c08 100644 --- a/plugins/lua/dig.lua +++ b/plugins/lua/dig.lua @@ -20,10 +20,30 @@ WarmDampOverlay.ATTRS{ overlay_only=true, } -function WarmDampOverlay:onRenderFrame(dc) +function WarmDampOverlay:onRenderFrame() pathable.paintScreenWarmDamp() end -OVERLAY_WIDGETS = {asciiwarmdamp=WarmDampOverlay} +CarveOverlay = defclass(CarveOverlay, overlay.OverlayWidget) +CarveOverlay.ATTRS{ + viewscreens={ + 'dwarfmode/Designate/SMOOTH', + 'dwarfmode/Designate/ENGRAVE', + 'dwarfmode/Designate/TRACK', + 'dwarfmode/Designate/FORTIFY', + 'dwarfmode/Designate/ERASE', + }, + default_enabled=true, + overlay_only=true, +} + +function CarveOverlay:onRenderFrame() + pathable.paintScreenCarve() +end + +OVERLAY_WIDGETS = { + asciiwarmdamp=WarmDampOverlay, + asciicarve=CarveOverlay, +} return _ENV diff --git a/plugins/pathable.cpp b/plugins/pathable.cpp index 12a69dd31..83918fd4b 100644 --- a/plugins/pathable.cpp +++ b/plugins/pathable.cpp @@ -1,4 +1,5 @@ #include "Debug.h" +#include "MemAccess.h" #include "PluginManager.h" #include "TileTypes.h" @@ -209,8 +210,87 @@ static void paintScreenWarmDamp(bool show_hidden = false) { } } +static bool is_designated_for_smoothing(const df::coord &pos) { + auto des = Maps::getTileDesignation(pos); + if (!des) + return false; + return des->bits.smooth == 1; +} + +static bool is_designated_for_engraving(const df::coord &pos) { + auto des = Maps::getTileDesignation(pos); + if (!des) + return false; + return des->bits.smooth == 2; +} + +static bool is_designated_for_track_carving(const df::coord &pos) { + auto occ = Maps::getTileOccupancy(pos); + if (!occ) + return false; + return occ->bits.carve_track_east || occ->bits.carve_track_north || occ->bits.carve_track_south || occ->bits.carve_track_west; +} + +static bool is_smooth_wall(const df::coord &pos) { + df::tiletype *tt = Maps::getTileType(pos); + return tt && tileSpecial(*tt) == df::tiletype_special::SMOOTH + && tileShape(*tt) == df::tiletype_shape::WALL; +} + +static bool blink(int delay) { + return (Core::getInstance().p->getTickCount()/delay) % 2 == 0; +} + +static void paintScreenCarve() { + DEBUG(log).print("entering paintScreenCarve\n"); + + if (Screen::inGraphicsMode() || blink(500)) + return; + + auto dims = Gui::getDwarfmodeViewDims().map(); + for (int y = dims.first.y; y <= dims.second.y; ++y) { + for (int x = dims.first.x; x <= dims.second.x; ++x) { + df::coord map_pos(*window_x + x, *window_y + y, *window_z); + + if (!Maps::isValidTilePos(map_pos)) + continue; + + if (!Maps::isTileVisible(map_pos)) { + TRACE(log).print("skipping hidden tile\n"); + continue; + } + + TRACE(log).print("scanning map tile at (%d, %d, %d) screen offset (%d, %d)\n", + map_pos.x, map_pos.y, map_pos.z, x, y); + + Screen::Pen cur_tile; + cur_tile.fg = COLOR_DARKGREY; + + if (is_designated_for_smoothing(map_pos)) { + if (is_smooth_wall(map_pos)) + cur_tile.ch = 206; // hash, indicating a fortification designation + else + cur_tile.ch = 219; // solid block, indicating a smoothing designation + } + else if (is_designated_for_engraving(map_pos)) { + cur_tile.ch = 10; // solid block with a circle on it + } + else if (is_designated_for_track_carving(map_pos)) { + cur_tile.ch = 186; // parallel tracks + } + else { + TRACE(log).print("skipping tile with no carving designation\n"); + continue; + } + + Screen::paintTile(cur_tile, x, y, true); + } + } +} + DFHACK_PLUGIN_LUA_FUNCTIONS { DFHACK_LUA_FUNCTION(paintScreenPathable), DFHACK_LUA_FUNCTION(paintScreenWarmDamp), + DFHACK_LUA_FUNCTION(paintScreenCarve), DFHACK_LUA_END };