flutter3d
Showcase Changelog 38 packages API reference

Describing the scene to a screen reader: the source

since 0.7.0 Widgets and the rest

Regions the guide quotes: announce (line 42), project (line 52), overlay (line 70).

1/// The scene, as something a screen reader can walk: one accessibility node
2/// per object, positioned where the camera actually projects it.
3///
4/// Quoted by `scene_semantics.md` and shown whole in the Source tab.
5library;
6
7import 'package:flutter/widgets.dart' show Size, SizedBox;
8import 'package:flutter3d/flutter3d.dart';
9import 'package:flutter3d_app/flutter3d_app.dart';
10import 'package:flutter3d_showcase/src/demo/demo.dart';
11import 'package:vector_math/vector_math.dart';
13final class SceneSemanticsDemo extends ShowcaseDemo {
14 late final MeshNode _leftWheel;
15 late final MeshNode _rightWheel;
17 @override
18 Scene build(DemoContext context) {
19 final material = Material(
20 name: 'wheel',
21 baseColor: Vector4(0.3, 0.3, 0.3, 1.0),
22 );
23 _leftWheel = MeshNode(
24 DeviceMesh.upload(context.device, SphereShape(segments: 16).build()),
25 material,
26 name: 'left-wheel',
27 )..setPosition(-0.6, 0, 0);
28 _rightWheel = MeshNode(
29 DeviceMesh.upload(context.device, SphereShape(segments: 16).build()),
30 material,
31 name: 'right-wheel',
32 )..setPosition(0.6, 0, 0);
33 return Scene()
34 ..add(_leftWheel)
35 ..add(_rightWheel)
36 ..add(
37 LightNode(name: 'sun', intensity: 3.0)
38 ..setLocalForward(Vector3(-0.4, -1.0, -0.3)),
39 );
40 }
42 List<SceneAnnouncement> _announcements() => <SceneAnnouncement>[
43 SceneAnnouncement(id: 'left', label: 'left wheel', node: _leftWheel),
44 SceneAnnouncement(id: 'right', label: 'right wheel', node: _rightWheel),
45 ];
47 @override
48 void verify(Scene scene, FrameResult frame) {
49 if (frame.drawCalls < 1) {
50 throw StateError('the wheels were not drawn');
51 }
52 final camera = CameraNode()..setPosition(0, 0, 4);
53 final objects = semanticObjectsFor(
54 _announcements(),
55 camera: camera,
56 size: const Size(320, 180),
57 );
58 if (objects.length != 2) {
59 throw StateError('both wheels should project to a semantic object');
60 }
61 final left = objects.firstWhere((SemanticObject o) => o.id == 'left');
62 final right = objects.firstWhere((SemanticObject o) => o.id == 'right');
63 if (!(left.bounds.center.dx < right.bounds.center.dx)) {
64 throw StateError(
65 'the left wheel should project to the left of the '
66 'right one',
67 );
68 }
70 // The widget that publishes the objects to the platform. It is not
71 // pumped here, only built, since the claim above is about the numbers
72 // it would be given.
73 final overlay = SceneSemantics(
74 objects: objects,
75 child: const SizedBox.shrink(),
76 );
77 if (overlay.objects.length != 2 || !overlay.enabled) {
78 throw StateError(
79 'the overlay should carry both objects, enabled by '
80 'default',
81 );
82 }
83 }