Skip to content

Commit 59b6c5f

Browse files
committed
feat: migrate from experimental decorators to TC39 Stage 3 decorators
- Rewrite all decorator definitions for TC39 (decorators.ts, decorators.functions.ts, nodeDecorator.ts) - Use Symbol.metadata for per-class metadata storage - Add 'accessor' keyword to all @expandToProperty and @addAccessorsForMaterialProperty properties - Flip addAccessorsForMaterialProperty pattern: decorator on public accessor - Rewrite 3MF XML decorators and Smart Filters decorators for TC39 - Update Lit viewer components with accessor keyword for @property/@state/@query - Remove experimentalDecorators from all tsconfig files - Add esnext.decorators and es2022.object to lib - Bump UMD build targets from ES5 to ES2015 (accessor requires it) - Replace _propStore access with getEditableProperties() helper - Add unit tests for decorator metadata and expandToProperty - Fix class self-references in decorator arguments (TS2449) - Remove experimentalDecorators from Playground/Snippet Loader compiler options
1 parent 74c5d70 commit 59b6c5f

74 files changed

Lines changed: 895 additions & 746 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/dev/core/src/BakedVertexAnimation/bakedVertexAnimationManager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,15 @@ export class BakedVertexAnimationManager implements IBakedVertexAnimationManager
7575
*/
7676
@serializeAsTexture()
7777
@expandToProperty("_markSubMeshesAsAttributesDirty")
78-
public texture: Nullable<BaseTexture>;
78+
public accessor texture: Nullable<BaseTexture>;
7979

8080
private _isEnabled = true;
8181
/**
8282
* Enable or disable the vertex animation manager
8383
*/
8484
@serialize()
8585
@expandToProperty("_markSubMeshesAsAttributesDirty")
86-
public isEnabled = true;
86+
public accessor isEnabled = true;
8787

8888
/**
8989
* The animation parameters for the mesh. See setAnimationParameters()

packages/dev/core/src/Decorators/nodeDecorator.ts

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,19 +107,50 @@ export function editableInPropertyPage(
107107
groupName: string = "PROPERTIES",
108108
options?: IEditablePropertyOption
109109
) {
110-
return (target: any, propertyKey: string) => {
111-
let propStore: IPropertyDescriptionForEdition[] = target._propStore;
112-
if (!propStore) {
110+
return (_value: unknown, context: { name: string | symbol; metadata: DecoratorMetadataObject }) => {
111+
const meta = context.metadata;
112+
let propStore: IPropertyDescriptionForEdition[];
113+
if (Object.hasOwn(meta, __bjsPropStoreKey)) {
114+
propStore = meta[__bjsPropStoreKey] as IPropertyDescriptionForEdition[];
115+
} else {
113116
propStore = [];
114-
target._propStore = propStore;
117+
meta[__bjsPropStoreKey] = propStore;
115118
}
116119
propStore.push({
117-
propertyName: propertyKey,
120+
propertyName: String(context.name),
118121
displayName: displayName,
119122
type: propertyType,
120123
groupName: groupName,
121124
options: options ?? {},
122-
className: target.getClassName(),
125+
className: "",
123126
});
124127
};
125128
}
129+
130+
/** @internal */
131+
export const __bjsPropStoreKey = "__bjs_prop_store__";
132+
133+
/**
134+
* Gets the editable properties for a given target using TC39 decorator metadata.
135+
* Walks the metadata prototype chain to include properties from parent classes.
136+
* @param target - the target object (instance or constructor)
137+
* @returns array of property descriptions
138+
*/
139+
export function getEditableProperties(target: any): IPropertyDescriptionForEdition[] {
140+
const ctor = typeof target === "function" ? target : target?.constructor;
141+
const metadata: DecoratorMetadataObject | undefined = ctor?.[Symbol.metadata];
142+
if (!metadata) {
143+
return [];
144+
}
145+
146+
const result: IPropertyDescriptionForEdition[] = [];
147+
let currentMeta: any = metadata;
148+
while (currentMeta) {
149+
if (Object.hasOwn(currentMeta, __bjsPropStoreKey)) {
150+
const store = currentMeta[__bjsPropStoreKey] as IPropertyDescriptionForEdition[];
151+
result.push(...store);
152+
}
153+
currentMeta = Object.getPrototypeOf(currentMeta);
154+
}
155+
return result;
156+
}

packages/dev/core/src/Lights/light.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ export abstract class Light extends Node implements ISortableLight {
211211
* exceeding the number allowed of the materials.
212212
*/
213213
@expandToProperty("_reorderLightsInScene")
214-
public renderPriority: number = 0;
214+
public accessor renderPriority: number = 0;
215215

216216
@serialize("shadowEnabled")
217217
private _shadowEnabled: boolean = true;

packages/dev/core/src/Materials/Background/backgroundMaterial.ts

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
247247
* Key light Color (multiply against the environment texture)
248248
*/
249249
@expandToProperty("_markAllSubMeshesAsLightsDirty")
250-
public primaryColor = Color3.White();
250+
public accessor primaryColor = Color3.White();
251251

252252
@serializeAsColor3()
253253
protected __perceptualColor: Nullable<Color3>;
@@ -292,14 +292,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
292292
* The primary color is used at the level chosen to define what the white area would look.
293293
*/
294294
@expandToProperty("_markAllSubMeshesAsLightsDirty")
295-
public get primaryColorHighlightLevel(): float {
296-
return this._primaryColorHighlightLevel;
297-
}
298-
public set primaryColorHighlightLevel(value: float) {
299-
this._primaryColorHighlightLevel = value;
300-
this._computePrimaryColors();
301-
this._markAllSubMeshesAsLightsDirty();
302-
}
295+
public accessor primaryColorHighlightLevel: float;
303296

304297
@serializeAsTexture()
305298
protected _reflectionTexture: Nullable<BaseTexture>;
@@ -308,7 +301,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
308301
* Should be author in a specific way for the best result (refer to the documentation).
309302
*/
310303
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
311-
public reflectionTexture: Nullable<BaseTexture> = null;
304+
public accessor reflectionTexture: Nullable<BaseTexture> = null;
312305

313306
@serialize()
314307
protected _reflectionBlur: float;
@@ -319,7 +312,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
319312
* texture twice.
320313
*/
321314
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
322-
public reflectionBlur: float = 0;
315+
public accessor reflectionBlur: float = 0;
323316

324317
@serializeAsTexture()
325318
protected _diffuseTexture: Nullable<BaseTexture>;
@@ -328,15 +321,15 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
328321
* Should be author in a specific way for the best result (refer to the documentation).
329322
*/
330323
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
331-
public diffuseTexture: Nullable<BaseTexture> = null;
324+
public accessor diffuseTexture: Nullable<BaseTexture> = null;
332325

333326
protected _shadowLights: Nullable<IShadowLight[]> = null;
334327
/**
335328
* Specify the list of lights casting shadow on the material.
336329
* All scene shadow lights will be included if null.
337330
*/
338331
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
339-
public shadowLights: Nullable<IShadowLight[]> = null;
332+
public accessor shadowLights: Nullable<IShadowLight[]> = null;
340333

341334
@serialize()
342335
protected _shadowLevel: float;
@@ -345,7 +338,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
345338
* 0 means black shadows and 1 means no shadows.
346339
*/
347340
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
348-
public shadowLevel: float = 0;
341+
public accessor shadowLevel: float = 0;
349342

350343
@serializeAsVector3()
351344
protected _sceneCenter: Vector3;
@@ -354,7 +347,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
354347
* It is usually zero but might be interesting to modify according to your setup.
355348
*/
356349
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
357-
public sceneCenter: Vector3 = Vector3.Zero();
350+
public accessor sceneCenter: Vector3 = Vector3.Zero();
358351

359352
@serialize()
360353
protected _opacityFresnel: boolean;
@@ -363,7 +356,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
363356
* This helps ensuring a nice transition when the camera goes under the ground.
364357
*/
365358
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
366-
public opacityFresnel: boolean = true;
359+
public accessor opacityFresnel: boolean = true;
367360

368361
@serialize()
369362
protected _reflectionFresnel: boolean;
@@ -372,7 +365,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
372365
* This helps adding a mirror texture on the ground.
373366
*/
374367
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
375-
public reflectionFresnel: boolean = false;
368+
public accessor reflectionFresnel: boolean = false;
376369

377370
@serialize()
378371
protected _reflectionFalloffDistance: number;
@@ -381,31 +374,31 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
381374
* This helps adding a nice falloff effect to the reflection if used as a mirror for instance.
382375
*/
383376
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
384-
public reflectionFalloffDistance: number = 0.0;
377+
public accessor reflectionFalloffDistance: number = 0.0;
385378

386379
@serialize()
387380
protected _reflectionAmount: number;
388381
/**
389382
* This specifies the weight of the reflection against the background in case of reflection Fresnel.
390383
*/
391384
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
392-
public reflectionAmount: number = 1.0;
385+
public accessor reflectionAmount: number = 1.0;
393386

394387
@serialize()
395388
protected _reflectionReflectance0: number;
396389
/**
397390
* This specifies the weight of the reflection at grazing angle.
398391
*/
399392
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
400-
public reflectionReflectance0: number = 0.05;
393+
public accessor reflectionReflectance0: number = 0.05;
401394

402395
@serialize()
403396
protected _reflectionReflectance90: number;
404397
/**
405398
* This specifies the weight of the reflection at a perpendicular point of view.
406399
*/
407400
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
408-
public reflectionReflectance90: number = 0.5;
401+
public accessor reflectionReflectance90: number = 0.5;
409402

410403
/**
411404
* Sets the reflection reflectance fresnel values according to the default standard
@@ -431,15 +424,15 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
431424
* Helps to directly use the maps channels instead of their level.
432425
*/
433426
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
434-
public useRGBColor: boolean = true;
427+
public accessor useRGBColor: boolean = true;
435428

436429
@serialize()
437430
protected _enableNoise: boolean;
438431
/**
439432
* This helps reducing the banding effect that could occur on the background.
440433
*/
441434
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
442-
public enableNoise: boolean = false;
435+
public accessor enableNoise: boolean = false;
443436

444437
/**
445438
* The current fov(field of view) multiplier, 0.0 - 2.0. Defaults to 1.0. Lower values "zoom in" and higher values "zoom out".
@@ -468,15 +461,15 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
468461
* Number of Simultaneous lights allowed on the material.
469462
*/
470463
@expandToProperty("_markAllSubMeshesAsTexturesDirty")
471-
public maxSimultaneousLights: int = 4;
464+
public accessor maxSimultaneousLights: int = 4;
472465

473466
@serialize()
474467
private _shadowOnly: boolean = false;
475468
/**
476469
* Make the material only render shadows
477470
*/
478471
@expandToProperty("_markAllSubMeshesAsLightsDirty")
479-
public shadowOnly: boolean = false;
472+
public accessor shadowOnly: boolean = false;
480473

481474
/**
482475
* Due to a bug in iOS10, video tags (which are using the background material) are in BGR and not RGB.
@@ -491,7 +484,7 @@ export class BackgroundMaterial extends BackgroundMaterialBase {
491484
*/
492485
@serialize()
493486
@expandToProperty("_markAllSubMeshesAsMiscDirty")
494-
public enableGroundProjection: boolean = false;
487+
public accessor enableGroundProjection: boolean = false;
495488

496489
/**
497490
* Defines the radius of the projected ground if enableGroundProjection is true.

packages/dev/core/src/Materials/GaussianSplatting/gaussianSplattingSolidColorMaterialPlugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class GaussianSplattingSolidColorMaterialPlugin extends MaterialPluginBas
2828
*/
2929
@serialize()
3030
@expandToProperty("_onIsEnabledChanged")
31-
public isEnabled = true;
31+
public accessor isEnabled = true;
3232

3333
/** @internal */
3434
public _onIsEnabledChanged(): void {

packages/dev/core/src/Materials/Node/Blocks/Dual/lightBlock.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class LightBlock extends NodeMaterialBlock {
3131

3232
/** Indicates that no code should be generated in the vertex shader. Can be useful in some specific circumstances (like when doing ray marching for eg) */
3333
@editableInPropertyPage("Generate only fragment code", PropertyTypeForEdition.Boolean, "ADVANCED", {
34-
notifiers: { rebuild: true, update: true, onValidation: LightBlock._OnGenerateOnlyFragmentCodeChanged },
34+
notifiers: { rebuild: true, update: true, onValidation: (block, prop) => LightBlock._OnGenerateOnlyFragmentCodeChanged(block, prop) },
3535
})
3636
public generateOnlyFragmentCode = false;
3737

packages/dev/core/src/Materials/Node/Blocks/Dual/reflectionTextureBaseBlock.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export abstract class ReflectionTextureBaseBlock extends NodeMaterialBlock {
101101

102102
/** Indicates that no code should be generated in the vertex shader. Can be useful in some specific circumstances (like when doing ray marching for eg) */
103103
@editableInPropertyPage("Generate only fragment code", PropertyTypeForEdition.Boolean, "ADVANCED", {
104-
notifiers: { rebuild: true, update: true, onValidation: ReflectionTextureBaseBlock._OnGenerateOnlyFragmentCodeChanged },
104+
notifiers: { rebuild: true, update: true, onValidation: (block, prop) => ReflectionTextureBaseBlock._OnGenerateOnlyFragmentCodeChanged(block, prop) },
105105
})
106106
public generateOnlyFragmentCode = false;
107107

packages/dev/core/src/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
320320

321321
/** Indicates that no code should be generated in the vertex shader. Can be useful in some specific circumstances (like when doing ray marching for eg) */
322322
@editableInPropertyPage("Generate only fragment code", PropertyTypeForEdition.Boolean, "ADVANCED", {
323-
notifiers: { rebuild: true, update: true, onValidation: PBRMetallicRoughnessBlock._OnGenerateOnlyFragmentCodeChanged },
323+
notifiers: { rebuild: true, update: true, onValidation: (block, prop) => PBRMetallicRoughnessBlock._OnGenerateOnlyFragmentCodeChanged(block, prop) },
324324
})
325325
public generateOnlyFragmentCode = false;
326326

0 commit comments

Comments
 (0)