UNPKG

@shopware-ag/dive

Version:

Shopware Spatial Framework

364 lines (315 loc) 12.9 kB
import { DIVERenderer, DIVERendererDefaultSettings, DIVERendererSettings, } from './renderer/Renderer.ts'; import { DIVEScene } from './scene/Scene.ts'; import DIVEPerspectiveCamera, { DIVEPerspectiveCameraDefaultSettings, DIVEPerspectiveCameraSettings, } from './camera/PerspectiveCamera.ts'; import DIVEOrbitControls, { DIVEOrbitControlsDefaultSettings, DIVEOrbitControlsSettings, } from './controls/OrbitControls.ts'; import DIVEToolbox from './toolbox/Toolbox.ts'; import { DIVECommunication } from './com/Communication.ts'; import { DIVEAnimationSystem } from './animation/AnimationSystem.ts'; import DIVEAxisCamera from './axiscamera/AxisCamera.ts'; import { getObjectDelta } from './helper/getObjectDelta/getObjectDelta.ts'; import { MathUtils } from 'three'; import { DIVEInfo } from './info/Info.ts'; import pkgjson from '../package.json'; export type DIVESettings = { autoResize: boolean; autoStart: boolean; displayAxes: boolean; renderer: Partial<DIVERendererSettings>; perspectiveCamera: Partial<DIVEPerspectiveCameraSettings>; orbitControls: Partial<DIVEOrbitControlsSettings>; }; export const DIVEDefaultSettings: DIVESettings = { autoResize: true, autoStart: true, displayAxes: false, renderer: DIVERendererDefaultSettings, perspectiveCamera: DIVEPerspectiveCameraDefaultSettings, orbitControls: DIVEOrbitControlsDefaultSettings, }; /** * #### DIVE * is the main class of the DIVE framework. * * An instance of this class delivers a complete 3D environment with a perspective camera, orbit controls, a toolbox, and a communication system. * ```ts * import { DIVE } from "@shopware-ag/dive"; * * const myWrapper = document.getElementById('myWrapper'); * * const dive = new DIVE(); * * myWrapper.appendChild(dive.Canvas); * * dive.Communication.Subscribe('GET_ALL_SCENE_DATA', () => { * // do something * })); * * dive.Communication.PerformAction('GET_ALL_SCENE_DATA', {}); * ``` * @module */ export default class DIVE { // static members public static QuickView( uri: string, settings?: Partial<DIVESettings>, ): DIVE { const dive = new DIVE(settings); dive.Communication.PerformAction('SET_CAMERA_TRANSFORM', { position: { x: 0, y: 2, z: 2 }, target: { x: 0, y: 0.5, z: 0 }, }); // generate scene light id const lightid = MathUtils.generateUUID(); // add scene light dive.Communication.PerformAction('ADD_OBJECT', { entityType: 'light', type: 'scene', name: 'light', id: lightid, enabled: true, visible: true, intensity: 1, color: 0xffffff, }); // generate model id const modelid = MathUtils.generateUUID(); // add loaded listener dive.Communication.Subscribe('MODEL_LOADED', (data) => { if (data.id !== modelid) return; const transform = dive.Communication.PerformAction( 'COMPUTE_ENCOMPASSING_VIEW', {}, ); dive.Communication.PerformAction('SET_CAMERA_TRANSFORM', { position: transform.position, target: transform.target, }); }); // instantiate model dive.Communication.PerformAction('ADD_OBJECT', { entityType: 'model', name: 'object', id: modelid, position: { x: 0, y: 0, z: 0 }, rotation: { x: 0, y: 0, z: 0 }, scale: { x: 1, y: 1, z: 1 }, uri: uri, visible: true, loaded: false, }); // set scene properties dive.Communication.PerformAction('UPDATE_SCENE', { backgroundColor: 0xffffff, gridEnabled: false, floorColor: 0xffffff, }); return dive; } // descriptive members private _settings: DIVESettings; private _resizeObserverId: string; private _width: number; private _height: number; // functional components private renderer: DIVERenderer; private scene: DIVEScene; private perspectiveCamera: DIVEPerspectiveCamera; private orbitControls: DIVEOrbitControls; private toolbox: DIVEToolbox; private communication: DIVECommunication; // additional components private animationSystem: DIVEAnimationSystem; private axisCamera: DIVEAxisCamera | null; // getters public get Communication(): DIVECommunication { return this.communication; } public get Canvas(): HTMLCanvasElement { return this.renderer.domElement; } public get Info(): DIVEInfo { return DIVEInfo; } // setters public set Settings(settings: Partial<DIVESettings>) { const settingsDelta = getObjectDelta(this._settings, settings); // apply renderer settings (we have to rebuild the renderer to apply the settings) if (settingsDelta.renderer) this.renderer = new DIVERenderer(this._settings.renderer); // apply perspective camera settings if (settingsDelta.perspectiveCamera) { if (settingsDelta.perspectiveCamera.fov !== undefined) this.perspectiveCamera.fov = settingsDelta.perspectiveCamera.fov; if (settingsDelta.perspectiveCamera.near !== undefined) this.perspectiveCamera.near = settingsDelta.perspectiveCamera.near; if (settingsDelta.perspectiveCamera.far !== undefined) this.perspectiveCamera.far = settingsDelta.perspectiveCamera.far; this.perspectiveCamera.OnResize( this.renderer.domElement.width, this.renderer.domElement.height, ); } // apply orbit controls settings if (settingsDelta.orbitControls) { if (settingsDelta.orbitControls.enableDamping !== undefined) this.orbitControls.enableDamping = settingsDelta.orbitControls.enableDamping; if (settingsDelta.orbitControls.dampingFactor !== undefined) this.orbitControls.dampingFactor = settingsDelta.orbitControls.dampingFactor; } if (settingsDelta.autoResize !== this._settings.autoResize) { if (settingsDelta.autoResize) { this.addResizeObserver(); } else { this.removeResizeObserver(); } } if (settingsDelta.displayAxes) { this.axisCamera = new DIVEAxisCamera( this.renderer, this.scene, this.orbitControls, ); } else { this.axisCamera?.Dispose(); this.axisCamera = null; } Object.assign(this._settings, settings); } constructor(settings?: Partial<DIVESettings>) { this._settings = { ...DIVEDefaultSettings, ...(settings !== undefined ? settings : {}), }; this._resizeObserverId = ''; this._width = 0; this._height = 0; // initialize functional components this.renderer = new DIVERenderer(this._settings.renderer); this.scene = new DIVEScene(); this.perspectiveCamera = new DIVEPerspectiveCamera( this._settings.perspectiveCamera, ); // initialize animation system this.animationSystem = new DIVEAnimationSystem(this.renderer); this.orbitControls = new DIVEOrbitControls( this.perspectiveCamera, this.renderer, this.animationSystem, this._settings.orbitControls, ); this.toolbox = new DIVEToolbox(this.scene, this.orbitControls); this.communication = new DIVECommunication( this.renderer, this.scene, this.orbitControls, this.toolbox, ); // initialize axis camera if (this._settings.displayAxes) { this.axisCamera = new DIVEAxisCamera( this.renderer, this.scene, this.orbitControls, ); } else { this.axisCamera = null; } // add resize observer if autoResize is enabled if (this._settings.autoResize) { this.addResizeObserver(); } // eslint-disable-next-line @typescript-eslint/no-explicit-any (window as any).DIVE = { PrintScene: () => { console.log(this.scene); }, }; console.log(`DIVE ${pkgjson.version} initialized successfully!`); console.log(` @@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@ @@@@+-:::::::---------------------==------------------------------=#@@@@ @@%=::::.......::---------------------------------------------------------+@@ @@+:::...........::-----------------------------------------------------------#@@ @@=:::.........::::::-------------------------------------------------------------%@ @%:::.......:::::::-----------------------------------------------------------------#@ @*:::.....:::::-----------------------------------------------------------------------*@ @%::::::.::::---------------------------------------------------------------------------@@ @@-:::::::::-----------------------------------------------------------------------------=@ @%::::::::--------------------------------------------------------------------------------%@ @+::::::::--------------------------------=@@@@@%-----------------------------------------%@ @=:::::::--------------------------------*@@ @@+---------------------------------------#@ @+:::::::-------------------------------*@ @*--------------------------------------%@ @#::::::::-----------------------------=@@ @@=-------------------------------------%@ @@-::::::::----------------------------@@ @@------------------------------------=@ @%:::::::::--------------------------*@ @*-----------------------------------@@ @*:::::::::-------------------------@@ @@----------------------------------%@ @#::::::::::----------------------%@ @%--------------------------------%@ @#:::::::::::-------------------=@@ @@=------------------------------%@ @@-::::::::::::----------------%@ @%----------------------------=@@ @@#::::::::::::::------------*@ @*--------------------------#@@ @@+::::::::::::::::--------@@ @@------------------------+@@ @@*:::::::::::::::::----@@ @@---------------------+@@ @@@-:::::::::::::::--#@ @#-----------------=%@@ @@%-::::::::::::-%@ @%-------------=%@@ @@@@+:::::::#@@ @@*-------*@@@@ @@@@@@@ @@@@@@ `); if (this._settings.autoStart) { // when everything is done, start the renderer this.renderer.StartRenderer(this.scene, this.perspectiveCamera); } } public Dispose(): void { this.removeResizeObserver(); this.renderer.Dispose(); this.orbitControls.Dispose(); this.axisCamera?.Dispose(); this.animationSystem.Dispose(); this.toolbox.Dispose(); this.communication.DestroyInstance(); } // methods public OnResize(width: number, height: number): void { // resize renderer this.renderer.OnResize(width, height); // resize camera this.perspectiveCamera.OnResize(width, height); } private addResizeObserver(): void { this._resizeObserverId = this.renderer.AddPreRenderCallback(() => { // check if the canvas is mounted const canvasWrapper = this.renderer.domElement.parentElement; if (!canvasWrapper) return; const { clientWidth, clientHeight } = canvasWrapper; if (clientWidth === this._width && clientHeight === this._height) return; this.OnResize(clientWidth, clientHeight); this._width = clientWidth; this._height = clientHeight; }); } private removeResizeObserver(): void { this.renderer.RemovePreRenderCallback(this._resizeObserverId); } } export { DIVE, DIVECommunication }; export * from './math/index.ts'; export type * from './com/actions/index.ts'; export type * from './com/types'; export type * from './types';