refactoring
This commit is contained in:
@@ -20,4 +20,5 @@ class ThermionFlutterPlugin {
|
||||
|
||||
return viewer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,98 +1,98 @@
|
||||
import 'dart:math';
|
||||
// import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
import 'package:vector_math/vector_math_64.dart' as v64;
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:thermion_flutter/thermion_flutter.dart';
|
||||
// import 'package:vector_math/vector_math_64.dart' as v64;
|
||||
|
||||
class CameraOrientationWidget extends StatefulWidget {
|
||||
final ThermionViewer viewer;
|
||||
// class CameraOrientationWidget extends StatefulWidget {
|
||||
// final ThermionViewer viewer;
|
||||
|
||||
const CameraOrientationWidget({Key? key, required this.viewer})
|
||||
: super(key: key);
|
||||
// const CameraOrientationWidget({Key? key, required this.viewer})
|
||||
// : super(key: key);
|
||||
|
||||
@override
|
||||
_CameraOrientationWidgetState createState() =>
|
||||
_CameraOrientationWidgetState();
|
||||
}
|
||||
// @override
|
||||
// _CameraOrientationWidgetState createState() =>
|
||||
// _CameraOrientationWidgetState();
|
||||
// }
|
||||
|
||||
class _CameraOrientationWidgetState extends State<CameraOrientationWidget>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
v64.Vector3? _position;
|
||||
v64.Matrix3? _rotation;
|
||||
// class _CameraOrientationWidgetState extends State<CameraOrientationWidget>
|
||||
// with SingleTickerProviderStateMixin {
|
||||
// late AnimationController _controller;
|
||||
// v64.Vector3? _position;
|
||||
// v64.Matrix3? _rotation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 16), // ~60 FPS
|
||||
)..repeat();
|
||||
// @override
|
||||
// void initState() {
|
||||
// super.initState();
|
||||
// _controller = AnimationController(
|
||||
// vsync: this,
|
||||
// duration: const Duration(milliseconds: 16), // ~60 FPS
|
||||
// )..repeat();
|
||||
|
||||
_controller.addListener(_updateCameraInfo);
|
||||
}
|
||||
// _controller.addListener(_updateCameraInfo);
|
||||
// }
|
||||
|
||||
void _updateCameraInfo() async {
|
||||
final camera = await widget.viewer.getActiveCamera();
|
||||
final position = await widget.viewer.getCameraPosition();
|
||||
final rotation = await widget.viewer.getCameraRotation();
|
||||
setState(() {
|
||||
_position = position;
|
||||
_rotation = rotation;
|
||||
});
|
||||
}
|
||||
// void _updateCameraInfo() async {
|
||||
// final camera = await widget.viewer.getActiveCamera();
|
||||
// final position = await widget.viewer.getCameraPosition();
|
||||
// final rotation = await widget.viewer.getCameraRotation();
|
||||
// setState(() {
|
||||
// _position = position;
|
||||
// _rotation = rotation;
|
||||
// });
|
||||
// }
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
// @override
|
||||
// void dispose() {
|
||||
// _controller.dispose();
|
||||
// super.dispose();
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withOpacity(0.7),
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Position: ${_formatVector(_position)}',
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Rotation: ${_formatMatrix(_rotation)}',
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Container(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// decoration: BoxDecoration(
|
||||
// color: Colors.black.withOpacity(0.7),
|
||||
// borderRadius: BorderRadius.circular(8.0),
|
||||
// ),
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// Text(
|
||||
// 'Position: ${_formatVector(_position)}',
|
||||
// style: const TextStyle(color: Colors.white),
|
||||
// ),
|
||||
// const SizedBox(height: 4),
|
||||
// Text(
|
||||
// 'Rotation: ${_formatMatrix(_rotation)}',
|
||||
// style: const TextStyle(color: Colors.white),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
|
||||
String _formatVector(v64.Vector3? vector) {
|
||||
if (vector == null) return 'N/A';
|
||||
return '(${vector.x.toStringAsFixed(2)}, ${vector.y.toStringAsFixed(2)}, ${vector.z.toStringAsFixed(2)})';
|
||||
}
|
||||
// String _formatVector(v64.Vector3? vector) {
|
||||
// if (vector == null) return 'N/A';
|
||||
// return '(${vector.x.toStringAsFixed(2)}, ${vector.y.toStringAsFixed(2)}, ${vector.z.toStringAsFixed(2)})';
|
||||
// }
|
||||
|
||||
String _formatMatrix(v64.Matrix3? matrix) {
|
||||
if (matrix == null) return 'N/A';
|
||||
return 'Yaw: ${_getYaw(matrix).toStringAsFixed(2)}°, Pitch: ${_getPitch(matrix).toStringAsFixed(2)}°, Roll: ${_getRoll(matrix).toStringAsFixed(2)}°';
|
||||
}
|
||||
// String _formatMatrix(v64.Matrix3? matrix) {
|
||||
// if (matrix == null) return 'N/A';
|
||||
// return 'Yaw: ${_getYaw(matrix).toStringAsFixed(2)}°, Pitch: ${_getPitch(matrix).toStringAsFixed(2)}°, Roll: ${_getRoll(matrix).toStringAsFixed(2)}°';
|
||||
// }
|
||||
|
||||
double _getYaw(v64.Matrix3 matrix) {
|
||||
return -atan2(matrix[2], matrix[0]) * 180 / pi;
|
||||
}
|
||||
// double _getYaw(v64.Matrix3 matrix) {
|
||||
// return -atan2(matrix[2], matrix[0]) * 180 / pi;
|
||||
// }
|
||||
|
||||
double _getPitch(v64.Matrix3 matrix) {
|
||||
return -asin(matrix[5]) * 180 / pi;
|
||||
}
|
||||
// double _getPitch(v64.Matrix3 matrix) {
|
||||
// return -asin(matrix[5]) * 180 / pi;
|
||||
// }
|
||||
|
||||
double _getRoll(v64.Matrix3 matrix) {
|
||||
return atan2(matrix[3], matrix[4]) * 180 / pi;
|
||||
}
|
||||
}
|
||||
// double _getRoll(v64.Matrix3 matrix) {
|
||||
// return atan2(matrix[3], matrix[4]) * 180 / pi;
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,79 +1,79 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:thermion_dart/thermion_dart.dart';
|
||||
|
||||
class CameraSelectorWidget extends StatefulWidget {
|
||||
final ThermionViewer viewer;
|
||||
// class CameraSelectorWidget extends StatefulWidget {
|
||||
// final ThermionViewer viewer;
|
||||
|
||||
const CameraSelectorWidget({Key? key, required this.viewer}) : super(key: key);
|
||||
// const CameraSelectorWidget({Key? key, required this.viewer}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CameraSelectorWidgetState createState() => _CameraSelectorWidgetState();
|
||||
}
|
||||
// @override
|
||||
// _CameraSelectorWidgetState createState() => _CameraSelectorWidgetState();
|
||||
// }
|
||||
|
||||
class _CameraSelectorWidgetState extends State<CameraSelectorWidget> {
|
||||
int _activeIndex = 0;
|
||||
// class _CameraSelectorWidgetState extends State<CameraSelectorWidget> {
|
||||
// int _activeIndex = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
int cameraCount = widget.viewer.getCameraCount();
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// int cameraCount = widget.viewer.getCameraCount();
|
||||
|
||||
return Container(
|
||||
height:32,
|
||||
margin: const EdgeInsets.all(8),
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_buildCameraButton("Main", 0),
|
||||
if (cameraCount > 1) const VerticalDivider(width: 16, thickness: 1),
|
||||
...List.generate(cameraCount - 1, (index) {
|
||||
return _buildCameraButton("${index + 1}", index + 1);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
// return Container(
|
||||
// height:32,
|
||||
// margin: const EdgeInsets.all(8),
|
||||
// padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
||||
// decoration: BoxDecoration(
|
||||
// color: Colors.white,
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// boxShadow: [
|
||||
// BoxShadow(
|
||||
// color: Colors.black.withOpacity(0.1),
|
||||
// blurRadius: 4,
|
||||
// offset: const Offset(0, 2),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// child: Row(
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// _buildCameraButton("Main", 0),
|
||||
// if (cameraCount > 1) const VerticalDivider(width: 16, thickness: 1),
|
||||
// ...List.generate(cameraCount - 1, (index) {
|
||||
// return _buildCameraButton("${index + 1}", index + 1);
|
||||
// }),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
|
||||
Widget _buildCameraButton(String label, int index) {
|
||||
bool isActive = _activeIndex == index;
|
||||
return Flexible(child:TextButton(
|
||||
onPressed: () async {
|
||||
if (index == 0) {
|
||||
await widget.viewer.setMainCamera();
|
||||
} else {
|
||||
Camera camera = widget.viewer.getCameraAt(index);
|
||||
await widget.viewer.setActiveCamera(camera);
|
||||
}
|
||||
setState(() {
|
||||
_activeIndex = index;
|
||||
});
|
||||
},
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
minimumSize: Size.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
backgroundColor: isActive ? Colors.blue.withOpacity(0.1) : null,
|
||||
),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
|
||||
color: isActive ? Colors.blue : Colors.black87,
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
// Widget _buildCameraButton(String label, int index) {
|
||||
// bool isActive = _activeIndex == index;
|
||||
// return Flexible(child:TextButton(
|
||||
// onPressed: () async {
|
||||
// if (index == 0) {
|
||||
// await widget.viewer.setMainCamera();
|
||||
// } else {
|
||||
// Camera camera = widget.viewer.getCameraAt(index);
|
||||
// await widget.viewer.setActiveCamera(camera);
|
||||
// }
|
||||
// setState(() {
|
||||
// _activeIndex = index;
|
||||
// });
|
||||
// },
|
||||
// style: TextButton.styleFrom(
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
// minimumSize: Size.zero,
|
||||
// tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
// backgroundColor: isActive ? Colors.blue.withOpacity(0.1) : null,
|
||||
// ),
|
||||
// child: Text(
|
||||
// label,
|
||||
// style: TextStyle(
|
||||
// fontSize: 10,
|
||||
// fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
|
||||
// color: isActive ? Colors.blue : Colors.black87,
|
||||
// ),
|
||||
// ),
|
||||
// ));
|
||||
// }
|
||||
// }
|
||||
@@ -1,110 +1,110 @@
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
// import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
// import 'package:thermion_dart/thermion_dart.dart';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:math';
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'dart:math';
|
||||
|
||||
class ChildRenderableWidget extends StatelessWidget {
|
||||
final ThermionViewer controller;
|
||||
final ThermionEntity entity;
|
||||
// class ChildRenderableWidget extends StatelessWidget {
|
||||
// final ThermionViewer controller;
|
||||
// final ThermionEntity entity;
|
||||
|
||||
const ChildRenderableWidget(
|
||||
{super.key, required this.controller, required this.entity});
|
||||
// const ChildRenderableWidget(
|
||||
// {super.key, required this.controller, required this.entity});
|
||||
|
||||
Widget _childRenderable(ThermionEntity childEntity) {
|
||||
var name = controller.getNameForEntity(childEntity) ?? "<none>";
|
||||
var names = controller.getMorphTargetNames(entity, childEntity);
|
||||
// Widget _childRenderable(ThermionEntity childEntity) {
|
||||
// var name = controller.getNameForEntity(childEntity) ?? "<none>";
|
||||
// var names = controller.getMorphTargetNames(entity, childEntity);
|
||||
|
||||
return FutureBuilder(
|
||||
future: names,
|
||||
builder: (_, morphTargetsSnapshot) {
|
||||
if (!morphTargetsSnapshot.hasData) {
|
||||
return Container();
|
||||
}
|
||||
var morphTargets = morphTargetsSnapshot.data!;
|
||||
// return FutureBuilder(
|
||||
// future: names,
|
||||
// builder: (_, morphTargetsSnapshot) {
|
||||
// if (!morphTargetsSnapshot.hasData) {
|
||||
// return Container();
|
||||
// }
|
||||
// var morphTargets = morphTargetsSnapshot.data!;
|
||||
|
||||
final menuChildren = <Widget>[];
|
||||
if (morphTargets.isEmpty) {
|
||||
menuChildren.add(Text("None"));
|
||||
} else {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
var newWeights = List.filled(morphTargets.length, i.toDouble());
|
||||
menuChildren.add(MenuItemButton(
|
||||
child: Text("Set to $i"),
|
||||
onPressed: () async {
|
||||
try {
|
||||
await controller!
|
||||
.setMorphTargetWeights(childEntity, newWeights);
|
||||
} catch (err, st) {
|
||||
print("Error setting morph target weights");
|
||||
print(err);
|
||||
print(st);
|
||||
}
|
||||
}));
|
||||
}
|
||||
menuChildren.add(MenuItemButton(
|
||||
child: Text("Animate all morph target from 0 to 1"),
|
||||
onPressed: () async {
|
||||
var morphData = MorphAnimationData(
|
||||
List<List<double>>.generate(
|
||||
120,
|
||||
(i) => List<double>.filled(
|
||||
morphTargets.length, i / 120)),
|
||||
morphTargets);
|
||||
await controller!.setMorphAnimationData(entity, morphData,
|
||||
targetMeshNames: [name]);
|
||||
}));
|
||||
menuChildren.addAll(morphTargets.map((t) => Text(t)));
|
||||
}
|
||||
return SubmenuButton(child: Text(name), menuChildren: menuChildren);
|
||||
});
|
||||
}
|
||||
// final menuChildren = <Widget>[];
|
||||
// if (morphTargets.isEmpty) {
|
||||
// menuChildren.add(Text("None"));
|
||||
// } else {
|
||||
// for (int i = 0; i < 2; i++) {
|
||||
// var newWeights = List.filled(morphTargets.length, i.toDouble());
|
||||
// menuChildren.add(MenuItemButton(
|
||||
// child: Text("Set to $i"),
|
||||
// onPressed: () async {
|
||||
// try {
|
||||
// await controller!
|
||||
// .setMorphTargetWeights(childEntity, newWeights);
|
||||
// } catch (err, st) {
|
||||
// print("Error setting morph target weights");
|
||||
// print(err);
|
||||
// print(st);
|
||||
// }
|
||||
// }));
|
||||
// }
|
||||
// menuChildren.add(MenuItemButton(
|
||||
// child: Text("Animate all morph target from 0 to 1"),
|
||||
// onPressed: () async {
|
||||
// var morphData = MorphAnimationData(
|
||||
// List<List<double>>.generate(
|
||||
// 120,
|
||||
// (i) => List<double>.filled(
|
||||
// morphTargets.length, i / 120)),
|
||||
// morphTargets);
|
||||
// await controller!.setMorphAnimationData(entity, morphData,
|
||||
// targetMeshNames: [name]);
|
||||
// }));
|
||||
// menuChildren.addAll(morphTargets.map((t) => Text(t)));
|
||||
// }
|
||||
// return SubmenuButton(child: Text(name), menuChildren: menuChildren);
|
||||
// });
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder(
|
||||
future: controller!.getChildEntities(entity, true),
|
||||
builder: (ctx, snapshot) {
|
||||
if (!snapshot.hasData) {
|
||||
return Container();
|
||||
}
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return FutureBuilder(
|
||||
// future: controller!.getChildEntities(entity, true),
|
||||
// builder: (ctx, snapshot) {
|
||||
// if (!snapshot.hasData) {
|
||||
// return Container();
|
||||
// }
|
||||
|
||||
var children = snapshot.data!;
|
||||
return SubmenuButton(
|
||||
child: Text("Renderable entities"),
|
||||
menuChildren: <Widget>[
|
||||
MenuItemButton(
|
||||
child: Text("Set children transforms to identity"),
|
||||
onPressed: () async {
|
||||
var childEntities =
|
||||
await controller.getChildEntities(entity, true);
|
||||
for (final child in childEntities) {
|
||||
await controller.setTransform(
|
||||
child, Matrix4.identity());
|
||||
}
|
||||
}),
|
||||
MenuItemButton(
|
||||
child: Text("Set children transforms to 90/X"),
|
||||
onPressed: () async {
|
||||
var childEntities =
|
||||
await controller.getChildEntities(entity, true);
|
||||
for (final child in childEntities) {
|
||||
await controller.setTransform(
|
||||
child, Matrix4.rotationX(pi / 2));
|
||||
}
|
||||
}),
|
||||
MenuItemButton(
|
||||
child: Text("Set children transforms to 90/Y"),
|
||||
onPressed: () async {
|
||||
var childEntities =
|
||||
await controller.getChildEntities(entity, true);
|
||||
for (final child in childEntities) {
|
||||
await controller.setTransform(
|
||||
child, Matrix4.rotationY(pi / 2));
|
||||
}
|
||||
}),
|
||||
] +
|
||||
children.map(_childRenderable).toList());
|
||||
});
|
||||
}
|
||||
}
|
||||
// var children = snapshot.data!;
|
||||
// return SubmenuButton(
|
||||
// child: Text("Renderable entities"),
|
||||
// menuChildren: <Widget>[
|
||||
// MenuItemButton(
|
||||
// child: Text("Set children transforms to identity"),
|
||||
// onPressed: () async {
|
||||
// var childEntities =
|
||||
// await controller.getChildEntities(entity, true);
|
||||
// for (final child in childEntities) {
|
||||
// await controller.setTransform(
|
||||
// child, Matrix4.identity());
|
||||
// }
|
||||
// }),
|
||||
// MenuItemButton(
|
||||
// child: Text("Set children transforms to 90/X"),
|
||||
// onPressed: () async {
|
||||
// var childEntities =
|
||||
// await controller.getChildEntities(entity, true);
|
||||
// for (final child in childEntities) {
|
||||
// await controller.setTransform(
|
||||
// child, Matrix4.rotationX(pi / 2));
|
||||
// }
|
||||
// }),
|
||||
// MenuItemButton(
|
||||
// child: Text("Set children transforms to 90/Y"),
|
||||
// onPressed: () async {
|
||||
// var childEntities =
|
||||
// await controller.getChildEntities(entity, true);
|
||||
// for (final child in childEntities) {
|
||||
// await controller.setTransform(
|
||||
// child, Matrix4.rotationY(pi / 2));
|
||||
// }
|
||||
// }),
|
||||
// ] +
|
||||
// children.map(_childRenderable).toList());
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,421 +1,421 @@
|
||||
import 'dart:math';
|
||||
// import 'dart:math';
|
||||
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
// import 'package:thermion_dart/thermion_dart.dart';
|
||||
// import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:flutter/widgets.dart';
|
||||
// import 'package:vector_math/vector_math_64.dart';
|
||||
|
||||
class SkeletonMenuItemWidget extends StatelessWidget {
|
||||
final ThermionViewer controller;
|
||||
final ThermionEntity entity;
|
||||
// class SkeletonMenuItemWidget extends StatelessWidget {
|
||||
// final ThermionViewer controller;
|
||||
// final ThermionEntity entity;
|
||||
|
||||
const SkeletonMenuItemWidget(
|
||||
{super.key, required this.controller, required this.entity});
|
||||
// const SkeletonMenuItemWidget(
|
||||
// {super.key, required this.controller, required this.entity});
|
||||
|
||||
void _addBoneAnimation(String bone) async {
|
||||
await controller.addAnimationComponent(entity);
|
||||
var numFrames = 120;
|
||||
var animationData = List<List<BoneAnimationFrame>>.generate(
|
||||
numFrames,
|
||||
(frameNum) => [
|
||||
(
|
||||
rotation: Quaternion.axisAngle(
|
||||
Vector3(1, 0, 0), (frameNum / 90) * 2 * pi),
|
||||
translation: Vector3.zero()
|
||||
)
|
||||
]);
|
||||
var animation =
|
||||
BoneAnimationData([bone], animationData, space: Space.ParentWorldRotation);
|
||||
await controller.addAnimationComponent(entity);
|
||||
await controller.addBoneAnimation(entity, animation);
|
||||
}
|
||||
// void _addBoneAnimation(String bone) async {
|
||||
// await controller.addAnimationComponent(entity);
|
||||
// var numFrames = 120;
|
||||
// var animationData = List<List<BoneAnimationFrame>>.generate(
|
||||
// numFrames,
|
||||
// (frameNum) => [
|
||||
// (
|
||||
// rotation: Quaternion.axisAngle(
|
||||
// Vector3(1, 0, 0), (frameNum / 90) * 2 * pi),
|
||||
// translation: Vector3.zero()
|
||||
// )
|
||||
// ]);
|
||||
// var animation =
|
||||
// BoneAnimationData([bone], animationData, space: Space.ParentWorldRotation);
|
||||
// await controller.addAnimationComponent(entity);
|
||||
// await controller.addBoneAnimation(entity, animation);
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var boneNames = controller.getBoneNames(entity);
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// var boneNames = controller.getBoneNames(entity);
|
||||
|
||||
return FutureBuilder(
|
||||
future: boneNames,
|
||||
builder: (_, boneNamesSnapshot) {
|
||||
if (!boneNamesSnapshot.hasData) {
|
||||
return Container();
|
||||
}
|
||||
var boneNames = boneNamesSnapshot.data!;
|
||||
if (boneNames.isEmpty) {
|
||||
return Text("No bones");
|
||||
}
|
||||
// return FutureBuilder(
|
||||
// future: boneNames,
|
||||
// builder: (_, boneNamesSnapshot) {
|
||||
// if (!boneNamesSnapshot.hasData) {
|
||||
// return Container();
|
||||
// }
|
||||
// var boneNames = boneNamesSnapshot.data!;
|
||||
// if (boneNames.isEmpty) {
|
||||
// return Text("No bones");
|
||||
// }
|
||||
|
||||
return SubmenuButton(
|
||||
menuChildren: <Widget>[
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await controller.resetBones(entity);
|
||||
},
|
||||
child: Text("Reset")),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await controller.resetBones(entity);
|
||||
// return SubmenuButton(
|
||||
// menuChildren: <Widget>[
|
||||
// MenuItemButton(
|
||||
// onPressed: () async {
|
||||
// await controller.resetBones(entity);
|
||||
// },
|
||||
// child: Text("Reset")),
|
||||
// MenuItemButton(
|
||||
// onPressed: () async {
|
||||
// await controller.resetBones(entity);
|
||||
|
||||
var bone = await controller.getBone(entity, 1);
|
||||
var frames = <List<BoneAnimationFrame>>[];
|
||||
for (int i = 0; i < 60; i++) {
|
||||
var frame = <BoneAnimationFrame>[];
|
||||
frame.add((
|
||||
rotation:
|
||||
Quaternion.axisAngle(
|
||||
Vector3(1, 0, 0), i/60 * pi/4) *
|
||||
(Quaternion.axisAngle(
|
||||
Vector3(0, 0, 1), i/60*-pi/4)
|
||||
*
|
||||
Quaternion.axisAngle(
|
||||
Vector3(0, 1, 0), i/60 * pi/4) ),
|
||||
translation: Vector3.zero()
|
||||
));
|
||||
frames.add(frame);
|
||||
}
|
||||
// var bone = await controller.getBone(entity, 1);
|
||||
// var frames = <List<BoneAnimationFrame>>[];
|
||||
// for (int i = 0; i < 60; i++) {
|
||||
// var frame = <BoneAnimationFrame>[];
|
||||
// frame.add((
|
||||
// rotation:
|
||||
// Quaternion.axisAngle(
|
||||
// Vector3(1, 0, 0), i/60 * pi/4) *
|
||||
// (Quaternion.axisAngle(
|
||||
// Vector3(0, 0, 1), i/60*-pi/4)
|
||||
// *
|
||||
// Quaternion.axisAngle(
|
||||
// Vector3(0, 1, 0), i/60 * pi/4) ),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frames.add(frame);
|
||||
// }
|
||||
|
||||
var animation = BoneAnimationData(["Bone.002"], frames,
|
||||
space: Space.ParentWorldRotation);
|
||||
await controller.addAnimationComponent(entity);
|
||||
await controller.addBoneAnimation(entity, animation);
|
||||
},
|
||||
child: Text("Test animation (parent space)")),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
await controller.resetBones(entity);
|
||||
// var animation = BoneAnimationData(["Bone.002"], frames,
|
||||
// space: Space.ParentWorldRotation);
|
||||
// await controller.addAnimationComponent(entity);
|
||||
// await controller.addBoneAnimation(entity, animation);
|
||||
// },
|
||||
// child: Text("Test animation (parent space)")),
|
||||
// MenuItemButton(
|
||||
// onPressed: () async {
|
||||
// await controller.resetBones(entity);
|
||||
|
||||
var bone = await controller.getBone(entity, 1);
|
||||
// var bone = await controller.getBone(entity, 1);
|
||||
|
||||
var frames = <List<BoneAnimationFrame>>[];
|
||||
for (int i = 0; i < 60; i++) {
|
||||
var frame = <BoneAnimationFrame>[];
|
||||
frame.add((
|
||||
rotation: Quaternion.axisAngle(
|
||||
Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||
translation: Vector3.zero()
|
||||
));
|
||||
frames.add(frame);
|
||||
}
|
||||
var animation = BoneAnimationData(
|
||||
["Bone.001"], frames,
|
||||
space: Space.Bone);
|
||||
await controller.addAnimationComponent(entity);
|
||||
await controller.addBoneAnimation(entity, animation);
|
||||
},
|
||||
child: Text("Test animation (bone space)")),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
var frames = <List<BoneAnimationFrame>>[];
|
||||
for (int i = 0; i < 60; i++) {
|
||||
var frame = <BoneAnimationFrame>[];
|
||||
frame.add((
|
||||
rotation: Quaternion.axisAngle(
|
||||
Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||
translation: Vector3.zero()
|
||||
));
|
||||
frames.add(frame);
|
||||
}
|
||||
var animation = BoneAnimationData(
|
||||
["Bone.001"], frames,
|
||||
space: Space.ParentWorldRotation);
|
||||
await controller.addAnimationComponent(entity);
|
||||
await controller.addBoneAnimation(entity, animation);
|
||||
},
|
||||
child: Text("Test animation 2")),
|
||||
MenuItemButton(
|
||||
onPressed: () async {
|
||||
var frames = <List<BoneAnimationFrame>>[];
|
||||
for (int i = 0; i < 60; i++) {
|
||||
var frame = <BoneAnimationFrame>[];
|
||||
frame.add((
|
||||
rotation: Quaternion.axisAngle(
|
||||
Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||
translation: Vector3.zero()
|
||||
));
|
||||
frames.add(frame);
|
||||
}
|
||||
var animation = BoneAnimationData(
|
||||
["Bone.002"], frames,
|
||||
space: Space.ParentWorldRotation);
|
||||
await controller.addAnimationComponent(entity);
|
||||
await controller.addBoneAnimation(entity, animation);
|
||||
},
|
||||
child: Text("Test animation 3"))
|
||||
] +
|
||||
boneNames
|
||||
.map((name) {
|
||||
var boneIndex = boneNames.indexOf(name);
|
||||
return SubmenuButton(child: Text(name), menuChildren: [
|
||||
MenuItemButton(
|
||||
child: Text("Print bone transforms "),
|
||||
onPressed: () async {
|
||||
var boneEntity =
|
||||
await controller.getBone(entity, boneIndex);
|
||||
var localTransform = await controller
|
||||
.getLocalTransform(boneEntity);
|
||||
var worldTransform = await controller
|
||||
.getWorldTransform(boneEntity);
|
||||
var inverseWorldTransform = Matrix4.identity()
|
||||
..copyInverse(worldTransform);
|
||||
print("Local $localTransform");
|
||||
print("World $worldTransform");
|
||||
print("World inverse $inverseWorldTransform");
|
||||
}),
|
||||
MenuItemButton(
|
||||
child: Text("Set bone transform to identity"),
|
||||
onPressed: () async {
|
||||
var boneEntity =
|
||||
await controller.getBone(entity, boneIndex);
|
||||
var localTransform = Matrix4.identity();
|
||||
await controller.setTransform(
|
||||
boneEntity, localTransform);
|
||||
await controller.updateBoneMatrices(entity);
|
||||
}),
|
||||
MenuItemButton(
|
||||
child: Text(
|
||||
"Set bone transform to 90/X (parent space)"),
|
||||
onPressed: () async {
|
||||
var boneEntity =
|
||||
await controller.getBone(entity, boneIndex);
|
||||
var localTransform = Matrix4.rotationX(pi / 2);
|
||||
await controller.setTransform(
|
||||
boneEntity, localTransform);
|
||||
await controller.updateBoneMatrices(entity);
|
||||
}),
|
||||
MenuItemButton(
|
||||
child: Text(
|
||||
"Set bone transform to 90/X (pose space)"),
|
||||
onPressed: () async {
|
||||
var boneEntity =
|
||||
await controller.getBone(entity, boneIndex);
|
||||
var localTransform = await controller
|
||||
.getLocalTransform(boneEntity);
|
||||
localTransform =
|
||||
localTransform * Matrix4.rotationX(pi / 2);
|
||||
await controller.setTransform(
|
||||
boneEntity, localTransform);
|
||||
await controller.updateBoneMatrices(entity);
|
||||
}),
|
||||
MenuItemButton(
|
||||
child: Text("Set bone transform to 90/X"),
|
||||
onPressed: () async {
|
||||
var boneEntity =
|
||||
await controller.getBone(entity, boneIndex);
|
||||
var localTransform = Matrix4.rotationX(pi / 2);
|
||||
await controller.setTransform(
|
||||
boneEntity, localTransform);
|
||||
await controller.updateBoneMatrices(entity);
|
||||
}),
|
||||
MenuItemButton(
|
||||
child: Text("Set bone transform to 0,-1,0"),
|
||||
onPressed: () async {
|
||||
var boneEntity =
|
||||
await controller.getBone(entity, boneIndex);
|
||||
var localTransform =
|
||||
Matrix4.translation(Vector3(0, -1, 0));
|
||||
await controller.setTransform(
|
||||
boneEntity, localTransform);
|
||||
await controller.updateBoneMatrices(entity);
|
||||
}),
|
||||
MenuItemButton(
|
||||
child: Text(
|
||||
"Set bone matrices/transform to identity"),
|
||||
onPressed: () async {
|
||||
var boneEntity = await controller.getBone(
|
||||
entity, boneNames.indexOf(name));
|
||||
await controller.setTransform(
|
||||
boneEntity, Matrix4.identity());
|
||||
var childEntities = await controller
|
||||
.getChildEntities(entity, true);
|
||||
for (final child in childEntities) {
|
||||
await controller.setBoneTransform(
|
||||
child,
|
||||
boneNames.indexOf(name),
|
||||
Matrix4.identity());
|
||||
}
|
||||
}),
|
||||
SubmenuButton(
|
||||
child: Text("Set bone matrices to"),
|
||||
menuChildren: [
|
||||
MenuItemButton(
|
||||
child: Text("Identity"),
|
||||
onPressed: () async {
|
||||
await controller
|
||||
.removeAnimationComponent(entity);
|
||||
for (var child in await controller
|
||||
.getChildEntities(entity, true)) {
|
||||
print(
|
||||
"Setting transform for ${await controller.getNameForEntity(child)}");
|
||||
await controller.setBoneTransform(
|
||||
child,
|
||||
boneNames.indexOf(name),
|
||||
Matrix4.identity());
|
||||
}
|
||||
}),
|
||||
SubmenuButton(
|
||||
child: Text("Global"),
|
||||
menuChildren: ["90/X", "90/Y"]
|
||||
.map((rot) => MenuItemButton(
|
||||
onPressed: () async {
|
||||
var transform = rot == "90/X"
|
||||
? Matrix4.rotationX(pi / 2)
|
||||
: Matrix4.rotationY(pi / 2);
|
||||
await controller
|
||||
.removeAnimationComponent(
|
||||
entity);
|
||||
// var frames = <List<BoneAnimationFrame>>[];
|
||||
// for (int i = 0; i < 60; i++) {
|
||||
// var frame = <BoneAnimationFrame>[];
|
||||
// frame.add((
|
||||
// rotation: Quaternion.axisAngle(
|
||||
// Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frames.add(frame);
|
||||
// }
|
||||
// var animation = BoneAnimationData(
|
||||
// ["Bone.001"], frames,
|
||||
// space: Space.Bone);
|
||||
// await controller.addAnimationComponent(entity);
|
||||
// await controller.addBoneAnimation(entity, animation);
|
||||
// },
|
||||
// child: Text("Test animation (bone space)")),
|
||||
// MenuItemButton(
|
||||
// onPressed: () async {
|
||||
// var frames = <List<BoneAnimationFrame>>[];
|
||||
// for (int i = 0; i < 60; i++) {
|
||||
// var frame = <BoneAnimationFrame>[];
|
||||
// frame.add((
|
||||
// rotation: Quaternion.axisAngle(
|
||||
// Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frames.add(frame);
|
||||
// }
|
||||
// var animation = BoneAnimationData(
|
||||
// ["Bone.001"], frames,
|
||||
// space: Space.ParentWorldRotation);
|
||||
// await controller.addAnimationComponent(entity);
|
||||
// await controller.addBoneAnimation(entity, animation);
|
||||
// },
|
||||
// child: Text("Test animation 2")),
|
||||
// MenuItemButton(
|
||||
// onPressed: () async {
|
||||
// var frames = <List<BoneAnimationFrame>>[];
|
||||
// for (int i = 0; i < 60; i++) {
|
||||
// var frame = <BoneAnimationFrame>[];
|
||||
// frame.add((
|
||||
// rotation: Quaternion.axisAngle(
|
||||
// Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frames.add(frame);
|
||||
// }
|
||||
// var animation = BoneAnimationData(
|
||||
// ["Bone.002"], frames,
|
||||
// space: Space.ParentWorldRotation);
|
||||
// await controller.addAnimationComponent(entity);
|
||||
// await controller.addBoneAnimation(entity, animation);
|
||||
// },
|
||||
// child: Text("Test animation 3"))
|
||||
// ] +
|
||||
// boneNames
|
||||
// .map((name) {
|
||||
// var boneIndex = boneNames.indexOf(name);
|
||||
// return SubmenuButton(child: Text(name), menuChildren: [
|
||||
// MenuItemButton(
|
||||
// child: Text("Print bone transforms "),
|
||||
// onPressed: () async {
|
||||
// var boneEntity =
|
||||
// await controller.getBone(entity, boneIndex);
|
||||
// var localTransform = await controller
|
||||
// .getLocalTransform(boneEntity);
|
||||
// var worldTransform = await controller
|
||||
// .getWorldTransform(boneEntity);
|
||||
// var inverseWorldTransform = Matrix4.identity()
|
||||
// ..copyInverse(worldTransform);
|
||||
// print("Local $localTransform");
|
||||
// print("World $worldTransform");
|
||||
// print("World inverse $inverseWorldTransform");
|
||||
// }),
|
||||
// MenuItemButton(
|
||||
// child: Text("Set bone transform to identity"),
|
||||
// onPressed: () async {
|
||||
// var boneEntity =
|
||||
// await controller.getBone(entity, boneIndex);
|
||||
// var localTransform = Matrix4.identity();
|
||||
// await controller.setTransform(
|
||||
// boneEntity, localTransform);
|
||||
// await controller.updateBoneMatrices(entity);
|
||||
// }),
|
||||
// MenuItemButton(
|
||||
// child: Text(
|
||||
// "Set bone transform to 90/X (parent space)"),
|
||||
// onPressed: () async {
|
||||
// var boneEntity =
|
||||
// await controller.getBone(entity, boneIndex);
|
||||
// var localTransform = Matrix4.rotationX(pi / 2);
|
||||
// await controller.setTransform(
|
||||
// boneEntity, localTransform);
|
||||
// await controller.updateBoneMatrices(entity);
|
||||
// }),
|
||||
// MenuItemButton(
|
||||
// child: Text(
|
||||
// "Set bone transform to 90/X (pose space)"),
|
||||
// onPressed: () async {
|
||||
// var boneEntity =
|
||||
// await controller.getBone(entity, boneIndex);
|
||||
// var localTransform = await controller
|
||||
// .getLocalTransform(boneEntity);
|
||||
// localTransform =
|
||||
// localTransform * Matrix4.rotationX(pi / 2);
|
||||
// await controller.setTransform(
|
||||
// boneEntity, localTransform);
|
||||
// await controller.updateBoneMatrices(entity);
|
||||
// }),
|
||||
// MenuItemButton(
|
||||
// child: Text("Set bone transform to 90/X"),
|
||||
// onPressed: () async {
|
||||
// var boneEntity =
|
||||
// await controller.getBone(entity, boneIndex);
|
||||
// var localTransform = Matrix4.rotationX(pi / 2);
|
||||
// await controller.setTransform(
|
||||
// boneEntity, localTransform);
|
||||
// await controller.updateBoneMatrices(entity);
|
||||
// }),
|
||||
// MenuItemButton(
|
||||
// child: Text("Set bone transform to 0,-1,0"),
|
||||
// onPressed: () async {
|
||||
// var boneEntity =
|
||||
// await controller.getBone(entity, boneIndex);
|
||||
// var localTransform =
|
||||
// Matrix4.translation(Vector3(0, -1, 0));
|
||||
// await controller.setTransform(
|
||||
// boneEntity, localTransform);
|
||||
// await controller.updateBoneMatrices(entity);
|
||||
// }),
|
||||
// MenuItemButton(
|
||||
// child: Text(
|
||||
// "Set bone matrices/transform to identity"),
|
||||
// onPressed: () async {
|
||||
// var boneEntity = await controller.getBone(
|
||||
// entity, boneNames.indexOf(name));
|
||||
// await controller.setTransform(
|
||||
// boneEntity, Matrix4.identity());
|
||||
// var childEntities = await controller
|
||||
// .getChildEntities(entity, true);
|
||||
// for (final child in childEntities) {
|
||||
// await controller.setBoneTransform(
|
||||
// child,
|
||||
// boneNames.indexOf(name),
|
||||
// Matrix4.identity());
|
||||
// }
|
||||
// }),
|
||||
// SubmenuButton(
|
||||
// child: Text("Set bone matrices to"),
|
||||
// menuChildren: [
|
||||
// MenuItemButton(
|
||||
// child: Text("Identity"),
|
||||
// onPressed: () async {
|
||||
// await controller
|
||||
// .removeAnimationComponent(entity);
|
||||
// for (var child in await controller
|
||||
// .getChildEntities(entity, true)) {
|
||||
// print(
|
||||
// "Setting transform for ${await controller.getNameForEntity(child)}");
|
||||
// await controller.setBoneTransform(
|
||||
// child,
|
||||
// boneNames.indexOf(name),
|
||||
// Matrix4.identity());
|
||||
// }
|
||||
// }),
|
||||
// SubmenuButton(
|
||||
// child: Text("Global"),
|
||||
// menuChildren: ["90/X", "90/Y"]
|
||||
// .map((rot) => MenuItemButton(
|
||||
// onPressed: () async {
|
||||
// var transform = rot == "90/X"
|
||||
// ? Matrix4.rotationX(pi / 2)
|
||||
// : Matrix4.rotationY(pi / 2);
|
||||
// await controller
|
||||
// .removeAnimationComponent(
|
||||
// entity);
|
||||
|
||||
var index =
|
||||
boneNames.indexOf(name);
|
||||
var childEntities =
|
||||
await controller
|
||||
.getChildEntities(
|
||||
entity, true);
|
||||
// var index =
|
||||
// boneNames.indexOf(name);
|
||||
// var childEntities =
|
||||
// await controller
|
||||
// .getChildEntities(
|
||||
// entity, true);
|
||||
|
||||
for (var child in childEntities) {
|
||||
print(
|
||||
"Setting transform for ${await controller.getNameForEntity(child)} / bone $name (index $index)");
|
||||
await controller
|
||||
.setBoneTransform(child,
|
||||
index, transform);
|
||||
}
|
||||
},
|
||||
child: Text(rot)))
|
||||
.toList()),
|
||||
SubmenuButton(
|
||||
child: Text("Bone"),
|
||||
menuChildren: ["90/X", "90/Y", "90/Z"]
|
||||
.map((rot) => MenuItemButton(
|
||||
onPressed: () async {
|
||||
await controller
|
||||
.removeAnimationComponent(
|
||||
entity);
|
||||
var index =
|
||||
boneNames.indexOf(name);
|
||||
var boneEntity = await controller
|
||||
.getBone(entity, index);
|
||||
var rotation = rot == "90/X"
|
||||
? Matrix4.rotationX(pi / 2)
|
||||
: rot == "90/Y"
|
||||
? Matrix4.rotationY(
|
||||
pi / 2)
|
||||
: Matrix4.rotationZ(
|
||||
pi / 2);
|
||||
// for (var child in childEntities) {
|
||||
// print(
|
||||
// "Setting transform for ${await controller.getNameForEntity(child)} / bone $name (index $index)");
|
||||
// await controller
|
||||
// .setBoneTransform(child,
|
||||
// index, transform);
|
||||
// }
|
||||
// },
|
||||
// child: Text(rot)))
|
||||
// .toList()),
|
||||
// SubmenuButton(
|
||||
// child: Text("Bone"),
|
||||
// menuChildren: ["90/X", "90/Y", "90/Z"]
|
||||
// .map((rot) => MenuItemButton(
|
||||
// onPressed: () async {
|
||||
// await controller
|
||||
// .removeAnimationComponent(
|
||||
// entity);
|
||||
// var index =
|
||||
// boneNames.indexOf(name);
|
||||
// var boneEntity = await controller
|
||||
// .getBone(entity, index);
|
||||
// var rotation = rot == "90/X"
|
||||
// ? Matrix4.rotationX(pi / 2)
|
||||
// : rot == "90/Y"
|
||||
// ? Matrix4.rotationY(
|
||||
// pi / 2)
|
||||
// : Matrix4.rotationZ(
|
||||
// pi / 2);
|
||||
|
||||
var inverseBindMatrix =
|
||||
await controller
|
||||
.getInverseBindMatrix(
|
||||
entity, index);
|
||||
var bindMatrix =
|
||||
Matrix4.identity();
|
||||
bindMatrix.copyInverse(
|
||||
inverseBindMatrix);
|
||||
var childEntities =
|
||||
await controller
|
||||
.getChildEntities(
|
||||
entity, true);
|
||||
// var inverseBindMatrix =
|
||||
// await controller
|
||||
// .getInverseBindMatrix(
|
||||
// entity, index);
|
||||
// var bindMatrix =
|
||||
// Matrix4.identity();
|
||||
// bindMatrix.copyInverse(
|
||||
// inverseBindMatrix);
|
||||
// var childEntities =
|
||||
// await controller
|
||||
// .getChildEntities(
|
||||
// entity, true);
|
||||
|
||||
for (var child in childEntities) {
|
||||
var childGlobalTransform =
|
||||
await controller
|
||||
.getWorldTransform(
|
||||
child);
|
||||
var inverseGlobalTransform =
|
||||
Matrix4.identity();
|
||||
inverseGlobalTransform
|
||||
.copyInverse(
|
||||
childGlobalTransform);
|
||||
var globalBoneTransform =
|
||||
childGlobalTransform *
|
||||
bindMatrix;
|
||||
// for (var child in childEntities) {
|
||||
// var childGlobalTransform =
|
||||
// await controller
|
||||
// .getWorldTransform(
|
||||
// child);
|
||||
// var inverseGlobalTransform =
|
||||
// Matrix4.identity();
|
||||
// inverseGlobalTransform
|
||||
// .copyInverse(
|
||||
// childGlobalTransform);
|
||||
// var globalBoneTransform =
|
||||
// childGlobalTransform *
|
||||
// bindMatrix;
|
||||
|
||||
var transform =
|
||||
(inverseGlobalTransform *
|
||||
(globalBoneTransform *
|
||||
rotation)) *
|
||||
inverseBindMatrix;
|
||||
await controller
|
||||
.setBoneTransform(child,
|
||||
index, transform);
|
||||
}
|
||||
},
|
||||
child: Text(rot)))
|
||||
.toList()),
|
||||
]),
|
||||
MenuItemButton(
|
||||
onPressed: () => _addBoneAnimation(name),
|
||||
child: Text(
|
||||
"Test animation (90 degreees around pose Y)")),
|
||||
]);
|
||||
})
|
||||
.cast<Widget>()
|
||||
.toList(),
|
||||
child: Text("Skeleton"));
|
||||
});
|
||||
}
|
||||
}
|
||||
// var transform =
|
||||
// (inverseGlobalTransform *
|
||||
// (globalBoneTransform *
|
||||
// rotation)) *
|
||||
// inverseBindMatrix;
|
||||
// await controller
|
||||
// .setBoneTransform(child,
|
||||
// index, transform);
|
||||
// }
|
||||
// },
|
||||
// child: Text(rot)))
|
||||
// .toList()),
|
||||
// ]),
|
||||
// MenuItemButton(
|
||||
// onPressed: () => _addBoneAnimation(name),
|
||||
// child: Text(
|
||||
// "Test animation (90 degreees around pose Y)")),
|
||||
// ]);
|
||||
// })
|
||||
// .cast<Widget>()
|
||||
// .toList(),
|
||||
// child: Text("Skeleton"));
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
// MenuItemButton(
|
||||
// onPressed: () async {
|
||||
// var frames = <List<BoneAnimationFrame>>[];
|
||||
// for (int i = 0; i < 60; i++) {
|
||||
// var frame = <BoneAnimationFrame>[];
|
||||
// frame.add((
|
||||
// rotation: Quaternion.axisAngle(
|
||||
// Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frame.add((
|
||||
// rotation: Quaternion.identity(),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frame.add((
|
||||
// rotation: Quaternion.identity(),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frames.add(frame);
|
||||
// }
|
||||
// for (int i = 0; i < 60; i++) {
|
||||
// var frame = <BoneAnimationFrame>[];
|
||||
// frame.add((
|
||||
// rotation: Quaternion.axisAngle(
|
||||
// Vector3(0, 0, 1), pi / 2),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frame.add((
|
||||
// rotation: Quaternion.axisAngle(
|
||||
// Vector3(1, 0, 0), i / 60 * (-pi / 2)),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frame.add((
|
||||
// rotation: Quaternion.identity(),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frames.add(frame);
|
||||
// }
|
||||
// for (int i = 0; i < 60; i++) {
|
||||
// var frame = <BoneAnimationFrame>[];
|
||||
// frame.add((
|
||||
// rotation: Quaternion.axisAngle(
|
||||
// Vector3(0, 0, 1), pi / 2),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frame.add((
|
||||
// rotation: Quaternion.axisAngle(
|
||||
// Vector3(1, 0, 0), (-pi / 2)),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frame.add((
|
||||
// rotation: Quaternion.axisAngle(
|
||||
// Vector3(1, 0, 0), i / 60 * (pi / 2)),
|
||||
// translation: Vector3.zero()
|
||||
// ));
|
||||
// frames.add(frame);
|
||||
// }
|
||||
// // MenuItemButton(
|
||||
// // onPressed: () async {
|
||||
// // var frames = <List<BoneAnimationFrame>>[];
|
||||
// // for (int i = 0; i < 60; i++) {
|
||||
// // var frame = <BoneAnimationFrame>[];
|
||||
// // frame.add((
|
||||
// // rotation: Quaternion.axisAngle(
|
||||
// // Vector3(0, 0, 1), (i / 60) * pi / 2),
|
||||
// // translation: Vector3.zero()
|
||||
// // ));
|
||||
// // frame.add((
|
||||
// // rotation: Quaternion.identity(),
|
||||
// // translation: Vector3.zero()
|
||||
// // ));
|
||||
// // frame.add((
|
||||
// // rotation: Quaternion.identity(),
|
||||
// // translation: Vector3.zero()
|
||||
// // ));
|
||||
// // frames.add(frame);
|
||||
// // }
|
||||
// // for (int i = 0; i < 60; i++) {
|
||||
// // var frame = <BoneAnimationFrame>[];
|
||||
// // frame.add((
|
||||
// // rotation: Quaternion.axisAngle(
|
||||
// // Vector3(0, 0, 1), pi / 2),
|
||||
// // translation: Vector3.zero()
|
||||
// // ));
|
||||
// // frame.add((
|
||||
// // rotation: Quaternion.axisAngle(
|
||||
// // Vector3(1, 0, 0), i / 60 * (-pi / 2)),
|
||||
// // translation: Vector3.zero()
|
||||
// // ));
|
||||
// // frame.add((
|
||||
// // rotation: Quaternion.identity(),
|
||||
// // translation: Vector3.zero()
|
||||
// // ));
|
||||
// // frames.add(frame);
|
||||
// // }
|
||||
// // for (int i = 0; i < 60; i++) {
|
||||
// // var frame = <BoneAnimationFrame>[];
|
||||
// // frame.add((
|
||||
// // rotation: Quaternion.axisAngle(
|
||||
// // Vector3(0, 0, 1), pi / 2),
|
||||
// // translation: Vector3.zero()
|
||||
// // ));
|
||||
// // frame.add((
|
||||
// // rotation: Quaternion.axisAngle(
|
||||
// // Vector3(1, 0, 0), (-pi / 2)),
|
||||
// // translation: Vector3.zero()
|
||||
// // ));
|
||||
// // frame.add((
|
||||
// // rotation: Quaternion.axisAngle(
|
||||
// // Vector3(1, 0, 0), i / 60 * (pi / 2)),
|
||||
// // translation: Vector3.zero()
|
||||
// // ));
|
||||
// // frames.add(frame);
|
||||
// // }
|
||||
|
||||
// var animation = BoneAnimationData(
|
||||
// ["Bone", "Bone.001", "Bone.002"], frames);
|
||||
// await controller.addAnimationComponent(entity);
|
||||
// await controller.addBoneAnimation(entity, animation);
|
||||
// },
|
||||
// child: Text("Test animation (pose space)")),
|
||||
// // var animation = BoneAnimationData(
|
||||
// // ["Bone", "Bone.001", "Bone.002"], frames);
|
||||
// // await controller.addAnimationComponent(entity);
|
||||
// // await controller.addBoneAnimation(entity, animation);
|
||||
// // },
|
||||
// // child: Text("Test animation (pose space)")),
|
||||
@@ -174,6 +174,7 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
|
||||
}
|
||||
|
||||
WidgetsBinding.instance.scheduleFrameCallback((d) async {
|
||||
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
@@ -241,7 +242,7 @@ class _ThermionTextureWidgetState extends State<ThermionTextureWidget> {
|
||||
_logger.info(
|
||||
"Resized texture to dimensions ${_texture!.width}x${_texture!.height} (pixel ratio : $dpr)");
|
||||
|
||||
await widget.viewer.view.setViewport(_texture!.width, _texture!.height);
|
||||
await widget.viewer.setViewport(_texture!.width, _texture!.height);
|
||||
|
||||
await widget.onResize?.call(
|
||||
Size(_texture!.width.toDouble(), _texture!.height.toDouble()),
|
||||
|
||||
@@ -11,6 +11,10 @@ public class ThermionFlutterTexture : NSObject, FlutterTexture {
|
||||
init(registry:FlutterTextureRegistry, width:Int64, height:Int64) {
|
||||
self.registry = registry
|
||||
self.texture = ThermionTextureSwift(width:width, height: height, isDepth: false)
|
||||
// if you need to debug
|
||||
// self.texture.fillColor()
|
||||
// let imageURL = URL(fileURLWithPath: "/Users/nickfisher/Documents/thermion/thermion_dart/test/assets/cube_texture_512x512.png")
|
||||
// let success = self.texture.fillWithPNGImage(imageURL: imageURL)
|
||||
super.init()
|
||||
self.flutterTextureId = registry.register(self)
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
../../../..//thermion_dart/native/macos/ThermionTexture.swift
|
||||
@@ -18,7 +18,7 @@ import 'package:thermion_flutter_platform_interface/thermion_flutter_texture.dar
|
||||
///
|
||||
class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
final channel = const MethodChannel("dev.thermion.flutter/event");
|
||||
|
||||
|
||||
late final _logger = Logger(this.runtimeType.toString());
|
||||
|
||||
static SwapChain? _swapChain;
|
||||
@@ -37,9 +37,10 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
return File(path.replaceAll("file://", "")).readAsBytesSync();
|
||||
}
|
||||
if (path.startsWith("asset://")) {
|
||||
throw UnimplementedError();
|
||||
path = path.replaceAll("asset://", "");
|
||||
}
|
||||
throw UnimplementedError();
|
||||
var asset = await rootBundle.load(path);
|
||||
return asset.buffer.asUint8List(asset.offsetInBytes);
|
||||
}
|
||||
|
||||
Future<ThermionViewer> createViewer({ThermionFlutterOptions? options}) async {
|
||||
@@ -92,18 +93,19 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
throw Exception("Unsupported platform");
|
||||
}
|
||||
}
|
||||
|
||||
final config = FFIFilamentConfig(
|
||||
backend: backend,
|
||||
resourceLoader: resourceLoader,
|
||||
resourceLoader: loadAsset,
|
||||
driver: driverPtr,
|
||||
platform: nullptr,
|
||||
sharedContext: sharedContextPtr,
|
||||
uberArchivePath: options?.uberarchivePath);
|
||||
|
||||
await FFIFilamentApp.create(config);
|
||||
await FFIFilamentApp.create(config: config);
|
||||
|
||||
final viewer = ThermionViewerFFI(
|
||||
loadAsset: loadAsset,
|
||||
loadAssetFromUri: loadAsset,
|
||||
);
|
||||
|
||||
await viewer.initialized;
|
||||
@@ -117,9 +119,10 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
// avoid this
|
||||
if (Platform.isMacOS || Platform.isIOS) {
|
||||
_swapChain = await FilamentApp.instance!.createHeadlessSwapChain(1, 1);
|
||||
await FilamentApp.instance!.register(_swapChain!, viewer.view);
|
||||
}
|
||||
|
||||
return viewer!;
|
||||
return viewer;
|
||||
}
|
||||
|
||||
Future<PlatformTextureDescriptor> createTextureDescriptor(
|
||||
@@ -157,27 +160,36 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
|
||||
_swapChain = await FilamentApp.instance!
|
||||
.createHeadlessSwapChain(descriptor.width, descriptor.height);
|
||||
await FilamentApp.instance!.register(_swapChain!, view);
|
||||
} else if (Platform.isAndroid) {
|
||||
if (_swapChain != null) {
|
||||
await FilamentApp.instance!.setRenderable(view, false);
|
||||
await FilamentApp.instance!.destroySwapChain(_swapChain!);
|
||||
}
|
||||
_swapChain = await FilamentApp.instance!.createSwapChain(descriptor.windowHandle!);
|
||||
_swapChain =
|
||||
await FilamentApp.instance!.createSwapChain(descriptor.windowHandle!);
|
||||
await FilamentApp.instance!.register(_swapChain!, view);
|
||||
|
||||
} else {
|
||||
final color = await FilamentApp.instance!.createTexture(
|
||||
descriptor.width, descriptor.height,
|
||||
importedTextureHandle: descriptor.hardwareId,
|
||||
flags: {
|
||||
TextureUsage.TEXTURE_USAGE_BLIT_DST,
|
||||
TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT,
|
||||
TextureUsage.TEXTURE_USAGE_SAMPLEABLE
|
||||
});
|
||||
final depth =
|
||||
await FilamentApp.instance!.createTexture(descriptor.width, descriptor.height, flags: {
|
||||
TextureUsage.TEXTURE_USAGE_BLIT_DST,
|
||||
TextureUsage.TEXTURE_USAGE_DEPTH_ATTACHMENT,
|
||||
TextureUsage.TEXTURE_USAGE_SAMPLEABLE
|
||||
});
|
||||
final color = await FilamentApp.instance!
|
||||
.createTexture(descriptor.width, descriptor.height,
|
||||
importedTextureHandle: descriptor.hardwareId,
|
||||
flags: {
|
||||
// TextureUsage.TEXTURE_USAGE_BLIT_DST,
|
||||
TextureUsage.TEXTURE_USAGE_COLOR_ATTACHMENT,
|
||||
TextureUsage.TEXTURE_USAGE_SAMPLEABLE
|
||||
},
|
||||
textureFormat: TextureFormat.RGBA8,
|
||||
textureSamplerType: TextureSamplerType.SAMPLER_2D);
|
||||
final depth = await FilamentApp.instance!
|
||||
.createTexture(descriptor.width, descriptor.height,
|
||||
flags: {
|
||||
// TextureUsage.TEXTURE_USAGE_BLIT_DST,
|
||||
TextureUsage.TEXTURE_USAGE_DEPTH_ATTACHMENT,
|
||||
TextureUsage.TEXTURE_USAGE_SAMPLEABLE,
|
||||
},
|
||||
textureFormat: TextureFormat.DEPTH32F,
|
||||
textureSamplerType: TextureSamplerType.SAMPLER_2D);
|
||||
|
||||
var renderTarget = await FilamentApp.instance!.createRenderTarget(
|
||||
descriptor.width, descriptor.height,
|
||||
@@ -185,7 +197,6 @@ class ThermionFlutterMethodChannelPlatform extends ThermionFlutterPlatform {
|
||||
|
||||
await view.setRenderTarget(renderTarget);
|
||||
}
|
||||
await FilamentApp.instance!.register(_swapChain!, view);
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:thermion_dart/thermion_dart.dart' as t;
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
import 'package:thermion_dart/thermion_dart.dart';
|
||||
import 'package:thermion_dart/src/filament/filament.dart';
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
import 'thermion_flutter_texture.dart';
|
||||
|
||||
class ThermionFlutterOptions {
|
||||
final String? uberarchivePath;
|
||||
final Backend? backend;
|
||||
|
||||
ThermionFlutterOptions({this.uberarchivePath});
|
||||
const ThermionFlutterOptions.empty() : uberarchivePath = null;
|
||||
const ThermionFlutterOptions({this.uberarchivePath = null, this.backend = null});
|
||||
}
|
||||
|
||||
|
||||
|
||||
abstract class ThermionFlutterPlatform extends PlatformInterface {
|
||||
ThermionFlutterPlatform() : super(token: _token);
|
||||
|
||||
@@ -34,12 +32,13 @@ abstract class ThermionFlutterPlatform extends PlatformInterface {
|
||||
{covariant ThermionFlutterOptions? options});
|
||||
|
||||
///
|
||||
/// Creates a raw rendering surface.
|
||||
/// Creates a raw rendering surface.
|
||||
///
|
||||
/// This is internal; unless you are [thermion_*] package developer, don't
|
||||
/// call this yourself. May not be supported on all platforms.
|
||||
///
|
||||
Future<PlatformTextureDescriptor> createTextureDescriptor(int width, int height);
|
||||
Future<PlatformTextureDescriptor> createTextureDescriptor(
|
||||
int width, int height);
|
||||
|
||||
///
|
||||
/// Destroys a raw rendering surface.
|
||||
@@ -53,15 +52,14 @@ abstract class ThermionFlutterPlatform extends PlatformInterface {
|
||||
/// call this yourself. May not be supported on all platforms.
|
||||
///
|
||||
Future<PlatformTextureDescriptor?> createTextureAndBindToView(
|
||||
t.View view, int width, int height);
|
||||
View view, int width, int height);
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
Future<PlatformTextureDescriptor?> resizeTexture(
|
||||
PlatformTextureDescriptor texture, t.View view, int width, int height);
|
||||
|
||||
PlatformTextureDescriptor texture, View view, int width, int height);
|
||||
|
||||
///
|
||||
///
|
||||
|
||||
@@ -31,7 +31,7 @@ class ThermionFlutterWebPlugin extends ThermionFlutterPlatform {
|
||||
(offsetTop * pixelRatio).ceil().toString();
|
||||
|
||||
_viewer!
|
||||
.updateViewportAndCameraProjection(width.ceil(), height.ceil(), 1.0);
|
||||
.setViewportAndCameraProjection(width.ceil(), height.ceil(), 1.0);
|
||||
|
||||
return PlatformTextureDescriptor(null, null, 0, 0, null);
|
||||
}
|
||||
@@ -53,7 +53,7 @@ class ThermionFlutterWebPlugin extends ThermionFlutterPlatform {
|
||||
(offsetLeft * pixelRatio).ceil().toString();
|
||||
(canvas as HTMLElement).style.top =
|
||||
(offsetTop * pixelRatio).ceil().toString();
|
||||
_viewer!.updateViewportAndCameraProjection(width, height, 1.0);
|
||||
_viewer!.setViewportAndCameraProjection(width, height, 1.0);
|
||||
return PlatformTextureDescriptor(null, null, 0, 0, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,5 @@ class ThermionFlutterWebOptions extends ThermionFlutterOptions {
|
||||
String? uberarchivePath})
|
||||
: super(uberarchivePath: uberarchivePath);
|
||||
|
||||
const ThermionFlutterWebOptions.empty(
|
||||
{this.importCanvasAsWidget = false,
|
||||
this.createCanvas = true,
|
||||
String? uberarchivePath})
|
||||
: super.empty();
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user