Bug 715647 - I want to be able to remove nodes from the Tilt view; r=rcampbell

This commit is contained in:
Victor Porof 2012-01-25 10:04:15 +02:00
Родитель a21903df5c
Коммит f841e96453
8 изменённых файлов: 357 добавлений и 33 удалений

Просмотреть файл

@ -480,6 +480,11 @@ TiltVisualizer.Presenter.prototype = {
this.maxTextureSize),
format: "RGB"
});
if ("function" === typeof this.onSetupTexture) {
this.onSetupTexture();
this.onSetupTexture = null;
}
},
/**
@ -502,6 +507,9 @@ TiltVisualizer.Presenter.prototype = {
return;
}
// save the mesh data for future use
this.meshData = aData;
// create the visualization mesh using the vertices, texture coordinates
// and indices computed when traversing the document object model
this.meshStacks = {
@ -524,19 +532,28 @@ TiltVisualizer.Presenter.prototype = {
this.highlightNode(this.inspectorUI.selection);
}
let zoom = TiltUtils.getDocumentZoom();
let width = Math.min(aData.meshWidth * zoom, renderer.width);
let height = Math.min(aData.meshHeight * zoom, renderer.height);
if (!this._initialMeshConfiguration) {
this._initialMeshConfiguration = true;
// set the necessary mesh offsets
this.transforms.offset[0] = -width * 0.5;
this.transforms.offset[1] = -height * 0.5;
let zoom = TiltUtils.getDocumentZoom();
let width = Math.min(aData.meshWidth * zoom, renderer.width);
let height = Math.min(aData.meshHeight * zoom, renderer.height);
// make sure the canvas is opaque now that the initialization is finished
this.canvas.style.background = TiltVisualizerStyle.canvas.background;
// set the necessary mesh offsets
this.transforms.offset[0] = -width * 0.5;
this.transforms.offset[1] = -height * 0.5;
this.drawVisualization();
this.redraw = true;
// make sure the canvas is opaque now that the initialization is finished
this.canvas.style.background = TiltVisualizerStyle.canvas.background;
this.drawVisualization();
this.redraw = true;
}
if ("function" === typeof this.onSetupMesh) {
this.onSetupMesh();
this.onSetupMesh = null;
}
},
/**
@ -626,9 +643,16 @@ TiltVisualizer.Presenter.prototype = {
* the current horizontal coordinate of the mouse
* @param {Number} y
* the current vertical coordinate of the mouse
* @param {Object} aProperties
* an object containing the following properties:
* {Function} onpick: function to be called after picking succeeded
* {Function} onfail: function to be called after picking failed
*/
highlightNodeAt: function TVP_highlightNodeAt(x, y)
highlightNodeAt: function TVP_highlightNodeAt(x, y, aProperties)
{
// make sure the properties parameter is a valid object
aProperties = aProperties || {};
// try to pick a mesh node using the current x, y coordinates
this.pickNode(x, y, {
@ -638,6 +662,10 @@ TiltVisualizer.Presenter.prototype = {
onfail: function TVP_onHighlightFail()
{
this.highlightNodeFor(-1);
if ("function" === typeof aProperties.onfail) {
aProperties.onfail();
}
}.bind(this),
/**
@ -649,6 +677,10 @@ TiltVisualizer.Presenter.prototype = {
onpick: function TVP_onHighlightPick(aIntersection)
{
this.highlightNodeFor(aIntersection.index);
if ("function" === typeof aProperties.onpick) {
aProperties.onpick();
}
}.bind(this)
});
},
@ -701,6 +733,32 @@ TiltVisualizer.Presenter.prototype = {
this.contentWindow.pageYOffset > 0);
},
/**
* Deletes a node from the visualization mesh.
*
* @param {Number} aNodeIndex
* the index of the node in the this.traverseData array;
* if not specified, it will default to the current selection
*/
deleteNode: function TVP_deleteNode(aNodeIndex)
{
// we probably don't want to delete the html or body node.. just sayin'
if ((aNodeIndex = aNodeIndex || this._currentSelection) < 1) {
return;
}
let renderer = this.renderer;
let meshData = this.meshData;
for (let i = 0, k = 36 * aNodeIndex; i < 36; i++) {
meshData.vertices[i + k] = 0;
}
this.meshStacks.vertices = new renderer.VertexBuffer(meshData.vertices, 3);
this.highlight.disabled = true;
this.redraw = true;
},
/**
* Picks a stacked dom node at the x and y screen coordinates and issues
* a callback function with the found intersection.
@ -923,7 +981,6 @@ TiltVisualizer.Controller.prototype = {
// bind commonly used mouse and keyboard events with the controller
canvas.addEventListener("mousedown", this.onMouseDown, false);
canvas.addEventListener("mouseup", this.onMouseUp, false);
canvas.addEventListener("click", this.onMouseClick, false);
canvas.addEventListener("mousemove", this.onMouseMove, false);
canvas.addEventListener("mouseover", this.onMouseOver, false);
canvas.addEventListener("mouseout", this.onMouseOut, false);
@ -946,7 +1003,6 @@ TiltVisualizer.Controller.prototype = {
canvas.removeEventListener("mousedown", this.onMouseDown, false);
canvas.removeEventListener("mouseup", this.onMouseUp, false);
canvas.removeEventListener("click", this.onMouseClick, false);
canvas.removeEventListener("mousemove", this.onMouseMove, false);
canvas.removeEventListener("mouseover", this.onMouseOver, false);
canvas.removeEventListener("mouseout", this.onMouseOut, false);
@ -979,10 +1035,11 @@ TiltVisualizer.Controller.prototype = {
e.stopPropagation();
// calculate x and y coordinates using using the client and target offset
let button = e.which;
this._downX = e.clientX - e.target.offsetLeft;
this._downY = e.clientY - e.target.offsetTop;
this.arcball.mouseDown(this._downX, this._downY, e.which);
this.arcball.mouseDown(this._downX, this._downY, button);
},
/**
@ -998,29 +1055,15 @@ TiltVisualizer.Controller.prototype = {
let upX = e.clientX - e.target.offsetLeft;
let upY = e.clientY - e.target.offsetTop;
this.arcball.mouseUp(upX, upY, button);
},
/**
* Called every time a mouse button is clicked.
*/
onMouseClick: function TVC_onMouseClick(e)
{
e.preventDefault();
e.stopPropagation();
// calculate x and y coordinates using using the client and target offset
let button = e.which;
let clickX = e.clientX - e.target.offsetLeft;
let clickY = e.clientY - e.target.offsetTop;
// a click in Tilt is issued only when the mouse pointer stays in
// relatively the same position
if (Math.abs(this._downX - clickX) < MOUSE_CLICK_THRESHOLD &&
Math.abs(this._downY - clickY) < MOUSE_CLICK_THRESHOLD) {
if (Math.abs(this._downX - upX) < MOUSE_CLICK_THRESHOLD &&
Math.abs(this._downY - upY) < MOUSE_CLICK_THRESHOLD) {
this.presenter.highlightNodeAt(clickX, clickY);
this.presenter.highlightNodeAt(upX, upY);
}
this.arcball.mouseUp(upX, upY, button);
},
/**
@ -1098,6 +1141,9 @@ TiltVisualizer.Controller.prototype = {
this.presenter.tiltUI.destroy(this.presenter.tiltUI.currentWindowId, 1);
return;
}
if (code === e.DOM_VK_X) {
this.presenter.deleteNode();
}
if (!e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey) {
e.preventDefault();

Просмотреть файл

@ -81,6 +81,11 @@ self.onmessage = function TWP_onMessage(event)
let v2b = [v2f[0], v2f[1], v2f[2] - thickness];
let v3b = [v3f[0], v3f[1], v3f[2] - thickness];
// don't do anything with degenerate quads
if (!v0f[0] && !v1f[0] && !v2f[0] && !v3f[0]) {
continue;
}
// 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

Просмотреть файл

@ -73,6 +73,11 @@ _BROWSER_TEST_FILES = \
browser_tilt_math05.js \
browser_tilt_math06.js \
browser_tilt_math07.js \
browser_tilt_picking.js \
browser_tilt_picking_delete.js \
browser_tilt_picking_highlight01.js \
browser_tilt_picking_highlight02.js \
browser_tilt_picking_highlight03.js \
browser_tilt_utils01.js \
browser_tilt_utils02.js \
browser_tilt_utils03.js \

Просмотреть файл

@ -0,0 +1,52 @@
/* 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, InspectorUI, TILT_DESTROYED */
"use strict";
function test() {
if (!isTiltEnabled()) {
info("Skipping picking test because Tilt isn't enabled.");
return;
}
if (!isWebGLSupported()) {
info("Skipping picking test because WebGL isn't supported.");
return;
}
waitForExplicitFinish();
createTab(function() {
createTilt({
onTiltOpen: function(instance)
{
let presenter = instance.presenter;
let canvas = presenter.canvas;
presenter.onSetupMesh = function() {
presenter.pickNode(canvas.width / 2, canvas.height / 2, {
onpick: function(data)
{
ok(data.index > 0,
"Simply picking a node didn't work properly.");
ok(!presenter.highlight.disabled,
"After only picking a node, it shouldn't be highlighted.");
Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
InspectorUI.closeInspectorUI();
}
});
};
}
});
});
}
function cleanup() {
Services.obs.removeObserver(cleanup, TILT_DESTROYED);
gBrowser.removeCurrentTab();
finish();
}

Просмотреть файл

@ -0,0 +1,67 @@
/* 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, InspectorUI, TILT_DESTROYED */
"use strict";
function test() {
if (!isTiltEnabled()) {
info("Skipping picking delete test because Tilt isn't enabled.");
return;
}
if (!isWebGLSupported()) {
info("Skipping picking delete test because WebGL isn't supported.");
return;
}
waitForExplicitFinish();
createTab(function() {
createTilt({
onTiltOpen: function(instance)
{
let presenter = instance.presenter;
let canvas = presenter.canvas;
presenter.onSetupMesh = function() {
presenter.highlightNodeAt(canvas.width / 2, canvas.height / 2, {
onpick: function()
{
ok(presenter._currentSelection > 0,
"Highlighting a node didn't work properly.");
ok(!presenter.highlight.disabled,
"After highlighting a node, it should be highlighted. D'oh.");
presenter.deleteNode();
ok(presenter._currentSelection > 0,
"Deleting a node shouldn't change the current selection.");
ok(presenter.highlight.disabled,
"After deleting a node, it shouldn't be highlighted.");
let nodeIndex = presenter._currentSelection;
let meshData = presenter.meshData;
for (let i = 0, k = 36 * nodeIndex; i < 36; i++) {
is(meshData.vertices[i + k], 0,
"The stack vertices weren't degenerated properly.");
}
Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
InspectorUI.closeInspectorUI();
}
});
};
}
});
});
}
function cleanup() {
Services.obs.removeObserver(cleanup, TILT_DESTROYED);
gBrowser.removeCurrentTab();
finish();
}

Просмотреть файл

@ -0,0 +1,50 @@
/* 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, InspectorUI, TILT_DESTROYED */
"use strict";
function test() {
if (!isTiltEnabled()) {
info("Skipping highlight test because Tilt isn't enabled.");
return;
}
if (!isWebGLSupported()) {
info("Skipping highlight test because WebGL isn't supported.");
return;
}
waitForExplicitFinish();
createTab(function() {
createTilt({
onTiltOpen: function(instance)
{
let presenter = instance.presenter;
presenter.onSetupMesh = function() {
let contentDocument = presenter.contentWindow.document;
let body = contentDocument.getElementsByTagName("body")[0];
presenter.highlightNode(body);
ok(presenter._currentSelection > 0,
"Highlighting a node didn't work properly.");
ok(!presenter.highlight.disabled,
"After highlighting a node, it should be highlighted. D'oh.");
Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
InspectorUI.closeInspectorUI();
};
}
});
});
}
function cleanup() {
Services.obs.removeObserver(cleanup, TILT_DESTROYED);
gBrowser.removeCurrentTab();
finish();
}

Просмотреть файл

@ -0,0 +1,52 @@
/* 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, InspectorUI, TILT_DESTROYED */
"use strict";
function test() {
if (!isTiltEnabled()) {
info("Skipping highlight test because Tilt isn't enabled.");
return;
}
if (!isWebGLSupported()) {
info("Skipping highlight test because WebGL isn't supported.");
return;
}
waitForExplicitFinish();
createTab(function() {
createTilt({
onTiltOpen: function(instance)
{
let presenter = instance.presenter;
let canvas = presenter.canvas;
presenter.onSetupMesh = function() {
presenter.highlightNodeAt(canvas.width / 2, canvas.height / 2, {
onpick: function()
{
ok(presenter._currentSelection > 0,
"Highlighting a node didn't work properly.");
ok(!presenter.highlight.disabled,
"After highlighting a node, it should be highlighted. D'oh.");
Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
InspectorUI.closeInspectorUI();
}
});
};
}
});
});
}
function cleanup() {
Services.obs.removeObserver(cleanup, TILT_DESTROYED);
gBrowser.removeCurrentTab();
finish();
}

Просмотреть файл

@ -0,0 +1,47 @@
/* 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, InspectorUI, TILT_DESTROYED */
"use strict";
function test() {
if (!isTiltEnabled()) {
info("Skipping highlight test because Tilt isn't enabled.");
return;
}
if (!isWebGLSupported()) {
info("Skipping highlight test because WebGL isn't supported.");
return;
}
waitForExplicitFinish();
createTab(function() {
createTilt({
onTiltOpen: function(instance)
{
let presenter = instance.presenter;
presenter.onSetupMesh = function() {
presenter.highlightNodeFor(1);
ok(presenter._currentSelection > 0,
"Highlighting a node didn't work properly.");
ok(!presenter.highlight.disabled,
"After highlighting a node, it should be highlighted. D'oh.");
Services.obs.addObserver(cleanup, TILT_DESTROYED, false);
InspectorUI.closeInspectorUI();
};
}
});
});
}
function cleanup() {
Services.obs.removeObserver(cleanup, TILT_DESTROYED);
gBrowser.removeCurrentTab();
finish();
}