@needle-tools/engine
Version:
Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in
156 lines • 6.05 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { MathUtils } from "three";
import { TransformControls } from "three/examples/jsm/controls/TransformControls.js";
import * as params from "../engine/engine_default_parameters.js";
import { serializable } from "../engine/engine_serialization_decorator.js";
import { Behaviour, GameObject } from "./Component.js";
import { OrbitControls } from "./OrbitControls.js";
import { SyncedTransform } from "./SyncedTransform.js";
/**
* TransformGizmo is a component that displays a gizmo for transforming the object in the scene.
* @category Helpers
* @group Components
*/
export class TransformGizmo extends Behaviour {
isGizmo = false;
translationSnap = 1;
rotationSnapAngle = 15;
scaleSnap = .25;
control;
orbit;
/** @internal */
onEnable() {
if (this.isGizmo && !params.showGizmos)
return;
if (!this.context.mainCamera)
return;
if (!this.control) {
this.control = new TransformControls(this.context.mainCamera, this.context.renderer.domElement);
this.control.visible = true;
this.control.enabled = true;
this.control.getRaycaster().layers.set(2);
this.control.size = 1;
this.control.traverse(x => {
const mesh = x;
mesh.layers.set(2);
if (mesh) {
const gizmoMat = mesh.material;
if (gizmoMat) {
gizmoMat.opacity = 0.3;
}
}
});
this.orbit = GameObject.getComponentInParent(this.context.mainCamera, OrbitControls) ?? undefined;
}
if (this.control) {
this.context.scene.add(this.control);
this.control.attach(this.gameObject);
this.control?.addEventListener('dragging-changed', this.onControlChangedEvent);
window.addEventListener('keydown', this.windowKeyDownListener);
window.addEventListener('keyup', this.windowKeyUpListener);
}
}
/** @internal */
onDisable() {
this.control?.removeFromParent();
this.control?.removeEventListener('dragging-changed', this.onControlChangedEvent);
window.removeEventListener('keydown', this.windowKeyDownListener);
window.removeEventListener('keyup', this.windowKeyUpListener);
}
enableSnapping() {
if (this.control) {
this.control.setTranslationSnap(this.translationSnap);
this.control.setRotationSnap(MathUtils.degToRad(this.rotationSnapAngle));
this.control.setScaleSnap(this.scaleSnap);
}
}
disableSnapping() {
if (this.control) {
this.control.setTranslationSnap(null);
this.control.setRotationSnap(null);
this.control.setScaleSnap(null);
}
}
onControlChangedEvent = (event) => {
const orbit = this.orbit;
if (orbit)
orbit.enabled = !event.value;
if (event.value) {
// request ownership on drag start
const sync = GameObject.getComponentInParent(this.gameObject, SyncedTransform);
if (sync) {
sync.requestOwnership();
}
}
};
windowKeyDownListener = (event) => {
if (!this.enabled)
return;
if (!this.control)
return;
switch (event.keyCode) {
case 81: // Q
this.control.setSpace(this.control.space === 'local' ? 'world' : 'local');
break;
case 16: // Shift
this.enableSnapping();
break;
case 87: // W
this.control.setMode('translate');
break;
case 69: // E
this.control.setMode('rotate');
break;
case 82: // R
this.control.setMode('scale');
break;
case 187:
case 107: // +, =, num+
this.control.setSize(this.control.size + 0.1);
break;
case 189:
case 109: // -, _, num-
this.control.setSize(Math.max(this.control.size - 0.1, 0.1));
break;
case 88: // X
this.control.showX = !this.control.showX;
break;
case 89: // Y
this.control.showY = !this.control.showY;
break;
case 90: // Z
this.control.showZ = !this.control.showZ;
break;
case 32: // Spacebar
this.control.enabled = !this.control.enabled;
break;
}
};
windowKeyUpListener = (event) => {
if (!this.enabled)
return;
switch (event.keyCode) {
case 16: // Shift
this.disableSnapping();
break;
}
};
}
__decorate([
serializable()
], TransformGizmo.prototype, "isGizmo", void 0);
__decorate([
serializable()
], TransformGizmo.prototype, "translationSnap", void 0);
__decorate([
serializable()
], TransformGizmo.prototype, "rotationSnapAngle", void 0);
__decorate([
serializable()
], TransformGizmo.prototype, "scaleSnap", void 0);
//# sourceMappingURL=TransformGizmo.js.map