molstar
Version:
A comprehensive macromolecular library.
195 lines • 9.27 kB
JavaScript
/**
* Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import { __assign } from "tslib";
import { Representation } from '../../mol-repr/representation';
import { ModifiersKeys, ButtonsType } from '../../mol-util/input/input-observer';
import { RxEventHelper } from '../../mol-util/rx-event-helper';
import { Vec2, Vec3 } from '../../mol-math/linear-algebra';
import { ParamDefinition as PD } from '../../mol-util/param-definition';
import { Bond } from '../../mol-model/structure';
var tmpPosA = Vec3();
var tmpPos = Vec3();
var tmpNorm = Vec3();
export var Canvas3dInteractionHelperParams = {
maxFps: PD.Numeric(30, { min: 10, max: 60, step: 10 }),
preferAtomPixelPadding: PD.Numeric(3, { min: 0, max: 20, step: 1 }, { description: 'Number of extra pixels at which to prefer atoms over bonds.' }),
};
var Canvas3dInteractionHelper = /** @class */ (function () {
function Canvas3dInteractionHelper(canvasIdentify, lociGetter, input, camera, props) {
var _this = this;
if (props === void 0) { props = {}; }
this.canvasIdentify = canvasIdentify;
this.lociGetter = lociGetter;
this.input = input;
this.camera = camera;
this.ev = RxEventHelper.create();
this.events = {
hover: this.ev(),
drag: this.ev(),
click: this.ev(),
};
this.startX = -1;
this.startY = -1;
this.endX = -1;
this.endY = -1;
this.id = void 0;
this.position = void 0;
this.currentIdentifyT = 0;
this.isInteracting = false;
this.prevLoci = Representation.Loci.Empty;
this.prevT = 0;
this.inside = false;
this.buttons = ButtonsType.create(0);
this.button = ButtonsType.create(0);
this.modifiers = ModifiersKeys.None;
this.props = __assign(__assign({}, PD.getDefaultValues(Canvas3dInteractionHelperParams)), props);
input.drag.subscribe(function (_a) {
var x = _a.x, y = _a.y, buttons = _a.buttons, button = _a.button, modifiers = _a.modifiers;
_this.isInteracting = true;
// console.log('drag');
_this.drag(x, y, buttons, button, modifiers);
});
input.move.subscribe(function (_a) {
var x = _a.x, y = _a.y, inside = _a.inside, buttons = _a.buttons, button = _a.button, modifiers = _a.modifiers;
if (!inside || _this.isInteracting)
return;
// console.log('move');
_this.move(x, y, buttons, button, modifiers);
});
input.leave.subscribe(function () {
// console.log('leave');
_this.leave();
});
input.click.subscribe(function (_a) {
var x = _a.x, y = _a.y, buttons = _a.buttons, button = _a.button, modifiers = _a.modifiers;
if (_this.outsideViewport(x, y))
return;
// console.log('click');
_this.click(x, y, buttons, button, modifiers);
});
input.interactionEnd.subscribe(function () {
// console.log('interactionEnd');
_this.isInteracting = false;
});
input.modifiers.subscribe(function (modifiers) {
// console.log('modifiers');
_this.modify(modifiers);
});
}
Canvas3dInteractionHelper.prototype.setProps = function (props) {
Object.assign(this.props, props);
};
Canvas3dInteractionHelper.prototype.identify = function (e, t) {
var xyChanged = this.startX !== this.endX || this.startY !== this.endY;
if (e === 2 /* Drag */) {
if (xyChanged && !Representation.Loci.isEmpty(this.prevLoci)) {
this.events.drag.next({ current: this.prevLoci, buttons: this.buttons, button: this.button, modifiers: this.modifiers, pageStart: Vec2.create(this.startX, this.startY), pageEnd: Vec2.create(this.endX, this.endY) });
this.startX = this.endX;
this.startY = this.endY;
}
return;
}
if (xyChanged) {
var pickData = this.canvasIdentify(this.endX, this.endY);
this.id = pickData === null || pickData === void 0 ? void 0 : pickData.id;
this.position = pickData === null || pickData === void 0 ? void 0 : pickData.position;
this.startX = this.endX;
this.startY = this.endY;
}
if (e === 1 /* Click */) {
var loci_1 = this.getLoci(this.id, this.position);
this.events.click.next({ current: loci_1, buttons: this.buttons, button: this.button, modifiers: this.modifiers, page: Vec2.create(this.endX, this.endY), position: this.position });
this.prevLoci = loci_1;
return;
}
if (!this.inside || this.currentIdentifyT !== t || !xyChanged || this.outsideViewport(this.endX, this.endY))
return;
var loci = this.getLoci(this.id, this.position);
this.events.hover.next({ current: loci, buttons: this.buttons, button: this.button, modifiers: this.modifiers, page: Vec2.create(this.endX, this.endY), position: this.position });
this.prevLoci = loci;
};
Canvas3dInteractionHelper.prototype.tick = function (t) {
if (this.inside && t - this.prevT > 1000 / this.props.maxFps) {
this.prevT = t;
this.currentIdentifyT = t;
this.identify(this.isInteracting ? 2 /* Drag */ : 0 /* Move */, t);
}
};
Canvas3dInteractionHelper.prototype.leave = function () {
this.inside = false;
if (!Representation.Loci.isEmpty(this.prevLoci)) {
this.prevLoci = Representation.Loci.Empty;
this.events.hover.next({ current: this.prevLoci, buttons: this.buttons, button: this.button, modifiers: this.modifiers });
}
};
Canvas3dInteractionHelper.prototype.move = function (x, y, buttons, button, modifiers) {
this.inside = true;
this.buttons = buttons;
this.button = button;
this.modifiers = modifiers;
this.endX = x;
this.endY = y;
};
Canvas3dInteractionHelper.prototype.click = function (x, y, buttons, button, modifiers) {
this.endX = x;
this.endY = y;
this.buttons = buttons;
this.button = button;
this.modifiers = modifiers;
this.identify(1 /* Click */, 0);
};
Canvas3dInteractionHelper.prototype.drag = function (x, y, buttons, button, modifiers) {
this.endX = x;
this.endY = y;
this.buttons = buttons;
this.button = button;
this.modifiers = modifiers;
this.identify(2 /* Drag */, 0);
};
Canvas3dInteractionHelper.prototype.modify = function (modifiers) {
if (ModifiersKeys.areEqual(modifiers, this.modifiers))
return;
this.modifiers = modifiers;
this.events.hover.next({ current: this.prevLoci, buttons: this.buttons, button: this.button, modifiers: this.modifiers, page: Vec2.create(this.endX, this.endY), position: this.position });
};
Canvas3dInteractionHelper.prototype.outsideViewport = function (x, y) {
var _a = this, input = _a.input, viewport = _a.camera.viewport;
x *= input.pixelRatio;
y *= input.pixelRatio;
return (x > viewport.x + viewport.width ||
input.height - y > viewport.y + viewport.height ||
x < viewport.x ||
input.height - y < viewport.y);
};
Canvas3dInteractionHelper.prototype.getLoci = function (pickingId, position) {
var _a;
var _b = this.lociGetter(pickingId), repr = _b.repr, loci = _b.loci;
if (position && repr && Bond.isLoci(loci) && loci.bonds.length === 2) {
var _c = loci.bonds[0], aUnit = _c.aUnit, aIndex = _c.aIndex;
aUnit.conformation.position(aUnit.elements[aIndex], tmpPosA);
Vec3.sub(tmpNorm, this.camera.state.position, this.camera.state.target);
Vec3.projectPointOnPlane(tmpPos, position, tmpNorm, tmpPosA);
var pixelSize = this.camera.getPixelSize(tmpPos);
var radius = repr.theme.size.size(loci.bonds[0]) * ((_a = repr.props.sizeFactor) !== null && _a !== void 0 ? _a : 1);
if (repr.props.lineSizeAttenuation === false) {
// divide by two to get radius
radius *= pixelSize / 2;
}
radius += this.props.preferAtomPixelPadding * pixelSize;
if (Vec3.distance(tmpPos, tmpPosA) < radius) {
return { repr: repr, loci: Bond.toFirstStructureElementLoci(loci) };
}
}
return { repr: repr, loci: loci };
};
Canvas3dInteractionHelper.prototype.dispose = function () {
this.ev.dispose();
};
return Canvas3dInteractionHelper;
}());
export { Canvas3dInteractionHelper };
//# sourceMappingURL=interaction-events.js.map