Last active
August 29, 2015 14:04
-
-
Save tarrouye/5f5f4939ffef4eb13380 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
--# Main | |
-- Page Controller class for Codea | |
-- By JakAttak | |
displayMode(FULLSCREEN) | |
function setup() | |
font("HelveticaNeue-UltraLight") | |
local title = Title("Page Controller") | |
page = PageController(title, page2, { draw = page3, touched = tpage3 }) | |
end | |
function draw() | |
background(255) | |
page:draw() | |
end | |
function touched(t) | |
page:touched(t) | |
end | |
-- Example pages | |
function page2() | |
pBackground(0, (noise(1000+ElapsedTime/100)+1.5)*128, (noise(1000+ElapsedTime/10)+1.5)*128, 255) | |
fontSize(40) fill(0, 0, 0, 255) | |
text("Hey, look, it's Page 2", WIDTH / 2, HEIGHT / 2) | |
end | |
function page3() | |
pBackground(255, 100, 100, 255) | |
stroke(0, 0, 0, 255) strokeWidth(2) if fillEllipse then fill(stroke()) else noFill() end | |
ellipse(WIDTH / 2, HEIGHT / 4, WIDTH / 4) | |
fontSize(40) fill(255, 255, 255, 255) textAlign(CENTER) | |
text("Page 3\n\nDemonstrates passing a table\n\nTry touching the ellipse", WIDTH / 2, HEIGHT / 1.5) | |
end | |
function tpage3(t) | |
if vec2(t.x, t.y):dist(vec2(WIDTH / 2, HEIGHT / 4)) <= WIDTH / 8 and t.state ~= ENDED then | |
fillEllipse = true | |
return true | |
else | |
fillEllipse = false | |
end | |
end | |
--# PageController | |
PageController = class() | |
function PageController:init(...) | |
self.pages = { ... } | |
self:managePages() | |
self.toSwitch = WIDTH / 4 | |
self.timePerPage = 1 | |
self.indicator = math.max(WIDTH, HEIGHT) / 100 | |
self.page, self.scroll, self.scrollo, self.locked = 1, 0, 0, false | |
end | |
function PageController:managePages() | |
for i, page in ipairs(self.pages) do | |
if typeOf(page) == "table" then | |
page.draw = page.draw or function() end | |
page.touched = page.touched or function() end | |
elseif typeOf(page) == "class" then | |
local dfun = page.draw or function() end | |
page.draw = function() dfun(page) end | |
local tfun = page.touched or function() end | |
page.touched = function(touch) tfun(page, touch) end | |
elseif typeOf(page) == "function" then | |
self.pages[i] = { draw = page, touched = function() end } | |
else | |
self.pages[i] = nil | |
end | |
end | |
end | |
function PageController:draw() | |
-- Draw pages that should be shown | |
pushMatrix() | |
translate(self.scrollo, 0) | |
if self.pages[self.page] ~= nil then | |
pushStyle() | |
self.pages[self.page].draw() | |
popStyle() | |
end | |
if self.pages[self.page - 1] ~= nil and self.scroll > 0 then | |
pushMatrix() | |
translate(-WIDTH, 0) | |
pushStyle() | |
self.pages[self.page - 1].draw() | |
popStyle() | |
popMatrix() | |
end | |
if self.pages[self.page + 1] ~= nil and self.scroll < 0 then | |
pushMatrix() | |
translate(WIDTH, 0) | |
pushStyle() | |
self.pages[self.page + 1].draw() | |
popStyle() | |
popMatrix() | |
end | |
popMatrix() | |
-- Draw page indicators | |
local w = self.indicator * (#self.pages * 2 - 1) | |
local x = (WIDTH / 2) - (w / 2) + self.indicator / 2 | |
for p = 1, #self.pages do | |
if p == self.page then fill(255) | |
else fill(255, 127) end | |
ellipse(x, self.indicator, self.indicator) | |
x = x + self.indicator * 2 | |
end | |
end | |
function PageController:closestPage() | |
local closest = self.page | |
if self.scrollo > self.toSwitch and self.page > 1 then | |
closest = self.page - 1 | |
elseif self.scrollo < -self.toSwitch and self.page < #self.pages then | |
closest = self.page + 1 | |
end | |
return closest | |
end | |
function PageController:touched(t) | |
-- Handle touching on pages | |
if self.scrollo == 0 then | |
if self.pages[self.page] ~= nil and self.pages[self.page].touched(t) == true then | |
return -- If touched something then no scrolling | |
end | |
end | |
-- No scrolling when locked | |
if self.locked then return end | |
-- Stop tween when dragging | |
if self.releasing ~= nil then | |
tween.stop(self.releasing) | |
end | |
-- Scroll from drag | |
self.scroll = self.scroll + t.deltaX | |
local min = self.pages[self.page].pcSlideMin or 0 | |
local off = math.max(0, math.abs(self.scroll) - min) | |
self.scrollo = off * math.sign(self.scroll) | |
-- Tweens to closest page | |
if t.state == ENDED then | |
local closestPage = self:closestPage() | |
local target = (self.page - closestPage) * WIDTH | |
if closestPage ~= self.page then self.locked = true end | |
local dur = (math.abs(self.scrollo) / (self.toSwitch)) / ((WIDTH / self.toSwitch) * self.timePerPage) | |
self.releasing = tween(dur, self, { scrollo = target, scroll = target }, tween.easing.cubicOut, function() | |
self.page = closestPage | |
self.scroll = 0 | |
self.scrollo = 0 | |
self.releasing = nil | |
self.locked = false | |
end) | |
end | |
end | |
-- Helper functions | |
function typeOf(x) | |
-- Extended type function | |
if x == nil then | |
return 'nil' | |
end | |
if type(x) == 'table' and x.is_a then | |
return('class') | |
end | |
local txt | |
if typeTable == nil then | |
typeTable = { | |
[getmetatable(vec2()).__index ] = 'vec2', | |
[getmetatable(vec3()).__index ] = 'vec3', | |
[getmetatable(color()).__index ] = 'color', | |
[getmetatable(image(1,1)).__index ] = 'image', | |
[getmetatable(matrix()).__index] = 'matrix', | |
[getmetatable(mesh()).__index ] = 'mesh' , | |
[getmetatable(physics.body(CIRCLE, 1)).__index] = 'physics body', | |
} | |
end | |
local i = getmetatable(x) | |
if i then | |
txt = typeTable[i.__index] | |
end | |
if txt then | |
return txt | |
end | |
txt = type(x) | |
return txt | |
end | |
math.sign = function(n) | |
if n < 0 then | |
return -1 | |
end | |
return 1 | |
end | |
function pBackground(...) | |
-- Called same as background, draws a rect instead so each page can have individual background | |
pushStyle() | |
rectMode(CORNERS) | |
fill(...) | |
rect(-WIDTH / 768, -WIDTH / 768, WIDTH + WIDTH / 768, HEIGHT + WIDTH / 768) | |
popStyle() | |
end | |
--# Title | |
-- An example of using a class with the Page Controller | |
Title = class() | |
function Title:init(name) | |
fontSize(WIDTH / 10) fill(255, 255, 255, 255) | |
local w, h = textSize(name) | |
local timg = image(w, h) setContext(timg) | |
text(name, w / 2, h / 2) | |
setContext() | |
self.m = mesh() | |
self.m.texture = timg | |
self.m:addRect(WIDTH / 2, HEIGHT / 2, w, h) | |
self.m.shader = shader("Effects:Ripple") | |
self.m.shader.freq = 0.08 | |
end | |
function Title:draw() | |
pBackground(0, 128, 255) | |
self.m.shader.time = ElapsedTime | |
self.m:draw() | |
fontSize(WIDTH / 30) fill(255, 255, 255, 255) | |
text("(swipe or drag to use)", WIDTH / 2, HEIGHT / 4) | |
end | |
function Title:touched(touch) | |
-- Codea does not automatically call this method | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment