Skip to content

Commit

Permalink
Add referenceResolutionPerUnit and fix hierarchy dirty bug (#37)
Browse files Browse the repository at this point in the history
Feat: add `referenceResolutionPerUnit`
Fix: fix hierarchy dirty bug
  • Loading branch information
cptbtptpbcptdtptp authored Jan 2, 2025
1 parent 185c659 commit 152368f
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 30 deletions.
3 changes: 2 additions & 1 deletion packages/core/src/2d/assembler/ISpriteAssembler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export interface ISpriteAssembler {
height: number,
pivot: Vector2,
flipX?: boolean,
flipY?: boolean
flipY?: boolean,
referenceResolutionPerUnit?: number
): void;
updateUVs(renderer: ISpriteRenderer): void;
updateColor(renderer: ISpriteRenderer, alpha?: number): void;
Expand Down
8 changes: 5 additions & 3 deletions packages/core/src/2d/assembler/SlicedSpriteAssembler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Matrix, Vector2 } from "@galacean/engine-math";
import { Engine } from "../../Engine";
import { StaticInterfaceImplement } from "../../base/StaticInterfaceImplement";
import { ISpriteAssembler } from "./ISpriteAssembler";
import { ISpriteRenderer } from "./ISpriteRenderer";
Expand Down Expand Up @@ -32,16 +33,17 @@ export class SlicedSpriteAssembler {
height: number,
pivot: Vector2,
flipX: boolean = false,
flipY: boolean = false
flipY: boolean = false,
referenceResolutionPerUnit: number = 1
): void {
const { sprite } = renderer;
const { border } = sprite;
// Update local positions.
const spritePositions = sprite._getPositions();
const { x: left, y: bottom } = spritePositions[0];
const { x: right, y: top } = spritePositions[3];
const expectWidth = sprite.width;
const expectHeight = sprite.height;
const expectWidth = sprite.width * referenceResolutionPerUnit;
const expectHeight = sprite.height * referenceResolutionPerUnit;
const fixedLeft = expectWidth * border.x;
const fixedBottom = expectHeight * border.y;
const fixedRight = expectWidth * border.z;
Expand Down
12 changes: 7 additions & 5 deletions packages/core/src/2d/assembler/TiledSpriteAssembler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ export class TiledSpriteAssembler {
height: number,
pivot: Vector2,
flipX: boolean = false,
flipY: boolean = false
flipY: boolean = false,
referenceResolutionPerUnit: number = 1
): void {
// Calculate row and column
const { _posRow: rPos, _posColumn: cPos, _uvRow: rUV, _uvColumn: cUV } = TiledSpriteAssembler;
TiledSpriteAssembler.resetData(
renderer,
TiledSpriteAssembler._calculateDividing(renderer, width, height, rPos, cPos, rUV, cUV)
TiledSpriteAssembler._calculateDividing(renderer, width, height, rPos, cPos, rUV, cUV, referenceResolutionPerUnit)
);
// Update renderer's worldMatrix
const { x: pivotX, y: pivotY } = pivot;
Expand Down Expand Up @@ -172,7 +173,8 @@ export class TiledSpriteAssembler {
rPos: DisorderedArray<number>,
cPos: DisorderedArray<number>,
rUV: DisorderedArray<number>,
cUV: DisorderedArray<number>
cUV: DisorderedArray<number>,
referenceResolutionPerUnit: number
): number {
rPos.length = cPos.length = rUV.length = cUV.length = 0;
const { sprite, tiledAdaptiveThreshold: threshold } = renderer;
Expand All @@ -181,8 +183,8 @@ export class TiledSpriteAssembler {
const { x: left, y: bottom } = spritePositions[0];
const { x: right, y: top } = spritePositions[3];
const [spriteUV0, spriteUV1, spriteUV2, spriteUV3] = sprite._getUVs();
const expectWidth = sprite.width;
const expectHeight = sprite.height;
const expectWidth = sprite.width * referenceResolutionPerUnit;
const expectHeight = sprite.height * referenceResolutionPerUnit;
const fixedL = expectWidth * border.x;
const fixedR = expectWidth * border.z;
const fixedLR = fixedL + fixedR;
Expand Down
21 changes: 19 additions & 2 deletions packages/ui/src/component/UICanvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { UIInteractive } from "./interactive/UIInteractive";
@dependentComponents(UITransform, DependentMode.AutoAdd)
export class UICanvas extends Component implements IElement {
/** @internal */
static _hierarchyCounter: number = 1;
private static _tempGroupAbleList: IGroupAble[] = [];

/** @internal */
Expand Down Expand Up @@ -79,10 +80,25 @@ export class UICanvas extends Component implements IElement {
@ignoreClone
private _distance: number = 10;
@deepClone
private _referenceResolution: Vector2 = new Vector2(8, 6);
private _referenceResolution: Vector2 = new Vector2(800, 600);
@deepClone
private _referenceResolutionPerUnit: number = 100;
@ignoreClone
private _hierarchyVersion: number = -1;

/**
* The conversion ratio between reference resolution and unit for UI elements in this canvas.
*/
get referenceResolutionPerUnit(): number {
return this._referenceResolutionPerUnit;
}

set referenceResolutionPerUnit(value: number) {
if (this._referenceResolutionPerUnit !== value) {
this._referenceResolutionPerUnit = value;
}
}

/**
* The reference resolution of the UI canvas in `ScreenSpaceCamera` and `ScreenSpaceOverlay` mode.
*/
Expand Down Expand Up @@ -332,6 +348,7 @@ export class UICanvas extends Component implements IElement {
renderers.length = this._walk(this.entity, renderers);
UICanvas._tempGroupAbleList.length = 0;
this._hierarchyVersion = uiHierarchyVersion;
++UICanvas._hierarchyCounter;
}
return renderers;
}
Expand Down Expand Up @@ -521,7 +538,7 @@ export class UICanvas extends Component implements IElement {
this._updateCameraObserver();
this._setRealRenderMode(this._getRealRenderMode());
if (isRootCanvas) {
this.entity._updateUIHierarchyVersion(this.engine.time.frameCount);
this.entity._updateUIHierarchyVersion(UICanvas._hierarchyCounter);
} else {
const { _disorderedElements: disorderedElements } = this;
disorderedElements.forEach((element: IElement) => {
Expand Down
8 changes: 6 additions & 2 deletions packages/ui/src/component/UIRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
ShaderProperty,
Vector3,
Vector4,
assignmentClone,
deepClone,
dependentComponents,
ignoreClone
Expand Down Expand Up @@ -77,6 +78,8 @@ export class UIRenderer extends Renderer implements IGraphics {
protected _alpha: number = 1;
@deepClone
protected _color: Color = new Color(1, 1, 1, 1);
@assignmentClone
protected _referenceResolutionPerUnit: number = 100;

/**
* Rendering color for the ui renderer.
Expand Down Expand Up @@ -154,7 +157,7 @@ export class UIRenderer extends Renderer implements IGraphics {
override _onEnableInScene(): void {
// @ts-ignore
this._overrideUpdate && this.scene._componentsManager.addOnUpdateRenderers(this);
this.entity._updateUIHierarchyVersion(this.engine.time.frameCount);
this.entity._updateUIHierarchyVersion(UICanvas._hierarchyCounter);
Utils.setRootCanvasDirty(this);
Utils.setGroupDirty(this);
}
Expand All @@ -163,6 +166,7 @@ export class UIRenderer extends Renderer implements IGraphics {
override _onDisableInScene(): void {
// @ts-ignore
this._overrideUpdate && this.scene._componentsManager.removeOnUpdateRenderers(this);
this.entity._updateUIHierarchyVersion(UICanvas._hierarchyCounter);
Utils.cleanRootCanvas(this);
Utils.cleanGroup(this);
}
Expand Down Expand Up @@ -205,7 +209,7 @@ export class UIRenderer extends Renderer implements IGraphics {
Utils.setRootCanvasDirty(this);
Utils.setGroupDirty(this);
case EntityModifyFlags.SiblingIndex:
entity._updateUIHierarchyVersion(this.engine.time.frameCount);
entity._updateUIHierarchyVersion(UICanvas._hierarchyCounter);
break;
default:
break;
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/component/UITransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Entity, Transform, Vector2, deepClone, ignoreClone } from "@galacean/en
*/
export class UITransform extends Transform {
@deepClone
private _size: Vector2 = new Vector2(1, 1);
private _size: Vector2 = new Vector2(100, 100);
@deepClone
private _pivot: Vector2 = new Vector2(0.5, 0.5);

Expand Down
18 changes: 16 additions & 2 deletions packages/ui/src/component/advanced/Image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,24 @@ export class Image extends UIRenderer implements ISpriteRenderer {
}

let { _dirtyUpdateFlag: dirtyUpdateFlag } = this;
const canvas = this._getRootCanvas();
if (this._referenceResolutionPerUnit !== canvas.referenceResolutionPerUnit) {
this._referenceResolutionPerUnit = canvas.referenceResolutionPerUnit;
dirtyUpdateFlag |= ImageUpdateFlags.Position;
}

// Update position
if (dirtyUpdateFlag & ImageUpdateFlags.Position) {
this._assembler.updatePositions(this, transform.worldMatrix, width, height, transform.pivot);
this._assembler.updatePositions(
this,
transform.worldMatrix,
width,
height,
transform.pivot,
false,
false,
this._referenceResolutionPerUnit
);
dirtyUpdateFlag &= ~ImageUpdateFlags.Position;
}

Expand All @@ -195,7 +210,6 @@ export class Image extends UIRenderer implements ISpriteRenderer {
this._dirtyUpdateFlag = dirtyUpdateFlag;
// Init sub render element.
const { engine } = context.camera;
const canvas = this._getRootCanvas();
const subRenderElement = engine._subRenderElementPool.get();
const subChunk = this._subChunk;
subRenderElement.set(this, material, subChunk.chunk.primitive, subChunk.subMesh, this.sprite.texture, subChunk);
Expand Down
28 changes: 18 additions & 10 deletions packages/ui/src/component/advanced/Label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,14 @@ export class Label extends UIRenderer implements ITextRenderer {
this._setDirtyFlagFalse(DirtyFlag.SubFont);
}

const canvas = this._getRootCanvas();
if (this._referenceResolutionPerUnit !== canvas.referenceResolutionPerUnit) {
this._referenceResolutionPerUnit = canvas.referenceResolutionPerUnit;
this._setDirtyFlagTrue(DirtyFlag.LocalPositionBounds);
}

if (this._isContainDirtyFlag(DirtyFlag.LocalPositionBounds)) {
this._updateLocalData();
this._setDirtyFlagFalse(DirtyFlag.LocalPositionBounds);
}

if (this._isContainDirtyFlag(DirtyFlag.WorldPosition)) {
Expand All @@ -324,7 +329,6 @@ export class Label extends UIRenderer implements ITextRenderer {
const engine = context.camera.engine;
const textSubRenderElementPool = engine._textSubRenderElementPool;
const material = this.getMaterial();
const canvas = this._getRootCanvas();
const renderElement = canvas._renderElement;
const textChunks = this._textChunks;
const isOverlay = canvas._realRenderMode === CanvasRenderMode.ScreenSpaceOverlay;
Expand Down Expand Up @@ -416,7 +420,7 @@ export class Label extends UIRenderer implements ITextRenderer {

private _updateLocalData(): void {
// @ts-ignore
const pixelsPerUnit = Engine._pixelsPerUnit;
const pixelsPerResolution = Engine._pixelsPerUnit / this._referenceResolutionPerUnit;
const { min, max } = this._localBounds;
const charRenderInfos = Label._charRenderInfos;
const charFont = this._getSubFont();
Expand All @@ -428,11 +432,15 @@ export class Label extends UIRenderer implements ITextRenderer {
const textMetrics = this.enableWrapping
? TextUtils.measureTextWithWrap(
this,
rendererWidth * pixelsPerUnit,
rendererHeight * pixelsPerUnit,
this._lineSpacing * pixelsPerUnit
rendererWidth * pixelsPerResolution,
rendererHeight * pixelsPerResolution,
this._lineSpacing * pixelsPerResolution
)
: TextUtils.measureTextWithoutWrap(this, rendererHeight * pixelsPerUnit, this._lineSpacing * pixelsPerUnit);
: TextUtils.measureTextWithoutWrap(
this,
rendererHeight * pixelsPerResolution,
this._lineSpacing * pixelsPerResolution
);
const { height, lines, lineWidths, lineHeight, lineMaxSizes } = textMetrics;
// @ts-ignore
const charRenderInfoPool = this.engine._charRenderInfoPool;
Expand All @@ -441,9 +449,9 @@ export class Label extends UIRenderer implements ITextRenderer {

if (linesLen > 0) {
const { horizontalAlignment } = this;
const pixelsPerUnitReciprocal = 1.0 / pixelsPerUnit;
rendererWidth *= pixelsPerUnit;
rendererHeight *= pixelsPerUnit;
const pixelsPerUnitReciprocal = 1.0 / pixelsPerResolution;
rendererWidth *= pixelsPerResolution;
rendererHeight *= pixelsPerResolution;
const halfRendererWidth = rendererWidth * 0.5;
const halfLineHeight = lineHeight * 0.5;

Expand Down
8 changes: 4 additions & 4 deletions packages/ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ import {
import uiDefaultFs from "./shader/uiDefault.fs.glsl";
import uiDefaultVs from "./shader/uiDefault.vs.glsl";

export { UICanvas } from "./component/UICanvas";
export { UIGroup } from "./component/UIGroup";
export { UIRenderer } from "./component/UIRenderer";
export { UITransform } from "./component/UITransform";
export { Button } from "./component/advanced/Button";
export { Image } from "./component/advanced/Image";
export { Label } from "./component/advanced/Label";
export { ColorTransition } from "./component/interactive/transition/ColorTransition";
export { ScaleTransition } from "./component/interactive/transition/ScaleTransition";
export { SpriteTransition } from "./component/interactive/transition/SpriteTransition";
export { Transition } from "./component/interactive/transition/Transition";
export { UICanvas } from "./component/UICanvas";
export { UIGroup } from "./component/UIGroup";
export { UIRenderer } from "./component/UIRenderer";
export { UITransform } from "./component/UITransform";
export { CanvasRenderMode } from "./enums/CanvasRenderMode";
export { ResolutionAdaptationStrategy } from "./enums/ResolutionAdaptationStrategy";
export { UIPointerEventEmitter } from "./input/UIPointerEventEmitter";
Expand Down

0 comments on commit 152368f

Please sign in to comment.