refactoring

This commit is contained in:
Nick Fisher
2025-03-21 14:56:20 +08:00
parent 1177a71f73
commit 255c0edd49
38 changed files with 1521 additions and 1207 deletions

View File

@@ -20,4 +20,5 @@ class ThermionFlutterPlugin {
return viewer;
}
}

View File

@@ -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;
// }
// }

View File

@@ -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,
// ),
// ),
// ));
// }
// }

View File

@@ -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());
// });
// }
// }

View File

@@ -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)")),

View File

@@ -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()),

View File

@@ -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)
}

View File

@@ -0,0 +1 @@
../../../..//thermion_dart/native/macos/ThermionTexture.swift

View File

@@ -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;
}

View File

@@ -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);
///
///

View File

@@ -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);
}

View File

@@ -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();
}