diff --git a/samples/gui/Sample_POI.ts b/samples/gui/Sample_POI.ts new file mode 100644 index 00000000..50d5cbf4 --- /dev/null +++ b/samples/gui/Sample_POI.ts @@ -0,0 +1,156 @@ +import { GUIHelp } from "@orillusion/debug/GUIHelp"; +import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; +import { Scene3D, PropertyAnimation, Engine3D, Object3D, Object3DUtil, PropertyAnimClip, WrapMode, WorldPanel, BillboardType, TextAnchor, UIImage, UIShadow, UITextField, Vector3, Color, Time } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; + +class Sample_POI { + scene: Scene3D; + panel: WorldPanel; + position: Vector3; + + async run() { + Engine3D.setting.shadow.autoUpdate = true; + Engine3D.setting.shadow.updateFrameRate = 1; + Engine3D.setting.shadow.shadowBound = 20; + Engine3D.setting.shadow.shadowBias = 0.0001; + + await Engine3D.init({ renderLoop: () => { this.loop(); } }); + let param = createSceneParam(); + param.camera.distance = 16; + let exampleScene = createExampleScene(param); + + GUIHelp.init(); + + this.scene = exampleScene.scene; + + Engine3D.startRenderView(exampleScene.view); + + await this.initScene(); + this.initDuckPOI(); + this.initScenePOI(); + } + + private modelContainer: Object3D; + + async initScene() { + // floor + let floor: Object3D = Object3DUtil.GetSingleCube(16, 0.1, 16, 1, 1, 1); + this.scene.addChild(floor); + await Engine3D.res.loadFont('fnt/0.fnt'); + + // load external model + let model = await Engine3D.res.loadGltf('PBR/Duck/Duck.gltf') as Object3D; + model.rotationY = 180; + this.modelContainer = new Object3D(); + this.modelContainer.addChild(model); + this.scene.addChild(this.modelContainer); + model.scaleX = model.scaleY = model.scaleZ = 0.01; + await this.initPropertyAnim(this.modelContainer); + + let chair = await Engine3D.res.loadGltf('PBR/SheenChair/SheenChair.gltf') as Object3D; + chair.scaleX = chair.scaleY = chair.scaleZ = 8; + this.scene.addChild(chair); + } + + private async initPropertyAnim(owner: Object3D) { + // add PropertyAnimation + let animation = owner.addComponent(PropertyAnimation); + + //load a animation clip + let json: any = await Engine3D.res.loadJSON('json/anim_0.json'); + let animClip = new PropertyAnimClip(); + animClip.parse(json); + animClip.wrapMode = WrapMode.Loop; + animation.defaultClip = animClip.name; + animation.autoPlay = true; + + // register clip to animation + animation.appendClip(animClip); + animation.play(animation.defaultClip); + return animation; + } + + private initDuckPOI() { + let canvas = this.scene.view.enableUICanvas(); + //panel + this.panel = new Object3D().addComponent(WorldPanel); + this.panel.billboard = BillboardType.BillboardXYZ; + //add to canvas + canvas.addChild(this.panel.object3D); + this.panel.object3D.localScale = new Vector3(0.1, 0.1, 0.1); + + //poi + let panelRoot = new Object3D(); + + this.panel.object3D.addChild(panelRoot); + + let image = panelRoot.addComponent(UIImage); + image.uiTransform.resize(32, 6); + image.uiTransform.setXY(20, 20); + + image.color = new Color(1, 1, 1, 0.5); + image.isShadowless = true; + let text = panelRoot.addComponent(UITextField); + + text.text = 'Happy Duck'; + text.fontSize = 4; + text.color = new Color(0, 0, 0, 1); + text.alignment = TextAnchor.MiddleCenter; + GUIUtil.renderUIPanel(this.panel, true); + } + + private sceneText: UITextField; + private initScenePOI() { + let canvas = this.scene.view.enableUICanvas(); + //panel + let panel = new Object3D().addComponent(WorldPanel); + panel.cullMode = "none"; + //add to canvas + canvas.addChild(panel.object3D); + panel.object3D.localScale = new Vector3(0.1, 0.1, 0.1); + + //poi + let panelRoot = new Object3D(); + panel.transform.rotationX = -30; + panel.transform.y = 3.1; + panel.transform.x = 1; + + panel.object3D.addChild(panelRoot); + let text = panelRoot.addComponent(UITextField); + text.uiTransform.resize(80, 16); + text.text = this.title; + text.fontSize = 10; + text.color = new Color(0.5, 1.0, 0.5, 1.0); + text.alignment = TextAnchor.MiddleLeft; + + panelRoot.addComponent(UIShadow).shadowOffset.multiplyScaler(0.2); + this.sceneText = text; + } + + private charCount = 0; + private title: string = 'Hello, Orillusion'; + private lastTitle = this.title; + private loop(): void { + if (this.panel) { + this.position ||= new Vector3(); + this.position.copyFrom(this.modelContainer.transform.worldPosition); + this.panel.object3D.localPosition = this.position; + } + if (this.sceneText) { + let count = 1 + Math.floor(Time.frame * 0.1) % 30; + if (this.charCount != count) { + this.charCount = count; + let newTitle = this.title.slice(0, this.charCount); + if (newTitle != this.lastTitle) { + this.sceneText.text = newTitle; + this.lastTitle = newTitle; + } + + } + + } + } + +} + +new Sample_POI().run(); \ No newline at end of file diff --git a/samples/gui/Sample_UIButton.ts b/samples/gui/Sample_UIButton.ts index dd7232c6..39264d6e 100644 --- a/samples/gui/Sample_UIButton.ts +++ b/samples/gui/Sample_UIButton.ts @@ -22,7 +22,7 @@ export class Sample_UIButton { exampleScene.scene.addChild(floor); floor.y = -40; - // enable ui canvas 0 + // enable ui canvas at index 0 let canvas = exampleScene.view.enableUICanvas(); //create UI root diff --git a/samples/gui/Sample_UIChangeParent.ts b/samples/gui/Sample_UIChangeParent.ts index 6624afab..1f3f5fd0 100644 --- a/samples/gui/Sample_UIChangeParent.ts +++ b/samples/gui/Sample_UIChangeParent.ts @@ -18,7 +18,7 @@ export class Sample_UIChangeParent { exampleScene.scene.addChild(floor); floor.y = -40; - // enable ui canvas 0 + // enable ui canvas at index 0 let canvas = exampleScene.view.enableUICanvas(); //create UI root diff --git a/samples/gui/Sample_UIImageColor.ts b/samples/gui/Sample_UIImageColor.ts index 130f0c1a..74876117 100644 --- a/samples/gui/Sample_UIImageColor.ts +++ b/samples/gui/Sample_UIImageColor.ts @@ -24,7 +24,7 @@ export class Sample_UIImageColor { exampleScene.scene.addChild(floor); floor.y = -40; - // enable ui canvas 0 + // enable ui canvas at index 0 let canvas = exampleScene.view.enableUICanvas(); //create UI root diff --git a/samples/gui/Sample_UIImageGroup.ts b/samples/gui/Sample_UIImageGroup.ts index cbf44f13..09e04675 100644 --- a/samples/gui/Sample_UIImageGroup.ts +++ b/samples/gui/Sample_UIImageGroup.ts @@ -28,12 +28,12 @@ export class Sample_UIImageGroup { } async createImageGroup() { - // enable ui canvas i - let canvas = this.scene.view.enableUICanvas(0); + // enable ui canvas + let canvas = this.scene.view.enableUICanvas(); //create UI root let panelRoot: Object3D = new Object3D(); //create panel - let panel = panelRoot.addComponent(ViewPanel, { billboard: true }); + let panel = panelRoot.addComponent(ViewPanel); canvas.addChild(panel.object3D); let bitmapTexture2D = new BitmapTexture2D(); diff --git a/samples/gui/Sample_UIImageShadow.ts b/samples/gui/Sample_UIImageShadow.ts index 414f6480..90872a98 100644 --- a/samples/gui/Sample_UIImageShadow.ts +++ b/samples/gui/Sample_UIImageShadow.ts @@ -3,7 +3,7 @@ import { createExampleScene } from "@samples/utils/ExampleScene"; import { Engine3D, Object3DUtil, Object3D, BitmapTexture2D, UIImage, makeAloneSprite, WorldPanel, UIShadow } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; -export class Sample_UIImageShadow { +class Sample_UIImageShadow { private img: UIImage; async run() { @@ -24,8 +24,7 @@ export class Sample_UIImageShadow { let panelRoot: Object3D = new Object3D(); panelRoot.scaleX = panelRoot.scaleY = panelRoot.scaleZ = 0.1; - // enable ui canvas 0 - + // enable ui canvas let canvas = exampleScene.view.enableUICanvas(); let panel = panelRoot.addComponent(WorldPanel); @@ -50,3 +49,5 @@ export class Sample_UIImageShadow { } } + +new Sample_UIImageShadow().run(); \ No newline at end of file diff --git a/samples/gui/Sample_UIMultiCanvas.ts b/samples/gui/Sample_UIMultiCanvas.ts new file mode 100644 index 00000000..f1dce363 --- /dev/null +++ b/samples/gui/Sample_UIMultiCanvas.ts @@ -0,0 +1,58 @@ +import { createExampleScene } from "@samples/utils/ExampleScene"; +import { Engine3D, Object3DUtil, Object3D, UIImage, ImageType, Color, UIPanel, ViewPanel, Scene3D, Vector2, UITextField, UIShadow } from "@orillusion/core"; + +class Sample_UIMultiCanvas { + async run() { + Engine3D.setting.shadow.autoUpdate = true; + Engine3D.setting.shadow.shadowBias = 0.002; + + await Engine3D.init(); + await Engine3D.res.loadFont('fnt/0.fnt'); + + let exampleScene = createExampleScene(); + Engine3D.startRenderView(exampleScene.view); + + // create floor + let floor = Object3DUtil.GetSingleCube(100, 2, 50, 0.5, 0.5, 0.5); + exampleScene.scene.addChild(floor); + floor.y = -40; + + let total: number = 4; + for (let i = 0; i < total; i++) { + let size: Vector2 = new Vector2(); + size.x = 500 - i * 100; + size.y = 400 - i * 100; + this.createPanel(exampleScene.scene, i, size); + } + + } + + private createPanel(scene: Scene3D, index: number, size: Vector2): UIPanel { + let panelRoot: Object3D = new Object3D(); + // enable ui canvas at index + let canvas = scene.view.enableUICanvas(index); + let panel = panelRoot.addComponent(ViewPanel); + canvas.addChild(panel.object3D); + // create image + let obj3D = new Object3D(); + panelRoot.addChild(obj3D); + let image = obj3D.addComponent(UIImage); + image.isShadowless = true; + image.imageType = ImageType.Sliced; + image.uiTransform.resize(size.x, size.y); + image.color = Color.random(); + + //text + let text = obj3D.addComponent(UITextField); + text.text = 'Canvas index: ' + index; + text.fontSize = 24; + + //shadow + let shadow = obj3D.addComponent(UIShadow); + shadow.shadowOffset.multiplyScaler(0.4); + return panel; + } + +} + +new Sample_UIMultiCanvas().run(); diff --git a/samples/gui/Sample_UIMultiPanel.ts b/samples/gui/Sample_UIMultiPanel.ts index 48eb1c72..b92c3806 100644 --- a/samples/gui/Sample_UIMultiPanel.ts +++ b/samples/gui/Sample_UIMultiPanel.ts @@ -1,7 +1,7 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { createExampleScene, createSceneParam } from "@samples/utils/ExampleScene"; import { GUIPanelBinder, sampleUIPanelDispatcher, sampleUIPanelClick } from "./panel/GUIBinder"; -import { Camera3D, Scene3D, View3D, Engine3D, Object3DUtil, Object3D, Vector3, WorldPanel, Time, zSorterUtil } from "@orillusion/core"; +import { Camera3D, Scene3D, View3D, Engine3D, Object3DUtil, Object3D, Vector3, WorldPanel, Time, zSorterUtil, BillboardType } from "@orillusion/core"; export class Sample_UIMultiPanel { camera: Camera3D; @@ -24,7 +24,7 @@ export class Sample_UIMultiPanel { this.scene = exampleScene.scene; this.camera = exampleScene.camera; this.view = exampleScene.view; - // enable ui canvas 0 + // enable ui canvas at index 0 let canvas = exampleScene.view.enableUICanvas(); let car = await Engine3D.res.loadGltf('gltfs/pbrCar/pbrCar.gltf'); @@ -51,7 +51,8 @@ export class Sample_UIMultiPanel { for (let i = 0; i < 50; i++) { //panel let panelRoot: Object3D = new Object3D(); - let panel = panelRoot.addComponent(WorldPanel, { billboard: true }); + let panel = panelRoot.addComponent(WorldPanel); + panel.billboard = BillboardType.BillboardXYZ; panel.needSortOnCameraZ = true; canvas.addChild(panel.object3D); diff --git a/samples/gui/Sample_UIPanelOrder.ts b/samples/gui/Sample_UIPanelOrder.ts index eee33fed..db3c4d02 100644 --- a/samples/gui/Sample_UIPanelOrder.ts +++ b/samples/gui/Sample_UIPanelOrder.ts @@ -1,6 +1,6 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { createExampleScene } from "@samples/utils/ExampleScene"; -import { Engine3D, Object3DUtil, Object3D, UIImage, ImageType, Color, WorldPanel, UIPanel, GUICanvas } from "@orillusion/core"; +import { Engine3D, Object3DUtil, Object3D, Color, WorldPanel, UIPanel, GUICanvas, BillboardType } from "@orillusion/core"; export class Sample_UIPanelOrder { @@ -20,7 +20,7 @@ export class Sample_UIPanelOrder { exampleScene.scene.addChild(floor); floor.y = -40; - // enable ui canvas 0 + // enable ui canvas at index 0 let canvas = exampleScene.view.enableUICanvas(); //create UI root let panelRoot: Object3D = new Object3D(); @@ -33,7 +33,6 @@ export class Sample_UIPanelOrder { let panel1 = this.createPanel(panelRoot, canvas, new Color(1.0, 0, 0.0, 0.8)); let panel2 = this.createPanel(panelRoot2, canvas, new Color(0, 0, 1, 0.8)); - panel1.needSortOnCameraZ = true; panel2.needSortOnCameraZ = true; @@ -48,15 +47,13 @@ export class Sample_UIPanelOrder { } private createPanel(panelRoot: Object3D, canvas: GUICanvas, color: Color): UIPanel { - let panel = panelRoot.addComponent(WorldPanel, { billboard: true }); + let panel = panelRoot.addComponent(WorldPanel); + panel.billboard = BillboardType.BillboardXYZ; canvas.addChild(panel.object3D); - // create image - let obj3D = new Object3D(); - panelRoot.addChild(obj3D); - let image = obj3D.addComponent(UIImage); - image.imageType = ImageType.Sliced; - image.uiTransform.resize(400, 300); - image.color = color; + panel.uiTransform.resize(400, 300); + panel.visible = true; + panel.color = color; + return panel; } diff --git a/samples/gui/Sample_UIPerformance.ts b/samples/gui/Sample_UIPerformance.ts index 38f0d976..368d0ab5 100644 --- a/samples/gui/Sample_UIPerformance.ts +++ b/samples/gui/Sample_UIPerformance.ts @@ -97,12 +97,12 @@ export class Sample_UISpriteSheet { } addLotOfSprite() { - // enable ui canvas i + // enable ui canvas at index 0 let canvas = this.scene.view.enableUICanvas(0); //create UI root let panelRoot: Object3D = new Object3D(); //create panel - let panel = panelRoot.addComponent(ViewPanel, { billboard: true }); + let panel = panelRoot.addComponent(ViewPanel); canvas.addChild(panel.object3D); //create sprite sheet list this.createSpriteSheets(panelRoot); @@ -113,7 +113,7 @@ export class Sample_UISpriteSheet { //create UI root let panelRoot: Object3D = new Object3D(); //create panel - let panel = panelRoot.addComponent(ViewPanel, { billboard: true }); + let panel = panelRoot.addComponent(ViewPanel); panel.panelOrder = 10000; canvas.addChild(panel.object3D); let textQuad = new Object3D(); diff --git a/samples/gui/Sample_UIPerformance2.ts b/samples/gui/Sample_UIPerformance2.ts index b764662d..a705a0b9 100644 --- a/samples/gui/Sample_UIPerformance2.ts +++ b/samples/gui/Sample_UIPerformance2.ts @@ -101,7 +101,7 @@ export class Sample_UIPerformance2 { } addLotOfSprite() { - // enable ui canvas i + // enable ui canvas at index 0 let canvas = this.scene.view.enableUICanvas(0); //create UI root let panelRoot: Object3D = new Object3D(); diff --git a/samples/gui/Sample_UISingleImage.ts b/samples/gui/Sample_UISingleImage.ts index 56dedae8..9723b17f 100644 --- a/samples/gui/Sample_UISingleImage.ts +++ b/samples/gui/Sample_UISingleImage.ts @@ -1,10 +1,9 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { createExampleScene } from "@samples/utils/ExampleScene"; -import { Engine3D, Object3DUtil, Object3D, BitmapTexture2D, UIImage, makeAloneSprite, WorldPanel } from "@orillusion/core"; +import { Engine3D, Object3DUtil, Object3D, BitmapTexture2D, UIImage, makeAloneSprite, WorldPanel, GPUCullMode } from "@orillusion/core"; +import { GUIUtil } from "@samples/utils/GUIUtil"; export class Sample_UISingleImage { - private img: UIImage; - async run() { Engine3D.setting.shadow.autoUpdate = true; Engine3D.setting.shadow.shadowBias = 0.002; @@ -32,13 +31,15 @@ export class Sample_UISingleImage { await bitmapTexture2D.load('textures/KB3D_NTT_Ads_basecolor.png'); let panel = panelRoot.addComponent(WorldPanel); + panel.cullMode = GPUCullMode.none; + + GUIUtil.renderUIPanel(panel, true); + canvas.addChild(panel.object3D); - let imageQuad = new Object3D(); - panelRoot.addChild(imageQuad); - this.img = imageQuad.addComponent(UIImage); - this.img.sprite = makeAloneSprite('KB3D_NTT_Ads_basecolor', bitmapTexture2D); - this.img.uiTransform.resize(600, 400); + panel.sprite = makeAloneSprite('KB3D_NTT_Ads_basecolor', bitmapTexture2D); + panel.uiTransform.resize(600, 400); + panel.visible = true; } } diff --git a/samples/gui/Sample_UISpriteSheet.ts b/samples/gui/Sample_UISpriteSheet.ts index 73d7e77d..045667d1 100644 --- a/samples/gui/Sample_UISpriteSheet.ts +++ b/samples/gui/Sample_UISpriteSheet.ts @@ -1,4 +1,4 @@ -import { Engine3D, Object3D, Object3DUtil, WorldPanel } from "@orillusion/core"; +import { BillboardType, Engine3D, Object3D, Object3DUtil, WorldPanel } from "@orillusion/core"; import { UIImage } from "../../src/components/gui/uiComponents/UIImage"; import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { createExampleScene } from "@samples/utils/ExampleScene"; @@ -18,14 +18,15 @@ export class Sample_UISpriteSheet { Engine3D.startRenderView(exampleScene.view); await Engine3D.res.loadAtlas('atlas/Sheet_atlas.json'); - // enable ui canvas 0 + // enable ui canvas at index 0 let canvas = exampleScene.view.enableUICanvas(); //create UI root let panelRoot: Object3D = new Object3D(); panelRoot.scaleX = panelRoot.scaleY = panelRoot.scaleZ = 0.4; //create panel - let panel = panelRoot.addComponent(WorldPanel, { billboard: true }); + let panel = panelRoot.addComponent(WorldPanel); + panel.billboard = BillboardType.BillboardY; canvas.addChild(panel.object3D); // diff --git a/samples/gui/Sample_UITextField.ts b/samples/gui/Sample_UITextField.ts index 7223d53d..4f7eadaa 100644 --- a/samples/gui/Sample_UITextField.ts +++ b/samples/gui/Sample_UITextField.ts @@ -1,6 +1,6 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; import { createExampleScene } from "@samples/utils/ExampleScene"; -import { Object3D, Engine3D, GUISpace, WorldPanel, ViewPanel, UITextField, TextAnchor, Object3DUtil, UIPanel, UIImage, UIShadow } from "@orillusion/core"; +import { Object3D, Engine3D, GUISpace, WorldPanel, ViewPanel, UITextField, TextAnchor, Object3DUtil, UIPanel, UIImage, UIShadow, BillboardType, GPUCullMode } from "@orillusion/core"; import { GUIUtil } from "@samples/utils/GUIUtil"; export class Sample_UITextField { @@ -19,7 +19,7 @@ export class Sample_UITextField { let floor = Object3DUtil.GetSingleCube(100, 20, 50, 0.5, 0.5, 0.5); exampleScene.scene.addChild(floor); - // enable ui canvas 0 + // enable ui canvas at index 0 let canvas = exampleScene.view.enableUICanvas(); //create UI root @@ -32,7 +32,8 @@ export class Sample_UITextField { if (space == GUISpace.World) { panelRoot.scaleX = panelRoot.scaleY = panelRoot.scaleZ = 0.2; - panel = panelRoot.addComponent(WorldPanel, { billboard: true }); + panel = panelRoot.addComponent(WorldPanel); + panel.billboard = BillboardType.BillboardY; } else { panelRoot.scaleX = panelRoot.scaleY = panelRoot.scaleZ = 1; panel = panelRoot.addComponent(ViewPanel); diff --git a/samples/gui/Sample_UIVisible.ts b/samples/gui/Sample_UIVisible.ts index 347a2c4f..e2ce5123 100644 --- a/samples/gui/Sample_UIVisible.ts +++ b/samples/gui/Sample_UIVisible.ts @@ -23,7 +23,7 @@ export class Sample_UIVisible { exampleScene.scene.addChild(floor); floor.y = -40; - // enable ui canvas 0 + // enable ui canvas at index 0 let canvas = exampleScene.view.enableUICanvas(); //create UI root diff --git a/samples/utils/GUIUtil.ts b/samples/utils/GUIUtil.ts index 430aeafa..1098bacd 100644 --- a/samples/utils/GUIUtil.ts +++ b/samples/utils/GUIUtil.ts @@ -1,5 +1,5 @@ import { GUIHelp } from "@orillusion/debug/GUIHelp"; -import { AtmosphericComponent, Color, DirectLight, PointLight, SpotLight, Transform, UIImage, UIShadow } from "@orillusion/core"; +import { AtmosphericComponent, BillboardType, Color, DirectLight, GPUCullMode, PointLight, SpotLight, Transform, UIImage, UIPanel, UIShadow } from "@orillusion/core"; import { UVMoveComponent } from "@samples/material/script/UVMoveComponent"; export class GUIUtil { @@ -116,7 +116,7 @@ export class GUIUtil { GUIHelp.endFolder(); } - public static renderUIShadow(image: UIShadow, open: boolean, name?: string) { + public static renderUIShadow(image: UIShadow, open: boolean = true, name?: string) { name ||= 'Image Shadow'; GUIHelp.addFolder(name); GUIHelp.add(image, 'shadowQuality', 0, 4, 1); @@ -136,5 +136,38 @@ export class GUIUtil { GUIHelp.endFolder(); } + public static renderUIPanel(panel: UIPanel, open: boolean = true, name?: string) { + name ||= 'GUI Panel'; + GUIHelp.addFolder(name); + //cull mode + let cullMode = {}; + cullMode[GPUCullMode.none] = GPUCullMode.none; + cullMode[GPUCullMode.front] = GPUCullMode.front; + cullMode[GPUCullMode.back] = GPUCullMode.back; + + // change cull mode by click dropdown box + GUIHelp.add({ cullMode: GPUCullMode.none }, 'cullMode', cullMode).onChange((v) => { + panel.cullMode = v; + }); + + //billboard + let billboard = {}; + billboard['None'] = BillboardType.None; + billboard['Y'] = BillboardType.BillboardY; + billboard['XYZ'] = BillboardType.BillboardXYZ; + + // change billboard by click dropdown box + GUIHelp.add({ billboard: panel.billboard }, 'billboard', billboard).onChange((v) => { + panel.billboard = v; + }); + + //depth test + if (panel['isWorldPanel']) { + GUIHelp.add(panel, 'depthTest'); + } + + open && GUIHelp.open(); + GUIHelp.endFolder(); + } } \ No newline at end of file diff --git a/src/components/BillboardComponent.ts b/src/components/BillboardComponent.ts index c5eb2775..4e066a9d 100644 --- a/src/components/BillboardComponent.ts +++ b/src/components/BillboardComponent.ts @@ -24,11 +24,10 @@ export class BillboardComponent extends ComponentBase { let camera = this.transform.view3D.camera; this._cameraDirection.copyFrom(camera.transform.back); if (this.type == BillboardType.BillboardXYZ) { - this._cameraDirection.normalize().multiplyScalar(100); } else if (this.type == BillboardType.BillboardY) { this._cameraDirection.y = 0; - this._cameraDirection.normalize().multiplyScalar(100); } + this._cameraDirection.normalize(); this.transform.lookAt(Vector3.ZERO, this._cameraDirection, camera.transform.up); } diff --git a/src/components/controller/HoverCameraController.ts b/src/components/controller/HoverCameraController.ts index 4758f87a..2e995442 100644 --- a/src/components/controller/HoverCameraController.ts +++ b/src/components/controller/HoverCameraController.ts @@ -1,11 +1,12 @@ -import { BoundUtil, View3D } from "../.."; import { Engine3D } from "../../Engine3D"; import { Camera3D } from "../../core/Camera3D"; +import { View3D } from "../../core/View3D"; import { Object3D } from "../../core/entities/Object3D"; import { PointerEvent3D } from "../../event/eventConst/PointerEvent3D"; import { clamp } from "../../math/MathUtil"; import { Quaternion } from "../../math/Quaternion"; import { Vector3 } from "../../math/Vector3"; +import { BoundUtil } from "../../util/BoundUtil"; import { Time } from "../../util/Time"; import { Vector3Ex } from "../../util/Vector3Ex"; import { ComponentBase } from "../ComponentBase"; diff --git a/src/components/gui/GUIConfig.ts b/src/components/gui/GUIConfig.ts index 93d36f41..df298d7f 100644 --- a/src/components/gui/GUIConfig.ts +++ b/src/components/gui/GUIConfig.ts @@ -2,7 +2,9 @@ export class GUIConfig { public static readonly vertexScale: number = 1; public static quadMaxCountForWorld: number = 256; public static quadMaxCountForView: number = 2048; - public static readonly SortOrderStart: number = 8000; + public static readonly SortOrderStartWorld: number = 7000; + public static readonly SortOrderStartView: number = 8000; + public static readonly SortOrderCanvasSpan: number = 10000; } export enum GUISpace { @@ -19,7 +21,7 @@ export enum ImageType { } export enum BillboardType { - Normal = 0, + None = 0, BillboardY = 9, BillboardXYZ = 10, } \ No newline at end of file diff --git a/src/components/gui/GUIExtension.ts b/src/components/gui/GUIExtension.ts index d816bcf9..8f8831ef 100644 --- a/src/components/gui/GUIExtension.ts +++ b/src/components/gui/GUIExtension.ts @@ -1,49 +1,4 @@ -// export function GUIBindImage(target: ELPObject3D, texture: GUISubTexture): UIImg { -// let img: UIImg = target.addComponent(UIImg); -// img.texture = texture; -// return img; -// } -// -// export function GUIBindText( -// target: ELPObject3D, -// text: string, -// fontSize?: number, -// width?: number, -// height?: number, -// color?: Vector4, -// font?: string, -// alignment?: number, -// lineSpacing?: number, -// ): UITextField { -// let uiText: UITextField = target.addComponent(UITextField); -// if (fontSize) uiText.fontSize = fontSize; -// if (font) uiText.font = font; -// if (color) uiText.color = color; -// if (alignment) uiText.alignment = alignment; -// if (lineSpacing) uiText.lineSpacing = lineSpacing; -// if (text) uiText.text = text; -// -// return uiText; -// } -// -// export function GUIBindPanel(obj: ELPObject3D, rendMode: GUISpace, order?: number) { -// let panel: UIPanel = null; -// if (rendMode == GUISpace.World) panel = obj.addComponent(WorldPanel); -// else panel = obj.addComponent(ViewPanel); -// if (order) panel.order = order; -// return panel; -// } -// -// export function GUICreateImage(texture: GUISubTexture, panel: ViewPanel): UIImg { -// let obj = new ELPObject3D(); -// let img = obj.addComponent(UIImg); -// img.texture = texture; -// obj.uiTransform.resize(texture.width, texture.height); -// panel.object.add(obj); -// return img; -// } - import { Texture } from "../../gfx/graphics/webGpu/core/texture/Texture"; import { GUISprite } from "./core/GUISprite"; import { GUITexture } from "./core/GUITexture"; diff --git a/src/components/gui/GUIPick.ts b/src/components/gui/GUIPick.ts index c8e81e4c..329defce 100644 --- a/src/components/gui/GUIPick.ts +++ b/src/components/gui/GUIPick.ts @@ -17,7 +17,7 @@ import { zSorterUtil } from '../../util/ZSorterUtil'; /** * Pickup logic for GUI interactive components - * @group GUI/IO + * @group GPU GUI */ export class GUIPick { // The ray used for bounding box pickup diff --git a/src/components/gui/GUIPickHelper.ts b/src/components/gui/GUIPickHelper.ts index 15e3e86d..f9867508 100644 --- a/src/components/gui/GUIPickHelper.ts +++ b/src/components/gui/GUIPickHelper.ts @@ -6,6 +6,10 @@ import { Vector3 } from "../../math/Vector3"; import { UITransform } from "./uiComponents/UITransform"; import { GUISpace } from "./GUIConfig"; +/** + * @internal + * @group GPU GUI + */ export class GUIPickHelper { private static _pt0: Vector3; private static _pt1: Vector3; diff --git a/src/components/gui/core/GUIAtlasTexture.ts b/src/components/gui/core/GUIAtlasTexture.ts index e80f1839..4b1b77b6 100644 --- a/src/components/gui/core/GUIAtlasTexture.ts +++ b/src/components/gui/core/GUIAtlasTexture.ts @@ -3,6 +3,10 @@ import { GUITexture } from './GUITexture'; import { Vector2 } from '../../../math/Vector2'; import { makeGUISprite } from '../GUIExtension'; +/** + * Atlas data + * @group GPU GUI + */ export class GUIAtlasTexture { private _spriteMap: Map = new Map(); private _spriteList: GUISprite[] = []; diff --git a/src/components/gui/core/GUICanvas.ts b/src/components/gui/core/GUICanvas.ts index 504c9ff7..3837aef0 100644 --- a/src/components/gui/core/GUICanvas.ts +++ b/src/components/gui/core/GUICanvas.ts @@ -8,9 +8,14 @@ import { GUIGeometryRebuild } from "./GUIGeometryRebuild"; import { GUIMaterial } from "./GUIMaterial"; import { GUIMesh } from "./GUIMesh"; +/** + * GUI Root Container + * @group GPU GUI + */ export class GUICanvas extends ComponentBase { private _rebuild: GUIGeometryRebuild; + public index: number = 0; init() { super.init(); this._rebuild = new GUIGeometryRebuild(); @@ -45,12 +50,13 @@ export class GUICanvas extends ComponentBase { let panelList: UIPanel[] = this.object3D.getComponentsByProperty('isUIPanel', true, true); let camera = this.object3D?.transform?.view3D?.camera; - let screenWidth = webGPUContext.canvas.clientWidth; let screenHeight = webGPUContext.canvas.clientHeight; + let transforms: UITransform[] = []; for (let panel of panelList) { + transforms.length = 0; let guiMesh: GUIMesh = panel.guiMesh; - let transforms: UITransform[] = panel.object3D.getComponents(UITransform); + panel.object3D.getComponents(UITransform, transforms); if (transforms.length > 0) { this._rebuild.build(transforms, guiMesh, panel.needUpdateGeometry); guiMesh.updateGUIData(screenWidth, screenHeight, camera); @@ -58,9 +64,14 @@ export class GUICanvas extends ComponentBase { t.needUpdateQuads = false; } } - // panel.guiMesh.enable = transforms.length > 0; + + //calc render order + let canvas = panel.object3D.getComponentFromParent(GUICanvas); + let canvasIndex = canvas ? canvas.index : 0; guiMesh.uiRenderer.enable = transforms.length > 0; - guiMesh.uiRenderer.renderOrder = GUIConfig.SortOrderStart + panel.panelOrder; + let renderStart = panel['isViewPanel'] ? GUIConfig.SortOrderStartView : GUIConfig.SortOrderStartWorld; + guiMesh.uiRenderer.renderOrder = canvasIndex * GUIConfig.SortOrderCanvasSpan + renderStart + panel.panelOrder; + // guiMesh.uiRenderer.needSortOnCameraZ = panel.needSortOnCameraZ; (guiMesh.uiRenderer.material as GUIMaterial).setLimitVertex(guiMesh.limitVertexCount); panel.needUpdateGeometry = false; diff --git a/src/components/gui/core/GUIDefine.ts b/src/components/gui/core/GUIDefine.ts index b58fe9b8..ccb6cb2d 100644 --- a/src/components/gui/core/GUIDefine.ts +++ b/src/components/gui/core/GUIDefine.ts @@ -1,3 +1,8 @@ +/** + * GUI Root Container + * @internal + * @group GPU GUI + */ export enum GUIQuadAttrEnum { NONE = 0, POSITION = 1 << 0, diff --git a/src/components/gui/core/GUIGeometry.ts b/src/components/gui/core/GUIGeometry.ts index 25791c80..5fc29af1 100644 --- a/src/components/gui/core/GUIGeometry.ts +++ b/src/components/gui/core/GUIGeometry.ts @@ -16,6 +16,10 @@ class GUIAttribute { } } +/** + * composite geometry of gui, holding and updating attribute data + * @group GPU GUI + */ export class GUIGeometry extends GeometryBase { private _attributeUV: Float32Array; private _attributeVIndex: Float32Array; diff --git a/src/components/gui/core/GUIGeometryRebuild.ts b/src/components/gui/core/GUIGeometryRebuild.ts index bba1baa3..2b80a876 100644 --- a/src/components/gui/core/GUIGeometryRebuild.ts +++ b/src/components/gui/core/GUIGeometryRebuild.ts @@ -8,7 +8,7 @@ import { GUITexture } from "./GUITexture"; /** * This class is responsible for performing the Geometry reconstruction work of the GUI - * @group GUI + * @group GPU GUI */ export class GUIGeometryRebuild { private _textureMap: Map = new Map(); diff --git a/src/components/gui/core/GUIMaterial.ts b/src/components/gui/core/GUIMaterial.ts index c447da8c..0062804c 100644 --- a/src/components/gui/core/GUIMaterial.ts +++ b/src/components/gui/core/GUIMaterial.ts @@ -1,10 +1,17 @@ -import { MaterialBase, ShaderLib, Vector2, BlendMode, GPUCompareFunction, GPUCullMode, Texture, Engine3D, registerMaterial } from "../../.."; +import { Engine3D } from "../../../Engine3D"; +import { ShaderLib } from "../../../assets/shader/ShaderLib"; +import { GPUCompareFunction, GPUCullMode } from "../../../gfx/graphics/webGpu/WebGPUConst"; +import { Texture } from "../../../gfx/graphics/webGpu/core/texture/Texture"; +import { BlendMode } from "../../../materials/BlendMode"; +import { MaterialBase } from "../../../materials/MaterialBase"; +import { registerMaterial } from "../../../materials/MaterialRegister"; +import { Vector2 } from "../../../math/Vector2"; import { GUISpace } from "../GUIConfig"; import { GUIShader } from "./GUIShader"; /** * material used in rendering GUI - * @group GUI + * @group GUI GPU */ export class GUIMaterial extends MaterialBase { constructor(space: GUISpace) { diff --git a/src/components/gui/core/GUIMesh.ts b/src/components/gui/core/GUIMesh.ts index 2e492ce5..2e8075f2 100644 --- a/src/components/gui/core/GUIMesh.ts +++ b/src/components/gui/core/GUIMesh.ts @@ -4,12 +4,15 @@ import { IBound } from "../../../core/bound/IBound"; import { Object3D } from "../../../core/entities/Object3D"; import { Texture } from "../../../gfx/graphics/webGpu/core/texture/Texture"; import { Vector3 } from "../../../math/Vector3"; -import { BillboardComponent } from "../../BillboardComponent"; -import { GUISpace, GUIConfig, BillboardType } from "../GUIConfig"; +import { GUISpace, GUIConfig } from "../GUIConfig"; import { GUIGeometry } from "./GUIGeometry"; import { GUIMaterial } from "./GUIMaterial"; import { GUIRenderer } from "./GUIRenderer"; +/** + * A object3D for GUI, holding material/geometry/renderer + * @group GPU GUI + */ export class GUIMesh extends Object3D { public uiRenderer: GUIRenderer; public geometry: GUIGeometry; @@ -18,7 +21,6 @@ export class GUIMesh extends Object3D { public limitVertexCount: number = 0; private readonly _maxCount: number = 128; - private _billboard: BillboardComponent; private _uiMaterial: GUIMaterial; constructor(space: GUISpace, param?) { @@ -55,13 +57,7 @@ export class GUIMesh extends Object3D { this.geometry = this.uiRenderer.geometry as GUIGeometry; this._uiMaterial = this.uiRenderer.material as GUIMaterial; - let useBillboard = param && param.billboard; - if (this.space == GUISpace.World && useBillboard) { - this._billboard = this.addComponent(BillboardComponent); - this._billboard.type = BillboardType.BillboardXYZ; - } - - this.uiRenderer.renderOrder = GUIConfig.SortOrderStart; + this.uiRenderer.renderOrder = GUIConfig.SortOrderStartWorld; } private _setTextures(textures: Texture[]): this { @@ -71,19 +67,5 @@ export class GUIMesh extends Object3D { public updateGUIData(screenWidth: number, screenHeight: number, camera: Camera3D) { this._uiMaterial.setScreenSize(screenWidth, screenHeight); - // this.transform.localPosition.copy(worldPanel.worldPosition); - // if (this.billboard) { - // this.billboard.enable = worldPanel.rotation == null; - // } - // if (worldPanel.rotation) { - // if (worldPanel.rotation instanceof Quaternion) { - // this.transform.localRotQuat.copyFrom(worldPanel.rotation); - // } else if (worldPanel.rotation instanceof Vector3) { - // this.transform.localRotation.copyFrom(worldPanel.rotation); - // // this.transform.localRotation.order = 'YZX'; - // } else { - // this.transform.localRotQuat.copyFrom(worldPanel.rotation.localRotation); - // } - // } } } diff --git a/src/components/gui/core/GUIQuad.ts b/src/components/gui/core/GUIQuad.ts index 94661678..02555220 100644 --- a/src/components/gui/core/GUIQuad.ts +++ b/src/components/gui/core/GUIQuad.ts @@ -10,6 +10,10 @@ import { GUIQuadAttrEnum } from "./GUIDefine"; let gui_help_mtx3: Matrix3; +/** + * The smallest unit in the GUI, basic information required for rendering a plane + * @group GPU GUI + */ export class GUIQuad { public x: number = 0; public y: number = 0; diff --git a/src/components/gui/core/GUIRenderer.ts b/src/components/gui/core/GUIRenderer.ts index d7d1bdd6..c92cb3b0 100644 --- a/src/components/gui/core/GUIRenderer.ts +++ b/src/components/gui/core/GUIRenderer.ts @@ -10,7 +10,7 @@ import { GUIMaterial } from "./GUIMaterial"; /** * GUI Renderer * Used to update Geometry and Buffer. - * @group GUI + * @group GPU GUI */ export class GUIRenderer extends MeshRenderer { diff --git a/src/components/gui/core/GUIShader.ts b/src/components/gui/core/GUIShader.ts index 148dbcdb..0be1572a 100644 --- a/src/components/gui/core/GUIShader.ts +++ b/src/components/gui/core/GUIShader.ts @@ -2,6 +2,10 @@ import { WorldMatrixUniform } from "../../../assets/shader/core/common/WorldMatrixUniform"; import { ColorPassFragmentOutput } from "../../../assets/shader/core/struct/ColorPassFragmentOutput"; +/** + * shader code + * @group GPU GUI + */ export class GUIShader { private static bindTextureArray() { let value = ``; diff --git a/src/components/gui/core/GUISprite.ts b/src/components/gui/core/GUISprite.ts index 063aa465..85f97288 100644 --- a/src/components/gui/core/GUISprite.ts +++ b/src/components/gui/core/GUISprite.ts @@ -3,6 +3,10 @@ import { Vector2 } from "../../../math/Vector2"; import { Vector4 } from "../../../math/Vector4"; import { GUITexture } from "./GUITexture"; +/** + * Sprites are simple 2D objects with graphical images + * @group GPU GUI + */ export class GUISprite { public id: string; public guiTexture: GUITexture; diff --git a/src/components/gui/core/GUITexture.ts b/src/components/gui/core/GUITexture.ts index 29fc17a8..dee26eeb 100644 --- a/src/components/gui/core/GUITexture.ts +++ b/src/components/gui/core/GUITexture.ts @@ -1,6 +1,10 @@ import { Engine3D } from "../../../Engine3D"; import { Texture } from "../../../gfx/graphics/webGpu/core/texture/Texture"; +/** + * @internal + * @group GPU GUI + */ export class GUITexture { private static _maxUid: number = -1; //Self increasing number, starting from 0 diff --git a/src/components/gui/uiComponents/UIButton.ts b/src/components/gui/uiComponents/UIButton.ts index 89423f55..f07fdb8f 100644 --- a/src/components/gui/uiComponents/UIButton.ts +++ b/src/components/gui/uiComponents/UIButton.ts @@ -5,6 +5,10 @@ import { UIInteractiveStyle } from './IUIInteractive'; import { UIImage } from './UIImage'; import { UIInteractive } from './UIInteractive'; +/** + * The basic components used in the GUI to respond to user interaction behavior and have an image component + * @group GPU GUI + */ export class UIButton extends UIInteractive { protected _spriteMap: Map; protected _image: UIImage; @@ -88,15 +92,19 @@ export class UIButton extends UIInteractive { } } - cloneTo(obj: Object3D) { + public cloneTo(obj: Object3D) { let component = obj.getOrAddComponent(UIButton); component.copyComponent(this); - component.downSprite = this.downSprite; - component.normalSprite = this.normalSprite; - component.disableSprite = this.disableSprite; - component.overSprite = this.overSprite; - component.mouseStyle = this.mouseStyle; - component.enable = this.enable; + } + + public copyComponent(from: this): this { + super.copyComponent(from); + this.downSprite = from.downSprite; + this.normalSprite = from.normalSprite; + this.disableSprite = from.disableSprite; + this.overSprite = from.overSprite; + this.mouseStyle = from.mouseStyle; + return this; } public destroy(): void { diff --git a/src/components/gui/uiComponents/UIComponentBase.ts b/src/components/gui/uiComponents/UIComponentBase.ts index 5dc91d28..2b9b679e 100644 --- a/src/components/gui/uiComponents/UIComponentBase.ts +++ b/src/components/gui/uiComponents/UIComponentBase.ts @@ -1,6 +1,10 @@ import { ComponentBase } from "../../ComponentBase"; import { UITransform } from "./UITransform"; +/** + * The basic component for all GUI component + * @group GPU GUI + */ export class UIComponentBase extends ComponentBase { protected _uiTransform: UITransform; protected _visible: boolean = true; diff --git a/src/components/gui/uiComponents/UIImage.ts b/src/components/gui/uiComponents/UIImage.ts index 5b21ad85..472035ee 100644 --- a/src/components/gui/uiComponents/UIImage.ts +++ b/src/components/gui/uiComponents/UIImage.ts @@ -6,20 +6,29 @@ import { ImageType } from '../GUIConfig'; import { Engine3D } from '../../../Engine3D'; import { UIRenderAble } from './UIRenderAble'; -// A UI component to display image/sprite/video +/** + * A GUI component to display image/sprite/video + * @group GPU GUI + */ export class UIImage extends UIRenderAble { init(param?: any): void { super.init?.(param); this.attachQuad(GUIQuad.spawnQuad()); + this.sprite = Engine3D.res.defaultGUISprite; } public cloneTo(obj: Object3D) { let component = obj.getOrAddComponent(UIImage); component.copyComponent(this); - component.sprite = this.sprite; - component.color = this.color; - component.imageType = this.imageType; + } + + public copyComponent(from: this): this { + super.copyComponent(from); + this.sprite = from.sprite; + this.color = from.color; + this.imageType = from.imageType; + return this; } public set sprite(value: GUISprite) { diff --git a/src/components/gui/uiComponents/UIImageGroup.ts b/src/components/gui/uiComponents/UIImageGroup.ts index 7b9a8d65..140886d6 100644 --- a/src/components/gui/uiComponents/UIImageGroup.ts +++ b/src/components/gui/uiComponents/UIImageGroup.ts @@ -5,9 +5,12 @@ import { GUISprite } from '../core/GUISprite'; import { ImageType } from '../GUIConfig'; import { Engine3D } from '../../../Engine3D'; import { UIRenderAble } from './UIRenderAble'; -import { Vector2 } from '../../..'; +import { Vector2 } from '../../../math/Vector2'; -// A UI component to display a group images/sprites/videos +/** + * A UI component to display a group images/sprites/videos + * @group GPU GUI + */ export class UIImageGroup extends UIRenderAble { private _count: number = 0; constructor() { @@ -20,6 +23,7 @@ export class UIImageGroup extends UIRenderAble { for (let i = 0; i < this._count; i++) { this.attachQuad(GUIQuad.spawnQuad()); } + this._uiTransform.resize(0, 0); } public getQuad(index: number) { @@ -29,11 +33,16 @@ export class UIImageGroup extends UIRenderAble { public cloneTo(obj: Object3D) { let component = obj.addComponent(UIImageGroup, { count: this._count }); component.copyComponent(this); - for (let i = 0; i < this._count; i++) { - component.setSprite(i, this.getSprite(i)); - component.setColor(i, this.getColor(i)); - component.setImageType(this.getImageType(i), i); + } + + public copyComponent(from: this): this { + super.copyComponent(from); + for (let i = 0; i < from._count; i++) { + this.setSprite(i, from.getSprite(i)); + this.setColor(i, from.getColor(i)); + this.setImageType(from.getImageType(i), i); } + return this; } public setSprite(index: number, value: GUISprite) { diff --git a/src/components/gui/uiComponents/UIInteractive.ts b/src/components/gui/uiComponents/UIInteractive.ts index fcdac1ee..8b1de968 100644 --- a/src/components/gui/uiComponents/UIInteractive.ts +++ b/src/components/gui/uiComponents/UIInteractive.ts @@ -5,7 +5,11 @@ import { Ray } from '../../../math/Ray'; import { GUIPickHelper } from '../GUIPickHelper'; import { Object3D } from '../../../core/entities/Object3D'; import { Vector3 } from '../../../math/Vector3'; -// basic class of interactive GUI component + +/** + * The basic class of interactive GUI component + * @group GPU GUI + */ export class UIInteractive extends UIComponentBase implements IUIInteractive { protected _style: UIInteractiveStyle = UIInteractiveStyle.NORMAL; protected _interactive: boolean = false; @@ -41,11 +45,16 @@ export class UIInteractive extends UIComponentBase implements IUIInteractive { return GUIPickHelper.rayPick(ray, screenPos, screenSize, mesh.space, this._uiTransform, mesh.transform.worldMatrix) } - cloneTo(obj: Object3D) { + public cloneTo(obj: Object3D) { let component = obj.getOrAddComponent(UIInteractive); component.copyComponent(this); - component.enable = this.enable; - component.interactive = this.interactive; - component.mouseStyle = this._style; + } + + public copyComponent(from: this): this { + super.copyComponent(from); + this.enable = from._enable; + this.interactive = from._interactive; + this.mouseStyle = from._style; + return this; } } diff --git a/src/components/gui/uiComponents/UIPanel.ts b/src/components/gui/uiComponents/UIPanel.ts index 2ab137ef..32c7e0d1 100644 --- a/src/components/gui/uiComponents/UIPanel.ts +++ b/src/components/gui/uiComponents/UIPanel.ts @@ -1,57 +1,39 @@ -import { View3D } from "../../.."; -import { GUISpace } from "../GUIConfig"; +import { Object3D, UITransform, View3D } from "../../.."; +import { BillboardComponent } from "../../BillboardComponent"; +import { BillboardType, GUISpace } from "../GUIConfig"; import { GUIMesh } from "../core/GUIMesh"; -import { UIComponentBase } from "./UIComponentBase"; +import { UIImage } from "./UIImage"; -//Container for UI components -export class UIPanel extends UIComponentBase { +/** + * Container for UI components + * @group GPU GUI + */ +export class UIPanel extends UIImage { public order: number; - public space: number = GUISpace.World; + public readonly space: number = GUISpace.World; public needUpdateGeometry: boolean = true; public panelOrder: number = 0; public needSortOnCameraZ?: boolean; protected _mesh: GUIMesh; + protected _billboard: BillboardComponent; + public readonly isUIPanel = true; public get guiMesh(): GUIMesh { return this._mesh; } - start() { - // throw new Error("Method not implemented."); - } - stop() { - // throw new Error("Method not implemented."); - } - onEnable?(view?: View3D) { - // throw new Error("Method not implemented."); - } - onDisable?(view?: View3D) { - // throw new Error("Method not implemented."); - } - onUpdate?(view?: View3D) { - // throw new Error("Method not implemented."); - } - onLateUpdate?(view?: View3D) { - // throw new Error("Method not implemented."); - } - onBeforeUpdate?(view?: View3D) { - // throw new Error("Method not implemented."); - } - onCompute?(view?: View3D, command?: GPUCommandEncoder) { - // throw new Error("Method not implemented."); - } - onGraphic?(view?: View3D) { - // throw new Error("Method not implemented."); + public cloneTo(obj: Object3D): void { + let component = obj.addComponent(UIPanel); + component.copyComponent(this); } - destroy(force?: boolean) { - // throw new Error("Method not implemented."); - } public copyComponent(from: this): this { - this.visible = from.visible; + super.copyComponent(from); this.order = from.order; this.panelOrder = from.panelOrder; this.needSortOnCameraZ = from.needSortOnCameraZ; + this.cullMode = from.cullMode; + this.billboard = from.billboard; return this; } @@ -59,6 +41,38 @@ export class UIPanel extends UIComponentBase { super.init(param); this._mesh = new GUIMesh(this.space, param); this.object3D.addChild(this._mesh); + this.visible = false; + } + + public set billboard(type: BillboardType) { + if (this.space == GUISpace.View) { + type = BillboardType.None; + } else { + console.warn('Cannot enable billboard in view space'); + } + if (type == BillboardType.BillboardXYZ || type == BillboardType.BillboardY) { + this._billboard = this._mesh.getOrAddComponent(BillboardComponent); + this._billboard.type = type; + } else { + this._mesh.removeComponent(BillboardComponent); + this._billboard = null; + } + } + + public get billboard() { + return this._billboard ? this._billboard.type : BillboardType.None; + } + + public set cullMode(value: GPUCullMode) { + if (this.space == GUISpace.World) { + this._mesh.uiRenderer.material.cullMode = value; + } else { + console.warn('Cannot change cullMode in view space'); + } + } + + public get cullMode() { + return this._mesh.uiRenderer.material.cullMode; } } diff --git a/src/components/gui/uiComponents/UIRenderAble.ts b/src/components/gui/uiComponents/UIRenderAble.ts index a3454e87..2ca3ddff 100644 --- a/src/components/gui/uiComponents/UIRenderAble.ts +++ b/src/components/gui/uiComponents/UIRenderAble.ts @@ -1,6 +1,10 @@ import { UIComponentBase } from "./UIComponentBase"; import { GUIQuad } from "../core/GUIQuad"; +/** + * The basic class of render able GUI component + * @group GPU GUI + */ export class UIRenderAble extends UIComponentBase { protected _mainQuads: GUIQuad[]; protected _shadowRender: UIRenderAble; @@ -114,6 +118,7 @@ export class UIRenderAble extends UIComponentBase { } public copyComponent(from: this): this { + super.copyComponent(from); this.isUIShadow = from.isUIShadow; this.isShadowless = from.isShadowless; return this; diff --git a/src/components/gui/uiComponents/UIShadow.ts b/src/components/gui/uiComponents/UIShadow.ts index 27af9caa..4ee2f755 100644 --- a/src/components/gui/uiComponents/UIShadow.ts +++ b/src/components/gui/uiComponents/UIShadow.ts @@ -1,7 +1,15 @@ -import { Color, Object3D, UIRenderAble, View3D, clamp } from "../../.."; +import { View3D } from "../../../core/View3D"; +import { Object3D } from "../../../core/entities/Object3D"; +import { Color } from "../../../math/Color"; +import { clamp } from "../../../math/MathUtil"; import { Vector2 } from "../../../math/Vector2"; import { GUIQuad } from "../core/GUIQuad"; +import { UIRenderAble } from "./UIRenderAble"; +/** + * The shadow component for gui + * @group GPU GUI + */ export class UIShadow extends UIRenderAble { private _shadowQuality: number = 1; private _shadowOffset: Vector2; @@ -14,6 +22,7 @@ export class UIShadow extends UIRenderAble { public init(param?: any): void { super.init?.(param); this._shadowRadius = 2; + this._shadowQuality = 1; this._shadowOffset = new Vector2(4, -4); this._shadowColor = new Color(0.1, 0.1, 0.1, 0.8); this._subShadowColor = this._shadowColor.clone(); @@ -23,11 +32,15 @@ export class UIShadow extends UIRenderAble { public cloneTo(obj: Object3D) { let component = obj.getOrAddComponent(UIShadow); component.copyComponent(this); - //shadow - component._shadowColor = this._shadowColor; - component._shadowOffset = this._shadowOffset; - component._shadowRadius = this._shadowRadius; - component._shadowQuality = this.shadowQuality; + } + + public copyComponent(from: this): this { + super.copyComponent(this); + this._shadowColor = from._shadowColor; + this._shadowOffset = from._shadowOffset; + this._shadowRadius = from._shadowRadius; + this._shadowQuality = from.shadowQuality; + return this; } public get shadowColor(): Color { diff --git a/src/components/gui/uiComponents/UITextField.ts b/src/components/gui/uiComponents/UITextField.ts index d76f1dfd..0ff2e66f 100644 --- a/src/components/gui/uiComponents/UITextField.ts +++ b/src/components/gui/uiComponents/UITextField.ts @@ -3,6 +3,10 @@ import { Color } from '../../../math/Color'; import { UIRenderAble } from './UIRenderAble'; import { TextAnchor, TextFieldLayout, TextFieldLine } from './TextFieldLayout'; +/** + * The textField component for gui + * @group GPU GUI + */ export class UITextField extends UIRenderAble { private _font: string = '微软雅黑'; private _fontSize: number = 14; @@ -19,13 +23,18 @@ export class UITextField extends UIRenderAble { cloneTo(obj: Object3D) { let component = obj.getOrAddComponent(UITextField); component.copyComponent(this); - component._font = this._font; - component._fontSize = this._fontSize; - component._originSize = this._originSize; - component._alignment = this._alignment; - component._lineSpacing = this._lineSpacing; - component._color.copyFrom(this._color); - component.text = this.text; + } + + public copyComponent(from: this): this { + super.copyComponent(from); + this._font = from._font; + this._fontSize = from._fontSize; + this._originSize = from._originSize; + this._alignment = from._alignment; + this._lineSpacing = from._lineSpacing; + this._color.copyFrom(from._color); + this.text = this.text; + return this; } public get originSize(): number { diff --git a/src/components/gui/uiComponents/UITransform.ts b/src/components/gui/uiComponents/UITransform.ts index 2c2781f6..02b36e3b 100644 --- a/src/components/gui/uiComponents/UITransform.ts +++ b/src/components/gui/uiComponents/UITransform.ts @@ -9,14 +9,18 @@ import { WorldPanel } from "./WorldPanel"; let help_matrix3: Matrix3; +/** + * The component for gui, holding information such as size, scaling, position, etc + * @group GPU GUI + */ export class UITransform extends ComponentBase { public useParentPivot: boolean = false; public parent: UITransform; public pivotX: number = 0.5; public pivotY: number = 0.5; - private _width: number = 1; - private _height: number = 1; + private _width: number = 100; + private _height: number = 100; private _localVisible: boolean = true; private _globalVisible: boolean = true; public guiMesh: GUIMesh; @@ -32,6 +36,11 @@ export class UITransform extends ComponentBase { this._worldMatrix = new Matrix3(); } + public init(param?: any): void { + super.init(param); + this.onParentChange(null, this.object3D.parent?.object3D); + } + public addUIInteractive(item: IUIInteractive): this { this._uiInteractiveList ||= []; this._uiInteractiveList.push(item); @@ -172,6 +181,15 @@ export class UITransform extends ComponentBase { this.object3D.scaleY = value; } + public get scaleZ(): number { + return this.object3D.scaleZ; + } + + public set scaleZ(value: number) { + this.onChange = true; + this.object3D.scaleZ = value; + } + private _localMatrix: Matrix3; private _worldMatrix: Matrix3; @@ -239,7 +257,12 @@ export class UITransform extends ComponentBase { public matrix(): Matrix3 { let mtx = this._localMatrix; let rot = this.object3D.rotationZ; - mtx.updateScaleAndRotation(this.object3D.scaleX, this.object3D.scaleY, rot, rot); + if (this.parent) { + mtx.updateScaleAndRotation(this.object3D.scaleX, this.object3D.scaleY, rot, rot); + } else { + //it's ui panel root + mtx.updateScaleAndRotation(1, 1, rot, rot); + } mtx.tx = this.object3D.x; mtx.ty = this.object3D.y; diff --git a/src/components/gui/uiComponents/ViewPanel.ts b/src/components/gui/uiComponents/ViewPanel.ts index dc444cb1..1c5432e4 100644 --- a/src/components/gui/uiComponents/ViewPanel.ts +++ b/src/components/gui/uiComponents/ViewPanel.ts @@ -2,17 +2,21 @@ import { Object3D } from '../../../core/entities/Object3D'; import { GUISpace } from '../GUIConfig'; import { UIPanel } from './UIPanel'; -// UI component container for view/screen space +/** + * + * UI component container for view/screen space + * @group GPU GUI + */ export class ViewPanel extends UIPanel { public readonly isViewPanel = true; - + public readonly space: GUISpace = GUISpace.View; constructor() { super(); - this.space = GUISpace.View; } public cloneTo(obj: Object3D) { let component: ViewPanel = obj.getOrAddComponent(ViewPanel); component.copyComponent(this); } + } diff --git a/src/components/gui/uiComponents/WorldPanel.ts b/src/components/gui/uiComponents/WorldPanel.ts index db650f78..d4392711 100644 --- a/src/components/gui/uiComponents/WorldPanel.ts +++ b/src/components/gui/uiComponents/WorldPanel.ts @@ -1,20 +1,42 @@ +import { GPUCompareFunction, View3D } from "../../.."; import { Object3D } from "../../../core/entities/Object3D"; import { GUISpace } from "../GUIConfig"; import { UIPanel } from "./UIPanel"; -// UI component container for world space +/** + * UI component container for world space + * @group GPU GUI + */ export class WorldPanel extends UIPanel { - public depthTest: boolean = false; public readonly isWorldPanel = true; + public readonly space: GUISpace = GUISpace.World; + private _depthTest: boolean = true; constructor() { super(); - this.space = GUISpace.World; } public cloneTo(obj: Object3D) { let component: WorldPanel = obj.getOrAddComponent(WorldPanel); component.copyComponent(this); - component.depthTest = this.depthTest; } + + public copyComponent(from: this): this { + super.copyComponent(from); + this.depthTest = from.depthTest; + return this; + } + + public get depthTest() { + return this._depthTest; + } + + public set depthTest(value: boolean) { + if (this._depthTest != value) { + this._depthTest = value; + let compare = this.depthTest ? GPUCompareFunction.less_equal : GPUCompareFunction.always; + this.guiMesh.uiRenderer.material.depthCompare = compare; + } + } + } diff --git a/src/components/renderer/RenderNode.ts b/src/components/renderer/RenderNode.ts index dd882380..0d31da54 100644 --- a/src/components/renderer/RenderNode.ts +++ b/src/components/renderer/RenderNode.ts @@ -1,4 +1,3 @@ -import { Reference, ShadowLightsCollect } from "../.."; import { Engine3D } from "../../Engine3D"; import { View3D } from "../../core/View3D"; import { GeometryBase } from "../../core/geometry/GeometryBase"; @@ -8,6 +7,7 @@ import { RenderShader } from "../../gfx/graphics/webGpu/shader/RenderShader"; import { ShaderReflection } from "../../gfx/graphics/webGpu/shader/value/ShaderReflectionInfo"; import { GPUContext } from "../../gfx/renderJob/GPUContext"; import { EntityCollect } from "../../gfx/renderJob/collect/EntityCollect"; +import { ShadowLightsCollect } from "../../gfx/renderJob/collect/ShadowLightsCollect"; import { RTResourceMap } from "../../gfx/renderJob/frame/RTResourceMap"; import { RenderContext } from "../../gfx/renderJob/passRenderer/RenderContext"; import { ClusterLightingBuffer } from "../../gfx/renderJob/passRenderer/cluster/ClusterLightingBuffer"; @@ -16,6 +16,7 @@ import { RendererPassState } from "../../gfx/renderJob/passRenderer/state/Render import { RendererType } from "../../gfx/renderJob/passRenderer/state/RendererType"; import { MaterialBase } from "../../materials/MaterialBase"; import { UUID } from "../../util/Global"; +import { Reference } from "../../util/Reference"; import { ComponentBase } from "../ComponentBase"; import { IESProfiles } from "../lights/IESProfiles"; diff --git a/src/core/View3D.ts b/src/core/View3D.ts index 48480c67..7f334f66 100644 --- a/src/core/View3D.ts +++ b/src/core/View3D.ts @@ -94,6 +94,7 @@ export class View3D extends CEventListener { let obj = new Object3D(); obj.name = 'Canvas ' + index; canvas = obj.addComponent(GUICanvas); + canvas.index = index; this.canvasList[index] = canvas; } diff --git a/src/core/entities/Object3D.ts b/src/core/entities/Object3D.ts index 01b972aa..9c6b91a3 100644 --- a/src/core/entities/Object3D.ts +++ b/src/core/entities/Object3D.ts @@ -51,8 +51,8 @@ export class Object3D extends Entity { if (!this.components.has(className)) { let instance: T = new c() as T; instance.object3D = this; - instance[`__init`](param); this.components.set(className, instance); + instance[`__init`](param); ComponentCollect.appendWaitStart(this, instance); return instance; } diff --git a/src/gfx/graphics/webGpu/shader/RenderShader.ts b/src/gfx/graphics/webGpu/shader/RenderShader.ts index 80f714e8..cec93141 100644 --- a/src/gfx/graphics/webGpu/shader/RenderShader.ts +++ b/src/gfx/graphics/webGpu/shader/RenderShader.ts @@ -27,7 +27,7 @@ import { GPUBufferType } from "../core/buffer/GPUBufferType"; import { MaterialDataUniformGPUBuffer } from "../core/buffer/MaterialDataUniformGPUBuffer"; import { ShaderUtil } from "./util/ShaderUtil"; -import { Reference } from "../../../.."; +import { Reference } from "../../../../util/Reference"; export class RenderShader extends ShaderBase { public useRz: boolean = false; diff --git a/src/gfx/renderJob/collect/ComponentCollect.ts b/src/gfx/renderJob/collect/ComponentCollect.ts index d3b81591..ef56fe8f 100644 --- a/src/gfx/renderJob/collect/ComponentCollect.ts +++ b/src/gfx/renderJob/collect/ComponentCollect.ts @@ -1,5 +1,5 @@ -import { View3D } from "../../.."; import { IComponent } from "../../../components/IComponent"; +import { View3D } from "../../../core/View3D"; import { Object3D } from "../../../core/entities/Object3D"; export class ComponentCollect { diff --git a/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts b/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts index 8d559097..adb6e32c 100644 --- a/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts +++ b/src/gfx/renderJob/passRenderer/graphic/Graphic3DRender.ts @@ -11,7 +11,7 @@ import { Graphics3DShape } from "./Graphics3DShape"; import { GraphicConfig } from "./GraphicConfig"; import { Graphic3DFillRenderer } from "./Graphic3DFillRenderer"; import { Graphic3DLineBatchRenderer } from "./Graphic3DLineBatchRenderer"; -import { BoundUtil } from "../../../.."; +import { BoundUtil } from "../../../../util/BoundUtil"; export class Graphic3D extends Object3D { diff --git a/src/loader/parser/FontParser.ts b/src/loader/parser/FontParser.ts index 764c1795..80d18038 100644 --- a/src/loader/parser/FontParser.ts +++ b/src/loader/parser/FontParser.ts @@ -1,4 +1,4 @@ -import { Engine3D } from "../.."; +import { Engine3D } from "../../Engine3D"; import { fonts } from "../../assets/Fonts"; import { GUISprite } from "../../components/gui/core/GUISprite"; import { GUITexture } from "../../components/gui/core/GUITexture"; diff --git a/src/materials/MaterialPass.ts b/src/materials/MaterialPass.ts index f6ea4d47..236a0ba5 100644 --- a/src/materials/MaterialPass.ts +++ b/src/materials/MaterialPass.ts @@ -100,7 +100,12 @@ export class MaterialPass { * Set whether use double side to render object */ public set doubleSide(value: boolean) { - this.renderShader.cullMode = value ? GPUCullMode.none : this.renderShader.cullMode; + if (value) this.renderShader.cullMode = GPUCullMode.none; + else { + if (this.renderShader.cullMode == GPUCullMode.none) { + this.renderShader.cullMode = GPUCullMode.back; + } + } } /** diff --git a/src/math/Vector2.ts b/src/math/Vector2.ts index 4b69e4ae..7f31c6d1 100644 --- a/src/math/Vector2.ts +++ b/src/math/Vector2.ts @@ -163,6 +163,17 @@ export class Vector2 { return target; } + /** + * Let's multiply the x and y values of this vector by a. + * @param a + * @param target + * @returns + */ + public multiplyScaler(a: number): this { + this.x *= a; + this.y *= a; + return this; + } /** * We're going to divide the x and y values of this vector by v. * @param v