diff --git a/lib/avatar_gesture_detector.dart b/lib/avatar_gesture_detector.dart new file mode 100644 index 00000000..5061b24c --- /dev/null +++ b/lib/avatar_gesture_detector.dart @@ -0,0 +1,159 @@ +// import 'dart:async'; + +// import 'package:flutter/gestures.dart'; +// import 'package:flutter/material.dart'; +// import 'filament_controller.dart'; +// import 'filament_widget.dart'; + +// enum GestureType { RotateCamera, PanCamera, PanBackground } + +// class AvatarGestureDetector extends StatefulWidget { +// final AvatarInstance controller; +// final bool showControls; + +// const AvatarGestureDetector({ +// Key? key, +// required this.controller, +// this.showControls = false, +// }) : super(key: key); + +// @override +// State createState() => _AvatarGestureDetectorState(); +// } + +// class _AvatarGestureDetectorState extends State { +// GestureType gestureType = GestureType.PanCamera; + +// final _icons = { +// GestureType.PanBackground: Icons.image, +// GestureType.PanCamera: Icons.pan_tool, +// GestureType.RotateCamera: Icons.rotate_90_degrees_ccw +// }; + +// // to avoid duplicating code for pan/rotate (panStart, panUpdate, panEnd, rotateStart, rotateUpdate etc) +// // we have only a single function for start/update/end. +// // when the gesture type is changed, these properties are updated to point to the correct function. +// late Future Function(double x, double y) _functionStart; +// late Future Function(double x, double y) _functionUpdate; +// late Future Function() _functionEnd; + +// double _lastScale = 0; + +// @override +// void initState() { +// _setFunction(); +// super.initState(); +// } + +// void _setFunction() { +// switch (gestureType) { +// case GestureType.RotateCamera: +// _functionStart = widget.controller.rotateStart; +// _functionUpdate = widget.controller.rotateUpdate; +// _functionEnd = widget.controller.rotateEnd; +// break; +// case GestureType.PanCamera: +// _functionStart = widget.controller.panStart; +// _functionUpdate = widget.controller.panUpdate; +// _functionEnd = widget.controller.panEnd; +// break; +// // TODO +// case GestureType.PanBackground: +// _functionStart = (x, y) async {}; +// _functionUpdate = (x, y) async {}; +// _functionEnd = () async {}; +// } +// } + +// @override +// void didUpdateWidget(AvatarGestureDetector oldWidget) { +// if (widget.showControls != oldWidget.showControls) { +// setState(() {}); +// } + +// super.didUpdateWidget(oldWidget); +// } + +// Timer? _scrollTimer; + +// @override +// Widget build(BuildContext context) { +// return Stack(children: [ +// Positioned.fill( +// // pinch zoom on mobile +// // couldn't find any equivalent for pointerCount in Listener so we use two widgets: +// // - outer is a GestureDetector only for pinch zoom +// // - inner is a Listener for all other gestures +// child: GestureDetector( +// // onScaleStart: (d) async { +// // if (d.pointerCount == 2) { +// // await widget.controller.zoomEnd(); +// // await widget.controller.zoomBegin(); +// // } +// // }, +// // onScaleEnd: (d) async { +// // if (d.pointerCount == 2) { +// // _lastScale = 0; +// // await widget.controller.zoomEnd(); +// // } +// // }, +// // onScaleUpdate: (d) async { +// // if (d.pointerCount == 2) { +// // if (_lastScale != 0) { +// // await widget.controller +// // .zoomUpdate(100 * (_lastScale - d.scale)); +// // } +// // } +// // _lastScale = d.scale; +// // }, +// child: Listener( +// onPointerSignal: (pointerSignal) async { +// // scroll-wheel zoom on desktop +// if (pointerSignal is PointerScrollEvent) { +// _scrollTimer?.cancel(); +// await widget.controller.zoomBegin(); +// await widget.controller.zoomUpdate( +// pointerSignal.scrollDelta.dy > 0 ? 10 : -10); +// _scrollTimer = Timer(Duration(milliseconds: 100), () { +// widget.controller.zoomEnd(); +// _scrollTimer = null; +// }); +// } else { +// print(pointerSignal); +// } +// }, +// onPointerPanZoomStart: (pzs) {}, +// onPointerDown: (d) async { +// await _functionStart( +// d.localPosition.dx, d.localPosition.dy); +// }, +// onPointerMove: (d) async { +// await _functionUpdate( +// d.localPosition.dx, d.localPosition.dy); +// }, +// onPointerUp: (d) async { +// await _functionEnd(); +// }, +// child: widget.child))), +// widget.showControls +// ? Align( +// alignment: Alignment.bottomRight, +// child: GestureDetector( +// onTap: () { +// setState(() { +// var curIdx = GestureType.values.indexOf(gestureType); +// var nextIdx = curIdx == GestureType.values.length - 1 +// ? 0 +// : curIdx + 1; +// gestureType = GestureType.values[nextIdx]; +// _setFunction(); +// }); +// }, +// child: Container( +// padding: const EdgeInsets.all(50), +// child: Icon(_icons[gestureType], color: Colors.green)), +// )) +// : Container() +// ]); +// } +// } diff --git a/lib/filament_controller.dart b/lib/filament_controller.dart index 20b24862..6f0e49b1 100644 --- a/lib/filament_controller.dart +++ b/lib/filament_controller.dart @@ -374,6 +374,7 @@ class PolyvoxFilamentController extends FilamentController { } Future setCameraModelMatrix(List matrix) async { + assert(matrix.length == 16); await _channel.invokeMethod( "setCameraModelMatrix", Float32List.fromList(matrix)); } diff --git a/lib/filament_gesture_detector.dart b/lib/filament_gesture_detector.dart index 76d0d957..7cce4da4 100644 --- a/lib/filament_gesture_detector.dart +++ b/lib/filament_gesture_detector.dart @@ -116,7 +116,7 @@ class _FilamentGestureDetectorState extends State { _scrollTimer?.cancel(); await widget.controller.zoomBegin(); await widget.controller.zoomUpdate( - pointerSignal.scrollDelta.dy > 0 ? 100 : -100); + pointerSignal.scrollDelta.dy > 0 ? 10 : -10); _scrollTimer = Timer(Duration(milliseconds: 100), () { widget.controller.zoomEnd(); _scrollTimer = null; diff --git a/linux/include/polyvox_filament/resource_loader.hpp b/linux/include/polyvox_filament/resource_loader.hpp index ee0157f0..c05c2c5e 100644 --- a/linux/include/polyvox_filament/resource_loader.hpp +++ b/linux/include/polyvox_filament/resource_loader.hpp @@ -30,14 +30,14 @@ ResourceBuffer loadResource(const char* name) { // this functions accepts URIs, so // - file:// points to a file on the filesystem // - asset:// points to an asset, usually resolved relative to the current working directory - // - no prefix is presumed to be an absolute file path + // - no prefix is presumed to be an asset if (name_str.rfind("file://", 0) == 0) { name_str = name_str.substr(7); } else if(name_str.rfind("asset://", 0) == 0) { name_str = name_str.substr(7); name_str = string(cwd) + string("/") + name_str; } else { - + name_str = string(cwd) + string("/build/linux/x64/debug/bundle/data/flutter_assets/") + name_str; } std::cout << "Loading resource at " << name_str.c_str() << std::endl; diff --git a/linux/polyvox_filament_plugin.cc b/linux/polyvox_filament_plugin.cc index d8ed3d54..479314b0 100644 --- a/linux/polyvox_filament_plugin.cc +++ b/linux/polyvox_filament_plugin.cc @@ -114,6 +114,12 @@ static FlMethodResponse* _loadSkybox(PolyvoxFilamentPlugin* self, FlMethodCall* return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); } +static FlMethodResponse* _remove_ibl(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { + remove_ibl(self->_viewer); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + static FlMethodResponse* _loadIbl(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { FlValue* args = fl_method_call_get_args(method_call); @@ -277,6 +283,23 @@ static FlMethodResponse* _set_position(PolyvoxFilamentPlugin* self, FlMethodCall return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); } +static FlMethodResponse* _set_rotation(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); + + set_rotation( + assetPtr, + (float)fl_value_get_float(fl_value_get_list_value(args, 1)), // rads + (float)fl_value_get_float(fl_value_get_list_value(args, 2)), // x + (float)fl_value_get_float(fl_value_get_list_value(args, 3)), // y + (float)fl_value_get_float(fl_value_get_list_value(args, 4)) // z + ); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + + + // static FlMethodResponse* _set_bone_transform(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { // FlValue* args = fl_method_call_get_args(method_call); // auto assetPtr = (void*)fl_value_get_int(fl_value_get_list_value(args, 0)); @@ -309,6 +332,13 @@ static FlMethodResponse* _set_camera(PolyvoxFilamentPlugin* self, FlMethodCall* return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); } +static FlMethodResponse* _set_camera_model_matrix(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { + FlValue* args = fl_method_call_get_args(method_call); + set_camera_model_matrix(self->_viewer, fl_value_get_float32_list(args)); + g_autoptr(FlValue) result = fl_value_new_string("OK"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); +} + static FlMethodResponse* _set_camera_position(PolyvoxFilamentPlugin* self, FlMethodCall* method_call) { FlValue* args = fl_method_call_get_args(method_call); auto x = (float)fl_value_get_float(fl_value_get_list_value(args, 0)); @@ -544,6 +574,8 @@ static void polyvox_filament_plugin_handle_method_call( response = _loadSkybox(self, method_call); } else if(strcmp(method, "loadIbl") == 0) { response = _loadIbl(self, method_call); + } else if(strcmp(method, "removeIbl") ==0) { + response = _remove_ibl(self, method_call); } else if(strcmp(method, "removeSkybox") == 0) { response = _removeSkybox(self, method_call); } else if(strcmp(method, "resize") == 0) { @@ -584,8 +616,12 @@ static void polyvox_filament_plugin_handle_method_call( response = _rotate_end(self, method_call); } else if(strcmp(method, "rotateUpdate") == 0) { response = _rotate_update(self, method_call); + } else if(strcmp(method, "setRotation") == 0) { + response = _set_rotation(self, method_call); } else if(strcmp(method, "setCamera") == 0) { response = _set_camera(self, method_call); + } else if(strcmp(method, "setCameraModelMatrix") == 0) { + response = _set_camera_model_matrix(self, method_call); } else if(strcmp(method, "setCameraPosition") == 0) { response = _set_camera_position(self, method_call); } else if(strcmp(method, "setCameraRotation") == 0) {