diff --git a/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart b/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart index 3ef2b774..e841f04c 100644 --- a/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart +++ b/thermion_dart/lib/src/bindings/src/thermion_dart_ffi.g.dart @@ -2876,9 +2876,9 @@ external bool GltfResourceLoader_loadResources( ); @ffi.Native< - ffi.Void Function(ffi.Pointer, EntityId, ffi.Int, + ffi.Bool Function(ffi.Pointer, EntityId, ffi.Int, ffi.Pointer)>(isLeaf: true) -external void RenderableManager_setMaterialInstanceAt( +external bool RenderableManager_setMaterialInstanceAt( ffi.Pointer tRenderableManager, int entityId, int primitiveIndex, @@ -2894,6 +2894,13 @@ external ffi.Pointer RenderableManager_getMaterialInstanceAt( int primitiveIndex, ); +@ffi.Native, EntityId)>( + isLeaf: true) +external int RenderableManager_getPrimitiveCount( + ffi.Pointer tRenderableManager, + int entityId, +); + @ffi.Native, EntityId)>( isLeaf: true) external bool RenderableManager_isRenderable( diff --git a/thermion_dart/lib/src/filament/src/implementation/background_image.dart b/thermion_dart/lib/src/filament/src/implementation/background_image.dart index 014e37c3..d647e627 100644 --- a/thermion_dart/lib/src/filament/src/implementation/background_image.dart +++ b/thermion_dart/lib/src/filament/src/implementation/background_image.dart @@ -128,13 +128,7 @@ class BackgroundImage extends ThermionAsset { Future setCastShadows(bool castShadows) { // TODO: implement setCastShadows throw UnimplementedError(); - } - - @override - Future setMaterialInstanceAt(covariant MaterialInstance instance) { - // TODO: implement setMaterialInstanceAt - throw UnimplementedError(); - } + } @override Future setReceiveShadows(bool castShadows) { diff --git a/thermion_dart/lib/src/filament/src/implementation/ffi_asset.dart b/thermion_dart/lib/src/filament/src/implementation/ffi_asset.dart index db9a72ae..39e71b30 100644 --- a/thermion_dart/lib/src/filament/src/implementation/ffi_asset.dart +++ b/thermion_dart/lib/src/filament/src/implementation/ffi_asset.dart @@ -444,9 +444,29 @@ class FFIAsset extends ThermionAsset { @override Future getMaterialInstanceAt( {ThermionEntity? entity, int index = 0}) async { - entity ??= this.entity; + + if (entity == null) { + if (RenderableManager_isRenderable(app.renderableManager, this.entity)) { + entity ??= this.entity; + } else { + for (final child in await getChildEntities()) { + if (RenderableManager_isRenderable(app.renderableManager, child)) { + entity = child; + break; + } + } + } + } + + if (entity == null) { + throw Exception("Failed to find renderable entity"); + } + var ptr = RenderableManager_getMaterialInstanceAt( Engine_getRenderableManager(app.engine), entity, 0); + if (ptr == nullptr) { + throw Exception("Failed to get material instance for asset"); + } return FFIMaterialInstance(ptr, app); } @@ -454,12 +474,34 @@ class FFIAsset extends ThermionAsset { /// /// @override - Future setMaterialInstanceAt(FFIMaterialInstance instance) async { - var childEntities = await getChildEntities(); - final entities = [entity, ...childEntities]; - for (final entity in entities) { - RenderableManager_setMaterialInstanceAt( - Engine_getRenderableManager(app.engine), entity, 0, instance.pointer); + Future setMaterialInstanceAt(FFIMaterialInstance instance, + {int? entity = null, int primitiveIndex = 0}) async { + + if (entity == null) { + if (RenderableManager_isRenderable(app.renderableManager, this.entity)) { + entity ??= this.entity; + } else { + for (final child in await getChildEntities()) { + if (RenderableManager_isRenderable(app.renderableManager, child)) { + entity = child; + break; + } + } + } + } + + if (entity == null) { + throw Exception("Failed to find renderable entity"); + } + + if (!RenderableManager_setMaterialInstanceAt( + Engine_getRenderableManager(app.engine), + entity, + primitiveIndex, + instance.pointer)) { + _logger.warning( + "Failed to set material instance for entity $entity at primitive index ${primitiveIndex}"); + } } diff --git a/thermion_dart/lib/src/filament/src/interface/asset.dart b/thermion_dart/lib/src/filament/src/interface/asset.dart index 5164968b..5b0d68a5 100644 --- a/thermion_dart/lib/src/filament/src/interface/asset.dart +++ b/thermion_dart/lib/src/filament/src/interface/asset.dart @@ -51,7 +51,10 @@ abstract class ThermionAsset { /// /// /// - Future setMaterialInstanceAt(covariant MaterialInstance instance); + Future setMaterialInstanceAt(covariant MaterialInstance instance, + {int? entity = null, int primitiveIndex = 0}) { + throw UnimplementedError(); + } /// /// Renders an outline around [entity] with the given color. diff --git a/thermion_dart/native/include/c_api/TRenderableManager.h b/thermion_dart/native/include/c_api/TRenderableManager.h index 7773e135..2f626630 100644 --- a/thermion_dart/native/include/c_api/TRenderableManager.h +++ b/thermion_dart/native/include/c_api/TRenderableManager.h @@ -8,8 +8,9 @@ extern "C" { #endif - EMSCRIPTEN_KEEPALIVE void RenderableManager_setMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex, TMaterialInstance *tMaterialInstance); + EMSCRIPTEN_KEEPALIVE bool RenderableManager_setMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex, TMaterialInstance *tMaterialInstance); EMSCRIPTEN_KEEPALIVE TMaterialInstance *RenderableManager_getMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex); + EMSCRIPTEN_KEEPALIVE size_t RenderableManager_getPrimitiveCount(TRenderableManager *tRenderableManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE bool RenderableManager_isRenderable(TRenderableManager *tRenderableManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE bool RenderableManager_hasComponent(TRenderableManager *tRenderableManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE bool RenderableManager_empty(TRenderableManager *tRenderableManager); diff --git a/thermion_dart/native/src/c_api/TRenderableManager.cpp b/thermion_dart/native/src/c_api/TRenderableManager.cpp index e8f03828..608998c8 100644 --- a/thermion_dart/native/src/c_api/TRenderableManager.cpp +++ b/thermion_dart/native/src/c_api/TRenderableManager.cpp @@ -16,13 +16,27 @@ namespace thermion using namespace filament; using namespace utils; - EMSCRIPTEN_KEEPALIVE void RenderableManager_setMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex, TMaterialInstance *tMaterialInstance) + EMSCRIPTEN_KEEPALIVE size_t RenderableManager_getPrimitiveCount(TRenderableManager *tRenderableManager, EntityId entityId) { + auto *renderableManager = reinterpret_cast(tRenderableManager); + const auto &entity = utils::Entity::import(entityId); + auto renderableInstance = renderableManager->getInstance(entity); + if(!renderableInstance.isValid()) { + return 0; + } + return renderableManager->getPrimitiveCount(renderableInstance); + } + + EMSCRIPTEN_KEEPALIVE bool RenderableManager_setMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex, TMaterialInstance *tMaterialInstance) { auto *renderableManager = reinterpret_cast(tRenderableManager); const auto &entity = utils::Entity::import(entityId); auto renderableInstance = renderableManager->getInstance(entity); + if(!renderableInstance.isValid()) { + return false; + } auto materialInstance = reinterpret_cast(tMaterialInstance); renderableManager->setMaterialInstanceAt(renderableInstance, primitiveIndex, materialInstance); + return true; } EMSCRIPTEN_KEEPALIVE TMaterialInstance *RenderableManager_getMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex) {