expose method for retrieving all child entities

This commit is contained in:
Nick Fisher
2024-03-26 00:24:21 +08:00
parent 849ad6c530
commit b357144a79
13 changed files with 101 additions and 21 deletions

View File

@@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -129,7 +130,7 @@ class ExampleWidgetState extends State<ExampleWidget> {
), ),
EntityListWidget(controller: _filamentController), EntityListWidget(controller: _filamentController),
Positioned( Positioned(
bottom: 0, bottom: Platform.isIOS ? 30 : 0,
left: 0, left: 0,
right: 10, right: 10,
height: 30, height: 30,
@@ -164,9 +165,8 @@ class ExampleWidgetState extends State<ExampleWidget> {
), ),
GestureDetector( GestureDetector(
onTap: () async { onTap: () async {
await _filamentController!.loadGlb( await _filamentController!
'assets/shapes/shapes.glb', .loadGlb('assets/shapes/shapes.glb', numInstances: 1);
numInstances: 10);
}, },
child: Container( child: Container(
color: Colors.transparent, color: Colors.transparent,

View File

@@ -215,6 +215,13 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
}, },
child: const Text("Add point light"), child: const Text("Add point light"),
), ),
MenuItemButton(
onPressed: () async {
await widget.controller
.addLight(3, 6500, 15000000, 0, 1, 0, 0, -1, 0, true);
},
child: const Text("Add spot light"),
),
MenuItemButton( MenuItemButton(
onPressed: () async { onPressed: () async {
await widget.controller.clearLights(); await widget.controller.clearLights();

View File

@@ -195,7 +195,7 @@ namespace flutter_filament
uint32_t _imageWidth = 0; uint32_t _imageWidth = 0;
mat4f _imageScale; mat4f _imageScale;
Texture *_imageTexture = nullptr; Texture *_imageTexture = nullptr;
utils::Entity *_imageEntity = nullptr; utils::Entity _imageEntity;
VertexBuffer *_imageVb = nullptr; VertexBuffer *_imageVb = nullptr;
IndexBuffer *_imageIb = nullptr; IndexBuffer *_imageIb = nullptr;
Material *_imageMaterial = nullptr; Material *_imageMaterial = nullptr;

View File

@@ -188,6 +188,7 @@ extern "C"
FLUTTER_PLUGIN_EXPORT const char *get_name_for_entity(void *const sceneManager, const EntityId entityId); FLUTTER_PLUGIN_EXPORT const char *get_name_for_entity(void *const sceneManager, const EntityId entityId);
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);
FLUTTER_PLUGIN_EXPORT int get_entity_count(void *const sceneManager, const EntityId target, bool renderableOnly); FLUTTER_PLUGIN_EXPORT int get_entity_count(void *const sceneManager, const EntityId target, bool renderableOnly);
FLUTTER_PLUGIN_EXPORT void get_entities(void *const sceneManager, const EntityId target, bool renderableOnly, EntityId* out);
FLUTTER_PLUGIN_EXPORT const char* get_entity_name_at(void *const sceneManager, const EntityId target, int index, bool renderableOnly); FLUTTER_PLUGIN_EXPORT const char* get_entity_name_at(void *const sceneManager, const EntityId target, int index, bool renderableOnly);
FLUTTER_PLUGIN_EXPORT void set_recording(void *const viewer, bool recording); FLUTTER_PLUGIN_EXPORT void set_recording(void *const viewer, bool recording);
FLUTTER_PLUGIN_EXPORT void set_recording_output_directory(void *const viewer, const char* outputDirectory); FLUTTER_PLUGIN_EXPORT void set_recording_output_directory(void *const viewer, const char* outputDirectory);

View File

@@ -130,6 +130,7 @@ namespace flutter_filament
EntityId entityId, EntityId entityId,
const char *entityName); const char *entityName);
int getEntityCount(EntityId entity, bool renderableOnly); int getEntityCount(EntityId entity, bool renderableOnly);
void getEntities(EntityId entity, bool renderableOnly, EntityId *out);
const char* getEntityNameAt(EntityId entity, int index, bool renderableOnly); const char* getEntityNameAt(EntityId entity, int index, bool renderableOnly);
void addCollisionComponent(EntityId entity, void (*onCollisionCallback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform); void addCollisionComponent(EntityId entity, void (*onCollisionCallback)(const EntityId entityId1, const EntityId entityId2), bool affectsCollidingTransform);
void removeCollisionComponent(EntityId entityId); void removeCollisionComponent(EntityId entityId);

View File

@@ -238,17 +238,16 @@ namespace flutter_filament
_imageIb->setBuffer(*_engine, {sFullScreenTriangleIndices, _imageIb->setBuffer(*_engine, {sFullScreenTriangleIndices,
sizeof(sFullScreenTriangleIndices)}); sizeof(sFullScreenTriangleIndices)});
utils::Entity imageEntity = em.create(); _imageEntity = em.create();
RenderableManager::Builder(1) RenderableManager::Builder(1)
.boundingBox({{}, {1.0f, 1.0f, 1.0f}}) .boundingBox({{}, {1.0f, 1.0f, 1.0f}})
.material(0, _imageMaterial->getDefaultInstance()) .material(0, _imageMaterial->getDefaultInstance())
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, _imageVb, .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, _imageVb,
_imageIb, 0, 3) _imageIb, 0, 3)
.culling(false) .culling(false)
.build(*_engine, imageEntity); .build(*_engine, _imageEntity);
_imageEntity = &imageEntity; _scene->addEntity(_imageEntity);
_scene->addEntity(imageEntity); Log("Added imageEntity %d", _imageEntity);
Log("Added imageEntity %d", imageEntity);
} }
void FilamentViewer::setAntiAliasing(bool msaa, bool fxaa, bool taa) { void FilamentViewer::setAntiAliasing(bool msaa, bool fxaa, bool taa) {
@@ -335,6 +334,8 @@ namespace flutter_filament
_lights.push_back(light); _lights.push_back(light);
auto entityId = Entity::smuggle(light); auto entityId = Entity::smuggle(light);
auto transformInstance = transformManager.getInstance(light);
transformManager.setTransform(transformInstance, math::mat4::translation(math::float3 { posX, posY, posZ}));
Log("Added light under entity ID %d of type %d with colour %f intensity %f at (%f, %f, %f) with direction (%f, %f, %f) with shadows %d", entityId, t, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows); Log("Added light under entity ID %d of type %d with colour %f intensity %f at (%f, %f, %f) with direction (%f, %f, %f) with shadows %d", entityId, t, colour, intensity, posX, posY, posZ, dirX, dirY, dirZ, shadows);
return entityId; return entityId;
} }
@@ -885,7 +886,7 @@ namespace flutter_filament
ResourceBuffer skyboxBuffer = _resourceLoaderWrapper->load(skyboxPath); ResourceBuffer skyboxBuffer = _resourceLoaderWrapper->load(skyboxPath);
// because this will go out of scope before the texture callback is invoked, we need to make a copy to the heap // because this will go out of scope before the texture callback is invoked, we need to make a copy of the variable itself (not its contents)
ResourceBuffer *skyboxBufferCopy = new ResourceBuffer(skyboxBuffer); ResourceBuffer *skyboxBufferCopy = new ResourceBuffer(skyboxBuffer);
if (skyboxBuffer.size <= 0) if (skyboxBuffer.size <= 0)
@@ -1449,9 +1450,12 @@ namespace flutter_filament
void FilamentViewer::pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y)) void FilamentViewer::pick(uint32_t x, uint32_t y, void (*callback)(EntityId entityId, int x, int y))
{ {
_view->pick(x, y, [=](filament::View::PickingQueryResult const &result) _view->pick(x, y, [=](filament::View::PickingQueryResult const &result)
{ {
callback(Entity::smuggle(result.renderable), x, y); if(result.renderable != _imageEntity) {
callback(Entity::smuggle(result.renderable), x, y);
}
}); });
} }

View File

@@ -562,6 +562,10 @@ extern "C"
return ((SceneManager *)sceneManager)->getEntityCount(target, renderableOnly); return ((SceneManager *)sceneManager)->getEntityCount(target, renderableOnly);
} }
FLUTTER_PLUGIN_EXPORT void get_entities(void *const sceneManager, const EntityId target, bool renderableOnly, EntityId* out) {
((SceneManager *)sceneManager)->getEntities(target, renderableOnly, out);
}
FLUTTER_PLUGIN_EXPORT const char* get_entity_name_at(void *const sceneManager, const EntityId target, int index, bool renderableOnly) { FLUTTER_PLUGIN_EXPORT const char* get_entity_name_at(void *const sceneManager, const EntityId target, int index, bool renderableOnly) {
return ((SceneManager *)sceneManager)->getEntityNameAt(target, index, renderableOnly); return ((SceneManager *)sceneManager)->getEntityNameAt(target, index, renderableOnly);
} }

View File

@@ -1529,6 +1529,34 @@ namespace flutter_filament
return instance->getEntityCount(); return instance->getEntityCount();
} }
void SceneManager::getEntities(EntityId entityId, bool renderableOnly, EntityId* out) {
const auto *instance = getInstanceByEntityId(entityId);
if(!instance) {
auto asset = getAssetByEntityId(entityId);
if(asset) {
instance = asset->getInstance();
} else {
return;
}
}
if(renderableOnly) {
int count = 0;
const auto& rm = _engine->getRenderableManager();
const Entity *entities = instance->getEntities();
int offset = 0;
for(int i=0; i < instance->getEntityCount(); i++) {
if(rm.hasComponent(entities[i])) {
out[offset] = Entity::smuggle(entities[i]);
}
}
} else {
for(int i=0;i < instance->getEntityCount(); i++) {
out[i] = Entity::smuggle(instance->getEntities()[i]);
}
}
}
const char* SceneManager::getEntityNameAt(EntityId entityId, int index, bool renderableOnly) { const char* SceneManager::getEntityNameAt(EntityId entityId, int index, bool renderableOnly) {
const auto *instance = getInstanceByEntityId(entityId); const auto *instance = getInstanceByEntityId(entityId);
if(!instance) { if(!instance) {

View File

@@ -65,6 +65,9 @@ class Gizmo {
} }
void detach() async { void detach() async {
await controller.setParent(x, 0);
await controller.setParent(y, 0);
await controller.setParent(z, 0);
await controller.hide(x, null); await controller.hide(x, null);
await controller.hide(y, null); await controller.hide(y, null);
await controller.hide(z, null); await controller.hide(z, null);

View File

@@ -576,6 +576,12 @@ abstract class FilamentController {
double orbitSpeedY = 0.01, double orbitSpeedY = 0.01,
double zoomSpeed = 0.01}); double zoomSpeed = 0.01});
///
/// Returns all child entities under [parent].
///
Future<List<FilamentEntity>> getChildEntities(
FilamentEntity parent, bool renderableOnly);
/// ///
/// Finds the child entity named [childName] associated with the given parent. /// Finds the child entity named [childName] associated with the given parent.
/// Usually, [parent] will be the return value from [loadGlb]/[loadGltf] and [childName] will be the name of a node/mesh. /// Usually, [parent] will be the return value from [loadGlb]/[loadGltf] and [childName] will be the name of a node/mesh.
@@ -584,9 +590,9 @@ abstract class FilamentController {
FilamentEntity parent, String childName); FilamentEntity parent, String childName);
/// ///
/// List all child entities under the given entity. /// List the name of all child entities under the given entity.
/// ///
Future<List<String>> getChildEntities(FilamentEntity entity, Future<List<String>> getChildEntityNames(FilamentEntity entity,
{bool renderableOnly = true}); {bool renderableOnly = true});
/// ///

View File

@@ -358,7 +358,7 @@ class FilamentControllerFFI extends FilamentController {
get_gizmo(_sceneManager!, out); get_gizmo(_sceneManager!, out);
var gizmo = Gizmo(out[0], out[1], out[2], this); var gizmo = Gizmo(out[0], out[1], out[2], this);
allocator.free(out); allocator.free(out);
_scene = SceneImpl(gizmo); _scene = SceneImpl(gizmo, this);
hasViewer.value = true; hasViewer.value = true;
_creating = false; _creating = false;
@@ -1504,8 +1504,19 @@ class FilamentControllerFFI extends FilamentController {
return childEntity; return childEntity;
} }
Future<List<FilamentEntity>> getChildEntities(
FilamentEntity parent, bool renderableOnly) async {
var count = get_entity_count(_sceneManager!, parent, renderableOnly);
var out = allocator<Int32>(count);
get_entities(_sceneManager!, parent, renderableOnly, out);
var outList =
List.generate(count, (index) => out[index]).cast<FilamentEntity>();
allocator.free(out);
return outList;
}
@override @override
Future<List<String>> getChildEntities(FilamentEntity entity, Future<List<String>> getChildEntityNames(FilamentEntity entity,
{bool renderableOnly = false}) async { {bool renderableOnly = false}) async {
var count = get_entity_count(_sceneManager!, entity, renderableOnly); var count = get_entity_count(_sceneManager!, entity, renderableOnly);
var names = <String>[]; var names = <String>[];

View File

@@ -885,6 +885,17 @@ external int get_entity_count(
bool renderableOnly, bool renderableOnly,
); );
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Bool, ffi.Pointer<EntityId>)>(
symbol: 'get_entities', assetId: 'flutter_filament_plugin')
external void get_entities(
ffi.Pointer<ffi.Void> sceneManager,
int target,
bool renderableOnly,
ffi.Pointer<EntityId> out,
);
@ffi.Native< @ffi.Native<
ffi.Pointer<ffi.Char> Function( ffi.Pointer<ffi.Char> Function(
ffi.Pointer<ffi.Void>, EntityId, ffi.Int, ffi.Bool)>( ffi.Pointer<ffi.Void>, EntityId, ffi.Int, ffi.Bool)>(

View File

@@ -9,7 +9,9 @@ class SceneImpl extends Scene {
final Gizmo _gizmo; final Gizmo _gizmo;
Gizmo get gizmo => _gizmo; Gizmo get gizmo => _gizmo;
SceneImpl(this._gizmo); FilamentController controller;
SceneImpl(this._gizmo, this.controller);
@override @override
FilamentEntity? selected; FilamentEntity? selected;
@@ -35,8 +37,9 @@ class SceneImpl extends Scene {
_onUpdatedController.add(true); _onUpdatedController.add(true);
} }
void unregisterLight(FilamentEntity entity) { void unregisterLight(FilamentEntity entity) async {
if (selected == entity) { var children = await controller.getChildEntities(entity, true);
if (selected == entity || children.contains(selected)) {
selected = null; selected = null;
_gizmo.detach(); _gizmo.detach();
} }
@@ -45,8 +48,9 @@ class SceneImpl extends Scene {
_onUpdatedController.add(true); _onUpdatedController.add(true);
} }
void unregisterEntity(FilamentEntity entity) { void unregisterEntity(FilamentEntity entity) async {
if (selected == entity) { var children = await controller.getChildEntities(entity, true);
if (selected == entity || children.contains(selected)) {
selected = null; selected = null;
_gizmo.detach(); _gizmo.detach();
} }