From fa6d0e1eb6a1fc0ff03c5fe929ccc8dbf01a5bf1 Mon Sep 17 00:00:00 2001 From: AZhan Date: Thu, 10 Apr 2025 14:25:09 +0800 Subject: [PATCH] Fixed the problem of `image` clone (#2603) * fix: 2d clone --- packages/core/src/2d/sprite/SpriteRenderer.ts | 3 +-- packages/ui/src/component/UICanvas.ts | 18 +++++++++---- packages/ui/src/component/advanced/Image.ts | 12 ++++++++- tests/src/ui/Image.test.ts | 14 ++++++++++ tests/src/ui/Text.test.ts | 21 ++++++++++++++- tests/src/ui/UICanvas.test.ts | 26 +++++++++++++++++++ 6 files changed, 85 insertions(+), 9 deletions(-) diff --git a/packages/core/src/2d/sprite/SpriteRenderer.ts b/packages/core/src/2d/sprite/SpriteRenderer.ts index 654cda067..afd05c76e 100644 --- a/packages/core/src/2d/sprite/SpriteRenderer.ts +++ b/packages/core/src/2d/sprite/SpriteRenderer.ts @@ -32,7 +32,7 @@ export class SpriteRenderer extends Renderer implements ISpriteRenderer { @ignoreClone private _drawMode: SpriteDrawMode; - @assignmentClone + @ignoreClone private _assembler: ISpriteAssembler; @assignmentClone private _tileMode: SpriteTileMode = SpriteTileMode.Continuous; @@ -287,7 +287,6 @@ export class SpriteRenderer extends Renderer implements ISpriteRenderer { */ override _cloneTo(target: SpriteRenderer, srcRoot: Entity, targetRoot: Entity): void { super._cloneTo(target, srcRoot, targetRoot); - target._assembler.resetData(target); target.sprite = this._sprite; target.drawMode = this._drawMode; } diff --git a/packages/ui/src/component/UICanvas.ts b/packages/ui/src/component/UICanvas.ts index 45dc1109d..8ab2e4a97 100644 --- a/packages/ui/src/component/UICanvas.ts +++ b/packages/ui/src/component/UICanvas.ts @@ -13,6 +13,7 @@ import { Ray, Vector2, Vector3, + assignmentClone, deepClone, dependentComponents, ignoreClone @@ -77,19 +78,19 @@ export class UICanvas extends Component implements IElement { @ignoreClone private _renderMode = CanvasRenderMode.WorldSpace; - @ignoreClone + @assignmentClone private _renderCamera: Camera; @ignoreClone private _cameraObserver: Camera; - @ignoreClone + @assignmentClone private _resolutionAdaptationMode = ResolutionAdaptationMode.HeightAdaptation; - @ignoreClone + @assignmentClone private _sortOrder: number = 0; - @ignoreClone + @assignmentClone private _distance: number = 10; @deepClone private _referenceResolution: Vector2 = new Vector2(800, 600); - @deepClone + @assignmentClone private _referenceResolutionPerUnit: number = 100; @ignoreClone private _hierarchyVersion: number = -1; @@ -381,6 +382,13 @@ export class UICanvas extends Component implements IElement { } } + /** + * @internal + */ + _cloneTo(target: UICanvas, srcRoot: Entity, targetRoot: Entity): void { + target.renderMode = this._renderMode; + } + private _getRenderers(): UIRenderer[] { const { _orderedRenderers: renderers, entity } = this; const uiHierarchyVersion = entity._uiHierarchyVersion; diff --git a/packages/ui/src/component/advanced/Image.ts b/packages/ui/src/component/advanced/Image.ts index a4031347b..404f248a0 100644 --- a/packages/ui/src/component/advanced/Image.ts +++ b/packages/ui/src/component/advanced/Image.ts @@ -29,7 +29,7 @@ export class Image extends UIRenderer implements ISpriteRenderer { private _sprite: Sprite = null; @ignoreClone private _drawMode: SpriteDrawMode; - @assignmentClone + @ignoreClone private _assembler: ISpriteAssembler; @assignmentClone private _tileMode: SpriteTileMode = SpriteTileMode.Continuous; @@ -149,6 +149,16 @@ export class Image extends UIRenderer implements ISpriteRenderer { } } + /** + * @internal + */ + _cloneTo(target: Image, srcRoot: Entity, targetRoot: Entity): void { + // @ts-ignore + super._cloneTo(target, srcRoot, targetRoot); + target.sprite = this._sprite; + target.drawMode = this._drawMode; + } + protected override _updateBounds(worldBounds: BoundingBox): void { const sprite = this._sprite; const rootCanvas = this._getRootCanvas(); diff --git a/tests/src/ui/Image.test.ts b/tests/src/ui/Image.test.ts index cef3cad4f..e1da58bfc 100644 --- a/tests/src/ui/Image.test.ts +++ b/tests/src/ui/Image.test.ts @@ -48,4 +48,18 @@ describe("Image", async () => { image.tiledAdaptiveThreshold = 1.5; expect(image.tiledAdaptiveThreshold).to.eq(1); }); + + it("Clone", () => { + const imageEntity = canvasEntity.createChild("Image"); + const image = imageEntity.addComponent(Image); + const sprite = new Sprite(engine, new Texture2D(engine, 100, 100)); + image.sprite = sprite; + image.drawMode = SpriteDrawMode.Sliced; + + const cloneEntity = imageEntity.clone(); + const cloneImage = cloneEntity.getComponent(Image); + + expect(cloneImage.sprite).to.eq(sprite); + expect(cloneImage.drawMode).to.eq(SpriteDrawMode.Sliced); + }); }); diff --git a/tests/src/ui/Text.test.ts b/tests/src/ui/Text.test.ts index 15498414f..6a0b0d101 100644 --- a/tests/src/ui/Text.test.ts +++ b/tests/src/ui/Text.test.ts @@ -1,4 +1,4 @@ -import { WebGLEngine } from "@galacean/engine"; +import { Font, WebGLEngine } from "@galacean/engine"; import { Text, UITransform } from "@galacean/engine-ui"; import { describe, expect, it } from "vitest"; @@ -100,4 +100,23 @@ describe("Text", async () => { label3.enableWrapping = true; label3.text = "hello world\nddl\nsdfjdslfsdfdssdfsdf"; }); + + it("Clone", () => { + const textEntity = canvasEntity.createChild("Image"); + const text = textEntity.addComponent(Text); + text.text = "hello world"; + text.fontSize = 30; + text.lineSpacing = 1; + text.enableWrapping = true; + text.font = Font.createFromOS(engine, "AlibabaSans"); + + const cloneEntity = textEntity.clone(); + const cloneText = cloneEntity.getComponent(Text); + + expect(cloneText.text).to.eq("hello world"); + expect(cloneText.fontSize).to.eq(30); + expect(cloneText.lineSpacing).to.eq(1); + expect(cloneText.enableWrapping).to.eq(true); + expect(cloneText.font).to.eq(text.font); + }); }); diff --git a/tests/src/ui/UICanvas.test.ts b/tests/src/ui/UICanvas.test.ts index 618fd6a40..74da18b59 100644 --- a/tests/src/ui/UICanvas.test.ts +++ b/tests/src/ui/UICanvas.test.ts @@ -265,4 +265,30 @@ describe("UICanvas", async () => { expect(Math.floor(canvasSize.x)).to.eq(168); expect(Math.floor(canvasSize.y)).to.eq(600); }); + + it("Clone", () => { + rootCanvas.renderMode = CanvasRenderMode.ScreenSpaceCamera; + rootCanvas.renderCamera = camera; + rootCanvas.distance = 10; + rootCanvas.referenceResolution = new Vector2(800, 600); + rootCanvas.resolutionAdaptationMode = ResolutionAdaptationMode.WidthAdaptation; + rootCanvas.referenceResolutionPerUnit = 100; + rootCanvas.sortOrder = 10; + const cloneEntity = canvasEntity.clone(); + const cloneCanvas = cloneEntity.getComponent(UICanvas); + console.log(cloneCanvas.entity.parent); + + expect(cloneCanvas.renderMode).to.eq(CanvasRenderMode.ScreenSpaceCamera); + expect(cloneCanvas.renderCamera).to.eq(camera); + expect(cloneCanvas.distance).to.eq(10); + expect(cloneCanvas.referenceResolution).to.deep.include({ x: 800, y: 600 }); + expect(cloneCanvas.resolutionAdaptationMode).to.eq(ResolutionAdaptationMode.WidthAdaptation); + expect(cloneCanvas.referenceResolutionPerUnit).to.eq(100); + expect(cloneCanvas.sortOrder).to.eq(10); + // @ts-ignore + expect(cloneCanvas._isRootCanvas).to.eq(false); + root.addChild(cloneEntity); + // @ts-ignore + expect(cloneCanvas._isRootCanvas).to.eq(true); + }); });