load overlay widget configuration

develop
myk002 2022-10-31 13:32:45 -07:00
parent bd318b7a21
commit a76c04c9ec
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
1 changed files with 88 additions and 0 deletions

@ -1,17 +1,105 @@
local _ENV = mkmodule('plugins.overlay')
local json = require('json')
local utils = require('utils')
local widgets = require('gui.widgets')
local WIDGETS_ENABLED_FILE = 'dfhack-config/overlay/widgets.json'
local WIDGETS_STATE_DIR = 'dfhack-config/overlay/widgets/'
local widget_db = {} -- map of widget name to state
local active_hotspot_widgets = {} -- map of widget names to the db entry
local active_viewscreen_widgets = {} -- map of vs_name to map of w.names -> db
local active_triggered_screen = nil
local function instantiate_widget(name, config)
local provider = config.provider
local ok, provider_env = pcall(require, provider)
if not ok then
ok, provider_env = pcall(require, 'plugins.'..provider)
end
if not ok then
ok, provider_env = pcall(reqscript, provider)
end
if not ok then
dfhack.printerr(
('error loading overlay widget "%s": could not find provider' ..
' environment "%s"')
:format(name, provider))
return nil
end
local classname = config.class
if not provider_env[classname] then
dfhack.printerr(
('error loading overlay widget "%s": could not find class "%s"')
:format(name, classname))
return nil
end
local frame = {}
local pos = utils.assign({x=-1, y=20}, config.pos or {})
if pos.x < 0 then frame.r = math.abs(pos.x) - 1 else frame.l = pos.x - 1 end
if pos.y < 0 then frame.b = math.abs(pos.y) - 1 else frame.t = pos.y - 1 end
return provider_env[classname]{frame=frame}
end
local function normalize_list(element_or_list)
if type(element_or_list) == 'table' then return element_or_list end
return {element_or_list}
end
-- allow "short form" to be specified, but use "long form"
local function normalize_viewscreen_name(vs_name)
if vs_name:match('viewscreen_.*st') then return vs_name end
return 'viewscreen_' .. vs_name .. 'st'
end
local function load_widget(name, config, enabled)
local widget = instantiate_widget(name, config)
if not widget then return end
local db_entry = {
widget=widget,
next_update_ms=widget.overlay_onupdate and 0 or math.huge,
}
widget_db[name] = db_entry
if not enabled then return end
if config.hotspot then
active_hotspot_widgets[name] = db_entry
end
for vs_name in ipairs(normalize_list(config.viewscreens)) do
vs_name = normalize_viewscreen_name(vs_name)
ensure_key(active_viewscreen_widgets, vs_name)[name] = db_entry
end
end
local function load_config(fname)
local ok, config = pcall(json.decode_file, fname)
return ok and config or {}
end
function reload()
widget_db = {}
active_hotspot_widgets = {}
active_viewscreen_widgets = {}
active_triggered_screen = nil
local enabled_map = load_config(WIDGETS_ENABLED_FILE)
for _,fname in ipairs(dfhack.filesystem.listdir(WIDGETS_STATE_DIR)) do
local _,_,name = fname:find('^(.*)%.json$')
if not name then goto continue end
local widget_config = load_config(WIDGETS_STATE_DIR..fname)
if not widget_config.provider or not widget_config.class then
dfhack.printerr(
('error loading overlay widget "%s": "provider" and' ..
' "class" must be specified in %s%s')
:format(name, WIDGETS_STATE_DIR, fname))
goto continue
end
load_widget(name, widget_config, not not enabled_map[name])
::continue::
end
end
-- reduces the next call by a small random amount to introduce jitter into the