//// uiwidgets.js// examples/libraries//// Created by Seiji Emery, 8/10/15// Copyright 2015 High Fidelity, Inc//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// (function(){ // Setup externals(function() { // We need a Vec2 impl, with add() and a clone function. If this is not part of hifi, we'll just add it:if (this.Vec2 == undefined) { var Vec2 = this.Vec2 = function (x, y) { this.x = x || 0.0; this.y = y || 0.0; } Vec2.sum = function (a, b) { return new Vec2(a.x + b.x, a.y + b.y); } Vec2.clone = function (v) { return new Vec2(v.x, v.y); }} else if (this.Vec2.clone == undefined) { this.Vec2.clone = function (v) { return { 'x': v.x || 0.0, 'y': v.y || 0.0 }; }} else {}})(); var Rect = function (xmin, ymin, xmax, ymax) { this.x0 = xmin; this.y0 = ymin; this.x1 = xmax; this.y1 = ymax;}Rect.prototype.grow = function (pt) { this.x0 = Math.min(this.x0, pt.x); this.y0 = Math.min(this.y0, pt.y); this.x1 = Math.max(this.x1, pt.x); this.y1 = Math.max(this.y1, pt.y);}Rect.prototype.getWidth = function () { return this.x1 - this.x0;}Rect.prototype.getHeight = function () { return this.y1 - this.y0;}Rect.prototype.getTopLeft = function () { return { 'x': this.x0, 'y': this.y0 };}Rect.prototype.getBtmRight = function () { return { 'x': this.x1, 'y': this.y1 };}Rect.prototype.getCenter = function () { return { 'x': 0.5 * (this.x1 + this.x0), 'y': 0.5 * (this.y1 + this.y0) };} var __trace = new Array();var __traceDepth = 0; var assert = function (cond, expr) { if (!cond) { var callstack = ""; var maxRecursion = 10; caller = arguments.callee.caller; while (maxRecursion > 0 && caller) { --maxRecursion; callstack += ">> " + caller.toString(); caller = caller.caller; } throw new Error("assertion failed: " + expr + " (" + cond + ")" + "\n" + "Called from: " + callstack + " " + "Traceback: \n\t" + __trace.join("\n\t")); }}var traceEnter = function(fcn) { var l = __trace.length; // print("TRACE ENTER: " + (l+1)); s = ""; for (var i = 0; i < __traceDepth+1; ++i) s += "-"; ++__traceDepth; __trace.push(s + fcn); __trace.push(__trace.pop() + ":" + this); return { 'exit': function () { --__traceDepth; // while (__trace.length != l) // __trace.pop(); } };} /// UI namespacevar UI = this.UI = {}; var rgb = UI.rgb = function (r, g, b) { if (typeof(r) == 'string') { rs = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(r); if (rs) { r = parseInt(rs[0], 16); g = parseInt(rs[1], 16); b = parseInt(rs[2], 16); } } if (typeof(r) != 'number' || typeof(g) != 'number' || typeof(b) != 'number') { ui.err("Invalid args to UI.rgb (" + r + ", " + g + ", " + b + ")"); return null; } return { 'red': r, 'green': g, 'blue': b };}var rgba = UI.rgba = function (r, g, b, a) { if (typeof(r) == 'string') return rgb(r); return { 'red': r || 0, 'green': g || 0, 'blue': b || 0, 'a': a };} /// Protected UI statevar ui = { defaultVisible: true, widgetList: new Array(), attachmentList: new Array()}; ui.complain = function (msg) { print("WARNING (uiwidgets.js): " + msg);}ui.errorHandler = function (err) { print(err);}ui.assert = function (condition, message) { if (!condition) { message = "FAILED ASSERT (uiwidgets.js): " + message || "(" + condition + ")"; ui.errorHandler(message); if (typeof(Error) !== 'undefined') throw new Error(message); throw message; }} UI.setDefaultVisibility = function (visible) { ui.defaultVisible = visible;} /// Wrapper around the overlays implfunction makeOverlay(type, properties) { var overlay = Overlays.addOverlay(type, properties); return { 'update': function (properties) { var _TRACE = traceEnter.call(this, "Overlay.update"); Overlays.editOverlay(overlay, properties); _TRACE.exit(); }, 'destroy': function () { var _TRACE = traceEnter.call(this, "Overlay.destroy"); Overlays.deleteOverlay(overlay); _TRACE.exit(); }, 'getId': function () { return overlay; } }} var COLOR_WHITE = rgb(255, 255, 255);var COLOR_GRAY = rgb(125, 125, 125); /// Base widget class.var Widget = function () {}; // Shared methods:var __widgetId = 0;Widget.prototype.constructor = function () { this.position = { 'x': 0.0, 'y': 0.0 }; this.dimensions = null; this.visible = ui.defaultVisible; this.parentVisible = null; this.actions = {}; this._dirty = true; this.parent = null; this.id = __widgetId++; ui.widgetList.push(this);}Widget.prototype.setPosition = function (x, y) { if (arguments.length == 1 && typeof(arguments[0]) == 'object') { x = arguments[0].x; y = arguments[0].y; } if (typeof(x) != 'number' || typeof(y) != 'number') { ui.complain("invalid arguments to " + this + ".setPosition: '" + arguments + "' (expected (x, y) or (vec2))"); } else { this.position.x = x; this.position.y = y; }}Widget.prototype.setVisible = function (visible) { this.visible = visible; this.parentVisible = null; // set dirty}Widget.prototype.isVisible = function () { if (this.parentVisible === null) this.parentVisible = this.parent ? this.parent.isVisible() : true; return this.visible && this.parentVisible;}// Store lists of actions (multiple callbacks per key)Widget.prototype.addAction = function (action, callback) { if (!this.actions[action]) this.actions[action] = [ callback ]; else this.actions[action].push(callback);}Widget.prototype.clearLayout = function () { this.dimensions = null; this.parentVisible = null;}// Overridden methods:Widget.prototype.toString = function () { return "[Widget " + this.id + " ]";}Widget.prototype.getOverlay = function () { return null;}Widget.prototype.getWidth = function () { return 0;}Widget.prototype.getHeight = function () { return 0;}Widget.prototype.hasOverlay = function () { return false;}Widget.prototype.applyLayout = function () {};Widget.prototype.updateOverlays = function () {}; /// Implements a simple auto-layouted container of methods./// @param properties/// dir: [string]/// layout direction. /// Can be one of [ '+x', '+y', '-x', '-y' ] for 2d directions./// border: { x: _, y: _ } /// Adds spacing to the widget on all sides (aka. margin). Defaults to 0./// padding: { x: _, y: _ }/// Padding in between each widget. Only one axis is used (the layout direction)./// visible: true | false/// Acts as both a widget (logical) property and is used for overlays./// Hiding this will hide all child widgets (non-destructively)./// Do not access this directly -- use setVisible(value) and isVisible() instead./// background: [object] /// Properties to use for the background overlay (if defined).///var WidgetStack = UI.WidgetStack = function (properties) { var _TRACE = traceEnter.call(this, "WidgetStack.constructor()"); Widget.prototype.constructor.call(this); assert(ui.widgetList[ui.widgetList.length-1] === this, "ui.widgetList.back() == this"); properties = properties || {}; properties['dir'] = properties['dir'] || '+y'; var dir = undefined; switch(properties['dir']) { case '+y': dir = { 'x': 0.0, 'y': 1.0 }; break; case '-y': dir = { 'x': 0.0, 'y': -1.0 }; break; case '+x': dir = { 'x': 1.0, 'y': 0.0 }; break; case '-x': dir = { 'x': -1.0, 'y': 0.0 }; break; default: ui.complain("Unrecognized UI.WidgetStack property 'dir': \"" + dir + "\""); } dir = dir || { 'x': 1.0, 'y': 0.0 }; this.layoutDir = dir; this.border = properties.border || { 'x': 0.0, 'y': 0.0 }; this.padding = properties.padding || { 'x': 0.0, 'y': 0.0 }; this.visible = properties.visible != undefined ? properties.visible : this.visible; if (properties.background) { var background = properties.background; background.x = this.position ? this.position.x : 0; background.y = this.position ? this.position.y : 0; background.width = background.width || 100.0; background.height = background.height || 100.0; background.backgroundColor = background.backgroundColor || COLOR_GRAY; background.backgroundAlpha = background.backgroundAlpha || 0.5; background.textColor = background.textColor || COLOR_WHITE; background.alpha = background.alpha || 1.0; background.visible = this.visible; this.backgroundOverlay = makeOverlay("text", background); } else { this.backgroundOverlay = null; } this.widgets = new Array(); _TRACE.exit();}WidgetStack.prototype = new Widget();WidgetStack.prototype.constructor = WidgetStack; WidgetStack.prototype.toString = function () { return "[WidgetStack " + this.id + " ]";} WidgetStack.prototype.add = function (widget) { this.widgets.push(widget); widget.parent = this; return widget;}WidgetStack.prototype.hasOverlay = function (overlayId) { return this.backgroundOverlay && this.backgroundOverlay.getId() === overlayId;}WidgetStack.prototype.getOverlay = function () { return this.backgroundOverlay;}WidgetStack.prototype.destroy = function () { if (this.backgroundOverlay) { this.backgroundOverlay.destroy(); this.backgroundOverlay = null; }}WidgetStack.prototype.setColor = function (color) { if (arguments.length != 1) { color = rgba.apply(arguments); } this.backgroundOverlay.update({ 'color': color, 'alpha': color.a });}var sumOf = function (list, f) { var sum = 0.0; list.forEach(function (elem) { sum += f(elem); }) return sum;}WidgetStack.prototype.calculateDimensions = function () { var totalWidth = 0.0, maxWidth = 0.0; var totalHeight = 0.0, maxHeight = 0.0; this.widgets.forEach(function (widget) { totalWidth += widget.getWidth() + this.padding.x; maxWidth = Math.max(maxWidth, widget.getWidth()); totalHeight += widget.getHeight() + this.padding.y; maxHeight = Math.max(maxHeight, widget.getHeight()); }, this); this.dimensions = { x: this.border.x * 2 + Math.max(totalWidth * this.layoutDir.x - this.padding.x, maxWidth), y: this.border.y * 2 + Math.max(totalHeight * this.layoutDir.y - this.padding.y, maxHeight) };}WidgetStack.prototype.getWidth = function () { if (!this.dimensions) this.calculateDimensions(); return this.dimensions.x;}WidgetStack.prototype.getHeight = function () { if (!this.dimensions) this.calculateDimensions(); return this.dimensions.y;}WidgetStack.prototype.applyLayout = function () { var x = this.position.x + this.border.x; var y = this.position.y + this.border.y; this.widgets.forEach(function (widget) { widget.setPosition(x, y); x += (widget.getWidth() + this.padding.x) * this.layoutDir.x; y += (widget.getHeight() + this.padding.y) * this.layoutDir.y; widget._parentVisible = this.isVisible(); }, this);}WidgetStack.prototype.updateOverlays = function () { if (this.backgroundOverlay) { this.backgroundOverlay.update({ width: this.getWidth(), height: this.getHeight(), x: this.position.x, y: this.position.y, visible: this.isVisible() }); }} /// GUI Textured Rectvar Image = UI.Image = function (properties) { Widget.prototype.constructor.call(this); this.visible = properties.visible != undefined ? properties.visible : this.visible; this.width = properties.width || 1.0; this.height = properties.height || 1.0; var imageProperties = { 'color': properties.color || COLOR_GRAY, 'alpha': properties.alpha || 1.0, 'imageURL': properties.imageURL, 'width': this.width, 'height': this.height, 'x': this.position ? this.position.x : 0.0, 'y': this.position ? this.position.y : 0.0, 'visible': this.visible } this.imageOverlay = makeOverlay("image", imageProperties);}Image.prototype = new Widget();Image.prototype.constructor = Image;Image.prototype.toString = function () { return "[UI.Image " + this.id + " ]";}Image.prototype.getHeight = function () { return this.height;}Image.prototype.getWidth = function () { return this.width;}Image.prototype.hasOverlay = function (overlayId) { return this.imageOverlay.getId() === overlayId;}Image.prototype.getOverlay = function () { return this.imageOverlay;}Image.prototype.destroy = function () { if (this.imageOverlay) { this.imageOverlay.destroy(); this.imageOverlay = null; }}Image.prototype.setColor = function (color) { if (arguments.length != 1) { color = rgba.apply(arguments); } this.imageOverlay.update({ 'color': color, 'alpha': color.a });}Image.prototype.getWidth = function () { return this.width;}Image.prototype.getHeight = function () { return this.height;}Image.prototype.updateOverlays = function () { this.imageOverlay.update({ width: this.width, height: this.height, x: this.position.x, y: this.position.y, visible: this.isVisible() });} /// GUI Rect. Internally implemented using a text overlay.var Box = UI.Box = function (properties) { Widget.prototype.constructor.call(this); properties = properties || {}; properties.width = properties.width || 10; properties.height = properties.height || 10; properties.visible = properties.visible !== undefined ? properties.visible : this.visible; properties.x = this.position.x; properties.y = this.position.y; this.width = properties.width; this.height = properties.height; this.visible = properties.visible; this.overlay = makeOverlay("text", properties);};Box.prototype = new Widget();Box.prototype.constructor = Box;Box.prototype.toString = function () { return "[UI.Box " + this.id + " ]";}Box.prototype.getWidth = function () { return this.width;}Box.prototype.getHeight = function () { return this.height;}Box.prototype.destroy = function () { if (this.overlay) { this.overlay.destroy(); this.overlay = null; }}Box.prototype.hasOverlay = function (overlayId) {Lines 1–500 of 1048. Load more
// // uiwidgets.js // examples/libraries // // Created by Seiji Emery, 8/10/15 // Copyright 2015 High Fidelity, Inc // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // (function(){ // Setup externals (function() { // We need a Vec2 impl, with add() and a clone function. If this is not part of hifi, we'll just add it: if (this.Vec2 == undefined) { var Vec2 = this.Vec2 = function (x, y) { this.x = x || 0.0; this.y = y || 0.0; } Vec2.sum = function (a, b) { return new Vec2(a.x + b.x, a.y + b.y); } Vec2.clone = function (v) { return new Vec2(v.x, v.y); } } else if (this.Vec2.clone == undefined) { this.Vec2.clone = function (v) { return { 'x': v.x || 0.0, 'y': v.y || 0.0 }; } } else {} })(); var Rect = function (xmin, ymin, xmax, ymax) { this.x0 = xmin; this.y0 = ymin; this.x1 = xmax; this.y1 = ymax; } Rect.prototype.grow = function (pt) { this.x0 = Math.min(this.x0, pt.x); this.y0 = Math.min(this.y0, pt.y); this.x1 = Math.max(this.x1, pt.x); this.y1 = Math.max(this.y1, pt.y); } Rect.prototype.getWidth = function () { return this.x1 - this.x0; } Rect.prototype.getHeight = function () { return this.y1 - this.y0; } Rect.prototype.getTopLeft = function () { return { 'x': this.x0, 'y': this.y0 }; } Rect.prototype.getBtmRight = function () { return { 'x': this.x1, 'y': this.y1 }; } Rect.prototype.getCenter = function () { return { 'x': 0.5 * (this.x1 + this.x0), 'y': 0.5 * (this.y1 + this.y0) }; } var __trace = new Array(); var __traceDepth = 0; var assert = function (cond, expr) { if (!cond) { var callstack = ""; var maxRecursion = 10; caller = arguments.callee.caller; while (maxRecursion > 0 && caller) { --maxRecursion; callstack += ">> " + caller.toString(); caller = caller.caller; } throw new Error("assertion failed: " + expr + " (" + cond + ")" + "\n" + "Called from: " + callstack + " " + "Traceback: \n\t" + __trace.join("\n\t")); } } var traceEnter = function(fcn) { var l = __trace.length; // print("TRACE ENTER: " + (l+1)); s = ""; for (var i = 0; i < __traceDepth+1; ++i) s += "-"; ++__traceDepth; __trace.push(s + fcn); __trace.push(__trace.pop() + ":" + this); return { 'exit': function () { --__traceDepth; // while (__trace.length != l) // __trace.pop(); } }; } /// UI namespace var UI = this.UI = {}; var rgb = UI.rgb = function (r, g, b) { if (typeof(r) == 'string') { rs = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(r); if (rs) { r = parseInt(rs[0], 16); g = parseInt(rs[1], 16); b = parseInt(rs[2], 16); } } if (typeof(r) != 'number' || typeof(g) != 'number' || typeof(b) != 'number') { ui.err("Invalid args to UI.rgb (" + r + ", " + g + ", " + b + ")"); return null; } return { 'red': r, 'green': g, 'blue': b }; } var rgba = UI.rgba = function (r, g, b, a) { if (typeof(r) == 'string') return rgb(r); return { 'red': r || 0, 'green': g || 0, 'blue': b || 0, 'a': a }; } /// Protected UI state var ui = { defaultVisible: true, widgetList: new Array(), attachmentList: new Array() }; ui.complain = function (msg) { print("WARNING (uiwidgets.js): " + msg); } ui.errorHandler = function (err) { print(err); } ui.assert = function (condition, message) { if (!condition) { message = "FAILED ASSERT (uiwidgets.js): " + message || "(" + condition + ")"; ui.errorHandler(message); if (typeof(Error) !== 'undefined') throw new Error(message); throw message; } } UI.setDefaultVisibility = function (visible) { ui.defaultVisible = visible; } /// Wrapper around the overlays impl function makeOverlay(type, properties) { var overlay = Overlays.addOverlay(type, properties); return { 'update': function (properties) { var _TRACE = traceEnter.call(this, "Overlay.update"); Overlays.editOverlay(overlay, properties); _TRACE.exit(); }, 'destroy': function () { var _TRACE = traceEnter.call(this, "Overlay.destroy"); Overlays.deleteOverlay(overlay); _TRACE.exit(); }, 'getId': function () { return overlay; } } } var COLOR_WHITE = rgb(255, 255, 255); var COLOR_GRAY = rgb(125, 125, 125); /// Base widget class. var Widget = function () {}; // Shared methods: var __widgetId = 0; Widget.prototype.constructor = function () { this.position = { 'x': 0.0, 'y': 0.0 }; this.dimensions = null; this.visible = ui.defaultVisible; this.parentVisible = null; this.actions = {}; this._dirty = true; this.parent = null; this.id = __widgetId++; ui.widgetList.push(this); } Widget.prototype.setPosition = function (x, y) { if (arguments.length == 1 && typeof(arguments[0]) == 'object') { x = arguments[0].x; y = arguments[0].y; } if (typeof(x) != 'number' || typeof(y) != 'number') { ui.complain("invalid arguments to " + this + ".setPosition: '" + arguments + "' (expected (x, y) or (vec2))"); } else { this.position.x = x; this.position.y = y; } } Widget.prototype.setVisible = function (visible) { this.visible = visible; this.parentVisible = null; // set dirty } Widget.prototype.isVisible = function () { if (this.parentVisible === null) this.parentVisible = this.parent ? this.parent.isVisible() : true; return this.visible && this.parentVisible; } // Store lists of actions (multiple callbacks per key) Widget.prototype.addAction = function (action, callback) { if (!this.actions[action]) this.actions[action] = [ callback ]; else this.actions[action].push(callback); } Widget.prototype.clearLayout = function () { this.dimensions = null; this.parentVisible = null; } // Overridden methods: Widget.prototype.toString = function () { return "[Widget " + this.id + " ]"; } Widget.prototype.getOverlay = function () { return null; } Widget.prototype.getWidth = function () { return 0; } Widget.prototype.getHeight = function () { return 0; } Widget.prototype.hasOverlay = function () { return false; } Widget.prototype.applyLayout = function () {}; Widget.prototype.updateOverlays = function () {}; /// Implements a simple auto-layouted container of methods. /// @param properties /// dir: [string] /// layout direction. /// Can be one of [ '+x', '+y', '-x', '-y' ] for 2d directions. /// border: { x: _, y: _ } /// Adds spacing to the widget on all sides (aka. margin). Defaults to 0. /// padding: { x: _, y: _ } /// Padding in between each widget. Only one axis is used (the layout direction). /// visible: true | false /// Acts as both a widget (logical) property and is used for overlays. /// Hiding this will hide all child widgets (non-destructively). /// Do not access this directly -- use setVisible(value) and isVisible() instead. /// background: [object] /// Properties to use for the background overlay (if defined). /// var WidgetStack = UI.WidgetStack = function (properties) { var _TRACE = traceEnter.call(this, "WidgetStack.constructor()"); Widget.prototype.constructor.call(this); assert(ui.widgetList[ui.widgetList.length-1] === this, "ui.widgetList.back() == this"); properties = properties || {}; properties['dir'] = properties['dir'] || '+y'; var dir = undefined; switch(properties['dir']) { case '+y': dir = { 'x': 0.0, 'y': 1.0 }; break; case '-y': dir = { 'x': 0.0, 'y': -1.0 }; break; case '+x': dir = { 'x': 1.0, 'y': 0.0 }; break; case '-x': dir = { 'x': -1.0, 'y': 0.0 }; break; default: ui.complain("Unrecognized UI.WidgetStack property 'dir': \"" + dir + "\""); } dir = dir || { 'x': 1.0, 'y': 0.0 }; this.layoutDir = dir; this.border = properties.border || { 'x': 0.0, 'y': 0.0 }; this.padding = properties.padding || { 'x': 0.0, 'y': 0.0 }; this.visible = properties.visible != undefined ? properties.visible : this.visible; if (properties.background) { var background = properties.background; background.x = this.position ? this.position.x : 0; background.y = this.position ? this.position.y : 0; background.width = background.width || 100.0; background.height = background.height || 100.0; background.backgroundColor = background.backgroundColor || COLOR_GRAY; background.backgroundAlpha = background.backgroundAlpha || 0.5; background.textColor = background.textColor || COLOR_WHITE; background.alpha = background.alpha || 1.0; background.visible = this.visible; this.backgroundOverlay = makeOverlay("text", background); } else { this.backgroundOverlay = null; } this.widgets = new Array(); _TRACE.exit(); } WidgetStack.prototype = new Widget(); WidgetStack.prototype.constructor = WidgetStack; WidgetStack.prototype.toString = function () { return "[WidgetStack " + this.id + " ]"; } WidgetStack.prototype.add = function (widget) { this.widgets.push(widget); widget.parent = this; return widget; } WidgetStack.prototype.hasOverlay = function (overlayId) { return this.backgroundOverlay && this.backgroundOverlay.getId() === overlayId; } WidgetStack.prototype.getOverlay = function () { return this.backgroundOverlay; } WidgetStack.prototype.destroy = function () { if (this.backgroundOverlay) { this.backgroundOverlay.destroy(); this.backgroundOverlay = null; } } WidgetStack.prototype.setColor = function (color) { if (arguments.length != 1) { color = rgba.apply(arguments); } this.backgroundOverlay.update({ 'color': color, 'alpha': color.a }); } var sumOf = function (list, f) { var sum = 0.0; list.forEach(function (elem) { sum += f(elem); }) return sum; } WidgetStack.prototype.calculateDimensions = function () { var totalWidth = 0.0, maxWidth = 0.0; var totalHeight = 0.0, maxHeight = 0.0; this.widgets.forEach(function (widget) { totalWidth += widget.getWidth() + this.padding.x; maxWidth = Math.max(maxWidth, widget.getWidth()); totalHeight += widget.getHeight() + this.padding.y; maxHeight = Math.max(maxHeight, widget.getHeight()); }, this); this.dimensions = { x: this.border.x * 2 + Math.max(totalWidth * this.layoutDir.x - this.padding.x, maxWidth), y: this.border.y * 2 + Math.max(totalHeight * this.layoutDir.y - this.padding.y, maxHeight) }; } WidgetStack.prototype.getWidth = function () { if (!this.dimensions) this.calculateDimensions(); return this.dimensions.x; } WidgetStack.prototype.getHeight = function () { if (!this.dimensions) this.calculateDimensions(); return this.dimensions.y; } WidgetStack.prototype.applyLayout = function () { var x = this.position.x + this.border.x; var y = this.position.y + this.border.y; this.widgets.forEach(function (widget) { widget.setPosition(x, y); x += (widget.getWidth() + this.padding.x) * this.layoutDir.x; y += (widget.getHeight() + this.padding.y) * this.layoutDir.y; widget._parentVisible = this.isVisible(); }, this); } WidgetStack.prototype.updateOverlays = function () { if (this.backgroundOverlay) { this.backgroundOverlay.update({ width: this.getWidth(), height: this.getHeight(), x: this.position.x, y: this.position.y, visible: this.isVisible() }); } } /// GUI Textured Rect var Image = UI.Image = function (properties) { Widget.prototype.constructor.call(this); this.visible = properties.visible != undefined ? properties.visible : this.visible; this.width = properties.width || 1.0; this.height = properties.height || 1.0; var imageProperties = { 'color': properties.color || COLOR_GRAY, 'alpha': properties.alpha || 1.0, 'imageURL': properties.imageURL, 'width': this.width, 'height': this.height, 'x': this.position ? this.position.x : 0.0, 'y': this.position ? this.position.y : 0.0, 'visible': this.visible } this.imageOverlay = makeOverlay("image", imageProperties); } Image.prototype = new Widget(); Image.prototype.constructor = Image; Image.prototype.toString = function () { return "[UI.Image " + this.id + " ]"; } Image.prototype.getHeight = function () { return this.height; } Image.prototype.getWidth = function () { return this.width; } Image.prototype.hasOverlay = function (overlayId) { return this.imageOverlay.getId() === overlayId; } Image.prototype.getOverlay = function () { return this.imageOverlay; } Image.prototype.destroy = function () { if (this.imageOverlay) { this.imageOverlay.destroy(); this.imageOverlay = null; } } Image.prototype.setColor = function (color) { if (arguments.length != 1) { color = rgba.apply(arguments); } this.imageOverlay.update({ 'color': color, 'alpha': color.a }); } Image.prototype.getWidth = function () { return this.width; } Image.prototype.getHeight = function () { return this.height; } Image.prototype.updateOverlays = function () { this.imageOverlay.update({ width: this.width, height: this.height, x: this.position.x, y: this.position.y, visible: this.isVisible() }); } /// GUI Rect. Internally implemented using a text overlay. var Box = UI.Box = function (properties) { Widget.prototype.constructor.call(this); properties = properties || {}; properties.width = properties.width || 10; properties.height = properties.height || 10; properties.visible = properties.visible !== undefined ? properties.visible : this.visible; properties.x = this.position.x; properties.y = this.position.y; this.width = properties.width; this.height = properties.height; this.visible = properties.visible; this.overlay = makeOverlay("text", properties); }; Box.prototype = new Widget(); Box.prototype.constructor = Box; Box.prototype.toString = function () { return "[UI.Box " + this.id + " ]"; } Box.prototype.getWidth = function () { return this.width; } Box.prototype.getHeight = function () { return this.height; } Box.prototype.destroy = function () { if (this.overlay) { this.overlay.destroy(); this.overlay = null; } } Box.prototype.hasOverlay = function (overlayId) {