michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: "use strict"; michael@0: michael@0: let {devtools} = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {}); michael@0: let TiltManager = devtools.require("devtools/tilt/tilt").TiltManager; michael@0: let TiltGL = devtools.require("devtools/tilt/tilt-gl"); michael@0: let {EPSILON, TiltMath, vec3, mat3, mat4, quat4} = devtools.require("devtools/tilt/tilt-math"); michael@0: let TiltUtils = devtools.require("devtools/tilt/tilt-utils"); michael@0: let {TiltVisualizer} = devtools.require("devtools/tilt/tilt-visualizer"); michael@0: michael@0: let tempScope = {}; michael@0: Components.utils.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tempScope); michael@0: let LayoutHelpers = tempScope.LayoutHelpers; michael@0: michael@0: michael@0: const DEFAULT_HTML = "data:text/html," + michael@0: "" + michael@0: "" + michael@0: "" + michael@0: "" + michael@0: "Three Laws" + michael@0: "" + michael@0: "" + michael@0: "
" + michael@0: "A robot may not injure a human being or, through inaction, allow a " + michael@0: "human being to come to harm." + michael@0: "
" + michael@0: "
" + michael@0: "A robot must obey the orders given to it by human beings, except " + michael@0: "where such orders would conflict with the First Law." + michael@0: "
" + michael@0: "
" + michael@0: "A robot must protect its own existence as long as such protection " + michael@0: "does not conflict with the First or Second Laws." + michael@0: "
" + michael@0: "
" + michael@0: "I like bacon." + michael@0: "
" + michael@0: "" + michael@0: ""; michael@0: michael@0: let Tilt = TiltManager.getTiltForBrowser(window); michael@0: michael@0: const STARTUP = Tilt.NOTIFICATIONS.STARTUP; michael@0: const INITIALIZING = Tilt.NOTIFICATIONS.INITIALIZING; michael@0: const INITIALIZED = Tilt.NOTIFICATIONS.INITIALIZED; michael@0: const DESTROYING = Tilt.NOTIFICATIONS.DESTROYING; michael@0: const BEFORE_DESTROYED = Tilt.NOTIFICATIONS.BEFORE_DESTROYED; michael@0: const DESTROYED = Tilt.NOTIFICATIONS.DESTROYED; michael@0: const SHOWN = Tilt.NOTIFICATIONS.SHOWN; michael@0: const HIDDEN = Tilt.NOTIFICATIONS.HIDDEN; michael@0: const HIGHLIGHTING = Tilt.NOTIFICATIONS.HIGHLIGHTING; michael@0: const UNHIGHLIGHTING = Tilt.NOTIFICATIONS.UNHIGHLIGHTING; michael@0: const NODE_REMOVED = Tilt.NOTIFICATIONS.NODE_REMOVED; michael@0: michael@0: const TILT_ENABLED = Services.prefs.getBoolPref("devtools.tilt.enabled"); michael@0: michael@0: gDevTools.testing = true; michael@0: SimpleTest.registerCleanupFunction(() => { michael@0: gDevTools.testing = false; michael@0: }); michael@0: michael@0: function isTiltEnabled() { michael@0: info("Apparently, Tilt is" + (TILT_ENABLED ? "" : " not") + " enabled."); michael@0: return TILT_ENABLED; michael@0: } michael@0: michael@0: function isWebGLSupported() { michael@0: let supported = !TiltGL.isWebGLForceEnabled() && michael@0: TiltGL.isWebGLSupported() && michael@0: TiltGL.create3DContext(createCanvas()); michael@0: michael@0: info("Apparently, WebGL is" + (supported ? "" : " not") + " supported."); michael@0: return supported; michael@0: } michael@0: michael@0: function isApprox(num1, num2, delta) { michael@0: if (Math.abs(num1 - num2) > (delta || EPSILON)) { michael@0: info("isApprox expected " + num1 + ", got " + num2 + " instead."); michael@0: return false; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: function isApproxVec(vec1, vec2, delta) { michael@0: vec1 = Array.prototype.slice.call(vec1); michael@0: vec2 = Array.prototype.slice.call(vec2); michael@0: michael@0: if (vec1.length !== vec2.length) { michael@0: return false; michael@0: } michael@0: for (let i = 0, len = vec1.length; i < len; i++) { michael@0: if (!isApprox(vec1[i], vec2[i], delta)) { michael@0: info("isApproxVec expected [" + vec1 + "], got [" + vec2 + "] instead."); michael@0: return false; michael@0: } michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: function isEqualVec(vec1, vec2) { michael@0: vec1 = Array.prototype.slice.call(vec1); michael@0: vec2 = Array.prototype.slice.call(vec2); michael@0: michael@0: if (vec1.length !== vec2.length) { michael@0: return false; michael@0: } michael@0: for (let i = 0, len = vec1.length; i < len; i++) { michael@0: if (vec1[i] !== vec2[i]) { michael@0: info("isEqualVec expected [" + vec1 + "], got [" + vec2 + "] instead."); michael@0: return false; michael@0: } michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: function createCanvas() { michael@0: return document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); michael@0: } michael@0: michael@0: michael@0: function createTab(callback, location) { michael@0: info("Creating a tab, with callback " + typeof callback + michael@0: ", and location " + location + "."); michael@0: michael@0: let tab = gBrowser.selectedTab = gBrowser.addTab(); michael@0: michael@0: gBrowser.selectedBrowser.addEventListener("load", function onLoad() { michael@0: gBrowser.selectedBrowser.removeEventListener("load", onLoad, true); michael@0: callback(tab); michael@0: }, true); michael@0: michael@0: gBrowser.selectedBrowser.contentWindow.location = location || DEFAULT_HTML; michael@0: return tab; michael@0: } michael@0: michael@0: michael@0: function createTilt(callbacks, close, suddenDeath) { michael@0: info("Creating Tilt, with callbacks {" + Object.keys(callbacks) + "}" + michael@0: ", autoclose param " + close + michael@0: ", and sudden death handler " + typeof suddenDeath + "."); michael@0: michael@0: handleFailure(suddenDeath); michael@0: michael@0: Services.prefs.setBoolPref("webgl.verbose", true); michael@0: TiltUtils.Output.suppressAlerts = true; michael@0: michael@0: info("Attempting to start Tilt."); michael@0: Services.obs.addObserver(onTiltOpen, INITIALIZING, false); michael@0: Tilt.toggle(); michael@0: michael@0: function onTiltOpen() { michael@0: info("Tilt was opened."); michael@0: Services.obs.removeObserver(onTiltOpen, INITIALIZING); michael@0: michael@0: executeSoon(function() { michael@0: if ("function" === typeof callbacks.onTiltOpen) { michael@0: info("Calling 'onTiltOpen'."); michael@0: callbacks.onTiltOpen(Tilt.visualizers[Tilt.currentWindowId]); michael@0: } michael@0: if (close) { michael@0: executeSoon(function() { michael@0: info("Attempting to close Tilt."); michael@0: Services.obs.addObserver(onTiltClose, DESTROYED, false); michael@0: Tilt.destroy(Tilt.currentWindowId); michael@0: }); michael@0: } michael@0: }); michael@0: } michael@0: michael@0: function onTiltClose() { michael@0: info("Tilt was closed."); michael@0: Services.obs.removeObserver(onTiltClose, DESTROYED); michael@0: michael@0: executeSoon(function() { michael@0: if ("function" === typeof callbacks.onTiltClose) { michael@0: info("Calling 'onTiltClose'."); michael@0: callbacks.onTiltClose(); michael@0: } michael@0: if ("function" === typeof callbacks.onEnd) { michael@0: info("Calling 'onEnd'."); michael@0: callbacks.onEnd(); michael@0: } michael@0: }); michael@0: } michael@0: michael@0: function handleFailure(suddenDeath) { michael@0: Tilt.failureCallback = function() { michael@0: info("Tilt FAIL."); michael@0: Services.obs.removeObserver(onTiltOpen, INITIALIZING); michael@0: michael@0: info("Now relying on sudden death handler " + typeof suddenDeath + "."); michael@0: suddenDeath && suddenDeath(); michael@0: } michael@0: } michael@0: } michael@0: michael@0: function getPickablePoint(presenter) { michael@0: let vertices = presenter._meshStacks[0].vertices.components; michael@0: michael@0: let topLeft = vec3.create([vertices[0], vertices[1], vertices[2]]); michael@0: let bottomRight = vec3.create([vertices[6], vertices[7], vertices[8]]); michael@0: let center = vec3.lerp(topLeft, bottomRight, 0.5, []); michael@0: michael@0: let renderer = presenter._renderer; michael@0: let viewport = [0, 0, renderer.width, renderer.height]; michael@0: michael@0: return vec3.project(center, viewport, renderer.mvMatrix, renderer.projMatrix); michael@0: }