Tutorial: How to change Buttons Event Function on fly (ie. OnMouseDown)

The place for any Hollywood tutorials
Post Reply
Bugala
Posts: 694
Joined: Sun Feb 14, 2010 7:11 pm

Tutorial: How to change Buttons Event Function on fly (ie. OnMouseDown)

Post by Bugala » Sun Jul 08, 2018 2:40 pm

What I have found as most clear way to do on my programs, is to change OnMouseDown, OnMouseOut, etc. functions on fly. However, this is not directly supported in Hollywood, so unfortunately your code will get couple of otherwise unnecessary extra lines.

First lets create example program that uses buttons:

Code: Select all

EnableLayers

Function button1func()
	DebugPrint("button 1 pressed")
EndFunction

Function button2func()
	DebugPrint("button 2 pressed")
EndFunction

Function button3func()
	DebugPrint("button 3 pressed")
EndFunction

SetFillStyle(#FILLCOLOR)
Box(50, 100, 100, 100, #RED, {name="button1box"})
Box(200, 100, 100, 100, #GREEN, {name="button2box"})
Box(350, 100, 100, 100, #BLUE, {name="button3box"})
 
MakeButton(1, #LAYERBUTTON, "button1box", True, False, {OnMouseDown = button1func})
MakeButton(2, #LAYERBUTTON, "button2box", True, False, {OnMouseDown = button2func})
MakeButton(3, #LAYERBUTTON, "button3box", True, False, {OnMouseDown = button3func})

Repeat
	WaitEvent()
Forever
If you run this program, you can see three different buttons, if you push them, you will get debugprint to print "button x pressed".

Now suppose I want to change the function into something else, I could try for example something like this (this is otherwise same, but notice couple of extra lines before repeat forever loop:

Code: Select all

EnableLayers

Function button1func()
	DebugPrint("button 1 pressed")
EndFunction

Function button2func()
	DebugPrint("button 2 pressed")
EndFunction

Function button3func()
	DebugPrint("button 3 pressed")
EndFunction

SetFillStyle(#FILLCOLOR)
Box(50, 100, 100, 100, #RED, {name="button1box"})
Box(200, 100, 100, 100, #GREEN, {name="button2box"})
Box(350, 100, 100, 100, #BLUE, {name="button3box"})
 
MakeButton(1, #LAYERBUTTON, "button1box", True, False, {OnMouseDown = button1func})
MakeButton(2, #LAYERBUTTON, "button2box", True, False, {OnMouseDown = button2func})
MakeButton(3, #LAYERBUTTON, "button3box", True, False, {OnMouseDown = button3func})


Function newfunc()
     DebugPrint("Red Button Pressed")
EndFunction

button1func = newfunc

button1func()


Repeat
	WaitEvent()
Forever
As you can see from the test of running function "button1func()" before going to repeat forever loop, you can see that the old "button1func()" is indeed replaced with "newfunc()", but when this "button1func()" is executed through OnMouseDown, you can see that it is still actually using the old "button1func()" that was originally put to it when button was being initialised, and by otherwords, the new program works exactly as the old version did, which was not our purpose, since we wanted to change the function associated with the button. This is slightly unfortunate choice in Hollywood, but luckily we can get around it.

First way to get around is that we delete the button and create the same button again with the new function associated with it, instead of the old one. However, this is a risky thing to do since there are so many moving parts that can go wrong, hence here is how i usually do it.

First lets make a one button version of the old version:

Code: Select all

EnableLayers

Function button1func()
	DebugPrint("Button 1 pressed")
EndFunction

SetFillStyle(#FILLCOLOR)
Box(50, 100, 100, 100, #RED, {name="button1box"})
 
MakeButton(1, #LAYERBUTTON, "button1box", True, False, {OnMouseDown = button1func})

Repeat
	WaitEvent()
Forever
Now lets do one change to this program now:

Code: Select all

EnableLayers

Function button1func()
	realbutton1func()
EndFunction

Function realbutton1func()
	DebugPrint("Button 1 pressed")
Function

SetFillStyle(#FILLCOLOR)
Box(50, 100, 100, 100, #RED, {name="button1box"})
 
MakeButton(1, #LAYERBUTTON, "button1box", True, False, {OnMouseDown = button1func})

Repeat
	WaitEvent()
Forever
In this new version, instead of Function directly doing what it is planned to be doing, it is calling another function that is doing what it is planning to do.
This would normally be unnecessary, but due to how OnMouseDown and other button events work, if we wish to replace the current function with a new function without creating the button again, this is what we must do.

Now here is the version that is now going to replace this buttons function on fly:

Code: Select all

EnableLayers

Function button1func()
	realbutton1func()
EndFunction

Function realbutton1func()
	DebugPrint("Button 1 pressed")
EndFunction

Function newfunc()
	DebugPrint("Red Button pressed")
EndFunction

SetFillStyle(#FILLCOLOR)
Box(50, 100, 100, 100, #RED, {name="button1box"})
 
MakeButton(1, #LAYERBUTTON, "button1box", True, False, {OnMouseDown = button1func})

realbutton1func = newfunc

Repeat
	WaitEvent()
Forever
In this version, i added "NewFunc()" again, and then AFTER i made the button 1, i replaced the "realbutton1func" with "newfunc", since function associated with OnMouseDown is "button1func" and "button1func" does nothing else but executes "realbutton1func", it means that if "realbutton1func" is being replaced with another function, then so is OnMouseDowns function in practice.


This Tutorial continues in: https://forums.hollywood-mal.com/viewto ... =11&t=1937

Post Reply