QCButton (or trying to Stand On the Shoulders of Giants Part II)

(Reference files here .)

After the release of classic code for Bill Atkinson's MacPaint and QuickDraw ( http://www.computerhistory.org/highlights/macpaint/ ) earlier in the week, I ended up reading the linked interviews with him, as well as Andy Herzfield, and then I even went through some old Steve Jobs interviews for a capper.

Somewhere in all of that, I read about a really straightforward and simple hit test technique that stored only two points, from which a rectangular area can then be deduced. The purpose of this was to stay within the limitations of early Macintosh hardware, but also because it was a simple way of handling the problem. I found the descriptions of problem solving techniques, and the general thought patterns described to be very interesting, and it inspired me to whip up a QuartzComposer hit test technique based on the description I read, which I posted about in my last entry.

A logical next step after the implementation of a solid hit test, is to make an actual button object, since a hit test is about half of the implementation of a button. By using the hit test logic to determine whether or not the cursor is over an image, and combining it with a type of toggle counter that responds to mouse up and down events, we can make a button engine, as long as everything is linked together to account for changes in button size or x/y translation.

I'm including the patches for reference in the Box.net widget, in the zip titled QCButtonPatch.zip. Inside, you will find a qtz based patch which needs to be installed in ~Library/Graphics/Quartz Composer Patches , and a demo that demonstrates function, by showing how clicking on the RoundedRect GUI Button in the QC Viewer triggers a macro on and off.

The limitation of this is that it should ideally be on the top level of a composition, and support is for 2D; if it is placed inside of offset 3D transforms, it will be affected by those transforms, and not track accurately unless one accounts for it with additional math between the mouse and the patch inputs. If one places this in a Render In Image and uses CI Filters or changes Pixel Width/Height, things may not appear to track correctly. In short, it has the same basic limitations inherent in the Interaction patch in QC, though it does not use it in any way.

For those so motivated, one may go into the QCButtonPatch and isolate the Off and On images for the button, for customized button appearance, but remember that the basic button hit test area is still rectangular, though tolerance is adjustable. This is the major factor behind my decision to go ahead and build in RoundedRect with this approach. Also, custom image would require a slightly different arrangement to be done best, which I tentatively plan to add or place into a separate patch that is honed for custom images. The RoundedRect is also a bit of an homage to a famous incident that established the shape as a Mac graphic primitive after Steve Jobs convinced Bill Atkinson to include it, by showing him the prevalence of it in "real life" by taking him on a walk where he pointed out every rounded rectangle.

I have never seen a robust (or actual) QC button that is both dependent on location (eg., performs a hit test), or with the ability to stick (one button click=On, second click=Off), and modes to turn on only on mouse down, shift on mouse up, or deliver a signal that can successfully turn macros on or off in this particular way, let alone one coded in QC. This is a utilitarian thing, but it is a highly useful Virtual Patch and is a major element for creating an on-screen GUI oriented qtz based patch for QC.

...and a hat's off to the inspiration I recieved from reading about the early days of Apple.

Edit: I added another little demo "QC Button Patch Demo 2 - Simple Game GUI", which is available in the Box.net widget apart from the zip file. A screengrab is shown below. Not fancy, but simple logic that allows for on screen gui and the logic to keep track of hits (which could be used to keep a score tally).