Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
79e9105
refactor(clone): add @defaultCloneMode and type-driven clone for cont…
Jun 17, 2026
a22e83c
refactor(clone): rewrite clone system — opt-out + default Assignment …
Jun 17, 2026
afce33d
refactor(clone): mark value-semantic classes with @defaultCloneMode(D…
Jun 17, 2026
94e6a03
fix(clone): remap nested Entity/Component refs via two-pass clone
Jun 22, 2026
a0e5fa9
refactor(clone): three-tier mode resolution + container default deep
Jun 22, 2026
297508f
refactor(clone): drop 171 field clone-mode decorators, rely on type d…
Jun 22, 2026
c5d6257
Merge remote-tracking branch 'upstream/dev/2.0' into fix/clone-opt-ou…
Jun 23, 2026
00498a1
ci: shard codecov unit tests (4 shards) to avoid browser crash on ful…
Jun 23, 2026
1561b72
docs(clone): drop CLONE_OPT_IN_AUDIT.md; design moved to PR description
Jun 23, 2026
d196914
ci: split codecov into 8 shards (vitest browser WebGL resource ceiling)
Jun 23, 2026
3cdd18c
test(clone): regression for texture refCount balance on clone/destroy
Jun 23, 2026
b8e754c
ci: revert codecov sharding experiment (let GitHub run the original f…
Jun 23, 2026
2139275
refactor(clone): decouple ref counting from the clone gate and unify …
Jul 2, 2026
13f3d95
Merge branch 'dev/2.0' into fix/clone-opt-out-assignment
Jul 2, 2026
9c5469c
refactor(clone): slot-ownership ref counting — gate acquires, owner r…
Jul 3, 2026
c2790dd
test(clone): refCount lifecycle suites + fix particle MeshShape mesh …
Jul 3, 2026
60135e9
refactor(clone)!: remove the deprecated shallowClone decorator
Jul 3, 2026
2a4309e
style(clone): order CloneManager members by visibility
Jul 3, 2026
88625db
refactor(clone): exempt user scripts from gate ref counting
Jul 3, 2026
2239fbd
refactor(clone): one uniform slot contract — no script special-casing
Jul 3, 2026
c7df2af
refactor(clone): move slot-ownership acquisition out of the gate
Jul 3, 2026
84e1b76
docs(clone): clarify the @deepClone-on-Remap branch is error recovery
Jul 3, 2026
3c26c2a
docs(clone): condense the CloneManager class comment
Jul 3, 2026
5b8da5a
test(clone): pin aliasing topology — shared instance clones into one …
Jul 3, 2026
e5894ae
refactor(clone): drop _cloneTo logic the type-driven gate already covers
Jul 3, 2026
8ef2a64
fix(mesh): type _onSkinUpdated's value as the union it actually carries
Jul 3, 2026
158fbdc
refactor(math): add a MathValue base class carrying the family clone …
Jul 3, 2026
1be50b0
Revert "refactor(math): add a MathValue base class carrying the famil…
Jul 3, 2026
5e3738d
test(clone): guard math value-type registration completeness
Jul 3, 2026
7dba7c1
feat(math): implement IClone/ICopy on Ray and register it Deep
Jul 3, 2026
de460e8
fix(clone): treat null-prototype objects as data containers
Jul 3, 2026
6c4cbb7
fix(clone): @deepClone on a registered asset recovers to sharing
Jul 3, 2026
56fb595
docs(clone): tighten comments in CloneManager and ComponentCloner
Jul 3, 2026
6a8688e
feat(clone): register runtime containers @defaultCloneMode(Ignore)
Jul 3, 2026
a3510d4
refactor(clone): drop @ignoreClone on runtime-container typed fields
Jul 3, 2026
887bfcc
docs(clone): define Deep as structure-fresh, member-semantic cloning
Jul 3, 2026
83e8328
docs(clone): correct stale or vacuous comments in gate and cloner
Jul 3, 2026
bdcc635
refactor(ui): centralize transition state ref counting in the base class
Jul 3, 2026
81c7991
test(math): cover Ray clone and copyFrom
Jul 3, 2026
e696681
fix(clone): release an owned counted preset displaced by an uncounted…
Jul 3, 2026
b0064ab
fix(clone): register typed-array clones in the identity map and harde…
Jul 3, 2026
d095812
fix(clone): route copyFrom dispatch after containers and close review…
Jul 3, 2026
6d0c7fe
test(clone): cover the rewritten Skin, PostProcess and TrailRenderer …
Jul 3, 2026
78ec199
docs(clone): align clone guides with the type-driven mechanism
Jul 3, 2026
9fa3cc2
refactor(clone): settle slot ownership unconditionally and fold dupli…
Jul 4, 2026
23f0459
test(clone): rename the suite after CloneManager and fix stale attrib…
Jul 4, 2026
2a91917
perf(clone): iterate Map/Set with for-of to avoid per-clone closure a…
Jul 4, 2026
c13dd08
docs(clone): drop a change-narrating comment on the Map branch
Jul 4, 2026
6d724c7
docs(clone): drop tense-relative wording from a lifecycle test comment
Jul 4, 2026
828008f
fix(particle): allow bare construction of ParticleCompositeGradient
Jul 4, 2026
16d95d6
test(clone): enforce the bare-construction contract for Deep-register…
Jul 4, 2026
f58d380
feat(clone): name the bare-construction contract when a deep clone ca…
Jul 4, 2026
843ab78
test(clone): pin the host-bound-in-container rejection as intended se…
Jul 4, 2026
9db6c66
test(clone): pin both host-bound-in-container behaviors by component …
Jul 4, 2026
f8ad0d7
fix(shader): cascade texture-array entries through the ref-count cont…
Jul 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions packages/core/src/clone/CloneManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,30 @@ export function deepClone(target: Object, propertyKey: string): void {
CloneManager.registerCloneMode(target, propertyKey, CloneMode.Deep);
}

/**
* Class decorator that sets the default clone mode for instances of the decorated type.
*
* When a field holds an instance of a type decorated with `@defaultCloneMode`, the clone system
* uses the specified mode instead of the default Assignment behavior. This applies when the field
* has no explicit per-field clone decorator, or when the value is encountered inside a container
* (Array, Map, Set) that is being deep-cloned.
*
* @param mode - The clone mode applied to instances of the decorated type
*
* @example
* ```ts
* @defaultCloneMode(CloneMode.Deep)
* class MyConfig {
* value = 0;
* }
* ```
*/
export function defaultCloneMode(mode: CloneMode) {
return function (target: Function): void {
Object.defineProperty(target.prototype, "_defaultCloneMode", { value: mode });
Comment thread
coderabbitai[bot] marked this conversation as resolved.
};
}

/**
* @internal
* Clone manager.
Expand Down Expand Up @@ -113,7 +137,18 @@ export class CloneManager {

if (cloneMode === CloneMode.Ignore) return;

// Primitives, undecorated, or @assignmentClone: direct assign
// If no per-field decorator, consult the value's type-level default clone mode
if (cloneMode === undefined && sourceProperty instanceof Object) {
const typeDefault = (<ICustomClone>sourceProperty)._defaultCloneMode;
if (typeDefault === CloneMode.Deep) {
cloneMode = CloneMode.Deep;
} else if (typeDefault === CloneMode.Shallow) {
cloneMode = CloneMode.Shallow;
}
// typeDefault === undefined or Assignment → fall through to assignment below
}

// Primitives, undecorated (no type default), or @assignmentClone: direct assign
if (!(sourceProperty instanceof Object) || cloneMode === undefined || cloneMode === CloneMode.Assignment) {
target[k] = sourceProperty;
return;
Expand Down Expand Up @@ -150,7 +185,7 @@ export class CloneManager {
<Array<any>>sourceProperty,
targetPropertyA,
i,
cloneMode,
undefined,
srcRoot,
targetRoot,
deepInstanceMap
Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/clone/ComponentCloner.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { Component } from "../Component";
import { Entity } from "../Entity";
import { CloneManager } from "./CloneManager";
import { CloneMode } from "./enums/CloneMode";

/**
* Custom clone interface.
*/
export interface ICustomClone {
/**
* @internal
* Default clone mode for instances of this type when encountered as a value in a field.
* Set via `@defaultCloneMode`. Absence defaults to Assignment (shared reference).
*/
readonly _defaultCloneMode?: CloneMode;
/**
* @internal
*/
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/shader/state/BlendState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { IHardwareRenderer } from "@galacean/engine-design";
import { Color } from "@galacean/engine-math";
import { RenderStateElementMap } from "../../BasicResources";
import { GLCapabilityType } from "../../base/Constant";
import { deepClone } from "../../clone/CloneManager";
import { deepClone, defaultCloneMode } from "../../clone/CloneManager";
import { CloneMode } from "../../clone/enums/CloneMode";
import { ShaderData } from "../ShaderData";
import { ShaderProperty } from "../ShaderProperty";
import { BlendFactor } from "../enums/BlendFactor";
Expand All @@ -15,6 +16,7 @@ import { RenderTargetBlendState } from "./RenderTargetBlendState";
/**
* Blend state.
*/
@defaultCloneMode(CloneMode.Deep)
export class BlendState {
private static _getGLBlendFactor(rhi: IHardwareRenderer, blendFactor: BlendFactor): number {
const gl = rhi.gl;
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/shader/state/DepthState.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { IHardwareRenderer } from "@galacean/engine-design";
import { RenderStateElementMap } from "../../BasicResources";
import { defaultCloneMode } from "../../clone/CloneManager";
import { CloneMode } from "../../clone/enums/CloneMode";
import { ShaderData } from "../ShaderData";
import { ShaderProperty } from "../ShaderProperty";
import { CompareFunction } from "../enums/CompareFunction";
Expand All @@ -9,6 +11,7 @@ import { RenderState } from "./RenderState";
/**
* Depth state.
*/
@defaultCloneMode(CloneMode.Deep)
export class DepthState {
private static _getGLCompareFunction(rhi: IHardwareRenderer, compareFunction: CompareFunction): number {
const gl = rhi.gl;
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/shader/state/RasterState.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { IHardwareRenderer } from "@galacean/engine-design";
import { RenderStateElementMap } from "../../BasicResources";
import { defaultCloneMode } from "../../clone/CloneManager";
import { CloneMode } from "../../clone/enums/CloneMode";
import { ShaderData } from "../ShaderData";
import { ShaderProperty } from "../ShaderProperty";
import { CullMode } from "../enums/CullMode";
Expand All @@ -9,6 +11,7 @@ import { RenderState } from "./RenderState";
/**
* Raster state.
*/
@defaultCloneMode(CloneMode.Deep)
export class RasterState {
/** Specifies whether or not front- and/or back-facing polygons can be culled. */
cullMode: CullMode = CullMode.Back;
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/shader/state/RenderState.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ShaderData, ShaderProperty } from "..";
import { RenderStateElementMap } from "../../BasicResources";
import { Engine } from "../../Engine";
import { deepClone } from "../../clone/CloneManager";
import { deepClone, defaultCloneMode } from "../../clone/CloneManager";
import { CloneMode } from "../../clone/enums/CloneMode";
import { RenderQueueType } from "../enums/RenderQueueType";
import { RenderStateElementKey } from "../enums/RenderStateElementKey";
import { BlendState } from "./BlendState";
Expand All @@ -12,6 +13,7 @@ import { StencilState } from "./StencilState";
/**
* Render state.
*/
@defaultCloneMode(CloneMode.Deep)
export class RenderState {
/** Blend state. */
@deepClone
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/shader/state/RenderTargetBlendState.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { defaultCloneMode } from "../../clone/CloneManager";
import { CloneMode } from "../../clone/enums/CloneMode";
import { BlendOperation } from "../enums/BlendOperation";
import { BlendFactor } from "../enums/BlendFactor";
import { ColorWriteMask } from "../enums/ColorWriteMask";

/**
* The blend state of the render target.
*/
@defaultCloneMode(CloneMode.Deep)
export class RenderTargetBlendState {
/** Whether to enable blend. */
enabled: boolean = false;
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/shader/state/StencilState.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { IHardwareRenderer } from "@galacean/engine-design";
import { RenderStateElementMap } from "../../BasicResources";
import { defaultCloneMode } from "../../clone/CloneManager";
import { CloneMode } from "../../clone/enums/CloneMode";
import { ShaderData } from "../ShaderData";
import { ShaderProperty } from "../ShaderProperty";
import { CompareFunction } from "../enums/CompareFunction";
Expand All @@ -10,6 +12,7 @@ import { RenderState } from "./RenderState";
/**
* Stencil state.
*/
@defaultCloneMode(CloneMode.Deep)
export class StencilState {
private static _getGLCompareFunction(rhi: IHardwareRenderer, compareFunction: CompareFunction): number {
const gl = rhi.gl;
Expand Down
Loading