allow partial morph animations

This commit is contained in:
Nick Fisher
2023-08-18 15:43:20 +08:00
parent 46ecacde12
commit ed72c16724
13 changed files with 174 additions and 135 deletions

Binary file not shown.

View File

@@ -175,6 +175,49 @@ class _ExampleWidgetState extends State<ExampleWidget> {
_item(() async { _item(() async {
_filamentController.clearAssets(); _filamentController.clearAssets();
}, 'clear all assets'), }, 'clear all assets'),
_item(() async {
var names =
await _filamentController.getMorphTargetNames(_cube!, "Cylinder");
await showDialog(
context: context,
builder: (ctx) {
return Container(
height: 100,
width: 100,
color: Colors.white,
child: Text(names.join(",")));
});
}, "show morph target names for Cylinder"),
_item(() {
_filamentController.setMorphTargetWeights(
_cube!, "Cylinder", List.filled(4, 1.0));
}, "set Cylinder morph weights to 1"),
_item(() {
_filamentController.setMorphTargetWeights(
_cube!, "Cylinder", List.filled(4, 0.0));
}, "set Cylinder morph weights to 0.0"),
_item(() async {
var morphs =
await _filamentController.getMorphTargetNames(_cube!, "Cylinder");
final animation = AnimationBuilder(
availableMorphs: morphs, framerate: 30, meshName: "Cylinder")
.setDuration(4)
.setMorphTargets(["Key 1", "Key 2"])
.interpolateMorphWeights(0, 4, 0, 1)
.build();
_filamentController.setMorphAnimationData(_cube!, animation);
}, "animate morph weights #1 and #2"),
_item(() async {
var morphs =
await _filamentController.getMorphTargetNames(_cube!, "Cylinder");
final animation = AnimationBuilder(
availableMorphs: morphs, framerate: 30, meshName: "Cylinder")
.setDuration(4)
.setMorphTargets(["Key 3", "Key 4"])
.interpolateMorphWeights(0, 4, 0, 1)
.build();
_filamentController.setMorphAnimationData(_cube!, animation);
}, "animate morph weights #3 and #4"),
]; ];
if (_animations != null) { if (_animations != null) {
children.addAll(_animations!.map((a) => _item(() { children.addAll(_animations!.map((a) => _item(() {
@@ -273,14 +316,7 @@ class _ExampleWidgetState extends State<ExampleWidget> {
// _flightHelmet ??= await _filamentController.loadGltf( // _flightHelmet ??= await _filamentController.loadGltf(
// 'assets/FlightHelmet/FlightHelmet.gltf', 'assets/FlightHelmet'); // 'assets/FlightHelmet/FlightHelmet.gltf', 'assets/FlightHelmet');
// break; // break;
// case 7:
// _filamentController.setMorphTargetWeights(
// _cube!, "Cube.001", List.filled(8, 1.0));
// break;
// case 8:
// _filamentController.setMorphTargetWeights(
// _cube!, "Cube.001", List.filled(8, 0));
// break;
// case 11: // case 11:
// setState(() { // setState(() {
// _loop = !_loop; // _loop = !_loop;
@@ -290,38 +326,6 @@ class _ExampleWidgetState extends State<ExampleWidget> {
// _filamentController.setCamera(_cube!, "Camera_Orientation"); // _filamentController.setCamera(_cube!, "Camera_Orientation");
// break; // break;
// case 15: // case 15:
// final animation = AnimationBuilder(
// controller: _filamentController,
// asset: _cube!,
// framerate: 30,
// meshName: "Cube.001")
// .setDuration(4)
// .interpolateMorphWeights(0, 4, 0, 1)
// // .interpolateBoneTransform(
// // "Bone.001",
// // "Cube.001",
// // 2,
// // 4,
// // v.Vector3.zero(),
// // v.Vector3.zero(),
// // // Vec3(x: 1, y: 1, z: 1),
// // v.Quaternion(0, 0, 0, 1),
// // v.Quaternion(1, 1, 1, 1))
// // Quaternion(x: 1, y: 1, z: 1, w: 1))
// .set();
// break;
// case 16:
// var names =
// await _filamentController.getMorphTargetNames(_cube!, "Cube");
// await showDialog(
// context: context,
// builder: (ctx) {
// return Container(
// height: 100,
// width: 100,
// color: Colors.white,
// child: Text(names.join(",")));
// });
// break; // break;
// case 17: // case 17:

View File

@@ -381,35 +381,41 @@ public class SwiftPolyvoxFilamentPlugin: NSObject, FlutterPlugin, FlutterTexture
let assetManager = args[0] as? Int64, let assetManager = args[0] as? Int64,
let asset = args[1] as? EntityId, let asset = args[1] as? EntityId,
let entityName = args[2] as? String, let entityName = args[2] as? String,
let morphData = args[3] as? FlutterStandardTypedData, let morphData = args[3] as? [Double],
let numMorphWeights = args[4] as? Int else { let numMorphWeights = args[4] as? Int32 else {
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Expected correct arguments for setMorphTargetWeights", details: nil)) result(FlutterError(code: "INVALID_ARGUMENTS", message: "Expected correct arguments for setMorphTargetWeights", details: nil))
return return
} }
let success = morphData.data.withUnsafeBytes { buffer in
buffer.withMemoryRebound(to: Float.self) { set_morph_target_weights(unsafeBitCast(assetManager, to:UnsafeMutableRawPointer.self), asset, entityName, morphData.map { Float($0) }, Int32(numMorphWeights))
set_morph_target_weights(unsafeBitCast(assetManager, to:UnsafeMutableRawPointer.self), asset, entityName, $0.baseAddress, Int32(numMorphWeights))
} result(true)
}
result(success)
case "setMorphAnimation": case "setMorphAnimation":
guard let args = call.arguments as? [Any], args.count == 7, guard let args = call.arguments as? [Any], args.count == 8,
let assetManager = args[0] as? Int64, let assetManager = args[0] as? Int64,
let asset = args[1] as? EntityId, let asset = args[1] as? EntityId,
let entityName = args[2] as? String, let entityName = args[2] as? String,
let morphData = args[3] as? FlutterStandardTypedData, let morphData = args[3] as? [Double],
let numMorphWeights = args[4] as? Int, let morphIndices = args[4] as? [Int32],
let numFrames = args[5] as? Int, let numMorphTargets = args[5] as? Int32,
let frameLengthInMs = args[6] as? Double else { let numFrames = args[6] as? Int32,
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Expected correct arguments for set_morph_animation", details: nil)) let frameLengthInMs = args[7] as? Double else {
result(FlutterError(code: "INVALID_ARGUMENTS", message: "Incorrect arguments provided for setMorphAnimation", details: nil))
return return
} }
let success = morphData.data.withUnsafeBytes { buffer in let frameData = morphData.map { Float($0) }
buffer.withMemoryRebound(to: Float.self) { let am = unsafeBitCast(assetManager, to:UnsafeMutableRawPointer.self)
set_morph_animation(unsafeBitCast(assetManager, to:UnsafeMutableRawPointer.self), asset, entityName, $0.baseAddress, Int32(numMorphWeights), Int32(numFrames), Float(frameLengthInMs))
} let success = set_morph_animation(
} am,
asset,
entityName,
frameData,
morphIndices,
Int32(numMorphTargets),
Int32(numFrames),
Float(frameLengthInMs))
result(success) result(success)
case "setBoneAnimation": case "setBoneAnimation":
guard let args = call.arguments as? [Any], args.count == 9, guard let args = call.arguments as? [Any], args.count == 9,

View File

@@ -45,9 +45,11 @@ namespace polyvox {
EntityId entityId, EntityId entityId,
const char* entityName, const char* entityName,
const float* const morphData, const float* const morphData,
int numMorphWeights, const int* const morphIndices,
int numMorphTargets,
int numFrames, int numFrames,
float frameLengthInMs); float frameLengthInMs);
void setMorphTargetWeights(EntityId entityId, const char* const entityName, const float* const weights, int count); void setMorphTargetWeights(EntityId entityId, const char* const entityName, const float* const weights, int count);
bool setBoneAnimationBuffer( bool setBoneAnimationBuffer(

View File

@@ -54,9 +54,11 @@ bool set_morph_animation(
EntityId asset, EntityId asset,
const char *const entityName, const char *const entityName,
const float *const morphData, const float *const morphData,
int numMorphWeights, const int* const morphIndices,
int numMorphTargets,
int numFrames, int numFrames,
float frameLengthInMs); float frameLengthInMs);
void set_bone_animation( void set_bone_animation(
void* assetManager, void* assetManager,
EntityId asset, EntityId asset,

View File

@@ -52,7 +52,7 @@ namespace polyvox {
int mNumFrames = -1; int mNumFrames = -1;
float mFrameLengthInMs = 0; float mFrameLengthInMs = 0;
vector<float> mFrameData; vector<float> mFrameData;
int mNumMorphWeights = 0; vector<int> mMorphIndices;
}; };
// //

View File

@@ -272,12 +272,16 @@ void AssetManager::updateAnimations() {
if(anim.mReverse) { if(anim.mReverse) {
frameNumber = lengthInFrames - frameNumber; frameNumber = lengthInFrames - frameNumber;
} }
// set the weights appropriately auto baseOffset = frameNumber * asset.mMorphAnimationBuffer.mMorphIndices.size();
rm.setMorphWeights( for(auto morphIndex : asset.mMorphAnimationBuffer.mMorphIndices) {
rm.getInstance(asset.mMorphAnimationBuffer.mMeshTarget), // set the weights appropriately
asset.mMorphAnimationBuffer.mFrameData.data() + (frameNumber * asset.mMorphAnimationBuffer.mNumMorphWeights), rm.setMorphWeights(
asset.mMorphAnimationBuffer.mNumMorphWeights rm.getInstance(asset.mMorphAnimationBuffer.mMeshTarget),
); asset.mMorphAnimationBuffer.mFrameData.data() + baseOffset + morphIndex,
1,
morphIndex
);
}
break; break;
} }
case AnimationType::BONE: { case AnimationType::BONE: {
@@ -416,7 +420,8 @@ bool AssetManager::setMorphAnimationBuffer(
EntityId entityId, EntityId entityId,
const char* entityName, const char* entityName,
const float* const morphData, const float* const morphData,
int numMorphWeights, const int* const morphIndices,
int numMorphTargets,
int numFrames, int numFrames,
float frameLengthInMs) { float frameLengthInMs) {
@@ -438,10 +443,13 @@ bool AssetManager::setMorphAnimationBuffer(
asset.mMorphAnimationBuffer.mFrameData.insert( asset.mMorphAnimationBuffer.mFrameData.insert(
asset.mMorphAnimationBuffer.mFrameData.begin(), asset.mMorphAnimationBuffer.mFrameData.begin(),
morphData, morphData,
morphData + (numFrames * numMorphWeights) morphData + (numFrames * numMorphTargets)
); );
asset.mMorphAnimationBuffer.mFrameLengthInMs = frameLengthInMs; asset.mMorphAnimationBuffer.mFrameLengthInMs = frameLengthInMs;
asset.mMorphAnimationBuffer.mNumMorphWeights = numMorphWeights; asset.mMorphAnimationBuffer.mMorphIndices.resize(numMorphTargets);
for(int i =0; i< numMorphTargets; i++) {
asset.mMorphAnimationBuffer.mMorphIndices[i] = morphIndices[i];
}
AnimationStatus animation; AnimationStatus animation;
animation.mDuration = (frameLengthInMs * numFrames) / 1000.0f; animation.mDuration = (frameLengthInMs * numFrames) / 1000.0f;

View File

@@ -196,7 +196,8 @@ extern "C" {
EntityId asset, EntityId asset,
const char* const entityName, const char* const entityName,
const float* const morphData, const float* const morphData,
int numMorphWeights, const int* const morphIndices,
int numMorphTargets,
int numFrames, int numFrames,
float frameLengthInMs) { float frameLengthInMs) {
@@ -204,7 +205,8 @@ extern "C" {
asset, asset,
entityName, entityName,
morphData, morphData,
numMorphWeights, morphIndices,
numMorphTargets,
numFrames, numFrames,
frameLengthInMs frameLengthInMs
); );

View File

@@ -1,4 +1,3 @@
import 'package:polyvox_filament/animations/bone_animation_data.dart';
import 'package:polyvox_filament/animations/morph_animation_data.dart'; import 'package:polyvox_filament/animations/morph_animation_data.dart';
import 'package:polyvox_filament/filament_controller.dart'; import 'package:polyvox_filament/filament_controller.dart';
@@ -6,7 +5,6 @@ import 'package:flutter/foundation.dart';
import 'package:vector_math/vector_math.dart'; import 'package:vector_math/vector_math.dart';
class AnimationBuilder { class AnimationBuilder {
final FilamentController controller;
// BoneAnimationData? BoneAnimationData; // BoneAnimationData? BoneAnimationData;
double _frameLengthInMs = 0; double _frameLengthInMs = 0;
double _duration = 0; double _duration = 0;
@@ -18,28 +16,25 @@ class AnimationBuilder {
// List<BoneAnimationData>? _BoneAnimationDatas = null; // List<BoneAnimationData>? _BoneAnimationDatas = null;
FilamentEntity asset;
String meshName; String meshName;
late List<String> morphNames; late List<String> availableMorphs;
late List<int> _morphTargets;
AnimationBuilder( AnimationBuilder(
{required this.controller, {required this.availableMorphs,
required this.asset,
required this.meshName, required this.meshName,
required int framerate}) { required int framerate}) {
_frameLengthInMs = 1000 / framerate; _frameLengthInMs = 1000 / framerate;
controller.getMorphTargetNames(asset, meshName).then((value) {
morphNames = value;
});
} }
void set() { MorphAnimationData build() {
if (morphNames.isEmpty == 0 || _duration == 0 || _frameLengthInMs == 0) if (availableMorphs.isEmpty == 0 || _duration == 0 || _frameLengthInMs == 0)
throw Exception(); throw Exception();
int numFrames = _duration * 1000 ~/ _frameLengthInMs; int numFrames = _duration * 1000 ~/ _frameLengthInMs;
final morphData = Float32List((numFrames * morphNames.length).toInt()); final morphData =
List<double>.filled((numFrames * _morphTargets.length).toInt(), 0.0);
var frameStart = (_interpMorphStart! * 1000) ~/ _frameLengthInMs; var frameStart = (_interpMorphStart! * 1000) ~/ _frameLengthInMs;
var frameEnd = (_interpMorphEnd! * 1000) ~/ _frameLengthInMs; var frameEnd = (_interpMorphEnd! * 1000) ~/ _frameLengthInMs;
@@ -49,17 +44,16 @@ class AnimationBuilder {
var val = ((1 - linear) * _interpMorphStartValue!) + var val = ((1 - linear) * _interpMorphStartValue!) +
(linear * _interpMorphEndValue!); (linear * _interpMorphEndValue!);
for (int j = 0; j < morphNames.length; j++) { for (int j = 0; j < _morphTargets.length; j++) {
morphData[(i * morphNames.length) + j] = val; morphData[(i * _morphTargets.length) + j] = val;
} }
} }
return MorphAnimationData(
var morphAnimation = meshName,
MorphAnimationData(meshName, morphData, morphNames, _frameLengthInMs); morphData,
_morphTargets.map((i) => availableMorphs[i]).toList(),
controller.setMorphAnimationData(asset, morphAnimation); _morphTargets,
// return Tuple2<MorphAnimationData, List<BoneAnimationData>>( _frameLengthInMs);
// morphAnimation, _BoneAnimationDatas!);
} }
AnimationBuilder setDuration(double secs) { AnimationBuilder setDuration(double secs) {
@@ -67,6 +61,11 @@ class AnimationBuilder {
return this; return this;
} }
AnimationBuilder setMorphTargets(List<String> names) {
_morphTargets = names.map((name) => availableMorphs.indexOf(name)).toList();
return this;
}
AnimationBuilder interpolateMorphWeights( AnimationBuilder interpolateMorphWeights(
double start, double end, double startValue, double endValue) { double start, double end, double startValue, double endValue) {
this._interpMorphStart = start; this._interpMorphStart = start;

View File

@@ -32,7 +32,11 @@ class DynamicAnimation {
} }
var morphAnimationData = MorphAnimationData( var morphAnimationData = MorphAnimationData(
meshName ?? "NULL", llf.item2, morphNames, frameLengthInMs); meshName ?? "NULL",
llf.item2,
morphNames,
List<int>.generate(morphNames.length, (index) => index),
frameLengthInMs);
final boneAnimations = <BoneAnimationData>[]; final boneAnimations = <BoneAnimationData>[];

View File

@@ -9,24 +9,25 @@ import 'dart:typed_data';
class MorphAnimationData { class MorphAnimationData {
final String meshName; final String meshName;
final List<String> morphNames; final List<String> morphNames;
final List<int> morphIndices;
final Float32List data; final List<double> data;
MorphAnimationData( MorphAnimationData(this.meshName, this.data, this.morphNames,
this.meshName, this.data, this.morphNames, this.frameLengthInMs) { this.morphIndices, this.frameLengthInMs) {
assert(data.length == morphNames.length * numFrames); assert(data.length == morphNames.length * numFrames);
} }
int get numMorphWeights => morphNames.length; int get numMorphTargets => morphNames.length;
int get numFrames => data.length ~/ numMorphWeights; int get numFrames => data.length ~/ numMorphTargets;
final double frameLengthInMs; final double frameLengthInMs;
Iterable<double> getData(String morphName) sync* { Iterable<double> getData(String morphName) sync* {
int index = morphNames.indexOf(morphName); int index = morphNames.indexOf(morphName);
for (int i = 0; i < numFrames; i++) { for (int i = 0; i < numFrames; i++) {
yield data[(i * numMorphWeights) + index]; yield data[(i * numMorphTargets) + index];
} }
} }
} }

View File

@@ -260,12 +260,14 @@ class FilamentController {
/// ///
void setMorphAnimationData( void setMorphAnimationData(
FilamentEntity asset, MorphAnimationData animation) async { FilamentEntity asset, MorphAnimationData animation) async {
print("SETTING animation with ${animation.data}");
await _channel.invokeMethod("setMorphAnimation", [ await _channel.invokeMethod("setMorphAnimation", [
_assetManager, _assetManager,
asset, asset,
animation.meshName, animation.meshName,
animation.data, animation.data,
animation.numMorphWeights, animation.morphIndices,
animation.numMorphTargets,
animation.numFrames, animation.numFrames,
animation.frameLengthInMs animation.frameLengthInMs
]); ]);

View File

@@ -450,21 +450,6 @@ class NativeLibrary {
late final _set_frame_interval = _set_frame_intervalPtr late final _set_frame_interval = _set_frame_intervalPtr
.asFunction<void Function(ffi.Pointer<ffi.Void>, double)>(); .asFunction<void Function(ffi.Pointer<ffi.Void>, double)>();
ffi.Pointer<ffi.Void> get_renderer(
ffi.Pointer<ffi.Void> viewer,
) {
return _get_renderer(
viewer,
);
}
late final _get_rendererPtr = _lookup<
ffi.NativeFunction<
ffi.Pointer<ffi.Void> Function(
ffi.Pointer<ffi.Void>)>>('get_renderer');
late final _get_renderer = _get_rendererPtr
.asFunction<ffi.Pointer<ffi.Void> Function(ffi.Pointer<ffi.Void>)>();
void update_viewport_and_camera_projection( void update_viewport_and_camera_projection(
ffi.Pointer<ffi.Void> viewer, ffi.Pointer<ffi.Void> viewer,
int width, int width,
@@ -652,7 +637,8 @@ class NativeLibrary {
int asset, int asset,
ffi.Pointer<ffi.Char> entityName, ffi.Pointer<ffi.Char> entityName,
ffi.Pointer<ffi.Float> morphData, ffi.Pointer<ffi.Float> morphData,
int numMorphWeights, ffi.Pointer<ffi.Int> morphIndices,
int numMorphTargets,
int numFrames, int numFrames,
double frameLengthInMs, double frameLengthInMs,
) { ) {
@@ -661,7 +647,8 @@ class NativeLibrary {
asset, asset,
entityName, entityName,
morphData, morphData,
numMorphWeights, morphIndices,
numMorphTargets,
numFrames, numFrames,
frameLengthInMs, frameLengthInMs,
); );
@@ -674,12 +661,13 @@ class NativeLibrary {
EntityId, EntityId,
ffi.Pointer<ffi.Char>, ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Float>, ffi.Pointer<ffi.Float>,
ffi.Pointer<ffi.Int>,
ffi.Int, ffi.Int,
ffi.Int, ffi.Int,
ffi.Float)>>('set_morph_animation'); ffi.Float)>>('set_morph_animation');
late final _set_morph_animation = _set_morph_animationPtr.asFunction< late final _set_morph_animation = _set_morph_animationPtr.asFunction<
int Function(ffi.Pointer<ffi.Void>, int, ffi.Pointer<ffi.Char>, int Function(ffi.Pointer<ffi.Void>, int, ffi.Pointer<ffi.Char>,
ffi.Pointer<ffi.Float>, int, int, double)>(); ffi.Pointer<ffi.Float>, ffi.Pointer<ffi.Int>, int, int, double)>();
void set_bone_animation( void set_bone_animation(
ffi.Pointer<ffi.Void> assetManager, ffi.Pointer<ffi.Void> assetManager,
@@ -735,6 +723,7 @@ class NativeLibrary {
int index, int index,
int loop, int loop,
int reverse, int reverse,
int replaceActive,
double crossfade, double crossfade,
) { ) {
return _play_animation( return _play_animation(
@@ -743,6 +732,7 @@ class NativeLibrary {
index, index,
loop, loop,
reverse, reverse,
replaceActive,
crossfade, crossfade,
); );
} }
@@ -750,9 +740,9 @@ class NativeLibrary {
late final _play_animationPtr = _lookup< late final _play_animationPtr = _lookup<
ffi.NativeFunction< ffi.NativeFunction<
ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId, ffi.Int, ffi.Int, ffi.Void Function(ffi.Pointer<ffi.Void>, EntityId, ffi.Int, ffi.Int,
ffi.Int, ffi.Float)>>('play_animation'); ffi.Int, ffi.Int, ffi.Float)>>('play_animation');
late final _play_animation = _play_animationPtr.asFunction< late final _play_animation = _play_animationPtr.asFunction<
void Function(ffi.Pointer<ffi.Void>, int, int, int, int, double)>(); void Function(ffi.Pointer<ffi.Void>, int, int, int, int, int, double)>();
void set_animation_frame( void set_animation_frame(
ffi.Pointer<ffi.Void> assetManager, ffi.Pointer<ffi.Void> assetManager,
@@ -832,6 +822,25 @@ class NativeLibrary {
late final _get_animation_name = _get_animation_namePtr.asFunction< late final _get_animation_name = _get_animation_namePtr.asFunction<
void Function(ffi.Pointer<ffi.Void>, int, ffi.Pointer<ffi.Char>, int)>(); void Function(ffi.Pointer<ffi.Void>, int, ffi.Pointer<ffi.Char>, int)>();
double get_animation_duration(
ffi.Pointer<ffi.Void> assetManager,
int asset,
int index,
) {
return _get_animation_duration(
assetManager,
asset,
index,
);
}
late final _get_animation_durationPtr = _lookup<
ffi.NativeFunction<
ffi.Float Function(ffi.Pointer<ffi.Void>, EntityId,
ffi.Int)>>('get_animation_duration');
late final _get_animation_duration = _get_animation_durationPtr
.asFunction<double Function(ffi.Pointer<ffi.Void>, int, int)>();
void get_morph_target_name( void get_morph_target_name(
ffi.Pointer<ffi.Void> assetManager, ffi.Pointer<ffi.Void> assetManager,
int asset, int asset,
@@ -1195,7 +1204,7 @@ class NativeLibrary {
late final _ios_dummy = _ios_dummyPtr.asFunction<void Function()>(); late final _ios_dummy = _ios_dummyPtr.asFunction<void Function()>();
} }
final class __mbstate_t extends ffi.Union { class __mbstate_t extends ffi.Union {
@ffi.Array.multi([128]) @ffi.Array.multi([128])
external ffi.Array<ffi.Char> __mbstate8; external ffi.Array<ffi.Char> __mbstate8;
@@ -1203,7 +1212,7 @@ final class __mbstate_t extends ffi.Union {
external int _mbstateL; external int _mbstateL;
} }
final class __darwin_pthread_handler_rec extends ffi.Struct { class __darwin_pthread_handler_rec extends ffi.Struct {
external ffi external ffi
.Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>> .Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Void>)>>
__routine; __routine;
@@ -1213,7 +1222,7 @@ final class __darwin_pthread_handler_rec extends ffi.Struct {
external ffi.Pointer<__darwin_pthread_handler_rec> __next; external ffi.Pointer<__darwin_pthread_handler_rec> __next;
} }
final class _opaque_pthread_attr_t extends ffi.Struct { class _opaque_pthread_attr_t extends ffi.Struct {
@ffi.Long() @ffi.Long()
external int __sig; external int __sig;
@@ -1221,7 +1230,7 @@ final class _opaque_pthread_attr_t extends ffi.Struct {
external ffi.Array<ffi.Char> __opaque; external ffi.Array<ffi.Char> __opaque;
} }
final class _opaque_pthread_cond_t extends ffi.Struct { class _opaque_pthread_cond_t extends ffi.Struct {
@ffi.Long() @ffi.Long()
external int __sig; external int __sig;
@@ -1229,7 +1238,7 @@ final class _opaque_pthread_cond_t extends ffi.Struct {
external ffi.Array<ffi.Char> __opaque; external ffi.Array<ffi.Char> __opaque;
} }
final class _opaque_pthread_condattr_t extends ffi.Struct { class _opaque_pthread_condattr_t extends ffi.Struct {
@ffi.Long() @ffi.Long()
external int __sig; external int __sig;
@@ -1237,7 +1246,7 @@ final class _opaque_pthread_condattr_t extends ffi.Struct {
external ffi.Array<ffi.Char> __opaque; external ffi.Array<ffi.Char> __opaque;
} }
final class _opaque_pthread_mutex_t extends ffi.Struct { class _opaque_pthread_mutex_t extends ffi.Struct {
@ffi.Long() @ffi.Long()
external int __sig; external int __sig;
@@ -1245,7 +1254,7 @@ final class _opaque_pthread_mutex_t extends ffi.Struct {
external ffi.Array<ffi.Char> __opaque; external ffi.Array<ffi.Char> __opaque;
} }
final class _opaque_pthread_mutexattr_t extends ffi.Struct { class _opaque_pthread_mutexattr_t extends ffi.Struct {
@ffi.Long() @ffi.Long()
external int __sig; external int __sig;
@@ -1253,7 +1262,7 @@ final class _opaque_pthread_mutexattr_t extends ffi.Struct {
external ffi.Array<ffi.Char> __opaque; external ffi.Array<ffi.Char> __opaque;
} }
final class _opaque_pthread_once_t extends ffi.Struct { class _opaque_pthread_once_t extends ffi.Struct {
@ffi.Long() @ffi.Long()
external int __sig; external int __sig;
@@ -1261,7 +1270,7 @@ final class _opaque_pthread_once_t extends ffi.Struct {
external ffi.Array<ffi.Char> __opaque; external ffi.Array<ffi.Char> __opaque;
} }
final class _opaque_pthread_rwlock_t extends ffi.Struct { class _opaque_pthread_rwlock_t extends ffi.Struct {
@ffi.Long() @ffi.Long()
external int __sig; external int __sig;
@@ -1269,7 +1278,7 @@ final class _opaque_pthread_rwlock_t extends ffi.Struct {
external ffi.Array<ffi.Char> __opaque; external ffi.Array<ffi.Char> __opaque;
} }
final class _opaque_pthread_rwlockattr_t extends ffi.Struct { class _opaque_pthread_rwlockattr_t extends ffi.Struct {
@ffi.Long() @ffi.Long()
external int __sig; external int __sig;
@@ -1277,7 +1286,7 @@ final class _opaque_pthread_rwlockattr_t extends ffi.Struct {
external ffi.Array<ffi.Char> __opaque; external ffi.Array<ffi.Char> __opaque;
} }
final class _opaque_pthread_t extends ffi.Struct { class _opaque_pthread_t extends ffi.Struct {
@ffi.Long() @ffi.Long()
external int __sig; external int __sig;
@@ -1287,7 +1296,7 @@ final class _opaque_pthread_t extends ffi.Struct {
external ffi.Array<ffi.Char> __opaque; external ffi.Array<ffi.Char> __opaque;
} }
final class ResourceBuffer extends ffi.Struct { class ResourceBuffer extends ffi.Struct {
external ffi.Pointer<ffi.Void> data; external ffi.Pointer<ffi.Void> data;
@ffi.Uint32() @ffi.Uint32()
@@ -1297,7 +1306,7 @@ final class ResourceBuffer extends ffi.Struct {
external int id; external int id;
} }
final class ResourceLoaderWrapper extends ffi.Struct { class ResourceLoaderWrapper extends ffi.Struct {
external LoadResource mLoadResource; external LoadResource mLoadResource;
external FreeResource mFreeResource; external FreeResource mFreeResource;