supermedium / superframe

:package: A super collection of A-Frame components.
https://supermedium.com/superframe/
MIT License
1.38k stars 424 forks source link

[text-geometry] No way to detect when text geometry loads. #105

Open donmccurdy opened 7 years ago

donmccurdy commented 7 years ago

Lots of components (e.g. physics) listen for model-loaded or object3dset events. The text-geometry uses the pattern here:

https://github.com/ngokevin/kframe/blob/master/components/text-geometry/index.js#L32-L45

Unfortunately this introduces a problem:

(1) An empty mesh is created first, and object3dset fires then. (2) If the font needs to be loaded, it will be attached to the (already created) THREE.Mesh asynchronously. This does not fire any event, so there's no way for systems like physics or pathfinding to know when it arrives.

A preferred pattern — and what I think we should encourage users to do in their components — would be to wait until geometry is available before calling el.setObject3D('mesh', mesh);.

See: https://github.com/donmccurdy/aframe-physics-system/issues/55

I assume this may have implications for attaching a material to the text?

homerjam commented 6 years ago

+1

subelsky commented 5 years ago

@donmccurdy I think I'm running into this on my project; is the fix a matter of changing that code so that it also waits for object3dset, like below? (untested) Or something more complex?

el.addEventListener('object3dset',() => {
    if (data.font.constructor === String) {
      // Load typeface.json font.
      fontLoader.load(data.font, function (response) {
        var textData = AFRAME.utils.clone(data);
        textData.font = response;
        mesh.geometry = new THREE.TextGeometry(data.value, textData);
      });
    } else if (data.font.constructor === Object) {
      // Set font if already have a typeface.json through setAttribute.
      mesh.geometry = new THREE.TextGeometry(data.value, data);
    } else {
      error('Must provide `font` (typeface.json) or `fontPath` (string) to text component.');
    }
  }, { once: true });

var mesh = el.getOrCreateObject3D('mesh', THREE.Mesh);
subelsky commented 5 years ago

I made a test case for this issue but was unable to reproduce it; it the text geometry component with aframe-physics-system and material and both seem to work:

https://glitch.com/~superframe-issue-105

I'm still pretty new to A-Frame so it's definitely possible something more subtle is going on. I'd be happy to dig into this further if someone could recommend a good next step.