mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-04 22:34:53 +08:00
[flutter] clean-up of ffi related code
This commit is contained in:
parent
d059ac01fd
commit
c9d7e687a9
@ -502,7 +502,8 @@ export class DartWriter {
|
||||
const lines: string[] = [];
|
||||
|
||||
lines.push('');
|
||||
lines.push("import '../ffi_proxy.dart';");
|
||||
lines.push("import 'package:universal_ffi/ffi.dart';");
|
||||
lines.push(`import 'package:universal_ffi/ffi_utils.dart';`);
|
||||
|
||||
lines.push("import 'spine_dart_bindings_generated.dart';");
|
||||
lines.push("import '../spine_bindings.dart';");
|
||||
@ -703,7 +704,8 @@ ${declaration} {`;
|
||||
|
||||
lines.push(this.generateHeader());
|
||||
lines.push('');
|
||||
lines.push("import '../ffi_proxy.dart';");
|
||||
lines.push(`import 'package:universal_ffi/ffi.dart';`);
|
||||
lines.push(`import 'package:universal_ffi/ffi_utils.dart';`);
|
||||
lines.push("import 'spine_dart_bindings_generated.dart';");
|
||||
lines.push("import '../spine_bindings.dart';");
|
||||
lines.push("import '../native_array.dart';");
|
||||
@ -1608,13 +1610,10 @@ ${declaration} {`;
|
||||
lines.push('');
|
||||
lines.push('// AUTO GENERATED FILE, DO NOT EDIT.');
|
||||
lines.push('');
|
||||
lines.push('// ignore_for_file: type_argument_not_matching_bounds');
|
||||
lines.push(`import 'package:flutter/services.dart';`);
|
||||
lines.push(`import 'package:wasm_ffi/ffi.dart';`);
|
||||
lines.push(`import 'package:universal_ffi/ffi.dart';`);
|
||||
lines.push('');
|
||||
lines.push(`import 'generated/spine_dart_bindings_generated.dart';`);
|
||||
lines.push('');
|
||||
lines.push('// Export this so malloc_web.dart can access it');
|
||||
lines.push('DynamicLibrary? dylibInstance;');
|
||||
lines.push('');
|
||||
lines.push('class SpineDartFFI {');
|
||||
@ -1655,7 +1654,7 @@ ${declaration} {`;
|
||||
lines.push(` dylibInstance = await DynamicLibrary.open('assets/packages/spine_flutter/lib/assets/libspine_flutter.js');`);
|
||||
lines.push('');
|
||||
lines.push(' // Now register all the opaque types');
|
||||
|
||||
|
||||
// Sort and write all registerOpaqueType calls
|
||||
const sortedTypes = Array.from(wrapperTypes).sort();
|
||||
for (const type of sortedTypes) {
|
||||
|
||||
@ -29,10 +29,10 @@ async function generateFFIBindings(spineCDir: string): Promise<void> {
|
||||
throw new Error('Failed to generate bindings');
|
||||
}
|
||||
|
||||
// Replace dart:ffi import with ffi_proxy.dart
|
||||
console.log('Replacing dart:ffi import with ffi_proxy.dart...');
|
||||
// Replace dart:ffi import with universal_ffi
|
||||
console.log('Replacing dart:ffi import with universal_ffi...');
|
||||
let content = fs.readFileSync(bindingsPath, 'utf8');
|
||||
content = content.replace("import 'dart:ffi' as ffi;", "import '../ffi_proxy.dart' as ffi;");
|
||||
content = content.replace("import 'dart:ffi' as ffi;", "import 'package:universal_ffi/ffi.dart' as ffi;");
|
||||
|
||||
// For web_ffi compatibility, we need to convert wrapper structs to Opaque
|
||||
console.log('Converting wrapper structs to Opaque for web_ffi compatibility...');
|
||||
|
||||
@ -194,6 +194,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
universal_ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_ffi
|
||||
sha256: "8f0e28bab34709e94541ff8c39d86294b686a6cc112561dd2aa071d4a4179609"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@ -1,911 +0,0 @@
|
||||
# Dart FFI Wrapper Generator
|
||||
|
||||
## Overview
|
||||
|
||||
A TypeScript-based code generator that extends the existing `spine-c/codegen` system to automatically generate clean, type-safe Dart wrapper classes over the raw FFI bindings. This eliminates the need for manual wrapper implementation while providing a native Dart API experience.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
spine-cpp (C++ source)
|
||||
↓ (existing type-extractor.ts)
|
||||
spine-cpp-types.json (type definitions)
|
||||
↓ (existing ir-generator.ts + c-writer.ts)
|
||||
spine-c (C bindings: .h/.c files)
|
||||
↓ (ffigen via generate_bindings.sh)
|
||||
spine_flutter_bindings_generated.dart (raw FFI)
|
||||
↓ (NEW: dart-generator.ts)
|
||||
spine_flutter.dart (clean Dart API)
|
||||
```
|
||||
|
||||
## Key Insights
|
||||
|
||||
### 1. Derivation vs Parsing
|
||||
Instead of parsing the generated FFI bindings, we **derive** what ffigen produces using the same C type information that generates the headers. This works because ffigen follows predictable transformation rules:
|
||||
|
||||
### 2. Predictable Disposal Pattern
|
||||
All C types follow a consistent disposal pattern (`spine_type_name` → `spine_type_name_dispose`), so we can derive disposal function names automatically instead of storing them.
|
||||
|
||||
### 3. Array Properties vs Regular Getters
|
||||
C functions that return `spine_array_*` types become special **Array<T> properties** in Dart, requiring different generation logic than primitive getters.
|
||||
|
||||
### FFigen Transformation Rules
|
||||
|
||||
| C Code | Generated Dart FFI |
|
||||
|--------|-------------------|
|
||||
| `SPINE_C_API float spine_animation_get_duration(spine_animation self);` | `double spine_animation_get_duration(Pointer<spine_animation_wrapper> self)` |
|
||||
| `SPINE_C_API void spine_animation_dispose(spine_animation self);` | `void spine_animation_dispose(Pointer<spine_animation_wrapper> self)` |
|
||||
| `typedef enum { BLEND_NORMAL, BLEND_ADDITIVE } spine_blend_mode;` | `enum spine_blend_mode { BLEND_NORMAL(0), BLEND_ADDITIVE(1) }` |
|
||||
| `SPINE_OPAQUE_TYPE(spine_animation)` | `typedef struct spine_animation_wrapper { char _dummy; } spine_animation_wrapper; typedef spine_animation_wrapper *spine_animation;` |
|
||||
| `spine_array_timeline spine_animation_get_timelines(spine_animation self);` | `Pointer<spine_array_timeline_wrapper> spine_animation_get_timelines(Pointer<spine_animation_wrapper> self)` → **Array<Timeline> property** |
|
||||
|
||||
## Generator Components
|
||||
|
||||
### 1. Type Mapping System (`dart-types.ts`)
|
||||
|
||||
Defines the structure for Dart wrapper types:
|
||||
|
||||
```typescript
|
||||
interface DartClass {
|
||||
name: string; // "Animation"
|
||||
cName: string; // "spine_animation"
|
||||
nativeType: string; // "Pointer<spine_animation_wrapper>"
|
||||
constructors: DartConstructor[];
|
||||
methods: DartMethod[];
|
||||
getters: DartGetter[];
|
||||
setters: DartSetter[];
|
||||
arrays: DartArrayGetter[]; // Properties that return Array<T> (e.g., animation.timelines)
|
||||
}
|
||||
|
||||
interface DartMethod {
|
||||
name: string; // "apply"
|
||||
cFunctionName: string; // "spine_animation_apply"
|
||||
returnType: DartType;
|
||||
parameters: DartParameter[];
|
||||
isStatic?: boolean;
|
||||
}
|
||||
|
||||
interface DartGetter {
|
||||
name: string; // "duration"
|
||||
cFunctionName: string; // "spine_animation_get_duration"
|
||||
returnType: DartType;
|
||||
}
|
||||
|
||||
interface DartSetter {
|
||||
name: string; // "duration"
|
||||
cFunctionName: string; // "spine_animation_set_duration"
|
||||
parameterType: DartType;
|
||||
}
|
||||
|
||||
interface DartArrayGetter {
|
||||
name: string; // "timelines" (Dart property name)
|
||||
elementType: string; // "Timeline" (element type inside Array<T>)
|
||||
cArrayType: string; // "spine_array_timeline" (C array type returned)
|
||||
cGetterName: string; // "spine_animation_get_timelines" (C function to call)
|
||||
}
|
||||
|
||||
interface DartConstructor {
|
||||
cFunctionName: string; // "spine_animation_create"
|
||||
parameters: DartParameter[];
|
||||
}
|
||||
|
||||
interface DartParameter {
|
||||
name: string;
|
||||
type: DartType;
|
||||
cType: string; // Original C type for conversion
|
||||
}
|
||||
|
||||
interface DartType {
|
||||
dart: string; // "double", "String", "Animation"
|
||||
isNullable?: boolean;
|
||||
isNative?: boolean; // true for primitives, false for wrapper classes
|
||||
}
|
||||
|
||||
interface DartEnum {
|
||||
name: string; // "BlendMode"
|
||||
cName: string; // "spine_blend_mode"
|
||||
values: DartEnumValue[];
|
||||
}
|
||||
|
||||
interface DartEnumValue {
|
||||
name: string; // "normal"
|
||||
cName: string; // "SPINE_BLEND_MODE_NORMAL"
|
||||
value: number;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Type Mapping Rules (`dart-type-mapper.ts`)
|
||||
|
||||
Converts C types to Dart types:
|
||||
|
||||
```typescript
|
||||
class DartTypeMapper {
|
||||
// Maps C types to Dart types
|
||||
private static readonly TYPE_MAP: Record<string, DartType> = {
|
||||
'float': { dart: 'double', isNative: true },
|
||||
'double': { dart: 'double', isNative: true },
|
||||
'int': { dart: 'int', isNative: true },
|
||||
'bool': { dart: 'bool', isNative: true },
|
||||
'char*': { dart: 'String', isNative: true },
|
||||
'const char*': { dart: 'String', isNative: true },
|
||||
'void': { dart: 'void', isNative: true },
|
||||
'spine_skeleton': { dart: 'Skeleton', isNative: false },
|
||||
'spine_animation': { dart: 'Animation', isNative: false },
|
||||
// ... more mappings
|
||||
};
|
||||
|
||||
static mapCTypeToDart(cType: string): DartType {
|
||||
// Handle pointers
|
||||
if (cType.endsWith('*')) {
|
||||
const baseType = cType.slice(0, -1).trim();
|
||||
const mapped = this.TYPE_MAP[baseType];
|
||||
return mapped ? { ...mapped, isNullable: true } : this.mapSpineType(baseType);
|
||||
}
|
||||
|
||||
// Handle direct mappings
|
||||
return this.TYPE_MAP[cType] || this.mapSpineType(cType);
|
||||
}
|
||||
|
||||
private static mapSpineType(cType: string): DartType {
|
||||
if (cType.startsWith('spine_')) {
|
||||
// spine_animation -> Animation
|
||||
const dartName = toPascalCase(cType.replace('spine_', ''));
|
||||
return { dart: dartName, isNative: false };
|
||||
}
|
||||
|
||||
// Default to dynamic for unknown types
|
||||
return { dart: 'dynamic', isNative: false };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Naming Convention Utilities (`dart-naming.ts`)
|
||||
|
||||
Handles C to Dart naming conversions:
|
||||
|
||||
```typescript
|
||||
export function toPascalCase(snakeCase: string): string {
|
||||
return snakeCase
|
||||
.split('_')
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
||||
.join('');
|
||||
}
|
||||
|
||||
export function toCamelCase(snakeCase: string): string {
|
||||
const pascal = toPascalCase(snakeCase);
|
||||
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
||||
}
|
||||
|
||||
export function extractMethodName(cFunctionName: string, className: string): string {
|
||||
// spine_animation_get_duration -> getDuration
|
||||
// spine_animation_set_duration -> setDuration
|
||||
// spine_animation_apply -> apply
|
||||
|
||||
const prefix = `spine_${toSnakeCase(className)}_`;
|
||||
if (!cFunctionName.startsWith(prefix)) {
|
||||
throw new Error(`Function ${cFunctionName} doesn't match expected prefix ${prefix}`);
|
||||
}
|
||||
|
||||
const methodPart = cFunctionName.slice(prefix.length);
|
||||
return toCamelCase(methodPart);
|
||||
}
|
||||
|
||||
export function isGetter(methodName: string): boolean {
|
||||
return methodName.startsWith('get_');
|
||||
}
|
||||
|
||||
export function isSetter(methodName: string): boolean {
|
||||
return methodName.startsWith('set_');
|
||||
}
|
||||
|
||||
export function extractPropertyName(methodName: string): string {
|
||||
// get_duration -> duration
|
||||
// set_duration -> duration
|
||||
if (methodName.startsWith('get_') || methodName.startsWith('set_')) {
|
||||
return methodName.slice(4);
|
||||
}
|
||||
return methodName;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Dart Code Generator (`dart-writer.ts`)
|
||||
|
||||
Generates the actual Dart wrapper files:
|
||||
|
||||
```typescript
|
||||
export class DartWriter {
|
||||
constructor(private outputDir: string, private bindingsImport: string) {}
|
||||
|
||||
async writeClass(dartClass: DartClass): Promise<void> {
|
||||
const lines: string[] = [];
|
||||
|
||||
// File header
|
||||
lines.push("// AUTO GENERATED FILE, DO NOT EDIT.");
|
||||
lines.push("// Generated by spine-c dart-wrapper generator");
|
||||
lines.push("");
|
||||
lines.push(`import '${this.bindingsImport}';`);
|
||||
lines.push("import 'dart:ffi';");
|
||||
lines.push("import 'array.dart';");
|
||||
lines.push("");
|
||||
|
||||
// Class declaration
|
||||
lines.push(`class ${dartClass.name} {`);
|
||||
lines.push(` final ${dartClass.nativeType} _ptr;`);
|
||||
lines.push(` final SpineFlutterBindings _bindings;`);
|
||||
lines.push("");
|
||||
|
||||
// Private constructor
|
||||
lines.push(` ${dartClass.name}._(this._ptr, this._bindings);`);
|
||||
lines.push("");
|
||||
|
||||
// Public constructors
|
||||
for (const constructor of dartClass.constructors) {
|
||||
lines.push(this.writeConstructor(dartClass, constructor));
|
||||
lines.push("");
|
||||
}
|
||||
|
||||
// Getters
|
||||
for (const getter of dartClass.getters) {
|
||||
lines.push(this.writeGetter(getter));
|
||||
}
|
||||
|
||||
// Setters
|
||||
for (const setter of dartClass.setters) {
|
||||
lines.push(this.writeSetter(setter));
|
||||
}
|
||||
|
||||
// Array getters
|
||||
for (const arrayGetter of dartClass.arrays) {
|
||||
lines.push(this.writeArrayGetter(arrayGetter));
|
||||
}
|
||||
|
||||
// Methods
|
||||
for (const method of dartClass.methods) {
|
||||
lines.push(this.writeMethod(method));
|
||||
lines.push("");
|
||||
}
|
||||
|
||||
// Disposal method (derived from class name)
|
||||
lines.push(` void dispose() => _bindings.${dartClass.cName}_dispose(_ptr);`);
|
||||
|
||||
lines.push("}");
|
||||
|
||||
// Write to file
|
||||
const fileName = `${toSnakeCase(dartClass.name)}.dart`;
|
||||
const filePath = path.join(this.outputDir, fileName);
|
||||
await fs.writeFile(filePath, lines.join('\n'));
|
||||
}
|
||||
|
||||
private writeConstructor(dartClass: DartClass, constructor: DartConstructor): string {
|
||||
const params = constructor.parameters.map(p =>
|
||||
`${p.type.dart} ${p.name}`
|
||||
).join(', ');
|
||||
|
||||
const args = constructor.parameters.map(p =>
|
||||
this.convertDartToC(p.name, p.type, p.cType)
|
||||
).join(', ');
|
||||
|
||||
return [
|
||||
` factory ${dartClass.name}.create(SpineFlutterBindings bindings${params ? ', ' + params : ''}) {`,
|
||||
` final ptr = bindings.${constructor.cFunctionName}(${args});`,
|
||||
` return ${dartClass.name}._(ptr, bindings);`,
|
||||
` }`
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
private writeGetter(getter: DartGetter): string {
|
||||
if (getter.returnType.isNative) {
|
||||
return ` ${getter.returnType.dart} get ${getter.name} => _bindings.${getter.cFunctionName}(_ptr);`;
|
||||
} else {
|
||||
return [
|
||||
` ${getter.returnType.dart} get ${getter.name} {`,
|
||||
` final ptr = _bindings.${getter.cFunctionName}(_ptr);`,
|
||||
` return ${getter.returnType.dart}._(ptr, _bindings);`,
|
||||
` }`
|
||||
].join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
private writeSetter(setter: DartSetter): string {
|
||||
const conversion = this.convertDartToC('value', setter.parameterType, '');
|
||||
return ` set ${setter.name}(${setter.parameterType.dart} value) => _bindings.${setter.cFunctionName}(_ptr, ${conversion});`;
|
||||
}
|
||||
|
||||
private writeArrayGetter(arrayGetter: DartArrayGetter): string {
|
||||
return [
|
||||
` Array<${arrayGetter.elementType}> get ${arrayGetter.name} {`,
|
||||
` final array = _bindings.${arrayGetter.cGetterName}(_ptr);`,
|
||||
` return Array.create<${arrayGetter.elementType}>(array, _bindings, ${arrayGetter.elementType}._);`,
|
||||
` }`
|
||||
].join('\n');
|
||||
}
|
||||
|
||||
private writeMethod(method: DartMethod): string {
|
||||
const params = method.parameters.map(p =>
|
||||
`${p.type.dart} ${p.name}`
|
||||
).join(', ');
|
||||
|
||||
const args = ['_ptr', ...method.parameters.map(p =>
|
||||
this.convertDartToC(p.name, p.type, p.cType)
|
||||
)].join(', ');
|
||||
|
||||
if (method.returnType.dart === 'void') {
|
||||
return [
|
||||
` void ${method.name}(${params}) {`,
|
||||
` _bindings.${method.cFunctionName}(${args});`,
|
||||
` }`
|
||||
].join('\n');
|
||||
} else if (method.returnType.isNative) {
|
||||
return [
|
||||
` ${method.returnType.dart} ${method.name}(${params}) {`,
|
||||
` return _bindings.${method.cFunctionName}(${args});`,
|
||||
` }`
|
||||
].join('\n');
|
||||
} else {
|
||||
return [
|
||||
` ${method.returnType.dart} ${method.name}(${params}) {`,
|
||||
` final ptr = _bindings.${method.cFunctionName}(${args});`,
|
||||
` return ${method.returnType.dart}._(ptr, _bindings);`,
|
||||
` }`
|
||||
].join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
private convertDartToC(dartValue: string, dartType: DartType, cType: string): string {
|
||||
if (dartType.isNative) {
|
||||
// Handle string conversion
|
||||
if (dartType.dart === 'String') {
|
||||
return `${dartValue}.toNativeUtf8().cast<Char>()`;
|
||||
}
|
||||
return dartValue;
|
||||
} else {
|
||||
// Wrapper class - extract the pointer
|
||||
return `${dartValue}._ptr`;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Generic Array Implementation (`dart-array-writer.ts`)
|
||||
|
||||
Generates a single reusable Array class:
|
||||
|
||||
```typescript
|
||||
export class DartArrayWriter {
|
||||
async writeArrayClass(outputDir: string): Promise<void> {
|
||||
const content = `
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
// Generated by spine-c dart-wrapper generator
|
||||
|
||||
import 'dart:collection';
|
||||
import 'dart:ffi';
|
||||
import 'spine_flutter_bindings_generated.dart';
|
||||
|
||||
class Array<T> extends ListBase<T> {
|
||||
final Pointer _nativeArray;
|
||||
final SpineFlutterBindings _bindings;
|
||||
final T Function(Pointer) _elementFactory;
|
||||
final String _arrayTypeName;
|
||||
|
||||
Array._(
|
||||
this._nativeArray,
|
||||
this._bindings,
|
||||
this._elementFactory,
|
||||
this._arrayTypeName,
|
||||
);
|
||||
|
||||
static Array<T> create<T>(
|
||||
Pointer nativeArray,
|
||||
SpineFlutterBindings bindings,
|
||||
T Function(Pointer) elementFactory,
|
||||
) {
|
||||
final typeName = T.toString().toLowerCase();
|
||||
return Array._(nativeArray, bindings, elementFactory, 'spine_array_\$typeName');
|
||||
}
|
||||
|
||||
@override
|
||||
int get length {
|
||||
// Use dynamic function lookup based on type
|
||||
switch (_arrayTypeName) {
|
||||
case 'spine_array_timeline':
|
||||
return _bindings.spine_array_timeline_get_size(_nativeArray.cast());
|
||||
case 'spine_array_bone_data':
|
||||
return _bindings.spine_array_bone_data_get_size(_nativeArray.cast());
|
||||
case 'spine_array_slot_data':
|
||||
return _bindings.spine_array_slot_data_get_size(_nativeArray.cast());
|
||||
// Add more cases as needed
|
||||
default:
|
||||
throw UnsupportedError('Unknown array type: \$_arrayTypeName');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
T operator [](int index) {
|
||||
if (index < 0 || index >= length) {
|
||||
throw RangeError.index(index, this);
|
||||
}
|
||||
|
||||
Pointer elementPtr;
|
||||
switch (_arrayTypeName) {
|
||||
case 'spine_array_timeline':
|
||||
elementPtr = _bindings.spine_array_timeline_get(_nativeArray.cast(), index);
|
||||
break;
|
||||
case 'spine_array_bone_data':
|
||||
elementPtr = _bindings.spine_array_bone_data_get(_nativeArray.cast(), index);
|
||||
break;
|
||||
case 'spine_array_slot_data':
|
||||
elementPtr = _bindings.spine_array_slot_data_get(_nativeArray.cast(), index);
|
||||
break;
|
||||
// Add more cases as needed
|
||||
default:
|
||||
throw UnsupportedError('Unknown array type: \$_arrayTypeName');
|
||||
}
|
||||
|
||||
return _elementFactory(elementPtr);
|
||||
}
|
||||
|
||||
@override
|
||||
void operator []=(int index, T value) {
|
||||
throw UnsupportedError('Array is read-only');
|
||||
}
|
||||
|
||||
@override
|
||||
set length(int newLength) {
|
||||
throw UnsupportedError('Array is read-only');
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const filePath = path.join(outputDir, 'array.dart');
|
||||
await fs.writeFile(filePath, content.trim());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Enum Generator (`dart-enum-writer.ts`)
|
||||
|
||||
Generates Dart enum wrappers:
|
||||
|
||||
```typescript
|
||||
export class DartEnumWriter {
|
||||
async writeEnum(dartEnum: DartEnum, outputDir: string): Promise<void> {
|
||||
const lines: string[] = [];
|
||||
|
||||
// File header
|
||||
lines.push("// AUTO GENERATED FILE, DO NOT EDIT.");
|
||||
lines.push("// Generated by spine-c dart-wrapper generator");
|
||||
lines.push("");
|
||||
|
||||
// Enum declaration
|
||||
lines.push(`enum ${dartEnum.name} {`);
|
||||
|
||||
// Enum values
|
||||
for (let i = 0; i < dartEnum.values.length; i++) {
|
||||
const value = dartEnum.values[i];
|
||||
const comma = i < dartEnum.values.length - 1 ? ',' : '';
|
||||
lines.push(` ${value.name}(${value.value})${comma}`);
|
||||
}
|
||||
|
||||
lines.push("");
|
||||
lines.push(" const ${dartEnum.name}(this.value);");
|
||||
lines.push(" final int value;");
|
||||
lines.push("");
|
||||
|
||||
// From native conversion
|
||||
lines.push(` static ${dartEnum.name} fromNative(int value) {`);
|
||||
lines.push(" switch (value) {");
|
||||
for (const value of dartEnum.values) {
|
||||
lines.push(` case ${value.value}: return ${dartEnum.name}.${value.name};`);
|
||||
}
|
||||
lines.push(` default: throw ArgumentError('Unknown ${dartEnum.name} value: \$value');`);
|
||||
lines.push(" }");
|
||||
lines.push(" }");
|
||||
lines.push("}");
|
||||
|
||||
// Write to file
|
||||
const fileName = `${toSnakeCase(dartEnum.name)}.dart`;
|
||||
const filePath = path.join(outputDir, fileName);
|
||||
await fs.writeFile(filePath, lines.join('\n'));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Main Generator Orchestrator (`dart-generator.ts`)
|
||||
|
||||
Coordinates the entire generation process:
|
||||
|
||||
```typescript
|
||||
import { CClassOrStruct, CEnum, CArrayType } from './c-types';
|
||||
import { DartClass, DartEnum } from './dart-types';
|
||||
import { DartTypeMapper } from './dart-type-mapper';
|
||||
import { DartWriter } from './dart-writer';
|
||||
import { DartEnumWriter } from './dart-enum-writer';
|
||||
import { DartArrayWriter } from './dart-array-writer';
|
||||
import { extractMethodName, isGetter, isSetter, extractPropertyName } from './dart-naming';
|
||||
|
||||
export class DartGenerator {
|
||||
private typeMapper = new DartTypeMapper();
|
||||
private writer: DartWriter;
|
||||
private enumWriter = new DartEnumWriter();
|
||||
private arrayWriter = new DartArrayWriter();
|
||||
|
||||
constructor(
|
||||
private cTypes: CClassOrStruct[],
|
||||
private cEnums: CEnum[],
|
||||
private cArrayTypes: CArrayType[],
|
||||
private outputDir: string,
|
||||
private bindingsImport: string = 'spine_flutter_bindings_generated.dart'
|
||||
) {
|
||||
this.writer = new DartWriter(outputDir, bindingsImport);
|
||||
}
|
||||
|
||||
async generateAll(): Promise<void> {
|
||||
// Ensure output directory exists
|
||||
await fs.mkdir(this.outputDir, { recursive: true });
|
||||
|
||||
console.log(`Generating ${this.cTypes.length} Dart wrapper classes...`);
|
||||
|
||||
// Generate wrapper classes
|
||||
for (const cType of this.cTypes) {
|
||||
const dartClass = this.convertCTypeToDartClass(cType);
|
||||
await this.writer.writeClass(dartClass);
|
||||
console.log(`Generated: ${dartClass.name}`);
|
||||
}
|
||||
|
||||
console.log(`Generating ${this.cEnums.length} Dart enums...`);
|
||||
|
||||
// Generate enums
|
||||
for (const cEnum of this.cEnums) {
|
||||
const dartEnum = this.convertCEnumToDartEnum(cEnum);
|
||||
await this.enumWriter.writeEnum(dartEnum, this.outputDir);
|
||||
console.log(`Generated enum: ${dartEnum.name}`);
|
||||
}
|
||||
|
||||
// Generate generic Array class
|
||||
await this.arrayWriter.writeArrayClass(this.outputDir);
|
||||
console.log('Generated: Array<T>');
|
||||
|
||||
console.log('Dart wrapper generation complete!');
|
||||
}
|
||||
|
||||
private convertCTypeToDartClass(cType: CClassOrStruct): DartClass {
|
||||
const className = toPascalCase(cType.name.replace('spine_', ''));
|
||||
|
||||
// Separate getters, setters, and regular methods
|
||||
const getters: DartGetter[] = [];
|
||||
const setters: DartSetter[] = [];
|
||||
const methods: DartMethod[] = [];
|
||||
const constructors: DartConstructor[] = [];
|
||||
const arrays: DartArrayGetter[] = [];
|
||||
|
||||
for (const method of cType.methods) {
|
||||
const methodName = extractMethodName(method.name, cType.name);
|
||||
|
||||
if (method.name.includes('_create')) {
|
||||
// Constructor
|
||||
constructors.push({
|
||||
cFunctionName: method.name,
|
||||
parameters: method.parameters.slice(0, -1).map(p => ({
|
||||
name: p.name,
|
||||
type: this.typeMapper.mapCTypeToDart(p.type),
|
||||
cType: p.type
|
||||
}))
|
||||
});
|
||||
} else if (isGetter(methodName)) {
|
||||
// Getter
|
||||
const propertyName = extractPropertyName(methodName);
|
||||
const returnType = this.typeMapper.mapCTypeToDart(method.returnType);
|
||||
|
||||
// Check if this is an array getter
|
||||
if (method.returnType.startsWith('spine_array_')) {
|
||||
const elementType = this.extractArrayElementType(method.returnType);
|
||||
arrays.push({
|
||||
name: propertyName,
|
||||
elementType,
|
||||
cArrayType: method.returnType,
|
||||
cGetterName: method.name
|
||||
});
|
||||
} else {
|
||||
getters.push({
|
||||
name: propertyName,
|
||||
cFunctionName: method.name,
|
||||
returnType
|
||||
});
|
||||
}
|
||||
} else if (isSetter(methodName)) {
|
||||
// Setter
|
||||
const propertyName = extractPropertyName(methodName);
|
||||
const paramType = this.typeMapper.mapCTypeToDart(method.parameters[1].type);
|
||||
setters.push({
|
||||
name: propertyName,
|
||||
cFunctionName: method.name,
|
||||
parameterType: paramType
|
||||
});
|
||||
} else {
|
||||
// Regular method
|
||||
methods.push({
|
||||
name: methodName,
|
||||
cFunctionName: method.name,
|
||||
returnType: this.typeMapper.mapCTypeToDart(method.returnType),
|
||||
parameters: method.parameters.slice(1).map(p => ({
|
||||
name: p.name,
|
||||
type: this.typeMapper.mapCTypeToDart(p.type),
|
||||
cType: p.type
|
||||
}))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: className,
|
||||
cName: cType.name,
|
||||
nativeType: `Pointer<${cType.name}_wrapper>`,
|
||||
constructors,
|
||||
methods,
|
||||
getters,
|
||||
setters,
|
||||
arrays
|
||||
};
|
||||
}
|
||||
|
||||
private convertCEnumToDartEnum(cEnum: CEnum): DartEnum {
|
||||
return {
|
||||
name: toPascalCase(cEnum.name.replace('spine_', '')),
|
||||
cName: cEnum.name,
|
||||
values: cEnum.values.map(value => ({
|
||||
name: toCamelCase(value.name.replace(/^SPINE_.*?_/, '')),
|
||||
cName: value.name,
|
||||
value: value.value
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
private extractArrayElementType(arrayType: string): string {
|
||||
// spine_array_timeline -> Timeline
|
||||
// spine_array_bone_data -> BoneData
|
||||
const match = arrayType.match(/spine_array_(.+)/);
|
||||
if (!match) throw new Error(`Invalid array type: ${arrayType}`);
|
||||
|
||||
return toPascalCase(match[1]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8. Integration with Existing Codegen (`index.ts` modifications)
|
||||
|
||||
Extend the existing main function:
|
||||
|
||||
```typescript
|
||||
// Add to existing imports
|
||||
import { DartGenerator } from './dart-generator';
|
||||
|
||||
// Add to existing main() function after C generation
|
||||
async function main() {
|
||||
// ... existing C generation code ...
|
||||
|
||||
// Write all C files to disk
|
||||
const cWriter = new CWriter(path.join(__dirname, '../../src/generated'));
|
||||
await cWriter.writeAll(cTypes, cEnums, cArrayTypes);
|
||||
|
||||
console.log('C code generation complete!');
|
||||
|
||||
// NEW: Generate Dart wrappers
|
||||
const dartOutputDir = path.join(__dirname, '../../../lib/src/generated');
|
||||
const dartGenerator = new DartGenerator(
|
||||
cTypes,
|
||||
cEnums,
|
||||
cArrayTypes,
|
||||
dartOutputDir
|
||||
);
|
||||
|
||||
await dartGenerator.generateAll();
|
||||
|
||||
console.log('All code generation complete!');
|
||||
}
|
||||
```
|
||||
|
||||
## Generated Output Structure
|
||||
|
||||
After running the generator, the output structure will be:
|
||||
|
||||
```
|
||||
lib/
|
||||
├── spine_flutter.dart # Main export file
|
||||
├── spine_flutter_bindings_generated.dart # Raw FFI bindings (from ffigen)
|
||||
└── src/
|
||||
└── generated/
|
||||
├── array.dart # Generic Array<T> implementation
|
||||
├── animation.dart # Animation wrapper class
|
||||
├── skeleton.dart # Skeleton wrapper class
|
||||
├── bone_data.dart # BoneData wrapper class
|
||||
├── blend_mode.dart # BlendMode enum
|
||||
└── ... # More generated classes and enums
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Before (Manual FFI Usage)
|
||||
```dart
|
||||
// Raw FFI - error-prone and verbose
|
||||
final skeletonDataPtr = bindings.spine_skeleton_data_create_from_file('skeleton.json'.toNativeUtf8().cast());
|
||||
final bonesArrayPtr = bindings.spine_skeleton_data_get_bones(skeletonDataPtr);
|
||||
final numBones = bindings.spine_skeleton_data_get_num_bones(skeletonDataPtr);
|
||||
|
||||
for (int i = 0; i < numBones; i++) {
|
||||
final bonePtr = bindings.spine_array_bone_data_get(bonesArrayPtr, i);
|
||||
final namePtr = bindings.spine_bone_data_get_name(bonePtr);
|
||||
final name = namePtr.cast<Utf8>().toDartString();
|
||||
print('Bone: $name');
|
||||
}
|
||||
|
||||
bindings.spine_skeleton_data_dispose(skeletonDataPtr);
|
||||
```
|
||||
|
||||
### After (Generated Wrapper Usage)
|
||||
```dart
|
||||
// Clean, type-safe API
|
||||
final skeletonData = SkeletonData.fromFile(bindings, 'skeleton.json');
|
||||
final bones = skeletonData.bones; // Array<BoneData>
|
||||
|
||||
for (final bone in bones) { // Natural Dart iteration
|
||||
print('Bone: ${bone.name}'); // Direct property access
|
||||
}
|
||||
|
||||
skeletonData.dispose(); // Clean disposal
|
||||
```
|
||||
|
||||
### Advanced Usage
|
||||
```dart
|
||||
// Complex operations made simple
|
||||
final skeleton = Skeleton.create(bindings, skeletonData);
|
||||
final animState = AnimationState.create(bindings, animStateData);
|
||||
|
||||
// Arrays work like native Dart Lists
|
||||
final animations = skeleton.data.animations;
|
||||
final firstAnim = animations[0];
|
||||
final animCount = animations.length;
|
||||
|
||||
// Functional programming support
|
||||
final animNames = animations.map((a) => a.name).toList();
|
||||
final longAnims = animations.where((a) => a.duration > 5.0).toList();
|
||||
|
||||
// Enum usage
|
||||
skeleton.setSkin('goblin');
|
||||
animState.setAnimation(0, firstAnim, true);
|
||||
animState.setMixByName('idle', 'walk', 0.2);
|
||||
|
||||
// Chaining operations
|
||||
skeleton.data.bones
|
||||
.where((bone) => bone.parent != null)
|
||||
.forEach((bone) => print('Child bone: ${bone.name}'));
|
||||
```
|
||||
|
||||
## Build Integration
|
||||
|
||||
### 1. Update `generate_bindings.sh`
|
||||
|
||||
Add Dart wrapper generation to the existing script:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# ... existing FFI generation code ...
|
||||
|
||||
# Generate Dart wrappers
|
||||
echo "Generating Dart wrapper classes..."
|
||||
cd src/spine-c/codegen
|
||||
npm run generate-dart
|
||||
|
||||
echo "✅ All code generation completed!"
|
||||
```
|
||||
|
||||
### 2. Add npm script to `spine-c/codegen/package.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"generate": "npm run build && node dist/index.js",
|
||||
"generate-dart": "npm run build && node dist/index.js --dart-only",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Update `pubspec.yaml` dependencies
|
||||
|
||||
The generated code will require:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
ffi: ^2.1.0
|
||||
# ... existing dependencies
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
### 1. **Developer Experience**
|
||||
- **Type Safety**: Compile-time checking prevents FFI pointer errors
|
||||
- **IDE Support**: Full autocomplete, documentation, and refactoring
|
||||
- **Familiar API**: Uses standard Dart patterns (getters, setters, Lists)
|
||||
- **Memory Safety**: Automatic lifetime management with dispose patterns
|
||||
|
||||
### 2. **Performance**
|
||||
- **Zero Copy**: Arrays provide lazy access to native data
|
||||
- **Minimal Overhead**: Thin wrappers over FFI calls
|
||||
- **Batch Operations**: Array operations can be optimized in native code
|
||||
|
||||
### 3. **Maintainability**
|
||||
- **Automatic Updates**: Changes to C++ API automatically flow through
|
||||
- **Consistent Patterns**: All classes follow the same conventions
|
||||
- **Documentation**: Generated code includes comprehensive docs
|
||||
- **Testing**: Type-safe API makes unit testing straightforward
|
||||
|
||||
### 4. **Reliability**
|
||||
- **No Manual Coding**: Eliminates human error in wrapper implementation
|
||||
- **Validated Generation**: Uses proven C type information
|
||||
- **Comprehensive Coverage**: Every C function gets a Dart wrapper
|
||||
|
||||
## Implementation Timeline
|
||||
|
||||
### Phase 1: Core Infrastructure (1-2 weeks)
|
||||
- [ ] Set up TypeScript generator project structure
|
||||
- [ ] Implement basic type mapping system
|
||||
- [ ] Create simple class generator for basic types
|
||||
- [ ] Test with a few example classes (Animation, Skeleton)
|
||||
|
||||
### Phase 2: Array Support (1 week)
|
||||
- [ ] Implement generic Array<T> class
|
||||
- [ ] Add array detection and generation logic
|
||||
- [ ] Test array functionality with timeline/bone arrays
|
||||
|
||||
### Phase 3: Enum Support (3-5 days)
|
||||
- [ ] Add enum detection and generation
|
||||
- [ ] Implement enum value mapping
|
||||
- [ ] Test with BlendMode and other enums
|
||||
|
||||
### Phase 4: Advanced Features (1 week)
|
||||
- [ ] Add constructor detection and generation
|
||||
- [ ] Implement property getter/setter pairing
|
||||
- [ ] Add disposal pattern detection
|
||||
- [ ] Memory management best practices
|
||||
|
||||
### Phase 5: Integration & Polish (3-5 days)
|
||||
- [ ] Integrate with existing build pipeline
|
||||
- [ ] Add comprehensive documentation
|
||||
- [ ] Create migration guide from manual FFI
|
||||
- [ ] Performance testing and optimization
|
||||
|
||||
### Phase 6: Testing & Validation (1 week)
|
||||
- [ ] Unit tests for all generated wrappers
|
||||
- [ ] Integration tests with actual Spine files
|
||||
- [ ] Performance benchmarks vs raw FFI
|
||||
- [ ] Documentation and examples
|
||||
|
||||
**Total Estimated Time: 4-6 weeks**
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### 1. **Advanced Memory Management**
|
||||
- Automatic disposal when objects go out of scope
|
||||
- Reference counting for shared objects
|
||||
- Memory leak detection in debug mode
|
||||
|
||||
### 2. **Performance Optimizations**
|
||||
- Cached property access
|
||||
- Batch array operations
|
||||
- Native collection implementations
|
||||
|
||||
### 3. **Developer Tools**
|
||||
- Debug visualizations for Spine objects
|
||||
- Memory usage monitoring
|
||||
- Performance profiling integration
|
||||
|
||||
### 4. **API Enhancements**
|
||||
- Async/Future support for long operations
|
||||
- Stream-based event handling
|
||||
- Reactive programming patterns
|
||||
|
||||
This comprehensive generator will transform the Spine Flutter experience from low-level FFI manipulation to a clean, type-safe, and performant Dart API that feels native to the Flutter ecosystem.
|
||||
@ -1,34 +0,0 @@
|
||||
///
|
||||
/// Spine Runtimes License Agreement
|
||||
/// Last updated April 5, 2025. Replaces all prior versions.
|
||||
///
|
||||
/// Copyright (c) 2013-2025, Esoteric Software LLC
|
||||
///
|
||||
/// Integration of the Spine Runtimes into software or otherwise creating
|
||||
/// derivative works of the Spine Runtimes is permitted under the terms and
|
||||
/// conditions of Section 2 of the Spine Editor License Agreement:
|
||||
/// http://esotericsoftware.com/spine-editor-license
|
||||
///
|
||||
/// Otherwise, it is permitted to integrate the Spine Runtimes into software
|
||||
/// or otherwise create derivative works of the Spine Runtimes (collectively,
|
||||
/// "Products"), provided that each user of the Products must obtain their own
|
||||
/// Spine Editor license and redistribution of the Products in any form must
|
||||
/// include this license and copyright notice.
|
||||
///
|
||||
/// THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
|
||||
/// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
/// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
/// DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
|
||||
/// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
/// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
|
||||
/// BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
|
||||
/// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
/// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
/// THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
///
|
||||
|
||||
export 'dart:ffi' if (dart.library.html) 'package:wasm_ffi/ffi.dart';
|
||||
|
||||
export 'package:ffi/ffi.dart' if (dart.library.html) 'package:wasm_ffi/ffi_utils.dart';
|
||||
// Only export our custom malloc on native platforms
|
||||
export 'malloc_native.dart' if (dart.library.io) 'malloc_native.dart';
|
||||
@ -1,87 +0,0 @@
|
||||
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'ffi_proxy.dart';
|
||||
|
||||
/// The contents of a native zero-terminated array of UTF-8 code units.
|
||||
///
|
||||
/// The Utf8 type itself has no functionality, it's only intended to be used
|
||||
/// through a `Pointer<Utf8>` representing the entire array. This pointer is
|
||||
/// the equivalent of a char pointer (`const char*`) in C code.
|
||||
final class Utf8 extends Opaque {}
|
||||
|
||||
/// Extension method for converting a`Pointer<Utf8>` to a [String].
|
||||
extension Utf8Pointer on Pointer<Utf8> {
|
||||
/// The number of UTF-8 code units in this zero-terminated UTF-8 string.
|
||||
///
|
||||
/// The UTF-8 code units of the strings are the non-zero code units up to the
|
||||
/// first zero code unit.
|
||||
int get length {
|
||||
_ensureNotNullptr('length');
|
||||
final codeUnits = cast<Uint8>();
|
||||
return _length(codeUnits);
|
||||
}
|
||||
|
||||
/// Converts this UTF-8 encoded string to a Dart string.
|
||||
///
|
||||
/// Decodes the UTF-8 code units of this zero-terminated byte array as
|
||||
/// Unicode code points and creates a Dart string containing those code
|
||||
/// points.
|
||||
///
|
||||
/// If [length] is provided, zero-termination is ignored and the result can
|
||||
/// contain NUL characters.
|
||||
///
|
||||
/// If [length] is not provided, the returned string is the string up til
|
||||
/// but not including the first NUL character.
|
||||
String toDartString({int? length}) {
|
||||
_ensureNotNullptr('toDartString');
|
||||
final codeUnits = cast<Uint8>();
|
||||
if (length != null) {
|
||||
RangeError.checkNotNegative(length, 'length');
|
||||
} else {
|
||||
length = _length(codeUnits);
|
||||
}
|
||||
return utf8.decode(codeUnits.asTypedList(length));
|
||||
}
|
||||
|
||||
static int _length(Pointer<Uint8> codeUnits) {
|
||||
var length = 0;
|
||||
while (codeUnits[length] != 0) {
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
void _ensureNotNullptr(String operation) {
|
||||
if (this == nullptr) {
|
||||
throw UnsupportedError("Operation '$operation' not allowed on a 'nullptr'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension method for converting a [String] to a `Pointer<Utf8>`.
|
||||
extension StringUtf8Pointer on String {
|
||||
/// Creates a zero-terminated [Utf8] code-unit array from this String.
|
||||
///
|
||||
/// If this [String] contains NUL characters, converting it back to a string
|
||||
/// using [Utf8Pointer.toDartString] will truncate the result if a length is
|
||||
/// not passed.
|
||||
///
|
||||
/// Unpaired surrogate code points in this [String] will be encoded as
|
||||
/// replacement characters (U+FFFD, encoded as the bytes 0xEF 0xBF 0xBD) in
|
||||
/// the UTF-8 encoded result. See [Utf8Encoder] for details on encoding.
|
||||
///
|
||||
/// Returns an [allocator]-allocated pointer to the result.
|
||||
Pointer<Utf8> toNativeUtf8({Allocator allocator = malloc}) {
|
||||
final units = utf8.encode(this);
|
||||
final Pointer<Uint8> result = allocator<Uint8>(units.length + 1);
|
||||
final Uint8List nativeString = result.asTypedList(units.length + 1);
|
||||
nativeString.setAll(0, units);
|
||||
nativeString[units.length] = 0;
|
||||
return result.cast();
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'curve_timeline1.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'animation.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'animation.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import '../native_array.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'atlas.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'format.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'bounding_box_attachment.dart';
|
||||
import 'clipping_attachment.dart';
|
||||
import 'mesh_attachment.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'slot_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'bone_local.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'inherit.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'bone_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'bone_timeline.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'color.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'color.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
import 'constraint_data.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
import 'constraint.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'curve_timeline.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'event_data.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'event.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'from_property.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'from_property.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'from_property.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'from_property.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'from_property.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'from_property.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'bone_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
|
||||
/// LinkedMesh wrapper
|
||||
abstract class LinkedMesh {
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'constraint_timeline1.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'constraint_timeline1.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'physics_constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'rtti.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'physics_constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'physics_constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'physics_constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'physics_constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'physics_constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'physics_constraint_timeline.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'attachment.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
|
||||
/// Posed wrapper
|
||||
abstract class Posed {
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'blend_mode.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'slot_curve_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'slot_curve_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'slot_curve_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'slot_curve_timeline.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'bone_timeline1.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'bone_timeline2.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'bone_timeline1.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'bone_timeline1.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'attachment.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'bone_timeline2.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'bone_timeline1.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'bone_timeline1.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'atlas.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'arrays.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'animation.dart';
|
||||
|
||||
@ -29,7 +29,8 @@
|
||||
|
||||
// AUTO GENERATED FILE, DO NOT EDIT.
|
||||
|
||||
import '../ffi_proxy.dart';
|
||||
import 'package:universal_ffi/ffi.dart';
|
||||
import 'package:universal_ffi/ffi_utils.dart';
|
||||
import 'spine_dart_bindings_generated.dart';
|
||||
import '../spine_bindings.dart';
|
||||
import 'atlas.dart';
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user