programming buttons

BlitzMax Forums/BlitzMax Programming/programming buttons

So im wanting to write my own custom buttons for my game, but im not certain the best way to detect when one is pressed. Is there are info out there about the different methods, i need to be able to have oddly shaped buttons, like be able to have a .png image that only triggers when i click a non-alpha part.

Probably not the most efficient way to do it, but this works:
Graphics 640, 480, 0 ,0

TButton.Create("button.png", 100, 100, clicky)

While Not KeyDown(KEY_ESCAPE)
	Cls
	
	TButton.UpdateAll()
	TButton.DrawAll()
	
	Flip
Wend
End

Function clicky()
	Print "clicked "+MouseX()+" : "+MouseY()
End Function

Type TButton
	Field image:TImage
	Field X:Float
	Field Y:Float
	Global list:TList
	Field onClick()
	Field _mouseOver:Int = False
	Field _pixmap:TPixmap
	
	Method Draw()
		DrawImage(image, X, Y)
	End Method
	
	
	Method Update()
		
		If ( MouseX() >= X And MouseX() <= X + image.width ) Then
			If ( MouseY() >= Y And MouseY() <= Y+image.height ) Then
				_mouseOver = True
			Else
				_mouseOver = False
			EndIf
		Else
			_mouseOver = False
		EndIf
		
		If ( MouseHit(1) ) Then
			If (_mouseOver) Then
				If HitTest(MouseX()-X, MouseY()-Y) Then
					If (onClick <> Null) Then
						onClick()
					EndIf
				EndIf
			EndIf
			FlushMouse()
		EndIf
	End Method
	
	
	Method HitTest:Int(hitX:Float, hitY:Float)
		Local pix:Int = ReadPixel(_pixmap, hitX, hitY)
		
		If pix & $FF000000 Then Return True
	End Method
	
	
	Function DrawAll()
		
		For Local button:TButton = EachIn TButton.list
			
			button.Draw()
			
		Next
		
	End Function
	
	
	Function UpdateAll()
		
		For Local button:TButton = EachIn TButton.list
			
			button.Update()
			
		Next
		
	End Function
	
	
	Function Create:TButton(imagePath:String, X:Float, Y:Float, clickHandler())
		Local temp:TButton = New TButton
			If (TButton.list = Null) Then TButton.list = New TList
			temp.image = LoadImage(imagePath)
			If (temp.image = Null) Then 
				RuntimeError("Unable to load image "+imagePath)
				End
			EndIf
			
			temp._pixmap = LoadPixmap(imagePath)
			temp.X = X
			temp.Y = Y
			temp.onClick = clickHandler
			TButton.list.addLast(temp)
			
		Return temp
	End Function
End Type


Thanks man, i get whats going on there i thought there pretty much what i was thinking. but this line

Method HitTest:Int(hitX:Float, hitY:Float)
	Local pix:Int = ReadPixel(_pixmap, hitX, hitY)
	If pix & $FF000000 Then Return True
End Method


I got some of this, but just so i understand could you explain how the hit test works?

the $FF000000 represents an AARRGGBB integer, the $FF portion being full opacity, doing a bitwise AND between it and the pixel we are checking will return a boolean true when the pixel has full opacity

Technically, that line could be changed to:
Return pix & $FF000000

in fact a further optimisation could be:
Method HitTest:Int(hitX:Float, hitY:Float)
	Return ReadPixel(_pixmap, hitX, hitY) & $FF000000
End Method


And if further optimised could be something like:
If ReadPixel(_pixmap, MouseX()-X, MouseY()-Y) & $FF000000 Then
	If (onClick <> Null) Then
		onClick()
	EndIf
EndIf


I'm not sure I'm explaining it as well as I could, my brain understands it better than I do.

DING DING DING! i had no idea i could check for opacity :) hit the nail on the head there, thanks so much!