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
//! Ink → engine external-function bindings (synchronous kinds).
//!
//! When an ink story calls an `EXTERNAL` function, the runtime asks an
//! [`ExternalFnHandler`] how to resolve it. This module provides a
//! registry-backed handler ([`BrinkHandler`]) plus app-level registration
//! verbs for the two *synchronous* binding kinds:
//!
//! - **`bind_brink_fn`** — a pure function `Fn(&[Value]) -> impl Into<Value>`.
//! No World access; resolved inline while the VM steps. Use for math,
//! formatting, table lookups against captured data.
//! - **`bind_brink_command`** — fire-and-forget: parse the ink args into a
//! Bevy [`Event`] and trigger it. The event is *buffered* during stepping
//! (the handler can't touch the World mid-step) and flushed afterward —
//! via [`BrinkHandler::flush`] on the normal playback path, or fired
//! directly against the World once the call completes when reached
//! through [`call_ink_function`]'s exclusive-`&mut World` driver (issue
//! #1096: this used to fall through to the in-story fallback silently).
//! Optionally returns a value to ink via [`BrinkCommand::reply`].
//!
//! plus a third, *world-access* kind used by engine→ink calls:
//!
//! - **`bind_brink_query`** — a Bevy system with arbitrary `SystemParam`s
//! that reads the World and returns a [`Value`]. It can't run inline
//! while the VM steps, so [`call_ink_function`] (an exclusive-`&mut World`
//! driver) runs it via `run_system_with` between evaluation suspensions —
//! letting an ink function called from the engine query anything in the
//! World, with no upfront declaration.
//!
//! ## Wiring it up
//!
//! ```no_run
//! # use bevy_app::App;
//! # use bevy_ecs::event::Event;
//! # use bevy_brink::{BrinkBindingsAppExt, BrinkCommand, Value};
//! # #[derive(Event, Clone, BrinkCommand)]
//! # struct PlaySound { name: String, volume: f32 }
//! # let mut app = App::new();
//! app.bind_brink_fn::<(), _, _>("clamp01", |args| {
//! args.first().and_then(Value::as_float).unwrap_or(0.0).clamp(0.0, 1.0)
//! });
//! app.bind_brink_command::<(), PlaySound>("play_sound");
//! ```
//!
//! Then, in the system that drives flows, build a handler from the
//! registry, step the flow with it, and flush:
//!
//! ```no_run
//! # use bevy_ecs::entity::Entity;
//! # use bevy_ecs::system::{Commands, ResMut};
//! # use bevy_brink::{BrinkBindings, BrinkContext, BrinkFlow, BrinkGlobals, Program, RuntimeError};
//! # use brink_format::LineEntry;
//! # fn example(
//! # bindings: &BrinkBindings,
//! # flow: &mut BrinkFlow,
//! # mut globals: ResMut<BrinkGlobals>,
//! # mut ctx: BrinkContext,
//! # program: &Program,
//! # tables: &[Vec<LineEntry>],
//! # entity: Entity,
//! # mut commands: Commands,
//! # ) -> Result<(), RuntimeError> {
//! let handler = bindings.handler();
//! let mut view = bevy_brink::flow_context_view(&mut globals, &mut ctx);
//! let line = flow.step_one(program, tables, &mut view, &handler, entity, &mut commands)?;
//! handler.flush(&mut commands);
//! # let _ = line;
//! # Ok(())
//! # }
//! ```
//!
//! ## Module layout
//!
//! Split per issue #684 into two responsibilities: [`registration`] is *how
//! engine code registers callable bindings* ([`BrinkBindings`],
//! [`BrinkHandler`], [`BrinkBindingsAppExt`]); [`drive`] is *how the engine
//! drives ink execution and resolves externals* ([`call_ink_function`],
//! [`advance_flow`], [`resolve_pending_externals`]). Both are re-exported
//! here so `bevy_brink::bindings::*` paths (and the crate-root re-exports in
//! `lib.rs`) stay stable regardless of which file an item lives in.
pub use ;
pub use TriggerFn;
pub use ;