MaterialParameters.fromMetadata constructor

MaterialParameters.fromMetadata(
  1. Shader shader,
  2. Map<String, Object?> metadata
)

Builds parameters from a shader's reflection plus a .fmat sidecar entry.

Offsets and the block size come from shader; types, defaults, and hints come from metadata. Throws if a parameter named in the metadata is not present in the compiled shader block (a stale bundle or metadata).

Implementation

factory MaterialParameters.fromMetadata(
  gpu.Shader shader,
  Map<String, Object?> metadata,
) {
  final blockName =
      (metadata['uniform_block'] as String?) ?? 'MaterialParams';
  final slot = shader.getUniformSlot(blockName);
  final sizeInBytes = slot.sizeInBytes ?? 0;

  final layout = <String, _ParamSlot>{};
  final defaults = <String, Object>{};
  for (final raw in (metadata['parameters'] as List?) ?? const []) {
    final p = (raw as Map).cast<String, Object?>();
    final name = p['name'] as String;
    final type = FmatType.fromToken(p['type'] as String);
    if (type == null) {
      throw StateError('Unknown parameter type "${p['type']}" for "$name".');
    }
    final offset = slot.getMemberOffsetInBytes(name);
    if (offset == null) {
      throw StateError(
        'Material parameter "$name" is not present in the compiled shader '
        'block "$blockName" (stale bundle or metadata).',
      );
    }
    final hint = (p['hint'] as Map?)?.cast<String, Object?>();
    layout[name] = _ParamSlot(
      type,
      offset,
      sourceColor: hint?['kind'] == 'source_color',
    );
    final defaultValue = p['default'];
    if (defaultValue != null) defaults[name] = defaultValue;
  }

  final samplers = <String, _SamplerSlot>{};
  for (final raw in (metadata['samplers'] as List?) ?? const []) {
    final s = (raw as Map).cast<String, Object?>();
    final hint = (s['hint'] as Map?)?.cast<String, Object?>();
    samplers[s['name'] as String] = _SamplerSlot(
      _hintKind(hint?['kind'] as String?),
    );
  }

  final params = MaterialParameters._(
    blockName,
    ByteData(sizeInBytes),
    layout,
    samplers,
  );
  defaults.forEach(params._applyDefault);
  return params;
}