Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gizmo fixes #6763

Merged
merged 11 commits into from
Jun 28, 2024
Prev Previous commit
Next Next commit
gizmo jsdoc and format cleanup
  • Loading branch information
kpal81xd committed Jun 28, 2024
commit 2d620387097ac7418af3d3dc024a0df5bcb26f2f
87 changes: 60 additions & 27 deletions src/extras/gizmo/gizmo.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ class Gizmo extends EventHandler {

this._app = app;
this._device = app.graphicsDevice;
this._deviceStartSize = Math.max(this._device.width, this._device.height);
this._camera = camera;
this._layer = layer;

Expand All @@ -256,32 +255,9 @@ class Gizmo extends EventHandler {

this._updateScale();

this._onPointerDown = (e) => {
if (!this.root.enabled || document.pointerLockElement) {
return;
}
const selection = this._getSelection(e.offsetX, e.offsetY);
if (selection[0]) {
e.preventDefault();
}
this.fire(Gizmo.EVENT_POINTERDOWN, e.offsetX, e.offsetY, selection[0]);
};
this._onPointerMove = (e) => {
if (!this.root.enabled || document.pointerLockElement) {
return;
}
const selection = this._getSelection(e.offsetX, e.offsetY);
if (selection[0]) {
e.preventDefault();
}
this.fire(Gizmo.EVENT_POINTERMOVE, e.offsetX, e.offsetY, selection[0]);
};
this._onPointerUp = (e) => {
if (!this.root.enabled || document.pointerLockElement) {
return;
}
this.fire(Gizmo.EVENT_POINTERUP);
};
this._onPointerDown = this._onPointerDown.bind(this);
this._onPointerMove = this._onPointerMove.bind(this);
this._onPointerUp = this._onPointerUp.bind(this);

this._device.canvas.addEventListener('pointerdown', this._onPointerDown);
this._device.canvas.addEventListener('pointermove', this._onPointerMove);
Expand Down Expand Up @@ -335,6 +311,49 @@ class Gizmo extends EventHandler {
return this._size;
}

/**
* @param {PointerEvent} e - The pointer event.
* @private
*/
_onPointerDown(e) {
if (!this.root.enabled || document.pointerLockElement) {
return;
}
const selection = this._getSelection(e.offsetX, e.offsetY);
if (selection[0]) {
e.preventDefault();
}
this.fire(Gizmo.EVENT_POINTERDOWN, e.offsetX, e.offsetY, selection[0]);
}

/**
* @param {PointerEvent} e - The pointer event.
* @private
*/
_onPointerMove(e) {
if (!this.root.enabled || document.pointerLockElement) {
return;
}
const selection = this._getSelection(e.offsetX, e.offsetY);
if (selection[0]) {
e.preventDefault();
}
this.fire(Gizmo.EVENT_POINTERMOVE, e.offsetX, e.offsetY, selection[0]);
}

/**
* @private
*/
_onPointerUp() {
if (!this.root.enabled || document.pointerLockElement) {
return;
}
this.fire(Gizmo.EVENT_POINTERUP);
}

/**
* @protected
*/
_updatePosition() {
tmpV1.set(0, 0, 0);
for (let i = 0; i < this.nodes.length; i++) {
Expand All @@ -347,6 +366,9 @@ class Gizmo extends EventHandler {
this.fire(Gizmo.EVENT_POSITIONUPDATE, tmpV1);
}

/**
* @protected
*/
_updateRotation() {
tmpV1.set(0, 0, 0);
if (this._coordSpace === GIZMO_LOCAL && this.nodes.length !== 0) {
Expand All @@ -357,6 +379,9 @@ class Gizmo extends EventHandler {
this.fire(Gizmo.EVENT_ROTATIONUPDATE, tmpV1);
}

/**
* @protected
*/
_updateScale() {
if (this._camera.projection === PROJECTION_PERSPECTIVE) {
const gizmoPos = this.root.getPosition();
Expand All @@ -372,6 +397,12 @@ class Gizmo extends EventHandler {
this.fire(Gizmo.EVENT_SCALEUPDATE, this._scale);
}

/**
* @param {number} x - The x coordinate.
* @param {number} y - The y coordinate.
* @returns {import('../../scene/mesh-instance.js').MeshInstance[]} - The mesh instances.
* @private
*/
_getSelection(x, y) {
const start = this._camera.screenToWorld(x, y, this._camera.nearClip);
const end = this._camera.screenToWorld(x, y, this._camera.farClip);
Expand All @@ -383,6 +414,8 @@ class Gizmo extends EventHandler {
const parentTM = parent.getWorldTransform();
for (let j = 0; j < triData.length; j++) {
const { tris, transform, priority } = triData[j];

// combine node world transform with transform of tri relative to parent
const triWTM = tmpM1.copy(parentTM).mul(transform);
const invTriWTM = tmpM2.copy(triWTM).invert();

Expand Down
92 changes: 74 additions & 18 deletions src/extras/gizmo/rotate-gizmo.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { PROJECTION_ORTHOGRAPHIC, PROJECTION_PERSPECTIVE } from '../../scene/con

import { AxisDisk } from './axis-shapes.js';
import { GIZMO_LOCAL } from './gizmo.js';
import { TransformGizmo } from "./transform-gizmo.js";
import { SHAPEAXIS_FACE, SHAPEAXIS_X, SHAPEAXIS_Y, SHAPEAXIS_Z, TransformGizmo } from "./transform-gizmo.js";

// temporary variables
const tmpV1 = new Vec3();
Expand All @@ -28,31 +28,31 @@ const ROTATE_SCALE = 900;
class RotateGizmo extends TransformGizmo {
_shapes = {
z: new AxisDisk(this._device, {
axis: 'z',
axis: SHAPEAXIS_Z,
layers: [this._layer.id],
rotation: new Vec3(90, 0, 90),
defaultColor: this._meshColors.axis.z,
hoverColor: this._meshColors.hover.z,
sectorAngle: 180
}),
x: new AxisDisk(this._device, {
axis: 'x',
axis: SHAPEAXIS_X,
layers: [this._layer.id],
rotation: new Vec3(0, 0, -90),
defaultColor: this._meshColors.axis.x,
hoverColor: this._meshColors.hover.x,
sectorAngle: 180
}),
y: new AxisDisk(this._device, {
axis: 'y',
axis: SHAPEAXIS_Y,
layers: [this._layer.id],
rotation: new Vec3(0, 0, 0),
defaultColor: this._meshColors.axis.y,
hoverColor: this._meshColors.hover.y,
sectorAngle: 180
}),
face: new AxisDisk(this._device, {
axis: 'face',
axis: SHAPEAXIS_FACE,
layers: [this._layer.id],
rotation: this._getLookAtEulerAngles(this._camera.entity.getPosition()),
defaultColor: this._meshColors.axis.face,
Expand Down Expand Up @@ -129,7 +129,7 @@ class RotateGizmo extends TransformGizmo {

this._createTransform();

this.on('transform:start', () => {
this.on(TransformGizmo.EVENT_TRANSFORMSTART, () => {
this._storeNodeRotations();

// store guide points
Expand All @@ -139,7 +139,7 @@ class RotateGizmo extends TransformGizmo {
this._drag(true);
});

this.on('transform:move', (pointDelta, angleDelta) => {
this.on(TransformGizmo.EVENT_TRANSFORMMOVE, (pointDelta, angleDelta) => {
const axis = this._selectedAxis;

if (this.snap) {
Expand All @@ -150,11 +150,11 @@ class RotateGizmo extends TransformGizmo {
this._updateGuidePoints(angleDelta);
});

this.on('transform:end', () => {
this.on(TransformGizmo.EVENT_TRANSFORMEND, () => {
this._drag(false);
});

this.on('nodes:detach', () => {
this.on(TransformGizmo.EVENT_NODESDETACH, () => {
this._nodeLocalRotations.clear();
this._nodeRotations.clear();
this._nodeOffsets.clear();
Expand Down Expand Up @@ -264,28 +264,40 @@ class RotateGizmo extends TransformGizmo {
return this._shapes.x.tolerance;
}

/**
* @param {string} prop - The property.
* @param {any} value - The value.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the type here number?

* @private
*/
_setDiskProp(prop, value) {
this._shapes.x[prop] = value;
this._shapes.y[prop] = value;
this._shapes.z[prop] = value;
}

/**
* @private
*/
_storeGuidePoints() {
const gizmoPos = this.root.getPosition();
const axis = this._selectedAxis;
const isFacing = axis === 'face';
const isFacing = axis === SHAPEAXIS_FACE;
const scale = isFacing ? this.faceRingRadius : this.xyzRingRadius;

this._guideAngleStart.copy(this._selectionStartPoint).sub(gizmoPos).normalize();
this._guideAngleStart.mulScalar(scale);
this._guideAngleEnd.copy(this._guideAngleStart);
}

/**
* @param {number} angleDelta - The angle delta.
* @private
*/
_updateGuidePoints(angleDelta) {
const gizmoPos = this.root.getPosition();
const cameraPos = this._camera.entity.getPosition();
const axis = this._selectedAxis;
const isFacing = axis === 'face';
const isFacing = axis === SHAPEAXIS_FACE;

tmpV1.set(0, 0, 0);
if (isFacing) {
Expand All @@ -298,12 +310,24 @@ class RotateGizmo extends TransformGizmo {
tmpQ1.transformVector(this._guideAngleStart, this._guideAngleEnd);
}

/**
* @param {Vec3} pos - The position.
* @param {string} axis - The axis.
* @param {Vec3} point - The point.
* @param {Color} [color] - The color.
* @private
*/
_drawGuideAngleLine(pos, axis, point, color = this._guideColors[axis]) {
tmpV1.set(0, 0, 0);
tmpV2.copy(point).mulScalar(this._scale);
this._app.drawLine(tmpV1.add(pos), tmpV2.add(pos), color, false, this._layer);
}

/**
* @param {Vec3} position - The position.
* @returns {Vec3} The look at euler angles.
* @private
*/
_getLookAtEulerAngles(position) {
tmpV1.set(0, 0, 0);
tmpM1.setLookAt(tmpV1, position, Vec3.UP);
Expand All @@ -313,6 +337,9 @@ class RotateGizmo extends TransformGizmo {
return tmpV1;
}

/**
* @private
*/
_faceAxisLookAtCamera() {
if (this._camera.projection === PROJECTION_PERSPECTIVE) {
this._shapes.face.entity.lookAt(this._camera.entity.getPosition());
Expand All @@ -325,6 +352,9 @@ class RotateGizmo extends TransformGizmo {
}
}

/**
* @private
*/
_xyzAxisLookAtCamera() {
if (this._camera.projection === PROJECTION_PERSPECTIVE) {
const gizmoPos = this.root.getPosition();
Expand All @@ -342,6 +372,10 @@ class RotateGizmo extends TransformGizmo {
this._shapes.z.entity.setLocalEulerAngles(90, 0, angle + 90);
}

/**
* @param {boolean} state - The state.
* @private
*/
_drag(state) {
for (const axis in this._shapes) {
const shape = this._shapes[axis];
Expand All @@ -351,9 +385,12 @@ class RotateGizmo extends TransformGizmo {
shape.hide(state);
}
}
this.fire('render:update');
this.fire(TransformGizmo.EVENT_RENDERUPDATE);
}

/**
* @private
*/
_storeNodeRotations() {
const gizmoPos = this.root.getPosition();
for (let i = 0; i < this.nodes.length; i++) {
Expand All @@ -364,12 +401,21 @@ class RotateGizmo extends TransformGizmo {
}
}

/**
* @param {string} axis - The axis.
* @param {number} angleDelta - The angle delta.
* @private
*/
_setNodeRotations(axis, angleDelta) {
const gizmoPos = this.root.getPosition();
const cameraPos = this._camera.entity.getPosition();
const isFacing = axis === 'face';
const isFacing = axis === SHAPEAXIS_FACE;
for (let i = 0; i < this.nodes.length; i++) {
const node = this.nodes[i];
const rot = this._nodeRotations.get(node);
if (!rot) {
continue;
}

if (isFacing) {
tmpV1.copy(cameraPos).sub(gizmoPos).normalize();
Expand All @@ -381,12 +427,16 @@ class RotateGizmo extends TransformGizmo {
tmpQ1.setFromAxisAngle(tmpV1, angleDelta);

if (!isFacing && this._coordSpace === GIZMO_LOCAL) {
tmpQ2.copy(this._nodeLocalRotations.get(node)).mul(tmpQ1);
tmpQ2.copy(rot).mul(tmpQ1);
node.setLocalRotation(tmpQ2);
} else {
tmpV1.copy(this._nodeOffsets.get(node));
const offset = this._nodeOffsets.get(node);
if (!offset) {
continue;
}
tmpV1.copy(offset);
tmpQ1.transformVector(tmpV1, tmpV1);
tmpQ2.copy(tmpQ1).mul(this._nodeRotations.get(node));
tmpQ2.copy(tmpQ1).mul(rot);

// N.B. Rotation via quaternion when scale inverted causes scale warping?
node.setEulerAngles(tmpQ2.getEulerAngles());
Expand All @@ -399,14 +449,20 @@ class RotateGizmo extends TransformGizmo {
}
}

/**
* @param {number} x - The x coordinate.
* @param {number} y - The y coordinate.
* @returns {{ point: Vec3, angle: number }} The point and angle.
* @protected
*/
_screenToPoint(x, y) {
const gizmoPos = this.root.getPosition();
const mouseWPos = this._camera.screenToWorld(x, y, 1);

const axis = this._selectedAxis;

const ray = this._createRay(mouseWPos);
const plane = this._createPlane(axis, axis === 'face', false);
const plane = this._createPlane(axis, axis === SHAPEAXIS_FACE, false);

const point = new Vec3();
let angle = 0;
Expand All @@ -416,7 +472,7 @@ class RotateGizmo extends TransformGizmo {
// calculate angle
const facingDir = tmpV1.sub2(ray.origin, gizmoPos).normalize();
const facingDot = plane.normal.dot(facingDir);
if (axis === 'face' || Math.abs(facingDot) > FACING_THRESHOLD) {
if (axis === SHAPEAXIS_FACE || Math.abs(facingDot) > FACING_THRESHOLD) {
// plane facing camera so based on mouse position around gizmo
tmpQ1.copy(this._camera.entity.getRotation()).invert();

Expand Down
Loading