|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 "use strict"; |
|
4 |
|
5 let {devtools} = Components.utils.import("resource://gre/modules/devtools/Loader.jsm", {}); |
|
6 let TiltManager = devtools.require("devtools/tilt/tilt").TiltManager; |
|
7 let TiltGL = devtools.require("devtools/tilt/tilt-gl"); |
|
8 let {EPSILON, TiltMath, vec3, mat3, mat4, quat4} = devtools.require("devtools/tilt/tilt-math"); |
|
9 let TiltUtils = devtools.require("devtools/tilt/tilt-utils"); |
|
10 let {TiltVisualizer} = devtools.require("devtools/tilt/tilt-visualizer"); |
|
11 |
|
12 let tempScope = {}; |
|
13 Components.utils.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tempScope); |
|
14 let LayoutHelpers = tempScope.LayoutHelpers; |
|
15 |
|
16 |
|
17 const DEFAULT_HTML = "data:text/html," + |
|
18 "<DOCTYPE html>" + |
|
19 "<html>" + |
|
20 "<head>" + |
|
21 "<meta charset='utf-8'/>" + |
|
22 "<title>Three Laws</title>" + |
|
23 "</head>" + |
|
24 "<body>" + |
|
25 "<div id='first-law'>" + |
|
26 "A robot may not injure a human being or, through inaction, allow a " + |
|
27 "human being to come to harm." + |
|
28 "</div>" + |
|
29 "<div>" + |
|
30 "A robot must obey the orders given to it by human beings, except " + |
|
31 "where such orders would conflict with the First Law." + |
|
32 "</div>" + |
|
33 "<div>" + |
|
34 "A robot must protect its own existence as long as such protection " + |
|
35 "does not conflict with the First or Second Laws." + |
|
36 "</div>" + |
|
37 "<div id='far-far-away' style='position: absolute; top: 250%;'>" + |
|
38 "I like bacon." + |
|
39 "</div>" + |
|
40 "<body>" + |
|
41 "</html>"; |
|
42 |
|
43 let Tilt = TiltManager.getTiltForBrowser(window); |
|
44 |
|
45 const STARTUP = Tilt.NOTIFICATIONS.STARTUP; |
|
46 const INITIALIZING = Tilt.NOTIFICATIONS.INITIALIZING; |
|
47 const INITIALIZED = Tilt.NOTIFICATIONS.INITIALIZED; |
|
48 const DESTROYING = Tilt.NOTIFICATIONS.DESTROYING; |
|
49 const BEFORE_DESTROYED = Tilt.NOTIFICATIONS.BEFORE_DESTROYED; |
|
50 const DESTROYED = Tilt.NOTIFICATIONS.DESTROYED; |
|
51 const SHOWN = Tilt.NOTIFICATIONS.SHOWN; |
|
52 const HIDDEN = Tilt.NOTIFICATIONS.HIDDEN; |
|
53 const HIGHLIGHTING = Tilt.NOTIFICATIONS.HIGHLIGHTING; |
|
54 const UNHIGHLIGHTING = Tilt.NOTIFICATIONS.UNHIGHLIGHTING; |
|
55 const NODE_REMOVED = Tilt.NOTIFICATIONS.NODE_REMOVED; |
|
56 |
|
57 const TILT_ENABLED = Services.prefs.getBoolPref("devtools.tilt.enabled"); |
|
58 |
|
59 gDevTools.testing = true; |
|
60 SimpleTest.registerCleanupFunction(() => { |
|
61 gDevTools.testing = false; |
|
62 }); |
|
63 |
|
64 function isTiltEnabled() { |
|
65 info("Apparently, Tilt is" + (TILT_ENABLED ? "" : " not") + " enabled."); |
|
66 return TILT_ENABLED; |
|
67 } |
|
68 |
|
69 function isWebGLSupported() { |
|
70 let supported = !TiltGL.isWebGLForceEnabled() && |
|
71 TiltGL.isWebGLSupported() && |
|
72 TiltGL.create3DContext(createCanvas()); |
|
73 |
|
74 info("Apparently, WebGL is" + (supported ? "" : " not") + " supported."); |
|
75 return supported; |
|
76 } |
|
77 |
|
78 function isApprox(num1, num2, delta) { |
|
79 if (Math.abs(num1 - num2) > (delta || EPSILON)) { |
|
80 info("isApprox expected " + num1 + ", got " + num2 + " instead."); |
|
81 return false; |
|
82 } |
|
83 return true; |
|
84 } |
|
85 |
|
86 function isApproxVec(vec1, vec2, delta) { |
|
87 vec1 = Array.prototype.slice.call(vec1); |
|
88 vec2 = Array.prototype.slice.call(vec2); |
|
89 |
|
90 if (vec1.length !== vec2.length) { |
|
91 return false; |
|
92 } |
|
93 for (let i = 0, len = vec1.length; i < len; i++) { |
|
94 if (!isApprox(vec1[i], vec2[i], delta)) { |
|
95 info("isApproxVec expected [" + vec1 + "], got [" + vec2 + "] instead."); |
|
96 return false; |
|
97 } |
|
98 } |
|
99 return true; |
|
100 } |
|
101 |
|
102 function isEqualVec(vec1, vec2) { |
|
103 vec1 = Array.prototype.slice.call(vec1); |
|
104 vec2 = Array.prototype.slice.call(vec2); |
|
105 |
|
106 if (vec1.length !== vec2.length) { |
|
107 return false; |
|
108 } |
|
109 for (let i = 0, len = vec1.length; i < len; i++) { |
|
110 if (vec1[i] !== vec2[i]) { |
|
111 info("isEqualVec expected [" + vec1 + "], got [" + vec2 + "] instead."); |
|
112 return false; |
|
113 } |
|
114 } |
|
115 return true; |
|
116 } |
|
117 |
|
118 function createCanvas() { |
|
119 return document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); |
|
120 } |
|
121 |
|
122 |
|
123 function createTab(callback, location) { |
|
124 info("Creating a tab, with callback " + typeof callback + |
|
125 ", and location " + location + "."); |
|
126 |
|
127 let tab = gBrowser.selectedTab = gBrowser.addTab(); |
|
128 |
|
129 gBrowser.selectedBrowser.addEventListener("load", function onLoad() { |
|
130 gBrowser.selectedBrowser.removeEventListener("load", onLoad, true); |
|
131 callback(tab); |
|
132 }, true); |
|
133 |
|
134 gBrowser.selectedBrowser.contentWindow.location = location || DEFAULT_HTML; |
|
135 return tab; |
|
136 } |
|
137 |
|
138 |
|
139 function createTilt(callbacks, close, suddenDeath) { |
|
140 info("Creating Tilt, with callbacks {" + Object.keys(callbacks) + "}" + |
|
141 ", autoclose param " + close + |
|
142 ", and sudden death handler " + typeof suddenDeath + "."); |
|
143 |
|
144 handleFailure(suddenDeath); |
|
145 |
|
146 Services.prefs.setBoolPref("webgl.verbose", true); |
|
147 TiltUtils.Output.suppressAlerts = true; |
|
148 |
|
149 info("Attempting to start Tilt."); |
|
150 Services.obs.addObserver(onTiltOpen, INITIALIZING, false); |
|
151 Tilt.toggle(); |
|
152 |
|
153 function onTiltOpen() { |
|
154 info("Tilt was opened."); |
|
155 Services.obs.removeObserver(onTiltOpen, INITIALIZING); |
|
156 |
|
157 executeSoon(function() { |
|
158 if ("function" === typeof callbacks.onTiltOpen) { |
|
159 info("Calling 'onTiltOpen'."); |
|
160 callbacks.onTiltOpen(Tilt.visualizers[Tilt.currentWindowId]); |
|
161 } |
|
162 if (close) { |
|
163 executeSoon(function() { |
|
164 info("Attempting to close Tilt."); |
|
165 Services.obs.addObserver(onTiltClose, DESTROYED, false); |
|
166 Tilt.destroy(Tilt.currentWindowId); |
|
167 }); |
|
168 } |
|
169 }); |
|
170 } |
|
171 |
|
172 function onTiltClose() { |
|
173 info("Tilt was closed."); |
|
174 Services.obs.removeObserver(onTiltClose, DESTROYED); |
|
175 |
|
176 executeSoon(function() { |
|
177 if ("function" === typeof callbacks.onTiltClose) { |
|
178 info("Calling 'onTiltClose'."); |
|
179 callbacks.onTiltClose(); |
|
180 } |
|
181 if ("function" === typeof callbacks.onEnd) { |
|
182 info("Calling 'onEnd'."); |
|
183 callbacks.onEnd(); |
|
184 } |
|
185 }); |
|
186 } |
|
187 |
|
188 function handleFailure(suddenDeath) { |
|
189 Tilt.failureCallback = function() { |
|
190 info("Tilt FAIL."); |
|
191 Services.obs.removeObserver(onTiltOpen, INITIALIZING); |
|
192 |
|
193 info("Now relying on sudden death handler " + typeof suddenDeath + "."); |
|
194 suddenDeath && suddenDeath(); |
|
195 } |
|
196 } |
|
197 } |
|
198 |
|
199 function getPickablePoint(presenter) { |
|
200 let vertices = presenter._meshStacks[0].vertices.components; |
|
201 |
|
202 let topLeft = vec3.create([vertices[0], vertices[1], vertices[2]]); |
|
203 let bottomRight = vec3.create([vertices[6], vertices[7], vertices[8]]); |
|
204 let center = vec3.lerp(topLeft, bottomRight, 0.5, []); |
|
205 |
|
206 let renderer = presenter._renderer; |
|
207 let viewport = [0, 0, renderer.width, renderer.height]; |
|
208 |
|
209 return vec3.project(center, viewport, renderer.mvMatrix, renderer.projMatrix); |
|
210 } |