@mlightcad/three-viewcube
Version:
A highly customizable standalone view cube addon for three.js
266 lines • 11.9 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
import * as THREE from 'three';
import { DEFAULT_FACENAMES } from './faceNames';
import { FACES } from './viewCubeData';
import { ViewCube } from './viewCube';
import { FixedPosGizmo, ObjectPosition } from './fixedPosGizmo';
var MAIN_COLOR = 0xdddddd;
var HOVER_COLOR = 0xf2f5ce;
var OUTLINE_COLOR = 0xcccccc;
/**
* Default view cube option values
*/
export var DEFAULT_VIEWCUBE_OPTIONS = {
pos: ObjectPosition.RIGHT_TOP,
dimension: 150,
faceColor: MAIN_COLOR,
hoverColor: HOVER_COLOR,
outlineColor: OUTLINE_COLOR,
faceNames: DEFAULT_FACENAMES,
fontSize: 60,
};
/**
* A highly customizable standalone view cube gizmo for three.js.
*/
var ViewCubeGizmo = /** @class */ (function (_super) {
__extends(ViewCubeGizmo, _super);
/**
* Construct one instance of view cube gizmo
* @param camera Camera used in your canvas
* @param renderer Renderer used in your canvas
* @param options Options to customize view cube gizmo
*/
function ViewCubeGizmo(camera, renderer, options) {
if (options === void 0) { options = DEFAULT_VIEWCUBE_OPTIONS; }
var _this = this;
var mergedOptions = __assign(__assign({}, DEFAULT_VIEWCUBE_OPTIONS), options);
_this = _super.call(this, camera, renderer, options.dimension, options.pos) || this;
_this.cube = new ViewCube(2, 0.2, true, mergedOptions.faceColor, mergedOptions.outlineColor, mergedOptions.faceNames, mergedOptions.fontSize);
_this.add(_this.cube);
_this.handleMouseMove = _this.handleMouseMove.bind(_this);
_this.handleMouseClick = _this.handleMouseClick.bind(_this);
_this.listen(renderer.domElement);
return _this;
}
/**
* Free the GPU-related resources allocated by this instance. Call this method whenever this instance
* is no longer used in your app.
*/
ViewCubeGizmo.prototype.dispose = function () {
this.cube.dispose();
};
ViewCubeGizmo.prototype.listen = function (domElement) {
domElement.addEventListener('mousemove', this.handleMouseMove);
domElement.addEventListener('click', this.handleMouseClick);
};
ViewCubeGizmo.prototype.handleMouseClick = function (event) {
var bbox = this.calculateViewportBbox();
if (bbox.containsPoint(new THREE.Vector2(event.offsetX, event.offsetY))) {
var pos = this.calculatePosInViewport(event.offsetX, event.offsetY, bbox);
this.checkSideTouch(pos.x, pos.y);
}
};
ViewCubeGizmo.prototype.handleMouseMove = function (event) {
var bbox = this.calculateViewportBbox();
if (bbox.containsPoint(new THREE.Vector2(event.offsetX, event.offsetY))) {
var pos = this.calculatePosInViewport(event.offsetX, event.offsetY, bbox);
this.checkSideOver(pos.x, pos.y);
}
};
ViewCubeGizmo.prototype.checkSideTouch = function (x, y) {
var e_1, _a;
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(new THREE.Vector2(x, y), this.gizmoCamera);
var intersects = raycaster.intersectObjects(this.cube.children, true);
if (intersects.length) {
try {
for (var intersects_1 = __values(intersects), intersects_1_1 = intersects_1.next(); !intersects_1_1.done; intersects_1_1 = intersects_1.next()) {
var object = intersects_1_1.value.object;
if (object.name) {
var quaternion = this.getRotation(object.name);
this.dispatchEvent({
type: 'change',
quaternion: quaternion
});
break;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (intersects_1_1 && !intersects_1_1.done && (_a = intersects_1.return)) _a.call(intersects_1);
}
finally { if (e_1) throw e_1.error; }
}
}
};
ViewCubeGizmo.prototype.checkSideOver = function (x, y) {
var e_2, _a;
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(new THREE.Vector2(x, y), this.gizmoCamera);
var intersects = raycaster.intersectObjects(this.cube.children, true);
// unhover
this.cube.traverse(function (obj) {
if (obj.name) {
var mesh = obj;
mesh.material.color.setHex(MAIN_COLOR);
}
});
// check hover
if (intersects.length) {
var _loop_1 = function (object) {
if (object.name) {
object.parent.children.forEach(function (child) {
if (child.name === object.name) {
var mesh = child;
mesh.material.color.setHex(HOVER_COLOR);
}
});
return "break";
}
};
try {
for (var intersects_2 = __values(intersects), intersects_2_1 = intersects_2.next(); !intersects_2_1.done; intersects_2_1 = intersects_2.next()) {
var object = intersects_2_1.value.object;
var state_1 = _loop_1(object);
if (state_1 === "break")
break;
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (intersects_2_1 && !intersects_2_1.done && (_a = intersects_2.return)) _a.call(intersects_2);
}
finally { if (e_2) throw e_2.error; }
}
}
};
ViewCubeGizmo.prototype.getRotation = function (side) {
var targetQuaternion = new THREE.Quaternion();
switch (side) {
case FACES.FRONT:
targetQuaternion.setFromEuler(new THREE.Euler());
break;
case FACES.RIGHT:
targetQuaternion.setFromEuler(new THREE.Euler(0, Math.PI * 0.5, 0));
break;
case FACES.BACK:
targetQuaternion.setFromEuler(new THREE.Euler(0, Math.PI, 0));
break;
case FACES.LEFT:
targetQuaternion.setFromEuler(new THREE.Euler(0, -Math.PI * 0.5, 0));
break;
case FACES.TOP:
targetQuaternion.setFromEuler(new THREE.Euler(-Math.PI * 0.5, 0, 0));
break;
case FACES.BOTTOM:
targetQuaternion.setFromEuler(new THREE.Euler(Math.PI * 0.5, 0, 0));
break;
case FACES.TOP_FRONT_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(-Math.PI * 0.25, 0, 0));
break;
case FACES.TOP_RIGHT_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(-Math.PI * 0.25, Math.PI * 0.5, 0, 'YXZ'));
break;
case FACES.TOP_BACK_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(-Math.PI * 0.25, Math.PI, 0, 'YXZ'));
break;
case FACES.TOP_LEFT_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(-Math.PI * 0.25, -Math.PI * 0.5, 0, 'YXZ'));
break;
case FACES.BOTTOM_FRONT_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(Math.PI * 0.25, 0, 0));
break;
case FACES.BOTTOM_RIGHT_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(Math.PI * 0.25, Math.PI * 0.5, 0, 'YXZ'));
break;
case FACES.BOTTOM_BACK_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(Math.PI * 0.25, Math.PI, 0, 'YXZ'));
break;
case FACES.BOTTOM_LEFT_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(Math.PI * 0.25, -Math.PI * 0.5, 0, 'YXZ'));
break;
case FACES.FRONT_RIGHT_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(0, Math.PI * 0.25, 0));
break;
case FACES.BACK_RIGHT_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(0, Math.PI * 0.75, 0));
break;
case FACES.BACK_LEFT_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(0, -Math.PI * 0.75, 0));
break;
case FACES.FRONT_LEFT_EDGE:
targetQuaternion.setFromEuler(new THREE.Euler(0, -Math.PI * 0.25, 0));
break;
case FACES.TOP_FRONT_RIGHT_CORNER:
targetQuaternion.setFromEuler(new THREE.Euler(-Math.PI * 0.25, -Math.PI * 1.75, 0));
break;
case FACES.TOP_BACK_RIGHT_CORNER:
targetQuaternion.setFromEuler(new THREE.Euler(Math.PI * 0.25, -Math.PI * 1.25, 0));
break;
case FACES.TOP_BACK_LEFT_CORNER:
targetQuaternion.setFromEuler(new THREE.Euler(Math.PI * 0.25, -Math.PI * 0.75, 0));
break;
case FACES.TOP_FRONT_LEFT_CORNER:
targetQuaternion.setFromEuler(new THREE.Euler(-Math.PI * 0.25, -Math.PI * 0.25, 0));
break;
case FACES.BOTTOM_FRONT_RIGHT_CORNER:
targetQuaternion.setFromEuler(new THREE.Euler(Math.PI * 0.25, -Math.PI * 1.75, 0));
break;
case FACES.BOTTOM_BACK_RIGHT_CORNER:
targetQuaternion.setFromEuler(new THREE.Euler(-Math.PI * 0.25, -Math.PI * 1.25, 0));
break;
case FACES.BOTTOM_BACK_LEFT_CORNER:
targetQuaternion.setFromEuler(new THREE.Euler(-Math.PI * 0.25, -Math.PI * 0.75, 0));
break;
case FACES.BOTTOM_FRONT_LEFT_CORNER:
targetQuaternion.setFromEuler(new THREE.Euler(Math.PI * 0.25, -Math.PI * 0.25, 0));
break;
default:
console.error("[ViewCubeGizmo]: Invalid face, edge, or corner name '".concat(side, "'!"));
break;
}
return targetQuaternion;
};
return ViewCubeGizmo;
}(FixedPosGizmo));
export { ViewCubeGizmo };
//# sourceMappingURL=viewCubeGizmo.js.map