mirror of
https://github.com/emilk/egui.git
synced 2026-09-01 22:30:03 -04:00
Remove some slightly overengineered stuff
This commit is contained in:
@@ -87,8 +87,6 @@ pub struct Harness<'a, State: 'static = ()> {
|
|||||||
queued_events: EventQueue,
|
queued_events: EventQueue,
|
||||||
|
|
||||||
plugins: Vec<Box<dyn Plugin<State>>>,
|
plugins: Vec<Box<dyn Plugin<State>>>,
|
||||||
pending_plugins: Vec<Box<dyn Plugin<State>>>,
|
|
||||||
in_dispatch: bool,
|
|
||||||
entry_location: Option<&'static std::panic::Location<'static>>,
|
entry_location: Option<&'static std::panic::Location<'static>>,
|
||||||
consumed_event_locations: Vec<&'static std::panic::Location<'static>>,
|
consumed_event_locations: Vec<&'static std::panic::Location<'static>>,
|
||||||
last_accesskit_update: Option<egui::accesskit::TreeUpdate>,
|
last_accesskit_update: Option<egui::accesskit::TreeUpdate>,
|
||||||
@@ -181,8 +179,6 @@ impl<'a, State: 'static> Harness<'a, State> {
|
|||||||
queued_events: Default::default(),
|
queued_events: Default::default(),
|
||||||
|
|
||||||
plugins,
|
plugins,
|
||||||
pending_plugins: Vec::new(),
|
|
||||||
in_dispatch: false,
|
|
||||||
entry_location: None,
|
entry_location: None,
|
||||||
consumed_event_locations: Vec::new(),
|
consumed_event_locations: Vec::new(),
|
||||||
last_accesskit_update: Some(initial_accesskit),
|
last_accesskit_update: Some(initial_accesskit),
|
||||||
@@ -206,13 +202,12 @@ impl<'a, State: 'static> Harness<'a, State> {
|
|||||||
/// Register a [`Plugin`] after construction.
|
/// Register a [`Plugin`] after construction.
|
||||||
///
|
///
|
||||||
/// See [`HarnessBuilder::with_plugin`] to register before the first frame runs.
|
/// See [`HarnessBuilder::with_plugin`] to register before the first frame runs.
|
||||||
|
///
|
||||||
|
/// Calling this from inside a plugin hook is allowed — the new plugin is appended to
|
||||||
|
/// the list but does not receive the currently-dispatching hook; it starts firing on
|
||||||
|
/// the next dispatch.
|
||||||
pub fn add_plugin(&mut self, plugin: impl Plugin<State>) {
|
pub fn add_plugin(&mut self, plugin: impl Plugin<State>) {
|
||||||
let boxed: Box<dyn Plugin<State>> = Box::new(plugin);
|
self.plugins.push(Box::new(plugin));
|
||||||
if self.in_dispatch {
|
|
||||||
self.pending_plugins.push(boxed);
|
|
||||||
} else {
|
|
||||||
self.plugins.push(boxed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow a registered plugin by type. Returns the first plugin of the matching type
|
/// Borrow a registered plugin by type. Returns the first plugin of the matching type
|
||||||
@@ -246,11 +241,9 @@ impl<'a, State: 'static> Harness<'a, State> {
|
|||||||
|
|
||||||
/// Advance the harness by one frame without firing plugin hooks.
|
/// Advance the harness by one frame without firing plugin hooks.
|
||||||
///
|
///
|
||||||
/// Use this from inside a plugin hook when the plugin needs to drive additional
|
/// This is useful for running steps within a plugin, without ending in an infinite loop where
|
||||||
/// frames — e.g. an inspector plugin that blocks on user input and re-renders
|
/// the plugin is called again.
|
||||||
/// after each injected event. Calling [`Self::step`] or [`Self::run`] from inside
|
pub fn step_no_side_effects(&mut self) {
|
||||||
/// a hook would recurse infinitely through that plugin's own `after_step`.
|
|
||||||
pub fn advance_frame(&mut self) {
|
|
||||||
self._step_inner(false);
|
self._step_inner(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,17 +269,13 @@ impl<'a, State: 'static> Harness<'a, State> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut plugins = std::mem::take(&mut self.plugins);
|
let mut plugins = std::mem::take(&mut self.plugins);
|
||||||
self.in_dispatch = true;
|
|
||||||
for p in &mut plugins {
|
for p in &mut plugins {
|
||||||
f(p.as_mut(), self);
|
f(p.as_mut(), self);
|
||||||
}
|
}
|
||||||
self.in_dispatch = false;
|
// Handle the case where a plugin is registered within some other plugin
|
||||||
|
let added = std::mem::take(&mut self.plugins);
|
||||||
self.plugins = plugins;
|
self.plugins = plugins;
|
||||||
// Promote any plugins registered mid-dispatch to the end of the active list.
|
self.plugins.extend(added);
|
||||||
if !self.pending_plugins.is_empty() {
|
|
||||||
let pending = std::mem::take(&mut self.pending_plugins);
|
|
||||||
self.plugins.extend(pending);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new Harness with the given ui closure and a state.
|
/// Create a new Harness with the given ui closure and a state.
|
||||||
@@ -346,10 +335,6 @@ impl<'a, State: 'static> Harness<'a, State> {
|
|||||||
/// update the Harness.
|
/// update the Harness.
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn step(&mut self) {
|
pub fn step(&mut self) {
|
||||||
debug_assert!(
|
|
||||||
!self.in_dispatch,
|
|
||||||
"Harness::step called from inside a plugin hook — use Harness::advance_frame instead to avoid infinite recursion"
|
|
||||||
);
|
|
||||||
self.entry_location = Some(std::panic::Location::caller());
|
self.entry_location = Some(std::panic::Location::caller());
|
||||||
let events = std::mem::take(&mut *self.queued_events.lock());
|
let events = std::mem::take(&mut *self.queued_events.lock());
|
||||||
if events.is_empty() {
|
if events.is_empty() {
|
||||||
@@ -381,7 +366,7 @@ impl<'a, State: 'static> Harness<'a, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Core frame advance. Does NOT fire plugin hooks — callable from within
|
/// Core frame advance. Does NOT fire plugin hooks — callable from within
|
||||||
/// hooks via [`Self::advance_frame`] without recursing.
|
/// hooks via [`Self::step_no_side_effects`] without recursing.
|
||||||
fn _step_inner(&mut self, sizing_pass: bool) {
|
fn _step_inner(&mut self, sizing_pass: bool) {
|
||||||
self.input.predicted_dt = self.step_dt;
|
self.input.predicted_dt = self.step_dt;
|
||||||
|
|
||||||
@@ -461,10 +446,6 @@ impl<'a, State: 'static> Harness<'a, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn _try_run(&mut self, sleep: bool) -> Result<u64, ExceededMaxStepsError> {
|
fn _try_run(&mut self, sleep: bool) -> Result<u64, ExceededMaxStepsError> {
|
||||||
debug_assert!(
|
|
||||||
!self.in_dispatch,
|
|
||||||
"Harness::run / Harness::try_run called from inside a plugin hook — use Harness::advance_frame instead to avoid infinite recursion"
|
|
||||||
);
|
|
||||||
self.dispatch(|p, h| p.before_run(h));
|
self.dispatch(|p, h| p.before_run(h));
|
||||||
|
|
||||||
let mut steps = 0;
|
let mut steps = 0;
|
||||||
|
|||||||
@@ -34,10 +34,9 @@ use crate::{ExceededMaxStepsError, Harness};
|
|||||||
/// # Re-entrancy
|
/// # Re-entrancy
|
||||||
///
|
///
|
||||||
/// Plugin hooks receive `&mut Harness`. Calling [`Harness::step`] / [`Harness::run`] /
|
/// Plugin hooks receive `&mut Harness`. Calling [`Harness::step`] / [`Harness::run`] /
|
||||||
/// etc. from inside a hook is forbidden (it would recurse infinitely through your own
|
/// etc. from inside a hook will recurse infinitely through your own `after_step`. If
|
||||||
/// `after_step`) and is caught by a `debug_assert!`. If a plugin needs to advance the
|
/// a plugin needs to advance the harness from inside a hook — e.g. an inspector that
|
||||||
/// harness from inside a hook — e.g. an inspector that blocks on user input — use
|
/// blocks on user input — use [`Harness::advance_frame`] instead.
|
||||||
/// [`Harness::advance_frame`] instead.
|
|
||||||
#[expect(unused_variables, reason = "default no-op impls")]
|
#[expect(unused_variables, reason = "default no-op impls")]
|
||||||
pub trait Plugin<State = ()>: Send + Any {
|
pub trait Plugin<State = ()>: Send + Any {
|
||||||
/// Called once at the start of every `run()` / `try_run()` / `try_run_realtime()` /
|
/// Called once at the start of every `run()` / `try_run()` / `try_run_realtime()` /
|
||||||
|
|||||||
@@ -233,26 +233,6 @@ fn on_test_result_sees_panic() {
|
|||||||
assert_eq!(last, Some("on_test_result:fail"), "log = {log:?}");
|
assert_eq!(last, Some("on_test_result:fail"), "log = {log:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calling `Harness::step` from inside a plugin hook should panic in debug builds
|
|
||||||
/// (the `in_dispatch` guard).
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
#[test]
|
|
||||||
#[should_panic(expected = "inside a plugin hook")]
|
|
||||||
fn reentrant_step_panics_in_debug() {
|
|
||||||
struct Misbehaver;
|
|
||||||
impl<S: 'static> Plugin<S> for Misbehaver {
|
|
||||||
fn after_step(&mut self, h: &mut Harness<'_, S>) {
|
|
||||||
// Forbidden: step from inside a hook.
|
|
||||||
h.step();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut harness = Harness::builder().with_plugin(Misbehaver).build_ui(|ui| {
|
|
||||||
ui.label("hi");
|
|
||||||
});
|
|
||||||
harness.step();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `on_snapshot` fires with an Err result for a missing snapshot.
|
/// `on_snapshot` fires with an Err result for a missing snapshot.
|
||||||
#[cfg(feature = "snapshot")]
|
#[cfg(feature = "snapshot")]
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user