Last active
January 16, 2019 13:31
-
-
Save flamewing/5f33a42aa5d1a7e46f412483065a2b43 to your computer and use it in GitHub Desktop.
Moonscript experiments
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-------------------------------------------------------------------------------- | |
-- This file is part of the Lua HUD for TASing Sega Genesis Sonic games. | |
-- | |
-- This program is free software: you can redistribute it and/or modify | |
-- it under the terms of the GNU Lesser General Public License as | |
-- published by the Free Software Foundation, either version 3 of the | |
-- License, or (at your option) any later version. | |
-- | |
-- This program is distributed in the hope that it will be useful, | |
-- but WITHOUT ANY WARRANTY; without even the implied warranty of | |
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
-- GNU General Public License for more details. | |
-- | |
-- You should have received a copy of the GNU Lesser General Public License | |
-- along with this program. If not, see <http://www.gnu.org/licenses/>. | |
-------------------------------------------------------------------------------- | |
-------------------------------------------------------------------------------- | |
-- User interface widgets for Lua in Gens. | |
-- Written by: Marzo Junior | |
-------------------------------------------------------------------------------- | |
require "headers/input-handler" | |
require "headers/ui-icons" | |
-------------------------------------------------------------------------------- | |
-- Export all names from this module | |
-------------------------------------------------------------------------------- | |
export * | |
-------------------------------------------------------------------------------- | |
-- A couple static assertions | |
-------------------------------------------------------------------------------- | |
assert_widget = (obj) -> assert obj != nil and obj.__class == Widget | |
assert_function = (fun) -> | |
ty = type(fun) | |
assert ty == "function", debug.traceback("Error: Function expected for variable 'fun', got '#{ty}'.") | |
-------------------------------------------------------------------------------- | |
-- Generic abstract base interface: store position only. | |
-- Should not be used on its own. | |
-------------------------------------------------------------------------------- | |
class Widget | |
add: (child, dx, dy) => | |
error debug.traceback("Error: Pure virtual function 'Widget:add' called."), 0 | |
-- Note: calling this from any but derived widgets with an 'add' member will | |
-- result in an error. | |
add_status_icon: (dx, dy, image, text, border, fill, txtxoff = 20, txtyoff = 4) => | |
icon = Icon_widget 0, 0, image | |
watch = Text_widget 0, 0, text, border, fill | |
@add icon, dx, dy | |
@add watch, dx + txtxoff, dy + txtyoff | |
-- Move to different location. | |
move: (x, y) => @x, @y = x, y | |
-- Create widget and set position. | |
new: (x, y) => @x, @y = x, y | |
-------------------------------------------------------------------------------- | |
-- A widget which displays an image. | |
-------------------------------------------------------------------------------- | |
class Icon_widget extends Widget | |
-- 'image' can be a gdimage or a drawing function. The latter requires an | |
-- object to be supplied so that the function knowns what to do. | |
new: (x, y, image) => | |
super x, y | |
@image = image | |
switch type(image) | |
when "function" | |
@draw = => | |
gui.drawimage @x, @y, ui_icons[@\image!] | |
true | |
when "string" | |
@draw = => | |
gui.drawimage @x, @y, ui_icons[@image] | |
true | |
else | |
@draw = => false | |
-------------------------------------------------------------------------------- | |
-- A widget which displays text. | |
-------------------------------------------------------------------------------- | |
class Text_widget extends Widget | |
-- 'image' can be a raw string or a function. The latter requires an | |
-- object to be supplied so that the function knowns what to do. | |
new: (x, y, text, border = {0, 0, 0, 0}, fill = {255, 255, 255, 255}) => | |
super x, y | |
@text = text | |
@border = border | |
@fill = fill | |
switch type(text) | |
when "function" | |
@draw = => | |
gui.text @x, @y, @\text!, @fill, @border | |
true | |
when "string" | |
@draw = => | |
gui.text @x, @y, @text, @fill, @border | |
true | |
else | |
@draw = => false | |
-------------------------------------------------------------------------------- | |
-- A container widget which draws a rectangular box. | |
-------------------------------------------------------------------------------- | |
class Frame_widget extends Widget | |
-- Children are added relative. | |
add: (child, dx, dy) => | |
assert_widget child | |
child\move @x + dx, @y + dy | |
table.insert @children, child | |
-- Moves all children too. | |
move: (x, y) => | |
super x, y | |
dx = x - @x | |
dy = y - @y | |
for _,m in pairs @children | |
m\move m.x + dx, m.y + dy | |
-- Also draws the contained widgets. | |
draw: => | |
gui.box @x, @y, @x + @w, @y + @h, @fill, @border | |
for _,m in pairs @children | |
m\draw! | |
true | |
new: (x, y, w, h, border = {0, 0, 127, 255}, fill = {0, 0, 0, 192}) => | |
super x, y | |
@w = w | |
@h = h | |
@border = border | |
@fill = fill | |
@children = {} | |
-------------------------------------------------------------------------------- | |
-- A clickable version of a frame widget. | |
-------------------------------------------------------------------------------- | |
class Clickable_widget extends Frame_widget | |
-- Check if mouse is on the widget's area. | |
is_hot: => | |
@hot = (mouse.x >= @x) and (mouse.y >= @y) and (mouse.x <= @x + @w) and (mouse.y <= @y + @h) | |
-- Draw widget with different colors to indicate 'hot' or being clicked. | |
draw: => | |
fill = @fill | |
border = @border | |
if @\is_hot! | |
border = {255, 255, 255, 255} | |
if mouse.click | |
fill = {127, 0, 0, 255} | |
@.on_click @udata | |
else | |
fill = {0, 0, 127, 255} | |
gui.box @x, @y, @x + @w, @y + @h, fill, border | |
for _,m in pairs @children | |
m\draw! | |
true | |
new: (callback, udata, text, w, h, border = {0, 0, 255, 255}, fill = {0, 0, 127, 255}) => | |
assert_function callback | |
super x, y, w, h, border, fill | |
@hot = false | |
@on_click = callback | |
@udata = udata | |
make_button: (callback, udata, text, w, h, border, fill) -> | |
btn = Clickable_widget 0, 0, w, h, callback, udata, border, fill | |
btn\add Text_widget(0, 0, text), 1 + math.floor((w + 1 - 4 * #text)/2), 1 | |
btn | |
-------------------------------------------------------------------------------- | |
-- Clickable widget with 'on' and 'off' states. This widget has a separate | |
-- list of children that are drawn if the widget is 'off'. | |
-------------------------------------------------------------------------------- | |
class Toggle_widget extends Clickable_widget | |
get_children: => | |
if @active | |
@children | |
else | |
@off_children | |
add: (child, dx, dy, active) => | |
assert_widget child | |
child\move @x + dx, @y + dy | |
table.insert @\get_children!, child | |
move: (x, y) => | |
@x, @y = x, y | |
dx = x - @x | |
dy = y - @y | |
for _,m in pairs @children | |
m\move m.x + dx, m.y + dy | |
for _,m in pairs @off_children | |
m\move m.x + dx, m.y + dy | |
draw: => | |
fill = @fill | |
border = @border | |
if @\is_hot! | |
border = {255, 255, 255, 255} | |
if mouse.click | |
fill = {127, 0, 0, 255} | |
@.on_click @udata | |
else | |
fill = {0, 0, 127, 255} | |
gui.box @x, @y, @x + @w, @y + @h, fill, border | |
for _,m in pairs @\get_children! | |
m\draw! | |
true | |
-- 'callback' is a function to be called when the container is 'toggled'. | |
-- 'udata' is an object which is passed to 'callback'. | |
new: (x, y, w, h, callback, udata, active, border = {0, 0, 255, 255}, fill = {0, 0, 127, 255}) => | |
super x, y, w, h, callback, udata, border, fill | |
@active = active | |
@off_children = {} | |
make_toggle: (dim, horiz, callback, udata, active) -> | |
local w, h | |
if horiz | |
w, h = dim, 3 | |
else | |
w, h = 3, dim | |
Toggle_widget 0, 0, w, h, callback, udata, active | |
-------------------------------------------------------------------------------- | |
-- Container widget with a separate toggle widget. The toggle widget is used | |
-- to toggle the display of the container's children on or off. | |
-------------------------------------------------------------------------------- | |
class Container_widget extends Widget | |
toggled: => @active = not @active | |
set_state: (flag) => | |
@active = flag | |
if @toggle | |
@toggle.active = flag | |
add: (child, dx, dy) => | |
assert_widget child | |
child\move @x + dx, @y + dy | |
table.insert @\get_children!, child | |
add_toggle: (child, dx, dy) => | |
assert_widget child | |
child\move @x + dx, @y + dy | |
@toggle = child | |
move: (x, y) => | |
@x, @y = x, y | |
dx = x - @x | |
dy = y - @y | |
if @toggle | |
@toggle\move @toggle.x + dx, @toggle.y + dy | |
for _,m in pairs @children | |
m\move m.x + dx, m.y + dy | |
draw: => | |
if @active | |
for _,m in pairs @children | |
m\draw! | |
if @toggle | |
@toggle\draw! | |
@active | |
new: (x, y, active = false) => | |
super x, y | |
@active = active | |
@children = {} | |
@toggle = nil | |
-------------------------------------------------------------------------------- | |
-- Container which only shows if certain definable conditions hold. | |
-------------------------------------------------------------------------------- | |
class Conditional_widget extends Container_widget | |
add_toggle: (child, dx, dy) => | |
assert_widget child | |
error debug.traceback("Error: Container_widget cannot have a toggle."), 0 | |
move: (x, y) => | |
@x, @y = x, y | |
dx = x - @x | |
dy = y - @y | |
for _,m in pairs @children | |
m\move m.x + dx, m.y + dy | |
draw: => | |
@active = @.is_active @obj | |
if @active | |
for _,m in pairs @children | |
m\draw! | |
@active | |
-- 'is_active' is a function that defines the conditions under which the | |
-- widget appears. 'obj' is an object which is passed to 'is_active'. | |
new: (x, y, active = false, is_active = (=> false), obj = nil) => | |
assert_function is_active | |
super x, y, active | |
@is_active = is_active | |
@children = {} | |
@obj = obj |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment