Merge pull request #2366 from myk002/myk_overlay_dwarfmonitor
[dwarfmonitor] migrate widgets to overlay v2develop
commit
3cf14610f9
@ -1,21 +1,3 @@
|
|||||||
{
|
{
|
||||||
"widgets": [
|
"date_format": "Y-M-D"
|
||||||
{
|
|
||||||
"type": "weather",
|
|
||||||
"x": 22,
|
|
||||||
"y": -1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "date",
|
|
||||||
"x": -30,
|
|
||||||
"y": 0,
|
|
||||||
"format": "Y-M-D"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "misery",
|
|
||||||
"x": -2,
|
|
||||||
"y": -1,
|
|
||||||
"anchor": "right"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -1,175 +1,184 @@
|
|||||||
local _ENV = mkmodule('plugins.dwarfmonitor')
|
local _ENV = mkmodule('plugins.dwarfmonitor')
|
||||||
|
|
||||||
local gps = df.global.gps
|
local json = require('json')
|
||||||
local gui = require 'gui'
|
local guidm = require('gui.dwarfmode')
|
||||||
|
local overlay = require('plugins.overlay')
|
||||||
|
|
||||||
config = {}
|
local DWARFMONITOR_CONFIG_FILE = 'dfhack-config/dwarfmonitor.json'
|
||||||
widgets = {}
|
|
||||||
|
|
||||||
function dmerror(desc)
|
-- ------------- --
|
||||||
qerror('dwarfmonitor: ' .. tostring(desc))
|
-- WeatherWidget --
|
||||||
end
|
-- ------------- --
|
||||||
|
|
||||||
|
WeatherWidget = defclass(WeatherWidget, overlay.OverlayWidget)
|
||||||
|
WeatherWidget.ATTRS{
|
||||||
|
default_pos={x=15,y=-1},
|
||||||
|
viewscreens={'dungeonmode', 'dwarfmode'},
|
||||||
|
}
|
||||||
|
|
||||||
Widget = defclass(Widget)
|
function WeatherWidget:init()
|
||||||
function Widget:init(opts)
|
self.rain = false
|
||||||
self.opts = opts
|
self.snow = false
|
||||||
end
|
end
|
||||||
function Widget:get_pos()
|
|
||||||
local x = self.opts.x >= 0 and self.opts.x or gps.dimx + self.opts.x
|
function WeatherWidget:overlay_onupdate()
|
||||||
local y = self.opts.y >= 0 and self.opts.y or gps.dimy + self.opts.y
|
local rain, snow = false, false
|
||||||
if self.opts.anchor == 'right' then
|
local cw = df.global.current_weather
|
||||||
x = x - (self:get_width() or 0) + 1
|
for i=0,4 do
|
||||||
|
for j=0,4 do
|
||||||
|
weather = cw[i][j]
|
||||||
|
if weather == df.weather_type.Rain then rain = true end
|
||||||
|
if weather == df.weather_type.Snow then snow = true end
|
||||||
end
|
end
|
||||||
return x, y
|
|
||||||
end
|
|
||||||
function Widget:render()
|
|
||||||
if monitor_state(self.opts.type) == false then
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
self:update()
|
self.frame.w = (rain and 4 or 0) + (snow and 4 or 0) +
|
||||||
local x, y = self:get_pos()
|
((snow and rain) and 1 or 0)
|
||||||
local p = gui.Painter.new_xy(x, y, gps.dimx - 1, y)
|
self.rain, self.snow = rain, snow
|
||||||
self:render_body(p)
|
|
||||||
end
|
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()
|
function WeatherWidget:onRenderBody(dc)
|
||||||
self.counts = get_weather_counts()
|
if self.rain then dc:string('Rain', COLOR_LIGHTBLUE):advance(1) end
|
||||||
|
if self.snow then dc:string('Snow', COLOR_WHITE) end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Widget_weather:get_width()
|
-- ---------- --
|
||||||
if self.counts.rain > 0 then
|
-- DateWidget --
|
||||||
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)
|
local function get_date_format()
|
||||||
if self.counts.rain > 0 then
|
local ok, config = pcall(json.decode_file, DWARFMONITOR_CONFIG_FILE)
|
||||||
p:string('Rain', COLOR_LIGHTBLUE):advance(1)
|
if not ok or not config.date_format then
|
||||||
end
|
return 'Y-M-D'
|
||||||
if self.counts.snow > 0 then
|
|
||||||
p:string('Snow', COLOR_WHITE)
|
|
||||||
end
|
end
|
||||||
|
return config.date_format
|
||||||
end
|
end
|
||||||
|
|
||||||
Widget_date = defclass(Widget_date, Widget)
|
DateWidget = defclass(DateWidget, overlay.OverlayWidget)
|
||||||
Widget_date.ATTRS = {
|
DateWidget.ATTRS{
|
||||||
output = ''
|
default_pos={x=-16,y=1},
|
||||||
|
viewscreens={'dungeonmode', 'dwarfmode'},
|
||||||
}
|
}
|
||||||
|
|
||||||
function Widget_date:update()
|
function DateWidget:init()
|
||||||
if not self.opts.format then
|
self.datestr = ''
|
||||||
self.opts.format = 'Y-M-D'
|
self.fmt = get_date_format()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function DateWidget:overlay_onupdate()
|
||||||
local year = dfhack.world.ReadCurrentYear()
|
local year = dfhack.world.ReadCurrentYear()
|
||||||
local month = dfhack.world.ReadCurrentMonth() + 1
|
local month = dfhack.world.ReadCurrentMonth() + 1
|
||||||
local day = dfhack.world.ReadCurrentDay()
|
local day = dfhack.world.ReadCurrentDay()
|
||||||
self.output = 'Date:'
|
|
||||||
for i = 1, #self.opts.format do
|
local fmt = self.fmt
|
||||||
local c = self.opts.format:sub(i, i)
|
local datestr = 'Date:'
|
||||||
|
for i=1,#fmt do
|
||||||
|
local c = fmt:sub(i, i)
|
||||||
if c == 'y' or c == 'Y' then
|
if c == 'y' or c == 'Y' then
|
||||||
self.output = self.output .. year
|
datestr = datestr .. year
|
||||||
elseif c == 'm' or c == 'M' then
|
elseif c == 'm' or c == 'M' then
|
||||||
if c == 'M' and month < 10 then
|
if c == 'M' and month < 10 then
|
||||||
self.output = self.output .. '0'
|
datestr = datestr .. '0'
|
||||||
end
|
end
|
||||||
self.output = self.output .. month
|
datestr = datestr .. month
|
||||||
elseif c == 'd' or c == 'D' then
|
elseif c == 'd' or c == 'D' then
|
||||||
if c == 'D' and day < 10 then
|
if c == 'D' and day < 10 then
|
||||||
self.output = self.output .. '0'
|
datestr = datestr .. '0'
|
||||||
end
|
end
|
||||||
self.output = self.output .. day
|
datestr = datestr .. day
|
||||||
else
|
else
|
||||||
self.output = self.output .. c
|
datestr = datestr .. c
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function Widget_date:get_width()
|
self.frame.w = #datestr
|
||||||
return #self.output
|
self.datestr = datestr
|
||||||
end
|
end
|
||||||
|
|
||||||
function Widget_date:render_body(p)
|
function DateWidget:onRenderBody(dc)
|
||||||
p:string(self.output, COLOR_GREY)
|
dc:string(self.datestr, COLOR_GREY)
|
||||||
end
|
end
|
||||||
|
|
||||||
Widget_misery = defclass(Widget_misery, Widget)
|
-- ------------ --
|
||||||
|
-- MiseryWidget --
|
||||||
|
-- ------------ --
|
||||||
|
|
||||||
function Widget_misery:update()
|
MiseryWidget = defclass(MiseryWidget, overlay.OverlayWidget)
|
||||||
self.data = get_misery_data()
|
MiseryWidget.ATTRS{
|
||||||
end
|
default_pos={x=-2,y=-1},
|
||||||
|
viewscreens={'dwarfmode'},
|
||||||
|
}
|
||||||
|
|
||||||
function Widget_misery:get_width()
|
function MiseryWidget:init()
|
||||||
local w = 2 + 6
|
self.colors = getStressCategoryColors()
|
||||||
for k, v in pairs(self.data) do
|
self.stress_category_counts = {}
|
||||||
w = w + #tostring(v.value)
|
|
||||||
end
|
|
||||||
return w
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Widget_misery:render_body(p)
|
function MiseryWidget:overlay_onupdate()
|
||||||
p:string("H:", COLOR_WHITE)
|
local counts, num_colors = {}, #self.colors
|
||||||
for i = 0, 6 do
|
for _,unit in ipairs(df.global.world.units.active) do
|
||||||
local v = self.data[i]
|
local stress_category = math.min(num_colors,
|
||||||
p:string(tostring(v.value), v.color)
|
dfhack.units.getStressCategory(unit))
|
||||||
if not v.last then
|
counts[stress_category] = (counts[stress_category] or 0) + 1
|
||||||
p:string("/", COLOR_WHITE)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local width = 2 + num_colors - 1 -- 'H:' plus the slashes
|
||||||
|
for i=1,num_colors do
|
||||||
|
width = width + #tostring(counts[i] or 0)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
Widget_cursor = defclass(Widget_cursor, Widget)
|
self.stress_category_counts = counts
|
||||||
|
self.frame.w = width
|
||||||
|
end
|
||||||
|
|
||||||
function Widget_cursor:update()
|
function MiseryWidget:onRenderBody(dc)
|
||||||
if gps.mouse_x == -1 and not self.opts.show_invalid then
|
dc:string('H:', COLOR_WHITE)
|
||||||
self.output = ''
|
local counts = self.stress_category_counts
|
||||||
return
|
for i,color in ipairs(self.colors) do
|
||||||
|
dc:string(tostring(counts[i] or 0), color)
|
||||||
|
if i < #self.colors then dc:string('/', COLOR_WHITE) end
|
||||||
end
|
end
|
||||||
self.output = (self.opts.format or '(x,y)'):gsub('[xX]', gps.mouse_x):gsub('[yY]', gps.mouse_y)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Widget_cursor:get_width()
|
-- ------------ --
|
||||||
return #self.output
|
-- CursorWidget --
|
||||||
end
|
-- ------------ --
|
||||||
|
|
||||||
function Widget_cursor:render_body(p)
|
CursorWidget = defclass(CursorWidget, overlay.OverlayWidget)
|
||||||
p:string(self.output)
|
CursorWidget.ATTRS{
|
||||||
end
|
default_pos={x=2,y=-4},
|
||||||
|
viewscreens={'dungeonmode', 'dwarfmode'},
|
||||||
|
}
|
||||||
|
|
||||||
function render_all()
|
function CursorWidget:onRenderBody(dc)
|
||||||
for _, w in pairs(widgets) do
|
local screenx, screeny = dfhack.screen.getMousePos()
|
||||||
w:render()
|
local mouse_map = dfhack.gui.getMousePos()
|
||||||
end
|
local keyboard_map = guidm.getCursorPos()
|
||||||
end
|
|
||||||
|
|
||||||
function load_config()
|
local text = {}
|
||||||
config = require('json').decode_file('dfhack-config/dwarfmonitor.json')
|
table.insert(text, ('mouse UI grid (%d,%d)'):format(screenx, screeny))
|
||||||
if not config.widgets then
|
if mouse_map then
|
||||||
dmerror('No widgets enabled')
|
table.insert(text, ('mouse map coord (%d,%d,%d)')
|
||||||
|
:format(mouse_map.x, mouse_map.y, mouse_map.z))
|
||||||
end
|
end
|
||||||
if type(config.widgets) ~= 'table' then
|
if keyboard_map then
|
||||||
dmerror('"widgets" is not a table')
|
table.insert(text, ('kbd cursor coord (%d,%d,%d)')
|
||||||
|
:format(keyboard_map.x, keyboard_map.y, keyboard_map.z))
|
||||||
end
|
end
|
||||||
widgets = {}
|
local width = 0
|
||||||
for _, opts in pairs(config.widgets) do
|
for i,line in ipairs(text) do
|
||||||
if type(opts) ~= 'table' then dmerror('"widgets" is not an array') end
|
dc:seek(0, i-1):string(line)
|
||||||
if not opts.type then dmerror('Widget missing type field') end
|
width = math.max(width, #line)
|
||||||
local cls = _ENV['Widget_' .. opts.type]
|
|
||||||
if not cls then
|
|
||||||
dmerror('Invalid widget type: ' .. opts.type)
|
|
||||||
end
|
|
||||||
table.insert(widgets, cls(opts))
|
|
||||||
end
|
end
|
||||||
|
self.frame.w = width
|
||||||
|
self.frame.h = #text
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- register our widgets with the overlay
|
||||||
|
OVERLAY_WIDGETS = {
|
||||||
|
cursor=CursorWidget,
|
||||||
|
date=DateWidget,
|
||||||
|
misery=MiseryWidget,
|
||||||
|
weather=WeatherWidget,
|
||||||
|
}
|
||||||
|
|
||||||
return _ENV
|
return _ENV
|
||||||
|
Loading…
Reference in New Issue