hexyz is tower defense game, and a lua library for dealing with hexagonal grids
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.

251 lines
8.4 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. -- text popup in the middle of the screen that dissapates
  2. function gui_alert(message, color, decay_time)
  3. win.scene:append(
  4. am.scale(3) ^ am.text(message, color or COLORS.WHITE)
  5. :action(coroutine.create(function(self)
  6. am.wait(am.tween(self, decay_time or 1, { color = vec4(0) }, am.ease_in_out))
  7. win.scene:remove(self)
  8. end))
  9. )
  10. end
  11. local function gui_make_backing_rect(
  12. position,
  13. content_width,
  14. content_height,
  15. padding
  16. )
  17. local half_width = content_width/2
  18. local half_height = content_height/2
  19. local x1 = position[1] - half_width - padding
  20. local y1 = position[2] - half_height - padding
  21. local x2 = position[1] + half_width + padding
  22. local y2 = position[2] + half_height + padding
  23. return x1, y1, x2, y2
  24. end
  25. -- args {
  26. -- position vec2
  27. -- onclick function
  28. -- padding number
  29. --
  30. -- min_width number
  31. -- min_height number
  32. --
  33. -- label string
  34. -- font {
  35. -- color vec4
  36. -- halign "center" | "left" | "right"
  37. -- valign "center" | "top" | "bottom"
  38. -- }
  39. -- }
  40. function gui_make_button(args)
  41. local args = args or {}
  42. local position = args.position or vec2(0)
  43. local onclick = args.onclick
  44. local padding = args.padding or 6
  45. local min_width = args.min_width or 0
  46. local min_height = args.min_height or 0
  47. local label = args.label or ""
  48. local font = args.font or {
  49. color = vec4(1),
  50. halign = "center",
  51. valign = "center"
  52. }
  53. local scene = am.group()
  54. local text = am.text(args.label or "", font.color, font.halign, font.valign)
  55. scene:append(am.translate(args.position) ^ text)
  56. local content_width = math.max(min_width, text.width)
  57. local content_height = math.max(min_height, text.height)
  58. local x1, y1, x2, y2 = gui_make_backing_rect(position, content_width, content_height, padding)
  59. local back_rect = am.rect(x1 - padding/2, y1, x2, y2 + padding/2, vec4(0, 0, 0, 1))
  60. local front_rect = am.rect(x1, y1, x2, y2, vec4(0.4))
  61. scene:prepend(front_rect)
  62. scene:prepend(back_rect)
  63. scene:action(function(self)
  64. if point_in_rect(win:mouse_position(), back_rect) then
  65. if win:mouse_pressed"left" then
  66. front_rect.color = vec4(0.4)
  67. if onclick then
  68. onclick()
  69. end
  70. else
  71. front_rect.color = vec4(0, 0, 0, 1)
  72. end
  73. else
  74. front_rect.color = vec4(0.4)
  75. end
  76. end)
  77. return scene
  78. end
  79. -- args {
  80. -- position vec2
  81. -- dimensions vec2
  82. -- max number
  83. -- padding number
  84. -- validate function(string) -> bool
  85. -- onchange function(new_value) -> void
  86. -- }
  87. function gui_make_textfield(
  88. args
  89. )
  90. local args = args or {}
  91. local position = args.position or vec2(0)
  92. local dimensions = args.dimensions or vec2(100, 40)
  93. local validate = args.validate or function(string) return true end
  94. local width, height = dimensions.x, dimensions.y
  95. local max = args.max or 10
  96. local padding = args.padding or 6
  97. local half_width = width/2
  98. local half_height = height/2
  99. local x1 = position[1] - half_width - padding
  100. local y1 = position[2] - half_height - padding
  101. local x2 = position[1] + half_width + padding
  102. local y2 = position[2] + half_height + padding
  103. local back_rect = am.rect(x1 - padding/2, y1, x2, y2 + padding/2, vec4(0, 0, 0, 1))
  104. local front_rect = am.rect(x1, y1, x2, y2, vec4(0.4))
  105. local function blink_cursor(cursor)
  106. while true do
  107. am.wait(am.delay(0.4))
  108. cursor.color = vec4(0)
  109. am.wait(am.delay(0.4))
  110. cursor.color = vec4(0, 0, 0, 1)
  111. end
  112. end
  113. local group = am.group{
  114. back_rect,
  115. front_rect,
  116. am.translate(position + vec2(-width/2 + padding, 0)) ^ am.group(
  117. am.scale(2) ^ am.text("", vec4(0, 0, 0, 1), "left"),
  118. (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"
  119. )
  120. }
  121. group"text".text = "";
  122. group:action(function(self)
  123. local keys = win:keys_pressed()
  124. if #keys == 0 then return end
  125. local chars = {}
  126. local shift = win:key_down("lshift") or win:key_down("rshift")
  127. for i,k in pairs(keys) do
  128. if k:len() == 1 then -- @HACK alphabetical or digit characters
  129. if string.match(k, "%a") then
  130. if shift then
  131. table.insert(chars, k:upper())
  132. else
  133. table.insert(chars, k)
  134. end
  135. elseif string.match(k, "%d") then
  136. if shift then
  137. if k == "1" then table.insert(chars, "!")
  138. elseif k == "2" then table.insert(chars, "@")
  139. elseif k == "3" then table.insert(chars, "#")
  140. elseif k == "4" then table.insert(chars, "$")
  141. elseif k == "5" then table.insert(chars, "%")
  142. elseif k == "6" then table.insert(chars, "^")
  143. elseif k == "7" then table.insert(chars, "&")
  144. elseif k == "8" then table.insert(chars, "*")
  145. elseif k == "9" then table.insert(chars, "(")
  146. elseif k == "0" then table.insert(chars, ")")
  147. end
  148. else
  149. table.insert(chars, k)
  150. end
  151. end
  152. -- begin non-alphabetical/digit
  153. elseif k == "minus" then
  154. if shift then table.insert(chars, "_")
  155. else table.insert(chars, "-") end
  156. elseif k == "equals" then
  157. if shift then table.insert(chars, "=")
  158. else table.insert(chars, "+") end
  159. elseif k == "leftbracket" then
  160. if shift then table.insert(chars, "{")
  161. else table.insert(chars, "[") end
  162. elseif k == "rightbracket" then
  163. if shift then table.insert(chars, "}")
  164. else table.insert(chars, "]") end
  165. elseif k == "backslash" then
  166. if shift then table.insert(chars, "|")
  167. else table.insert(chars, "\\") end
  168. elseif k == "semicolon" then
  169. if shift then table.insert(chars, ":")
  170. else table.insert(chars, ";") end
  171. elseif k == "quote" then
  172. if shift then table.insert(chars, "\"")
  173. else table.insert(chars, "'") end
  174. elseif k == "backquote" then
  175. if shift then table.insert(chars, "~")
  176. else table.insert(chars, "`") end
  177. elseif k == "comma" then
  178. if shift then table.insert(chars, "<")
  179. else table.insert(chars, ",") end
  180. elseif k == "period" then
  181. if shift then table.insert(chars, ">")
  182. else table.insert(chars, ".") end
  183. elseif k == "slash" then
  184. if shift then table.insert(chars, "?")
  185. else table.insert(chars, "/") end
  186. -- control characters
  187. elseif k == "backspace" then
  188. -- @NOTE this doesn't preserve the order of chars in the array so if
  189. -- someone presses a the key "a" then the backspace key in the same frame, in that order
  190. -- the backspace occurs first
  191. if self"text".text:len() ~= 0 then
  192. self"text".text = self"text".text:sub(1, self"text".text:len() - 1)
  193. self"cursor".position2d = self"cursor".position2d - vec2(9 * 2, 0)
  194. end
  195. elseif k == "tab" then
  196. -- @TODO
  197. elseif k == "space" then
  198. table.insert(chars, " ")
  199. elseif k == "capslock" then
  200. -- @TODO
  201. end
  202. end
  203. for _,c in pairs(chars) do
  204. if validate(self"text".text .. c) then
  205. if self"text".text:len() <= max then
  206. self"text".text = self"text".text .. c
  207. self"cursor".position2d = self"cursor".position2d + vec2(9 * 2, 0)
  208. end
  209. end
  210. end
  211. end)
  212. function get_value()
  213. return group"text".text
  214. end
  215. return group, get_value
  216. end
  217. function gui_open_modal()
  218. end