Buttons // Annoying!

Hello, i love coding but, the thing that gets me fustrated is buttons!!!
i would like a button class but please; tell me what to do to make a callback when i touch the button. Thanks :slight_smile:

@NoobDoge, I have created a button class not too long ago that I’m willing to share with you. It’s pretty good-looking in my opinion and easy to use. It’s about as easy to use as the parameter buttons. Here’s the class along with some code using the class as an example:

-- Use this function to perform your initial setup
function setup()
    fontSize(50)
    Test = Button({pos=vec2(500,400),text="Green Button",colour=color(0,255,0),colourSharpness=140,callback=function() print("Button Pressed!") end})
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)
    
    Test:draw()
end

function touched(t)
    Test:press(t)
end

function brighten(c,amount)
    return color(c.r+amount,c.g+amount,c.b+amount,c.a)
end

function pointInRectCenter(pointX, pointY, x, y, w, h)
    return pointX >= x - w/2 and pointX <= x + w/2 and pointY >= y - h/2 and pointY <= y + h/2
end

-- Button
Button = class()
function Button:init(data)
    pushMatrix()
    
    self.callback = data.callback
    self.pos = vec2(data.pos.x,data.pos.y) or vec2(data.x,data.y) or vec2(0,0)
    self.txt = data.text or "Button"
    self.txtC = data.textColour or color(40)
    self.font = data.font or "Futura-Medium"
    self.size = data.size or 50
    fontSize(self.size)
    local w,h = textSize(data.text)
    self.c = data.colour or color(200)
    self.cSpread = data.colourSharpness or 140
    
    self.mesh = mesh()
    local left = self.pos.x - w/2
    local right = self.pos.x + w/2
    local top = self.pos.y + h/2
    local bottom = self.pos.y - h/2
    self.mesh.vertices = {vec2(left,bottom),vec2(left,top),vec2(right,top)
                        ,vec2(left,bottom),vec2(right,top),vec2(right,bottom)}
    self.mesh.colors = {brighten(self.c,-self.cSpread),self.c,self.c
                        ,brighten(self.c,-self.cSpread),self.c,brighten(self.c,-self.cSpread)}
    
    popMatrix()
end

function Button:draw()
    pushMatrix()
    pushStyle()
    
    self.mesh:draw()
    fill(self.txtC)
    font(self.font)
    fontSize(self.size/1.2)
    textMode(CENTER)
    textAlign(CENTER)
    text(self.txt,self.pos.x,self.pos.y)
    
    popStyle()
    popMatrix()
end

function Button:press(t)
    pushMatrix()
    
    fontSize(self.size)
    local w,h = textSize(self.txt)
    
    popMatrix()
    
    if pointInRectCenter(t.x,t.y,self.pos.x,self.pos.y,w,h) then
        if t.state == ENDED then
            if self.callback then
                self.callback()
            end
            self.mesh.colors = {brighten(self.c,-self.cSpread),self.c,self.c
                        ,brighten(self.c,-self.cSpread),self.c,brighten(self.c,-self.cSpread)}
            else
            self.mesh.colors = {self.c,brighten(self.c,-self.cSpread),brighten(self.c,-self.cSpread)
                        ,self.c,brighten(self.c,-self.cSpread),self.c}
        end
    end
end

take note that the functions “brighten” and “pointInRectCenter” must be present for the buttons to work properly

If you don’t feel like figuring out how to use it yourself, have no fear, the explanations are here ;)!

Creating your button object:
When you make your button object, you can set a number of variables and options in the first parameter of Button:init() (which is a table). Below is a list of explanations for each of these variables and options. None of these variables or options are required to be set to avoid any errors, but you probably want to set a few of them (like the x and y position).

Setting the position (x and y) of your button:
in the table of the first parameter of Button:init() you can set the initial x and y coordinates of your button with either “pos” (which is a vec2) or “x” (which is a float or integer) and “y” (which is a float or integer as well). For example, I could create a button in the position of, say… x:100, y:400 like so:

ExampleButton = Button( {pos = vec2(100,400)} )

or like so:

ExampleButton = Button( {x = 100, y = 400} )

Adding a callback (a function that gets called when the button is pressed):
When your creating your Button object, you can set the callback in the table found in the first parameter of Button:init() with “callback”. For example, I can make a button that prints “hi” when it’s pressed like so:

ExampleButton = Button( {callback = function() print("hi") end} )

You can also make it call any existing function like the following:

ExampleButton = Button( {callback = exampleFunction} )

Setting the text that shows up on your button:
You can set the text of your button in the table found in the first parameter of Button:init(). The key is “text”. Below is an example of a button object with a customized text.

MyButton = Button( {text = "Simple Button"} )

Before we end this paragraph, take note that the default value for the text of your button is “Button”. If you simply don’t want your button to have any text, you can do that like so:

ButtonWithoutLabel = Button( {text = ""} )

Setting the text colour:
The text colour is also settable in the table found in Button:init(). the key is “textColour” (which is a color()). Example of a button with red text:

AButton = Button( {textColour = color(255,0,0)} )

Setting the font of the text:
This can also be set in the table found in the parentheses of Button:init(data). the key is “font” (which is a string). simple! I don’t think I really need to write any more examples anymore. I’m sure you get it, but if you don’t just ask me, and I write some more examples for you.

Setting the size of your button:
You can set the size of your button with the key “size” in the table, “data” found in Button:init(data).

Setting the colour of your button:
You can set the base colour of your button with the key “colour” (which is a color()) in the table “data”. If you don’t set this value manually, it will default to color(200).

Tweaking the shading effect:
These buttons look real fancy with their neat shading effects. You can tweak how quickly it fades from bright to dark with the key “colourSharpness” (which is a float or integer). Just one more example, why not?

CoolButton = Button( {colourSharpness = 200} )

If you don’t set the colourSharpness variable, it will default to 140, which I think makes a good look.

So yeah. That’s probably more than enough you need to know about how to use this class, but if you have any questions, just ask me.

wow! thankyou so much ! this will help me a lot :slight_smile:

You don’t need to use pushMatrix and popMatrix unless you’re using translate rotate scale or setting a new modelMatrix inbetween the push and the pop.

Oh, woops. I didnt see that there. I made this class back when I thought “pushMatrix” and “popMatrix” were for things like “ellipseMode”, “rectMode”, “font”, and pretty much just everything other than “fill” and “stroke”. I’m not sure why I thought that, but that’s why “pushMatrix” and “popMatrix” were there. Anyway, here’s the class again, without the unnecessary matrix pushing and popping.

function brighten(c,amount)
    return color(c.r+amount,c.g+amount,c.b+amount,c.a)
end

function pointInRectCenter(pointX, pointY, x, y, w, h)
    return pointX >= x - w/2 and pointX <= x + w/2 and pointY >= y - h/2 and pointY <= y + h/2
end

-- Button
Button = class()
function Button:init(data)
    pushStyle()

    self.callback = data.callback
    self.pos = vec2(data.pos.x,data.pos.y) or vec2(data.x,data.y) or vec2(0,0)
    self.txt = data.text or "Button"
    self.txtC = data.textColour or color(40)
    self.font = data.font or "Futura-Medium"
    self.size = data.size or 50
    fontSize(self.size)
    local w,h = textSize(data.text)
    self.c = data.colour or color(200)
    self.cSpread = data.colourSharpness or 140

    self.mesh = mesh()
    local left = self.pos.x - w/2
    local right = self.pos.x + w/2
    local top = self.pos.y + h/2
    local bottom = self.pos.y - h/2
    self.mesh.vertices = {vec2(left,bottom),vec2(left,top),vec2(right,top)
                        ,vec2(left,bottom),vec2(right,top),vec2(right,bottom)}
    self.mesh.colors = {brighten(self.c,-self.cSpread),self.c,self.c
                        ,brighten(self.c,-self.cSpread),self.c,brighten(self.c,-self.cSpread)}

    popStyle()
end

function Button:draw()
    pushStyle()

    self.mesh:draw()
    fill(self.txtC)
    font(self.font)
    fontSize(self.size/1.2)
    textMode(CENTER)
    textAlign(CENTER)
    text(self.txt,self.pos.x,self.pos.y)

    popStyle()
end

function Button:press(t)
    pushStyle()

    fontSize(self.size)
    local w,h = textSize(self.txt)

    popStyle()

    if pointInRectCenter(t.x,t.y,self.pos.x,self.pos.y,w,h) then
        if t.state == ENDED then
            if self.callback then
                self.callback()
            end
            self.mesh.colors = {brighten(self.c,-self.cSpread),self.c,self.c
                        ,brighten(self.c,-self.cSpread),self.c,brighten(self.c,-self.cSpread)}
            else
            self.mesh.colors = {self.c,brighten(self.c,-self.cSpread),brighten(self.c,-self.cSpread)
                        ,self.c,brighten(self.c,-self.cSpread),self.c}
        end
    end
end

were for things like “ellipseMode”, “rectMode”, “font”, and pretty much just everything other than “fill” and “stroke”.

You’re thinking of pushStyle popStyle (and it does include fill and stroke). I should have realised that’s what you meant.