mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 689920 - Integrate Tilt with existing Firefox developer tools; r=cedric,msucan,rcampbell
This commit is contained in:
parent
aa57690f35
commit
3cca7b2af8
@ -1013,6 +1013,12 @@ pref("devtools.inspector.htmlHeight", 112);
|
||||
// Enable the style inspector
|
||||
pref("devtools.styleinspector.enabled", true);
|
||||
|
||||
// Enable the Tilt inspector
|
||||
pref("devtools.tilt.enabled", true);
|
||||
|
||||
// Enable the Tilt inspector even if WebGL capabilities are not detected
|
||||
pref("devtools.tilt.force-enabled", false);
|
||||
|
||||
// Enable the rules view
|
||||
pref("devtools.ruleview.enabled", true);
|
||||
|
||||
|
@ -148,6 +148,8 @@
|
||||
oncommand="InspectorUI.toggleInspection();"/>
|
||||
<command id="Inspector:Sidebar"
|
||||
oncommand="InspectorUI.toggleSidebar();"/>
|
||||
<command id="Inspector:Tilt"
|
||||
oncommand="Tilt.initialize();"/>
|
||||
</commandset>
|
||||
|
||||
<broadcasterset id="mainBroadcasterSet">
|
||||
|
@ -55,6 +55,7 @@
|
||||
# David Dahl <ddahl@mozilla.com>
|
||||
# Patrick Walton <pcwalton@mozilla.com>
|
||||
# Mihai Sucan <mihai.sucan@gmail.com>
|
||||
# Victor Porof <vporof@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -179,6 +180,12 @@ XPCOMUtils.defineLazyGetter(this, "InspectorUI", function() {
|
||||
return new tmp.InspectorUI(window);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "Tilt", function() {
|
||||
let tmp = {};
|
||||
Cu.import("resource:///modules/devtools/Tilt.jsm", tmp);
|
||||
return new tmp.Tilt(window);
|
||||
});
|
||||
|
||||
let gInitialPages = [
|
||||
"about:blank",
|
||||
"about:privatebrowsing",
|
||||
|
@ -37,6 +37,7 @@
|
||||
# Patrick Walton <pcwalton@mozilla.com>
|
||||
# David Dahl <ddahl@mozilla.com>
|
||||
# Frank Yan <fyan@mozilla.com>
|
||||
# Victor Porof <vporof@mozilla.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -1007,6 +1008,11 @@
|
||||
flex="1" orient="horizontal"
|
||||
clicktoscroll="true"/>
|
||||
<hbox id="inspector-tools">
|
||||
<toolbarbutton id="inspector-3D-button"
|
||||
hidden="true"
|
||||
label="&inspect3DButton.label;"
|
||||
accesskey="&inspect3DButton.accesskey;"
|
||||
command="Inspector:Tilt"/>
|
||||
<toolbarbutton id="inspector-style-button"
|
||||
label="&inspectStyleButton.label;"
|
||||
accesskey="&inspectStyleButton.accesskey;"
|
||||
|
@ -52,6 +52,7 @@ DIRS = \
|
||||
sourceeditor \
|
||||
styleeditor \
|
||||
styleinspector \
|
||||
tilt \
|
||||
scratchpad \
|
||||
shared \
|
||||
$(NULL)
|
||||
|
@ -928,6 +928,7 @@ InspectorUI.prototype = {
|
||||
this.chromeDoc.getElementById("inspector-inspect-toolbutton");
|
||||
|
||||
this.initTools();
|
||||
this.chromeWin.Tilt.setup();
|
||||
|
||||
if (this.treePanelEnabled) {
|
||||
this.treePanel = new TreePanel(this.chromeWin, this);
|
||||
@ -1190,6 +1191,7 @@ InspectorUI.prototype = {
|
||||
}
|
||||
|
||||
this.breadcrumbs.update();
|
||||
this.chromeWin.Tilt.update(aNode);
|
||||
|
||||
this.toolsSelect(aScroll);
|
||||
},
|
||||
|
53
browser/devtools/tilt/Makefile.in
Normal file
53
browser/devtools/tilt/Makefile.in
Normal file
@ -0,0 +1,53 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Victor Porof <vporof@mozilla.com> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += test
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/*.jsm $(FINAL_TARGET)/modules/devtools
|
||||
$(NSINSTALL) $(srcdir)/*.js $(FINAL_TARGET)/modules/devtools
|
313
browser/devtools/tilt/Tilt.jsm
Normal file
313
browser/devtools/tilt/Tilt.jsm
Normal file
@ -0,0 +1,313 @@
|
||||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Tilt: A WebGL-based 3D visualization of a webpage.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Victor Porof <vporof@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
***** END LICENSE BLOCK *****/
|
||||
|
||||
/*global Components, Services, TiltGL, TiltUtils, TiltVisualizer */
|
||||
"use strict";
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
||||
// Tilt notifications dispatched through the nsIObserverService.
|
||||
const TILT_NOTIFICATIONS = {
|
||||
|
||||
// Fires when Tilt completes the initialization.
|
||||
INITIALIZED: "tilt-initialized",
|
||||
|
||||
// Fires when Tilt is destroyed.
|
||||
DESTROYED: "tilt-destroyed",
|
||||
|
||||
// Fires when Tilt is shown (after a tab-switch).
|
||||
SHOWN: "tilt-shown",
|
||||
|
||||
// Fires when Tilt is hidden (after a tab-switch).
|
||||
HIDDEN: "tilt-hidden"
|
||||
};
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/TiltGL.jsm");
|
||||
Cu.import("resource:///modules/devtools/TiltUtils.jsm");
|
||||
Cu.import("resource:///modules/devtools/TiltVisualizer.jsm");
|
||||
|
||||
let EXPORTED_SYMBOLS = ["Tilt"];
|
||||
|
||||
/**
|
||||
* Object managing instances of the visualizer.
|
||||
*
|
||||
* @param {Window} aWindow
|
||||
* the chrome window used by each visualizer instance
|
||||
*/
|
||||
function Tilt(aWindow)
|
||||
{
|
||||
/**
|
||||
* Save a reference to the top-level window.
|
||||
*/
|
||||
this.chromeWindow = aWindow;
|
||||
|
||||
/**
|
||||
* All the instances of TiltVisualizer.
|
||||
*/
|
||||
this.visualizers = {};
|
||||
|
||||
/**
|
||||
* Shortcut for accessing notifications strings.
|
||||
*/
|
||||
this.NOTIFICATIONS = TILT_NOTIFICATIONS;
|
||||
}
|
||||
|
||||
Tilt.prototype = {
|
||||
|
||||
/**
|
||||
* Initializes a visualizer for the current tab.
|
||||
*/
|
||||
initialize: function T_initialize()
|
||||
{
|
||||
let id = this.currentWindowId;
|
||||
|
||||
// if the visualizer for the current tab is already open, destroy it now
|
||||
if (this.visualizers[id]) {
|
||||
this.destroy(id);
|
||||
return;
|
||||
}
|
||||
|
||||
// create a visualizer instance for the current tab
|
||||
this.visualizers[id] = new TiltVisualizer({
|
||||
parentNode: this.chromeWindow.gBrowser.selectedBrowser.parentNode,
|
||||
contentWindow: this.chromeWindow.gBrowser.selectedBrowser.contentWindow,
|
||||
requestAnimationFrame: this.chromeWindow.mozRequestAnimationFrame,
|
||||
inspectorUI: this.chromeWindow.InspectorUI
|
||||
});
|
||||
|
||||
// make sure the visualizer object was initialized properly
|
||||
if (!this.visualizers[id].isInitialized()) {
|
||||
this.destroy(id);
|
||||
return;
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.INITIALIZED, null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroys a specific instance of the visualizer.
|
||||
*
|
||||
* @param {String} aId
|
||||
* the identifier of the instance in the visualizers array
|
||||
*/
|
||||
destroy: function T_destroy(aId)
|
||||
{
|
||||
// if the visualizer is already destroyed, don't do anything
|
||||
if (!this.visualizers[aId]) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.visualizers[aId].removeOverlay();
|
||||
this.visualizers[aId].cleanup();
|
||||
this.visualizers[aId] = null;
|
||||
|
||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.DESTROYED, null);
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles any supplementary post-initialization work, done immediately
|
||||
* after a TILT_NOTIFICATIONS.INITIALIZED notification.
|
||||
*/
|
||||
_whenInitialized: function T__whenInitialized()
|
||||
{
|
||||
this._whenShown();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles any supplementary post-destruction work, done immediately
|
||||
* after a TILT_NOTIFICATIONS.DESTROYED notification.
|
||||
*/
|
||||
_whenDestroyed: function T__whenDestroyed()
|
||||
{
|
||||
this._whenHidden();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles any necessary changes done when the Tilt surface is shown,
|
||||
* after a TILT_NOTIFICATIONS.SHOWN notification.
|
||||
*/
|
||||
_whenShown: function T__whenShown()
|
||||
{
|
||||
this.tiltButton.checked = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles any necessary changes done when the Tilt surface is hidden,
|
||||
* after a TILT_NOTIFICATIONS.HIDDEN notification.
|
||||
*/
|
||||
_whenHidden: function T__whenHidden()
|
||||
{
|
||||
this.tiltButton.checked = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the event fired when a tab is selected.
|
||||
*/
|
||||
_onTabSelect: function T__onTabSelect()
|
||||
{
|
||||
if (this.visualizers[this.currentWindowId]) {
|
||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.SHOWN, null);
|
||||
} else {
|
||||
Services.obs.notifyObservers(null, TILT_NOTIFICATIONS.HIDDEN, null);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* A node was selected in the Inspector.
|
||||
* Called from InspectorUI.
|
||||
*
|
||||
* @param {Element} aNode
|
||||
* the newly selected node
|
||||
*/
|
||||
update: function T_update(aNode) {
|
||||
let id = this.currentWindowId;
|
||||
|
||||
if (this.visualizers[id]) {
|
||||
this.visualizers[id].presenter.highlightNode(aNode);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add the browser event listeners to handle state changes.
|
||||
* Called from InspectorUI.
|
||||
*/
|
||||
setup: function T_setup()
|
||||
{
|
||||
if (this._setupFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
// load the preferences from the devtools.tilt branch
|
||||
TiltVisualizer.Prefs.load();
|
||||
|
||||
// hide the button in the Inspector toolbar if Tilt is not enabled
|
||||
this.tiltButton.hidden = !this.enabled;
|
||||
|
||||
// add the necessary observers to handle specific notifications
|
||||
Services.obs.addObserver(
|
||||
this._whenInitialized.bind(this), TILT_NOTIFICATIONS.INITIALIZED, false);
|
||||
Services.obs.addObserver(
|
||||
this._whenDestroyed.bind(this), TILT_NOTIFICATIONS.DESTROYED, false);
|
||||
Services.obs.addObserver(
|
||||
this._whenShown.bind(this), TILT_NOTIFICATIONS.SHOWN, false);
|
||||
Services.obs.addObserver(
|
||||
this._whenHidden.bind(this), TILT_NOTIFICATIONS.HIDDEN, false);
|
||||
Services.obs.addObserver(function(aSubject, aTopic, aWinId) {
|
||||
this.destroy(aWinId); }.bind(this),
|
||||
this.chromeWindow.InspectorUI.INSPECTOR_NOTIFICATIONS.DESTROYED, false);
|
||||
|
||||
this.chromeWindow.gBrowser.tabContainer.addEventListener("TabSelect",
|
||||
this._onTabSelect.bind(this), false);
|
||||
|
||||
|
||||
// FIXME: this shouldn't be done here, see bug #705131
|
||||
let onOpened = function() {
|
||||
if (this.visualizers[this.currentWindowId]) {
|
||||
this.chromeWindow.InspectorUI.stopInspecting();
|
||||
this.inspectButton.disabled = true;
|
||||
this.highlighterContainer.style.display = "none";
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
let onClosed = function() {
|
||||
this.inspectButton.disabled = false;
|
||||
this.highlighterContainer.style.display = "";
|
||||
}.bind(this);
|
||||
|
||||
Services.obs.addObserver(onOpened,
|
||||
this.chromeWindow.InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||
Services.obs.addObserver(onClosed,
|
||||
this.chromeWindow.InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
|
||||
Services.obs.addObserver(onOpened,
|
||||
TILT_NOTIFICATIONS.INITIALIZED, false);
|
||||
Services.obs.addObserver(onClosed,
|
||||
TILT_NOTIFICATIONS.DESTROYED, false);
|
||||
|
||||
|
||||
this._setupFinished = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if this tool is enabled.
|
||||
*/
|
||||
get enabled()
|
||||
{
|
||||
return (TiltVisualizer.Prefs.enabled &&
|
||||
(TiltVisualizer.Prefs.forceEnabled || TiltGL.isWebGLSupported()));
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the ID of the current window object to identify the visualizer.
|
||||
*/
|
||||
get currentWindowId()
|
||||
{
|
||||
let gBrowser = this.chromeWindow.gBrowser;
|
||||
return TiltUtils.getWindowId(gBrowser.selectedBrowser.contentWindow);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the Tilt button in the Inspector toolbar.
|
||||
*/
|
||||
get tiltButton()
|
||||
{
|
||||
return this.chromeWindow.document.getElementById(
|
||||
"inspector-3D-button");
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the Inspect button in the Inspector toolbar.
|
||||
* FIXME: this shouldn't be needed here, remove after bug #705131
|
||||
*/
|
||||
get inspectButton()
|
||||
{
|
||||
return this.chromeWindow.document.getElementById(
|
||||
"inspector-inspect-toolbutton");
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the Highlighter contaniner stack.
|
||||
* FIXME: this shouldn't be needed here, remove after bug #705131
|
||||
*/
|
||||
get highlighterContainer()
|
||||
{
|
||||
return this.chromeWindow.document.getElementById(
|
||||
"highlighter-container");
|
||||
}
|
||||
};
|
1615
browser/devtools/tilt/TiltGL.jsm
Normal file
1615
browser/devtools/tilt/TiltGL.jsm
Normal file
File diff suppressed because it is too large
Load Diff
2348
browser/devtools/tilt/TiltMath.jsm
Normal file
2348
browser/devtools/tilt/TiltMath.jsm
Normal file
File diff suppressed because it is too large
Load Diff
685
browser/devtools/tilt/TiltUtils.jsm
Normal file
685
browser/devtools/tilt/TiltUtils.jsm
Normal file
@ -0,0 +1,685 @@
|
||||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Tilt: A WebGL-based 3D visualization of a webpage.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Victor Porof <vporof@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
***** END LICENSE BLOCK *****/
|
||||
|
||||
/*global Components, Services, XPCOMUtils */
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let EXPORTED_SYMBOLS = ["TiltUtils"];
|
||||
|
||||
/**
|
||||
* Module containing various helper functions used throughout Tilt.
|
||||
*/
|
||||
let TiltUtils = {};
|
||||
|
||||
/**
|
||||
* Various console/prompt output functions required by the engine.
|
||||
*/
|
||||
TiltUtils.Output = {
|
||||
|
||||
/**
|
||||
* Logs a message to the console.
|
||||
*
|
||||
* @param {String} aMessage
|
||||
* the message to be logged
|
||||
*/
|
||||
log: function TUO_log(aMessage)
|
||||
{
|
||||
// get the console service
|
||||
let consoleService = Cc["@mozilla.org/consoleservice;1"]
|
||||
.getService(Ci.nsIConsoleService);
|
||||
|
||||
// log the message
|
||||
consoleService.logStringMessage(aMessage);
|
||||
},
|
||||
|
||||
/**
|
||||
* Logs an error to the console.
|
||||
*
|
||||
* @param {String} aMessage
|
||||
* the message to be logged
|
||||
* @param {Object} aProperties
|
||||
* and object containing script error initialization details
|
||||
*/
|
||||
error: function TUO_error(aMessage, aProperties)
|
||||
{
|
||||
// make sure the properties parameter is a valid object
|
||||
aProperties = aProperties || {};
|
||||
|
||||
// get the console service
|
||||
let consoleService = Cc["@mozilla.org/consoleservice;1"]
|
||||
.getService(Ci.nsIConsoleService);
|
||||
|
||||
// get the script error service
|
||||
let scriptError = Cc["@mozilla.org/scripterror;1"]
|
||||
.createInstance(Ci.nsIScriptError);
|
||||
|
||||
// initialize a script error
|
||||
scriptError.init(aMessage,
|
||||
aProperties.sourceName || "",
|
||||
aProperties.sourceLine || "",
|
||||
aProperties.lineNumber || 0,
|
||||
aProperties.columnNumber || 0,
|
||||
aProperties.flags || 0,
|
||||
aProperties.category || "");
|
||||
|
||||
// log the error
|
||||
consoleService.logMessage(scriptError);
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows a modal alert message popup.
|
||||
*
|
||||
* @param {String} aTitle
|
||||
* the title of the popup
|
||||
* @param {String} aMessage
|
||||
* the message to be logged
|
||||
*/
|
||||
alert: function TUO_alert(aTitle, aMessage)
|
||||
{
|
||||
if (!aMessage) {
|
||||
aMessage = aTitle;
|
||||
aTitle = "";
|
||||
}
|
||||
|
||||
// get the prompt service
|
||||
let prompt = Cc["@mozilla.org/embedcomp/prompt-service;1"]
|
||||
.getService(Ci.nsIPromptService);
|
||||
|
||||
// show the alert message
|
||||
prompt.alert(null, aTitle, aMessage);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper functions for managing preferences.
|
||||
*/
|
||||
TiltUtils.Preferences = {
|
||||
|
||||
/**
|
||||
* Gets a custom Tilt preference.
|
||||
* If the preference does not exist, undefined is returned. If it does exist,
|
||||
* but the type is not correctly specified, null is returned.
|
||||
*
|
||||
* @param {String} aPref
|
||||
* the preference name
|
||||
* @param {String} aType
|
||||
* either "boolean", "string" or "integer"
|
||||
*
|
||||
* @return {Boolean | String | Number} the requested preference
|
||||
*/
|
||||
get: function TUP_get(aPref, aType)
|
||||
{
|
||||
if (!aPref || !aType) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let prefs = this._branch;
|
||||
|
||||
switch(aType) {
|
||||
case "boolean":
|
||||
return prefs.getBoolPref(aPref);
|
||||
case "string":
|
||||
return prefs.getCharPref(aPref);
|
||||
case "integer":
|
||||
return prefs.getIntPref(aPref);
|
||||
}
|
||||
return null;
|
||||
|
||||
} catch(e) {
|
||||
// handle any unexpected exceptions
|
||||
TiltUtils.Output.error(e.message);
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets a custom Tilt preference.
|
||||
* If the preference already exists, it is overwritten.
|
||||
*
|
||||
* @param {String} aPref
|
||||
* the preference name
|
||||
* @param {String} aType
|
||||
* either "boolean", "string" or "integer"
|
||||
* @param {String} aValue
|
||||
* a new preference value
|
||||
*
|
||||
* @return {Boolean} true if the preference was set successfully
|
||||
*/
|
||||
set: function TUP_set(aPref, aType, aValue)
|
||||
{
|
||||
if (!aPref || !aType || aValue === undefined || aValue === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let prefs = this._branch;
|
||||
|
||||
switch(aType) {
|
||||
case "boolean":
|
||||
return prefs.setBoolPref(aPref, aValue);
|
||||
case "string":
|
||||
return prefs.setCharPref(aPref, aValue);
|
||||
case "integer":
|
||||
return prefs.setIntPref(aPref, aValue);
|
||||
}
|
||||
} catch(e) {
|
||||
// handle any unexpected exceptions
|
||||
TiltUtils.Output.error(e.message);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a custom Tilt preference.
|
||||
* If the preference already exists, it is left unchanged.
|
||||
*
|
||||
* @param {String} aPref
|
||||
* the preference name
|
||||
* @param {String} aType
|
||||
* either "boolean", "string" or "integer"
|
||||
* @param {String} aValue
|
||||
* the initial preference value
|
||||
*
|
||||
* @return {Boolean} true if the preference was initialized successfully
|
||||
*/
|
||||
create: function TUP_create(aPref, aType, aValue)
|
||||
{
|
||||
if (!aPref || !aType || aValue === undefined || aValue === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let prefs = this._branch;
|
||||
|
||||
if (!prefs.prefHasUserValue(aPref)) {
|
||||
switch(aType) {
|
||||
case "boolean":
|
||||
return prefs.setBoolPref(aPref, aValue);
|
||||
case "string":
|
||||
return prefs.setCharPref(aPref, aValue);
|
||||
case "integer":
|
||||
return prefs.setIntPref(aPref, aValue);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
// handle any unexpected exceptions
|
||||
TiltUtils.Output.error(e.message);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* The preferences branch for this extension.
|
||||
*/
|
||||
_branch: (function(aBranch) {
|
||||
return Cc["@mozilla.org/preferences-service;1"]
|
||||
.getService(Ci.nsIPrefService)
|
||||
.getBranch(aBranch);
|
||||
|
||||
}("devtools.tilt."))
|
||||
};
|
||||
|
||||
/**
|
||||
* Easy way to access the string bundle.
|
||||
*/
|
||||
TiltUtils.L10n = {
|
||||
|
||||
/**
|
||||
* The string bundle element.
|
||||
*/
|
||||
stringBundle: null,
|
||||
|
||||
/**
|
||||
* Returns a string in the string bundle.
|
||||
* If the string bundle is not found, null is returned.
|
||||
*
|
||||
* @param {String} aName
|
||||
* the string name in the bundle
|
||||
*
|
||||
* @return {String} the equivalent string from the bundle
|
||||
*/
|
||||
get: function TUL_get(aName)
|
||||
{
|
||||
// check to see if the parent string bundle document element is valid
|
||||
if (!this.stringBundle || !aName) {
|
||||
return null;
|
||||
}
|
||||
return this.stringBundle.GetStringFromName(aName);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a formatted string using the string bundle.
|
||||
* If the string bundle is not found, null is returned.
|
||||
*
|
||||
* @param {String} aName
|
||||
* the string name in the bundle
|
||||
* @param {Array} aArgs
|
||||
* an array of arguments for the formatted string
|
||||
*
|
||||
* @return {String} the equivalent formatted string from the bundle
|
||||
*/
|
||||
format: function TUL_format(aName, aArgs)
|
||||
{
|
||||
// check to see if the parent string bundle document element is valid
|
||||
if (!this.stringBundle || !aName || !aArgs) {
|
||||
return null;
|
||||
}
|
||||
return this.stringBundle.formatStringFromName(aName, aArgs, aArgs.length);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Utilities for accessing and manipulating a document.
|
||||
*/
|
||||
TiltUtils.DOM = {
|
||||
|
||||
/**
|
||||
* Current parent node object used when creating canvas elements.
|
||||
*/
|
||||
parentNode: null,
|
||||
|
||||
/**
|
||||
* Helper method, allowing to easily create and manage a canvas element.
|
||||
* If the width and height params are falsy, they default to the parent node
|
||||
* client width and height.
|
||||
*
|
||||
* @param {Document} aParentNode
|
||||
* the parent node used to create the canvas
|
||||
* if not specified, it will be reused from the cache
|
||||
* @param {Object} aProperties
|
||||
* optional, object containing some of the following props:
|
||||
* {Boolean} focusable
|
||||
* optional, true to make the canvas focusable
|
||||
* {Boolean} append
|
||||
* optional, true to append the canvas to the parent node
|
||||
* {Number} width
|
||||
* optional, specifies the width of the canvas
|
||||
* {Number} height
|
||||
* optional, specifies the height of the canvas
|
||||
* {String} id
|
||||
* optional, id for the created canvas element
|
||||
*
|
||||
* @return {HTMLCanvasElement} the newly created canvas element
|
||||
*/
|
||||
initCanvas: function TUD_initCanvas(aParentNode, aProperties)
|
||||
{
|
||||
// check to see if the parent node element is valid
|
||||
if (!(aParentNode = aParentNode || this.parentNode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// make sure the properties parameter is a valid object
|
||||
aProperties = aProperties || {};
|
||||
|
||||
// cache this parent node so that it can be reused
|
||||
this.parentNode = aParentNode;
|
||||
|
||||
// create the canvas element
|
||||
let canvas = aParentNode.ownerDocument.
|
||||
createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
|
||||
let width = aProperties.width || aParentNode.clientWidth;
|
||||
let height = aProperties.height || aParentNode.clientHeight;
|
||||
let id = aProperties.id || null;
|
||||
|
||||
canvas.setAttribute("style", "min-width: 1px; min-height: 1px;");
|
||||
canvas.setAttribute("width", width);
|
||||
canvas.setAttribute("height", height);
|
||||
canvas.setAttribute("id", id);
|
||||
|
||||
// the canvas is unfocusable by default, we may require otherwise
|
||||
if (aProperties.focusable) {
|
||||
canvas.setAttribute("tabindex", "1");
|
||||
canvas.style.outline = "none";
|
||||
}
|
||||
|
||||
// append the canvas element to the current parent node, if specified
|
||||
if (aProperties.append) {
|
||||
aParentNode.appendChild(canvas);
|
||||
}
|
||||
|
||||
return canvas;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the full webpage dimensions (width and height).
|
||||
*
|
||||
* @param {Window} aContentWindow
|
||||
* the content window holding the document
|
||||
*
|
||||
* @return {Object} an object containing the width and height coords
|
||||
*/
|
||||
getContentWindowDimensions: function TUD_getContentWindowDimensions(
|
||||
aContentWindow)
|
||||
{
|
||||
return {
|
||||
width: aContentWindow.innerWidth + aContentWindow.scrollMaxX,
|
||||
height: aContentWindow.innerHeight + aContentWindow.scrollMaxY
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the absolute x, y, width and height coordinates of a node, or null
|
||||
* if the passed node is not an ELEMENT_NODE.
|
||||
*
|
||||
* @param {Element} aNode
|
||||
* the node which coordinates need to be calculated
|
||||
* @param {Window} aContentWindow
|
||||
* optional, the window content holding the the document
|
||||
*
|
||||
* @return {Object} an object containing the top, left, width, height coords
|
||||
*/
|
||||
getNodeCoordinates: function TUD_getNodeCoordinates(aNode, aContentWindow) {
|
||||
// make sure the contentWindow parameter is a valid object
|
||||
aContentWindow = aContentWindow || {};
|
||||
|
||||
if (aNode.nodeType !== 1) { // Node.ELEMENT_NODE
|
||||
return null;
|
||||
}
|
||||
|
||||
let rect = {
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
|
||||
// the preferred way of getting the bounding client rectangle
|
||||
let clientRect = aNode.getBoundingClientRect();
|
||||
rect.top = clientRect.top + aContentWindow.pageYOffset;
|
||||
rect.left = clientRect.left + aContentWindow.pageXOffset;
|
||||
rect.width = clientRect.width;
|
||||
rect.height = clientRect.height;
|
||||
|
||||
// compute the iframe position and its offset if necessary
|
||||
let frameRect = this.getFrameOffset(
|
||||
aNode.ownerDocument.defaultView.frameElement, aContentWindow);
|
||||
|
||||
if (frameRect) {
|
||||
rect.top += frameRect.top;
|
||||
rect.left += frameRect.left;
|
||||
}
|
||||
|
||||
return rect;
|
||||
},
|
||||
|
||||
/**
|
||||
* Retuns the parent iframe position and its offset (borders and padding),
|
||||
* or null if the passed frame is not valid.
|
||||
*
|
||||
* @param {Element} aNode
|
||||
* the iframe which offset need to be calculated
|
||||
* @param {Window} aContentWindow
|
||||
* optional, the window content holding the the document
|
||||
*
|
||||
* @return {Object} an object containing the top and left coords
|
||||
*/
|
||||
getFrameOffset: (function() {
|
||||
let cache = {};
|
||||
|
||||
return function TUD_getFrameOffset(aFrame, aContentWindow) {
|
||||
// make sure the contentWindow parameter is a valid object
|
||||
aContentWindow = aContentWindow || {};
|
||||
|
||||
if (!aFrame) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let id = TiltUtils.getWindowId(aFrame.contentWindow) + "," +
|
||||
aContentWindow.pageXOffset || 0 + "," +
|
||||
aContentWindow.pageYOffset || 0;
|
||||
|
||||
// check the cache to see if this iframe offset wasn't calculated already
|
||||
if (cache[id] !== undefined) {
|
||||
return cache[id];
|
||||
}
|
||||
|
||||
let offset = {
|
||||
top: 0,
|
||||
left: 0
|
||||
};
|
||||
|
||||
// take the parent iframe bounding rect position into account
|
||||
let frameRect = aFrame.getBoundingClientRect();
|
||||
offset.top = frameRect.top;
|
||||
offset.left = frameRect.left;
|
||||
|
||||
// compute the iframe content offset (iframe border + padding)
|
||||
// bug #626359
|
||||
let style = aFrame.contentWindow.getComputedStyle(aFrame, null);
|
||||
if (style) {
|
||||
offset.top +=
|
||||
parseInt(style.getPropertyValue("padding-top")) +
|
||||
parseInt(style.getPropertyValue("border-top-width"));
|
||||
offset.left +=
|
||||
parseInt(style.getPropertyValue("padding-left")) +
|
||||
parseInt(style.getPropertyValue("border-left-width"));
|
||||
}
|
||||
|
||||
return (cache[id] = offset);
|
||||
};
|
||||
}()),
|
||||
|
||||
/**
|
||||
* Traverses a document object model & calculates useful info for each node.
|
||||
*
|
||||
* @param {Window} aContentWindow
|
||||
* the window content holding the document
|
||||
* @param {Object} aProperties
|
||||
* optional, an object containing the following properties:
|
||||
* {Object} invisibleElements
|
||||
* elements which should be ignored
|
||||
* {Number} minSize
|
||||
* the minimum dimensions needed for a node to be traversed
|
||||
* {Number} maxX
|
||||
* the maximum left position of an element
|
||||
* {Number} maxY
|
||||
* the maximum top position of an element
|
||||
*
|
||||
* @return {Array} list containing nodes depths, coordinates and local names
|
||||
*/
|
||||
traverse: function TUD_traverse(aContentWindow, aProperties)
|
||||
{
|
||||
// make sure the properties parameter is a valid object
|
||||
aProperties = aProperties || {};
|
||||
|
||||
let aInvisibleElements = aProperties.invisibleElements || {};
|
||||
let aMinSize = aProperties.minSize || -1;
|
||||
let aMaxX = aProperties.maxX || Number.MAX_VALUE;
|
||||
let aMaxY = aProperties.maxY || Number.MAX_VALUE;
|
||||
|
||||
let nodes = aContentWindow.document.childNodes;
|
||||
let store = { info: [], nodes: [] };
|
||||
let depth = 0;
|
||||
|
||||
while (nodes.length) {
|
||||
let queue = [];
|
||||
|
||||
for (let i = 0, len = nodes.length; i < len; i++) {
|
||||
let node = nodes[i];
|
||||
|
||||
// skip some nodes to avoid visualization meshes that are too bloated
|
||||
let name = node.localName;
|
||||
if (!name || aInvisibleElements[name]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get the x, y, width and height coordinates of the node
|
||||
let coord = this.getNodeCoordinates(node, aContentWindow);
|
||||
if (!coord) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// the maximum size slices the traversal where needed
|
||||
if (coord.left > aMaxX || coord.top > aMaxY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// use this node only if it actually has visible dimensions
|
||||
if (coord.width > aMinSize && coord.height > aMinSize) {
|
||||
|
||||
// save the necessary details into a list to be returned later
|
||||
store.info.push({ depth: depth, coord: coord, name: name });
|
||||
store.nodes.push(node);
|
||||
}
|
||||
|
||||
// prepare the queue array
|
||||
Array.prototype.push.apply(queue, name === "iframe" ?
|
||||
node.contentDocument.childNodes :
|
||||
node.childNodes);
|
||||
}
|
||||
nodes = queue;
|
||||
depth++;
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Binds a new owner object to the child functions.
|
||||
* If the new parent is not specified, it will default to the passed scope.
|
||||
*
|
||||
* @param {Object} aScope
|
||||
* the object from which all functions will be rebound
|
||||
* @param {String} aRegex
|
||||
* a regular expression to identify certain functions
|
||||
* @param {Object} aParent
|
||||
* the new parent for the object's functions
|
||||
*/
|
||||
TiltUtils.bindObjectFunc = function TU_bindObjectFunc(aScope, aRegex, aParent)
|
||||
{
|
||||
if (!aScope) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i in aScope) {
|
||||
try {
|
||||
if ("function" === typeof aScope[i] && (aRegex ? i.match(aRegex) : 1)) {
|
||||
aScope[i] = aScope[i].bind(aParent || aScope);
|
||||
}
|
||||
} catch(e) {
|
||||
TiltUtils.Output.error(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys an object and deletes all members.
|
||||
*
|
||||
* @param {Object} aScope
|
||||
* the object from which all children will be destroyed
|
||||
*/
|
||||
TiltUtils.destroyObject = function TU_destroyObject(aScope)
|
||||
{
|
||||
if (!aScope) {
|
||||
return;
|
||||
}
|
||||
|
||||
// objects in Tilt usually use a function to handle internal destruction
|
||||
if ("function" === typeof aScope.finalize) {
|
||||
aScope.finalize();
|
||||
}
|
||||
for (let i in aScope) {
|
||||
if (aScope.hasOwnProperty(i)) {
|
||||
delete aScope[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the unique ID of a window object.
|
||||
*
|
||||
* @param {Window} aWindow
|
||||
* the window to get the ID from
|
||||
*
|
||||
* @return {Number} the window ID
|
||||
*/
|
||||
TiltUtils.getWindowId = function TU_getWindowId(aWindow)
|
||||
{
|
||||
if (!aWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
return aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.currentInnerWindowID;
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs a garbage collection.
|
||||
*/
|
||||
TiltUtils.gc = function TU_gc()
|
||||
{
|
||||
var browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Ci.nsIWindowMediator)
|
||||
.getMostRecentWindow("navigator:browser");
|
||||
|
||||
browserWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindowUtils)
|
||||
.garbageCollect();
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears the cache and sets all the variables to null.
|
||||
*/
|
||||
TiltUtils.clearCache = function TU_clearCache()
|
||||
{
|
||||
TiltUtils.DOM.parentNode = null;
|
||||
};
|
||||
|
||||
// bind the owner object to the necessary functions
|
||||
TiltUtils.bindObjectFunc(TiltUtils.Output);
|
||||
TiltUtils.bindObjectFunc(TiltUtils.Preferences);
|
||||
TiltUtils.bindObjectFunc(TiltUtils.L10n);
|
||||
TiltUtils.bindObjectFunc(TiltUtils.DOM);
|
||||
|
||||
// set the necessary string bundle
|
||||
XPCOMUtils.defineLazyGetter(TiltUtils.L10n, "stringBundle", function() {
|
||||
return Services.strings.createBundle(
|
||||
"chrome://browser/locale/devtools/tilt.properties");
|
||||
});
|
1587
browser/devtools/tilt/TiltVisualizer.jsm
Normal file
1587
browser/devtools/tilt/TiltVisualizer.jsm
Normal file
File diff suppressed because it is too large
Load Diff
86
browser/devtools/tilt/TiltVisualizerStyle.jsm
Normal file
86
browser/devtools/tilt/TiltVisualizerStyle.jsm
Normal file
@ -0,0 +1,86 @@
|
||||
/* -*- Mode: javascript, tab-width: 2, indent-tabs-mode: nil, c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"), you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Tilt: A WebGL-based 3D visualization of a webpage.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Victor Porof <vporof@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
***** END LICENSE BLOCK *****/
|
||||
|
||||
/*global Components, TiltMath */
|
||||
"use strict";
|
||||
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource:///modules/devtools/TiltMath.jsm");
|
||||
|
||||
let EXPORTED_SYMBOLS = ["TiltVisualizerStyle"];
|
||||
let rgba = TiltMath.hex2rgba;
|
||||
|
||||
/**
|
||||
* Various colors and style settings used throughout Tilt.
|
||||
*/
|
||||
let TiltVisualizerStyle = {
|
||||
|
||||
canvas: {
|
||||
background: "-moz-linear-gradient(top, #454545 0%, #000 100%)",
|
||||
},
|
||||
|
||||
nodes: {
|
||||
highlight: {
|
||||
defaultFill: rgba("#555"),
|
||||
defaultStroke: rgba("#000"),
|
||||
defaultStrokeWeight: 1
|
||||
},
|
||||
|
||||
html: rgba("#8880"),
|
||||
body: rgba("#fff0"),
|
||||
h1: rgba("#e667af"),
|
||||
h2: rgba("#c667af"),
|
||||
h3: rgba("#a667af"),
|
||||
h4: rgba("#8667af"),
|
||||
h5: rgba("#8647af"),
|
||||
h6: rgba("#8627af"),
|
||||
div: rgba("#5dc8cd"),
|
||||
span: rgba("#67e46f"),
|
||||
table: rgba("#ff0700"),
|
||||
tr: rgba("#ff4540"),
|
||||
td: rgba("#ff7673"),
|
||||
ul: rgba("#4671d5"),
|
||||
li: rgba("#6c8cd5"),
|
||||
p: rgba("#aaa"),
|
||||
a: rgba("#123eab"),
|
||||
img: rgba("#ffb473"),
|
||||
iframe: rgba("#85004b")
|
||||
}
|
||||
};
|
297
browser/devtools/tilt/TiltWorkerCrafter.js
Normal file
297
browser/devtools/tilt/TiltWorkerCrafter.js
Normal file
@ -0,0 +1,297 @@
|
||||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Tilt: A WebGL-based 3D visualization of a webpage.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Victor Porof <vporof@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
***** END LICENSE BLOCK *****/
|
||||
|
||||
/*global self*/
|
||||
"use strict";
|
||||
|
||||
const SIXTEEN_OVER_255 = 16 / 255;
|
||||
const ONE_OVER_255 = 1 / 255;
|
||||
|
||||
/**
|
||||
* Given the initialization data (thickness, sizes and information about
|
||||
* each DOM node) this worker sends back the arrays representing
|
||||
* vertices, texture coords, colors, indices and all the needed data for
|
||||
* rendering the DOM visualization mesh.
|
||||
*
|
||||
* Used in the TiltVisualization.Presenter object.
|
||||
*/
|
||||
self.onmessage = function TWC_onMessage(event)
|
||||
{
|
||||
let data = event.data;
|
||||
let thickness = data.thickness;
|
||||
let style = data.style;
|
||||
let texWidth = data.texWidth;
|
||||
let texHeight = data.texHeight;
|
||||
let nodesInfo = data.nodesInfo;
|
||||
|
||||
// create the arrays used to construct the 3D mesh data
|
||||
let vertices = [];
|
||||
let texCoord = [];
|
||||
let color = [];
|
||||
let stacksIndices = [];
|
||||
let wireframeIndices = [];
|
||||
let meshWidth = 0;
|
||||
let meshHeight = 0;
|
||||
|
||||
// seed the random function to get the same values each time
|
||||
// we're doing this to avoid ugly z-fighting with overlapping nodes
|
||||
self.random.seed(0);
|
||||
|
||||
// go through all the dom nodes and compute the verts, texcoord etc.
|
||||
for (let n = 0, i = 0, len = nodesInfo.length; n < len; n++) {
|
||||
let info = nodesInfo[n];
|
||||
let depth = info.depth;
|
||||
let coord = info.coord;
|
||||
|
||||
// calculate the stack x, y, z, width and height coordinates
|
||||
let z = depth * thickness;
|
||||
let y = coord.top;
|
||||
let x = coord.left;
|
||||
let w = coord.width;
|
||||
let h = coord.height;
|
||||
|
||||
// the maximum texture size slices the visualization mesh where needed
|
||||
if (x + w > texWidth) {
|
||||
w = texWidth - x;
|
||||
}
|
||||
if (y + h > texHeight) {
|
||||
h = texHeight - y;
|
||||
}
|
||||
|
||||
x += self.random.next();
|
||||
y += self.random.next();
|
||||
w -= self.random.next() * 0.1;
|
||||
h -= self.random.next() * 0.1;
|
||||
|
||||
let xpw = x + w;
|
||||
let yph = y + h;
|
||||
let zmt = z - thickness;
|
||||
|
||||
let xotw = x / texWidth;
|
||||
let yoth = y / texHeight;
|
||||
let xpwotw = xpw / texWidth;
|
||||
let yphoth = yph / texHeight;
|
||||
|
||||
// calculate the margin fill color
|
||||
let fill = style[info.name] || style.highlight.defaultFill;
|
||||
|
||||
let r = fill[0];
|
||||
let g = fill[1];
|
||||
let b = fill[2];
|
||||
let g10 = r * 1.1;
|
||||
let g11 = g * 1.1;
|
||||
let g12 = b * 1.1;
|
||||
let g20 = r * 0.6;
|
||||
let g21 = g * 0.6;
|
||||
let g22 = b * 0.6;
|
||||
|
||||
// compute the vertices
|
||||
vertices.push(x, y, z, /* front */ // 0
|
||||
x, yph, z, // 1
|
||||
xpw, yph, z, // 2
|
||||
xpw, y, z, // 3
|
||||
// we don't duplicate vertices for the left and right faces, because
|
||||
// they can be reused from the bottom and top faces; we do, however,
|
||||
// duplicate some vertices from front face, because it has custom
|
||||
// texture coordinates which are not shared by the other faces
|
||||
x, y, z, /* front */ // 4
|
||||
x, yph, z, // 5
|
||||
xpw, yph, z, // 6
|
||||
xpw, y, z, // 7
|
||||
x, y, zmt, /* back */ // 8
|
||||
x, yph, zmt, // 9
|
||||
xpw, yph, zmt, // 10
|
||||
xpw, y, zmt); // 11
|
||||
|
||||
// compute the texture coordinates
|
||||
texCoord.push(xotw, yoth,
|
||||
xotw, yphoth,
|
||||
xpwotw, yphoth,
|
||||
xpwotw, yoth,
|
||||
-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0);
|
||||
|
||||
// compute the colors for each vertex in the mesh
|
||||
color.push(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
g10, g11, g12,
|
||||
g10, g11, g12,
|
||||
g10, g11, g12,
|
||||
g10, g11, g12,
|
||||
g20, g21, g22,
|
||||
g20, g21, g22,
|
||||
g20, g21, g22,
|
||||
g20, g21, g22);
|
||||
|
||||
let ip1 = i + 1;
|
||||
let ip2 = ip1 + 1;
|
||||
let ip3 = ip2 + 1;
|
||||
let ip4 = ip3 + 1;
|
||||
let ip5 = ip4 + 1;
|
||||
let ip6 = ip5 + 1;
|
||||
let ip7 = ip6 + 1;
|
||||
let ip8 = ip7 + 1;
|
||||
let ip9 = ip8 + 1;
|
||||
let ip10 = ip9 + 1;
|
||||
let ip11 = ip10 + 1;
|
||||
|
||||
// compute the stack indices
|
||||
stacksIndices.unshift(i, ip1, ip2, i, ip2, ip3,
|
||||
ip8, ip9, ip5, ip8, ip5, ip4,
|
||||
ip7, ip6, ip10, ip7, ip10, ip11,
|
||||
ip8, ip4, ip7, ip8, ip7, ip11,
|
||||
ip5, ip9, ip10, ip5, ip10, ip6);
|
||||
|
||||
// compute the wireframe indices
|
||||
if (depth !== 0) {
|
||||
wireframeIndices.unshift(i, ip1, ip1, ip2,
|
||||
ip2, ip3, ip3, i,
|
||||
ip8, i, ip9, ip1,
|
||||
ip11, ip3, ip10, ip2);
|
||||
}
|
||||
|
||||
// number of vertex points, used for creating the indices array
|
||||
i += 12; // a vertex has 3 coords: x, y and z
|
||||
|
||||
// set the maximum mesh width and height to calculate the center offset
|
||||
meshWidth = Math.max(w, meshWidth);
|
||||
meshHeight = Math.max(h, meshHeight);
|
||||
}
|
||||
|
||||
self.postMessage({
|
||||
vertices: vertices,
|
||||
texCoord: texCoord,
|
||||
color: color,
|
||||
stacksIndices: stacksIndices,
|
||||
wireframeIndices: wireframeIndices,
|
||||
meshWidth: meshWidth,
|
||||
meshHeight: meshHeight
|
||||
});
|
||||
close();
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility functions for generating random numbers using the Alea algorithm.
|
||||
*/
|
||||
self.random = {
|
||||
|
||||
/**
|
||||
* The generator function, automatically created with seed 0.
|
||||
*/
|
||||
_generator: null,
|
||||
|
||||
/**
|
||||
* Returns a new random number between [0..1)
|
||||
*/
|
||||
next: function RNG_next()
|
||||
{
|
||||
return this._generator();
|
||||
},
|
||||
|
||||
/**
|
||||
* From http://baagoe.com/en/RandomMusings/javascript
|
||||
* Johannes Baagoe <baagoe@baagoe.com>, 2010
|
||||
*
|
||||
* Seeds a random generator function with a set of passed arguments.
|
||||
*/
|
||||
seed: function RNG_seed()
|
||||
{
|
||||
let s0 = 0;
|
||||
let s1 = 0;
|
||||
let s2 = 0;
|
||||
let c = 1;
|
||||
|
||||
if (arguments.length === 0) {
|
||||
return this.seed(+new Date());
|
||||
} else {
|
||||
s0 = this.mash(" ");
|
||||
s1 = this.mash(" ");
|
||||
s2 = this.mash(" ");
|
||||
|
||||
for (let i = 0, len = arguments.length; i < len; i++) {
|
||||
s0 -= this.mash(arguments[i]);
|
||||
if (s0 < 0) {
|
||||
s0 += 1;
|
||||
}
|
||||
s1 -= this.mash(arguments[i]);
|
||||
if (s1 < 0) {
|
||||
s1 += 1;
|
||||
}
|
||||
s2 -= this.mash(arguments[i]);
|
||||
if (s2 < 0) {
|
||||
s2 += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let random = function() {
|
||||
let t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
|
||||
s0 = s1;
|
||||
s1 = s2;
|
||||
return (s2 = t - (c = t | 0));
|
||||
};
|
||||
random.uint32 = function() {
|
||||
return random() * 0x100000000; // 2^32
|
||||
};
|
||||
random.fract53 = function() {
|
||||
return random() +
|
||||
(random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
|
||||
};
|
||||
return (this._generator = random);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* From http://baagoe.com/en/RandomMusings/javascript
|
||||
* Johannes Baagoe <baagoe@baagoe.com>, 2010
|
||||
*/
|
||||
mash: function RNG_mash(data)
|
||||
{
|
||||
let h, n = 0xefc8249d;
|
||||
|
||||
for (let i = 0, data = data.toString(), len = data.length; i < len; i++) {
|
||||
n += data.charCodeAt(i);
|
||||
h = 0.02519603282416938 * n;
|
||||
n = h >>> 0;
|
||||
h -= n;
|
||||
h *= n;
|
||||
n = h >>> 0;
|
||||
h -= n;
|
||||
n += h * 0x100000000; // 2^32
|
||||
}
|
||||
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
|
||||
}
|
||||
};
|
217
browser/devtools/tilt/TiltWorkerPicker.js
Normal file
217
browser/devtools/tilt/TiltWorkerPicker.js
Normal file
@ -0,0 +1,217 @@
|
||||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Tilt: A WebGL-based 3D visualization of a webpage.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Victor Porof <vporof@mozilla.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
***** END LICENSE BLOCK *****/
|
||||
|
||||
/*global self*/
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* This worker handles picking, given a set of vertices and a ray (calculates
|
||||
* the intersection points and offers back information about the closest hit).
|
||||
*
|
||||
* Used in the TiltVisualization.Presenter object.
|
||||
*/
|
||||
self.onmessage = function TWP_onMessage(event)
|
||||
{
|
||||
let data = event.data;
|
||||
let thickness = data.thickness;
|
||||
let vertices = data.vertices;
|
||||
let ray = data.ray;
|
||||
|
||||
let intersection = null;
|
||||
let hit = [];
|
||||
|
||||
// calculates the squared distance between two points
|
||||
function dsq(p1, p2) {
|
||||
let xd = p2[0] - p1[0];
|
||||
let yd = p2[1] - p1[1];
|
||||
let zd = p2[2] - p1[2];
|
||||
|
||||
return xd * xd + yd * yd + zd * zd;
|
||||
}
|
||||
|
||||
// check each stack face in the visualization mesh for intersections with
|
||||
// the mouse ray (using a ray picking algorithm)
|
||||
for (let i = 0, len = vertices.length; i < len; i += 36) {
|
||||
|
||||
// the front quad
|
||||
let v0f = [vertices[i], vertices[i + 1], vertices[i + 2]];
|
||||
let v1f = [vertices[i + 3], vertices[i + 4], vertices[i + 5]];
|
||||
let v2f = [vertices[i + 6], vertices[i + 7], vertices[i + 8]];
|
||||
let v3f = [vertices[i + 9], vertices[i + 10], vertices[i + 11]];
|
||||
|
||||
// the back quad
|
||||
let v0b = [v0f[0], v0f[1], v0f[2] - thickness];
|
||||
let v1b = [v1f[0], v1f[1], v1f[2] - thickness];
|
||||
let v2b = [v2f[0], v2f[1], v2f[2] - thickness];
|
||||
let v3b = [v3f[0], v3f[1], v3f[2] - thickness];
|
||||
|
||||
// for each triangle in the stack box, check for the intersections
|
||||
if (self.intersect(v0f, v1f, v2f, ray, hit) || // front left
|
||||
self.intersect(v0f, v2f, v3f, ray, hit) || // front right
|
||||
self.intersect(v0b, v1b, v1f, ray, hit) || // left back
|
||||
self.intersect(v0b, v1f, v0f, ray, hit) || // left front
|
||||
self.intersect(v3f, v2b, v3b, ray, hit) || // right back
|
||||
self.intersect(v3f, v2f, v2b, ray, hit) || // right front
|
||||
self.intersect(v0b, v0f, v3f, ray, hit) || // top left
|
||||
self.intersect(v0b, v3f, v3b, ray, hit) || // top right
|
||||
self.intersect(v1f, v1b, v2b, ray, hit) || // bottom left
|
||||
self.intersect(v1f, v2b, v2f, ray, hit)) { // bottom right
|
||||
|
||||
// calculate the distance between the intersection hit point and camera
|
||||
let d = dsq(hit, ray.origin);
|
||||
|
||||
// we're picking the closest stack in the mesh from the camera
|
||||
if (intersection === null || d < intersection.distance) {
|
||||
intersection = {
|
||||
// each mesh stack is composed of 12 vertices, so there's information
|
||||
// about a node once in 12 * 3 = 36 iterations (to avoid duplication)
|
||||
index: i / 36,
|
||||
distance: d
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.postMessage(intersection);
|
||||
close();
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility function for finding intersections between a ray and a triangle.
|
||||
*/
|
||||
self.intersect = (function() {
|
||||
|
||||
// creates a new instance of a vector
|
||||
function create() {
|
||||
return new Float32Array(3);
|
||||
}
|
||||
|
||||
// performs a vector addition
|
||||
function add(aVec, aVec2, aDest) {
|
||||
aDest[0] = aVec[0] + aVec2[0];
|
||||
aDest[1] = aVec[1] + aVec2[1];
|
||||
aDest[2] = aVec[2] + aVec2[2];
|
||||
return aDest;
|
||||
}
|
||||
|
||||
// performs a vector subtraction
|
||||
function subtract(aVec, aVec2, aDest) {
|
||||
aDest[0] = aVec[0] - aVec2[0];
|
||||
aDest[1] = aVec[1] - aVec2[1];
|
||||
aDest[2] = aVec[2] - aVec2[2];
|
||||
return aDest;
|
||||
}
|
||||
|
||||
// performs a vector scaling
|
||||
function scale(aVec, aVal, aDest) {
|
||||
aDest[0] = aVec[0] * aVal;
|
||||
aDest[1] = aVec[1] * aVal;
|
||||
aDest[2] = aVec[2] * aVal;
|
||||
return aDest;
|
||||
}
|
||||
|
||||
// generates the cross product of two vectors
|
||||
function cross(aVec, aVec2, aDest) {
|
||||
let x = aVec[0];
|
||||
let y = aVec[1];
|
||||
let z = aVec[2];
|
||||
let x2 = aVec2[0];
|
||||
let y2 = aVec2[1];
|
||||
let z2 = aVec2[2];
|
||||
|
||||
aDest[0] = y * z2 - z * y2;
|
||||
aDest[1] = z * x2 - x * z2;
|
||||
aDest[2] = x * y2 - y * x2;
|
||||
return aDest;
|
||||
}
|
||||
|
||||
// calculates the dot product of two vectors
|
||||
function dot(aVec, aVec2) {
|
||||
return aVec[0] * aVec2[0] + aVec[1] * aVec2[1] + aVec[2] * aVec2[2];
|
||||
}
|
||||
|
||||
let edge1 = create();
|
||||
let edge2 = create();
|
||||
let pvec = create();
|
||||
let tvec = create();
|
||||
let qvec = create();
|
||||
let lvec = create();
|
||||
|
||||
// checks for ray-triangle intersections using the Fast Minimum-Storage
|
||||
// (simplified) algorithm by Tomas Moller and Ben Trumbore
|
||||
return function intersect(aVert0, aVert1, aVert2, aRay, aDest) {
|
||||
let dir = aRay.direction;
|
||||
let orig = aRay.origin;
|
||||
|
||||
// find vectors for two edges sharing vert0
|
||||
subtract(aVert1, aVert0, edge1);
|
||||
subtract(aVert2, aVert0, edge2);
|
||||
|
||||
// begin calculating determinant - also used to calculate the U parameter
|
||||
cross(dir, edge2, pvec);
|
||||
|
||||
// if determinant is near zero, ray lines in plane of triangle
|
||||
let inv_det = 1 / dot(edge1, pvec);
|
||||
|
||||
// calculate distance from vert0 to ray origin
|
||||
subtract(orig, aVert0, tvec);
|
||||
|
||||
// calculate U parameter and test bounds
|
||||
let u = dot(tvec, pvec) * inv_det;
|
||||
if (u < 0 || u > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// prepare to test V parameter
|
||||
cross(tvec, edge1, qvec);
|
||||
|
||||
// calculate V parameter and test bounds
|
||||
let v = dot(dir, qvec) * inv_det;
|
||||
if (v < 0 || u + v > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// calculate T, ray intersects triangle
|
||||
let t = dot(edge2, qvec) * inv_det;
|
||||
|
||||
scale(dir, t, lvec);
|
||||
add(orig, lvec, aDest);
|
||||
return true;
|
||||
};
|
||||
}());
|
80
browser/devtools/tilt/test/Makefile.in
Normal file
80
browser/devtools/tilt/test/Makefile.in
Normal file
@ -0,0 +1,80 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation
|
||||
# Portions created by the Initial Developer are Copyright (C) 2011
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Victor Porof <vporof@mozilla.com> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = browser/devtools/tilt/test
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_TEST_FILES = \
|
||||
head.js \
|
||||
browser_tilt_01_lazy_getter.js \
|
||||
browser_tilt_02_notifications.js \
|
||||
browser_tilt_03_tab_switch.js \
|
||||
browser_tilt_04_initialization.js \
|
||||
browser_tilt_05_destruction.js \
|
||||
browser_tilt_arcball.js \
|
||||
browser_tilt_gl01.js \
|
||||
browser_tilt_gl02.js \
|
||||
browser_tilt_gl03.js \
|
||||
browser_tilt_gl04.js \
|
||||
browser_tilt_gl05.js \
|
||||
browser_tilt_gl06.js \
|
||||
browser_tilt_gl07.js \
|
||||
browser_tilt_gl08.js \
|
||||
browser_tilt_math01.js \
|
||||
browser_tilt_math02.js \
|
||||
browser_tilt_math03.js \
|
||||
browser_tilt_math04.js \
|
||||
browser_tilt_math05.js \
|
||||
browser_tilt_math06.js \
|
||||
browser_tilt_math07.js \
|
||||
browser_tilt_utils01.js \
|
||||
browser_tilt_utils02.js \
|
||||
browser_tilt_utils03.js \
|
||||
browser_tilt_utils04.js \
|
||||
browser_tilt_utils05.js \
|
||||
browser_tilt_utils06.js \
|
||||
browser_tilt_visualizer.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
16
browser/devtools/tilt/test/browser_tilt_01_lazy_getter.js
Normal file
16
browser/devtools/tilt/test/browser_tilt_01_lazy_getter.js
Normal file
@ -0,0 +1,16 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, Tilt */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
ok(Tilt,
|
||||
"The Tilt object wasn't got correctly via defineLazyGetter.");
|
||||
is(Tilt.chromeWindow, window,
|
||||
"The top-level window wasn't saved correctly");
|
||||
ok(Tilt.visualizers,
|
||||
"The holder object for all the instances of the visualizer doesn't exist.")
|
||||
ok(Tilt.NOTIFICATIONS,
|
||||
"The notifications constants weren't referenced correctly.");
|
||||
}
|
97
browser/devtools/tilt/test/browser_tilt_02_notifications.js
Normal file
97
browser/devtools/tilt/test/browser_tilt_02_notifications.js
Normal file
@ -0,0 +1,97 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, info, waitForExplicitFinish, finish, executeSoon, gBrowser */
|
||||
/*global isTiltEnabled, isWebGLSupported, createTab, createTilt, Tilt */
|
||||
/*global Services, TILT_INITIALIZED, TILT_DESTROYED, TILT_SHOWN, TILT_HIDDEN */
|
||||
"use strict";
|
||||
|
||||
let tab0, tab1;
|
||||
let testStep = -1;
|
||||
let tabEvents = "";
|
||||
|
||||
function test() {
|
||||
if (!isTiltEnabled()) {
|
||||
info("Skipping notifications test because Tilt isn't enabled.");
|
||||
return;
|
||||
}
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping notifications test because WebGL isn't supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.tabContainer.addEventListener("TabSelect", tabSelect, false);
|
||||
createNewTab();
|
||||
}
|
||||
|
||||
function createNewTab() {
|
||||
tab0 = gBrowser.selectedTab;
|
||||
|
||||
tab1 = createTab(function() {
|
||||
Services.obs.addObserver(tab_TILT_INITIALIZED, TILT_INITIALIZED, false);
|
||||
Services.obs.addObserver(tab_TILT_DESTROYED, TILT_DESTROYED, false);
|
||||
Services.obs.addObserver(tab_TILT_SHOWN, TILT_SHOWN, false);
|
||||
Services.obs.addObserver(tab_TILT_HIDDEN, TILT_HIDDEN, false);
|
||||
|
||||
createTilt({
|
||||
onTiltOpen: function()
|
||||
{
|
||||
testStep = 0;
|
||||
tabSelect();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function tab_TILT_INITIALIZED() {
|
||||
tabEvents += "ti;";
|
||||
}
|
||||
|
||||
function tab_TILT_DESTROYED() {
|
||||
tabEvents += "td;";
|
||||
}
|
||||
|
||||
function tab_TILT_SHOWN() {
|
||||
tabEvents += "ts;";
|
||||
}
|
||||
|
||||
function tab_TILT_HIDDEN() {
|
||||
tabEvents += "th;";
|
||||
}
|
||||
|
||||
let testSteps = [
|
||||
function step0() {
|
||||
gBrowser.selectedTab = tab0;
|
||||
},
|
||||
function step1() {
|
||||
gBrowser.selectedTab = tab1;
|
||||
},
|
||||
function step2() {
|
||||
Tilt.destroy(Tilt.currentWindowId);
|
||||
|
||||
Services.obs.removeObserver(tab_TILT_INITIALIZED, TILT_INITIALIZED, false);
|
||||
Services.obs.removeObserver(tab_TILT_DESTROYED, TILT_DESTROYED, false);
|
||||
Services.obs.removeObserver(tab_TILT_SHOWN, TILT_SHOWN, false);
|
||||
Services.obs.removeObserver(tab_TILT_HIDDEN, TILT_HIDDEN, false);
|
||||
gBrowser.removeCurrentTab();
|
||||
},
|
||||
function step3_cleanup() {
|
||||
is(tabEvents, "ti;th;ts;td;",
|
||||
"The notifications weren't fired in the correct order.");
|
||||
|
||||
tab0 = null;
|
||||
tab1 = null;
|
||||
|
||||
gBrowser.tabContainer.removeEventListener("TabSelect", tabSelect, false);
|
||||
finish();
|
||||
}
|
||||
];
|
||||
|
||||
function tabSelect() {
|
||||
if (testStep !== -1) {
|
||||
executeSoon(testSteps[testStep]);
|
||||
testStep++;
|
||||
}
|
||||
}
|
119
browser/devtools/tilt/test/browser_tilt_03_tab_switch.js
Normal file
119
browser/devtools/tilt/test/browser_tilt_03_tab_switch.js
Normal file
@ -0,0 +1,119 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, info, waitForExplicitFinish, finish, executeSoon, gBrowser */
|
||||
/*global isTiltEnabled, isWebGLSupported, createTab, createTilt, Tilt */
|
||||
"use strict";
|
||||
|
||||
let tab0, tab1, tab2;
|
||||
let testStep = -1;
|
||||
|
||||
function test() {
|
||||
if (!isTiltEnabled()) {
|
||||
info("Skipping tab switch test because Tilt isn't enabled.");
|
||||
return;
|
||||
}
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping tab switch test because WebGL isn't supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.tabContainer.addEventListener("TabSelect", tabSelect, false);
|
||||
createTab1();
|
||||
}
|
||||
|
||||
function createTab1() {
|
||||
tab0 = gBrowser.selectedTab;
|
||||
|
||||
tab1 = createTab(function() {
|
||||
createTilt({
|
||||
onInspectorOpen: function()
|
||||
{
|
||||
ok(Tilt.tiltButton.checked === false,
|
||||
"The toolbar tilt button shouldn't be pressed before Tilt is open.");
|
||||
},
|
||||
onTiltOpen: function()
|
||||
{
|
||||
createTab2();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function createTab2() {
|
||||
tab2 = createTab(function() {
|
||||
|
||||
createTilt({
|
||||
onInspectorOpen: function()
|
||||
{
|
||||
ok(Tilt.tiltButton.checked === false,
|
||||
"The toolbar tilt button shouldn't be pressed before Tilt is open.");
|
||||
},
|
||||
onTiltOpen: function()
|
||||
{
|
||||
testStep = 0;
|
||||
tabSelect();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let testSteps = [
|
||||
function step0() {
|
||||
ok(Tilt.tiltButton.checked === true,
|
||||
"The toolbar tilt button should have been pressed at step0 (tab 2).");
|
||||
|
||||
gBrowser.selectedTab = tab1;
|
||||
},
|
||||
function step1() {
|
||||
ok(Tilt.tiltButton.checked === true,
|
||||
"The toolbar tilt button should have been pressed at step1 (tab 1).");
|
||||
|
||||
gBrowser.selectedTab = tab0;
|
||||
},
|
||||
function step2() {
|
||||
ok(Tilt.tiltButton.checked === false,
|
||||
"The toolbar tilt button shouldn't have been pressed at step2 (tab 0).");
|
||||
|
||||
gBrowser.selectedTab = tab1;
|
||||
},
|
||||
function step3() {
|
||||
ok(Tilt.tiltButton.checked === true,
|
||||
"The toolbar tilt button should have been pressed at step3 (tab 1).");
|
||||
|
||||
gBrowser.selectedTab = tab2;
|
||||
},
|
||||
function step4() {
|
||||
ok(Tilt.tiltButton.checked === true,
|
||||
"The toolbar tilt button should have been pressed at step4 (tab 2).");
|
||||
|
||||
Tilt.destroy(Tilt.currentWindowId);
|
||||
gBrowser.removeCurrentTab();
|
||||
},
|
||||
function step5() {
|
||||
ok(Tilt.tiltButton.checked === true,
|
||||
"The toolbar tilt button should have been pressed at step5 (tab 1).");
|
||||
|
||||
Tilt.destroy(Tilt.currentWindowId);
|
||||
gBrowser.removeCurrentTab();
|
||||
},
|
||||
function step6_cleanup() {
|
||||
ok(Tilt.tiltButton.checked === false,
|
||||
"The toolbar tilt button shouldn't have been pressed at step6 (tab 0).");
|
||||
|
||||
tab1 = null;
|
||||
tab2 = null;
|
||||
|
||||
gBrowser.tabContainer.removeEventListener("TabSelect", tabSelect, false);
|
||||
finish();
|
||||
}
|
||||
];
|
||||
|
||||
function tabSelect() {
|
||||
if (testStep !== -1) {
|
||||
executeSoon(testSteps[testStep]);
|
||||
testStep++;
|
||||
}
|
||||
}
|
56
browser/devtools/tilt/test/browser_tilt_04_initialization.js
Normal file
56
browser/devtools/tilt/test/browser_tilt_04_initialization.js
Normal file
@ -0,0 +1,56 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, info, waitForExplicitFinish, finish, gBrowser */
|
||||
/*global isTiltEnabled, isWebGLSupported, createTab, createTilt */
|
||||
/*global Tilt, TiltUtils, TiltVisualizer */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
if (!isTiltEnabled()) {
|
||||
info("Skipping initialization test because Tilt isn't enabled.");
|
||||
return;
|
||||
}
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping initialization test because WebGL isn't supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
createTab(function() {
|
||||
let id = TiltUtils.getWindowId(gBrowser.selectedBrowser.contentWindow);
|
||||
|
||||
is(id, Tilt.currentWindowId,
|
||||
"The unique window identifiers should match for the same window.");
|
||||
|
||||
createTilt({
|
||||
onInspectorOpen: function() {
|
||||
is(Tilt.visualizers[id], null,
|
||||
"A instance of the visualizer shouldn't be initialized yet.");
|
||||
|
||||
is(typeof TiltVisualizer.Prefs.enabled, "boolean",
|
||||
"The 'enabled' pref should have been loaded by now.");
|
||||
is(typeof TiltVisualizer.Prefs.forceEnabled, "boolean",
|
||||
"The 'force-enabled' pref should have been loaded by now.");
|
||||
},
|
||||
onTiltOpen: function()
|
||||
{
|
||||
ok(Tilt.visualizers[id] instanceof TiltVisualizer,
|
||||
"A new instance of the visualizer wasn't created properly.");
|
||||
ok(Tilt.visualizers[id].isInitialized(),
|
||||
"The new instance of the visualizer wasn't initialized properly.");
|
||||
},
|
||||
onTiltClose: function()
|
||||
{
|
||||
is(Tilt.visualizers[id], null,
|
||||
"The current instance of the visualizer wasn't destroyed properly.");
|
||||
},
|
||||
onEnd: function()
|
||||
{
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
}
|
41
browser/devtools/tilt/test/browser_tilt_05_destruction.js
Normal file
41
browser/devtools/tilt/test/browser_tilt_05_destruction.js
Normal file
@ -0,0 +1,41 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, info, waitForExplicitFinish, finish, gBrowser */
|
||||
/*global isTiltEnabled, isWebGLSupported, createTab, createTilt */
|
||||
/*global Services, Tilt, TiltUtils, InspectorUI, TILT_DESTROYED */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
if (!isTiltEnabled()) {
|
||||
info("Skipping destruction test because Tilt isn't enabled.");
|
||||
return;
|
||||
}
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping destruction test because WebGL isn't supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
createTab(function() {
|
||||
createTilt({
|
||||
onTiltOpen: function()
|
||||
{
|
||||
Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
|
||||
InspectorUI.closeInspectorUI();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
let id = TiltUtils.getWindowId(gBrowser.selectedBrowser.contentWindow);
|
||||
|
||||
is(Tilt.visualizers[id], null,
|
||||
"The current instance of the visualizer wasn't destroyed properly.");
|
||||
|
||||
Services.obs.removeObserver(cleanup, TILT_DESTROYED);
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
333
browser/devtools/tilt/test/browser_tilt_arcball.js
Normal file
333
browser/devtools/tilt/test/browser_tilt_arcball.js
Normal file
@ -0,0 +1,333 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, isApproxVec, vec3, quat4, TiltVisualizer */
|
||||
"use strict";
|
||||
|
||||
function cloneUpdate(update) {
|
||||
return {
|
||||
rotation: quat4.create(update.rotation),
|
||||
translation: vec3.create(update.translation)
|
||||
};
|
||||
}
|
||||
|
||||
function isExpectedUpdate(update1, update2) {
|
||||
if (update1.length !== update2.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0, len = update1.length; i < len; i++) {
|
||||
if (!isApproxVec(update1[i].rotation, update2[i].rotation) ||
|
||||
!isApproxVec(update1[i].translation, update2[i].translation)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function test() {
|
||||
let arcball1 = new TiltVisualizer.Arcball(123, 456);
|
||||
|
||||
is(arcball1.width, 123,
|
||||
"The first arcball width wasn't set correctly.");
|
||||
is(arcball1.height, 456,
|
||||
"The first arcball height wasn't set correctly.");
|
||||
is(arcball1.radius, 123,
|
||||
"The first arcball radius wasn't implicitly set correctly.");
|
||||
|
||||
|
||||
let arcball2 = new TiltVisualizer.Arcball(987, 654);
|
||||
|
||||
is(arcball2.width, 987,
|
||||
"The second arcball width wasn't set correctly.");
|
||||
is(arcball2.height, 654,
|
||||
"The second arcball height wasn't set correctly.");
|
||||
is(arcball2.radius, 654,
|
||||
"The second arcball radius wasn't implicitly set correctly.");
|
||||
|
||||
|
||||
let arcball3 = new TiltVisualizer.Arcball(512, 512);
|
||||
|
||||
let sphereVec = vec3.create();
|
||||
arcball3.pointToSphere(123, 456, 256, 512, 512, sphereVec);
|
||||
|
||||
ok(isApproxVec(sphereVec, [-0.009765625, 0.390625, 0.9204980731010437]),
|
||||
"The pointToSphere() function didn't map the coordinates correctly.");
|
||||
|
||||
let stack1 = [];
|
||||
let expect1 = [
|
||||
{ rotation: [
|
||||
-0.054038457572460175, 0.015347825363278389,
|
||||
-0.02533721923828125, -0.9980993270874023],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.09048379212617874, 0.024709727615118027,
|
||||
-0.04307326674461365, -0.9946591854095459],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.11537143588066101, 0.03063894622027874,
|
||||
-0.05548851564526558, -0.9912980198860168],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.13250185549259186, 0.03449848294258118,
|
||||
-0.0641791820526123, -0.9885009527206421],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.14435507357120514, 0.037062086164951324,
|
||||
-0.07026264816522598, -0.9863321781158447],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.15258607268333435, 0.03879034146666527,
|
||||
-0.07452107220888138, -0.9847128391265869],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.1583157479763031, 0.03996811807155609,
|
||||
-0.07750196009874344, -0.9835304617881775],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.16231097280979156, 0.04077700152993202,
|
||||
-0.07958859205245972, -0.982679009437561],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.16510005295276642, 0.04133564606308937,
|
||||
-0.08104922622442245, -0.9820714592933655],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.16704875230789185, 0.04172303527593613,
|
||||
-0.08207167685031891, -0.9816405177116394],
|
||||
translation: [0, 0, 0] }];
|
||||
|
||||
arcball3.mouseDown(10, 10, 1);
|
||||
arcball3.mouseMove(10, 100);
|
||||
for (let i1 = 0; i1 < 10; i1++) {
|
||||
stack1.push(cloneUpdate(arcball3.update()));
|
||||
}
|
||||
|
||||
ok(isExpectedUpdate(stack1, expect1),
|
||||
"Mouse down & move events didn't create the expected transform. results.");
|
||||
|
||||
let stack2 = [];
|
||||
let expect2 = [
|
||||
{ rotation: [
|
||||
-0.1684110015630722, 0.04199237748980522,
|
||||
-0.0827873945236206, -0.9813361167907715],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.16936375200748444, 0.04218007251620293,
|
||||
-0.08328840136528015, -0.9811217188835144],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.17003019154071808, 0.04231100529432297,
|
||||
-0.08363909274339676, -0.9809709787368774],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.17049652338027954, 0.042402446269989014,
|
||||
-0.0838845893740654, -0.9808651208877563],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.17082282900810242, 0.042466338723897934,
|
||||
-0.08405643701553345, -0.9807908535003662],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.17105120420455933, 0.04251104220747948,
|
||||
-0.08417671173810959, -0.9807388186454773],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.17121103405952454, 0.04254228621721268,
|
||||
-0.08426092565059662, -0.9807023406028748],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.17132291197776794, 0.042564138770103455,
|
||||
-0.08431987464427948, -0.9806767106056213],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.1714012324810028, 0.04257945716381073,
|
||||
-0.08436112850904465, -0.9806588888168335],
|
||||
translation: [0, 0, 0] },
|
||||
{ rotation: [
|
||||
-0.17145603895187378, 0.042590171098709106,
|
||||
-0.08439001441001892, -0.9806463718414307],
|
||||
translation: [0, 0, 0] }];
|
||||
|
||||
arcball3.mouseUp(100, 100);
|
||||
for (let i2 = 0; i2 < 10; i2++) {
|
||||
stack2.push(cloneUpdate(arcball3.update()));
|
||||
}
|
||||
|
||||
ok(isExpectedUpdate(stack2, expect2),
|
||||
"Mouse up events didn't create the expected transformation results.");
|
||||
|
||||
let stack3 = [];
|
||||
let expect3 = [
|
||||
{ rotation: [
|
||||
-0.17149439454078674, 0.04259764403104782,
|
||||
-0.08441022783517838, -0.9806375503540039],
|
||||
translation: [0, 0, -1] },
|
||||
{ rotation: [
|
||||
-0.17152123153209686, 0.04260288551449776,
|
||||
-0.08442437648773193, -0.980631411075592],
|
||||
translation: [0, 0, -1.899999976158142] },
|
||||
{ rotation: [
|
||||
-0.1715400665998459, 0.04260658100247383,
|
||||
-0.08443428575992584, -0.9806271195411682],
|
||||
translation: [0, 0, -2.7100000381469727] },
|
||||
{ rotation: [
|
||||
-0.17155319452285767, 0.04260912910103798,
|
||||
-0.08444121479988098, -0.9806240797042847],
|
||||
translation: [0, 0, -3.439000129699707] },
|
||||
{ rotation: [
|
||||
-0.17156240344047546, 0.042610932141542435,
|
||||
-0.08444607257843018, -0.9806219935417175],
|
||||
translation: [0, 0, -4.095099925994873] },
|
||||
{ rotation: [
|
||||
-0.1715688556432724, 0.042612191289663315,
|
||||
-0.08444946259260178, -0.9806205034255981],
|
||||
translation: [0, 0, -4.685589790344238] },
|
||||
{ rotation: [
|
||||
-0.17157337069511414, 0.04261308163404465,
|
||||
-0.0844518393278122, -0.980619490146637],
|
||||
translation: [0, 0, -5.217031002044678] },
|
||||
{ rotation: [
|
||||
-0.17157652974128723, 0.0426136814057827,
|
||||
-0.0844535157084465, -0.9806187748908997],
|
||||
translation: [0, 0, -5.6953277587890625] },
|
||||
{ rotation: [
|
||||
-0.17157875001430511, 0.04261413961648941,
|
||||
-0.08445467799901962, -0.9806182980537415],
|
||||
translation: [0, 0, -6.125794887542725] },
|
||||
{ rotation: [
|
||||
-0.17158031463623047, 0.04261442646384239,
|
||||
-0.08445550501346588, -0.980617880821228],
|
||||
translation: [0, 0, -6.5132155418396] }];
|
||||
|
||||
arcball3.mouseScroll(10);
|
||||
for (let i3 = 0; i3 < 10; i3++) {
|
||||
stack3.push(cloneUpdate(arcball3.update()));
|
||||
}
|
||||
|
||||
ok(isExpectedUpdate(stack3, expect3),
|
||||
"Mouse scroll events didn't create the expected transformation results.");
|
||||
|
||||
let stack4 = [];
|
||||
let expect4 = [
|
||||
{ rotation: [
|
||||
-0.17158135771751404, 0.04261462762951851,
|
||||
-0.08445606380701065, -0.9806176424026489],
|
||||
translation: [0, 0, -6.861894130706787] },
|
||||
{ rotation: [
|
||||
-0.1715821474790573, 0.04261479899287224,
|
||||
-0.08445646613836288, -0.9806175231933594],
|
||||
translation: [0, 0, -7.1757049560546875] },
|
||||
{ rotation: [
|
||||
-0.1715826541185379, 0.0426148846745491,
|
||||
-0.08445674180984497, -0.980617344379425],
|
||||
translation: [0, 0, -7.458134651184082] },
|
||||
{ rotation: [
|
||||
-0.17158304154872894, 0.04261497035622597,
|
||||
-0.08445693552494049, -0.9806172847747803],
|
||||
translation: [0, 0, -7.7123212814331055] },
|
||||
{ rotation: [
|
||||
-0.17158329486846924, 0.042615000158548355,
|
||||
-0.08445708453655243, -0.9806172251701355],
|
||||
translation: [0, 0, -7.941089153289795] },
|
||||
{ rotation: [
|
||||
-0.17158347368240356, 0.04261505603790283,
|
||||
-0.084457166492939, -0.9806172251701355],
|
||||
translation: [0, 0, -8.146980285644531] },
|
||||
{ rotation: [
|
||||
-0.1715836226940155, 0.04261508584022522,
|
||||
-0.08445724099874496, -0.9806171655654907],
|
||||
translation: [0, 0, -8.332282066345215] },
|
||||
{ rotation: [
|
||||
-0.17158368229866028, 0.04261508584022522,
|
||||
-0.08445728570222855, -0.980617105960846],
|
||||
translation: [0, 0, -8.499053955078125] },
|
||||
{ rotation: [
|
||||
-0.17158377170562744, 0.04261511191725731,
|
||||
-0.08445732295513153, -0.980617105960846],
|
||||
translation: [0, 0, -8.649148941040039] },
|
||||
{ rotation: [
|
||||
-0.17158380150794983, 0.04261511191725731,
|
||||
-0.08445733785629272, -0.980617105960846],
|
||||
translation: [0, 0, -8.784234046936035] }];
|
||||
|
||||
arcball3.keyDown(65);
|
||||
arcball3.keyDown(68);
|
||||
arcball3.keyDown(87);
|
||||
arcball3.keyDown(83);
|
||||
arcball3.keyDown(37);
|
||||
arcball3.keyDown(39);
|
||||
arcball3.keyDown(38);
|
||||
arcball3.keyDown(40);
|
||||
for (let i4 = 0; i4 < 10; i4++) {
|
||||
stack4.push(cloneUpdate(arcball3.update()));
|
||||
}
|
||||
|
||||
ok(isExpectedUpdate(stack4, expect4),
|
||||
"Key down events didn't create the expected transformation results.");
|
||||
|
||||
let stack5 = [];
|
||||
let expect5 = [
|
||||
{ rotation: [
|
||||
-0.1715838462114334, 0.04261511191725731,
|
||||
-0.08445736765861511, -0.980617105960846],
|
||||
translation: [0, 0, -8.905810356140137] },
|
||||
{ rotation: [
|
||||
-0.1715838462114334, 0.04261511191725731,
|
||||
-0.08445736765861511, -0.980617105960846],
|
||||
translation: [0, 0, -9.015229225158691] },
|
||||
{ rotation: [
|
||||
-0.1715838462114334, 0.04261511191725731,
|
||||
-0.08445736765861511, -0.980617105960846],
|
||||
translation: [0, 0, -9.113706588745117] },
|
||||
{ rotation: [
|
||||
-0.1715838611125946, 0.04261511191725731,
|
||||
-0.0844573825597763, -0.9806170463562012],
|
||||
translation: [0, 0, -9.202336311340332] },
|
||||
{ rotation: [
|
||||
-0.17158392071723938, 0.0426151417195797,
|
||||
-0.0844573974609375, -0.980617105960846],
|
||||
translation: [0, 0, -9.282102584838867] },
|
||||
{ rotation: [
|
||||
-0.17158392071723938, 0.0426151417195797,
|
||||
-0.0844573974609375, -0.980617105960846],
|
||||
translation: [0, 0, -9.35389232635498] },
|
||||
{ rotation: [
|
||||
-0.17158392071723938, 0.0426151417195797,
|
||||
-0.0844573974609375, -0.980617105960846],
|
||||
translation: [0, 0, -9.418502807617188] },
|
||||
{ rotation: [
|
||||
-0.17158392071723938, 0.0426151417195797,
|
||||
-0.0844573974609375, -0.980617105960846],
|
||||
translation: [0, 0, -9.476652145385742] },
|
||||
{ rotation: [
|
||||
-0.17158392071723938, 0.0426151417195797,
|
||||
-0.0844573974609375, -0.980617105960846],
|
||||
translation: [0, 0, -9.528986930847168] },
|
||||
{ rotation: [
|
||||
-0.17158392071723938, 0.0426151417195797,
|
||||
-0.0844573974609375, -0.980617105960846],
|
||||
translation: [0, 0, -9.576087951660156] }];
|
||||
|
||||
arcball3.keyUp(65);
|
||||
arcball3.keyUp(68);
|
||||
arcball3.keyUp(87);
|
||||
arcball3.keyUp(83);
|
||||
arcball3.keyUp(37);
|
||||
arcball3.keyUp(39);
|
||||
arcball3.keyUp(38);
|
||||
arcball3.keyUp(40);
|
||||
for (let i5 = 0; i5 < 10; i5++) {
|
||||
stack5.push(cloneUpdate(arcball3.update()));
|
||||
}
|
||||
|
||||
ok(isExpectedUpdate(stack5, expect5),
|
||||
"Key up events didn't create the expected transformation results.");
|
||||
|
||||
arcball3.resize(123, 456);
|
||||
is(arcball3.width, 123,
|
||||
"The arcball width wasn't updated correctly.");
|
||||
is(arcball3.height, 456,
|
||||
"The arcball height wasn't updated correctly.");
|
||||
is(arcball3.radius, 123,
|
||||
"The arcball radius wasn't implicitly updated correctly.");
|
||||
}
|
158
browser/devtools/tilt/test/browser_tilt_gl01.js
Normal file
158
browser/devtools/tilt/test/browser_tilt_gl01.js
Normal file
@ -0,0 +1,158 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, info, isApproxVec, isWebGLSupported, createCanvas, TiltGL */
|
||||
/*global WebGLRenderingContext, WebGLProgram */
|
||||
"use strict";
|
||||
|
||||
let isWebGLAvailable;
|
||||
|
||||
function onWebGLFail() {
|
||||
isWebGLAvailable = false;
|
||||
}
|
||||
|
||||
function onWebGLSuccess() {
|
||||
isWebGLAvailable = true;
|
||||
}
|
||||
|
||||
function test() {
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping tilt_gl01 because WebGL isn't supported on this hardware.");
|
||||
return;
|
||||
}
|
||||
|
||||
let canvas = createCanvas();
|
||||
|
||||
let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
|
||||
let gl = renderer.context;
|
||||
|
||||
if (!isWebGLAvailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ok(renderer,
|
||||
"The TiltGL.Renderer constructor should have initialized a new object.");
|
||||
|
||||
ok(gl instanceof WebGLRenderingContext,
|
||||
"The renderer context wasn't created correctly from the passed canvas.");
|
||||
|
||||
|
||||
let clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE),
|
||||
clearDepth = gl.getParameter(gl.DEPTH_CLEAR_VALUE);
|
||||
|
||||
is(clearColor[0], 0,
|
||||
"The default red clear color wasn't set correctly at initialization.");
|
||||
is(clearColor[1], 0,
|
||||
"The default green clear color wasn't set correctly at initialization.");
|
||||
is(clearColor[2], 0,
|
||||
"The default blue clear color wasn't set correctly at initialization.");
|
||||
is(clearColor[3], 0,
|
||||
"The default alpha clear color wasn't set correctly at initialization.");
|
||||
is(clearDepth, 1,
|
||||
"The default clear depth wasn't set correctly at initialization.");
|
||||
|
||||
is(renderer.width, canvas.width,
|
||||
"The renderer width wasn't set correctly from the passed canvas.");
|
||||
is(renderer.height, canvas.height,
|
||||
"The renderer height wasn't set correctly from the passed canvas.");
|
||||
|
||||
ok(renderer.mvMatrix,
|
||||
"The model view matrix wasn't initialized properly.");
|
||||
ok(renderer.projMatrix,
|
||||
"The model view matrix wasn't initialized properly.");
|
||||
|
||||
ok(isApproxVec(renderer._fillColor, [1, 1, 1, 1]),
|
||||
"The default fill color wasn't set correctly.");
|
||||
ok(isApproxVec(renderer._strokeColor, [0, 0, 0, 1]),
|
||||
"The default stroke color wasn't set correctly.");
|
||||
is(renderer._strokeWeightValue, 1,
|
||||
"The default stroke weight wasn't set correctly.");
|
||||
|
||||
ok(renderer._colorShader,
|
||||
"A default color shader should have been created.");
|
||||
|
||||
ok(typeof renderer.Program, "function",
|
||||
"At init, the renderer should have created a Program constructor.");
|
||||
ok(typeof renderer.VertexBuffer, "function",
|
||||
"At init, the renderer should have created a VertexBuffer constructor.");
|
||||
ok(typeof renderer.IndexBuffer, "function",
|
||||
"At init, the renderer should have created a IndexBuffer constructor.");
|
||||
ok(typeof renderer.Texture, "function",
|
||||
"At init, the renderer should have created a Texture constructor.");
|
||||
|
||||
renderer.depthTest(true);
|
||||
is(gl.getParameter(gl.DEPTH_TEST), true,
|
||||
"The depth test wasn't enabled when requested.");
|
||||
|
||||
renderer.depthTest(false);
|
||||
is(gl.getParameter(gl.DEPTH_TEST), false,
|
||||
"The depth test wasn't disabled when requested.");
|
||||
|
||||
renderer.stencilTest(true);
|
||||
is(gl.getParameter(gl.STENCIL_TEST), true,
|
||||
"The stencil test wasn't enabled when requested.");
|
||||
|
||||
renderer.stencilTest(false);
|
||||
is(gl.getParameter(gl.STENCIL_TEST), false,
|
||||
"The stencil test wasn't disabled when requested.");
|
||||
|
||||
renderer.cullFace("front");
|
||||
is(gl.getParameter(gl.CULL_FACE), true,
|
||||
"The cull face wasn't enabled when requested.");
|
||||
is(gl.getParameter(gl.CULL_FACE_MODE), gl.FRONT,
|
||||
"The cull face front mode wasn't set correctly.");
|
||||
|
||||
renderer.cullFace("back");
|
||||
is(gl.getParameter(gl.CULL_FACE), true,
|
||||
"The cull face wasn't enabled when requested.");
|
||||
is(gl.getParameter(gl.CULL_FACE_MODE), gl.BACK,
|
||||
"The cull face back mode wasn't set correctly.");
|
||||
|
||||
renderer.cullFace("both");
|
||||
is(gl.getParameter(gl.CULL_FACE), true,
|
||||
"The cull face wasn't enabled when requested.");
|
||||
is(gl.getParameter(gl.CULL_FACE_MODE), gl.FRONT_AND_BACK,
|
||||
"The cull face back mode wasn't set correctly.");
|
||||
|
||||
renderer.cullFace(false);
|
||||
is(gl.getParameter(gl.CULL_FACE), false,
|
||||
"The cull face wasn't disabled when requested.");
|
||||
|
||||
renderer.frontFace("cw");
|
||||
is(gl.getParameter(gl.FRONT_FACE), gl.CW,
|
||||
"The front face cw mode wasn't set correctly.");
|
||||
|
||||
renderer.frontFace("ccw");
|
||||
is(gl.getParameter(gl.FRONT_FACE), gl.CCW,
|
||||
"The front face ccw mode wasn't set correctly.");
|
||||
|
||||
renderer.blendMode("alpha");
|
||||
is(gl.getParameter(gl.BLEND), true,
|
||||
"The blend mode wasn't enabled when requested.");
|
||||
is(gl.getParameter(gl.BLEND_SRC_ALPHA), gl.SRC_ALPHA,
|
||||
"The soruce blend func wasn't set correctly.");
|
||||
is(gl.getParameter(gl.BLEND_DST_ALPHA), gl.ONE_MINUS_SRC_ALPHA,
|
||||
"The destination blend func wasn't set correctly.");
|
||||
|
||||
renderer.blendMode("add");
|
||||
is(gl.getParameter(gl.BLEND), true,
|
||||
"The blend mode wasn't enabled when requested.");
|
||||
is(gl.getParameter(gl.BLEND_SRC_ALPHA), gl.SRC_ALPHA,
|
||||
"The soruce blend func wasn't set correctly.");
|
||||
is(gl.getParameter(gl.BLEND_DST_ALPHA), gl.ONE,
|
||||
"The destination blend func wasn't set correctly.");
|
||||
|
||||
renderer.blendMode(false);
|
||||
is(gl.getParameter(gl.CULL_FACE), false,
|
||||
"The blend mode wasn't disabled when requested.");
|
||||
|
||||
|
||||
is(gl.getParameter(gl.CURRENT_PROGRAM), null,
|
||||
"No program should be initially set in the WebGL context.");
|
||||
|
||||
renderer.useColorShader(new renderer.VertexBuffer([1, 2, 3], 3));
|
||||
|
||||
ok(gl.getParameter(gl.CURRENT_PROGRAM) instanceof WebGLProgram,
|
||||
"The correct program hasn't been set in the WebGL context.");
|
||||
}
|
46
browser/devtools/tilt/test/browser_tilt_gl02.js
Normal file
46
browser/devtools/tilt/test/browser_tilt_gl02.js
Normal file
@ -0,0 +1,46 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, info, isApproxVec, isWebGLSupported, createCanvas, TiltGL */
|
||||
"use strict";
|
||||
|
||||
let isWebGLAvailable;
|
||||
|
||||
function onWebGLFail() {
|
||||
isWebGLAvailable = false;
|
||||
}
|
||||
|
||||
function onWebGLSuccess() {
|
||||
isWebGLAvailable = true;
|
||||
}
|
||||
|
||||
function test() {
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping tilt_gl02 because WebGL isn't supported on this hardware.");
|
||||
return;
|
||||
}
|
||||
|
||||
let canvas = createCanvas();
|
||||
|
||||
let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
|
||||
let gl = renderer.context;
|
||||
|
||||
if (!isWebGLAvailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
renderer.fill([1, 0, 0, 1]);
|
||||
ok(isApproxVec(renderer._fillColor, [1, 0, 0, 1]),
|
||||
"The fill color wasn't set correctly.");
|
||||
|
||||
renderer.stroke([0, 1, 0, 1]);
|
||||
ok(isApproxVec(renderer._strokeColor, [0, 1, 0, 1]),
|
||||
"The stroke color wasn't set correctly.");
|
||||
|
||||
renderer.strokeWeight(2);
|
||||
is(renderer._strokeWeightValue, 2,
|
||||
"The stroke weight wasn't set correctly.");
|
||||
is(gl.getParameter(gl.LINE_WIDTH), 2,
|
||||
"The stroke weight wasn't applied correctly.");
|
||||
}
|
69
browser/devtools/tilt/test/browser_tilt_gl03.js
Normal file
69
browser/devtools/tilt/test/browser_tilt_gl03.js
Normal file
@ -0,0 +1,69 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, info, isApproxVec, isWebGLSupported, createCanvas, TiltGL */
|
||||
"use strict";
|
||||
|
||||
let isWebGLAvailable;
|
||||
|
||||
function onWebGLFail() {
|
||||
isWebGLAvailable = false;
|
||||
}
|
||||
|
||||
function onWebGLSuccess() {
|
||||
isWebGLAvailable = true;
|
||||
}
|
||||
|
||||
function test() {
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping tilt_gl03 because WebGL isn't supported on this hardware.");
|
||||
return;
|
||||
}
|
||||
|
||||
let canvas = createCanvas();
|
||||
|
||||
let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
|
||||
let gl = renderer.context;
|
||||
|
||||
if (!isWebGLAvailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
renderer.defaults();
|
||||
is(gl.getParameter(gl.DEPTH_TEST), true,
|
||||
"The depth test wasn't set to the correct default value.");
|
||||
is(gl.getParameter(gl.STENCIL_TEST), false,
|
||||
"The stencil test wasn't set to the correct default value.");
|
||||
is(gl.getParameter(gl.CULL_FACE), false,
|
||||
"The cull face wasn't set to the correct default value.");
|
||||
is(gl.getParameter(gl.FRONT_FACE), gl.CCW,
|
||||
"The front face wasn't set to the correct default value.");
|
||||
is(gl.getParameter(gl.BLEND), true,
|
||||
"The blend mode wasn't set to the correct default value.");
|
||||
is(gl.getParameter(gl.BLEND_SRC_ALPHA), gl.SRC_ALPHA,
|
||||
"The soruce blend func wasn't set to the correct default value.");
|
||||
is(gl.getParameter(gl.BLEND_DST_ALPHA), gl.ONE_MINUS_SRC_ALPHA,
|
||||
"The destination blend func wasn't set to the correct default value.");
|
||||
|
||||
|
||||
ok(isApproxVec(renderer._fillColor, [1, 1, 1, 1]),
|
||||
"The fill color wasn't set to the correct default value.");
|
||||
ok(isApproxVec(renderer._strokeColor, [0, 0, 0, 1]),
|
||||
"The stroke color wasn't set to the correct default value.");
|
||||
is(renderer._strokeWeightValue, 1,
|
||||
"The stroke weight wasn't set to the correct default value.");
|
||||
is(gl.getParameter(gl.LINE_WIDTH), 1,
|
||||
"The stroke weight wasn't applied with the correct default value.");
|
||||
|
||||
|
||||
ok(isApproxVec(renderer.projMatrix, [
|
||||
1.2071068286895752, 0, 0, 0, 0, -2.4142136573791504, 0, 0, 0, 0,
|
||||
-1.0202020406723022, -1, -181.06602478027344, 181.06602478027344,
|
||||
148.14492797851562, 181.06602478027344
|
||||
]), "The default perspective projection matrix wasn't set correctly.");
|
||||
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
|
||||
]), "The default model view matrix wasn't set correctly.");
|
||||
}
|
116
browser/devtools/tilt/test/browser_tilt_gl04.js
Normal file
116
browser/devtools/tilt/test/browser_tilt_gl04.js
Normal file
@ -0,0 +1,116 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, info, isApproxVec, isWebGLSupported, createCanvas, TiltGL */
|
||||
"use strict";
|
||||
|
||||
let isWebGLAvailable;
|
||||
|
||||
function onWebGLFail() {
|
||||
isWebGLAvailable = false;
|
||||
}
|
||||
|
||||
function onWebGLSuccess() {
|
||||
isWebGLAvailable = true;
|
||||
}
|
||||
|
||||
function test() {
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping tilt_gl04 because WebGL isn't supported on this hardware.");
|
||||
return;
|
||||
}
|
||||
|
||||
let canvas = createCanvas();
|
||||
|
||||
let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
|
||||
let gl = renderer.context;
|
||||
|
||||
if (!isWebGLAvailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
renderer.perspective();
|
||||
ok(isApproxVec(renderer.projMatrix, [
|
||||
1.2071068286895752, 0, 0, 0, 0, -2.4142136573791504, 0, 0, 0, 0,
|
||||
-1.0202020406723022, -1, -181.06602478027344, 181.06602478027344,
|
||||
148.14492797851562, 181.06602478027344
|
||||
]), "The default perspective proj. matrix wasn't calculated correctly.");
|
||||
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
|
||||
]), "Changing the perpective matrix should reset the modelview by default.");
|
||||
|
||||
|
||||
renderer.ortho();
|
||||
ok(isApproxVec(renderer.projMatrix, [
|
||||
0.006666666828095913, 0, 0, 0, 0, -0.013333333656191826, 0, 0, 0, 0, -1,
|
||||
0, -1, 1, 0, 1
|
||||
]), "The default ortho proj. matrix wasn't calculated correctly.");
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
|
||||
]), "Changing the ortho matrix should reset the modelview by default.");
|
||||
|
||||
|
||||
renderer.projection(mat4.perspective(45, 1, 0.1, 100));
|
||||
ok(isApproxVec(renderer.projMatrix, [
|
||||
2.4142136573791504, 0, 0, 0, 0, 2.4142136573791504, 0, 0, 0, 0,
|
||||
-1.0020020008087158, -1, 0, 0, -0.20020020008087158, 0
|
||||
]), "A custom proj. matrix couldn't be set correctly.");
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
|
||||
]), "Setting a custom proj. matrix should reset the model view by default.");
|
||||
|
||||
|
||||
renderer.translate(1, 1, 1);
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1
|
||||
]), "The translation transformation wasn't applied correctly.");
|
||||
|
||||
renderer.rotate(0.5, 1, 1, 1);
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
0.9183883666992188, 0.317602276802063, -0.23599065840244293, 0,
|
||||
-0.23599065840244293, 0.9183883666992188, 0.317602276802063, 0,
|
||||
0.317602276802063, -0.23599065840244293, 0.9183883666992188, 0, 1, 1, 1, 1
|
||||
]), "The rotation transformation wasn't applied correctly.");
|
||||
|
||||
renderer.rotateX(0.5);
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
0.9183883666992188, 0.317602276802063, -0.23599065840244293, 0,
|
||||
-0.05483464524149895, 0.6928216814994812, 0.7190210819244385, 0,
|
||||
0.391862154006958, -0.6474001407623291, 0.6536949872970581, 0, 1, 1, 1, 1
|
||||
]), "The X rotation transformation wasn't applied correctly.");
|
||||
|
||||
renderer.rotateY(0.5);
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
0.6180928945541382, 0.5891023874282837, -0.5204993486404419, 0,
|
||||
-0.05483464524149895, 0.6928216814994812, 0.7190210819244385, 0,
|
||||
0.7841902375221252, -0.4158804416656494, 0.4605313837528229, 0, 1, 1, 1, 1
|
||||
]), "The Y rotation transformation wasn't applied correctly.");
|
||||
|
||||
renderer.rotateZ(0.5);
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
0.5161384344100952, 0.8491423726081848, -0.11206408590078354, 0,
|
||||
-0.3444514572620392, 0.3255774974822998, 0.8805410265922546, 0,
|
||||
0.7841902375221252, -0.4158804416656494, 0.4605313837528229, 0, 1, 1, 1, 1
|
||||
]), "The Z rotation transformation wasn't applied correctly.");
|
||||
|
||||
renderer.scale(2, 2, 2);
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
1.0322768688201904, 1.6982847452163696, -0.22412817180156708, 0,
|
||||
-0.6889029145240784, 0.6511549949645996, 1.7610820531845093, 0,
|
||||
1.5683804750442505, -0.8317608833312988, 0.9210627675056458, 0, 1, 1, 1, 1
|
||||
]), "The Z rotation transformation wasn't applied correctly.");
|
||||
|
||||
renderer.transform(mat4.create());
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
1.0322768688201904, 1.6982847452163696, -0.22412817180156708, 0,
|
||||
-0.6889029145240784, 0.6511549949645996, 1.7610820531845093, 0,
|
||||
1.5683804750442505, -0.8317608833312988, 0.9210627675056458, 0, 1, 1, 1, 1
|
||||
]), "The identity matrix transformation wasn't applied correctly.");
|
||||
|
||||
renderer.origin(1, 1, 1);
|
||||
ok(isApproxVec(renderer.mvMatrix, [
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
|
||||
]), "The origin wasn't reset to identity correctly.");
|
||||
}
|
42
browser/devtools/tilt/test/browser_tilt_gl05.js
Normal file
42
browser/devtools/tilt/test/browser_tilt_gl05.js
Normal file
@ -0,0 +1,42 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, info, isWebGLSupported, createCanvas, TiltGL */
|
||||
"use strict";
|
||||
|
||||
let isWebGLAvailable;
|
||||
|
||||
function onWebGLFail() {
|
||||
isWebGLAvailable = false;
|
||||
}
|
||||
|
||||
function onWebGLSuccess() {
|
||||
isWebGLAvailable = true;
|
||||
}
|
||||
|
||||
function test() {
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping tilt_gl05 because WebGL isn't supported on this hardware.");
|
||||
return;
|
||||
}
|
||||
|
||||
let canvas = createCanvas();
|
||||
|
||||
let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
|
||||
let gl = renderer.context;
|
||||
|
||||
if (!isWebGLAvailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let mesh = {
|
||||
vertices: new renderer.VertexBuffer([1, 2, 3], 3),
|
||||
indices: new renderer.IndexBuffer([1]),
|
||||
};
|
||||
|
||||
ok(mesh.vertices instanceof TiltGL.VertexBuffer,
|
||||
"The mesh vertices weren't saved at initialization.");
|
||||
ok(mesh.indices instanceof TiltGL.IndexBuffer,
|
||||
"The mesh indices weren't saved at initialization.");
|
||||
}
|
59
browser/devtools/tilt/test/browser_tilt_gl06.js
Normal file
59
browser/devtools/tilt/test/browser_tilt_gl06.js
Normal file
@ -0,0 +1,59 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, info, isWebGLSupported, createCanvas, TiltGL */
|
||||
"use strict";
|
||||
|
||||
let isWebGLAvailable;
|
||||
|
||||
function onWebGLFail() {
|
||||
isWebGLAvailable = false;
|
||||
}
|
||||
|
||||
function onWebGLSuccess() {
|
||||
isWebGLAvailable = true;
|
||||
}
|
||||
|
||||
function test() {
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping tilt_gl06 because WebGL isn't supported on this hardware.");
|
||||
return;
|
||||
}
|
||||
|
||||
let canvas = createCanvas();
|
||||
|
||||
let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
|
||||
let gl = renderer.context;
|
||||
|
||||
if (!isWebGLAvailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let vb = new renderer.VertexBuffer([1, 2, 3, 4, 5, 6], 3);
|
||||
|
||||
ok(vb instanceof TiltGL.VertexBuffer,
|
||||
"The vertex buffer object wasn't instantiated correctly.");
|
||||
ok(vb._ref,
|
||||
"The vertex buffer gl element wasn't created at initialization.");
|
||||
ok(vb.components,
|
||||
"The vertex buffer components weren't created at initialization.");
|
||||
is(vb.itemSize, 3,
|
||||
"The vertex buffer item size isn't set correctly.");
|
||||
is(vb.numItems, 2,
|
||||
"The vertex buffer number of items weren't calculated correctly.");
|
||||
|
||||
|
||||
let ib = new renderer.IndexBuffer([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
|
||||
ok(ib instanceof TiltGL.IndexBuffer,
|
||||
"The index buffer object wasn't instantiated correctly.");
|
||||
ok(ib._ref,
|
||||
"The index buffer gl element wasn't created at initialization.");
|
||||
ok(ib.components,
|
||||
"The index buffer components weren't created at initialization.");
|
||||
is(ib.itemSize, 1,
|
||||
"The index buffer item size isn't set correctly.");
|
||||
is(ib.numItems, 10,
|
||||
"The index buffer number of items weren't calculated correctly.");
|
||||
}
|
60
browser/devtools/tilt/test/browser_tilt_gl07.js
Normal file
60
browser/devtools/tilt/test/browser_tilt_gl07.js
Normal file
@ -0,0 +1,60 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, isnot, info, isWebGLSupported, createCanvas, TiltGL */
|
||||
"use strict";
|
||||
|
||||
let isWebGLAvailable;
|
||||
|
||||
function onWebGLFail() {
|
||||
isWebGLAvailable = false;
|
||||
}
|
||||
|
||||
function onWebGLSuccess() {
|
||||
isWebGLAvailable = true;
|
||||
}
|
||||
|
||||
function test() {
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping tilt_gl07 because WebGL isn't supported on this hardware.");
|
||||
return;
|
||||
}
|
||||
|
||||
let canvas = createCanvas();
|
||||
|
||||
let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
|
||||
let gl = renderer.context;
|
||||
|
||||
if (!isWebGLAvailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let p = new renderer.Program({
|
||||
vs: TiltGL.ColorShader.vs,
|
||||
fs: TiltGL.ColorShader.fs,
|
||||
attributes: ["vertexPosition"],
|
||||
uniforms: ["mvMatrix", "projMatrix", "fill"]
|
||||
});
|
||||
|
||||
ok(p instanceof TiltGL.Program,
|
||||
"The program object wasn't instantiated correctly.");
|
||||
|
||||
ok(p._ref,
|
||||
"The program WebGL object wasn't created properly.");
|
||||
isnot(p._id, -1,
|
||||
"The program id wasn't set properly.");
|
||||
ok(p._attributes,
|
||||
"The program attributes cache wasn't created properly.");
|
||||
ok(p._uniforms,
|
||||
"The program uniforms cache wasn't created properly.");
|
||||
|
||||
is(typeof p._attributes.vertexPosition, "number",
|
||||
"The vertexPosition attribute wasn't cached as it should.");
|
||||
is(typeof p._uniforms.mvMatrix, "object",
|
||||
"The mvMatrix uniform wasn't cached as it should.");
|
||||
is(typeof p._uniforms.projMatrix, "object",
|
||||
"The projMatrix uniform wasn't cached as it should.");
|
||||
is(typeof p._uniforms.fill, "object",
|
||||
"The fill uniform wasn't cached as it should.");
|
||||
}
|
51
browser/devtools/tilt/test/browser_tilt_gl08.js
Normal file
51
browser/devtools/tilt/test/browser_tilt_gl08.js
Normal file
@ -0,0 +1,51 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, isnot, info, isWebGLSupported, createCanvas, TiltGL */
|
||||
"use strict";
|
||||
|
||||
let isWebGLAvailable;
|
||||
|
||||
function onWebGLFail() {
|
||||
isWebGLAvailable = false;
|
||||
}
|
||||
|
||||
function onWebGLSuccess() {
|
||||
isWebGLAvailable = true;
|
||||
}
|
||||
|
||||
function test() {
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping tilt_gl08 because WebGL isn't supported on this hardware.");
|
||||
return;
|
||||
}
|
||||
|
||||
let canvas = createCanvas();
|
||||
|
||||
let renderer = new TiltGL.Renderer(canvas, onWebGLFail, onWebGLSuccess);
|
||||
let gl = renderer.context;
|
||||
|
||||
if (!isWebGLAvailable) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let t = new renderer.Texture({
|
||||
source: canvas,
|
||||
format: "RGB"
|
||||
});
|
||||
|
||||
ok(t instanceof TiltGL.Texture,
|
||||
"The texture object wasn't instantiated correctly.");
|
||||
|
||||
ok(t._ref,
|
||||
"The texture WebGL object wasn't created properly.");
|
||||
isnot(t._id, -1,
|
||||
"The texture id wasn't set properly.");
|
||||
isnot(t.width, -1,
|
||||
"The texture width wasn't set properly.");
|
||||
isnot(t.height, -1,
|
||||
"The texture height wasn't set properly.");
|
||||
ok(t.loaded,
|
||||
"The texture loaded flag wasn't set to true as it should.");
|
||||
}
|
61
browser/devtools/tilt/test/browser_tilt_math01.js
Normal file
61
browser/devtools/tilt/test/browser_tilt_math01.js
Normal file
@ -0,0 +1,61 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, isApprox, isApproxVec, TiltMath */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
ok(isApprox(TiltMath.radians(30), 0.523598775),
|
||||
"The radians() function didn't calculate the value correctly.");
|
||||
|
||||
ok(isApprox(TiltMath.degrees(0.5), 28.64788975),
|
||||
"The degrees() function didn't calculate the value correctly.");
|
||||
|
||||
ok(isApprox(TiltMath.map(0.5, 0, 1, 0, 100), 50),
|
||||
"The map() function didn't calculate the value correctly.");
|
||||
|
||||
is(TiltMath.isPowerOfTwo(32), true,
|
||||
"The isPowerOfTwo() function didn't return the expected value.");
|
||||
|
||||
is(TiltMath.isPowerOfTwo(33), false,
|
||||
"The isPowerOfTwo() function didn't return the expected value.");
|
||||
|
||||
ok(isApprox(TiltMath.nextPowerOfTwo(31), 32),
|
||||
"The nextPowerOfTwo() function didn't calculate the 1st value correctly.");
|
||||
|
||||
ok(isApprox(TiltMath.nextPowerOfTwo(32), 32),
|
||||
"The nextPowerOfTwo() function didn't calculate the 2nd value correctly.");
|
||||
|
||||
ok(isApprox(TiltMath.nextPowerOfTwo(33), 64),
|
||||
"The nextPowerOfTwo() function didn't calculate the 3rd value correctly.");
|
||||
|
||||
ok(isApprox(TiltMath.clamp(5, 1, 3), 3),
|
||||
"The clamp() function didn't calculate the 1st value correctly.");
|
||||
|
||||
ok(isApprox(TiltMath.clamp(5, 3, 1), 3),
|
||||
"The clamp() function didn't calculate the 2nd value correctly.");
|
||||
|
||||
ok(isApprox(TiltMath.saturate(5), 1),
|
||||
"The saturate() function didn't calculate the 1st value correctly.");
|
||||
|
||||
ok(isApprox(TiltMath.saturate(-5), 0),
|
||||
"The saturate() function didn't calculate the 2nd value correctly.");
|
||||
|
||||
ok(isApproxVec(TiltMath.hex2rgba("#f00"), [1, 0, 0, 1]),
|
||||
"The hex2rgba() function didn't calculate the 1st rgba values correctly.");
|
||||
|
||||
ok(isApproxVec(TiltMath.hex2rgba("#f008"), [1, 0, 0, 0.53]),
|
||||
"The hex2rgba() function didn't calculate the 2nd rgba values correctly.");
|
||||
|
||||
ok(isApproxVec(TiltMath.hex2rgba("#ff0000"), [1, 0, 0, 1]),
|
||||
"The hex2rgba() function didn't calculate the 3rd rgba values correctly.");
|
||||
|
||||
ok(isApproxVec(TiltMath.hex2rgba("#ff0000aa"), [1, 0, 0, 0.66]),
|
||||
"The hex2rgba() function didn't calculate the 4th rgba values correctly.");
|
||||
|
||||
ok(isApproxVec(TiltMath.hex2rgba("rgba(255, 0, 0, 0.5)"), [1, 0, 0, 0.5]),
|
||||
"The hex2rgba() function didn't calculate the 5th rgba values correctly.");
|
||||
|
||||
ok(isApproxVec(TiltMath.hex2rgba("rgb(255, 0, 0)"), [1, 0, 0, 1]),
|
||||
"The hex2rgba() function didn't calculate the 6th rgba values correctly.");
|
||||
}
|
106
browser/devtools/tilt/test/browser_tilt_math02.js
Normal file
106
browser/devtools/tilt/test/browser_tilt_math02.js
Normal file
@ -0,0 +1,106 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, isApproxVec, vec3, mat4 */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let v1 = vec3.create();
|
||||
|
||||
ok(v1, "Should have created a vector with vec3.create().");
|
||||
is(v1.length, 3, "A vec3 should have 3 elements.");
|
||||
|
||||
ok(isApproxVec(v1, [0, 0, 0]),
|
||||
"When created, a vec3 should have the values default to 0.");
|
||||
|
||||
vec3.set([1, 2, 3], v1);
|
||||
ok(isApproxVec(v1, [1, 2, 3]),
|
||||
"The vec3.set() function didn't set the values correctly.");
|
||||
|
||||
vec3.zero(v1);
|
||||
ok(isApproxVec(v1, [0, 0, 0]),
|
||||
"The vec3.zero() function didn't set the values correctly.");
|
||||
|
||||
let v2 = vec3.create([4, 5, 6]);
|
||||
ok(isApproxVec(v2, [4, 5, 6]),
|
||||
"When cloning arrays, a vec3 should have the values copied.");
|
||||
|
||||
let v3 = vec3.create(v2);
|
||||
ok(isApproxVec(v3, [4, 5, 6]),
|
||||
"When cloning vectors, a vec3 should have the values copied.");
|
||||
|
||||
vec3.add(v2, v3);
|
||||
ok(isApproxVec(v2, [8, 10, 12]),
|
||||
"The vec3.add() function didn't set the x value correctly.");
|
||||
|
||||
vec3.subtract(v2, v3);
|
||||
ok(isApproxVec(v2, [4, 5, 6]),
|
||||
"The vec3.subtract() function didn't set the values correctly.");
|
||||
|
||||
vec3.negate(v2);
|
||||
ok(isApproxVec(v2, [-4, -5, -6]),
|
||||
"The vec3.negate() function didn't set the values correctly.");
|
||||
|
||||
vec3.scale(v2, -2);
|
||||
ok(isApproxVec(v2, [8, 10, 12]),
|
||||
"The vec3.scale() function didn't set the values correctly.");
|
||||
|
||||
vec3.normalize(v1);
|
||||
ok(isApproxVec(v1, [0, 0, 0]),
|
||||
"Normalizing a vector with zero length should return [0, 0, 0].");
|
||||
|
||||
vec3.normalize(v2);
|
||||
ok(isApproxVec(v2, [
|
||||
0.4558423161506653, 0.5698028802871704, 0.6837634444236755
|
||||
]), "The vec3.normalize() function didn't set the values correctly.");
|
||||
|
||||
vec3.cross(v2, v3);
|
||||
ok(isApproxVec(v2, [
|
||||
5.960464477539063e-8, -1.1920928955078125e-7, 5.960464477539063e-8
|
||||
]), "The vec3.cross() function didn't set the values correctly.");
|
||||
|
||||
vec3.dot(v2, v3);
|
||||
ok(isApproxVec(v2, [
|
||||
5.960464477539063e-8, -1.1920928955078125e-7, 5.960464477539063e-8
|
||||
]), "The vec3.dot() function didn't set the values correctly.");
|
||||
|
||||
ok(isApproxVec([vec3.length(v2)], [1.4600096599955427e-7]),
|
||||
"The vec3.length() function didn't calculate the value correctly.");
|
||||
|
||||
vec3.direction(v2, v3);
|
||||
ok(isApproxVec(v2, [
|
||||
-0.4558422863483429, -0.5698028802871704, -0.6837634444236755
|
||||
]), "The vec3.direction() function didn't set the values correctly.");
|
||||
|
||||
vec3.lerp(v2, v3, 0.5);
|
||||
ok(isApproxVec(v2, [
|
||||
1.7720788717269897, 2.2150986194610596, 2.65811824798584
|
||||
]), "The vec3.lerp() function didn't set the values correctly.");
|
||||
|
||||
|
||||
vec3.project([100, 100, 10], [0, 0, 100, 100],
|
||||
mat4.create(), mat4.perspective(45, 1, 0.1, 100), v1);
|
||||
ok(isApproxVec(v1, [-1157.10693359375, 1257.10693359375, 0]),
|
||||
"The vec3.project() function didn't set the values correctly.");
|
||||
|
||||
vec3.unproject([100, 100, 1], [0, 0, 100, 100],
|
||||
mat4.create(), mat4.perspective(45, 1, 0.1, 100), v1);
|
||||
ok(isApproxVec(v1, [
|
||||
41.420406341552734, -41.420406341552734, -99.99771118164062
|
||||
]), "The vec3.project() function didn't set the values correctly.");
|
||||
|
||||
|
||||
let ray = vec3.createRay([10, 10, 0], [100, 100, 1], [0, 0, 100, 100],
|
||||
mat4.create(), mat4.perspective(45, 1, 0.1, 100));
|
||||
|
||||
ok(isApproxVec(ray.origin, [
|
||||
-0.03313708305358887, 0.03313708305358887, -0.1000000014901161
|
||||
]), "The vec3.createRay() function didn't create the position correctly.");
|
||||
ok(isApproxVec(ray.direction, [
|
||||
0.35788586614428364, -0.35788586614428364, -0.862458934459091
|
||||
]), "The vec3.createRay() function didn't create the direction correctly.");
|
||||
|
||||
|
||||
is(vec3.str([0, 0, 0]), "[0, 0, 0]",
|
||||
"The vec3.str() function didn't work properly.");
|
||||
}
|
35
browser/devtools/tilt/test/browser_tilt_math03.js
Normal file
35
browser/devtools/tilt/test/browser_tilt_math03.js
Normal file
@ -0,0 +1,35 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, isApproxVec, mat3 */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let m1 = mat3.create();
|
||||
|
||||
ok(m1, "Should have created a matrix with mat3.create().");
|
||||
is(m1.length, 9, "A mat3 should have 9 elements.");
|
||||
|
||||
ok(isApproxVec(m1, [1, 0, 0, 0, 1, 0, 0, 0, 1]),
|
||||
"When created, a mat3 should have the values default to identity.");
|
||||
|
||||
mat3.set([1, 2, 3, 4, 5, 6, 7, 8, 9], m1);
|
||||
ok(isApproxVec(m1, [1, 2, 3, 4, 5, 6, 7, 8, 9]),
|
||||
"The mat3.set() function didn't set the values correctly.");
|
||||
|
||||
mat3.transpose(m1);
|
||||
ok(isApproxVec(m1, [1, 4, 7, 2, 5, 8, 3, 6, 9]),
|
||||
"The mat3.transpose() function didn't set the values correctly.");
|
||||
|
||||
mat3.identity(m1);
|
||||
ok(isApproxVec(m1, [1, 0, 0, 0, 1, 0, 0, 0, 1]),
|
||||
"The mat3.identity() function didn't set the values correctly.");
|
||||
|
||||
let m2 = mat3.toMat4(m1);
|
||||
ok(isApproxVec(m2, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
|
||||
"The mat3.toMat4() function didn't set the values correctly.");
|
||||
|
||||
|
||||
is(mat3.str([1, 2, 3, 4, 5, 6, 7, 8, 9]), "[1, 2, 3, 4, 5, 6, 7, 8, 9]",
|
||||
"The mat3.str() function didn't work properly.");
|
||||
}
|
51
browser/devtools/tilt/test/browser_tilt_math04.js
Normal file
51
browser/devtools/tilt/test/browser_tilt_math04.js
Normal file
@ -0,0 +1,51 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, isApprox, isApproxVec, mat4 */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let m1 = mat4.create();
|
||||
|
||||
ok(m1, "Should have created a matrix with mat4.create().");
|
||||
is(m1.length, 16, "A mat4 should have 16 elements.");
|
||||
|
||||
ok(isApproxVec(m1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
|
||||
"When created, a mat4 should have the values default to identity.");
|
||||
|
||||
mat4.set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], m1);
|
||||
ok(isApproxVec(m1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
|
||||
"The mat4.set() function didn't set the values correctly.");
|
||||
|
||||
mat4.transpose(m1);
|
||||
ok(isApproxVec(m1, [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]),
|
||||
"The mat4.transpose() function didn't set the values correctly.");
|
||||
|
||||
mat4.identity(m1);
|
||||
ok(isApproxVec(m1, [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]),
|
||||
"The mat4.identity() function didn't set the values correctly.");
|
||||
|
||||
ok(isApprox(mat4.determinant(m1), 1),
|
||||
"The mat4.determinant() function didn't calculate the value correctly.");
|
||||
|
||||
let m2 = mat4.inverse([1, 3, 1, 1, 1, 1, 2, 1, 2, 3, 4, 1, 1, 1, 1, 1]);
|
||||
ok(isApproxVec(m2, [
|
||||
-1, -3, 1, 3, 0.5, 0, 0, -0.5, 0, 1, 0, -1, 0.5, 2, -1, -0.5
|
||||
]), "The mat4.inverse() function didn't calculate the values correctly.");
|
||||
|
||||
let m3 = mat4.toRotationMat([
|
||||
1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]);
|
||||
ok(isApproxVec(m3, [
|
||||
1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 0, 0, 0, 1
|
||||
]), "The mat4.toRotationMat() func. didn't calculate the values correctly.");
|
||||
|
||||
let m4 = mat4.toMat3([
|
||||
1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]);
|
||||
ok(isApproxVec(m4, [1, 5, 9, 2, 6, 10, 3, 7, 11]),
|
||||
"The mat4.toMat3() function didn't set the values correctly.");
|
||||
|
||||
let m5 = mat4.toInverseMat3([
|
||||
1, 3, 1, 1, 1, 1, 2, 1, 2, 3, 4, 1, 1, 1, 1, 1]);
|
||||
ok(isApproxVec(m5, [2, 9, -5, 0, -2, 1, -1, -3, 2]),
|
||||
"The mat4.toInverseMat3() function didn't set the values correctly.");
|
||||
}
|
103
browser/devtools/tilt/test/browser_tilt_math05.js
Normal file
103
browser/devtools/tilt/test/browser_tilt_math05.js
Normal file
@ -0,0 +1,103 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, isApproxVec, mat4 */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let m1 = mat4.create([
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
|
||||
|
||||
let m2 = mat4.create([
|
||||
0, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]);
|
||||
|
||||
mat4.multiply(m1, m2);
|
||||
ok(isApproxVec(m1, [
|
||||
275, 302, 329, 356, 304, 336, 368, 400,
|
||||
332, 368, 404, 440, 360, 400, 440, 480
|
||||
]), "The mat4.multiply() function didn't set the values correctly.");
|
||||
|
||||
let v1 = mat4.multiplyVec3(m1, [1, 2, 3]);
|
||||
ok(isApproxVec(v1, [2239, 2478, 2717]),
|
||||
"The mat4.multiplyVec3() function didn't set the values correctly.");
|
||||
|
||||
let v2 = mat4.multiplyVec4(m1, [1, 2, 3, 0]);
|
||||
ok(isApproxVec(v2, [1879, 2078, 2277, 2476]),
|
||||
"The mat4.multiplyVec4() function didn't set the values correctly.");
|
||||
|
||||
mat4.translate(m1, [1, 2, 3]);
|
||||
ok(isApproxVec(m1, [
|
||||
275, 302, 329, 356, 304, 336, 368, 400,
|
||||
332, 368, 404, 440, 2239, 2478, 2717, 2956
|
||||
]), "The mat4.translate() function didn't set the values correctly.");
|
||||
|
||||
mat4.scale(m1, [1, 2, 3]);
|
||||
ok(isApproxVec(m1, [
|
||||
275, 302, 329, 356, 608, 672, 736, 800,
|
||||
996, 1104, 1212, 1320, 2239, 2478, 2717, 2956
|
||||
]), "The mat4.scale() function didn't set the values correctly.");
|
||||
|
||||
mat4.rotate(m1, 0.5, [1, 1, 1]);
|
||||
ok(isApproxVec(m1, [
|
||||
210.6123046875, 230.2483367919922, 249.88438415527344, 269.5204162597656,
|
||||
809.8145751953125, 896.520751953125, 983.2268676757812,
|
||||
1069.9329833984375, 858.5731201171875, 951.23095703125,
|
||||
1043.8887939453125, 1136.5465087890625, 2239, 2478, 2717, 2956
|
||||
]), "The mat4.rotate() function didn't set the values correctly.");
|
||||
|
||||
mat4.rotateX(m1, 0.5);
|
||||
ok(isApproxVec(m1, [
|
||||
210.6123046875, 230.2483367919922, 249.88438415527344, 269.5204162597656,
|
||||
1122.301025390625, 1242.8154296875, 1363.3297119140625,
|
||||
1483.843994140625, 365.2230224609375, 404.96875, 444.71453857421875,
|
||||
484.460205078125, 2239, 2478, 2717, 2956
|
||||
]), "The mat4.rotateX() function didn't set the values correctly.");
|
||||
|
||||
mat4.rotateY(m1, 0.5);
|
||||
ok(isApproxVec(m1, [
|
||||
9.732441902160645, 7.909564018249512, 6.086670875549316,
|
||||
4.263822555541992, 1122.301025390625, 1242.8154296875, 1363.3297119140625,
|
||||
1483.843994140625, 421.48626708984375, 465.78045654296875,
|
||||
510.0746765136719, 554.3687744140625, 2239, 2478, 2717, 2956
|
||||
]), "The mat4.rotateY() function didn't set the values correctly.");
|
||||
|
||||
mat4.rotateZ(m1, 0.5);
|
||||
ok(isApproxVec(m1, [
|
||||
546.6007690429688, 602.7787475585938, 658.9566650390625, 715.1345825195312,
|
||||
980.245849609375, 1086.881103515625, 1193.5162353515625,
|
||||
1300.1514892578125, 421.48626708984375, 465.78045654296875,
|
||||
510.0746765136719, 554.3687744140625, 2239, 2478, 2717, 2956
|
||||
]), "The mat4.rotateZ() function didn't set the values correctly.");
|
||||
|
||||
|
||||
let m3 = mat4.frustum(0, 100, 200, 0, 0.1, 100);
|
||||
ok(isApproxVec(m3, [
|
||||
0.0020000000949949026, 0, 0, 0, 0, -0.0010000000474974513, 0, 0, 1, -1,
|
||||
-1.0020020008087158, -1, 0, 0, -0.20020020008087158, 0
|
||||
]), "The mat4.frustum() function didn't compute the values correctly.");
|
||||
|
||||
let m4 = mat4.perspective(45, 1.6, 0.1, 100);
|
||||
ok(isApproxVec(m4, [1.5088834762573242, 0, 0, 0, 0, 2.4142136573791504, 0,
|
||||
0, 0, 0, -1.0020020008087158, -1, 0, 0, -0.20020020008087158, 0
|
||||
]), "The mat4.frustum() function didn't compute the values correctly.");
|
||||
|
||||
let m5 = mat4.ortho(0, 100, 200, 0, -1, 1);
|
||||
ok(isApproxVec(m5, [
|
||||
0.019999999552965164, 0, 0, 0, 0, -0.009999999776482582, 0, 0,
|
||||
0, 0, -1, 0, -1, 1, 0, 1
|
||||
]), "The mat4.ortho() function didn't compute the values correctly.");
|
||||
|
||||
let m6 = mat4.lookAt([1, 2, 3], [4, 5, 6], [0, 1, 0]);
|
||||
ok(isApproxVec(m6, [
|
||||
-0.7071067690849304, -0.40824830532073975, -0.5773502588272095, 0, 0,
|
||||
0.8164966106414795, -0.5773502588272095, 0, 0.7071067690849304,
|
||||
-0.40824830532073975, -0.5773502588272095, 0, -1.4142135381698608, 0,
|
||||
3.464101552963257, 1
|
||||
]), "The mat4.lookAt() function didn't compute the values correctly.");
|
||||
|
||||
|
||||
is(mat4.str([
|
||||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
|
||||
"[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]",
|
||||
"The mat4.str() function didn't work properly.");
|
||||
}
|
44
browser/devtools/tilt/test/browser_tilt_math06.js
Normal file
44
browser/devtools/tilt/test/browser_tilt_math06.js
Normal file
@ -0,0 +1,44 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, isApprox, isApproxVec, quat4 */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let q1 = quat4.create();
|
||||
|
||||
ok(q1, "Should have created a quaternion with quat4.create().");
|
||||
is(q1.length, 4, "A quat4 should have 4 elements.");
|
||||
|
||||
ok(isApproxVec(q1, [0, 0, 0, 1]),
|
||||
"When created, a vec3 should have the values default to identity.");
|
||||
|
||||
quat4.set([1, 2, 3, 4], q1);
|
||||
ok(isApproxVec(q1, [1, 2, 3, 4]),
|
||||
"The quat4.set() function didn't set the values correctly.");
|
||||
|
||||
quat4.identity(q1);
|
||||
ok(isApproxVec(q1, [0, 0, 0, 1]),
|
||||
"The quat4.identity() function didn't set the values correctly.");
|
||||
|
||||
quat4.set([5, 6, 7, 8], q1);
|
||||
ok(isApproxVec(q1, [5, 6, 7, 8]),
|
||||
"The quat4.set() function didn't set the values correctly.");
|
||||
|
||||
quat4.calculateW(q1);
|
||||
ok(isApproxVec(q1, [5, 6, 7, -10.440306663513184]),
|
||||
"The quat4.calculateW() function didn't compute the values correctly.");
|
||||
|
||||
quat4.inverse(q1);
|
||||
ok(isApproxVec(q1, [-5, -6, -7, -10.440306663513184]),
|
||||
"The quat4.inverse() function didn't compute the values correctly.");
|
||||
|
||||
quat4.normalize(q1);
|
||||
ok(isApproxVec(q1, [
|
||||
-0.33786869049072266, -0.40544241666793823,
|
||||
-0.4730161726474762, -0.7054905295372009
|
||||
]), "The quat4.normalize() function didn't compute the values correctly.");
|
||||
|
||||
ok(isApprox(quat4.length(q1), 1),
|
||||
"The mat4.length() function didn't calculate the value correctly.");
|
||||
}
|
51
browser/devtools/tilt/test/browser_tilt_math07.js
Normal file
51
browser/devtools/tilt/test/browser_tilt_math07.js
Normal file
@ -0,0 +1,51 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, isApproxVec, quat4 */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let q1 = quat4.create([1, 2, 3, 4]);
|
||||
let q2 = quat4.create([5, 6, 7, 8]);
|
||||
|
||||
quat4.multiply(q1, q2);
|
||||
ok(isApproxVec(q1, [24, 48, 48, -6]),
|
||||
"The quat4.multiply() function didn't set the values correctly.");
|
||||
|
||||
let v1 = quat4.multiplyVec3(q1, [9, 9, 9]);
|
||||
ok(isApproxVec(v1, [5508, 54756, 59940]),
|
||||
"The quat4.multiplyVec3() function didn't set the values correctly.");
|
||||
|
||||
let m1 = quat4.toMat3(q1);
|
||||
ok(isApproxVec(m1, [
|
||||
-9215, 2880, 1728, 1728, -5759, 4896, 2880, 4320, -5759
|
||||
]), "The quat4.toMat3() function didn't set the values correctly.");
|
||||
|
||||
let m2 = quat4.toMat4(q1);
|
||||
ok(isApproxVec(m2, [
|
||||
-9215, 2880, 1728, 0, 1728, -5759, 4896, 0,
|
||||
2880, 4320, -5759, 0, 0, 0, 0, 1
|
||||
]), "The quat4.toMat4() function didn't set the values correctly.");
|
||||
|
||||
quat4.calculateW(q1);
|
||||
quat4.calculateW(q2);
|
||||
quat4.slerp(q1, q2, 0.5);
|
||||
ok(isApproxVec(q1, [24, 48, 48, -71.99305725097656]),
|
||||
"The quat4.slerp() function didn't set the values correctly.");
|
||||
|
||||
let q3 = quat4.fromAxis([1, 1, 1], 0.5);
|
||||
ok(isApproxVec(q3, [
|
||||
0.24740396440029144, 0.24740396440029144, 0.24740396440029144,
|
||||
0.9689124226570129
|
||||
]), "The quat4.fromAxis() function didn't compute the values correctly.");
|
||||
|
||||
let q4 = quat4.fromEuler(0.5, 0.75, 1.25);
|
||||
ok(isApproxVec(q4, [
|
||||
0.15310347080230713, 0.39433568716049194,
|
||||
0.4540249705314636, 0.7841683626174927
|
||||
]), "The quat4.fromEuler() function didn't compute the values correctly.");
|
||||
|
||||
|
||||
is(quat4.str([1, 2, 3, 4]), "[1, 2, 3, 4]",
|
||||
"The quat4.str() function didn't work properly.");
|
||||
}
|
71
browser/devtools/tilt/test/browser_tilt_utils01.js
Normal file
71
browser/devtools/tilt/test/browser_tilt_utils01.js
Normal file
@ -0,0 +1,71 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, TiltUtils */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let prefs = TiltUtils.Preferences;
|
||||
ok(prefs, "The TiltUtils.Preferences wasn't found.");
|
||||
|
||||
prefs.create("test-pref-bool", "boolean", true);
|
||||
prefs.create("test-pref-int", "integer", 42);
|
||||
prefs.create("test-pref-string", "string", "hello world!");
|
||||
|
||||
is(prefs.get("test-pref-bool", "boolean"), true,
|
||||
"The boolean test preference wasn't initially set correctly.");
|
||||
is(prefs.get("test-pref-int", "integer"), 42,
|
||||
"The integer test preference wasn't initially set correctly.");
|
||||
is(prefs.get("test-pref-string", "string"), "hello world!",
|
||||
"The string test preference wasn't initially set correctly.");
|
||||
|
||||
|
||||
prefs.set("test-pref-bool", "boolean", false);
|
||||
prefs.set("test-pref-int", "integer", 24);
|
||||
prefs.set("test-pref-string", "string", "!dlrow olleh");
|
||||
|
||||
is(prefs.get("test-pref-bool", "boolean"), false,
|
||||
"The boolean test preference wasn't changed correctly.");
|
||||
is(prefs.get("test-pref-int", "integer"), 24,
|
||||
"The integer test preference wasn't changed correctly.");
|
||||
is(prefs.get("test-pref-string", "string"), "!dlrow olleh",
|
||||
"The string test preference wasn't changed correctly.");
|
||||
|
||||
|
||||
is(typeof prefs.get("unknown-pref", "boolean"), "undefined",
|
||||
"Inexisted boolean prefs should be handled as undefined.");
|
||||
is(typeof prefs.get("unknown-pref", "integer"), "undefined",
|
||||
"Inexisted integer prefs should be handled as undefined.");
|
||||
is(typeof prefs.get("unknown-pref", "string"), "undefined",
|
||||
"Inexisted string prefs should be handled as undefined.");
|
||||
|
||||
|
||||
is(prefs.get("test-pref-bool", "integer"), null,
|
||||
"The get() boolean function didn't handle incorrect types as it should.");
|
||||
is(prefs.get("test-pref-bool", "string"), null,
|
||||
"The get() boolean function didn't handle incorrect types as it should.");
|
||||
is(prefs.get("test-pref-int", "boolean"), null,
|
||||
"The get() integer function didn't handle incorrect types as it should.");
|
||||
is(prefs.get("test-pref-int", "string"), null,
|
||||
"The get() integer function didn't handle incorrect types as it should.");
|
||||
is(prefs.get("test-pref-string", "boolean"), null,
|
||||
"The get() string function didn't handle incorrect types as it should.");
|
||||
is(prefs.get("test-pref-string", "integer"), null,
|
||||
"The get() string function didn't handle incorrect types as it should.");
|
||||
|
||||
|
||||
is(typeof prefs.get(), "undefined",
|
||||
"The get() function should not work if not enough params are passed.");
|
||||
is(typeof prefs.set(), "undefined",
|
||||
"The set() function should not work if not enough params are passed.");
|
||||
is(typeof prefs.create(), "undefined",
|
||||
"The create() function should not work if not enough params are passed.");
|
||||
|
||||
|
||||
is(prefs.get("test-pref-wrong-type", "wrong-type", 1), null,
|
||||
"The get() function should expect only correct pref types.");
|
||||
is(prefs.set("test-pref-wrong-type", "wrong-type", 1), false,
|
||||
"The set() function should expect only correct pref types.");
|
||||
is(prefs.create("test-pref-wrong-type", "wrong-type", 1), false,
|
||||
"The create() function should expect only correct pref types.");
|
||||
}
|
23
browser/devtools/tilt/test/browser_tilt_utils02.js
Normal file
23
browser/devtools/tilt/test/browser_tilt_utils02.js
Normal file
@ -0,0 +1,23 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, TiltUtils */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let l10 = TiltUtils.L10n;
|
||||
ok(l10, "The TiltUtils.L10n wasn't found.");
|
||||
|
||||
|
||||
ok(l10.stringBundle,
|
||||
"The necessary string bundle wasn't found.");
|
||||
is(l10.get(), null,
|
||||
"The get() function shouldn't work if no params are passed.");
|
||||
is(l10.format(), null,
|
||||
"The format() function shouldn't work if no params are passed.");
|
||||
|
||||
is(typeof l10.get("initWebGL.error"), "string",
|
||||
"No valid string was returned from a corect name in the bundle.");
|
||||
is(typeof l10.format("linkProgram.error", ["error"]), "string",
|
||||
"No valid formatted string was returned from a name in the bundle.");
|
||||
}
|
20
browser/devtools/tilt/test/browser_tilt_utils03.js
Normal file
20
browser/devtools/tilt/test/browser_tilt_utils03.js
Normal file
@ -0,0 +1,20 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, TiltUtils */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let dom = TiltUtils.DOM;
|
||||
|
||||
is(dom.parentNode, null,
|
||||
"The parent node should not be initially set.");
|
||||
|
||||
dom.parentNode = {};
|
||||
ok(dom.parentNode,
|
||||
"The parent node should now be set.");
|
||||
|
||||
TiltUtils.clearCache();
|
||||
is(dom.parentNode, null,
|
||||
"The parent node should not be set after clearing the cache.");
|
||||
}
|
56
browser/devtools/tilt/test/browser_tilt_utils04.js
Normal file
56
browser/devtools/tilt/test/browser_tilt_utils04.js
Normal file
@ -0,0 +1,56 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, gBrowser, TiltUtils */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
let dom = TiltUtils.DOM;
|
||||
ok(dom, "The TiltUtils.DOM wasn't found.");
|
||||
|
||||
|
||||
is(dom.initCanvas(), null,
|
||||
"The initCanvas() function shouldn't work if no parent node is set.");
|
||||
|
||||
|
||||
dom.parentNode = gBrowser.parentNode;
|
||||
ok(dom.parentNode,
|
||||
"The necessary parent node wasn't found.");
|
||||
|
||||
|
||||
let canvas = dom.initCanvas(null, {
|
||||
append: true,
|
||||
focusable: true,
|
||||
width: 123,
|
||||
height: 456,
|
||||
id: "tilt-test-canvas"
|
||||
});
|
||||
|
||||
is(canvas.width, 123,
|
||||
"The test canvas doesn't have the correct width set.");
|
||||
is(canvas.height, 456,
|
||||
"The test canvas doesn't have the correct height set.");
|
||||
is(canvas.getAttribute("tabindex"), 1,
|
||||
"The test canvas tab index wasn't set correctly.");
|
||||
is(canvas.getAttribute("id"), "tilt-test-canvas",
|
||||
"The test canvas doesn't have the correct id set.");
|
||||
ok(dom.parentNode.ownerDocument.getElementById(canvas.id),
|
||||
"A canvas should be appended to the parent node if specified.");
|
||||
canvas.parentNode.removeChild(canvas);
|
||||
|
||||
let canvas2 = dom.initCanvas(null, { id: "tilt-test-canvas2" });
|
||||
|
||||
is(canvas2.width, dom.parentNode.clientWidth,
|
||||
"The second test canvas doesn't have the implicit width set.");
|
||||
is(canvas2.height, dom.parentNode.clientHeight,
|
||||
"The second test canvas doesn't have the implicit height set.");
|
||||
is(canvas2.id, "tilt-test-canvas2",
|
||||
"The second test canvas doesn't have the correct id set.");
|
||||
is(dom.parentNode.ownerDocument.getElementById(canvas2.id), null,
|
||||
"A canvas shouldn't be appended to the parent node if not specified.");
|
||||
|
||||
|
||||
dom.parentNode = null;
|
||||
is(dom.parentNode, null,
|
||||
"The necessary parent node shouldn't be found anymore.");
|
||||
}
|
109
browser/devtools/tilt/test/browser_tilt_utils05.js
Normal file
109
browser/devtools/tilt/test/browser_tilt_utils05.js
Normal file
@ -0,0 +1,109 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, waitForExplicitFinish, finish, gBrowser, TiltUtils */
|
||||
"use strict";
|
||||
|
||||
function init(callback) {
|
||||
let iframe = gBrowser.ownerDocument.createElement("iframe");
|
||||
|
||||
iframe.addEventListener("load", function onLoad() {
|
||||
iframe.removeEventListener("load", onLoad, true);
|
||||
callback(iframe);
|
||||
|
||||
gBrowser.parentNode.removeChild(iframe);
|
||||
finish();
|
||||
}, true);
|
||||
|
||||
iframe.setAttribute("src", ["data:text/html,",
|
||||
"<!DOCTYPE html>",
|
||||
"<html>",
|
||||
"<head>",
|
||||
"<style>",
|
||||
"</style>",
|
||||
"<script>",
|
||||
"</script>",
|
||||
"</head>",
|
||||
"<body style='margin: 0;'>",
|
||||
"<div style='margin-top: 98px;" +
|
||||
"margin-left: 76px;" +
|
||||
"width: 123px;" +
|
||||
"height: 456px;' id='test-div'>",
|
||||
"<span></span>",
|
||||
"</div>",
|
||||
"</body>",
|
||||
"</html>"
|
||||
].join(""));
|
||||
|
||||
gBrowser.parentNode.appendChild(iframe);
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
ok(TiltUtils, "The TiltUtils object doesn't exist.");
|
||||
|
||||
let dom = TiltUtils.DOM;
|
||||
ok(dom, "The TiltUtils.DOM wasn't found.");
|
||||
|
||||
init(function(iframe) {
|
||||
let cwDimensions = dom.getContentWindowDimensions(iframe.contentWindow);
|
||||
|
||||
is(cwDimensions.width - iframe.contentWindow.scrollMaxX,
|
||||
iframe.contentWindow.innerWidth,
|
||||
"The content window width wasn't calculated correctly.");
|
||||
is(cwDimensions.height - iframe.contentWindow.scrollMaxY,
|
||||
iframe.contentWindow.innerHeight,
|
||||
"The content window height wasn't calculated correctly.");
|
||||
|
||||
|
||||
let nodeCoordinates = dom.getNodeCoordinates(
|
||||
iframe.contentDocument.getElementById("test-div"), iframe.contentWindow);
|
||||
|
||||
let frameOffset = dom.getFrameOffset(iframe);
|
||||
|
||||
is(nodeCoordinates.top, frameOffset.top + 98,
|
||||
"The node coordinates top value wasn't calculated correctly.");
|
||||
is(nodeCoordinates.left, frameOffset.left + 76,
|
||||
"The node coordinates left value wasn't calculated correctly.");
|
||||
is(nodeCoordinates.width, 123,
|
||||
"The node coordinates width value wasn't calculated correctly.");
|
||||
is(nodeCoordinates.height, 456,
|
||||
"The node coordinates height value wasn't calculated correctly.");
|
||||
|
||||
|
||||
let store = dom.traverse(iframe.contentWindow);
|
||||
|
||||
is(store.nodes.length, 7,
|
||||
"The traverse() function didn't walk the correct number of nodes.");
|
||||
is(store.info.length, 7,
|
||||
"The traverse() function didn't examine the correct number of nodes.");
|
||||
is(store.info[0].name, "html",
|
||||
"the 1st traversed node isn't the expected one.");
|
||||
is(store.info[0].depth, 0,
|
||||
"the 1st traversed node doesn't have the expected depth.");
|
||||
is(store.info[1].name, "head",
|
||||
"the 2nd traversed node isn't the expected one.");
|
||||
is(store.info[1].depth, 1,
|
||||
"the 2nd traversed node doesn't have the expected depth.");
|
||||
is(store.info[2].name, "body",
|
||||
"the 3rd traversed node isn't the expected one.");
|
||||
is(store.info[2].depth, 1,
|
||||
"the 3rd traversed node doesn't have the expected depth.");
|
||||
is(store.info[3].name, "style",
|
||||
"the 4th traversed node isn't the expected one.");
|
||||
is(store.info[3].depth, 2,
|
||||
"the 4th traversed node doesn't have the expected depth.");
|
||||
is(store.info[4].name, "script",
|
||||
"the 5th traversed node isn't the expected one.");
|
||||
is(store.info[4].depth, 2,
|
||||
"the 5th traversed node doesn't have the expected depth.");
|
||||
is(store.info[5].name, "div",
|
||||
"the 6th traversed node isn't the expected one.");
|
||||
is(store.info[5].depth, 2,
|
||||
"the 6th traversed node doesn't have the expected depth.");
|
||||
is(store.info[6].name, "span",
|
||||
"the 7th traversed node isn't the expected one.");
|
||||
is(store.info[6].depth, 3,
|
||||
"the 7th traversed node doesn't have the expected depth.");
|
||||
});
|
||||
}
|
46
browser/devtools/tilt/test/browser_tilt_utils06.js
Normal file
46
browser/devtools/tilt/test/browser_tilt_utils06.js
Normal file
@ -0,0 +1,46 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, isnot, gBrowser, TiltUtils */
|
||||
"use strict";
|
||||
|
||||
let someObject = {
|
||||
a: 1,
|
||||
func: function()
|
||||
{
|
||||
this.b = 2;
|
||||
}
|
||||
};
|
||||
|
||||
let anotherObject = {
|
||||
finalize: function()
|
||||
{
|
||||
someObject.c = 3;
|
||||
}
|
||||
};
|
||||
|
||||
function test() {
|
||||
ok(TiltUtils, "The TiltUtils object doesn't exist.");
|
||||
|
||||
TiltUtils.bindObjectFunc(someObject, "", anotherObject);
|
||||
someObject.func();
|
||||
|
||||
is(someObject.a, 1,
|
||||
"The bindObjectFunc() messed the non-function members of the object.");
|
||||
isnot(someObject.b, 2,
|
||||
"The bindObjectFunc() didn't ignore the old scope correctly.");
|
||||
is(anotherObject.b, 2,
|
||||
"The bindObjectFunc() didn't set the new scope correctly.");
|
||||
|
||||
|
||||
TiltUtils.destroyObject(anotherObject);
|
||||
is(someObject.c, 3,
|
||||
"The finalize function wasn't called when an object was destroyed.");
|
||||
|
||||
|
||||
TiltUtils.destroyObject(someObject);
|
||||
is(typeof someObject.a, "undefined",
|
||||
"Not all members of the destroyed object were deleted.");
|
||||
is(typeof someObject.func, "undefined",
|
||||
"Not all function members of the destroyed object were deleted.");
|
||||
}
|
124
browser/devtools/tilt/test/browser_tilt_visualizer.js
Normal file
124
browser/devtools/tilt/test/browser_tilt_visualizer.js
Normal file
@ -0,0 +1,124 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global ok, is, info, isApproxVec, isTiltEnabled, isWebGLSupported, gBrowser*/
|
||||
/*global TiltVisualizer */
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
if (!isTiltEnabled()) {
|
||||
info("Skipping notifications test because Tilt isn't enabled.");
|
||||
return;
|
||||
}
|
||||
if (!isWebGLSupported()) {
|
||||
info("Skipping visualizer test because WebGL isn't supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
let webGLError = false;
|
||||
let webGLLoad = false;
|
||||
|
||||
let visualizer = new TiltVisualizer({
|
||||
parentNode: gBrowser.selectedBrowser.parentNode,
|
||||
contentWindow: gBrowser.selectedBrowser.contentWindow,
|
||||
requestAnimationFrame: window.mozRequestAnimationFrame,
|
||||
|
||||
onError: function onWebGLError()
|
||||
{
|
||||
webGLError = true;
|
||||
},
|
||||
|
||||
onLoad: function onWebGLLoad()
|
||||
{
|
||||
webGLLoad = true;
|
||||
}
|
||||
});
|
||||
|
||||
ok(webGLError ^ webGLLoad,
|
||||
"The WebGL context should either be created or not.");
|
||||
|
||||
if (webGLError) {
|
||||
info("Skipping visualizer test because WebGL couldn't be initialized.");
|
||||
return;
|
||||
}
|
||||
|
||||
ok(visualizer.canvas,
|
||||
"Visualizer constructor should have created a child canvas object.");
|
||||
ok(visualizer.presenter,
|
||||
"Visualizer constructor should have created a child presenter object.");
|
||||
ok(visualizer.controller,
|
||||
"Visualizer constructor should have created a child controller object.");
|
||||
ok(visualizer.isInitialized(),
|
||||
"The visualizer should have been initialized properly.");
|
||||
ok(visualizer.presenter.isInitialized(),
|
||||
"The visualizer presenter should have been initialized properly.");
|
||||
ok(visualizer.controller.isInitialized(),
|
||||
"The visualizer controller should have been initialized properly.");
|
||||
|
||||
testPresenter(visualizer.presenter);
|
||||
testController(visualizer.controller);
|
||||
|
||||
visualizer.removeOverlay();
|
||||
is(visualizer.canvas.parentNode, null,
|
||||
"The visualizer canvas wasn't removed from the parent node.");
|
||||
|
||||
visualizer.cleanup();
|
||||
is(visualizer.presenter, undefined,
|
||||
"The visualizer presenter wasn't destroyed.");
|
||||
is(visualizer.controller, undefined,
|
||||
"The visualizer controller wasn't destroyed.");
|
||||
is(visualizer.canvas, undefined,
|
||||
"The visualizer canvas wasn't destroyed.");
|
||||
}
|
||||
|
||||
function testPresenter(presenter) {
|
||||
ok(presenter.renderer,
|
||||
"The presenter renderer wasn't initialized properly.");
|
||||
ok(presenter.visualizationProgram,
|
||||
"The presenter visualizationProgram wasn't initialized properly.");
|
||||
ok(presenter.texture,
|
||||
"The presenter texture wasn't initialized properly.");
|
||||
ok(!presenter.meshStacks,
|
||||
"The presenter meshStacks shouldn't be initialized yet.");
|
||||
ok(!presenter.meshWireframe,
|
||||
"The presenter meshWireframe shouldn't be initialized yet.");
|
||||
ok(presenter.traverseData,
|
||||
"The presenter nodesInformation wasn't initialized properly.");
|
||||
ok(presenter.highlight,
|
||||
"The presenter highlight wasn't initialized properly.");
|
||||
ok(presenter.highlight.disabled,
|
||||
"The presenter highlight should be initially disabled");
|
||||
ok(isApproxVec(presenter.highlight.v0, [0, 0, 0]),
|
||||
"The presenter highlight first vertex should be initially zeroed.");
|
||||
ok(isApproxVec(presenter.highlight.v1, [0, 0, 0]),
|
||||
"The presenter highlight second vertex should be initially zeroed.");
|
||||
ok(isApproxVec(presenter.highlight.v2, [0, 0, 0]),
|
||||
"The presenter highlight third vertex should be initially zeroed.");
|
||||
ok(isApproxVec(presenter.highlight.v3, [0, 0, 0]),
|
||||
"The presenter highlight fourth vertex should be initially zeroed.");
|
||||
ok(presenter.transforms,
|
||||
"The presenter transforms wasn't initialized properly.");
|
||||
ok(isApproxVec(presenter.transforms.offset, [0, 0, 0]),
|
||||
"The presenter transforms offset should be initially zeroed.");
|
||||
ok(isApproxVec(presenter.transforms.translation, [0, 0, 0]),
|
||||
"The presenter transforms translation should be initially zeroed.");
|
||||
ok(isApproxVec(presenter.transforms.rotation, [0, 0, 0, 1]),
|
||||
"The presenter transforms rotation should be initially set to identity.");
|
||||
|
||||
presenter.setTranslation([1, 2, 3]);
|
||||
presenter.setRotation([5, 6, 7, 8]);
|
||||
|
||||
ok(isApproxVec(presenter.transforms.translation, [1, 2, 3]),
|
||||
"The presenter transforms translation wasn't modified as it should");
|
||||
ok(isApproxVec(presenter.transforms.rotation, [5, 6, 7, 8]),
|
||||
"The presenter transforms rotation wasn't modified as it should");
|
||||
ok(presenter.redraw,
|
||||
"The new transforms should have issued a redraw request.");
|
||||
}
|
||||
|
||||
function testController(controller) {
|
||||
ok(controller.arcball,
|
||||
"The controller arcball wasn't initialized properly.");
|
||||
ok(!controller.coordinates,
|
||||
"The presenter meshWireframe shouldn't be initialized yet.");
|
||||
}
|
151
browser/devtools/tilt/test/head.js
Normal file
151
browser/devtools/tilt/test/head.js
Normal file
@ -0,0 +1,151 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*global Services, Components, gBrowser, executeSoon */
|
||||
/*global InspectorUI, Tilt, TiltGL, EPSILON */
|
||||
"use strict";
|
||||
|
||||
Components.utils.import("resource:///modules/devtools/TiltGL.jsm");
|
||||
Components.utils.import("resource:///modules/devtools/TiltMath.jsm");
|
||||
Components.utils.import("resource:///modules/devtools/TiltUtils.jsm");
|
||||
Components.utils.import("resource:///modules/devtools/TiltVisualizer.jsm");
|
||||
|
||||
|
||||
const DEFAULT_HTML = "data:text/html," +
|
||||
"<DOCTYPE html>" +
|
||||
"<html>" +
|
||||
"<head>" +
|
||||
"<title>Three Laws</title>" +
|
||||
"</head>" +
|
||||
"<body>" +
|
||||
"<div>" +
|
||||
"A robot may not injure a human being or, through inaction, allow a" +
|
||||
"human being to come to harm." +
|
||||
"</div>" +
|
||||
"<div>" +
|
||||
"A robot must obey the orders given to it by human beings, except" +
|
||||
"where such orders would conflict with the First Law." +
|
||||
"</div>" +
|
||||
"<div>" +
|
||||
"A robot must protect its own existence as long as such protection" +
|
||||
"does not conflict with the First or Second Laws." +
|
||||
"</div>" +
|
||||
"<body>" +
|
||||
"</html>";
|
||||
|
||||
const INSPECTOR_OPENED = InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED;
|
||||
const INSPECTOR_CLOSED = InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED;
|
||||
|
||||
const TILT_INITIALIZED = Tilt.NOTIFICATIONS.INITIALIZED;
|
||||
const TILT_DESTROYED = Tilt.NOTIFICATIONS.DESTROYED;
|
||||
const TILT_SHOWN = Tilt.NOTIFICATIONS.SHOWN;
|
||||
const TILT_HIDDEN = Tilt.NOTIFICATIONS.HIDDEN;
|
||||
|
||||
const TILT_ENABLED = Services.prefs.getBoolPref("devtools.tilt.enabled");
|
||||
const INSP_ENABLED = Services.prefs.getBoolPref("devtools.inspector.enabled");
|
||||
|
||||
|
||||
function isTiltEnabled() {
|
||||
return TILT_ENABLED && INSP_ENABLED;
|
||||
}
|
||||
|
||||
function isWebGLSupported() {
|
||||
return TiltGL.isWebGLSupported() &&
|
||||
TiltGL.create3DContext(
|
||||
document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"));
|
||||
}
|
||||
|
||||
function isApprox(num1, num2) {
|
||||
return Math.abs(num1 - num2) < EPSILON;
|
||||
}
|
||||
|
||||
function isApproxVec(vec1, vec2) {
|
||||
if (vec1.length !== vec2.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0, len = vec1.length; i < len; i++) {
|
||||
if (!isApprox(vec1[i], vec2[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function createCanvas() {
|
||||
return gBrowser.parentNode
|
||||
.ownerDocument
|
||||
.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
}
|
||||
|
||||
|
||||
function createTab(callback, location) {
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
callback(tab);
|
||||
}, true);
|
||||
|
||||
gBrowser.selectedBrowser.contentWindow.location = location || DEFAULT_HTML;
|
||||
return tab;
|
||||
}
|
||||
|
||||
|
||||
function createTilt(callbacks, close) {
|
||||
Services.obs.addObserver(onInspectorOpen, INSPECTOR_OPENED, false);
|
||||
InspectorUI.toggleInspectorUI();
|
||||
|
||||
function onInspectorOpen() {
|
||||
Services.obs.removeObserver(onInspectorOpen, INSPECTOR_OPENED);
|
||||
|
||||
executeSoon(function() {
|
||||
if ("function" === typeof callbacks.onInspectorOpen) {
|
||||
callbacks.onInspectorOpen();
|
||||
}
|
||||
Services.obs.addObserver(onTiltOpen, TILT_INITIALIZED, false);
|
||||
Tilt.initialize();
|
||||
});
|
||||
}
|
||||
|
||||
function onTiltOpen() {
|
||||
Services.obs.removeObserver(onTiltOpen, TILT_INITIALIZED);
|
||||
|
||||
executeSoon(function() {
|
||||
if ("function" === typeof callbacks.onTiltOpen) {
|
||||
callbacks.onTiltOpen();
|
||||
}
|
||||
if (close) {
|
||||
Services.obs.addObserver(onTiltClose, TILT_DESTROYED, false);
|
||||
Tilt.destroy(Tilt.currentWindowId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onTiltClose() {
|
||||
Services.obs.removeObserver(onTiltClose, TILT_DESTROYED);
|
||||
|
||||
executeSoon(function() {
|
||||
if ("function" === typeof callbacks.onTiltClose) {
|
||||
callbacks.onTiltClose();
|
||||
}
|
||||
if (close) {
|
||||
Services.obs.addObserver(onInspectorClose, INSPECTOR_CLOSED, false);
|
||||
InspectorUI.closeInspectorUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onInspectorClose() {
|
||||
Services.obs.removeObserver(onInspectorClose, INSPECTOR_CLOSED);
|
||||
|
||||
executeSoon(function() {
|
||||
if ("function" === typeof callbacks.onInspectorClose) {
|
||||
callbacks.onInspectorClose();
|
||||
}
|
||||
if ("function" === typeof callbacks.onEnd) {
|
||||
callbacks.onEnd();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -217,6 +217,8 @@ can reach it easily. -->
|
||||
<!ENTITY inspectButton.label "Inspect">
|
||||
<!ENTITY inspectButton.accesskey "I">
|
||||
<!ENTITY inspectCloseButton.tooltiptext "Close Inspector">
|
||||
<!ENTITY inspect3DButton.label "3D">
|
||||
<!ENTITY inspect3DButton.accesskey "M">
|
||||
<!ENTITY inspectStyleButton.label "Style">
|
||||
<!ENTITY inspectStyleButton.accesskey "S">
|
||||
|
||||
|
45
browser/locales/en-US/chrome/browser/devtools/tilt.properties
Executable file
45
browser/locales/en-US/chrome/browser/devtools/tilt.properties
Executable file
@ -0,0 +1,45 @@
|
||||
# LOCALIZATION NOTE These strings are used inside the Tilt Inspector
|
||||
# which is available from the Web Developer sub-menu -> 'Tilt'.
|
||||
#
|
||||
# The correct localization of this file might be to keep it in
|
||||
# English, or another language commonly spoken among web developers.
|
||||
# You want to make that choice consistent across the developer tools.
|
||||
# A good criteria is the language in which you'd find the best
|
||||
# documentation on web development on the web.
|
||||
|
||||
# LOCALIZATION NOTE (initTilt.error): Tilt requires WebGL capabilities, which
|
||||
# are not available on every hardware. This message is displayed as an modal
|
||||
# popup window when initialization fails because of unsupported hardware.
|
||||
initTilt.error = Could not initialize Tilt, please check the\ntroubleshooting information available at http://get.webgl.org/troubleshooting
|
||||
|
||||
# LOCALIZATION NOTE (initWebGL.error): Tilt requires WebGL capabilities, which
|
||||
# are not available on every hardware. This message is displayed in the console
|
||||
# when initialization fails because of unsupported hardware.
|
||||
initWebGL.error = Could not initialize the WebGL context, your hardware or drivers may not support it.
|
||||
|
||||
# LOCALIZATION NOTE (linkProgram.error): This error happens when the WebGL
|
||||
# context can't link two compiled shader programs together. It is displayed in
|
||||
# the Error Console.
|
||||
linkProgram.error = Could not initialize shader program: %S
|
||||
|
||||
# LOCALIZATION NOTE (compileShader.source.error): This error is caused when the
|
||||
# source (uri or path) of a shader is not the expected one. It is displayed in
|
||||
# the Error Console.
|
||||
compileShader.source.error = Bad shader source type (expected String).
|
||||
|
||||
# LOCALIATION NOTE (compileShader.type.error): There are two types of shader
|
||||
# programs - vertex and fragment. At a shader initialization, if none of these
|
||||
# two types is specified, this compile-time error is shown. It is displayed in
|
||||
# the Error Console.
|
||||
compileShader.type.error = Wrong shader type specified for: %S
|
||||
|
||||
# LOCALIZATION NOTE (compileShader.compile.error): If the shader source and
|
||||
# type are correctly specified, there may be syntax errors in the shader code.
|
||||
# If this is the case, this compile-time error is shown. It is displayed in
|
||||
# the Error Console.
|
||||
compileShader.compile.error = Shader compile status:\n%S
|
||||
|
||||
# LOCALIZATION NOTE (compileShader.source.error): This error is caused when the
|
||||
# source (canvas or image) of a texture is not as expected. It is displayed in
|
||||
# the Error Console.
|
||||
initTexture.source.error = Bad texture source type (expected Image).
|
@ -19,6 +19,7 @@
|
||||
locale/browser/devtools/gclicommands.properties (%chrome/browser/devtools/gclicommands.properties)
|
||||
locale/browser/devtools/webconsole.properties (%chrome/browser/devtools/webconsole.properties)
|
||||
locale/browser/devtools/inspector.properties (%chrome/browser/devtools/inspector.properties)
|
||||
locale/browser/devtools/tilt.properties (%chrome/browser/devtools/tilt.properties)
|
||||
locale/browser/devtools/scratchpad.properties (%chrome/browser/devtools/scratchpad.properties)
|
||||
locale/browser/devtools/scratchpad.dtd (%chrome/browser/devtools/scratchpad.dtd)
|
||||
locale/browser/devtools/styleeditor.properties (%chrome/browser/devtools/styleeditor.properties)
|
||||
|
Loading…
Reference in New Issue
Block a user