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 example update #6622

Merged
merged 6 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/iframe/example.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
body {
margin: 0;
overflow-y: hidden;
background-color: #000;
}

#application-canvas {
width: 100%;
height: 100%;
Expand Down
55 changes: 18 additions & 37 deletions examples/src/examples/misc/gizmos.example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ if (!(canvas instanceof HTMLCanvasElement)) {

// class for handling gizmo
const { GizmoHandler } = await localImport('gizmo-handler.mjs');
const { Grid } = await localImport('grid.mjs');
const { Selector } = await localImport('selector.mjs');

const gfxOptions = {
deviceTypes: [deviceType],
Expand Down Expand Up @@ -162,14 +164,14 @@ const setType = (/** @type {string} */ value) => {

// call method from top context (same as controls)
// @ts-ignore
window.top.setType(value);
window.top.setType?.(value);
};
const setProj = (/** @type {number} */ value) => {
data.set('camera.proj', value + 1);

// call method from top context (same as controls)
// @ts-ignore
window.top.setProj(value);
window.top.setProj?.(value);
};

// key event handlers
Expand Down Expand Up @@ -209,7 +211,7 @@ window.addEventListener('keypress', keypress);

// gizmo and camera set handler
const tmpC = new pc.Color();
data.on('*:set', (/** @type {string} */ path, value) => {
data.on('*:set', (/** @type {string} */ path, /** @type {any} */ value) => {
const pathArray = path.split('.');

switch (pathArray[0]) {
Expand Down Expand Up @@ -246,55 +248,34 @@ data.on('*:set', (/** @type {string} */ path, value) => {
}
});

// picker
const picker = new pc.Picker(app, canvas.clientWidth, canvas.clientHeight);
const worldLayer = layers.getLayerByName('World');
const pickerLayers = [worldLayer];

const onPointerDown = (/** @type {PointerEvent} */ e) => {
// selector
const selector = new Selector(app, camera.camera, [layers.getLayerByName('World')]);
selector.on('select', (/** @type {pc.GraphNode} */ node, /** @type {boolean} */ clear) => {
if (gizmoHandler.ignorePicker) {
return;
}

if (picker) {
picker.resize(canvas.clientWidth, canvas.clientHeight);
picker.prepare(camera.camera, app.scene, pickerLayers);
}

picker.getSelectionAsync(e.clientX - 1, e.clientY - 1, 2, 2).then((selection) => {
if (!selection[0]) {
gizmoHandler.clear();
return;
}

gizmoHandler.add(selection[0].node, !e.ctrlKey && !e.metaKey);
});
};
window.addEventListener('pointerdown', onPointerDown);
gizmoHandler.add(node, clear);
});
selector.on('deselect', () => {
gizmoHandler.clear();
});

// grid
const gridColor = new pc.Color(1, 1, 1, 0.5);
const gridHalfSize = 4;
/**
* @type {pc.Vec3[]}
*/
const gridLines = [];
for (let i = 0; i < gridHalfSize * 2 + 1; i++) {
gridLines.push(new pc.Vec3(-gridHalfSize, 0, i - gridHalfSize), new pc.Vec3(gridHalfSize, 0, i - gridHalfSize));
gridLines.push(new pc.Vec3(i - gridHalfSize, 0, -gridHalfSize), new pc.Vec3(i - gridHalfSize, 0, gridHalfSize));
}
app.on('update', () => {
app.drawLines(gridLines, gridColor);
const grid = new Grid();

app.on('update', (/** @type {number} */ dt) => {
grid.draw(app);
});

app.on('destroy', () => {
gizmoHandler.destroy();
selector.destroy();

window.removeEventListener('resize', resize);
window.removeEventListener('keydown', keydown);
window.removeEventListener('keyup', keyup);
window.removeEventListener('keypress', keypress);
window.removeEventListener('pointerdown', onPointerDown);
});

export { app };
77 changes: 77 additions & 0 deletions examples/src/examples/misc/gizmos.grid.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as pc from 'playcanvas';

class Grid {
/**
* @type {pc.Vec3[]}
* @private
*/
_lines = [];

/**
* @type {pc.Color}
* @private
*/
_color = new pc.Color(1, 1, 1, 0.5);

/**
* @type {pc.Vec2}
* @private
*/
_halfExtents = new pc.Vec2(4, 4);

constructor() {
this._setLines();
}

set halfExtents(value) {
this._halfExtents.copy(value);
this._setLines();
}

get halfExtents() {
return this._halfExtents;
}

set color(value) {
this._color.copy(value);
}

get color() {
return this._color;
}

/**
* @private
*/
_setLines() {
this._lines = [
new pc.Vec3(-this._halfExtents.x, 0, 0),
new pc.Vec3(this._halfExtents.x, 0, 0),
new pc.Vec3(0, 0, -this._halfExtents.y),
new pc.Vec3(0, 0, this._halfExtents.y)
];
for (let i = -this._halfExtents.x; i <= this._halfExtents.x; i++) {
if (i === 0) {
continue;
}
this._lines.push(new pc.Vec3(i, 0, -this._halfExtents.y));
this._lines.push(new pc.Vec3(i, 0, this._halfExtents.y));
}
for (let i = -this._halfExtents.y; i <= this._halfExtents.y; i++) {
if (i === 0) {
continue;
}
this._lines.push(new pc.Vec3(-this._halfExtents.x, 0, i));
this._lines.push(new pc.Vec3(this._halfExtents.x, 0, i));
}
}

/**
* @param {pc.AppBase} app - The app.
*/
draw(app) {
app.drawLines(this._lines, this._color);
}
}

export { Grid };
93 changes: 93 additions & 0 deletions examples/src/examples/misc/gizmos.selector.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import * as pc from 'playcanvas';

class Selector extends pc.EventHandler {
/**
* @type {pc.CameraComponent}
* @private
*/
_camera;

/**
* @type {pc.Scene}
* @private
*/
_scene;

/**
* @type {pc.Picker}
* @private
*/
_picker;

/**
* @type {pc.Layer[]}
* @private
*/
_layers;

/**
* @type {pc.Vec2}
* @private
*/
_start = new pc.Vec2();

/**
* @param {pc.AppBase} app - The app.
* @param {pc.CameraComponent} camera - The camera to pick from.
* @param {pc.Layer[]} [layers] - The layers to pick from.
*/
constructor(app, camera, layers = []) {
super();
this._camera = camera;
this._scene = app.scene;
const device = app.graphicsDevice;
this._picker = new pc.Picker(app, device.canvas.width, device.canvas.height);
this._layers = layers;

this._onPointerDown = this._onPointerDown.bind(this);
this._onPointerUp = this._onPointerUp.bind(this);

window.addEventListener('pointerdown', this._onPointerDown);
window.addEventListener('pointerup', this._onPointerUp);
}

/**
* @param {MouseEvent} e - The event.
* @private
*/
_onPointerDown(e) {
this._start.set(e.clientX, e.clientY);
}

/**
* @param {MouseEvent} e - The event.
* @private
*/
_onPointerUp(e) {
if (e.clientX !== this._start.x || e.clientY !== this._start.y) {
return;
}

if (this._picker) {
const device = this._picker.device;
this._picker.resize(device.canvas.width, device.canvas.height);
this._picker.prepare(this._camera, this._scene, this._layers);
}

const selection = this._picker.getSelection(e.clientX, e.clientY, 2, 2);

if (!selection[0]) {
this.fire('deselect');
return;
}

this.fire('select', selection[0].node, !e.ctrlKey && !e.metaKey);
}

destroy() {
window.removeEventListener('pointerdown', this._onPointerDown);
window.removeEventListener('pointerup', this._onPointerUp);
}
}

export { Selector };