You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
8.5 KiB
256 lines
8.5 KiB
|
|
-- text popup in the middle of the screen that dissapates
|
|
function gui_alert(message, color, decay_time)
|
|
win.scene:append(
|
|
am.scale(3) ^ am.text(message, color or COLORS.WHITE)
|
|
:action(coroutine.create(function(self)
|
|
am.wait(am.tween(self, decay_time or 1, { color = vec4(0) }, am.ease_in_out))
|
|
win.scene:remove(self)
|
|
end))
|
|
)
|
|
end
|
|
|
|
local function gui_make_backing_rect(
|
|
position,
|
|
content_width,
|
|
content_height,
|
|
padding
|
|
)
|
|
local half_width = content_width/2
|
|
local half_height = content_height/2
|
|
|
|
local x1 = position[1] - half_width - padding
|
|
local y1 = position[2] - half_height - padding
|
|
local x2 = position[1] + half_width + padding
|
|
local y2 = position[2] + half_height + padding
|
|
|
|
return x1, y1, x2, y2
|
|
end
|
|
|
|
-- args {
|
|
-- position vec2
|
|
-- onclick function
|
|
-- padding number
|
|
--
|
|
-- min_width number
|
|
-- min_height number
|
|
--
|
|
-- label string
|
|
-- font {
|
|
-- color vec4
|
|
-- halign "center" | "left" | "right"
|
|
-- valign "center" | "top" | "bottom"
|
|
-- }
|
|
-- }
|
|
function gui_make_button(args)
|
|
local args = args or {}
|
|
|
|
local position = args.position or vec2(0)
|
|
local onclick = args.onclick
|
|
local padding = args.padding or 6
|
|
|
|
local min_width = args.min_width or 0
|
|
local min_height = args.min_height or 0
|
|
|
|
local label = args.label or ""
|
|
local font = args.font or {
|
|
color = vec4(1),
|
|
halign = "center",
|
|
valign = "center"
|
|
}
|
|
|
|
local scene = am.group()
|
|
|
|
local text = am.text(args.label or "", font.color, font.halign, font.valign)
|
|
scene:append(am.translate(args.position) ^ text)
|
|
|
|
local content_width = math.max(min_width, text.width)
|
|
local content_height = math.max(min_height, text.height)
|
|
|
|
local x1, y1, x2, y2 = gui_make_backing_rect(position, content_width, content_height, padding)
|
|
|
|
local back_rect = am.rect(x1 - padding/2, y1, x2, y2 + padding/2, vec4(0, 0, 0, 1))
|
|
local front_rect = am.rect(x1, y1, x2, y2, vec4(0.4))
|
|
scene:prepend(front_rect)
|
|
scene:prepend(back_rect)
|
|
|
|
scene:action(function(self)
|
|
if point_in_rect(win:mouse_position(), back_rect) then
|
|
if win:mouse_pressed"left" then
|
|
front_rect.color = vec4(0.4)
|
|
|
|
if onclick then
|
|
onclick()
|
|
end
|
|
else
|
|
front_rect.color = vec4(0, 0, 0, 1)
|
|
end
|
|
else
|
|
front_rect.color = vec4(0.4)
|
|
end
|
|
end)
|
|
|
|
return scene
|
|
end
|
|
|
|
-- args {
|
|
-- position vec2
|
|
-- dimensions vec2
|
|
-- max number
|
|
-- padding number
|
|
-- validate function(string) -> bool
|
|
-- onchange function(new_value) -> void
|
|
-- }
|
|
function gui_make_textfield(
|
|
args
|
|
)
|
|
local args = args or {}
|
|
local position = args.position or vec2(0)
|
|
local dimensions = args.dimensions or vec2(100, 40)
|
|
local validate = args.validate or function(string) return true end
|
|
local width, height = dimensions.x, dimensions.y
|
|
local max = args.max or 10
|
|
local padding = args.padding or 6
|
|
local half_width = width/2
|
|
local half_height = height/2
|
|
|
|
local x1 = position[1] - half_width - padding
|
|
local y1 = position[2] - half_height - padding
|
|
local x2 = position[1] + half_width + padding
|
|
local y2 = position[2] + half_height + padding
|
|
|
|
local back_rect = am.rect(x1 - padding/2, y1, x2, y2 + padding/2, vec4(0, 0, 0, 1))
|
|
local front_rect = am.rect(x1, y1, x2, y2, vec4(0.4))
|
|
|
|
local function blink_cursor(cursor)
|
|
while true do
|
|
am.wait(am.delay(0.4))
|
|
cursor.color = vec4(0)
|
|
am.wait(am.delay(0.4))
|
|
cursor.color = vec4(0, 0, 0, 1)
|
|
end
|
|
end
|
|
|
|
local group = am.group{
|
|
back_rect,
|
|
front_rect,
|
|
am.translate(position + vec2(-width/2 + padding, 0)) ^ am.group(
|
|
am.scale(2) ^ am.text("", vec4(0, 0, 0, 1), "left"),
|
|
(am.translate(0, -8) ^ am.line(vec2(0, 0), vec2(16, 0), 2, vec4(0, 0, 0, 1)):action(coroutine.create(blink_cursor))):tag"cursor"
|
|
)
|
|
}
|
|
|
|
group"text".text = "";
|
|
|
|
group:action(function(self)
|
|
local keys = win:keys_pressed()
|
|
if #keys == 0 then return end
|
|
|
|
local chars = {}
|
|
local shift = win:key_down("lshift") or win:key_down("rshift")
|
|
for i,k in pairs(keys) do
|
|
if k:len() == 1 then -- @HACK alphabetical or digit characters
|
|
if string.match(k, "%a") then
|
|
if shift then
|
|
table.insert(chars, k:upper())
|
|
else
|
|
table.insert(chars, k)
|
|
end
|
|
elseif string.match(k, "%d") then
|
|
if shift then
|
|
if k == "1" then table.insert(chars, "!")
|
|
elseif k == "2" then table.insert(chars, "@")
|
|
elseif k == "3" then table.insert(chars, "#")
|
|
elseif k == "4" then table.insert(chars, "$")
|
|
elseif k == "5" then table.insert(chars, "%")
|
|
elseif k == "6" then table.insert(chars, "^")
|
|
elseif k == "7" then table.insert(chars, "&")
|
|
elseif k == "8" then table.insert(chars, "*")
|
|
elseif k == "9" then table.insert(chars, "(")
|
|
elseif k == "0" then table.insert(chars, ")")
|
|
end
|
|
else
|
|
table.insert(chars, k)
|
|
end
|
|
end
|
|
-- begin non-alphabetical/digit
|
|
elseif k == "minus" then
|
|
if shift then table.insert(chars, "_")
|
|
else table.insert(chars, "-") end
|
|
elseif k == "equals" then
|
|
if shift then table.insert(chars, "=")
|
|
else table.insert(chars, "+") end
|
|
elseif k == "leftbracket" then
|
|
if shift then table.insert(chars, "{")
|
|
else table.insert(chars, "[") end
|
|
elseif k == "rightbracket" then
|
|
if shift then table.insert(chars, "}")
|
|
else table.insert(chars, "]") end
|
|
elseif k == "backslash" then
|
|
if shift then table.insert(chars, "|")
|
|
else table.insert(chars, "\\") end
|
|
elseif k == "semicolon" then
|
|
if shift then table.insert(chars, ":")
|
|
else table.insert(chars, ";") end
|
|
elseif k == "quote" then
|
|
if shift then table.insert(chars, "\"")
|
|
else table.insert(chars, "'") end
|
|
elseif k == "backquote" then
|
|
if shift then table.insert(chars, "~")
|
|
else table.insert(chars, "`") end
|
|
elseif k == "comma" then
|
|
if shift then table.insert(chars, "<")
|
|
else table.insert(chars, ",") end
|
|
elseif k == "period" then
|
|
if shift then table.insert(chars, ">")
|
|
else table.insert(chars, ".") end
|
|
elseif k == "slash" then
|
|
if shift then table.insert(chars, "?")
|
|
else table.insert(chars, "/") end
|
|
|
|
-- control characters
|
|
elseif k == "backspace" then
|
|
-- @NOTE this doesn't preserve the order of chars in the array so if
|
|
-- someone presses a the key "a" then the backspace key in the same frame, in that order
|
|
-- the backspace occurs first
|
|
if self"text".text:len() ~= 0 then
|
|
self"text".text = self"text".text:sub(1, self"text".text:len() - 1)
|
|
self"cursor".position2d = self"cursor".position2d - vec2(9 * 2, 0)
|
|
self"cursor".hidden = false
|
|
end
|
|
elseif k == "tab" then
|
|
-- @TODO
|
|
|
|
elseif k == "space" then
|
|
table.insert(chars, " ")
|
|
|
|
elseif k == "capslock" then
|
|
-- @TODO
|
|
end
|
|
end
|
|
|
|
for _,c in pairs(chars) do
|
|
if validate(self"text".text .. c) then
|
|
local len = self"text".text:len()
|
|
if len <= max then
|
|
self"text".text = self"text".text .. c
|
|
self"cursor".position2d = self"cursor".position2d + vec2(9 * 2, 0)
|
|
if len == max then
|
|
self"cursor".hidden = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
function get_value()
|
|
return group"text".text
|
|
end
|
|
|
|
return group, get_value
|
|
end
|
|
|
|
function gui_open_modal()
|
|
|
|
end
|
|
|