Skip to content

Commit

Permalink
Self Updating Gauges (#5)
Browse files Browse the repository at this point in the history
* Add self updating gauges, add some getValueAt updates back to archon
* Bump version
* Adjusting docs, adding some additional debugc echos
* Include usage information
* Update README
  • Loading branch information
demonnic authored Aug 8, 2020
1 parent b26a143 commit f62a95d
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 6 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ These files contain the modules in the MDK. You only need to include those files
* ftext.lua
* basic fText. Documentation at https://github.com/demonnic/fText/wiki

* sortbox.lua
* SortBox, an alternative to H/VBox which can be either, and also provides options for sorting its contents. Overview at https://github.com/demonnic/MDK/wiki/SortBox

* sug.lua
* Self Updating Gauges, will watch a set of variables and update itself on a timer based on what values those variables hold. Documentation at https://demonnic.github.io/mdk/current/classes/SUG.html

* textformatter.lua
* TextFormatter, a reusable fText object. Must have ftext.lua in the same directory. Documentation at https://github.com/demonnic/fText/wiki/TextFormatter

Expand All @@ -36,9 +42,6 @@ These files contain the modules in the MDK. You only need to include those files
* timergauge.lua
* TimerGauge, an extension of Geyser.Gauge which serves as an animated countdown timer. Overview at https://github.com/demonnic/MDK/wiki/TimerGauge

* sortbox.lua
* SortBox, an alternative to H/VBox which can be either, and also provides options for sorting its contents. Overview at https://github.com/demonnic/MDK/wiki/SortBox

* luaunit.lua
* LuaUnit, for writing unit tests for your packages. Modified slightly for use with Mudlet. Documentation at https://github.com/bluebird75/luaunit

Expand Down
3 changes: 2 additions & 1 deletion src/resources/archon.lua
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ function Archon.verify_entry(entry)
end

local function digForValue(dataFrom, tableTo)
if table.size(tableTo) == 0 then
if dataFrom == nil or table.size(tableTo) == 0 then
return dataFrom
else
local newData = dataFrom[tableTo[1]]
Expand All @@ -144,6 +144,7 @@ local function digForValue(dataFrom, tableTo)
end

function Archon.getValueAt(accessString)
if accessString == "" then return nil end
local tempTable = accessString:split("%.")
local accessTable = {}
for i,v in ipairs(tempTable) do
Expand Down
2 changes: 1 addition & 1 deletion src/resources/mdkversion.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.8
1.0.9
201 changes: 201 additions & 0 deletions src/resources/sug.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
--- Self Updating Gauge, extends <a href="https://www.mudlet.org/geyser/files/geyser/GeyserGauge.html">Geyser.Gauge</a>
--@classmod SUG
--@author Damian Monogue <demonnic@gmail.com>
--@copyright 2020 Damian Monogue
--@license MIT, see LICENSE.lua

local SUG = {
name = "SelfUpdatingGaugeClass",
active = true,
updateTime = 333,
currentVariable = "",
maxVariable = "",
defaultCurrent = 50,
defaultMax = 100,
textTemplate = " |c/|m |p%",
strict = true,
}

--- Creates a new Self Updating Gauge.
--@tparam table cons table of options which control the Gauge's behaviour. In addition to all valid contraints for Geyser.Gauge, SUG adds:
--<br>
--<table class="tg">
--<tr>
-- <th>name</th>
-- <th>description</th>
-- <th>default</th>
--</tr>
--<tr>
-- <td class="tg-odd">active</td>
-- <td class="tg-odd">boolean, if true starts the timer updating</td>
-- <td class="tg-odd">true</td>
--</tr>
--<tr>
-- <td class="tg-even">updateTime</td>
-- <td class="tg-even">How often should the gauge autoupdate? Milliseconds</td>
-- <td class="tg-even">333</td>
--</tr>
--<tr>
-- <td class="tg-odd">currentVariable</td>
-- <td class="tg-odd">What variable will hold the 'current' value of the gauge? Pass the name as a string, IE "currentHP" or "gmcp.Char.Vitals.hp"</td>
-- <td class="tg-odd">""</td>
--</tr>
--<tr>
-- <td class="tg-even">maxVariable</td>
-- <td class="tg-even">What variable will hold the 'current' value of the gauge? Pass the name as a string, IE "maxHP" or "gmcp.Char.Vitals.maxhp"</td>
-- <td class="tg-even">""</td>
--</tr>
--<tr>
-- <td class="tg-odd">textTemplate</td>
-- <td class="tg-odd">Template to use for the text on the gauge. "|c" replaced with current value, "|m" replaced with max value, "|p" replaced with the % full the gauge should be</td>
-- <td class="tg-odd">" |c/|m |p%"</td>
--</tr>
--<tr>
-- <td class="tg-even">defaultCurrent</td>
-- <td class="tg-even">What value to use if the currentVariable points to nil or something which cannot be made a number?</td>
-- <td class="tg-even">50</td>
--</tr>
--<tr>
-- <td class="tg-odd">defaultMax</td>
-- <td class="tg-odd">What value to use if the maxVariable points to nil or something which cannot be made a number?</td>
-- <td class="tg-odd">100</td>
--</tr>
--</table>
--@param parent The Geyser container for this gauge
--@usage local SUG = require("MDK-1.sug") --the following will watch "gmcp.Char.Vitals.hp" and "gmcp.Char.Vitals.maxhp" and update itself every 333 milliseconds
-- myGauge = SUG:new({
-- name = "myGauge",
-- currentVariable = "gmcp.Char.Vitals.hp", --if this is nil, it will use the defaultCurrent of 50
-- maxVariable = "gmcp.Char.Vitals.maxhp", --if this is nil, it will use the defaultMax of 100.
-- height = 50,
-- })
function SUG:new(cons, container)
local funcName = "SUG:new(cons, container)"
cons = cons or {}
local consType = type(cons)
assert(consType == "table", string.format("%s: cons as table expected, got %s", funcName, consType))
local me = SUG.parent:new(cons, container)
setmetatable(me, self)
self.__index = self
-- apply any styling requested
if me.cssFront then
if not me.cssBack then
me.cssBack = me.cssFront .. "background-color: black;"
end
me:setStyleSheet(me.cssFront, me.cssBack, me.cssText)
end
if me.active then me:start() end
return me
end

-- internal function, recursively digs for a value within subtables if possible
local function digForValue(dataFrom, tableTo)
if digForValue == nil or table.size(tableTo) == 0 then
return dataFrom
else
local newData = dataFrom[tableTo[1]]
table.remove(tableTo, 1)
return digForValue(newData, tableTo)
end
end

-- Internal function, used to turn a string variable name into a value
local function getValueAt(accessString)
if accessString == "" then return nil end
local tempTable = accessString:split("%.")
local accessTable = {}
for i,v in ipairs(tempTable) do
if tonumber(v) then
accessTable[i] = tonumber(v)
else
accessTable[i] = v
end
end
return digForValue(_G, accessTable)
end

--- Set the name of the variable the Self Updating Gauge watches for the 'current' value of the gauge
--@tparam string variableName The name of the variable to get the current value for the gauge. For instance "currentHP", "gmcp.Char.Vitals.hp" etc
function SUG:setCurrentVariable(variableName)
local nameType = type(variableName)
local funcName = "SUG:setCurrentVariable(variableName)"
assert(nameType == "string", string.format("%s: variableName as string expected, got: %s",funcName, nameType))
local val = getValueAt(variableName)
local valType = type(tonumber(val))
assert(valType == "number", string.format("%s: variableName must point to a variable which is a number or coercable into one. %s points to a %s", funcName, variableName, type(val)))
self.currentVariable = variableName
self:update()
end

--- Set the name of the variable the Self Updating Gauge watches for the 'max' value of the gauge
--@tparam string variableName The name of the variable to get the max value for the gauge. For instance "maxHP", "gmcp.Char.Vitals.maxhp" etc. Set to "" to only check the current value
function SUG:setMaxVariable(variableName)
if variableName == "" then
self.maxVariable = variableName
self:update()
return
end
local nameType = type(variableName)
local funcName = "SUG:setMaxVariable(variableName)"
assert(nameType == "string", string.format("%s: variableName as string expected, got: %s",funcName, nameType))
local val = getValueAt(variableName)
local valType = type(tonumber(val))
assert(valType == "number", string.format("%s: variableName must point to a variable which is a number or coercable into one. %s points to a %s", funcName, variableName, type(val)))
self.maxVariable = variableName
self:update()
end

--- Set the template for the Self Updating Gauge to set the text with. "|c" is replaced by the current value, "|m" is replaced by the max value, and "|p" is replaced by the percentage current/max
--@tparam string template The template to use for the text on the gauge. If the max value is 200 and current is 68, then |c will be replace by 68, |m replaced by 200, and |p replaced by 34.
function SUG:setTextTemplate(template)
local templateType = type(template)
local funcName = "SUG:setTextTemplate(template)"
assert(templateType == "string", string.format("%s: template as string expected, got %s", funcName, templateType))
self.textTemplate = template
self:update()
end

--- Stops the Self Updating Gauge from updating
function SUG:stop()
self.active = false
if self.timer then
killTimer(self.timer)
self.timer = nil
end
end

--- Starts the Self Updating Gauge updating. If it is already updating, it will restart it.
function SUG:start()
SUG:stop()
self.active = true
self.timer = tempTimer(self.updateTime / 1000, function() self:update() end, true)
end

--- Reads the values from currentVariable and maxVariable, and updates the gauge's value and text.
function SUG:update()
local current = getValueAt(self.currentVariable)
local max = getValueAt(self.maxVariable)
current = tonumber(current)
max = tonumber(max)
if current == nil then
current = self.defaultCurrent
debugc(string.format("Self Updating Gauge named %s is trying to update with an invalid current value. Using the defaultCurrent instead. currentVariable: '%s' maxVariable: '%s'", self.name, self.currentVariable, self.maxVariable))
end
if max == nil then
max = self.defaultMax
if self.maxVariable ~= "" then
debugc(string.format("Self Updating Gauge named %s is trying to update with an invalid max value. Using the defaultCurrent instead. currentVariable: '%s' maxVariable: '%s'", self.name, self.currentVariable, self.maxVariable))
end
end
local text = self.textTemplate
local percent = math.floor((current / max * 100) + 0.5)
text = text:gsub("|c", current)
text = text:gsub("|m", max)
text = text:gsub("|p", percent)
self:setValue(current, max, text)
end

SUG.parent = Geyser.Gauge
setmetatable(SUG, Geyser.Gauge)

return SUG
2 changes: 1 addition & 1 deletion src/scripts/MDKExample/Example.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
MDKExample = MDKExample or { version = "1.0.8" }
MDKExample = MDKExample or { version = "1.0.9" }
function MDKExample.exampleFText()
local fText = require("@PKGNAME@.ftext")
cecho(fText.fText("Testing!", {width = 40, formatType = 'c', textColor = '<orange>', capColor = '<purple>', cap = '[TEST]'}))
Expand Down

0 comments on commit f62a95d

Please sign in to comment.