Skip to content

Commit

Permalink
feat(gui): Add api to control visible of gui component (#166)
Browse files Browse the repository at this point in the history
Add api to control visible of ui component
Add visible property of ui component
improve clone function of all ui component
  • Loading branch information
hellmor committed May 23, 2023
1 parent a867ea7 commit 5caee15
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 38 deletions.
88 changes: 88 additions & 0 deletions samples/gui/Sample_UIVisible.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { createExampleScene } from "@samples/utils/ExampleScene";
import { Engine3D, Object3DUtil, Object3D, UIImage, ImageType, Camera3D, WorldPanel, UITransform } from "@orillusion/core";

export class Sample_UIVisible {
imageComponentList: UIImage[];
uiTransform: UITransform;
counter: number = 0;
spriteCount = 10;
async run() {
Engine3D.setting.shadow.autoUpdate = true;
Engine3D.setting.shadow.shadowBias = 0.002;

GUIHelp.init();

await Engine3D.init({ renderLoop: () => { this.renderUpdate(); } });

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;

// enable ui canvas 0
let canvas = exampleScene.view.enableUICanvas();

//create UI root
let panelRoot: Object3D = new Object3D();
panelRoot.scaleX = panelRoot.scaleY = panelRoot.scaleZ = 0.2;

await Engine3D.res.loadAtlas('atlas/Sheet_atlas.json');

let panel = panelRoot.addComponent(WorldPanel);
canvas.addChild(panel.object3D);


this.imageComponentList = [];
let frameStart = 65;
// create sprite list

for (let i = 0; i < this.spriteCount; i++) {
let imageQuad = new Object3D();
panelRoot.addChild(imageQuad);
let img = imageQuad.addComponent(UIImage);
let frameKey = (i + frameStart).toString().padStart(5, '0');
img.sprite = Engine3D.res.getGUISprite(frameKey);
img.imageType = ImageType.Sliced;
img.uiTransform.resize(200, 200);
img.uiTransform.x = (i - (this.spriteCount - 1) * 0.5) * 50;
this.imageComponentList.push(img);
}

//create panel
let quadGroup: Object3D = new Object3D();
panelRoot.addChild(quadGroup);
this.uiTransform = quadGroup.addComponent(UITransform);
let pi_2 = Math.PI * 2;
let rectCount = 50;
for (let i = 0; i < rectCount; i++) {
let rect = new Object3D();
quadGroup.addChild(rect);
let img = rect.addComponent(UIImage);
img.uiTransform.resize(10, 10);
let angle = i / rectCount * pi_2;
img.uiTransform.x = Math.sin(angle) * 160;
img.uiTransform.y = Math.cos(angle) * 160;
}
}

renderUpdate() {
if (this.imageComponentList) {
this.counter += 0.02;
let mathSin = (Math.sin(this.counter) + 1) * 0.5;
let index = Math.floor(mathSin * this.imageComponentList.length);

//component visible
for (let i = 0; i < this.imageComponentList.length; i++) {
this.imageComponentList[i].visible = i != index;
}

// transform visible
this.uiTransform.visible = index % 2 == 0;
}

}
}
2 changes: 1 addition & 1 deletion src/components/gui/GUIPick.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ export class GUIPick {

let intersect: { intersect: boolean; intersectPoint?: Vector3; distance: number; interactive?: IUIInteractive };
for (const iterator of colliders) {
if (iterator.interactive && iterator.enable) {
if (iterator.interactive && iterator.enable && iterator.interactiveVisible) {
intersect = iterator.rayPick(this._ray, screenPos, screenSize);
if (intersect) {
intersect.interactive = iterator;
Expand Down
6 changes: 3 additions & 3 deletions src/components/gui/core/GUIGeometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export class GUIGeometry extends GeometryBase {
let sizePositionArray = quadNum * 4 * 2;
this._vPosition = new StorageGPUBuffer(sizePositionArray, 0);
this._positionArray = new Float32Array(this._vPosition.memory.shareDataBuffer);
//Each quad has : color/uvRec_size/uvBorder_size/uvSlice_size/textureID/slot
//Each quad has : color/uvRec_size/uvBorder_size/uvSlice_size/textureID/visible
let sizeUniformArray = quadNum * (4 + 4 + 4 + 2 + 2);
this._vUniform = new StorageGPUBuffer(sizeUniformArray, 0);
this._uniformArray = new Float32Array(this._vUniform.memory.shareDataBuffer);
Expand Down Expand Up @@ -165,7 +165,7 @@ export class GUIGeometry extends GeometryBase {
let color = quad.color;
let uvRec = texture.uvRec;
let uvBorder = texture.uvBorder;
//Each quad has: color/uvRec_size/uvBorder_size/uvSlice_size/textureID
//Each quad has: color/uvRec_size/uvBorder_size/uvSlice_size/textureID/visible

let offset = (4 + 4 + 4 + 2 + 2) * i;
this._uniformArray[offset + 0] = color.r;
Expand All @@ -186,7 +186,7 @@ export class GUIGeometry extends GeometryBase {
this._uniformArray[offset + 12] = uvSliceWidth;
this._uniformArray[offset + 13] = uvSliceHeight;
this._uniformArray[offset + 14] = textureID;
this._uniformArray[offset + 15] = 0;//free
this._uniformArray[offset + 15] = quad.visible ? 1 : 0;

this._onUniformChange = true;
}
Expand Down
16 changes: 13 additions & 3 deletions src/components/gui/core/GUIQuad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ let gui_help_mtx3: Matrix3;
export class GUIQuad {
public x: number = 0;
public y: number = 0;
public z: number;
public z: number = 0;
public width: number = 1;
public height: number = 1;

Expand All @@ -21,15 +21,14 @@ export class GUIQuad {

private _globalWidth: number = 0;
private _globalHeight: number = 0;

private _visible: boolean = true;
private _offsetX: number = 0;
private _offsetY: number = 0;
protected _sprite: GUISprite = Engine3D.res.defaultGUISprite;
public readonly color: Color = new Color(1, 1, 1, 1);
public imageType: ImageType = ImageType.Simple;
public onChange: boolean = true;


private static textPool: PoolNode<GUIQuad>;

static get quadPool(): PoolNode<GUIQuad> {
Expand All @@ -39,6 +38,17 @@ export class GUIQuad {
return this.textPool;
}

public get visible(): boolean {
return this._visible;
}

public set visible(value: boolean) {
if (value != this._visible) {
this._visible = value;
this.onChange = true;
}
}

public get sprite() {
return this._sprite;
}
Expand Down
18 changes: 11 additions & 7 deletions src/components/gui/core/GUIShader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export class GUIShader {
vUvBorder: vec4<f32>,
vUvSlice: vec2<f32>,
vTextureID: f32,
slot: f32
vVisible: f32
}
struct MaterialUniform{
Expand Down Expand Up @@ -160,11 +160,14 @@ export class GUIShader {
let quadIndex = u32(vertex.vIndex * 0.25);
var vUniformData = vUniformBuffer[quadIndex];
var op = 2.0 * vec2<f32>(vPositionBuffer[u32(vertexIndex)]) / materialUniform.screen;
var op = vec2<f32>(0.0001);
if(vUniformData.vVisible > 0.5){
op = 2.0 * vec2<f32>(vPositionBuffer[u32(vertexIndex)]) / materialUniform.screen;
}
vertexOut.member = vec4<f32>(op.x, op.y, vertexIndex * 0.0001, 1.0);
vertexOut.vUV = vec2<f32>(vertex.uv);
vertexOut.vUvRec = vUniformData.vUvRec;
vertexOut.vColor4 = vUniformData.vColor4;
vertexOut.vUvBorder = vUniformData.vUvBorder;
Expand All @@ -188,9 +191,10 @@ export class GUIShader {
var vUniformData = vUniformBuffer[quadIndex];
var localPos = vec4<f32>(vPositionBuffer[u32(vertexIndex)], vertexIndex * 0.0001, 1.0) ;
var op = globalUniform.projMat * globalUniform.viewMat * modelMatrix * localPos ;
var op = vec4<f32>(0.0001);
if(vUniformData.vVisible > 0.5){
op = globalUniform.projMat * globalUniform.viewMat * modelMatrix * localPos ;
}
vertexOut.member = op;
vertexOut.vUV = vec2<f32>(vertex.uv);
Expand Down
3 changes: 3 additions & 0 deletions src/components/gui/uiComponents/IUIInteractive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ export enum UIInteractiveStyle {
export interface IUIInteractive {
interactive: boolean;
enable: boolean;
visible: boolean;
object3D?: CEventDispatcher;

get interactiveVisible(): boolean;

rayPick(ray: Ray, screenPos: Vector2, screenSize: Vector2);

destroy(): void;
Expand Down
1 change: 1 addition & 0 deletions src/components/gui/uiComponents/UIButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export class UIButton extends UIInteractive {

cloneTo(obj: Object3D) {
let component = obj.getOrAddComponent(UIButton);
component.copyComponent(this);
component.downSprite = this.downSprite;
component.normalSprite = this.normalSprite;
component.disableSprite = this.disableSprite;
Expand Down
21 changes: 20 additions & 1 deletion src/components/gui/uiComponents/UIComponentBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,31 @@ import { UITransform } from "./UITransform";

export class UIComponentBase extends ComponentBase {
protected _uiTransform: UITransform;

protected _visible: boolean = true;
public get uiTransform() {
return this._uiTransform;
}

public get visible(): boolean {
return this._visible;
}

public set visible(value: boolean) {
if (this._visible != value) {
this._visible = value;
this.onUIComponentVisible && this.onUIComponentVisible(this._visible);
}
}

init(param?: any) {
super.init(param);
this._uiTransform = this.object3D.getOrAddComponent(UITransform);
this._uiTransform.eventDispatcher.addEventListener(UITransform.Resize, this.onTransformResize, this);
}

protected onUITransformVisible?(visible: boolean): void;
protected onUIComponentVisible?(visible: boolean): void;

//Called when component size changes
protected onTransformResize(): void { }

Expand All @@ -32,4 +46,9 @@ export class UIComponentBase extends ComponentBase {
this._uiTransform.quads.length = 0;
return this;
}

public copyComponent(from: this): this {
this.visible = from.visible;
return this;
}
}
14 changes: 14 additions & 0 deletions src/components/gui/uiComponents/UIImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class UIImage extends UIComponentBase {

public cloneTo(obj: Object3D) {
let component = obj.getOrAddComponent(UIImage);
component.copyComponent(this);
component.sprite = this.sprite;
component.color = this.color;
component.imageType = this.imageType;
Expand All @@ -35,6 +36,19 @@ export class UIImage extends UIComponentBase {
return this._quad.sprite;
}

protected onUIComponentVisible(visible: boolean): void {
this.applyComponentVisible();
}

protected onUITransformVisible(visible: boolean): void {
this.applyComponentVisible();
}

private applyComponentVisible(): void {
let isHidden = !this._visible || !this._uiTransform.globalVisible;
this._quad.visible = !isHidden;
}

public get color() {
return this._quad.color;
}
Expand Down
5 changes: 5 additions & 0 deletions src/components/gui/uiComponents/UIInteractive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export class UIInteractive extends UIComponentBase implements IUIInteractive {
this._style = value;
}

public get interactiveVisible(): boolean {
return this._uiTransform.globalVisible && this._visible;
}

init(param?: any) {
super.init(param);
this._uiTransform.addUIInteractive(this);
Expand All @@ -39,6 +43,7 @@ export class UIInteractive extends UIComponentBase implements IUIInteractive {

cloneTo(obj: Object3D) {
let component = obj.getOrAddComponent(UIInteractive);
component.copyComponent(this);
component.enable = this.enable;
component.interactive = this.interactive;
component.mouseStyle = this._style;
Expand Down
15 changes: 9 additions & 6 deletions src/components/gui/uiComponents/UIPanel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Object3D, View3D } from "../../..";
import { View3D } from "../../..";
import { GUISpace } from "../GUIConfig";
import { GUIMesh } from "../core/GUIMesh";
import { UIComponentBase } from "./UIComponentBase";
Expand All @@ -8,7 +8,6 @@ export class UIPanel extends UIComponentBase {
public order: number;
public space: number = GUISpace.World;
public needUpdateGeometry: boolean = true;
public uuid: string;
public panelOrder: number = 0;
public needSortOnCameraZ?: boolean;
protected _mesh: GUIMesh;
Expand Down Expand Up @@ -44,16 +43,20 @@ export class UIPanel extends UIComponentBase {
onGraphic?(view?: View3D) {
// throw new Error("Method not implemented.");
}
cloneTo(obj: Object3D) {
// throw new Error("Method not implemented.");
}

destroy(force?: boolean) {
// throw new Error("Method not implemented.");
}
public copyComponent(from: this): this {
this.visible = from.visible;
this.order = from.order;
this.panelOrder = from.panelOrder;
this.needSortOnCameraZ = from.needSortOnCameraZ;
return this;
}

init(param?: any) {
super.init(param);
this.uuid = this.object3D.uuid;
this._mesh = new GUIMesh(this.space, param);
this.object3D.addChild(this._mesh);
}
Expand Down
Loading

0 comments on commit 5caee15

Please sign in to comment.