1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
//! Turnkey rebind propagation for third-party materials that sample a headless
//! webview's texture (see `WebviewTextureTarget`).
//!
//! Base contract (no trait needed): when the injected GPU texture for a
//! `WebviewTextureTarget` is (re)created — first frame, resize, handle swap —
//! bevy_cef touches the target `Image` asset, firing
//! `AssetEvent::Modified { id }`. A consumer that manages its own material can
//! listen for that event and `get_mut` its material asset to rebuild the bind
//! group:
//!
//! ```ignore
//! fn rebuild_on_webview_rebind(
//! mut events: MessageReader<AssetEvent<Image>>,
//! mut materials: ResMut<Assets<MyMaterial>>,
//! my: Res<MyHandles>, // your own bookkeeping: target id + material handle
//! ) {
//! for event in events.read() {
//! if let AssetEvent::Modified { id } = event
//! && *id == my.target.id()
//! {
//! let _ = materials.get_mut(&my.material);
//! }
//! }
//! }
//! ```
//!
//! Ordering caveat for the manual path: the rebind image-touch ALSO makes
//! `prepare_assets::<GpuImage>` re-upload the CPU placeholder that same frame
//! (the `Modified` event is shared). A material bind group rebuilt that frame
//! must therefore be prepared AFTER bevy_cef's GPU injection, or it can
//! capture the placeholder instead of the webview texture — and stay black
//! forever, because nothing rebuilds it once the rebind window closes.
//! [`WebviewTargetUiMaterialPlugin`] configures that ordering automatically;
//! manual consumers must order [`WebviewGpuImageInjectSet`] before their
//! material's `prepare_assets` in the `Render` schedule (see the set's docs).
//!
//! This module is compiled on every platform so downstream crates never need
//! `#[cfg]`; on non-macOS the plugin registers nothing (the headless texture
//! path is macOS-only).
use AssetId;
use *;
use PhantomData;
/// Render-world system set containing bevy_cef's webview GPU texture injection
/// (`RenderSystems::PrepareAssets` phase; populated on macOS only).
///
/// A material that samples a `WebviewTextureTarget` image must build its bind
/// group AFTER this set: on rebind frames the image-touch re-uploads the CPU
/// placeholder, and an unordered rebuild can land between that re-upload and
/// the injection, capturing the placeholder permanently.
/// [`WebviewTargetUiMaterialPlugin`] adds the required edge automatically;
/// manual consumers do:
///
/// ```ignore
/// use bevy::render::{Render, RenderApp, render_asset::prepare_assets};
/// use bevy::ui_render::PreparedUiMaterial;
///
/// render_app.configure_sets(
/// Render,
/// WebviewGpuImageInjectSet.before(prepare_assets::<PreparedUiMaterial<MyMaterial>>),
/// );
/// ```
;
/// Tells bevy_cef which webview texture targets an asset references, so
/// [`WebviewTargetUiMaterialPlugin`] can rebuild its bind group on rebind
/// frames.
///
/// Bounded on [`Asset`] (not a material trait): the mechanism — "touch the
/// asset so its own `Modified` event re-prepares it" — is identical for every
/// material kind, so future `Material` / `Material2d` plugin variants reuse
/// this same trait.
/// Registers rebind propagation for a third-party [`UiMaterial`] sampling a
/// headless webview texture: on rebind frames, every `M` asset whose
/// [`WebviewTextureSlot::webview_targets`] contains a rebinding target id is
/// touched, so Bevy rebuilds its bind group against the freshly injected
/// texture (instead of sampling the stale placeholder forever).
///
/// Add your own `UiMaterialPlugin::<M>` as usual — this plugin only adds the
/// rebind system and may be combined with any number of material types.
;