mirror of
https://github.com/rive-app/rive-flutter.git
synced 2025-06-26 17:56:28 +08:00
Adding toc reading.
This commit is contained in:
@ -1,5 +1,11 @@
|
||||
import 'dart:collection';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:rive/src/core/field_types/core_color_type.dart';
|
||||
import 'package:rive/src/core/field_types/core_double_type.dart';
|
||||
import 'package:rive/src/core/field_types/core_field_type.dart';
|
||||
import 'package:rive/src/core/field_types/core_string_type.dart';
|
||||
import 'package:rive/src/core/field_types/core_uint_type.dart';
|
||||
import 'package:rive/src/rive_core/component.dart';
|
||||
import 'package:rive/src/rive_core/runtime/runtime_header.dart';
|
||||
import 'package:rive/src/rive_core/backboard.dart';
|
||||
@ -19,6 +25,8 @@ class RiveFile {
|
||||
Backboard _backboard;
|
||||
Backboard get backboard => _backboard;
|
||||
|
||||
final _propertyToField = HashMap<int, CoreFieldType>();
|
||||
|
||||
final List<Artboard> _artboards = [];
|
||||
List<Artboard> get artboards => _artboards;
|
||||
|
||||
@ -29,7 +37,37 @@ class RiveFile {
|
||||
var reader = BinaryReader(bytes);
|
||||
_header = RuntimeHeader.read(reader);
|
||||
|
||||
_backboard = readRuntimeObject<Backboard>(reader);
|
||||
// Read property fields toc.
|
||||
final indexToField = <CoreFieldType>[
|
||||
RiveCoreContext.uintType,
|
||||
RiveCoreContext.stringType,
|
||||
RiveCoreContext.doubleType,
|
||||
RiveCoreContext.colorType
|
||||
];
|
||||
|
||||
var propertyKeys = <int>[];
|
||||
for (int propertyKey = reader.readVarUint();
|
||||
propertyKey != 0;
|
||||
propertyKey = reader.readVarUint()) {
|
||||
propertyKeys.add(propertyKey);
|
||||
}
|
||||
int currentInt = 0;
|
||||
int currentBit = 8;
|
||||
for (final propertyKey in propertyKeys) {
|
||||
if (currentBit == 8) {
|
||||
currentInt = reader.readUint32();
|
||||
currentBit = 0;
|
||||
}
|
||||
int fieldIndex = (currentInt >> currentBit) & 3;
|
||||
if (fieldIndex < 0 || fieldIndex >= indexToField.length) {
|
||||
throw RiveFormatErrorException('unexpected field index $fieldIndex');
|
||||
}
|
||||
|
||||
_propertyToField[propertyKey] = indexToField[fieldIndex];
|
||||
currentBit += 2;
|
||||
}
|
||||
|
||||
_backboard = _readRuntimeObject<Backboard>(reader);
|
||||
if (_backboard == null) {
|
||||
throw const RiveFormatErrorException(
|
||||
'expected first object to be a Backboard');
|
||||
@ -42,7 +80,7 @@ class RiveFile {
|
||||
throw const RiveFormatErrorException(
|
||||
'artboards must contain at least one object (themselves)');
|
||||
}
|
||||
var artboard = readRuntimeObject(reader, RuntimeArtboard());
|
||||
var artboard = _readRuntimeObject(reader, RuntimeArtboard());
|
||||
// Kind of weird, but the artboard is the core context at runtime, so we
|
||||
// want other objects to be able to resolve it. It's always at the 0
|
||||
// index.
|
||||
@ -50,7 +88,7 @@ class RiveFile {
|
||||
_artboards.add(artboard);
|
||||
// var objects = List<Core<RiveCoreContext>>(numObjects);
|
||||
for (int i = 1; i < numObjects; i++) {
|
||||
Core<CoreContext> object = readRuntimeObject(reader);
|
||||
Core<CoreContext> object = _readRuntimeObject(reader);
|
||||
// N.B. we add objects that don't load (null) too as we need to look
|
||||
// them up by index.
|
||||
artboard.addObject(object);
|
||||
@ -60,7 +98,7 @@ class RiveFile {
|
||||
// in before the hierarchy resolves (batch add completes).
|
||||
var numAnimations = reader.readVarUint();
|
||||
for (int i = 0; i < numAnimations; i++) {
|
||||
var animation = readRuntimeObject<Animation>(reader);
|
||||
var animation = _readRuntimeObject<Animation>(reader);
|
||||
if (animation == null) {
|
||||
continue;
|
||||
}
|
||||
@ -70,7 +108,7 @@ class RiveFile {
|
||||
var numKeyedObjects = reader.readVarUint();
|
||||
var keyedObjects = List<KeyedObject>(numKeyedObjects);
|
||||
for (int j = 0; j < numKeyedObjects; j++) {
|
||||
var keyedObject = readRuntimeObject<KeyedObject>(reader);
|
||||
var keyedObject = _readRuntimeObject<KeyedObject>(reader);
|
||||
if (keyedObject == null) {
|
||||
continue;
|
||||
}
|
||||
@ -81,7 +119,7 @@ class RiveFile {
|
||||
|
||||
var numKeyedProperties = reader.readVarUint();
|
||||
for (int k = 0; k < numKeyedProperties; k++) {
|
||||
var keyedProperty = readRuntimeObject<KeyedProperty>(reader);
|
||||
var keyedProperty = _readRuntimeObject<KeyedProperty>(reader);
|
||||
if (keyedProperty == null) {
|
||||
continue;
|
||||
}
|
||||
@ -90,7 +128,7 @@ class RiveFile {
|
||||
|
||||
var numKeyframes = reader.readVarUint();
|
||||
for (int l = 0; l < numKeyframes; l++) {
|
||||
var keyframe = readRuntimeObject<KeyFrame>(reader);
|
||||
var keyframe = _readRuntimeObject<KeyFrame>(reader);
|
||||
if (keyframe == null) {
|
||||
continue;
|
||||
}
|
||||
@ -126,32 +164,38 @@ class RiveFile {
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
T readRuntimeObject<T extends Core<CoreContext>>(BinaryReader reader,
|
||||
[T instance]) {
|
||||
int coreObjectKey = reader.readVarUint();
|
||||
|
||||
var object = instance ?? RiveCoreContext.makeCoreInstance(coreObjectKey);
|
||||
if (object is! T) {
|
||||
return null;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int propertyKey = reader.readVarUint();
|
||||
if (propertyKey == 0) {
|
||||
// Terminator. https://media.giphy.com/media/7TtvTUMm9mp20/giphy.gif
|
||||
break;
|
||||
}
|
||||
|
||||
var fieldType = RiveCoreContext.coreType(propertyKey);
|
||||
if (fieldType == null) {
|
||||
void _skipProperty(BinaryReader reader, int propertyKey) {
|
||||
var field = _propertyToField[propertyKey];
|
||||
if (field == null) {
|
||||
throw UnsupportedError('Unsupported property key $propertyKey. '
|
||||
'A new runtime is likely necessary to play this file.');
|
||||
}
|
||||
|
||||
RiveCoreContext.setObjectProperty(
|
||||
object, propertyKey, fieldType.deserialize(reader));
|
||||
// Desrialize but don't do anything with the contents...
|
||||
field.deserialize(reader);
|
||||
}
|
||||
|
||||
T _readRuntimeObject<T extends Core<CoreContext>>(BinaryReader reader,
|
||||
[T instance]) {
|
||||
int coreObjectKey = reader.readVarUint();
|
||||
|
||||
var object = instance ?? RiveCoreContext.makeCoreInstance(coreObjectKey);
|
||||
|
||||
while (true) {
|
||||
int propertyKey = reader.readVarUint();
|
||||
if (propertyKey == 0) {
|
||||
// Terminator. https://media.giphy.com/media/7TtvTUMm9mp20/giphy.gif
|
||||
break;
|
||||
}
|
||||
|
||||
var fieldType = RiveCoreContext.coreType(propertyKey);
|
||||
if (fieldType == null || object == null) {
|
||||
_skipProperty(reader, propertyKey);
|
||||
} else if (object != null) {
|
||||
RiveCoreContext.setObjectProperty(
|
||||
object, propertyKey, fieldType.deserialize(reader));
|
||||
}
|
||||
}
|
||||
return object as T;
|
||||
}
|
||||
return object as T;
|
||||
}
|
||||
|
Reference in New Issue
Block a user