From f25df878258d63e6c3089ba724004271f51d77b9 Mon Sep 17 00:00:00 2001 From: Eric Westphal Date: Fri, 10 Mar 2017 22:03:35 -0500 Subject: [PATCH] Add G Meter to UI. --- web/Makefile | 2 +- web/css/ahrs.css | 115 ++ web/css/main.css | 54 - web/index.html | 3 +- web/js/j3di-all.js | 3240 ---------------------------------------- web/js/j3di-all.min.js | 2 - web/js/svg.min.js | 3 + web/plates/gps.html | 23 +- web/plates/js/ahrs.js | 96 +- web/plates/js/gps.js | 6 +- web/stratux.appcache | 3 +- 11 files changed, 236 insertions(+), 3311 deletions(-) create mode 100644 web/css/ahrs.css delete mode 100644 web/js/j3di-all.js delete mode 100644 web/js/j3di-all.min.js create mode 100644 web/js/svg.min.js diff --git a/web/Makefile b/web/Makefile index cbf8254f..d85a7b5e 100644 --- a/web/Makefile +++ b/web/Makefile @@ -10,7 +10,7 @@ all: mkdir -p /var/www/js cp js/main.js /var/www/js cp js/addtohomescreen.min.js /var/www/js - cp js/j3di-all.min.js /var/www/js + cp js/svg.min.js /var/www/js mkdir -p /var/www/img cp img/logo*.png /var/www/img cp img/screen*.png /var/www/img diff --git a/web/css/ahrs.css b/web/css/ahrs.css new file mode 100644 index 00000000..10e1337e --- /dev/null +++ b/web/css/ahrs.css @@ -0,0 +1,115 @@ +/* Thanks to https://codepen.io/fskirschbaum/pen/MYJNaj for the indicator template */ + +.indicator { + margin: 0 1%; + width: 18%; + height: 100%; + background-color: #ABFF00; + border-radius: 10%; + box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 9px, #89FF00 0 2px 12px; +} + +.indicator.off { + background-color: #F00; +} + +.indicator.on { + background-color: #ABFF00; +} + +.indicator.blink { + background-color: #F00; + -webkit-animation: blinkRed 1s infinite; + -moz-animation: blinkRed 1s infinite; + -ms-animation: blinkRed 1s infinite; + -o-animation: blinkRed 1s infinite; + animation: blinkRed 1s infinite; +} + +@-webkit-keyframes blinkRed { + from { background-color: #F22; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F22; } +} +@-moz-keyframes blinkRed { + from { background-color: #F22; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F22; } +} +@-ms-keyframes blinkRed { + from { background-color: #F22; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F22; } +} +@-o-keyframes blinkRed { + from { background-color: #F22; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F22; } +} +@keyframes blinkRed { + from { background-color: #F22; } + 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} + to { background-color: #F22; } +} + +/* For g-meter */ +.gMeter .reset { + fill: #121512; + stroke: #222522; +} + +.gMeter .card { + fill: #121512; + stroke: #222522; +} + +.gMeter .center { + fill: #172017; + stroke: #222522; +} + +.gMeter .pointer { + stroke: #bbbbcc; + fill: #ddddee; +} + +.gMeter .pointerBG { + fill: #bbbbcc; +} + +.gMeter .marks { + fill: #ddddee; + stroke: #eeeeff; + stroke-width: 4; +} + +.gMeter .big { + stroke-width: 6; +} + +.gMeter .one { + stroke-width: 8; +} + +.gMeter .limit { + fill: #dd2222; + stroke: #ff1111; + stroke-width: 6; +} + +.gMeter .text { + font-size: 1em; + font-family: sans-serif; + text-anchor: middle; + stroke-width: 0; + fill: #ddddee; +} + +.gMeter .card .text { + font-size: 2.5em; +} + +.gMeter .reset .text { + text-anchor: start; +} + diff --git a/web/css/main.css b/web/css/main.css index f7783d50..643dc24f 100644 --- a/web/css/main.css +++ b/web/css/main.css @@ -440,57 +440,3 @@ body { transition: transform 0 ease; } } - -/* Thanks to https://codepen.io/fskirschbaum/pen/MYJNaj for the indicator template */ - -.indicator { - margin: 0 1%; - width: 18%; - height: 100%; - background-color: #ABFF00; - border-radius: 10%; - box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 9px, #89FF00 0 2px 12px; -} - -.indicator.off { - background-color: #F00; -} - -.indicator.on { - background-color: #ABFF00; -} - -.indicator.blink { - background-color: #F00; - -webkit-animation: blinkRed 1s infinite; - -moz-animation: blinkRed 1s infinite; - -ms-animation: blinkRed 1s infinite; - -o-animation: blinkRed 1s infinite; - animation: blinkRed 1s infinite; -} - -@-webkit-keyframes blinkRed { - from { background-color: #F22; } - 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} - to { background-color: #F22; } -} -@-moz-keyframes blinkRed { - from { background-color: #F22; } - 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} - to { background-color: #F22; } -} -@-ms-keyframes blinkRed { - from { background-color: #F22; } - 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} - to { background-color: #F22; } -} -@-o-keyframes blinkRed { - from { background-color: #F22; } - 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} - to { background-color: #F22; } -} -@keyframes blinkRed { - from { background-color: #F22; } - 50% { background-color: #A00; box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #441313 0 -1px 9px, rgba(255, 0, 0, 0.5) 0 2px 0;} - to { background-color: #F22; } -} diff --git a/web/index.html b/web/index.html index 48594d4e..491f1eb2 100644 --- a/web/index.html +++ b/web/index.html @@ -37,6 +37,7 @@ + @@ -61,7 +63,6 @@ - diff --git a/web/js/j3di-all.js b/web/js/j3di-all.js deleted file mode 100644 index f19457c5..00000000 --- a/web/js/j3di-all.js +++ /dev/null @@ -1,3240 +0,0 @@ -/* - * Copyright 2010, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -/** - * @fileoverview This file contains functions every webgl program will need - * a version of one way or another. - * - * Instead of setting up a context manually it is recommended to - * use. This will check for success or failure. On failure it - * will attempt to present an approriate message to the user. - * - * gl = WebGLUtils.setupWebGL(canvas); - * - * For animated WebGL apps use of setTimeout or setInterval are - * discouraged. It is recommended you structure your rendering - * loop like this. - * - * function render() { - * window.requestAnimFrame(render, canvas); - * - * // do rendering - * ... - * } - * render(); - * - * This will call your rendering function up to the refresh rate - * of your display but will stop rendering if your app is not - * visible. - */ - -WebGLUtils = function () { - - /** - * Creates the HTLM for a failure message - * @param {string} canvasContainerId id of container of th - * canvas. - * @return {string} The html. - */ - var makeFailHTML = function (msg) { - return '' + - '' + - '
' + - '
' + - '
' + msg + '
' + - '
' + - '
'; - }; - - /** - * Mesasge for getting a webgl browser - * @type {string} - */ - var GET_A_WEBGL_BROWSER = '' + - 'This page requires a browser that supports WebGL.
' + - 'Click here to upgrade your browser.'; - - /** - * Mesasge for need better hardware - * @type {string} - */ - var OTHER_PROBLEM = '' + - "It doesn't appear your computer can support WebGL.
" + - 'Click here for more information.'; - - /** - * Creates a webgl context. If creation fails it will - * change the contents of the container of the - * tag to an error message with the correct links for WebGL. - * @param {Element} canvas. The canvas element to create a - * context from. - * @param {WebGLContextCreationAttirbutes} opt_attribs Any - * creation attributes you want to pass in. - * @return {WebGLRenderingContext} The created context. - */ - var setupWebGL = function (canvas, opt_attribs) { - function showLink(str) { - var container = canvas.parentNode; - if (container) { - container.innerHTML = makeFailHTML(str); - } - }; - - if (!window.WebGLRenderingContext) { - showLink(GET_A_WEBGL_BROWSER); - return null; - } - - var context = create3DContext(canvas, opt_attribs); - if (!context) { - showLink(OTHER_PROBLEM); - } - return context; - }; - - /** - * Creates a webgl context. - * @param {!Canvas} canvas The canvas tag to get context - * from. If one is not passed in one will be created. - * @return {!WebGLContext} The created context. - */ - var create3DContext = function (canvas, opt_attribs) { - var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"]; - var context = null; - for (var ii = 0; ii < names.length; ++ii) { - try { - context = canvas.getContext(names[ii], opt_attribs); - } catch (e) {} - if (context) { - break; - } - } - return context; - }; - - return { - create3DContext: create3DContext, - setupWebGL: setupWebGL - }; -}(); - -/** - * Provides requestAnimationFrame in a cross browser way. - */ -window.requestAnimFrame = (function () { - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function ( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element) { - return window.setTimeout(callback, 1000 / 60); - }; -})(); - -/** - * Provides cancelAnimationFrame in a cross browser way. - */ -window.cancelAnimFrame = (function () { - return window.cancelAnimationFrame || - window.webkitCancelAnimationFrame || - window.mozCancelAnimationFrame || - window.oCancelAnimationFrame || - window.msCancelAnimationFrame || - window.clearTimeout; -})(); - - -/* - ** Copyright (c) 2012 The Khronos Group Inc. - ** - ** Permission is hereby granted, free of charge, to any person obtaining a - ** copy of this software and/or associated documentation files (the - ** "Materials"), to deal in the Materials without restriction, including - ** without limitation the rights to use, copy, modify, merge, publish, - ** distribute, sublicense, and/or sell copies of the Materials, and to - ** permit persons to whom the Materials are furnished to do so, subject to - ** the following conditions: - ** - ** The above copyright notice and this permission notice shall be included - ** in all copies or substantial portions of the Materials. - ** - ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. - */ - -// Various functions for helping debug WebGL apps. - -WebGLDebugUtils = function () { - - /** - * Wrapped logging function. - * @param {string} msg Message to log. - */ - var log = function (msg) { - if (window.console && window.console.log) { - window.console.log(msg); - } - }; - - /** - * Wrapped error logging function. - * @param {string} msg Message to log. - */ - var error = function (msg) { - if (window.console && window.console.error) { - window.console.error(msg); - } else { - log(msg); - } - }; - - - /** - * Which arguments are enums based on the number of arguments to the function. - * So - * 'texImage2D': { - * 9: { 0:true, 2:true, 6:true, 7:true }, - * 6: { 0:true, 2:true, 3:true, 4:true }, - * }, - * - * means if there are 9 arguments then 6 and 7 are enums, if there are 6 - * arguments 3 and 4 are enums - * - * @type {!Object.} - */ - var glValidEnumContexts = { - // Generic setters and getters - - 'enable': { - 1: { - 0: true - } - }, - 'disable': { - 1: { - 0: true - } - }, - 'getParameter': { - 1: { - 0: true - } - }, - - // Rendering - - 'drawArrays': { - 3: { - 0: true - } - }, - 'drawElements': { - 4: { - 0: true, - 2: true - } - }, - - // Shaders - - 'createShader': { - 1: { - 0: true - } - }, - 'getShaderParameter': { - 2: { - 1: true - } - }, - 'getProgramParameter': { - 2: { - 1: true - } - }, - 'getShaderPrecisionFormat': { - 2: { - 0: true, - 1: true - } - }, - - // Vertex attributes - - 'getVertexAttrib': { - 2: { - 1: true - } - }, - 'vertexAttribPointer': { - 6: { - 2: true - } - }, - - // Textures - - 'bindTexture': { - 2: { - 0: true - } - }, - 'activeTexture': { - 1: { - 0: true - } - }, - 'getTexParameter': { - 2: { - 0: true, - 1: true - } - }, - 'texParameterf': { - 3: { - 0: true, - 1: true - } - }, - 'texParameteri': { - 3: { - 0: true, - 1: true, - 2: true - } - }, - 'texImage2D': { - 9: { - 0: true, - 2: true, - 6: true, - 7: true - }, - 6: { - 0: true, - 2: true, - 3: true, - 4: true - } - }, - 'texSubImage2D': { - 9: { - 0: true, - 6: true, - 7: true - }, - 7: { - 0: true, - 4: true, - 5: true - } - }, - 'copyTexImage2D': { - 8: { - 0: true, - 2: true - } - }, - 'copyTexSubImage2D': { - 8: { - 0: true - } - }, - 'generateMipmap': { - 1: { - 0: true - } - }, - 'compressedTexImage2D': { - 7: { - 0: true, - 2: true - } - }, - 'compressedTexSubImage2D': { - 8: { - 0: true, - 6: true - } - }, - - // Buffer objects - - 'bindBuffer': { - 2: { - 0: true - } - }, - 'bufferData': { - 3: { - 0: true, - 2: true - } - }, - 'bufferSubData': { - 3: { - 0: true - } - }, - 'getBufferParameter': { - 2: { - 0: true, - 1: true - } - }, - - // Renderbuffers and framebuffers - - 'pixelStorei': { - 2: { - 0: true, - 1: true - } - }, - 'readPixels': { - 7: { - 4: true, - 5: true - } - }, - 'bindRenderbuffer': { - 2: { - 0: true - } - }, - 'bindFramebuffer': { - 2: { - 0: true - } - }, - 'checkFramebufferStatus': { - 1: { - 0: true - } - }, - 'framebufferRenderbuffer': { - 4: { - 0: true, - 1: true, - 2: true - } - }, - 'framebufferTexture2D': { - 5: { - 0: true, - 1: true, - 2: true - } - }, - 'getFramebufferAttachmentParameter': { - 3: { - 0: true, - 1: true, - 2: true - } - }, - 'getRenderbufferParameter': { - 2: { - 0: true, - 1: true - } - }, - 'renderbufferStorage': { - 4: { - 0: true, - 1: true - } - }, - - // Frame buffer operations (clear, blend, depth test, stencil) - - 'clear': { - 1: { - 0: { - 'enumBitwiseOr': ['COLOR_BUFFER_BIT', 'DEPTH_BUFFER_BIT', 'STENCIL_BUFFER_BIT'] - } - } - }, - 'depthFunc': { - 1: { - 0: true - } - }, - 'blendFunc': { - 2: { - 0: true, - 1: true - } - }, - 'blendFuncSeparate': { - 4: { - 0: true, - 1: true, - 2: true, - 3: true - } - }, - 'blendEquation': { - 1: { - 0: true - } - }, - 'blendEquationSeparate': { - 2: { - 0: true, - 1: true - } - }, - 'stencilFunc': { - 3: { - 0: true - } - }, - 'stencilFuncSeparate': { - 4: { - 0: true, - 1: true - } - }, - 'stencilMaskSeparate': { - 2: { - 0: true - } - }, - 'stencilOp': { - 3: { - 0: true, - 1: true, - 2: true - } - }, - 'stencilOpSeparate': { - 4: { - 0: true, - 1: true, - 2: true, - 3: true - } - }, - - // Culling - - 'cullFace': { - 1: { - 0: true - } - }, - 'frontFace': { - 1: { - 0: true - } - }, - - // ANGLE_instanced_arrays extension - - 'drawArraysInstancedANGLE': { - 4: { - 0: true - } - }, - 'drawElementsInstancedANGLE': { - 5: { - 0: true, - 2: true - } - }, - - // EXT_blend_minmax extension - - 'blendEquationEXT': { - 1: { - 0: true - } - } - }; - - /** - * Map of numbers to names. - * @type {Object} - */ - var glEnums = null; - - /** - * Map of names to numbers. - * @type {Object} - */ - var enumStringToValue = null; - - /** - * Initializes this module. Safe to call more than once. - * @param {!WebGLRenderingContext} ctx A WebGL context. If - * you have more than one context it doesn't matter which one - * you pass in, it is only used to pull out constants. - */ - function init(ctx) { - if (glEnums == null) { - glEnums = {}; - enumStringToValue = {}; - for (var propertyName in ctx) { - if (typeof ctx[propertyName] == 'number') { - glEnums[ctx[propertyName]] = propertyName; - enumStringToValue[propertyName] = ctx[propertyName]; - } - } - } - } - - /** - * Checks the utils have been initialized. - */ - function checkInit() { - if (glEnums == null) { - throw 'WebGLDebugUtils.init(ctx) not called'; - } - } - - /** - * Returns true or false if value matches any WebGL enum - * @param {*} value Value to check if it might be an enum. - * @return {boolean} True if value matches one of the WebGL defined enums - */ - function mightBeEnum(value) { - checkInit(); - return (glEnums[value] !== undefined); - } - - /** - * Gets an string version of an WebGL enum. - * - * Example: - * var str = WebGLDebugUtil.glEnumToString(ctx.getError()); - * - * @param {number} value Value to return an enum for - * @return {string} The string version of the enum. - */ - function glEnumToString(value) { - checkInit(); - var name = glEnums[value]; - return (name !== undefined) ? ("gl." + name) : - ("/*UNKNOWN WebGL ENUM*/ 0x" + value.toString(16) + ""); - } - - /** - * Returns the string version of a WebGL argument. - * Attempts to convert enum arguments to strings. - * @param {string} functionName the name of the WebGL function. - * @param {number} numArgs the number of arguments passed to the function. - * @param {number} argumentIndx the index of the argument. - * @param {*} value The value of the argument. - * @return {string} The value as a string. - */ - function glFunctionArgToString(functionName, numArgs, argumentIndex, value) { - var funcInfo = glValidEnumContexts[functionName]; - if (funcInfo !== undefined) { - var funcInfo = funcInfo[numArgs]; - if (funcInfo !== undefined) { - if (funcInfo[argumentIndex]) { - if (typeof funcInfo[argumentIndex] === 'object' && - funcInfo[argumentIndex]['enumBitwiseOr'] !== undefined) { - var enums = funcInfo[argumentIndex]['enumBitwiseOr']; - var orResult = 0; - var orEnums = []; - for (var i = 0; i < enums.length; ++i) { - var enumValue = enumStringToValue[enums[i]]; - if ((value & enumValue) !== 0) { - orResult |= enumValue; - orEnums.push(glEnumToString(enumValue)); - } - } - if (orResult === value) { - return orEnums.join(' | '); - } else { - return glEnumToString(value); - } - } else { - return glEnumToString(value); - } - } - } - } - if (value === null) { - return "null"; - } else if (value === undefined) { - return "undefined"; - } else { - return value.toString(); - } - } - - /** - * Converts the arguments of a WebGL function to a string. - * Attempts to convert enum arguments to strings. - * - * @param {string} functionName the name of the WebGL function. - * @param {number} args The arguments. - * @return {string} The arguments as a string. - */ - function glFunctionArgsToString(functionName, args) { - // apparently we can't do args.join(","); - var argStr = ""; - var numArgs = args.length; - for (var ii = 0; ii < numArgs; ++ii) { - argStr += ((ii == 0) ? '' : ', ') + - glFunctionArgToString(functionName, numArgs, ii, args[ii]); - } - return argStr; - }; - - - function makePropertyWrapper(wrapper, original, propertyName) { - //log("wrap prop: " + propertyName); - wrapper.__defineGetter__(propertyName, function () { - return original[propertyName]; - }); - // TODO(gmane): this needs to handle properties that take more than - // one value? - wrapper.__defineSetter__(propertyName, function (value) { - //log("set: " + propertyName); - original[propertyName] = value; - }); - } - - // Makes a function that calls a function on another object. - function makeFunctionWrapper(original, functionName) { - //log("wrap fn: " + functionName); - var f = original[functionName]; - return function () { - //log("call: " + functionName); - var result = f.apply(original, arguments); - return result; - }; - } - - /** - * Given a WebGL context returns a wrapped context that calls - * gl.getError after every command and calls a function if the - * result is not gl.NO_ERROR. - * - * @param {!WebGLRenderingContext} ctx The webgl context to - * wrap. - * @param {!function(err, funcName, args): void} opt_onErrorFunc - * The function to call when gl.getError returns an - * error. If not specified the default function calls - * console.log with a message. - * @param {!function(funcName, args): void} opt_onFunc The - * function to call when each webgl function is called. - * You can use this to log all calls for example. - * @param {!WebGLRenderingContext} opt_err_ctx The webgl context - * to call getError on if different than ctx. - */ - function makeDebugContext(ctx, opt_onErrorFunc, opt_onFunc, opt_err_ctx) { - opt_err_ctx = opt_err_ctx || ctx; - init(ctx); - opt_onErrorFunc = opt_onErrorFunc || function (err, functionName, args) { - // apparently we can't do args.join(","); - var argStr = ""; - var numArgs = args.length; - for (var ii = 0; ii < numArgs; ++ii) { - argStr += ((ii == 0) ? '' : ', ') + - glFunctionArgToString(functionName, numArgs, ii, args[ii]); - } - error("WebGL error " + glEnumToString(err) + " in " + functionName + - "(" + argStr + ")"); - }; - - // Holds booleans for each GL error so after we get the error ourselves - // we can still return it to the client app. - var glErrorShadow = {}; - - // Makes a function that calls a WebGL function and then calls getError. - function makeErrorWrapper(ctx, functionName) { - return function () { - if (opt_onFunc) { - opt_onFunc(functionName, arguments); - } - var result = ctx[functionName].apply(ctx, arguments); - var err = opt_err_ctx.getError(); - if (err != 0) { - glErrorShadow[err] = true; - opt_onErrorFunc(err, functionName, arguments); - } - return result; - }; - } - - // Make a an object that has a copy of every property of the WebGL context - // but wraps all functions. - var wrapper = {}; - for (var propertyName in ctx) { - if (typeof ctx[propertyName] == 'function') { - if (propertyName != 'getExtension') { - wrapper[propertyName] = makeErrorWrapper(ctx, propertyName); - } else { - var wrapped = makeErrorWrapper(ctx, propertyName); - wrapper[propertyName] = function () { - var result = wrapped.apply(ctx, arguments); - return makeDebugContext(result, opt_onErrorFunc, opt_onFunc, opt_err_ctx); - }; - } - } else { - makePropertyWrapper(wrapper, ctx, propertyName); - } - } - - // Override the getError function with one that returns our saved results. - wrapper.getError = function () { - for (var err in glErrorShadow) { - if (glErrorShadow.hasOwnProperty(err)) { - if (glErrorShadow[err]) { - glErrorShadow[err] = false; - return err; - } - } - } - return ctx.NO_ERROR; - }; - - return wrapper; - } - - function resetToInitialState(ctx) { - var numAttribs = ctx.getParameter(ctx.MAX_VERTEX_ATTRIBS); - var tmp = ctx.createBuffer(); - ctx.bindBuffer(ctx.ARRAY_BUFFER, tmp); - for (var ii = 0; ii < numAttribs; ++ii) { - ctx.disableVertexAttribArray(ii); - ctx.vertexAttribPointer(ii, 4, ctx.FLOAT, false, 0, 0); - ctx.vertexAttrib1f(ii, 0); - } - ctx.deleteBuffer(tmp); - - var numTextureUnits = ctx.getParameter(ctx.MAX_TEXTURE_IMAGE_UNITS); - for (var ii = 0; ii < numTextureUnits; ++ii) { - ctx.activeTexture(ctx.TEXTURE0 + ii); - ctx.bindTexture(ctx.TEXTURE_CUBE_MAP, null); - ctx.bindTexture(ctx.TEXTURE_2D, null); - } - - ctx.activeTexture(ctx.TEXTURE0); - ctx.useProgram(null); - ctx.bindBuffer(ctx.ARRAY_BUFFER, null); - ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null); - ctx.bindFramebuffer(ctx.FRAMEBUFFER, null); - ctx.bindRenderbuffer(ctx.RENDERBUFFER, null); - ctx.disable(ctx.BLEND); - ctx.disable(ctx.CULL_FACE); - ctx.disable(ctx.DEPTH_TEST); - ctx.disable(ctx.DITHER); - ctx.disable(ctx.SCISSOR_TEST); - ctx.blendColor(0, 0, 0, 0); - ctx.blendEquation(ctx.FUNC_ADD); - ctx.blendFunc(ctx.ONE, ctx.ZERO); - ctx.clearColor(0, 0, 0, 0); - ctx.clearDepth(1); - ctx.clearStencil(-1); - ctx.colorMask(true, true, true, true); - ctx.cullFace(ctx.BACK); - ctx.depthFunc(ctx.LESS); - ctx.depthMask(true); - ctx.depthRange(0, 1); - ctx.frontFace(ctx.CCW); - ctx.hint(ctx.GENERATE_MIPMAP_HINT, ctx.DONT_CARE); - ctx.lineWidth(1); - ctx.pixelStorei(ctx.PACK_ALIGNMENT, 4); - ctx.pixelStorei(ctx.UNPACK_ALIGNMENT, 4); - ctx.pixelStorei(ctx.UNPACK_FLIP_Y_WEBGL, false); - ctx.pixelStorei(ctx.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false); - // TODO: Delete this IF. - if (ctx.UNPACK_COLORSPACE_CONVERSION_WEBGL) { - ctx.pixelStorei(ctx.UNPACK_COLORSPACE_CONVERSION_WEBGL, ctx.BROWSER_DEFAULT_WEBGL); - } - ctx.polygonOffset(0, 0); - ctx.sampleCoverage(1, false); - ctx.scissor(0, 0, ctx.canvas.width, ctx.canvas.height); - ctx.stencilFunc(ctx.ALWAYS, 0, 0xFFFFFFFF); - ctx.stencilMask(0xFFFFFFFF); - ctx.stencilOp(ctx.KEEP, ctx.KEEP, ctx.KEEP); - ctx.viewport(0, 0, ctx.canvas.width, ctx.canvas.height); - ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT | ctx.STENCIL_BUFFER_BIT); - - // TODO: This should NOT be needed but Firefox fails with 'hint' - while (ctx.getError()); - } - - function makeLostContextSimulatingCanvas(canvas) { - var unwrappedContext_; - var wrappedContext_; - var onLost_ = []; - var onRestored_ = []; - var wrappedContext_ = {}; - var contextId_ = 1; - var contextLost_ = false; - var resourceId_ = 0; - var resourceDb_ = []; - var numCallsToLoseContext_ = 0; - var numCalls_ = 0; - var canRestore_ = false; - var restoreTimeout_ = 0; - - // Holds booleans for each GL error so can simulate errors. - var glErrorShadow_ = {}; - - canvas.getContext = function (f) { - return function () { - var ctx = f.apply(canvas, arguments); - // Did we get a context and is it a WebGL context? - if (ctx instanceof WebGLRenderingContext) { - if (ctx != unwrappedContext_) { - if (unwrappedContext_) { - throw "got different context" - } - unwrappedContext_ = ctx; - wrappedContext_ = makeLostContextSimulatingContext(unwrappedContext_); - } - return wrappedContext_; - } - return ctx; - } - }(canvas.getContext); - - function wrapEvent(listener) { - if (typeof (listener) == "function") { - return listener; - } else { - return function (info) { - listener.handleEvent(info); - } - } - } - - var addOnContextLostListener = function (listener) { - onLost_.push(wrapEvent(listener)); - }; - - var addOnContextRestoredListener = function (listener) { - onRestored_.push(wrapEvent(listener)); - }; - - - function wrapAddEventListener(canvas) { - var f = canvas.addEventListener; - canvas.addEventListener = function (type, listener, bubble) { - switch (type) { - case 'webglcontextlost': - addOnContextLostListener(listener); - break; - case 'webglcontextrestored': - addOnContextRestoredListener(listener); - break; - default: - f.apply(canvas, arguments); - } - }; - } - - wrapAddEventListener(canvas); - - canvas.loseContext = function () { - if (!contextLost_) { - contextLost_ = true; - numCallsToLoseContext_ = 0; - ++contextId_; - while (unwrappedContext_.getError()); - clearErrors(); - glErrorShadow_[unwrappedContext_.CONTEXT_LOST_WEBGL] = true; - var event = makeWebGLContextEvent("context lost"); - var callbacks = onLost_.slice(); - setTimeout(function () { - //log("numCallbacks:" + callbacks.length); - for (var ii = 0; ii < callbacks.length; ++ii) { - //log("calling callback:" + ii); - callbacks[ii](event); - } - if (restoreTimeout_ >= 0) { - setTimeout(function () { - canvas.restoreContext(); - }, restoreTimeout_); - } - }, 0); - } - }; - - canvas.restoreContext = function () { - if (contextLost_) { - if (onRestored_.length) { - setTimeout(function () { - if (!canRestore_) { - throw "can not restore. webglcontestlost listener did not call event.preventDefault"; - } - freeResources(); - resetToInitialState(unwrappedContext_); - contextLost_ = false; - numCalls_ = 0; - canRestore_ = false; - var callbacks = onRestored_.slice(); - var event = makeWebGLContextEvent("context restored"); - for (var ii = 0; ii < callbacks.length; ++ii) { - callbacks[ii](event); - } - }, 0); - } - } - }; - - canvas.loseContextInNCalls = function (numCalls) { - if (contextLost_) { - throw "You can not ask a lost contet to be lost"; - } - numCallsToLoseContext_ = numCalls_ + numCalls; - }; - - canvas.getNumCalls = function () { - return numCalls_; - }; - - canvas.setRestoreTimeout = function (timeout) { - restoreTimeout_ = timeout; - }; - - function isWebGLObject(obj) { - //return false; - return (obj instanceof WebGLBuffer || - obj instanceof WebGLFramebuffer || - obj instanceof WebGLProgram || - obj instanceof WebGLRenderbuffer || - obj instanceof WebGLShader || - obj instanceof WebGLTexture); - } - - function checkResources(args) { - for (var ii = 0; ii < args.length; ++ii) { - var arg = args[ii]; - if (isWebGLObject(arg)) { - return arg.__webglDebugContextLostId__ == contextId_; - } - } - return true; - } - - function clearErrors() { - var k = Object.keys(glErrorShadow_); - for (var ii = 0; ii < k.length; ++ii) { - delete glErrorShadow_[k]; - } - } - - function loseContextIfTime() { - ++numCalls_; - if (!contextLost_) { - if (numCallsToLoseContext_ == numCalls_) { - canvas.loseContext(); - } - } - } - - // Makes a function that simulates WebGL when out of context. - function makeLostContextFunctionWrapper(ctx, functionName) { - var f = ctx[functionName]; - return function () { - // log("calling:" + functionName); - // Only call the functions if the context is not lost. - loseContextIfTime(); - if (!contextLost_) { - //if (!checkResources(arguments)) { - // glErrorShadow_[wrappedContext_.INVALID_OPERATION] = true; - // return; - //} - var result = f.apply(ctx, arguments); - return result; - } - }; - } - - function freeResources() { - for (var ii = 0; ii < resourceDb_.length; ++ii) { - var resource = resourceDb_[ii]; - if (resource instanceof WebGLBuffer) { - unwrappedContext_.deleteBuffer(resource); - } else if (resource instanceof WebGLFramebuffer) { - unwrappedContext_.deleteFramebuffer(resource); - } else if (resource instanceof WebGLProgram) { - unwrappedContext_.deleteProgram(resource); - } else if (resource instanceof WebGLRenderbuffer) { - unwrappedContext_.deleteRenderbuffer(resource); - } else if (resource instanceof WebGLShader) { - unwrappedContext_.deleteShader(resource); - } else if (resource instanceof WebGLTexture) { - unwrappedContext_.deleteTexture(resource); - } - } - } - - function makeWebGLContextEvent(statusMessage) { - return { - statusMessage: statusMessage, - preventDefault: function () { - canRestore_ = true; - } - }; - } - - return canvas; - - function makeLostContextSimulatingContext(ctx) { - // copy all functions and properties to wrapper - for (var propertyName in ctx) { - if (typeof ctx[propertyName] == 'function') { - wrappedContext_[propertyName] = makeLostContextFunctionWrapper( - ctx, propertyName); - } else { - makePropertyWrapper(wrappedContext_, ctx, propertyName); - } - } - - // Wrap a few functions specially. - wrappedContext_.getError = function () { - loseContextIfTime(); - if (!contextLost_) { - var err; - while (err = unwrappedContext_.getError()) { - glErrorShadow_[err] = true; - } - } - for (var err in glErrorShadow_) { - if (glErrorShadow_[err]) { - delete glErrorShadow_[err]; - return err; - } - } - return wrappedContext_.NO_ERROR; - }; - - var creationFunctions = [ - "createBuffer", - "createFramebuffer", - "createProgram", - "createRenderbuffer", - "createShader", - "createTexture" - ]; - for (var ii = 0; ii < creationFunctions.length; ++ii) { - var functionName = creationFunctions[ii]; - wrappedContext_[functionName] = function (f) { - return function () { - loseContextIfTime(); - if (contextLost_) { - return null; - } - var obj = f.apply(ctx, arguments); - obj.__webglDebugContextLostId__ = contextId_; - resourceDb_.push(obj); - return obj; - }; - }(ctx[functionName]); - } - - var functionsThatShouldReturnNull = [ - "getActiveAttrib", - "getActiveUniform", - "getBufferParameter", - "getContextAttributes", - "getAttachedShaders", - "getFramebufferAttachmentParameter", - "getParameter", - "getProgramParameter", - "getProgramInfoLog", - "getRenderbufferParameter", - "getShaderParameter", - "getShaderInfoLog", - "getShaderSource", - "getTexParameter", - "getUniform", - "getUniformLocation", - "getVertexAttrib" - ]; - for (var ii = 0; ii < functionsThatShouldReturnNull.length; ++ii) { - var functionName = functionsThatShouldReturnNull[ii]; - wrappedContext_[functionName] = function (f) { - return function () { - loseContextIfTime(); - if (contextLost_) { - return null; - } - return f.apply(ctx, arguments); - } - }(wrappedContext_[functionName]); - } - - var isFunctions = [ - "isBuffer", - "isEnabled", - "isFramebuffer", - "isProgram", - "isRenderbuffer", - "isShader", - "isTexture" - ]; - for (var ii = 0; ii < isFunctions.length; ++ii) { - var functionName = isFunctions[ii]; - wrappedContext_[functionName] = function (f) { - return function () { - loseContextIfTime(); - if (contextLost_) { - return false; - } - return f.apply(ctx, arguments); - } - }(wrappedContext_[functionName]); - } - - wrappedContext_.checkFramebufferStatus = function (f) { - return function () { - loseContextIfTime(); - if (contextLost_) { - return wrappedContext_.FRAMEBUFFER_UNSUPPORTED; - } - return f.apply(ctx, arguments); - }; - }(wrappedContext_.checkFramebufferStatus); - - wrappedContext_.getAttribLocation = function (f) { - return function () { - loseContextIfTime(); - if (contextLost_) { - return -1; - } - return f.apply(ctx, arguments); - }; - }(wrappedContext_.getAttribLocation); - - wrappedContext_.getVertexAttribOffset = function (f) { - return function () { - loseContextIfTime(); - if (contextLost_) { - return 0; - } - return f.apply(ctx, arguments); - }; - }(wrappedContext_.getVertexAttribOffset); - - wrappedContext_.isContextLost = function () { - return contextLost_; - }; - - return wrappedContext_; - } - } - - return { - /** - * Initializes this module. Safe to call more than once. - * @param {!WebGLRenderingContext} ctx A WebGL context. If - * you have more than one context it doesn't matter which one - * you pass in, it is only used to pull out constants. - */ - 'init': init, - - /** - * Returns true or false if value matches any WebGL enum - * @param {*} value Value to check if it might be an enum. - * @return {boolean} True if value matches one of the WebGL defined enums - */ - 'mightBeEnum': mightBeEnum, - - /** - * Gets an string version of an WebGL enum. - * - * Example: - * WebGLDebugUtil.init(ctx); - * var str = WebGLDebugUtil.glEnumToString(ctx.getError()); - * - * @param {number} value Value to return an enum for - * @return {string} The string version of the enum. - */ - 'glEnumToString': glEnumToString, - - /** - * Converts the argument of a WebGL function to a string. - * Attempts to convert enum arguments to strings. - * - * Example: - * WebGLDebugUtil.init(ctx); - * var str = WebGLDebugUtil.glFunctionArgToString('bindTexture', 2, 0, gl.TEXTURE_2D); - * - * would return 'TEXTURE_2D' - * - * @param {string} functionName the name of the WebGL function. - * @param {number} numArgs The number of arguments - * @param {number} argumentIndx the index of the argument. - * @param {*} value The value of the argument. - * @return {string} The value as a string. - */ - 'glFunctionArgToString': glFunctionArgToString, - - /** - * Converts the arguments of a WebGL function to a string. - * Attempts to convert enum arguments to strings. - * - * @param {string} functionName the name of the WebGL function. - * @param {number} args The arguments. - * @return {string} The arguments as a string. - */ - 'glFunctionArgsToString': glFunctionArgsToString, - - /** - * Given a WebGL context returns a wrapped context that calls - * gl.getError after every command and calls a function if the - * result is not NO_ERROR. - * - * You can supply your own function if you want. For example, if you'd like - * an exception thrown on any GL error you could do this - * - * function throwOnGLError(err, funcName, args) { - * throw WebGLDebugUtils.glEnumToString(err) + - * " was caused by call to " + funcName; - * }; - * - * ctx = WebGLDebugUtils.makeDebugContext( - * canvas.getContext("webgl"), throwOnGLError); - * - * @param {!WebGLRenderingContext} ctx The webgl context to wrap. - * @param {!function(err, funcName, args): void} opt_onErrorFunc The function - * to call when gl.getError returns an error. If not specified the default - * function calls console.log with a message. - * @param {!function(funcName, args): void} opt_onFunc The - * function to call when each webgl function is called. You - * can use this to log all calls for example. - */ - 'makeDebugContext': makeDebugContext, - - /** - * Given a canvas element returns a wrapped canvas element that will - * simulate lost context. The canvas returned adds the following functions. - * - * loseContext: - * simulates a lost context event. - * - * restoreContext: - * simulates the context being restored. - * - * lostContextInNCalls: - * loses the context after N gl calls. - * - * getNumCalls: - * tells you how many gl calls there have been so far. - * - * setRestoreTimeout: - * sets the number of milliseconds until the context is restored - * after it has been lost. Defaults to 0. Pass -1 to prevent - * automatic restoring. - * - * @param {!Canvas} canvas The canvas element to wrap. - */ - 'makeLostContextSimulatingCanvas': makeLostContextSimulatingCanvas, - - /** - * Resets a context to the initial state. - * @param {!WebGLRenderingContext} ctx The webgl context to - * reset. - */ - 'resetToInitialState': resetToInitialState - }; - -}(); - - -/* - * Copyright (C) 2009 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// -// initWebGL -// -// Initialize the Canvas element with the passed name as a WebGL object and return the -// WebGLRenderingContext. -function initWebGL(canvasName, vshader, fshader, attribs, clearColor, clearDepth) { - var canvas = document.getElementById(canvasName); - return gl = WebGLUtils.setupWebGL(canvas); -} - -function log(msg) { - if (window.console && window.console.log) { - window.console.log(msg); - } -} - -// Load shaders with the passed names and create a program with them. Return this program -// in the 'program' property of the returned context. -// -// For each string in the passed attribs array, bind an attrib with that name at that index. -// Once the attribs are bound, link the program and then use it. -// -// Set the clear color to the passed array (4 values) and set the clear depth to the passed value. -// Enable depth testing and blending with a blend func of (SRC_ALPHA, ONE_MINUS_SRC_ALPHA) -// -// A console function is added to the context: console(string). This can be replaced -// by the caller. By default, it maps to the window.console() function on WebKit and to -// an empty function on other browsers. -// -function simpleSetup(gl, vshader, fshader, attribs, clearColor, clearDepth) { - // create our shaders - var vertexShader = loadShader(gl, vshader); - var fragmentShader = loadShader(gl, fshader); - - // Create the program object - var program = gl.createProgram(); - - // Attach our two shaders to the program - gl.attachShader(program, vertexShader); - gl.attachShader(program, fragmentShader); - - // Bind attributes - for (var i = 0; i < attribs.length; ++i) - gl.bindAttribLocation(program, i, attribs[i]); - - // Link the program - gl.linkProgram(program); - - // Check the link status - var linked = gl.getProgramParameter(program, gl.LINK_STATUS); - if (!linked && !gl.isContextLost()) { - // something went wrong with the link - var error = gl.getProgramInfoLog(program); - log("Error in program linking:" + error); - - gl.deleteProgram(program); - gl.deleteProgram(fragmentShader); - gl.deleteProgram(vertexShader); - - return null; - } - - gl.useProgram(program); - - gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); - gl.clearDepth(clearDepth); - - gl.enable(gl.DEPTH_TEST); - gl.enable(gl.BLEND); - gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - - return program; -} - -// -// loadShader -// -// 'shaderId' is the id of a