Skip to content

Commit

Permalink
Support GUI (#2375)
Browse files Browse the repository at this point in the history
* feat(2d): support GUI
  • Loading branch information
singlecoder authored Jan 9, 2025
1 parent 63a5662 commit 8703a2d
Show file tree
Hide file tree
Showing 96 changed files with 6,168 additions and 1,293 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ jobs:
cp -r ${{ github.workspace }}/packages/galacean/dist ${{ github.workspace }}/temp/@galacean/engine
mkdir -p ${{ github.workspace }}/temp/@galacean/engine-xr
cp -r ${{ github.workspace }}/packages/xr/dist ${{ github.workspace }}/temp/@galacean/engine-xr
mkdir -p ${{ github.workspace }}/temp/@galacean/engine-ui
cp -r ${{ github.workspace }}/packages/ui/dist ${{ github.workspace }}/temp/@galacean/engine-ui
mkdir -p ${{ github.workspace }}/temp/@galacean/engine-shaderlab
cp -r ${{ github.workspace }}/packages/shader-lab/dist ${{ github.workspace }}/temp/@galacean/engine-shaderlab
mkdir -p ${{ github.workspace }}/temp/@galacean/engine-shader-shaderlab
Expand Down Expand Up @@ -113,6 +115,7 @@ jobs:
"engine": [
"${{ github.workspace }}/temp/@galacean/engine/dist/browser.js",
"${{ github.workspace }}/temp/@galacean/engine-xr/dist/browser.js",
"${{ github.workspace }}/temp/@galacean/engine-ui/dist/browser.js",
"${{ github.workspace }}/temp/@galacean/engine-shaderlab/dist/browser.js",
"${{ github.workspace }}/temp/@galacean/engine-shader-shaderlab/dist/browser.js",
"${{ github.workspace }}/temp/@galacean/engine-physics-lite/dist/browser.js",
Expand Down
22 changes: 16 additions & 6 deletions packages/core/src/2d/assembler/ISpriteAssembler.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import { Renderer } from "../../Renderer";
import { Matrix, Vector2 } from "@galacean/engine-math";
import { ISpriteRenderer } from "./ISpriteRenderer";

/**
* @internal
* Interface for sprite assembler.
*/
export interface ISpriteAssembler {
resetData(renderer: Renderer, vertexCount?: number): void;
updatePositions?(renderer: Renderer): void;
updateUVs?(renderer: Renderer): void;
updateColor?(renderer: Renderer): void;
resetData(renderer: ISpriteRenderer, vertexCount?: number): void;
updatePositions(
renderer: ISpriteRenderer,
worldMatrix: Matrix,
width: number,
height: number,
pivot: Vector2,
flipX: boolean,
flipY: boolean,
referenceResolutionPerUnit?: number
): void;
updateUVs(renderer: ISpriteRenderer): void;
updateColor(renderer: ISpriteRenderer, alpha: number): void;
}
17 changes: 17 additions & 0 deletions packages/core/src/2d/assembler/ISpriteRenderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Color } from "@galacean/engine-math";
import { PrimitiveChunkManager } from "../../RenderPipeline/PrimitiveChunkManager";
import { SubPrimitiveChunk } from "../../RenderPipeline/SubPrimitiveChunk";
import { SpriteTileMode } from "../enums/SpriteTileMode";
import { Sprite } from "../sprite";

/**
* Interface for sprite renderer.
*/
export interface ISpriteRenderer {
sprite: Sprite;
color?: Color;
tileMode?: SpriteTileMode;
tiledAdaptiveThreshold?: number;
_subChunk: SubPrimitiveChunk;
_getChunkManager(): PrimitiveChunkManager;
}
49 changes: 29 additions & 20 deletions packages/core/src/2d/assembler/SimpleSpriteAssembler.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { BoundingBox, Matrix } from "@galacean/engine-math";
import { BoundingBox, Matrix, Vector2 } from "@galacean/engine-math";
import { StaticInterfaceImplement } from "../../base/StaticInterfaceImplement";
import { SpriteMask } from "../sprite";
import { SpriteRenderer } from "../sprite/SpriteRenderer";
import { ISpriteAssembler } from "./ISpriteAssembler";
import { ISpriteRenderer } from "./ISpriteRenderer";

/**
* @internal
* Assemble vertex data for the sprite renderer in simple mode.
*/
@StaticInterfaceImplement<ISpriteAssembler>()
export class SimpleSpriteAssembler {
static _rectangleTriangles = [0, 1, 2, 2, 1, 3];
static _worldMatrix = new Matrix();
private static _rectangleTriangles = [0, 1, 2, 2, 1, 3];
private static _matrix = new Matrix();

static resetData(renderer: SpriteRenderer | SpriteMask): void {
static resetData(renderer: ISpriteRenderer): void {
const manager = renderer._getChunkManager();
const lastSubChunk = renderer._subChunk;
lastSubChunk && manager.freeSubChunk(lastSubChunk);
Expand All @@ -21,16 +20,24 @@ export class SimpleSpriteAssembler {
renderer._subChunk = subChunk;
}

static updatePositions(renderer: SpriteRenderer | SpriteMask): void {
const { width, height, sprite } = renderer;
const { x: pivotX, y: pivotY } = sprite.pivot;
static updatePositions(
renderer: ISpriteRenderer,
worldMatrix: Matrix,
width: number,
height: number,
pivot: Vector2,
flipX: boolean,
flipY: boolean
): void {
const { sprite } = renderer;
const { x: pivotX, y: pivotY } = pivot;
// Position to World
const modelMatrix = SimpleSpriteAssembler._matrix;
const { elements: wE } = modelMatrix;
// Renderer's worldMatrix
const worldMatrix = SimpleSpriteAssembler._worldMatrix;
const { elements: wE } = worldMatrix;
// Parent's worldMatrix
const { elements: pWE } = renderer.entity.transform.worldMatrix;
const sx = renderer.flipX ? -width : width;
const sy = renderer.flipY ? -height : height;
const { elements: pWE } = worldMatrix;
const sx = flipX ? -width : width;
const sy = flipY ? -height : height;
(wE[0] = pWE[0] * sx), (wE[1] = pWE[1] * sx), (wE[2] = pWE[2] * sx);
(wE[4] = pWE[4] * sy), (wE[5] = pWE[5] * sy), (wE[6] = pWE[6] * sy);
(wE[8] = pWE[8]), (wE[9] = pWE[9]), (wE[10] = pWE[10]);
Expand All @@ -54,10 +61,11 @@ export class SimpleSpriteAssembler {
vertices[o + 2] = wE[2] * x + wE[6] * y + wE[14];
}

BoundingBox.transform(sprite._getBounds(), worldMatrix, renderer._bounds);
// @ts-ignore
BoundingBox.transform(sprite._getBounds(), modelMatrix, renderer._bounds);
}

static updateUVs(renderer: SpriteRenderer | SpriteMask): void {
static updateUVs(renderer: ISpriteRenderer): void {
const spriteUVs = renderer.sprite._getUVs();
const { x: left, y: bottom } = spriteUVs[0];
const { x: right, y: top } = spriteUVs[3];
Expand All @@ -74,15 +82,16 @@ export class SimpleSpriteAssembler {
vertices[offset + 28] = top;
}

static updateColor(renderer: SpriteRenderer): void {
static updateColor(renderer: ISpriteRenderer, alpha: number): void {
const subChunk = renderer._subChunk;
const { r, g, b, a } = renderer.color;
const finalAlpha = a * alpha;
const vertices = subChunk.chunk.vertices;
for (let i = 0, o = subChunk.vertexArea.start + 5; i < 4; ++i, o += 9) {
vertices[o] = r;
vertices[o + 1] = g;
vertices[o + 2] = b;
vertices[o + 3] = a;
vertices[o + 3] = finalAlpha;
}
}
}
88 changes: 48 additions & 40 deletions packages/core/src/2d/assembler/SlicedSpriteAssembler.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { Matrix } from "@galacean/engine-math";
import { Matrix, Vector2 } from "@galacean/engine-math";
import { StaticInterfaceImplement } from "../../base/StaticInterfaceImplement";
import { SpriteRenderer } from "../sprite/SpriteRenderer";
import { ISpriteAssembler } from "./ISpriteAssembler";
import { ISpriteRenderer } from "./ISpriteRenderer";

/**
* @internal
* Assemble vertex data for the sprite renderer in sliced mode.
*/
@StaticInterfaceImplement<ISpriteAssembler>()
export class SlicedSpriteAssembler {
static _rectangleTriangles = [
private static _rectangleTriangles = [
0, 1, 4, 1, 5, 4, 1, 2, 5, 2, 6, 5, 2, 3, 6, 3, 7, 6, 4, 5, 8, 5, 9, 8, 5, 6, 9, 6, 10, 9, 6, 7, 10, 7, 11, 10, 8,
9, 12, 9, 13, 12, 9, 10, 13, 10, 14, 13, 10, 11, 14, 11, 15, 14
];
static _worldMatrix = new Matrix();
private static _matrix = new Matrix();
private static _row = new Array<number>(4);
private static _column = new Array<number>(4);

static resetData(renderer: SpriteRenderer): void {
static resetData(renderer: ISpriteRenderer): void {
const manager = renderer._getChunkManager();
const lastSubChunk = renderer._subChunk;
lastSubChunk && manager.freeSubChunk(lastSubChunk);
Expand All @@ -23,14 +25,24 @@ export class SlicedSpriteAssembler {
renderer._subChunk = subChunk;
}

static updatePositions(renderer: SpriteRenderer): void {
const { width, height, sprite } = renderer;
static updatePositions(
renderer: ISpriteRenderer,
worldMatrix: Matrix,
width: number,
height: number,
pivot: Vector2,
flipX: boolean,
flipY: boolean,
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 { width: expectWidth, height: expectHeight } = sprite;
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 All @@ -47,42 +59,36 @@ export class SlicedSpriteAssembler {
// column
// ------------------------
// Calculate row and column.
let row: number[], column: number[];
const { _row: row, _column: column } = SlicedSpriteAssembler;
if (fixedLeft + fixedRight > width) {
const widthScale = width / (fixedLeft + fixedRight);
row = [
expectWidth * left * widthScale,
fixedLeft * widthScale,
fixedLeft * widthScale,
width - expectWidth * (1 - right) * widthScale
];
(row[0] = expectWidth * left * widthScale), (row[1] = row[2] = fixedLeft * widthScale);
row[3] = width - expectWidth * (1 - right) * widthScale;
} else {
row = [expectWidth * left, fixedLeft, width - fixedRight, width - expectWidth * (1 - right)];
(row[0] = expectWidth * left), (row[1] = fixedLeft), (row[2] = width - fixedRight);
row[3] = width - expectWidth * (1 - right);
}

if (fixedTop + fixedBottom > height) {
const heightScale = height / (fixedTop + fixedBottom);
column = [
expectHeight * bottom * heightScale,
fixedBottom * heightScale,
fixedBottom * heightScale,
height - expectHeight * (1 - top) * heightScale
];
(column[0] = expectHeight * bottom * heightScale), (column[1] = column[2] = fixedBottom * heightScale);
column[3] = height - expectHeight * (1 - top) * heightScale;
} else {
column = [expectHeight * bottom, fixedBottom, height - fixedTop, height - expectHeight * (1 - top)];
(column[0] = expectHeight * bottom), (column[1] = fixedBottom), (column[2] = height - fixedTop);
column[3] = height - expectHeight * (1 - top);
}

// Update renderer's worldMatrix.
const { x: pivotX, y: pivotY } = renderer.sprite.pivot;
const localTransX = renderer.width * pivotX;
const localTransY = renderer.height * pivotY;
const { x: pivotX, y: pivotY } = pivot;
const localTransX = width * pivotX;
const localTransY = height * pivotY;
// Position to World
const modelMatrix = SlicedSpriteAssembler._matrix;
const { elements: wE } = modelMatrix;
// Renderer's worldMatrix.
const worldMatrix = SlicedSpriteAssembler._worldMatrix;
const { elements: wE } = worldMatrix;
// Parent's worldMatrix.
const { elements: pWE } = renderer.entity.transform.worldMatrix;
const sx = renderer.flipX ? -1 : 1;
const sy = renderer.flipY ? -1 : 1;
const { elements: pWE } = worldMatrix;
const sx = flipX ? -1 : 1;
const sy = flipY ? -1 : 1;
(wE[0] = pWE[0] * sx), (wE[1] = pWE[1] * sx), (wE[2] = pWE[2] * sx);
(wE[4] = pWE[4] * sy), (wE[5] = pWE[5] * sy), (wE[6] = pWE[6] * sy);
(wE[8] = pWE[8]), (wE[9] = pWE[9]), (wE[10] = pWE[10]);
Expand Down Expand Up @@ -112,13 +118,14 @@ export class SlicedSpriteAssembler {
}
}

const { min, max } = renderer._bounds;
min.set(row[0], column[0], 0);
max.set(row[3], column[3], 0);
renderer._bounds.transform(worldMatrix);
// @ts-ignore
const bounds = renderer._bounds;
bounds.min.set(row[0], column[0], 0);
bounds.max.set(row[3], column[3], 0);
bounds.transform(modelMatrix);
}

static updateUVs(renderer: SpriteRenderer): void {
static updateUVs(renderer: ISpriteRenderer): void {
const subChunk = renderer._subChunk;
const vertices = subChunk.chunk.vertices;
const spriteUVs = renderer.sprite._getUVs();
Expand All @@ -131,15 +138,16 @@ export class SlicedSpriteAssembler {
}
}

static updateColor(renderer: SpriteRenderer): void {
static updateColor(renderer: ISpriteRenderer, alpha: number): void {
const subChunk = renderer._subChunk;
const { r, g, b, a } = renderer.color;
const finalAlpha = a * alpha;
const vertices = subChunk.chunk.vertices;
for (let i = 0, o = subChunk.vertexArea.start + 5; i < 16; ++i, o += 9) {
vertices[o] = r;
vertices[o + 1] = g;
vertices[o + 2] = b;
vertices[o + 3] = a;
vertices[o + 3] = finalAlpha;
}
}
}
Loading

0 comments on commit 8703a2d

Please sign in to comment.