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

[BETA] ESM Multi-Camera script updates #7078

Merged
merged 7 commits into from
Oct 30, 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
35 changes: 22 additions & 13 deletions examples/src/examples/camera/multi.controls.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@
* @returns {JSX.Element} The returned JSX Element.
*/
export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
const { BindingTwoWay, LabelGroup, Panel, SliderInput } = ReactPCUI;
const { BindingTwoWay, LabelGroup, Panel, BooleanInput, SliderInput } = ReactPCUI;

return fragment(
jsx(
LabelGroup,
{ text: 'Zoom reset' },
jsx(BooleanInput, {
type: 'toggle',
binding: new BindingTwoWay(),
link: { observer, path: 'example.zoomReset' }
})
),
jsx(
Panel,
{ headerText: 'Attributes' },
Expand All @@ -14,7 +23,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Focus FOV' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.focusFov' },
link: { observer, path: 'attr.focusFov' },
min: 30,
max: 120
})
Expand All @@ -24,7 +33,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Look sensitivity' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.lookSensitivity' },
link: { observer, path: 'attr.lookSensitivity' },
min: 0.1,
max: 1,
step: 0.01
Expand All @@ -35,7 +44,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Look damping' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.lookDamping' },
link: { observer, path: 'attr.lookDamping' },
min: 0,
max: 0.99,
step: 0.01
Expand All @@ -46,7 +55,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Move damping' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.moveDamping' },
link: { observer, path: 'attr.moveDamping' },
min: 0,
max: 0.99,
step: 0.01
Expand All @@ -57,7 +66,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Pinch speed' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.pinchSpeed' },
link: { observer, path: 'attr.pinchSpeed' },
min: 1,
max: 10
})
Expand All @@ -67,7 +76,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Wheel speed' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.wheelSpeed' },
link: { observer, path: 'attr.wheelSpeed' },
min: 0.001,
max: 0.01,
step: 0.001
Expand All @@ -78,7 +87,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Zoom min' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.zoomMin' },
link: { observer, path: 'attr.zoomMin' },
min: 0.001,
max: 0.01,
step: 0.001
Expand All @@ -89,7 +98,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Zoom max' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.zoomMax' },
link: { observer, path: 'attr.zoomMax' },
min: 1,
max: 10
})
Expand All @@ -99,7 +108,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Zoom scale min' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.zoomScaleMin' },
link: { observer, path: 'attr.zoomScaleMin' },
min: 0.001,
max: 0.01,
step: 0.001
Expand All @@ -110,7 +119,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Move speed' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.moveSpeed' },
link: { observer, path: 'attr.moveSpeed' },
min: 1,
max: 10
})
Expand All @@ -120,7 +129,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Sprint speed' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.sprintSpeed' },
link: { observer, path: 'attr.sprintSpeed' },
min: 1,
max: 10
})
Expand All @@ -130,7 +139,7 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
{ text: 'Crouch speed' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'camera.crouchSpeed' },
link: { observer, path: 'attr.crouchSpeed' },
min: 1,
max: 10
})
Expand Down
56 changes: 41 additions & 15 deletions examples/src/examples/camera/multi.example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -60,27 +60,51 @@ await new Promise((resolve) => {
new pc.AssetListLoader(Object.values(assets), app.assets).load(resolve);
});

/**
* Calculate the bounding box of an entity.
*
* @param {pc.BoundingBox} bbox - The bounding box.
* @param {pc.Entity} entity - The entity.
* @returns {pc.BoundingBox} The bounding box.
*/
const calcEntityAABB = (bbox, entity) => {
bbox.center.set(0, 0, 0);
bbox.halfExtents.set(0, 0, 0);
entity.findComponents('render').forEach((render) => {
render.meshInstances.forEach((/** @type {pc.MeshInstance} */ mi) => {
bbox.add(mi.aabb);
});
});
return bbox;
};

/**
* @param {pc.Entity} focus - The entity to focus the camera on.
* @returns {pc.Entity} The multi-camera entity.
* @returns {MultiCamera} The multi-camera script.
*/
const createMultiCamera = (focus) => {
const camera = new pc.Entity();
camera.addComponent('camera');
camera.addComponent('script');

const start = new pc.Vec3(0, 20, 30);
const bbox = calcEntityAABB(new pc.BoundingBox(), focus);
const cameraDist = start.distance(bbox.center);

const multiCamera = new pc.Entity();
multiCamera.addComponent('script');
const script = /** @type {MultiCamera} */ (multiCamera.script.create(MultiCamera, {
/** @type {MultiCamera} */
const script = camera.script.create(MultiCamera, {
attributes: {
target: canvas
sceneSize: bbox.halfExtents.length()
}
}));
script.attach(camera);
});

// focus on entity when 'f' key is pressed
const onKeyDown = (/** @type {KeyboardEvent} */ e) => {
if (e.key === 'f') {
script.focusOnEntity(focus);
if (data.get('example.zoomReset')) {
script.resetZoom(cameraDist);
}
script.focus(bbox.center);
}
};
window.addEventListener('keydown', onKeyDown);
Expand All @@ -90,12 +114,12 @@ const createMultiCamera = (focus) => {

// wait until after canvas resized to focus on entity
const resize = new ResizeObserver(() => {
script.focusOnEntity(focus, true);
resize.disconnect();
script.focus(bbox.center, start);
});
resize.observe(canvas);

return multiCamera;
return script;
};

app.start();
Expand All @@ -116,11 +140,13 @@ const statue = assets.statue.resource.instantiateRenderEntity();
statue.setLocalPosition(0, -0.5, 0);
app.root.addChild(statue);

const multiCamera = createMultiCamera(statue);
app.root.addChild(multiCamera);
const multiCameraScript = createMultiCamera(statue);

// Bind controls to camera attributes
data.set('camera', {
data.set('example', {
zoomReset: true
});
data.set('attr', {
focusFov: 75,
lookSensitivity: 0.2,
lookDamping: 0.97,
Expand All @@ -136,10 +162,10 @@ data.set('camera', {
});
data.on('*:set', (/** @type {string} */ path, /** @type {any} */ value) => {
const [category, key] = path.split('.');
if (category !== 'camera') {
if (category !== 'attr') {
return;
}
multiCamera.script.multiCamera[key] = value;
multiCameraScript[key] = value;
});

export { app };
Loading