add method

Future<SceneNode?> add(
  1. EntityDef entity
)

Decodes and instantiates entity's asset if it names a model; null and no effect otherwise, PropVisuals.add's own "not every entity is mine" contract. Awaited by the caller, not fired and forgotten the way FixtureVisuals._addModel is — a lesson's steps read a node's rest position the moment the level opens, so the model has to already be in the scene by the time LevelReady/LessonReady is emitted, not two frames later.

Implementation

Future<SceneNode?> add(EntityDef entity) async {
  if (entity.type != entityType) return null;

  final path = entity.string('asset');
  if (path == null) {
    onIssue(Issue('$entityType "${entity.name ?? '?'}" names no asset'));
    return null;
  }

  final generation = _generation;
  final ModelAsset asset;
  try {
    // Whichever kind of path the level wrote: an `assets_src/` source goes
    // to the file the build hook converted it into, anything else is read
    // as it stands — see [loadModelByPath].
    final document = await loadModelByPath(path, bundleSource: _source);
    asset = await ModelAsset.fromDocument(
      document,
      device: device,
      name: path,
    );
  } catch (error) {
    onIssue(
      Issue(
        '$entityType "${entity.name ?? '?'}" could not load "$path": $error',
      ),
    );
    return null;
  }
  // [dispose] ran while the file was being read: the upload is released
  // here, since no list [dispose] walks will ever hold it, and nothing goes
  // into a scene nobody draws any more.
  if (generation != _generation) {
    asset.release(device);
    return null;
  }
  _assets.add(asset);

  final instance = asset.instantiate(scene, name: entity.name);
  instance.root.setPositionFrom(entity.position);
  instance.root.setRotationYawPitchRoll(entity.yaw, 0.0, 0.0);
  _instances.add(instance);

  final entityName = entity.name;
  if (entityName != null) {
    _nodes[entityName] = instance.root;
    for (var i = 0; i < asset.nodes.length; i++) {
      final nodeName = asset.nodes[i].name;
      if (nodeName != null) {
        _nodes['$entityName#$nodeName'] = instance.nodes[i];
      }
    }
  }
  return instance.root;
}