Skip to content

Fix: Support custom asset loading for GSplat (getter-only props)#316

Open
No-LAN-B wants to merge 3 commits intoplaycanvas:mainfrom
No-LAN-B:main
Open

Fix: Support custom asset loading for GSplat (getter-only props)#316
No-LAN-B wants to merge 3 commits intoplaycanvas:mainfrom
No-LAN-B:main

Conversation

@No-LAN-B
Copy link

@No-LAN-B No-LAN-B commented Feb 27, 2026

Problem (Addresses Issue - #315 )

Using with a custom-loaded asset (e.g. from a @playcanvas/splat-transform loader) throws:

Cannot set property id of #<GSplatComponent> which has only a getter
  at createComponentDefinition (validation.ts)

The same pattern can affect any component that exposes getter-only props (e.g. id).

Root cause

  • 1.) getPseudoPublicProps includes getter-only properties (e.g. GSplatComponent.id) in the props used to build the schema.
  • 2.) createComponentDefinition then adds a schema entry for each of those props with a default.
  • 3.) validatePropsWithDefaults / validatePropsPartial fill validated props from the schema, so read-only props like id are always present with a default.
  • 4.) applyProps assigns every validated prop to the instance. Assigning to a getter-only property throws, so the flow fails even when the user never sets id.

So the failure comes from the generic “apply all schema props” path trying to assign to getter-only props, not from the custom asset loading path itself.

Solution

  • Detect getter-only in createComponentDefinition using the property descriptor (get without set) and mark them as read-only.
  • Schema entries without apply (number, string, boolean, Mat4, Material): set readOnly: true on the schema entry when the prop is getter-only.
  • Schema entries with apply (Color, Vec2, Vec3, Vec4, Quat, Arrays, Null): keep the existing apply callbacks and add an early return when the prop is read-only so they never assign.
  • applyProps: skip when propDef is missing or propDef.readOnly is true, so we never call apply or direct-assign for read-only props.

Getter-only props stay in the schema (so the public API stays complete and anything that relies on them being present still works), but they are never applied, so the “Cannot set property id” error is fixed.

Changes

  • PropValidator: optional readOnly?: boolean.
  • applyProps: guard with if (!propDef || propDef.readOnly) return before applying.
  • createComponentDefinition: detect getter-only via descriptor and set propertyInfo.readOnly; add ...(propertyInfo.readOnly && { readOnly: true }) to schema entries that have no apply (Mat4, number, string, boolean, Material); add if (propertyInfo.readOnly) return at the start of every apply callback for types that have apply.

Result

  • Custom-loaded assets work with without throwing.
  • No change for components that don’t expose getter-only props.
  • Getter-only props remain in the schema for docs/API completeness and are simply skipped at apply time.

@changeset-bot
Copy link

changeset-bot bot commented Feb 27, 2026

⚠️ No Changeset found

Latest commit: d80fca7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant