Reimplement dwarfmonitor widgets in Lua (and improve customizability)
Widget positions and a few other options (e.g. date formats) can be specified in dfhack-config/dwarfmonitor.json on a per-instance basis. Related changes: * Fixed an issue loading JSON files from Lua * JSON files in dfhack-config (only dwarfmonitor.json currently) are no longer copied into the DF directory when building DFHack. This keeps developers' personal settings intact, but will require copying over changes made to DFHack's copies manually. * Fixed incorrect config path in dwarfmonitor helpdevelop
parent
06cf6530fc
commit
93c9a41a3a
@ -1,3 +1,21 @@
|
||||
{
|
||||
"date_format": "y-m-d"
|
||||
"widgets": [
|
||||
{
|
||||
"type": "weather",
|
||||
"x": 1,
|
||||
"y": -1
|
||||
},
|
||||
{
|
||||
"type": "date",
|
||||
"x": -30,
|
||||
"y": 0,
|
||||
"format": "Y-M-D"
|
||||
},
|
||||
{
|
||||
"type": "misery",
|
||||
"x": -2,
|
||||
"y": -1,
|
||||
"anchor": "right"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -0,0 +1,157 @@
|
||||
local _ENV = mkmodule('plugins.dwarfmonitor')
|
||||
|
||||
local gps = df.global.gps
|
||||
local gui = require 'gui'
|
||||
|
||||
config = {}
|
||||
widgets = {}
|
||||
|
||||
function dmerror(desc)
|
||||
qerror('dwarfmonitor: ' .. tostring(desc))
|
||||
end
|
||||
|
||||
Widget = defclass(Widget)
|
||||
function Widget:init(opts)
|
||||
self.opts = opts
|
||||
end
|
||||
function Widget:get_pos()
|
||||
local x = self.opts.x >= 0 and self.opts.x or gps.dimx + self.opts.x
|
||||
local y = self.opts.y >= 0 and self.opts.y or gps.dimy + self.opts.y
|
||||
if self.opts.anchor == 'right' then
|
||||
x = x - (self:get_width() or 0) + 1
|
||||
end
|
||||
return x, y
|
||||
end
|
||||
function Widget:render()
|
||||
if not monitor_state(self.opts.type) then
|
||||
return
|
||||
end
|
||||
self:update()
|
||||
local x, y = self:get_pos()
|
||||
local p = gui.Painter.new_xy(x, y, gps.dimx - 1, y)
|
||||
self:render_body(p)
|
||||
end
|
||||
function Widget:update() end
|
||||
function Widget:get_width() end
|
||||
function Widget:render_body() end
|
||||
|
||||
Widget_weather = defclass(Widget_weather, Widget)
|
||||
|
||||
function Widget_weather:update()
|
||||
self.counts = get_weather_counts()
|
||||
end
|
||||
|
||||
function Widget_weather:get_width()
|
||||
if self.counts.rain > 0 then
|
||||
if self.counts.snow > 0 then
|
||||
return 9
|
||||
end
|
||||
return 4
|
||||
elseif self.counts.snow > 0 then
|
||||
return 4
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function Widget_weather:render_body(p)
|
||||
if self.counts.rain > 0 then
|
||||
p:string('Rain', COLOR_LIGHTBLUE):advance(1)
|
||||
end
|
||||
if self.counts.snow > 0 then
|
||||
p:string('Snow', COLOR_WHITE)
|
||||
end
|
||||
end
|
||||
|
||||
Widget_date = defclass(Widget_date, Widget)
|
||||
Widget_date.ATTRS = {
|
||||
output = ''
|
||||
}
|
||||
|
||||
function Widget_date:update()
|
||||
if not self.opts.format then
|
||||
self.opts.format = 'Y-M-D'
|
||||
end
|
||||
local year = dfhack.world.ReadCurrentYear()
|
||||
local month = dfhack.world.ReadCurrentMonth() + 1
|
||||
local day = dfhack.world.ReadCurrentDay()
|
||||
self.output = 'Date:'
|
||||
for i = 1, #self.opts.format do
|
||||
local c = self.opts.format:sub(i, i)
|
||||
if c == 'y' or c == 'Y' then
|
||||
self.output = self.output .. year
|
||||
elseif c == 'm' or c == 'M' then
|
||||
if c == 'M' and month < 10 then
|
||||
self.output = self.output .. '0'
|
||||
end
|
||||
self.output = self.output .. month
|
||||
elseif c == 'd' or c == 'D' then
|
||||
if c == 'D' and day < 10 then
|
||||
self.output = self.output .. '0'
|
||||
end
|
||||
self.output = self.output .. day
|
||||
else
|
||||
self.output = self.output .. c
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Widget_date:get_width()
|
||||
return #self.output
|
||||
end
|
||||
|
||||
function Widget_date:render_body(p)
|
||||
p:string(self.output, COLOR_GREY)
|
||||
end
|
||||
|
||||
Widget_misery = defclass(Widget_misery, Widget)
|
||||
|
||||
function Widget_misery:update()
|
||||
self.data = get_misery_data()
|
||||
end
|
||||
|
||||
function Widget_misery:get_width()
|
||||
local w = 2 + 6
|
||||
for k, v in pairs(self.data) do
|
||||
w = w + #tostring(v.value)
|
||||
end
|
||||
return w
|
||||
end
|
||||
|
||||
function Widget_misery:render_body(p)
|
||||
p:string("H:", COLOR_WHITE)
|
||||
for i = 0, 6 do
|
||||
local v = self.data[i]
|
||||
p:string(tostring(v.value), v.color)
|
||||
if not v.last then
|
||||
p:string("/", COLOR_WHITE)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function render_all()
|
||||
for _, w in pairs(widgets) do
|
||||
w:render()
|
||||
end
|
||||
end
|
||||
|
||||
function load_config()
|
||||
config = require('json').decode_file('dfhack-config/dwarfmonitor.json')
|
||||
if not config.widgets then
|
||||
dmerror('No widgets enabled')
|
||||
end
|
||||
if type(config.widgets) ~= 'table' then
|
||||
dmerror('"widgets" is not a table')
|
||||
end
|
||||
widgets = {}
|
||||
for _, opts in pairs(config.widgets) do
|
||||
if type(opts) ~= 'table' then qerror('"widgets" is not an array') end
|
||||
if not opts.type then dmerror('Widget missing type field') end
|
||||
local cls = _ENV['Widget_' .. opts.type]
|
||||
if not cls then
|
||||
dmerror('Invalid widget type: ' .. opts.type)
|
||||
end
|
||||
table.insert(widgets, cls(opts))
|
||||
end
|
||||
end
|
||||
|
||||
return _ENV
|
Loading…
Reference in New Issue