diff --git a/ios/include/FlutterFilamentFFIApi.h b/ios/include/FlutterFilamentFFIApi.h index 097f369a..22dbb4a7 100644 --- a/ios/include/FlutterFilamentFFIApi.h +++ b/ios/include/FlutterFilamentFFIApi.h @@ -4,98 +4,119 @@ #include "FlutterFilamentApi.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/// -/// This header replicates most of the methods in FlutterFilamentApi.h, and is only intended to be used to generate client FFI bindings. -/// The intention is that calling one of these methods will call its respective method in FlutterFilamentApi.h, but wrapped in some kind of thread runner to ensure thread safety. -/// + /// + /// This header replicates most of the methods in FlutterFilamentApi.h, and is only intended to be used to generate client FFI bindings. + /// The intention is that calling one of these methods will call its respective method in FlutterFilamentApi.h, but wrapped in some kind of thread runner to ensure thread safety. + /// -typedef int32_t EntityId; -typedef void (*FilamentRenderCallback)(void* const owner); + typedef int32_t EntityId; + typedef void (*FilamentRenderCallback)(void *const owner); -FLUTTER_PLUGIN_EXPORT void* const create_filament_viewer_ffi(void* const context, void* const platform, const char* uberArchivePath, const ResourceLoaderWrapper* const loader, void (*renderCallback)(void* const renderCallbackOwner), void* const renderCallbackOwner); -FLUTTER_PLUGIN_EXPORT void create_swap_chain_ffi(void* const viewer, void* const surface, uint32_t width, uint32_t height); -FLUTTER_PLUGIN_EXPORT void destroy_swap_chain_ffi(void* const viewer); -FLUTTER_PLUGIN_EXPORT void create_render_target_ffi(void* const viewer, intptr_t nativeTextureId, uint32_t width, uint32_t height); -FLUTTER_PLUGIN_EXPORT void destroy_filament_viewer_ffi(void* const viewer); -FLUTTER_PLUGIN_EXPORT void render_ffi(void* const viewer); -FLUTTER_PLUGIN_EXPORT FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback); -FLUTTER_PLUGIN_EXPORT void set_rendering_ffi(void* const viewer, bool rendering); -FLUTTER_PLUGIN_EXPORT void set_frame_interval_ffi(float frameInterval); -FLUTTER_PLUGIN_EXPORT void update_viewport_and_camera_projection_ffi(void* const viewer, const uint32_t width, const uint32_t height, const float scaleFactor); -FLUTTER_PLUGIN_EXPORT void set_background_color_ffi(void* const viewer, const float r, const float g, const float b, const float a); -FLUTTER_PLUGIN_EXPORT void clear_background_image_ffi(void* const viewer); -FLUTTER_PLUGIN_EXPORT void set_background_image_ffi(void* const viewer, const char *path, bool fillHeight); -FLUTTER_PLUGIN_EXPORT void set_background_image_position_ffi(void* const viewer, float x, float y, bool clamp); -FLUTTER_PLUGIN_EXPORT void set_tone_mapping_ffi(void* const viewer, int toneMapping); -FLUTTER_PLUGIN_EXPORT void set_bloom_ffi(void* const viewer, float strength); -FLUTTER_PLUGIN_EXPORT void load_skybox_ffi(void* const viewer, const char *skyboxPath); -FLUTTER_PLUGIN_EXPORT void load_ibl_ffi(void* const viewer, const char *iblPath, float intensity); -FLUTTER_PLUGIN_EXPORT void remove_skybox_ffi(void* const viewer); -FLUTTER_PLUGIN_EXPORT void remove_ibl_ffi(void* const viewer); -FLUTTER_PLUGIN_EXPORT EntityId add_light_ffi(void* const viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, float dirX, float dirY, float dirZ, bool shadows); -FLUTTER_PLUGIN_EXPORT void remove_light_ffi(void* const viewer, EntityId entityId); -FLUTTER_PLUGIN_EXPORT void clear_lights_ffi(void* const viewer); -FLUTTER_PLUGIN_EXPORT EntityId load_glb_ffi(void* const sceneManager, const char *assetPath, int numInstances); -FLUTTER_PLUGIN_EXPORT EntityId load_glb_from_buffer_ffi(void* const sceneManager, const void* const data, size_t length, int numInstances); -FLUTTER_PLUGIN_EXPORT EntityId load_gltf_ffi(void* const sceneManager, const char *assetPath, const char *relativePath); -FLUTTER_PLUGIN_EXPORT EntityId create_instance_ffi(void* const sceneManager, EntityId entityId); -FLUTTER_PLUGIN_EXPORT void remove_entity_ffi(void* const viewer, EntityId asset); -FLUTTER_PLUGIN_EXPORT void clear_entities_ffi(void* const viewer); -FLUTTER_PLUGIN_EXPORT bool set_camera_ffi(void* const viewer, EntityId asset, const char *nodeName); -FLUTTER_PLUGIN_EXPORT void apply_weights_ffi( - void* const sceneManager, - EntityId asset, - const char *const entityName, - float *const weights, - int count - ); + FLUTTER_PLUGIN_EXPORT void create_filament_viewer_ffi( + void *const context, + void *const platform, + const char *uberArchivePath, + const ResourceLoaderWrapper *const loader, + void (*renderCallback)(void *const renderCallbackOwner), + void *const renderCallbackOwner, + void (*callback)(void* const viewer) + ); + FLUTTER_PLUGIN_EXPORT void create_swap_chain_ffi(void *const viewer, void *const surface, uint32_t width, uint32_t height, void (*onComplete)()); + FLUTTER_PLUGIN_EXPORT void destroy_swap_chain_ffi(void *const viewer, void (*onComplete)()); + FLUTTER_PLUGIN_EXPORT void create_render_target_ffi(void *const viewer, intptr_t nativeTextureId, uint32_t width, uint32_t height, void (*onComplete)()); + FLUTTER_PLUGIN_EXPORT void destroy_filament_viewer_ffi(void *const viewer); + FLUTTER_PLUGIN_EXPORT void render_ffi(void *const viewer); + FLUTTER_PLUGIN_EXPORT FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback); + FLUTTER_PLUGIN_EXPORT void set_rendering_ffi(void *const viewer, bool rendering); + FLUTTER_PLUGIN_EXPORT void set_frame_interval_ffi(float frameInterval); + FLUTTER_PLUGIN_EXPORT void update_viewport_and_camera_projection_ffi(void *const viewer, const uint32_t width, const uint32_t height, const float scaleFactor, void (*onComplete)()); + FLUTTER_PLUGIN_EXPORT void set_background_color_ffi(void *const viewer, const float r, const float g, const float b, const float a); + FLUTTER_PLUGIN_EXPORT void clear_background_image_ffi(void *const viewer); + FLUTTER_PLUGIN_EXPORT void set_background_image_ffi(void *const viewer, const char *path, bool fillHeight); + FLUTTER_PLUGIN_EXPORT void set_background_image_position_ffi(void *const viewer, float x, float y, bool clamp); + FLUTTER_PLUGIN_EXPORT void set_tone_mapping_ffi(void *const viewer, int toneMapping); + FLUTTER_PLUGIN_EXPORT void set_bloom_ffi(void *const viewer, float strength); + FLUTTER_PLUGIN_EXPORT void load_skybox_ffi(void *const viewer, const char *skyboxPath); + FLUTTER_PLUGIN_EXPORT void load_ibl_ffi(void *const viewer, const char *iblPath, float intensity); + FLUTTER_PLUGIN_EXPORT void remove_skybox_ffi(void *const viewer); + FLUTTER_PLUGIN_EXPORT void remove_ibl_ffi(void *const viewer); + FLUTTER_PLUGIN_EXPORT void add_light_ffi( + void *const viewer, + uint8_t type, + float colour, + float intensity, + float posX, + float posY, + float posZ, + float dirX, + float dirY, + float dirZ, + bool shadows, + void (*callback)(EntityId)); + FLUTTER_PLUGIN_EXPORT void remove_light_ffi(void *const viewer, EntityId entityId); + FLUTTER_PLUGIN_EXPORT void clear_lights_ffi(void *const viewer); + FLUTTER_PLUGIN_EXPORT void load_glb_ffi(void *const sceneManager, const char *assetPath, int numInstances, void (*callback)(EntityId)); + FLUTTER_PLUGIN_EXPORT void load_glb_from_buffer_ffi(void *const sceneManager, const void *const data, size_t length, int numInstances, void (*callback)(EntityId)); + FLUTTER_PLUGIN_EXPORT void load_gltf_ffi(void *const sceneManager, const char *assetPath, const char *relativePath, void (*callback)(EntityId)); + FLUTTER_PLUGIN_EXPORT void create_instance_ffi(void *const sceneManager, EntityId entityId, void (*callback)(EntityId)); + FLUTTER_PLUGIN_EXPORT void remove_entity_ffi(void *const viewer, EntityId asset, void (*callback)()); + FLUTTER_PLUGIN_EXPORT void clear_entities_ffi(void *const viewer, void (*callback)()); + FLUTTER_PLUGIN_EXPORT void set_camera_ffi(void *const viewer, EntityId asset, const char *nodeName, void (*callback)(bool)); + FLUTTER_PLUGIN_EXPORT void apply_weights_ffi( + void *const sceneManager, + EntityId asset, + const char *const entityName, + float *const weights, + int count); -FLUTTER_PLUGIN_EXPORT void play_animation_ffi(void* const sceneManager, EntityId asset, int index, bool loop, bool reverse, bool replaceActive, float crossfade); -FLUTTER_PLUGIN_EXPORT void set_animation_frame_ffi(void* const sceneManager, EntityId asset, int animationIndex, int animationFrame); -FLUTTER_PLUGIN_EXPORT void stop_animation_ffi(void* const sceneManager, EntityId asset, int index); -FLUTTER_PLUGIN_EXPORT int get_animation_count_ffi(void* const sceneManager, EntityId asset); -FLUTTER_PLUGIN_EXPORT void get_animation_name_ffi(void* const sceneManager, EntityId asset, char *const outPtr, int index); -FLUTTER_PLUGIN_EXPORT void get_morph_target_name_ffi(void* const sceneManager, EntityId asset, const char *meshName, char *const outPtr, int index); -FLUTTER_PLUGIN_EXPORT int get_morph_target_name_count_ffi(void* const sceneManager, EntityId asset, const char *meshName); -FLUTTER_PLUGIN_EXPORT void set_morph_target_weights_ffi(void* const sceneManager, - EntityId asset, - const char *const entityName, - const float *const morphData, - int numWeights - ); -FLUTTER_PLUGIN_EXPORT bool set_morph_animation_ffi( - void *sceneManager, - EntityId asset, - const char *const entityName, - const float *const morphData, - const int *const morphIndices, - int numMorphTargets, - int numFrames, - float frameLengthInMs); -FLUTTER_PLUGIN_EXPORT bool set_bone_transform_ffi( - void *sceneManager, - EntityId asset, - const char *entityName, - const float *const transform, - const char *boneName); -FLUTTER_PLUGIN_EXPORT void add_bone_animation_ffi( - void *sceneManager, - EntityId asset, - const float *const frameData, - int numFrames, - const char *const boneName, - const char **const meshNames, - int numMeshTargets, - float frameLengthInMs, - bool isModelSpace); -FLUTTER_PLUGIN_EXPORT void set_post_processing_ffi(void* const viewer, bool enabled); -FLUTTER_PLUGIN_EXPORT void pick_ffi(void* const viewer, int x, int y, EntityId* entityId); -FLUTTER_PLUGIN_EXPORT void reset_to_rest_pose_ffi(void* const sceneManager, EntityId entityId); -FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi(); -FLUTTER_PLUGIN_EXPORT EntityId create_geometry_ffi(void* const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath); + FLUTTER_PLUGIN_EXPORT void play_animation_ffi(void *const sceneManager, EntityId asset, int index, bool loop, bool reverse, bool replaceActive, float crossfade); + FLUTTER_PLUGIN_EXPORT void set_animation_frame_ffi(void *const sceneManager, EntityId asset, int animationIndex, int animationFrame); + FLUTTER_PLUGIN_EXPORT void stop_animation_ffi(void *const sceneManager, EntityId asset, int index); + FLUTTER_PLUGIN_EXPORT void get_animation_count_ffi(void *const sceneManager, EntityId asset, void (*callback)(int)); + FLUTTER_PLUGIN_EXPORT void get_animation_name_ffi(void *const sceneManager, EntityId asset, char *const outPtr, int index, void (*callback)()); + FLUTTER_PLUGIN_EXPORT void get_morph_target_name_ffi(void *const sceneManager, EntityId asset, const char *meshName, char *const outPtr, int index, void (*callback)()); + FLUTTER_PLUGIN_EXPORT void get_morph_target_name_count_ffi(void *const sceneManager, EntityId asset, const char *meshName, void (*callback)(int32_t)); + FLUTTER_PLUGIN_EXPORT void set_morph_target_weights_ffi(void *const sceneManager, + EntityId asset, + const char *const entityName, + const float *const morphData, + int numWeights); + FLUTTER_PLUGIN_EXPORT void set_morph_animation_ffi( + void *sceneManager, + EntityId asset, + const char *const entityName, + const float *const morphData, + const int *const morphIndices, + int numMorphTargets, + int numFrames, + float frameLengthInMs, + void (*callback)(bool)); + FLUTTER_PLUGIN_EXPORT void set_bone_transform_ffi( + void *sceneManager, + EntityId asset, + const char *entityName, + const float *const transform, + const char *boneName, + void (*callback)(bool)); + FLUTTER_PLUGIN_EXPORT void add_bone_animation_ffi( + void *sceneManager, + EntityId asset, + const float *const frameData, + int numFrames, + const char *const boneName, + const char **const meshNames, + int numMeshTargets, + float frameLengthInMs, + bool isModelSpace); + FLUTTER_PLUGIN_EXPORT void set_post_processing_ffi(void *const viewer, bool enabled); + FLUTTER_PLUGIN_EXPORT void pick_ffi(void *const viewer, int x, int y, EntityId *entityId); + FLUTTER_PLUGIN_EXPORT void reset_to_rest_pose_ffi(void *const sceneManager, EntityId entityId); + FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi(); + FLUTTER_PLUGIN_EXPORT void create_geometry_ffi(void *const viewer, float *vertices, int numVertices, uint16_t *indices, int numIndices, const char *materialPath, void (*callback)(EntityId)); #ifdef __cplusplus } diff --git a/ios/include/SceneManager.hpp b/ios/include/SceneManager.hpp index 8281f861..52465eb3 100644 --- a/ios/include/SceneManager.hpp +++ b/ios/include/SceneManager.hpp @@ -44,9 +44,9 @@ namespace flutter_filament EntityId loadGltf(const char *uri, const char *relativeResourcePath); //// - /// @brief - /// @param uri - /// @param numInstances + /// @brief Load the GLB from the specified path, optionally creating multiple instances. + /// @param uri the path to the asset. Should be either asset:// (representing a Flutter asset), or file:// (representing a filesystem file). + /// @param numInstances the number of instances to create. /// @return an Entity representing the FilamentAsset associated with the loaded FilamentAsset. /// EntityId loadGlb(const char *uri, int numInstances); @@ -103,7 +103,7 @@ namespace flutter_filament /// @param meshName an array of mesh names under [entity] that should be animated /// @param numMeshTargets the number of meshes under [meshName] /// @param frameLengthInMs the length of each frame in ms - /// @return + /// @return true if the bone animation was successfully enqueued bool addBoneAnimation( EntityId entity, const float *const frameData, @@ -134,12 +134,11 @@ namespace flutter_filament /// @brief returns the number of instances of the FilamentAsset represented by the given entity. /// @param entityId - /// @return + /// @return the number of instances int getInstanceCount(EntityId entityId); /// @brief returns an array containing all instances of the FilamentAsset represented by the given entity. /// @param entityId - /// @return void getInstances(EntityId entityId, EntityId* out); friend class FilamentViewer; diff --git a/ios/src/FlutterFilamentApi.cpp b/ios/src/FlutterFilamentApi.cpp index 31882754..bf92d288 100644 --- a/ios/src/FlutterFilamentApi.cpp +++ b/ios/src/FlutterFilamentApi.cpp @@ -598,7 +598,7 @@ extern "C" } FLUTTER_PLUGIN_EXPORT EntityId create_geometry(void *const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath) { - return ((FilamentViewer*)viewer)->createGeometry(vertices, (size_t)numVertices, indices, numIndices, materialPath); + return ((FilamentViewer*)viewer)->createGeometry(vertices, (uint32_t)numVertices, indices, numIndices, materialPath); } FLUTTER_PLUGIN_EXPORT EntityId find_child_entity_by_name(void *const sceneManager, const EntityId parent, const char* name) { diff --git a/ios/src/FlutterFilamentFFIApi.cpp b/ios/src/FlutterFilamentFFIApi.cpp index 020971d1..a380d348 100644 --- a/ios/src/FlutterFilamentFFIApi.cpp +++ b/ios/src/FlutterFilamentFFIApi.cpp @@ -64,10 +64,9 @@ public: } if (_rendering) { - auto frameStart = std::chrono::high_resolution_clock::now(); + // auto frameStart = std::chrono::high_resolution_clock::now(); doRender(); - auto frameEnd = std::chrono::high_resolution_clock::now(); - // Log("Took %f milliseconds for render", float(std::chrono::duration_cast(frameEnd - frameStart).count())); + // auto frameEnd = std::chrono::high_resolution_clock::now(); } elapsed = float(std::chrono::duration_cast(now - last).count()); @@ -98,10 +97,12 @@ public: _t->join(); } - void *const createViewer(void *const context, void *const platform, + void createViewer(void *const context, void *const platform, const char *uberArchivePath, const ResourceLoaderWrapper *const loader, - void (*renderCallback)(void *), void *const owner) { + void (*renderCallback)(void *), + void *const owner, + void (*callback)(void* const) ) { _renderCallback = renderCallback; _renderCallbackOwner = owner; std::packaged_task lambda([=]() mutable { @@ -117,34 +118,30 @@ public: #else _viewer = new FilamentViewer(context, loader, platform, uberArchivePath); #endif + callback(_viewer); return _viewer; }); auto fut = add_task(lambda); - fut.wait(); - _viewer = fut.get(); - return (void *const)_viewer; } void destroyViewer() { - std::packaged_task lambda([&]() mutable { + std::packaged_task lambda([=]() mutable { _rendering = false; destroy_filament_viewer(_viewer); _viewer = nullptr; }); auto fut = add_task(lambda); - fut.wait(); } void setRendering(bool rendering) { std::packaged_task lambda( - [&]() mutable { this->_rendering = rendering; }); + [=]() mutable { this->_rendering = rendering; }); auto fut = add_task(lambda); - fut.wait(); } void doRender() { - auto now = std::chrono::high_resolution_clock::now(); - auto nanos = std::chrono::duration_cast(now.time_since_epoch()).count(); + // auto now = std::chrono::high_resolution_clock::now(); + // auto nanos = std::chrono::duration_cast(now.time_since_epoch()).count(); render(_viewer, 0, nullptr, nullptr, nullptr); _lastRenderTime = std::chrono::high_resolution_clock::now(); if(_renderCallback) { @@ -189,16 +186,17 @@ extern "C" { static RenderLoop *_rl; -FLUTTER_PLUGIN_EXPORT void *const create_filament_viewer_ffi( +FLUTTER_PLUGIN_EXPORT void create_filament_viewer_ffi( void *const context, void *const platform, const char *uberArchivePath, const ResourceLoaderWrapper *const loader, void (*renderCallback)(void *const renderCallbackOwner), - void *const renderCallbackOwner) { + void *const renderCallbackOwner, + void (*callback)(void* const) ) { if (!_rl) { _rl = new RenderLoop(); } - return _rl->createViewer(context, platform, uberArchivePath, loader, - renderCallback, renderCallbackOwner); + _rl->createViewer(context, platform, uberArchivePath, loader, + renderCallback, renderCallbackOwner, callback); } FLUTTER_PLUGIN_EXPORT void destroy_filament_viewer_ffi(void *const viewer) { @@ -208,44 +206,49 @@ FLUTTER_PLUGIN_EXPORT void destroy_filament_viewer_ffi(void *const viewer) { FLUTTER_PLUGIN_EXPORT void create_swap_chain_ffi(void *const viewer, void *const surface, uint32_t width, - uint32_t height) { - Log("Creating swapchain %dx%d", width, height); + uint32_t height, + void (*onComplete)()) { + Log("Creating swapchain %dx%d with viewer %d", width, height, viewer); std::packaged_task lambda( - [&]() mutable { create_swap_chain(viewer, surface, width, height); }); + [=]() mutable { + create_swap_chain(viewer, surface, width, height); + onComplete(); + }); auto fut = _rl->add_task(lambda); - fut.wait(); } -FLUTTER_PLUGIN_EXPORT void destroy_swap_chain_ffi(void *const viewer) { +FLUTTER_PLUGIN_EXPORT void destroy_swap_chain_ffi(void *const viewer, void (*onComplete)()) { Log("Destroying swapchain"); std::packaged_task lambda( - [&]() mutable { + [=]() mutable { destroy_swap_chain(viewer); + onComplete(); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void create_render_target_ffi(void *const viewer, intptr_t nativeTextureId, uint32_t width, - uint32_t height) { - std::packaged_task lambda([&]() mutable { + uint32_t height, + void (*onComplete)()) { + std::packaged_task lambda([=]() mutable { create_render_target(viewer, nativeTextureId, width, height); + onComplete(); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void update_viewport_and_camera_projection_ffi( void *const viewer, const uint32_t width, const uint32_t height, - const float scaleFactor) { + const float scaleFactor, + void (*onComplete)()) { Log("Update viewport %dx%d", width, height); - std::packaged_task lambda([&]() mutable { + std::packaged_task lambda([=]() mutable { update_viewport_and_camera_projection(viewer, width, height, scaleFactor); + onComplete(); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void set_rendering_ffi(void *const viewer, @@ -268,173 +271,173 @@ set_frame_interval_ffi(float frameIntervalInMilliseconds) { } FLUTTER_PLUGIN_EXPORT void render_ffi(void *const viewer) { - std::packaged_task lambda([&]() mutable { _rl->doRender(); }); + std::packaged_task lambda([=]() mutable { _rl->doRender(); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void set_background_color_ffi(void *const viewer, const float r, const float g, const float b, const float a) { std::packaged_task lambda( - [&]() mutable { set_background_color(viewer, r, g, b, a); }); + [=]() mutable { set_background_color(viewer, r, g, b, a); }); auto fut = _rl->add_task(lambda); - fut.wait(); } -FLUTTER_PLUGIN_EXPORT EntityId load_gltf_ffi(void *const sceneManager, +FLUTTER_PLUGIN_EXPORT void load_gltf_ffi(void *const sceneManager, const char *path, - const char *relativeResourcePath) { - std::packaged_task lambda([&]() mutable { - return load_gltf(sceneManager, path, relativeResourcePath); + const char *relativeResourcePath, + void (*callback)(EntityId)) { + std::packaged_task lambda([=]() mutable { + auto entity = load_gltf(sceneManager, path, relativeResourcePath); + callback(entity); + return entity; }); auto fut = _rl->add_task(lambda); - fut.wait(); - return fut.get(); } -FLUTTER_PLUGIN_EXPORT EntityId load_glb_ffi(void *const sceneManager, - const char *path, int numInstances) { +FLUTTER_PLUGIN_EXPORT void load_glb_ffi(void *const sceneManager, + const char *path, int numInstances, void (*callback)(EntityId)) { std::packaged_task lambda( - [&]() mutable { return load_glb(sceneManager, path, numInstances); }); + [=]() mutable { + auto entity = load_glb(sceneManager, path, numInstances); + callback(entity); + return entity; + }); auto fut = _rl->add_task(lambda); - fut.wait(); - return fut.get(); } -FLUTTER_PLUGIN_EXPORT EntityId load_glb_from_buffer_ffi(void *const sceneManager, - const void *const data, size_t length, int numInstances) { +FLUTTER_PLUGIN_EXPORT void load_glb_from_buffer_ffi(void *const sceneManager, + const void *const data, size_t length, int numInstances, void (*callback)(EntityId)) { std::packaged_task lambda( - [&]() mutable { return load_glb_from_buffer(sceneManager, data, length); }); + [=]() mutable { + auto entity = load_glb_from_buffer(sceneManager, data, length); + callback(entity); + return entity; + }); auto fut = _rl->add_task(lambda); - fut.wait(); - return fut.get(); } FLUTTER_PLUGIN_EXPORT void clear_background_image_ffi(void *const viewer) { - std::packaged_task lambda([&] { clear_background_image(viewer); }); + std::packaged_task lambda([=] { clear_background_image(viewer); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void set_background_image_ffi(void *const viewer, const char *path, bool fillHeight) { std::packaged_task lambda( - [&] { set_background_image(viewer, path, fillHeight); }); + [=] { set_background_image(viewer, path, fillHeight); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void set_background_image_position_ffi(void *const viewer, float x, float y, bool clamp) { std::packaged_task lambda( - [&] { set_background_image_position(viewer, x, y, clamp); }); + [=] { set_background_image_position(viewer, x, y, clamp); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void set_tone_mapping_ffi(void *const viewer, int toneMapping) { std::packaged_task lambda( - [&] { set_tone_mapping(viewer, toneMapping); }); + [=] { set_tone_mapping(viewer, toneMapping); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void set_bloom_ffi(void *const viewer, float strength) { - std::packaged_task lambda([&] { set_bloom(viewer, strength); }); + std::packaged_task lambda([=] { set_bloom(viewer, strength); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void load_skybox_ffi(void *const viewer, const char *skyboxPath) { - std::packaged_task lambda([&] { load_skybox(viewer, skyboxPath); }); + std::packaged_task lambda([=] { load_skybox(viewer, skyboxPath); }); auto fut = _rl->add_task(lambda); - fut.wait(); } + FLUTTER_PLUGIN_EXPORT void load_ibl_ffi(void *const viewer, const char *iblPath, float intensity) { std::packaged_task lambda( - [&] { load_ibl(viewer, iblPath, intensity); }); + [=] { load_ibl(viewer, iblPath, intensity); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void remove_skybox_ffi(void *const viewer) { - std::packaged_task lambda([&] { remove_skybox(viewer); }); + std::packaged_task lambda([=] { remove_skybox(viewer); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void remove_ibl_ffi(void *const viewer) { - std::packaged_task lambda([&] { remove_ibl(viewer); }); + std::packaged_task lambda([=] { remove_ibl(viewer); }); auto fut = _rl->add_task(lambda); - fut.wait(); } -EntityId add_light_ffi(void *const viewer, uint8_t type, float colour, +void add_light_ffi(void *const viewer, uint8_t type, float colour, float intensity, float posX, float posY, float posZ, - float dirX, float dirY, float dirZ, bool shadows) { - std::packaged_task lambda([&] { - return add_light(viewer, type, colour, intensity, posX, posY, posZ, dirX, + float dirX, float dirY, float dirZ, bool shadows, void (*callback)(EntityId)) { + std::packaged_task lambda([=] { + auto entity = add_light(viewer, type, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows); + callback(entity); + return entity; }); auto fut = _rl->add_task(lambda); - fut.wait(); - return fut.get(); } FLUTTER_PLUGIN_EXPORT void remove_light_ffi(void *const viewer, EntityId entityId) { - std::packaged_task lambda([&] { remove_light(viewer, entityId); }); + std::packaged_task lambda([=] { remove_light(viewer, entityId); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void clear_lights_ffi(void *const viewer) { - std::packaged_task lambda([&] { clear_lights(viewer); }); + std::packaged_task lambda([=] { clear_lights(viewer); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void remove_entity_ffi(void *const viewer, - EntityId asset) { - std::packaged_task lambda([&] { remove_entity(viewer, asset); }); + EntityId asset, void (*callback)()) { + std::packaged_task lambda([=] { + remove_entity(viewer, asset); + callback(); + }); auto fut = _rl->add_task(lambda); - fut.wait(); -} -FLUTTER_PLUGIN_EXPORT void clear_entities_ffi(void *const viewer) { - std::packaged_task lambda([&] { clear_entities(viewer); }); - auto fut = _rl->add_task(lambda); - fut.wait(); } -FLUTTER_PLUGIN_EXPORT bool set_camera_ffi(void *const viewer, EntityId asset, - const char *nodeName) { - std::packaged_task lambda( - [&] { return set_camera(viewer, asset, nodeName); }); +FLUTTER_PLUGIN_EXPORT void clear_entities_ffi(void *const viewer, void (*callback)()) { + std::packaged_task lambda([=] { + clear_entities(viewer); + callback(); + }); + auto fut = _rl->add_task(lambda); +} + +FLUTTER_PLUGIN_EXPORT void set_camera_ffi(void *const viewer, EntityId asset, + const char *nodeName, void (*callback)(bool)) { + std::packaged_task lambda( + [=] { + auto success = set_camera(viewer, asset, nodeName); + callback(success); + return success; + }); auto fut = _rl->add_task(lambda); - fut.wait(); - return fut.get(); } FLUTTER_PLUGIN_EXPORT void get_morph_target_name_ffi(void *sceneManager, EntityId asset, - const char *meshName, char *const outPtr, int index) { - std::packaged_task lambda([&] { + const char *meshName, char *const outPtr, int index, void (*callback)()) { + std::packaged_task lambda([=] { get_morph_target_name(sceneManager, asset, meshName, outPtr, index); + callback(); }); auto fut = _rl->add_task(lambda); - fut.wait(); } -FLUTTER_PLUGIN_EXPORT int +FLUTTER_PLUGIN_EXPORT void get_morph_target_name_count_ffi(void *sceneManager, EntityId asset, - const char *meshName) { - std::packaged_task lambda([&] { - return get_morph_target_name_count(sceneManager, asset, meshName); + const char *meshName, void (*callback)(int)) { + std::packaged_task lambda([=] { + auto count = get_morph_target_name_count(sceneManager, asset, meshName); + callback(count); + return count; }); auto fut = _rl->add_task(lambda); - fut.wait(); - return fut.get(); } @@ -444,73 +447,77 @@ FLUTTER_PLUGIN_EXPORT void play_animation_ffi(void *const sceneManager, bool loop, bool reverse, bool replaceActive, float crossfade) { - std::packaged_task lambda([&] { + std::packaged_task lambda([=] { play_animation(sceneManager, asset, index, loop, reverse, replaceActive, crossfade); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void set_animation_frame_ffi(void *const sceneManager, EntityId asset, int animationIndex, int animationFrame) { - std::packaged_task lambda([&] { + std::packaged_task lambda([=] { set_animation_frame(sceneManager, asset, animationIndex, animationFrame); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void stop_animation_ffi(void *const sceneManager, EntityId asset, int index) { std::packaged_task lambda( - [&] { stop_animation(sceneManager, asset, index); }); + [=] { stop_animation(sceneManager, asset, index); }); auto fut = _rl->add_task(lambda); - fut.wait(); } -FLUTTER_PLUGIN_EXPORT int get_animation_count_ffi(void *const sceneManager, - EntityId asset) { +FLUTTER_PLUGIN_EXPORT void get_animation_count_ffi(void *const sceneManager, + EntityId asset, + void (*callback)(int)) { std::packaged_task lambda( - [&] { return get_animation_count(sceneManager, asset); }); + [=] { + auto count = get_animation_count(sceneManager, asset); + callback(count); + return count; + }); auto fut = _rl->add_task(lambda); - fut.wait(); - return fut.get(); } + FLUTTER_PLUGIN_EXPORT void get_animation_name_ffi(void *const sceneManager, EntityId asset, char *const outPtr, - int index) { + int index, + void (*callback)()) { std::packaged_task lambda( - [&] { get_animation_name(sceneManager, asset, outPtr, index); }); + [=] { + get_animation_name(sceneManager, asset, outPtr, index); + callback(); + }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void set_post_processing_ffi(void *const viewer, bool enabled) { std::packaged_task lambda( - [&] { set_post_processing(viewer, enabled); }); + [=] { set_post_processing(viewer, enabled); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void pick_ffi(void *const viewer, int x, int y, EntityId *entityId) { - std::packaged_task lambda([&] { pick(viewer, x, y, entityId); }); + std::packaged_task lambda([=] { pick(viewer, x, y, entityId); }); auto fut = _rl->add_task(lambda); - fut.wait(); } -FLUTTER_PLUGIN_EXPORT const char * -get_name_for_entity_ffi(void *const sceneManager, const EntityId entityId) { +FLUTTER_PLUGIN_EXPORT void +get_name_for_entity_ffi(void *const sceneManager, const EntityId entityId, void (*callback)(const char*)) { std::packaged_task lambda( - [&] { return get_name_for_entity(sceneManager, entityId); }); + [=] { + auto name = get_name_for_entity(sceneManager, entityId); + callback(name); + return name; + }); auto fut = _rl->add_task(lambda); - fut.wait(); - return fut.get(); } void set_morph_target_weights_ffi(void *const sceneManager, @@ -519,12 +526,13 @@ void set_morph_target_weights_ffi(void *const sceneManager, const float *const morphData, int numWeights) { std::packaged_task lambda( - [&] { return set_morph_target_weights(sceneManager, asset, entityName, morphData, numWeights); }); + [=] { + set_morph_target_weights(sceneManager, asset, entityName, morphData, numWeights); + }); auto fut = _rl->add_task(lambda); - fut.wait(); } -bool set_morph_animation_ffi( +void set_morph_animation_ffi( void *sceneManager, EntityId asset, const char *const entityName, @@ -532,35 +540,38 @@ bool set_morph_animation_ffi( const int *const morphIndices, int numMorphTargets, int numFrames, - float frameLengthInMs) { + float frameLengthInMs, + void (*callback)(bool)) { std::packaged_task lambda( - [&] { - return set_morph_animation(sceneManager, asset, entityName, morphData, morphIndices, numMorphTargets, numFrames, frameLengthInMs); + [=] { + auto success = set_morph_animation(sceneManager, asset, entityName, morphData, morphIndices, numMorphTargets, numFrames, frameLengthInMs); + callback(success); + return success; }); auto fut = _rl->add_task(lambda); - fut.wait(); - return fut.get(); } -FLUTTER_PLUGIN_EXPORT bool set_bone_transform_ffi( +FLUTTER_PLUGIN_EXPORT void set_bone_transform_ffi( void *sceneManager, EntityId asset, const char *entityName, const float *const transform, - const char *boneName) { + const char *boneName, + void (*callback)(bool)) { std::packaged_task lambda( - [&] { return set_bone_transform(sceneManager, asset, entityName, transform, boneName); }); + [=] { + auto success = set_bone_transform(sceneManager, asset, entityName, transform, boneName); + callback(success); + return success; + }); auto fut = _rl->add_task(lambda); - fut.wait(); - return fut.get(); } FLUTTER_PLUGIN_EXPORT void reset_to_rest_pose_ffi(void* const sceneManager, EntityId entityId) { std::packaged_task lambda( - [&] { return reset_to_rest_pose(sceneManager, entityId); }); + [=] { return reset_to_rest_pose(sceneManager, entityId); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void add_bone_animation_ffi( @@ -579,19 +590,18 @@ FLUTTER_PLUGIN_EXPORT void add_bone_animation_ffi( add_bone_animation(sceneManager, asset, frameData, numFrames, boneName, meshNames, numMeshTargets, frameLengthInMs, isModelSpace); }); auto fut = _rl->add_task(lambda); - fut.wait(); } FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi() { Log("Dummy called"); } -FLUTTER_PLUGIN_EXPORT EntityId create_geometry_ffi(void* const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath) { +FLUTTER_PLUGIN_EXPORT void create_geometry_ffi(void* const viewer, float* vertices, int numVertices, uint16_t* indices, int numIndices, const char* materialPath, void (*callback)(EntityId) ) { std::packaged_task lambda( [=] { - return create_geometry(viewer, vertices, numVertices, indices, numIndices, materialPath); + auto entity = create_geometry(viewer, vertices, numVertices, indices, numIndices, materialPath); + callback(entity); + return entity; }); auto fut = _rl->add_task(lambda); - fut.wait(); - return fut.get(); } } diff --git a/ios/src/SceneManager.cpp b/ios/src/SceneManager.cpp index 675ce9e1..01f312c7 100644 --- a/ios/src/SceneManager.cpp +++ b/ios/src/SceneManager.cpp @@ -1208,6 +1208,20 @@ namespace flutter_filament _collisionComponentManager->elementAt<2>(collisionInstance) = affectsTransform; } + void SceneManager::removeCollisionComponent(EntityId entityId) { + std::lock_guard lock(_mutex); + const auto *instance = getInstanceByEntityId(entityId); + if(!instance) { + auto asset = getAssetByEntityId(entityId); + if(!asset) { + return; + } else { + instance = asset->getInstance(); + } + } + _collisionComponentManager->removeComponent(instance->getRoot()); + } + void SceneManager::testCollisions(EntityId entityId) { const auto *instance = getInstanceByEntityId(entityId); if(!instance) { diff --git a/ios/src/StreamBufferAdapter.cpp b/ios/src/StreamBufferAdapter.cpp index fcbc6cd7..7ba83a71 100644 --- a/ios/src/StreamBufferAdapter.cpp +++ b/ios/src/StreamBufferAdapter.cpp @@ -68,7 +68,7 @@ std::streampos StreamBufferAdapter::seekoff(std::streamoff off, std::ios_base::s if(way == std::ios_base::beg) { setg(eback(), eback()+off, egptr()); } else if(way == std::ios_base::cur) { - gbump(off); + gbump((int)off); } else { setg(eback(), egptr()-off, egptr()); } diff --git a/lib/filament_controller_ffi.dart b/lib/filament_controller_ffi.dart index f1a6df5b..5a5facc8 100644 --- a/lib/filament_controller_ffi.dart +++ b/lib/filament_controller_ffi.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'dart:typed_data'; import 'dart:ui' as ui; import 'dart:developer' as dev; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:ffi/ffi.dart'; import 'package:flutter/widgets.dart'; @@ -140,7 +141,7 @@ class FilamentControllerFFI extends FilamentController { Future setFrameRate(int framerate) async { final interval = 1000.0 / framerate; set_frame_interval_ffi(interval); - dev.log("Set frame interval to $interval"); + print("Set frame interval to $interval"); } @override @@ -182,7 +183,82 @@ class FilamentControllerFFI extends FilamentController { await _channel.invokeMethod( "destroyTexture", textureDetails.value!.textureId); } - dev.log("Texture destroyed"); + print("Texture destroyed"); + } + + Future _withVoidCallback( + Function(Pointer>) func) async { + final completer = Completer(); + // ignore: prefer_function_declarations_over_variables + void Function() callback = () { + completer.complete(); + }; + final nativeCallable = NativeCallable.listener(callback); + func.call(nativeCallable.nativeFunction); + await completer.future; + nativeCallable.close(); + } + + Future> _withVoidPointerCallback( + Function(Pointer)>>) + func) async { + final completer = Completer>(); + // ignore: prefer_function_declarations_over_variables + void Function(Pointer) callback = (Pointer ptr) { + completer.complete(ptr); + }; + final nativeCallable = + NativeCallable)>.listener(callback); + func.call(nativeCallable.nativeFunction); + await completer.future; + nativeCallable.close(); + return completer.future; + } + + Future _withBoolCallback( + Function(Pointer>) func) async { + final completer = Completer(); + // ignore: prefer_function_declarations_over_variables + void Function(bool) callback = (bool result) { + completer.complete(result); + }; + final nativeCallable = + NativeCallable.listener(callback); + func.call(nativeCallable.nativeFunction); + await completer.future; + nativeCallable.close(); + return completer.future; + } + + Future _withIntCallback( + Function(Pointer>) func) async { + final completer = Completer(); + // ignore: prefer_function_declarations_over_variables + void Function(int) callback = (int result) { + completer.complete(result); + }; + final nativeCallable = + NativeCallable.listener(callback); + func.call(nativeCallable.nativeFunction); + await completer.future; + nativeCallable.close(); + return completer.future; + } + + Future _withCharPtrCallback( + Function(Pointer)>>) + func) async { + final completer = Completer(); + // ignore: prefer_function_declarations_over_variables + void Function(Pointer) callback = (Pointer result) { + completer.complete(result.cast().toDartString()); + }; + final nativeCallable = + NativeCallable)>.listener(callback); + func.call(nativeCallable.nativeFunction); + await completer.future; + nativeCallable.close(); + return completer.future; } bool _creating = false; @@ -190,6 +266,7 @@ class FilamentControllerFFI extends FilamentController { /// /// Called by `FilamentWidget`. You do not need to call this yourself. /// + /// @override Future createViewer() async { if (_creating) { @@ -234,43 +311,60 @@ class FilamentControllerFFI extends FilamentController { var renderingSurface = await _createRenderingSurface(); - dev.log("Got rendering surface"); + print("Got rendering surface"); final uberarchivePtr = uberArchivePath?.toNativeUtf8().cast() ?? nullptr; - _viewer = create_filament_viewer_ffi( - Pointer.fromAddress(renderingSurface.sharedContext), - _driver, - uberarchivePtr, - loader, - renderCallback, - renderCallbackOwner); + _viewer = await _withVoidPointerCallback((callback) => + create_filament_viewer_ffi( + Pointer.fromAddress(renderingSurface.sharedContext), + _driver, + uberarchivePtr, + loader, + renderCallback, + renderCallbackOwner, + callback)); + allocator.free(uberarchivePtr); - dev.log("Created viewer"); + + print("Created viewer ${_viewer!.address}"); if (_viewer!.address == 0) { throw Exception("Failed to create viewer. Check logs for details"); } _sceneManager = get_scene_manager(_viewer!); - create_swap_chain_ffi(_viewer!, renderingSurface.surface, - _rect.value!.width.toInt(), _rect.value!.height.toInt()); - dev.log("Created swap chain"); + await _withVoidCallback((callback) { + create_swap_chain_ffi(_viewer!, renderingSurface.surface, + _rect.value!.width.toInt(), _rect.value!.height.toInt(), callback); + }); + + print("Created swap chain"); if (renderingSurface.textureHandle != 0) { - dev.log( + print( "Creating render target from native texture ${renderingSurface.textureHandle}"); - create_render_target_ffi(_viewer!, renderingSurface.textureHandle, - _rect.value!.width.toInt(), _rect.value!.height.toInt()); + await _withVoidCallback((callback) => create_render_target_ffi( + _viewer!, + renderingSurface.textureHandle, + _rect.value!.width.toInt(), + _rect.value!.height.toInt(), + callback)); } textureDetails.value = TextureDetails( textureId: renderingSurface.flutterTextureId, width: _rect.value!.width.toInt(), height: _rect.value!.height.toInt()); - dev.log("texture details ${textureDetails.value}"); - update_viewport_and_camera_projection_ffi( - _viewer!, _rect.value!.width.toInt(), _rect.value!.height.toInt(), 1.0); + print("texture details ${textureDetails.value}"); + await _withVoidCallback((callback) { + update_viewport_and_camera_projection_ffi( + _viewer!, + _rect.value!.width.toInt(), + _rect.value!.height.toInt(), + 1.0, + callback); + }); hasViewer.value = true; _creating = false; } @@ -365,7 +459,8 @@ class FilamentControllerFFI extends FilamentController { set_rendering_ffi(_viewer!, false); if (!_usesBackingWindow) { - destroy_swap_chain_ffi(_viewer!); + await _withVoidCallback( + (callback) => destroy_swap_chain_ffi(_viewer!, callback)); } if (requiresTextureWidget) { @@ -374,7 +469,7 @@ class FilamentControllerFFI extends FilamentController { "destroyTexture", textureDetails.value!.textureId); } } else if (Platform.isWindows) { - dev.log("Resizing window with rect ${_rect.value}"); + print("Resizing window with rect ${_rect.value}"); await _channel.invokeMethod("resizeWindow", [ _rect.value!.width, _rect.value!.height, @@ -390,15 +485,23 @@ class FilamentControllerFFI extends FilamentController { } if (!_usesBackingWindow) { - create_swap_chain_ffi(_viewer!, renderingSurface.surface, - _rect.value!.width.toInt(), _rect.value!.height.toInt()); + _withVoidCallback((callback) => create_swap_chain_ffi( + _viewer!, + renderingSurface.surface, + _rect.value!.width.toInt(), + _rect.value!.height.toInt(), + callback)); } if (renderingSurface.textureHandle != 0) { - dev.log( + print( "Creating render target from native texture ${renderingSurface.textureHandle}"); - create_render_target_ffi(_viewer!, renderingSurface.textureHandle, - _rect.value!.width.toInt(), _rect.value!.height.toInt()); + _withVoidCallback((callback) => create_render_target_ffi( + _viewer!, + renderingSurface.textureHandle, + _rect.value!.width.toInt(), + _rect.value!.height.toInt(), + callback)); } textureDetails.value = TextureDetails( @@ -406,8 +509,12 @@ class FilamentControllerFFI extends FilamentController { width: _rect.value!.width.toInt(), height: _rect.value!.height.toInt()); - update_viewport_and_camera_projection_ffi(_viewer!, - _rect.value!.width.toInt(), _rect.value!.height.toInt(), 1.0); + _withVoidCallback((callback) => update_viewport_and_camera_projection_ffi( + _viewer!, + _rect.value!.width.toInt(), + _rect.value!.height.toInt(), + 1.0, + callback)); await setRendering(_rendering); } finally { @@ -518,8 +625,19 @@ class FilamentControllerFFI extends FilamentController { if (_viewer == null) { throw Exception("No viewer available, ignoring"); } - var entity = add_light_ffi(_viewer!, type, colour, intensity, posX, posY, - posZ, dirX, dirY, dirZ, castShadows); + var entity = await _withIntCallback((callback) => add_light_ffi( + _viewer!, + type, + colour, + intensity, + posX, + posY, + posZ, + dirX, + dirY, + dirZ, + castShadows, + callback)); _onLoadController.sink.add(entity); _lights.add(entity); return entity; @@ -572,8 +690,8 @@ class FilamentControllerFFI extends FilamentController { data = (ptr.cast(), asset.lengthInBytes); } - var entity = load_glb_from_buffer_ffi( - _sceneManager!, data.$1, data.$2, numInstances); + var entity = await _withIntCallback((callback) => load_glb_from_buffer_ffi( + _sceneManager!, data.$1, data.$2, numInstances, callback)); if (!cache) { allocator.free(data.$1); } else { @@ -587,7 +705,8 @@ class FilamentControllerFFI extends FilamentController { @override Future createInstance(FilamentEntity entity) async { - var created = create_instance(_sceneManager!, entity); + var created = await _withIntCallback( + (callback) => create_instance(_sceneManager!, entity)); if (created == _FILAMENT_ASSET_ERROR) { throw Exception("Failed to create instance"); } @@ -630,7 +749,8 @@ class FilamentControllerFFI extends FilamentController { throw Exception("Not yet implemented"); } final pathPtr = path.toNativeUtf8().cast(); - var entity = load_glb_ffi(_sceneManager!, pathPtr, numInstances); + var entity = await _withIntCallback((callback) => + load_glb_ffi(_sceneManager!, pathPtr, numInstances, callback)); allocator.free(pathPtr); if (entity == _FILAMENT_ASSET_ERROR) { throw Exception("An error occurred loading the asset at $path"); @@ -653,8 +773,8 @@ class FilamentControllerFFI extends FilamentController { final pathPtr = path.toNativeUtf8().cast(); final relativeResourcePathPtr = relativeResourcePath.toNativeUtf8().cast(); - var entity = - load_gltf_ffi(_sceneManager!, pathPtr, relativeResourcePathPtr); + var entity = await _withIntCallback((callback) => load_gltf_ffi( + _sceneManager!, pathPtr, relativeResourcePathPtr, callback)); allocator.free(pathPtr); allocator.free(relativeResourcePathPtr); if (entity == _FILAMENT_ASSET_ERROR) { @@ -739,8 +859,9 @@ class FilamentControllerFFI extends FilamentController { } var names = []; var meshNamePtr = meshName.toNativeUtf8().cast(); - var count = - get_morph_target_name_count_ffi(_sceneManager!, entity, meshNamePtr); + var count = await _withIntCallback((callback) => + get_morph_target_name_count_ffi( + _sceneManager!, entity, meshNamePtr, callback)); var outPtr = allocator(255); for (int i = 0; i < count; i++) { get_morph_target_name(_sceneManager!, entity, meshNamePtr, outPtr, i); @@ -760,9 +881,11 @@ class FilamentControllerFFI extends FilamentController { var names = []; var outPtr = allocator(255); for (int i = 0; i < animationCount; i++) { - get_animation_name_ffi(_sceneManager!, entity, outPtr, i); + await _withVoidCallback((callback) => + get_animation_name_ffi(_sceneManager!, entity, outPtr, i, callback)); names.add(outPtr.cast().toDartString()); } + allocator.free(outPtr); return names; } @@ -896,7 +1019,8 @@ class FilamentControllerFFI extends FilamentController { throw Exception("No viewer available, ignoring"); } _entities.remove(entity); - remove_entity_ffi(_viewer!, entity); + await _withVoidCallback( + (callback) => remove_entity_ffi(_viewer!, entity, callback)); _onUnloadController.add(entity); } @@ -905,7 +1029,8 @@ class FilamentControllerFFI extends FilamentController { if (_viewer == null) { throw Exception("No viewer available, ignoring"); } - clear_entities_ffi(_viewer!); + await _withVoidCallback( + (callback) => clear_entities_ffi(_viewer!, callback)); for (final entity in _entities) { _onUnloadController.add(entity); @@ -1537,8 +1662,14 @@ class FilamentControllerFFI extends FilamentController { indicesPtr.elementAt(i).value = indices[i]; } - var entity = create_geometry_ffi(_viewer!, vertexPtr, vertices.length, - indicesPtr, indices.length, materialPathPtr.cast()); + var entity = await _withIntCallback((callback) => create_geometry_ffi( + _viewer!, + vertexPtr, + vertices.length, + indicesPtr, + indices.length, + materialPathPtr.cast(), + callback)); if (entity == _FILAMENT_ASSET_ERROR) { throw Exception("Failed to create geometry"); } diff --git a/lib/generated_bindings.dart b/lib/generated_bindings.dart index bdc9b2c0..d4d2529f 100644 --- a/lib/generated_bindings.dart +++ b/lib/generated_bindings.dart @@ -984,7 +984,10 @@ external void test_collisions( ffi.NativeFunction< ffi.Void Function( ffi.Pointer renderCallbackOwner)>>, - ffi.Pointer)>( + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer viewer)>>)>( symbol: 'create_filament_viewer_ffi', assetId: 'flutter_filament_plugin') external ffi.Pointer create_filament_viewer_ffi( ffi.Pointer context, @@ -996,34 +999,46 @@ external ffi.Pointer create_filament_viewer_ffi( ffi.Void Function(ffi.Pointer renderCallbackOwner)>> renderCallback, ffi.Pointer renderCallbackOwner, + ffi.Pointer< + ffi.NativeFunction viewer)>> + callback, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.Uint32, ffi.Uint32)>( + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Uint32, + ffi.Pointer>)>( symbol: 'create_swap_chain_ffi', assetId: 'flutter_filament_plugin') external void create_swap_chain_ffi( ffi.Pointer viewer, ffi.Pointer surface, int width, int height, -); - -@ffi.Native)>( - symbol: 'destroy_swap_chain_ffi', assetId: 'flutter_filament_plugin') -external void destroy_swap_chain_ffi( - ffi.Pointer viewer, + ffi.Pointer> onComplete, ); @ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.IntPtr, ffi.Uint32, ffi.Uint32)>( + ffi.Void Function(ffi.Pointer, + ffi.Pointer>)>( + symbol: 'destroy_swap_chain_ffi', assetId: 'flutter_filament_plugin') +external void destroy_swap_chain_ffi( + ffi.Pointer viewer, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.IntPtr, ffi.Uint32, + ffi.Uint32, ffi.Pointer>)>( symbol: 'create_render_target_ffi', assetId: 'flutter_filament_plugin') external void create_render_target_ffi( ffi.Pointer viewer, int nativeTextureId, int width, int height, + ffi.Pointer> onComplete, ); @ffi.Native)>( @@ -1059,8 +1074,8 @@ external void set_frame_interval_ffi( ); @ffi.Native< - ffi.Void Function( - ffi.Pointer, ffi.Uint32, ffi.Uint32, ffi.Float)>( + ffi.Void Function(ffi.Pointer, ffi.Uint32, ffi.Uint32, + ffi.Float, ffi.Pointer>)>( symbol: 'update_viewport_and_camera_projection_ffi', assetId: 'flutter_filament_plugin') external void update_viewport_and_camera_projection_ffi( @@ -1068,6 +1083,7 @@ external void update_viewport_and_camera_projection_ffi( int width, int height, double scaleFactor, + ffi.Pointer> onComplete, ); @ffi.Native< @@ -1153,19 +1169,21 @@ external void remove_ibl_ffi( ); @ffi.Native< - EntityId Function( - ffi.Pointer, - ffi.Uint8, - ffi.Float, - ffi.Float, - ffi.Float, - ffi.Float, - ffi.Float, - ffi.Float, - ffi.Float, - ffi.Float, - ffi.Bool)>(symbol: 'add_light_ffi', assetId: 'flutter_filament_plugin') -external int add_light_ffi( + ffi.Void Function( + ffi.Pointer, + ffi.Uint8, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Float, + ffi.Bool, + ffi.Pointer>)>( + symbol: 'add_light_ffi', assetId: 'flutter_filament_plugin') +external void add_light_ffi( ffi.Pointer viewer, int type, double colour, @@ -1177,6 +1195,7 @@ external int add_light_ffi( double dirY, double dirZ, bool shadows, + ffi.Pointer> callback, ); @ffi.Native, EntityId)>( @@ -1193,63 +1212,87 @@ external void clear_lights_ffi( ); @ffi.Native< - EntityId Function(ffi.Pointer, ffi.Pointer, - ffi.Int)>(symbol: 'load_glb_ffi', assetId: 'flutter_filament_plugin') -external int load_glb_ffi( + ffi.Void Function(ffi.Pointer, ffi.Pointer, ffi.Int, + ffi.Pointer>)>( + symbol: 'load_glb_ffi', assetId: 'flutter_filament_plugin') +external void load_glb_ffi( ffi.Pointer sceneManager, ffi.Pointer assetPath, int numInstances, + ffi.Pointer> callback, ); @ffi.Native< - EntityId Function( - ffi.Pointer, ffi.Pointer, ffi.Size, ffi.Int)>( + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Int, + ffi.Pointer>)>( symbol: 'load_glb_from_buffer_ffi', assetId: 'flutter_filament_plugin') -external int load_glb_from_buffer_ffi( +external void load_glb_from_buffer_ffi( ffi.Pointer sceneManager, ffi.Pointer data, int length, int numInstances, + ffi.Pointer> callback, ); @ffi.Native< - EntityId Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>( + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer>)>( symbol: 'load_gltf_ffi', assetId: 'flutter_filament_plugin') -external int load_gltf_ffi( +external void load_gltf_ffi( ffi.Pointer sceneManager, ffi.Pointer assetPath, ffi.Pointer relativePath, + ffi.Pointer> callback, ); -@ffi.Native, EntityId)>( +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, + ffi.Pointer>)>( symbol: 'create_instance_ffi', assetId: 'flutter_filament_plugin') -external int create_instance_ffi( +external void create_instance_ffi( ffi.Pointer sceneManager, int entityId, + ffi.Pointer> callback, ); -@ffi.Native, EntityId)>( +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, + ffi.Pointer>)>( symbol: 'remove_entity_ffi', assetId: 'flutter_filament_plugin') external void remove_entity_ffi( ffi.Pointer viewer, int asset, + ffi.Pointer> callback, ); -@ffi.Native)>( +@ffi.Native< + ffi.Void Function(ffi.Pointer, + ffi.Pointer>)>( symbol: 'clear_entities_ffi', assetId: 'flutter_filament_plugin') external void clear_entities_ffi( ffi.Pointer viewer, + ffi.Pointer> callback, ); @ffi.Native< ffi.Bool Function( - ffi.Pointer, EntityId, ffi.Pointer)>( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer>)>( symbol: 'set_camera_ffi', assetId: 'flutter_filament_plugin') external bool set_camera_ffi( ffi.Pointer viewer, int asset, ffi.Pointer nodeName, + ffi.Pointer> callback, ); @ffi.Native< @@ -1296,27 +1339,40 @@ external void stop_animation_ffi( int index, ); -@ffi.Native, EntityId)>( +@ffi.Native< + ffi.Void Function(ffi.Pointer, EntityId, + ffi.Pointer>)>( symbol: 'get_animation_count_ffi', assetId: 'flutter_filament_plugin') -external int get_animation_count_ffi( +external void get_animation_count_ffi( ffi.Pointer sceneManager, int asset, + ffi.Pointer> callback, ); @ffi.Native< ffi.Void Function( - ffi.Pointer, EntityId, ffi.Pointer, ffi.Int)>( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Int, + ffi.Pointer>)>( symbol: 'get_animation_name_ffi', assetId: 'flutter_filament_plugin') external void get_animation_name_ffi( ffi.Pointer sceneManager, int asset, ffi.Pointer outPtr, int index, + ffi.Pointer> callback, ); @ffi.Native< - ffi.Void Function(ffi.Pointer, EntityId, - ffi.Pointer, ffi.Pointer, ffi.Int)>( + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer, + ffi.Int, + ffi.Pointer>)>( symbol: 'get_morph_target_name_ffi', assetId: 'flutter_filament_plugin') external void get_morph_target_name_ffi( ffi.Pointer sceneManager, @@ -1324,17 +1380,22 @@ external void get_morph_target_name_ffi( ffi.Pointer meshName, ffi.Pointer outPtr, int index, + ffi.Pointer> callback, ); @ffi.Native< - ffi.Int Function( - ffi.Pointer, EntityId, ffi.Pointer)>( + ffi.Void Function( + ffi.Pointer, + EntityId, + ffi.Pointer, + ffi.Pointer>)>( symbol: 'get_morph_target_name_count_ffi', assetId: 'flutter_filament_plugin') -external int get_morph_target_name_count_ffi( +external void get_morph_target_name_count_ffi( ffi.Pointer sceneManager, int asset, ffi.Pointer meshName, + ffi.Pointer> callback, ); @ffi.Native< @@ -1350,7 +1411,7 @@ external void set_morph_target_weights_ffi( ); @ffi.Native< - ffi.Bool Function( + ffi.Void Function( ffi.Pointer, EntityId, ffi.Pointer, @@ -1358,9 +1419,10 @@ external void set_morph_target_weights_ffi( ffi.Pointer, ffi.Int, ffi.Int, - ffi.Float)>( + ffi.Float, + ffi.Pointer>)>( symbol: 'set_morph_animation_ffi', assetId: 'flutter_filament_plugin') -external bool set_morph_animation_ffi( +external void set_morph_animation_ffi( ffi.Pointer sceneManager, int asset, ffi.Pointer entityName, @@ -1369,22 +1431,25 @@ external bool set_morph_animation_ffi( int numMorphTargets, int numFrames, double frameLengthInMs, + ffi.Pointer> callback, ); @ffi.Native< - ffi.Bool Function( + ffi.Void Function( ffi.Pointer, EntityId, ffi.Pointer, ffi.Pointer, - ffi.Pointer)>( + ffi.Pointer, + ffi.Pointer>)>( symbol: 'set_bone_transform_ffi', assetId: 'flutter_filament_plugin') -external bool set_bone_transform_ffi( +external void set_bone_transform_ffi( ffi.Pointer sceneManager, int asset, ffi.Pointer entityName, ffi.Pointer transform, ffi.Pointer boneName, + ffi.Pointer> callback, ); @ffi.Native< @@ -1441,16 +1506,23 @@ external void reset_to_rest_pose_ffi( external void ios_dummy_ffi(); @ffi.Native< - EntityId Function(ffi.Pointer, ffi.Pointer, - ffi.Int, ffi.Pointer, ffi.Int, ffi.Pointer)>( + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Int, + ffi.Pointer, + ffi.Int, + ffi.Pointer, + ffi.Pointer>)>( symbol: 'create_geometry_ffi', assetId: 'flutter_filament_plugin') -external int create_geometry_ffi( +external void create_geometry_ffi( ffi.Pointer viewer, ffi.Pointer vertices, int numVertices, ffi.Pointer indices, int numIndices, ffi.Pointer materialPath, + ffi.Pointer> callback, ); final class __mbstate_t extends ffi.Union { diff --git a/lib/widgets/filament_gesture_detector_mobile.dart b/lib/widgets/filament_gesture_detector_mobile.dart index 3645a082..8865cc69 100644 --- a/lib/widgets/filament_gesture_detector_mobile.dart +++ b/lib/widgets/filament_gesture_detector_mobile.dart @@ -124,15 +124,20 @@ class _FilamentGestureDetectorMobileState double _lastScale = 0; // pinch zoom on mobile - // couldn't find any equivalent for pointerCount in Listener so we use two widgets: - // - outer is a GestureDetector only for pinch zoom - // - inner is a Listener for all other gestures (including scroll zoom on desktop) + // couldn't find any equivalent for pointerCount in Listener (?) so we use a GestureDetector @override Widget build(BuildContext context) { return Stack(children: [ Positioned.fill( child: GestureDetector( - behavior: HitTestBehavior.opaque, + behavior: HitTestBehavior.translucent, + onTapDown: (d) { + if (widget.enablePicking) { + print("PICK"); + widget.controller.pick( + d.globalPosition.dx.toInt(), d.globalPosition.dy.toInt()); + } + }, onDoubleTap: () { setState(() { _rotateOnPointerMove = !_rotateOnPointerMove; diff --git a/macos/flutter_filament.podspec b/macos/flutter_filament.podspec index 7853340f..0bd55cb7 100644 --- a/macos/flutter_filament.podspec +++ b/macos/flutter_filament.podspec @@ -33,7 +33,7 @@ A new Flutter plugin project. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", - 'OTHER_CXXFLAGS' => '"--std=c++17" "-fmodules" "-fcxx-modules" "-fvisibility=default" "$(inherited)"', + 'OTHER_CXXFLAGS' => '"--std=c++17" "-fmodules" "-fcxx-modules" "-fvisibility=default" "-Wno-documentation-deprecated-sync" "$(inherited)"', 'OTHER_CFLAGS' => '"-fvisibility=default" "$(inherited)"', 'USER_HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}/include" "${PODS_TARGET_SRCROOT}/include/filament" "$(inherited)"', 'ALWAYS_SEARCH_USER_PATHS' => 'YES',