Skip to content

Commit

Permalink
feat(GUI): Improve GUI (#172)
Browse files Browse the repository at this point in the history
GUI components can update with changes in object3D hierarchy;
Implement self destruction logic.
simplified code
  • Loading branch information
hellmor committed May 24, 2023
1 parent 281b240 commit 5c7c6ef
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 58 deletions.
98 changes: 98 additions & 0 deletions samples/gui/Sample_UIChangeParent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { GUIHelp } from "@orillusion/debug/GUIHelp";
import { createExampleScene } from "@samples/utils/ExampleScene";
import { Engine3D, Object3DUtil, Object3D, ViewPanel, UIImage, ImageType, UIPanel, makeAloneSprite, Color, Time, UITransform } from "@orillusion/core";

export class Sample_UIChangeParent {
async run() {
Engine3D.setting.shadow.autoUpdate = true;
Engine3D.setting.shadow.shadowBias = 0.002;

GUIHelp.init();

await Engine3D.init({ renderLoop: () => { this.loop(); } });
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();

let panel: UIPanel = panelRoot.addComponent(ViewPanel);

//add panel
canvas.addChild(panel.object3D);

//create logo
let logoObject = new Object3D();
{
panelRoot.addChild(logoObject);

let image1: UIImage = logoObject.addComponent(UIImage);
let logoTexture = await Engine3D.res.loadTexture('png/logo.png');
image1.sprite = makeAloneSprite('logo', logoTexture);
image1.uiTransform.resize(100, 100);
}

//create image0
let holder0 = new Object3D();
{
panelRoot.addChild(holder0);

let image1: UIImage = holder0.addComponent(UIImage);
image1.color = new Color(0.8, 0.8, 0.8, 0.5);
image1.uiTransform.resize(600, 400);
}

//create image1
let holder1 = new Object3D();
{
panelRoot.addChild(holder1);

let image1: UIImage = holder1.addComponent(UIImage);
image1.color = new Color(0.2, 0.4, 0.2, 0.8);
image1.uiTransform.resize(200, 160);
image1.uiTransform.x = 160;
}
this.holder1 = holder1.getComponent(UITransform);

//create image2
let image2: UIImage;
let holder2 = new Object3D();
{
panelRoot.addChild(holder2);

image2 = holder2.addComponent(UIImage);
image2.color = new Color(0.4, 0.2, 0.2, 0.8);
image2.uiTransform.resize(200, 160);
image2.uiTransform.x = -160;
}

setInterval(() => {
let lastParent = logoObject?.parent?.object3D;
if (lastParent == holder2) {
holder1.addChild(logoObject);
} else {
holder2.addChild(logoObject);
}
}, 1000);

GUIHelp.addButton('Remove Background', () => {
holder0.removeComponent(UIImage);
})
GUIHelp.open();
}

private holder1: UITransform;
private loop(): void {
if (this.holder1) {
this.holder1.y = Math.sin(Time.time * 0.005) * 50;
}
}
}
1 change: 1 addition & 0 deletions src/components/ComponentBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export class ComponentBase implements IComponent {
public onBeforeUpdate?(view?: View3D);
public onCompute?(view?: View3D, command?: GPUCommandEncoder);
public onGraphic?(view?: View3D);
public onParentChange?(lastParent?: Object3D, currentParent?: Object3D);

/**
*
Expand Down
4 changes: 3 additions & 1 deletion src/components/IComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,7 @@ export interface IComponent {
onCompute?(view?: View3D, command?: GPUCommandEncoder);
onGraphic?(view?: View3D);
cloneTo(obj: Object3D);
destroy(force?: boolean)
destroy(force?: boolean);
onParentChange?(lastParent?: Object3D, currentParent?: Object3D);

}
8 changes: 8 additions & 0 deletions src/components/Transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ export class Transform extends ComponentBase {
}

public set parent(value: Transform) {
//why don't it need to compare the data
//if (this._parent !== value){}
let lastParent = this._parent?.object3D;
this._parent = value;
let hasRoot = value ? value.scene3D : null;
if (!hasRoot) {
Expand All @@ -132,6 +135,11 @@ export class Transform extends ComponentBase {
if (value) {
this.transform.updateWorldMatrix();
}

//notify parent change
this.object3D.components.forEach((c) => {
c.onParentChange?.(lastParent, this._parent?.object3D);
});
}

public set enable(value: boolean) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/gui/core/GUIGeometryRebuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class GUIGeometryRebuild {
}
}

if (needUpdateQuads || quad.onChange || forceUpdate) {
if (needUpdateQuads || quad.onChange || isGeometryDirty) {
quad.transformQuad(transform);
}
if (quad.onChange) {
Expand Down
16 changes: 14 additions & 2 deletions src/components/gui/uiComponents/UIButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ import { UIInteractive } from './UIInteractive';
export class UIButton extends UIInteractive {
protected _spriteMap: Map<UIInteractiveStyle, GUISprite>;
protected _image: UIImage;

private _isCreateImage: boolean;
init(param?: any) {
super.init(param);
this._interactive = true;
this._spriteMap = new Map<UIInteractiveStyle, GUISprite>();
this._image = this.object3D.getOrAddComponent(UIImage);
this._image = this.object3D.getComponent(UIImage);
this._isCreateImage = this._image == null;
if (!this._image) {
this._image = this.object3D.addComponent(UIImage);
}
}

onEnable() {
Expand Down Expand Up @@ -94,4 +98,12 @@ export class UIButton extends UIInteractive {
component.mouseStyle = this.mouseStyle;
component.enable = this.enable;
}

public destroy(): void {
if (this._isCreateImage && this._image) {
this.object3D.removeComponent(UIImage);
this._image = null;
}
super.destroy();
}
}
29 changes: 21 additions & 8 deletions src/components/gui/uiComponents/UIComponentBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { UITransform } from "./UITransform";
export class UIComponentBase extends ComponentBase {
protected _uiTransform: UITransform;
protected _visible: boolean = true;
protected readonly _exlusiveQuads: GUIQuad[] = [];

public get uiTransform() {
return this._uiTransform;
}
Expand All @@ -23,27 +25,38 @@ export class UIComponentBase extends ComponentBase {
init(param?: any) {
super.init(param);
this._uiTransform = this.object3D.getOrAddComponent(UITransform);
this._uiTransform.eventDispatcher.addEventListener(UITransform.Resize, this.onTransformResize, this);
this._uiTransform.setNeedUpdateUIPanel();
}

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

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

public destroy() {
this._uiTransform.eventDispatcher.removeEventListener(UITransform.Resize, this.onTransformResize, this);
this.detachQuads();
this._uiTransform.setNeedUpdateUIPanel();
super.destroy();
}

public addQuad(quad: GUIQuad): this {
protected attachQuad(quad: GUIQuad): this {
this._exlusiveQuads.push(quad);
this._uiTransform.quads.push(quad);
return this;
}

public clean(): this {
this._uiTransform.quads.length = 0;
protected detachQuads(): this {
let allQuads = this._uiTransform.quads;
while (this._exlusiveQuads.length > 0) {
let quad = this._exlusiveQuads.shift();
if (quad) {
quad.sprite = null;
GUIQuad.quadPool.pushBack(quad);
let index = allQuads.indexOf(quad);
if (index >= 0) {
allQuads.splice(index, 1);
}
}
}
return this;
}

Expand Down
5 changes: 3 additions & 2 deletions src/components/gui/uiComponents/UIImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ export class UIImage extends UIComponentBase {

public init() {
super.init();
this._quad = new GUIQuad();
this._uiTransform.quads.push(this._quad);
this._quad = GUIQuad.quadPool.getOne(GUIQuad);
this.attachQuad(this._quad);
}

public cloneTo(obj: Object3D) {
Expand Down Expand Up @@ -68,5 +68,6 @@ export class UIImage extends UIComponentBase {
this._quad.onChange = true;
}
}

}

48 changes: 16 additions & 32 deletions src/components/gui/uiComponents/UITextField.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Object3D } from '../../../core/entities/Object3D';
import { Color } from '../../../math/Color';
import { GUIQuad } from '../core/GUIQuad';
import { TextAnchor, TextFieldLayout, TextFieldLine } from './TextFieldLayout';
import { UIComponentBase } from './UIComponentBase';

Expand All @@ -11,7 +10,6 @@ export class UITextField extends UIComponentBase {
private _alignment: TextAnchor = 0;
private _lineSpacing: number = 1;
private _text: string = '';
private _textQuads: GUIQuad[] = [];
private readonly _color: Color = new Color(1, 1, 1, 1);

constructor() {
Expand Down Expand Up @@ -49,7 +47,7 @@ export class UITextField extends UIComponentBase {
public set fontSize(value: number) {
if (this._fontSize != value) {
this._fontSize = value;
this.reLayout();
this.layoutText();
}
}

Expand All @@ -61,46 +59,28 @@ export class UITextField extends UIComponentBase {
if (this._text != value) {
if (!value) value = '';
this._text = value;
this.reLayout();
this.layoutText();
}
}

public clean(): this {
let allQuads = this._uiTransform.quads;
while (this._textQuads.length > 0) {
let quad = this._textQuads.shift();
if (quad) {
quad.sprite = null;
GUIQuad.quadPool.pushBack(quad);
let index = allQuads.indexOf(quad);
if (index >= 0) {
allQuads.splice(index, 1);
}
}

}
return this;
}

private textLine: TextFieldLine[] = null;
private layoutProxy: TextFieldLayout = new TextFieldLayout();

private reLayout() {
this.clean();
private layoutText() {
this.detachQuads();
this.textLine = this.layoutProxy.layout(this);
for (let i: number = 0, count = this.textLine.length; i < count; i++) {
let line = this.textLine[i];
for (let j: number = 0, count = line.quadList.length; j < count; j++) {
let quad = line.quadList[j];
if (quad) {
this.addQuad(quad);
this._textQuads.push(quad);
this.attachQuad(quad);
}
}
}
//refresh color;
this.color = this._color;
this._uiTransform.markNeedsUpdateGUIMesh();
this._uiTransform.setNeedUpdateUIPanel();
this.onUIComponentVisible && this.onUIComponentVisible(this._visible);
}

Expand All @@ -114,14 +94,13 @@ export class UITextField extends UIComponentBase {

private applyComponentVisible(): void {
let isHidden = !this._visible || !this._uiTransform.globalVisible;
for (let quad of this._textQuads) {
for (let quad of this._exlusiveQuads) {
quad && (quad.visible = !isHidden);
}
}

protected onTransformResize() {
super.onTransformResize();
this.reLayout();
this.layoutText();
}

public get color(): Color {
Expand All @@ -130,7 +109,7 @@ export class UITextField extends UIComponentBase {

public set color(value: Color) {
this._color.copyFrom(value);
for (let quad of this._textQuads) {
for (let quad of this._exlusiveQuads) {
quad.color.copyFrom(value);
quad.onChange = true;
}
Expand All @@ -143,7 +122,7 @@ export class UITextField extends UIComponentBase {
public set alignment(value: TextAnchor) {
if (this._alignment != value) {
this._alignment = value;
this.reLayout();
this.layoutText();
}
}

Expand All @@ -154,9 +133,14 @@ export class UITextField extends UIComponentBase {
public set lineSpacing(value: number) {
if (this._lineSpacing != value) {
this._lineSpacing = value;
this.reLayout();
this.layoutText();
}
}

public destroy(): void {
this.detachQuads();
super.destroy();
}
}


0 comments on commit 5c7c6ef

Please sign in to comment.