decentraland / sdk

PM repository for SDK
Apache License 2.0
4 stars 4 forks source link

Make onChange() work on custom components #1140

Open nearnshaw opened 1 month ago

nearnshaw commented 1 month ago

Today, the onChange function only works on native SDK components. It would be ideal for it to also work on any custom component defined in the scene.

here's a snippet to show that it doesn't work today:

import { engine, Entity, InputAction, MeshCollider, MeshRenderer, PointerEvents, pointerEventsSystem, Schemas, Transform } from '@dcl/sdk/ecs'
import { Quaternion, Vector3 } from '@dcl/sdk/math'

const CustomComponent = engine.defineComponent('customComponent', {
  visible: Schemas.Boolean,
})

export async function main() {

    const cube = engine.addEntity()
    Transform.create(cube, {
      position: Vector3.create(8, 1, 8),
    })
    MeshCollider.setBox(cube)
    MeshRenderer.setBox(cube)

    CustomComponent.create(cube, {
      visible: true
    })

    Transform.onChange(cube, (transform) => {
      if (!transform) {
        console.log('transform is null')
        return
      }
      console.log('cube position', transform.position)
      // console.log('customComponent visible', CustomComponent.get(cube).visible)
    })

    CustomComponent.onChange(cube, (customComponentNew) => {
      console.log('customComponent changed')
      if (!customComponentNew) {
        console.log('customComponent has been removed')
        return
      }
      console.log('customComponent visible', customComponentNew.visible)
    })

    pointerEventsSystem.onPointerDown(
      {
        entity: cube,
        opts: {
          button: InputAction.IA_PRIMARY,
          hoverText: 'click me',
        }
      },
      () => {
        Transform.getMutable(cube).position.z += 1
        CustomComponent.getMutable(cube).visible = !CustomComponent.get(cube).visible
      }
    )    
}

Without this helper, creators have to resort to the following:

export function checkForChanges() {
  for (const [entity] of engine.getEntitiesWith(CustomComponent)) {
    // check for changes
  }
}

engine.addSystem(checkForChanges)
ProteanCoding commented 3 weeks ago

This seems to be due to an underlying bug affecting a variety of the already-existing components, not just the custom ones. E.g., PlayerEquippedData is not working as expected in this example.