Skip to content

Commit

Permalink
move mouse handling code to separate file
Browse files Browse the repository at this point in the history
  • Loading branch information
biasmv committed Feb 22, 2015
1 parent 532a49b commit 6a2a81c
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 118 deletions.
1 change: 1 addition & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ SOURCE_FILES = [
'src/mol/symmetry.js',
'src/pv.js',
'src/slab.js',
'src/mouse.js',
'src/touch.js',
'src/unique-object-id-pool.js',
'src/utils.js',
Expand Down
2 changes: 0 additions & 2 deletions demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ function load(pdb_id) {
structure = io.pdb(data);
//mol.assignHelixSheet(structure);
cartoon();

viewer.autoZoom();
}});
}
Expand Down Expand Up @@ -201,7 +200,6 @@ viewer = pv.Viewer(document.getElementById('viewer'), {
background : '#333', animateTime: 500,
});
viewer.addListener('viewerReady', longHelices);

window.addEventListener('resize', function() {
viewer.fitParent();
});
Expand Down
171 changes: 171 additions & 0 deletions src/mouse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Copyright (c) 2013-2015 Marco Biasini
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

define([
'./gl-matrix',
'./utils',
],
function(
glMatrix,
utils) {

"use strict";

var vec3 = glMatrix.vec3;


function MouseHandler(canvas, viewer, cam, animationTime) {
this._viewer = viewer;
this._canvas = canvas;
this._cam = cam;
this._canvas = canvas;
this._animationTime = animationTime;
this._init();
}

MouseHandler.prototype = {

_centerOnClicked : function(picked) {
if (picked === null) {
return;
}
var transformedPos = vec3.create();
var newAtom = picked.object().atom;
var pos = newAtom.pos();
if (picked.transform()) {
vec3.transformMat4(transformedPos, pos, picked.transform());
this._viewer.setCenter(transformedPos, this._animationTime);
} else {
this._viewer.setCenter(pos, this._animationTime);
}
},

_mouseUp : function() {
var canvas = this._canvas;
canvas.removeEventListener('mousemove', this._mouseRotateListener);
canvas.removeEventListener('mousemove', this._mousePanListener);
canvas.removeEventListener('mouseup', this._mouseUpListener);
document.removeEventListener('mouseup', this._mouseUpListener);
document.removeEventListener('mousemove', this._mouseRotateListener);
document.removeEventListener('mousemove', this._mousePanListener);
},

setCam : function(cam) {
this._cam = cam;
},

_init : function() {
this._mousePanListener = utils.bind(this, this._mousePan);
this._mouseRotateListener = utils.bind(this, this._mouseRotate);
this._mouseUpListener = utils.bind(this, this._mouseUp);

// Firefox responds to the wheel event, whereas other browsers listen to
// the mousewheel event. Register different event handlers, depending on
// what properties are available.
this._canvas.onWheel(utils.bind(this, this._mouseWheelFF),
utils.bind(this, this._mouseWheel));
this._canvas.on('dblclick', utils.bind(this, this._mouseDoubleClick));
this._canvas.on('mousedown', utils.bind(this, this._mouseDown));
return true;
},

_mouseWheel : function(event) {
this._cam.zoom(event.wheelDelta < 0 ? -1 : 1);
event.preventDefault();
this._viewer.requestRedraw();
},

_mouseWheelFF : function(event) {
this._cam.zoom(event.deltaY < 0 ? 1 : -1);
event.preventDefault();
this._viewer.requestRedraw();
},

_mouseDoubleClick : (function() {
return function(event) {
var rect = this._canvas.domElement().getBoundingClientRect();
var picked = this._viewer.pick(
{ x : event.clientX - rect.left, y : event.clientY - rect.top });
this._viewer._dispatchEvent(event, 'atomDoubleClicked', picked);
this._viewer.requestRedraw();
};
})(),

_mouseDown : function(event) {
if (event.button !== 0) {
return;
}
var currentTime = (new Date()).getTime();
// make sure it isn't a double click
if (typeof this.lastClickTime === 'undefined' ||
(currentTime - this.lastClickTime > 300)) {
this.lastClickTime = currentTime;
var rect = this._canvas.domElement().getBoundingClientRect();
var picked = this._viewer.pick(
{ x : event.clientX - rect.left, y : event.clientY - rect.top });
this._viewer._dispatchEvent(event, 'atomClicked', picked);
}
event.preventDefault();
if (event.shiftKey === true) {
this._canvas.on('mousemove', this._mousePanListener);
document.addEventListener('mousemove', this._mousePanListener, false);
} else {
this._canvas.on('mousemove', this._mouseRotateListener);
document.addEventListener('mousemove', this._mouseRotateListener, false);
}
this._canvas.on('mouseup', this._mouseUpListener);
document.addEventListener('mouseup', this._mouseUpListener, false);
this._lastMousePos = { x : event.pageX, y : event.pageY };
},

_mouseRotate : function(event) {
var newMousePos = { x : event.pageX, y : event.pageY };
var delta = {
x : newMousePos.x - this._lastMousePos.x,
y : newMousePos.y - this._lastMousePos.y
};

var speed = 0.005;
this._cam.rotateX(speed * delta.y);
this._cam.rotateY(speed * delta.x);
this._lastMousePos = newMousePos;
this._viewer.requestRedraw();
},

_mousePan : function(event) {
var newMousePos = { x : event.pageX, y : event.pageY };
var delta = {
x : newMousePos.x - this._lastMousePos.x,
y : newMousePos.y - this._lastMousePos.y
};

// adjust speed according to distance to camera center, it's not
// perfect but gives good enough results.
var speed = 0.001 * this._cam.zoom();
this._cam.panXY(speed * delta.x, speed * delta.y);
this._lastMousePos = newMousePos;
this._viewer.requestRedraw();
}

};

return MouseHandler;

});
124 changes: 8 additions & 116 deletions src/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ define([
'./gfx/cam',
'./gfx/shaders',
'./touch',
'./mouse',
'./gfx/render',
'./gfx/label',
'./gfx/custom-mesh',
Expand All @@ -47,6 +48,7 @@ define([
Cam,
shaders,
TouchHandler,
MouseHandler,
render,
TextLabel,
CustomMesh,
Expand Down Expand Up @@ -207,21 +209,6 @@ Viewer.prototype = {
return options;
},

_centerOnClicked : function(picked) {
if (picked === null) {
return;
}
var transformedPos = vec3.create();
var newAtom = picked.object().atom;
var pos = newAtom.pos();
if (picked.transform()) {
vec3.transformMat4(transformedPos, pos, picked.transform());
this.setCenter(transformedPos, this._options.animateTime);
} else {
this.setCenter(pos, this._options.animateTime);
}
},

// with rendering to avoid flickering.
_ensureSize : function() {
if (!this._resize) {
Expand Down Expand Up @@ -307,16 +294,6 @@ Viewer.prototype = {
this._pickBuffer = new FrameBuffer(this._canvas.gl(), fbOptions);
},

_mouseUp : function() {
var canvas = this._canvas;
canvas.removeEventListener('mousemove', this._mouseRotateListener);
canvas.removeEventListener('mousemove', this._mousePanListener);
canvas.removeEventListener('mouseup', this._mouseUpListener);
document.removeEventListener('mouseup', this._mouseUpListener);
document.removeEventListener('mousemove', this._mouseRotateListener);
document.removeEventListener('mousemove', this._mousePanListener);
},

_initViewer : function() {
if (!this._canvas.initGL()) {
this._domElement.removeChild(this._canvas);
Expand All @@ -333,6 +310,7 @@ Viewer.prototype = {
this._cam.setUpsamplingFactor(this._canvas.superSamplingFactor());
this._cam.fog(this._options.fog);
this._cam.setFogColor(this._options.background);
this._mouseHandler.setCam(this._cam);

var c = this._canvas;
var p = shouldUseHighPrecision() ? 'highp' : 'mediump';
Expand All @@ -346,17 +324,6 @@ Viewer.prototype = {

this._boundDraw = utils.bind(this, this._draw);

this._mousePanListener = utils.bind(this, this._mousePan);
this._mouseRotateListener = utils.bind(this, this._mouseRotate);
this._mouseUpListener = utils.bind(this, this._mouseUp);

// Firefox responds to the wheel event, whereas other browsers listen to
// the mousewheel event. Register different event handlers, depending on
// what properties are available.
this._canvas.onWheel(utils.bind(this, this._mouseWheelFF),
utils.bind(this, this._mouseWheel));
this._canvas.on('dblclick', utils.bind(this, this._mouseDoubleClick));
this._canvas.on('mousedown', utils.bind(this, this._mouseDown));
this._touchHandler = new TouchHandler(this._canvas.domElement(),
this, this._cam);

Expand Down Expand Up @@ -394,6 +361,8 @@ Viewer.prototype = {
this._textureCanvas = document.createElement('canvas');
this._textureCanvas.style.display = 'none';
this._domElement.appendChild(this._textureCanvas);
this._mouseHandler = new MouseHandler(this._canvas, this, this._cam,
this._options.animateTime);
},

setRotation : function(rotation, ms) {
Expand Down Expand Up @@ -495,37 +464,16 @@ Viewer.prototype = {
this._objects = [];
},

_mouseWheel : function(event) {
this._cam.zoom(event.wheelDelta < 0 ? -1 : 1);
event.preventDefault();
this.requestRedraw();
},

_mouseWheelFF : function(event) {
this._cam.zoom(event.deltaY < 0 ? 1 : -1);
event.preventDefault();
this.requestRedraw();
},

_mouseDoubleClick : (function() {
return function(event) {
var rect = this._canvas.domElement().getBoundingClientRect();
var picked = this.pick(
{ x : event.clientX - rect.left, y : event.clientY - rect.top });
this._dispatchEvent(event, 'atomDoubleClicked', picked);
this.requestRedraw();
};
})(),


addListener : function(eventName, callback) {
var callbacks = this.listenerMap[eventName];
if (typeof callbacks === 'undefined') {
callbacks = [];
this.listenerMap[eventName] = callbacks;
}
if (callback === 'center') {
callbacks.push(utils.bind(this, this._centerOnClicked));
var cb = utils.bind(this._mouseHandler,
this._mouseHandler._centerOnClicked);
callbacks.push(cb);
} else {
callbacks.push(callback);
}
Expand Down Expand Up @@ -553,62 +501,6 @@ Viewer.prototype = {
}
},

_mouseDown : function(event) {
if (event.button !== 0) {
return;
}
var currentTime = (new Date()).getTime();
// make sure it isn't a double click
if (typeof this.lastClickTime === 'undefined' ||
(currentTime - this.lastClickTime > 300)) {
this.lastClickTime = currentTime;
var rect = this._canvas.domElement().getBoundingClientRect();
var picked = this.pick(
{ x : event.clientX - rect.left, y : event.clientY - rect.top });
this._dispatchEvent(event, 'atomClicked', picked);
}
event.preventDefault();
if (event.shiftKey === true) {
this._canvas.on('mousemove', this._mousePanListener);
document.addEventListener('mousemove', this._mousePanListener, false);
} else {
this._canvas.on('mousemove', this._mouseRotateListener);
document.addEventListener('mousemove', this._mouseRotateListener, false);
}
this._canvas.on('mouseup', this._mouseUpListener);
document.addEventListener('mouseup', this._mouseUpListener, false);
this._lastMousePos = { x : event.pageX, y : event.pageY };
},

_mouseRotate : function(event) {
var newMousePos = { x : event.pageX, y : event.pageY };
var delta = {
x : newMousePos.x - this._lastMousePos.x,
y : newMousePos.y - this._lastMousePos.y
};

var speed = 0.005;
this._cam.rotateX(speed * delta.y);
this._cam.rotateY(speed * delta.x);
this._lastMousePos = newMousePos;
this.requestRedraw();
},

_mousePan : function(event) {
var newMousePos = { x : event.pageX, y : event.pageY };
var delta = {
x : newMousePos.x - this._lastMousePos.x,
y : newMousePos.y - this._lastMousePos.y
};

// adjust speed according to distance to camera center, it's not
// perfect but gives good enough results.
var speed = 0.001 * this._cam.zoom();
this._cam.panXY(speed * delta.x, speed * delta.y);
this._lastMousePos = newMousePos;
this.requestRedraw();
},

RENDER_MODES : [
'sline', 'lines', 'trace', 'lineTrace', 'cartoon', 'tube', 'spheres',
'ballsAndSticks',
Expand Down

0 comments on commit 6a2a81c

Please sign in to comment.