motionFromJson function
MotionDocument
motionFromJson(
- Map<
String, Object?> json, { - required String sceneClassName,
- required SceneDocument scene,
The inverse of MotionDocumentJson.toJson.
scene is required because a group holds the NODE it animates, and JSON
can only carry the name — so this is the one place a name becomes a node
again, and it is a read of something the editor wrote.
Implementation
MotionDocument motionFromJson(
Map<String, Object?> json, {
required String sceneClassName,
required SceneDocument scene,
}) {
var doc = MotionDocument(sceneClassName: sceneClassName);
for (var raw in (json['params'] as List? ?? const [])) {
var p = (raw as Map).cast<String, Object?>();
var kind = SceneParamKind.values.byName(p['kind']! as String);
doc.params.add(
SceneParamDecl(
p['name']! as String,
kind,
_paramValue(kind, p['default']),
),
);
}
for (var raw in (json['groups'] as List? ?? const [])) {
var g = (raw as Map).cast<String, Object?>();
var target = g['target']! as String;
var node = scene.nodeNamed(target);
if (node == null) {
throw ArgumentError(
'the motion animates "$target", which this scene does not declare',
);
}
var group = AnimateGroup(node, name: g['name']! as String);
for (var e in ((g['tracks'] as Map?) ?? const {}).entries) {
group.tracks['${e.key}'] = _trackFromJson(
(e.value as Map).cast<String, Object?>(),
);
}
// A payload written before the maps became one carried the argument
// tracks under their bare names in a map of their own.
for (var e in ((g['args'] as Map?) ?? const {}).entries) {
group.tracks['$sceneArgsPrefix${e.key}'] = _trackFromJson(
(e.value as Map).cast<String, Object?>(),
);
}
doc.groups.add(group);
}
doc.timeline = _exprFromJson(
(json['timeline']! as Map).cast<String, Object?>(),
doc,
);
return doc;
}