Merge pull request #3761 from myk002/myk_asciismooth

[dig] add ASCII-mode highlight for smoothing and carving designations
develop
Myk 2023-09-10 13:24:44 -07:00 committed by GitHub
commit 0098b9f916
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 180 additions and 9 deletions

@ -54,6 +54,7 @@ Template for new versions:
## New Tools ## New Tools
## New Features ## New Features
- `dig`: new overlay for ASCII mode that visualizes designations for smoothing, engraving, carving tracks, and carving fortifications
## Fixes ## Fixes
- `buildingplan`: make the construction dimensions readout visible again - `buildingplan`: make the construction dimensions readout visible again

@ -183,8 +183,19 @@ After you have a pattern set, you can use ``expdig`` to apply it again.
Overlay Overlay
------- -------
This tool also provides an overlay that is managed by the `overlay` framework. This tool also provides two overlays that are managed by the `overlay`
When the ``dig.asciiwarmdamp`` overlay is enabled and you are in non-graphics framework. Both have no effect when in graphics mode, but when in ASCII mode,
(ASCII) mode, warm tiles will be highlighted in red and damp tiles will be they display useful highlights that are otherwise missing from the ASCII mode
highlighted in blue. Box selection characters and the keyboard cursor will also 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. 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.

@ -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_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); 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); 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); 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); return getTileOccupancy(pos.x, pos.y, pos.z);
} }

@ -20,10 +20,30 @@ WarmDampOverlay.ATTRS{
overlay_only=true, overlay_only=true,
} }
function WarmDampOverlay:onRenderFrame(dc) function WarmDampOverlay:onRenderFrame()
pathable.paintScreenWarmDamp() pathable.paintScreenWarmDamp()
end 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 return _ENV

@ -1,4 +1,5 @@
#include "Debug.h" #include "Debug.h"
#include "MemAccess.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "TileTypes.h" #include "TileTypes.h"
@ -10,6 +11,7 @@
#include "df/init.h" #include "df/init.h"
#include "df/map_block.h" #include "df/map_block.h"
#include "df/tile_designation.h" #include "df/tile_designation.h"
#include "df/block_square_event_designation_priorityst.h"
#include <functional> #include <functional>
@ -209,8 +211,145 @@ 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 char get_track_char(const df::coord &pos) {
auto occ = Maps::getTileOccupancy(pos);
if (occ->bits.carve_track_east && occ->bits.carve_track_north && occ->bits.carve_track_south && occ->bits.carve_track_west)
return (char)0xCE; // NSEW
if (occ->bits.carve_track_east && occ->bits.carve_track_north && occ->bits.carve_track_south)
return (char)0xCC; // NSE
if (occ->bits.carve_track_east && occ->bits.carve_track_north && occ->bits.carve_track_west)
return (char)0xCA; // NEW
if (occ->bits.carve_track_east && occ->bits.carve_track_south && occ->bits.carve_track_west)
return (char)0xCB; // SEW
if (occ->bits.carve_track_north && occ->bits.carve_track_south && occ->bits.carve_track_west)
return (char)0xB9; // NSW
if (occ->bits.carve_track_north && occ->bits.carve_track_south)
return (char)0xBA; // NS
if (occ->bits.carve_track_east && occ->bits.carve_track_west)
return (char)0xCD; // EW
if (occ->bits.carve_track_east && occ->bits.carve_track_north)
return (char)0xC8; // NE
if (occ->bits.carve_track_north && occ->bits.carve_track_west)
return (char)0xBC; // NW
if (occ->bits.carve_track_east && occ->bits.carve_track_south)
return (char)0xC9; // SE
if (occ->bits.carve_track_south && occ->bits.carve_track_west)
return (char)0xBB; // SW
if (occ->bits.carve_track_north)
return (char)0xD0; // N
if (occ->bits.carve_track_south)
return (char)0xD2; // S
if (occ->bits.carve_track_east)
return (char)0xC6; // E
if (occ->bits.carve_track_west)
return (char)0xB5; // W
return (char)0xC5; // single line cross; should never happen
}
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 char get_tile_char(const df::coord &pos, char desig_char, bool draw_priority) {
if (!draw_priority)
return desig_char;
std::vector<df::block_square_event_designation_priorityst *> priorities;
Maps::SortBlockEvents(Maps::getTileBlock(pos), NULL, NULL, NULL, NULL, NULL, NULL, NULL, &priorities);
if (priorities.empty())
return desig_char;
switch (priorities[0]->priority[pos.x % 16][pos.y % 16] / 1000) {
case 1: return '1';
case 2: return '2';
case 3: return '3';
case 4: return '4';
case 5: return '5';
case 6: return '6';
case 7: return '7';
default:
return '4';
}
}
static void paintScreenCarve() {
DEBUG(log).print("entering paintScreenCarve\n");
if (Screen::inGraphicsMode() || blink(500))
return;
bool draw_priority = blink(1000);
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 = get_tile_char(map_pos, (char)206, draw_priority); // hash, indicating a fortification designation
else
cur_tile.ch = get_tile_char(map_pos, (char)219, draw_priority); // solid block, indicating a smoothing designation
}
else if (is_designated_for_engraving(map_pos)) {
cur_tile.ch = get_tile_char(map_pos, (char)10, draw_priority); // solid block with a circle on it
}
else if (is_designated_for_track_carving(map_pos)) {
cur_tile.ch = get_tile_char(map_pos, get_track_char(map_pos), draw_priority); // directional track
}
else {
TRACE(log).print("skipping tile with no carving designation\n");
continue;
}
Screen::paintTile(cur_tile, x, y, true);
}
}
}
DFHACK_PLUGIN_LUA_FUNCTIONS { DFHACK_PLUGIN_LUA_FUNCTIONS {
DFHACK_LUA_FUNCTION(paintScreenPathable), DFHACK_LUA_FUNCTION(paintScreenPathable),
DFHACK_LUA_FUNCTION(paintScreenWarmDamp), DFHACK_LUA_FUNCTION(paintScreenWarmDamp),
DFHACK_LUA_FUNCTION(paintScreenCarve),
DFHACK_LUA_END DFHACK_LUA_END
}; };