add (very rough) gizmo, restructure Dart package into library, add EntityListWidget

This commit is contained in:
Nick Fisher
2024-03-25 22:21:37 +08:00
parent 66ae0a4d08
commit 357c585d44
53 changed files with 2913 additions and 568 deletions

View File

@@ -1,22 +1,19 @@
import 'dart:async';
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_example/camera_matrix_overlay.dart';
import 'package:flutter_filament_example/menus/controller_menu.dart';
import 'package:flutter_filament_example/example_viewport.dart';
import 'package:flutter_filament_example/picker_result_widget.dart';
import 'package:flutter_filament_example/menus/scene_menu.dart';
import 'package:flutter_filament/filament_controller.dart';
import 'package:flutter_filament/flutter_filament.dart';
const loadDefaultScene = bool.hasEnvironment('--load-default-scene');
const foo = String.fromEnvironment('foo');
void main() async {
print(loadDefaultScene);
print(foo);
runApp(const MyApp());
}
@@ -31,7 +28,15 @@ class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
theme: ThemeData(
useMaterial3: true,
textTheme: const TextTheme(
labelLarge: TextStyle(fontSize: 12),
displayMedium: TextStyle(fontSize: 12),
headlineMedium: const TextStyle(fontSize: 12),
titleMedium: TextStyle(fontSize: 12),
bodyLarge: TextStyle(fontSize: 14),
bodyMedium: TextStyle(fontSize: 12))),
// showPerformanceOverlay: true,
home: const Scaffold(body: ExampleWidget()));
}
@@ -69,12 +74,6 @@ class ExampleWidgetState extends State<ExampleWidget> {
static bool hasSkybox = false;
static bool coneHidden = false;
static final assets = <FilamentEntity>[];
static FilamentEntity? flightHelmet;
static FilamentEntity? buster;
static FilamentEntity? directionalLight;
static bool loop = false;
static final showProjectionMatrices = ValueNotifier<bool>(false);
@@ -90,13 +89,13 @@ class ExampleWidgetState extends State<ExampleWidget> {
});
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
await _filamentController!.createViewer();
_createEntityLoadListener();
await _filamentController!
.loadSkybox("assets/default_env/default_env_skybox.ktx");
await _filamentController!.setRendering(true);
assets.add(
await _filamentController!.loadGlb("assets/shapes/shapes.glb"));
await _filamentController!.loadGlb("assets/shapes/shapes.glb");
await _filamentController!
.setCameraManipulatorOptions(zoomSpeed: 1.0);
@@ -114,82 +113,9 @@ class ExampleWidgetState extends State<ExampleWidget> {
_listener.cancel();
}
void _createEntityLoadListener() {
_listener =
_filamentController!.onLoad.listen((FilamentEntity entity) async {
assets.add(entity);
if (mounted) {
setState(() {});
}
print(_filamentController!.getNameForEntity(entity) ?? "NAME NOT FOUND");
});
}
EntityTransformController? _transformController;
FilamentEntity? _controlled;
final _sharedFocusNode = FocusNode();
Widget _assetEntry(FilamentEntity entity) {
return FutureBuilder(
future: _filamentController!.getAnimationNames(entity),
builder: (_, animations) {
if (animations.data == null) {
return Container();
}
return Row(children: [
Text("Asset ${entity}"),
IconButton(
iconSize: 14,
tooltip: "Transform to unit cube",
onPressed: () async {
await _filamentController!.transformToUnitCube(entity);
},
icon: const Icon(Icons.settings_overscan_outlined)),
IconButton(
iconSize: 14,
tooltip: "Attach mouse control",
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(
iconSize: 14,
tooltip: "Remove",
onPressed: () async {
await _filamentController!.removeEntity(entity);
assets.remove(entity);
setState(() {});
},
icon: const Icon(Icons.cancel_sharp)),
if (animations.data!.isNotEmpty)
PopupMenuButton(
tooltip: "Animations",
itemBuilder: (_) => animations.data!
.map((a) => PopupMenuItem<String>(
value: a,
child: Text(a),
))
.toList(),
onSelected: (value) async {
print("Playing animation $value");
await _filamentController!
.playAnimation(entity, animations.data!.indexOf(value!));
},
)
]);
});
}
final _sharedFocusNode = FocusNode();
@override
Widget build(BuildContext context) {
@@ -201,26 +127,14 @@ class ExampleWidgetState extends State<ExampleWidget> {
padding: _viewportMargin,
keyboardFocusNode: _sharedFocusNode),
),
EntityListWidget(controller: _filamentController),
Positioned(
bottom: 80,
left: 10,
height: 200,
width: 300,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 10),
height: 100,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.white.withOpacity(0.25),
),
child: ListView(children: assets.map(_assetEntry).toList()))),
Positioned(
bottom: 10,
left: 10,
bottom: 0,
left: 0,
right: 10,
height: 60,
height: 30,
child: Container(
height: 60,
height: 30,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: Colors.white.withOpacity(0.25),
@@ -231,11 +145,17 @@ class ExampleWidgetState extends State<ExampleWidget> {
ControllerMenu(
sharedFocusNode: _sharedFocusNode,
controller: _filamentController,
onToggleViewport: () {
setState(() {
_viewportMargin = (_viewportMargin == EdgeInsets.zero)
? const EdgeInsets.all(30)
: EdgeInsets.zero;
});
},
onControllerDestroyed: () {},
onControllerCreated: (controller) {
setState(() {
_filamentController = controller;
_createEntityLoadListener();
});
}),
SceneMenu(
@@ -251,21 +171,21 @@ class ExampleWidgetState extends State<ExampleWidget> {
child: Container(
color: Colors.transparent,
child: const Text("shapes.glb"))),
SizedBox(width: 5),
const SizedBox(width: 5),
GestureDetector(
onTap: () async {
await _filamentController!.loadGlb('assets/1.glb');
},
child: Container(
color: Colors.transparent, child: const Text("1.glb"))),
SizedBox(width: 5),
const SizedBox(width: 5),
GestureDetector(
onTap: () async {
await _filamentController!.loadGlb('assets/2.glb');
},
child: Container(
color: Colors.transparent, child: const Text("2.glb"))),
SizedBox(width: 5),
const SizedBox(width: 5),
GestureDetector(
onTap: () async {
await _filamentController!.loadGlb('assets/3.glb');
@@ -273,21 +193,11 @@ class ExampleWidgetState extends State<ExampleWidget> {
child: Container(
color: Colors.transparent, child: const Text("3.glb"))),
Expanded(child: Container()),
TextButton(
child: const Text("Toggle viewport size"),
onPressed: () {
setState(() {
_viewportMargin = (_viewportMargin == EdgeInsets.zero)
? const EdgeInsets.all(30)
: EdgeInsets.zero;
});
},
)
]))),
_filamentController == null
? Container()
: Padding(
padding: const EdgeInsets.only(top: 40, left: 20, right: 20),
padding: const EdgeInsets.only(top: 10, left: 20, right: 20),
child: ValueListenableBuilder(
valueListenable: showProjectionMatrices,
builder: (ctx, value, child) => CameraMatrixOverlay(