Skip to content

Commit

Permalink
Add a script that implements a linked mechanism browser.
Browse files Browse the repository at this point in the history
  • Loading branch information
angavrilov committed Aug 20, 2012
1 parent 38a07a4 commit 601a3a7
Show file tree
Hide file tree
Showing 5 changed files with 350 additions and 3 deletions.
3 changes: 3 additions & 0 deletions dfhack.init-example
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ keybinding add Shift-I "job-material CINNABAR"
keybinding add Shift-B "job-material COBALTITE"
keybinding add Shift-O "job-material OBSIDIAN"
keybinding add Shift-G "job-material GLASS_GREEN"

# browse linked mechanisms
keybinding add Ctrl-M@dwarfmode/QueryBuilding/Some gui/mechanisms
23 changes: 23 additions & 0 deletions library/LuaApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1180,6 +1180,28 @@ static int screen_isDismissed(lua_State *L)
return 1;
}

static int screen_doSimulateInput(lua_State *L)
{
auto screen = Lua::CheckDFObject<df::viewscreen>(L, 1);
luaL_checktype(L, 2, LUA_TTABLE);

if (!screen)
luaL_argerror(L, 1, "NULL screen");

int sz = lua_rawlen(L, 2);
std::set<df::interface_key> keys;

for (int j = 1; j <= sz; j++)
{
lua_rawgeti(L, 2, j);
keys.insert((df::interface_key)lua_tointeger(L, -1));
lua_pop(L, 1);
}

screen->feed(&keys);
return 0;
}

}

static const luaL_Reg dfhack_screen_funcs[] = {
Expand All @@ -1192,6 +1214,7 @@ static const luaL_Reg dfhack_screen_funcs[] = {
{ "show", &Lua::CallWithCatchWrapper<screen_show> },
{ "dismiss", screen_dismiss },
{ "isDismissed", screen_isDismissed },
{ "_doSimulateInput", screen_doSimulateInput },
{ NULL, NULL }
};

Expand Down
65 changes: 62 additions & 3 deletions library/lua/gui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,42 @@ local _ENV = mkmodule('gui')

local dscreen = dfhack.screen

CLEAR_PEN = {ch=32,fg=0,bg=0}

function simulateInput(screen,...)
local keys = {}
local function push_key(arg)
local kv = arg
if type(arg) == 'string' then
kv = df.interface_key[arg]
if kv == nil then
error('Invalid keycode: '..arg)
end
end
if type(arg) == 'number' then
keys[#keys+1] = kv
end
end
for i = 1,select('#',...) do
local arg = select(i,...)
if arg ~= nil then
local t = type(arg)
if type(arg) == 'table' then
for k,v in pairs(arg) do
if v == true then
push_key(k)
else
push_key(v)
end
end
else
push_key(arg)
end
end
end
dscreen._doSimulateInput(screen, keys)
end

Screen = defclass(Screen, dfhack.screen)

function Screen.new(attrs)
Expand All @@ -26,6 +62,12 @@ function Screen:renderParent()
end
end

function Screen:inputToParent(...)
if self._native and self._native.parent then
simulateInput(self._native.parent, ...)
end
end

function paint_border(x1,y1,x2,y2,color,title)
local pen = { ch = ' ', fg = COLOR_BLACK, bg = color }
dscreen.fillRect(pen,x1,y1,x2,y1)
Expand All @@ -40,20 +82,37 @@ function paint_border(x1,y1,x2,y2,color,title)
end
end

function Screen:renderFrame(color,title,width,height)
local function hint_coord(gap,hint)
if hint and hint > 0 then
return math.min(hint,gap)
elseif hint and hint < 0 then
return math.max(0,gap-hint)
else
return math.floor(gap/2)
end
end

function mkdims_xy(x1,y1,x2,y2)
return { x1=x1, y1=y1, x2=x2, y2=y2, width=x2-x1+1, height=y2-y1+1 }
end
function mkdims_wh(x1,y1,w,h)
return { x1=x1, y1=y1, x2=x1+w-1, y2=y1+h-1, width=w, height=h }
end

function Screen:renderFrame(color,title,width,height,xhint,yhint)
local sw, sh = dscreen.getWindowSize()
local iw, ih = sw-2, sh-2
width = math.min(width or iw, iw)
height = math.min(height or ih, ih)
local gw, gh = iw-width, ih-height
local x1, y1 = math.floor(gw/2), math.floor(gh/2)
local x1, y1 = hint_coord(gw,xhint), hint_coord(gh,yhint)
local x2, y2 = x1+width+1, y1+height+1

if gw == 0 and gh == 0 then
dscreen.clear()
else
self:renderParent()
dscreen.fillRect({ch=' ',fg=0,bg=0},x1,y1,x2,y2)
dscreen.fillRect(CLEAR_PEN,x1,y1,x2,y2)
end

paint_border(x1,y1,x2,y2,color,title)
Expand Down
119 changes: 119 additions & 0 deletions library/lua/gui/dwarfmode.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
-- Support for messing with the dwarfmode screen

local _ENV = mkmodule('gui.dwarfmode')

local gui = require('gui')
local dscreen = dfhack.screen

AREA_MAP_WIDTH = 23
MENU_WIDTH = 30

function getPanelLayout()
local sw, sh = dscreen.getWindowSize()
local view_height = sh-2
local view_rb = sw-1
local area_x2 = sw-AREA_MAP_WIDTH-2
local menu_x2 = sw-MENU_WIDTH-2
local menu_x1 = area_x2-MENU_WIDTH-1
local area_pos = df.global.ui_area_map_width
local menu_pos = df.global.ui_menu_width
local rv = {}

if area_pos < 3 then
rv.area_map = gui.mkdims_xy(area_x2+1,1,view_rb-1,view_height)
view_rb = area_x2
end
if menu_pos < area_pos or df.global.ui.main.mode ~= 0 then
if menu_pos >= area_pos then
rv.menu_forced = true
menu_pos = area_pos-1
end
local menu_x = menu_x2
if menu_pos < 2 then menu_x = menu_x1 end
rv.menu = gui.mkdims_xy(menu_x+1,1,view_rb-1,view_height)
view_rb = menu_x
end
rv.area_pos = area_pos
rv.menu_pos = menu_pos
rv.map = gui.mkdims_xy(1,1,view_rb-1,view_height)
return rv
end

function getViewportPos()
return {
x = df.global.window_x,
y = df.global.window_y,
z = df.global.window_z
}
end

function getCursorPos()
return copyall(df.global.cursor)
end

function setCursorPos(cursor)
df.global.cursor = cursor
end

function setViewportPos(layout,view)
local map = df.global.world.map
df.global.window_x = math.max(0, math.min(view.x, map.x_count-layout.map.width))
df.global.window_y = math.max(0, math.min(view.y, map.y_count-layout.map.height))
df.global.window_z = math.max(0, math.min(view.z, map.z_count-1))
return getViewportPos()
end

function centerViewportOn(layout,target)
local mapsz = layout.map
local view = xyz2pos(
target.x-math.floor(layout.map.width/2),
target.y-math.floor(layout.map.height/2),
target.z
)
return setViewportPos(layout, view)
end

function isInViewport(layout,view,target,gap)
gap = gap or 0
return target.x-gap >= view.x and target.x+gap < view.x+layout.map.width
and target.y-gap >= view.y and target.y+gap < view.y+layout.map.height
and target.z == view.z
end

DwarfOverlay = defclass(DwarfOverlay, gui.Screen)

function DwarfOverlay:updateLayout()
self.df_layout = getPanelLayout()
self.df_viewport = getViewportPos()
self.df_cursor = getCursorPos()
end

local move_keys = {
'CURSOR_UP', 'CURSOR_DOWN', 'CURSOR_LEFT', 'CURSOR_RIGHT',
'CURSOR_UPLEFT', 'CURSOR_UPRIGHT', 'CURSOR_DOWNLEFT', 'CURSOR_DOWNRIGHT',
'CURSOR_UP_FAST', 'CURSOR_DOWN_FAST', 'CURSOR_LEFT_FAST', 'CURSOR_RIGHT_FAST',
'CURSOR_UPLEFT_FAST', 'CURSOR_UPRIGHT_FAST', 'CURSOR_DOWNLEFT_FAST', 'CURSOR_DOWNRIGHT_FAST',
'CURSOR_UP_Z', 'CURSOR_DOWN_Z', 'CURSOR_UP_Z_AUX', 'CURSOR_DOWN_Z_AUX'
}

function DwarfOverlay:propagateMoveKeys(keys)
for _,v in ipairs(move_keys) do
if keys[v] then
self:inputToParent(v)
return
end
end
end

function DwarfOverlay:onIdle()
dscreen.invalidate()
end

function DwarfOverlay:clearMenu()
local menu = self.df_layout.menu
if not menu then return nil end
dscreen.fillRect(gui.CLEAR_PEN,menu.x1,menu.y1,menu.x2,menu.y2)
return menu.x1,menu.y1,menu.width,menu.height
end

return _ENV
Loading

0 comments on commit 601a3a7

Please sign in to comment.