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.Void Function(ffi.Pointer<TRenderableManager>, EntityId, ffi.Int,
ffi.Bool Function(ffi.Pointer<TRenderableManager>, EntityId, ffi.Int,
ffi.Pointer<TMaterialInstance>)>(isLeaf: true)
external void RenderableManager_setMaterialInstanceAt(
external bool RenderableManager_setMaterialInstanceAt(
ffi.Pointer<TRenderableManager> tRenderableManager,
int entityId,
int primitiveIndex,
@@ -2894,6 +2894,13 @@ external ffi.Pointer<TMaterialInstance> RenderableManager_getMaterialInstanceAt(
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)>(
isLeaf: true)
external bool RenderableManager_isRenderable(

View File

@@ -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) {

View File

@@ -444,9 +444,29 @@ class FFIAsset extends ThermionAsset {
@override
Future<MaterialInstance> 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 = <ThermionEntity>[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}");
}
}

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.