diff options
Diffstat (limited to 'src/ui')
| -rw-r--r-- | src/ui/button.moon | 133 | ||||
| -rw-r--r-- | src/ui/checkbox.moon | 13 | ||||
| -rw-r--r-- | src/ui/joystick.moon | 98 | ||||
| -rw-r--r-- | src/ui/textbox.moon | 78 |
4 files changed, 322 insertions, 0 deletions
diff --git a/src/ui/button.moon b/src/ui/button.moon new file mode 100644 index 0000000..9b55a44 --- /dev/null +++ b/src/ui/button.moon @@ -0,0 +1,133 @@ + +s = require("sprites") +util = require("util") +color = require("color") +world = require("world") +sprites = require("sprites") +states = {"up","down"} +rows = {"upper","mid","lower"} +cols = {"left","mid","right"} +class Button + --am.sprite() only works once the window is created + @initialized = false + @initialize: => + 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") + @initialized = true + new: (x,y,w,h,text,font)=> + if not @@initialized + @@initialize! + @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 + )) + @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 + )) + if font + @text = am.text(font, text, "left","top", color.am_color.foreground) + else + @text = am.text(text, "left", "top", color.am_color.foreground) + position\append( + am.translate(@@down_upper_left.width, -@@down_upper_right.height)\append( + am.scale(world.controller.text_size)\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/checkbox.moon b/src/ui/checkbox.moon new file mode 100644 index 0000000..e76a790 --- /dev/null +++ b/src/ui/checkbox.moon @@ -0,0 +1,13 @@ +Button = require("ui.button") +class Checkbox extends Button + fire: (e) => + if e.event == "mouse_down" + if @depressed + @up! + else + @down! + --@down! + if @on + @on(@depressed) + +Checkbox diff --git a/src/ui/joystick.moon b/src/ui/joystick.moon new file mode 100644 index 0000000..98936ed --- /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 + @initialized = false + @initialize: => + @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)) + @initialized = true + new: (x,y,r)=> + if not @@initialized + @@initialize! + @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..38c6d84 --- /dev/null +++ b/src/ui/textbox.moon @@ -0,0 +1,78 @@ + +color = require("color") +Button = require("ui.button") +am.eval_js(require("textbox_bridge")) + +valid_chars = "abcdefghijklmnopqrstuvwxyz" +shifted_nums = "!@#$%^&*()" +i = 0 +class Textbox extends Button + new: (x,y,w,h,value,placeholder) => + super(x,y,w,h,value) + @id = i + i = i + 1 + args = am.to_json({ + name: value or "" + placeholder: placeholder or "" + }) + --am.eval_js("window.amulet.window_has_focus = 0;") + am.eval_js("window.TEXTBOX.create_textbox(" .. args .. ");") + 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\action(() => + if not @should_hide + @hidden = math.floor(am.current_time! * 2) % 2 == 0 + else + @hidden = true + ) + @cursor.should_hide = true + @text\append(@cursor) + @cursor_pos = #@text.text + @update_cursor_pos! + @max_chars = math.huge + @cursor + down: () => + super! + --@cursor.should_hide = false + --@text.color = color.am_color.foreground + print("textbox down") + am.eval_js("window.TEXTBOX.focus(" .. am.to_json({id: @id}) .. ");") + up: () => + super! + print("Textbox up") + am.eval_js("window.TEXTBOX.blur(" .. am.to_json({id: @id}) .. ");") + val = am.eval_js("window.TEXTBOX.get_text(" .. am.to_json({id:@id}) .. ");") + print("Up, got val:", val) + --@cursor.should_hide = true + --@text.color = color.am_color.shadow + update_cursor_pos: () => + @.cursor("translate").x = @cursor_pos * 9 + fire: (e) => + if e.event == "mouse_down" + @down! + if @on + @on(e) + add_key = e.event == "keys_pressed" and @depressed + if add_key + for key in *e.data + if key == "kp_enter" or key == "enter" + if @on + @on(e) + elseif key == "escape" + @up! + + @update_cursor_pos! + text = @text.text + newtext = am.eval_js("window.TEXTBOX.get_text(" .. am.to_json({id:@id}) .. ");") + if newtext != text + @text.text = newtext + if @onchange + @onchange! + false + +Textbox |
