make all FFI calls async with completers

This commit is contained in:
Nick Fisher
2024-03-05 13:51:57 +08:00
parent 39fa9387e6
commit adfb607eb7
10 changed files with 598 additions and 346 deletions

View File

@@ -4,98 +4,119 @@
#include "FlutterFilamentApi.h" #include "FlutterFilamentApi.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
/// ///
/// This header replicates most of the methods in FlutterFilamentApi.h, and is only intended to be used to generate client FFI bindings. /// 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. /// 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 int32_t EntityId;
typedef void (*FilamentRenderCallback)(void* const owner); 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_filament_viewer_ffi(
FLUTTER_PLUGIN_EXPORT void create_swap_chain_ffi(void* const viewer, void* const surface, uint32_t width, uint32_t height); void *const context,
FLUTTER_PLUGIN_EXPORT void destroy_swap_chain_ffi(void* const viewer); void *const platform,
FLUTTER_PLUGIN_EXPORT void create_render_target_ffi(void* const viewer, intptr_t nativeTextureId, uint32_t width, uint32_t height); const char *uberArchivePath,
FLUTTER_PLUGIN_EXPORT void destroy_filament_viewer_ffi(void* const viewer); const ResourceLoaderWrapper *const loader,
FLUTTER_PLUGIN_EXPORT void render_ffi(void* const viewer); void (*renderCallback)(void *const renderCallbackOwner),
FLUTTER_PLUGIN_EXPORT FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback); void *const renderCallbackOwner,
FLUTTER_PLUGIN_EXPORT void set_rendering_ffi(void* const viewer, bool rendering); void (*callback)(void* const viewer)
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 create_swap_chain_ffi(void *const viewer, void *const surface, uint32_t width, uint32_t height, 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 destroy_swap_chain_ffi(void *const viewer, void (*onComplete)());
FLUTTER_PLUGIN_EXPORT void clear_background_image_ffi(void* const viewer); 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 set_background_image_ffi(void* const viewer, const char *path, bool fillHeight); FLUTTER_PLUGIN_EXPORT void destroy_filament_viewer_ffi(void *const viewer);
FLUTTER_PLUGIN_EXPORT void set_background_image_position_ffi(void* const viewer, float x, float y, bool clamp); FLUTTER_PLUGIN_EXPORT void render_ffi(void *const viewer);
FLUTTER_PLUGIN_EXPORT void set_tone_mapping_ffi(void* const viewer, int toneMapping); FLUTTER_PLUGIN_EXPORT FilamentRenderCallback make_render_callback_fn_pointer(FilamentRenderCallback);
FLUTTER_PLUGIN_EXPORT void set_bloom_ffi(void* const viewer, float strength); FLUTTER_PLUGIN_EXPORT void set_rendering_ffi(void *const viewer, bool rendering);
FLUTTER_PLUGIN_EXPORT void load_skybox_ffi(void* const viewer, const char *skyboxPath); FLUTTER_PLUGIN_EXPORT void set_frame_interval_ffi(float frameInterval);
FLUTTER_PLUGIN_EXPORT void load_ibl_ffi(void* const viewer, const char *iblPath, float intensity); 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 remove_skybox_ffi(void* const viewer); 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 remove_ibl_ffi(void* const viewer); FLUTTER_PLUGIN_EXPORT void clear_background_image_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 set_background_image_ffi(void *const viewer, const char *path, bool fillHeight);
FLUTTER_PLUGIN_EXPORT void remove_light_ffi(void* const viewer, EntityId entityId); FLUTTER_PLUGIN_EXPORT void set_background_image_position_ffi(void *const viewer, float x, float y, bool clamp);
FLUTTER_PLUGIN_EXPORT void clear_lights_ffi(void* const viewer); FLUTTER_PLUGIN_EXPORT void set_tone_mapping_ffi(void *const viewer, int toneMapping);
FLUTTER_PLUGIN_EXPORT EntityId load_glb_ffi(void* const sceneManager, const char *assetPath, int numInstances); FLUTTER_PLUGIN_EXPORT void set_bloom_ffi(void *const viewer, float strength);
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_skybox_ffi(void *const viewer, const char *skyboxPath);
FLUTTER_PLUGIN_EXPORT EntityId load_gltf_ffi(void* const sceneManager, const char *assetPath, const char *relativePath); FLUTTER_PLUGIN_EXPORT void load_ibl_ffi(void *const viewer, const char *iblPath, float intensity);
FLUTTER_PLUGIN_EXPORT EntityId create_instance_ffi(void* const sceneManager, EntityId entityId); FLUTTER_PLUGIN_EXPORT void remove_skybox_ffi(void *const viewer);
FLUTTER_PLUGIN_EXPORT void remove_entity_ffi(void* const viewer, EntityId asset); FLUTTER_PLUGIN_EXPORT void remove_ibl_ffi(void *const viewer);
FLUTTER_PLUGIN_EXPORT void clear_entities_ffi(void* const viewer); FLUTTER_PLUGIN_EXPORT void add_light_ffi(
FLUTTER_PLUGIN_EXPORT bool set_camera_ffi(void* const viewer, EntityId asset, const char *nodeName); void *const viewer,
FLUTTER_PLUGIN_EXPORT void apply_weights_ffi( uint8_t type,
void* const sceneManager, float colour,
EntityId asset, float intensity,
const char *const entityName, float posX,
float *const weights, float posY,
int count 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 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 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 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_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); 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); 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 int get_morph_target_name_count_ffi(void* const sceneManager, EntityId asset, const char *meshName); 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, FLUTTER_PLUGIN_EXPORT void set_morph_target_weights_ffi(void *const sceneManager,
EntityId asset, EntityId asset,
const char *const entityName, const char *const entityName,
const float *const morphData, const float *const morphData,
int numWeights int numWeights);
); FLUTTER_PLUGIN_EXPORT void set_morph_animation_ffi(
FLUTTER_PLUGIN_EXPORT bool set_morph_animation_ffi( void *sceneManager,
void *sceneManager, EntityId asset,
EntityId asset, const char *const entityName,
const char *const entityName, const float *const morphData,
const float *const morphData, const int *const morphIndices,
const int *const morphIndices, int numMorphTargets,
int numMorphTargets, int numFrames,
int numFrames, float frameLengthInMs,
float frameLengthInMs); void (*callback)(bool));
FLUTTER_PLUGIN_EXPORT bool set_bone_transform_ffi( FLUTTER_PLUGIN_EXPORT void set_bone_transform_ffi(
void *sceneManager, void *sceneManager,
EntityId asset, EntityId asset,
const char *entityName, const char *entityName,
const float *const transform, const float *const transform,
const char *boneName); const char *boneName,
FLUTTER_PLUGIN_EXPORT void add_bone_animation_ffi( void (*callback)(bool));
void *sceneManager, FLUTTER_PLUGIN_EXPORT void add_bone_animation_ffi(
EntityId asset, void *sceneManager,
const float *const frameData, EntityId asset,
int numFrames, const float *const frameData,
const char *const boneName, int numFrames,
const char **const meshNames, const char *const boneName,
int numMeshTargets, const char **const meshNames,
float frameLengthInMs, int numMeshTargets,
bool isModelSpace); float frameLengthInMs,
FLUTTER_PLUGIN_EXPORT void set_post_processing_ffi(void* const viewer, bool enabled); bool isModelSpace);
FLUTTER_PLUGIN_EXPORT void pick_ffi(void* const viewer, int x, int y, EntityId* entityId); FLUTTER_PLUGIN_EXPORT void set_post_processing_ffi(void *const viewer, bool enabled);
FLUTTER_PLUGIN_EXPORT void reset_to_rest_pose_ffi(void* const sceneManager, EntityId entityId); FLUTTER_PLUGIN_EXPORT void pick_ffi(void *const viewer, int x, int y, EntityId *entityId);
FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi(); FLUTTER_PLUGIN_EXPORT void reset_to_rest_pose_ffi(void *const sceneManager, EntityId entityId);
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 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 #ifdef __cplusplus
} }

View File

@@ -44,9 +44,9 @@ namespace flutter_filament
EntityId loadGltf(const char *uri, const char *relativeResourcePath); EntityId loadGltf(const char *uri, const char *relativeResourcePath);
//// ////
/// @brief /// @brief Load the GLB from the specified path, optionally creating multiple instances.
/// @param uri /// @param uri the path to the asset. Should be either asset:// (representing a Flutter asset), or file:// (representing a filesystem file).
/// @param numInstances /// @param numInstances the number of instances to create.
/// @return an Entity representing the FilamentAsset associated with the loaded FilamentAsset. /// @return an Entity representing the FilamentAsset associated with the loaded FilamentAsset.
/// ///
EntityId loadGlb(const char *uri, int numInstances); 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 meshName an array of mesh names under [entity] that should be animated
/// @param numMeshTargets the number of meshes under [meshName] /// @param numMeshTargets the number of meshes under [meshName]
/// @param frameLengthInMs the length of each frame in ms /// @param frameLengthInMs the length of each frame in ms
/// @return /// @return true if the bone animation was successfully enqueued
bool addBoneAnimation( bool addBoneAnimation(
EntityId entity, EntityId entity,
const float *const frameData, 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. /// @brief returns the number of instances of the FilamentAsset represented by the given entity.
/// @param entityId /// @param entityId
/// @return /// @return the number of instances
int getInstanceCount(EntityId entityId); int getInstanceCount(EntityId entityId);
/// @brief returns an array containing all instances of the FilamentAsset represented by the given entity. /// @brief returns an array containing all instances of the FilamentAsset represented by the given entity.
/// @param entityId /// @param entityId
/// @return
void getInstances(EntityId entityId, EntityId* out); void getInstances(EntityId entityId, EntityId* out);
friend class FilamentViewer; friend class FilamentViewer;

View File

@@ -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) { 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) { FLUTTER_PLUGIN_EXPORT EntityId find_child_entity_by_name(void *const sceneManager, const EntityId parent, const char* name) {

View File

@@ -64,10 +64,9 @@ public:
} }
if (_rendering) { if (_rendering) {
auto frameStart = std::chrono::high_resolution_clock::now(); // auto frameStart = std::chrono::high_resolution_clock::now();
doRender(); doRender();
auto frameEnd = std::chrono::high_resolution_clock::now(); // auto frameEnd = std::chrono::high_resolution_clock::now();
// Log("Took %f milliseconds for render", float(std::chrono::duration_cast<std::chrono::milliseconds>(frameEnd - frameStart).count()));
} }
elapsed = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - last).count()); elapsed = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - last).count());
@@ -98,10 +97,12 @@ public:
_t->join(); _t->join();
} }
void *const createViewer(void *const context, void *const platform, void createViewer(void *const context, void *const platform,
const char *uberArchivePath, const char *uberArchivePath,
const ResourceLoaderWrapper *const loader, const ResourceLoaderWrapper *const loader,
void (*renderCallback)(void *), void *const owner) { void (*renderCallback)(void *),
void *const owner,
void (*callback)(void* const) ) {
_renderCallback = renderCallback; _renderCallback = renderCallback;
_renderCallbackOwner = owner; _renderCallbackOwner = owner;
std::packaged_task<FilamentViewer *()> lambda([=]() mutable { std::packaged_task<FilamentViewer *()> lambda([=]() mutable {
@@ -117,34 +118,30 @@ public:
#else #else
_viewer = new FilamentViewer(context, loader, platform, uberArchivePath); _viewer = new FilamentViewer(context, loader, platform, uberArchivePath);
#endif #endif
callback(_viewer);
return _viewer; return _viewer;
}); });
auto fut = add_task(lambda); auto fut = add_task(lambda);
fut.wait();
_viewer = fut.get();
return (void *const)_viewer;
} }
void destroyViewer() { void destroyViewer() {
std::packaged_task<void()> lambda([&]() mutable { std::packaged_task<void()> lambda([=]() mutable {
_rendering = false; _rendering = false;
destroy_filament_viewer(_viewer); destroy_filament_viewer(_viewer);
_viewer = nullptr; _viewer = nullptr;
}); });
auto fut = add_task(lambda); auto fut = add_task(lambda);
fut.wait();
} }
void setRendering(bool rendering) { void setRendering(bool rendering) {
std::packaged_task<void()> lambda( std::packaged_task<void()> lambda(
[&]() mutable { this->_rendering = rendering; }); [=]() mutable { this->_rendering = rendering; });
auto fut = add_task(lambda); auto fut = add_task(lambda);
fut.wait();
} }
void doRender() { void doRender() {
auto now = std::chrono::high_resolution_clock::now(); // auto now = std::chrono::high_resolution_clock::now();
auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count(); // auto nanos = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
render(_viewer, 0, nullptr, nullptr, nullptr); render(_viewer, 0, nullptr, nullptr, nullptr);
_lastRenderTime = std::chrono::high_resolution_clock::now(); _lastRenderTime = std::chrono::high_resolution_clock::now();
if(_renderCallback) { if(_renderCallback) {
@@ -189,16 +186,17 @@ extern "C" {
static RenderLoop *_rl; 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, void *const context, void *const platform, const char *uberArchivePath,
const ResourceLoaderWrapper *const loader, const ResourceLoaderWrapper *const loader,
void (*renderCallback)(void *const renderCallbackOwner), void (*renderCallback)(void *const renderCallbackOwner),
void *const renderCallbackOwner) { void *const renderCallbackOwner,
void (*callback)(void* const) ) {
if (!_rl) { if (!_rl) {
_rl = new RenderLoop(); _rl = new RenderLoop();
} }
return _rl->createViewer(context, platform, uberArchivePath, loader, _rl->createViewer(context, platform, uberArchivePath, loader,
renderCallback, renderCallbackOwner); renderCallback, renderCallbackOwner, callback);
} }
FLUTTER_PLUGIN_EXPORT void destroy_filament_viewer_ffi(void *const viewer) { 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, FLUTTER_PLUGIN_EXPORT void create_swap_chain_ffi(void *const viewer,
void *const surface, void *const surface,
uint32_t width, uint32_t width,
uint32_t height) { uint32_t height,
Log("Creating swapchain %dx%d", width, height); void (*onComplete)()) {
Log("Creating swapchain %dx%d with viewer %d", width, height, viewer);
std::packaged_task<void()> lambda( std::packaged_task<void()> lambda(
[&]() mutable { create_swap_chain(viewer, surface, width, height); }); [=]() mutable {
create_swap_chain(viewer, surface, width, height);
onComplete();
});
auto fut = _rl->add_task(lambda); 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"); Log("Destroying swapchain");
std::packaged_task<void()> lambda( std::packaged_task<void()> lambda(
[&]() mutable { [=]() mutable {
destroy_swap_chain(viewer); destroy_swap_chain(viewer);
onComplete();
}); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void create_render_target_ffi(void *const viewer, FLUTTER_PLUGIN_EXPORT void create_render_target_ffi(void *const viewer,
intptr_t nativeTextureId, intptr_t nativeTextureId,
uint32_t width, uint32_t width,
uint32_t height) { uint32_t height,
std::packaged_task<void()> lambda([&]() mutable { void (*onComplete)()) {
std::packaged_task<void()> lambda([=]() mutable {
create_render_target(viewer, nativeTextureId, width, height); create_render_target(viewer, nativeTextureId, width, height);
onComplete();
}); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void update_viewport_and_camera_projection_ffi( FLUTTER_PLUGIN_EXPORT void update_viewport_and_camera_projection_ffi(
void *const viewer, const uint32_t width, const uint32_t height, 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); Log("Update viewport %dx%d", width, height);
std::packaged_task<void()> lambda([&]() mutable { std::packaged_task<void()> lambda([=]() mutable {
update_viewport_and_camera_projection(viewer, width, height, scaleFactor); update_viewport_and_camera_projection(viewer, width, height, scaleFactor);
onComplete();
}); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void set_rendering_ffi(void *const viewer, 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) { FLUTTER_PLUGIN_EXPORT void render_ffi(void *const viewer) {
std::packaged_task<void()> lambda([&]() mutable { _rl->doRender(); }); std::packaged_task<void()> lambda([=]() mutable { _rl->doRender(); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void FLUTTER_PLUGIN_EXPORT void
set_background_color_ffi(void *const viewer, const float r, const float g, set_background_color_ffi(void *const viewer, const float r, const float g,
const float b, const float a) { const float b, const float a) {
std::packaged_task<void()> lambda( std::packaged_task<void()> 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); 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 *path,
const char *relativeResourcePath) { const char *relativeResourcePath,
std::packaged_task<EntityId()> lambda([&]() mutable { void (*callback)(EntityId)) {
return load_gltf(sceneManager, path, relativeResourcePath); std::packaged_task<EntityId()> lambda([=]() mutable {
auto entity = load_gltf(sceneManager, path, relativeResourcePath);
callback(entity);
return entity;
}); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
return fut.get();
} }
FLUTTER_PLUGIN_EXPORT EntityId load_glb_ffi(void *const sceneManager, FLUTTER_PLUGIN_EXPORT void load_glb_ffi(void *const sceneManager,
const char *path, int numInstances) { const char *path, int numInstances, void (*callback)(EntityId)) {
std::packaged_task<EntityId()> lambda( std::packaged_task<EntityId()> 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); auto fut = _rl->add_task(lambda);
fut.wait();
return fut.get();
} }
FLUTTER_PLUGIN_EXPORT EntityId load_glb_from_buffer_ffi(void *const sceneManager, FLUTTER_PLUGIN_EXPORT void load_glb_from_buffer_ffi(void *const sceneManager,
const void *const data, size_t length, int numInstances) { const void *const data, size_t length, int numInstances, void (*callback)(EntityId)) {
std::packaged_task<EntityId()> lambda( std::packaged_task<EntityId()> 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); auto fut = _rl->add_task(lambda);
fut.wait();
return fut.get();
} }
FLUTTER_PLUGIN_EXPORT void clear_background_image_ffi(void *const viewer) { FLUTTER_PLUGIN_EXPORT void clear_background_image_ffi(void *const viewer) {
std::packaged_task<void()> lambda([&] { clear_background_image(viewer); }); std::packaged_task<void()> lambda([=] { clear_background_image(viewer); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void set_background_image_ffi(void *const viewer, FLUTTER_PLUGIN_EXPORT void set_background_image_ffi(void *const viewer,
const char *path, const char *path,
bool fillHeight) { bool fillHeight) {
std::packaged_task<void()> lambda( std::packaged_task<void()> lambda(
[&] { set_background_image(viewer, path, fillHeight); }); [=] { set_background_image(viewer, path, fillHeight); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void set_background_image_position_ffi(void *const viewer, FLUTTER_PLUGIN_EXPORT void set_background_image_position_ffi(void *const viewer,
float x, float y, float x, float y,
bool clamp) { bool clamp) {
std::packaged_task<void()> lambda( std::packaged_task<void()> lambda(
[&] { set_background_image_position(viewer, x, y, clamp); }); [=] { set_background_image_position(viewer, x, y, clamp); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void set_tone_mapping_ffi(void *const viewer, FLUTTER_PLUGIN_EXPORT void set_tone_mapping_ffi(void *const viewer,
int toneMapping) { int toneMapping) {
std::packaged_task<void()> lambda( std::packaged_task<void()> lambda(
[&] { set_tone_mapping(viewer, toneMapping); }); [=] { set_tone_mapping(viewer, toneMapping); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void set_bloom_ffi(void *const viewer, float strength) { FLUTTER_PLUGIN_EXPORT void set_bloom_ffi(void *const viewer, float strength) {
std::packaged_task<void()> lambda([&] { set_bloom(viewer, strength); }); std::packaged_task<void()> lambda([=] { set_bloom(viewer, strength); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void load_skybox_ffi(void *const viewer, FLUTTER_PLUGIN_EXPORT void load_skybox_ffi(void *const viewer,
const char *skyboxPath) { const char *skyboxPath) {
std::packaged_task<void()> lambda([&] { load_skybox(viewer, skyboxPath); }); std::packaged_task<void()> lambda([=] { load_skybox(viewer, skyboxPath); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void load_ibl_ffi(void *const viewer, const char *iblPath, FLUTTER_PLUGIN_EXPORT void load_ibl_ffi(void *const viewer, const char *iblPath,
float intensity) { float intensity) {
std::packaged_task<void()> lambda( std::packaged_task<void()> lambda(
[&] { load_ibl(viewer, iblPath, intensity); }); [=] { load_ibl(viewer, iblPath, intensity); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void remove_skybox_ffi(void *const viewer) { FLUTTER_PLUGIN_EXPORT void remove_skybox_ffi(void *const viewer) {
std::packaged_task<void()> lambda([&] { remove_skybox(viewer); }); std::packaged_task<void()> lambda([=] { remove_skybox(viewer); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void remove_ibl_ffi(void *const viewer) { FLUTTER_PLUGIN_EXPORT void remove_ibl_ffi(void *const viewer) {
std::packaged_task<void()> lambda([&] { remove_ibl(viewer); }); std::packaged_task<void()> lambda([=] { remove_ibl(viewer); });
auto fut = _rl->add_task(lambda); 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 intensity, float posX, float posY, float posZ,
float dirX, float dirY, float dirZ, bool shadows) { float dirX, float dirY, float dirZ, bool shadows, void (*callback)(EntityId)) {
std::packaged_task<EntityId()> lambda([&] { std::packaged_task<EntityId()> lambda([=] {
return add_light(viewer, type, colour, intensity, posX, posY, posZ, dirX, auto entity = add_light(viewer, type, colour, intensity, posX, posY, posZ, dirX,
dirY, dirZ, shadows); dirY, dirZ, shadows);
callback(entity);
return entity;
}); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
return fut.get();
} }
FLUTTER_PLUGIN_EXPORT void remove_light_ffi(void *const viewer, FLUTTER_PLUGIN_EXPORT void remove_light_ffi(void *const viewer,
EntityId entityId) { EntityId entityId) {
std::packaged_task<void()> lambda([&] { remove_light(viewer, entityId); }); std::packaged_task<void()> lambda([=] { remove_light(viewer, entityId); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void clear_lights_ffi(void *const viewer) { FLUTTER_PLUGIN_EXPORT void clear_lights_ffi(void *const viewer) {
std::packaged_task<void()> lambda([&] { clear_lights(viewer); }); std::packaged_task<void()> lambda([=] { clear_lights(viewer); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void remove_entity_ffi(void *const viewer, FLUTTER_PLUGIN_EXPORT void remove_entity_ffi(void *const viewer,
EntityId asset) { EntityId asset, void (*callback)()) {
std::packaged_task<void()> lambda([&] { remove_entity(viewer, asset); }); std::packaged_task<void()> lambda([=] {
remove_entity(viewer, asset);
callback();
});
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
}
FLUTTER_PLUGIN_EXPORT void clear_entities_ffi(void *const viewer) {
std::packaged_task<void()> lambda([&] { clear_entities(viewer); });
auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT bool set_camera_ffi(void *const viewer, EntityId asset, FLUTTER_PLUGIN_EXPORT void clear_entities_ffi(void *const viewer, void (*callback)()) {
const char *nodeName) { std::packaged_task<void()> lambda([=] {
std::packaged_task<bool()> lambda( clear_entities(viewer);
[&] { return set_camera(viewer, asset, nodeName); }); 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<bool()> lambda(
[=] {
auto success = set_camera(viewer, asset, nodeName);
callback(success);
return success;
});
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
return fut.get();
} }
FLUTTER_PLUGIN_EXPORT void FLUTTER_PLUGIN_EXPORT void
get_morph_target_name_ffi(void *sceneManager, EntityId asset, get_morph_target_name_ffi(void *sceneManager, EntityId asset,
const char *meshName, char *const outPtr, int index) { const char *meshName, char *const outPtr, int index, void (*callback)()) {
std::packaged_task<void()> lambda([&] { std::packaged_task<void()> lambda([=] {
get_morph_target_name(sceneManager, asset, meshName, outPtr, index); get_morph_target_name(sceneManager, asset, meshName, outPtr, index);
callback();
}); });
auto fut = _rl->add_task(lambda); 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, get_morph_target_name_count_ffi(void *sceneManager, EntityId asset,
const char *meshName) { const char *meshName, void (*callback)(int)) {
std::packaged_task<int()> lambda([&] { std::packaged_task<int()> lambda([=] {
return get_morph_target_name_count(sceneManager, asset, meshName); auto count = get_morph_target_name_count(sceneManager, asset, meshName);
callback(count);
return count;
}); });
auto fut = _rl->add_task(lambda); 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 loop, bool reverse,
bool replaceActive, bool replaceActive,
float crossfade) { float crossfade) {
std::packaged_task<void()> lambda([&] { std::packaged_task<void()> lambda([=] {
play_animation(sceneManager, asset, index, loop, reverse, replaceActive, play_animation(sceneManager, asset, index, loop, reverse, replaceActive,
crossfade); crossfade);
}); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void set_animation_frame_ffi(void *const sceneManager, FLUTTER_PLUGIN_EXPORT void set_animation_frame_ffi(void *const sceneManager,
EntityId asset, EntityId asset,
int animationIndex, int animationIndex,
int animationFrame) { int animationFrame) {
std::packaged_task<void()> lambda([&] { std::packaged_task<void()> lambda([=] {
set_animation_frame(sceneManager, asset, animationIndex, animationFrame); set_animation_frame(sceneManager, asset, animationIndex, animationFrame);
}); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void stop_animation_ffi(void *const sceneManager, FLUTTER_PLUGIN_EXPORT void stop_animation_ffi(void *const sceneManager,
EntityId asset, int index) { EntityId asset, int index) {
std::packaged_task<void()> lambda( std::packaged_task<void()> lambda(
[&] { stop_animation(sceneManager, asset, index); }); [=] { stop_animation(sceneManager, asset, index); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT int get_animation_count_ffi(void *const sceneManager, FLUTTER_PLUGIN_EXPORT void get_animation_count_ffi(void *const sceneManager,
EntityId asset) { EntityId asset,
void (*callback)(int)) {
std::packaged_task<int()> lambda( std::packaged_task<int()> lambda(
[&] { return get_animation_count(sceneManager, asset); }); [=] {
auto count = get_animation_count(sceneManager, asset);
callback(count);
return count;
});
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
return fut.get();
} }
FLUTTER_PLUGIN_EXPORT void get_animation_name_ffi(void *const sceneManager, FLUTTER_PLUGIN_EXPORT void get_animation_name_ffi(void *const sceneManager,
EntityId asset, EntityId asset,
char *const outPtr, char *const outPtr,
int index) { int index,
void (*callback)()) {
std::packaged_task<void()> lambda( std::packaged_task<void()> lambda(
[&] { get_animation_name(sceneManager, asset, outPtr, index); }); [=] {
get_animation_name(sceneManager, asset, outPtr, index);
callback();
});
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void set_post_processing_ffi(void *const viewer, FLUTTER_PLUGIN_EXPORT void set_post_processing_ffi(void *const viewer,
bool enabled) { bool enabled) {
std::packaged_task<void()> lambda( std::packaged_task<void()> lambda(
[&] { set_post_processing(viewer, enabled); }); [=] { set_post_processing(viewer, enabled); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void pick_ffi(void *const viewer, int x, int y, FLUTTER_PLUGIN_EXPORT void pick_ffi(void *const viewer, int x, int y,
EntityId *entityId) { EntityId *entityId) {
std::packaged_task<void()> lambda([&] { pick(viewer, x, y, entityId); }); std::packaged_task<void()> lambda([=] { pick(viewer, x, y, entityId); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT const char * FLUTTER_PLUGIN_EXPORT void
get_name_for_entity_ffi(void *const sceneManager, const EntityId entityId) { get_name_for_entity_ffi(void *const sceneManager, const EntityId entityId, void (*callback)(const char*)) {
std::packaged_task<const char *()> lambda( std::packaged_task<const char *()> 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); auto fut = _rl->add_task(lambda);
fut.wait();
return fut.get();
} }
void set_morph_target_weights_ffi(void *const sceneManager, 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, const float *const morphData,
int numWeights) { int numWeights) {
std::packaged_task<void()> lambda( std::packaged_task<void()> 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); auto fut = _rl->add_task(lambda);
fut.wait();
} }
bool set_morph_animation_ffi( void set_morph_animation_ffi(
void *sceneManager, void *sceneManager,
EntityId asset, EntityId asset,
const char *const entityName, const char *const entityName,
@@ -532,35 +540,38 @@ bool set_morph_animation_ffi(
const int *const morphIndices, const int *const morphIndices,
int numMorphTargets, int numMorphTargets,
int numFrames, int numFrames,
float frameLengthInMs) { float frameLengthInMs,
void (*callback)(bool)) {
std::packaged_task<bool()> lambda( std::packaged_task<bool()> 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); 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, void *sceneManager,
EntityId asset, EntityId asset,
const char *entityName, const char *entityName,
const float *const transform, const float *const transform,
const char *boneName) { const char *boneName,
void (*callback)(bool)) {
std::packaged_task<bool()> lambda( std::packaged_task<bool()> 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); 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) { FLUTTER_PLUGIN_EXPORT void reset_to_rest_pose_ffi(void* const sceneManager, EntityId entityId) {
std::packaged_task<void()> lambda( std::packaged_task<void()> lambda(
[&] { return reset_to_rest_pose(sceneManager, entityId); }); [=] { return reset_to_rest_pose(sceneManager, entityId); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void add_bone_animation_ffi( 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); add_bone_animation(sceneManager, asset, frameData, numFrames, boneName, meshNames, numMeshTargets, frameLengthInMs, isModelSpace);
}); });
auto fut = _rl->add_task(lambda); auto fut = _rl->add_task(lambda);
fut.wait();
} }
FLUTTER_PLUGIN_EXPORT void ios_dummy_ffi() { Log("Dummy called"); } 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<EntityId()> lambda( std::packaged_task<EntityId()> 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); auto fut = _rl->add_task(lambda);
fut.wait();
return fut.get();
} }
} }

View File

@@ -1208,6 +1208,20 @@ namespace flutter_filament
_collisionComponentManager->elementAt<2>(collisionInstance) = affectsTransform; _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) { void SceneManager::testCollisions(EntityId entityId) {
const auto *instance = getInstanceByEntityId(entityId); const auto *instance = getInstanceByEntityId(entityId);
if(!instance) { if(!instance) {

View File

@@ -68,7 +68,7 @@ std::streampos StreamBufferAdapter::seekoff(std::streamoff off, std::ios_base::s
if(way == std::ios_base::beg) { if(way == std::ios_base::beg) {
setg(eback(), eback()+off, egptr()); setg(eback(), eback()+off, egptr());
} else if(way == std::ios_base::cur) { } else if(way == std::ios_base::cur) {
gbump(off); gbump((int)off);
} else { } else {
setg(eback(), egptr()-off, egptr()); setg(eback(), egptr()-off, egptr());
} }

View File

@@ -4,6 +4,7 @@ import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'dart:developer' as dev; import 'dart:developer' as dev;
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:ffi/ffi.dart'; import 'package:ffi/ffi.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
@@ -140,7 +141,7 @@ class FilamentControllerFFI extends FilamentController {
Future setFrameRate(int framerate) async { Future setFrameRate(int framerate) async {
final interval = 1000.0 / framerate; final interval = 1000.0 / framerate;
set_frame_interval_ffi(interval); set_frame_interval_ffi(interval);
dev.log("Set frame interval to $interval"); print("Set frame interval to $interval");
} }
@override @override
@@ -182,7 +183,82 @@ class FilamentControllerFFI extends FilamentController {
await _channel.invokeMethod( await _channel.invokeMethod(
"destroyTexture", textureDetails.value!.textureId); "destroyTexture", textureDetails.value!.textureId);
} }
dev.log("Texture destroyed"); print("Texture destroyed");
}
Future<void> _withVoidCallback(
Function(Pointer<NativeFunction<Void Function()>>) func) async {
final completer = Completer();
// ignore: prefer_function_declarations_over_variables
void Function() callback = () {
completer.complete();
};
final nativeCallable = NativeCallable<Void Function()>.listener(callback);
func.call(nativeCallable.nativeFunction);
await completer.future;
nativeCallable.close();
}
Future<Pointer<Void>> _withVoidPointerCallback(
Function(Pointer<NativeFunction<Void Function(Pointer<Void>)>>)
func) async {
final completer = Completer<Pointer<Void>>();
// ignore: prefer_function_declarations_over_variables
void Function(Pointer<Void>) callback = (Pointer<Void> ptr) {
completer.complete(ptr);
};
final nativeCallable =
NativeCallable<Void Function(Pointer<Void>)>.listener(callback);
func.call(nativeCallable.nativeFunction);
await completer.future;
nativeCallable.close();
return completer.future;
}
Future<bool> _withBoolCallback(
Function(Pointer<NativeFunction<Void Function(Bool)>>) func) async {
final completer = Completer<bool>();
// ignore: prefer_function_declarations_over_variables
void Function(bool) callback = (bool result) {
completer.complete(result);
};
final nativeCallable =
NativeCallable<Void Function(Bool)>.listener(callback);
func.call(nativeCallable.nativeFunction);
await completer.future;
nativeCallable.close();
return completer.future;
}
Future<int> _withIntCallback(
Function(Pointer<NativeFunction<Void Function(Int32)>>) func) async {
final completer = Completer<int>();
// ignore: prefer_function_declarations_over_variables
void Function(int) callback = (int result) {
completer.complete(result);
};
final nativeCallable =
NativeCallable<Void Function(Int32)>.listener(callback);
func.call(nativeCallable.nativeFunction);
await completer.future;
nativeCallable.close();
return completer.future;
}
Future<String> _withCharPtrCallback(
Function(Pointer<NativeFunction<Void Function(Pointer<Char>)>>)
func) async {
final completer = Completer<String>();
// ignore: prefer_function_declarations_over_variables
void Function(Pointer<Char>) callback = (Pointer<Char> result) {
completer.complete(result.cast<Utf8>().toDartString());
};
final nativeCallable =
NativeCallable<Void Function(Pointer<Char>)>.listener(callback);
func.call(nativeCallable.nativeFunction);
await completer.future;
nativeCallable.close();
return completer.future;
} }
bool _creating = false; bool _creating = false;
@@ -190,6 +266,7 @@ class FilamentControllerFFI extends FilamentController {
/// ///
/// Called by `FilamentWidget`. You do not need to call this yourself. /// Called by `FilamentWidget`. You do not need to call this yourself.
/// ///
///
@override @override
Future createViewer() async { Future createViewer() async {
if (_creating) { if (_creating) {
@@ -234,43 +311,60 @@ class FilamentControllerFFI extends FilamentController {
var renderingSurface = await _createRenderingSurface(); var renderingSurface = await _createRenderingSurface();
dev.log("Got rendering surface"); print("Got rendering surface");
final uberarchivePtr = final uberarchivePtr =
uberArchivePath?.toNativeUtf8().cast<Char>() ?? nullptr; uberArchivePath?.toNativeUtf8().cast<Char>() ?? nullptr;
_viewer = create_filament_viewer_ffi( _viewer = await _withVoidPointerCallback((callback) =>
Pointer<Void>.fromAddress(renderingSurface.sharedContext), create_filament_viewer_ffi(
_driver, Pointer<Void>.fromAddress(renderingSurface.sharedContext),
uberarchivePtr, _driver,
loader, uberarchivePtr,
renderCallback, loader,
renderCallbackOwner); renderCallback,
renderCallbackOwner,
callback));
allocator.free(uberarchivePtr); allocator.free(uberarchivePtr);
dev.log("Created viewer");
print("Created viewer ${_viewer!.address}");
if (_viewer!.address == 0) { if (_viewer!.address == 0) {
throw Exception("Failed to create viewer. Check logs for details"); throw Exception("Failed to create viewer. Check logs for details");
} }
_sceneManager = get_scene_manager(_viewer!); _sceneManager = get_scene_manager(_viewer!);
create_swap_chain_ffi(_viewer!, renderingSurface.surface, await _withVoidCallback((callback) {
_rect.value!.width.toInt(), _rect.value!.height.toInt()); create_swap_chain_ffi(_viewer!, renderingSurface.surface,
dev.log("Created swap chain"); _rect.value!.width.toInt(), _rect.value!.height.toInt(), callback);
});
print("Created swap chain");
if (renderingSurface.textureHandle != 0) { if (renderingSurface.textureHandle != 0) {
dev.log( print(
"Creating render target from native texture ${renderingSurface.textureHandle}"); "Creating render target from native texture ${renderingSurface.textureHandle}");
create_render_target_ffi(_viewer!, renderingSurface.textureHandle, await _withVoidCallback((callback) => create_render_target_ffi(
_rect.value!.width.toInt(), _rect.value!.height.toInt()); _viewer!,
renderingSurface.textureHandle,
_rect.value!.width.toInt(),
_rect.value!.height.toInt(),
callback));
} }
textureDetails.value = TextureDetails( textureDetails.value = TextureDetails(
textureId: renderingSurface.flutterTextureId, textureId: renderingSurface.flutterTextureId,
width: _rect.value!.width.toInt(), width: _rect.value!.width.toInt(),
height: _rect.value!.height.toInt()); height: _rect.value!.height.toInt());
dev.log("texture details ${textureDetails.value}"); print("texture details ${textureDetails.value}");
update_viewport_and_camera_projection_ffi( await _withVoidCallback((callback) {
_viewer!, _rect.value!.width.toInt(), _rect.value!.height.toInt(), 1.0); update_viewport_and_camera_projection_ffi(
_viewer!,
_rect.value!.width.toInt(),
_rect.value!.height.toInt(),
1.0,
callback);
});
hasViewer.value = true; hasViewer.value = true;
_creating = false; _creating = false;
} }
@@ -365,7 +459,8 @@ class FilamentControllerFFI extends FilamentController {
set_rendering_ffi(_viewer!, false); set_rendering_ffi(_viewer!, false);
if (!_usesBackingWindow) { if (!_usesBackingWindow) {
destroy_swap_chain_ffi(_viewer!); await _withVoidCallback(
(callback) => destroy_swap_chain_ffi(_viewer!, callback));
} }
if (requiresTextureWidget) { if (requiresTextureWidget) {
@@ -374,7 +469,7 @@ class FilamentControllerFFI extends FilamentController {
"destroyTexture", textureDetails.value!.textureId); "destroyTexture", textureDetails.value!.textureId);
} }
} else if (Platform.isWindows) { } else if (Platform.isWindows) {
dev.log("Resizing window with rect ${_rect.value}"); print("Resizing window with rect ${_rect.value}");
await _channel.invokeMethod("resizeWindow", [ await _channel.invokeMethod("resizeWindow", [
_rect.value!.width, _rect.value!.width,
_rect.value!.height, _rect.value!.height,
@@ -390,15 +485,23 @@ class FilamentControllerFFI extends FilamentController {
} }
if (!_usesBackingWindow) { if (!_usesBackingWindow) {
create_swap_chain_ffi(_viewer!, renderingSurface.surface, _withVoidCallback((callback) => create_swap_chain_ffi(
_rect.value!.width.toInt(), _rect.value!.height.toInt()); _viewer!,
renderingSurface.surface,
_rect.value!.width.toInt(),
_rect.value!.height.toInt(),
callback));
} }
if (renderingSurface.textureHandle != 0) { if (renderingSurface.textureHandle != 0) {
dev.log( print(
"Creating render target from native texture ${renderingSurface.textureHandle}"); "Creating render target from native texture ${renderingSurface.textureHandle}");
create_render_target_ffi(_viewer!, renderingSurface.textureHandle, _withVoidCallback((callback) => create_render_target_ffi(
_rect.value!.width.toInt(), _rect.value!.height.toInt()); _viewer!,
renderingSurface.textureHandle,
_rect.value!.width.toInt(),
_rect.value!.height.toInt(),
callback));
} }
textureDetails.value = TextureDetails( textureDetails.value = TextureDetails(
@@ -406,8 +509,12 @@ class FilamentControllerFFI extends FilamentController {
width: _rect.value!.width.toInt(), width: _rect.value!.width.toInt(),
height: _rect.value!.height.toInt()); height: _rect.value!.height.toInt());
update_viewport_and_camera_projection_ffi(_viewer!, _withVoidCallback((callback) => update_viewport_and_camera_projection_ffi(
_rect.value!.width.toInt(), _rect.value!.height.toInt(), 1.0); _viewer!,
_rect.value!.width.toInt(),
_rect.value!.height.toInt(),
1.0,
callback));
await setRendering(_rendering); await setRendering(_rendering);
} finally { } finally {
@@ -518,8 +625,19 @@ class FilamentControllerFFI extends FilamentController {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
var entity = add_light_ffi(_viewer!, type, colour, intensity, posX, posY, var entity = await _withIntCallback((callback) => add_light_ffi(
posZ, dirX, dirY, dirZ, castShadows); _viewer!,
type,
colour,
intensity,
posX,
posY,
posZ,
dirX,
dirY,
dirZ,
castShadows,
callback));
_onLoadController.sink.add(entity); _onLoadController.sink.add(entity);
_lights.add(entity); _lights.add(entity);
return entity; return entity;
@@ -572,8 +690,8 @@ class FilamentControllerFFI extends FilamentController {
data = (ptr.cast<Void>(), asset.lengthInBytes); data = (ptr.cast<Void>(), asset.lengthInBytes);
} }
var entity = load_glb_from_buffer_ffi( var entity = await _withIntCallback((callback) => load_glb_from_buffer_ffi(
_sceneManager!, data.$1, data.$2, numInstances); _sceneManager!, data.$1, data.$2, numInstances, callback));
if (!cache) { if (!cache) {
allocator.free(data.$1); allocator.free(data.$1);
} else { } else {
@@ -587,7 +705,8 @@ class FilamentControllerFFI extends FilamentController {
@override @override
Future<FilamentEntity> createInstance(FilamentEntity entity) async { Future<FilamentEntity> createInstance(FilamentEntity entity) async {
var created = create_instance(_sceneManager!, entity); var created = await _withIntCallback(
(callback) => create_instance(_sceneManager!, entity));
if (created == _FILAMENT_ASSET_ERROR) { if (created == _FILAMENT_ASSET_ERROR) {
throw Exception("Failed to create instance"); throw Exception("Failed to create instance");
} }
@@ -630,7 +749,8 @@ class FilamentControllerFFI extends FilamentController {
throw Exception("Not yet implemented"); throw Exception("Not yet implemented");
} }
final pathPtr = path.toNativeUtf8().cast<Char>(); final pathPtr = path.toNativeUtf8().cast<Char>();
var entity = load_glb_ffi(_sceneManager!, pathPtr, numInstances); var entity = await _withIntCallback((callback) =>
load_glb_ffi(_sceneManager!, pathPtr, numInstances, callback));
allocator.free(pathPtr); allocator.free(pathPtr);
if (entity == _FILAMENT_ASSET_ERROR) { if (entity == _FILAMENT_ASSET_ERROR) {
throw Exception("An error occurred loading the asset at $path"); throw Exception("An error occurred loading the asset at $path");
@@ -653,8 +773,8 @@ class FilamentControllerFFI extends FilamentController {
final pathPtr = path.toNativeUtf8().cast<Char>(); final pathPtr = path.toNativeUtf8().cast<Char>();
final relativeResourcePathPtr = final relativeResourcePathPtr =
relativeResourcePath.toNativeUtf8().cast<Char>(); relativeResourcePath.toNativeUtf8().cast<Char>();
var entity = var entity = await _withIntCallback((callback) => load_gltf_ffi(
load_gltf_ffi(_sceneManager!, pathPtr, relativeResourcePathPtr); _sceneManager!, pathPtr, relativeResourcePathPtr, callback));
allocator.free(pathPtr); allocator.free(pathPtr);
allocator.free(relativeResourcePathPtr); allocator.free(relativeResourcePathPtr);
if (entity == _FILAMENT_ASSET_ERROR) { if (entity == _FILAMENT_ASSET_ERROR) {
@@ -739,8 +859,9 @@ class FilamentControllerFFI extends FilamentController {
} }
var names = <String>[]; var names = <String>[];
var meshNamePtr = meshName.toNativeUtf8().cast<Char>(); var meshNamePtr = meshName.toNativeUtf8().cast<Char>();
var count = var count = await _withIntCallback((callback) =>
get_morph_target_name_count_ffi(_sceneManager!, entity, meshNamePtr); get_morph_target_name_count_ffi(
_sceneManager!, entity, meshNamePtr, callback));
var outPtr = allocator<Char>(255); var outPtr = allocator<Char>(255);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
get_morph_target_name(_sceneManager!, entity, meshNamePtr, outPtr, i); get_morph_target_name(_sceneManager!, entity, meshNamePtr, outPtr, i);
@@ -760,9 +881,11 @@ class FilamentControllerFFI extends FilamentController {
var names = <String>[]; var names = <String>[];
var outPtr = allocator<Char>(255); var outPtr = allocator<Char>(255);
for (int i = 0; i < animationCount; i++) { 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<Utf8>().toDartString()); names.add(outPtr.cast<Utf8>().toDartString());
} }
allocator.free(outPtr);
return names; return names;
} }
@@ -896,7 +1019,8 @@ class FilamentControllerFFI extends FilamentController {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
_entities.remove(entity); _entities.remove(entity);
remove_entity_ffi(_viewer!, entity); await _withVoidCallback(
(callback) => remove_entity_ffi(_viewer!, entity, callback));
_onUnloadController.add(entity); _onUnloadController.add(entity);
} }
@@ -905,7 +1029,8 @@ class FilamentControllerFFI extends FilamentController {
if (_viewer == null) { if (_viewer == null) {
throw Exception("No viewer available, ignoring"); throw Exception("No viewer available, ignoring");
} }
clear_entities_ffi(_viewer!); await _withVoidCallback(
(callback) => clear_entities_ffi(_viewer!, callback));
for (final entity in _entities) { for (final entity in _entities) {
_onUnloadController.add(entity); _onUnloadController.add(entity);
@@ -1537,8 +1662,14 @@ class FilamentControllerFFI extends FilamentController {
indicesPtr.elementAt(i).value = indices[i]; indicesPtr.elementAt(i).value = indices[i];
} }
var entity = create_geometry_ffi(_viewer!, vertexPtr, vertices.length, var entity = await _withIntCallback((callback) => create_geometry_ffi(
indicesPtr, indices.length, materialPathPtr.cast<Char>()); _viewer!,
vertexPtr,
vertices.length,
indicesPtr,
indices.length,
materialPathPtr.cast<Char>(),
callback));
if (entity == _FILAMENT_ASSET_ERROR) { if (entity == _FILAMENT_ASSET_ERROR) {
throw Exception("Failed to create geometry"); throw Exception("Failed to create geometry");
} }

View File

@@ -984,7 +984,10 @@ external void test_collisions(
ffi.NativeFunction< ffi.NativeFunction<
ffi.Void Function( ffi.Void Function(
ffi.Pointer<ffi.Void> renderCallbackOwner)>>, ffi.Pointer<ffi.Void> renderCallbackOwner)>>,
ffi.Pointer<ffi.Void>)>( ffi.Pointer<ffi.Void>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<ffi.Void> viewer)>>)>(
symbol: 'create_filament_viewer_ffi', assetId: 'flutter_filament_plugin') symbol: 'create_filament_viewer_ffi', assetId: 'flutter_filament_plugin')
external ffi.Pointer<ffi.Void> create_filament_viewer_ffi( external ffi.Pointer<ffi.Void> create_filament_viewer_ffi(
ffi.Pointer<ffi.Void> context, ffi.Pointer<ffi.Void> context,
@@ -996,34 +999,46 @@ external ffi.Pointer<ffi.Void> create_filament_viewer_ffi(
ffi.Void Function(ffi.Pointer<ffi.Void> renderCallbackOwner)>> ffi.Void Function(ffi.Pointer<ffi.Void> renderCallbackOwner)>>
renderCallback, renderCallback,
ffi.Pointer<ffi.Void> renderCallbackOwner, ffi.Pointer<ffi.Void> renderCallbackOwner,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void> viewer)>>
callback,
); );
@ffi.Native< @ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, ffi.Void Function(
ffi.Uint32, ffi.Uint32)>( ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Void>,
ffi.Uint32,
ffi.Uint32,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: 'create_swap_chain_ffi', assetId: 'flutter_filament_plugin') symbol: 'create_swap_chain_ffi', assetId: 'flutter_filament_plugin')
external void create_swap_chain_ffi( external void create_swap_chain_ffi(
ffi.Pointer<ffi.Void> viewer, ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<ffi.Void> surface, ffi.Pointer<ffi.Void> surface,
int width, int width,
int height, int height,
); ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(
symbol: 'destroy_swap_chain_ffi', assetId: 'flutter_filament_plugin')
external void destroy_swap_chain_ffi(
ffi.Pointer<ffi.Void> viewer,
); );
@ffi.Native< @ffi.Native<
ffi.Void Function( ffi.Void Function(ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Void>, ffi.IntPtr, ffi.Uint32, ffi.Uint32)>( ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: 'destroy_swap_chain_ffi', assetId: 'flutter_filament_plugin')
external void destroy_swap_chain_ffi(
ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.IntPtr, ffi.Uint32,
ffi.Uint32, ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: 'create_render_target_ffi', assetId: 'flutter_filament_plugin') symbol: 'create_render_target_ffi', assetId: 'flutter_filament_plugin')
external void create_render_target_ffi( external void create_render_target_ffi(
ffi.Pointer<ffi.Void> viewer, ffi.Pointer<ffi.Void> viewer,
int nativeTextureId, int nativeTextureId,
int width, int width,
int height, int height,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
); );
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>( @ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>(
@@ -1059,8 +1074,8 @@ external void set_frame_interval_ffi(
); );
@ffi.Native< @ffi.Native<
ffi.Void Function( ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Uint32, ffi.Uint32,
ffi.Pointer<ffi.Void>, ffi.Uint32, ffi.Uint32, ffi.Float)>( ffi.Float, ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: 'update_viewport_and_camera_projection_ffi', symbol: 'update_viewport_and_camera_projection_ffi',
assetId: 'flutter_filament_plugin') assetId: 'flutter_filament_plugin')
external void update_viewport_and_camera_projection_ffi( external void update_viewport_and_camera_projection_ffi(
@@ -1068,6 +1083,7 @@ external void update_viewport_and_camera_projection_ffi(
int width, int width,
int height, int height,
double scaleFactor, double scaleFactor,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
); );
@ffi.Native< @ffi.Native<
@@ -1153,19 +1169,21 @@ external void remove_ibl_ffi(
); );
@ffi.Native< @ffi.Native<
EntityId Function( ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
ffi.Uint8, ffi.Uint8,
ffi.Float, ffi.Float,
ffi.Float, ffi.Float,
ffi.Float, ffi.Float,
ffi.Float, ffi.Float,
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') ffi.Bool,
external int add_light_ffi( ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
symbol: 'add_light_ffi', assetId: 'flutter_filament_plugin')
external void add_light_ffi(
ffi.Pointer<ffi.Void> viewer, ffi.Pointer<ffi.Void> viewer,
int type, int type,
double colour, double colour,
@@ -1177,6 +1195,7 @@ external int add_light_ffi(
double dirY, double dirY,
double dirZ, double dirZ,
bool shadows, bool shadows,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
); );
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId)>( @ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId)>(
@@ -1193,63 +1212,87 @@ external void clear_lights_ffi(
); );
@ffi.Native< @ffi.Native<
EntityId Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>, ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>, ffi.Int,
ffi.Int)>(symbol: 'load_glb_ffi', assetId: 'flutter_filament_plugin') ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
external int load_glb_ffi( symbol: 'load_glb_ffi', assetId: 'flutter_filament_plugin')
external void load_glb_ffi(
ffi.Pointer<ffi.Void> sceneManager, ffi.Pointer<ffi.Void> sceneManager,
ffi.Pointer<ffi.Char> assetPath, ffi.Pointer<ffi.Char> assetPath,
int numInstances, int numInstances,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
); );
@ffi.Native< @ffi.Native<
EntityId Function( ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, ffi.Size, ffi.Int)>( ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Void>,
ffi.Size,
ffi.Int,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
symbol: 'load_glb_from_buffer_ffi', assetId: 'flutter_filament_plugin') 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<ffi.Void> sceneManager, ffi.Pointer<ffi.Void> sceneManager,
ffi.Pointer<ffi.Void> data, ffi.Pointer<ffi.Void> data,
int length, int length,
int numInstances, int numInstances,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
); );
@ffi.Native< @ffi.Native<
EntityId Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Char>, ffi.Void Function(
ffi.Pointer<ffi.Char>)>( ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
symbol: 'load_gltf_ffi', assetId: 'flutter_filament_plugin') symbol: 'load_gltf_ffi', assetId: 'flutter_filament_plugin')
external int load_gltf_ffi( external void load_gltf_ffi(
ffi.Pointer<ffi.Void> sceneManager, ffi.Pointer<ffi.Void> sceneManager,
ffi.Pointer<ffi.Char> assetPath, ffi.Pointer<ffi.Char> assetPath,
ffi.Pointer<ffi.Char> relativePath, ffi.Pointer<ffi.Char> relativePath,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
); );
@ffi.Native<EntityId Function(ffi.Pointer<ffi.Void>, EntityId)>( @ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
symbol: 'create_instance_ffi', assetId: 'flutter_filament_plugin') symbol: 'create_instance_ffi', assetId: 'flutter_filament_plugin')
external int create_instance_ffi( external void create_instance_ffi(
ffi.Pointer<ffi.Void> sceneManager, ffi.Pointer<ffi.Void> sceneManager,
int entityId, int entityId,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
); );
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId)>( @ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: 'remove_entity_ffi', assetId: 'flutter_filament_plugin') symbol: 'remove_entity_ffi', assetId: 'flutter_filament_plugin')
external void remove_entity_ffi( external void remove_entity_ffi(
ffi.Pointer<ffi.Void> viewer, ffi.Pointer<ffi.Void> viewer,
int asset, int asset,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
); );
@ffi.Native<ffi.Void Function(ffi.Pointer<ffi.Void>)>( @ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: 'clear_entities_ffi', assetId: 'flutter_filament_plugin') symbol: 'clear_entities_ffi', assetId: 'flutter_filament_plugin')
external void clear_entities_ffi( external void clear_entities_ffi(
ffi.Pointer<ffi.Void> viewer, ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
); );
@ffi.Native< @ffi.Native<
ffi.Bool Function( ffi.Bool Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Pointer<ffi.Char>)>( ffi.Pointer<ffi.Void>,
EntityId,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: 'set_camera_ffi', assetId: 'flutter_filament_plugin') symbol: 'set_camera_ffi', assetId: 'flutter_filament_plugin')
external bool set_camera_ffi( external bool set_camera_ffi(
ffi.Pointer<ffi.Void> viewer, ffi.Pointer<ffi.Void> viewer,
int asset, int asset,
ffi.Pointer<ffi.Char> nodeName, ffi.Pointer<ffi.Char> nodeName,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
); );
@ffi.Native< @ffi.Native<
@@ -1296,27 +1339,40 @@ external void stop_animation_ffi(
int index, int index,
); );
@ffi.Native<ffi.Int Function(ffi.Pointer<ffi.Void>, EntityId)>( @ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>)>(
symbol: 'get_animation_count_ffi', assetId: 'flutter_filament_plugin') symbol: 'get_animation_count_ffi', assetId: 'flutter_filament_plugin')
external int get_animation_count_ffi( external void get_animation_count_ffi(
ffi.Pointer<ffi.Void> sceneManager, ffi.Pointer<ffi.Void> sceneManager,
int asset, int asset,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int)>> callback,
); );
@ffi.Native< @ffi.Native<
ffi.Void Function( ffi.Void Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Pointer<ffi.Char>, ffi.Int)>( ffi.Pointer<ffi.Void>,
EntityId,
ffi.Pointer<ffi.Char>,
ffi.Int,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: 'get_animation_name_ffi', assetId: 'flutter_filament_plugin') symbol: 'get_animation_name_ffi', assetId: 'flutter_filament_plugin')
external void get_animation_name_ffi( external void get_animation_name_ffi(
ffi.Pointer<ffi.Void> sceneManager, ffi.Pointer<ffi.Void> sceneManager,
int asset, int asset,
ffi.Pointer<ffi.Char> outPtr, ffi.Pointer<ffi.Char> outPtr,
int index, int index,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
); );
@ffi.Native< @ffi.Native<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId, ffi.Void Function(
ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>, ffi.Int)>( ffi.Pointer<ffi.Void>,
EntityId,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Char>,
ffi.Int,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>(
symbol: 'get_morph_target_name_ffi', assetId: 'flutter_filament_plugin') symbol: 'get_morph_target_name_ffi', assetId: 'flutter_filament_plugin')
external void get_morph_target_name_ffi( external void get_morph_target_name_ffi(
ffi.Pointer<ffi.Void> sceneManager, ffi.Pointer<ffi.Void> sceneManager,
@@ -1324,17 +1380,22 @@ external void get_morph_target_name_ffi(
ffi.Pointer<ffi.Char> meshName, ffi.Pointer<ffi.Char> meshName,
ffi.Pointer<ffi.Char> outPtr, ffi.Pointer<ffi.Char> outPtr,
int index, int index,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> callback,
); );
@ffi.Native< @ffi.Native<
ffi.Int Function( ffi.Void Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Pointer<ffi.Char>)>( ffi.Pointer<ffi.Void>,
EntityId,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int32)>>)>(
symbol: 'get_morph_target_name_count_ffi', symbol: 'get_morph_target_name_count_ffi',
assetId: 'flutter_filament_plugin') assetId: 'flutter_filament_plugin')
external int get_morph_target_name_count_ffi( external void get_morph_target_name_count_ffi(
ffi.Pointer<ffi.Void> sceneManager, ffi.Pointer<ffi.Void> sceneManager,
int asset, int asset,
ffi.Pointer<ffi.Char> meshName, ffi.Pointer<ffi.Char> meshName,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Int32)>> callback,
); );
@ffi.Native< @ffi.Native<
@@ -1350,7 +1411,7 @@ external void set_morph_target_weights_ffi(
); );
@ffi.Native< @ffi.Native<
ffi.Bool Function( ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
EntityId, EntityId,
ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>,
@@ -1358,9 +1419,10 @@ external void set_morph_target_weights_ffi(
ffi.Pointer<ffi.Int>, ffi.Pointer<ffi.Int>,
ffi.Int, ffi.Int,
ffi.Int, ffi.Int,
ffi.Float)>( ffi.Float,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>>)>(
symbol: 'set_morph_animation_ffi', assetId: 'flutter_filament_plugin') symbol: 'set_morph_animation_ffi', assetId: 'flutter_filament_plugin')
external bool set_morph_animation_ffi( external void set_morph_animation_ffi(
ffi.Pointer<ffi.Void> sceneManager, ffi.Pointer<ffi.Void> sceneManager,
int asset, int asset,
ffi.Pointer<ffi.Char> entityName, ffi.Pointer<ffi.Char> entityName,
@@ -1369,22 +1431,25 @@ external bool set_morph_animation_ffi(
int numMorphTargets, int numMorphTargets,
int numFrames, int numFrames,
double frameLengthInMs, double frameLengthInMs,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> callback,
); );
@ffi.Native< @ffi.Native<
ffi.Bool Function( ffi.Void Function(
ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
EntityId, EntityId,
ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Float>, ffi.Pointer<ffi.Float>,
ffi.Pointer<ffi.Char>)>( ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>>)>(
symbol: 'set_bone_transform_ffi', assetId: 'flutter_filament_plugin') symbol: 'set_bone_transform_ffi', assetId: 'flutter_filament_plugin')
external bool set_bone_transform_ffi( external void set_bone_transform_ffi(
ffi.Pointer<ffi.Void> sceneManager, ffi.Pointer<ffi.Void> sceneManager,
int asset, int asset,
ffi.Pointer<ffi.Char> entityName, ffi.Pointer<ffi.Char> entityName,
ffi.Pointer<ffi.Float> transform, ffi.Pointer<ffi.Float> transform,
ffi.Pointer<ffi.Char> boneName, ffi.Pointer<ffi.Char> boneName,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Bool)>> callback,
); );
@ffi.Native< @ffi.Native<
@@ -1441,16 +1506,23 @@ external void reset_to_rest_pose_ffi(
external void ios_dummy_ffi(); external void ios_dummy_ffi();
@ffi.Native< @ffi.Native<
EntityId Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Float>, ffi.Void Function(
ffi.Int, ffi.Pointer<ffi.Uint16>, ffi.Int, ffi.Pointer<ffi.Char>)>( ffi.Pointer<ffi.Void>,
ffi.Pointer<ffi.Float>,
ffi.Int,
ffi.Pointer<ffi.Uint16>,
ffi.Int,
ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>>)>(
symbol: 'create_geometry_ffi', assetId: 'flutter_filament_plugin') symbol: 'create_geometry_ffi', assetId: 'flutter_filament_plugin')
external int create_geometry_ffi( external void create_geometry_ffi(
ffi.Pointer<ffi.Void> viewer, ffi.Pointer<ffi.Void> viewer,
ffi.Pointer<ffi.Float> vertices, ffi.Pointer<ffi.Float> vertices,
int numVertices, int numVertices,
ffi.Pointer<ffi.Uint16> indices, ffi.Pointer<ffi.Uint16> indices,
int numIndices, int numIndices,
ffi.Pointer<ffi.Char> materialPath, ffi.Pointer<ffi.Char> materialPath,
ffi.Pointer<ffi.NativeFunction<ffi.Void Function(EntityId)>> callback,
); );
final class __mbstate_t extends ffi.Union { final class __mbstate_t extends ffi.Union {

View File

@@ -124,15 +124,20 @@ class _FilamentGestureDetectorMobileState
double _lastScale = 0; double _lastScale = 0;
// pinch zoom on mobile // pinch zoom on mobile
// couldn't find any equivalent for pointerCount in Listener so we use two widgets: // couldn't find any equivalent for pointerCount in Listener (?) so we use a GestureDetector
// - outer is a GestureDetector only for pinch zoom
// - inner is a Listener for all other gestures (including scroll zoom on desktop)
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Stack(children: [ return Stack(children: [
Positioned.fill( Positioned.fill(
child: GestureDetector( 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: () { onDoubleTap: () {
setState(() { setState(() {
_rotateOnPointerMove = !_rotateOnPointerMove; _rotateOnPointerMove = !_rotateOnPointerMove;

View File

@@ -33,7 +33,7 @@ A new Flutter plugin project.
s.pod_target_xcconfig = { s.pod_target_xcconfig = {
'DEFINES_MODULE' => 'YES', 'DEFINES_MODULE' => 'YES',
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17", "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)"', 'OTHER_CFLAGS' => '"-fvisibility=default" "$(inherited)"',
'USER_HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}/include" "${PODS_TARGET_SRCROOT}/include/filament" "$(inherited)"', 'USER_HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}/include" "${PODS_TARGET_SRCROOT}/include/filament" "$(inherited)"',
'ALWAYS_SEARCH_USER_PATHS' => 'YES', 'ALWAYS_SEARCH_USER_PATHS' => 'YES',