diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..339a774
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,5 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..df87cf9
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index 88f3db6..c83d27d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,19 +23,21 @@ builtin-parser = ["dep:logos"]
[dependencies]
# This crate by itself doesn't use any bevy features, but `bevy_egui` (dep) uses "bevy_asset".
-bevy = { version = "0.14.0", default-features = false, features = [] }
-bevy_egui = "0.28.0"
+bevy = { version = "0.16.0", default-features = false, features = ["bevy_log", "bevy_color"] }
+bevy_reflect = "0.16.0"
+bevy_egui = "0.34.1"
chrono = "0.4.31"
tracing-log = "0.2.0"
tracing-subscriber = "0.3.18"
web-time = "1.0.0"
+winit = "0.30.5"
# builtin-parser features
logos = { version = "0.14.0", optional = true }
fuzzy-matcher = { version = "0.3.7", optional = true }
[dev-dependencies]
-bevy = "0.14.0"
+bevy = "0.16.0"
[lints]
clippy.useless_format = "allow"
diff --git a/src/builtin_parser/runner.rs b/src/builtin_parser/runner.rs
index 1146605..f53fcfc 100644
--- a/src/builtin_parser/runner.rs
+++ b/src/builtin_parser/runner.rs
@@ -8,8 +8,6 @@ use bevy::reflect::{
DynamicEnum, DynamicTuple, ReflectMut, TypeInfo, TypeRegistration, VariantInfo,
};
-use crate::ui::COMMAND_RESULT_NAME;
-
use self::error::EvalError;
use self::member::{eval_member_expression, eval_path, Path};
use self::reflection::{object_to_dynamic_struct, CreateRegistration, IntoResource};
@@ -142,7 +140,7 @@ pub fn run(ast: Ast, world: &mut World) -> Result<(), ExecutionError> {
value => {
let value = value.try_format(span, world, ®istrations)?;
- info!(name: COMMAND_RESULT_NAME, "{}{value}", crate::ui::COMMAND_RESULT_PREFIX);
+ info!(name: crate::ui::COMMAND_RESULT_NAME, "{}{value}", crate::ui::COMMAND_RESULT_PREFIX);
}
}
}
@@ -332,7 +330,11 @@ fn eval_expression(
}?;
dynamic_tuple.insert_boxed(
- element.value.into_inner().reflect(element.span, ty)?,
+ element
+ .value
+ .into_inner()
+ .reflect(element.span, ty)?
+ .into_partial_reflect(),
);
}
@@ -369,13 +371,9 @@ fn eval_expression(
.reflect_path_mut(resource.path.as_str())
.unwrap();
- reflect.set(value_reflect).map_err(|value_reflect| {
- EvalError::IncompatibleReflectTypes {
- span,
- expected: reflect.reflect_type_path().to_string(),
- actual: value_reflect.reflect_type_path().to_string(),
- }
- })?;
+ reflect
+ .try_apply(value_reflect.as_partial_reflect())
+ .map_err(|apply_error| EvalError::ApplyError { apply_error, span })?;
}
}
@@ -441,7 +439,6 @@ fn eval_expression(
)?;
Ok(Value::StructTuple { name, tuple })
}
-
Expression::BinaryOp {
left,
operator,
diff --git a/src/builtin_parser/runner/environment.rs b/src/builtin_parser/runner/environment.rs
index b30d345..32bf463 100644
--- a/src/builtin_parser/runner/environment.rs
+++ b/src/builtin_parser/runner/environment.rs
@@ -5,7 +5,7 @@ use std::fmt::Debug;
use crate::builtin_parser::SpanExtension;
use bevy::ecs::world::World;
-use bevy::log::warn;
+use bevy::prelude::*;
use bevy::reflect::TypeRegistration;
use logos::Span;
diff --git a/src/builtin_parser/runner/error.rs b/src/builtin_parser/runner/error.rs
index 6892de4..b3cafc3 100644
--- a/src/builtin_parser/runner/error.rs
+++ b/src/builtin_parser/runner/error.rs
@@ -1,5 +1,6 @@
use std::borrow::Cow;
+use bevy::reflect::ApplyError;
use logos::Span;
use crate::builtin_parser::number::Number;
@@ -75,6 +76,10 @@ pub enum EvalError {
field_index: usize,
tuple_size: usize,
},
+ ApplyError {
+ apply_error: ApplyError,
+ span: Span,
+ },
}
impl EvalError {
@@ -106,6 +111,7 @@ impl EvalError {
E::InvalidOperation { span, .. } => vec![span.clone()],
E::IncorrectAccessOperation { span, .. } => vec![span.clone()],
E::FieldNotFoundInTuple { span, .. } => vec![span.clone()],
+ E::ApplyError { span, .. } => vec![span.clone()],
}
}
/// Returns all the hints for this error.
@@ -232,6 +238,15 @@ impl std::fmt::Display for EvalError {
f,
"Field {field_index} is out of bounds for tuple of size {tuple_size}"
),
+ E::ApplyError {
+ apply_error,
+ span: _,
+ } => {
+ write!(
+ f,
+ "Error while applying value (todo make this error better): {apply_error}"
+ )
+ }
}
}
}
diff --git a/src/builtin_parser/runner/reflection.rs b/src/builtin_parser/runner/reflection.rs
index 2114f5d..f8bd2e1 100644
--- a/src/builtin_parser/runner/reflection.rs
+++ b/src/builtin_parser/runner/reflection.rs
@@ -46,15 +46,16 @@ impl IntoResource {
}
pub fn object_to_dynamic_struct(
- hashmap: HashMap,
+ _hashmap: HashMap,
) -> Result {
- let mut dynamic_struct = DynamicStruct::default();
+ todo!()
+ // let mut dynamic_struct = DynamicStruct::default();
- for (key, (value, span, reflect)) in hashmap {
- dynamic_struct.insert_boxed(&key, value.reflect(span, reflect)?);
- }
+ // for (key, (value, span, reflect)) in hashmap {
+ // dynamic_struct.insert_boxed(&key, value.reflect(span, reflect)?);
+ // }
- Ok(dynamic_struct)
+ // Ok(dynamic_struct)
}
pub fn mut_dyn_reflect<'a>(
diff --git a/src/builtin_parser/runner/stdlib.rs b/src/builtin_parser/runner/stdlib.rs
index 938df3b..0561f25 100644
--- a/src/builtin_parser/runner/stdlib.rs
+++ b/src/builtin_parser/runner/stdlib.rs
@@ -1,7 +1,7 @@
use crate::builtin_parser::runner::environment::Variable;
use crate::register;
use bevy::ecs::world::World;
-use bevy::log::info;
+use bevy::prelude::*;
use bevy::reflect::TypeRegistration;
use std::cell::Ref;
use std::ops::Range;
diff --git a/src/builtin_parser/runner/unique_rc.rs b/src/builtin_parser/runner/unique_rc.rs
index f4e5c29..1b5f016 100644
--- a/src/builtin_parser/runner/unique_rc.rs
+++ b/src/builtin_parser/runner/unique_rc.rs
@@ -46,7 +46,7 @@ impl UniqueRc {
.into_inner()
}
}
-impl Clone for UniqueRc {
+impl Clone for UniqueRc {
fn clone(&self) -> Self {
let t = self.borrow_inner().clone().into_inner();
diff --git a/src/builtin_parser/runner/value.rs b/src/builtin_parser/runner/value.rs
index 711ed3a..ac1487c 100644
--- a/src/builtin_parser/runner/value.rs
+++ b/src/builtin_parser/runner/value.rs
@@ -12,7 +12,7 @@ use super::unique_rc::WeakRef;
use bevy::ecs::world::World;
use bevy::reflect::{
- DynamicStruct, DynamicTuple, GetPath, Reflect, ReflectRef, TypeInfo, TypeRegistration,
+ DynamicStruct, DynamicTuple, GetPath, PartialReflect, ReflectRef, TypeInfo, TypeRegistration,
VariantInfo, VariantType,
};
@@ -61,13 +61,15 @@ pub enum Value {
}
impl Value {
- /// Converts this value into a [`Box`].
+ /// Converts this value into a [`Box`].
///
/// `ty` is used for type inference.
- pub fn reflect(self, span: Span, ty: &str) -> Result, EvalError> {
+ pub fn reflect(self, span: Span, ty: &str) -> Result, EvalError> {
match self {
Value::None => Ok(Box::new(())),
- Value::Number(number) => number.reflect(span, ty),
+ Value::Number(number) => number
+ .reflect(span, ty)
+ .map(PartialReflect::into_partial_reflect),
Value::Boolean(boolean) => Ok(Box::new(boolean)),
Value::String(string) => Ok(Box::new(string)),
Value::Reference(_reference) => Err(EvalError::CannotReflectReference(span)),
@@ -245,7 +247,7 @@ fn fancy_debug_print(
let reflect = dyn_reflect.reflect_path(resource.path.as_str()).unwrap();
- fn debug_subprint(reflect: &dyn Reflect, indentation: usize) -> String {
+ fn debug_subprint(reflect: &dyn PartialReflect, indentation: usize) -> String {
let mut f = String::new();
let reflect_ref = reflect.reflect_ref();
let indentation_string = TAB.repeat(indentation);
@@ -311,9 +313,10 @@ fn fancy_debug_print(
VariantType::Unit => {}
}
}
- ReflectRef::Value(_) => {
+ ReflectRef::Opaque(_) => {
f += &format!("{reflect:?}");
}
+ ReflectRef::Set(_) => todo!(),
}
f
@@ -343,6 +346,7 @@ fn fancy_debug_print(
ReflectRef::List(_) => todo!(),
ReflectRef::Array(_) => todo!(),
ReflectRef::Map(_) => todo!(),
+ ReflectRef::Set(_) => todo!(),
ReflectRef::Enum(set_variant_info) => {
// Print out the enum types
f += &format!("enum {} {{\n", set_variant_info.reflect_short_type_path());
@@ -401,7 +405,7 @@ fn fancy_debug_print(
VariantType::Unit => {}
}
}
- ReflectRef::Value(value) => {
+ ReflectRef::Opaque(value) => {
f += &format!("{value:?}");
}
}
diff --git a/src/command.rs b/src/command.rs
index 8ab6fa4..a3f0bd5 100644
--- a/src/command.rs
+++ b/src/command.rs
@@ -3,7 +3,6 @@
use std::borrow::Cow;
use std::ops::Range;
-use bevy::ecs::world::Command;
use bevy::prelude::*;
/// The command parser currently being used by the dev console.
@@ -168,6 +167,7 @@ impl Command for ExecuteCommand {
}
}
+#[allow(missing_docs)]
#[derive(Resource, Default, Deref, DerefMut)]
#[cfg(feature = "completions")]
pub struct AutoCompletions(pub(crate) Vec);
diff --git a/src/lib.rs b/src/lib.rs
index 46fb4cb..78f1c23 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -21,7 +21,9 @@ pub struct DevConsolePlugin;
impl Plugin for DevConsolePlugin {
fn build(&self, app: &mut App) {
if !app.is_plugin_added::() {
- app.add_plugins(EguiPlugin);
+ app.add_plugins(EguiPlugin {
+ enable_multipass_for_primary_context: false,
+ });
}
#[cfg(feature = "builtin-parser")]
diff --git a/src/logging.rs b/src/logging.rs
index 1c375ad..af638ad 100644
--- a/src/logging.rs
+++ b/src/logging.rs
@@ -1,8 +1,7 @@
//! Custom [LogPlugin](bevy::log::LogPlugin) functionality.
-use bevy::log::{BoxedLayer, Level};
+use bevy::log::tracing::Subscriber;
use bevy::prelude::*;
-use bevy::utils::tracing::Subscriber;
use std::sync::mpsc;
use tracing_subscriber::field::Visit;
use tracing_subscriber::Layer;
@@ -10,7 +9,7 @@ use web_time::SystemTime;
/// A function that implements the log reading functionality for the
/// developer console via [`LogPlugin::custom_layer`](bevy::log::LogPlugin::custom_layer).
-pub fn custom_log_layer(app: &mut App) -> Option {
+pub fn custom_log_layer(app: &mut App) -> Option {
Some(Box::new(create_custom_log_layer(app)))
}
@@ -39,7 +38,7 @@ pub(crate) struct LogMessage {
pub target: &'static str,
/// The level of verbosity of the described span.
- pub level: Level,
+ pub level: bevy::log::Level,
/// The name of the Rust module where the span occurred,
/// or `None` if this could not be determined.
@@ -62,7 +61,7 @@ fn transfer_log_events(
receiver: NonSend,
mut log_events: EventWriter,
) {
- log_events.send_batch(receiver.0.try_iter());
+ log_events.write_batch(receiver.0.try_iter());
}
/// This struct temporarily stores [`LogMessage`]s before they are
@@ -76,7 +75,7 @@ struct LogCaptureLayer {
impl Layer for LogCaptureLayer {
fn on_event(
&self,
- event: &bevy::utils::tracing::Event<'_>,
+ event: &bevy::log::tracing::Event<'_>,
_ctx: tracing_subscriber::layer::Context<'_, S>,
) {
let mut message = None;
@@ -104,7 +103,7 @@ struct LogEventVisitor<'a>(&'a mut Option);
impl Visit for LogEventVisitor<'_> {
fn record_debug(
&mut self,
- field: &bevy::utils::tracing::field::Field,
+ field: &bevy::log::tracing::field::Field,
value: &dyn std::fmt::Debug,
) {
// Only log out messages
diff --git a/src/ui.rs b/src/ui.rs
index aa859d5..a42bf8d 100644
--- a/src/ui.rs
+++ b/src/ui.rs
@@ -31,6 +31,7 @@ pub const COMMAND_MESSAGE_NAME: &str = "console_command";
/// Identifier for log messages that show the result of a command.
pub const COMMAND_RESULT_NAME: &str = "console_result";
+#[allow(missing_docs)]
#[derive(Default, Resource)]
pub struct ConsoleUiState {
/// Whether the console is open or not.
@@ -117,7 +118,7 @@ pub fn render_ui(
info!(name: COMMAND_MESSAGE_NAME, "{COMMAND_MESSAGE_PREFIX}{}", command.trim());
// Get the owned command string by replacing it with an empty string
let command = std::mem::take(command);
- commands.add(ExecuteCommand(command));
+ commands.queue(ExecuteCommand(command));
}
}
@@ -125,18 +126,18 @@ pub fn render_ui(
submit_command(&mut state.command, commands);
}
- completions::change_selected_completion(ui, state, &completions);
+ completions::change_selected_completion(ui, state, completions);
// A General rule when creating layouts in egui is to place elements which fill remaining space last.
// Since immediate mode ui can't predict the final sizes of widgets until they've already been drawn
// Thus we create a bottom panel first, where our text edit and submit button resides.
egui::TopBottomPanel::bottom("bottom panel")
- .frame(egui::Frame::none().outer_margin(egui::Margin {
- left: 5.0,
- right: 5.0,
- top: 5. + 6.,
- bottom: 5.0,
+ .frame(egui::Frame::NONE.outer_margin(egui::Margin {
+ left: 5,
+ right: 5,
+ top: 5 + 6,
+ bottom: 5,
}))
.show_inside(ui, |ui| {
let text_edit_id = egui::Id::new("text_edit");
@@ -169,8 +170,8 @@ pub fn render_ui(
state,
ui,
commands,
- &completions,
- &config,
+ completions,
+ config,
);
// Each time we open the console, we want to set focus to the text edit control.
@@ -188,7 +189,7 @@ pub fn render_ui(
let mut command_index = 0;
for (id, (message, is_new)) in state.log.iter_mut().enumerate() {
- add_log(ui, id, message, is_new, hints, &config, &mut command_index);
+ add_log(ui, id, message, is_new, hints, config, &mut command_index);
}
});
});
diff --git a/src/ui/completions.rs b/src/ui/completions.rs
index 208cc13..026a512 100644
--- a/src/ui/completions.rs
+++ b/src/ui/completions.rs
@@ -60,7 +60,7 @@ pub fn completions(
// If not found, the whole substring is a word
None => before_cursor,
};
- commands.add(UpdateAutoComplete(keyword_before.to_owned()));
+ commands.queue(UpdateAutoComplete(keyword_before.to_owned()));
} else {
ui.memory_mut(|mem| {
if mem.is_popup_open(text_edit_complete_id) {