don't share a single material instance for all highlighted objects
destroy highlight material instances on highlight asset destroyed expose highlight instances on Scene via getAssetForHighlight
This commit is contained in:
@@ -47,26 +47,42 @@ class FFIScene extends Scene {
|
|||||||
///
|
///
|
||||||
@override
|
@override
|
||||||
Future removeStencilHighlight(ThermionAsset asset) async {
|
Future removeStencilHighlight(ThermionAsset asset) async {
|
||||||
if (!_highlighted.contains(asset)) {
|
if (!_highlightInstances.containsKey(asset)) {
|
||||||
_logger
|
_logger
|
||||||
.warning("No stencil highlight for asset (entity ${asset.entity})");
|
.warning("No stencil highlight for asset (entity ${asset.entity})");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_logger
|
_logger
|
||||||
.info("Removing stencil highlight for asset (entity ${asset.entity})");
|
.info("Removing stencil highlight for asset (entity ${asset.entity})");
|
||||||
_highlighted.remove(asset);
|
|
||||||
final highlight = _highlightInstances[asset]!;
|
final highlight = _highlightInstances[asset]!;
|
||||||
|
_highlightInstances.remove(asset);
|
||||||
|
|
||||||
await remove(highlight);
|
await remove(highlight);
|
||||||
|
final materialInstance = await highlight.getMaterialInstanceAt();
|
||||||
await FilamentApp.instance!.destroyAsset(highlight);
|
await FilamentApp.instance!.destroyAsset(highlight);
|
||||||
|
await materialInstance.destroy();
|
||||||
|
|
||||||
_logger
|
_logger
|
||||||
.info("Removed stencil highlight for asset (entity ${asset.entity})");
|
.info("Removed stencil highlight for asset (entity ${asset.entity})");
|
||||||
}
|
}
|
||||||
|
|
||||||
static MaterialInstance? _highlightMaterialInstance;
|
final _highlightInstances = <ThermionAsset, ThermionAsset>{};
|
||||||
final _highlightInstances = <ThermionAsset, FFIAsset>{};
|
|
||||||
final _highlighted = <ThermionAsset>{};
|
Future<ThermionAsset?> getAssetForHighlight(ThermionEntity entity) async {
|
||||||
|
for (final asset in _highlightInstances.keys) {
|
||||||
|
var highlightAsset = _highlightInstances[asset]!;
|
||||||
|
if (highlightAsset.entity == entity) {
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
for (final child in await highlightAsset.getChildEntities()) {
|
||||||
|
if (child == entity) {
|
||||||
|
return asset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@@ -80,21 +96,21 @@ class FFIScene extends Scene {
|
|||||||
int primitiveIndex = 0}) async {
|
int primitiveIndex = 0}) async {
|
||||||
entity ??= asset.entity;
|
entity ??= asset.entity;
|
||||||
|
|
||||||
if (_highlighted.contains(asset)) {
|
if (_highlightInstances.containsKey(asset)) {
|
||||||
_logger
|
_logger
|
||||||
.info("Stencil highlight exists for asset (entity ${asset.entity})");
|
.info("Stencil highlight exists for asset (entity ${asset.entity})");
|
||||||
|
var instance = _highlightInstances[asset];
|
||||||
|
var highlightMaterialInstance = await instance!.getMaterialInstanceAt();
|
||||||
|
await highlightMaterialInstance.setParameterFloat4(
|
||||||
|
"baseColorFactor", r, g, b, 1.0);
|
||||||
} else {
|
} else {
|
||||||
_highlighted.add(asset);
|
var highlightMaterialInstance =
|
||||||
_highlightMaterialInstance ??=
|
|
||||||
await FilamentApp.instance!.createUnlitMaterialInstance();
|
await FilamentApp.instance!.createUnlitMaterialInstance();
|
||||||
var highlightInstance = await asset
|
var highlightInstance = await asset
|
||||||
.createInstance(materialInstances: [_highlightMaterialInstance!]);
|
.createInstance(materialInstances: [highlightMaterialInstance]);
|
||||||
|
_highlightInstances[asset] = highlightInstance as FFIAsset;
|
||||||
await highlightInstance.setCastShadows(false);
|
await highlightInstance.setCastShadows(false);
|
||||||
await highlightInstance.setReceiveShadows(false);
|
await highlightInstance.setReceiveShadows(false);
|
||||||
|
|
||||||
_highlightInstances[asset] = highlightInstance as FFIAsset;
|
|
||||||
|
|
||||||
|
|
||||||
var sourceMaterialInstance =
|
var sourceMaterialInstance =
|
||||||
await asset.getMaterialInstanceAt(entity: entity);
|
await asset.getMaterialInstanceAt(entity: entity);
|
||||||
@@ -108,13 +124,13 @@ class FFIScene extends Scene {
|
|||||||
await sourceMaterialInstance
|
await sourceMaterialInstance
|
||||||
.setStencilReferenceValue(View.STENCIL_HIGHLIGHT_REFERENCE_VALUE);
|
.setStencilReferenceValue(View.STENCIL_HIGHLIGHT_REFERENCE_VALUE);
|
||||||
|
|
||||||
await _highlightMaterialInstance!
|
await highlightMaterialInstance
|
||||||
.setStencilCompareFunction(SamplerCompareFunction.NE);
|
.setStencilCompareFunction(SamplerCompareFunction.NE);
|
||||||
await _highlightMaterialInstance!
|
await highlightMaterialInstance
|
||||||
.setStencilReferenceValue(View.STENCIL_HIGHLIGHT_REFERENCE_VALUE);
|
.setStencilReferenceValue(View.STENCIL_HIGHLIGHT_REFERENCE_VALUE);
|
||||||
await _highlightMaterialInstance!.setDepthCullingEnabled(true);
|
await highlightMaterialInstance.setDepthCullingEnabled(true);
|
||||||
await _highlightMaterialInstance!
|
await highlightMaterialInstance.setParameterFloat4(
|
||||||
.setParameterFloat4("baseColorFactor", r, g, b, 1.0);
|
"baseColorFactor", r, g, b, 1.0);
|
||||||
|
|
||||||
await add(highlightInstance);
|
await add(highlightInstance);
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ abstract class Scene {
|
|||||||
///
|
///
|
||||||
Future removeEntity(ThermionEntity entity);
|
Future removeEntity(ThermionEntity entity);
|
||||||
|
|
||||||
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
|
Future<ThermionAsset?> getAssetForHighlight(ThermionEntity entity);
|
||||||
|
|
||||||
/// Renders an outline around [entity] with the given color.
|
/// Renders an outline around [entity] with the given color.
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ void main() async {
|
|||||||
|
|
||||||
await testHelper.capture(viewer.view, "stencil_highlight");
|
await testHelper.capture(viewer.view, "stencil_highlight");
|
||||||
await scene.removeStencilHighlight(cube);
|
await scene.removeStencilHighlight(cube);
|
||||||
|
|
||||||
await testHelper.capture(viewer.view, "stencil_highlight_removed");
|
await testHelper.capture(viewer.view, "stencil_highlight_removed");
|
||||||
}, createStencilBuffer: true);
|
}, createStencilBuffer: true);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user