update example project

This commit is contained in:
Nick Fisher
2024-02-15 13:47:22 +08:00
parent 0b315f3dfe
commit da123d6274
5 changed files with 108 additions and 19 deletions

View File

@@ -1,26 +1,36 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_filament/entities/entity_transform_controller.dart';
import 'package:flutter_filament/filament_controller.dart'; import 'package:flutter_filament/filament_controller.dart';
import 'package:flutter_filament/widgets/entity_controller_mouse_widget.dart';
import 'package:flutter_filament/widgets/filament_gesture_detector.dart'; import 'package:flutter_filament/widgets/filament_gesture_detector.dart';
import 'package:flutter_filament/widgets/filament_widget.dart'; import 'package:flutter_filament/widgets/filament_widget.dart';
class ExampleViewport extends StatelessWidget { class ExampleViewport extends StatelessWidget {
final FilamentController? controller; final FilamentController? controller;
final EntityTransformController? entityTransformController;
final EdgeInsets padding; final EdgeInsets padding;
final FocusNode keyboardFocusNode;
const ExampleViewport( const ExampleViewport(
{super.key, required this.controller, required this.padding}); {super.key,
required this.controller,
required this.padding,
required this.keyboardFocusNode,
this.entityTransformController});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return controller != null return controller != null
? Padding( ? Padding(
padding: padding, padding: padding,
child: FilamentGestureDetector( child: EntityTransformMouseControllerWidget(
showControlOverlay: true, transformController: entityTransformController,
controller: controller!, child: FilamentGestureDetector(
child: FilamentWidget( showControlOverlay: true,
controller: controller!, controller: controller!,
))) child: FilamentWidget(
controller: controller!,
))))
: Container(); : Container();
} }
} }

View File

@@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_filament/entities/entity_transform_controller.dart';
import 'package:flutter_filament/filament_controller_ffi.dart'; import 'package:flutter_filament/filament_controller_ffi.dart';
import 'package:flutter_filament_example/camera_matrix_overlay.dart'; import 'package:flutter_filament_example/camera_matrix_overlay.dart';
import 'package:flutter_filament_example/menus/controller_menu.dart'; import 'package:flutter_filament_example/menus/controller_menu.dart';
@@ -11,9 +12,11 @@ import 'package:flutter_filament_example/menus/scene_menu.dart';
import 'package:flutter_filament/filament_controller.dart'; import 'package:flutter_filament/filament_controller.dart';
const loadDefaultScene = bool.hasEnvironment('--load-default-scene'); const loadDefaultScene = bool.hasEnvironment('--load-default-scene');
const foo = String.fromEnvironment('foo');
void main() async { void main() async {
print(loadDefaultScene); print(loadDefaultScene);
print(foo);
runApp(const MyApp()); runApp(const MyApp());
} }
@@ -99,6 +102,9 @@ class ExampleWidgetState extends State<ExampleWidget> {
await _filamentController!.loadGlb("assets/shapes/shapes.glb")); await _filamentController!.loadGlb("assets/shapes/shapes.glb"));
ExampleWidgetState.animations = ExampleWidgetState.animations =
await _filamentController!.getAnimationNames(assets.first); await _filamentController!.getAnimationNames(assets.first);
await _filamentController!
.setCameraManipulatorOptions(zoomSpeed: 1.0);
hasSkybox = true; hasSkybox = true;
rendering = true; rendering = true;
}); });
@@ -112,6 +118,10 @@ class ExampleWidgetState extends State<ExampleWidget> {
_listener.cancel(); _listener.cancel();
} }
EntityTransformController? _transformController;
FilamentEntity? _controlled;
final _sharedFocusNode = FocusNode();
Widget _assetEntry(FilamentEntity entity) { Widget _assetEntry(FilamentEntity entity) {
return Row(children: [ return Row(children: [
Text("Asset ${entity}"), Text("Asset ${entity}"),
@@ -121,13 +131,28 @@ class ExampleWidgetState extends State<ExampleWidget> {
await _filamentController!.transformToUnitCube(entity); await _filamentController!.transformToUnitCube(entity);
}, },
icon: const Icon(Icons.settings_overscan_outlined)), icon: const Icon(Icons.settings_overscan_outlined)),
IconButton(
onPressed: () async {
_transformController?.dispose();
if (_controlled == entity) {
_controlled = null;
} else {
_controlled = entity;
_transformController?.dispose();
_transformController =
EntityTransformController(_filamentController!, entity);
}
setState(() {});
},
icon: Icon(Icons.control_camera,
color: _controlled == entity ? Colors.green : Colors.black)),
IconButton( IconButton(
onPressed: () async { onPressed: () async {
await _filamentController!.removeAsset(entity); await _filamentController!.removeAsset(entity);
assets.remove(entity); assets.remove(entity);
setState(() {}); setState(() {});
}, },
icon: const Icon(Icons.cancel_sharp)) icon: const Icon(Icons.cancel_sharp)),
]); ]);
; ;
} }
@@ -137,9 +162,10 @@ class ExampleWidgetState extends State<ExampleWidget> {
return Stack(children: [ return Stack(children: [
Positioned.fill( Positioned.fill(
child: ExampleViewport( child: ExampleViewport(
controller: _filamentController, controller: _filamentController,
padding: _viewportMargin, entityTransformController: _transformController,
), padding: _viewportMargin,
keyboardFocusNode: _sharedFocusNode),
), ),
Positioned( Positioned(
bottom: 80, bottom: 80,
@@ -147,7 +173,7 @@ class ExampleWidgetState extends State<ExampleWidget> {
height: 200, height: 200,
width: 300, width: 300,
child: Container( child: Container(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 10), padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
height: 100, height: 100,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30), borderRadius: BorderRadius.circular(30),
@@ -169,6 +195,7 @@ class ExampleWidgetState extends State<ExampleWidget> {
child: child:
Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ Row(crossAxisAlignment: CrossAxisAlignment.center, children: [
ControllerMenu( ControllerMenu(
sharedFocusNode: _sharedFocusNode,
controller: _filamentController, controller: _filamentController,
onControllerDestroyed: () {}, onControllerDestroyed: () {},
onControllerCreated: (controller) { onControllerCreated: (controller) {
@@ -188,6 +215,7 @@ class ExampleWidgetState extends State<ExampleWidget> {
}); });
}), }),
SceneMenu( SceneMenu(
sharedFocusNode: _sharedFocusNode,
controller: _filamentController, controller: _filamentController,
), ),
GestureDetector( GestureDetector(

View File

@@ -4,6 +4,7 @@ import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_filament/animations/animation_data.dart'; import 'package:flutter_filament/animations/animation_data.dart';
import 'package:flutter_filament/filament_controller.dart'; import 'package:flutter_filament/filament_controller.dart';
import 'package:flutter_filament_example/main.dart'; import 'package:flutter_filament_example/main.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
@@ -27,8 +28,22 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
Widget _shapesSubmenu() { Widget _shapesSubmenu() {
var children = [ var children = [
MenuItemButton( MenuItemButton(
closeOnActivate: false,
onPressed: () async { onPressed: () async {
Timer.periodic(Duration(milliseconds: 50), (_) async { var entity = await widget.controller
.getChildEntity(ExampleWidgetState.assets.last, "Cylinder");
await showDialog(
context: context,
builder: (BuildContext context) {
return Center(
child: Container(
color: Colors.white, child: Text(entity.toString())));
});
},
child: const Text('Find Cylinder entity by name')),
MenuItemButton(
onPressed: () async {
Timer.periodic(const Duration(milliseconds: 50), (_) async {
await widget.controller.setBoneTransform( await widget.controller.setBoneTransform(
ExampleWidgetState.assets.last, ExampleWidgetState.assets.last,
"Cylinder", "Cylinder",
@@ -143,11 +158,40 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
return SubmenuButton(menuChildren: children, child: const Text("Shapes")); return SubmenuButton(menuChildren: children, child: const Text("Shapes"));
} }
Widget _geometrySubmenu() {
return MenuItemButton(
onPressed: () async {
await widget.controller.createGeometry([
-1,
0,
-1,
-1,
0,
1,
1,
0,
1,
1,
0,
-1,
], [
0,
1,
2,
2,
3,
0
], "asset://assets/solidcolor.filamat");
},
child: const Text("Custom geometry"));
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SubmenuButton( return SubmenuButton(
menuChildren: [ menuChildren: [
_shapesSubmenu(), _shapesSubmenu(),
_geometrySubmenu(),
MenuItemButton( MenuItemButton(
onPressed: () async { onPressed: () async {
ExampleWidgetState.directionalLight = await widget.controller ExampleWidgetState.directionalLight = await widget.controller

View File

@@ -9,11 +9,13 @@ class ControllerMenu extends StatefulWidget {
final FilamentController? controller; final FilamentController? controller;
final void Function(FilamentController controller) onControllerCreated; final void Function(FilamentController controller) onControllerCreated;
final void Function() onControllerDestroyed; final void Function() onControllerDestroyed;
final FocusNode sharedFocusNode;
ControllerMenu( ControllerMenu(
{this.controller, {this.controller,
required this.onControllerCreated, required this.onControllerCreated,
required this.onControllerDestroyed}); required this.onControllerDestroyed,
required this.sharedFocusNode});
@override @override
State<StatefulWidget> createState() => _ControllerMenuState(); State<StatefulWidget> createState() => _ControllerMenuState();
@@ -21,7 +23,6 @@ class ControllerMenu extends StatefulWidget {
class _ControllerMenuState extends State<ControllerMenu> { class _ControllerMenuState extends State<ControllerMenu> {
FilamentController? _filamentController; FilamentController? _filamentController;
final FocusNode _buttonFocusNode = FocusNode(debugLabel: 'Camera Menu');
void _createController({String? uberArchivePath}) { void _createController({String? uberArchivePath}) {
if (_filamentController != null) { if (_filamentController != null) {
@@ -57,8 +58,10 @@ class _ControllerMenuState extends State<ControllerMenu> {
child: const Text("Create FilamentViewer"), child: const Text("Create FilamentViewer"),
onPressed: _filamentController == null onPressed: _filamentController == null
? null ? null
: () { : () async {
_filamentController!.createViewer(); await _filamentController!.createViewer();
await _filamentController!
.setCameraManipulatorOptions(zoomSpeed: 1.0);
}, },
), ),
MenuItemButton( MenuItemButton(
@@ -96,7 +99,7 @@ class _ControllerMenuState extends State<ControllerMenu> {
]); ]);
} }
return MenuAnchor( return MenuAnchor(
childFocusNode: _buttonFocusNode, childFocusNode: widget.sharedFocusNode,
menuChildren: items, menuChildren: items,
builder: builder:
(BuildContext context, MenuController controller, Widget? child) { (BuildContext context, MenuController controller, Widget? child) {

View File

@@ -7,8 +7,10 @@ import 'package:flutter_filament_example/menus/rendering_submenu.dart';
class SceneMenu extends StatefulWidget { class SceneMenu extends StatefulWidget {
final FilamentController? controller; final FilamentController? controller;
final FocusNode sharedFocusNode;
const SceneMenu({super.key, required this.controller}); const SceneMenu(
{super.key, required this.controller, required this.sharedFocusNode});
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() {
@@ -34,6 +36,8 @@ class _SceneMenuState extends State<SceneMenu> {
widget.controller?.hasViewer ?? ValueNotifier<bool>(false), widget.controller?.hasViewer ?? ValueNotifier<bool>(false),
builder: (BuildContext ctx, bool hasViewer, Widget? child) { builder: (BuildContext ctx, bool hasViewer, Widget? child) {
return MenuAnchor( return MenuAnchor(
onClose: () {},
childFocusNode: widget.sharedFocusNode,
menuChildren: widget.controller == null menuChildren: widget.controller == null
? [] ? []
: <Widget>[ : <Widget>[