An Introduction To Programming With Processing

Creating a user defined function

Datatyping a function

The first line of a function definition must be used to declare the function, and as you are aware declaration in Processing means giving the function (variable or other entity) a name and datatyping it. Some programming languages might refer to the first line of a user defined function as a function header. Naming a function is a very similar process to that of naming a variable as you will see in the following code fragment forming the first line of our user defined function:
boolean overButton() 
The parenthesis following the function name are used to contain declarative parameters. These parameters will be defined within the function body, in our case this function does not accept any parameters so we leave the parenthesis empty. As you have been using functions that accept parameters user defined functions can also be created to accept parameters that you define. In comparison to setup() or draw() our function is being datatyped as a boolean, all functions must return a datatype or use the void keyword like setup() and draw(). As void does not return any data it is subsequently not classed as a datatype within Processing (and traditionally in C/C++) but as a structural element, this differs to other higher level languages (some of which are closely tied to Processing such as Arduino) that do consider void as a datatype. Nonetheless our function is going to return data of type boolean, which will be used to determine whether the user's mouse is over the slider button or not.


Determining a range

Determining Ranges

In order to calculate whether the mouse is over the slider button or not we will have to determine the range in which the slider button is located. We already know where the slider button is in terms of X and Y because these are values determined by parameters if the image() function used to draw the image. We can use this information, along with the width and height object variables to work out the slider button's range.

In the previous image if A and B where variables the image() function to render the slider button could be rewritten as:

image(sliderFd, A, B);
This method of expressing the X and Y parameters as variables is particularly useful to us because, we would like the slider button to be able to “slide” along the X axis, this means the value of A would need to be dynamic. As the slider button only moves along the X axis the variable B will not change, however this value is used in more than one situation, firstly to determine the Y position of the image that will form the area along which the slider button can be dragged referred to as sliderBk (short for slider background), secondly to determine the Y position of the slider button referred to as sliderFd (short for slider foreground) and thirdly referenced within the range we will set up shortly to determine the clickable area of the button. As a result this value has been declared as a variable of type int and named margin. This way if at a later stage we decide to move the entire slider down in order to make room for other graphical elements above it then all we need to do is update the value associated with margin, instead of having to find and change an explicit value scattered throughout the source code. The value described as A in the previous image requires a more meaningful name, something that is self documenting. As a result this value has been named buttonXPos, declared as a variable in the global region and datatyped as an int:

nt buttonXPos;
Eventually we'd like to replace the X parameter for the image() function rendering sliderFd in the X position determined by buttonXPos. As we are aware what the variable buttonXPos is going to represent we're going to set it up with a temporary value within our sketch to test our user defined function. So we're going to add a temporary statement for testing and debugging purposes to the draw() function which assigns a value to buttonXPos and then changes the image() function of which sliderFd is associated with to reflect this assignment statement. Once the buttonXPos variable is declared in global space, you can edit the draw() structure to include the first command and update the appropriate image command:
...
//temp for debugging 
buttonXPos = width/2 - sliderBk.width/2;
...
image(sliderFd,buttonXPos ,margin); 
Once we are sure that our function is working we will return to the temporary statement that we adding for debugging and testing purposes and include the buttonXPos variable assignment statement within an if() structure. We are now ready to proceed with setting up our function. To briefly recap our function has been declared as type boolean and given the name overButton(), setting up the range will occur within a conditional consisting of multiple comparisons and will look like this:
boolean overButton(){
  if (mouseX >= buttonXPos && mouseX <= buttonXPos +  sliderFd.width && mouseY >= margin && mouseY <= margin +  sliderFd.height)
    {
     …
Although this conditional might look a little confusing at first, when broken down into the four distinctive elements that it is comprised of it tends too make a lot more sense. So lets have a look at what each comparison is calculating and how these four different expressions put together will either return a value of true or false, which will ultimately determine whether the following code block of the if() structure is run or not.
Comparison 1: mouseX >= buttonXPos
Range 01
This checks if the mouse is anywhere in the highlighted area of the following image. If the mouse is then a value of true is returned and Processing will continue to evaluate the rest of the conditional.

Comparison 2: mouseX <= buttonXPos + sliderFd.width
Range 02
This comparison is only evaluated if the previous comparison evaluated to true because a logical AND operator (&&) separates the two comparisons and as you are aware in order for a logical AND operator to return a value of true all expressions within the conditional must evaluate to true. So if one of these comparisons making up this compound conditional (as it is sometimes referred to as) evaluates to false, there is no need for Processing to continue to evaluate the rest of the conditional as the value of the conditional will invariably equate to false. This particular comparison will only return a value of false if the mouse's X value is less than the right edge of the slider button.
Comparison 3:mouseY >= margin
Range 03
Once again this comparison is only evaluated if the previous comparison was true because both comparisons are separated with &&. This comparison returns a value of true only if the mouse is below the top of the slider button.
Comparison 4: mouseY <= margin + sliderFd.height
Range 04
Another && precedes this comparison which will finally only return true and determine if the entire compound conditional evaluates to true if the mouse's Y value is less than the bottom of the slider button.

Now that we have the range setup we're going to tell Processing what to do when the conditional evaluates to true or false.