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
- ``Gui::getDwarfmodeDims``: now only returns map viewport dimensions; menu dimensions are obsolete
- ``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
- 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``: new functions ``setOption()`` and ``getOptionPen()``
- ``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
- ``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.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

@ -2266,6 +2266,12 @@ a table with the following possible fields:
Specifies that the tile should be shaded with *fg/bg*.
``tile_fg, tile_bg``
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:
@ -3654,7 +3660,17 @@ Misc
* ``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...)``
@ -4582,8 +4598,8 @@ containing newlines, or a table with the following possible fields:
* ``token.width = ...``
If specified either as a value or a callback, the text field is padded
or truncated to the specified number.
If specified either as a value or a callback, the text (or tile) field is
padded or truncated to the specified number.
* ``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)
{
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);
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;
int8_t tile_fg, tile_bg;
bool write_to_lower = false;
bool keep_lower = false;
bool valid() const { return tile >= 0; }
bool empty() const { return ch == 0 && tile == 0; }

@ -9,7 +9,9 @@ local getval = utils.getval
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 = {
_MOUSE_L = true,

@ -659,7 +659,7 @@ function EditField:postUpdateLayout()
end
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 = '_'
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
dc:advance(self.text_offset):string(txt)
dc:string((' '):rep(dc.clip_x2 - dc.x))
end
function EditField:insert(text)
@ -1102,6 +1101,9 @@ function render_text(obj,dc,x0,y0,pen,dpen,disabled)
x = x + 1
if dc then
dc:tile(nil, token.tile)
if token.width then
dc:advance(token.width-1)
end
end
end

@ -128,9 +128,9 @@ static bool doSetTile_map(const Pen &pen, int x, int y) {
return false;
long texpos = pen.tile;
if (texpos == 0) {
if (!texpos && pen.ch)
texpos = init->font.large_font_texpos[(uint8_t)pen.ch];
}
if (texpos)
vp->screentexpos_interface[index] = texpos;
return true;
}
@ -157,6 +157,7 @@ static bool doSetTile_default(const Pen &pen, int x, int y, bool map)
*screen = 0;
*texpos = 0;
if (!pen.keep_lower)
*texpos_lower = 0;
gps->screentexpos_anchored[index] = 0;
// 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;
*texpos = 0;
if (!pen.keep_lower)
*texpos_lower = 0;
gps->screentexpos_top_anchored[index] = 0;
*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.write_to_lower)
*texpos_lower = pen.tile;
else
*texpos = pen.tile;
} else {
} else if (pen.ch) {
screen[0] = uint8_t(pen.ch);
*texpos_lower = 909;
*texpos_lower = 909; // basic black background
}
auto rgb_fg = &gps->uccolor[fg][0];