support foreground and background writing from pens

develop
Myk Taylor 2023-01-11 18:23:16 -08:00
parent 3ed65aedbf
commit 079d5e4178
No known key found for this signature in database
7 changed files with 50 additions and 9 deletions

@ -49,6 +49,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## API ## API
- ``Gui::getDwarfmodeDims``: now only returns map viewport dimensions; menu dimensions are obsolete - ``Gui::getDwarfmodeDims``: now only returns map viewport dimensions; menu dimensions are obsolete
- ``Gui::getDFViewscreen``: returns the topmost underlying DF viewscreen - ``Gui::getDFViewscreen``: returns the topmost underlying DF viewscreen
- ``Screen::Pen``: now accepts ``keep_lower`` and ``write_to_lower`` properties to support foreground and background textures in graphics mode
## Lua ## Lua
- Removed ``os.execute()`` and ``io.popen()`` built-in functions - Removed ``os.execute()`` and ``io.popen()`` built-in functions
@ -58,10 +59,13 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- ``widgets.CycleHotkeyLabel``: now supports rendering option labels in the color of your choice - ``widgets.CycleHotkeyLabel``: now supports rendering option labels in the color of your choice
- ``widgets.CycleHotkeyLabel``: new functions ``setOption()`` and ``getOptionPen()`` - ``widgets.CycleHotkeyLabel``: new functions ``setOption()`` and ``getOptionPen()``
- ``widgets.ToggleHotkeyLabel``: now renders the ``On`` option in green text - ``widgets.ToggleHotkeyLabel``: now renders the ``On`` option in green text
- ``widgets.Label``: tiles can now have an associated width
- `overlay`: ``OverlayWidget`` now inherits from ``Panel`` instead of ``Widget`` to get all the frame and mouse integration goodies - `overlay`: ``OverlayWidget`` now inherits from ``Panel`` instead of ``Widget`` to get all the frame and mouse integration goodies
- ``dfhack.gui.getDFViewscreen()``: returns the topmost underlying DF viewscreen - ``dfhack.gui.getDFViewscreen()``: returns the topmost underlying DF viewscreen
- ``gui.ZScreen``: Screen subclass that implements window raising, multi-viewscreen input handling, and viewscreen event pass-through so the underlying map can be interacted with and dragged around while DFHack screens are visible - ``gui.ZScreen``: Screen subclass that implements window raising, multi-viewscreen input handling, and viewscreen event pass-through so the underlying map can be interacted with and dragged around while DFHack screens are visible
- ``gui.View``: new function ``view:getMouseFramePos()`` for detecting whether the mouse is within (or over) the exterior frame of a view - ``gui.View``: new function ``view:getMouseFramePos()`` for detecting whether the mouse is within (or over) the exterior frame of a view
- ``gui.CLEAR_PEN``: now clears the background and foreground and writes to the background (before it would always write to the foreground)
- ``gui.KEEP_LOWER_PEN``: a general use pen that writes associated tiles to the foreground while keeping the existing background
## Internals ## Internals

@ -2266,6 +2266,12 @@ a table with the following possible fields:
Specifies that the tile should be shaded with *fg/bg*. Specifies that the tile should be shaded with *fg/bg*.
``tile_fg, tile_bg`` ``tile_fg, tile_bg``
If specified, overrides *tile_color* and supplies shading colors directly. If specified, overrides *tile_color* and supplies shading colors directly.
``keep_lower``
If set to true, will not overwrite the background tile when filling in
the foreground tile.
``write_to_lower``
If set to true, the specified ``tile`` will be written to the background
instead of the foreground.
Alternatively, it may be a pre-parsed native object with the following API: Alternatively, it may be a pre-parsed native object with the following API:
@ -3654,7 +3660,13 @@ Misc
* ``CLEAR_PEN`` * ``CLEAR_PEN``
The black pen used to clear the screen. The black pen used to clear the screen. In graphics mode, it will clear the
foreground and set the background to the standard black tile.
* ``KEEP_LOWER_PEN``
A pen that will write tiles over existing background tiles instead of clearing
them.
* ``simulateInput(screen, keys...)`` * ``simulateInput(screen, keys...)``
@ -4582,8 +4594,8 @@ containing newlines, or a table with the following possible fields:
* ``token.width = ...`` * ``token.width = ...``
If specified either as a value or a callback, the text field is padded If specified either as a value or a callback, the text (or tile) field is
or truncated to the specified number. padded or truncated to the specified number.
* ``token.pad_char = '?'`` * ``token.pad_char = '?'``

@ -177,6 +177,17 @@ static bool get_char_field(lua_State *L, char *pf, int idx, const char *name, ch
} }
} }
static bool get_bool_field(lua_State *L, bool *pf, int idx, const char *name, bool defval) {
lua_getfield(L, idx, name);
bool nil = lua_isnil(L, -1);
if (nil)
*pf = defval;
else
*pf = lua_toboolean(L, -1);
lua_pop(L, 1);
return !nil;
}
static void decode_pen(lua_State *L, Pen &pen, int idx) static void decode_pen(lua_State *L, Pen &pen, int idx)
{ {
idx = lua_absindex(L, idx); idx = lua_absindex(L, idx);
@ -208,6 +219,9 @@ static void decode_pen(lua_State *L, Pen &pen, int idx)
pen.tile_mode = (lua_toboolean(L, -1) ? Pen::CharColor : Pen::AsIs); pen.tile_mode = (lua_toboolean(L, -1) ? Pen::CharColor : Pen::AsIs);
lua_pop(L, 1); lua_pop(L, 1);
} }
get_bool_field(L, &pen.keep_lower, idx, "keep_lower", false);
get_bool_field(L, &pen.write_to_lower, idx, "write_to_lower", false);
} }
/************************************************** /**************************************************

@ -84,6 +84,9 @@ namespace DFHack
} tile_mode; } tile_mode;
int8_t tile_fg, tile_bg; int8_t tile_fg, tile_bg;
bool write_to_lower = false;
bool keep_lower = false;
bool valid() const { return tile >= 0; } bool valid() const { return tile >= 0; }
bool empty() const { return ch == 0 && tile == 0; } bool empty() const { return ch == 0 && tile == 0; }

@ -9,7 +9,8 @@ local getval = utils.getval
local to_pen = dfhack.pen.parse local to_pen = dfhack.pen.parse
CLEAR_PEN = to_pen{tile=909, ch=32, fg=0, bg=0} CLEAR_PEN = to_pen{tile=909, ch=32, fg=0, bg=0, write_to_lower=true}
KEEP_LOWER_PEN = to_pen{ch=32, fg=0, bg=0, keep_lower=true}
local FAKE_INPUT_KEYS = { local FAKE_INPUT_KEYS = {
_MOUSE_L = true, _MOUSE_L = true,

@ -688,7 +688,6 @@ function EditField:onRenderBody(dc)
end_pos == #txt and '' or string.char(26)) end_pos == #txt and '' or string.char(26))
end end
dc:advance(self.text_offset):string(txt) dc:advance(self.text_offset):string(txt)
dc:string((' '):rep(dc.clip_x2 - dc.x))
end end
function EditField:insert(text) function EditField:insert(text)
@ -1102,6 +1101,9 @@ function render_text(obj,dc,x0,y0,pen,dpen,disabled)
x = x + 1 x = x + 1
if dc then if dc then
dc:tile(nil, token.tile) dc:tile(nil, token.tile)
if token.width then
dc:advance(token.width-1)
end
end end
end end

@ -157,6 +157,7 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map)
*screen = 0; *screen = 0;
*texpos = 0; *texpos = 0;
if (!pen.keep_lower)
*texpos_lower = 0; *texpos_lower = 0;
gps->screentexpos_anchored[index] = 0; gps->screentexpos_anchored[index] = 0;
// keep SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE so occluded anchored textures // keep SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE so occluded anchored textures
@ -171,6 +172,7 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map)
*screen = 0; *screen = 0;
*texpos = 0; *texpos = 0;
if (!pen.keep_lower)
*texpos_lower = 0; *texpos_lower = 0;
gps->screentexpos_top_anchored[index] = 0; gps->screentexpos_top_anchored[index] = 0;
*flag &= 4; // keep SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE *flag &= 4; // keep SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE
@ -190,10 +192,13 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map)
} }
if (pen.tile && use_graphics) { if (pen.tile && use_graphics) {
if (pen.write_to_lower)
*texpos_lower = pen.tile;
else
*texpos = pen.tile; *texpos = pen.tile;
} else { } else {
screen[0] = uint8_t(pen.ch); screen[0] = uint8_t(pen.ch);
*texpos_lower = 909; *texpos_lower = 909; // basic black background
} }
auto rgb_fg = &gps->uccolor[fg][0]; auto rgb_fg = &gps->uccolor[fg][0];