add (very rough) gizmo, restructure Dart package into library, add EntityListWidget
This commit is contained in:
@@ -2,7 +2,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_filament/filament_controller.dart';
|
||||
import 'package:flutter_filament/flutter_filament.dart';
|
||||
import 'package:vector_math/vector_math_64.dart' as v;
|
||||
|
||||
class CameraMatrixOverlay extends StatefulWidget {
|
||||
@@ -96,7 +96,7 @@ class _CameraMatrixOverlayState extends State<CameraMatrixOverlay> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text("Camera position : $_cameraPosition $_cameraRotation",
|
||||
Text("Camera : $_cameraPosition $_cameraRotation",
|
||||
style:
|
||||
const TextStyle(color: Colors.white, fontSize: 10)),
|
||||
// widget.showProjectionMatrices
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
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/widgets/entity_controller_mouse_widget.dart';
|
||||
import 'package:flutter_filament/widgets/filament_gesture_detector.dart';
|
||||
import 'package:flutter_filament/widgets/filament_widget.dart';
|
||||
import 'package:flutter_filament/flutter_filament.dart';
|
||||
|
||||
class ExampleViewport extends StatelessWidget {
|
||||
final FilamentController? controller;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_filament/animations/animation_data.dart';
|
||||
|
||||
import 'package:flutter_filament/filament_controller.dart';
|
||||
import 'package:flutter_filament/flutter_filament.dart';
|
||||
import 'package:flutter_filament_example/main.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
@@ -30,8 +26,8 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
|
||||
MenuItemButton(
|
||||
closeOnActivate: false,
|
||||
onPressed: () async {
|
||||
var entity = await widget.controller
|
||||
.getChildEntity(ExampleWidgetState.assets.last, "Cylinder");
|
||||
var entity = await widget.controller.getChildEntity(
|
||||
widget.controller.scene.listEntities().last, "Cylinder");
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
@@ -44,7 +40,7 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await widget.controller.addBoneAnimation(
|
||||
ExampleWidgetState.assets.last,
|
||||
widget.controller.scene.listEntities().last,
|
||||
BoneAnimationData([
|
||||
"Bone"
|
||||
], [
|
||||
@@ -59,13 +55,14 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
|
||||
const Text('Set bone transform for Cylinder (pi/2 rotation X)')),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await widget.controller.resetBones(ExampleWidgetState.assets.last);
|
||||
await widget.controller
|
||||
.resetBones(widget.controller.scene.listEntities().last);
|
||||
},
|
||||
child: const Text('Reset bones for Cylinder')),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await widget.controller.addBoneAnimation(
|
||||
ExampleWidgetState.assets.last,
|
||||
widget.controller.scene.listEntities().last,
|
||||
BoneAnimationData(
|
||||
["Bone"],
|
||||
["Cylinder"],
|
||||
@@ -84,7 +81,7 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
|
||||
closeOnActivate: false,
|
||||
onPressed: () async {
|
||||
var names = await widget.controller.getMorphTargetNames(
|
||||
ExampleWidgetState.assets.last, "Cylinder");
|
||||
widget.controller.scene.listEntities().last, "Cylinder");
|
||||
print("NAMES : $names");
|
||||
await showDialog(
|
||||
context: context,
|
||||
@@ -100,7 +97,7 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
widget.controller.setMorphTargetWeights(
|
||||
ExampleWidgetState.assets.last,
|
||||
widget.controller.scene.listEntities().last,
|
||||
"Cylinder",
|
||||
List.filled(4, 1.0));
|
||||
},
|
||||
@@ -108,24 +105,26 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
widget.controller.setMorphTargetWeights(
|
||||
ExampleWidgetState.assets.last,
|
||||
widget.controller.scene.listEntities().last,
|
||||
"Cylinder",
|
||||
List.filled(4, 0.0));
|
||||
},
|
||||
child: const Text("Set Cylinder morph weights to 0")),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
widget.controller
|
||||
.setPosition(ExampleWidgetState.assets.last, 1.0, 1.0, -1.0);
|
||||
widget.controller.setPosition(
|
||||
widget.controller.scene.listEntities().last, 1.0, 1.0, -1.0);
|
||||
},
|
||||
child: const Text('Set position to 1, 1, -1'),
|
||||
),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
if (ExampleWidgetState.coneHidden) {
|
||||
widget.controller.reveal(ExampleWidgetState.assets.last, "Cone");
|
||||
widget.controller
|
||||
.reveal(widget.controller.scene.listEntities().last, "Cone");
|
||||
} else {
|
||||
widget.controller.hide(ExampleWidgetState.assets.last, "Cone");
|
||||
widget.controller
|
||||
.hide(widget.controller.scene.listEntities().last, "Cone");
|
||||
}
|
||||
|
||||
ExampleWidgetState.coneHidden = !ExampleWidgetState.coneHidden;
|
||||
@@ -135,7 +134,10 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
widget.controller.setMaterialColor(
|
||||
ExampleWidgetState.assets.last, "Cone", 0, Colors.purple);
|
||||
widget.controller.scene.listEntities().last,
|
||||
"Cone",
|
||||
0,
|
||||
Colors.purple);
|
||||
},
|
||||
child: const Text("Set cone material color to purple")),
|
||||
MenuItemButton(
|
||||
@@ -150,31 +152,47 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
|
||||
}
|
||||
|
||||
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"));
|
||||
return SubmenuButton(
|
||||
menuChildren: [
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
var verts = [
|
||||
-1.0,
|
||||
0.0,
|
||||
-1.0,
|
||||
-1.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0,
|
||||
0.0,
|
||||
-1.0,
|
||||
];
|
||||
var indices = [0, 1, 2, 2, 3, 0];
|
||||
var geom = await widget.controller.createGeometry(verts, indices,
|
||||
materialPath: "asset://assets/solidcolor.filamat");
|
||||
},
|
||||
child: const Text("Quad")),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await widget.controller.createGeometry([
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
], [
|
||||
0,
|
||||
1
|
||||
], primitiveType: PrimitiveType.LINES);
|
||||
},
|
||||
child: const Text("Line"))
|
||||
],
|
||||
child: const Text("Custom Geometry"),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -185,50 +203,24 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
|
||||
_geometrySubmenu(),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
ExampleWidgetState.directionalLight = await widget.controller
|
||||
await widget.controller
|
||||
.addLight(1, 6500, 150000, 0, 1, 0, 0, -1, 0, true);
|
||||
},
|
||||
child: const Text("Add directional light"),
|
||||
),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await widget.controller
|
||||
.addLight(2, 6500, 150000, 0, 1, 0, 0, -1, 0, true);
|
||||
},
|
||||
child: const Text("Add point light"),
|
||||
),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await widget.controller.clearLights();
|
||||
},
|
||||
child: const Text("Clear lights"),
|
||||
),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
if (ExampleWidgetState.buster == null) {
|
||||
ExampleWidgetState.buster = await widget.controller.loadGltf(
|
||||
"assets/BusterDrone/scene.gltf", "assets/BusterDrone",
|
||||
force: true);
|
||||
await widget.controller
|
||||
.playAnimation(ExampleWidgetState.buster!, 0, loop: true);
|
||||
} else {
|
||||
await widget.controller
|
||||
.removeEntity(ExampleWidgetState.buster!);
|
||||
ExampleWidgetState.buster = null;
|
||||
}
|
||||
},
|
||||
child: Text(ExampleWidgetState.buster == null
|
||||
? 'Load buster'
|
||||
: 'Remove buster')),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
if (ExampleWidgetState.flightHelmet == null) {
|
||||
ExampleWidgetState.flightHelmet ??= await widget.controller
|
||||
.loadGltf('assets/FlightHelmet/FlightHelmet.gltf',
|
||||
'assets/FlightHelmet',
|
||||
force: true);
|
||||
} else {
|
||||
await widget.controller
|
||||
.removeEntity(ExampleWidgetState.flightHelmet!);
|
||||
ExampleWidgetState.flightHelmet = null;
|
||||
}
|
||||
},
|
||||
child: Text(ExampleWidgetState.flightHelmet == null
|
||||
? 'Load flight helmet'
|
||||
: 'Remove flight helmet')),
|
||||
MenuItemButton(
|
||||
onPressed: () {
|
||||
widget.controller.setBackgroundColor(const Color(0xAA73C9FA));
|
||||
@@ -272,9 +264,6 @@ class _AssetSubmenuState extends State<AssetSubmenu> {
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await widget.controller.clearEntities();
|
||||
ExampleWidgetState.flightHelmet = null;
|
||||
ExampleWidgetState.buster = null;
|
||||
ExampleWidgetState.assets.clear();
|
||||
},
|
||||
child: const Text('Clear assets')),
|
||||
],
|
||||
|
||||
@@ -3,7 +3,8 @@ import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:vector_math/vector_math_64.dart' as v;
|
||||
import 'package:flutter_filament/filament_controller.dart';
|
||||
import 'package:flutter_filament/flutter_filament.dart';
|
||||
|
||||
import 'package:flutter_filament_example/main.dart';
|
||||
|
||||
class CameraSubmenu extends StatefulWidget {
|
||||
@@ -104,20 +105,6 @@ class _CameraSubmenuState extends State<CameraSubmenu> {
|
||||
},
|
||||
child: const Text('Move to 0,0,0, facing towards 0,0,-1'),
|
||||
),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await widget.controller
|
||||
.setCamera(ExampleWidgetState.assets.last!, null);
|
||||
},
|
||||
child: const Text('Set to first camera in last added asset'),
|
||||
),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await widget.controller
|
||||
.moveCameraToAsset(ExampleWidgetState.assets.last!);
|
||||
},
|
||||
child: const Text("Move to last added asset"),
|
||||
),
|
||||
MenuItemButton(
|
||||
onPressed: () {
|
||||
widget.controller.setCameraRotation(
|
||||
|
||||
@@ -2,11 +2,12 @@ import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_filament/filament_controller.dart';
|
||||
import 'package:flutter_filament/filament_controller_ffi.dart';
|
||||
|
||||
import 'package:flutter_filament/flutter_filament.dart';
|
||||
|
||||
class ControllerMenu extends StatefulWidget {
|
||||
final FilamentController? controller;
|
||||
final void Function() onToggleViewport;
|
||||
final void Function(FilamentController controller) onControllerCreated;
|
||||
final void Function() onControllerDestroyed;
|
||||
final FocusNode sharedFocusNode;
|
||||
@@ -15,7 +16,8 @@ class ControllerMenu extends StatefulWidget {
|
||||
{this.controller,
|
||||
required this.onControllerCreated,
|
||||
required this.onControllerDestroyed,
|
||||
required this.sharedFocusNode});
|
||||
required this.sharedFocusNode,
|
||||
required this.onToggleViewport});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ControllerMenuState();
|
||||
@@ -60,6 +62,7 @@ class _ControllerMenuState extends State<ControllerMenu> {
|
||||
? null
|
||||
: () async {
|
||||
await _filamentController!.createViewer();
|
||||
|
||||
await _filamentController!
|
||||
.setCameraManipulatorOptions(zoomSpeed: 1.0);
|
||||
},
|
||||
@@ -100,7 +103,13 @@ class _ControllerMenuState extends State<ControllerMenu> {
|
||||
}
|
||||
return MenuAnchor(
|
||||
childFocusNode: widget.sharedFocusNode,
|
||||
menuChildren: items,
|
||||
menuChildren: items +
|
||||
[
|
||||
TextButton(
|
||||
child: const Text("Toggle viewport size"),
|
||||
onPressed: widget.onToggleViewport,
|
||||
)
|
||||
],
|
||||
builder:
|
||||
(BuildContext context, MenuController controller, Widget? child) {
|
||||
return TextButton(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_filament/filament_controller.dart';
|
||||
import 'package:flutter_filament/flutter_filament.dart';
|
||||
import 'package:flutter_filament_example/main.dart';
|
||||
|
||||
class RenderingSubmenu extends StatefulWidget {
|
||||
@@ -64,6 +64,13 @@ class _RenderingSubmenuState extends State<RenderingSubmenu> {
|
||||
child: Text(
|
||||
"Turn recording ${ExampleWidgetState.recording ? "OFF" : "ON"}) "),
|
||||
),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await widget.controller
|
||||
.addLight(2, 6000, 100000, 0, 0, 0, 0, 1, 0, false);
|
||||
},
|
||||
child: Text("Add light"),
|
||||
),
|
||||
],
|
||||
child: const Text("Rendering"),
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_filament/filament_controller.dart';
|
||||
import 'package:flutter_filament/flutter_filament.dart';
|
||||
import 'package:flutter_filament_example/menus/asset_submenu.dart';
|
||||
import 'package:flutter_filament_example/menus/camera_submenu.dart';
|
||||
import 'package:flutter_filament_example/menus/rendering_submenu.dart';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_filament/filament_controller.dart';
|
||||
import 'package:flutter_filament/flutter_filament.dart';
|
||||
|
||||
class PickerResultWidget extends StatelessWidget {
|
||||
final FilamentController controller;
|
||||
|
||||
Reference in New Issue
Block a user