Refactor for better configuration and node management
parent
805a4273aa
commit
30247ffb87
19
config.lua
19
config.lua
|
@ -1,12 +1,13 @@
|
|||
return {
|
||||
transitionTime = 1,
|
||||
cycleTime = 5,
|
||||
screens = {
|
||||
require 'screens.at',
|
||||
require 'screens.cube',
|
||||
require 'screens.weather',
|
||||
require 'screens.time',
|
||||
require 'screens.misery',
|
||||
require 'screens.screen1',
|
||||
displayTime = 2,
|
||||
transitionTime = 0.5,
|
||||
nodes = {
|
||||
{'nodes.at'},
|
||||
{'nodes.cube'},
|
||||
{'nodes.time'},
|
||||
{'nodes.weather'},
|
||||
{'nodes.misery', displayTime = 7},
|
||||
{'nodes.screen1'},
|
||||
},
|
||||
environment = os.getenv('ENV') or 'prod',
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
local NodeManager = class('NodeManager', {
|
||||
state = 'running',
|
||||
stateTime = 0,
|
||||
currentNode = nil,
|
||||
})
|
||||
|
||||
function NodeManager:init(config)
|
||||
self.config = config
|
||||
self.nodes = {}
|
||||
self.nodeConfs = {}
|
||||
|
||||
self.currentNode = nil
|
||||
|
||||
print('Initializing NodeManager')
|
||||
end
|
||||
|
||||
function NodeManager:load()
|
||||
self:configChanged()
|
||||
end
|
||||
|
||||
function NodeManager:resize(w, h)
|
||||
self.secondaryCanvas = love.graphics.newCanvas(w, h)
|
||||
end
|
||||
|
||||
function NodeManager:configChanged()
|
||||
local cnt = {}
|
||||
local newNodes = {}
|
||||
local newNodeConfs = {}
|
||||
|
||||
for _, c_ in ipairs(self.config.nodes) do
|
||||
local nodeConfig = lume.clone(c_)
|
||||
local hash = inspect(nodeConfig)
|
||||
if cnt[hash] == nil then cnt[hash] = 0 end
|
||||
cnt[hash] = cnt[hash] + 1
|
||||
hash = hash .. '-' .. tostring(cnt[hash])
|
||||
|
||||
local nodeName = nodeConfig[1]
|
||||
table.remove(nodeConfig, 1)
|
||||
|
||||
if self.nodeConfs[hash] then
|
||||
print('Using existing node:', self.nodeConfs[hash], hash)
|
||||
newNodes[#newNodes + 1] = self.nodeConfs[hash]
|
||||
else
|
||||
print('Creating new node.', nodeName, inspect(nodeConfig))
|
||||
local status, err = pcall(function()
|
||||
newNodes[#newNodes + 1] = require(nodeName)(nodeConfig)
|
||||
end)
|
||||
if err then
|
||||
print("Error occured while loading", nodeName, err)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
newNodeConfs[hash] = newNodes[#newNodes]
|
||||
end
|
||||
|
||||
self.nodes = newNodes
|
||||
self.nodeConfs = newNodeConfs
|
||||
end
|
||||
|
||||
function NodeManager:render()
|
||||
if not self.currentNode then self.currentNode = self.nodes[1] end
|
||||
if not self.currentNode then return end
|
||||
|
||||
|
||||
love.graphics.print('state: ' .. self.state .. '; counter: ' .. tostring(self.stateTime), 50, 50)
|
||||
|
||||
self.currentNode:render()
|
||||
|
||||
if self.state == 'transitioning' and self.currentNode ~= self.nextNode and self.nextNode then
|
||||
self.secondaryCanvas:renderTo(function()
|
||||
self.nextNode:render()
|
||||
end)
|
||||
love.graphics.setColor(255, 255, 255, 255 * (self.stateTime / self.config.transitionTime))
|
||||
love.graphics.draw(self.secondaryCanvas, 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function NodeManager:update(dt)
|
||||
if not self.currentNode then self.currentNode = self.nodes[1] end
|
||||
if not self.currentNode then return end
|
||||
|
||||
self.stateTime = self.stateTime + dt
|
||||
|
||||
if self.state == 'transitioning' and self.stateTime >= self.config.transitionTime then
|
||||
self.stateTime = 0
|
||||
self.state = 'running'
|
||||
self.currentNode:afterExit()
|
||||
-- self.currentNode, self.nextNode = self.nextNode, self.nodes[(lume.find(self.nodes, self.nextNode) or 1) % #self.nodes + 1]
|
||||
self.currentNode = self.nextNode
|
||||
self.currentNode:afterEnter()
|
||||
elseif self.state == 'running' and self.stateTime >= (self.currentNode.displayTime or self.config.displayTime) then
|
||||
self.stateTime = 0
|
||||
self.state = 'transitioning'
|
||||
self.currentNode:beforeExit()
|
||||
self.nextNode = self.nodes[(lume.find(self.nodes, self.currentNode) or 1) % #self.nodes + 1]
|
||||
self.nextNode:beforeEnter()
|
||||
end
|
||||
|
||||
self.currentNode:update(dt)
|
||||
if self.state == 'transitioning' and self.currentNode ~= self.nextNode and self.nextNode then
|
||||
self.nextNode:update(dt)
|
||||
end
|
||||
end
|
||||
|
||||
return NodeManager
|
|
@ -0,0 +1,16 @@
|
|||
local Node = class('Node', {})
|
||||
|
||||
function Node:init(opts)
|
||||
for i, n in pairs(opts) do
|
||||
self[i] = n
|
||||
end
|
||||
end
|
||||
|
||||
function Node:update(dt) end
|
||||
|
||||
function Node:beforeEnter() end
|
||||
function Node:afterEnter() end
|
||||
function Node:beforeExit() end
|
||||
function Node:afterExit() end
|
||||
|
||||
return Node
|
|
@ -0,0 +1,33 @@
|
|||
local ThreadNode = Node:extend('ThreadNode', {
|
||||
threadFile = nil,
|
||||
threadChannel = nil,
|
||||
updateInterval = 5,
|
||||
lastUpdate = 0,
|
||||
state = nil,
|
||||
})
|
||||
|
||||
function ThreadNode:update(dt)
|
||||
if not self.state then self:checkUpdate() end
|
||||
end
|
||||
|
||||
function ThreadNode:checkUpdate()
|
||||
if self.threadFile and self.threadChannel then
|
||||
if self.lastUpdate < love.timer.getTime() - self.updateInterval or
|
||||
(not self.state and self.lastUpdate < love.timer.getTime() - 5) then
|
||||
self.lastUpdate = love.timer.getTime()
|
||||
print(self.threadChannel, "Updating...")
|
||||
|
||||
local updateThread = love.thread.newThread(self.threadFile)
|
||||
updateThread:start()
|
||||
end
|
||||
|
||||
self.state = love.thread.getChannel(self.threadChannel):pop() or self.state
|
||||
end
|
||||
end
|
||||
|
||||
function ThreadNode:afterExit()
|
||||
print('exit')
|
||||
self:checkUpdate()
|
||||
end
|
||||
|
||||
return ThreadNode
|
84
main.lua
84
main.lua
|
@ -1,17 +1,24 @@
|
|||
local debugGraph = require 'vendor.debugGraph'
|
||||
local inspect = require 'vendor.inspect'
|
||||
local push = require 'vendor.push'
|
||||
local lurker = require 'vendor.lurker'
|
||||
class = require('vendor.30log')
|
||||
inspect = require('vendor.inspect')
|
||||
lume = require('vendor.lume')
|
||||
|
||||
Node = require('core.node')
|
||||
ThreadNode = require('core.thread-node')
|
||||
NodeManager = require('core.node-manager')
|
||||
|
||||
local config = require('config')
|
||||
|
||||
environment = os.getenv('ENV')
|
||||
local push = require('vendor.push')
|
||||
local lurker = require('vendor.lurker')
|
||||
local debugGraph = require('vendor.debugGraph')
|
||||
|
||||
local fpsGraph, memGraph;
|
||||
|
||||
local gameWidth, gameHeight = 1280, 720
|
||||
local windowWidth, windowHeight = love.window.getDesktopDimensions()
|
||||
windowWidth, windowHeight = windowWidth*.5, windowHeight*.5 --make the window a bit smaller than the screen itself
|
||||
|
||||
if environment == 'DEV' then
|
||||
if config.environment == 'dev' then
|
||||
push:setupScreen(gameWidth, gameHeight, windowWidth, windowHeight, {fullscreen = false, resizable = true})
|
||||
else
|
||||
push:setupScreen(gameWidth, gameHeight, gameWidth, gameHeight, {fullscreen = true})
|
||||
|
@ -19,37 +26,22 @@ end
|
|||
|
||||
function love.resize(w, h)
|
||||
push:resize(w, h)
|
||||
secondaryCanvas = love.graphics.newCanvas(push:getWidth(), push:getHeight())
|
||||
manager:resize(w, h)
|
||||
end
|
||||
|
||||
function love.load()
|
||||
state = {
|
||||
currentScreen = 1,
|
||||
transitioning = false,
|
||||
stateCounter = 0,
|
||||
}
|
||||
manager = NodeManager(config)
|
||||
manager:load()
|
||||
manager:resize(push:getWidth(), push:getHeight())
|
||||
|
||||
love.mouse.setVisible( false )
|
||||
|
||||
secondaryCanvas = love.graphics.newCanvas(push:getWidth(), push:getHeight())
|
||||
|
||||
fpsGraph = debugGraph:new('fps', 0, 0)
|
||||
memGraph = debugGraph:new('mem', 0, 30)
|
||||
|
||||
for key, node in ipairs(config.screens) do
|
||||
node.load()
|
||||
end
|
||||
|
||||
lurker.quiet = true
|
||||
end
|
||||
|
||||
function lurker.preswap(f)
|
||||
if f:match('_thread.lua') then
|
||||
print("Preventing _thread update!")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function getw() return push:getWidth() end
|
||||
function geth() return push:getHeight() end
|
||||
|
||||
|
@ -60,14 +52,7 @@ function love.draw()
|
|||
oldw, oldh = love.graphics.getWidth, love.graphics.getHeight
|
||||
love.graphics.getWidth, love.graphics.getHeight = getw, geth
|
||||
|
||||
config.screens[state.currentScreen].render()
|
||||
|
||||
if state.transitioning then
|
||||
-- Render next screen into canvas and fade accordingly
|
||||
secondaryCanvas:renderTo(config.screens[state.currentScreen % #config.screens + 1].render)
|
||||
love.graphics.setColor(255, 255, 255, 255 * (state.stateCounter / config.transitionTime)) -- red, green, blue, opacity (this would be white with 20% opacity)
|
||||
love.graphics.draw(secondaryCanvas, 0, 0)
|
||||
end
|
||||
manager:render()
|
||||
|
||||
-- Draw graphs
|
||||
love.graphics.setColor(255, 255, 255, 128)
|
||||
|
@ -83,30 +68,21 @@ function love.draw()
|
|||
end
|
||||
|
||||
function love.update(dt)
|
||||
config.screens[state.currentScreen].update(dt)
|
||||
|
||||
if state.transitioning then
|
||||
config.screens[state.currentScreen % #config.screens + 1].update(dt)
|
||||
end
|
||||
|
||||
state.stateCounter = state.stateCounter + dt
|
||||
|
||||
if state.transitioning then
|
||||
if state.stateCounter >= config.transitionTime then
|
||||
state.stateCounter = 0
|
||||
state.transitioning = false
|
||||
state.currentScreen = (state.currentScreen % #config.screens) + 1
|
||||
end
|
||||
else
|
||||
if state.stateCounter >= config.cycleTime then
|
||||
state.stateCounter = 0
|
||||
state.transitioning = true
|
||||
end
|
||||
end
|
||||
manager:update(dt)
|
||||
|
||||
-- Update the graphs
|
||||
fpsGraph:update(dt)
|
||||
memGraph:update(dt)
|
||||
|
||||
lurker.update()
|
||||
end
|
||||
|
||||
function lurker.preswap(f)
|
||||
if f == 'config.lua' then
|
||||
print('config reloaded, notifying nodemanager')
|
||||
package.loaded['config'] = nil
|
||||
manager.config = require('config');
|
||||
manager:configChanged();
|
||||
elseif f:match('_thread.lua') then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
local node = ThreadNode:extend('nodes.at', {
|
||||
threadFile = 'nodes/at_thread.lua',
|
||||
threadChannel = 'at',
|
||||
|
||||
api = 'http://at.hackerspace.pl/api',
|
||||
})
|
||||
|
||||
local bigFont = love.graphics.newFont('fonts/Lato-Light.ttf', 80)
|
||||
local textFont = love.graphics.newFont('fonts/Lato-Light.ttf', 50)
|
||||
local smallFont = love.graphics.newFont('fonts/Lato-Light.ttf', 30)
|
||||
|
||||
function node:render()
|
||||
love.graphics.setColor( 0, 0, 0 )
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
|
||||
if self.state then
|
||||
love.graphics.setColor( 255, 255, 255, 100 )
|
||||
love.graphics.setFont(bigFont)
|
||||
love.graphics.printf('Currently at hackerspace:', 50, 100, love.graphics.getWidth() - 100, 'center')
|
||||
|
||||
usersList = (table.concat(lume.map(self.state.users, function(v) return v.login end), ', ') or 'nobody...') .. '\n'
|
||||
|
||||
if self.state.unknown > 0 then
|
||||
usersList = usersList .. '\n...and ' .. tostring(self.state.unknown) .. ' unknown creatures'
|
||||
end
|
||||
|
||||
if self.state.kektops > 0 then
|
||||
usersList = usersList .. '\n...and ' .. tostring(self.state.kektops) .. ' kektops'
|
||||
end
|
||||
|
||||
if self.state.esps > 0 then
|
||||
usersList = usersList .. '\n...and ' .. tostring(self.state.esps) .. ' ESPs'
|
||||
end
|
||||
|
||||
love.graphics.setColor( 255, 255, 255 )
|
||||
love.graphics.setFont(textFont)
|
||||
love.graphics.printf(usersList, 50, 220, love.graphics.getWidth() - 100, 'center')
|
||||
else
|
||||
love.graphics.setColor( 255, 255, 255, 80 )
|
||||
|
||||
love.graphics.setFont(smallFont)
|
||||
love.graphics.printf("Loading at...", 0, love.graphics.getHeight() - 200, love.graphics.getWidth(), 'center')
|
||||
end
|
||||
end
|
||||
|
||||
return node
|
|
@ -1,4 +1,5 @@
|
|||
local node = {}
|
||||
local node = Node:extend('nodes.at', {
|
||||
})
|
||||
local papa = love.graphics.newImage("papa.png")
|
||||
local h = 25.0
|
||||
local v = {
|
||||
|
@ -31,9 +32,7 @@ local E = 100 * math.tan(2*math.pi/3)
|
|||
|
||||
function to2d(p) return p[1] * E / (p[3]+E), p[2] * E / (p[3]+E) end
|
||||
|
||||
function node.load() end
|
||||
|
||||
function node.render()
|
||||
function node:render()
|
||||
love.graphics.setColor( 0, 0, 0 )
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
love.graphics.setColor( 255, 255, 255 )
|
||||
|
@ -47,7 +46,7 @@ function node.render()
|
|||
end
|
||||
end
|
||||
|
||||
function node.update(dt)
|
||||
function node:update(dt)
|
||||
for _, vec in ipairs(v) do
|
||||
angle = -dt/3
|
||||
nv0 = math.cos(angle) * vec[1] + math.sin(angle) * vec[3]
|
|
@ -1,29 +1,27 @@
|
|||
local node = {}
|
||||
local node = ThreadNode:extend('node.misery', {
|
||||
threadFile = 'nodes/misery_thread.lua',
|
||||
threadChannel = 'misery',
|
||||
|
||||
updateInterval = 2 * 60,
|
||||
})
|
||||
|
||||
local inspect = require('vendor.inspect')
|
||||
|
||||
local textFont = love.graphics.newFont('fonts/Lato-Light.ttf', 50)
|
||||
local smallFont = love.graphics.newFont('fonts/Lato-Light.ttf', 30)
|
||||
|
||||
local updateInterval = 2 * 60
|
||||
local lastUpdate = 0
|
||||
local state = nil
|
||||
|
||||
function node.load() end
|
||||
function node.unload() end
|
||||
|
||||
function node.render()
|
||||
function node:render()
|
||||
love.graphics.setColor( 0, 0, 0 )
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
|
||||
if state then
|
||||
if self.state then
|
||||
love.graphics.setColor( 255, 255, 255 )
|
||||
love.graphics.setFont(textFont)
|
||||
love.graphics.printf(state.entry, 50, 180, love.graphics.getWidth() - 100, 'center')
|
||||
love.graphics.printf(self.state.entry, 50, 180, love.graphics.getWidth() - 100, 'center')
|
||||
|
||||
love.graphics.setColor( 255, 255, 255, 200 )
|
||||
love.graphics.setFont(smallFont)
|
||||
local description = 'added by ' .. state.author .. ' on ' .. os.date('%Y/%m/%d %X', state.added)
|
||||
local description = 'added by ' .. self.state.author .. ' on ' .. os.date('%Y/%m/%d %X', self.state.added)
|
||||
love.graphics.printf(description, 200, love.graphics.getHeight() - 100, love.graphics.getWidth() - 400, 'center')
|
||||
else
|
||||
love.graphics.setColor( 255, 255, 255, 80 )
|
||||
|
@ -33,17 +31,4 @@ function node.render()
|
|||
end
|
||||
end
|
||||
|
||||
function node.update(dt)
|
||||
if lastUpdate < love.timer.getTime() - updateInterval or
|
||||
(not state and lastUpdate < love.timer.getTime() - 5) then
|
||||
lastUpdate = love.timer.getTime()
|
||||
print("Updating...")
|
||||
|
||||
local updateThread = love.thread.newThread('screens/misery_thread.lua')
|
||||
updateThread:start()
|
||||
end
|
||||
|
||||
state = love.thread.getChannel('misery'):pop() or state
|
||||
end
|
||||
|
||||
return node
|
|
@ -1,9 +1,6 @@
|
|||
local node = {}
|
||||
local node = Node:extend('nodes.screen1', {})
|
||||
|
||||
function node.load()
|
||||
end
|
||||
|
||||
function node.render()
|
||||
function node:render()
|
||||
love.graphics.setColor( 0, 0, 0 )
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
|
||||
|
@ -16,7 +13,4 @@ function node.render()
|
|||
end
|
||||
end
|
||||
|
||||
function node.update(dt)
|
||||
end
|
||||
|
||||
return node
|
|
@ -1,11 +1,9 @@
|
|||
local node = {}
|
||||
local node = Node:extend('nodes.time', {})
|
||||
|
||||
local textFont = love.graphics.newFont('fonts/Lato-Thin.ttf', 400)
|
||||
local smallFont = love.graphics.newFont('fonts/Lato-Light.ttf', 60)
|
||||
|
||||
function node.load() end
|
||||
|
||||
function node.render()
|
||||
function node:render()
|
||||
love.graphics.setColor( 0, 0, 0 )
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
|
||||
|
@ -18,7 +16,4 @@ function node.render()
|
|||
love.graphics.printf(os.date('%Y/%m/%d'), 0, 575, love.graphics.getWidth(), 'center');
|
||||
end
|
||||
|
||||
function node.update(dt)
|
||||
end
|
||||
|
||||
return node
|
|
@ -0,0 +1,50 @@
|
|||
local node = ThreadNode:extend('nodes.weather', {
|
||||
threadFile = 'nodes/weather_thread.lua',
|
||||
threadChannel = 'weather',
|
||||
|
||||
updateInterval = 5 * 60,
|
||||
})
|
||||
|
||||
local weatherFont = love.graphics.newFont('fonts/weathericons-regular-webfont.ttf', 400)
|
||||
local textFont = love.graphics.newFont('fonts/Lato-Thin.ttf', 300)
|
||||
local smallFont = love.graphics.newFont('fonts/Lato-Light.ttf', 30)
|
||||
|
||||
local weatherGlyphs = {
|
||||
snow = "",
|
||||
mist = "",
|
||||
clear = "",
|
||||
clouds = "",
|
||||
}
|
||||
|
||||
function node:render()
|
||||
love.graphics.setColor( 0, 0, 0 )
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
|
||||
if self.state then
|
||||
love.graphics.setColor( 255, 255, 255 )
|
||||
|
||||
if weatherGlyphs[self.state.weather] then
|
||||
love.graphics.setFont(weatherFont)
|
||||
love.graphics.print(weatherGlyphs[self.state.weather], 120, 35)
|
||||
else
|
||||
love.graphics.setFont(smallFont)
|
||||
love.graphics.print(self.state.weather, 150, love.graphics.getHeight()/2 - 60)
|
||||
end
|
||||
|
||||
love.graphics.setFont(textFont)
|
||||
love.graphics.printf(tostring(self.state.temperature) .. "°", 600, 150, 650, 'center')
|
||||
|
||||
love.graphics.setFont(smallFont)
|
||||
love.graphics.printf(os.date("Last update: %Y/%m/%d %H:%M", self.state.lastUpdate), 0, love.graphics.getHeight() - 60, love.graphics.getWidth(), 'center')
|
||||
if self.state.insideTemperature then
|
||||
love.graphics.printf("Room: " .. tostring(self.state.insideTemperature) .. "° / " .. tostring(self.state.insideHumidity) .. "%RH", 0, love.graphics.getHeight() - 100, love.graphics.getWidth(), 'center')
|
||||
end
|
||||
else
|
||||
love.graphics.setColor( 255, 255, 255, 80 )
|
||||
|
||||
love.graphics.setFont(smallFont)
|
||||
love.graphics.printf("Loading weather...", 0, love.graphics.getHeight() - 200, love.graphics.getWidth(), 'center')
|
||||
end
|
||||
end
|
||||
|
||||
return node
|
|
@ -1,63 +0,0 @@
|
|||
local node = {}
|
||||
|
||||
local lume = require('vendor.lume');
|
||||
|
||||
local bigFont = love.graphics.newFont('fonts/Lato-Light.ttf', 80)
|
||||
local textFont = love.graphics.newFont('fonts/Lato-Light.ttf', 50)
|
||||
local smallFont = love.graphics.newFont('fonts/Lato-Light.ttf', 30)
|
||||
|
||||
local updateInterval = 2 * 60
|
||||
local lastUpdate = 0
|
||||
local state = nil
|
||||
|
||||
function node.load() end
|
||||
function node.unload() end
|
||||
|
||||
function node.render()
|
||||
love.graphics.setColor( 0, 0, 0 )
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
|
||||
if state then
|
||||
love.graphics.setColor( 255, 255, 255, 100 )
|
||||
love.graphics.setFont(bigFont)
|
||||
love.graphics.printf('Currently at hackerspace:', 50, 100, love.graphics.getWidth() - 100, 'center')
|
||||
|
||||
usersList = (table.concat(lume.map(state.users, function(v) return v.login end), ', ') or 'nobody...') .. '\n'
|
||||
|
||||
if state.unknown > 0 then
|
||||
usersList = usersList .. '\n...and ' .. tostring(state.unknown) .. ' unknown creatures'
|
||||
end
|
||||
|
||||
if state.kektops > 0 then
|
||||
usersList = usersList .. '\n...and ' .. tostring(state.kektops) .. ' kektops'
|
||||
end
|
||||
|
||||
if state.esps > 0 then
|
||||
usersList = usersList .. '\n...and ' .. tostring(state.esps) .. ' ESPs'
|
||||
end
|
||||
|
||||
love.graphics.setColor( 255, 255, 255 )
|
||||
love.graphics.setFont(textFont)
|
||||
love.graphics.printf(usersList, 50, 220, love.graphics.getWidth() - 100, 'center')
|
||||
else
|
||||
love.graphics.setColor( 255, 255, 255, 80 )
|
||||
|
||||
love.graphics.setFont(smallFont)
|
||||
love.graphics.printf("Loading at...", 0, love.graphics.getHeight() - 200, love.graphics.getWidth(), 'center')
|
||||
end
|
||||
end
|
||||
|
||||
function node.update(dt)
|
||||
if lastUpdate < love.timer.getTime() - updateInterval or
|
||||
(not state and lastUpdate < love.timer.getTime() - 5) then
|
||||
lastUpdate = love.timer.getTime()
|
||||
print("Updating...")
|
||||
|
||||
local updateThread = love.thread.newThread('screens/at_thread.lua')
|
||||
updateThread:start()
|
||||
end
|
||||
|
||||
state = love.thread.getChannel('at'):pop() or state
|
||||
end
|
||||
|
||||
return node
|
|
@ -1,19 +0,0 @@
|
|||
local node = {}
|
||||
|
||||
function node.render()
|
||||
love.graphics.setColor( 80, 0, 0 )
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
|
||||
love.graphics.setColor(255, 255, 255, 255)
|
||||
love.graphics.setNewFont(90)
|
||||
|
||||
love.graphics.printf("Screen 2!", 0, love.graphics.getHeight()/2 - 45, love.graphics.getWidth(), 'center')
|
||||
|
||||
love.graphics.setColor(255, 50, 0)
|
||||
love.graphics.circle("fill", 60, 300, 50)
|
||||
end
|
||||
|
||||
function node.update(dt)
|
||||
end
|
||||
|
||||
return node
|
|
@ -1,67 +0,0 @@
|
|||
local node = {}
|
||||
|
||||
local inspect = require('vendor.inspect')
|
||||
|
||||
local weatherFont = love.graphics.newFont('fonts/weathericons-regular-webfont.ttf', 400)
|
||||
local textFont = love.graphics.newFont('fonts/Lato-Thin.ttf', 300)
|
||||
local smallFont = love.graphics.newFont('fonts/Lato-Light.ttf', 30)
|
||||
|
||||
local weatherGlyphs = {
|
||||
snow = "",
|
||||
mist = "",
|
||||
clear = "",
|
||||
clouds = "",
|
||||
}
|
||||
|
||||
local updateInterval = 5 * 60
|
||||
local lastUpdate = 0
|
||||
local state = nil
|
||||
|
||||
function node.load() end
|
||||
function node.unload() end
|
||||
|
||||
function node.render()
|
||||
love.graphics.setColor( 0, 0, 0 )
|
||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
|
||||
|
||||
if state then
|
||||
love.graphics.setColor( 255, 255, 255 )
|
||||
|
||||
if weatherGlyphs[state.weather] then
|
||||
love.graphics.setFont(weatherFont)
|
||||
love.graphics.print(weatherGlyphs[state.weather], 120, 35)
|
||||
else
|
||||
love.graphics.setFont(smallFont)
|
||||
love.graphics.print(state.weather, 150, love.graphics.getHeight()/2 - 60)
|
||||
end
|
||||
|
||||
love.graphics.setFont(textFont)
|
||||
love.graphics.printf(tostring(state.temperature) .. "°", 600, 150, 650, 'center')
|
||||
|
||||
love.graphics.setFont(smallFont)
|
||||
love.graphics.printf(os.date("Last update: %Y/%m/%d %H:%M", state.lastUpdate), 0, love.graphics.getHeight() - 60, love.graphics.getWidth(), 'center')
|
||||
if state.insideTemperature then
|
||||
love.graphics.printf("Room: " .. tostring(state.insideTemperature) .. "° / " .. tostring(state.insideHumidity) .. "%RH", 0, love.graphics.getHeight() - 100, love.graphics.getWidth(), 'center')
|
||||
end
|
||||
else
|
||||
love.graphics.setColor( 255, 255, 255, 80 )
|
||||
|
||||
love.graphics.setFont(smallFont)
|
||||
love.graphics.printf("Loading weather...", 0, love.graphics.getHeight() - 200, love.graphics.getWidth(), 'center')
|
||||
end
|
||||
end
|
||||
|
||||
function node.update(dt)
|
||||
if lastUpdate < love.timer.getTime() - updateInterval or
|
||||
(not state and lastUpdate < love.timer.getTime() - 5) then
|
||||
lastUpdate = love.timer.getTime()
|
||||
print("Updating...")
|
||||
|
||||
local updateThread = love.thread.newThread('screens/weather_thread.lua')
|
||||
updateThread:start()
|
||||
end
|
||||
|
||||
state = love.thread.getChannel('weather'):pop() or state
|
||||
end
|
||||
|
||||
return node
|
|
@ -0,0 +1,31 @@
|
|||
local next, assert, pairs, type, tostring, setmetatable, baseMt, _instances, _classes, _class = next, assert, pairs, type, tostring, setmetatable, {}, setmetatable({},{__mode = 'k'}), setmetatable({},{__mode = 'k'})
|
||||
local function assert_call_from_class(class, method) assert(_classes[class], ('Wrong method call. Expected class:%s.'):format(method)) end; local function assert_call_from_instance(instance, method) assert(_instances[instance], ('Wrong method call. Expected instance:%s.'):format(method)) end
|
||||
local function bind(f, v) return function(...) return f(v, ...) end end
|
||||
local default_filter = function() return true end
|
||||
local function deep_copy(t, dest, aType) t = t or {}; local r = dest or {}; for k,v in pairs(t) do if aType ~= nil and type(v) == aType then r[k] = (type(v) == 'table') and ((_classes[v] or _instances[v]) and v or deep_copy(v)) or v elseif aType == nil then r[k] = (type(v) == 'table') and k~= '__index' and ((_classes[v] or _instances[v]) and v or deep_copy(v)) or v end; end return r end
|
||||
local function instantiate(call_init,self,...) assert_call_from_class(self, 'new(...) or class(...)'); local instance = {class = self}; _instances[instance] = tostring(instance); deep_copy(self, instance, 'table')
|
||||
instance.__index, instance.__subclasses, instance.__instances, instance.mixins = nil, nil, nil, nil; setmetatable(instance,self); if call_init and self.init then if type(self.init) == 'table' then deep_copy(self.init, instance) else self.init(instance, ...) end end; return instance
|
||||
end
|
||||
local function extend(self, name, extra_params)
|
||||
assert_call_from_class(self, 'extend(...)'); local heir = {}; _classes[heir] = tostring(heir); self.__subclasses[heir] = true; deep_copy(extra_params, deep_copy(self, heir))
|
||||
heir.name, heir.__index, heir.super, heir.mixins = extra_params and extra_params.name or name, heir, self, {}; return setmetatable(heir,self)
|
||||
end
|
||||
baseMt = { __call = function (self,...) return self:new(...) end, __tostring = function(self,...)
|
||||
if _instances[self] then return ("instance of '%s' (%s)"):format(rawget(self.class,'name') or '?', _instances[self]) end; return _classes[self] and ("class '%s' (%s)"):format(rawget(self,'name') or '?', _classes[self]) or self end
|
||||
}; _classes[baseMt] = tostring(baseMt); setmetatable(baseMt, {__tostring = baseMt.__tostring})
|
||||
local class = {isClass = function(t) return not not _classes[t] end, isInstance = function(t) return not not _instances[t] end}
|
||||
_class = function(name, attr) local c = deep_copy(attr); _classes[c] = tostring(c)
|
||||
c.name, c.__tostring, c.__call, c.new, c.create, c.extend, c.__index, c.mixins, c.__instances, c.__subclasses = name or c.name, baseMt.__tostring, baseMt.__call, bind(instantiate, true), bind(instantiate, false), extend, c, setmetatable({},{__mode = 'k'}), setmetatable({},{__mode = 'k'}), setmetatable({},{__mode = 'k'})
|
||||
c.subclasses = function(self, filter, ...) assert_call_from_class(self, 'subclasses(class)'); filter = filter or default_filter; local subclasses = {}; for class in pairs(_classes) do if class ~= baseMt and class:subclassOf(self) and filter(class,...) then subclasses[#subclasses + 1] = class end end; return subclasses end
|
||||
c.instances = function(self, filter, ...) assert_call_from_class(self, 'instances(class)'); filter = filter or default_filter; local instances = {}; for instance in pairs(_instances) do if instance:instanceOf(self) and filter(instance, ...) then instances[#instances + 1] = instance end end; return instances end
|
||||
c.subclassOf = function(self, superclass) assert_call_from_class(self, 'subclassOf(superclass)'); assert(class.isClass(superclass), 'Wrong argument given to method "subclassOf()". Expected a class.'); local super = self.super; while super do if super == superclass then return true end; super = super.super end; return false end
|
||||
c.classOf = function(self, subclass) assert_call_from_class(self, 'classOf(subclass)'); assert(class.isClass(subclass), 'Wrong argument given to method "classOf()". Expected a class.'); return subclass:subclassOf(self) end
|
||||
c.instanceOf = function(self, fromclass) assert_call_from_instance(self, 'instanceOf(class)'); assert(class.isClass(fromclass), 'Wrong argument given to method "instanceOf()". Expected a class.'); return ((self.class == fromclass) or (self.class:subclassOf(fromclass))) end
|
||||
c.cast = function(self, toclass) assert_call_from_instance(self, 'instanceOf(class)'); assert(class.isClass(toclass), 'Wrong argument given to method "cast()". Expected a class.'); setmetatable(self, toclass); self.class = toclass; return self end
|
||||
c.with = function(self,...) assert_call_from_class(self, 'with(mixin)'); for _, mixin in ipairs({...}) do assert(self.mixins[mixin] ~= true, ('Attempted to include a mixin which was already included in %s'):format(tostring(self))); self.mixins[mixin] = true; deep_copy(mixin, self, 'function') end return self end
|
||||
c.includes = function(self, mixin) assert_call_from_class(self,'includes(mixin)'); return not not (self.mixins[mixin] or (self.super and self.super:includes(mixin))) end
|
||||
c.without = function(self, ...) assert_call_from_class(self, 'without(mixin)'); for _, mixin in ipairs({...}) do
|
||||
assert(self.mixins[mixin] == true, ('Attempted to remove a mixin which is not included in %s'):format(tostring(self))); local classes = self:subclasses(); classes[#classes + 1] = self
|
||||
for _, class in ipairs(classes) do for method_name, method in pairs(mixin) do if type(method) == 'function' then class[method_name] = nil end end end; self.mixins[mixin] = nil end; return self end; return setmetatable(c, baseMt) end
|
||||
class._DESCRIPTION = '30 lines library for object orientation in Lua'; class._VERSION = '30log v1.2.0'; class._URL = 'http://github.com/Yonaba/30log'; class._LICENSE = 'MIT LICENSE <http://www.opensource.org/licenses/mit-license.php>'
|
||||
return setmetatable(class,{__call = function(_,...) return _class(...) end })
|
Loading…
Reference in New Issue