summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorAlexander M Pickering <alex@cogarr.net>2025-01-09 18:11:46 -0600
committerAlexander M Pickering <alex@cogarr.net>2025-01-09 18:11:46 -0600
commitdecb72f936060a65bff18e9cbf33642ea3a71cd0 (patch)
tree3b07bb1bfc1e4f0e39ec4ff8e0c243cd4fab0d61 /src/ui
parent726876d42270f8974fd495be91127ea7585472ff (diff)
downloadggj25-decb72f936060a65bff18e9cbf33642ea3a71cd0.tar.gz
ggj25-decb72f936060a65bff18e9cbf33642ea3a71cd0.tar.bz2
ggj25-decb72f936060a65bff18e9cbf33642ea3a71cd0.zip
Work
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/button.moon131
-rw-r--r--src/ui/joystick.moon98
-rw-r--r--src/ui/textbox.moon119
3 files changed, 348 insertions, 0 deletions
diff --git a/src/ui/button.moon b/src/ui/button.moon
new file mode 100644
index 0000000..789ecae
--- /dev/null
+++ b/src/ui/button.moon
@@ -0,0 +1,131 @@
+
+s = require("ui.sprites")
+util = require("util")
+color = require("color")
+states = {"up","down"}
+rows = {"upper","mid","lower"}
+cols = {"left","mid","right"}
+class Button
+ --am.sprite() only works once the window is created
+ @initalized = false
+ @initalize: =>
+ for _, state, _, row, _, col in util.cartesian(states, rows, cols)
+ name = table.concat({state,row,col},"_")
+ assert(s["button_" .. name], "Failed to find sprite:" .. name)
+ @[name] = am.sprite(s["button_" .. name],"left","top")
+ @initalized = true
+ new: (x,y,w,h,text)=>
+ if not @@initalized
+ @@initalize!
+ @em = 16 -- width of a character
+ text = text or ""
+ assert(w > 15, "Button must have at least width 15")
+ @node = am.group!
+ position = am.translate(x,y+h)\tag("position")
+ @up_sprites = am.group!
+ position\append(@up_sprites)
+ @down_sprites = am.group!
+ @node\append(position)
+ @up_sprites\append(@@up_upper_left)
+ @up_sprites\append(
+ am.translate(@@up_upper_left.width,0)\append(
+ am.scale(w - @@up_upper_left.width - @@up_upper_right.width,1)\append(
+ @@up_upper_mid
+ )))
+ @up_sprites\append(
+ am.translate(w - @@up_upper_right.width, 0)\append(
+ @@up_upper_right
+ ))
+ mid_height = h - @@up_upper_left.height - @@up_lower_left.height
+ @up_sprites\append(
+ am.translate(0,-@@up_upper_left.height)\append(
+ am.scale(1,mid_height)\append(
+ @@up_mid_left
+ )))
+ @up_sprites\append(
+ am.translate(@@up_upper_left.width, -@@up_upper_left.height)\append(
+ am.scale(w - @@up_mid_left.width - @@up_mid_right.width, h - @@up_upper_mid.height - @@up_lower_mid.height)\append(
+ @@up_mid_mid
+ )))
+ @up_sprites\append(
+ am.translate(w - @@up_mid_right.width,-@@up_upper_right.height)\append(
+ am.scale(1,h - @@up_upper_right.height - @@up_lower_right.height)\append(
+ @@up_mid_right
+ )))
+ @up_sprites\append(
+ am.translate(0,-(h - @@up_lower_left.height))\append(
+ @@up_lower_left
+ ))
+ @up_sprites\append(
+ am.translate(@@up_lower_left.width,-(h - @@up_lower_mid.height))\append(
+ am.scale(w - @@up_lower_left.width - @@up_lower_right.width,1)\append(
+ @@up_lower_mid
+ )))
+ @up_sprites\append(
+ am.translate(w - @@up_lower_right.width, -(h - @@up_lower_right.height))\append(
+ @@up_lower_right
+ ))
+ @up_sprites\append(
+ am.translate(@@up_upper_left.width, -@@up_upper_right.height)\append(
+ am.text(text, "left","top", color.am_color.foreground)
+ ))
+ @down_sprites\append(@@down_upper_left)
+ @down_sprites\append(
+ am.translate(@@down_upper_left.width,0)\append(
+ am.scale(w - @@down_upper_left.width - @@down_upper_right.width,1)\append(
+ @@down_upper_mid
+ )))
+ @down_sprites\append(
+ am.translate(w - @@down_upper_right.width, 0)\append(
+ @@down_upper_right
+ ))
+ mid_height = h - @@down_upper_left.height - @@down_lower_left.height
+ @down_sprites\append(
+ am.translate(0,-@@down_upper_left.height)\append(
+ am.scale(1,mid_height)\append(
+ @@down_mid_left
+ )))
+ @down_sprites\append(
+ am.translate(@@down_upper_left.width, -@@down_upper_left.height)\append(
+ am.scale(w - @@down_mid_left.width - @@down_mid_right.width, h - @@down_upper_mid.height - @@down_lower_mid.height)\append(
+ @@down_mid_mid
+ )))
+ @down_sprites\append(
+ am.translate(w - @@down_mid_right.width,-@@down_upper_right.height)\append(
+ am.scale(1,h - @@down_upper_right.height - @@down_lower_right.height)\append(
+ @@down_mid_right
+ )))
+ @down_sprites\append(
+ am.translate(0,-(h - @@down_lower_left.height))\append(
+ @@down_lower_left
+ ))
+ @down_sprites\append(
+ am.translate(@@down_lower_left.width,-(h - @@down_lower_mid.height))\append(
+ am.scale(w - @@down_lower_left.width - @@down_lower_right.width,1)\append(
+ @@down_lower_mid
+ )))
+ @down_sprites\append(
+ am.translate(w - @@down_lower_right.width, -(h - @@down_lower_right.height))\append(
+ @@down_lower_right
+ ))
+ @text = am.text(text, "left","top", color.am_color.foreground)
+ position\append(
+ am.translate(@@down_upper_left.width, -@@down_upper_right.height)\append(
+ @text
+ ))
+ @depressed = false
+ down: () =>
+ @depressed = true
+ @.node("position")\replace(@up_sprites, @down_sprites)
+ up: () =>
+ @depressed = false
+ @.node("position")\replace(@down_sprites, @up_sprites)
+ fire: (e) =>
+ if e.event == "touches_began" or e.event == "mouse_down"
+ @down!
+ if @on
+ @on(e)
+ if e.event == "touches_ended" or e.event == "mouse_up"
+ @up!
+
+Button
diff --git a/src/ui/joystick.moon b/src/ui/joystick.moon
new file mode 100644
index 0000000..168e18b
--- /dev/null
+++ b/src/ui/joystick.moon
@@ -0,0 +1,98 @@
+
+color = require("color")
+window = require("window")
+
+circle_cache = setmetatable({},{__mode: "v"})
+hollow_circle = (x,y,radius, thickness, color) ->
+ key = string.format("%d\0%d\0%d\0%d",x,y,radius, thickness)
+ if circle_cache[key]
+ return circle_cache[key]
+ arr = {}
+ segments = 60
+ step = (2*math.pi) / segments
+ for i = 0,2*math.pi, step
+ arr[#arr+1] = vec2(i+step, 1)
+ arr[#arr+1] = vec2(i, 1)
+ arr[#arr+1] = vec2(i+step,0)
+ arr[#arr+1] = vec2(i+step,0)
+ arr[#arr+1] = vec2(i,1)
+ arr[#arr+1] = vec2(i,0)
+ circle = am.use_program(am.program([[
+ precision highp float;
+ attribute vec2 index;
+ uniform float thickness;
+ uniform float radius;
+ uniform mat4 MV;
+ uniform mat4 P;
+ void main() {
+ float distance = thickness * index[1];
+ vec2 vert = vec2(cos(index[0]) * (radius - distance), sin(index[0]) * (radius - distance));
+ gl_Position = P * MV * vec4(vert, 0.0, 1.0);
+ }
+ ]],[[
+ precision mediump float;
+ uniform vec4 color;
+ void main() {
+ gl_FragColor = color;
+ }
+ ]]))\append(am.bind({
+ MV: mat4(
+ 1, 0, 0, 0
+ 0, 1, 0, 0
+ 0, 0, 1, 0
+ x, y, 0, 1
+ )
+ thickness: thickness
+ radius: radius
+ index: am.vec2_array(arr)
+ color: color
+ })\append(am.draw("triangles")))
+ circle_cache[key] = circle
+ circle
+
+class Joystick
+ --am.sprite() only works once the window is created
+ @initalized = false
+ @initalize: =>
+ @hollow_circle = am.group!
+ step = 0.5
+ thickness = 0.02
+ lastpoint = vec2(1,0)
+ print("color.am_color.background is:", color.am_color.background)
+ for k,v in pairs(color.am_color)
+ print(k,":",v)
+ highlight_start = (5/8) * math.pi
+ highlight_end = (7/8) * math.pi
+ shadow_start = (3/2) * math.pi
+ shadow_end = 2 * math.pi
+ for i = 0,2*math.pi,step
+ nextpoint = vec2(math.cos(i), math.sin(i))
+ @hollow_circle\append(am.line(lastpoint + vec2(1,1), nextpoint + vec2(1,1), thickness, color.am_color.outline))
+ --@hollow_circle\append(am.line(lastpoint, nextpoint, thickness, color.am_color.background))
+ lastpoint = nextpoint
+ @hollow_circle\append(am.line(lastpoint, vec2(1,0), thickness * 2, color.am_color.outline))
+ @hollow_circle\append(am.line(lastpoint,vec2(1,0), thickness, color.am_color.background))
+ @initalized = true
+ new: (x,y,r)=>
+ if not @@initalized
+ @@initalize!
+ @node = am.group!
+ position = am.translate(x,y)\tag("position")
+ @node\append(position)
+ --position\append(am.circle(vec2(x,y), r, color.am_color.background))
+ @stick_pos = am.translate(0,0)\tag("stick")
+ position\append(
+ @stick_pos\append(
+ am.circle(vec2(0,0), r/9, color.am_color.outline)\append(
+ am.circle(vec2(0,0), r/10, color.am_color.background)\append(
+ am.circle(vec2(-r/60,r/60),r/15, color.am_color.foreground)\append(
+ am.circle(vec2(5,-5),r/13, color.am_color.background)
+ )))))
+ --position\append(am.scale(r,r)\append(@@hollow_circle))
+ --position\append(am.circle(vec2(x,y),r)\append(am.blend("subtract")\append(am.circle(vec2(x,y),r-10))))
+ position\append(hollow_circle(x,y,r,8,color.am_color.outline))
+ position\append(hollow_circle(x,y,r-math.sqrt(2),5,color.am_color.background))
+ fire: (tbl) =>
+ print("Fired",tbl)
+
+Joystick
diff --git a/src/ui/textbox.moon b/src/ui/textbox.moon
new file mode 100644
index 0000000..3c6151d
--- /dev/null
+++ b/src/ui/textbox.moon
@@ -0,0 +1,119 @@
+
+color = require("color")
+Button = require("ui.button")
+
+valid_chars = "abcdefghijklmnopqrstuvwxyz"
+shifted_nums = "!@#$%^&*()"
+class Textbox extends Button
+ new: (x,y,w,h,value,placeholder) =>
+ super(x,y,w,h,value)
+ if value == ""
+ @text.text = placeholder
+ @text.color = color.am_color.shadow
+ @cursor = am.group(
+ am.translate(@em,0)\append(
+ am.rect(0,0,@em/4,-@em,color.am_color.foreground)
+ ))
+ @cursor.hidden = true
+ @text\append(@cursor)
+ @cursor_pos = #@text.text
+ @update_cursor_pos!
+ @valid_chars = {}
+ @max_chars = math.huge
+ for i = 1, #valid_chars
+ char = valid_chars\sub(i,i)
+ @valid_chars[char] = char
+ @valid_chars[char\upper] = char\upper
+ for i = 0,9
+ @valid_chars[tostring(i)] = tostring(i)
+ @valid_chars["kp_" .. tostring(i)] = tostring(i)
+ @valid_chars.kp_divide = "/"
+ @valid_chars.kp_multiply = "*"
+ @valid_chars.kp_minus = "-"
+ @valid_chars.kp_plus = "+"
+ @valid_chars.kp_period = "."
+ @valid_chars.space = " "
+ @valid_chars.minus = "-"
+ @valid_chars.MINUS = "_"
+ @valid_chars.equals = "="
+ @valid_chars.EQUALS = "+"
+ @valid_chars.leftbracket = "["
+ @valid_chars.LEFTBRACKET = "{"
+ @valid_chars.rightbracket = "]"
+ @valid_chars.RIGHTBRACKET = "}"
+ @valid_chars.semicolon = ";"
+ @valid_chars.SEMICOLON = ":"
+ @valid_chars.quote = "'"
+ @valid_chars.QUOTE = '"'
+ @valid_chars.backquote = "`"
+ @valid_chars.BACKQUOTE = "~"
+ @valid_chars.comma = ","
+ @valid_chars.COMMA = "<"
+ @valid_chars.period = "."
+ @valid_chars.PERIOD = ">"
+ @valid_chars.slash = "/"
+ @valid_chars.SLASH = "?"
+ @cursor
+ down: () =>
+ super!
+ @cursor.hidden = false
+ @text.color = color.am_color.foreground
+ up: () =>
+ super!
+ @cursor.hidden = true
+ @text.color = color.am_color.shadow
+ update_cursor_pos: () =>
+ @.cursor("translate").x = @cursor_pos * 9
+ fire: (e) =>
+ print("cursor pos is", @cursor_pos)
+ if e.event == "mouse_down"
+ @down!
+ if @on
+ @on(e)
+ add_key = e.event == "keys_pressed" and @depressed
+ if add_key
+ t = @text.text
+ for key in *e.data
+ print("analyzing key:",key)
+ if key == "delete" or key == "backspace"
+ @cursor_pos -=1
+ if @cursor_pos < 0
+ @cursor_pos = 0
+ t = t\sub(1,@cursor_pos) .. t\sub(@cursor_pos+2)
+ elseif key == "home"
+ @cursor_pos = 0
+ elseif key == "end"
+ @cursor_pos = #t
+ elseif key == "right"
+ @cursor_pos += 1
+ if @cursor_pos > #t
+ @cursor_pos = #t
+ elseif key == "left"
+ @cursor_pos -= 1
+ if @cursor_pos < 0
+ @cursor_pos = 0
+ elseif tonumber(key) and tonumber(key) >= 0 and tonumber(key) <= 9
+ kn = tonumber(key)
+ nd = key
+ if e.shift
+ nd = shifted_nums\sub(kn,kn)
+ @cursor_pos += 1
+ t = t\sub(1,@cursor_pos) .. nd .. t\sub(@cursor_pos)
+ elseif key == "kp_enter" or key == "enter"
+ if @on
+ @on(e)
+ elseif key == "escape"
+ @up!
+ else
+ if e.shift and key\sub(1,3) ~= "kp_"
+ key = key\upper!
+ if @valid_chars[key]
+ @cursor_pos += 1
+ t = t\sub(0,@cursor_pos) .. @valid_chars[key] .. t\sub(@cursor_pos)
+ if #t > @max_chars
+ t = t\sub(1,@max_chars)
+ @text.text = t
+ @update_cursor_pos!
+ add_key
+
+Textbox