|
||||||||
| PREV NEXT | FRAMES NO FRAMES | |||||||
Example usage of lfo.jsui UI elements javascript code.
Contains Button, IconButton, and TextButton UI object classes,
as well as a generic event handler, and code showing how to use
them all to create a fully-functional GUI in Max/MSP/Jitter's JSUI
object.
Version: $Id: example.lfo.jsui.js,v 1.4 2006/09/06 10:53:08 evan Exp $
| Class Summary | |
| Button | |
| ExampleGUIHandler | |
| GUIHandler | |
| IconButton | |
| TextButton | |
| Method Summary | |
static Array
|
arrayMultiply(<Array> a, <Array> b)
Multiply 2 arrays of same length. |
static void
|
bang()
Bang == draw |
static void
|
draw(<Boolean> forceDraw)
Draw UI elements to jsui, as necessary. |
static void
|
getProp(propName)
Print a property to outlet (not to be confused with getprop) |
static void
|
init()
Initialize everything. |
static void
|
loadbang()
Set up file paths, mostly for loading icons later. |
static void
|
onclick(x,y,button,cmd,shift,capslock,option,ctrl)
Mouse input function. |
static void
|
ondblclick(x,y,button,cmd,shift,capslock,option,ctrl)
Mouse input function. |
static void
|
ondrag(x,y,button,cmd,shift,capslock,option,ctrl)
Mouse input function. |
static void
|
onidle(x,y,button,cmd,shift,capslock,option,ctrl)
Mouse input function. |
static void
|
onidleout(x,y,button,cmd,shift,capslock,option,ctrl)
Mouse input function. |
static void
|
printProp(propName)
Print a property to Max window |
static void
|
setupButtons()
Button setup functions |
static void
|
updateButtons()
Update Button locations on the screen, for all Buttons. |
/** * @fileoverview * * Example usage of lfo.jsui UI elements javascript code. * Contains Button, IconButton, and TextButton UI object classes, * as well as a generic event handler, and code showing how to use * them all to create a fully-functional GUI in Max/MSP/Jitter's JSUI * object. * @version $Id: example.lfo.jsui.js,v 1.4 2006/09/06 10:53:08 evan Exp $ * */ /** * Set number if inlets (jsui method) */ inlets = 1; /** * Set number if outlets (jsui method) */ outlets = 1; //sketch.ortho3d(); /** * The name to change the patcher window to, if runing as a standalone or app. * @type String */ var standaloneName = "LFO (lowfrequency.org) lfo.jsui Tester"; /** * Whether or not the jsui can be drawn. * @type Boolean */ var okToDraw = false; /** * Force the jsui to clear and redraw everything. * @type Boolean */ var forceDraw = false; /** * Report the mouse state out of the outlet * @type Boolean * @see #onclick * @see #ondblclick * @see #ondrag * @see #onidle * @see #onidleout */ var reportMouse = true; /** * jsui background color (R,G,B,A). * @type Array(4) */ var brgb; var sInfoOverlayColor; var sInfoTextColor; var sInfoFontSize; var sInfoFont; /** * Scale of this jsui instance (x/y) * @type float */ var jsuiScale; /** * Maximum and minimum x coordinates for this jsui (OpenGL). * @type Array(2) */ var jsuiXBounds; /** * Maximum and minimum y coordinates for this jsui (OpenGL). * Almost always (1,-1) * @type Array(2) */ var jsuiYBounds; /** * Whether the jsui needs to clear and redraw everything. * @type Boolean */ var needsClear = true; /** * File path for this application (if it is an app or standalone) * @type String */ var appFilePath; /** * File path for the icon image files (named "/icons", relative to app path) * @type String */ var iconsFilePath; /** * Example Button variables */ var rotateCWButton, rotateCCWButton, sillyButton1, sillyButton2; /** * Example Button position variables (each stored separately) */ var rotateCWButtonXY, rotateCCWButtonXY, sillyButton1XY, sillyButton2XY; /** * Image file name, for the IconButton. * @see #iconsFilePath */ var rotateCWButtonImg = "rotateCW.gif"; /** * Image file name, for the IconButton. * @see #iconsFilePath */ var rotateCCWButtonImg = "rotateCCW.gif"; /** * These are arrays of buttons in the UI. * In a real app, it would be useful to divide you buttons up into "sets" * or arrays of Buttons, making it easier to catch maouse events and * re-draw only portions of the UI */ var sillyButtons, rotateButtons; // UI-event handler var buttonsHandler; var debug = 0; // debug level - 1 is most verbose, 2 is major errors, 0 is off // UI event vars var clickedButton = ""; //mouse click var dblclickedButton = ""; //mouse dblclick var overButton = ""; //mouseover /******************* patcher state related functions *********/ declareattribute("brgb", null, null, 1); declareattribute("sInfoOverlayColor", null, null, 1); declareattribute("sInfoTextColor", null, null, 1); declareattribute("sInfoFontSize", null, null, 1); declareattribute("sInfoFont", null, null, 1); declareattribute("rotateCWButtonXY", null, null, 1); declareattribute("rotateCCWButtonXY", null, null, 1); declareattribute("sillyButton1XY", null, null, 1); declareattribute("sillyButton2XY", null, null, 1); /************************************************** * Utility functions that every jsui js should have * @ignore */ /** * Print a property to outlet (not to be confused with getprop) */ function getProp(propName) { outlet(0, "prop", propName, eval(propName)); } /** * Print a property to Max window */ function printProp(propName) { post(eval(propName+".toString()")); } /** * Multiply 2 arrays of same length. * @param {Array} a * @param {Array} b * @return New Array with each consecutive element of a multiplied by * each consecutive element of b * @type Array */ function arrayMultiply(a, b) { var c=0; dest = new Array(a.length); for (c=0; c < a.length; c++) { dest[c] = a[c]*b[c]; } return dest; } /*************************************************/ /** * Set up file paths, mostly for loading icons later. */ function loadbang() { iconsFilePath = ""; appFilePath = ""; if (max.isruntime) appFilePath = max.apppath; else { var tmp = this.patcher.filepath.split("/"); //if (debug == 1) //post("Filepath: "+ tmp + "\n"); tmp.pop(); //remove patcher name for(var c=0; c<tmp.length; c++) { appFilePath += tmp[c] + "/"; } } iconsFilePath = appFilePath + "icons/"; init(); } /************************************************* * Button setup functions * * NOTE: there are clearly better ways of doing this. * This way is just very straightforward. This is an example file, after all. * For instance, if you wanted to create a row of transport buttons, instead of writing * out all of this button code, just make an array of button names ("play", "stop", etc) * and have the icon file names be modifications of those names (ex: "play_icn.gif"). * It would save a lot of time! */ function setupButtons() { rotateButtons = new Array(); rotateCWButton = null; rotateCWButton = new IconButton("rotateCWButton", sketch, iconsFilePath+rotateCWButtonImg); //rotateCWButton.debug = 1; rotateCWButton.setHandler(buttonsHandler); rotateButtons.push(rotateCWButton); rotateCWButton.setActive(true); rotateCCWButton = null; rotateCCWButton = new IconButton("rotateCCWButton", sketch, iconsFilePath+rotateCCWButtonImg); rotateCCWButton.setHandler(buttonsHandler); rotateButtons.push(rotateCCWButton); rotateCCWButton.setActive(true); rotateCCWButton.setHidden(false); for (var c=0; c < rotateButtons.length; c++) { rotateButtons[c].data = rotateButtons[c].name; rotateButtons[c].overmask = [0.9, 0.9, 0., 0.3]; rotateButtons[c].clickmask = [0., 0., 0.9, 0.3]; } var text_dims = [0,0]; sillyButtons = new Array(); sillyButton1 = null; sillyButton1 = new TextButton("sillyButton1", sketch, "silliness"); //sillyButton1.debug = 1; sillyButton1.sketcher.font(sillyButton1.font); sillyButton1.sketcher.fontsize(sillyButton1.fontSize); text_dims = sillyButton1.sketcher.gettextinfo(sillyButton1.text); sillyButton1.setSize(text_dims[0]+4, text_dims[1]+8); sillyButton1.setHandler(buttonsHandler); sillyButtons.push(sillyButton1); sillyButton1.setActive(true); sillyButton1.setHidden(false); sillyButton2 = null; sillyButton2 = new TextButton("sillyButton2", sketch, "very silly"); sillyButton2.sketcher.font(sillyButton2.font); sillyButton2.sketcher.fontsize(sillyButton2.fontSize); text_dims = sillyButton2.sketcher.gettextinfo(sillyButton2.text); sillyButton2.setSize(text_dims[0]+4, text_dims[1]+6); sillyButton2.setHandler(buttonsHandler); sillyButtons.push(sillyButton2); sillyButton2.setActive(true); for (var c=0; c < sillyButtons.length; c++) { sillyButtons[c].data = sillyButtons[c].name; sillyButtons[c].overmask = [0.9, 0.9, 0., 0.3]; sillyButtons[c].clickmask = [0., 0., 0.9, 0.3]; } } /** * Update Button locations on the screen, for all Buttons. * Setting their screenLocation forces them to redraw. */ function updateButtons() { rotateCCWButton.setScreenLocation(rotateCCWButtonXY[0],rotateCCWButtonXY[1]); rotateCWButton.setScreenLocation(rotateCWButtonXY[0],rotateCWButtonXY[1]); sillyButton1.setScreenLocation(sillyButton1XY[0],sillyButton1XY[1]); sillyButton2.setScreenLocation(sillyButton2XY[0],sillyButton2XY[1]); needsClear = true; } /** * Initialize everything. */ function init() { okToDraw = false; if (!brgb) brgb = [0.25, 0.25, 0.25]; if (!sInfoOverlayColor) sInfoOverlayColor = [0.8, 0.8, 0.8, 0.3]; if (!sInfoTextColor) sInfoTextColor = [0.9, 0.9, 0.9, 0.7]; if (!sInfoFontSize) sInfoFontSize = 10; if (!sInfoFont) sInfoFont = "Helvetica"; if (!rotateCCWButtonXY) rotateCCWButtonXY =[0,0]; if (!rotateCWButtonXY) rotateCWButtonXY =[0,0]; if (!sillyButton1XY) sillyButton1XY =[0,0]; if (!sillyButton2XY) sillyButton2XY =[0,0]; rotateButtons = null; rotateButtons = new Array(); sillyButtons = null; sillyButtons = new Array(); if (debug == 1) post("Sketch size: " + sketch.size); jsuiScale = [2/sketch.size[0], 2/sketch.size[1]]; jsuiXBounds = [-sketch.size[0]/sketch.size[1], sketch.size[0]/sketch.size[1]]; jsuiYBounds = [-1, 1]; buttonsHandler = new ExampleGUIHandler(); setupButtons(); updateButtons(); okToDraw = true; needsClear = true; draw(); // this is for standalone if (max.isruntime) this.patcher.wind.title = standaloneName; } /** * Bang == draw * @see #draw */ function bang() { draw(); } /** * Draw UI elements to jsui, as necessary. Calls draw() method on each UI element. * @param {Boolean} forceDraw Optional, but if true, clear jsui and redraw everything. */ function draw(forceDraw) { var force = false; if (forceDraw || needsClear) { force = true; // erase background sketch.glclearcolor(brgb); sketch.glclear(); needsClear = false; /* sketch.glcolor(sInfoOverlayColor); sketch.quad(jsuiXBounds[0], -0.2, 0, jsuiXBounds[0], 0, 0, jsuiXBounds[1]-screensButtonsWidth, 0, 0, jsuiXBounds[1]-screensButtonsWidth, -0.2, 0); sketch.quad(jsuiXBounds[1]-screensButtonsWidth, -0.2, 0, jsuiXBounds[1]-screensButtonsWidth, 0.2, 0, jsuiXBounds[1], 0.2, 0, jsuiXBounds[1], -0.2, 0); */ } if (okToDraw) { outlet(0, "draw"); // draw buttons for (var c=0; c < rotateButtons.length; c++) { rotateButtons[c].draw(force); } for (var c=0; c < sillyButtons.length; c++) { sillyButtons[c].draw(force); } // draw surfaces/screens info overlay in middle //drawSInfoOverlay(); } refresh(); } /** * Recalculate scale and x-boundaries when jsui object is resized in Max. * @param {int} w width (pixels) * @param {int} h height (pixels) * @private */ function onresize(w,h) { jsuiScale = [2/sketch.size[0], 2/sketch.size[1]]; jsuiXBounds = [-sketch.size[0]/sketch.size[1], sketch.size[0]/sketch.size[1]]; draw(true); refresh(); } /** * @ignore */ onresize.local = 1; //private /************* Mouse Input Functions ********************/ /** * Mouse input function. Catches mouse idle event. * If reportMouse is set, outputs mouse state out first inlet. */ function onidle (x,y,button,cmd,shift,capslock,option,ctrl) { if (reportMouse) outlet(0,"mouse",x,y,button,cmd,shift,capslock,option,ctrl); for (var c=0; c < rotateButtons.length; c++) { rotateButtons[c].onidle (x,y,button,cmd,shift,capslock,option,ctrl); } for (var c=0; c < sillyButtons.length; c++) { sillyButtons[c].onidle (x,y,button,cmd,shift,capslock,option,ctrl); } } /** * Mouse input function. Catches mouse idle event. * If reportMouse is set, outputs mouse state out first inlet. */ function onidleout (x,y,button,cmd,shift,capslock,option,ctrl) { for (var c=0; c < rotateButtons.length; c++) { rotateButtons[c].onidleout (x,y,button,cmd,shift,capslock,option,ctrl); } for (var c=0; c < sillyButtons.length; c++) { sillyButtons[c].onidleout (x,y,button,cmd,shift,capslock,option,ctrl); } } /** * Mouse input function. Catches mouse idle event. * If reportMouse is set, outputs mouse state out first inlet. */ function onclick (x,y,button,cmd,shift,capslock,option,ctrl) { if (reportMouse) outlet(0,"mouse",x,y,button,cmd,shift,capslock,option,ctrl); for (var c=0; c < rotateButtons.length; c++) { rotateButtons[c].onclick (x,y,button,cmd,shift,capslock,option,ctrl); } for (var c=0; c < sillyButtons.length; c++) { sillyButtons[c].onclick (x,y,button,cmd,shift,capslock,option,ctrl); } } /** * Mouse input function. Catches mouse idle event. * If reportMouse is set, outputs mouse state out first inlet. */ function ondblclick (x,y,button,cmd,shift,capslock,option,ctrl) { for (var c=0; c < rotateButtons.length; c++) { rotateButtons[c].ondblclick (x,y,button,cmd,shift,capslock,option,ctrl); } for (var c=0; c < sillyButtons.length; c++) { sillyButtons[c].ondblclick (x,y,button,cmd,shift,capslock,option,ctrl); } } /** * Mouse input function. Catches mouse idle event. * If reportMouse is set, outputs mouse state out first inlet. */ function ondrag (x,y,button,cmd,shift,capslock,option,ctrl) { if (reportMouse) outlet(0,"mouse",x,y,button,cmd,shift,capslock,option,ctrl); for (var c=0; c < rotateButtons.length; c++) { rotateButtons[c].ondrag (x,y,button,cmd,shift,capslock,option,ctrl); } for (var c=0; c < sillyButtons.length; c++) { sillyButtons[c].ondrag (x,y,button,cmd,shift,capslock,option,ctrl); } } /********************************************************************* lfo.jsui.js *********************************************************************/ /** * Simple Button classes for GUI events. * Reports it's data to a listener object with the functions * clicked, mouseOver, mouseOut defined. * Buttons are drawn around a center point (location). * @param {String} name This will be the name of the button (a way of identifying it) * @param {Object} sketcher The sketch object that will draw the button, associated with this jsui * * @constructor * $Id: example.lfo.jsui.js,v 1.4 2006/09/06 10:53:08 evan Exp $ */ function Button(name, sketcher) { if (name) this.name = name; else this.name = "button"; /** * The data (object) to broadcast to this Button's handler when clicked. */ this.data = null; /** * A reference to an OpenGL drawing context (sketch object) * @type sketch */ if (sketcher) this.sketcher = sketcher; else this.sketcher = new Sketch(2,2); /** * A string identifier for this class. * @type String */ this.className = "Button"; /** * Reference to a handler object to broadcast UI events to */ this.handler = null; /** * Whether the mouse was positioned over this button last time we checked. * @type Boolean */ this.mouseWasOver = false; /** * Whether this Button was clicked. * @type Boolean */ this.clicked = false; /** * Location of this Button in screen coordinates (pixels) (x,y,z) * (Top left corner of drawn Button) * @type Array(3) * @see #setScreenLocation */ this.screenLocation = [0,0,0]; /** * Location of this Button in OpenGL world coordinates (x,y,z) * (Center of drawn Button) * @type Array(3) * @see #setWorldLocation */ this.worldLocation = [0,0,1]; /** * Size of this Button in screen coordinates (pixels) (x,y) * @type Array(2) * @see #setSize */ this.size = new Array(2); /** * Scale of this Button in OpenGL world coordinates (x,y) * @type Array(2) * @see #setScale */ this.scale = new Array(0.1, 0.05); /** * Base OpenGL color of this Button - [R,G,B,A] * @type Array(4) */ this.color = new Array(0.2, 0.2, 0.2, 1.); /** * Base OpenGL hitmask (mouse click overlay) color of this Button - [R,G,B,A] * @type Array(4) */ this.hitmask = new Array(0., 0., 0.5, 0.3); /** * Base OpenGL overmask (mouse over overlay) color of this Button - [R,G,B,A] * @type Array(4) */ this.overmask = new Array(0.5, 0.5, 0.9, 0.2); /** * Base OpenGL inactive state mask color of this Button - [R,G,B,A] * @see #setActive * @type Array(4) */ this.inactivemask = new Array(0.7, 0.7, 0.7, 0.3); /** * Whether or not this Button needs to be re-drawn fully when draw() is called again. * @type Array(4) * @private */ this.needsDraw = true; /** * If non-zero, posts verbose debugging information to the Max window. * @type Boolean */ this.debug = 0; //spit out debugging information = levels are 0,1,2 (0 is off, 2 is least verbose) /** * How many frames (calls to draw()) elapse before the clicked state is reset. * @type int * @see #draw */ this.clickedHoldMax = 4; //how many drawing cycles to stay "clicked" for /** * Current number of frames (calls to draw()) that have elapsed while clicked state was true. * @type int * @see #draw */ this.clickedCount = 0; /** * Whether or not this Button listens to GUI events (active state, deactivated state) * @type Boolean * @see #draw * @see #hitTest */ this.active = true; /** * Whether or not this Button should be drawn. * @type Boolean * @see #draw */ this.hidden = false; /** * Whether this button holds after clicking until it's either clicked again or reset. * @type Boolean * @see #draw */ this.toggle = false; this.setScale(0.1, 0.05); this.setScreenLocation(0,0,0); } /** * Sets this Button as active (receives mouse events) * @param {Boolean} state True if the Button should listen to events, false if it should ignore them. */ Button.prototype.setActive = function(state) { this.active = state; this.needsDraw = true; } /** * Get this Button's active state (if it is receiving mouse events) * @return true (listening to events) or false (ignoring events) * @type Boolean */ Button.prototype.getActive = function() { return this.active; } /** * Sets this Button as hidden (not drawn) or not hidden (drawn) * @param {Boolean} state True if the Button will not be drawn */ Button.prototype.setHidden = function(state) { this.hidden = state; } /** * Get this Button's hidden state (if it should be drawn) * @return true (not drawn) or false (drawn) * @type Boolean */ Button.prototype.getHidden = function() { return this.hidden; } /** * Sets the scale (as in OpenGL, the scale is 2x the width of the drawn button) * @param {int} sx x scale * @param {int} sy y scale */ Button.prototype.setScale = function(sx,sy) { this.scale = new Array(sx,sy); //pretend we're drawing this at 0,0 to get screen-size var w0 = this.sketcher.worldtoscreen(0, 0, 0); var w1 = this.sketcher.worldtoscreen(2*sx, 0, 0); this.size[0] = w1[0] - w0[0]; var h0 = this.sketcher.worldtoscreen(0, 0, 0); var h1 = this.sketcher.worldtoscreen(0,2*sy, 0); this.size[1] = h0[1] - h1[1]; this.onresize(); } /** * Get this Button's scale. * @return Array of [x-scale, y-scale] * @type Array(2) */ Button.prototype.getScale = function() { return this.scale; } /** * Sets the size of the button (width, height in pixels) * @param {int} sx x size (pixels) * @param {int} sy y size (pixels) */ Button.prototype.setSize = function(sx,sy) { this.size = new Array(sx,sy); //pretend we're drawing this at 0,0 to get world-size var w0 = this.sketcher.screentoworld(0, 0, 0); var w1 = this.sketcher.screentoworld(sx*0.5, 0, 0); this.scale[0] = w1[0] - w0[0]; var h0 = this.sketcher.screentoworld(0, 0, 0); var h1 = this.sketcher.screentoworld(0,sy*0.5, 0); this.scale[1] = h0[1] - h1[1]; this.onresize(); } /** * Get this Button's size (width, height) in pixels * @return Array of [x-size, y-size] * @type Array(2) */ Button.prototype.getSize = function() { return this.size; } /** * Set the location of this button in world coords (OpenGL, for sketch) * @param {float} x x coordinate * @param {float} y y coordinate * @param {float} z z coordinate */ Button.prototype.setWorldLocation = function(x,y,z) { this.worldLocation = [x,y,z]; // sketch draws a plane centered around location, // but screen co-ords represent the bounding rectangle // need to represent bounding box here var tmp = new Array(this.worldLocation.length); tmp[0] = this.worldLocation[0] - this.scale[0]; tmp[1] = this.worldLocation[1] + this.scale[1]; tmp[2] = this.worldLocation[2]; this.screenLocation = this.sketcher.worldtoscreen(tmp); this.needsDraw = true; } /** * Get the location of this button in world coords (OpenGL, for sketch) * @return 3-member Array of floats [x,y,z] * @type Array(3) */ Button.prototype.getWorldLocation = function() { return this.worldLocation; } /** * Set the location of this button in screen coordinates (pixels) * @param {int} x x coordinate * @param {int} y y coordinate * @param {int} z z coordinate (optional) */ Button.prototype.setScreenLocation = function(x,y,z) { this.screenLocation[0] = x; this.screenLocation[1] = y; if ((z != null) || (z != undefined)) this.screenLocation[2] = z; else z=0; var tmp = this.sketcher.screentoworld(this.screenLocation); // sketch draws a plane centered around location, // but screen co-ords represent the bounding rectangle // need to represent center here tmp[0] += this.scale[0]; tmp[1] -= this.scale[1]; this.worldLocation = tmp; if (this.debug == 1) post("screen location: " + this.screenLocation + "\n" + "world location: " + this.worldLocation + "\n"); this.needsDraw = true; } /** * Get the location of this button in screen coordinates (pixels) * @return 3-member Array of ints [x,y,z] * @type Array(3) */ Button.prototype.getScreenLocation = function() { return (this.screenLocation); } /** * Mouse click event handler */ Button.prototype.onclick = function(x,y,button,cmd,shift,capslock,option,ctrl) { if (this.hitTest(x,y)) { if (this.debug == 1) post(this.name + " button: " + button + "\n"); if (this.toggle && this.clicked) this.clicked = false; //unclick else this.clicked = true; this.needsDraw = true; if(this.handler) this.handler.clicked(this.data, x,y,button,cmd,shift,capslock,option,ctrl); } // something needs to externally reset this // else this.clicked = false; } /** * Manual/code-triggered mouse click event handler. * @param {Boolean} showPush Whether or not to show the push when drawing the Button to screen. */ Button.prototype.push = function(showPush) { if (this.debug == 1) post(this.name + "button (push): " + button + "\n"); if (this.toggle && this.clicked) this.clicked = false; //unclick else this.clicked = true; if (showPush) this.needsDraw = true; if(this.handler) this.handler.clicked(this.data, -1,-1,0,0,0,0,0,0); } /** * Mouse idle event handler */ Button.prototype.onidle = function (x,y,button,cmd,shift,capslock,option,ctrl) { if (this.hitTest(x,y)) { this.mouseWasOver = true; if (this.debug == 1) post ("MOUSEOver " + this.name + "\n"); this.needsDraw = true; if(this.handler) this.handler.mouseover(this.data, x,y,button,cmd,shift,capslock,option,ctrl); } else { // only report changes //clear mouseOvers if (this.mouseWasOver) { this.mouseWasOver = false; this.needsDraw = true; if(this.handler) this.handler.mouseout(this.data, x,y,button,cmd,shift,capslock,option,ctrl); } if (this.debug == 1) post("MOUSEOut " + this.name + "\n"); } } /** * Mouse double-click event handler */ Button.prototype.ondblclick = function(x, y, button, mod1, shift, caps, opt, mod2) { if (this.hitTest(x,y)) if(this.handler) this.handler.dblclicked(this.data, x, y, button, mod1, shift, caps, opt, mod2); } /** * Mouse drag event handler */ Button.prototype.ondrag = function(x, y, button, mod1, shift, caps, opt, mod2) {} /** * Mouse idleout event handler */ Button.prototype.onidleout = function(x, y, button, mod1, shift, caps, opt, mod2) { //clear mouseOvers if (this.mouseWasOver) { this.mouseWasOver = false; this.needsDraw = true; if(this.handler) this.handler.idleout(this.data, x, y, button, mod1, shift, caps, opt, mod2); } if (this.debug == 1) post("MOUSEOut " + this.name + "\n"); } /** * Actions to perform when the Button is resized. Can be overloaded. */ Button.prototype.onresize = function() { this.needsDraw = true; } /** * Test if an x,y coordinate falls within the Button's boundaries. * @param {int} x x-coordinate * @param {int} y y-coordinate */ Button.prototype.hitTest = function(x,y) { var over = false; // only test if the button is active if (this.active) { //note: screen location coords are with respect to top left (0,0) if ( ((x > this.screenLocation[0]) && (x < (this.screenLocation[0]+this.size[0]))) && ((y > this.screenLocation[1]) && (y < (this.screenLocation[1]+this.size[1]))) ) over = true; if (this.debug == 1) { var os = "false"; if (over) os = "true"; post("hitTest " + over + " (" + this.name + ") sl[0]= " + this.screenLocation[0] + "\n" + "size[0]= " + this.size[0] +"\n" + "mx=" + x + "\n" + "sl[1]= " + this.screenLocation[1] + "\n" + "size[1]= " + this.size[1] +"\n" + "mx=" + x + "\n"); } } return over; } /** * Set reference to handler obect for Button events * @param {Object} hobj Handler object that will receive this Button's events. */ Button.prototype.setHandler = function(hobj) { this.handler = hobj; } /** * Get reference tohandler obect for Button events * @return Reference to handler object that will receive this Button's events. * @type Object */ Button.prototype.getHandler = function() { return this.handler; } /** * Set the clicked state of this Button, update GUI. Usually, this is only called * internally. * * A Button's clicked state is set to true after it is pressed, and remains * true for a number of drawing frames (this.clickedCount) while the clicked overlay * is drawn, and then it reset back to false. * @param {Boolean} state The new internal clicked state of the Button, true or false * */ Button.prototype.setClicked = function(state) { this.clicked = state; this.needsDraw = true; } /** * Main OpenGL drawing routine for drawing this Button to the screen, using its * internal reference to the jsui "sketch" object. The "base" is drawn first {@link #drawBase}, then * a mouseover overlay {@link #drawOverOverlay} or inactive overlay {@link #drawInactiveOverOverlay}. * This function is designed to be flexible so it does NOT need to be overloaded by child classes. * * Normally, the Button will only re-draw if it has to (if an event has taken place * that affects the onscreen appearance of the Button, and if it is NOT hidden). * * @param {Boolean} force Force the drawing of the Button. * */ Button.prototype.draw = function(force) { if (!this.hidden) if (force || this.needsDraw) with (this.sketcher) { this.needsDraw = false; gldisable("blend"); // glpushmatrix(); this.drawBase(); glenable("blend"); glblendfunc("src_alpha","one_minus_src_alpha"); if (this.active) { if (this.clicked) { this.drawClickedOverlay(); if (!this.toggle) { // reset clicked this.clickedCount++; // still needs to be drawn this.needsDraw = true; if (this.clickedCount >= this.clickedHoldMax) { this.setClicked(false); this.clickedCount = 0; } } } else if (this.mouseWasOver) { this.drawOverOverlay(); } } else { this.drawInactiveOverlay(); } // glpopmatrix(); } } /** * Draw only basic button elements. * This function is designed to be be overloaded by child classes for Buttons of * different appearances. */ Button.prototype.drawBase = function() { with (this.sketcher) { glcolor(this.color); moveto(this.worldLocation); plane(this.scale); } } /** * Draw blended overlay showing button was clicked. */ Button.prototype.drawClickedOverlay = function() { with (this.sketcher) { glcolor(this.hitmask); moveto(this.worldLocation); plane(this.scale); } } /** * Draw blended overlay showing mouse is over Button. */ Button.prototype.drawOverOverlay = function() { with (this.sketcher) { glcolor(this.overmask); moveto(this.worldLocation); plane(this.scale); } } /** * Draw blended overlay showing Button is not receiving UI events (not active). */ Button.prototype.drawInactiveOverlay = function() { with (this.sketcher) { glcolor(this.inactivemask); moveto(this.worldLocation); plane(this.scale); } } /** * Return string representation of this object * @return String of data about this object * @type String */ Button.prototype.toString = function() { var outstring = ":::Button:::\n"; with (this) { outstring += "Button name: " + name + "\n"; outstring += "Button class: " + className + "\n"; if (data) outstring += "Button data: " + data + "\n"; if (handler) outstring += "Button handler class: " + handler.className + "\n"; if (sketcher) outstring += "Button sketcher (" + sketcher + ")\n"; outstring += "Button active: " + active + "\n"; outstring += "Button hidden: " + hidden + "\n"; outstring += "\n"; outstring += "Button screen location: " + screenLocation + "\n"; outstring += "Button world location: " + worldLocation + "\n"; outstring += "Button world scale: " + scale + "\n"; outstring += "Button screen size: " + size + "\n"; outstring += "\n"; outstring += "Button color: " + color + "\n"; outstring += "Button hitcolor: " + hitmask + "\n"; outstring += "Button overcolor: " + overmask + "\n"; outstring += "Button inactivecolor: " + inactivemask + "\n"; } return outstring; } /** * Returns a new clone (a new Button object exactly like this one) * @return Button clone * @type Button */ Button.prototype.clone = function() { var nbutton = new Button(this.name, this.sketcher); if (typeof(this.data) == "object") { nbutton.data = new Array(this.data.length); for (var i=0; i<this.data.length;i++) nbutton.data[i] = this.data[i]; } else nbutton.data = this.data; nbutton.className = this.className; nbutton.handler = this.handler; nbutton.color = [this.color[0],this.color[1],this.color[2],this.color[3]]; nbutton.hitmask = [this.hitmask[0],this.hitmask[1],this.hitmask[2],this.hitmask[3]]; nbutton.overmask = [this.overmask[0],this.overmask[1],this.overmask[2],this.overmask[3]]; nbutton.inactivemask = [this.inactivemask[0],this.inactivemask[1],this.inactivemask[2],this.inactivemask[3]]; nbutton.clickedHoldMax = this.clickedHoldMax; nbutton.clickedCount = 0; nbutton.active = this.active; nbutton.hidden = this.hidden; nbutton.setScale(this.scale[0], this.scale[1]); nbutton.setScreenLocation(this.screenLocation[0], this.screenLocation[1], this.screenLocation[2]); return nbutton; } /** * Simple GUI Button subclass with picture icon. * Inherits from button parent class. Square by default. * @constructor */ function IconButton(name, sketcher, iconFile) { /** * @private */ this.parent = Button; this.parent(name, sketcher); /** * Name of the class: "IconButton" * @final * @type String * @see Button#className */ this.className = "IconButton"; /** * R,G,B,A color of this Button's base (will tint image). * Base color is by default all white [1,1,1,1]. * @type Array(4) */ this.color = [1,1,1,1]; /** * File name of an image file for this Button's icon. * @type String */ this.iconFile = iconFile || ""; if (this.iconFile != "") { /** * Image object holding the loaded iconFile's data. * @type Image * @private */ this.iconImage = new Image(this.iconFile); this.setSize(this.iconImage.size[0], this.iconImage.size[1]); } else this.iconImage = null; } // inherit from Button class IconButton.prototype = new Button; /** * Loads an icon image file, returns true if success, false otherwise. * @return true if success, false otherwise. * @type Boolean */ IconButton.prototype.loadIcon = function(iconFile) { var return_val = false; if (iconFile) this.iconFile = iconFile; if (this.iconFile != "") { this.iconImage = new Image(this.iconFile); return_val = true; } else { if (this.debug > 0) post("IconButton ("+this.name+") called loadIcon with no icon filename set\n"); this.iconImage = null; return_val = true; // set button size properties this.setSize(this.iconImage.size[0], this.iconImage.size[1]); } this.needsDraw = true; return return_val; } /** * Overloaded drawBase function from Button that draws only the icon image. */ IconButton.prototype.drawBase = function() { this.sketcher.glcolor(this.color); this.sketcher.copypixels(this.iconImage, this.screenLocation[0],this.screenLocation[1]); } /** * Simple GUI Button subclass with text label. * Inherits from button parent class. It's square by default. * @constructor */ function TextButton(name, sketcher, text) { /** * @private */ this.parent = Button; this.parent(name, sketcher); /** * Name of the class: "TextButton" * @final * @type String * @see Button#className */ this.className = "TextButton"; /** * R,G,B,A color of this Button's text. * Text color is by default solid black [0,0,0,1]. * @type Array(4) */ this.textColor = [0,0,0,1]; /** * Font name for text. * @type String */ this.font = "Arial"; /** * Font size (points) for text. * @type float */ this.fontSize = 10; //points /** * Text to display across Button. * @type String */ this.text = text || "button"; } // inherit from Button class TextButton.prototype = new Button; /** * Set this Button's text string. * @param {String} text text string to display across Button. * @param {String} font Font name for text. * @param {float} fontSize Font size in points. */ TextButton.prototype.setText = function(text, font, fontSize) { this.text = text; if (font) this.font = font; if (fontSize) this.fontSize = fontSize; this.needsDraw = true; } /** * Get this Button's text string. * @return text string * @type String */ TextButton.prototype.getText = function() { return this.text; } /** * Overloaded drawBase function from Button that draws a plain rectangle and then text. */ TextButton.prototype.drawBase = function() { with (this.sketcher) { glcolor(this.color); moveto(this.worldLocation); plane(this.scale); // move to top left corner move(-this.scale[0]+0.02,-0.02); font(this.font); fontsize(this.fontSize); glcolor(this.textColor); text(this.text); moveto(this.worldLocation); } } /** * Simple GUI-related events handler interface class for GUI events. * Handles calls for associated GUILIstener. * @constructor */ function GUIHandler() { /** * Name of the class: "GUIHandler" * @final * @type String */ this.className = "GUIHandler"; } GUIHandler.prototype.clicked = function(data,x,y,button,cmd,shift,capslock,option,ctrl) {} GUIHandler.prototype.dblclicked = function(data,x,y,button,cmd,shift,capslock,option,ctrl) {} GUIHandler.prototype.dragged = function(data,x,y,button,cmd,shift,capslock,option,ctrl) {} GUIHandler.prototype.mouseover = function(data,x,y,button,cmd,shift,capslock,option,ctrl) {} GUIHandler.prototype.mouseout = function(data,x,y,button,cmd,shift,capslock,option,ctrl) {} GUIHandler.prototype.idleout = function(data,x,y,button,cmd,shift,capslock,option,ctrl) {} /********************************************************************* end lfo.jsui.js *********************************************************************/ /** * Simple GUI-related events handler class for GUI events. * Receives events from UI elements and simply outputs them out the first outlet of the jsui. * @constructor * @base GUIHandler */ function ExampleGUIHandler() { /** * Name of the class: "ExampleGUIHandler" * @final * @type String * @see GUIHandler#className */ this.className = "SillyGUIHandler"; /** * @private */ this.parent = GUIHandler; } ExampleGUIHandler.prototype = new GUIHandler; ExampleGUIHandler.prototype.clicked = function(data,x,y,button,cmd,shift,capslock,option,ctrl) { outlet(0,"clicked", data,x,y,button,cmd,shift,capslock,option,ctrl); clickedButton = data; } ExampleGUIHandler.prototype.dblclicked = function(data,x,y,button,cmd,shift,capslock,option,ctrl) { outlet(0,"dblclicked", data,x,y,button,cmd,shift,capslock,option,ctrl); dblclickedButton = data; } ExampleGUIHandler.prototype.dragged = function(data,x,y,button,cmd,shift,capslock,option,ctrl) { outlet(0,"dragged", data,x,y,button,cmd,shift,capslock,option,ctrl); draggedButton = data; } ExampleGUIHandler.prototype.mouseover = function(data,x,y,button,cmd,shift,capslock,option,ctrl) { outlet(0,"over", data,x,y,button,cmd,shift,capslock,option,ctrl); overButton = data; } ExampleGUIHandler.prototype.mouseout = function(data,x,y,button,cmd,shift,capslock,option,ctrl) { outlet(0,"over", data,x,y,button,cmd,shift,capslock,option,ctrl); overButton = ""; } ExampleGUIHandler.prototype.idleout = function(data,x, y, button, mod1, shift, caps, opt, mod2) { overButton = ""; }
|
||||||||
| PREV NEXT | FRAMES NO FRAMES | |||||||