@playcanvas/web-components
Version:
Web Components for the PlayCanvas Engine
558 lines (490 loc) • 15.7 kB
text/typescript
import { CameraComponent, Color, Vec4, GAMMA_NONE, GAMMA_SRGB, PROJECTION_ORTHOGRAPHIC, PROJECTION_PERSPECTIVE, TONEMAP_LINEAR, TONEMAP_FILMIC, TONEMAP_NEUTRAL, TONEMAP_ACES2, TONEMAP_ACES, TONEMAP_HEJL, TONEMAP_NONE, XRTYPE_VR } from 'playcanvas';
import { ComponentElement } from './component';
import { parseColor, parseVec4 } from '../utils';
const tonemaps = new Map([
['none', TONEMAP_NONE],
['linear', TONEMAP_LINEAR],
['filmic', TONEMAP_FILMIC],
['hejl', TONEMAP_HEJL],
['aces', TONEMAP_ACES],
['aces2', TONEMAP_ACES2],
['neutral', TONEMAP_NEUTRAL]
]);
/**
* The CameraComponentElement interface provides properties and methods for manipulating
* {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-camera/ | `<pc-camera>`} elements.
* The CameraComponentElement interface also inherits the properties and methods of the
* {@link HTMLElement} interface.
*
* @category Components
*/
class CameraComponentElement extends ComponentElement {
private _clearColor = new Color(0.75, 0.75, 0.75, 1);
private _clearColorBuffer = true;
private _clearDepthBuffer = true;
private _clearStencilBuffer = false;
private _cullFaces = true;
private _farClip = 1000;
private _flipFaces = false;
private _fov = 45;
private _frustumCulling = true;
private _gamma: 'linear' | 'srgb' = 'srgb';
private _horizontalFov = false;
private _nearClip = 0.1;
private _orthographic = false;
private _orthoHeight = 10;
private _priority = 0;
private _rect = new Vec4(0, 0, 1, 1);
private _scissorRect = new Vec4(0, 0, 1, 1);
private _tonemap: 'none' | 'linear' | 'filmic' | 'hejl' | 'aces' | 'aces2' | 'neutral' = 'none';
/** @ignore */
constructor() {
super('camera');
}
getInitialComponentData() {
return {
clearColor: this._clearColor,
clearColorBuffer: this._clearColorBuffer,
clearDepthBuffer: this._clearDepthBuffer,
clearStencilBuffer: this._clearStencilBuffer,
cullFaces: this._cullFaces,
farClip: this._farClip,
flipFaces: this._flipFaces,
fov: this._fov,
frustumCulling: this._frustumCulling,
gammaCorrection: this._gamma === 'srgb' ? GAMMA_SRGB : GAMMA_NONE,
horizontalFov: this._horizontalFov,
nearClip: this._nearClip,
orthographic: this._orthographic,
orthoHeight: this._orthoHeight,
priority: this._priority,
rect: this._rect,
scissorRect: this._scissorRect,
toneMapping: tonemaps.get(this._tonemap)
};
}
get xrAvailable() {
const xrManager = this.component?.system.app.xr;
return xrManager && xrManager.supported && xrManager.isAvailable(XRTYPE_VR);
}
/**
* Starts the camera in XR mode.
* @param type - The type of XR mode to start.
* @param space - The space to start the camera in.
*/
startXr(type: 'immersive-ar' | 'immersive-vr', space: 'bounded-floor' | 'local' | 'local-floor' | 'unbounded' | 'viewer') {
if (this.component && this.xrAvailable) {
this.component.startXr(type, space, {
callback: (err: any) => {
if (err) console.error(`WebXR Immersive VR failed to start: ${err.message}`);
}
});
}
}
/**
* Ends the camera's XR mode.
*/
endXr() {
if (this.component) {
this.component.endXr();
}
}
/**
* Gets the underlying PlayCanvas camera component.
* @returns The camera component.
*/
get component(): CameraComponent | null {
return super.component as CameraComponent | null;
}
/**
* Sets the clear color of the camera.
* @param value - The clear color.
*/
set clearColor(value) {
this._clearColor = value;
if (this.component) {
this.component.clearColor = value;
}
}
/**
* Gets the clear color of the camera.
* @returns The clear color.
*/
get clearColor(): Color {
return this._clearColor;
}
/**
* Sets the clear color buffer of the camera.
* @param value - The clear color buffer.
*/
set clearColorBuffer(value: boolean) {
this._clearColorBuffer = value;
if (this.component) {
this.component.clearColorBuffer = value;
}
}
/**
* Gets the clear color buffer of the camera.
* @returns The clear color buffer.
*/
get clearColorBuffer(): boolean {
return this._clearColorBuffer;
}
/**
* Sets the clear depth buffer of the camera.
* @param value - The clear depth buffer.
*/
set clearDepthBuffer(value: boolean) {
this._clearDepthBuffer = value;
if (this.component) {
this.component.clearDepthBuffer = value;
}
}
/**
* Gets the clear depth buffer of the camera.
* @returns The clear depth buffer.
*/
get clearDepthBuffer(): boolean {
return this._clearDepthBuffer;
}
/**
* Sets the clear stencil buffer of the camera.
* @param value - The clear stencil buffer.
*/
set clearStencilBuffer(value: boolean) {
this._clearStencilBuffer = value;
if (this.component) {
this.component.clearStencilBuffer = value;
}
}
/**
* Gets the clear stencil buffer of the camera.
* @returns The clear stencil buffer.
*/
get clearStencilBuffer(): boolean {
return this._clearStencilBuffer;
}
/**
* Sets the cull faces of the camera.
* @param value - The cull faces.
*/
set cullFaces(value: boolean) {
this._cullFaces = value;
if (this.component) {
this.component.cullFaces = value;
}
}
/**
* Gets the cull faces of the camera.
* @returns The cull faces.
*/
get cullFaces(): boolean {
return this._cullFaces;
}
/**
* Sets the far clip distance of the camera.
* @param value - The far clip distance.
*/
set farClip(value: number) {
this._farClip = value;
if (this.component) {
this.component.farClip = value;
}
}
/**
* Gets the far clip distance of the camera.
* @returns The far clip distance.
*/
get farClip(): number {
return this._farClip;
}
/**
* Sets the flip faces of the camera.
* @param value - The flip faces.
*/
set flipFaces(value: boolean) {
this._flipFaces = value;
if (this.component) {
this.component.flipFaces = value;
}
}
/**
* Gets the flip faces of the camera.
* @returns The flip faces.
*/
get flipFaces(): boolean {
return this._flipFaces;
}
/**
* Sets the field of view of the camera.
* @param value - The field of view.
*/
set fov(value: number) {
this._fov = value;
if (this.component) {
this.component.fov = value;
}
}
/**
* Gets the field of view of the camera.
* @returns The field of view.
*/
get fov(): number {
return this._fov;
}
/**
* Sets the frustum culling of the camera.
* @param value - The frustum culling.
*/
set frustumCulling(value: boolean) {
this._frustumCulling = value;
if (this.component) {
this.component.frustumCulling = value;
}
}
/**
* Gets the frustum culling of the camera.
* @returns The frustum culling.
*/
get frustumCulling(): boolean {
return this._frustumCulling;
}
/**
* Sets the gamma correction of the camera.
* @param value - The gamma correction.
*/
set gamma(value: 'linear' | 'srgb') {
this._gamma = value;
if (this.component) {
this.component.gammaCorrection = value === 'srgb' ? GAMMA_SRGB : GAMMA_NONE;
}
}
/**
* Gets the gamma correction of the camera.
* @returns The gamma correction.
*/
get gamma(): 'linear' | 'srgb' {
return this._gamma;
}
/**
* Sets whether the camera's field of view (fov) is horizontal or vertical. Defaults to false
* (meaning it is vertical be default).
* @param value - Whether the camera's field of view is horizontal.
*/
set horizontalFov(value: boolean) {
this._horizontalFov = value;
if (this.component) {
this.component.horizontalFov = value;
}
}
/**
* Gets whether the camera's field of view (fov) is horizontal or vertical.
* @returns Whether the camera's field of view is horizontal.
*/
get horizontalFov(): boolean {
return this._horizontalFov;
}
/**
* Sets the near clip distance of the camera.
* @param value - The near clip distance.
*/
set nearClip(value: number) {
this._nearClip = value;
if (this.component) {
this.component.nearClip = value;
}
}
/**
* Gets the near clip distance of the camera.
* @returns The near clip distance.
*/
get nearClip(): number {
return this._nearClip;
}
/**
* Sets the orthographic projection of the camera.
* @param value - The orthographic projection.
*/
set orthographic(value) {
this._orthographic = value;
if (this.component) {
this.component.projection = value ? PROJECTION_ORTHOGRAPHIC : PROJECTION_PERSPECTIVE;
}
}
/**
* Gets the orthographic projection of the camera.
* @returns The orthographic projection.
*/
get orthographic(): boolean {
return this._orthographic;
}
/**
* Sets the orthographic height of the camera.
* @param value - The orthographic height.
*/
set orthoHeight(value: number) {
this._orthoHeight = value;
if (this.component) {
this.component.orthoHeight = value;
}
}
/**
* Gets the orthographic height of the camera.
* @returns The orthographic height.
*/
get orthoHeight() {
return this._orthoHeight;
}
/**
* Sets the priority of the camera.
* @param value - The priority.
*/
set priority(value: number) {
this._priority = value;
if (this.component) {
this.component.priority = value;
}
}
/**
* Gets the priority of the camera.
* @returns The priority.
*/
get priority(): number {
return this._priority;
}
/**
* Sets the rect of the camera.
* @param value - The rect.
*/
set rect(value: Vec4) {
this._rect = value;
if (this.component) {
this.component.rect = value;
}
}
/**
* Gets the rect of the camera.
* @returns The rect.
*/
get rect(): Vec4 {
return this._rect;
}
/**
* Sets the scissor rect of the camera.
* @param value - The scissor rect.
*/
set scissorRect(value: Vec4) {
this._scissorRect = value;
if (this.component) {
this.component.scissorRect = value;
}
}
/**
* Gets the scissor rect of the camera.
* @returns The scissor rect.
*/
get scissorRect(): Vec4 {
return this._scissorRect;
}
/**
* Sets the tone mapping of the camera.
* @param value - The tone mapping.
*/
set tonemap(value: 'none' | 'linear' | 'filmic' | 'hejl' | 'aces' | 'aces2' | 'neutral') {
this._tonemap = value;
if (this.component) {
this.component.toneMapping = tonemaps.get(value) ?? TONEMAP_NONE;
}
}
/**
* Gets the tone mapping of the camera.
* @returns The tone mapping.
*/
get tonemap(): 'none' | 'linear' | 'filmic' | 'hejl' | 'aces' | 'aces2' | 'neutral' {
return this._tonemap;
}
static get observedAttributes() {
return [
...super.observedAttributes,
'clear-color',
'clear-color-buffer',
'clear-depth-buffer',
'clear-stencil-buffer',
'cull-faces',
'far-clip',
'flip-faces',
'fov',
'frustum-culling',
'gamma',
'horizontal-fov',
'near-clip',
'orthographic',
'ortho-height',
'priority',
'rect',
'scissor-rect',
'tonemap'
];
}
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
super.attributeChangedCallback(name, _oldValue, newValue);
switch (name) {
case 'clear-color':
this.clearColor = parseColor(newValue);
break;
case 'clear-color-buffer':
this.clearColorBuffer = newValue !== 'false';
break;
case 'clear-depth-buffer':
this.clearDepthBuffer = newValue !== 'false';
break;
case 'clear-stencil-buffer':
this.clearStencilBuffer = newValue !== 'false';
break;
case 'cull-faces':
this.cullFaces = newValue !== 'false';
break;
case 'far-clip':
this.farClip = parseFloat(newValue);
break;
case 'flip-faces':
this.flipFaces = newValue !== 'true';
break;
case 'fov':
this.fov = parseFloat(newValue);
break;
case 'frustum-culling':
this.frustumCulling = newValue !== 'false';
break;
case 'gamma':
this.gamma = newValue as 'linear' | 'srgb';
break;
case 'horizontal-fov':
this.horizontalFov = this.hasAttribute('horizontal-fov');
break;
case 'near-clip':
this.nearClip = parseFloat(newValue);
break;
case 'orthographic':
this.orthographic = this.hasAttribute('orthographic');
break;
case 'ortho-height':
this.orthoHeight = parseFloat(newValue);
break;
case 'priority':
this.priority = parseFloat(newValue);
break;
case 'rect':
this.rect = parseVec4(newValue);
break;
case 'scissor-rect':
this.scissorRect = parseVec4(newValue);
break;
case 'tonemap':
this.tonemap = newValue as 'none' | 'linear' | 'filmic' | 'hejl' | 'aces' | 'aces2' | 'neutral';
break;
}
}
}
customElements.define('pc-camera', CameraComponentElement);
export { CameraComponentElement };