Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 84a73d9

Browse files
authored
[Impeller Scene] Add SceneNodeValue for synchronously fetching loaded ipscenes (#38913)
1 parent eb18ac0 commit 84a73d9

File tree

1 file changed

+57
-10
lines changed

1 file changed

+57
-10
lines changed

lib/ui/experiments/scene.dart

+57-10
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ class SceneNode extends NativeFieldWrapperClass1 {
1717
/// The asset must be a file produced as the output of the `scenec` importer.
1818
/// The constructed object should then be reused via the [shader]
1919
/// method to create [Shader] objects that can be used by [Shader.paint].
20-
static Future<SceneNode> fromAsset(String assetKey) {
20+
static SceneNodeValue fromAsset(String assetKey) {
2121
// The flutter tool converts all asset keys with spaces into URI
2222
// encoded paths (replacing ' ' with '%20', for example). We perform
2323
// the same encoding here so that users can load assets with the same
2424
// key they have written in the pubspec.
2525
final String encodedKey = Uri(path: Uri.encodeFull(assetKey)).path;
2626
{
27-
final Future<SceneNode>? futureSceneNode = _ipsceneRegistry[encodedKey]?.target;
27+
final SceneNodeValue? futureSceneNode = _ipsceneRegistry[encodedKey]?.target;
2828
if (futureSceneNode != null) {
2929
return futureSceneNode;
3030
}
@@ -45,14 +45,15 @@ class SceneNode extends NativeFieldWrapperClass1 {
4545
return null;
4646
}).then((_) => sceneNode);
4747

48-
_ipsceneRegistry[encodedKey] = WeakReference<Future<SceneNode>>(futureSceneNode);
49-
return futureSceneNode;
48+
final SceneNodeValue result = SceneNodeValue.fromFuture(futureSceneNode);
49+
_ipsceneRegistry[encodedKey] = WeakReference<SceneNodeValue>(result);
50+
return result;
5051
}
5152

52-
static SceneNode fromTransform(Float64List matrix4) {
53+
static SceneNodeValue fromTransform(Float64List matrix4) {
5354
final SceneNode sceneNode = SceneNode._create();
5455
sceneNode._initFromTransform(matrix4);
55-
return sceneNode;
56+
return SceneNodeValue.fromValue(sceneNode);
5657
}
5758

5859
void addChild(SceneNode sceneNode) {
@@ -75,11 +76,11 @@ class SceneNode extends NativeFieldWrapperClass1 {
7576
// SceneNode.fromAsset. It holds weak references to the SceneNodes so that the
7677
// case where an in-use ipscene is requested again can be fast, but scenes
7778
// that are no longer referenced are not retained because of the cache.
78-
static final Map<String, WeakReference<Future<SceneNode>>> _ipsceneRegistry =
79-
<String, WeakReference<Future<SceneNode>>>{};
79+
static final Map<String, WeakReference<SceneNodeValue>> _ipsceneRegistry =
80+
<String, WeakReference<SceneNodeValue>>{};
8081

8182
static Future<void> _reinitializeScene(String assetKey) async {
82-
final WeakReference<Future<SceneNode>>? sceneRef = _ipsceneRegistry == null
83+
final WeakReference<SceneNodeValue>? sceneRef = _ipsceneRegistry == null
8384
? null
8485
: _ipsceneRegistry[assetKey];
8586

@@ -89,7 +90,7 @@ class SceneNode extends NativeFieldWrapperClass1 {
8990
return;
9091
}
9192

92-
final Future<SceneNode>? sceneNodeFuture = sceneRef.target;
93+
final Future<SceneNode>? sceneNodeFuture = sceneRef.target?.future;
9394
if (sceneNodeFuture == null) {
9495
return;
9596
}
@@ -129,6 +130,52 @@ class SceneNode extends NativeFieldWrapperClass1 {
129130
SceneShader sceneShader() => SceneShader._(this, debugName: _debugName);
130131
}
131132

133+
class SceneNodeValue {
134+
SceneNodeValue._(this._future, this._value) {
135+
_future?.then((SceneNode result) => _value = result);
136+
}
137+
138+
static SceneNodeValue fromFuture(Future<SceneNode> future) {
139+
return SceneNodeValue._(future, null);
140+
}
141+
142+
static SceneNodeValue fromValue(SceneNode value) {
143+
return SceneNodeValue._(null, value);
144+
}
145+
146+
final Future<SceneNode>? _future;
147+
SceneNode? _value;
148+
149+
bool get isComplete {
150+
return _value != null;
151+
}
152+
153+
Future<SceneNode>? get future {
154+
return _future;
155+
}
156+
157+
SceneNode? get value {
158+
return _value;
159+
}
160+
161+
/// Calls `callback` when the `SceneNode` has finished initializing. If the
162+
/// initialization is already finished, `callback` is called synchronously.
163+
SceneNodeValue whenComplete(void Function(SceneNode) callback) {
164+
if (_value == null && _future == null) {
165+
return this;
166+
}
167+
168+
if (_value != null) {
169+
callback(_value!);
170+
return this;
171+
}
172+
173+
// _future != null
174+
_future!.then((SceneNode node) => callback(node));
175+
return this;
176+
}
177+
}
178+
132179
/// A [Shader] generated from a [SceneNode].
133180
///
134181
/// Instances of this class can be obtained from the

0 commit comments

Comments
 (0)