Merge pull request #2591 from myk002/myk_penn

support foreground and background writing from pens
develop
Myk 2023-01-12 21:00:38 -08:00 committed by GitHub
commit 68e373100b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 60 additions and 14 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,17 @@ 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.
* ``TRANSPARENT_PEN``
A pen that will clear all textures from the UI layer, making the tile transparent.
* ``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 +4598,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,9 @@ 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}
TRANSPARENT_PEN = to_pen{tile=0, ch=0}
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,

@ -659,7 +659,7 @@ function EditField:postUpdateLayout()
end end
function EditField:onRenderBody(dc) function EditField:onRenderBody(dc)
dc:pen(self.text_pen or COLOR_LIGHTCYAN):fill(0,0,dc.width-1,0) dc:pen(self.text_pen or COLOR_LIGHTCYAN)
local cursor_char = '_' local cursor_char = '_'
if not getval(self.active) or not self.focus or gui.blink_visible(300) then if not getval(self.active) or not self.focus or gui.blink_visible(300) then
@ -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

@ -128,10 +128,10 @@ static bool doSetTile_map(const Pen &pen, int x, int y) {
return false; return false;
long texpos = pen.tile; long texpos = pen.tile;
if (texpos == 0) { if (!texpos && pen.ch)
texpos = init->font.large_font_texpos[(uint8_t)pen.ch]; texpos = init->font.large_font_texpos[(uint8_t)pen.ch];
} if (texpos)
vp->screentexpos_interface[index] = texpos; vp->screentexpos_interface[index] = texpos;
return true; return true;
} }
@ -157,7 +157,8 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map)
*screen = 0; *screen = 0;
*texpos = 0; *texpos = 0;
*texpos_lower = 0; if (!pen.keep_lower)
*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
// don't appear corrupted // don't appear corrupted
@ -171,7 +172,8 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map)
*screen = 0; *screen = 0;
*texpos = 0; *texpos = 0;
*texpos_lower = 0; if (!pen.keep_lower)
*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) {
*texpos = pen.tile; if (pen.write_to_lower)
} else { *texpos_lower = pen.tile;
else
*texpos = pen.tile;
} else if (pen.ch) {
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];