feat: add capture() function and expose viewportDimensions on ThermionViewer (allows easier saving of captured images to PNG)
This commit is contained in:
@@ -1059,6 +1059,15 @@ external void render_ffi(
|
||||
ffi.Pointer<ffi.Void> viewer,
|
||||
);
|
||||
|
||||
@ffi.Native<
|
||||
ffi.Void Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Uint8>,
|
||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>()
|
||||
external void capture_ffi(
|
||||
ffi.Pointer<ffi.Void> viewer,
|
||||
ffi.Pointer<ffi.Uint8> out,
|
||||
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>> onComplete,
|
||||
);
|
||||
|
||||
@ffi.Native<FilamentRenderCallback Function(FilamentRenderCallback)>()
|
||||
external FilamentRenderCallback make_render_callback_fn_pointer(
|
||||
FilamentRenderCallback arg0,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:thermion_dart/thermion_dart/scene.dart';
|
||||
import 'package:vector_math/vector_math_64.dart';
|
||||
@@ -19,11 +20,11 @@ enum LightType {
|
||||
SPOT,
|
||||
}
|
||||
|
||||
enum ShadowType {
|
||||
PCF, //!< percentage-closer filtered shadows (default)
|
||||
VSM, //!< variance shadows
|
||||
DPCF, //!< PCF with contact hardening simulation
|
||||
PCSS, //!< PCF with soft shadows and contact hardening
|
||||
enum ShadowType {
|
||||
PCF, //!< percentage-closer filtered shadows (default)
|
||||
VSM, //!< variance shadows
|
||||
DPCF, //!< PCF with contact hardening simulation
|
||||
PCSS, //!< PCF with soft shadows and contact hardening
|
||||
}
|
||||
|
||||
// copied from filament/backened/DriverEnums.h
|
||||
@@ -57,6 +58,11 @@ abstract class ThermionViewer {
|
||||
|
||||
Future<bool> get initialized;
|
||||
|
||||
///
|
||||
/// The current dimensions of the viewport (in physical pixels).
|
||||
///
|
||||
late (double, double) viewportDimensions;
|
||||
|
||||
///
|
||||
/// The result(s) of calling [pick] (see below).
|
||||
/// This may be a broadcast stream, so you should ensure you have subscribed to this stream before calling [pick].
|
||||
@@ -79,6 +85,12 @@ abstract class ThermionViewer {
|
||||
///
|
||||
Future render();
|
||||
|
||||
|
||||
///
|
||||
/// Render a single frame to the viewport and copy the pixel buffer to [out].
|
||||
///
|
||||
Future<Uint8List> capture();
|
||||
|
||||
///
|
||||
/// Sets the framerate for continuous rendering when [setRendering] is enabled.
|
||||
///
|
||||
@@ -270,10 +282,9 @@ abstract class ThermionViewer {
|
||||
{List<String>? targetMeshNames});
|
||||
|
||||
///
|
||||
/// Clear all current morph animations for [entity].
|
||||
/// Clear all current morph animations for [entity].
|
||||
///
|
||||
Future clearMorphAnimationData(
|
||||
ThermionEntity entity);
|
||||
Future clearMorphAnimationData(ThermionEntity entity);
|
||||
|
||||
///
|
||||
/// Resets all bones in the given entity to their rest pose.
|
||||
@@ -736,7 +747,6 @@ abstract class ThermionViewer {
|
||||
/// Register a callback to be invoked when this viewer is disposed.
|
||||
///
|
||||
void onDispose(Future Function() callback);
|
||||
|
||||
}
|
||||
|
||||
abstract class AbstractGizmo {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
import 'package:animation_tools_dart/animation_tools_dart.dart';
|
||||
import 'package:thermion_dart/thermion_dart/compatibility/compatibility.dart';
|
||||
import 'package:thermion_dart/thermion_dart/entities/gizmo.dart';
|
||||
@@ -24,8 +25,6 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
|
||||
double _pixelRatio = 1.0;
|
||||
|
||||
late (double, double) viewportDimensions;
|
||||
|
||||
Pointer<Void>? _sceneManager;
|
||||
|
||||
Pointer<Void>? _viewer;
|
||||
@@ -163,6 +162,23 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
render_ffi(_viewer!);
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@override
|
||||
Future<Uint8List> capture() async {
|
||||
final length = this.viewportDimensions.$1.toInt() *
|
||||
this.viewportDimensions.$2.toInt() *
|
||||
4;
|
||||
final out = allocator<Uint8>(length);
|
||||
await withVoidCallback((cb) {
|
||||
capture_ffi(_viewer!, out, cb);
|
||||
});
|
||||
final data = Uint8List.fromList(out.asTypedList(length));
|
||||
allocator.free(out);
|
||||
return data;
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
@@ -198,7 +214,6 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
await callback.call();
|
||||
}
|
||||
_onDispose.clear();
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
@@ -602,13 +617,9 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
Future clearMorphAnimationData(ThermionEntity entity) async {
|
||||
var meshEntities = await getChildEntities(entity, true);
|
||||
|
||||
for(final childEntity in meshEntities) {
|
||||
clear_morph_animation(
|
||||
_sceneManager!,
|
||||
childEntity);
|
||||
for (final childEntity in meshEntities) {
|
||||
clear_morph_animation(_sceneManager!, childEntity);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
@@ -982,8 +993,8 @@ class ThermionViewerFFI extends ThermionViewer {
|
||||
bool replaceActive = true,
|
||||
double crossfade = 0.0,
|
||||
double startOffset = 0.0}) async {
|
||||
play_animation(
|
||||
_sceneManager!, entity, index, loop, reverse, replaceActive, crossfade, startOffset);
|
||||
play_animation(_sceneManager!, entity, index, loop, reverse, replaceActive,
|
||||
crossfade, startOffset);
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:thermion_dart/thermion_dart/scene.dart';
|
||||
import 'package:thermion_dart/thermion_dart/thermion_viewer.dart';
|
||||
@@ -750,4 +751,10 @@ class ThermionViewerStub extends ThermionViewer {
|
||||
// TODO: implement setSoftShadowOptions
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> capture() {
|
||||
// TODO: implement capture
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user