Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Codea in Codea by Simeon, in one file
--# Main
function keyHeight()
if CurrentOrientation == LANDSCAPE_LEFT or
CurrentOrientation == LANDSCAPE_RIGHT then
return 350
else
return 260
end
end
function layoutAndDrawKeys()
local start = WIDTH
local keySz = 30
local height = keyHeight()
for i = #keys,1,-1 do
local k = keys[i]
k.pos = vec2( start - keySz, height + keySz )
start = start - 2*keySz
k:draw()
end
trash.pos = vec2(WIDTH - keySz - 10, HEIGHT - keySz - 20)
trash:draw()
end
function setup()
showKeyboard()
displayMode(FULLSCREEN_NO_BUTTONS)
buffer = Buffer()
local closeKey = EmButton(vec2(0,0), "◀")
closeKey.color = color(255,100,50,255)
closeKey.action = function() close() end
local startKey = EmButton(vec2(0,0), "⏪")
startKey.action = function() buffer:moveCursor(vec2(0,-1000)) end
local endKey = EmButton(vec2(0,0), "⏩")
endKey.action = function() buffer:moveCursor(vec2(0,1000)) end
local leftKey = EmButton(vec2(0,0), "⬅")
leftKey.action = function() buffer:moveCursor(vec2(0,-1)) end
local rightKey = EmButton(vec2(0,0), "➡")
rightKey.action = function() buffer:moveCursor(vec2(0,1)) end
local upKey = EmButton(vec2(0,0), "⬆")
upKey.action = function() buffer:moveCursor(vec2(-1,0)) end
local downKey = EmButton(vec2(0,0), "⬇")
downKey.action = function() buffer:moveCursor(vec2(1,0)) end
local keyKey = EmButton(vec2(0,0), "📝")
keyKey.action = function() showKeyboard() end
local pKey = EmButton(vec2(0,0), "A")
pKey.action = function()
if displayMode() == STANDARD then
displayMode(FULLSCREEN_NO_BUTTONS)
else displayMode(STANDARD)
print(buffer:toString()) end
end
keys = {closeKey,startKey,leftKey,
rightKey,endKey,upKey,
downKey,keyKey,pKey}
trash = EmButton(vec2(0,0), "❌")
trash.action = function() buffer:clear() end
end
function keyboard(key)
buffer:insertCharacter(key)
end
function touched(touch)
for k,v in pairs(keys) do
v:touched(touch)
end
trash:touched(touch)
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
resetStyle()
local str = buffer:toString()
local chunk = loadstring(str)
if chunk then
chunk()
else
str = buffer:toStringWithoutActiveLine()
chunk = loadstring(str)
if chunk then chunk() end
end
resetStyle()
fill(0,0,0,50)
rectMode(CORNER)
rect(0,0,WIDTH,HEIGHT)
-- Do your drawing here
buffer:draw()
layoutAndDrawKeys()
end
--# Buffer
Buffer = class()
function Buffer:init()
self.buffer = {}
self.font = "Inconsolata"
self.fontSize = 20
-- x = line, y = pos
self.cursor = vec2(1,1)
self.t = 0
self.cursorBlink = 0
end
function Buffer:setStyle()
textMode(CORNER)
font( self.font )
fill(255)
fontSize( self.fontSize )
textWrapWidth(10000)
end
function Buffer:cursorToScreen(c)
-- Get a subset of the buffer
local lines = table_slice( self.buffer, 1, c.x )
local l = self.buffer[c.x]
local upToStr = self:bufferToString(lines)
local lstr = nil
if l then
lstr = table.concat(l)
end
pushStyle()
self:setStyle()
local lw = 0
local _,lh = textSize("A")
local emptyLine = true
if lstr and lstr ~= "" then
lw,lh = textSize(string.sub(lstr,1,c.y - 1))
emptyLine = false
end
local pw,ph = textSize(upToStr)
if emptyLine then
ph = ph + lh
end
popStyle()
return lw,(ph - lh/2)
end
function Buffer:bufferToString(b)
local bstrings = {}
for k,v in pairs(b) do
table.insert(bstrings, table.concat( b[k] ) )
end
return table.concat( bstrings, "\n" )
end
function Buffer:moveCursor(o)
self.cursor = self.cursor + o
self.cursor.x = math.max(1, math.min(self.cursor.x, #self.buffer))
local l = self.buffer[self.cursor.x]
local y = self.cursor.y
y = math.max(1, math.min(y, #l + 1))
self.cursor.y = y
end
function Buffer:insertCharacter(c)
local l = self.buffer[self.cursor.x]
if l == nil then
l = {}
self.buffer[self.cursor.x] = l
end
if c == "\n" then
local start = table_slice(l,1,self.cursor.y)
local tail = table_slice(l,self.cursor.y+1,#l)
table[self.cursor.x] = start
table.insert(self.buffer, self.cursor.x+1, tail)
self.cursor = vec2( self.cursor.x + 1, 1 )
elseif c == BACKSPACE then
if self.cursor.y == 1 then
-- delete line
local prevLine = self.buffer[self.cursor.x - 1]
table.remove(self.buffer, self.cursor.x)
if prevLine then
self.cursor = vec2(self.cursor.x - 1, #prevLine + 1)
table_append( prevLine, l )
end
else
-- delete character
table.remove(l, self.cursor.y - 1 )
self.cursor = vec2(self.cursor.x, self.cursor.y - 1 )
end
else
table.insert(l, self.cursor.y, c)
self.cursor = vec2( self.cursor.x, self.cursor.y + 1 )
end
end
function Buffer:draw()
self.t = self.t + 8 * DeltaTime
self.cursorBlink = (math.sin(self.t) + 1) * 128
pushStyle()
self:setStyle()
local str = self:toString()
local w,h = textSize(str)
pushMatrix()
translate( 40, -40 )
text(str, 0, HEIGHT - h)
-- Draw cursor
-- Cursor pos x,y
local cpx,cpy = self:cursorToScreen(self.cursor)
fill(0, 87, 255, self.cursorBlink)
rectMode(CENTER)
rect(cpx,HEIGHT - cpy,5,22)
popMatrix()
popStyle()
end
function Buffer:clear()
self.cursor = vec2(1,1)
self.buffer = {}
end
function Buffer:toString()
return self:bufferToString(self.buffer)
end
function Buffer:toStringWithoutActiveLine()
local bstrings = {}
for k,v in pairs(self.buffer) do
if k ~= self.cursor.x then
table.insert(bstrings, table.concat( self.buffer[k] ) )
end
end
return table.concat( bstrings, "\n" )
end
--# EmButton
-- Emoji Button
EmButton = class()
function EmButton:init(pos,txt)
-- you can accept and set parameters here
self.pos = pos
self.text = txt
self.action = nil
self.highlight = false
self.color = color(255,255,255,255)
end
function EmButton:size()
pushStyle()
self:setStyle()
local w,h = textSize(self.text)
popStyle()
return w,h
end
function EmButton:hitTest(lp)
local w,h = self:size()
local left,right = self.pos.x - w/2, self.pos.x + w/2
local top,bottom = self.pos.y + h/2, self.pos.y - h/2
if lp.x > left and lp.x < right and
lp.y > bottom and lp.y < top then
return true
end
return false
end
function EmButton:setStyle()
fill(self.color)
noStroke()
textMode(CENTER)
fontSize(50)
font("AppleColorEmoji")
end
function EmButton:draw()
pushMatrix()
translate(self.pos.x,self.pos.y)
pushStyle()
self:setStyle()
text(self.text,0,0)
popStyle()
popMatrix()
end
function EmButton:touched(touch)
if touch.state == ENDED then
-- Tapped
if self:hitTest( vec2(touch.x,touch.y) ) then
if self.action then self.action() end
end
end
end
--# Util
function table_append (t1, t2)
local t1s = #t1
for k,v in pairs(t2) do t1[k + t1s] = v end
end
function table_slice (values,i1,i2)
local res = {}
local n = #values
-- default values for range
i1 = i1 or 1
i2 = i2 or n
if i2 < 0 then
i2 = n + i2 + 1
elseif i2 > n then
i2 = n
end
if i1 < 1 or i1 > n then
return {}
end
local k = 1
for i = i1,i2 do
res[k] = values[i]
k = k + 1
end
return res
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.