add missing methods to wasm viewer

This commit is contained in:
Nick Fisher
2024-08-24 16:25:37 +08:00
parent 026acb7467
commit c0941e3b7f

View File

@@ -5,6 +5,8 @@ import 'dart:math';
import 'dart:typed_data' as td; import 'dart:typed_data' as td;
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:thermion_dart/thermion_dart/entities/abstract_gizmo.dart';
import 'package:thermion_dart/thermion_dart/entities/gizmo.dart';
import 'package:thermion_dart/thermion_dart/scene.dart'; import 'package:thermion_dart/thermion_dart/scene.dart';
import 'package:web/web.dart'; import 'package:web/web.dart';
import 'package:animation_tools_dart/animation_tools_dart.dart'; import 'package:animation_tools_dart/animation_tools_dart.dart';
@@ -57,6 +59,8 @@ class ThermionViewerWasm implements ThermionViewer {
late (double, double) viewportDimensions; late (double, double) viewportDimensions;
late double pixelRatio;
/// ///
/// Construct an instance of this class by explicitly passing the /// Construct an instance of this class by explicitly passing the
/// module instance via the [module] property, or by specifying [moduleName], /// module instance via the [module] property, or by specifying [moduleName],
@@ -116,6 +120,23 @@ class ThermionViewerWasm implements ThermionViewer {
updateViewportAndCameraProjection(width, height, 1.0); updateViewportAndCameraProjection(width, height, 1.0);
_sceneManager = _module!.ccall("get_scene_manager", "void*", _sceneManager = _module!.ccall("get_scene_manager", "void*",
["void*".toJS].toJS, [_viewer!].toJS, null) as JSNumber; ["void*".toJS].toJS, [_viewer!].toJS, null) as JSNumber;
_pickCallbackPtr = _module!.addFunction(_onPickCallback.toJS, "viii");
// _module!.removeFunction(_pickCallbackPtr);
var gizmoOut = _module!._malloc(4 * 4) as JSNumber;
_module!.ccall("get_gizmo", "void", ["void*".toJS, "void*".toJS].toJS,
[_sceneManager!, gizmoOut].toJS, null);
var x = _module!.getValue(gizmoOut, "i32") as JSNumber;
var y = _module!.getValue((gizmoOut.toDartInt + 4).toJS, "i32") as JSNumber;
var z = _module!.getValue((gizmoOut.toDartInt + 8).toJS, "i32") as JSNumber;
var center =
_module!.getValue((gizmoOut.toDartInt + 12).toJS, "i32") as JSNumber;
_gizmo =
Gizmo(x.toDartInt, y.toDartInt, z.toDartInt, center.toDartInt, this);
_module!._free(gizmoOut);
_initialized = true; _initialized = true;
} }
@@ -150,6 +171,9 @@ class ThermionViewerWasm implements ThermionViewer {
void updateViewportAndCameraProjection( void updateViewportAndCameraProjection(
int width, int height, double scaleFactor) { int width, int height, double scaleFactor) {
if (width == 0 || height == 0) {
throw Exception("Width/height must be greater than zero");
}
_width = width; _width = width;
_height = height; _height = height;
viewportDimensions = (width.toDouble(), height.toDouble()); viewportDimensions = (width.toDouble(), height.toDouble());
@@ -166,9 +190,12 @@ class ThermionViewerWasm implements ThermionViewer {
return _initialized; return _initialized;
} }
final _pickResultController =
StreamController<FilamentPickResult>.broadcast();
@override @override
Stream<FilamentPickResult> get pickResult { Stream<FilamentPickResult> get pickResult {
throw UnimplementedError(); return _pickResultController.stream;
} }
@override @override
@@ -628,8 +655,8 @@ class ThermionViewerWasm implements ThermionViewer {
} }
@override @override
// TODO: implement gizmo AbstractGizmo? get gizmo => _gizmo;
AbstractGizmo? get gizmo => throw UnimplementedError(); Gizmo? _gizmo;
@override @override
Future hide(ThermionEntity entity, String? meshName) async { Future hide(ThermionEntity entity, String? meshName) async {
@@ -788,19 +815,17 @@ class ThermionViewerWasm implements ThermionViewer {
final pixelBuffer = _module!._malloc(_width * _height * 4) as JSNumber; final pixelBuffer = _module!._malloc(_width * _height * 4) as JSNumber;
final completer = Completer(); final completer = Completer();
final callback = () { final callback = () {
print("Callback invoked!");
completer.complete(); completer.complete();
}; };
final callbackPtr = _module!.addFunction(callback.toJS, "v"); final callbackPtr = _module!.addFunction(callback.toJS, "v");
print("Aded functrion ${callbackPtr}, calling capture...");
_module!.ccall( _module!.ccall(
"capture", "capture",
"void", "void",
["void*".toJS, "uint8_t*".toJS, "void*".toJS].toJS, ["void*".toJS, "uint8_t*".toJS, "void*".toJS].toJS,
[_viewer!, pixelBuffer, callbackPtr].toJS, [_viewer!, pixelBuffer, callbackPtr].toJS,
null); null);
print("Waiting for completer...");
int iter = 0; int iter = 0;
while (true) { while (true) {
await Future.delayed(Duration(milliseconds: 5)); await Future.delayed(Duration(milliseconds: 5));
@@ -1389,32 +1414,47 @@ class ThermionViewerWasm implements ThermionViewer {
@override @override
Future panEnd() async { Future panEnd() async {
_module!.ccall("grab_end", "void", _module!
["void*".toJS].toJS, [_viewer!].toJS, null); .ccall("grab_end", "void", ["void*".toJS].toJS, [_viewer!].toJS, null);
} }
@override @override
Future panStart(double x, double y) async { Future panStart(double x, double y) async {
_module!.ccall("grab_begin", "void", _module!.ccall(
["void*".toJS, "float".toJS, "float".toJS, "bool".toJS].toJS, [_viewer!, x.toJS, y.toJS, true.toJS].toJS, null); "grab_begin",
"void",
["void*".toJS, "float".toJS, "float".toJS, "bool".toJS].toJS,
[_viewer!, x.toJS, y.toJS, true.toJS].toJS,
null);
} }
@override @override
Future panUpdate(double x, double y) async { Future panUpdate(double x, double y) async {
_module!.ccall("grab_update", "void", _module!.ccall(
["void*".toJS, "float".toJS, "float".toJS].toJS, [_viewer!, x.toJS, y.toJS].toJS, null); "grab_update",
"void",
["void*".toJS, "float".toJS, "float".toJS].toJS,
[_viewer!, x.toJS, y.toJS].toJS,
null);
}
late JSNumber _pickCallbackPtr;
void _onPickCallback(ThermionEntity entity, int x, int y) {
_pickResultController
.add((entity: entity, x: x.toDouble(), y: y.toDouble()));
} }
@override @override
void pick(int x, int y) { void pick(int x, int y) async {
throw UnimplementedError(); x = (x * pixelRatio).ceil();
// _module!.ccall("filament_pick", "void", y = (y * pixelRatio).ceil();
// ["void*".toJS, "int".toJS, "int".toJS, "void*".toJS].toJS, [ _module!.ccall(
// _viewer!, "filament_pick",
// x.toJS, "void",
// y.toJS, ["void*".toJS, "int".toJS, "int".toJS, "void*".toJS].toJS,
// (entityId, x, y) {}.toJS [_viewer!, x.toJS, y.toJS, _pickCallbackPtr].toJS,
// ]); null);
} }
@override @override
@@ -1566,20 +1606,15 @@ class ThermionViewerWasm implements ThermionViewer {
@override @override
Future reveal(ThermionEntity entity, String? meshName) async { Future reveal(ThermionEntity entity, String? meshName) async {
if (meshName != null) { final result = _module!.ccall(
final result = _module!.ccall( "reveal_mesh",
"reveal_mesh", "int",
"int", ["void*".toJS, "int".toJS, "string".toJS].toJS,
["void*".toJS, "int".toJS, "string".toJS].toJS, [_sceneManager!, entity.toJS, meshName?.toJS].toJS,
[_sceneManager!, entity.toJS, meshName.toJS].toJS, null) as JSNumber;
null) as JSNumber; if (result.toDartInt == -1) {
if (result.toDartInt == -1) {
throw Exception(
"Failed to reveal mesh ${meshName} on entity ${entity.toJS}");
}
} else {
throw Exception( throw Exception(
"Cannot reveal mesh, meshName must be specified when invoking this method"); "Failed to reveal mesh ${meshName} on entity ${entity.toJS}");
} }
} }
@@ -1597,20 +1632,28 @@ class ThermionViewerWasm implements ThermionViewer {
@override @override
Future rotateStart(double x, double y) async { Future rotateStart(double x, double y) async {
_module!.ccall("grab_begin", "void", _module!.ccall(
["void*".toJS, "float".toJS, "float".toJS, "bool".toJS].toJS, [_viewer!, x.toJS, y.toJS, false.toJS].toJS, null); "grab_begin",
"void",
["void*".toJS, "float".toJS, "float".toJS, "bool".toJS].toJS,
[_viewer!, x.toJS, y.toJS, false.toJS].toJS,
null);
} }
@override @override
Future rotateUpdate(double x, double y) async { Future rotateUpdate(double x, double y) async {
_module!.ccall("grab_update", "void", _module!.ccall(
["void*".toJS, "float".toJS, "float".toJS].toJS, [_viewer!, x.toJS, y.toJS].toJS, null); "grab_update",
"void",
["void*".toJS, "float".toJS, "float".toJS].toJS,
[_viewer!, x.toJS, y.toJS].toJS,
null);
} }
@override @override
Future rotateEnd() async { Future rotateEnd() async {
_module!.ccall("grab_end", "void", _module!
["void*".toJS].toJS, [_viewer!].toJS, null); .ccall("grab_end", "void", ["void*".toJS].toJS, [_viewer!].toJS, null);
} }
@override @override
@@ -1737,12 +1780,12 @@ class ThermionViewerWasm implements ThermionViewer {
} }
@override @override
Future setCameraFov(double degrees, double width, double height) async { Future setCameraFov(double degrees, {bool horizontal = true}) async {
_module!.ccall( _module!.ccall(
"set_camera_fov", "set_camera_fov",
"void", "void",
["void*".toJS, "float".toJS, "float".toJS].toJS, ["void*".toJS, "float".toJS, "bool".toJS].toJS,
[_viewer!, degrees.toJS, (width / height).toJS].toJS, [_viewer!, degrees.toJS, horizontal.toJS].toJS,
null); null);
} }
@@ -1850,12 +1893,13 @@ class ThermionViewerWasm implements ThermionViewer {
} }
@override @override
Future setParent(ThermionEntity child, ThermionEntity parent) async { Future setParent(ThermionEntity child, ThermionEntity parent,
{bool preserveScaling = false}) async {
_module!.ccall( _module!.ccall(
"set_parent", "set_parent",
"void", "void",
["void*".toJS, "int".toJS, "int".toJS].toJS, ["void*".toJS, "int".toJS, "int".toJS, "bool".toJS].toJS,
[_sceneManager!, child.toJS, parent.toJS].toJS, [_sceneManager!, child.toJS, parent.toJS, preserveScaling.toJS].toJS,
null); null);
} }
@@ -1999,8 +2043,8 @@ class ThermionViewerWasm implements ThermionViewer {
@override @override
Future zoomEnd() async { Future zoomEnd() async {
_module! _module!.ccall(
.ccall("scroll_end", "void", ["void*".toJS].toJS, [_viewer!].toJS, null); "scroll_end", "void", ["void*".toJS].toJS, [_viewer!].toJS, null);
} }
@override @override
@@ -2047,4 +2091,96 @@ class ThermionViewerWasm implements ThermionViewer {
[_viewer!, penumbraScale.toJS, penumbraRatioScale.toJS].toJS, [_viewer!, penumbraScale.toJS, penumbraRatioScale.toJS].toJS,
null); null);
} }
@override
Future<Aabb2> getBoundingBox(ThermionEntity entity) {
var minX = _module!._malloc(4);
var minY = _module!._malloc(4);
var maxX = _module!._malloc(4);
var maxY = _module!._malloc(4);
_module!.ccall(
"get_bounding_box_to_out",
"void",
[
"void*".toJS,
"int".toJS,
"float*".toJS,
"float*".toJS,
"float*".toJS,
"float*".toJS
].toJS,
[_sceneManager!, entity.toJS, minX, minY, maxX, maxY].toJS,
null);
final min = Vector2(
(_module!.getValue(minX, "float") as JSNumber).toDartDouble,
(_module!.getValue(minY, "float") as JSNumber).toDartDouble);
final max = Vector2(
(_module!.getValue(maxX, "float") as JSNumber).toDartDouble,
(_module!.getValue(maxY, "float") as JSNumber).toDartDouble);
final box = Aabb2.minMax(min, max);
_module!._free(minX);
_module!._free(minY);
_module!._free(maxX);
_module!._free(maxY);
return Future.value(box);
}
@override
Future<double> getCameraFov(bool horizontal) async {
var fov = _module!.ccall(
"get_camera_fov",
"float",
["void*".toJS, "bool".toJS].toJS,
[_viewer!, horizontal.toJS].toJS,
null);
return (fov as JSNumber).toDartDouble;
}
@override
Future queueRelativePositionUpdateWorldAxis(ThermionEntity entity,
double viewportX, double viewportY, double x, double y, double z) async {
_module!.ccall(
"queue_relative_position_update_world_axis",
"void",
[
"void*".toJS,
"int".toJS,
"float".toJS,
"float".toJS,
"float".toJS,
"float".toJS,
"float".toJS
].toJS,
[
_sceneManager!,
entity.toJS,
viewportX.toJS,
viewportY.toJS,
x.toJS,
y.toJS,
z.toJS
].toJS,
null);
}
@override
Future setLayerEnabled(int layer, bool enabled) async {
_module!.ccall(
"set_layer_enabled",
"void",
[
"void*".toJS,
"int".toJS,
"bool".toJS,
].toJS,
[
_sceneManager!,
layer.toJS,
enabled.toJS,
].toJS,
null);
}
} }