I notice many button functions that people create have small flaws, for example, if I hold the mouse button and move the mouse around randomly, I may accidentally press the button.
It's not the programmer's fault, but the limitation of a single function, taken out of context, and no global varibles.
I have created a very forgiving button that works in phases and requires global variables or, preferably a global array of data. It allows you to, when holding down the mouse on the button, change your mind by simply moving the mouse out of the button.
This is the source code for an example:
`Setup
set display mode 800,600,32,0 `display
set window on : set window size 816,612 `window
sync on : sync rate 32 : sync sleep 1 `syncronizing
`button array
buttons=10 `number of buttons
dim ButtonData(buttons,2) `setup array with 2 data per button (phase and press)
`define button variables
Bleft=375
Btop=290
Bright=425
Bbottom=310
`color palette
global grey1 as dword `create global color
grey1= rgb(31,31,31) `define color
global grey2 as dword
grey2= rgb(63,63,63)
global grey3 as dword
grey3= rgb(127,127,127)
global grey4 as dword
grey4= rgb(191,191,191)
global white as dword
white= rgb(255,255,255)
global green1 as dword
green1= rgb(0,63,0)
global green2 as dword
green2= rgb(0,255,0)
`setup background color
red=0 : green=0 : blue=128
`start loop
do
`refresh frame
cls rgb(red,green,blue)
`setup reservation box for button
box Bleft,Btop,Bright,Bbottom,grey2,grey3,grey2,grey3
`Use function to setup button
UpdateButton(1, Bleft, Btop, Bright, Bbottom, grey4, grey1, 1)
`setup text using button phase
if ButtonData(1,1)=0
ink green1,0
else
ink green2,0
endif
center text 400,290,"Color"
`Check for button press
ink white,0
if ButtonData(1,2)
red=rnd(255) : green=rnd(255) : blue=rnd(255)
endif
`syncronize and goto do
sync
loop
`Custom Function(feel free to use), returns one if mouse inside defined box, else 0
function MouseInside(left,top,right,bottom)
if mousex()>left and mousey()>top and mousex()<right and mousey()<bottom then inside=1
endfunction inside
`La pièce de résistance , the button function
function UpdateButton(arraynumber, left, top, right, bottom, lightcolor as dword, darkcolor as dword, outlineflag)
phase= ButtonData(arraynumber, 1)
`phase zero is nothing, defined by no mouse contact
if phase=0
ButtonData(arraynumber,1)=0 `sets phase data
ButtonData(arraynumber,2)=0 `sets press data
if MouseInside(left, top, right, bottom) and mouseclick()=0 then phase=1 `option to move to phase one
endif
`phase one is a box with optional outline, defined by mouse over the button
if phase= 1
ButtonData(arraynumber,1)=1 `sets phase data
ButtonData(arraynumber,2)=0 `sets press data
box left, top, right, bottom, darkcolor, lightcolor, darkcolor, lightcolor
if outlineflag `start of optional outline
ink darkcolor,0
line left, top, left, bottom
line left, bottom, right, bottom
line right, bottom, right, top
line right, top, left, top
endif `end of optional outline
if not MouseInside(left, top, right, bottom) then ButtonData(arraynumber,1)=0 `option to return to phase zero
if mouseclick()=1 then phase=2 `option to move to phase two
endif
`phase two is an inverted box, meant to appear pressed, outline optional, defined by mouse inside and click
if phase= 2
ButtonData(arraynumber,1)=2 `sets phase data
ButtonData(arraynumber,2)=0 `sets press data
box left, top, right, bottom, lightcolor, darkcolor, lightcolor, darkcolor
if outlineflag `start of optional outline
ink darkcolor,0
line left, top, left, bottom
line left, bottom, right, bottom
line right, bottom, right, top
line right, top, left, top
endif `end of optional outline
if not MouseInside(left, top, right, bottom) then ButtonData(arraynumber,1)=0 `option to return to phase zero
if mouseclick()=0 then phase=3 `option to move to phase three
endif
`phase three is a single-frame data setting, allows press to equal one for one frame within the loop
if phase=3
ButtonData(arraynumber,2)=1 `sets press data
ButtonData(arraynumber,1)=1 `sets phase data(returns to one because mouseclick()=0)
endif
endfunction
Note: I believe the best way to use the function it to first create a variable (or constant) that matches the amount of buttons in use, then create an array called "ButtonData" and give it dimensions of the said variable by 2, ex. ButtonData(buttons,2). The array returns data, so ButtonData(button,1)= phase in progress and ButtonData(button,2)= press(1 or 0).
Good luck everyone!