-
-
Save SkyTheCoder/a72dfc048d7cb7265a0d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# Passdrag | |
Passdrag | |
= class() -- Looks odd as code, but nice if it crashes | |
local ellipseMesh = function(width, height, top, bottom, change) -- Function to create a(n) circle/ellipse mesh with a gradient | |
local pwidth, pheight, ptop, pbototom, pchange | |
pwidth = width or 128 | |
if type(height) == "number" or height == nil then | |
pheight = height or width | |
ptop = top or color(255) | |
if type(bottom) == "userdata" then | |
pbottom = bottom or ptop | |
pchange = change or 1 | |
else | |
pbottom = ptop | |
pchange = bottom or 1 | |
end | |
else | |
pheight = width | |
ptop = height or color(255) | |
if type(top) == "userdata" then | |
pbottom = top or ptop | |
pchange = bottom or 1 | |
else | |
pbottom = ptop | |
pchange = top or 1 | |
end | |
end | |
pwidth, pheight = pwidth / 2, pheight / 2 | |
local m = mesh() | |
local v = {} | |
local c = {} | |
local p = {} | |
for d = 0, 360, pchange do | |
local r = math.rad(d) | |
table.insert(p, vec2(pwidth * math.sin(r), pheight * math.cos(r))) | |
end | |
v = triangulate(p) | |
m.vertices = v | |
for k, v in ipairs(v) do | |
table.insert(c, ptop:mix(pbottom, v:normalize().y * 0.5 + 0.5)) | |
end | |
m.colors = c | |
return m | |
end | |
function Passdrag:init(x, y, size) -- Passdrag GUI & handler setup | |
self.rot = {a = 0} | |
self.tid = 0 | |
self.size = size | |
self.x, self.y = x, y | |
self.ePos = vec2(0, size) | |
self.styles = { | |
Light = { | |
bg = color(255), | |
txt = color(200), | |
cFill = color(255), | |
cStroke = color(220), | |
cDark = color(210), | |
pWidth = 5, | |
}, | |
Dark = { | |
bg = color(0), | |
txt = color(40), | |
cFill = color(30), | |
cStroke = color(25), | |
cDark = color(20), | |
pWidth = 5 | |
}, | |
Retro = { | |
bg = color(128, 96, 64, 255), | |
txt = color(64, 24, 16), | |
cFill = color(136, 102, 74, 255), | |
cStroke = color(74, 32, 24), | |
cDark = color(64, 24, 16), | |
pWidth = 3, | |
}, | |
Nature = { | |
bg = color(191, 255, 191), | |
txt = color(31, 63, 31), | |
cFill = color(74, 136, 74), | |
cStroke = color(63, 127, 63), | |
cDark = color(48, 112, 48), | |
pWidth = 5, | |
}, | |
Sky = { | |
bg = color(191, 223, 255), | |
txt = color(255), | |
cFill = color(95, 191, 255), | |
cStroke = color(240, 240), | |
cDark = color(74, 120, 255), | |
pWidth = 8, | |
}, | |
} | |
self.oldStyles = self.styles | |
self.style = "Light" | |
self.darkness = {a = 0} | |
self:updateMesh() | |
self.sequence = "" | |
self.lastChar = "" | |
end | |
function Passdrag:updateMesh() -- Update the gradiented mesh, not recommended for manual use | |
self.m = ellipseMesh(self.size / 3 - self.styles[self.style].pWidth, self.styles[self.style].cFill, self.styles[self.style].cDark, 10) | |
end | |
function Passdrag:setStyle(x) -- Set style to x | |
self.style = x | |
self:updateMesh() | |
end | |
function Passdrag:addStyle(x, y) -- Add style x with a preset of y | |
self.styles[x] = y | |
end | |
function Passdrag:duplicateStyle(x, y) -- Make a new style y, with the presets of x | |
self.styles[y] = self.styles[x] | |
end | |
function Passdrag:deleteStyle(x) -- Delete style x | |
self.styles[x] = nil | |
end | |
function Passdrag:restoreStyle(x) -- Restore style (x or current) to its original preset | |
x = x or self.style | |
self.styles[x] = self.oldStyles[x] | |
end | |
function Passdrag:restoreStyles() -- Restore all styles to their original presets | |
self.styles = self.oldStyles | |
end | |
function Passdrag:addChar(x) -- Add character to current drag, not recommended for manual use | |
if x ~= self.lastChar then | |
self.sequence = self.sequence .. x | |
self.lastChar = x | |
end | |
end | |
function Passdrag:resetSequence() -- Reset drag | |
self.sequence = "" | |
self.lastChar = "" | |
end | |
function Passdrag:draw() -- Draw the GUI and update | |
for k, v in pairs(self.styles[self.style]) do | |
self["g" .. k] = v | |
end | |
local checks = {"bg", "txt", "cFill", "cStroke", "cDark", "pWidth"} | |
for k, v in ipairs(checks) do | |
if self["s" .. v] ~= nil then | |
self.styles[style][v] = self["s" .. v] | |
self["s" .. v] = nil | |
end | |
end | |
local deg = math.floor(math.abs((math.deg(self.rot.a) - 90) / 45) + 0.5) | |
if deg == 8 then | |
deg = 0 | |
end | |
for i = 1, 3 do | |
if deg <= 5 then | |
deg = deg + 2 | |
elseif deg >= 6 then | |
deg = deg - 6 | |
end | |
end | |
self:addChar(tostring(deg + 1)) | |
local c = {} | |
for k, v in ipairs(self.m.vertices) do | |
table.insert(c, self.styles[self.style].cFill:mix(self.styles[self.style].cDark:mix(self.styles[self.style].cFill, self.darkness.a), v:normalize().y * 0.5 + 0.5)) | |
end | |
self.m.colors = c | |
pushMatrix() | |
pushStyle() | |
fill(self.styles[self.style].cFill) | |
stroke(self.styles[self.style].cStroke) | |
strokeWidth(self.styles[self.style].pWidth) | |
self.ePos.x, self.ePos.y = math.sin(-self.rot.a) * self.size / 2, math.cos(-self.rot.a) * self.size / 2 | |
translate(self.x, self.y) | |
pushMatrix() | |
translate(self.ePos.x, self.ePos.y) | |
ellipse(0, 0, self.size / 3) | |
self.m:draw() | |
fill(0, 0) | |
ellipse(0, 0, self.size / 3) | |
popMatrix() | |
for i = 0, 7 do | |
pushMatrix() | |
rotate(i * (360 / 8)) | |
line(self.size - self.size / 4, 0, self.size, 0) | |
popMatrix() | |
end | |
popStyle() | |
popMatrix() | |
end | |
function Passdrag:touched(touch) -- Handles touches & animations on the GUI | |
if self.tid == 0 and touch.state == BEGAN and vec2(touch.x - self.x, touch.y - self.y):dist(self.ePos) < self.size / 3 then | |
self.tid = touch.id | |
if self.t ~= nil then | |
tween.stop(self.t) | |
end | |
if self.t2 ~= nil then | |
tween.stop(self.t2) | |
end | |
self.t = tween(0.45, self.darkness, {a = 1}, tween.easing.quadInOut) | |
end | |
if touch.id == self.tid and (touch.state == BEGAN or touch.state == MOVING) then | |
self.rot.a = math.atan2(touch.y - HEIGHT / 2, touch.x - WIDTH / 2) - math.pi / 2 | |
local deg = math.floor(math.abs((math.deg(self.rot.a) - 90) / 45) + 0.5) | |
if deg == 8 then | |
deg = 0 | |
end | |
for i = 1, 3 do | |
if deg <= 5 then | |
deg = deg + 2 | |
elseif deg >= 6 then | |
deg = deg - 6 | |
end | |
end | |
self:addChar(tostring(deg + 1)) | |
end | |
if touch.id == self.tid and (touch.state == ENDED or touch.state == CANCELLED) then | |
self.tid = 0 | |
tween.stop(self.t) | |
self.t = tween(0.45, self.darkness, {a = 0}, tween.easing.quadInOut) | |
self.t2 = tween(0.45, self.rot, {a = math.rad(((math.floor(math.deg(self.rot.a) / 45 - 0.5) + 0.5) + 0.5) * 45)}) | |
end | |
end | |
--# Main | |
-- Passdrag | |
function setup() | |
print() | |
pd = Passdrag(WIDTH / 2, HEIGHT / 2, 200) | |
styles = {"Light", "Dark", "Retro", "Nature", "Sky"} | |
parameter.integer("Style", 1, #styles, 1) | |
parameter.watch("styles[Style]") | |
parameter.watch("pd.sequence") | |
parameter.action("Save Passdrag", function() | |
savePassdrag() | |
output.clear() | |
print() | |
tween.delay(0.1, function() | |
output.clear() | |
print() | |
print("Passdrag saved") | |
end) | |
end) | |
parameter.watch("Saved_Passdrag") | |
parameter.watch("Passdrag_Matches_Saved") | |
end | |
function draw() | |
pd:setStyle(styles[Style]) | |
background(pd.styles[pd.style].bg) | |
Saved_Passdrag = readPassdrag() | |
Passdrag_Matches_Saved = pd.sequence == Saved_Passdrag | |
pd:draw() | |
font("HelveticaNeue-Light") | |
fontSize(48) | |
fill(pd.styles[pd.style].txt) | |
text("Passdrag", WIDTH / 2, HEIGHT - HEIGHT / 16) | |
fontSize(24) | |
text("Your drag: " .. pd.sequence, WIDTH / 2, HEIGHT - HEIGHT / 8) | |
text("Drag length: " .. pd.sequence:len(), WIDTH / 2, HEIGHT - HEIGHT / 6) | |
end | |
function touched(touch) | |
pd:touched(touch) | |
end | |
function savePassdrag() | |
local fileName = "passdrag.txt" | |
local file = os.getenv("HOME") .. "/Documents/" .. fileName | |
local wFd = io.open(file, "w") | |
wFd:write(pd.sequence) | |
wFd:close() | |
end | |
function readPassdrag() | |
local fileName = "passdrag.txt" | |
local file = os.getenv("HOME") .. "/Documents/" .. fileName | |
local rFd = io.open(file, "r") | |
local v = "" | |
if rFd ~= nil then | |
for i in rFd:lines() do | |
v = v .. i | |
end | |
end | |
if rFd ~= nil then | |
rFd:close() | |
end | |
return v | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment