clocktoy/clock.lua

147 lines
3.5 KiB
Lua
Raw Normal View History

2024-03-27 06:05:06 +00:00
local MAX_MINUTES = 60 * 12
2024-03-24 22:26:07 +00:00
2024-03-27 03:57:50 +00:00
local Time = {}
Time.__index = Time
2024-03-27 06:05:06 +00:00
local function newTimeRaw(rawMinutes)
2024-03-27 03:57:50 +00:00
local t = {
2024-03-27 06:05:06 +00:00
rawminutes = rawMinutes % MAX_MINUTES
2024-03-27 03:57:50 +00:00
}
2024-03-27 06:05:06 +00:00
return setmetatable(t, Time)
end
function Time:new(hour, minute)
return newTimeRaw((hour or 12) % 12 * 60 + (minute or 0))
2024-03-27 03:57:50 +00:00
end
2024-03-27 06:05:06 +00:00
function Time:get()
local h = math.floor(self.rawminutes / 60 % 12)
if h == 0 then h = 12 end
local m = self.rawminutes % 60
return h, m
2024-03-27 03:57:50 +00:00
end
2024-03-27 06:05:06 +00:00
function Time:getHoursSinceTwelve()
local h = self.rawminutes / 60
if h < 1 then h = h + 12 end
return h
end
function Time:addMinutes(minutes)
return newTimeRaw(self.rawminutes + minutes)
2024-03-27 03:57:50 +00:00
end
function Time:fmt()
2024-03-27 06:05:06 +00:00
local h, m = self:get()
return string.format("%2d:%02d", h, m)
end
local function pointToTurns(x, y)
local rawTurns = math.atan2(y, x) / 2 / math.pi
local _, clockTurns = math.modf(rawTurns + 1.25)
return clockTurns
end
local function turnsToRads(turns)
return turns * 2 * math.pi - 0.5 * math.pi
2024-03-27 03:57:50 +00:00
end
2024-03-24 22:26:07 +00:00
local Hand = {}
Hand.__index = Hand
2024-03-27 03:57:50 +00:00
function Hand:new(length, color)
2024-03-24 22:26:07 +00:00
local h = {
length = (length or 10),
2024-03-27 06:05:06 +00:00
color = (color or {1,1,1})
2024-03-24 22:26:07 +00:00
}
return setmetatable(h, self)
end
2024-03-27 06:05:06 +00:00
function Hand:draw(turns)
2024-03-24 22:26:07 +00:00
love.graphics.push("all")
love.graphics.setColor(unpack(self.color))
2024-03-27 06:05:06 +00:00
love.graphics.rotate(turnsToRads(turns) + 0.5 * math.pi)
2024-03-24 22:26:07 +00:00
love.graphics.rectangle("fill", -10, 10, 20, -self.length)
love.graphics.pop()
end
2024-03-27 03:57:50 +00:00
local Clock = {}
Clock.__index = Clock
function Clock:new(time, diameter, transform)
local c = {
time = (time or Time:new()),
2024-03-27 06:05:06 +00:00
minuteHand = Hand:new(240, {1,0,0}),
hourHand = Hand:new(180, {0,0.5,0.5}),
2024-03-27 03:57:50 +00:00
dragging = false,
transform = transform or love.math.newTransform(),
radius = diameter and diameter/2 or 300
}
return setmetatable(c, self)
end
function Clock:setTime(time)
self.time = time
end
function Clock:getTime()
return self.time
end
function Clock:draw()
2024-03-27 06:05:06 +00:00
local _, m = self.time:get()
local h = self.time:getHoursSinceTwelve()
2024-03-27 03:57:50 +00:00
love.graphics.push("all")
love.graphics.applyTransform(self.transform)
love.graphics.setColor(0.5, 0.5, 0.5)
love.graphics.circle("fill", 0, 0, self.radius)
2024-03-27 06:05:06 +00:00
self.minuteHand:draw(m / 60)
self.hourHand:draw(h / 12)
2024-03-27 03:57:50 +00:00
love.graphics.pop()
end
local function clockContainsPoint(clock, x, y)
local localX, localY = clock.transform:inverseTransformPoint(x, y)
local dist = math.sqrt(localX^2 + localY^2)
return dist <= clock.radius
end
local function clockPointAt(clock, x, y)
local localX, localY = clock.transform:inverseTransformPoint(x, y)
2024-03-27 06:05:06 +00:00
local minutes = pointToTurns(localX, localY) * 60
local _, oldMinutes = clock.time:get()
local dMinutes = minutes - oldMinutes
-- Adjust for rolling over
if dMinutes < -30 then
dMinutes = dMinutes + 60
elseif dMinutes > 30 then
dMinutes = dMinutes - 60
end
clock.time = clock.time:addMinutes(dMinutes)
2024-03-27 03:57:50 +00:00
end
function Clock:movemouse(x, y)
if self.dragging then
local localX, localY = self.transform:inverseTransformPoint(x, y)
clockPointAt(self, x, y)
-- TODO update clock hands
end
end
function Clock:pressmouse(x, y, button)
if not self.dragging and button == 1 and clockContainsPoint(self, x,y) then
self.dragging = true
clockPointAt(self, x, y)
-- TODO update clock hands
end
end
function Clock:releasemouse(button)
if button == 1 then self.dragging = false end
end
return Clock