refactoring

This commit is contained in:
Nick Fisher
2025-03-19 15:42:11 +08:00
parent 627447f8b0
commit 102429e090
20 changed files with 508 additions and 590 deletions

View File

@@ -3,17 +3,27 @@ library;
import 'package:animation_tools_dart/animation_tools_dart.dart';
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';
import 'entity.dart';
export 'geometry.dart';
export 'gltf.dart';
export 'light_options.dart';
///
/// Represents a renderable object (i.e. not cameras or lights).
///
/// At a low level, Filament works with entities. In practice,
/// it can be difficult to work directly with these at a higher level
/// because:
/// a) certain objects don't map exactly to entities (e.g. glTF assets, which
/// are represented by a hierarchy of entities).
/// b) it is not trivial to create instances directly from entities
///
/// [ThermionAsset] is intended to provide a unified high-level interface
/// for working with renderable objects.
///
///
abstract class ThermionAsset {
///
///
/// The top-most entity in the hierarchy. If this is a glTF asset
///
ThermionEntity get entity;
@@ -22,6 +32,11 @@ abstract class ThermionAsset {
///
Future<List<ThermionEntity>> getChildEntities();
///
///
///
Future<ThermionEntity?> getChildEntity(String childName);
///
///
///
@@ -95,7 +110,7 @@ abstract class ThermionAsset {
///
/// Schedules the glTF animation at [index] in [asset] to start playing on the next frame.
///
Future playAnimation(ThermionAsset asset, int index,
Future playAnimation(int index,
{bool loop = false,
bool reverse = false,
bool replaceActive = true,
@@ -105,7 +120,7 @@ abstract class ThermionAsset {
///
/// Schedules the glTF animation at [index] in [entity] to start playing on the next frame.
///
Future playAnimationByName(covariant ThermionAsset asset, String name,
Future playAnimationByName(String name,
{bool loop = false,
bool reverse = false,
bool replaceActive = true,
@@ -114,20 +129,19 @@ abstract class ThermionAsset {
///
///
///
Future setGltfAnimationFrame(
covariant ThermionAsset asset, int index, int animationFrame);
Future setGltfAnimationFrame(int index, int animationFrame);
///
///
///
Future stopAnimation(covariant ThermionAsset asset, int animationIndex);
Future stopAnimation(int animationIndex);
///
///
///
Future stopAnimationByName(covariant ThermionAsset asset, String name);
Future stopAnimationByName(String name);
///
///
/// Set the weights for all morph targets in [entity] to [weights].
/// Note that [weights] must contain values for ALL morph targets, but no exception will be thrown if you don't do so (you'll just get incorrect results).
/// If you only want to set one value, set all others to zero (check [getMorphTargetNames] if you need the get a list of all morph targets).
@@ -137,27 +151,24 @@ abstract class ThermionAsset {
Future setMorphTargetWeights(ThermionEntity entity, List<double> weights);
///
/// Gets the names of all morph targets for the child renderable [childEntity] under [entity].
/// Gets the names of all morph targets for [entity] (which must be a renderable entity)
///
Future<List<String>> getMorphTargetNames(
covariant ThermionAsset asset, ThermionEntity childEntity);
Future<List<String>> getMorphTargetNames({ThermionEntity? entity});
///
/// Gets the names of all bones for the armature at [skinIndex] under the specified [entity].
/// Gets the names of all bones for the skin at [skinIndex].
///
Future<List<String>> getBoneNames(covariant ThermionAsset asset,
{int skinIndex = 0});
Future<List<String>> getBoneNames({int skinIndex = 0});
///
/// Gets the names of all glTF animations embedded in the specified entity.
///
Future<List<String>> getAnimationNames(covariant ThermionAsset asset);
Future<List<String>> getAnimationNames();
///
/// Returns the length (in seconds) of the animation at the given index.
///
Future<double> getAnimationDuration(
covariant ThermionAsset asset, int animationIndex);
Future<double> getAnimationDuration(int animationIndex);
///
/// Construct animation(s) for every entity under [asset]. If [targetMeshNames] is provided, only entities with matching names will be animated.
@@ -166,8 +177,7 @@ abstract class ThermionAsset {
/// throwing an exception if any cannot be found.
/// It is permissible for [animation] to omit any targets that do exist under [meshName]; these simply won't be animated.
///
Future setMorphAnimationData(
covariant ThermionAsset asset, MorphAnimationData animation,
Future setMorphAnimationData(MorphAnimationData animation,
{List<String>? targetMeshNames});
///
@@ -179,7 +189,7 @@ abstract class ThermionAsset {
/// Resets all bones in the given entity to their rest pose.
/// This should be done before every call to addBoneAnimation.
///
Future resetBones(ThermionAsset asset);
Future resetBones();
///
/// Enqueues and plays the [animation] for the specified bone(s).
@@ -199,7 +209,7 @@ abstract class ThermionAsset {
/// This will be applied in reverse after [fadeOutInSecs].
///
///
Future addBoneAnimation(ThermionAsset asset, BoneAnimationData animation,
Future addBoneAnimation(BoneAnimationData animation,
{int skinIndex = 0,
double fadeInInSecs = 0.0,
double fadeOutInSecs = 0.0,
@@ -209,32 +219,29 @@ abstract class ThermionAsset {
/// Gets the entity representing the bone at [boneIndex]/[skinIndex].
/// The returned entity is only intended for use with [getWorldTransform].
///
Future<ThermionEntity> getBone(covariant ThermionAsset asset, int boneIndex,
{int skinIndex = 0});
Future<ThermionEntity> getBone(int boneIndex, {int skinIndex = 0});
///
/// Gets the local (relative to parent) transform for [entity].
///
Future<Matrix4> getLocalTransform(ThermionEntity entity);
Future<Matrix4> getLocalTransform({ThermionEntity? entity});
///
/// Gets the world transform for [entity].
///
Future<Matrix4> getWorldTransform(ThermionEntity entity);
Future<Matrix4> getWorldTransform({ThermionEntity? entity});
///
/// Gets the inverse bind (pose) matrix for the bone.
/// Note that [parent] must be the ThermionEntity returned by [loadGlb/loadGltf], not any other method ([getChildEntity] etc).
/// This is because all joint information is internally stored with the parent entity.
///
Future<Matrix4> getInverseBindMatrix(
covariant ThermionAsset asset, int boneIndex,
{int skinIndex = 0});
Future<Matrix4> getInverseBindMatrix(int boneIndex, {int skinIndex = 0});
///
/// Sets the transform (relative to its parent) for [entity].
///
Future setTransform(ThermionEntity entity, Matrix4 transform);
Future setTransform(Matrix4 transform, {ThermionEntity? entity});
///
/// Updates the bone matrices for [entity] (which must be the ThermionEntity
@@ -264,4 +271,3 @@ abstract class ThermionAsset {
///
Future removeAnimationComponent(ThermionEntity entity);
}

View File

@@ -1,5 +1,4 @@
import 'dart:typed_data';
import 'package:thermion_dart/src/filament/src/engine.dart';
import 'package:thermion_dart/thermion_dart.dart';
@@ -29,7 +28,6 @@ class FilamentConfig<T, U> {
}
abstract class FilamentApp<T> {
static FilamentApp? instance;
final T engine;
@@ -170,13 +168,6 @@ abstract class FilamentApp<T> {
Future<MaterialInstance> getMaterialInstanceAt(
ThermionEntity entity, int index);
///
///
///
@override
Future<ThermionAsset> createGeometry(Geometry geometry,
{List<MaterialInstance>? materialInstances, bool keepData = false});
///
///
///
@@ -206,4 +197,27 @@ abstract class FilamentApp<T> {
///
///
Future unregisterRequestFrameHook(Future Function() hook);
///
/// Retrieves the name assigned to the given entity (usually corresponds to the glTF mesh name).
///
String? getNameForEntity(ThermionEntity entity);
///
/// Gets the parent entity of [entity]. Returns null if the entity has no parent.
///
Future<ThermionEntity?> getParent(ThermionEntity entity);
///
/// Gets the ancestor (ultimate parent) entity of [entity]. Returns null if the entity has no parent.
///
Future<ThermionEntity?> getAncestor(ThermionEntity entity);
///
/// Sets the parent transform of [child] to [parent].
///
Future setParent(ThermionEntity child, ThermionEntity? parent,
{bool preserveScaling});
Future<MaterialInstance> createImageMaterialInstance();
}

View File

@@ -1,4 +1,5 @@
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/filament/src/scene.dart';
import 'package:thermion_dart/thermion_dart.dart';
///
@@ -18,6 +19,7 @@ class Viewport {
enum QualityLevel { LOW, MEDIUM, HIGH, ULTRA }
abstract class View {
Future<Scene> getScene();
Future<Viewport> getViewport();
Future setViewport(int width, int height);
Future<RenderTarget?> getRenderTarget();

View File

@@ -1,8 +1,6 @@
import 'dart:async';
import 'package:logging/logging.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';
import 'implementations/fixed_orbit_camera_rotation_delegate.dart';
import 'implementations/free_flight_camera_delegate.dart';
@@ -64,7 +62,7 @@ class DelegateInputHandler implements InputHandler {
_inputDeltas[gestureType] = Vector3.zero();
}
viewer.registerRequestFrameHook(process);
FilamentApp.instance!.registerRequestFrameHook(process);
}
factory DelegateInputHandler.fixedOrbit(ThermionViewer viewer,
@@ -75,7 +73,7 @@ class DelegateInputHandler implements InputHandler {
DelegateInputHandler(
viewer: viewer,
pickDelegate: pickDelegate,
transformDelegate: FixedOrbitRotateInputHandlerDelegate(viewer,
transformDelegate: FixedOrbitRotateInputHandlerDelegate(viewer.view,
minimumDistance: minimumDistance),
actions: {
InputType.MMB_HOLD_AND_MOVE: InputAction.ROTATE,
@@ -96,9 +94,8 @@ class DelegateInputHandler implements InputHandler {
DelegateInputHandler(
viewer: viewer,
pickDelegate: pickDelegate,
transformDelegate: FreeFlightInputHandlerDelegate(viewer,
transformDelegate: FreeFlightInputHandlerDelegate(viewer.view,
clampY: clampY,
entity: entity,
rotationSensitivity: rotateSensitivity,
zoomSensitivity: zoomSensitivity,
panSensitivity: panSensitivity,
@@ -245,7 +242,7 @@ class DelegateInputHandler implements InputHandler {
@override
Future dispose() async {
viewer.unregisterRequestFrameHook(process);
FilamentApp.instance!.unregisterRequestFrameHook(process);
}
@override

View File

@@ -10,8 +10,7 @@ import '../input_handler.dart';
/// point.
///
class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
final ThermionViewer viewer;
late Future<Camera> _camera;
final View view;
final double minimumDistance;
late final Vector3 target;
@@ -24,20 +23,17 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
Timer? _updateTimer;
FixedOrbitRotateInputHandlerDelegate(
this.viewer, {
this.view, {
Vector3? target,
this.minimumDistance = 10.0,
this.rotationSensitivity = 0.01,
this.zoomSensitivity = 0.1,
}) {
this.target = target ?? Vector3.zero();
_camera = viewer.getMainCamera().then((Camera cam) async {
var viewMatrix = makeViewMatrix(Vector3(0.0, 0, -minimumDistance),
this.target, Vector3(0.0, 1.0, 0.0));
viewMatrix.invert();
await cam.setTransform(viewMatrix);
return cam;
view.getCamera().then((camera) {
camera.lookAt(Vector3(0.0, 0, -minimumDistance),
focus: this.target, up: Vector3(0.0, 1.0, 0.0));
});
}
@@ -81,12 +77,13 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
_executing = true;
final view = await viewer.getViewAt(0);
final camera = await view.getCamera();
final viewport = await view.getViewport();
var viewMatrix = await viewer.getCameraViewMatrix();
var modelMatrix = await viewer.getCameraModelMatrix();
var projectionMatrix = await viewer.getCameraProjectionMatrix();
var viewMatrix = await camera.getViewMatrix();
var modelMatrix = await camera.getModelMatrix();
var projectionMatrix = await camera.getProjectionMatrix();
var inverseProjectionMatrix = projectionMatrix.clone()..invert();
Vector3 currentPosition = modelMatrix.getTranslation();
@@ -117,14 +114,14 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
Matrix4 newViewMatrix = makeViewMatrix(currentPosition, target, up);
newViewMatrix.invert();
await (await _camera).setModelMatrix(newViewMatrix);
await camera.setModelMatrix(newViewMatrix);
updatedModelMatrix = newViewMatrix;
}
} else if (_queuedRotationDelta.length != 0) {
double rotateX = _queuedRotationDelta.x * rotationSensitivity;
double rotateY = _queuedRotationDelta.y * rotationSensitivity;
var modelMatrix = await viewer.getCameraModelMatrix();
var modelMatrix = await camera.getModelMatrix();
// for simplicity, we always assume a fixed coordinate system where
// we are rotating around world Y and camera X
@@ -136,7 +133,7 @@ class FixedOrbitRotateInputHandlerDelegate implements InputHandlerDelegate {
.asRotationMatrix());
modelMatrix = rot1 * rot2 * modelMatrix;
await (await _camera).setModelMatrix(modelMatrix);
await camera.setModelMatrix(modelMatrix);
updatedModelMatrix = modelMatrix;
}

View File

@@ -5,8 +5,8 @@ import '../delegates.dart';
import '../input_handler.dart';
class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
final ThermionViewer viewer;
late Future<ThermionEntity> entity;
final View view;
final Vector3? minBounds;
final Vector3? maxBounds;
final double rotationSensitivity;
@@ -20,21 +20,14 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
double _queuedZoomDelta = 0.0;
Vector3 _queuedMoveDelta = Vector3.zero();
FreeFlightInputHandlerDelegate(this.viewer,
FreeFlightInputHandlerDelegate(this.view,
{this.minBounds,
this.maxBounds,
this.rotationSensitivity = 0.001,
this.movementSensitivity = 0.1,
this.zoomSensitivity = 0.1,
this.panSensitivity = 0.1,
this.clampY,
ThermionEntity? entity}) {
if (entity != null) {
this.entity = Future.value(entity);
} else {
this.entity = viewer.getMainCameraEntity();
}
}
this.clampY}) {}
@override
Future<void> queue(InputAction action, Vector3? delta) async {
@@ -76,9 +69,9 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
return null;
}
final activeCamera = await viewer.getActiveCamera();
final activeCamera = await view.getCamera();
Matrix4 current = await viewer.getLocalTransform(await entity);
Matrix4 current = await activeCamera.getModelMatrix();
Vector3 relativeTranslation = Vector3.zero();
Quaternion relativeRotation = Quaternion.identity();
@@ -121,17 +114,18 @@ class FreeFlightInputHandlerDelegate implements InputHandlerDelegate {
_queuedMoveDelta = Vector3.zero();
}
// If the managed entity is not the active camera, we need to apply the rotation from the current camera model matrix
// to the entity's translation
if (await entity != activeCamera.getEntity()) {
Matrix4 modelMatrix = await activeCamera.getModelMatrix();
relativeTranslation = modelMatrix.getRotation() * relativeTranslation;
}
// // If the managed entity is not the active camera, we need to apply the rotation from the current camera model matrix
// // to the entity's translation
// if (await entity != activeCamera.getEntity()) {
// Matrix4 modelMatrix = await activeCamera.getModelMatrix();
// relativeTranslation = modelMatrix.getRotation() * relativeTranslation;
// }
var updated = Matrix4.compose(
relativeTranslation, relativeRotation, Vector3(1, 1, 1)) *
current;
await viewer.setTransform(await entity, updated);
await activeCamera.setModelMatrix(updated);
_executing = false;
return updated;

View File

@@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:math';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';
class _Gizmo {
final ThermionViewer viewer;
@@ -16,7 +15,7 @@ class _Gizmo {
_Gizmo(this._gizmo, this.viewer, this.type);
static Future<_Gizmo> forType(ThermionViewer viewer, GizmoType type) async {
final view = await viewer.getViewAt(0);
final view = await viewer.view;
return _Gizmo(await viewer.createGizmo(view, type), viewer, type);
}
@@ -26,12 +25,14 @@ class _Gizmo {
}
Future hide() async {
await _gizmo.removeFromScene();
final scene = await viewer.view.getScene();
await scene.remove(_gizmo);
}
Future reveal() async {
await _gizmo.addToScene();
gizmoTransform = await viewer.getWorldTransform(_gizmo.entity);
final scene = await viewer.view.getScene();
await scene.add(_gizmo);
gizmoTransform = await _gizmo.getWorldTransform();
}
double _getAngleBetweenVectors(Vector2 v1, Vector2 v2) {
@@ -76,17 +77,17 @@ class _Gizmo {
await _updateRotation(currentPosition, delta);
}
await viewer.setTransform(_gizmo.entity, gizmoTransform!);
await _gizmo.setTransform(gizmoTransform!);
transformUpdates.add((transform: gizmoTransform!));
}
Future<void>? _updateTranslation(
Vector2 currentPosition, Vector2 delta) async {
var view = await viewer.getViewAt(0);
var view = await viewer.view;
var camera = await viewer.getActiveCamera();
var viewport = await view.getViewport();
var projectionMatrix = await viewer.getCameraProjectionMatrix();
var projectionMatrix = await camera.getProjectionMatrix();
var viewMatrix = await camera.getViewMatrix();
var inverseViewMatrix = await camera.getModelMatrix();
var inverseProjectionMatrix = projectionMatrix.clone()..invert();
@@ -121,10 +122,9 @@ class _Gizmo {
}
Future<void>? _updateRotation(Vector2 currentPosition, Vector2 delta) async {
var view = await viewer.getViewAt(0);
var camera = await viewer.getActiveCamera();
var viewport = await view.getViewport();
var projectionMatrix = await viewer.getCameraProjectionMatrix();
var camera = await viewer.view.getCamera();
var viewport = await viewer.view.getViewport();
var projectionMatrix = await camera.getProjectionMatrix();
var viewMatrix = await camera.getViewMatrix();
// Get gizmo center in screen space
@@ -187,7 +187,6 @@ class _Gizmo {
}
class GizmoInputHandler extends InputHandler {
final ThermionViewer viewer;
late final _gizmos = <GizmoType, _Gizmo>{};
@@ -202,7 +201,7 @@ class GizmoInputHandler extends InputHandler {
}
_attached = entity;
if (_active != null) {
await viewer.setParent(_attached!, _active!._gizmo.entity);
await FilamentApp.instance!.setParent(_attached!, _active!._gizmo.entity);
await _active!.reveal();
}
}
@@ -215,7 +214,7 @@ class GizmoInputHandler extends InputHandler {
if (_attached == null) {
return;
}
await viewer.setParent(_attached!, 0);
await FilamentApp.instance!.setParent(_attached!, null);
await _active?.hide();
_attached = null;
}

View File

@@ -1,43 +0,0 @@
import 'dart:typed_data';
import 'package:vector_math/vector_math_64.dart';
import '../../viewer/viewer.dart';
class AxisWidget {
final ThermionViewer _viewer;
final ThermionEntity xAxis;
final ThermionEntity yAxis;
final ThermionEntity zAxis;
AxisWidget._(this.xAxis, this.yAxis, this.zAxis, this._viewer);
static Future<Axis> create(ThermionViewer viewer) async {
final xAxis = await viewer.createGeometry(
Geometry(Float32List.fromList([0, 0, 0, 10, 0, 0]), [0, 1],
primitiveType: PrimitiveType.LINES),
materialInstances: [await viewer.createUnlitMaterialInstance()]);
final yAxis = await viewer.createGeometry(
Geometry(Float32List.fromList([0, 0, 0, 0, 10, 0]), [0, 1],
primitiveType: PrimitiveType.LINES),
materialInstances: [await viewer.createUnlitMaterialInstance()]);
final zAxis = await viewer.createGeometry(
Geometry(Float32List.fromList([0, 0, 0, 0, 0, 10]), [0, 1],
primitiveType: PrimitiveType.LINES),
materialInstances: [await viewer.createUnlitMaterialInstance()]);
throw Exception("TODO");
// await viewer!.setMaterialPropertyFloat4(
// xAxis, "baseColorFactor", 0, 1.0, 0.0, 0.0, 1.0);
// await viewer!.setMaterialPropertyFloat4(
// yAxis, "baseColorFactor", 0, 0.0, 1.0, 0.0, 1.0);
// await viewer!.setMaterialPropertyFloat4(
// zAxis, "baseColorFactor", 0, 0.0, 0.0, 1.0, 1.0);
// return Axis._(xAxis, yAxis, zAxis, viewer);
}
Future setTransform(Matrix4 transform) async {
await _viewer.setTransform(xAxis, transform);
await _viewer.setTransform(yAxis, transform);
await _viewer.setTransform(zAxis, transform);
}
}

View File

@@ -1,5 +1,4 @@
library;
export 'src/geometry.dart';
export 'src/axis.dart';
export 'src/image.dart';

View File

@@ -5,25 +5,23 @@ import 'package:animation_tools_dart/src/morph_animation_data.dart';
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_scene.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart';
import 'package:thermion_dart/thermion_dart.dart';
class BackgroundImage extends ThermionAsset {
final ThermionAsset asset;
ThermionEntity get entity => asset.entity;
Texture? _backgroundImageTexture;
FFIMaterial? _imageMaterial;
FFITextureSampler? _imageSampler;
final FFIScene scene;
final FilamentApp app;
BackgroundImage._(this.asset, this.scene, this.app,
this._backgroundImageTexture, this._imageMaterial, this._imageSampler);
BackgroundImage._(
this.asset, this.scene, this._backgroundImageTexture, this._imageSampler);
Future destroy() async {
Scene_removeEntity(scene.scene, entity);
@@ -32,33 +30,39 @@ class BackgroundImage extends ThermionAsset {
}
static Future<BackgroundImage> create(
FFIFilamentApp app, FFIScene scene, Uint8List imageData) async {
final image = await app.decodeImage(imageData);
var backgroundImageTexture = await app.createTexture(
await image.getWidth(), await image.getHeight());
var imageMaterial = FFIMaterial(Material_createImageMaterial(), app);
var imageSampler = await app.createTextureSampler() as FFITextureSampler;
ThermionViewer viewer, FFIScene scene, Uint8List imageData) async {
final image = await FilamentApp.instance!.decodeImage(imageData);
var backgroundImageTexture = await FilamentApp.instance!
.createTexture(await image.getWidth(), await image.getHeight());
var imageSampler =
await FilamentApp.instance!.createTextureSampler() as FFITextureSampler;
var imageMaterialInstance =
await imageMaterial!.createInstance() as FFIMaterialInstance;
await FilamentApp.instance!.createImageMaterialInstance();
await imageMaterialInstance.setParameterTexture(
"image",
backgroundImageTexture as FFITexture,
imageSampler as FFITextureSampler);
"image", backgroundImageTexture as FFITexture, imageSampler);
var backgroundImage =
await app.createGeometry(GeometryHelper.fullscreenQuad()) as FFIAsset;
await viewer.createGeometry(GeometryHelper.fullscreenQuad());
backgroundImage.setMaterialInstanceAt(imageMaterialInstance);
await scene.add(backgroundImage);
return BackgroundImage._(backgroundImage, scene, app,
backgroundImageTexture, imageMaterial, imageSampler);
await scene.add(backgroundImage as FFIAsset);
return BackgroundImage._(
backgroundImage, scene, backgroundImageTexture, imageSampler);
}
///
///
///
@override
Future<ThermionAsset> createInstance(
{covariant List<MaterialInstance>? materialInstances = null}) {
throw UnimplementedError();
}
///
///
///
@override
Future<List<ThermionEntity>> getChildEntities() async {
return [];
@@ -129,7 +133,11 @@ class BackgroundImage extends ThermionAsset {
}
@override
Future addBoneAnimation(ThermionAsset asset, BoneAnimationData animation, {int skinIndex = 0, double fadeInInSecs = 0.0, double fadeOutInSecs = 0.0, double maxDelta = 1.0}) {
Future addBoneAnimation(BoneAnimationData animation,
{int skinIndex = 0,
double fadeInInSecs = 0.0,
double fadeOutInSecs = 0.0,
double maxDelta = 1.0}) {
// TODO: implement addBoneAnimation
throw UnimplementedError();
}
@@ -141,61 +149,76 @@ class BackgroundImage extends ThermionAsset {
}
@override
Future<double> getAnimationDuration(covariant ThermionAsset asset, int animationIndex) {
Future<double> getAnimationDuration(int animationIndex) {
// TODO: implement getAnimationDuration
throw UnimplementedError();
}
@override
Future<List<String>> getAnimationNames(covariant ThermionAsset asset) {
Future<List<String>> getAnimationNames() {
// TODO: implement getAnimationNames
throw UnimplementedError();
}
@override
Future<ThermionEntity> getBone(covariant ThermionAsset asset, int boneIndex, {int skinIndex = 0}) {
Future<ThermionEntity> getBone(int boneIndex, {int skinIndex = 0}) {
// TODO: implement getBone
throw UnimplementedError();
}
@override
Future<List<String>> getBoneNames(covariant ThermionAsset asset, {int skinIndex = 0}) {
Future<List<String>> getBoneNames({int skinIndex = 0}) {
// TODO: implement getBoneNames
throw UnimplementedError();
}
@override
Future<Matrix4> getInverseBindMatrix(covariant ThermionAsset asset, int boneIndex, {int skinIndex = 0}) {
Future<ThermionEntity?> getChildEntity(String childName) {
// TODO: implement getChildEntity
throw UnimplementedError();
}
@override
Future<Matrix4> getInverseBindMatrix(int boneIndex, {int skinIndex = 0}) {
// TODO: implement getInverseBindMatrix
throw UnimplementedError();
}
@override
Future<Matrix4> getLocalTransform(ThermionEntity entity) {
Future<Matrix4> getLocalTransform({ThermionEntity? entity}) {
// TODO: implement getLocalTransform
throw UnimplementedError();
}
@override
Future<List<String>> getMorphTargetNames(covariant ThermionAsset asset, ThermionEntity childEntity) {
Future<List<String>> getMorphTargetNames({ThermionEntity? entity}) {
// TODO: implement getMorphTargetNames
throw UnimplementedError();
}
@override
Future<Matrix4> getWorldTransform(ThermionEntity entity) {
Future<Matrix4> getWorldTransform({ThermionEntity? entity}) {
// TODO: implement getWorldTransform
throw UnimplementedError();
}
@override
Future playAnimation(ThermionAsset asset, int index, {bool loop = false, bool reverse = false, bool replaceActive = true, double crossfade = 0.0, double startOffset = 0.0}) {
Future playAnimation(int index,
{bool loop = false,
bool reverse = false,
bool replaceActive = true,
double crossfade = 0.0,
double startOffset = 0.0}) {
// TODO: implement playAnimation
throw UnimplementedError();
}
@override
Future playAnimationByName(covariant ThermionAsset asset, String name, {bool loop = false, bool reverse = false, bool replaceActive = true, double crossfade = 0.0}) {
Future playAnimationByName(String name,
{bool loop = false,
bool reverse = false,
bool replaceActive = true,
double crossfade = 0.0}) {
// TODO: implement playAnimationByName
throw UnimplementedError();
}
@@ -207,25 +230,28 @@ class BackgroundImage extends ThermionAsset {
}
@override
Future resetBones(ThermionAsset asset) {
Future resetBones() {
// TODO: implement resetBones
throw UnimplementedError();
}
@override
Future setBoneTransform(ThermionEntity entity, int boneIndex, Matrix4 transform, {int skinIndex = 0}) {
Future setBoneTransform(
ThermionEntity entity, int boneIndex, Matrix4 transform,
{int skinIndex = 0}) {
// TODO: implement setBoneTransform
throw UnimplementedError();
}
@override
Future setGltfAnimationFrame(covariant ThermionAsset asset, int index, int animationFrame) {
Future setGltfAnimationFrame(int index, int animationFrame) {
// TODO: implement setGltfAnimationFrame
throw UnimplementedError();
}
@override
Future setMorphAnimationData(covariant ThermionAsset asset, MorphAnimationData animation, {List<String>? targetMeshNames}) {
Future setMorphAnimationData(MorphAnimationData animation,
{List<String>? targetMeshNames}) {
// TODO: implement setMorphAnimationData
throw UnimplementedError();
}
@@ -243,13 +269,13 @@ class BackgroundImage extends ThermionAsset {
}
@override
Future stopAnimation(covariant ThermionAsset asset, int animationIndex) {
Future stopAnimation(int animationIndex) {
// TODO: implement stopAnimation
throw UnimplementedError();
}
@override
Future stopAnimationByName(covariant ThermionAsset asset, String name) {
Future stopAnimationByName(String name) {
// TODO: implement stopAnimationByName
throw UnimplementedError();
}

View File

@@ -1,5 +1,7 @@
import 'dart:typed_data';
import 'package:animation_tools_dart/animation_tools_dart.dart';
import 'package:logging/logging.dart';
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/utils/src/matrix.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
@@ -8,10 +10,8 @@ import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart' as v64;
import 'package:vector_math/vector_math_64.dart';
class FFIAsset extends ThermionAsset {
///
///
///
@@ -22,6 +22,11 @@ class FFIAsset extends ThermionAsset {
///
final FFIFilamentApp app;
///
///
///
final Pointer<TAnimationManager> animationManager;
///
///
///
@@ -37,10 +42,13 @@ class FFIAsset extends ThermionAsset {
///
late final ThermionEntity entity;
late final _logger = Logger(this.runtimeType.toString());
///
///
///
FFIAsset(this.asset, this.app, {this.isInstance = false}) {
FFIAsset(this.asset, this.app, this.animationManager,
{this.isInstance = false}) {
entity = SceneAsset_getEntity(asset);
}
@@ -59,8 +67,7 @@ class FFIAsset extends ThermionAsset {
///
///
@override
Future<ThermionEntity?> getChildEntity(
FFIAsset asset, String childName) async {
Future<ThermionEntity?> getChildEntity(String childName) async {
final childEntities = await getChildEntities();
for (final entity in childEntities) {
var name = NameComponentManager_getName(app.nameComponentManager, entity);
@@ -71,6 +78,9 @@ class FFIAsset extends ThermionAsset {
return null;
}
///
///
///
@override
Future<ThermionAsset> getInstance(int index) async {
if (isInstance) {
@@ -81,7 +91,7 @@ class FFIAsset extends ThermionAsset {
if (instance == nullptr) {
throw Exception("No instance available at index $index");
}
return FFIAsset(instance, app);
return FFIAsset(instance, app, animationManager);
}
///
@@ -111,7 +121,7 @@ class FFIAsset extends ThermionAsset {
if (created == FILAMENT_ASSET_ERROR) {
throw Exception("Failed to create instance");
}
return FFIAsset(created, app);
return FFIAsset(created, app, animationManager);
}
///
@@ -129,7 +139,7 @@ class FFIAsset extends ThermionAsset {
Future<List<ThermionAsset>> getInstances() async {
var count = await getInstanceCount();
final result = List<ThermionAsset>.generate(count, (i) {
return FFIAsset(SceneAsset_getInstance(asset, i), app);
return FFIAsset(SceneAsset_getInstance(asset, i), app, animationManager);
});
return result;
@@ -163,7 +173,7 @@ class FFIAsset extends ThermionAsset {
var targetEntity = this.entity;
if (entityIndex != null) {
final childEntities = await this.getChildEntities();
targetEntity = childEntities[entityIndex!];
targetEntity = childEntities[entityIndex];
}
var sourceMaterialInstance = FFIMaterialInstance(
RenderableManager_getMaterialInstanceAt(
@@ -209,7 +219,7 @@ class FFIAsset extends ThermionAsset {
if (entityIndex != null) {
var highlightChildEntities = await _highlight!.getChildEntities();
targetHighlightEntity = highlightChildEntities[entityIndex!];
targetHighlightEntity = highlightChildEntities[entityIndex];
}
RenderableManager_setPriority(
@@ -397,7 +407,8 @@ class FFIAsset extends ThermionAsset {
///
///
Future transformToUnitCube() async {
TransformManager_transformToUnitCube(app.transformManager, entity, SceneAsset_getBoundingBox(asset));
TransformManager_transformToUnitCube(
app.transformManager, entity, SceneAsset_getBoundingBox(asset));
}
///
@@ -439,33 +450,35 @@ class FFIAsset extends ThermionAsset {
///
///
@override
Future<List<String>> getMorphTargetNames(
covariant FFIAsset asset, ThermionEntity childEntity) async {
Future<List<String>> getMorphTargetNames({ThermionEntity? entity}) async {
var names = <String>[];
entity ??= this.entity;
var count = AnimationManager_getMorphTargetNameCount(
animationManager, asset.asset, childEntity);
animationManager, asset, entity);
var outPtr = allocator<Char>(255);
for (int i = 0; i < count; i++) {
AnimationManager_getMorphTargetName(
animationManager, asset.asset, childEntity, outPtr, i);
animationManager, asset, entity, outPtr, i);
names.add(outPtr.cast<Utf8>().toDartString());
}
allocator.free(outPtr);
return names.cast<String>();
}
Future<List<String>> getBoneNames(covariant FFIAsset asset,
{int skinIndex = 0}) async {
///
///
///
Future<List<String>> getBoneNames({int skinIndex = 0}) async {
var count =
AnimationManager_getBoneCount(animationManager, asset.asset, skinIndex);
AnimationManager_getBoneCount(animationManager, asset, skinIndex);
var out = allocator<Pointer<Char>>(count);
for (int i = 0; i < count; i++) {
out[i] = allocator<Char>(255);
}
AnimationManager_getBoneNames(
animationManager, asset.asset, out, skinIndex);
AnimationManager_getBoneNames(animationManager, asset, out, skinIndex);
var names = <String>[];
for (int i = 0; i < count; i++) {
var namePtr = out[i];
@@ -478,14 +491,13 @@ class FFIAsset extends ThermionAsset {
///
///
@override
Future<List<String>> getAnimationNames(covariant FFIAsset asset) async {
Future<List<String>> getAnimationNames() async {
var animationCount =
AnimationManager_getAnimationCount(animationManager, asset.asset);
AnimationManager_getAnimationCount(animationManager, asset);
var names = <String>[];
var outPtr = allocator<Char>(255);
for (int i = 0; i < animationCount; i++) {
AnimationManager_getAnimationName(
animationManager, asset.asset, outPtr, i);
AnimationManager_getAnimationName(animationManager, asset, outPtr, i);
names.add(outPtr.cast<Utf8>().toDartString());
}
allocator.free(outPtr);
@@ -497,24 +509,26 @@ class FFIAsset extends ThermionAsset {
///
///
@override
Future<double> getAnimationDuration(
FFIAsset asset, int animationIndex) async {
Future<double> getAnimationDuration(int animationIndex) async {
return AnimationManager_getAnimationDuration(
animationManager, asset.asset, animationIndex);
animationManager, asset, animationIndex);
}
///
///
///
Future<double> getAnimationDurationByName(FFIAsset asset, String name) async {
var animations = await getAnimationNames(asset);
Future<double> getAnimationDurationByName(String name) async {
var animations = await getAnimationNames();
var index = animations.indexOf(name);
if (index == -1) {
throw Exception("Failed to find animation $name");
}
return getAnimationDuration(asset, index);
return getAnimationDuration(index);
}
///
///
///
Future clearMorphAnimationData(ThermionEntity entity) async {
if (!AnimationManager_clearMorphAnimation(animationManager, entity)) {
throw Exception("Failed to clear morph animation");
@@ -525,11 +539,13 @@ class FFIAsset extends ThermionAsset {
///
///
@override
Future setMorphAnimationData(FFIAsset asset, MorphAnimationData animation,
Future setMorphAnimationData(MorphAnimationData animation,
{List<String>? targetMeshNames}) async {
var meshEntities = await getChildEntities(asset);
var meshEntities = await getChildEntities();
var meshNames = meshEntities.map((e) => getNameForEntity(e)).toList();
var meshNames = meshEntities
.map((e) => FilamentApp.instance!.getNameForEntity(e))
.toList();
if (targetMeshNames != null) {
for (final targetMeshName in targetMeshNames) {
if (!meshNames.contains(targetMeshName)) {
@@ -554,7 +570,7 @@ class FFIAsset extends ThermionAsset {
continue;
}
var meshMorphTargets = await getMorphTargetNames(asset, meshEntity);
var meshMorphTargets = await getMorphTargetNames(entity: meshEntity);
var intersection = animation.morphTargets
.toSet()
@@ -598,7 +614,7 @@ class FFIAsset extends ThermionAsset {
/// Currently, scale is not supported.
///
@override
Future addBoneAnimation(covariant FFIAsset asset, BoneAnimationData animation,
Future addBoneAnimation(BoneAnimationData animation,
{int skinIndex = 0,
double fadeOutInSecs = 0.0,
double fadeInInSecs = 0.0,
@@ -610,10 +626,10 @@ class FFIAsset extends ThermionAsset {
if (skinIndex != 0) {
throw UnimplementedError("TODO - support skinIndex != 0 ");
}
var boneNames = await getBoneNames(asset);
var boneNames = await getBoneNames();
var restLocalTransformsRaw = allocator<Float>(boneNames.length * 16);
AnimationManager_getRestLocalTransforms(animationManager, asset.asset,
skinIndex, restLocalTransformsRaw, boneNames.length);
AnimationManager_getRestLocalTransforms(animationManager, asset, skinIndex,
restLocalTransformsRaw, boneNames.length);
var restLocalTransforms = <Matrix4>[];
for (int i = 0; i < boneNames.length; i++) {
@@ -630,7 +646,7 @@ class FFIAsset extends ThermionAsset {
var data = allocator<Float>(numFrames * 16);
var bones = await Future.wait(List<Future<ThermionEntity>>.generate(
boneNames.length, (i) => getBone(asset, i)));
boneNames.length, (i) => getBone(i)));
for (int i = 0; i < animation.bones.length; i++) {
var boneName = animation.bones[i];
@@ -645,13 +661,15 @@ class FFIAsset extends ThermionAsset {
var world = Matrix4.identity();
// this odd use of ! is intentional, without it, the WASM optimizer gets in trouble
var parentBoneEntity = (await getParent(boneEntity))!;
var parentBoneEntity =
(await FilamentApp.instance!.getParent(boneEntity))!;
while (true) {
if (!bones.contains(parentBoneEntity!)) {
break;
}
world = restLocalTransforms[bones.indexOf(parentBoneEntity!)] * world;
parentBoneEntity = (await getParent(parentBoneEntity))!;
parentBoneEntity =
(await FilamentApp.instance!.getParent(parentBoneEntity))!;
}
world = Matrix4.identity()..setRotation(world.getRotation());
@@ -677,7 +695,7 @@ class FFIAsset extends ThermionAsset {
AnimationManager_addBoneAnimation(
animationManager,
asset.asset,
asset,
skinIndex,
entityBoneIndex,
data,
@@ -693,7 +711,8 @@ class FFIAsset extends ThermionAsset {
///
///
///
Future<Matrix4> getLocalTransform(ThermionEntity entity) async {
Future<Matrix4> getLocalTransform({ThermionEntity? entity}) async {
entity ??= this.entity;
return double4x4ToMatrix4(
TransformManager_getLocalTransform(app.transformManager, entity));
}
@@ -701,7 +720,8 @@ class FFIAsset extends ThermionAsset {
///
///
///
Future<Matrix4> getWorldTransform(ThermionEntity entity) async {
Future<Matrix4> getWorldTransform({ThermionEntity? entity}) async {
entity ??= this.entity;
return double4x4ToMatrix4(
TransformManager_getWorldTransform(app.transformManager, entity));
}
@@ -709,12 +729,13 @@ class FFIAsset extends ThermionAsset {
///
///
///
Future setTransform(ThermionEntity entity, Matrix4 transform) async {
Future setTransform(Matrix4 transform, {ThermionEntity? entity}) async {
entity ??= this.entity;
TransformManager_setTransform(
app.transformManager, entity, matrix4ToDouble4x4(transform));
}
///
///
///
///
Future updateBoneMatrices(ThermionEntity entity) async {
@@ -731,24 +752,23 @@ class FFIAsset extends ThermionAsset {
///
///
///
Future<Matrix4> getInverseBindMatrix(FFIAsset asset, int boneIndex,
Future<Matrix4> getInverseBindMatrix(int boneIndex,
{int skinIndex = 0}) async {
var matrix = Float32List(16);
AnimationManager_getInverseBindMatrix(
animationManager, asset.asset, skinIndex, boneIndex, matrix.address);
animationManager, asset, skinIndex, boneIndex, matrix.address);
return Matrix4.fromList(matrix);
}
///
///
///
Future<ThermionEntity> getBone(FFIAsset asset, int boneIndex,
{int skinIndex = 0}) async {
Future<ThermionEntity> getBone(int boneIndex, {int skinIndex = 0}) async {
if (skinIndex != 0) {
throw UnimplementedError("TOOD");
}
return AnimationManager_getBone(
animationManager, asset.asset, skinIndex, boneIndex);
animationManager, asset, skinIndex, boneIndex);
}
///
@@ -781,22 +801,21 @@ class FFIAsset extends ThermionAsset {
///
///
@override
Future resetBones(covariant FFIAsset asset) async {
AnimationManager_resetToRestPose(animationManager, asset.asset);
Future resetBones() async {
AnimationManager_resetToRestPose(animationManager, asset);
}
///
///
///
@override
Future playAnimation(covariant FFIAsset asset, int index,
Future playAnimation(int index,
{bool loop = false,
bool reverse = false,
bool replaceActive = true,
double crossfade = 0.0,
double startOffset = 0.0}) async {
AnimationManager_playAnimation(animationManager, asset.asset, index, loop,
AnimationManager_playAnimation(animationManager, asset, index, loop,
reverse, replaceActive, crossfade, startOffset);
}
@@ -804,34 +823,33 @@ class FFIAsset extends ThermionAsset {
///
///
@override
Future stopAnimation(FFIAsset asset, int animationIndex) async {
AnimationManager_stopAnimation(
animationManager, asset.asset, animationIndex);
Future stopAnimation(int animationIndex) async {
AnimationManager_stopAnimation(animationManager, asset, animationIndex);
}
///
///
///
@override
Future stopAnimationByName(FFIAsset asset, String name) async {
var animations = await getAnimationNames(asset);
await stopAnimation(asset, animations.indexOf(name));
Future stopAnimationByName(String name) async {
var animations = await getAnimationNames();
await stopAnimation(animations.indexOf(name));
}
///
///
///
@override
Future playAnimationByName(FFIAsset asset, String name,
Future playAnimationByName(String name,
{bool loop = false,
bool reverse = false,
bool replaceActive = true,
double crossfade = 0.0,
bool wait = false}) async {
var animations = await getAnimationNames(asset);
var animations = await getAnimationNames();
var index = animations.indexOf(name);
var duration = await getAnimationDuration(asset, index);
await playAnimation(asset, index,
var duration = await getAnimationDuration(index);
await playAnimation(index,
loop: loop,
reverse: reverse,
replaceActive: replaceActive,
@@ -845,13 +863,12 @@ class FFIAsset extends ThermionAsset {
///
///
@override
Future setGltfAnimationFrame(
FFIAsset asset, int index, int animationFrame) async {
Future setGltfAnimationFrame(int index, int animationFrame) async {
AnimationManager_setGltfAnimationFrame(
animationManager, asset.asset, index, animationFrame);
animationManager, asset, index, animationFrame);
}
///
///
///
///
@override
@@ -865,5 +882,4 @@ class FFIAsset extends ThermionAsset {
Future removeAnimationComponent(ThermionEntity entity) async {
AnimationManager_removeAnimationComponent(animationManager, entity);
}
}

View File

@@ -2,12 +2,12 @@ import 'dart:async';
import 'dart:typed_data';
import 'package:thermion_dart/src/viewer/src/ffi/src/callbacks.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_swapchain.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_texture.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_view.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_viewer_ffi.dart';
import 'package:thermion_dart/thermion_dart.dart';
typedef RenderCallback = Pointer<NativeFunction<Void Function(Pointer<Void>)>>;
@@ -59,7 +59,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
if (FilamentApp.instance != null) {
await FilamentApp.instance!.destroy();
}
RenderLoop_destroy();
RenderLoop_create();
@@ -102,7 +102,6 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
ubershaderMaterialProvider,
renderTicker,
nameComponentManager);
}
final _views = <FFISwapChain, List<FFIView>>{};
@@ -170,6 +169,9 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
});
}
///
///
///
@override
Future destroy() async {
for (final swapChain in _views.keys) {
@@ -177,6 +179,12 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
await setRenderable(view, false);
}
}
for (final swapChain in _views.keys) {
await destroySwapChain(swapChain);
}
RenderLoop_destroy();
RenderTicker_destroy(renderTicker);
Engine_destroy(engine);
}
///
@@ -205,7 +213,7 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
var bitmask = flags.fold(0, (a, b) => a | b.index);
final texturePtr = await withPointerCallback<TTexture>((cb) {
Texture_buildRenderThread(
engine!,
engine,
width,
height,
depth,
@@ -225,6 +233,9 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
);
}
///
///
///
Future<TextureSampler> createTextureSampler(
{TextureMinFilter minFilter = TextureMinFilter.LINEAR,
TextureMagFilter magFilter = TextureMagFilter.LINEAR,
@@ -397,49 +408,6 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
return _gridMaterial!;
}
///
///
///
@override
Future<ThermionAsset> createGeometry(Geometry geometry,
{List<MaterialInstance>? materialInstances,
bool keepData = false}) async {
var assetPtr = await withPointerCallback<TSceneAsset>((callback) {
var ptrList = Int64List(materialInstances?.length ?? 0);
if (materialInstances != null && materialInstances.isNotEmpty) {
ptrList.setRange(
0,
materialInstances.length,
materialInstances
.cast<FFIMaterialInstance>()
.map((mi) => mi.pointer.address)
.toList());
}
return SceneAsset_createGeometryRenderThread(
engine,
geometry.vertices.address,
geometry.vertices.length,
geometry.normals.address,
geometry.normals.length,
geometry.uvs.address,
geometry.uvs.length,
geometry.indices.address,
geometry.indices.length,
geometry.primitiveType.index,
ptrList.address.cast<Pointer<TMaterialInstance>>(),
ptrList.length,
callback);
});
if (assetPtr == nullptr) {
throw Exception("Failed to create geometry");
}
var asset = FFIAsset(assetPtr, this);
return asset;
}
///
///
///
@@ -460,6 +428,9 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
RenderTicker_renderRenderThread(renderTicker, 0);
}
///
///
///
@override
Future register(
covariant FFISwapChain swapChain, covariant FFIView view) async {
@@ -468,6 +439,9 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
final _hooks = <Future Function()>[];
///
///
///
@override
Future registerRequestFrameHook(Future Function() hook) async {
if (!_hooks.contains(hook)) {
@@ -475,6 +449,9 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
}
}
///
///
///
@override
Future unregisterRequestFrameHook(Future Function() hook) async {
if (_hooks.contains(hook)) {
@@ -504,4 +481,61 @@ class FFIFilamentApp extends FilamentApp<Pointer> {
print("WARNING - render call timed out");
}
}
///
///
///
@override
Future setParent(ThermionEntity child, ThermionEntity? parent,
{bool preserveScaling = false}) async {
TransformManager_setParent(transformManager, child,
parent ?? FILAMENT_ENTITY_NULL, preserveScaling);
}
///
///
///
@override
Future<ThermionEntity?> getParent(ThermionEntity child) async {
var parent = TransformManager_getParent(transformManager, child);
if (parent == FILAMENT_ASSET_ERROR) {
return null;
}
return parent;
}
///
///
///
@override
Future<ThermionEntity?> getAncestor(ThermionEntity child) async {
var parent = TransformManager_getAncestor(transformManager, child);
if (parent == FILAMENT_ASSET_ERROR) {
return null;
}
return parent;
}
///
///
///
@override
String? getNameForEntity(ThermionEntity entity) {
final result = NameComponentManager_getName(nameComponentManager, entity);
if (result == nullptr) {
return null;
}
return result.cast<Utf8>().toDartString();
}
Material? _imageMaterial;
@override
Future<MaterialInstance> createImageMaterialInstance() async {
_imageMaterial ??= FFIMaterial(Material_createImageMaterial(),
FilamentApp.instance! as FFIFilamentApp);
var instance =
await _imageMaterial!.createInstance() as FFIMaterialInstance;
return instance;
}
}

View File

@@ -6,13 +6,12 @@ import 'package:thermion_dart/thermion_dart.dart';
import 'ffi_view.dart';
class FFIGizmo extends FFIAsset implements GizmoAsset {
final Set<ThermionEntity> gizmoEntities;
final Set<ThermionEntity> entities;
late NativeCallable<GizmoPickCallbackFunction> _nativeCallback;
void Function(GizmoPickResultType axis, Vector3 coords)? _callback;
late FFIView _view;
late FFIView view;
void _onPickResult(int resultType, double x, double y, double z) {
_callback?.call(GizmoPickResultType.values[resultType], Vector3(x, y, z));
@@ -23,13 +22,16 @@ class FFIGizmo extends FFIAsset implements GizmoAsset {
// return SceneManager_isGridEntity(sceneManager, entity);
}
bool isGizmoEntity(ThermionEntity entity) => gizmoEntities.contains(entity);
bool isGizmoEntity(ThermionEntity entity) => entities.contains(entity);
FFIGizmo(
this._view,
super.pointer,
super.app,
this.gizmoEntities) {
FFIGizmo(
super.asset,
super.app,
super.animationManager,
{
required this.view,
required this.entities,
}) {
_nativeCallback =
NativeCallable<GizmoPickCallbackFunction>.listener(_onPickResult);
}
@@ -53,7 +55,7 @@ class FFIGizmo extends FFIAsset implements GizmoAsset {
{Future Function(GizmoPickResultType result, Vector3 coords)?
handler}) async {
_callback = handler;
final viewport = await _view.getViewport();
final viewport = await view.getViewport();
y = viewport.height - y;
Gizmo_pick(asset.cast<TGizmo>(), x, y, _nativeCallback.nativeFunction);

View File

@@ -1,17 +1,11 @@
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart';
import 'package:thermion_dart/src/filament/src/scene.dart';
import 'callbacks.dart';
class FFIScene extends Scene {
final Pointer<TScene> scene;
final FFIFilamentApp app;
FFIRenderTarget? renderTarget;
FFIScene(this.scene, this.app) {}
FFIScene(this.scene);
@override
Future add(covariant FFIAsset asset) async {

View File

@@ -1,3 +1,4 @@
import 'package:thermion_dart/src/filament/src/scene.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_scene.dart';
@@ -113,4 +114,10 @@ class FFIView extends View {
Future setLayerVisibility(VisibilityLayers layer, bool visible) async {
View_setLayerEnabled(view, layer.value, visible);
}
@override
Future<Scene> getScene() async {
final ptr = View_getScene(view);
return FFIScene(ptr);
}
}

View File

@@ -3,11 +3,12 @@ import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
class GridOverlay extends FFIAsset {
GridOverlay(super.asset, super.app);
GridOverlay(super.asset, super.app, super.animationManager);
static Future<GridOverlay> create(FFIFilamentApp app) async {
static Future<GridOverlay> create(FFIFilamentApp app, Pointer<TAnimationManager> animationManager) async {
final gridMaterial = await app.gridMaterial;
final asset = SceneAsset_createGrid(app.engine, gridMaterial.pointer);
return GridOverlay(asset, app);
return GridOverlay(asset, app, animationManager);
}
}

View File

@@ -1443,6 +1443,11 @@ external ffi.Pointer<TRenderTicker> RenderTicker_create(
ffi.Pointer<TRenderer> tRenderer,
);
@ffi.Native<ffi.Void Function(ffi.Pointer<TRenderTicker>)>(isLeaf: true)
external void RenderTicker_destroy(
ffi.Pointer<TRenderTicker> tRenderTicker,
);
@ffi.Native<
ffi.Void Function(ffi.Pointer<TRenderTicker>,
ffi.Pointer<TAnimationManager>)>(isLeaf: true)
@@ -2958,6 +2963,11 @@ ffi.Pointer<TEngine> Engine_create(
disableHandleUseAfterFreeCheck,
);
@ffi.Native<ffi.Pointer<TEngine> Function(ffi.Pointer<TEngine>)>(isLeaf: true)
external ffi.Pointer<TEngine> Engine_destroy(
ffi.Pointer<TEngine> tEngine,
);
@ffi.Native<ffi.Pointer<TRenderer> Function(ffi.Pointer<TEngine>)>(isLeaf: true)
external ffi.Pointer<TRenderer> Engine_createRenderer(
ffi.Pointer<TEngine> tEngine,
@@ -3521,6 +3531,15 @@ external void AnimationManager_setGltfAnimationFrame(
int frame,
);
@ffi.Native<
ffi.Pointer<ffi.Void> Function(LoadFilamentResourceFromOwner,
FreeFilamentResourceFromOwner, ffi.Pointer<ffi.Void>)>(isLeaf: true)
external ffi.Pointer<ffi.Void> make_resource_loader(
LoadFilamentResourceFromOwner loadFn,
FreeFilamentResourceFromOwner freeFn,
ffi.Pointer<ffi.Void> owner,
);
final class TCamera extends ffi.Opaque {}
final class TEngine extends ffi.Opaque {}
@@ -4575,6 +4594,55 @@ enum TBackend {
};
}
final class ResourceBuffer extends ffi.Struct {
external ffi.Pointer<ffi.Void> data;
@ffi.Int32()
external int size;
@ffi.Int32()
external int id;
}
final class ResourceLoaderWrapper extends ffi.Struct {
external LoadFilamentResource loadResource;
external FreeFilamentResource freeResource;
external LoadFilamentResourceFromOwner loadFromOwner;
external FreeFilamentResourceFromOwner freeFromOwner;
external ffi.Pointer<ffi.Void> owner;
external LoadFilamentResourceIntoOutPointer loadToOut;
}
typedef LoadFilamentResource
= ffi.Pointer<ffi.NativeFunction<LoadFilamentResourceFunction>>;
typedef LoadFilamentResourceFunction = ResourceBuffer Function(
ffi.Pointer<ffi.Char> uri);
typedef FreeFilamentResource
= ffi.Pointer<ffi.NativeFunction<FreeFilamentResourceFunction>>;
typedef FreeFilamentResourceFunction = ffi.Void Function(ResourceBuffer);
typedef DartFreeFilamentResourceFunction = void Function(ResourceBuffer);
typedef LoadFilamentResourceFromOwner
= ffi.Pointer<ffi.NativeFunction<LoadFilamentResourceFromOwnerFunction>>;
typedef LoadFilamentResourceFromOwnerFunction = ResourceBuffer Function(
ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Void>);
typedef FreeFilamentResourceFromOwner
= ffi.Pointer<ffi.NativeFunction<FreeFilamentResourceFromOwnerFunction>>;
typedef FreeFilamentResourceFromOwnerFunction = ffi.Void Function(
ResourceBuffer, ffi.Pointer<ffi.Void>);
typedef DartFreeFilamentResourceFromOwnerFunction = void Function(
ResourceBuffer, ffi.Pointer<ffi.Void>);
typedef LoadFilamentResourceIntoOutPointer = ffi
.Pointer<ffi.NativeFunction<LoadFilamentResourceIntoOutPointerFunction>>;
typedef LoadFilamentResourceIntoOutPointerFunction = ffi.Void Function(
ffi.Pointer<ffi.Char> uri, ffi.Pointer<ResourceBuffer> out);
typedef DartLoadFilamentResourceIntoOutPointerFunction = void Function(
ffi.Pointer<ffi.Char> uri, ffi.Pointer<ResourceBuffer> out);
const int __bool_true_false_are_defined = 1;
const int true1 = 1;

View File

@@ -2,19 +2,17 @@ import 'dart:async';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:animation_tools_dart/animation_tools_dart.dart';
import 'package:thermion_dart/src/filament/src/light_options.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/background_image.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_filament_app.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_render_target.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_scene.dart';
import 'package:thermion_dart/src/filament/src/layers.dart';
import 'package:thermion_dart/src/viewer/src/ffi/src/grid_overlay.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';
import 'package:vector_math/vector_math_64.dart' as v64;
import '../../../../utils/src/matrix.dart';
import '../../thermion_viewer_base.dart';
import 'package:logging/logging.dart';
import 'callbacks.dart';
@@ -88,13 +86,15 @@ class ThermionViewerFFI extends ThermionViewer {
await withPointerCallback<TView>(
(cb) => Engine_createViewRenderThread(app.engine, cb)),
app);
scene = FFIScene(Engine_createScene(app.engine), app);
scene = FFIScene(Engine_createScene(app.engine));
await view.setScene(scene);
final camera = FFICamera(
await withPointerCallback<TCamera>(
(cb) => Engine_createCameraRenderThread(app.engine, cb)),
app);
_cameras.add(camera);
await view.setCamera(camera);
if (renderTarget != null) {
await view.setRenderTarget(renderTarget);
}
@@ -193,7 +193,7 @@ class ThermionViewerFFI extends ThermionViewer {
@override
Future setBackgroundImage(String path, {bool fillHeight = false}) async {
final imageData = await loadAsset(path);
_backgroundImage = await BackgroundImage.create(app, scene, imageData);
_backgroundImage = await BackgroundImage.create(this, scene, imageData);
}
///
@@ -406,7 +406,7 @@ class ThermionViewerFFI extends ThermionViewer {
throw Exception("An error occurred loading the asset");
}
var thermionAsset = FFIAsset(asset, app);
var thermionAsset = FFIAsset(asset, app, animationManager);
_assets.add(thermionAsset);
@@ -550,19 +550,6 @@ class ThermionViewerFFI extends ThermionViewer {
app.lightManager, lightEntity, direction.x, direction.y, direction.z);
}
///
///
///
@override
String? getNameForEntity(ThermionEntity entity) {
final result =
NameComponentManager_getName(app.nameComponentManager, entity);
if (result == nullptr) {
return null;
}
return result.cast<Utf8>().toDartString();
}
void _onPickResult(int requestId, ThermionEntity entityId, double depth,
double fragX, double fragY, double fragZ) async {
if (!_pickRequests.containsKey(requestId)) {
@@ -611,40 +598,6 @@ class ThermionViewerFFI extends ThermionViewer {
});
}
///
///
///
@override
Future setParent(ThermionEntity child, ThermionEntity? parent,
{bool preserveScaling = false}) async {
TransformManager_setParent(app.transformManager, child,
parent ?? FILAMENT_ENTITY_NULL, preserveScaling);
}
///
///
///
@override
Future<ThermionEntity?> getParent(ThermionEntity child) async {
var parent = TransformManager_getParent(app.transformManager, child);
if (parent == FILAMENT_ASSET_ERROR) {
return null;
}
return parent;
}
///
///
///
@override
Future<ThermionEntity?> getAncestor(ThermionEntity child) async {
var parent = TransformManager_getAncestor(app.transformManager, child);
if (parent == FILAMENT_ASSET_ERROR) {
return null;
}
return parent;
}
///
///
///
@@ -678,7 +631,7 @@ class ThermionViewerFFI extends ThermionViewer {
///
///
Future showGridOverlay() async {
_grid ??= _grid = await GridOverlay.create(app);
_grid ??= _grid = await GridOverlay.create(app, animationManager);
await scene.add(_grid!);
await view.setLayerVisibility(VisibilityLayers.OVERLAY, true);
}
@@ -749,6 +702,52 @@ class ThermionViewerFFI extends ThermionViewer {
}
}
///
///
///
@override
Future<ThermionAsset> createGeometry(Geometry geometry,
{List<MaterialInstance>? materialInstances,
bool keepData = false}) async {
var assetPtr = await withPointerCallback<TSceneAsset>((callback) {
var ptrList = Int64List(materialInstances?.length ?? 0);
if (materialInstances != null && materialInstances.isNotEmpty) {
ptrList.setRange(
0,
materialInstances.length,
materialInstances
.cast<FFIMaterialInstance>()
.map((mi) => mi.pointer.address)
.toList());
}
return SceneAsset_createGeometryRenderThread(
app.engine,
geometry.vertices.address,
geometry.vertices.length,
geometry.normals.address,
geometry.normals.length,
geometry.uvs.address,
geometry.uvs.length,
geometry.indices.address,
geometry.indices.length,
geometry.primitiveType.index,
ptrList.address.cast<Pointer<TMaterialInstance>>(),
ptrList.length,
callback);
});
if (assetPtr == nullptr) {
throw Exception("Failed to create geometry");
}
var asset = FFIAsset(assetPtr, app, animationManager);
return asset;
}
////
///
//
@override
Future<GizmoAsset> createGizmo(FFIView view, GizmoType gizmoType) async {
throw UnimplementedError();

View File

@@ -1,4 +1,5 @@
import 'package:thermion_dart/src/filament/src/filament_app.dart';
import 'package:thermion_dart/src/filament/src/light_options.dart';
import '../../filament/src/shared_types.dart';
import 'dart:typed_data';
import 'package:vector_math/vector_math_64.dart';
@@ -12,10 +13,13 @@ import 'dart:async';
/// Multiple instances can be created; each will correspond
/// broadly to a single Filament Scene/View.
///
/// If you know yhat you are doing, you can use a lower level interface by
/// If you know yhat you are doing, you can use a lower level interface by
/// using the methods directly via FilamentApp.instance;
///
abstract class ThermionViewer {
Future<bool> get initialized;
///
///
///
@@ -142,7 +146,7 @@ abstract class ThermionViewer {
bool keepData = false,
int priority = 4,
int layer = 0,
bool loadResourcesAsync});
bool loadResourcesAsync = false});
///
/// Load the .gltf asset at the given path, adding all entities to the scene.
@@ -225,32 +229,17 @@ abstract class ThermionViewer {
///
Future pick(int x, int y, void Function(PickResult) resultHandler);
///
/// Retrieves the name assigned to the given ThermionEntity (usually corresponds to the glTF mesh name).
///
String? getNameForEntity(ThermionEntity entity);
///
/// Gets the parent entity of [entity]. Returns null if the entity has no parent.
///
Future<ThermionEntity?> getParent(ThermionEntity entity);
///
/// Gets the ancestor (ultimate parent) entity of [entity]. Returns null if the entity has no parent.
///
Future<ThermionEntity?> getAncestor(ThermionEntity entity);
///
/// Sets the parent transform of [child] to [parent].
///
Future setParent(ThermionEntity child, ThermionEntity? parent,
{bool preserveScaling});
///
/// Sets the draw priority for the given entity. See RenderableManager.h for more details.
///
Future setPriority(ThermionEntity entityId, int priority);
///
///
///
Future<ThermionAsset> createGeometry(Geometry geometry,
{List<MaterialInstance>? materialInstances, bool keepData = false});
///
/// The gizmo for translating/rotating objects. Only one gizmo can be active for a given view.
///

View File

@@ -1,33 +1,14 @@
import 'dart:typed_data';
import 'package:animation_tools_dart/src/bone_animation_data.dart';
import 'package:animation_tools_dart/src/morph_animation_data.dart';
import 'package:thermion_dart/src/filament/src/light_options.dart';
import 'package:thermion_dart/thermion_dart.dart';
import 'package:vector_math/vector_math_64.dart';
class ThermionViewerStub extends ThermionViewer {
@override
Future addAnimationComponent(ThermionEntity entity) {
// TODO: implement addAnimationComponent
throw UnimplementedError();
}
@override
Future addBoneAnimation(ThermionAsset asset, BoneAnimationData animation, {int skinIndex = 0, double fadeInInSecs = 0.0, double fadeOutInSecs = 0.0, double maxDelta = 1.0}) {
// TODO: implement addBoneAnimation
throw UnimplementedError();
}
@override
Future<ThermionEntity> addDirectLight(DirectLight light) {
// TODO: implement addDirectLight
throw UnimplementedError();
}
@override
// TODO: implement app
FilamentApp get app => throw UnimplementedError();
@override
Future clearBackgroundImage() {
// TODO: implement clearBackgroundImage
@@ -35,14 +16,14 @@ class ThermionViewerStub extends ThermionViewer {
}
@override
Future clearMorphAnimationData(ThermionEntity entity) {
// TODO: implement clearMorphAnimationData
Future<Camera> createCamera() {
// TODO: implement createCamera
throw UnimplementedError();
}
@override
Future<Camera> createCamera() {
// TODO: implement createCamera
Future<ThermionAsset> createGeometry(Geometry geometry, {List<MaterialInstance>? materialInstances, bool keepData = false}) {
// TODO: implement createGeometry
throw UnimplementedError();
}
@@ -88,72 +69,12 @@ class ThermionViewerStub extends ThermionViewer {
throw UnimplementedError();
}
@override
Future<ThermionEntity?> getAncestor(ThermionEntity entity) {
// TODO: implement getAncestor
throw UnimplementedError();
}
@override
Future<double> getAnimationDuration(covariant ThermionAsset asset, int animationIndex) {
// TODO: implement getAnimationDuration
throw UnimplementedError();
}
@override
Future<List<String>> getAnimationNames(covariant ThermionAsset asset) {
// TODO: implement getAnimationNames
throw UnimplementedError();
}
@override
Future<ThermionEntity> getBone(covariant ThermionAsset asset, int boneIndex, {int skinIndex = 0}) {
// TODO: implement getBone
throw UnimplementedError();
}
@override
Future<List<String>> getBoneNames(covariant ThermionAsset asset, {int skinIndex = 0}) {
// TODO: implement getBoneNames
throw UnimplementedError();
}
@override
int getCameraCount() {
// TODO: implement getCameraCount
throw UnimplementedError();
}
@override
Future<Matrix4> getInverseBindMatrix(covariant ThermionAsset asset, int boneIndex, {int skinIndex = 0}) {
// TODO: implement getInverseBindMatrix
throw UnimplementedError();
}
@override
Future<Matrix4> getLocalTransform(ThermionEntity entity) {
// TODO: implement getLocalTransform
throw UnimplementedError();
}
@override
Future<List<String>> getMorphTargetNames(covariant ThermionAsset asset, ThermionEntity childEntity) {
// TODO: implement getMorphTargetNames
throw UnimplementedError();
}
@override
String? getNameForEntity(ThermionEntity entity) {
// TODO: implement getNameForEntity
throw UnimplementedError();
}
@override
Future<ThermionEntity?> getParent(ThermionEntity entity) {
// TODO: implement getParent
throw UnimplementedError();
}
@override
Future<Aabb3> getRenderableBoundingBox(ThermionEntity entity) {
// TODO: implement getRenderableBoundingBox
@@ -167,10 +88,8 @@ class ThermionViewerStub extends ThermionViewer {
}
@override
Future<Matrix4> getWorldTransform(ThermionEntity entity) {
// TODO: implement getWorldTransform
throw UnimplementedError();
}
// TODO: implement initialized
Future<bool> get initialized => throw UnimplementedError();
@override
Future<ThermionAsset> loadGlb(String path, {int numInstances = 1, bool keepData = false}) {
@@ -217,30 +136,6 @@ class ThermionViewerStub extends ThermionViewer {
throw UnimplementedError();
}
@override
Future playAnimation(ThermionAsset asset, int index, {bool loop = false, bool reverse = false, bool replaceActive = true, double crossfade = 0.0, double startOffset = 0.0}) {
// TODO: implement playAnimation
throw UnimplementedError();
}
@override
Future playAnimationByName(covariant ThermionAsset asset, String name, {bool loop = false, bool reverse = false, bool replaceActive = true, double crossfade = 0.0}) {
// TODO: implement playAnimationByName
throw UnimplementedError();
}
@override
Future registerRequestFrameHook(Future Function() hook) {
// TODO: implement registerRequestFrameHook
throw UnimplementedError();
}
@override
Future removeAnimationComponent(ThermionEntity entity) {
// TODO: implement removeAnimationComponent
throw UnimplementedError();
}
@override
Future removeGridOverlay() {
// TODO: implement removeGridOverlay
@@ -275,18 +170,6 @@ class ThermionViewerStub extends ThermionViewer {
// TODO: implement rendering
bool get rendering => throw UnimplementedError();
@override
Future requestFrame() {
// TODO: implement requestFrame
throw UnimplementedError();
}
@override
Future resetBones(ThermionAsset asset) {
// TODO: implement resetBones
throw UnimplementedError();
}
@override
Future rotateIbl(Matrix3 rotation) {
// TODO: implement rotateIbl
@@ -329,30 +212,12 @@ class ThermionViewerStub extends ThermionViewer {
throw UnimplementedError();
}
@override
Future setBoneTransform(ThermionEntity entity, int boneIndex, Matrix4 transform, {int skinIndex = 0}) {
// TODO: implement setBoneTransform
throw UnimplementedError();
}
@override
Future setCamera(ThermionEntity entity, String? name) {
// TODO: implement setCamera
throw UnimplementedError();
}
@override
Future setFrameRate(int framerate) {
// TODO: implement setFrameRate
throw UnimplementedError();
}
@override
Future setGltfAnimationFrame(covariant ThermionAsset asset, int index, int animationFrame) {
// TODO: implement setGltfAnimationFrame
throw UnimplementedError();
}
@override
Future setLightDirection(ThermionEntity lightEntity, Vector3 direction) {
// TODO: implement setLightDirection
@@ -365,24 +230,6 @@ class ThermionViewerStub extends ThermionViewer {
throw UnimplementedError();
}
@override
Future setMorphAnimationData(covariant ThermionAsset asset, MorphAnimationData animation, {List<String>? targetMeshNames}) {
// TODO: implement setMorphAnimationData
throw UnimplementedError();
}
@override
Future setMorphTargetWeights(ThermionEntity entity, List<double> weights) {
// TODO: implement setMorphTargetWeights
throw UnimplementedError();
}
@override
Future setParent(ThermionEntity child, ThermionEntity? parent, {bool preserveScaling= false}) {
// TODO: implement setParent
throw UnimplementedError();
}
@override
Future setPostProcessing(bool enabled) {
// TODO: implement setPostProcessing
@@ -425,12 +272,6 @@ class ThermionViewerStub extends ThermionViewer {
throw UnimplementedError();
}
@override
Future setTransform(ThermionEntity entity, Matrix4 transform) {
// TODO: implement setTransform
throw UnimplementedError();
}
@override
Future setViewFrustumCulling(bool enabled) {
// TODO: implement setViewFrustumCulling
@@ -443,32 +284,8 @@ class ThermionViewerStub extends ThermionViewer {
throw UnimplementedError();
}
@override
Future stopAnimation(covariant ThermionAsset asset, int animationIndex) {
// TODO: implement stopAnimation
throw UnimplementedError();
}
@override
Future stopAnimationByName(covariant ThermionAsset asset, String name) {
// TODO: implement stopAnimationByName
throw UnimplementedError();
}
@override
Future unregisterRequestFrameHook(Future Function() hook) {
// TODO: implement unregisterRequestFrameHook
throw UnimplementedError();
}
@override
Future updateBoneMatrices(ThermionEntity entity) {
// TODO: implement updateBoneMatrices
throw UnimplementedError();
}
@override
// TODO: implement view
View get view => throw UnimplementedError();
}