CS 106 Winter 2018

Lab 04: User Interfaces



Question 1 Singles

In your L04 folder, create a new sketch called Singles. In that sketch, write the following functions.

  1. Write a function called line() that behaves exactly like the built-in line() function, except that it takes two PVectors as parameters instead of four floats, and draws the line connecting the points represented by those PVectors. The body of your function should call the built-in version of line(), and you shouldn't return a value. Note that Processing won't get confused by the two versions of line()—it can tell them apart by their different argument types.

  2. The perimeter of a shape is the sum of the lengths of its edges. Write a function perimeter() that takes an array of PVectors as its argument, and returns the perimeter of the shape defined by that sequence of points. Note that PVector has a built-in method called dist(), which is the easiest way to measure the length of each edge. Remember that you need to add in the distance from the last point in the array back to the first one!

  3. Write a function doubler() that takes an array of integers as input and returns a new array twice as long in which each element of the original array is given twice. That is, if you pass in the array {1, 2, 3} you would get back the array {1, 1, 2, 2, 3, 3}.

You are encouraged, but not required, to test your functions by writing a setup() function that calls them and checks whether the correct answers are returned.

If you want, save your work in the sketch Singles.


Question 2 Zig Zags With Direct Manipuation

In Lab 03, you wrote a sketch that drew zig zags whose shapes were controlled by three numbers:

In that sketch, you drew a set of zig zags of different shapes to make a scene. Here you will draw a single zig zag, but you will add a direct manipulation user interface that allows the user to control its shape. The interface requires two "handles" (small discs that the user will interact with). One lives at the start of the zig zag on the left edge of the sketch window, and can be moved only up and down to control y. The other is drawn at the first peak of the zig zag, and simultaneously controls w and h. The final interface will look something like this:



In the provided starter code, open the sketch ZigZagDirectManip. You will see code borrowed from the Lab 03 solution set, in particular a complete function zigzag(). The sketch is set up to draw a single zig zag based on values of y, w, and h that are stored in global variables (which comprise the model, in the language of Module 04). Now add the following to the sketch:

  1. At the end of draw(), add code to draw the two direct manipulation handles, as shown in the video above. Don't worry for now about changing their colours when they're being manipulated—just draw them in black for starters. Run your code and verify that the handles are drawn in the correct locations.

  2. Write a mousePressed() function that uses hit testing to check whether the user clicked on either of the two handles. If they did, use one or more global variables of your choosing to keep track of this fact. There are two natural choices for the global variable(s):

    • Use a single integer that can take one of three different values, corresponding to "I didn't touch anything", "I want to manipulate the y handle", and "I want to manipulate the w/h handle". Set this integer to one of those three values in mousePressed().

    • Use two booleans that separately keep track of "I want to manipulate the y handle" and "I want to manipulate the w/h handle". Set those two booleans to an appropriate combination of true/false values in mousePressed(). (You'll need to make sure they're never both set to true at the same time.)

    (If you're confused about these options, look at the sample sketches SquareEllipse and SquareEllipse2.)

    You may want to add code to setup() to set these global variables to correspond to "I didn't touch anything"—when the sketch first starts, no dragging is taking place.

  3. Write a mouseReleased() function. However you're keeping track of the dragging mode in global variables above, this function should reset the state of the sketch to "I didn't touch anything".

  4. Write a mouseDragged() function. It should work as follows:

    • If the user is currently manipulating the y handle, then update the current value of the global variable y. The zig zag should move up and down the screen. The handle should move it it, always moving vertically and never to the left or right.

    • If the user is currently manipulating the w/h handle, then update the values of w and h so that the first peak in the zig zag moves with the mouse. As shown in the lecture notes, remember to update based on mouseX-pmouseX and mouseY-pmouseY, so that handles move more smoothly.

      We need one additional constraint here: we don't want to allow the zig zag to become infinitely wiggly, which would crash the sketch. When you change the value of w, check to see if the new value of w is less than 5. If it is, set it to 5.

  5. Finally, go back to draw(), where you draw the handles. Change your code so that each handle is drawn differently if the user is currently manipulating it. That's most easily done by changing its fill colour.

Save your work in the sketch ZigZagDirectManip. Put it in a folder called L04 (If you start with the provided code, this should be automatic.)

Question 3 Spirograph



A Spirograph is a classic drawing toy in which a gear holding a pen rotates inside or around a larger gear. You will be given code to draw Spirograph designs, to which you must add interactive user interface controls using ControlP5. Proceed as follows:

  1. In the provided starter code, open the Spirograph sketch.

  2. Initially, the sketch doesn't do anything. Add a call to drawSpirograph() at the end of draw() and run the sketch to see a simple Spirograph pattern on the screen. That's the only change you need to make to draw().

  3. Make sure you have the ControlP5 library installed. If you don't have it already, follow the same instructions you followed to install RiTa in Lab 01 and Assignment 01, with this new library name.

  4. Now add the basic skeleton of the ControlP5 library, as in the many sample sketches for Module 05:

    • An import statement at the top of the sketch.

    • A global variable that holds an instance of the ControlP5 class.

    • A line in the setup() function that initializes the global variable to a new ControlP5 instance.

  5. Create a slider to manipulate the global variable big_teeth (the number of teeth in the big ring-shaped gear in the video):

    • Add code to setup() to build a slider (using the addSlider() method of your ControlP5 instance). Store the result in a global Slider variable.

    • Give the slider a reasonable size and position in the window (keeping in mind that you'll be adding a few additional UI elements).

    • Constrain the slider to range over values from 20 to 120. You can also call the method setDecimalPrecision( 0 ) on the slider so that its display rounds to whole numbers.

    • Finally, create a controlEvent() hook at the bottom of the sketch, as demonstrated in lectures. When you detect that your slider was manipulated, get the slider's value and store it in the global variable big_teeth. Once that's working, you should be able to move the slider and see the Spirograph drawing change interactively.

  6. Repeat the process above with a second slider to control the variable little_teeth (the number of teeth in the gear moved by the pencil). Let that slider range over whole number values from 10 to 60.

  7. Add a slider to control the variable l, which can range over real numbers between 0 and 1.

  8. Add a slider to control the radius, which can range over real numbers between 50 and 250.

  9. Finally, add a toggle switch that controls the boolean variable inside (see the ControlP5 addToggle() method). Clicking the toggle should flip the value of the global variable, flipping the Spirograph drawing over to the outside of the large gear (it'll get larger).

  10. Make sure to arrange your interface in a reasonable way (widgets that don't overlap and don't get too much in the way of the drawing). Here's an example.


Save your work in a sketch called Spirograph. Put it in a folder called L04 (If you start with the provided code, this should be automatic.)

Submission

When you are ready to submit, please follow these steps.

  1. Please ensure that any sketches you submit compile and run. It's better to submit a sketch that runs smoothly but implements fewer required features than one that has broken code for all features. If you get partway into a feature but can't make it work, comment it out so that the sketch works correctly without it.

  2. If necessary, review the Code Style Guide and use Processing's built-in auto format tool. You do not need to use the precise coding style outlined in the guide, but whatever style you use, your code must be clear, concise, consistent, and commented.

  3. If necessary, review the How To Submit document for a reminder on how to submit to LEARN.

  4. Make sure to include a comment at the top of all source files containing your name and student ID number.

  5. Create a zip file called L04.zip containing the entire L04 folder and its subfolders ZigZagDirectManip and Spirograph.

  6. Upload L04.zip to LEARN. Remember that you can (and should!) submit as many times as you like. That way, if there's a catastrophe, you and the course staff will still have access to a recent version of your code.

  7. If LEARN isn't working, and only if LEARN isn't working, please email your ZIP file to the course account (see the course home page for the address). In this case, you must mail your ZIP file before the deadline. Please use this only for emergencies, not "just in case". Submissions received after the deadline may receive feedback, but their marks will not count.