Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

button class

edited February 2012 in General Posts: 168

hey guys, i just saw you all are contributing something to this forum, like the scenemanager or spritely, and i just wanted to contribute something to. i think a button class is something what everyone needs, and i tried to make as much possibilities as i can. i hope it helps you! (usage guide implemented)

button = class()
-- by max tamussino
-- contact: max@visuals.at


function button:init(title,x1,y1,x2,y2,colorPressed,colorNotPressed,image1,image2)
    -- this button class makes it easier to create buttons. the best thing is: it keeps
    -- the touched function short ;)
    -- so here is how to use it:
    -- - the title the title should be a string, and should represent the function of the button,
    --   like: "closeButton"
    -- - x1,y1,x2,y2 are the coordinates
    -- - good to know: the button can either be a rect or a sprite (in spritely or not). 
    --        1) For the rect:
    --        - colorPressed: the color the rect is filled with when the button is pressed.
    --        - colorNotPressed: the color the rect is filled with when the button is not pressed.
    --        - image1: must be set to ""rect"" (string!!).
    --        - image2: must be nil.
    --        - coordinates: for rectMode(CORNERS)
    --        2) For the sprite:
    --               Two possibilities:
    --               a) changing image:
    --                   - this possibility changes the normal image (image1) to image2 if 
    --                     the button is touched.
    --                   - colorPressed and colorNotPressed both must be nil.
    --                   - image1: normal image
    --                   - image2: displayed instead of the normal one when touched.
    --               b) changing tint:
    --                   - this possibility changes the fill color of the sprite if the 1
    --                     button is touched
    --                   - colorPressed: the tint() if the button is not touched
    --                   - colorNotPressed: the tint() if the button is touched
    --                   - image2: must be nil
    --
    --
    -- the button:getInfo() function returns a table with the title ( [1] )and the state( [2] ).
    -- to use this, you can can keep track of your buttonstates like this:
    --
    --
    --
    --
    --    if button:getInfo()[2] == 3 then
    --        if button:getInfo()[1] == "closeButton" then
    --            close()
    --        elseif button:getInfo()[1] == "openMenuButton" then
    --            if not menuShown then
    --                menuShown = true
    --            else
    --                menuShown = false
    --            end
    --        elseif button:getInfo()[1] == "showHelpScreenButton" then
    --            if not helpScreenShown then
    --                helpScreenShown = true
    --            else
    --                helpScreenShown = false
    --            end
    --        end
    --    end
    --
    -- i hope it helps you guys! have fun creating buttons! :)
    
    self.title = title
    self.x1 = x1
    self.y1 = y1
    self.x2 = x2
    self.y2 = y2
    self.cp = colorPressed
    self.cnp = colorNotPressed
    self.image1 = image1
    if not self.cp then
        if not self.cnp then 
            self.image2 = image2
        end
    end
    self.pressed = false
    rectMode(CORNERS)
end

function button:draw()
    if self.state == 1 or self.state == 2 then
        self.pressed = true
    else
        self.pressed = false
    end
    
    if self.image1 == "rect" then
        if self.pressed then
            fill(self.cp)
        else
            fill(self.cnp)
        end
        rect(self.x1,self.y1,self.x2,self.y2)
    elseif self.image2 then
        if self.pressed then
            sprite(self.image2,self.x1,self.y1,self.x2,self.y2)
        else
            sprite(self.image1,self.x1,self.y1,self.x2,self.y2)
        end
    else
        if self.pressed then
            tint(self.cp)
        else
            tint(self.cnp)
        end
        sprite(self.image1,self.x1,self.y1,self.x2,self.y2)
    end
    
    if self.state == 3 then
        if ElapsedTime > a + 0.1 then
            self.state = 0
        end
    end
end

function button:touched()
    t = CurrentTouch
    if t.x > self.x1 and t.y > self.y1 and t.x < self.x2 and t.y < self.y2 then
        if t.state == BEGAN then
            self.state = 1
        elseif t.state == MOVING then
            self.state = 2
        elseif t.state == ENDED then
            self.state = 3
            a = ElapsedTime
        end
    else
        self.state = 0
    end
end

function button:getInfo()
    return {self.title, self.state}
end

maxiking16

Comments

  • edited February 2012 Posts: 2,820

    Nice. Thanks. I also like to do small classes like my smooth changing color class I haven't had a chance to post.

  • hah, i have one of these too :D

  • Posts: 118

    Thanks @Maxiking16. Why is there


    a = ElapsedTime

    in the button:touched() ?

  • Posts: 2,820

    How many lines of code is your color class? Just curiouse.

  • edited February 2012 Posts: 168

    @Herwig : because it Saves the Time when the Finger leaves the button (then the State is 3), and in the draw, 0.1 seconds later the State gets changed to 0, to prevent the Button from having State 3 everytime.

    @Zoyt : Not long, about 50 Lines or something.

  • Posts: 118

    @Maxiking16 wouldn't it be better to put that in the class, rather than in a global variable?

  • Well, actally.. Your right. I'll change it.

  • Posts: 2,820

    Do you want to enter this in my competition?

  • Id Love to!

  • Posts: 2,820

    Good.

  • edited March 2012 Posts: 21

    I needed something else for my button class, so i did below additions. I will share it here so others can use it too.

    When you have lots of buttons and if you need to remove/add them along your code, you need a good list for your buttons to quickly add/remove them and also search among them.

    First i added a global named "button_list" in my setup as nil.
    Then i added these lines into my button class init:

        self.prev = nil
        self.next = button_list
        button_list = self
        if self.next then self.next.prev = self end
    

    self.prev is previous button in the list, self.next is the next one as you can guess.
    With this, when a button created, it adds that button to the list.

    My main touch function:

        if button_list == nil then return end
        
        ch = button_list
        repeat
            ch:touched()
            if ch:getInfo()[2] == 3 then
                if ch:getInfo()[1] == "CloseButton" then close() end
                if ch:getInfo()[1] == "CloseButton2" then remove_button( close_2 ) end
            end
            ch = ch.next
        until ch == nil
    

    CloseButton and CloseButton2 are just examples.

    Here is the piece where i draw buttons in my draw main:

        if button_list ~= nil
        then
            ch = button_list
            repeat
                ch:draw()
                ch = ch.next 
            until ch == nil
        end
    

    Also i have this function to remove a button if needed:

    function remove_button(b)
        
        if b == button_list
        then
            if button_list.next then button_list.next.prev = nil end
            button_list = button_list.next
        else
            if b.next 
            then 
                b.next.prev = b.prev
                if b.prev then b.prev.next = b.next end
            else
                if b.prev then b.prev.next = nil end
            end
            
        end
        b = nil    
    end
    

    Hope this helps out those who need to improve their button classes. There can be bugs, i didnt have much chance to test, just wanted to share and do my bit of help for the great Codea community.

  • Posts: 21

    erm, can i learn how you add piece of code to posts so they show properly ?

    [code]
    ch=nil
    [/code]

    like this ?

  • Posts: 2,161

    I edited the post to do the code. This forum uses PHP Markdown Extra. Code blocks are either indented 4 spaces or "fenced" by a line with ~~~ on it before and after.

  • Posts: 21

    Thanks Andrew

  • Posts: 41

    Thanks Maxiking, this looks great!

    Would you be up for adding a wee bit more instruction for us total newbies? I created my buttons in setup() and I'm calling button:draw() from my draw() function. But how do I integrate with touched()? Do I call button:touched() from my main touched() function?

    Could you perhaps add, in your instructions, sample code that would create a simple button and watch for a press? (I know this should be obvious from looking at the code, but I'm still such a beginner that I can't quite figure it out.)

  • edited March 2012 Posts: 21

    there is an example for it in his instructions Goatherd,

    just call your button's touched in your main "touched" function like

     my_button:touched()
    

    then check its state anywhere you want, like:

        if button:getInfo()[2] == 3 then
             if button:getInfo()[1] == "closeButton" then
                 close()
    

    This button closes your running code.

  • Posts: 41

    Thanks Reldonas. I thought that was basically what I was doing, but I'm doing something wrong. It draws the button on the screen, showing the "not touched" color, but the color doesn't change when I press the button, and the displayed text never changes from "nothing yet".

    Here's my code (with apologies for the truly ill-advised button name, which didn't occur to me until I got to the "mybutt:touched" portion...)

    --# Main
    function setup()
      colp=color(221, 255, 0, 255)
      colnp=color(0, 255, 15, 255)
      mybutt=button("num1",500,500,650,450,colp,colnp,"rect")
      fontSize(48)
      font("AmericanTypewriter-Bold")
      disp="nothing yet"
    end
    
    function draw()
      mybutt:draw()
    
      if mybutt:getInfo()[2]==1 then
        disp="it is 1"
      elseif mybutt:getInfo()[2]==2 then
        disp="it is 2"
      elseif mybutt:getInfo()[2]==3 then
        disp="it is 3"
      end
    
      text(disp,WIDTH/2,HEIGHT/2)
    
    end
    
    function touched(touch)
      mybutt:touched()
    end
    
    -- Maxiking's button code follows here
    

    Thanks for any pointers on whatever probably-terribly-embarrassing mistake I'm making.

  • edited March 2012 Posts: 21

    Your code is ok :) just your coordinates are wrong :) i mean at least for Maxiking's code. x1 and x2 should be lower left corner of rect, x2 and y2 upper right. So when you make x2>x1 and y2>y1; it works.

  • Posts: 41

    lol and thank you. That's an even goofier error than what I expected I was making.

  • Posts: 1,226

    Hi All,

    Just playing around with buttons and looked at rounded corners on rectangles. Simeon put some code in the library but I struggled to get anything from it - probably due to parameters passed in the calls - well, that's what happens in my routines. Simeon used a rounded line drawing suggested by Andrew to achieve it. Bortels gave his thanks as he was going to try the four part ellipses in the corners method. That's the one I used.

    The code is fairly straightforward and is minimised - using a recursive call for bordered buttons. I'm sure someone could make it much tidier and more professional.

    I've also added a crude text label for the button and wrapped it in a demo to try out location and parameters on the screen to select options. Colour selection and font styling would be a nice addon - I've been thinking about incorporating named styles.

    Here's the code:


    -- Main function setup()     saveProjectInfo("Description", "Cornered buttons demo")     saveProjectInfo("Version", "1.002 beta")     saveProjectInfo("Author", "Bri_G")         -- set up the function call parameters to play with the buttons     -- all self explanatory except cr which is the curvature control     -- note parameter range affects output, distortions are possible     parameter("cr",0,1,1)     iparameter("border",0,4,0)     iparameter("x",0,600,200)     iparameter("y",0,600,200)     iparameter("w",100,600,200)     iparameter("h",0,100,40)         butText = ""            end function draw()     -- This sets the background color to black     background(0, 0, 0)     -- Set the fill color     fill(255,0,0)     -- call the roundRect function     roundRect("trial button",x,y,w,h,cr,border) end          function roundRect(butText,x,y,w,h,cr,border)     local d     if cr > 1 then cr = 1 end     d = h*cr     r=d/2         fill(43, 68, 174, 255)         ellipse(x+r,y+r,d,d)         ellipse(x+w-r,y+r,d,d)         ellipse(x+r,y+h-r,d,d)         ellipse(x+w-r,y+h-r,d,d)     --  fill(198, 39, 39, 255)         rect(x+r,y,w-d,h)         rect(x,y+r,w,h-d)         fill(226, 221, 221, 255)       -- print centred text              text(butText,x+w/2,y+h/2)     if border > 0 then         fill(173, 50, 79, 255)         ellipse(x+r,y+r,d,d)         ellipse(x+w-r,y+r,d,d)         ellipse(x+r,y+h-r,d,d)         ellipse(x+w-r,y+h-r,d,d)         fill(198, 39, 39, 255)         rect(x+r,y,w-d,h)         rect(x,y+r,w,h-d)     -- adjust internal variables for inner shape     -- retain temp copies of variables for text usage     -- then draw inner button         xx, yy, ww, hh = x, y, w, h         x = x + border         y = y + border         w = w - 2*border         h = h - 2*border                    roundRect("trial button",x,y,w,h,cr,0)            end      end

    Hope this embeds properly - I'll be uploading to one of the code repositories soon and will post links. Tried to include a picture - does this site have a picture repository to upload to so that we can link in properly. I haven't at the moment and may need to look into it. Also, other forums I've used have editing options to add HTML code so that you can embed pics etc directly - does this forum?

    Finally Andrew - any chance you can give me a link to the code routine you wrote for Touch recognition and selection. Your link just points to your site - Wow!!! but difficult to search. Thanks.

    Bri_G
    :)

  • edited April 2012 Posts: 1,226

    Hi All,

    Just a quick note - if you want to see how this works add a fill() command before the ellipse code with a contrasting colour. You then see how the corners are built up using the parameter sliders e.g. for 'cr'.

    Secondly - this code is just from play time - it will need tidying up if you wish to use it as a library, mainly making more variables local and push and pop the styles and matrix before/after the routines. I'll produce a better package if there's enough interest.

    Have fun.

    Bri_G

    ;-)

  • Posts: 1,226

    Hi All,

    Here's my first follow up. Added push an' pop, plus I've also added named styles.

    Try it out.

    -- Main
    function setup()
        saveProjectInfo("Description", "Cornered buttons demo")
        saveProjectInfo("Version", "1.002 beta")
        saveProjectInfo("Author", "Bri_G")    
        -- set up the function call parameters to play with the buttons
        -- all self explanatory except cr which is the curvature control
        -- note parameter range affects output, distortions are possible
        parameter("cr",0,1,1)
        iparameter("border",0,4,0)
        iparameter("x",0,600,200)
        iparameter("y",0,600,200)
        iparameter("w",100,600,200)
        iparameter("h",0,100,40)    
        butText = ""
        name = ""
        on = 1
        off = 0          
    end
    
    function draw()
        -- This sets the background color to black
        background(0, 0, 0)
        -- Set the fill color
        fill(255,0,0)
        -- call the roundRect function
        roundRect("trial button",x,y,w,h,cr,border)
    end
            
    
    function roundRect(butText,x,y,w,h,cr,border)
        pushStyle()
        pushMatrix()
        if cr > 1 then cr = 1 end
            d = h*cr
            r=d/2
            style("backStyle", on)
            ellipse(x+r,y+r,d,d)
            ellipse(x+w-r,y+r,d,d)
            ellipse(x+r,y+h-r,d,d)
            ellipse(x+w-r,y+h-r,d,d)
            rect(x+r,y,w-d,h)
            rect(x,y+r,w,h-d)
            style("backStyle", off) 
        -- print centred text
            style("fontStyle", on)    
            text(butText,x+w/2,y+h/2)    
            style("fontStyle", off)
        if border > 0 then
            fill(173, 50, 79, 255)
            style("frontStyle", on)
            ellipse(x+r,y+r,d,d)
            ellipse(x+w-r,y+r,d,d)
            ellipse(x+r,y+h-r,d,d)    
            ellipse(x+w-r,y+h-r,d,d)
            rect(x+r,y,w-d,h)
            rect(x,y+r,w,h-d)
            style("frontStyle", off)        
        -- adjust internal variables for inner shape
        -- retain temp copies of variables for text usage
        -- then draw inner button
            xx, yy, ww, hh = x, y, w, h
            x = x + border
            y = y + border
            w = w - 2*border
            h = h - 2*border           
            roundRect("trial button",x,y,w,h,cr,0)       
        end
        popMatrix()
        popStyle()   
    end
    
    function style(name,condition)
        if condition == on then
            pushStyle()
            pushMatrix()
            if name == "butStyle" then
                strokeWidth()
                fill(226, 28, 28, 255)            
            elseif name == "backStyle" then
                fill(43,68,174,255)
            elseif name == "frontStyle" then
                fill(136, 205, 60, 255)           
            elseif name == "fontStyle" then
                font("Arial-BoldMT")
                fontSize(17)
                fill(226, 239, 37, 255)
            end
        elseif condition == off then
            popStyle()
            popMatrix()
        end
    end
    
    

    Next thing on the agenda - need to link it to the Touch detection routines.

    Bri_G

    :)

  • Posts: 2,161

    Sorry, missed the request. My code is at http://www.math.ntnu.no/~stacey/HowDidIDoThat/iPad/Codea.html. Actually, the touch class is in the anagram program which is one of the sample programs in Codea.

  • Posts: 1,226

    Hi Andrew,

    No probs, thanks for the link - I'll chase the code up form the Codea example. I need to add elements to my button code and also to another app I'm working on.

    Bri_G

    :)

Sign In or Register to comment.