when getMaterialInstance/setMaterialInstance are called, if entity is not renderable, return false

if no entity is passed, iterate through all entities and use the first renderable entity
This commit is contained in:
Nick Fisher
2025-05-23 16:27:38 +08:00
parent 725f36a860
commit 195a625738
6 changed files with 80 additions and 19 deletions

View File

@@ -2876,9 +2876,9 @@ external bool GltfResourceLoader_loadResources(
); );
@ffi.Native< @ffi.Native<
ffi.Void Function(ffi.Pointer<TRenderableManager>, EntityId, ffi.Int, ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId, ffi.Int,
ffi.Pointer<TMaterialInstance>)>(isLeaf: true) ffi.Pointer<TMaterialInstance>)>(isLeaf: true)
external void RenderableManager_setMaterialInstanceAt( external bool RenderableManager_setMaterialInstanceAt(
ffi.Pointer<TRenderableManager> tRenderableManager, ffi.Pointer<TRenderableManager> tRenderableManager,
int entityId, int entityId,
int primitiveIndex, int primitiveIndex,
@@ -2894,6 +2894,13 @@ external ffi.Pointer<TMaterialInstance> RenderableManager_getMaterialInstanceAt(
int primitiveIndex, int primitiveIndex,
); );
@ffi.Native<ffi.Size Function(ffi.Pointer<TRenderableManager>, EntityId)>(
isLeaf: true)
external int RenderableManager_getPrimitiveCount(
ffi.Pointer<TRenderableManager> tRenderableManager,
int entityId,
);
@ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId)>( @ffi.Native<ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId)>(
isLeaf: true) isLeaf: true)
external bool RenderableManager_isRenderable( external bool RenderableManager_isRenderable(

View File

@@ -130,12 +130,6 @@ class BackgroundImage extends ThermionAsset {
throw UnimplementedError(); throw UnimplementedError();
} }
@override
Future setMaterialInstanceAt(covariant MaterialInstance instance) {
// TODO: implement setMaterialInstanceAt
throw UnimplementedError();
}
@override @override
Future setReceiveShadows(bool castShadows) { Future setReceiveShadows(bool castShadows) {
// TODO: implement setReceiveShadows // TODO: implement setReceiveShadows

View File

@@ -444,9 +444,29 @@ class FFIAsset extends ThermionAsset {
@override @override
Future<MaterialInstance> getMaterialInstanceAt( Future<MaterialInstance> getMaterialInstanceAt(
{ThermionEntity? entity, int index = 0}) async { {ThermionEntity? entity, int index = 0}) async {
if (entity == null) {
if (RenderableManager_isRenderable(app.renderableManager, this.entity)) {
entity ??= 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( var ptr = RenderableManager_getMaterialInstanceAt(
Engine_getRenderableManager(app.engine), entity, 0); Engine_getRenderableManager(app.engine), entity, 0);
if (ptr == nullptr) {
throw Exception("Failed to get material instance for asset");
}
return FFIMaterialInstance(ptr, app); return FFIMaterialInstance(ptr, app);
} }
@@ -454,12 +474,34 @@ class FFIAsset extends ThermionAsset {
/// ///
/// ///
@override @override
Future setMaterialInstanceAt(FFIMaterialInstance instance) async { Future setMaterialInstanceAt(FFIMaterialInstance instance,
var childEntities = await getChildEntities(); {int? entity = null, int primitiveIndex = 0}) async {
final entities = <ThermionEntity>[entity, ...childEntities];
for (final entity in entities) { if (entity == null) {
RenderableManager_setMaterialInstanceAt( if (RenderableManager_isRenderable(app.renderableManager, this.entity)) {
Engine_getRenderableManager(app.engine), entity, 0, instance.pointer); 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}");
} }
} }

View File

@@ -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. /// Renders an outline around [entity] with the given color.

View File

@@ -8,8 +8,9 @@ extern "C"
{ {
#endif #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 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_isRenderable(TRenderableManager *tRenderableManager, EntityId entityId);
EMSCRIPTEN_KEEPALIVE bool RenderableManager_hasComponent(TRenderableManager *tRenderableManager, EntityId entityId); EMSCRIPTEN_KEEPALIVE bool RenderableManager_hasComponent(TRenderableManager *tRenderableManager, EntityId entityId);
EMSCRIPTEN_KEEPALIVE bool RenderableManager_empty(TRenderableManager *tRenderableManager); EMSCRIPTEN_KEEPALIVE bool RenderableManager_empty(TRenderableManager *tRenderableManager);

View File

@@ -16,13 +16,27 @@ namespace thermion
using namespace filament; using namespace filament;
using namespace utils; 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<filament::RenderableManager *>(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<filament::RenderableManager *>(tRenderableManager); auto *renderableManager = reinterpret_cast<filament::RenderableManager *>(tRenderableManager);
const auto &entity = utils::Entity::import(entityId); const auto &entity = utils::Entity::import(entityId);
auto renderableInstance = renderableManager->getInstance(entity); auto renderableInstance = renderableManager->getInstance(entity);
if(!renderableInstance.isValid()) {
return false;
}
auto materialInstance = reinterpret_cast<MaterialInstance *>(tMaterialInstance); auto materialInstance = reinterpret_cast<MaterialInstance *>(tMaterialInstance);
renderableManager->setMaterialInstanceAt(renderableInstance, primitiveIndex, materialInstance); renderableManager->setMaterialInstanceAt(renderableInstance, primitiveIndex, materialInstance);
return true;
} }
EMSCRIPTEN_KEEPALIVE TMaterialInstance *RenderableManager_getMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex) { EMSCRIPTEN_KEEPALIVE TMaterialInstance *RenderableManager_getMaterialInstanceAt(TRenderableManager *tRenderableManager, EntityId entityId, int primitiveIndex) {