From d3d1fa1430010d9a7bee71253eb3d6352292d305 Mon Sep 17 00:00:00 2001 From: Wally Hackenslacker Date: Sun, 12 Oct 2025 00:36:29 -0400 Subject: [PATCH] Added horizontal bars to UI components. --- src/gstates/menus/options.lua | 43 ++++++++++++- src/ui/bar.lua | 113 ++++++++++++++++++++++++++++++++++ src/ui/chkbox.lua | 55 +++++++++++++++++ src/ui/element.lua | 14 +++++ src/ui/hbox.lua | 4 +- src/ui/layout.lua | 2 +- src/ui/vbox.lua | 4 +- 7 files changed, 227 insertions(+), 8 deletions(-) create mode 100644 src/ui/bar.lua create mode 100644 src/ui/chkbox.lua diff --git a/src/gstates/menus/options.lua b/src/gstates/menus/options.lua index cbe2652..6f1e5e3 100644 --- a/src/gstates/menus/options.lua +++ b/src/gstates/menus/options.lua @@ -10,6 +10,8 @@ local Color = require 'src.utils.color' local HBox = require 'src.ui.hbox' local Label = require 'src.ui.label' local TextButton = require 'src.ui.textbtn' +local Checkbox = require 'src.ui.chkbox' +local Bar = require 'src.ui.bar' ------------------------------------------------------------------------------ @@ -26,12 +28,20 @@ local OptionsMenu = make_class(BaseMenu) function OptionsMenu:_init(parent, title_font, button_font) BaseMenu._init(self, parent, "Options Menu", constants.OPTIONS_MENU, 'imgs/cpu.png') - -- Create UI elements of the main menu. + -- Create UI elements of the menu. self.container:add(Label(nil, nil, 'Options', title_font, Color(215, 0, 0), true)) local box = HBox() box:add(Label(nil, nil, 'Enable Permadeath', button_font)) - box:add(Label(nil, nil, 'X', button_font)) + box:add(Checkbox( + function() + settings.permadeath = not settings.permadeath + end, + function() + return settings.permadeath + end, + 17, + 15)) self.container:add(box) box = HBox() @@ -40,14 +50,41 @@ function OptionsMenu:_init(parent, title_font, button_font) box = HBox() box:add(Label(nil, nil, 'Sound Volume', button_font)) + box:add(Bar( + function(v) + settings.soundvol = math.ceil(v) + end, + function() + return settings.soundvol + end, + 0, 100, + 175, 15)) self.container:add(box) box = HBox() + box.spacing = 13 box:add(Label(nil, nil, 'Music Volume', button_font)) + box:add(Bar( + function(v) + settings.musicvol = math.ceil(v) + end, + function() + return settings.musicvol + end, + 0, 100, + 175, 15)) self.container:add(box) box = HBox() - box:add(TextButton('Go Back', button_font, nil, nil, function() parent.next_menu = constants.MAIN_MENU end)) + box:add(TextButton( + 'Go Back', + button_font, + nil, + nil, + function() + settings:save_settings() + parent.next_menu = constants.MAIN_MENU + end)) self.container:add(box) end diff --git a/src/ui/bar.lua b/src/ui/bar.lua new file mode 100644 index 0000000..c09b43e --- /dev/null +++ b/src/ui/bar.lua @@ -0,0 +1,113 @@ +------------------------------------------------------------------------------ +-- Imports +------------------------------------------------------------------------------ + +local love = require 'love' +local make_class = require 'src.utils.classes' +local collisions = require 'src.utils.colls' +local UIElement = require 'src.ui.element' +local Color = require 'src.utils.color' + + +------------------------------------------------------------------------------ +-- Class definitions +------------------------------------------------------------------------------ + +local Bar = make_class(UIElement) + + +------------------------------------------------------------------------------ +-- Class methods +------------------------------------------------------------------------------ + +function Bar:_init(callback, val_fn, min, max, w, h, color, sel_color, press_col, float, x, y) + UIElement._init(self, x, y, float) + self.callback = callback + self.val_fn = val_fn + self.min = min + self.max = max + self.w = w + self.h = h + self.base_col = color ~= nil and color or Color(255, 255, 255) + self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0) + self.press_col = press_col ~= nil and press_col or Color(99, 99, 139) + self.disbl_col = Color(95, 63, 75) +end + + +function Bar:set_dimensions() + self.w = self.w + self.h = self.h +end + + +function Bar:draw() + local color = self.callback == nil and self.disbl_col or ((self.pressed and self.press_col) or ((self.selected and self.sel_color) or self.base_col)) + + local v = (self.val_fn() + math.abs(self.min)) / (self.max + math.abs(self.min)) + + love.graphics.setColor(color.r, color.g, color.b) + love.graphics.rectangle('line', self.x, self.y, self.w, self.h) + love.graphics.rectangle('fill', self.x, self.y, self.w * v, self.h) + love.graphics.setColor() +end + + +function Bar:_mouse2bar(x) + local v = math.max(math.min(((x - self.x) / self.w), 1.0), 0.0) + return (v * (self.max + math.abs(self.min))) - self.min +end + + +function Bar:mousemoved(x, y) + -- Select if the pointer is inside the button's bounding rect. + self.selected = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h) + + -- If the button was pressed then check if the pointer is no longer inside the button. + if self.pressed then + -- If it's not, then mark the button as "was pressed". + self.pressed = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h) + self.was_pressed = true + self.callback(self:_mouse2bar(x)) + end + + -- If the button was pressed and the pointer is inside the button right now. + if self.was_pressed and collisions.point_in_square(x, y, self.x, self.y, self.w, self.h) then + -- Then mark the button as pressed again. + self.pressed = true + self.was_pressed = false + self.callback(self:_mouse2bar(x)) + end +end + + +function Bar:mousepressed(x, y, btn) + -- If the pointer was inside the button when it was pressed then mark the button as pressed. + if btn == 0 then + self.pressed = collisions.point_in_square(x, y, self.x, self.y, self.w, self.h) + end +end + + +function Bar:mousereleased(x, _, btn) + if btn == 0 then + if self.pressed then + -- If the button was pressed then execute the callback if any and unmark as pressed. + if self.callback ~= nil then + self.callback(self:_mouse2bar(x)) + end + + self.pressed = false + end + + -- The button no longer was pressed. + self.was_pressed = false + end +end + + +------------------------------------------------------------------------------ +-- Module return +------------------------------------------------------------------------------ + +return Bar diff --git a/src/ui/chkbox.lua b/src/ui/chkbox.lua new file mode 100644 index 0000000..97d2f3a --- /dev/null +++ b/src/ui/chkbox.lua @@ -0,0 +1,55 @@ +------------------------------------------------------------------------------ +-- Imports +------------------------------------------------------------------------------ + +local love = require 'love' +local make_class = require 'src.utils.classes' +local Button = require 'src.ui.button' +local Color = require 'src.utils.color' + + +------------------------------------------------------------------------------ +-- Class definitions +------------------------------------------------------------------------------ + +local Checkbox = make_class(Button) + + +------------------------------------------------------------------------------ +-- Class methods +------------------------------------------------------------------------------ + +function Checkbox:_init(callback, value, w, h, color, sel_color, press_col, float, x, y) + Button._init(self, x, y, callback, float) + self.value = value + self.w = w ~= nil and w or 20 + self.h = h ~= nil and h or 20 + self.base_col = color ~= nil and color or Color(255, 255, 255) + self.sel_color = sel_color ~= nil and sel_color or Color(215, 0, 0) + self.press_col = press_col ~= nil and press_col or Color(99, 99, 139) + self.disbl_col = Color(95, 63, 75) +end + + +function Checkbox:set_dimensions() + self.w = self.w + self.h = self.h +end + + +function Checkbox:draw() + local color = self.callback == nil and self.disbl_col or ((self.pressed and self.press_col) or ((self.selected and self.sel_color) or self.base_col)) + local mode = nil + if self.value() then mode = 'fill' else mode = 'line' end + + love.graphics.setColor(color.r, color.g, color.b) + love.graphics.rectangle(mode, self.x, self.y, self.w, self.h) + love.graphics.setColor() +end + + +------------------------------------------------------------------------------ +-- Module return +------------------------------------------------------------------------------ + +return Checkbox diff --git a/src/ui/element.lua b/src/ui/element.lua index 5052b6c..13cd2ee 100644 --- a/src/ui/element.lua +++ b/src/ui/element.lua @@ -34,6 +34,20 @@ function UIElement:set_dimensions() end + +function UIElement:load() +end + + +function UIElement:unload() +end + + +function UIElement:is_loaded() + return true +end + + ------------------------------------------------------------------------------ -- Module return ------------------------------------------------------------------------------ diff --git a/src/ui/hbox.lua b/src/ui/hbox.lua index cd6c8f3..dd88b8e 100644 --- a/src/ui/hbox.lua +++ b/src/ui/hbox.lua @@ -32,7 +32,7 @@ function HBox:load() v.y = self.y v.x = _x - _x = _x + v.w + self.s + _x = _x + v.w + self.spacing end end @@ -42,7 +42,7 @@ function HBox:set_dimensions() self.w = 0 for i, v in pairs(self.elements) do self.w = self.w + v.w - if i < #self.elements then self.w = self.w + self.s end + if i < #self.elements then self.w = self.w + self.spacing end end end diff --git a/src/ui/layout.lua b/src/ui/layout.lua index 3207c65..3e06dc5 100644 --- a/src/ui/layout.lua +++ b/src/ui/layout.lua @@ -23,7 +23,7 @@ function Layout:_init(x, y, w, h, spacing, float) self.y = y ~= nil and y or 0 self.w = w self.h = h - self.s = spacing ~= nil and spacing or 10 + self.spacing = spacing ~= nil and spacing or 10 self.elements = {} end diff --git a/src/ui/vbox.lua b/src/ui/vbox.lua index 1424df6..fac1def 100644 --- a/src/ui/vbox.lua +++ b/src/ui/vbox.lua @@ -36,7 +36,7 @@ function VBox:load() end v.y = _y - _y = _y + v.h + self.s + _y = _y + v.h + self.spacing end end @@ -53,7 +53,7 @@ function VBox:set_dimensions() self.h = 0 for i, v in pairs(self.elements) do self.h = self.h + v.h - if i < #self.elements then self.h = self.h + self.s end + if i < #self.elements then self.h = self.h + self.spacing end end end end