allow directly creating an entity and setting transform

This commit is contained in:
Nick Fisher
2025-05-24 16:33:58 +08:00
parent 75a9950909
commit 1e812ebe93
5 changed files with 96 additions and 30 deletions

View File

@@ -10,6 +10,7 @@ import 'package:thermion_dart/src/filament/src/implementation/ffi_scene.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_swapchain.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_texture.dart';
import 'package:thermion_dart/src/filament/src/implementation/ffi_view.dart';
import 'package:thermion_dart/src/utils/src/matrix.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:logging/logging.dart';
import 'resource_loader.dart';
@@ -1092,4 +1093,23 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
void onDestroy(Future Function() callback) {
_onDestroy.add(callback);
}
///
///
///
Future<ThermionEntity> createEntity(
{bool createTransformComponent = true}) async {
final entity = EntityManager_createEntity(Engine_getEntityManager(engine));
if (createTransformComponent) {
TransformManager_createComponent(transformManager, entity);
}
return entity;
}
///
///
///
Future setTransform(ThermionEntity entity, Matrix4 transform) async {
TransformManager_setTransform(transformManager, entity, matrix4ToDouble4x4(transform));
}
}

View File

@@ -320,4 +320,14 @@ abstract class FilamentApp<T> {
///
///
void onDestroy(Future Function() callback);
///
///
///
Future<ThermionEntity> createEntity({bool createTransformComponent = true});
///
///
///
Future setTransform(ThermionEntity entity, Matrix4 transform);
}

View File

@@ -183,6 +183,12 @@ namespace thermion
return reinterpret_cast<TLightManager *>(&lightManager);
}
EMSCRIPTEN_KEEPALIVE TEntityManager *Engine_getEntityManager(TEngine *tEngine) {
auto *engine = reinterpret_cast<Engine *>(tEngine);
auto &entityManager = engine->getEntityManager();
return reinterpret_cast<TEntityManager *>(&entityManager);
}
EMSCRIPTEN_KEEPALIVE TCamera *Engine_createCamera(TEngine *tEngine)
{
auto *engine = reinterpret_cast<Engine *>(tEngine);
@@ -404,6 +410,11 @@ namespace thermion
engine->destroy(indirectLight);
}
EMSCRIPTEN_KEEPALIVE EntityId EntityManager_createEntity(TEntityManager *tEntityManager) {
auto entityManager = reinterpret_cast<utils::EntityManager *>(tEntityManager);
auto entity = entityManager->create();
}
#ifdef __cplusplus
}
}

View File

@@ -168,4 +168,14 @@ extern "C"
return Entity::smuggle(parent);
}
EMSCRIPTEN_KEEPALIVE void TransformManager_createComponent(TTransformManager *tTransformManager, EntityId entityId) {
auto tm = reinterpret_cast<TransformManager *>(tTransformManager);
auto entity = Entity::import(entityId);
if(tm->hasComponent(entity)) {
Log("Entity already has transform component");
return;
}
tm->create(entity);
}
}

View File

@@ -8,45 +8,60 @@ import 'helpers.dart';
void main() async {
final testHelper = TestHelper("transforms");
await testHelper.setup();
group("transforms", () {
test('set/unset parent geometry', () async {
await testHelper.withViewer((viewer) async {
var blueMaterialInstance =
await FilamentApp.instance!.createUnlitMaterialInstance();
final blueCube = await viewer.createGeometry(
GeometryHelper.cube(normals: false, uvs: false),
materialInstances: [blueMaterialInstance]);
await blueMaterialInstance.setParameterFloat4(
"baseColorFactor", 0.0, 0.0, 1.0, 1.0);
// Position blue cube slightly behind and to the right
await blueCube
.setTransform(Matrix4.translation(Vector3(1.0, 0.0, -1.0)));
test('create entity and set as parent', () async {
await testHelper.withViewer((viewer) async {
final cube = await viewer
.createGeometry(GeometryHelper.cube(normals: false, uvs: false));
var greenMaterialInstance =
await FilamentApp.instance!.createUnlitMaterialInstance();
final greenCube = await viewer.createGeometry(
GeometryHelper.cube(normals: false, uvs: false),
materialInstances: [greenMaterialInstance]);
await greenMaterialInstance.setParameterFloat4(
"baseColorFactor", 0.0, 1.0, 0.0, 1.0);
await testHelper.capture(viewer.view, "create_entity_before_parent");
final entity = await FilamentApp.instance!.createEntity();
await viewer.addToScene(blueCube);
await viewer.addToScene(greenCube);
await FilamentApp.instance!.setParent(cube.entity, entity);
await testHelper.capture(viewer.view, "before_parent");
await FilamentApp.instance!.setTransform(entity, Matrix4.translation(Vector3.all(-1)));
await FilamentApp.instance!.setParent(blueCube.entity, greenCube.entity);
await testHelper.capture(viewer.view, "create_entity_after_parent");
await greenCube.setTransform(Matrix4.translation(Vector3.all(-1)));
});
});
await testHelper.capture(viewer.view, "after_parent");
test('set/unset parent geometry', () async {
await testHelper.withViewer((viewer) async {
var blueMaterialInstance =
await FilamentApp.instance!.createUnlitMaterialInstance();
final blueCube = await viewer.createGeometry(
GeometryHelper.cube(normals: false, uvs: false),
materialInstances: [blueMaterialInstance]);
await blueMaterialInstance.setParameterFloat4(
"baseColorFactor", 0.0, 0.0, 1.0, 1.0);
await FilamentApp.instance!.setParent(blueCube.entity, null);
// Position blue cube slightly behind and to the right
await blueCube.setTransform(Matrix4.translation(Vector3(1.0, 0.0, -1.0)));
await testHelper.capture(viewer.view, "unparent");
});
var greenMaterialInstance =
await FilamentApp.instance!.createUnlitMaterialInstance();
final greenCube = await viewer.createGeometry(
GeometryHelper.cube(normals: false, uvs: false),
materialInstances: [greenMaterialInstance]);
await greenMaterialInstance.setParameterFloat4(
"baseColorFactor", 0.0, 1.0, 0.0, 1.0);
await viewer.addToScene(blueCube);
await viewer.addToScene(greenCube);
await testHelper.capture(viewer.view, "before_parent");
await FilamentApp.instance!.setParent(blueCube.entity, greenCube.entity);
await greenCube.setTransform(Matrix4.translation(Vector3.all(-1)));
await testHelper.capture(viewer.view, "after_parent");
await FilamentApp.instance!.setParent(blueCube.entity, null);
await testHelper.capture(viewer.view, "unparent");
});
});
}