diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_gizmo.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_gizmo.dart index 66473ca9..a1d179df 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_gizmo.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_gizmo.dart @@ -2,13 +2,13 @@ import 'dart:async'; import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart'; import 'package:thermion_dart/src/viewer/src/shared_types/entities.dart'; +import 'thermion_dart.g.dart'; import 'package:thermion_dart/thermion_dart.dart'; import 'package:vector_math/vector_math_64.dart'; import 'ffi_view.dart'; class FFIGizmo extends FFIAsset implements GizmoAsset { - final Set nonPickableEntities; final Set gizmoEntities; late NativeCallable _nativeCallback; @@ -20,8 +20,10 @@ class FFIGizmo extends FFIAsset implements GizmoAsset { _callback?.call(GizmoPickResultType.values[resultType], Vector3(x, y, z)); } - bool isNonPickable(ThermionEntity entity) => - nonPickableEntities.contains(entity); + bool isNonPickable(ThermionEntity entity) { + return SceneManager_isGridEntity(sceneManager!, entity); + } + bool isGizmoEntity(ThermionEntity entity) => gizmoEntities.contains(entity); FFIGizmo( @@ -30,7 +32,6 @@ class FFIGizmo extends FFIAsset implements GizmoAsset { super.sceneManager, super.renderableManager, super.unlitMaterialProvider, - this.nonPickableEntities, this.gizmoEntities) { _nativeCallback = NativeCallable.listener(_onPickResult); diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart index 7b6525bf..b71332a3 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart @@ -1905,16 +1905,17 @@ external ffi.Pointer ffi.Pointer tSceneManager, ); -@ffi.Native)>(isLeaf: true) -external int SceneManager_getOverlayEntityCount( +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer SceneManager_createGrid( ffi.Pointer tSceneManager, ); -@ffi.Native, ffi.Size)>( +@ffi.Native, EntityId)>( isLeaf: true) -external int SceneManager_getOverlayEntityAt( +external bool SceneManager_isGridEntity( ffi.Pointer tSceneManager, - int index, + int entityId, ); @ffi.Native< diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart index aa689ec0..b72d16a3 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart @@ -1755,6 +1755,31 @@ class ThermionViewerFFI extends ThermionViewer { SceneManager_setVisibilityLayer(_sceneManager!, entity, layer.value); } + FFIAsset? _grid; + + /// + /// + /// + Future showGridOverlay() async { + final ptr = SceneManager_createGrid(_sceneManager!); + _grid ??= FFIAsset(ptr, _sceneManager!, _engine!, _unlitMaterialProvider!); + await _grid!.addToScene(); + } + + /// + /// + /// + Future removeGridOverlay() async { + if (_grid != null) { + await _grid!.removeFromScene(); + SceneManager_destroyAsset(_sceneManager!, _grid!.pointer); + _grid = null; + } + } + + /// + /// + /// Future unproject(ThermionEntity entity, Uint8List input, int inputWidth, int inputHeight, int outWidth, int outHeight) async { final outPtr = Uint8List(outWidth * outHeight * 4); @@ -1933,6 +1958,9 @@ class ThermionViewerFFI extends ThermionViewer { return instance; } + /// + /// + /// @override Future requestFrame() async { for (final hook in _hooks) { @@ -1963,6 +1991,9 @@ class ThermionViewerFFI extends ThermionViewer { return camera; } + /// + /// + /// Future destroyCamera(FFICamera camera) async { SceneManager_destroyCamera(_sceneManager!, camera.camera); } @@ -2037,10 +2068,6 @@ class ThermionViewerFFI extends ThermionViewer { if (gizmo == nullptr) { throw Exception("Failed to create gizmo"); } - final overlayEntityCount = - SceneManager_getOverlayEntityCount(_sceneManager!); - final overlayEntities = List.generate(overlayEntityCount, - (i) => SceneManager_getOverlayEntityAt(_sceneManager!, i)).toSet(); final gizmoEntityCount = SceneAsset_getChildEntityCount(gizmo.cast()); @@ -2054,7 +2081,6 @@ class ThermionViewerFFI extends ThermionViewer { _sceneManager!, _engine!, nullptr, - overlayEntities, gizmoEntities.toSet() ..add(SceneAsset_getEntity(gizmo.cast()))); } diff --git a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart index ad0bba9b..a6528a10 100644 --- a/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart +++ b/thermion_dart/lib/src/viewer/src/thermion_viewer_base.dart @@ -724,8 +724,7 @@ abstract class ThermionViewer { /// /// The gizmo for translating/rotating objects. Only one gizmo can be active for a given view. /// - Future createGizmo(covariant View view, - GizmoType type); + Future createGizmo(covariant View view, GizmoType type); /// /// Register a callback to be invoked when this viewer is disposed. @@ -763,6 +762,16 @@ abstract class ThermionViewer { /// Future setVisibilityLayer(ThermionEntity entity, VisibilityLayers layer); + /// + /// + /// + Future showGridOverlay(); + + /// + /// + /// + Future removeGridOverlay(); + /// /// Decodes the specified image data and creates a texture. /// @@ -875,7 +884,7 @@ abstract class ThermionViewer { /// /// Returns the camera specified by the given index. Note that the camera at /// index 0 is always the main camera; this cannot be destroyed. - /// + /// /// Throws an exception if the index is out-of-bounds. /// Camera getCameraAt(int index); diff --git a/thermion_dart/native/include/c_api/TSceneManager.h b/thermion_dart/native/include/c_api/TSceneManager.h index 5b3f17a9..7e1a6cc0 100644 --- a/thermion_dart/native/include/c_api/TSceneManager.h +++ b/thermion_dart/native/include/c_api/TSceneManager.h @@ -57,8 +57,9 @@ extern "C" EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAll(TSceneManager *tSceneManager); EMSCRIPTEN_KEEPALIVE void *SceneManager_destroyAsset(TSceneManager *tSceneManager, TSceneAsset *sceneAsset); EMSCRIPTEN_KEEPALIVE TNameComponentManager *SceneManager_getNameComponentManager(TSceneManager *tSceneManager); - EMSCRIPTEN_KEEPALIVE size_t SceneManager_getOverlayEntityCount(TSceneManager *tSceneManager); - EMSCRIPTEN_KEEPALIVE EntityId SceneManager_getOverlayEntityAt(TSceneManager *tSceneManager, size_t index); + + EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_createGrid(TSceneManager *tSceneManager); + EMSCRIPTEN_KEEPALIVE bool SceneManager_isGridEntity(TSceneManager *tSceneManager, EntityId entityId); #ifdef __cplusplus diff --git a/thermion_dart/native/include/scene/GridOverlay.hpp b/thermion_dart/native/include/scene/GridOverlay.hpp index 26abee73..dc88f2b2 100644 --- a/thermion_dart/native/include/scene/GridOverlay.hpp +++ b/thermion_dart/native/include/scene/GridOverlay.hpp @@ -1,49 +1,56 @@ #pragma once -#include +#include +#include -#include #include #include #include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include +#include +#include "scene/SceneAsset.hpp" namespace thermion { using namespace filament; -using namespace utils; -class GridOverlay { - public: - GridOverlay(Engine& engine); - void destroy(); +class GridOverlay : public SceneAsset { +public: + GridOverlay(Engine& engine); + ~GridOverlay(); - utils::Entity sphere() { - return _sphereEntity; - } + SceneAssetType getType() override { return SceneAsset::SceneAssetType::Gizmo; } + bool isInstance() override { return false; } + + SceneAsset* createInstance(MaterialInstance** materialInstances = nullptr, + size_t materialInstanceCount = 0) override; + + MaterialInstance** getMaterialInstances() override { return &_materialInstance; } + size_t getMaterialInstanceCount() override { return 1; } + + void addAllEntities(Scene* scene) override; + void removeAllEntities(Scene* scene) override; + + void setPriority(RenderableManager& rm, int priority) override; + void setLayer(RenderableManager& rm, int layer) override; - utils::Entity grid() { - return _gridEntity; - } - - private: - Engine &_engine; - utils::Entity _gridEntity; - utils::Entity _sphereEntity; - Material* _material; - MaterialInstance* _materialInstance; - MaterialInstance* _sphereMaterialInstance; + size_t getInstanceCount() override { return _instances.size(); } + SceneAsset* getInstanceByEntity(utils::Entity entity) override; + SceneAsset* getInstanceAt(size_t index) override; + size_t getChildEntityCount() override { return 2; } + const Entity* getChildEntities() override; + Entity findEntityByName(const char* name) override; + +private: + Engine& _engine; + utils::Entity _gridEntity; + utils::Entity _sphereEntity; + Entity _childEntities[2]; + Material* _material; + MaterialInstance* _materialInstance; + std::vector> _instances; + + void createGrid(); + void createSphere(); }; -} \ No newline at end of file +} // namespace thermion \ No newline at end of file diff --git a/thermion_dart/native/include/scene/SceneManager.hpp b/thermion_dart/native/include/scene/SceneManager.hpp index 4bd09180..6af8171a 100644 --- a/thermion_dart/native/include/scene/SceneManager.hpp +++ b/thermion_dart/native/include/scene/SceneManager.hpp @@ -299,21 +299,9 @@ namespace thermion return _ncm; } - Entity getOverlayEntity(size_t index) { - if(index == 0) { - return _gridOverlay->grid(); - } else if(index == 1) { - return _gridOverlay->sphere(); - } else { - return Entity(); - } - } - - size_t getOverlayEntityCount() { - return 2; - } - + SceneAsset *createGrid(); + bool isGridEntity(utils::Entity entity); private: gltfio::AssetLoader *_assetLoader = nullptr; @@ -345,7 +333,7 @@ namespace thermion std::unique_ptr _animationManager = std::nullptr_t(); std::unique_ptr _collisionComponentManager = std::nullptr_t(); - GridOverlay *_gridOverlay = std::nullptr_t(); + std::unique_ptr _grid = std::nullptr_t(); void _updateTransforms(); }; diff --git a/thermion_dart/native/src/GridOverlay.cpp b/thermion_dart/native/src/GridOverlay.cpp index 709f1741..dc0208a4 100644 --- a/thermion_dart/native/src/GridOverlay.cpp +++ b/thermion_dart/native/src/GridOverlay.cpp @@ -1,31 +1,36 @@ -#ifdef _WIN32 -#define _USE_MATH_DEFINES -#include -#endif - #include "scene/GridOverlay.hpp" - -#include -#include -#include -#include -#include -#include - -#include "material/grid.h" #include "scene/SceneManager.hpp" +#include "material/grid.h" #include "Log.hpp" namespace thermion { - using namespace filament::gltfio; - GridOverlay::GridOverlay(Engine &engine) : _engine(engine) { - auto &entityManager = EntityManager::get(); - auto &transformManager = engine.getTransformManager(); + createGrid(); + createSphere(); + _childEntities[0] = _gridEntity; + _childEntities[1] = _sphereEntity; + } + GridOverlay::~GridOverlay() + { + auto &rm = _engine.getRenderableManager(); + auto &tm = _engine.getTransformManager(); + + rm.destroy(_sphereEntity); + rm.destroy(_gridEntity); + tm.destroy(_sphereEntity); + tm.destroy(_gridEntity); + _engine.destroy(_sphereEntity); + _engine.destroy(_gridEntity); + _engine.destroy(_materialInstance); + _engine.destroy(_material); + } + + void GridOverlay::createGrid() + { const int gridSize = 100; const float gridSpacing = 1.0f; int vertexCount = (gridSize + 1) * 4; // 2 axes, 2 vertices per line @@ -61,10 +66,10 @@ namespace thermion .vertexCount(vertexCount) .bufferCount(1) .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3) - .build(engine); + .build(_engine); - vb->setBufferAt(engine, 0, VertexBuffer::BufferDescriptor(gridVertices, vertexCount * sizeof(filament::math::float3), [](void *buffer, size_t size, void *) - { delete[] static_cast(buffer); })); + vb->setBufferAt(_engine, 0, VertexBuffer::BufferDescriptor(gridVertices, vertexCount * sizeof(math::float3), [](void *buffer, size_t size, void *) + { delete[] static_cast(buffer); })); uint32_t *gridIndices = new uint32_t[vertexCount]; for (uint32_t i = 0; i < vertexCount; ++i) @@ -75,22 +80,22 @@ namespace thermion auto ib = IndexBuffer::Builder() .indexCount(vertexCount) .bufferType(IndexBuffer::IndexType::UINT) - .build(engine); + .build(_engine); - ib->setBuffer(engine, IndexBuffer::BufferDescriptor( - gridIndices, vertexCount * sizeof(uint32_t), - [](void *buffer, size_t size, void *) - { delete[] static_cast(buffer); })); + ib->setBuffer(_engine, IndexBuffer::BufferDescriptor( + gridIndices, + vertexCount * sizeof(uint32_t), + [](void *buffer, size_t size, void *) + { delete[] static_cast(buffer); })); - _gridEntity = entityManager.create(); + _gridEntity = utils::EntityManager::get().create(); _material = Material::Builder() .package(GRID_PACKAGE, GRID_GRID_SIZE) - .build(engine); + .build(_engine); _materialInstance = _material->createInstance(); - - _materialInstance->setParameter("maxDistance", 50.0f); // Adjust as needed - _materialInstance->setParameter("color", math::float3{0.05f, 0.05f, 0.05f}); // Gray color for the grid + _materialInstance->setParameter("maxDistance", 50.0f); + _materialInstance->setParameter("color", math::float3{0.05f, 0.05f, 0.05f}); RenderableManager::Builder(1) .boundingBox({{-gridSize * gridSpacing / 2, 0, -gridSize * gridSpacing / 2}, @@ -102,12 +107,16 @@ namespace thermion .culling(true) .receiveShadows(false) .castShadows(false) - .build(engine, _gridEntity); + .build(_engine, _gridEntity); + } + + void GridOverlay::createSphere() + { const float sphereRadius = 0.05f; const int sphereSegments = 16; const int sphereRings = 16; - vertexCount = (sphereRings + 1) * (sphereSegments + 1); + int vertexCount = (sphereRings + 1) * (sphereSegments + 1); int indexCount = sphereRings * sphereSegments * 6; math::float3 *vertices = new math::float3[vertexCount]; @@ -158,22 +167,23 @@ namespace thermion .vertexCount(vertexCount) .bufferCount(1) .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3) - .build(engine); + .build(_engine); - sphereVb->setBufferAt(engine, 0, VertexBuffer::BufferDescriptor(vertices, vertexCount * sizeof(math::float3), [](void *buffer, size_t size, void *) - { delete[] static_cast(buffer); })); + sphereVb->setBufferAt(_engine, 0, VertexBuffer::BufferDescriptor(vertices, vertexCount * sizeof(math::float3), [](void *buffer, size_t size, void *) + { delete[] static_cast(buffer); })); auto sphereIb = IndexBuffer::Builder() .indexCount(indexCount) .bufferType(IndexBuffer::IndexType::UINT) - .build(engine); + .build(_engine); - sphereIb->setBuffer(engine, IndexBuffer::BufferDescriptor( - indices, indexCount * sizeof(uint32_t), - [](void *buffer, size_t size, void *) - { delete[] static_cast(buffer); })); + sphereIb->setBuffer(_engine, IndexBuffer::BufferDescriptor( + indices, + indexCount * sizeof(uint32_t), + [](void *buffer, size_t size, void *) + { delete[] static_cast(buffer); })); - _sphereEntity = entityManager.create(); + _sphereEntity = utils::EntityManager::get().create(); RenderableManager::Builder(1) .boundingBox({{-sphereRadius, -sphereRadius, -sphereRadius}, @@ -184,19 +194,70 @@ namespace thermion .culling(true) .receiveShadows(false) .castShadows(false) - .build(engine, _sphereEntity); + .build(_engine, _sphereEntity); } - void GridOverlay::destroy() + SceneAsset *GridOverlay::createInstance(MaterialInstance **materialInstances, size_t materialInstanceCount) { - auto &rm = _engine.getRenderableManager(); - auto &tm = _engine.getTransformManager(); - rm.destroy(_sphereEntity); - rm.destroy(_gridEntity); - tm.destroy(_sphereEntity); - tm.destroy(_gridEntity); - _engine.destroy(_sphereEntity); - _engine.destroy(_gridEntity); + auto instance = std::make_unique(_engine); + auto *raw = instance.get(); + _instances.push_back(std::move(instance)); + return reinterpret_cast(raw); + } + + void GridOverlay::addAllEntities(Scene *scene) + { + scene->addEntity(_gridEntity); + scene->addEntity(_sphereEntity); + } + + void GridOverlay::removeAllEntities(Scene *scene) + { + scene->remove(_gridEntity); + scene->remove(_sphereEntity); + } + + void GridOverlay::setPriority(RenderableManager &rm, int priority) + { + auto gridInstance = rm.getInstance(_gridEntity); + rm.setPriority(gridInstance, priority); + auto sphereInstance = rm.getInstance(_sphereEntity); + rm.setPriority(sphereInstance, priority); + } + + void GridOverlay::setLayer(RenderableManager &rm, int layer) + { + auto gridInstance = rm.getInstance(_gridEntity); + rm.setLayerMask(gridInstance, 0xFF, 1u << (uint8_t)layer); + auto sphereInstance = rm.getInstance(_sphereEntity); + rm.setLayerMask(sphereInstance, 0xFF, 1u << (uint8_t)layer); + } + + SceneAsset *GridOverlay::getInstanceByEntity(utils::Entity entity) + { + for (auto &instance : _instances) + { + if (instance->_gridEntity == entity || instance->_sphereEntity == entity) + { + return instance.get(); + } + } + return nullptr; + } + + SceneAsset *GridOverlay::getInstanceAt(size_t index) + { + return _instances[index].get(); + } + + const Entity *GridOverlay::getChildEntities() + { + return _childEntities; + } + + Entity GridOverlay::findEntityByName(const char *name) + { + return Entity(); // Not implemented } } // namespace thermion \ No newline at end of file diff --git a/thermion_dart/native/src/c_api/TSceneManager.cpp b/thermion_dart/native/src/c_api/TSceneManager.cpp index 931539ff..a8053d74 100644 --- a/thermion_dart/native/src/c_api/TSceneManager.cpp +++ b/thermion_dart/native/src/c_api/TSceneManager.cpp @@ -207,13 +207,15 @@ extern "C" return reinterpret_cast(sceneManager->getNameComponentManager()); } - EMSCRIPTEN_KEEPALIVE size_t SceneManager_getOverlayEntityCount(TSceneManager *tSceneManager) { + EMSCRIPTEN_KEEPALIVE TSceneAsset *SceneManager_createGrid(TSceneManager *tSceneManager) { auto *sceneManager = reinterpret_cast(tSceneManager); - return sceneManager->getOverlayEntityCount(); + auto *grid = sceneManager->createGrid(); + return reinterpret_cast(grid); } - EMSCRIPTEN_KEEPALIVE EntityId SceneManager_getOverlayEntityAt(TSceneManager *tSceneManager, size_t index) { + + EMSCRIPTEN_KEEPALIVE bool SceneManager_isGridEntity(TSceneManager *tSceneManager, EntityId entityId) { auto *sceneManager = reinterpret_cast(tSceneManager); - auto entity = sceneManager->getOverlayEntity(index); - return utils::Entity::smuggle(entity); + return sceneManager->isGridEntity(utils::Entity::import(entityId)); } + } \ No newline at end of file diff --git a/thermion_dart/native/src/scene/SceneManager.cpp b/thermion_dart/native/src/scene/SceneManager.cpp index 39ffe0d8..0104f3bf 100644 --- a/thermion_dart/native/src/scene/SceneManager.cpp +++ b/thermion_dart/native/src/scene/SceneManager.cpp @@ -107,11 +107,6 @@ namespace thermion _animationManager = std::make_unique(_engine, _scene); - _gridOverlay = new GridOverlay(*_engine); - - _scene->addEntity(_gridOverlay->sphere()); - _scene->addEntity(_gridOverlay->grid()); - _unlitFixedSizeMaterial = Material::Builder() .package(UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_DATA, UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE) @@ -131,8 +126,8 @@ namespace thermion _engine->destroy(_unlitFixedSizeMaterial); _cameras.clear(); - - _gridOverlay->destroy(); + + _grid = nullptr; _gltfResourceLoader->asyncCancelLoad(); _ubershaderProvider->destroyMaterials(); @@ -148,6 +143,28 @@ namespace thermion AssetLoader::destroy(&_assetLoader); } + SceneAsset *SceneManager::createGrid() { + if(!_grid) { + _grid = std::make_unique(*_engine); + } + return _grid.get(); + } + + bool SceneManager::isGridEntity(utils::Entity entity) { + if(!_grid) { + return false; + } + if(entity == _grid->getEntity()) { + return true; + } + for(int i =0; i < _grid->getChildEntityCount(); i++) { + if(entity == _grid->getChildEntities()[i]) { + return true; + } + } + return false; + } + Gizmo *SceneManager::createGizmo(View *view, Scene *scene) { auto gizmo = std::make_unique(_engine, view, scene, _unlitFixedSizeMaterial);