use std::marker::PhantomData;
use bevy_asset::{AssetEvent, Assets};
use bevy_ecs::change_detection::{DetectChanges, Ref};
use bevy_ecs::component::Component;
use bevy_ecs::message::MessageReader;
use bevy_ecs::system::{Query, Res};
use crate::asset::{BrinkProgram, LineTablesAsset, ProgramAsset};
use crate::flow::BrinkFlow;
use crate::line_tables::BrinkLocale;
#[derive(Component)]
pub struct BrinkTranscript<M: Send + Sync + 'static = ()> {
pub lines: Vec<(String, Vec<String>)>,
cached_len: usize,
_marker: PhantomData<fn() -> M>,
}
impl<M: Send + Sync + 'static> Default for BrinkTranscript<M> {
fn default() -> Self {
Self {
lines: Vec::new(),
cached_len: 0,
_marker: PhantomData,
}
}
}
impl<M: Send + Sync + 'static> BrinkTranscript<M> {
#[must_use]
pub fn text(&self) -> String {
let n = self.lines.len();
let total: usize = self.lines.iter().map(|(s, _)| s.len()).sum();
let mut out = String::with_capacity(total + n.saturating_sub(1));
for (i, (text, _)) in self.lines.iter().enumerate() {
if i > 0 {
out.push('\n');
}
out.push_str(text);
}
out
}
}
#[expect(
clippy::needless_pass_by_value,
clippy::type_complexity,
reason = "bevy systems take Res/Query by value and have complex query tuples"
)]
pub fn refresh_transcripts<M: Send + Sync + 'static>(
mut events: MessageReader<AssetEvent<LineTablesAsset>>,
mut flows: Query<(
&BrinkFlow<M>,
&BrinkProgram<M>,
Ref<BrinkLocale<M>>,
&mut BrinkTranscript<M>,
)>,
programs: Res<Assets<ProgramAsset>>,
line_tables: Res<Assets<LineTablesAsset>>,
) {
let any_locale_modified = events
.read()
.any(|ev| matches!(ev, AssetEvent::Modified { .. }));
for (flow, program_h, locale_h, mut transcript) in &mut flows {
let current_len = flow.inner.transcript_len();
let locale_changed = locale_h.is_changed();
let needs_refresh =
current_len != transcript.cached_len || locale_changed || any_locale_modified;
if !needs_refresh {
continue;
}
let Some(program_asset) = programs.get(&program_h.handle) else {
continue;
};
let Some(lt_asset) = line_tables.get(&locale_h.handle) else {
continue;
};
transcript.lines = brink_runtime::transcript::render_transcript(
flow.inner.transcript(),
&program_asset.program,
<_asset.tables,
None,
flow.inner.fragments(),
);
transcript.cached_len = current_len;
}
}