Skip to content
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
14 changes: 7 additions & 7 deletions examples/js/example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ document.addEventListener('DOMContentLoaded', async () => {
const cameraRootEntity = cameraElement.parentElement.parentElement.entity;
const cameraEntity = cameraElement.parentElement.entity;

app.xr.on('start', () => {
app.xr?.on('start', () => {
// Cache original camera rig positions and rotations
positionRoot.copy(cameraRootEntity.getPosition());
rotationRoot.copy(cameraRootEntity.getRotation());
Expand All @@ -92,7 +92,7 @@ document.addEventListener('DOMContentLoaded', async () => {
}
});

app.xr.on('end', () => {
app.xr?.on('end', () => {
// Restore original camera rig positions and rotations
cameraRootEntity.setPosition(positionRoot);
cameraRootEntity.setRotation(rotationRoot);
Expand All @@ -110,27 +110,27 @@ document.addEventListener('DOMContentLoaded', async () => {
title: 'Enter AR',
onClick: () => cameraElement.startXr('immersive-ar', 'local-floor')
});
arButton.style.display = app.xr.isAvailable('immersive-ar') ? 'block' : 'none';
arButton.style.display = app.xr?.isAvailable('immersive-ar') ? 'block' : 'none';
container.appendChild(arButton);

const vrButton = createButton({
icon: VR_ICON,
title: 'Enter VR',
onClick: () => cameraElement.startXr('immersive-vr', 'local-floor')
});
vrButton.style.display = app.xr.isAvailable('immersive-vr') ? 'block' : 'none';
vrButton.style.display = app.xr?.isAvailable('immersive-vr') ? 'block' : 'none';
container.appendChild(vrButton);

app.xr.on('available:immersive-ar', (available) => {
app.xr?.on('available:immersive-ar', (available) => {
arButton.style.display = available ? 'block' : 'none';
});

app.xr.on('available:immersive-vr', (available) => {
app.xr?.on('available:immersive-vr', (available) => {
vrButton.style.display = available ? 'block' : 'none';
});

window.addEventListener('keydown', (event) => {
if (event.key === 'Escape' && app.xr.active) {
if (event.key === 'Escape' && app.xr?.active) {
cameraElement.endXr();
}
});
Expand Down
150 changes: 137 additions & 13 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,67 @@
import { Application, CameraComponent, FILLMODE_FILL_WINDOW, GraphNode, Keyboard, Mouse, Picker, RESOLUTION_AUTO } from 'playcanvas';
import {
AppBase,
AppOptions,
CameraComponent,
createGraphicsDevice,
FILLMODE_FILL_WINDOW,
GraphNode,
Keyboard,
Mouse,
Picker,
RESOLUTION_AUTO,
AnimComponentSystem,
AnimationComponentSystem,
AudioListenerComponentSystem,
ButtonComponentSystem,
CameraComponentSystem,
CollisionComponentSystem,
ElementComponentSystem,
GSplatComponentSystem,
JointComponentSystem,
LayoutChildComponentSystem,
LayoutGroupComponentSystem,
LightComponentSystem,
ModelComponentSystem,
ParticleSystemComponentSystem,
RenderComponentSystem,
RigidBodyComponentSystem,
ScriptComponentSystem,
ScreenComponentSystem,
ScrollbarComponentSystem,
ScrollViewComponentSystem,
SoundComponentSystem,
SpriteComponentSystem,
ZoneComponentSystem,
RenderHandler,
AnimationHandler,
AnimClipHandler,
AnimStateGraphHandler,
AudioHandler,
BinaryHandler,
ContainerHandler,
CssHandler,
CubemapHandler,
FolderHandler,
FontHandler,
GSplatHandler,
HierarchyHandler,
HtmlHandler,
JsonHandler,
MaterialHandler,
ModelHandler,
SceneHandler,
ScriptHandler,
ShaderHandler,
SpriteHandler,
TemplateHandler,
TextHandler,
TextureHandler,
TextureAtlasHandler,
BatchManager,
SoundManager,
Lightmapper,
XrManager
} from 'playcanvas';

import { AssetElement } from './asset';
import { AsyncElement } from './async-element';
Expand Down Expand Up @@ -51,7 +114,7 @@ class AppElement extends AsyncElement {
/**
* The PlayCanvas application instance.
*/
app: Application | null = null;
app: AppBase | null = null;

/**
* Creates a new AppElement instance.
Expand All @@ -76,18 +139,79 @@ class AppElement extends AsyncElement {
this._canvas = document.createElement('canvas');
this.appendChild(this._canvas);

// Initialize the PlayCanvas application
this.app = new Application(this._canvas, {
graphicsDeviceOptions: {
alpha: this._alpha,
antialias: this._antialias,
depth: this._depth,
stencil: this._stencil
},
keyboard: new Keyboard(window),
mouse: new Mouse(this._canvas)
const device = await createGraphicsDevice(this._canvas, {
// @ts-ignore - alpha needs to be documented
alpha: this._alpha,
antialias: this._antialias,
depth: this._depth,
deviceTypes: ['webgl2'],
stencil: this._stencil
});
this.app.graphicsDevice.maxPixelRatio = this._highResolution ? window.devicePixelRatio : 1;
device.maxPixelRatio = this._highResolution ? window.devicePixelRatio : 1;

const createOptions = new AppOptions();
createOptions.graphicsDevice = device;
createOptions.keyboard = new Keyboard(window);
createOptions.mouse = new Mouse(this._canvas);
createOptions.componentSystems = [
AnimComponentSystem,
AnimationComponentSystem,
AudioListenerComponentSystem,
ButtonComponentSystem,
CameraComponentSystem,
CollisionComponentSystem,
ElementComponentSystem,
GSplatComponentSystem,
JointComponentSystem,
LayoutChildComponentSystem,
LayoutGroupComponentSystem,
LightComponentSystem,
ModelComponentSystem,
ParticleSystemComponentSystem,
RenderComponentSystem,
RigidBodyComponentSystem,
ScreenComponentSystem,
ScriptComponentSystem,
ScrollbarComponentSystem,
ScrollViewComponentSystem,
SoundComponentSystem,
SpriteComponentSystem,
ZoneComponentSystem
];
createOptions.resourceHandlers = [
AnimClipHandler,
AnimationHandler,
AnimStateGraphHandler,
AudioHandler,
BinaryHandler,
CssHandler,
ContainerHandler,
CubemapHandler,
FolderHandler,
FontHandler,
GSplatHandler,
HierarchyHandler,
HtmlHandler,
JsonHandler,
MaterialHandler,
ModelHandler,
RenderHandler,
ScriptHandler,
SceneHandler,
ShaderHandler,
SpriteHandler,
TemplateHandler,
TextHandler,
TextureAtlasHandler,
TextureHandler
];
createOptions.soundManager = new SoundManager();
createOptions.lightmapper = Lightmapper;
createOptions.batchManager = BatchManager;
createOptions.xr = XrManager;

this.app = new AppBase(this._canvas);
this.app.init(createOptions);

this.app.setCanvasFillMode(FILLMODE_FILL_WINDOW);
this.app.setCanvasResolution(RESOLUTION_AUTO);
Expand Down
6 changes: 3 additions & 3 deletions src/entity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Application, Entity, Vec3 } from 'playcanvas';
import { AppBase, Entity, Vec3 } from 'playcanvas';

import { AsyncElement } from './async-element';
import { parseVec3 } from './utils';
Expand Down Expand Up @@ -50,7 +50,7 @@ class EntityElement extends AsyncElement {
*/
entity: Entity | null = null;

createEntity(app: Application) {
createEntity(app: AppBase) {
// Create a new entity
this.entity = new Entity(this.getAttribute('name') || this._name, app);

Expand Down Expand Up @@ -105,7 +105,7 @@ class EntityElement extends AsyncElement {
});
}

buildHierarchy(app: Application) {
buildHierarchy(app: AppBase) {
if (!this.entity) return;

const closestEntity = this.closestEntity;
Expand Down