1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 22:53:14 -04:00

Remove some slightly overengineered stuff

This commit is contained in:
lucasmerlin
2026-04-23 17:28:22 +02:00
parent e12b76365a
commit 2cb6b4b733
3 changed files with 15 additions and 55 deletions

View File

@@ -87,8 +87,6 @@ pub struct Harness<'a, State: 'static = ()> {
queued_events: EventQueue,
plugins: Vec<Box<dyn Plugin<State>>>,
pending_plugins: Vec<Box<dyn Plugin<State>>>,
in_dispatch: bool,
entry_location: Option<&'static std::panic::Location<'static>>,
consumed_event_locations: Vec<&'static std::panic::Location<'static>>,
last_accesskit_update: Option<egui::accesskit::TreeUpdate>,
@@ -181,8 +179,6 @@ impl<'a, State: 'static> Harness<'a, State> {
queued_events: Default::default(),
plugins,
pending_plugins: Vec::new(),
in_dispatch: false,
entry_location: None,
consumed_event_locations: Vec::new(),
last_accesskit_update: Some(initial_accesskit),
@@ -206,13 +202,12 @@ impl<'a, State: 'static> Harness<'a, State> {
/// Register a [`Plugin`] after construction.
///
/// 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>) {
let boxed: Box<dyn Plugin<State>> = Box::new(plugin);
if self.in_dispatch {
self.pending_plugins.push(boxed);
} else {
self.plugins.push(boxed);
}
self.plugins.push(Box::new(plugin));
}
/// 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.
///
/// Use this from inside a plugin hook when the plugin needs to drive additional
/// frames — e.g. an inspector plugin that blocks on user input and re-renders
/// after each injected event. Calling [`Self::step`] or [`Self::run`] from inside
/// a hook would recurse infinitely through that plugin's own `after_step`.
pub fn advance_frame(&mut self) {
/// This is useful for running steps within a plugin, without ending in an infinite loop where
/// the plugin is called again.
pub fn step_no_side_effects(&mut self) {
self._step_inner(false);
}
@@ -276,17 +269,13 @@ impl<'a, State: 'static> Harness<'a, State> {
return;
}
let mut plugins = std::mem::take(&mut self.plugins);
self.in_dispatch = true;
for p in &mut plugins {
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;
// Promote any plugins registered mid-dispatch to the end of the active list.
if !self.pending_plugins.is_empty() {
let pending = std::mem::take(&mut self.pending_plugins);
self.plugins.extend(pending);
}
self.plugins.extend(added);
}
/// 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.
#[track_caller]
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());
let events = std::mem::take(&mut *self.queued_events.lock());
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
/// hooks via [`Self::advance_frame`] without recursing.
/// hooks via [`Self::step_no_side_effects`] without recursing.
fn _step_inner(&mut self, sizing_pass: bool) {
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> {
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));
let mut steps = 0;

View File

@@ -34,10 +34,9 @@ use crate::{ExceededMaxStepsError, Harness};
/// # Re-entrancy
///
/// Plugin hooks receive `&mut Harness`. Calling [`Harness::step`] / [`Harness::run`] /
/// etc. from inside a hook is forbidden (it would recurse infinitely through your own
/// `after_step`) and is caught by a `debug_assert!`. If a plugin needs to advance the
/// harness from inside a hook — e.g. an inspector that blocks on user input — use
/// [`Harness::advance_frame`] instead.
/// etc. from inside a hook will recurse infinitely through your own `after_step`. If
/// a plugin needs to advance the harness from inside a hook — e.g. an inspector that
/// blocks on user input — use [`Harness::advance_frame`] instead.
#[expect(unused_variables, reason = "default no-op impls")]
pub trait Plugin<State = ()>: Send + Any {
/// Called once at the start of every `run()` / `try_run()` / `try_run_realtime()` /

View File

@@ -233,26 +233,6 @@ fn on_test_result_sees_panic() {
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.
#[cfg(feature = "snapshot")]
#[test]