adoptUnchanged method
Carries realized resources over from previous (the realizer the live
scene was built with) for every resource whose spec and payload bytes
are unchanged, so a hot reload rebuilds only what actually changed
instead of re-uploading the whole document (seconds for a large scene).
Call before preload; preload skips carried-over entries.
Unchanged payload bytes are detected by object identity, which holds for sidecar-cached source loads and for documents sharing chunk buffers; a byte-equal but distinct buffer just rebuilds that resource.
Implementation
void adoptUnchanged(ResourceRealizer previous) {
const equality = DeepCollectionEquality();
final oldResources = _encodedResources(previous.document);
final newResources = _encodedResources(document);
bool payloadUnchanged(LocalId id) {
final old = previous.document.payloads[id];
final current = document.payloads[id];
if (old == null || current == null) return false;
return old.encoding == current.encoding &&
old.layout == current.layout &&
old.format == current.format &&
old.width == current.width &&
old.height == current.height &&
old.length == current.length &&
identical(old.bytes, current.bytes);
}
bool specUnchanged(LocalId id) =>
equality.equals(oldResources[id], newResources[id]);
final adoptedTextures = <LocalId>{};
for (final entry in document.resources.entries) {
final id = entry.key;
final resource = entry.value;
if (!specUnchanged(id)) continue;
switch (resource) {
case GeometryResource():
if (resource.vertices case final vertices?
when !payloadUnchanged(vertices)) {
continue;
}
if (resource.indices case final indices?
when !payloadUnchanged(indices)) {
continue;
}
final geometry = previous._geometries[id];
if (geometry != null) _geometries[id] = geometry;
case TextureResource():
if (resource.payload case final payload?
when !payloadUnchanged(payload)) {
continue;
}
final texture = previous._textures[id];
if (texture != null) {
_textures[id] = texture;
adoptedTextures.add(id);
}
case EnvironmentResource():
if (resource.environment case PayloadEnvironment(
:final payload,
) when !payloadUnchanged(payload)) {
continue;
}
final environment = previous._environments[id];
if (environment != null) _environments[id] = environment;
default:
break;
}
}
// A material realizes against its referenced textures, so it carries over
// only when they all did.
for (final entry in document.resources.entries) {
final id = entry.key;
final resource = entry.value;
if (resource is! MaterialResource || !specUnchanged(id)) continue;
final textureRefs = [
for (final value in resource.properties.values)
if (value case ResourceRefValue(:final id)) id,
];
if (!textureRefs.every(adoptedTextures.contains)) continue;
final material = previous._materials[id];
if (material != null) _materials[id] = material;
}
}