From 636d6e320ad887bba6c941aa487e6c8c7dc3f6c8 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Fri, 14 Jul 2023 00:32:52 +0200 Subject: [PATCH 01/58] Initial work on editor, start with ctrl+e --- src/common.rs | 4 +- src/gui_egui/components/add.rs | 2 +- src/gui_egui/components/constant.rs | 2 +- src/gui_egui/components/mux.rs | 7 +- src/gui_egui/components/probe.rs | 7 +- src/gui_egui/components/register.rs | 2 +- src/gui_egui/components/sext.rs | 2 +- src/gui_egui/components/wire.rs | 2 +- src/gui_egui/editor.rs | 144 ++++++++++++++++++++++++++++ src/gui_egui/gui.rs | 21 +++- src/gui_egui/keymap.rs | 90 +++++++++++++---- src/gui_egui/lib.rs | 0 src/gui_egui/menu.rs | 121 +++++++++++++++++++++-- src/gui_egui/mod.rs | 2 +- 14 files changed, 362 insertions(+), 44 deletions(-) create mode 100644 src/gui_egui/editor.rs create mode 100644 src/gui_egui/lib.rs diff --git a/src/common.rs b/src/common.rs index e82b4b3c..a0798812 100644 --- a/src/common.rs +++ b/src/common.rs @@ -72,8 +72,8 @@ pub trait EguiComponent: Component { fn render( &self, _ui: &mut egui::Ui, - _simulator: Simulator, - _start: egui::Vec2, + _simulator: Option, + _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, ) { diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index b387e95c..1e5798aa 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -9,7 +9,7 @@ impl EguiComponent for Add { fn render( &self, ui: &mut egui::Ui, - _simulator: Simulator, + _simulator: Option, offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 2b7a8e41..0c2cd254 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -7,7 +7,7 @@ impl EguiComponent for Constant { fn render( &self, ui: &mut egui::Ui, - _simulator: Simulator, + _simulator: Option, offset: egui::Vec2, scale: f32, clip_rect: Rect, diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 04f5f4a2..e0559973 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -7,7 +7,7 @@ impl EguiComponent for Mux { fn render( &self, ui: &mut egui::Ui, - simulator: Simulator, + simulator: Option, offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, @@ -23,7 +23,10 @@ impl EguiComponent for Mux { let pa = self.m_in.len() as f32; // selector - let select = simulator.get_input_val(&self.select); + let select = match simulator { + Some(s) => s.get_input_val(&self.select), + None => 0, + }; // The shape ui.painter().add(egui::Shape::closed_line( diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index fa3d756c..686b5692 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -7,7 +7,7 @@ impl EguiComponent for Probe { fn render( &self, ui: &mut egui::Ui, - simulator: Simulator, + simulator: Option, offset: egui::Vec2, scale: f32, clip_rect: Rect, @@ -16,7 +16,10 @@ impl EguiComponent for Probe { offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; let input = self.input.clone(); - let value = simulator.get_input_val(&input); + let value = match simulator { + Some(s) => s.get_input_val(&input), + None => 0, + }; Area::new(self.id.to_string()) .order(Order::Middle) .current_pos(offset.to_pos2()) diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index 3429fdc0..fe880d10 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -7,7 +7,7 @@ impl EguiComponent for Register { fn render( &self, ui: &mut egui::Ui, - _simulator: Simulator, + _simulator: Option, offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index d17006ca..b3ec4e72 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -6,7 +6,7 @@ impl EguiComponent for Sext { fn render( &self, _ui: &mut egui::Ui, - _simulator: Simulator, + _simulator: Option, _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index d6c6192f..d3493763 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -7,7 +7,7 @@ impl EguiComponent for Wire { fn render( &self, ui: &mut egui::Ui, - _simulator: Simulator, + _simulator: Option, offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs new file mode 100644 index 00000000..9bdb8973 --- /dev/null +++ b/src/gui_egui/editor.rs @@ -0,0 +1,144 @@ +use crate::common::ComponentStore; +use crate::gui_egui::{gui::Gui, helper::offset_helper, menu::Menu}; +use eframe::{egui, Frame}; +use egui::{Color32, Context, Pos2, Rect, Style, Ui, Vec2}; +use std::path::PathBuf; + +pub struct Editor { + pub component_store: ComponentStore, + pub scale: f32, + pub pan: Vec2, + pub offset: Vec2, + pub clip_rect: Rect, + pub side_panel_width: f32, + pub ui_change: bool, +} + +impl Editor { + pub fn gui(cs: ComponentStore, _path: &PathBuf) -> Self { + Editor { + component_store: cs, + scale: 1f32, + pan: Vec2::new(0f32, 0f32), + offset: Vec2 { x: 0f32, y: 0f32 }, + clip_rect: Rect { + min: Pos2 { x: 0f32, y: 0f32 }, + max: Pos2 { + x: 1000f32, + y: 1000f32, + }, + }, + side_panel_width: 400f32, + ui_change: true, + } + } + + pub fn update(ctx: &Context, frame: &mut Frame, gui: &mut Gui) { + let frame = egui::Frame::none().fill(egui::Color32::WHITE); + + if Editor::editor(gui).should_area_update(ctx) { + egui::TopBottomPanel::top("topBarEditor").show(ctx, |ui| { + Menu::new_editor(ui, gui); + }); + Editor::library(ctx, gui); + let top = + egui::containers::panel::PanelState::load(ctx, egui::Id::from("topBarEditor")) + .unwrap(); + let side = + egui::containers::panel::PanelState::load(ctx, egui::Id::from("leftLibrary")) + .unwrap(); + Editor::editor(gui).offset = egui::Vec2 { + x: side.rect.max.x, + y: top.rect.max.y, + }; + Editor::editor(gui).clip_rect = egui::Rect { + min: Editor::editor(gui).offset.to_pos2(), + max: egui::Pos2 { + x: f32::INFINITY, + y: f32::INFINITY, + }, + }; + egui::Context::request_repaint(ctx); + } else { + egui::TopBottomPanel::top("topBarEditor").show(ctx, |ui| { + Menu::new_editor(ui, gui); + }); + Editor::library(ctx, gui); + Editor::draw_area(ctx, gui, frame); + } + } + + fn should_area_update(&mut self, ctx: &egui::Context) -> bool { + if self.ui_change { + self.ui_change = false; + true + } else { + (egui::containers::panel::PanelState::load(ctx, egui::Id::from("topBarEditor")) + .unwrap() + .rect + .max + .y + - self.offset.y) + .abs() + > 0.1 + || (egui::containers::panel::PanelState::load(ctx, egui::Id::from("leftLibrary")) + .unwrap() + .rect + .max + .x + - self.offset.x) + .abs() + > 0.1 + } + } + + fn library(ctx: &Context, gui: &mut Gui) { + egui::SidePanel::left("leftLibrary") + .default_width(gui.editor.as_mut().unwrap().side_panel_width) + .frame(egui::Frame::side_top_panel(&(*ctx.style()).clone()).fill(Color32::WHITE)) + .show(ctx, |ui| { + egui::ScrollArea::vertical().show(ui, |ui| { + ui.horizontal(|ui| { + // + }); + }); + }); + // + } + + fn draw_area(ctx: &Context, gui: &mut Gui, frame: egui::Frame) { + let central_panel = egui::CentralPanel::default().frame(frame).show(ctx, |ui| { + ui.set_clip_rect(Editor::editor(gui).clip_rect); + // draw a marker to show 0,0 + + { + let s = Editor::editor(gui); + ui.painter().add(egui::Shape::line( + vec![ + offset_helper((30f32, 0f32), s.scale, s.offset + s.pan), + offset_helper((0f32, 0f32), s.scale, s.offset + s.pan), + offset_helper((0f32, 30f32), s.scale, s.offset + s.pan), + ], + egui::Stroke { + width: s.scale, + color: egui::Color32::BLACK, + }, + )); + } + + let s = Editor::editor(gui); + for c in s.component_store.store.clone() { + c.render(ui, None, s.offset + s.pan, s.scale, s.clip_rect); + } + }); + + let cpr = central_panel.response.interact(egui::Sense::drag()); + if cpr.dragged_by(egui::PointerButton::Middle) { + Editor::editor(gui).pan += cpr.drag_delta(); + } + } + + fn editor(gui: &mut Gui) -> &mut Editor { + gui.editor.as_mut().unwrap() + } +} diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index 1d723238..bb653afc 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -1,5 +1,5 @@ use crate::common::{ComponentStore, Simulator}; -use crate::gui_egui::{keymap, keymap::Shortcuts, menu::Menu}; +use crate::gui_egui::{editor::Editor, keymap, keymap::Shortcuts, menu::Menu}; use eframe::egui; use std::path::PathBuf; @@ -17,6 +17,8 @@ pub struct Gui { pub clip_rect: egui::Rect, pub shortcuts: Shortcuts, pub pause: bool, + pub editor: Option, + pub editor_use: bool, } pub fn gui(cs: &ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { @@ -37,18 +39,31 @@ pub fn gui(cs: &ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { clip_rect: egui::Rect::NOTHING, shortcuts: Shortcuts::new(), pause: true, + editor: None, + editor_use: false, }; eframe::run_native("SyncRim", options, Box::new(|_cc| Box::new(gui))) } impl eframe::App for Gui { - fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { + fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { self.shortcuts.inputs(ctx, self); + if self.editor_use { + //let a = self.editor.as_mut().unwrap(); + //a.update(ctx, frame, self); + crate::gui_egui::editor::Editor::update(ctx, frame, self); + return; + } let frame = egui::Frame::none().fill(egui::Color32::WHITE); + //let frame = egui::Frame::canvas(&(*ctx.style()).clone()); // For getting the correct offset for our drawing we need to get the top bar // and side panel of the ui once before we draw if self.should_area_update(ctx) { + // todo: Implement proper light and dark mode? + // for testing light and dark mode + //ctx.set_visuals(egui::Visuals::dark()); + //ctx.set_visuals(egui::Visuals::light()); self.top_bar(ctx); self.side_panel(ctx); let top = @@ -107,7 +122,7 @@ impl Gui { for c in &self.simulator.ordered_components { c.render( ui, - self.simulator.clone(), + Some(self.simulator.clone()), self.offset + self.pan, self.scale, self.clip_rect, diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 7d8e3c6e..79947a26 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -1,3 +1,4 @@ +use crate::common::ComponentStore; use egui::{Key, KeyboardShortcut, Modifiers}; #[derive(Copy, Clone)] @@ -6,6 +7,7 @@ pub struct Shortcuts { pub file_open: KeyboardShortcut, pub file_save: KeyboardShortcut, pub file_save_as: KeyboardShortcut, + pub file_editor_toggle: KeyboardShortcut, pub file_preferences: KeyboardShortcut, pub file_quit: KeyboardShortcut, pub edit_cut: KeyboardShortcut, @@ -74,6 +76,10 @@ impl Shortcuts { }, key: Key::S, }, + file_editor_toggle: KeyboardShortcut { + modifiers: ctrl, + key: Key::E, + }, file_preferences: KeyboardShortcut { modifiers: ctrl, key: Key::P, @@ -148,6 +154,9 @@ impl Shortcuts { if ctx.input_mut(|i| i.consume_shortcut(&self.file_save_as)) { file_save_as_fn(gui); } + if ctx.input_mut(|i| i.consume_shortcut(&self.file_editor_toggle)) { + file_editor_toggle_fn(gui); + } if ctx.input_mut(|i| i.consume_shortcut(&self.file_preferences)) { file_preferences_fn(gui); } @@ -194,47 +203,86 @@ pub fn file_new_fn(_gui: &mut crate::gui_egui::gui::Gui) {} pub fn file_open_fn(_gui: &mut crate::gui_egui::gui::Gui) {} pub fn file_save_fn(_gui: &mut crate::gui_egui::gui::Gui) {} pub fn file_save_as_fn(_gui: &mut crate::gui_egui::gui::Gui) {} +pub fn file_editor_toggle_fn(gui: &mut crate::gui_egui::gui::Gui) { + match gui.editor_use { + true => { + gui.editor_use = false; + // todo: Make us swap back into simulator mode (create new simulator) + } + false => { + gui.editor + .get_or_insert(crate::gui_egui::editor::Editor::gui( + ComponentStore { + store: gui.simulator.ordered_components.clone(), + }, + &gui.path, + )); + + gui.editor_use = true; + } + } +} pub fn file_preferences_fn(_gui: &mut crate::gui_egui::gui::Gui) {} pub fn file_quit_fn(_gui: &mut crate::gui_egui::gui::Gui) {} pub fn edit_cut_fn(_gui: &mut crate::gui_egui::gui::Gui) {} pub fn edit_copy_fn(_gui: &mut crate::gui_egui::gui::Gui) {} pub fn edit_paste_fn(_gui: &mut crate::gui_egui::gui::Gui) {} pub fn view_zoom_in_fn(gui: &mut crate::gui_egui::gui::Gui) { - match gui.scale { - x if (0.0f32..0.2f32).contains(&x) => gui.scale = 0.25f32, - x if (0.2f32..0.4f32).contains(&x) => gui.scale = 0.5f32, - x if (0.4f32..0.6f32).contains(&x) => gui.scale = 1f32, - x if (0.9f32..1.1f32).contains(&x) => gui.scale = 1.5f32, - x if (1.4f32..1.6f32).contains(&x) => gui.scale = 2f32, - _ => gui.scale = 2f32, + let scale: &mut f32 = match gui.editor_use { + true => &mut gui.editor.as_mut().unwrap().scale, + false => &mut gui.scale, + }; + match *scale { + x if (0.0f32..0.2f32).contains(&x) => *scale = 0.25f32, + x if (0.2f32..0.4f32).contains(&x) => *scale = 0.5f32, + x if (0.4f32..0.6f32).contains(&x) => *scale = 1f32, + x if (0.9f32..1.1f32).contains(&x) => *scale = 1.5f32, + x if (1.4f32..1.6f32).contains(&x) => *scale = 2f32, + _ => *scale = 2f32, } } pub fn view_zoom_out_fn(gui: &mut crate::gui_egui::gui::Gui) { - match gui.scale { - x if (0.2f32..0.4f32).contains(&x) => gui.scale = 0.1f32, - x if (0.4f32..0.6f32).contains(&x) => gui.scale = 0.25f32, - x if (0.9f32..1.1f32).contains(&x) => gui.scale = 0.5f32, - x if (1.4f32..1.6f32).contains(&x) => gui.scale = 1f32, - x if (1.9f32..2.1f32).contains(&x) => gui.scale = 1.5f32, - _ => gui.scale = 0.1f32, + let scale: &mut f32 = match gui.editor_use { + true => &mut gui.editor.as_mut().unwrap().scale, + false => &mut gui.scale, + }; + match *scale { + x if (0.2f32..0.4f32).contains(&x) => *scale = 0.1f32, + x if (0.4f32..0.6f32).contains(&x) => *scale = 0.25f32, + x if (0.9f32..1.1f32).contains(&x) => *scale = 0.5f32, + x if (1.4f32..1.6f32).contains(&x) => *scale = 1f32, + x if (1.9f32..2.1f32).contains(&x) => *scale = 1.5f32, + _ => *scale = 0.1f32, } } pub fn control_play_toggle(gui: &mut crate::gui_egui::gui::Gui) { - gui.pause = !gui.pause; + if !gui.editor_use { + gui.pause = !gui.pause; + } } pub fn control_play(gui: &mut crate::gui_egui::gui::Gui) { - gui.pause = false; + if !gui.editor_use { + gui.pause = false; + } } pub fn control_pause(gui: &mut crate::gui_egui::gui::Gui) { - gui.pause = true; + if !gui.editor_use { + gui.pause = true; + } } pub fn control_reset(gui: &mut crate::gui_egui::gui::Gui) { - gui.simulator.reset(&mut gui.clock); - gui.pause = true; + if !gui.editor_use { + gui.simulator.reset(&mut gui.clock); + gui.pause = true; + } } pub fn control_step_forward(gui: &mut crate::gui_egui::gui::Gui) { - gui.simulator.clock(&mut gui.clock); + if !gui.editor_use { + gui.simulator.clock(&mut gui.clock); + } } pub fn control_step_back(gui: &mut crate::gui_egui::gui::Gui) { - gui.simulator.un_clock(&mut gui.clock); + if !gui.editor_use { + gui.simulator.un_clock(&mut gui.clock); + } } diff --git a/src/gui_egui/lib.rs b/src/gui_egui/lib.rs new file mode 100644 index 00000000..e69de29b diff --git a/src/gui_egui/menu.rs b/src/gui_egui/menu.rs index ec03623c..e528612c 100644 --- a/src/gui_egui/menu.rs +++ b/src/gui_egui/menu.rs @@ -1,8 +1,10 @@ +use crate::gui_egui::{editor::Editor, gui::Gui, keymap}; + pub(crate) struct Menu {} impl Menu { #[allow(clippy::new_ret_no_self)] - pub(crate) fn new(ui: &mut egui::Ui, gui: &mut crate::gui_egui::gui::Gui) { + pub(crate) fn new(ui: &mut egui::Ui, gui: &mut Gui) { fn btn(ui: &mut egui::Ui, name: &str, keys: egui::KeyboardShortcut) -> egui::Response { ui.add(egui::Button::new(name).shortcut_text(ui.ctx().format_shortcut(&keys))) } @@ -29,6 +31,9 @@ impl Menu { // Save As here } ui.separator(); + if btn(ui, "Editor", gui.shortcuts.file_editor_toggle).clicked() { + keymap::file_editor_toggle_fn(gui); + } if btn(ui, "Preferences", gui.shortcuts.file_preferences).clicked() { // Preferences here } @@ -51,10 +56,10 @@ impl Menu { ui.menu_button("View", |ui| { if btn(ui, "Zoom In", gui.shortcuts.view_zoom_in).clicked() { - crate::gui_egui::keymap::view_zoom_in_fn(gui); + keymap::view_zoom_in_fn(gui); } if btn(ui, "Zoom Out", gui.shortcuts.view_zoom_out).clicked() { - crate::gui_egui::keymap::view_zoom_out_fn(gui); + keymap::view_zoom_out_fn(gui); } ui.menu_button("Zoom Level", |ui| { if ui.button("10%").clicked() { @@ -95,21 +100,121 @@ impl Menu { }); ui.horizontal(|ui| { if ui.button("⟲").clicked() { - crate::gui_egui::keymap::control_reset(gui); + keymap::control_reset(gui); } if ui.button("⏮").clicked() { - crate::gui_egui::keymap::control_step_back(gui); + keymap::control_step_back(gui); } if ui.button("⏭").clicked() { - crate::gui_egui::keymap::control_step_forward(gui); + keymap::control_step_forward(gui); } if ui.button("▶").clicked() { - crate::gui_egui::keymap::control_play(gui); + keymap::control_play(gui); } if ui.button("⏸").clicked() { - crate::gui_egui::keymap::control_pause(gui); + keymap::control_pause(gui); } ui.label(format!("Clock #{}", gui.clock)); }); } + + #[allow(clippy::new_ret_no_self)] + pub(crate) fn new_editor(ui: &mut egui::Ui, gui: &mut Gui) { + fn btn(ui: &mut egui::Ui, name: &str, keys: egui::KeyboardShortcut) -> egui::Response { + ui.add(egui::Button::new(name).shortcut_text(ui.ctx().format_shortcut(&keys))) + } + fn editor(gui: &mut Gui) -> &mut Editor { + gui.editor.as_mut().unwrap() + } + + egui::menu::bar(ui, |ui| { + ui.menu_button("File", |ui| { + if btn(ui, "File", gui.shortcuts.file_new).clicked() { + // New here editor + } + if btn(ui, "Open", gui.shortcuts.file_open).clicked() { + // Open here editor + } + ui.menu_button("Open Recent", |_ui| { + // Recent here + //if ui.button("file1").clicked() { + // // Open file editor + //} + }); + ui.separator(); + if btn(ui, "Save", gui.shortcuts.file_save).clicked() { + // Save here editor + } + if btn(ui, "Save As", gui.shortcuts.file_save_as).clicked() { + // Save As here editor + } + ui.separator(); + if btn(ui, "Simulator", gui.shortcuts.file_editor_toggle).clicked() { + keymap::file_editor_toggle_fn(gui); + } + if btn(ui, "Preferences", gui.shortcuts.file_preferences).clicked() { + // Preferences here editor + } + if btn(ui, "Quit", gui.shortcuts.file_quit).clicked() { + // Quit here editor + } + }); + + ui.menu_button("Edit", |ui| { + if btn(ui, "Cut", gui.shortcuts.edit_cut).clicked() { + // Cut here + } + if btn(ui, "Copy", gui.shortcuts.edit_copy).clicked() { + // Copy here + } + if btn(ui, "Paste", gui.shortcuts.edit_paste).clicked() { + // Paste here + } + }); + + ui.menu_button("View", |ui| { + if btn(ui, "Zoom In", gui.shortcuts.view_zoom_in).clicked() { + keymap::view_zoom_in_fn(gui); + } + if btn(ui, "Zoom Out", gui.shortcuts.view_zoom_out).clicked() { + keymap::view_zoom_out_fn(gui); + } + ui.menu_button("Zoom Level", |ui| { + if ui.button("10%").clicked() { + // 10% zoom here here + editor(gui).scale = 0.1f32; + } + if ui.button("25%").clicked() { + // 25% zoom here here + editor(gui).scale = 0.25f32; + } + if ui.button("50%").clicked() { + // 50% zoom here here + editor(gui).scale = 0.5f32; + } + if ui.button("100%").clicked() { + // 100% zoom here here + editor(gui).scale = 1f32; + } + if ui.button("150%").clicked() { + // 150% zoom here here + editor(gui).scale = 1.5f32; + } + if ui.button("200%").clicked() { + // 200% zoom here here + editor(gui).scale = 2f32; + } + }); + }); + + ui.menu_button("Help", |ui| { + if ui.button("Show license").clicked() { + // Show license here + } + if ui.button("About").clicked() { + // About here + } + }); + }); + } } diff --git a/src/gui_egui/mod.rs b/src/gui_egui/mod.rs index b5bb2a35..6c7aef5a 100644 --- a/src/gui_egui/mod.rs +++ b/src/gui_egui/mod.rs @@ -1,4 +1,4 @@ - +mod editor; mod gui; mod helper; mod keymap; From be66429d3064c4445dfbaec313fe2a5807a2cd40 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Fri, 14 Jul 2023 00:35:29 +0200 Subject: [PATCH 02/58] quick cleanup --- src/gui_egui/gui.rs | 2 -- src/gui_egui/lib.rs | 0 2 files changed, 2 deletions(-) delete mode 100644 src/gui_egui/lib.rs diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index bb653afc..adb22530 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -49,8 +49,6 @@ impl eframe::App for Gui { fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { self.shortcuts.inputs(ctx, self); if self.editor_use { - //let a = self.editor.as_mut().unwrap(); - //a.update(ctx, frame, self); crate::gui_egui::editor::Editor::update(ctx, frame, self); return; } diff --git a/src/gui_egui/lib.rs b/src/gui_egui/lib.rs deleted file mode 100644 index e69de29b..00000000 From c7da50cf243df6114118453af5fb7d7a2c07789d Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Fri, 14 Jul 2023 16:20:22 +0200 Subject: [PATCH 03/58] Moving components works, connections do not change/work --- examples/add.rs | 32 +++++++++---------- src/common.rs | 21 +++++++++--- src/component_store.rs | 4 ++- src/gui_egui/components/add.rs | 48 +++++++++++++++++++++++++--- src/gui_egui/components/constant.rs | 48 +++++++++++++++++++++++++--- src/gui_egui/components/mux.rs | 21 +++++++++++- src/gui_egui/components/probe.rs | 45 ++++++++++++++++++++++++-- src/gui_egui/components/probe_out.rs | 22 +++++++++++-- src/gui_egui/components/register.rs | 20 +++++++++++- src/gui_egui/components/sext.rs | 3 +- src/gui_egui/components/wire.rs | 29 ++++++++++++++++- src/gui_egui/editor.rs | 32 ++++++++++++------- src/gui_egui/gui.rs | 2 +- src/gui_egui/helper.rs | 29 ++++++++++++++++- src/simulator.rs | 12 +++---- 15 files changed, 310 insertions(+), 58 deletions(-) diff --git a/examples/add.rs b/examples/add.rs index 84e09f8e..fda2e7c6 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -1,4 +1,4 @@ -use std::{path::PathBuf, rc::Rc}; +use std::{cell::RefCell, path::PathBuf, rc::Rc}; use syncrim::{ common::{ComponentStore, Input}, components::*, @@ -7,51 +7,51 @@ use syncrim::{ fn main() { let cs = ComponentStore { store: vec![ - Rc::new(Add { + Rc::new(RefCell::new(Add { id: "add".to_string(), pos: (200.0, 120.0), a_in: Input::new("c1", 0), b_in: Input::new("c2", 0), - }), - Rc::new(Constant { + })), + Rc::new(RefCell::new(Constant { id: "c1".to_string(), pos: (100.0, 100.0), value: 3, - }), - Rc::new(Constant { + })), + Rc::new(RefCell::new(Constant { id: "c2".to_string(), pos: (100.0, 140.0), value: 4, - }), - Rc::new(Wire { + })), + Rc::new(RefCell::new(Wire { id: "w1".to_string(), pos: (110.0, 100.0), delta: (70.0, 0.0), input: Input::new("c1", 0), - }), - Rc::new(Wire { + })), + Rc::new(RefCell::new(Wire { id: "w2".to_string(), pos: (110.0, 140.0), delta: (70.0, 0.0), input: Input::new("c2", 0), - }), - Rc::new(Wire { + })), + Rc::new(RefCell::new(Wire { id: "w3".to_string(), pos: (220.0, 120.0), delta: (40.0, 0.0), input: Input::new("add", 0), - }), - Rc::new(Probe { + })), + Rc::new(RefCell::new(Probe { id: "p1".to_string(), pos: (270.0, 120.0), input: Input::new("add", 0), - }), + })), ], }; let path = PathBuf::from("add.json"); - cs.save_file(&path); + //cs.save_file(&path); #[cfg(feature = "gui-egui")] syncrim::gui_egui::gui(&cs, &path).ok(); diff --git a/src/common.rs b/src/common.rs index a0798812..8a790c37 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,5 +1,6 @@ use petgraph::Graph; use serde::{Deserialize, Serialize}; +use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; @@ -10,13 +11,15 @@ pub type Signal = u32; pub type SignedSignal = i32; #[cfg(not(any(feature = "gui-vizia", feature = "gui-egui")))] -type Components = Vec>; +type Components = Vec>>; #[cfg(feature = "gui-vizia")] -type Components = Vec>; +type Components = Vec>>; +// todo: Probably make a separate ComponentsEditor type +// so we don't have to use refcell everywhere #[cfg(feature = "gui-egui")] -type Components = Vec>; +type Components = Vec>>; #[cfg_attr(feature = "gui-vizia", derive(Lens))] #[derive(Clone)] @@ -31,7 +34,7 @@ pub struct Simulator { pub graph: Graph, } -#[derive(Serialize, Deserialize)] +//#[derive(Serialize, Deserialize)] pub struct ComponentStore { pub store: Components, } @@ -76,6 +79,16 @@ pub trait EguiComponent: Component { _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, + ) -> Option { + None + } + fn render_editor( + &mut self, + _ui: &mut egui::Ui, + _simulator: Option, + _offset: egui::Vec2, + _scale: f32, + _clip_rect: egui::Rect, ) { } } diff --git a/src/component_store.rs b/src/component_store.rs index 629b032f..8efef0ff 100644 --- a/src/component_store.rs +++ b/src/component_store.rs @@ -3,6 +3,7 @@ use crate::common::ComponentStore; use std::{fs::File, io::prelude::*, path::PathBuf}; impl ComponentStore { + /* pub fn load(json: &str) -> Self { serde_json::from_str(json).unwrap() } @@ -24,6 +25,7 @@ impl ComponentStore { } pub fn to_(&self) { - self.store.iter().for_each(|c| c.to_()); + self.store.iter().for_each(|c| c.borrow().to_()); } + */ } diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 1e5798aa..feb4959a 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,8 +1,9 @@ -use crate::gui_egui::helper::offset_helper; +use crate::gui_egui::helper::{offset_helper, out_of_bounds}; use crate::{ common::{EguiComponent, Simulator}, components::Add, }; +use egui::{PointerButton, Sense, Vec2}; #[typetag::serde] impl EguiComponent for Add { @@ -12,11 +13,11 @@ impl EguiComponent for Add { _simulator: Option, offset: egui::Vec2, scale: f32, - _clip_rect: egui::Rect, - ) { + clip_rect: egui::Rect, + ) -> Option { // 41x81 // middle: 21x 41y (0 0) - let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; + let oh: fn((f32, f32), f32, Vec2) -> egui::Pos2 = offset_helper; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -57,5 +58,44 @@ impl EguiComponent for Add { color: egui::Color32::BLACK, }, )); + let rect = egui::Rect { + min: oh((-20f32, -40f32), s, o), + max: oh((20f32, 40f32), s, o), + }; + let rect = out_of_bounds(rect, clip_rect); + let r = ui.allocate_rect( + rect, + Sense { + click: true, + drag: true, + focusable: true, + }, + ); + if r.hovered() && !r.dragged() { + egui::containers::popup::show_tooltip_for( + ui.ctx(), + egui::Id::new(self.id.clone()), + &rect, + |ui| { + ui.label("test"); + }, + ); + } + Some(r) + } + + fn render_editor( + &mut self, + ui: &mut egui::Ui, + simulator: Option, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + ) { + let resp = Add::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + if resp.dragged_by(PointerButton::Primary) { + let delta = resp.drag_delta(); + self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); + } } } diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 0c2cd254..7829ce51 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,6 +1,7 @@ use crate::common::{EguiComponent, Simulator}; use crate::components::Constant; -use egui::{Align2, Area, Color32, Order, Rect, RichText}; +use crate::gui_egui::helper::out_of_bounds; +use egui::{Align2, Area, Color32, Order, Rect, RichText, Sense}; #[typetag::serde] impl EguiComponent for Constant { @@ -11,15 +12,16 @@ impl EguiComponent for Constant { offset: egui::Vec2, scale: f32, clip_rect: Rect, - ) { + ) -> Option { let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; - Area::new(self.id.to_string()) + let area = Area::new(self.id.to_string()) .order(Order::Middle) .current_pos(offset.to_pos2()) .movable(false) .enabled(true) + .interactable(false) .pivot(Align2::CENTER_CENTER) .show(ui.ctx(), |ui| { ui.set_clip_rect(clip_rect); @@ -27,8 +29,44 @@ impl EguiComponent for Constant { RichText::new(self.value.to_string()) .size(scale * 12f32) .background_color(Color32::LIGHT_GREEN), - ) - .on_hover_text(format!("{:#x}", self.value)); + ); + //.on_hover_text(format!("{:#x}", self.value)); }); + let rect = area.response.rect; + let rect = out_of_bounds(rect, clip_rect); + let r = ui.allocate_rect( + rect, + Sense { + click: true, + drag: true, + focusable: true, + }, + ); + if r.hovered() && !r.dragged() { + egui::containers::popup::show_tooltip_for( + ui.ctx(), + egui::Id::new(self.id.clone()), + &rect, + |ui| { + ui.label(self.value.to_string()); + }, + ); + } + Some(r) + } + + fn render_editor( + &mut self, + ui: &mut egui::Ui, + simulator: Option, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + ) { + let resp = Constant::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + if resp.dragged_by(egui::PointerButton::Primary) { + let delta = resp.drag_delta(); + self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); + } } } diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index e0559973..2f90aa30 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -11,7 +11,7 @@ impl EguiComponent for Mux { offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, - ) { + ) -> Option { // 41x(20*ports + 11) // middle: 21x ((20*ports + 10)/2+1)y (0 0) let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; @@ -58,5 +58,24 @@ impl EguiComponent for Mux { color: egui::Color32::RED, }, )); + None } + + /* + fn interactive_rect(&self, ui: &mut egui::Ui, offset: egui::Vec2, scale: f32) -> egui::Rect { + // 41x(20*ports + 11) + // middle: 21x ((20*ports + 10)/2+1)y (0 0) + let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + let pa = self.m_in.len() as f32; + egui::Rect { + min: oh((-20f32, pa * (-10f32) - 10f32), s, o), + max: oh((20f32, pa * (10f32) + 10f32), s, o), + } + } + */ } diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 686b5692..7f861422 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -1,6 +1,7 @@ use crate::common::{EguiComponent, Simulator}; use crate::components::Probe; -use egui::{Align2, Area, Color32, Order, Rect, RichText}; +use crate::gui_egui::helper::out_of_bounds; +use egui::{Align2, Area, Color32, Order, Rect, RichText, Sense}; #[typetag::serde] impl EguiComponent for Probe { @@ -11,7 +12,7 @@ impl EguiComponent for Probe { offset: egui::Vec2, scale: f32, clip_rect: Rect, - ) { + ) -> Option { let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -20,11 +21,12 @@ impl EguiComponent for Probe { Some(s) => s.get_input_val(&input), None => 0, }; - Area::new(self.id.to_string()) + let area = Area::new(self.id.to_string()) .order(Order::Middle) .current_pos(offset.to_pos2()) .movable(false) .enabled(true) + .interactable(false) .pivot(Align2::CENTER_CENTER) .show(ui.ctx(), |ui| { ui.set_clip_rect(clip_rect); @@ -35,5 +37,42 @@ impl EguiComponent for Probe { ) .on_hover_text(format!("{:#x}", value)); }); + + let rect = area.response.rect; + let rect = out_of_bounds(rect, clip_rect); + let r = ui.allocate_rect( + rect, + Sense { + click: true, + drag: true, + focusable: true, + }, + ); + if r.hovered() && !r.dragged() { + egui::containers::popup::show_tooltip_for( + ui.ctx(), + egui::Id::new(self.id.clone()), + &rect, + |ui| { + ui.label(format!("{:?}", value)); + }, + ); + } + Some(r) + } + + fn render_editor( + &mut self, + ui: &mut egui::Ui, + simulator: Option, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + ) { + let resp = Probe::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + if resp.dragged_by(egui::PointerButton::Primary) { + let delta = resp.drag_delta(); + self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); + } } } diff --git a/src/gui_egui/components/probe_out.rs b/src/gui_egui/components/probe_out.rs index 5144e774..8b85ce76 100644 --- a/src/gui_egui/components/probe_out.rs +++ b/src/gui_egui/components/probe_out.rs @@ -1,5 +1,23 @@ -use crate::common::EguiComponent; +use crate::common::{EguiComponent, Simulator}; use crate::components::ProbeOut; +use egui::Rect; #[typetag::serde] -impl EguiComponent for ProbeOut {} +impl EguiComponent for ProbeOut { + fn render( + &self, + ui: &mut egui::Ui, + _simulator: Option, + offset: egui::Vec2, + scale: f32, + clip_rect: Rect, + ) -> Option { + todo!(); + None + } + /* + fn interactive_rect(&self, ui: &mut egui::Ui, offset: egui::Vec2, scale: f32) -> egui::Rect { + todo!() + } + */ +} diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index fe880d10..81d0029c 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -11,7 +11,7 @@ impl EguiComponent for Register { offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, - ) { + ) -> Option { // 21x41 // middle: 11x 21y (0 0) let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; @@ -37,5 +37,23 @@ impl EguiComponent for Register { color: egui::Color32::BLACK, }, )); + None } + + /* + fn interactive_rect(&self, ui: &mut egui::Ui, offset: egui::Vec2, scale: f32) -> egui::Rect { + // 21x41 + // middle: 11x 21y (0 0) + let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + egui::Rect { + min: oh((-10f32, -20f32), s, o), + max: oh((10f32, 20f32), s, o), + } + } + */ } diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index b3ec4e72..2fd574d1 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -10,7 +10,8 @@ impl EguiComponent for Sext { _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, - ) { + ) -> Option { todo!("implement sext"); + None } } diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index d3493763..6a3af460 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -11,7 +11,7 @@ impl EguiComponent for Wire { offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, - ) { + ) -> Option { let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; let mut offset = offset; offset.x += self.pos.0 * scale; @@ -28,5 +28,32 @@ impl EguiComponent for Wire { color: egui::Color32::BLACK, }, )); + let rect = egui::Rect { + min: oh((0f32, 0f32), s, o), + max: oh((self.delta.0, self.delta.1), s, o), + }; + Some(ui.allocate_rect( + rect, + egui::Sense { + click: true, + drag: true, + focusable: true, + }, + )) + } + + fn render_editor( + &mut self, + ui: &mut egui::Ui, + simulator: Option, + offset: egui::Vec2, + scale: f32, + clip_rect: egui::Rect, + ) { + let resp = Wire::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + if resp.dragged_by(egui::PointerButton::Primary) { + let delta = resp.drag_delta(); + self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); + } } } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 9bdb8973..2f42e548 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -36,7 +36,7 @@ impl Editor { pub fn update(ctx: &Context, frame: &mut Frame, gui: &mut Gui) { let frame = egui::Frame::none().fill(egui::Color32::WHITE); - if Editor::editor(gui).should_area_update(ctx) { + if Editor::gui_to_editor(gui).should_area_update(ctx) { egui::TopBottomPanel::top("topBarEditor").show(ctx, |ui| { Menu::new_editor(ui, gui); }); @@ -47,12 +47,12 @@ impl Editor { let side = egui::containers::panel::PanelState::load(ctx, egui::Id::from("leftLibrary")) .unwrap(); - Editor::editor(gui).offset = egui::Vec2 { + Editor::gui_to_editor(gui).offset = egui::Vec2 { x: side.rect.max.x, y: top.rect.max.y, }; - Editor::editor(gui).clip_rect = egui::Rect { - min: Editor::editor(gui).offset.to_pos2(), + Editor::gui_to_editor(gui).clip_rect = egui::Rect { + min: Editor::gui_to_editor(gui).offset.to_pos2(), max: egui::Pos2 { x: f32::INFINITY, y: f32::INFINITY, @@ -99,6 +99,7 @@ impl Editor { .show(ctx, |ui| { egui::ScrollArea::vertical().show(ui, |ui| { ui.horizontal(|ui| { + // }); }); @@ -108,11 +109,11 @@ impl Editor { fn draw_area(ctx: &Context, gui: &mut Gui, frame: egui::Frame) { let central_panel = egui::CentralPanel::default().frame(frame).show(ctx, |ui| { - ui.set_clip_rect(Editor::editor(gui).clip_rect); - // draw a marker to show 0,0 + ui.set_clip_rect(Editor::gui_to_editor(gui).clip_rect); + // draw a marker to show 0,0 { - let s = Editor::editor(gui); + let s = Editor::gui_to_editor(gui); ui.painter().add(egui::Shape::line( vec![ offset_helper((30f32, 0f32), s.scale, s.offset + s.pan), @@ -126,19 +127,28 @@ impl Editor { )); } - let s = Editor::editor(gui); + let s = Editor::gui_to_editor(gui); for c in s.component_store.store.clone() { - c.render(ui, None, s.offset + s.pan, s.scale, s.clip_rect); + let resp = + c.borrow_mut() + .render_editor(ui, None, s.offset + s.pan, s.scale, s.clip_rect); + //println!("{:?}", r); + //println!("is: {}", ctx.is_pointer_over_area()); + /* + egui::containers::popup::show_tooltip_for(ctx, id, &r, |ui| { + ui.label("asd"); + }); + */ } }); let cpr = central_panel.response.interact(egui::Sense::drag()); if cpr.dragged_by(egui::PointerButton::Middle) { - Editor::editor(gui).pan += cpr.drag_delta(); + Editor::gui_to_editor(gui).pan += cpr.drag_delta(); } } - fn editor(gui: &mut Gui) -> &mut Editor { + fn gui_to_editor(gui: &mut Gui) -> &mut Editor { gui.editor.as_mut().unwrap() } } diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index adb22530..2f5e4f6f 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -118,7 +118,7 @@ impl Gui { ui.set_clip_rect(self.clip_rect); // Don't draw over the rest of the ui for c in &self.simulator.ordered_components { - c.render( + c.borrow().render( ui, Some(self.simulator.clone()), self.offset + self.pan, diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index f3045963..277e18cb 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -1,6 +1,33 @@ -pub fn offset_helper(xy: (f32, f32), scale: f32, offset: egui::Vec2) -> egui::Pos2 { +use egui::{Pos2, Rect, Vec2}; + +pub fn offset_helper(xy: (f32, f32), scale: f32, offset: Vec2) -> Pos2 { egui::Pos2 { x: xy.0 * scale, y: xy.1 * scale, } + offset } + +pub fn out_of_bounds(request: Rect, clip_rect: Rect) -> Rect { + let mut rect = Rect::NOTHING; + if request.max.x < clip_rect.min.x || request.max.y < clip_rect.min.y { + return rect; + } else if request.min.x > clip_rect.max.x || request.min.y > clip_rect.max.y { + return rect; + } + rect = request; + if request.max.x > clip_rect.max.x { + rect.max.x = clip_rect.max.x; + } + if request.max.y > clip_rect.max.y { + rect.max.y = clip_rect.max.y; + } + if request.min.x < clip_rect.min.x { + rect.min.x = clip_rect.min.x; + } + if request.min.y < clip_rect.min.y { + rect.min.y = clip_rect.min.y; + } + return rect; +} + +//pub fn diff --git a/src/simulator.rs b/src/simulator.rs index c3ffad74..df6922f7 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -28,7 +28,7 @@ impl Simulator { println!("-- allocate storage for lensed outputs"); for c in &component_store.store { - let (id, ports) = c.get_id_ports(); + let (id, ports) = c.borrow().get_id_ports(); println!("id {}, ports {:?}", id, ports); // start index for outputs related to component @@ -58,19 +58,19 @@ impl Simulator { println!("\nid_node {:?}", id_node); for (node, c) in &node_comp { - println!("node {:?}, comp_id {:?}", node, c.get_id_ports()); + println!("node {:?}, comp_id {:?}", node, c.borrow().get_id_ports()); } // insert edges for (to_id, c) in &id_component { let to_component = id_component.get(to_id).unwrap(); - let (_, ports) = to_component.get_id_ports(); + let (_, ports) = to_component.borrow().get_id_ports(); println!("to_id :{}, ports: {:?}", to_id, ports); if ports.out_type == OutputType::Combinatorial { let to_node = id_node.get(to_id).unwrap(); - let (_, ports) = c.get_id_ports(); + let (_, ports) = c.borrow().get_id_ports(); for in_port in &ports.inputs { let from_id = &in_port.id; @@ -98,7 +98,7 @@ impl Simulator { let component_ids: Vec = ordered_components .iter() - .map(|c| c.get_id_ports().0) + .map(|c| c.borrow().get_id_ports().0) .collect(); let mut simulator = Simulator { @@ -150,7 +150,7 @@ impl Simulator { let ordered_components = self.ordered_components.clone(); for component in ordered_components { - component.evaluate(self); + component.borrow().evaluate(self); } *clock = self.history.len(); } From 31505a2a4b2c314b3f3f2e6c02254675c367786d Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Fri, 14 Jul 2023 18:55:43 +0200 Subject: [PATCH 04/58] Left side library (very limited), drag in new objects (to be better) --- src/common.rs | 6 +- src/gui_egui/components/add.rs | 25 +++++++- src/gui_egui/components/constant.rs | 25 +++++++- src/gui_egui/components/probe.rs | 23 +++++++- src/gui_egui/components/wire.rs | 70 +++++++++++++++++------ src/gui_egui/editor.rs | 89 +++++++++++++++++++++++------ src/gui_egui/keymap.rs | 8 ++- 7 files changed, 202 insertions(+), 44 deletions(-) diff --git a/src/common.rs b/src/common.rs index 8a790c37..59d75263 100644 --- a/src/common.rs +++ b/src/common.rs @@ -89,7 +89,11 @@ pub trait EguiComponent: Component { _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, - ) { + ) -> bool { + false + } + fn size(&self) -> egui::Rect { + egui::Rect::NOTHING } } diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index feb4959a..0cd6354d 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -3,7 +3,7 @@ use crate::{ common::{EguiComponent, Simulator}, components::Add, }; -use egui::{PointerButton, Sense, Vec2}; +use egui::{PointerButton, Pos2, Rect, Sense, Vec2}; #[typetag::serde] impl EguiComponent for Add { @@ -77,7 +77,8 @@ impl EguiComponent for Add { egui::Id::new(self.id.clone()), &rect, |ui| { - ui.label("test"); + ui.label(format!("Id: {}", self.id.clone())); + ui.label("ALU"); }, ); } @@ -91,11 +92,29 @@ impl EguiComponent for Add { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - ) { + ) -> bool { + let mut delete = false; let resp = Add::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta(); self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } + if resp.drag_released_by(PointerButton::Primary) { + if self.pos.0 < offset.x { + println!("delete!"); + delete = true; + } + } + delete + } + + fn size(&self) -> Rect { + Rect { + min: Pos2 { + x: -20f32, + y: -40f32, + }, + max: Pos2 { x: 20f32, y: 40f32 }, + } } } diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 7829ce51..247a2779 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,7 +1,7 @@ use crate::common::{EguiComponent, Simulator}; use crate::components::Constant; use crate::gui_egui::helper::out_of_bounds; -use egui::{Align2, Area, Color32, Order, Rect, RichText, Sense}; +use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Sense}; #[typetag::serde] impl EguiComponent for Constant { @@ -48,6 +48,7 @@ impl EguiComponent for Constant { egui::Id::new(self.id.clone()), &rect, |ui| { + ui.label(format!("Id: {}", self.id.clone())); ui.label(self.value.to_string()); }, ); @@ -62,11 +63,29 @@ impl EguiComponent for Constant { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - ) { + ) -> bool { + let mut delete = false; let resp = Constant::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); - if resp.dragged_by(egui::PointerButton::Primary) { + if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta(); self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } + if resp.drag_released_by(PointerButton::Primary) { + if self.pos.0 < offset.x { + println!("delete!"); + delete = true; + } + } + delete + } + + fn size(&self) -> Rect { + Rect { + min: Pos2 { + x: -10f32, + y: -10f32, + }, + max: Pos2 { x: 10f32, y: 10f32 }, + } } } diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 7f861422..32c72b69 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -1,7 +1,7 @@ use crate::common::{EguiComponent, Simulator}; use crate::components::Probe; use crate::gui_egui::helper::out_of_bounds; -use egui::{Align2, Area, Color32, Order, Rect, RichText, Sense}; +use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Sense}; #[typetag::serde] impl EguiComponent for Probe { @@ -54,6 +54,7 @@ impl EguiComponent for Probe { egui::Id::new(self.id.clone()), &rect, |ui| { + ui.label(format!("Id: {}", self.id.clone())); ui.label(format!("{:?}", value)); }, ); @@ -68,11 +69,29 @@ impl EguiComponent for Probe { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - ) { + ) -> bool { + let mut delete = false; let resp = Probe::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); if resp.dragged_by(egui::PointerButton::Primary) { let delta = resp.drag_delta(); self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } + if resp.drag_released_by(PointerButton::Primary) { + if self.pos.0 < offset.x { + println!("delete!"); + delete = true; + } + } + delete + } + + fn size(&self) -> Rect { + Rect { + min: Pos2 { + x: -10f32, + y: -10f32, + }, + max: Pos2 { x: 10f32, y: 10f32 }, + } } } diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 6a3af460..a3daae1b 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -1,59 +1,93 @@ use crate::common::{EguiComponent, Simulator}; use crate::components::Wire; use crate::gui_egui::helper::offset_helper; +use egui::{ + containers, Color32, Id, PointerButton, Pos2, Rect, Response, Sense, Shape, Stroke, Ui, Vec2, +}; #[typetag::serde] impl EguiComponent for Wire { fn render( &self, - ui: &mut egui::Ui, - _simulator: Option, - offset: egui::Vec2, + ui: &mut Ui, + simulator: Option, + offset: Vec2, scale: f32, - _clip_rect: egui::Rect, - ) -> Option { - let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; + _clip_rect: Rect, + ) -> Option { + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; let s = scale; let o = offset; - ui.painter().add(egui::Shape::line_segment( + ui.painter().add(Shape::line_segment( [ oh((0f32, 0f32), s, o), oh((self.delta.0, self.delta.1), s, o), ], - egui::Stroke { + Stroke { width: scale, - color: egui::Color32::BLACK, + color: Color32::BLACK, }, )); - let rect = egui::Rect { + let rect = Rect { min: oh((0f32, 0f32), s, o), max: oh((self.delta.0, self.delta.1), s, o), }; - Some(ui.allocate_rect( + let r = ui.allocate_rect( rect, - egui::Sense { + Sense { click: true, drag: true, focusable: true, }, - )) + ); + if r.hovered() && !r.dragged() { + containers::popup::show_tooltip_for(ui.ctx(), Id::new(self.id.clone()), &rect, |ui| { + ui.label(format!("Id: {}", self.id.clone())); + match simulator { + Some(s) => { + ui.label(format!("{}", s.get_input_val(&self.input))); + } + _ => (), + } + }); + } + + Some(r) } fn render_editor( &mut self, - ui: &mut egui::Ui, + ui: &mut Ui, simulator: Option, - offset: egui::Vec2, + offset: Vec2, scale: f32, - clip_rect: egui::Rect, - ) { + clip_rect: Rect, + ) -> bool { + let mut delete = false; let resp = Wire::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); - if resp.dragged_by(egui::PointerButton::Primary) { + if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta(); self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } + if resp.drag_released_by(PointerButton::Primary) { + if self.pos.0 < offset.x { + println!("delete!"); + delete = true; + } + } + delete + } + + fn size(&self) -> Rect { + Rect { + min: Pos2 { x: 0f32, y: 0f32 }, + max: Pos2 { + x: self.delta.0, + y: self.delta.1, + }, + } } } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 2f42e548..6682754c 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -1,8 +1,9 @@ -use crate::common::ComponentStore; +use crate::common::{ComponentStore, Input}; +use crate::components::*; use crate::gui_egui::{gui::Gui, helper::offset_helper, menu::Menu}; use eframe::{egui, Frame}; -use egui::{Color32, Context, Pos2, Rect, Style, Ui, Vec2}; -use std::path::PathBuf; +use egui::{Color32, Context, PointerButton, Pos2, Rect, Style, Ui, Vec2}; +use std::{cell::RefCell, path::PathBuf, rc::Rc}; pub struct Editor { pub component_store: ComponentStore, @@ -12,6 +13,7 @@ pub struct Editor { pub clip_rect: Rect, pub side_panel_width: f32, pub ui_change: bool, + pub library: ComponentStore, } impl Editor { @@ -30,6 +32,32 @@ impl Editor { }, side_panel_width: 400f32, ui_change: true, + library: ComponentStore { + store: vec![ + Rc::new(RefCell::new(Add { + id: "add".to_string(), + pos: (0.0, 0.0), + a_in: Input::new("c1", 0), + b_in: Input::new("c2", 0), + })), + Rc::new(RefCell::new(Constant { + id: "c1".to_string(), + pos: (0.0, 0.0), + value: 3, + })), + Rc::new(RefCell::new(Wire { + id: "w1".to_string(), + pos: (0.0, 0.0), + delta: (70.0, 0.0), + input: Input::new("c1", 0), + })), + Rc::new(RefCell::new(Probe { + id: "p1".to_string(), + pos: (0.0, 0.0), + input: Input::new("add", 0), + })), + ], + }, } } @@ -52,7 +80,10 @@ impl Editor { y: top.rect.max.y, }; Editor::gui_to_editor(gui).clip_rect = egui::Rect { - min: Editor::gui_to_editor(gui).offset.to_pos2(), + min: egui::Pos2 { + x: 0f32, + y: Editor::gui_to_editor(gui).offset.to_pos2().y, + }, max: egui::Pos2 { x: f32::INFINITY, y: f32::INFINITY, @@ -92,6 +123,7 @@ impl Editor { } } + // Clicking library items will create a clone of them and insert them into the component store fn library(ctx: &Context, gui: &mut Gui) { egui::SidePanel::left("leftLibrary") .default_width(gui.editor.as_mut().unwrap().side_panel_width) @@ -99,8 +131,39 @@ impl Editor { .show(ctx, |ui| { egui::ScrollArea::vertical().show(ui, |ui| { ui.horizontal(|ui| { - - // + let s = Editor::gui_to_editor(gui); + let mut padding = Vec2 { + x: s.offset.x / 2f32, + y: s.offset.y + 10f32, + }; + let clip_rect = Rect { + min: Pos2 { + x: 0f32, + y: s.offset.y, + }, + max: Pos2 { + x: s.offset.x, + y: f32::INFINITY, + }, + }; + for c in s.library.store.iter() { + let size = c.borrow_mut().size(); + padding.y = padding.y - s.scale * size.min.y; + let resp = c + .borrow_mut() + .render(ui, None, padding, s.scale, clip_rect) + .unwrap(); + // Create new component + if resp.drag_started_by(PointerButton::Primary) { + s.component_store.store.push(Rc::new(RefCell::new(Add { + id: "add".to_string(), + pos: (0.0, 0.0), + a_in: Input::new("c1", 0), + b_in: Input::new("c2", 0), + }))); + } + padding.y = resp.rect.max.y + 10f32; + } }); }); }); @@ -128,18 +191,12 @@ impl Editor { } let s = Editor::gui_to_editor(gui); - for c in s.component_store.store.clone() { - let resp = + s.component_store.store.retain(|c| { + let delete = c.borrow_mut() .render_editor(ui, None, s.offset + s.pan, s.scale, s.clip_rect); - //println!("{:?}", r); - //println!("is: {}", ctx.is_pointer_over_area()); - /* - egui::containers::popup::show_tooltip_for(ctx, id, &r, |ui| { - ui.label("asd"); - }); - */ - } + !delete + }); }); let cpr = central_panel.response.interact(egui::Sense::drag()); diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 79947a26..53d26037 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -1,4 +1,4 @@ -use crate::common::ComponentStore; +use crate::common::{ComponentStore, Simulator}; use egui::{Key, KeyboardShortcut, Modifiers}; #[derive(Copy, Clone)] @@ -207,6 +207,12 @@ pub fn file_editor_toggle_fn(gui: &mut crate::gui_egui::gui::Gui) { match gui.editor_use { true => { gui.editor_use = false; + match gui.editor.as_mut() { + Some(e) => { + gui.simulator = Simulator::new(&e.component_store, &mut 0); + } + _ => (), + } // todo: Make us swap back into simulator mode (create new simulator) } false => { From d06db4f94fdc4eb00224741bf6eb359de1f307d2 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Wed, 19 Jul 2023 02:53:54 +0200 Subject: [PATCH 05/58] properties window (only for add right now) --- examples/add.rs | 13 ++- src/common.rs | 10 ++- src/components/add.rs | 15 ++++ src/gui_egui/components/add.rs | 59 ++++++++++++-- src/gui_egui/components/constant.rs | 15 ++-- src/gui_egui/components/probe.rs | 15 ++-- src/gui_egui/components/wire.rs | 18 +++-- src/gui_egui/editor.rs | 120 ++++++++++++++++++++++------ src/gui_egui/helper.rs | 26 +++++- src/gui_egui/mod.rs | 2 +- 10 files changed, 230 insertions(+), 63 deletions(-) diff --git a/examples/add.rs b/examples/add.rs index fda2e7c6..851c289d 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -7,13 +7,12 @@ use syncrim::{ fn main() { let cs = ComponentStore { store: vec![ - Rc::new(RefCell::new(Add { - id: "add".to_string(), - pos: (200.0, 120.0), - a_in: Input::new("c1", 0), - - b_in: Input::new("c2", 0), - })), + Rc::new(RefCell::new(Add::new( + "add".to_string(), + (200.0, 120.0), + Input::new("c1", 0), + Input::new("c2", 0), + ))), Rc::new(RefCell::new(Constant { id: "c1".to_string(), pos: (100.0, 100.0), diff --git a/src/common.rs b/src/common.rs index 59d75263..ac2e8374 100644 --- a/src/common.rs +++ b/src/common.rs @@ -19,7 +19,7 @@ type Components = Vec>>; // todo: Probably make a separate ComponentsEditor type // so we don't have to use refcell everywhere #[cfg(feature = "gui-egui")] -type Components = Vec>>; +pub type Components = Vec>>; #[cfg_attr(feature = "gui-vizia", derive(Lens))] #[derive(Clone)] @@ -89,8 +89,12 @@ pub trait EguiComponent: Component { _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, - ) -> bool { - false + _components: &Components, + ) -> crate::gui_egui::helper::EditorRenderReturn { + crate::gui_egui::helper::EditorRenderReturn { + delete: false, + resp: None, + } } fn size(&self) -> egui::Rect { egui::Rect::NOTHING diff --git a/src/components/add.rs b/src/components/add.rs index 7b1a2160..1da6f381 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -7,6 +7,21 @@ pub struct Add { pub pos: (f32, f32), pub a_in: Input, pub b_in: Input, + // this is ugly... (egui) + #[cfg(feature = "gui-egui")] + pub properties_window: bool, +} + +impl Add { + pub fn new(id: String, pos: (f32, f32), a_in: Input, b_in: Input) -> Self { + Add { + id, + pos, + a_in, + b_in, + properties_window: false, + } + } } #[typetag::serde] diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 0cd6354d..e75a19eb 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,9 +1,12 @@ -use crate::gui_egui::helper::{offset_helper, out_of_bounds}; +use crate::gui_egui::helper::{offset_helper, out_of_bounds, EditorRenderReturn}; use crate::{ - common::{EguiComponent, Simulator}, + common::{Components, EguiComponent, Simulator}, components::Add, }; -use egui::{PointerButton, Pos2, Rect, Sense, Vec2}; +use egui::{ + containers::{ComboBox, Window}, + PointerButton, Pos2, Rect, Sense, Vec2, +}; #[typetag::serde] impl EguiComponent for Add { @@ -92,20 +95,62 @@ impl EguiComponent for Add { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - ) -> bool { + cs: &Components, + ) -> EditorRenderReturn { let mut delete = false; let resp = Add::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta(); self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } + if resp.drag_released_by(PointerButton::Primary) { - if self.pos.0 < offset.x { - println!("delete!"); + if resp.interact_pointer_pos().unwrap().x < offset.x { delete = true; } } - delete + if self.properties_window { + let mut a_in = self.a_in.id.clone(); + let mut b_in = self.b_in.id.clone(); + let resp = Window::new(format!("Properties: {}", self.id)).show(ui.ctx(), |ui| { + let r = ComboBox::from_label("a_in") + .selected_text(format!("{:?}", a_in)) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => self.id.clone(), + }; + ui.selectable_value(&mut a_in, id.clone(), id); + } + }); + let r2 = ComboBox::from_label("b_in") + .selected_text(format!("{:?}", b_in)) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => self.id.clone(), + }; + ui.selectable_value(&mut b_in, id.clone(), id); + } + }); + }); + if resp.unwrap().response.clicked_elsewhere() { + self.properties_window = false; + } + } + + if resp.clicked_by(PointerButton::Secondary) { + println!("opening properties window"); + // Open properties window + self.properties_window = true; + } + + EditorRenderReturn { + delete, + resp: Some(resp), + } } fn size(&self) -> Rect { diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 247a2779..02f06dc1 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,6 +1,6 @@ -use crate::common::{EguiComponent, Simulator}; +use crate::common::{Components, EguiComponent, Simulator}; use crate::components::Constant; -use crate::gui_egui::helper::out_of_bounds; +use crate::gui_egui::helper::{out_of_bounds, EditorRenderReturn}; use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Sense}; #[typetag::serde] @@ -63,7 +63,8 @@ impl EguiComponent for Constant { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - ) -> bool { + _cs: &Components, + ) -> EditorRenderReturn { let mut delete = false; let resp = Constant::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); if resp.dragged_by(PointerButton::Primary) { @@ -71,12 +72,14 @@ impl EguiComponent for Constant { self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } if resp.drag_released_by(PointerButton::Primary) { - if self.pos.0 < offset.x { - println!("delete!"); + if resp.interact_pointer_pos().unwrap().x < offset.x { delete = true; } } - delete + EditorRenderReturn { + delete, + resp: Some(resp), + } } fn size(&self) -> Rect { diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 32c72b69..5c84f21f 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -1,6 +1,6 @@ -use crate::common::{EguiComponent, Simulator}; +use crate::common::{Components, EguiComponent, Simulator}; use crate::components::Probe; -use crate::gui_egui::helper::out_of_bounds; +use crate::gui_egui::helper::{out_of_bounds, EditorRenderReturn}; use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Sense}; #[typetag::serde] @@ -69,7 +69,8 @@ impl EguiComponent for Probe { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - ) -> bool { + _cs: &Components, + ) -> EditorRenderReturn { let mut delete = false; let resp = Probe::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); if resp.dragged_by(egui::PointerButton::Primary) { @@ -77,12 +78,14 @@ impl EguiComponent for Probe { self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } if resp.drag_released_by(PointerButton::Primary) { - if self.pos.0 < offset.x { - println!("delete!"); + if resp.interact_pointer_pos().unwrap().x < offset.x { delete = true; } } - delete + EditorRenderReturn { + delete, + resp: Some(resp), + } } fn size(&self) -> Rect { diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index a3daae1b..bcf8991d 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -1,6 +1,6 @@ -use crate::common::{EguiComponent, Simulator}; +use crate::common::{Components, EguiComponent, Simulator}; use crate::components::Wire; -use crate::gui_egui::helper::offset_helper; +use crate::gui_egui::helper::{offset_helper, out_of_bounds, EditorRenderReturn}; use egui::{ containers, Color32, Id, PointerButton, Pos2, Rect, Response, Sense, Shape, Stroke, Ui, Vec2, }; @@ -13,7 +13,7 @@ impl EguiComponent for Wire { simulator: Option, offset: Vec2, scale: f32, - _clip_rect: Rect, + clip_rect: Rect, ) -> Option { let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; let mut offset = offset; @@ -35,6 +35,7 @@ impl EguiComponent for Wire { min: oh((0f32, 0f32), s, o), max: oh((self.delta.0, self.delta.1), s, o), }; + let rect = out_of_bounds(rect, clip_rect); let r = ui.allocate_rect( rect, Sense { @@ -65,7 +66,8 @@ impl EguiComponent for Wire { offset: Vec2, scale: f32, clip_rect: Rect, - ) -> bool { + _cs: &Components, + ) -> EditorRenderReturn { let mut delete = false; let resp = Wire::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); if resp.dragged_by(PointerButton::Primary) { @@ -73,12 +75,14 @@ impl EguiComponent for Wire { self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } if resp.drag_released_by(PointerButton::Primary) { - if self.pos.0 < offset.x { - println!("delete!"); + if resp.interact_pointer_pos().unwrap().x < offset.x { delete = true; } } - delete + EditorRenderReturn { + delete, + resp: Some(resp), + } } fn size(&self) -> Rect { diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 6682754c..72d8a69f 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -1,8 +1,12 @@ -use crate::common::{ComponentStore, Input}; +use crate::common::{ComponentStore, EguiComponent, Input}; use crate::components::*; -use crate::gui_egui::{gui::Gui, helper::offset_helper, menu::Menu}; +use crate::gui_egui::{ + gui::Gui, + helper::{offset_helper, unique_component_name}, + menu::Menu, +}; use eframe::{egui, Frame}; -use egui::{Color32, Context, PointerButton, Pos2, Rect, Style, Ui, Vec2}; +use egui::{Color32, Context, PointerButton, Pos2, Rect, Response, Style, Ui, Vec2}; use std::{cell::RefCell, path::PathBuf, rc::Rc}; pub struct Editor { @@ -14,10 +18,12 @@ pub struct Editor { pub side_panel_width: f32, pub ui_change: bool, pub library: ComponentStore, + pub dummy_input: Input, } impl Editor { pub fn gui(cs: ComponentStore, _path: &PathBuf) -> Self { + let dummy_input = Input::new("x", 0); Editor { component_store: cs, scale: 1f32, @@ -34,30 +40,31 @@ impl Editor { ui_change: true, library: ComponentStore { store: vec![ - Rc::new(RefCell::new(Add { - id: "add".to_string(), - pos: (0.0, 0.0), - a_in: Input::new("c1", 0), - b_in: Input::new("c2", 0), - })), + Rc::new(RefCell::new(Add::new( + "add".to_string(), + (0.0, 0.0), + dummy_input.clone(), + dummy_input.clone(), + ))), Rc::new(RefCell::new(Constant { - id: "c1".to_string(), + id: "c".to_string(), pos: (0.0, 0.0), - value: 3, + value: 0, })), Rc::new(RefCell::new(Wire { - id: "w1".to_string(), + id: "w".to_string(), pos: (0.0, 0.0), delta: (70.0, 0.0), - input: Input::new("c1", 0), + input: dummy_input.clone(), })), Rc::new(RefCell::new(Probe { - id: "p1".to_string(), + id: "p".to_string(), pos: (0.0, 0.0), - input: Input::new("add", 0), + input: dummy_input.clone(), })), ], }, + dummy_input, } } @@ -81,7 +88,8 @@ impl Editor { }; Editor::gui_to_editor(gui).clip_rect = egui::Rect { min: egui::Pos2 { - x: 0f32, + //x: 0f32, + x: Editor::gui_to_editor(gui).offset.to_pos2().x, y: Editor::gui_to_editor(gui).offset.to_pos2().y, }, max: egui::Pos2 { @@ -153,14 +161,74 @@ impl Editor { .borrow_mut() .render(ui, None, padding, s.scale, clip_rect) .unwrap(); + // Create new component if resp.drag_started_by(PointerButton::Primary) { - s.component_store.store.push(Rc::new(RefCell::new(Add { - id: "add".to_string(), - pos: (0.0, 0.0), - a_in: Input::new("c1", 0), - b_in: Input::new("c2", 0), - }))); + let _resp = match c.borrow_mut().get_id_ports().0.as_str() { + // todo: Make this a lot better and not hardcoded + "c" => { + let id = unique_component_name(&s.component_store, "c"); + let comp: Rc> = + Rc::new(RefCell::new(Constant { + id, + pos: (0.0, 0.0), + value: 0, + })); + let resp = comp + .borrow_mut() + .render(ui, None, padding, s.scale, clip_rect); + s.component_store.store.push(comp); + resp + } + "w" => { + let id = unique_component_name(&s.component_store, "w"); + let comp: Rc> = + Rc::new(RefCell::new(Wire { + id, + pos: (0.0, 0.0), + delta: (70.0, 0.0), + input: s.dummy_input.clone(), + })); + let resp = comp + .borrow_mut() + .render(ui, None, padding, s.scale, clip_rect); + s.component_store.store.push(comp); + resp + } + "p" => { + let id = unique_component_name(&s.component_store, "p"); + let comp: Rc> = + Rc::new(RefCell::new(Probe { + id, + pos: (0.0, 0.0), + input: s.dummy_input.clone(), + })); + let resp = comp + .borrow_mut() + .render(ui, None, padding, s.scale, clip_rect); + s.component_store.store.push(comp); + resp + } + "add" | _ => { + let id = unique_component_name(&s.component_store, "add"); + let comp: Rc> = + Rc::new(RefCell::new(Add::new( + id, + (0.0, 0.0), + s.dummy_input.clone(), + s.dummy_input.clone(), + ))); + let resp = comp + .borrow_mut() + .render(ui, None, padding, s.scale, clip_rect); + s.component_store.store.push(comp); + resp + } + }; + // todo: use resp to make it draggable instantly + // I'm unsure if this is actually possible + // since it's not possible to create events/set currently + // dragged entity } padding.y = resp.rect.max.y + 10f32; } @@ -190,11 +258,13 @@ impl Editor { )); } + let xd = gui.simulator.ordered_components.clone(); let s = Editor::gui_to_editor(gui); s.component_store.store.retain(|c| { - let delete = - c.borrow_mut() - .render_editor(ui, None, s.offset + s.pan, s.scale, s.clip_rect); + let delete = c + .borrow_mut() + .render_editor(ui, None, s.offset + s.pan, s.scale, s.clip_rect, &xd) + .delete; !delete }); }); diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 277e18cb..603bac5e 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -1,4 +1,10 @@ -use egui::{Pos2, Rect, Vec2}; +use crate::common::ComponentStore; +use egui::{Pos2, Rect, Response, Vec2}; + +pub struct EditorRenderReturn { + pub delete: bool, + pub resp: Option, +} pub fn offset_helper(xy: (f32, f32), scale: f32, offset: Vec2) -> Pos2 { egui::Pos2 { @@ -30,4 +36,22 @@ pub fn out_of_bounds(request: Rect, clip_rect: Rect) -> Rect { return rect; } +pub fn unique_component_name(cs: &ComponentStore, id: &str) -> String { + let mut new_id: String = id.into(); + let mut contains_id = true; + while contains_id { + contains_id = false; + for c in cs.store.iter() { + let (id, _) = c.borrow_mut().get_id_ports(); + if id == new_id { + contains_id = true; + // todo: make this fancier + new_id.push_str("1"); + break; + } + } + } + String::from(new_id) +} + //pub fn diff --git a/src/gui_egui/mod.rs b/src/gui_egui/mod.rs index 6c7aef5a..f6a86c70 100644 --- a/src/gui_egui/mod.rs +++ b/src/gui_egui/mod.rs @@ -1,6 +1,6 @@ mod editor; mod gui; -mod helper; +pub mod helper; mod keymap; mod menu; From 3ecaad91a983668651865cb76cb2bb6f5aa07feb Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Wed, 19 Jul 2023 15:43:56 +0200 Subject: [PATCH 06/58] properties window now allows to select inputs and their fields as well as changing the id and position --- examples/add.rs | 66 ++++++------- src/common.rs | 6 ++ src/components/add.rs | 5 +- src/components/constant.rs | 15 +++ src/components/probe.rs | 15 +++ src/components/wire.rs | 16 ++++ src/fern.rs | 3 + src/gui_egui/components/add.rs | 140 ++++++++++++++++++++++------ src/gui_egui/components/constant.rs | 68 +++++++++++++- src/gui_egui/components/probe.rs | 99 +++++++++++++++++++- src/gui_egui/components/wire.rs | 83 ++++++++++++++++- src/gui_egui/editor.rs | 78 +++++++++------- src/gui_egui/helper.rs | 13 ++- 13 files changed, 494 insertions(+), 113 deletions(-) diff --git a/examples/add.rs b/examples/add.rs index 0c6476d5..4f9ed779 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -15,39 +15,39 @@ fn main() { Input::new("c1", "out"), Input::new("c2", "out"), ))), - Rc::new(RefCell::new(Constant { - id: "c1".to_string(), - pos: (100.0, 100.0), - value: 3, - })), - Rc::new(RefCell::new(Constant { - id: "c2".to_string(), - pos: (100.0, 140.0), - value: 4, - })), - Rc::new(RefCell::new(Wire { - id: "w1".to_string(), - pos: (110.0, 100.0), - delta: (70.0, 0.0), - input: Input::new("c1", "out"), - })), - Rc::new(RefCell::new(Wire { - id: "w2".to_string(), - pos: (110.0, 140.0), - delta: (70.0, 0.0), - input: Input::new("c2", "out"), - })), - Rc::new(RefCell::new(Wire { - id: "w3".to_string(), - pos: (220.0, 120.0), - delta: (40.0, 0.0), - input: Input::new("add", "out"), - })), - Rc::new(RefCell::new(Probe { - id: "p1".to_string(), - pos: (270.0, 120.0), - input: Input::new("add", "out"), - })), + Rc::new(RefCell::new(Constant::new( + "c1".to_string(), + (100.0, 100.0), + 3, + ))), + Rc::new(RefCell::new(Constant::new( + "c2".to_string(), + (100.0, 140.0), + 4, + ))), + Rc::new(RefCell::new(Wire::new( + "w1".to_string(), + (110.0, 100.0), + (70.0, 0.0), + Input::new("c1", "out"), + ))), + Rc::new(RefCell::new(Wire::new( + "w2".to_string(), + (110.0, 140.0), + (70.0, 0.0), + Input::new("c2", "out"), + ))), + Rc::new(RefCell::new(Wire::new( + "w3".to_string(), + (220.0, 120.0), + (40.0, 0.0), + Input::new("add", "out"), + ))), + Rc::new(RefCell::new(Probe::new( + "p1".to_string(), + (270.0, 120.0), + Input::new("add", "out"), + ))), ], }; diff --git a/src/common.rs b/src/common.rs index b907c347..fbcff2d7 100644 --- a/src/common.rs +++ b/src/common.rs @@ -111,6 +111,12 @@ pub trait EguiComponent: Component { } } +#[cfg(feature = "gui-egui")] +pub struct EguiExtra { + pub properties_window: bool, + pub id_tmp: String, +} + #[derive(Debug, Clone)] pub struct Ports { pub inputs: Vec, diff --git a/src/components/add.rs b/src/components/add.rs index 0f99eebf..bc4bb141 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -9,18 +9,19 @@ pub struct Add { pub a_in: Input, pub b_in: Input, // this is ugly... (egui) - #[cfg(feature = "gui-egui")] pub properties_window: bool, + pub id_tmp: Id, } impl Add { pub fn new(id: String, pos: (f32, f32), a_in: Input, b_in: Input) -> Self { Add { - id, + id: id.clone(), pos, a_in, b_in, properties_window: false, + id_tmp: id, } } } diff --git a/src/components/constant.rs b/src/components/constant.rs index a0b98866..4ce8ad3b 100644 --- a/src/components/constant.rs +++ b/src/components/constant.rs @@ -6,6 +6,21 @@ pub struct Constant { pub id: Id, pub pos: (f32, f32), pub value: Signal, + // this is ugly... (egui) + pub properties_window: bool, + pub id_tmp: Id, +} + +impl Constant { + pub fn new(id: String, pos: (f32, f32), value: Signal) -> Self { + Constant { + id: id.clone(), + pos, + value, + properties_window: false, + id_tmp: id, + } + } } #[typetag::serde] diff --git a/src/components/probe.rs b/src/components/probe.rs index 1d5436ca..b24915d0 100644 --- a/src/components/probe.rs +++ b/src/components/probe.rs @@ -6,6 +6,21 @@ pub struct Probe { pub id: Id, pub pos: (f32, f32), pub input: Input, + // this is ugly... (egui) + pub properties_window: bool, + pub id_tmp: Id, +} + +impl Probe { + pub fn new(id: String, pos: (f32, f32), input: Input) -> Self { + Probe { + id: id.clone(), + pos, + input, + properties_window: false, + id_tmp: id, + } + } } #[typetag::serde] diff --git a/src/components/wire.rs b/src/components/wire.rs index 4b461ac6..3db5eb6c 100644 --- a/src/components/wire.rs +++ b/src/components/wire.rs @@ -7,6 +7,22 @@ pub struct Wire { pub pos: (f32, f32), pub delta: (f32, f32), pub input: Input, + // this is ugly... (egui) + pub properties_window: bool, + pub id_tmp: Id, +} + +impl Wire { + pub fn new(id: String, pos: (f32, f32), delta: (f32, f32), input: Input) -> Self { + Wire { + id: id.clone(), + pos, + delta, + input, + properties_window: false, + id_tmp: id, + } + } } #[typetag::serde] diff --git a/src/fern.rs b/src/fern.rs index 9704d145..0c24e37c 100644 --- a/src/fern.rs +++ b/src/fern.rs @@ -30,6 +30,9 @@ pub fn fern_setup() { .level_for("cosmic_text::font::fallback", LevelFilter::Warn) .level_for("async_io::driver", LevelFilter::Warn); + #[cfg(feature = "gui-egui")] + let f = f.level_for("eframe::native::run", LevelFilter::Info); + f // Output to stdout, files, and other Dispatch configurations .chain(std::io::stdout()) diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index ccf7fb58..646efa0a 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,12 +1,15 @@ -use crate::gui_egui::helper::{offset_helper, out_of_bounds, EditorRenderReturn}; +use crate::gui_egui::helper::{ + offset_helper, out_of_bounds, unique_component_name, EditorRenderReturn, +}; use crate::{ common::{Components, EguiComponent, Simulator}, components::Add, }; use egui::{ containers::{ComboBox, Window}, - PointerButton, Pos2, Rect, Sense, Vec2, + Frame, Margin, PointerButton, Pos2, Rect, Rounding, Sense, Vec2, }; +use epaint::Shadow; #[typetag::serde] impl EguiComponent for Add { @@ -100,7 +103,7 @@ impl EguiComponent for Add { let mut delete = false; let resp = Add::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta(); + let delta = resp.drag_delta() / scale; self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } @@ -112,37 +115,122 @@ impl EguiComponent for Add { if self.properties_window { let mut a_in = self.a_in.id.clone(); let mut b_in = self.b_in.id.clone(); - let resp = Window::new(format!("Properties: {}", self.id)).show(ui.ctx(), |ui| { - let r = ComboBox::from_label("a_in") - .selected_text(format!("{:?}", a_in)) - .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => self.id.clone(), - }; - ui.selectable_value(&mut a_in, id.clone(), id); + let mut a_in_field = self.a_in.field.clone(); + let mut b_in_field = self.b_in.field.clone(); + let w_resp = Window::new(format!("Properties: {}", self.id)) + .frame(Frame { + inner_margin: Margin::same(10f32), + outer_margin: Margin::same(0f32), + rounding: Rounding::same(10f32), + shadow: Shadow::small_dark(), + fill: ui.visuals().panel_fill, + stroke: ui.visuals().window_stroke, + }) + .default_pos(Pos2 { + x: (resp.rect.min.x + resp.rect.max.x) / 2f32, + y: (resp.rect.min.y + resp.rect.max.y) / 2f32, + }) + .show(ui.ctx(), |ui| { + ui.horizontal(|ui| { + let id_label = ui.label("Id: "); + let r = ui + .text_edit_singleline(&mut self.id_tmp) + .labelled_by(id_label.id); + if r.lost_focus() && self.id_tmp != self.id { + self.id = unique_component_name(cs, self.id_tmp.as_str()); } }); - let r2 = ComboBox::from_label("b_in") - .selected_text(format!("{:?}", b_in)) - .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => self.id.clone(), - }; - ui.selectable_value(&mut b_in, id.clone(), id); - } + + ui.horizontal(|ui| { + ui.add( + egui::Slider::new(&mut self.pos.0, 0f32..=1000f32) + .text("pos x") + .clamp_to_range(false), + ); + ui.add( + egui::Slider::new(&mut self.pos.1, 0f32..=1000f32) + .text("pos y") + .clamp_to_range(false), + ); + }); + ui.horizontal(|ui| { + ComboBox::from_label("a_in.id") + .selected_text(format!("{}", a_in)) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => self.id.clone(), + }; + ui.selectable_value(&mut a_in, id.clone(), id); + } + }); + ComboBox::from_label("a_in.field") + .selected_text(format!("{}", b_in_field)) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => self.id.clone(), + }; + if id != a_in { + continue; + } + let fields = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().1.outputs, + Err(_) => vec![], + }; + for field in fields { + ui.selectable_value(&mut b_in_field, field.clone(), field); + } + } + }); + }); + + ui.horizontal(|ui| { + ComboBox::from_label("b_in.id") + .selected_text(format!("{}", b_in)) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => self.id.clone(), + }; + ui.selectable_value(&mut b_in, id.clone(), id); + } + }); + ComboBox::from_label("b_in.field") + .selected_text(format!("{}", b_in_field)) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => self.id.clone(), + }; + if id != b_in { + continue; + } + let fields = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().1.outputs, + Err(_) => vec![], + }; + for field in fields { + ui.selectable_value(&mut b_in_field, field.clone(), field); + } + } + }); }); - }); - if resp.unwrap().response.clicked_elsewhere() { + self.a_in.id = a_in; + self.b_in.id = b_in; + self.a_in.field = a_in_field; + self.b_in.field = b_in_field; + }); + if w_resp.unwrap().response.clicked_elsewhere() { self.properties_window = false; } } if resp.clicked_by(PointerButton::Secondary) { - println!("opening properties window"); // Open properties window self.properties_window = true; } diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 02f06dc1..35d9a9ab 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,7 +1,11 @@ use crate::common::{Components, EguiComponent, Simulator}; use crate::components::Constant; -use crate::gui_egui::helper::{out_of_bounds, EditorRenderReturn}; -use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Sense}; +use crate::gui_egui::helper::{out_of_bounds, unique_component_name, EditorRenderReturn}; +use egui::{ + Align2, Area, Color32, Frame, Margin, Order, PointerButton, Pos2, Rect, RichText, Rounding, + Sense, Window, +}; +use epaint::Shadow; #[typetag::serde] impl EguiComponent for Constant { @@ -63,12 +67,12 @@ impl EguiComponent for Constant { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - _cs: &Components, + cs: &Components, ) -> EditorRenderReturn { let mut delete = false; let resp = Constant::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta(); + let delta = resp.drag_delta() / scale; self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } if resp.drag_released_by(PointerButton::Primary) { @@ -76,6 +80,62 @@ impl EguiComponent for Constant { delete = true; } } + + if self.properties_window { + let resp = Window::new(format!("Properties: {}", self.id)) + .frame(Frame { + inner_margin: Margin::same(10f32), + outer_margin: Margin::same(0f32), + rounding: Rounding::same(10f32), + shadow: Shadow::small_dark(), + fill: ui.visuals().panel_fill, + stroke: ui.visuals().window_stroke, + }) + .default_pos(Pos2 { + x: (resp.rect.min.x + resp.rect.max.x) / 2f32, + y: (resp.rect.min.y + resp.rect.max.y) / 2f32, + }) + .show(ui.ctx(), |ui| { + ui.horizontal(|ui| { + let id_label = ui.label("Id: "); + let r = ui + .text_edit_singleline(&mut self.id_tmp) + .labelled_by(id_label.id); + if r.lost_focus() && self.id_tmp != self.id { + self.id = unique_component_name(cs, self.id_tmp.as_str()); + } + }); + + ui.horizontal(|ui| { + ui.add( + egui::Slider::new(&mut self.pos.0, 0f32..=1000f32) + .text("pos x") + .clamp_to_range(false), + ); + ui.add( + egui::Slider::new(&mut self.pos.1, 0f32..=1000f32) + .text("pos y") + .clamp_to_range(false), + ); + }); + ui.add(egui::Slider::new(&mut self.value, u32::MIN..=u32::MAX).text("value")); + /* + ui.horizontal(|ui| { + + ui.text_edit_singleline(value); + }); + */ + }); + if resp.unwrap().response.clicked_elsewhere() { + self.properties_window = false; + } + } + + if resp.clicked_by(PointerButton::Secondary) { + // Open properties window + self.properties_window = true; + } + EditorRenderReturn { delete, resp: Some(resp), diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 5c84f21f..977a01e4 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -1,7 +1,11 @@ use crate::common::{Components, EguiComponent, Simulator}; use crate::components::Probe; -use crate::gui_egui::helper::{out_of_bounds, EditorRenderReturn}; -use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Sense}; +use crate::gui_egui::helper::{out_of_bounds, unique_component_name, EditorRenderReturn}; +use egui::{ + Align2, Area, Color32, ComboBox, Frame, Margin, Order, PointerButton, Pos2, Rect, RichText, + Rounding, Sense, Window, +}; +use epaint::Shadow; #[typetag::serde] impl EguiComponent for Probe { @@ -69,19 +73,106 @@ impl EguiComponent for Probe { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - _cs: &Components, + cs: &Components, ) -> EditorRenderReturn { let mut delete = false; let resp = Probe::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); if resp.dragged_by(egui::PointerButton::Primary) { - let delta = resp.drag_delta(); + let delta = resp.drag_delta() / scale; self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } + if resp.drag_released_by(PointerButton::Primary) { if resp.interact_pointer_pos().unwrap().x < offset.x { delete = true; } } + + if self.properties_window { + let mut input = self.input.id.clone(); + let mut input_field = self.input.field.clone(); + let resp = Window::new(format!("Properties: {}", self.id)) + .frame(Frame { + inner_margin: Margin::same(10f32), + outer_margin: Margin::same(0f32), + rounding: Rounding::same(10f32), + shadow: Shadow::small_dark(), + fill: ui.visuals().panel_fill, + stroke: ui.visuals().window_stroke, + }) + .default_pos(Pos2 { + x: (resp.rect.min.x + resp.rect.max.x) / 2f32, + y: (resp.rect.min.y + resp.rect.max.y) / 2f32, + }) + .show(ui.ctx(), |ui| { + ui.horizontal(|ui| { + let id_label = ui.label("Id: "); + let r = ui + .text_edit_singleline(&mut self.id_tmp) + .labelled_by(id_label.id); + if r.lost_focus() && self.id_tmp != self.id { + self.id = unique_component_name(cs, self.id_tmp.as_str()); + } + }); + + ui.horizontal(|ui| { + ui.add( + egui::Slider::new(&mut self.pos.0, 0f32..=1000f32) + .text("pos x") + .clamp_to_range(false), + ); + ui.add( + egui::Slider::new(&mut self.pos.1, 0f32..=1000f32) + .text("pos y") + .clamp_to_range(false), + ); + }); + ui.horizontal(|ui| { + ComboBox::from_label("input") + .selected_text(format!("{}", input)) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => self.id.clone(), + }; + ui.selectable_value(&mut input, id.clone(), id); + } + }); + ComboBox::from_label("field") + .selected_text(format!("{}", input_field)) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => self.id.clone(), + }; + if id != input { + continue; + } + let fields = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().1.outputs, + Err(_) => vec![self.input.id.clone()], + }; + for field in fields { + ui.selectable_value(&mut input_field, field.clone(), field); + } + } + }); + }); + self.input.id = input; + self.input.field = input_field; + }); + if resp.unwrap().response.clicked_elsewhere() { + self.properties_window = false; + } + } + + if resp.clicked_by(PointerButton::Secondary) { + // Open properties window + self.properties_window = true; + } + EditorRenderReturn { delete, resp: Some(resp), diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index bcf8991d..2e7f2de8 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -1,9 +1,13 @@ use crate::common::{Components, EguiComponent, Simulator}; use crate::components::Wire; -use crate::gui_egui::helper::{offset_helper, out_of_bounds, EditorRenderReturn}; +use crate::gui_egui::helper::{ + offset_helper, out_of_bounds, unique_component_name, EditorRenderReturn, +}; use egui::{ - containers, Color32, Id, PointerButton, Pos2, Rect, Response, Sense, Shape, Stroke, Ui, Vec2, + containers, Color32, ComboBox, Frame, Id, Margin, PointerButton, Pos2, Rect, Response, + Rounding, Sense, Shape, Stroke, Ui, Vec2, Window, }; +use epaint::Shadow; #[typetag::serde] impl EguiComponent for Wire { @@ -66,12 +70,12 @@ impl EguiComponent for Wire { offset: Vec2, scale: f32, clip_rect: Rect, - _cs: &Components, + cs: &Components, ) -> EditorRenderReturn { let mut delete = false; let resp = Wire::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta(); + let delta = resp.drag_delta() / scale; self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } if resp.drag_released_by(PointerButton::Primary) { @@ -79,6 +83,77 @@ impl EguiComponent for Wire { delete = true; } } + if self.properties_window { + let mut input = self.input.id.clone(); + let resp = Window::new(format!("Properties: {}", self.id)) + .frame(Frame { + inner_margin: Margin::same(10f32), + outer_margin: Margin::same(0f32), + rounding: Rounding::same(10f32), + shadow: Shadow::small_dark(), + fill: ui.visuals().panel_fill, + stroke: ui.visuals().window_stroke, + }) + .default_pos(Pos2 { + x: (resp.rect.min.x + resp.rect.max.x) / 2f32, + y: (resp.rect.min.y + resp.rect.max.y) / 2f32, + }) + .show(ui.ctx(), |ui| { + ui.horizontal(|ui| { + let id_label = ui.label("Id: "); + let r = ui + .text_edit_singleline(&mut self.id_tmp) + .labelled_by(id_label.id); + if r.lost_focus() && self.id_tmp != self.id { + self.id = unique_component_name(cs, self.id_tmp.as_str()); + } + }); + + ui.horizontal(|ui| { + ui.add( + egui::Slider::new(&mut self.pos.0, 0f32..=1000f32) + .text("pos x") + .clamp_to_range(false), + ); + ui.add( + egui::Slider::new(&mut self.pos.1, 0f32..=1000f32) + .text("pos y") + .clamp_to_range(false), + ); + }); + let r = ComboBox::from_label("input") + .selected_text(format!("{}", input)) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => self.id.clone(), + }; + ui.selectable_value(&mut input, id.clone(), id); + } + }); + ui.add( + egui::Slider::new(&mut self.delta.0, 0f32..=1000f32) + .text("delta x") + .clamp_to_range(false), + ); + ui.add( + egui::Slider::new(&mut self.delta.1, 0f32..=1000f32) + .text("delta y") + .clamp_to_range(false), + ); + self.input.id = input; + }); + if resp.unwrap().response.clicked_elsewhere() { + self.properties_window = false; + } + } + + if resp.clicked_by(PointerButton::Secondary) { + // Open properties window + self.properties_window = true; + } + EditorRenderReturn { delete, resp: Some(resp), diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index a471bbb6..789727bd 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -3,6 +3,7 @@ use crate::components::*; use crate::gui_egui::{ gui::Gui, helper::{offset_helper, unique_component_name}, + keymap, menu::Menu, }; use eframe::{egui, Frame}; @@ -46,22 +47,18 @@ impl Editor { dummy_input.clone(), dummy_input.clone(), ))), - Rc::new(RefCell::new(Constant { - id: "c".to_string(), - pos: (0.0, 0.0), - value: 0, - })), - Rc::new(RefCell::new(Wire { - id: "w".to_string(), - pos: (0.0, 0.0), - delta: (70.0, 0.0), - input: dummy_input.clone(), - })), - Rc::new(RefCell::new(Probe { - id: "p".to_string(), - pos: (0.0, 0.0), - input: dummy_input.clone(), - })), + Rc::new(RefCell::new(Constant::new("c".to_string(), (0.0, 0.0), 0))), + Rc::new(RefCell::new(Wire::new( + "w".to_string(), + (0.0, 0.0), + (70.0, 0.0), + dummy_input.clone(), + ))), + Rc::new(RefCell::new(Probe::new( + "p".to_string(), + (0.0, 0.0), + dummy_input.clone(), + ))), ], }, dummy_input, @@ -167,13 +164,10 @@ impl Editor { let _resp = match c.borrow_mut().get_id_ports().0.as_str() { // todo: Make this a lot better and not hardcoded "c" => { - let id = unique_component_name(&s.component_store, "c"); + let id = + unique_component_name(&s.component_store.store, "c"); let comp: Rc> = - Rc::new(RefCell::new(Constant { - id, - pos: (0.0, 0.0), - value: 0, - })); + Rc::new(RefCell::new(Constant::new(id, (0.0, 0.0), 0))); let resp = comp .borrow_mut() .render(ui, None, padding, s.scale, clip_rect); @@ -181,14 +175,15 @@ impl Editor { resp } "w" => { - let id = unique_component_name(&s.component_store, "w"); + let id = + unique_component_name(&s.component_store.store, "w"); let comp: Rc> = - Rc::new(RefCell::new(Wire { + Rc::new(RefCell::new(Wire::new( id, - pos: (0.0, 0.0), - delta: (70.0, 0.0), - input: s.dummy_input.clone(), - })); + (0.0, 0.0), + (70.0, 0.0), + s.dummy_input.clone(), + ))); let resp = comp .borrow_mut() .render(ui, None, padding, s.scale, clip_rect); @@ -196,13 +191,14 @@ impl Editor { resp } "p" => { - let id = unique_component_name(&s.component_store, "p"); + let id = + unique_component_name(&s.component_store.store, "p"); let comp: Rc> = - Rc::new(RefCell::new(Probe { + Rc::new(RefCell::new(Probe::new( id, - pos: (0.0, 0.0), - input: s.dummy_input.clone(), - })); + (0.0, 0.0), + s.dummy_input.clone(), + ))); let resp = comp .borrow_mut() .render(ui, None, padding, s.scale, clip_rect); @@ -210,7 +206,8 @@ impl Editor { resp } "add" | _ => { - let id = unique_component_name(&s.component_store, "add"); + let id = + unique_component_name(&s.component_store.store, "add"); let comp: Rc> = Rc::new(RefCell::new(Add::new( id, @@ -258,12 +255,12 @@ impl Editor { )); } - let xd = gui.simulator.ordered_components.clone(); + let tcs = gui.simulator.ordered_components.clone(); let s = Editor::gui_to_editor(gui); s.component_store.store.retain(|c| { let delete = c .borrow_mut() - .render_editor(ui, None, s.offset + s.pan, s.scale, s.clip_rect, &xd) + .render_editor(ui, None, s.offset + s.pan, s.scale, s.clip_rect, &tcs) .delete; !delete }); @@ -273,6 +270,15 @@ impl Editor { if cpr.dragged_by(egui::PointerButton::Middle) { Editor::gui_to_editor(gui).pan += cpr.drag_delta(); } + if central_panel.response.hovered() { + ctx.input_mut(|i| { + if i.scroll_delta.y > 0f32 { + keymap::view_zoom_in_fn(gui); + } else if i.scroll_delta.y < 0f32 { + keymap::view_zoom_out_fn(gui); + } + }); + } } fn gui_to_editor(gui: &mut Gui) -> &mut Editor { diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 603bac5e..71f132ea 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -1,4 +1,4 @@ -use crate::common::ComponentStore; +use crate::common::Components; use egui::{Pos2, Rect, Response, Vec2}; pub struct EditorRenderReturn { @@ -36,13 +36,16 @@ pub fn out_of_bounds(request: Rect, clip_rect: Rect) -> Rect { return rect; } -pub fn unique_component_name(cs: &ComponentStore, id: &str) -> String { +pub fn unique_component_name(cs: &Components, id: &str) -> String { let mut new_id: String = id.into(); let mut contains_id = true; while contains_id { contains_id = false; - for c in cs.store.iter() { - let (id, _) = c.borrow_mut().get_id_ports(); + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0, + Err(e) => String::from(""), + }; if id == new_id { contains_id = true; // todo: make this fancier @@ -54,4 +57,6 @@ pub fn unique_component_name(cs: &ComponentStore, id: &str) -> String { String::from(new_id) } +// todo: Create the properties window the same way every time for the different components + //pub fn From 1521379a34cca7ca0a50938cde03508bab266106 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Fri, 21 Jul 2023 23:02:54 +0200 Subject: [PATCH 07/58] wire work on the editor, massive changes coming --- src/common.rs | 9 +- src/gui_egui/components/add.rs | 42 ++- src/gui_egui/components/constant.rs | 22 +- src/gui_egui/components/mux.rs | 2 +- src/gui_egui/components/probe.rs | 9 +- src/gui_egui/components/probe_out.rs | 2 +- src/gui_egui/components/register.rs | 2 +- src/gui_egui/components/sext.rs | 2 +- src/gui_egui/components/wire.rs | 236 +++++++++-------- src/gui_egui/editor.rs | 376 +++++++++++++++++++++------ src/gui_egui/helper.rs | 9 +- src/gui_egui/keymap.rs | 40 ++- src/gui_egui/menu.rs | 10 +- 13 files changed, 523 insertions(+), 238 deletions(-) diff --git a/src/common.rs b/src/common.rs index d8f9e6dd..030b23cd 100644 --- a/src/common.rs +++ b/src/common.rs @@ -92,9 +92,10 @@ pub trait EguiComponent: Component { _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, - ) -> Option { + ) -> Option> { None } + fn render_editor( &mut self, _ui: &mut egui::Ui, @@ -109,9 +110,15 @@ pub trait EguiComponent: Component { resp: None, } } + fn size(&self) -> egui::Rect { egui::Rect::NOTHING } + + /// Get ports location relative to self, (inputs, outputs) + fn ports_location(&self) -> Vec<(Id, egui::Pos2)> { + vec![] + } } #[cfg(feature = "gui-egui")] diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 646efa0a..756169a6 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -2,7 +2,7 @@ use crate::gui_egui::helper::{ offset_helper, out_of_bounds, unique_component_name, EditorRenderReturn, }; use crate::{ - common::{Components, EguiComponent, Simulator}, + common::{Components, EguiComponent, Id, Simulator}, components::Add, }; use egui::{ @@ -20,7 +20,7 @@ impl EguiComponent for Add { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - ) -> Option { + ) -> Option> { // 41x81 // middle: 21x 41y (0 0) let oh: fn((f32, f32), f32, Vec2) -> egui::Pos2 = offset_helper; @@ -72,11 +72,18 @@ impl EguiComponent for Add { let r = ui.allocate_rect( rect, Sense { - click: true, - drag: true, - focusable: true, - }, + click: false, + drag: false, + focusable: false, + }, /* + Sense { + click: true, + drag: true, + focusable: true, + }, + */ ); + if r.hovered() && !r.dragged() { egui::containers::popup::show_tooltip_for( ui.ctx(), @@ -88,7 +95,7 @@ impl EguiComponent for Add { }, ); } - Some(r) + Some(vec![r]) } fn render_editor( @@ -101,7 +108,13 @@ impl EguiComponent for Add { cs: &Components, ) -> EditorRenderReturn { let mut delete = false; - let resp = Add::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + let r_vec = Add::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + let resp = &r_vec[0]; + let resp = resp.interact(Sense { + click: true, + drag: true, + focusable: true, + }); if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta() / scale; self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); @@ -181,7 +194,7 @@ impl EguiComponent for Add { Err(_) => vec![], }; for field in fields { - ui.selectable_value(&mut b_in_field, field.clone(), field); + ui.selectable_value(&mut a_in_field, field.clone(), field); } } }); @@ -237,7 +250,7 @@ impl EguiComponent for Add { EditorRenderReturn { delete, - resp: Some(resp), + resp: Some(r_vec), } } @@ -250,4 +263,13 @@ impl EguiComponent for Add { max: Pos2 { x: 20f32, y: 40f32 }, } } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + (self.a_in.id.clone(), Pos2::new(-20f32, -20f32) + own_pos), + (self.b_in.id.clone(), Pos2::new(-20f32, 20f32) + own_pos), + (String::from("out"), Pos2::new(20f32, 0f32) + own_pos), + ] + } } diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 35d9a9ab..38a80d56 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -3,7 +3,7 @@ use crate::components::Constant; use crate::gui_egui::helper::{out_of_bounds, unique_component_name, EditorRenderReturn}; use egui::{ Align2, Area, Color32, Frame, Margin, Order, PointerButton, Pos2, Rect, RichText, Rounding, - Sense, Window, + Sense, Vec2, Window, }; use epaint::Shadow; @@ -16,7 +16,7 @@ impl EguiComponent for Constant { offset: egui::Vec2, scale: f32, clip_rect: Rect, - ) -> Option { + ) -> Option> { let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -57,7 +57,7 @@ impl EguiComponent for Constant { }, ); } - Some(r) + Some(vec![r]) } fn render_editor( @@ -70,7 +70,8 @@ impl EguiComponent for Constant { cs: &Components, ) -> EditorRenderReturn { let mut delete = false; - let resp = Constant::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + let r_vec = Constant::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + let resp = &r_vec[0]; if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta() / scale; self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); @@ -119,12 +120,6 @@ impl EguiComponent for Constant { ); }); ui.add(egui::Slider::new(&mut self.value, u32::MIN..=u32::MAX).text("value")); - /* - ui.horizontal(|ui| { - - ui.text_edit_singleline(value); - }); - */ }); if resp.unwrap().response.clicked_elsewhere() { self.properties_window = false; @@ -138,7 +133,7 @@ impl EguiComponent for Constant { EditorRenderReturn { delete, - resp: Some(resp), + resp: Some(r_vec), } } @@ -151,4 +146,9 @@ impl EguiComponent for Constant { max: Pos2 { x: 10f32, y: 10f32 }, } } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![(String::from("out"), Pos2::new(10f32, 0f32) + own_pos)] + } } diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 2f90aa30..73f1fe33 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -11,7 +11,7 @@ impl EguiComponent for Mux { offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, - ) -> Option { + ) -> Option> { // 41x(20*ports + 11) // middle: 21x ((20*ports + 10)/2+1)y (0 0) let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 977a01e4..425aaa83 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -16,7 +16,7 @@ impl EguiComponent for Probe { offset: egui::Vec2, scale: f32, clip_rect: Rect, - ) -> Option { + ) -> Option> { let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -63,7 +63,7 @@ impl EguiComponent for Probe { }, ); } - Some(r) + Some(vec![r]) } fn render_editor( @@ -76,7 +76,8 @@ impl EguiComponent for Probe { cs: &Components, ) -> EditorRenderReturn { let mut delete = false; - let resp = Probe::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + let r_vec = Probe::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + let resp = &r_vec[0]; if resp.dragged_by(egui::PointerButton::Primary) { let delta = resp.drag_delta() / scale; self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); @@ -175,7 +176,7 @@ impl EguiComponent for Probe { EditorRenderReturn { delete, - resp: Some(resp), + resp: Some(r_vec), } } diff --git a/src/gui_egui/components/probe_out.rs b/src/gui_egui/components/probe_out.rs index 8b85ce76..27c415e7 100644 --- a/src/gui_egui/components/probe_out.rs +++ b/src/gui_egui/components/probe_out.rs @@ -11,7 +11,7 @@ impl EguiComponent for ProbeOut { offset: egui::Vec2, scale: f32, clip_rect: Rect, - ) -> Option { + ) -> Option> { todo!(); None } diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index 81d0029c..ce4533db 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -11,7 +11,7 @@ impl EguiComponent for Register { offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, - ) -> Option { + ) -> Option> { // 21x41 // middle: 11x 21y (0 0) let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index 2fd574d1..e5dedb87 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -10,7 +10,7 @@ impl EguiComponent for Sext { _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, - ) -> Option { + ) -> Option> { todo!("implement sext"); None } diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 53cb7cd8..0e7fe420 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -4,8 +4,8 @@ use crate::gui_egui::helper::{ offset_helper, out_of_bounds, unique_component_name, EditorRenderReturn, }; use egui::{ - containers, Color32, ComboBox, Frame, Id, Margin, PointerButton, Pos2, Rect, Response, - Rounding, Sense, Shape, Stroke, Ui, Vec2, Window, + containers, Color32, ComboBox, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, + Sense, Shape, Stroke, Ui, Vec2, Window, }; use epaint::Shadow; @@ -17,8 +17,8 @@ impl EguiComponent for Wire { simulator: Option, offset: Vec2, scale: f32, - _clip_rect: egui::Rect, - ) { + clip_rect: egui::Rect, + ) -> Option> { let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; let offset = offset; let s = scale; @@ -29,38 +29,48 @@ impl EguiComponent for Wire { } ui.painter().add(egui::Shape::line( - line_vec, + line_vec.clone(), Stroke { width: scale, color: Color32::BLACK, }, )); - let rect = Rect { - min: oh((0f32, 0f32), s, o), - max: oh((self.delta.0, self.delta.1), s, o), - }; - let rect = out_of_bounds(rect, clip_rect); - let r = ui.allocate_rect( - rect, - Sense { - click: true, - drag: true, - focusable: true, - }, - ); - if r.hovered() && !r.dragged() { - containers::popup::show_tooltip_for(ui.ctx(), Id::new(self.id.clone()), &rect, |ui| { - ui.label(format!("Id: {}", self.id.clone())); - match simulator { - Some(s) => { - ui.label(format!("{}", s.get_input_val(&self.input))); - } - _ => (), - } - }); + let mut r_vec = vec![]; + + for (i, _) in line_vec[1..].iter().enumerate() { + let rect = Rect { + min: line_vec[i], + max: line_vec[i + 1], + }; + let rect = out_of_bounds(rect, clip_rect); + let r = ui.allocate_rect( + rect, + Sense { + click: true, + drag: true, + focusable: true, + }, + ); + if r.hovered() && !r.dragged() { + containers::popup::show_tooltip_for( + ui.ctx(), + egui::Id::new(self.id.clone()), + &rect, + |ui| { + ui.label(format!("Id: {}", self.id.clone())); + match &simulator { + Some(s) => { + ui.label(format!("{}", s.get_input_val(&self.input))); + } + _ => (), + } + }, + ); + } + r_vec.push(r); } - Some(r) + Some(r_vec) } fn render_editor( @@ -73,100 +83,114 @@ impl EguiComponent for Wire { cs: &Components, ) -> EditorRenderReturn { let mut delete = false; - let resp = Wire::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); - if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta() / scale; - self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); - } - if resp.drag_released_by(PointerButton::Primary) { - if resp.interact_pointer_pos().unwrap().x < offset.x { - delete = true; + let r_vec = Wire::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + for (i, resp) in r_vec.iter().enumerate() { + if resp.dragged_by(PointerButton::Primary) { + let delta = resp.drag_delta() / scale; + self.pos[i] = (self.pos[i].0 + delta.x, self.pos[i].1 + delta.y); + self.pos[i + 1] = (self.pos[i + 1].0 + delta.x, self.pos[i + 1].1 + delta.y); } - } - if self.properties_window { - let mut input = self.input.id.clone(); - let resp = Window::new(format!("Properties: {}", self.id)) - .frame(Frame { - inner_margin: Margin::same(10f32), - outer_margin: Margin::same(0f32), - rounding: Rounding::same(10f32), - shadow: Shadow::small_dark(), - fill: ui.visuals().panel_fill, - stroke: ui.visuals().window_stroke, - }) - .default_pos(Pos2 { - x: (resp.rect.min.x + resp.rect.max.x) / 2f32, - y: (resp.rect.min.y + resp.rect.max.y) / 2f32, - }) - .show(ui.ctx(), |ui| { - ui.horizontal(|ui| { - let id_label = ui.label("Id: "); - let r = ui - .text_edit_singleline(&mut self.id_tmp) - .labelled_by(id_label.id); - if r.lost_focus() && self.id_tmp != self.id { - self.id = unique_component_name(cs, self.id_tmp.as_str()); - } - }); - - ui.horizontal(|ui| { - ui.add( - egui::Slider::new(&mut self.pos.0, 0f32..=1000f32) - .text("pos x") - .clamp_to_range(false), - ); - ui.add( - egui::Slider::new(&mut self.pos.1, 0f32..=1000f32) - .text("pos y") - .clamp_to_range(false), - ); - }); - let r = ComboBox::from_label("input") - .selected_text(format!("{}", input)) - .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => self.id.clone(), - }; - ui.selectable_value(&mut input, id.clone(), id); + if resp.drag_released_by(PointerButton::Primary) { + if resp.interact_pointer_pos().unwrap().x < offset.x { + delete = true; + } + } + if self.properties_window { + let mut input = self.input.id.clone(); + let resp = Window::new(format!("Properties: {}", self.id)) + .frame(Frame { + inner_margin: Margin::same(10f32), + outer_margin: Margin::same(0f32), + rounding: Rounding::same(10f32), + shadow: Shadow::small_dark(), + fill: ui.visuals().panel_fill, + stroke: ui.visuals().window_stroke, + }) + .default_pos(Pos2 { + x: (resp.rect.min.x + resp.rect.max.x) / 2f32, + y: (resp.rect.min.y + resp.rect.max.y) / 2f32, + }) + .show(ui.ctx(), |ui| { + ui.horizontal(|ui| { + let id_label = ui.label("Id: "); + let r = ui + .text_edit_singleline(&mut self.id_tmp) + .labelled_by(id_label.id); + if r.lost_focus() && self.id_tmp != self.id { + self.id = unique_component_name(cs, self.id_tmp.as_str()); } }); - ui.add( - egui::Slider::new(&mut self.delta.0, 0f32..=1000f32) - .text("delta x") - .clamp_to_range(false), - ); - ui.add( - egui::Slider::new(&mut self.delta.1, 0f32..=1000f32) - .text("delta y") - .clamp_to_range(false), - ); - self.input.id = input; - }); - if resp.unwrap().response.clicked_elsewhere() { - self.properties_window = false; + + ui.horizontal(|ui| { + ui.add( + egui::Slider::new(&mut self.pos[i].0, 0f32..=1000f32) + .text("start x") + .clamp_to_range(false), + ); + ui.add( + egui::Slider::new(&mut self.pos[i].1, 0f32..=1000f32) + .text("start y") + .clamp_to_range(false), + ); + }); + ui.horizontal(|ui| { + ui.add( + egui::Slider::new(&mut self.pos[i + 1].0, 0f32..=1000f32) + .text("end x") + .clamp_to_range(false), + ); + ui.add( + egui::Slider::new(&mut self.pos[i + 1].1, 0f32..=1000f32) + .text("end y") + .clamp_to_range(false), + ); + }); + let r = ComboBox::from_label("input") + .selected_text(format!("{}", input)) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => self.id.clone(), + }; + ui.selectable_value(&mut input, id.clone(), id); + } + }); + self.input.id = input; + }); + if resp.unwrap().response.clicked_elsewhere() { + self.properties_window = false; + } } - } - if resp.clicked_by(PointerButton::Secondary) { - // Open properties window - self.properties_window = true; + if resp.clicked_by(PointerButton::Secondary) { + // Open properties window + self.properties_window = true; + } } EditorRenderReturn { delete, - resp: Some(resp), + resp: Some(r_vec), } } + // This isn't really it's true size fn size(&self) -> Rect { Rect { min: Pos2 { x: 0f32, y: 0f32 }, max: Pos2 { - x: self.delta.0, - y: self.delta.1, + x: self.pos[1].0, + y: self.pos[1].1, }, } } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let mut vec: Vec<(crate::common::Id, Pos2)> = vec![]; + for (i, pos) in self.pos.iter().enumerate() { + vec.push((format!("{}", i), Pos2 { x: pos.0, y: pos.1 })); + } + vec + } } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 789727bd..cdbc9ada 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -1,13 +1,15 @@ -use crate::common::{ComponentStore, EguiComponent, Input}; +use crate::common::{ComponentStore, Components, EguiComponent, Id, Input}; use crate::components::*; use crate::gui_egui::{ gui::Gui, - helper::{offset_helper, unique_component_name}, + helper::{offset_helper, offset_reverse_helper_pos2, unique_component_name}, keymap, menu::Menu, }; use eframe::{egui, Frame}; -use egui::{Color32, Context, PointerButton, Pos2, Rect, Response, Style, Ui, Vec2}; +use egui::{ + Color32, Context, LayerId, PointerButton, Pos2, Rect, Response, Shape, Stroke, Style, Ui, Vec2, +}; use std::{cell::RefCell, path::PathBuf, rc::Rc}; pub struct Editor { @@ -20,7 +22,25 @@ pub struct Editor { pub ui_change: bool, pub library: ComponentStore, pub dummy_input: Input, + pub wire_mode: bool, + pub wire_mode_ended: bool, + pub wire_last_pos: Option, + pub wire_input: Option, + pub wire_cursor_location: Pos2, + pub wire_start_comp_port: Option, + pub wire_end_comp_port: Option, + pub wire_temp_positions: Vec<(f32, f32)>, +} + +#[derive(Clone)] +pub struct CloseToComponent { + //comp: Ref, + pub comp: Rc>, + pub pos: Pos2, + pub dist: f32, + pub port: Id, } +// todo: enum for input mode, wire, component, none impl Editor { pub fn gui(cs: ComponentStore, _path: &PathBuf) -> Self { @@ -50,8 +70,7 @@ impl Editor { Rc::new(RefCell::new(Constant::new("c".to_string(), (0.0, 0.0), 0))), Rc::new(RefCell::new(Wire::new( "w".to_string(), - (0.0, 0.0), - (70.0, 0.0), + vec![(0.0, 0.0), (70.0, 0.0)], dummy_input.clone(), ))), Rc::new(RefCell::new(Probe::new( @@ -62,6 +81,15 @@ impl Editor { ], }, dummy_input, + wire_mode: false, + wire_mode_ended: true, + //wire_current: None, + wire_last_pos: None, + wire_input: None, + wire_cursor_location: Pos2::ZERO, + wire_start_comp_port: None, + wire_end_comp_port: None, + wire_temp_positions: vec![], } } @@ -154,80 +182,90 @@ impl Editor { for c in s.library.store.iter() { let size = c.borrow_mut().size(); padding.y = padding.y - s.scale * size.min.y; - let resp = c + let r_vec = c .borrow_mut() .render(ui, None, padding, s.scale, clip_rect) .unwrap(); - - // Create new component - if resp.drag_started_by(PointerButton::Primary) { - let _resp = match c.borrow_mut().get_id_ports().0.as_str() { - // todo: Make this a lot better and not hardcoded - "c" => { - let id = - unique_component_name(&s.component_store.store, "c"); - let comp: Rc> = - Rc::new(RefCell::new(Constant::new(id, (0.0, 0.0), 0))); - let resp = comp - .borrow_mut() - .render(ui, None, padding, s.scale, clip_rect); - s.component_store.store.push(comp); - resp - } - "w" => { - let id = - unique_component_name(&s.component_store.store, "w"); - let comp: Rc> = - Rc::new(RefCell::new(Wire::new( - id, - (0.0, 0.0), - (70.0, 0.0), - s.dummy_input.clone(), - ))); - let resp = comp - .borrow_mut() - .render(ui, None, padding, s.scale, clip_rect); - s.component_store.store.push(comp); - resp - } - "p" => { - let id = - unique_component_name(&s.component_store.store, "p"); - let comp: Rc> = - Rc::new(RefCell::new(Probe::new( - id, - (0.0, 0.0), - s.dummy_input.clone(), - ))); - let resp = comp - .borrow_mut() - .render(ui, None, padding, s.scale, clip_rect); - s.component_store.store.push(comp); - resp - } - "add" | _ => { - let id = - unique_component_name(&s.component_store.store, "add"); - let comp: Rc> = - Rc::new(RefCell::new(Add::new( - id, - (0.0, 0.0), - s.dummy_input.clone(), - s.dummy_input.clone(), - ))); - let resp = comp - .borrow_mut() - .render(ui, None, padding, s.scale, clip_rect); - s.component_store.store.push(comp); - resp - } - }; - // todo: use resp to make it draggable instantly - // I'm unsure if this is actually possible - // since it's not possible to create events/set currently - // dragged entity + let rect = r_vec[0].rect.clone(); + for resp in r_vec { + // Create new component + if resp.drag_started_by(PointerButton::Primary) { + let _resp = match c.borrow_mut().get_id_ports().0.as_str() { + // todo: Make this a lot better and not hardcoded + "c" => { + let id = unique_component_name( + &s.component_store.store, + "c", + ); + let comp: Rc> = Rc::new( + RefCell::new(Constant::new(id, (0.0, 0.0), 0)), + ); + let resp = comp + .borrow_mut() + .render(ui, None, padding, s.scale, clip_rect); + s.component_store.store.push(comp); + resp + } + "w" => { + let id = unique_component_name( + &s.component_store.store, + "w", + ); + let comp: Rc> = + Rc::new(RefCell::new(Wire::new( + id, + vec![(0.0, 0.0), (70.0, 0.0)], + s.dummy_input.clone(), + ))); + let resp = comp + .borrow_mut() + .render(ui, None, padding, s.scale, clip_rect); + s.component_store.store.push(comp); + resp + } + "p" => { + let id = unique_component_name( + &s.component_store.store, + "p", + ); + let comp: Rc> = + Rc::new(RefCell::new(Probe::new( + id, + (0.0, 0.0), + s.dummy_input.clone(), + ))); + let resp = comp + .borrow_mut() + .render(ui, None, padding, s.scale, clip_rect); + s.component_store.store.push(comp); + resp + } + "add" | _ => { + let id = unique_component_name( + &s.component_store.store, + "add", + ); + let comp: Rc> = + Rc::new(RefCell::new(Add::new( + id, + (0.0, 0.0), + s.dummy_input.clone(), + s.dummy_input.clone(), + ))); + let resp = comp + .borrow_mut() + .render(ui, None, padding, s.scale, clip_rect); + s.component_store.store.push(comp); + resp + } + }; + // todo: use resp to make it draggable instantly + // I'm unsure if this is actually possible + // since it's not possible to create events/set currently + // dragged entity + } } - padding.y = resp.rect.max.y + 10f32; + padding.y = rect.max.y + 10f32; } }); }); @@ -236,6 +274,7 @@ impl Editor { } fn draw_area(ctx: &Context, gui: &mut Gui, frame: egui::Frame) { + let mut layer_id: Option = None; let central_panel = egui::CentralPanel::default().frame(frame).show(ctx, |ui| { ui.set_clip_rect(Editor::gui_to_editor(gui).clip_rect); @@ -253,22 +292,125 @@ impl Editor { color: egui::Color32::BLACK, }, )); + layer_id = Some(ui.layer_id()); } let tcs = gui.simulator.ordered_components.clone(); let s = Editor::gui_to_editor(gui); - s.component_store.store.retain(|c| { - let delete = c - .borrow_mut() - .render_editor(ui, None, s.offset + s.pan, s.scale, s.clip_rect, &tcs) - .delete; - !delete - }); + if s.wire_mode { + for c in &s.component_store.store { + c.borrow_mut() + .render(ui, None, s.offset + s.pan, s.scale, s.clip_rect); + } + } else { + s.component_store.store.retain(|c| { + let delete = c + .borrow_mut() + .render_editor(ui, None, s.offset + s.pan, s.scale, s.clip_rect, &tcs) + .delete; + !delete + }); + } }); + let s = Editor::gui_to_editor(gui); let cpr = central_panel.response.interact(egui::Sense::drag()); - if cpr.dragged_by(egui::PointerButton::Middle) { - Editor::gui_to_editor(gui).pan += cpr.drag_delta(); + if cpr.dragged_by(PointerButton::Middle) { + s.pan += cpr.drag_delta(); + } + if s.wire_mode { + ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Crosshair); + + if cpr.drag_started_by(PointerButton::Primary) { + // todo: Snap functionality should also apply here + s.wire_mode_ended = false; + ctx.input_mut(|i| { + let origin = i.pointer.press_origin().unwrap(); + s.wire_cursor_location = origin; + + let offset_cursor_scale = offset_reverse_helper_pos2(origin, s.scale, s.offset); + let closest = Editor::clicked_close_to_input_output( + offset_cursor_scale, + &s.component_store.store, + ); + let closest_uw = closest.unwrap(); + + if s.wire_temp_positions.len() == 0 { + // requires at least one component on the canvas + let new_pos = closest_uw.pos; + let new_pos = offset_helper((new_pos.x, new_pos.y), s.scale, s.offset); + s.wire_temp_positions.push((new_pos.x, new_pos.y)); + } else if s.wire_temp_positions.len() > 0 && closest_uw.dist <= 10.0f32 { + // We should finish the component + let in_c = s.wire_start_comp_port.as_ref().unwrap(); + let out_c = s.wire_end_comp_port.as_ref().unwrap(); + let input = Editor::get_input_from_port( + &in_c.port, + &in_c.comp, + &out_c.port, + &out_c.comp, + ); + match input { + Some(i) => { + let id = unique_component_name(&s.component_store.store, "w"); + s.component_store. + store.push(Rc::new(RefCell::new(Wire::new(id, s.wire_temp_positions.clone(), i)))); + }, + None => { + println!("Seems like you don't have an input at the start or end of the wire"); + } + } + } else { + s.wire_temp_positions.push((origin.x, origin.y)); + } + }); + } else { + if cpr.drag_started_by(PointerButton::Secondary) { + // place wire end + // This should also occur when pressing an input/output after the first one + s.reset_wire_mode(); + } + + if !s.wire_mode_ended { + ctx.input_mut(|i| { + s.wire_cursor_location += i.pointer.delta(); + }); + let offset_cursor_scale = + offset_reverse_helper_pos2(s.wire_cursor_location, s.scale, s.offset); + let closest = Editor::clicked_close_to_input_output( + offset_cursor_scale, + &s.component_store.store, + ); + + let wire_shown_location = match closest { + Some(c) => { + if c.dist <= 10.0f32 { + // We are close enough to move the shown wire to here instead + println!("Closest: {:?} {}", c.pos, c.dist); + c.pos + s.offset + } else { + s.wire_cursor_location + } + } + None => s.wire_cursor_location, + }; + + let mut draw_vec: Vec = vec![]; // = s.wire_temp_positions.clone(); + for (posx, posy) in &s.wire_temp_positions { + draw_vec.push(Pos2::new(*posx, *posy)) + } + draw_vec.push(wire_shown_location); + ctx.layer_painter(layer_id.unwrap()).add(Shape::line( + draw_vec, + Stroke { + width: s.scale * 1.5f32, + color: Color32::BLACK, + }, + )); + } + } + } else { + ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Default); } if central_panel.response.hovered() { ctx.input_mut(|i| { @@ -281,6 +423,72 @@ impl Editor { } } + fn clicked_close_to_input_output( + clicked_pos: Pos2, + components: &Components, + ) -> Option { + let mut closest: Option = None; + for comp in components { + let ports = comp.borrow_mut().ports_location(); + for (port, pos) in ports { + match closest.as_ref() { + Some(c) => { + let dist = clicked_pos.distance(pos); + if dist < c.dist { + closest = Some(CloseToComponent { + comp: comp.clone(), + pos, + dist, + port, + }) + } + } + None => { + closest = Some(CloseToComponent { + comp: comp.clone(), + pos, + dist: clicked_pos.distance(pos), + port, + }) + } + }; + } + } + + closest + } + + fn get_input_from_port( + id_start: &Id, + comp_start: &Rc>, + id_end: &Id, + comp_end: &Rc>, + ) -> Option { + let (_, ports_start) = comp_start.borrow().get_id_ports(); + for input in ports_start.inputs { + if input.id == *id_start { + return Some(input); + } + } + let (_, ports_end) = comp_end.borrow().get_id_ports(); + for input in ports_end.inputs { + if input.id == *id_end { + return Some(input); + } + } + None + } + + pub fn reset_wire_mode(&mut self) { + self.wire_mode_ended = true; + self.wire_last_pos = None; + self.wire_input = None; + self.wire_cursor_location = Pos2::ZERO; + self.wire_start_comp_port = None; + self.wire_end_comp_port = None; + self.wire_temp_positions = vec![]; + } + fn gui_to_editor(gui: &mut Gui) -> &mut Editor { gui.editor.as_mut().unwrap() } diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 71f132ea..7dcadff8 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -3,7 +3,14 @@ use egui::{Pos2, Rect, Response, Vec2}; pub struct EditorRenderReturn { pub delete: bool, - pub resp: Option, + pub resp: Option>, +} + +pub fn offset_reverse_helper_pos2(xy: Pos2, scale: f32, offset: Vec2) -> Pos2 { + egui::Pos2 { + x: (xy.x - offset.x) * scale, + y: (xy.y - offset.y) * scale, + } } pub fn offset_helper(xy: (f32, f32), scale: f32, offset: Vec2) -> Pos2 { diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 53d26037..cfe98b5e 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -21,6 +21,7 @@ pub struct Shortcuts { pub control_reset: KeyboardShortcut, pub control_step_forward: KeyboardShortcut, pub control_step_back: KeyboardShortcut, + pub editor_wire: KeyboardShortcut, } impl Default for Shortcuts { @@ -138,6 +139,10 @@ impl Shortcuts { modifiers: shift, key: Key::F10, }, + editor_wire: KeyboardShortcut { + modifiers: none, + key: Key::W, + }, } } @@ -179,22 +184,25 @@ impl Shortcuts { view_zoom_out_fn(gui); } if ctx.input_mut(|i| i.consume_shortcut(&self.control_play_toggle)) { - control_play_toggle(gui); + control_play_toggle_fn(gui); } if ctx.input_mut(|i| i.consume_shortcut(&self.control_play)) { - control_play(gui); + control_play_fn(gui); } if ctx.input_mut(|i| i.consume_shortcut(&self.control_pause)) { - control_pause(gui); + control_pause_fn(gui); } if ctx.input_mut(|i| i.consume_shortcut(&self.control_reset)) { - control_reset(gui); + control_reset_fn(gui); } if ctx.input_mut(|i| i.consume_shortcut(&self.control_step_forward)) { - control_step_forward(gui); + control_step_forward_fn(gui); } if ctx.input_mut(|i| i.consume_shortcut(&self.control_step_back)) { - control_step_back(gui); + control_step_back_fn(gui); + } + if ctx.input_mut(|i| i.consume_shortcut(&self.editor_wire)) { + editor_wire_fn(gui); } } } @@ -261,34 +269,42 @@ pub fn view_zoom_out_fn(gui: &mut crate::gui_egui::gui::Gui) { _ => *scale = 0.1f32, } } -pub fn control_play_toggle(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_play_toggle_fn(gui: &mut crate::gui_egui::gui::Gui) { if !gui.editor_use { gui.pause = !gui.pause; } } -pub fn control_play(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_play_fn(gui: &mut crate::gui_egui::gui::Gui) { if !gui.editor_use { gui.pause = false; } } -pub fn control_pause(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_pause_fn(gui: &mut crate::gui_egui::gui::Gui) { if !gui.editor_use { gui.pause = true; } } -pub fn control_reset(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_reset_fn(gui: &mut crate::gui_egui::gui::Gui) { if !gui.editor_use { gui.simulator.reset(&mut gui.clock); gui.pause = true; } } -pub fn control_step_forward(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_step_forward_fn(gui: &mut crate::gui_egui::gui::Gui) { if !gui.editor_use { gui.simulator.clock(&mut gui.clock); } } -pub fn control_step_back(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_step_back_fn(gui: &mut crate::gui_egui::gui::Gui) { if !gui.editor_use { gui.simulator.un_clock(&mut gui.clock); } } +pub fn editor_wire_fn(gui: &mut crate::gui_egui::gui::Gui) { + if gui.editor_use { + let editor = gui.editor.as_mut().unwrap(); + editor.wire_mode = !editor.wire_mode; + editor.reset_wire_mode(); + println!("wire mode: {}", editor.wire_mode); + } +} diff --git a/src/gui_egui/menu.rs b/src/gui_egui/menu.rs index e528612c..d56f3f08 100644 --- a/src/gui_egui/menu.rs +++ b/src/gui_egui/menu.rs @@ -100,19 +100,19 @@ impl Menu { }); ui.horizontal(|ui| { if ui.button("⟲").clicked() { - keymap::control_reset(gui); + keymap::control_reset_fn(gui); } if ui.button("⏮").clicked() { - keymap::control_step_back(gui); + keymap::control_step_back_fn(gui); } if ui.button("⏭").clicked() { - keymap::control_step_forward(gui); + keymap::control_step_forward_fn(gui); } if ui.button("▶").clicked() { - keymap::control_play(gui); + keymap::control_play_fn(gui); } if ui.button("⏸").clicked() { - keymap::control_pause(gui); + keymap::control_pause_fn(gui); } ui.label(format!("Clock #{}", gui.clock)); }); From 401a7a59c59e3871f78ffa551dda77ff09cf7744 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 22 Jul 2023 17:43:24 +0200 Subject: [PATCH 08/58] Wires now somewhat work properly, small overhaul --- src/common.rs | 31 ++- src/gui_egui/components/add.rs | 31 +-- src/gui_egui/components/constant.rs | 18 +- src/gui_egui/components/mux.rs | 3 +- src/gui_egui/components/probe.rs | 18 +- src/gui_egui/components/probe_out.rs | 3 +- src/gui_egui/components/register.rs | 3 +- src/gui_egui/components/sext.rs | 3 +- src/gui_egui/components/wire.rs | 52 +++-- src/gui_egui/editor.rs | 281 ++++++++------------------- src/gui_egui/editor_wire.rs | 223 +++++++++++++++++++++ src/gui_egui/gui.rs | 3 +- src/gui_egui/helper.rs | 31 ++- src/gui_egui/keymap.rs | 15 +- src/gui_egui/mod.rs | 1 + 15 files changed, 433 insertions(+), 283 deletions(-) create mode 100644 src/gui_egui/editor_wire.rs diff --git a/src/common.rs b/src/common.rs index 030b23cd..2df65422 100644 --- a/src/common.rs +++ b/src/common.rs @@ -81,6 +81,27 @@ pub trait ViziaComponent: Component { fn view(&self, _cx: &mut vizia::context::Context) {} } +// Specific structs for egui +#[cfg(feature = "gui-egui")] +pub enum SnapPriority { + Default, + Wire, +} + +#[cfg(feature = "gui-egui")] +#[derive(Debug, Clone, Copy)] +pub enum EditorMode { + Default, + Wire, + Input, +} + +#[cfg(feature = "gui-egui")] +pub struct EditorRenderReturn { + pub delete: bool, + pub resp: Option>, +} + // Specific functionality for EGui frontend #[cfg(feature = "gui-egui")] #[typetag::serde(tag = "type")] @@ -92,6 +113,7 @@ pub trait EguiComponent: Component { _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, + _editor_mode: EditorMode, ) -> Option> { None } @@ -104,8 +126,9 @@ pub trait EguiComponent: Component { _scale: f32, _clip_rect: egui::Rect, _components: &Components, - ) -> crate::gui_egui::helper::EditorRenderReturn { - crate::gui_egui::helper::EditorRenderReturn { + _editor_mode: EditorMode, + ) -> EditorRenderReturn { + EditorRenderReturn { delete: false, resp: None, } @@ -119,6 +142,10 @@ pub trait EguiComponent: Component { fn ports_location(&self) -> Vec<(Id, egui::Pos2)> { vec![] } + + fn snap_priority(&self) -> SnapPriority { + SnapPriority::Default + } } #[cfg(feature = "gui-egui")] diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 756169a6..281d68f2 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,13 +1,13 @@ use crate::gui_egui::helper::{ - offset_helper, out_of_bounds, unique_component_name, EditorRenderReturn, + editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, }; use crate::{ - common::{Components, EguiComponent, Id, Simulator}, + common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Simulator}, components::Add, }; use egui::{ containers::{ComboBox, Window}, - Frame, Margin, PointerButton, Pos2, Rect, Rounding, Sense, Vec2, + Frame, Margin, PointerButton, Pos2, Rect, Rounding, Vec2, }; use epaint::Shadow; @@ -20,6 +20,7 @@ impl EguiComponent for Add { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, + editor_mode: EditorMode, ) -> Option> { // 41x81 // middle: 21x 41y (0 0) @@ -69,20 +70,7 @@ impl EguiComponent for Add { max: oh((20f32, 40f32), s, o), }; let rect = out_of_bounds(rect, clip_rect); - let r = ui.allocate_rect( - rect, - Sense { - click: false, - drag: false, - focusable: false, - }, /* - Sense { - click: true, - drag: true, - focusable: true, - }, - */ - ); + let r = ui.allocate_rect(rect, editor_mode_to_sense(editor_mode)); if r.hovered() && !r.dragged() { egui::containers::popup::show_tooltip_for( @@ -106,15 +94,12 @@ impl EguiComponent for Add { scale: f32, clip_rect: egui::Rect, cs: &Components, + editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; - let r_vec = Add::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + let r_vec = + Add::render(self, ui, simulator, offset, scale, clip_rect, editor_mode).unwrap(); let resp = &r_vec[0]; - let resp = resp.interact(Sense { - click: true, - drag: true, - focusable: true, - }); if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta() / scale; self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 38a80d56..a8cee20d 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,6 +1,6 @@ -use crate::common::{Components, EguiComponent, Simulator}; +use crate::common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Simulator}; use crate::components::Constant; -use crate::gui_egui::helper::{out_of_bounds, unique_component_name, EditorRenderReturn}; +use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; use egui::{ Align2, Area, Color32, Frame, Margin, Order, PointerButton, Pos2, Rect, RichText, Rounding, Sense, Vec2, Window, @@ -16,6 +16,7 @@ impl EguiComponent for Constant { offset: egui::Vec2, scale: f32, clip_rect: Rect, + editor_mode: EditorMode, ) -> Option> { let mut offset = offset; offset.x += self.pos.0 * scale; @@ -38,14 +39,7 @@ impl EguiComponent for Constant { }); let rect = area.response.rect; let rect = out_of_bounds(rect, clip_rect); - let r = ui.allocate_rect( - rect, - Sense { - click: true, - drag: true, - focusable: true, - }, - ); + let r = ui.allocate_rect(rect, editor_mode_to_sense(editor_mode)); if r.hovered() && !r.dragged() { egui::containers::popup::show_tooltip_for( ui.ctx(), @@ -68,9 +62,11 @@ impl EguiComponent for Constant { scale: f32, clip_rect: egui::Rect, cs: &Components, + editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; - let r_vec = Constant::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + let r_vec = + Constant::render(self, ui, simulator, offset, scale, clip_rect, editor_mode).unwrap(); let resp = &r_vec[0]; if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta() / scale; diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 73f1fe33..89246804 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -1,4 +1,4 @@ -use crate::common::{EguiComponent, Simulator}; +use crate::common::{EditorMode, EguiComponent, Simulator}; use crate::components::Mux; use crate::gui_egui::helper::offset_helper; @@ -11,6 +11,7 @@ impl EguiComponent for Mux { offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, + _editor_mode: EditorMode, ) -> Option> { // 41x(20*ports + 11) // middle: 21x ((20*ports + 10)/2+1)y (0 0) diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 425aaa83..8a6775d3 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -1,6 +1,6 @@ -use crate::common::{Components, EguiComponent, Simulator}; +use crate::common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Simulator}; use crate::components::Probe; -use crate::gui_egui::helper::{out_of_bounds, unique_component_name, EditorRenderReturn}; +use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; use egui::{ Align2, Area, Color32, ComboBox, Frame, Margin, Order, PointerButton, Pos2, Rect, RichText, Rounding, Sense, Window, @@ -16,6 +16,7 @@ impl EguiComponent for Probe { offset: egui::Vec2, scale: f32, clip_rect: Rect, + editor_mode: EditorMode, ) -> Option> { let mut offset = offset; offset.x += self.pos.0 * scale; @@ -44,14 +45,7 @@ impl EguiComponent for Probe { let rect = area.response.rect; let rect = out_of_bounds(rect, clip_rect); - let r = ui.allocate_rect( - rect, - Sense { - click: true, - drag: true, - focusable: true, - }, - ); + let r = ui.allocate_rect(rect, editor_mode_to_sense(editor_mode)); if r.hovered() && !r.dragged() { egui::containers::popup::show_tooltip_for( ui.ctx(), @@ -74,9 +68,11 @@ impl EguiComponent for Probe { scale: f32, clip_rect: egui::Rect, cs: &Components, + editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; - let r_vec = Probe::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + let r_vec = + Probe::render(self, ui, simulator, offset, scale, clip_rect, editor_mode).unwrap(); let resp = &r_vec[0]; if resp.dragged_by(egui::PointerButton::Primary) { let delta = resp.drag_delta() / scale; diff --git a/src/gui_egui/components/probe_out.rs b/src/gui_egui/components/probe_out.rs index 27c415e7..6c14da19 100644 --- a/src/gui_egui/components/probe_out.rs +++ b/src/gui_egui/components/probe_out.rs @@ -1,4 +1,4 @@ -use crate::common::{EguiComponent, Simulator}; +use crate::common::{EditorMode, EguiComponent, Simulator}; use crate::components::ProbeOut; use egui::Rect; @@ -11,6 +11,7 @@ impl EguiComponent for ProbeOut { offset: egui::Vec2, scale: f32, clip_rect: Rect, + _editor_mode: EditorMode, ) -> Option> { todo!(); None diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index ce4533db..261bae93 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -1,4 +1,4 @@ -use crate::common::{EguiComponent, Simulator}; +use crate::common::{EditorMode, EguiComponent, Simulator}; use crate::components::Register; use crate::gui_egui::helper::offset_helper; @@ -11,6 +11,7 @@ impl EguiComponent for Register { offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, + editor_mode: EditorMode, ) -> Option> { // 21x41 // middle: 11x 21y (0 0) diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index e5dedb87..fe3abc66 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -1,4 +1,4 @@ -use crate::common::{EguiComponent, Simulator}; +use crate::common::{EditorMode, EguiComponent, Simulator}; use crate::components::Sext; #[typetag::serde] @@ -10,6 +10,7 @@ impl EguiComponent for Sext { _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, + _editor_mode: EditorMode, ) -> Option> { todo!("implement sext"); None diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 0e7fe420..550be36c 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -1,11 +1,13 @@ -use crate::common::{Components, EguiComponent, Simulator}; +use crate::common::{ + Components, EditorMode, EditorRenderReturn, EguiComponent, Simulator, SnapPriority, +}; use crate::components::Wire; use crate::gui_egui::helper::{ - offset_helper, out_of_bounds, unique_component_name, EditorRenderReturn, + editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, }; use egui::{ containers, Color32, ComboBox, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, - Sense, Shape, Stroke, Ui, Vec2, Window, + Shape, Slider, Stroke, Ui, Vec2, Window, }; use epaint::Shadow; @@ -17,9 +19,10 @@ impl EguiComponent for Wire { simulator: Option, offset: Vec2, scale: f32, - clip_rect: egui::Rect, + clip_rect: Rect, + editor_mode: EditorMode, ) -> Option> { - let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; let offset = offset; let s = scale; let o = offset; @@ -28,7 +31,7 @@ impl EguiComponent for Wire { line_vec.push(oh(pos, s, o)); } - ui.painter().add(egui::Shape::line( + ui.painter().add(Shape::line( line_vec.clone(), Stroke { width: scale, @@ -38,19 +41,20 @@ impl EguiComponent for Wire { let mut r_vec = vec![]; for (i, _) in line_vec[1..].iter().enumerate() { + let (line_top_left, line_bottom_right) = + if line_vec[i].x > line_vec[i + 1].x || line_vec[i].y > line_vec[i + 1].y { + (line_vec[i + 1], line_vec[i]) + } else { + (line_vec[i], line_vec[i + 1]) + }; let rect = Rect { - min: line_vec[i], - max: line_vec[i + 1], + min: line_top_left, + max: line_bottom_right, + //min: line_vec[i], + //max: line_vec[i + 1], }; let rect = out_of_bounds(rect, clip_rect); - let r = ui.allocate_rect( - rect, - Sense { - click: true, - drag: true, - focusable: true, - }, - ); + let r = ui.allocate_rect(rect, editor_mode_to_sense(editor_mode)); if r.hovered() && !r.dragged() { containers::popup::show_tooltip_for( ui.ctx(), @@ -81,9 +85,11 @@ impl EguiComponent for Wire { scale: f32, clip_rect: Rect, cs: &Components, + editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; - let r_vec = Wire::render(self, ui, simulator, offset, scale, clip_rect).unwrap(); + let r_vec = + Wire::render(self, ui, simulator, offset, scale, clip_rect, editor_mode).unwrap(); for (i, resp) in r_vec.iter().enumerate() { if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta() / scale; @@ -123,24 +129,24 @@ impl EguiComponent for Wire { ui.horizontal(|ui| { ui.add( - egui::Slider::new(&mut self.pos[i].0, 0f32..=1000f32) + Slider::new(&mut self.pos[i].0, 0f32..=1000f32) .text("start x") .clamp_to_range(false), ); ui.add( - egui::Slider::new(&mut self.pos[i].1, 0f32..=1000f32) + Slider::new(&mut self.pos[i].1, 0f32..=1000f32) .text("start y") .clamp_to_range(false), ); }); ui.horizontal(|ui| { ui.add( - egui::Slider::new(&mut self.pos[i + 1].0, 0f32..=1000f32) + Slider::new(&mut self.pos[i + 1].0, 0f32..=1000f32) .text("end x") .clamp_to_range(false), ); ui.add( - egui::Slider::new(&mut self.pos[i + 1].1, 0f32..=1000f32) + Slider::new(&mut self.pos[i + 1].1, 0f32..=1000f32) .text("end y") .clamp_to_range(false), ); @@ -193,4 +199,8 @@ impl EguiComponent for Wire { } vec } + + fn snap_priority(&self) -> SnapPriority { + SnapPriority::Wire + } } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index cdbc9ada..9275ef90 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -1,4 +1,4 @@ -use crate::common::{ComponentStore, Components, EguiComponent, Id, Input}; +use crate::common::{ComponentStore, Components, EditorMode, EguiComponent, Id, Input}; use crate::components::*; use crate::gui_egui::{ gui::Gui, @@ -17,24 +17,23 @@ pub struct Editor { pub scale: f32, pub pan: Vec2, pub offset: Vec2, + pub offset_and_pan: Vec2, pub clip_rect: Rect, pub side_panel_width: f32, pub ui_change: bool, pub library: ComponentStore, pub dummy_input: Input, - pub wire_mode: bool, + pub editor_mode: EditorMode, pub wire_mode_ended: bool, pub wire_last_pos: Option, pub wire_input: Option, pub wire_cursor_location: Pos2, pub wire_start_comp_port: Option, - pub wire_end_comp_port: Option, pub wire_temp_positions: Vec<(f32, f32)>, } #[derive(Clone)] pub struct CloseToComponent { - //comp: Ref, pub comp: Rc>, pub pos: Pos2, pub dist: f32, @@ -49,7 +48,8 @@ impl Editor { component_store: cs, scale: 1f32, pan: Vec2::new(0f32, 0f32), - offset: Vec2 { x: 0f32, y: 0f32 }, + offset: Vec2::new(0f32, 0f32), + offset_and_pan: Vec2::new(0f32, 0f32), clip_rect: Rect { min: Pos2 { x: 0f32, y: 0f32 }, max: Pos2 { @@ -81,14 +81,12 @@ impl Editor { ], }, dummy_input, - wire_mode: false, + editor_mode: EditorMode::Default, wire_mode_ended: true, - //wire_current: None, wire_last_pos: None, wire_input: None, wire_cursor_location: Pos2::ZERO, wire_start_comp_port: None, - wire_end_comp_port: None, wire_temp_positions: vec![], } } @@ -107,15 +105,16 @@ impl Editor { let side = egui::containers::panel::PanelState::load(ctx, egui::Id::from("leftLibrary")) .unwrap(); - Editor::gui_to_editor(gui).offset = egui::Vec2 { + let e = Editor::gui_to_editor(gui); + e.offset = egui::Vec2 { x: side.rect.max.x, y: top.rect.max.y, }; - Editor::gui_to_editor(gui).clip_rect = egui::Rect { + e.offset_and_pan = e.pan + e.offset; + e.clip_rect = egui::Rect { min: egui::Pos2 { - //x: 0f32, - x: Editor::gui_to_editor(gui).offset.to_pos2().x, - y: Editor::gui_to_editor(gui).offset.to_pos2().y, + x: e.offset.to_pos2().x, + y: e.offset.to_pos2().y, }, max: egui::Pos2 { x: f32::INFINITY, @@ -184,7 +183,7 @@ impl Editor { padding.y = padding.y - s.scale * size.min.y; let r_vec = c .borrow_mut() - .render(ui, None, padding, s.scale, clip_rect) + .render(ui, None, padding, s.scale, clip_rect, s.editor_mode) .unwrap(); let rect = r_vec[0].rect.clone(); for resp in r_vec { @@ -200,9 +199,14 @@ impl Editor { let comp: Rc> = Rc::new( RefCell::new(Constant::new(id, (0.0, 0.0), 0)), ); - let resp = comp - .borrow_mut() - .render(ui, None, padding, s.scale, clip_rect); + let resp = comp.borrow_mut().render( + ui, + None, + padding, + s.scale, + clip_rect, + s.editor_mode, + ); s.component_store.store.push(comp); resp } @@ -217,9 +221,14 @@ impl Editor { vec![(0.0, 0.0), (70.0, 0.0)], s.dummy_input.clone(), ))); - let resp = comp - .borrow_mut() - .render(ui, None, padding, s.scale, clip_rect); + let resp = comp.borrow_mut().render( + ui, + None, + padding, + s.scale, + clip_rect, + s.editor_mode, + ); s.component_store.store.push(comp); resp } @@ -234,9 +243,14 @@ impl Editor { (0.0, 0.0), s.dummy_input.clone(), ))); - let resp = comp - .borrow_mut() - .render(ui, None, padding, s.scale, clip_rect); + let resp = comp.borrow_mut().render( + ui, + None, + padding, + s.scale, + clip_rect, + s.editor_mode, + ); s.component_store.store.push(comp); resp } @@ -252,9 +266,14 @@ impl Editor { s.dummy_input.clone(), s.dummy_input.clone(), ))); - let resp = comp - .borrow_mut() - .render(ui, None, padding, s.scale, clip_rect); + let resp = comp.borrow_mut().render( + ui, + None, + padding, + s.scale, + clip_rect, + s.editor_mode, + ); s.component_store.store.push(comp); resp } @@ -283,9 +302,9 @@ impl Editor { let s = Editor::gui_to_editor(gui); ui.painter().add(egui::Shape::line( vec![ - offset_helper((30f32, 0f32), s.scale, s.offset + s.pan), - offset_helper((0f32, 0f32), s.scale, s.offset + s.pan), - offset_helper((0f32, 30f32), s.scale, s.offset + s.pan), + offset_helper((30f32, 0f32), s.scale, s.offset_and_pan), + offset_helper((0f32, 0f32), s.scale, s.offset_and_pan), + offset_helper((0f32, 30f32), s.scale, s.offset_and_pan), ], egui::Stroke { width: s.scale, @@ -297,19 +316,36 @@ impl Editor { let tcs = gui.simulator.ordered_components.clone(); let s = Editor::gui_to_editor(gui); - if s.wire_mode { - for c in &s.component_store.store { - c.borrow_mut() - .render(ui, None, s.offset + s.pan, s.scale, s.clip_rect); + match s.editor_mode { + EditorMode::Wire => { + for c in &s.component_store.store { + c.borrow_mut().render( + ui, + None, + s.offset_and_pan, + s.scale, + s.clip_rect, + s.editor_mode, + ); + } + } + EditorMode::Default | EditorMode::Input => { + s.component_store.store.retain(|c| { + let delete = c + .borrow_mut() + .render_editor( + ui, + None, + s.offset_and_pan, + s.scale, + s.clip_rect, + &tcs, + s.editor_mode, + ) + .delete; + !delete + }); } - } else { - s.component_store.store.retain(|c| { - let delete = c - .borrow_mut() - .render_editor(ui, None, s.offset + s.pan, s.scale, s.clip_rect, &tcs) - .delete; - !delete - }); } }); let s = Editor::gui_to_editor(gui); @@ -317,100 +353,13 @@ impl Editor { let cpr = central_panel.response.interact(egui::Sense::drag()); if cpr.dragged_by(PointerButton::Middle) { s.pan += cpr.drag_delta(); + s.offset_and_pan = s.pan + s.offset; } - if s.wire_mode { - ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Crosshair); - - if cpr.drag_started_by(PointerButton::Primary) { - // todo: Snap functionality should also apply here - s.wire_mode_ended = false; - ctx.input_mut(|i| { - let origin = i.pointer.press_origin().unwrap(); - s.wire_cursor_location = origin; - - let offset_cursor_scale = offset_reverse_helper_pos2(origin, s.scale, s.offset); - let closest = Editor::clicked_close_to_input_output( - offset_cursor_scale, - &s.component_store.store, - ); - let closest_uw = closest.unwrap(); - - if s.wire_temp_positions.len() == 0 { - // requires at least one component on the canvas - let new_pos = closest_uw.pos; - let new_pos = offset_helper((new_pos.x, new_pos.y), s.scale, s.offset); - s.wire_temp_positions.push((new_pos.x, new_pos.y)); - } else if s.wire_temp_positions.len() > 0 && closest_uw.dist <= 10.0f32 { - // We should finish the component - let in_c = s.wire_start_comp_port.as_ref().unwrap(); - let out_c = s.wire_end_comp_port.as_ref().unwrap(); - let input = Editor::get_input_from_port( - &in_c.port, - &in_c.comp, - &out_c.port, - &out_c.comp, - ); - match input { - Some(i) => { - let id = unique_component_name(&s.component_store.store, "w"); - s.component_store. - store.push(Rc::new(RefCell::new(Wire::new(id, s.wire_temp_positions.clone(), i)))); - }, - None => { - println!("Seems like you don't have an input at the start or end of the wire"); - } - } - } else { - s.wire_temp_positions.push((origin.x, origin.y)); - } - }); - } else { - if cpr.drag_started_by(PointerButton::Secondary) { - // place wire end - // This should also occur when pressing an input/output after the first one - s.reset_wire_mode(); - } - - if !s.wire_mode_ended { - ctx.input_mut(|i| { - s.wire_cursor_location += i.pointer.delta(); - }); - let offset_cursor_scale = - offset_reverse_helper_pos2(s.wire_cursor_location, s.scale, s.offset); - let closest = Editor::clicked_close_to_input_output( - offset_cursor_scale, - &s.component_store.store, - ); - - let wire_shown_location = match closest { - Some(c) => { - if c.dist <= 10.0f32 { - // We are close enough to move the shown wire to here instead - println!("Closest: {:?} {}", c.pos, c.dist); - c.pos + s.offset - } else { - s.wire_cursor_location - } - } - None => s.wire_cursor_location, - }; - - let mut draw_vec: Vec = vec![]; // = s.wire_temp_positions.clone(); - for (posx, posy) in &s.wire_temp_positions { - draw_vec.push(Pos2::new(*posx, *posy)) - } - draw_vec.push(wire_shown_location); - ctx.layer_painter(layer_id.unwrap()).add(Shape::line( - draw_vec, - Stroke { - width: s.scale * 1.5f32, - color: Color32::BLACK, - }, - )); - } + match s.editor_mode { + EditorMode::Wire => crate::gui_egui::editor_wire::wire_mode(ctx, s, cpr, layer_id), + EditorMode::Input | EditorMode::Default => { + ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Default) } - } else { - ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Default); } if central_panel.response.hovered() { ctx.input_mut(|i| { @@ -423,72 +372,6 @@ impl Editor { } } - fn clicked_close_to_input_output( - clicked_pos: Pos2, - components: &Components, - ) -> Option { - let mut closest: Option = None; - for comp in components { - let ports = comp.borrow_mut().ports_location(); - for (port, pos) in ports { - match closest.as_ref() { - Some(c) => { - let dist = clicked_pos.distance(pos); - if dist < c.dist { - closest = Some(CloseToComponent { - comp: comp.clone(), - pos, - dist, - port, - }) - } - } - None => { - closest = Some(CloseToComponent { - comp: comp.clone(), - pos, - dist: clicked_pos.distance(pos), - port, - }) - } - }; - } - } - - closest - } - - fn get_input_from_port( - id_start: &Id, - comp_start: &Rc>, - id_end: &Id, - comp_end: &Rc>, - ) -> Option { - let (_, ports_start) = comp_start.borrow().get_id_ports(); - for input in ports_start.inputs { - if input.id == *id_start { - return Some(input); - } - } - let (_, ports_end) = comp_end.borrow().get_id_ports(); - for input in ports_end.inputs { - if input.id == *id_end { - return Some(input); - } - } - None - } - - pub fn reset_wire_mode(&mut self) { - self.wire_mode_ended = true; - self.wire_last_pos = None; - self.wire_input = None; - self.wire_cursor_location = Pos2::ZERO; - self.wire_start_comp_port = None; - self.wire_end_comp_port = None; - self.wire_temp_positions = vec![]; - } - fn gui_to_editor(gui: &mut Gui) -> &mut Editor { gui.editor.as_mut().unwrap() } diff --git a/src/gui_egui/editor_wire.rs b/src/gui_egui/editor_wire.rs new file mode 100644 index 00000000..42f4d8ea --- /dev/null +++ b/src/gui_egui/editor_wire.rs @@ -0,0 +1,223 @@ +use crate::common::{Components, EguiComponent, Id, Input, SnapPriority}; +use crate::components::Wire; +use crate::gui_egui::editor::{CloseToComponent, Editor}; +use crate::gui_egui::helper::{ + offset_helper, offset_reverse_helper, offset_reverse_helper_pos2, unique_component_name, +}; +use egui::{Color32, Context, CursorIcon, LayerId, PointerButton, Pos2, Response, Shape, Stroke}; +use std::{cell::RefCell, rc::Rc}; + +pub fn drag_started(ctx: &Context, e: &mut Editor, cpr: Response) { + // todo: Snap functionality should also apply here + e.wire_mode_ended = false; + ctx.input_mut(|i| { + let origin = i.pointer.press_origin().unwrap(); + e.wire_cursor_location = origin; + + let offset_cursor_scale = offset_reverse_helper_pos2(origin, e.scale, e.offset); + let (closest, closest_wire) = + clicked_close_to_input_output(offset_cursor_scale, &e.component_store.store); + let closest_uw = closest.clone().unwrap(); + + // First click ALWAYS has to start at a port so we force it + if e.wire_temp_positions.len() == 0 { + // requires at least one component on the canvas + e.wire_start_comp_port = closest; + let new_pos = closest_uw.pos; + let new_pos = offset_helper((new_pos.x, new_pos.y), e.scale, e.offset_and_pan); + e.wire_temp_positions.push((new_pos.x, new_pos.y)); + // We clicked close to a port so this will be the last click done + } else if e.wire_temp_positions.len() > 0 && closest_uw.dist <= 10.0f32 { + // We should finish the component + last_click(e, closest_uw); + // Click somewhere not near a component + } else { + let (wire1, wire2) = + wire_split_into_two(*e.wire_temp_positions.last().unwrap(), (origin.x, origin.y)); + e.wire_temp_positions.push(wire1); + e.wire_temp_positions.push(wire2); + //e.wire_temp_positions.push((origin.x, origin.y)); + } + }); +} + +pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { + let in_c = e.wire_start_comp_port.as_ref().unwrap(); + let out_c = closest_uw; + let input = get_input_from_port(&in_c.port, &in_c.comp, &out_c.port, &out_c.comp); + match input { + Some(i) => { + println!("Creating wire component"); + let id = unique_component_name(&e.component_store.store, "w"); + let mut pos_v: Vec<(f32, f32)> = vec![]; + + for pos in &e.wire_temp_positions { + let pos_2 = offset_reverse_helper(*pos, e.scale, e.offset_and_pan); + pos_v.push((pos_2.x, pos_2.y)); + } + + let last_pos = *e.wire_temp_positions.last().unwrap(); + let last_pos = offset_reverse_helper(last_pos, e.scale, e.offset_and_pan); + let mut v = + wire_split_into_two_vec((last_pos.x, last_pos.y), (out_c.pos.x, out_c.pos.y)); + pos_v.append(&mut v); + + e.component_store + .store + .push(Rc::new(RefCell::new(Wire::new(id, pos_v, i)))); + } + None => { + println!("Seems like you don't have an input at the start or end of the wire"); + } + } + reset_wire_mode(e); +} + +pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option) { + ctx.output_mut(|o| o.cursor_icon = CursorIcon::Crosshair); + + if cpr.drag_started_by(PointerButton::Primary) { + drag_started(ctx, e, cpr); + } else { + if cpr.drag_started_by(PointerButton::Secondary) { + // place wire end + // This should also occur when pressing an input/output after the first one + reset_wire_mode(e); + } + + if !e.wire_mode_ended { + ctx.input_mut(|i| { + e.wire_cursor_location += i.pointer.delta(); + }); + let offset_cursor_scale = + offset_reverse_helper_pos2(e.wire_cursor_location, e.scale, e.offset_and_pan); + let (closest, closest_wire) = + clicked_close_to_input_output(offset_cursor_scale, &e.component_store.store); + + let wire_shown_location = match closest { + Some(c) => { + if c.dist <= 10.0f32 { + // We are close enough to move the shown wire to here instead + c.pos + e.offset_and_pan + } else { + e.wire_cursor_location + } + } + None => e.wire_cursor_location, + }; + + let v = wire_split_into_two_vec( + *e.wire_temp_positions.last().unwrap(), + (wire_shown_location.x, wire_shown_location.y), + ); + let mut draw_vec: Vec = vec![]; // = s.wire_temp_positions.clone(); + for (posx, posy) in e + .wire_temp_positions + .clone() + .into_iter() + .chain(v.into_iter()) + { + draw_vec.push(Pos2::new(posx, posy)) + } + + ctx.layer_painter(layer_id.unwrap()).add(Shape::line( + draw_vec, + Stroke { + width: e.scale * 1.5f32, + color: Color32::BLACK, + }, + )); + } + } +} +pub fn wire_split_into_two_vec(prev: (f32, f32), current: (f32, f32)) -> Vec<(f32, f32)> { + let mut v = vec![]; + if f32::abs(current.0 - prev.0) < 0.1f32 && f32::abs(current.1 - prev.1) < 0.01f32 { + v.push(current); + } else { + let (wire1, wire2) = wire_split_into_two(prev, current); + v.push(wire1); + v.push(wire2); + } + v +} + +pub fn wire_split_into_two(prev: (f32, f32), current: (f32, f32)) -> ((f32, f32), (f32, f32)) { + if f32::abs(prev.0 - current.0) > f32::abs(prev.1 - current.1) { + ((current.0, prev.1), (current.0, current.1)) + } else { + ((prev.0, current.1), (current.0, current.1)) + } +} + +pub fn reset_wire_mode(e: &mut Editor) { + e.wire_mode_ended = true; + e.wire_last_pos = None; + e.wire_input = None; + e.wire_cursor_location = Pos2::ZERO; + e.wire_start_comp_port = None; + e.wire_temp_positions = vec![]; +} + +pub fn get_input_from_port( + id_start: &Id, + comp_start: &Rc>, + id_end: &Id, + comp_end: &Rc>, +) -> Option { + let (_, ports_start) = comp_start.borrow().get_id_ports(); + for input in ports_start.inputs { + if input.id == *id_start { + return Some(input); + } + } + let (_, ports_end) = comp_end.borrow().get_id_ports(); + for input in ports_end.inputs { + if input.id == *id_end { + return Some(input); + } + } + None +} + +/// returns (Component, Wire) +pub fn clicked_close_to_input_output( + clicked_pos: Pos2, + components: &Components, +) -> (Option, Option) { + let mut closest: Option = None; + let mut closest_wire: Option = None; + for comp in components { + let ports = comp.borrow_mut().ports_location(); + let prio = comp.borrow_mut().snap_priority(); + let clos: &mut Option = match prio { + SnapPriority::Wire => &mut closest_wire, + _ => &mut closest, + }; + for (port, pos) in ports { + match clos.as_ref() { + Some(c) => { + let dist = clicked_pos.distance(pos); + if dist < c.dist { + *clos = Some(CloseToComponent { + comp: comp.clone(), + pos, + dist, + port, + }) + } + } + None => { + *clos = Some(CloseToComponent { + comp: comp.clone(), + pos, + dist: clicked_pos.distance(pos), + port, + }) + } + }; + } + } + + (closest, closest_wire) +} diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index 2f5e4f6f..4d91353e 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -1,4 +1,4 @@ -use crate::common::{ComponentStore, Simulator}; +use crate::common::{ComponentStore, EditorMode, Simulator}; use crate::gui_egui::{editor::Editor, keymap, keymap::Shortcuts, menu::Menu}; use eframe::egui; use std::path::PathBuf; @@ -124,6 +124,7 @@ impl Gui { self.offset + self.pan, self.scale, self.clip_rect, + EditorMode::Default, ); } }); diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 7dcadff8..3d72e012 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -1,10 +1,5 @@ -use crate::common::Components; -use egui::{Pos2, Rect, Response, Vec2}; - -pub struct EditorRenderReturn { - pub delete: bool, - pub resp: Option>, -} +use crate::common::{Components, EditorMode}; +use egui::{Pos2, Rect, Response, Sense, Vec2}; pub fn offset_reverse_helper_pos2(xy: Pos2, scale: f32, offset: Vec2) -> Pos2 { egui::Pos2 { @@ -13,6 +8,13 @@ pub fn offset_reverse_helper_pos2(xy: Pos2, scale: f32, offset: Vec2) -> Pos2 { } } +pub fn offset_reverse_helper(xy: (f32, f32), scale: f32, offset: Vec2) -> Pos2 { + egui::Pos2 { + x: (xy.0 - offset.x) * scale, + y: (xy.1 - offset.y) * scale, + } +} + pub fn offset_helper(xy: (f32, f32), scale: f32, offset: Vec2) -> Pos2 { egui::Pos2 { x: xy.0 * scale, @@ -64,6 +66,21 @@ pub fn unique_component_name(cs: &Components, id: &str) -> String { String::from(new_id) } +pub fn editor_mode_to_sense(editor_mode: EditorMode) -> Sense { + match editor_mode { + EditorMode::Wire => Sense { + click: false, + drag: false, + focusable: false, + }, + _ => Sense { + click: true, + drag: true, + focusable: true, + }, + } +} + // todo: Create the properties window the same way every time for the different components //pub fn diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index cfe98b5e..6e38ef45 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -1,4 +1,4 @@ -use crate::common::{ComponentStore, Simulator}; +use crate::common::{ComponentStore, EditorMode, Simulator}; use egui::{Key, KeyboardShortcut, Modifiers}; #[derive(Copy, Clone)] @@ -303,8 +303,15 @@ pub fn control_step_back_fn(gui: &mut crate::gui_egui::gui::Gui) { pub fn editor_wire_fn(gui: &mut crate::gui_egui::gui::Gui) { if gui.editor_use { let editor = gui.editor.as_mut().unwrap(); - editor.wire_mode = !editor.wire_mode; - editor.reset_wire_mode(); - println!("wire mode: {}", editor.wire_mode); + match editor.editor_mode { + EditorMode::Default | EditorMode::Input => { + editor.editor_mode = EditorMode::Wire; + } + EditorMode::Wire => { + editor.editor_mode = EditorMode::Default; + } + } + crate::gui_egui::editor_wire::reset_wire_mode(editor); + println!("wire mode: {:?}", editor.editor_mode); } } diff --git a/src/gui_egui/mod.rs b/src/gui_egui/mod.rs index f6a86c70..36cceaa5 100644 --- a/src/gui_egui/mod.rs +++ b/src/gui_egui/mod.rs @@ -1,4 +1,5 @@ mod editor; +mod editor_wire; mod gui; pub mod helper; mod keymap; From 31bd526781efde2f4dd8cd229a6326ddbf6530b9 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 22 Jul 2023 20:07:19 +0200 Subject: [PATCH 09/58] Added an input mode --- src/common.rs | 1 + src/components/wire.rs | 1 + src/gui_egui/components/add.rs | 6 +- src/gui_egui/components/constant.rs | 4 + src/gui_egui/components/probe.rs | 11 ++- src/gui_egui/editor.rs | 143 ++-------------------------- src/gui_egui/keymap.rs | 71 ++++++++------ src/gui_egui/library.rs | 134 ++++++++++++++++++++++++++ src/gui_egui/mod.rs | 1 + 9 files changed, 210 insertions(+), 162 deletions(-) create mode 100644 src/gui_egui/library.rs diff --git a/src/common.rs b/src/common.rs index 2df65422..1b75eb49 100644 --- a/src/common.rs +++ b/src/common.rs @@ -146,6 +146,7 @@ pub trait EguiComponent: Component { fn snap_priority(&self) -> SnapPriority { SnapPriority::Default } + fn set_pos(&mut self, _pos: (f32, f32)) {} } #[cfg(feature = "gui-egui")] diff --git a/src/components/wire.rs b/src/components/wire.rs index 0a2a1c49..4a48e5b6 100644 --- a/src/components/wire.rs +++ b/src/components/wire.rs @@ -1,6 +1,7 @@ use crate::common::{Component, Id, Input, OutputType, Ports}; use log::*; use serde::{Deserialize, Serialize}; + #[derive(Serialize, Deserialize)] pub struct Wire { pub id: Id, diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 281d68f2..6cd4dff2 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -164,7 +164,7 @@ impl EguiComponent for Add { } }); ComboBox::from_label("a_in.field") - .selected_text(format!("{}", b_in_field)) + .selected_text(format!("{}", a_in_field)) .show_ui(ui, |ui| { for c in cs.iter() { let id = match c.try_borrow_mut() { @@ -257,4 +257,8 @@ impl EguiComponent for Add { (String::from("out"), Pos2::new(20f32, 0f32) + own_pos), ] } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } } diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index a8cee20d..6c78a2b8 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -147,4 +147,8 @@ impl EguiComponent for Constant { let own_pos = Vec2::new(self.pos.0, self.pos.1); vec![(String::from("out"), Pos2::new(10f32, 0f32) + own_pos)] } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } } diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 8a6775d3..b7537a2d 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -3,7 +3,7 @@ use crate::components::Probe; use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; use egui::{ Align2, Area, Color32, ComboBox, Frame, Margin, Order, PointerButton, Pos2, Rect, RichText, - Rounding, Sense, Window, + Rounding, Vec2, Window, }; use epaint::Shadow; @@ -185,4 +185,13 @@ impl EguiComponent for Probe { max: Pos2 { x: 10f32, y: 10f32 }, } } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![(self.input.id.clone(), Pos2::new(-10f32, 0f32) + own_pos)] + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 9275ef90..0c709066 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -30,6 +30,8 @@ pub struct Editor { pub wire_cursor_location: Pos2, pub wire_start_comp_port: Option, pub wire_temp_positions: Vec<(f32, f32)>, + pub input_comp: Option>>, + pub input_cursor_location: Pos2, } #[derive(Clone)] @@ -68,11 +70,6 @@ impl Editor { dummy_input.clone(), ))), Rc::new(RefCell::new(Constant::new("c".to_string(), (0.0, 0.0), 0))), - Rc::new(RefCell::new(Wire::new( - "w".to_string(), - vec![(0.0, 0.0), (70.0, 0.0)], - dummy_input.clone(), - ))), Rc::new(RefCell::new(Probe::new( "p".to_string(), (0.0, 0.0), @@ -88,6 +85,8 @@ impl Editor { wire_cursor_location: Pos2::ZERO, wire_start_comp_port: None, wire_temp_positions: vec![], + input_comp: None, + input_cursor_location: Pos2::ZERO, } } @@ -163,129 +162,8 @@ impl Editor { .show(ctx, |ui| { egui::ScrollArea::vertical().show(ui, |ui| { ui.horizontal(|ui| { - let s = Editor::gui_to_editor(gui); - let mut padding = Vec2 { - x: s.offset.x / 2f32, - y: s.offset.y + 10f32, - }; - let clip_rect = Rect { - min: Pos2 { - x: 0f32, - y: s.offset.y, - }, - max: Pos2 { - x: s.offset.x, - y: f32::INFINITY, - }, - }; - for c in s.library.store.iter() { - let size = c.borrow_mut().size(); - padding.y = padding.y - s.scale * size.min.y; - let r_vec = c - .borrow_mut() - .render(ui, None, padding, s.scale, clip_rect, s.editor_mode) - .unwrap(); - let rect = r_vec[0].rect.clone(); - for resp in r_vec { - // Create new component - if resp.drag_started_by(PointerButton::Primary) { - let _resp = match c.borrow_mut().get_id_ports().0.as_str() { - // todo: Make this a lot better and not hardcoded - "c" => { - let id = unique_component_name( - &s.component_store.store, - "c", - ); - let comp: Rc> = Rc::new( - RefCell::new(Constant::new(id, (0.0, 0.0), 0)), - ); - let resp = comp.borrow_mut().render( - ui, - None, - padding, - s.scale, - clip_rect, - s.editor_mode, - ); - s.component_store.store.push(comp); - resp - } - "w" => { - let id = unique_component_name( - &s.component_store.store, - "w", - ); - let comp: Rc> = - Rc::new(RefCell::new(Wire::new( - id, - vec![(0.0, 0.0), (70.0, 0.0)], - s.dummy_input.clone(), - ))); - let resp = comp.borrow_mut().render( - ui, - None, - padding, - s.scale, - clip_rect, - s.editor_mode, - ); - s.component_store.store.push(comp); - resp - } - "p" => { - let id = unique_component_name( - &s.component_store.store, - "p", - ); - let comp: Rc> = - Rc::new(RefCell::new(Probe::new( - id, - (0.0, 0.0), - s.dummy_input.clone(), - ))); - let resp = comp.borrow_mut().render( - ui, - None, - padding, - s.scale, - clip_rect, - s.editor_mode, - ); - s.component_store.store.push(comp); - resp - } - "add" | _ => { - let id = unique_component_name( - &s.component_store.store, - "add", - ); - let comp: Rc> = - Rc::new(RefCell::new(Add::new( - id, - (0.0, 0.0), - s.dummy_input.clone(), - s.dummy_input.clone(), - ))); - let resp = comp.borrow_mut().render( - ui, - None, - padding, - s.scale, - clip_rect, - s.editor_mode, - ); - s.component_store.store.push(comp); - resp - } - }; - // todo: use resp to make it draggable instantly - // I'm unsure if this is actually possible - // since it's not possible to create events/set currently - // dragged entity - } - } - padding.y = rect.max.y + 10f32; - } + let e = Editor::gui_to_editor(gui); + crate::gui_egui::library::show_library(e, ui); }); }); }); @@ -317,7 +195,7 @@ impl Editor { let tcs = gui.simulator.ordered_components.clone(); let s = Editor::gui_to_editor(gui); match s.editor_mode { - EditorMode::Wire => { + EditorMode::Wire | EditorMode::Input => { for c in &s.component_store.store { c.borrow_mut().render( ui, @@ -329,7 +207,7 @@ impl Editor { ); } } - EditorMode::Default | EditorMode::Input => { + EditorMode::Default => { s.component_store.store.retain(|c| { let delete = c .borrow_mut() @@ -357,9 +235,8 @@ impl Editor { } match s.editor_mode { EditorMode::Wire => crate::gui_egui::editor_wire::wire_mode(ctx, s, cpr, layer_id), - EditorMode::Input | EditorMode::Default => { - ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Default) - } + EditorMode::Input => crate::gui_egui::library::input_mode(ctx, s, cpr, layer_id), + EditorMode::Default => ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Default), } if central_panel.response.hovered() { ctx.input_mut(|i| { diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 6e38ef45..09545d11 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -1,4 +1,5 @@ use crate::common::{ComponentStore, EditorMode, Simulator}; +use crate::gui_egui::{editor::Editor, Gui}; use egui::{Key, KeyboardShortcut, Modifiers}; #[derive(Copy, Clone)] @@ -22,6 +23,7 @@ pub struct Shortcuts { pub control_step_forward: KeyboardShortcut, pub control_step_back: KeyboardShortcut, pub editor_wire: KeyboardShortcut, + pub editor_escape: KeyboardShortcut, } impl Default for Shortcuts { @@ -143,10 +145,14 @@ impl Shortcuts { modifiers: none, key: Key::W, }, + editor_escape: KeyboardShortcut { + modifiers: none, + key: Key::Escape, + }, } } - pub fn inputs(self, ctx: &egui::Context, gui: &mut crate::gui_egui::gui::Gui) { + pub fn inputs(self, ctx: &egui::Context, gui: &mut Gui) { if ctx.input_mut(|i| i.consume_shortcut(&self.file_new)) { file_new_fn(gui); } @@ -204,14 +210,17 @@ impl Shortcuts { if ctx.input_mut(|i| i.consume_shortcut(&self.editor_wire)) { editor_wire_fn(gui); } + if ctx.input_mut(|i| i.consume_shortcut(&self.editor_escape)) { + editor_escape_fn(gui); + } } } -pub fn file_new_fn(_gui: &mut crate::gui_egui::gui::Gui) {} -pub fn file_open_fn(_gui: &mut crate::gui_egui::gui::Gui) {} -pub fn file_save_fn(_gui: &mut crate::gui_egui::gui::Gui) {} -pub fn file_save_as_fn(_gui: &mut crate::gui_egui::gui::Gui) {} -pub fn file_editor_toggle_fn(gui: &mut crate::gui_egui::gui::Gui) { +pub fn file_new_fn(_gui: &mut Gui) {} +pub fn file_open_fn(_gui: &mut Gui) {} +pub fn file_save_fn(_gui: &mut Gui) {} +pub fn file_save_as_fn(_gui: &mut Gui) {} +pub fn file_editor_toggle_fn(gui: &mut Gui) { match gui.editor_use { true => { gui.editor_use = false; @@ -224,24 +233,23 @@ pub fn file_editor_toggle_fn(gui: &mut crate::gui_egui::gui::Gui) { // todo: Make us swap back into simulator mode (create new simulator) } false => { - gui.editor - .get_or_insert(crate::gui_egui::editor::Editor::gui( - ComponentStore { - store: gui.simulator.ordered_components.clone(), - }, - &gui.path, - )); + gui.editor.get_or_insert(Editor::gui( + ComponentStore { + store: gui.simulator.ordered_components.clone(), + }, + &gui.path, + )); gui.editor_use = true; } } } -pub fn file_preferences_fn(_gui: &mut crate::gui_egui::gui::Gui) {} -pub fn file_quit_fn(_gui: &mut crate::gui_egui::gui::Gui) {} -pub fn edit_cut_fn(_gui: &mut crate::gui_egui::gui::Gui) {} -pub fn edit_copy_fn(_gui: &mut crate::gui_egui::gui::Gui) {} -pub fn edit_paste_fn(_gui: &mut crate::gui_egui::gui::Gui) {} -pub fn view_zoom_in_fn(gui: &mut crate::gui_egui::gui::Gui) { +pub fn file_preferences_fn(_gui: &mut Gui) {} +pub fn file_quit_fn(_gui: &mut Gui) {} +pub fn edit_cut_fn(_gui: &mut Gui) {} +pub fn edit_copy_fn(_gui: &mut Gui) {} +pub fn edit_paste_fn(_gui: &mut Gui) {} +pub fn view_zoom_in_fn(gui: &mut Gui) { let scale: &mut f32 = match gui.editor_use { true => &mut gui.editor.as_mut().unwrap().scale, false => &mut gui.scale, @@ -255,7 +263,7 @@ pub fn view_zoom_in_fn(gui: &mut crate::gui_egui::gui::Gui) { _ => *scale = 2f32, } } -pub fn view_zoom_out_fn(gui: &mut crate::gui_egui::gui::Gui) { +pub fn view_zoom_out_fn(gui: &mut Gui) { let scale: &mut f32 = match gui.editor_use { true => &mut gui.editor.as_mut().unwrap().scale, false => &mut gui.scale, @@ -269,38 +277,38 @@ pub fn view_zoom_out_fn(gui: &mut crate::gui_egui::gui::Gui) { _ => *scale = 0.1f32, } } -pub fn control_play_toggle_fn(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_play_toggle_fn(gui: &mut Gui) { if !gui.editor_use { gui.pause = !gui.pause; } } -pub fn control_play_fn(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_play_fn(gui: &mut Gui) { if !gui.editor_use { gui.pause = false; } } -pub fn control_pause_fn(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_pause_fn(gui: &mut Gui) { if !gui.editor_use { gui.pause = true; } } -pub fn control_reset_fn(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_reset_fn(gui: &mut Gui) { if !gui.editor_use { gui.simulator.reset(&mut gui.clock); gui.pause = true; } } -pub fn control_step_forward_fn(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_step_forward_fn(gui: &mut Gui) { if !gui.editor_use { gui.simulator.clock(&mut gui.clock); } } -pub fn control_step_back_fn(gui: &mut crate::gui_egui::gui::Gui) { +pub fn control_step_back_fn(gui: &mut Gui) { if !gui.editor_use { gui.simulator.un_clock(&mut gui.clock); } } -pub fn editor_wire_fn(gui: &mut crate::gui_egui::gui::Gui) { +pub fn editor_wire_fn(gui: &mut Gui) { if gui.editor_use { let editor = gui.editor.as_mut().unwrap(); match editor.editor_mode { @@ -315,3 +323,12 @@ pub fn editor_wire_fn(gui: &mut crate::gui_egui::gui::Gui) { println!("wire mode: {:?}", editor.editor_mode); } } +pub fn editor_escape_fn(gui: &mut Gui) { + if gui.editor_use { + let editor = gui.editor.as_mut().unwrap(); + editor.editor_mode = EditorMode::Default; + crate::gui_egui::editor_wire::reset_wire_mode(editor); + crate::gui_egui::library::reset_input_mode(editor); + println!("wire mode: {:?}", editor.editor_mode); + } +} diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs new file mode 100644 index 00000000..a5987d2f --- /dev/null +++ b/src/gui_egui/library.rs @@ -0,0 +1,134 @@ +use crate::common::{EditorMode, EguiComponent}; +use crate::components::*; +use crate::gui_egui::{ + editor::Editor, + helper::{offset_reverse_helper_pos2, unique_component_name}, +}; +use egui::{Context, CursorIcon, LayerId, PointerButton, Pos2, Rect, Response, Ui, Vec2}; +use std::{cell::RefCell, path::PathBuf, rc::Rc}; + +pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option) { + let layer_id = layer_id.unwrap(); + ctx.output_mut(|o| o.cursor_icon = CursorIcon::None); + ctx.input_mut(|i| { + e.input_cursor_location += i.pointer.delta(); + }); + let clip_rect = Rect { + min: Pos2 { + x: 0f32, + y: e.offset.y, + }, + max: Pos2 { + x: f32::INFINITY, + y: f32::INFINITY, + }, + }; + let mut ui = Ui::new( + ctx.to_owned(), + layer_id, + "input".into(), + clip_rect, + Rect::EVERYTHING, + ); + e.input_comp.as_ref().unwrap().borrow_mut().render( + &mut ui, + None, + Vec2::new(e.input_cursor_location.x, e.input_cursor_location.y), + e.scale, + clip_rect, + e.editor_mode, + ); + + if cpr.drag_started_by(PointerButton::Primary) { + println!("add new item"); + add_comp_to_editor(e); + /* + //let comp = (*e.input_comp.as_mut().unwrap().borrow_mut()).clone(); + */ + } +} + +pub fn reset_input_mode(e: &mut Editor) { + e.input_comp = None; + e.input_cursor_location = Pos2::ZERO; +} + +pub fn show_library(e: &mut Editor, ui: &mut Ui) { + let mut padding = Vec2 { + x: e.offset.x / 2f32, + y: e.offset.y + 10f32, + }; + let clip_rect = Rect { + min: Pos2 { + x: 0f32, + y: e.offset.y, + }, + max: Pos2 { + x: e.offset.x, + y: f32::INFINITY, + }, + }; + for c in e.library.store.iter() { + let size = c.borrow_mut().size(); + padding.y = padding.y - e.scale * size.min.y; + let r_vec = c + .borrow_mut() + .render(ui, None, padding, e.scale, clip_rect, e.editor_mode) + .unwrap(); + let rect = r_vec[0].rect.clone(); + for resp in r_vec { + // Create new component + if resp.drag_started_by(PointerButton::Primary) { + e.editor_mode = EditorMode::Input; + e.input_comp = Some(c.clone()); + ui.input_mut(|i| { + let origin = i.pointer.press_origin().unwrap(); + e.input_cursor_location = origin; + }); + + //s.input_comp = Some( + //crate::gui_egui::library::reset_input_mode(s); + /* + */ + } + } + padding.y = rect.max.y + 10f32; + } +} + +pub fn add_comp_to_editor(e: &mut Editor) { + let pos = offset_reverse_helper_pos2(e.input_cursor_location, e.scale, e.offset); + let mut comp: Rc> = match e + .input_comp + .as_ref() + .unwrap() + .borrow_mut() + .get_id_ports() + .0 + .as_str() + { + "c" => { + let id = unique_component_name(&e.component_store.store, "c"); + Rc::new(RefCell::new(Constant::new(id, (0.0, 0.0), 0))) + } + "p" => { + let id = unique_component_name(&e.component_store.store, "p"); + Rc::new(RefCell::new(Probe::new( + id, + (0.0, 0.0), + e.dummy_input.clone(), + ))) + } + "add" | _ => { + let id = unique_component_name(&e.component_store.store, "add"); + Rc::new(RefCell::new(Add::new( + id, + (0.0, 0.0), + e.dummy_input.clone(), + e.dummy_input.clone(), + ))) + } + }; + comp.borrow_mut().set_pos((pos.x, pos.y)); + e.component_store.store.push(comp); +} diff --git a/src/gui_egui/mod.rs b/src/gui_egui/mod.rs index 36cceaa5..23808d7b 100644 --- a/src/gui_egui/mod.rs +++ b/src/gui_egui/mod.rs @@ -3,6 +3,7 @@ mod editor_wire; mod gui; pub mod helper; mod keymap; +mod library; mod menu; #[cfg(feature = "components")] From a9ea568d15b9661cabfb7c01fc0b9e1c453fd95c Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sun, 23 Jul 2023 15:15:43 +0200 Subject: [PATCH 10/58] can now connect inputs and outputs, workable state --- src/common.rs | 21 ++++++++++-- src/components/add.rs | 30 +++++++++++++---- src/components/mem.rs | 22 ++++++------- src/components/mux.rs | 31 +++++++++++++++--- src/components/probe.rs | 18 ++++++++--- src/components/register.rs | 6 ++-- src/components/sext.rs | 8 +++-- src/components/wire.rs | 11 ++++--- src/gui_egui/components/add.rs | 27 +++++++++++----- src/gui_egui/components/mux.rs | 2 +- src/gui_egui/components/probe.rs | 16 +++++----- src/gui_egui/components/wire.rs | 6 ++-- src/gui_egui/editor.rs | 50 ++++++++++------------------- src/gui_egui/editor_wire.rs | 55 +++++++++++++++++++++----------- src/gui_egui/library.rs | 6 +--- src/simulator.rs | 2 +- 16 files changed, 194 insertions(+), 117 deletions(-) diff --git a/src/common.rs b/src/common.rs index 1b75eb49..aa8a4cf8 100644 --- a/src/common.rs +++ b/src/common.rs @@ -63,6 +63,8 @@ pub trait Component { /// returns the (id, Ports) of the component fn get_id_ports(&self) -> (Id, Ports); + fn set_id_port(&mut self, _target_port_id: Id, _new_input: Input) {} + /// evaluate component based on current internal state fn clock(&self, _simulator: &mut Simulator) {} @@ -157,13 +159,13 @@ pub struct EguiExtra { #[derive(Debug, Clone)] pub struct Ports { - pub inputs: Vec, + pub inputs: Vec, pub out_type: OutputType, pub outputs: Vec, } impl Ports { - pub fn new(inputs: Vec<&Input>, out_type: OutputType, outputs: Vec<&str>) -> Self { + pub fn new(inputs: Vec<&InputId>, out_type: OutputType, outputs: Vec<&str>) -> Self { Ports { inputs: inputs.into_iter().cloned().collect(), out_type, @@ -187,6 +189,21 @@ impl Input { } } +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct InputId { + pub id: Id, + pub input: Input, +} + +impl InputId { + pub fn new(id_self: &str, id: &str, field: &str) -> Self { + InputId { + id: id_self.into(), + input: Input::new(id, field), + } + } +} + #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)] pub enum OutputType { // Will be evaluated as a combinatorial function from inputs to outputs diff --git a/src/components/add.rs b/src/components/add.rs index 84458742..830ccd79 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -1,4 +1,6 @@ -use crate::common::{Component, Id, Input, OutputType, Ports, Signal, SignedSignal, Simulator}; +use crate::common::{ + Component, Id, Input, InputId, OutputType, Ports, Signal, SignedSignal, Simulator, +}; use log::*; use serde::{Deserialize, Serialize}; @@ -6,8 +8,8 @@ use serde::{Deserialize, Serialize}; pub struct Add { pub id: Id, pub pos: (f32, f32), - pub a_in: Input, - pub b_in: Input, + pub a_in: InputId, + pub b_in: InputId, // this is ugly... (egui) pub properties_window: bool, pub id_tmp: Id, @@ -18,8 +20,14 @@ impl Add { Add { id: id.clone(), pos, - a_in, - b_in, + a_in: InputId { + id: String::from("a_in"), + input: a_in, + }, + b_in: InputId { + id: String::from("b_in"), + input: b_in, + }, properties_window: false, id_tmp: id, } @@ -46,8 +54,8 @@ impl Component for Add { // propagate addition to output fn clock(&self, simulator: &mut Simulator) { // get input values - let a_in = simulator.get_input_val(&self.a_in); - let b_in = simulator.get_input_val(&self.b_in); + let a_in = simulator.get_input_val(&self.a_in.input); + let b_in = simulator.get_input_val(&self.b_in.input); // compute addition (notice will panic on overflow) let (value, overflow) = @@ -65,4 +73,12 @@ impl Component for Add { simulator.set_out_val(&self.id, "out", value as Signal); simulator.set_out_val(&self.id, "overflow", Signal::from(overflow)); } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + "a_in" => self.a_in.input = new_input, + "b_in" => self.b_in.input = new_input, + _ => (), + } + } } diff --git a/src/components/mem.rs b/src/components/mem.rs index cdd77c91..b5465c57 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -1,4 +1,4 @@ -use crate::common::{Component, Id, Input, OutputType, Ports, Signal, Simulator}; +use crate::common::{Component, Id, Input, InputId, OutputType, Ports, Signal, Simulator}; use log::*; use num_enum::IntoPrimitive; use num_enum::TryFromPrimitive; @@ -16,11 +16,11 @@ pub struct Mem { pub big_endian: bool, // ports - pub data: Input, - pub addr: Input, - pub ctrl: Input, - pub sign: Input, - pub size: Input, + pub data: InputId, + pub addr: InputId, + pub ctrl: InputId, + pub sign: InputId, + pub size: InputId, // memory pub memory: Memory, @@ -195,11 +195,11 @@ impl Component for Mem { } fn clock(&self, simulator: &mut Simulator) { - let data = simulator.get_input_val(&self.data); - let addr = simulator.get_input_val(&self.addr) as usize; - let ctrl = MemCtrl::try_from(simulator.get_input_val(&self.ctrl) as u8).unwrap(); - let size = simulator.get_input_val(&self.size) as usize; - let sign = simulator.get_input_val(&self.sign) != 0; + let data = simulator.get_input_val(&self.data.input); + let addr = simulator.get_input_val(&self.addr.input) as usize; + let ctrl = MemCtrl::try_from(simulator.get_input_val(&self.ctrl.input) as u8).unwrap(); + let size = simulator.get_input_val(&self.size.input) as usize; + let sign = simulator.get_input_val(&self.sign.input) != 0; match ctrl { MemCtrl::Read => { diff --git a/src/components/mux.rs b/src/components/mux.rs index ced5acb6..12e68ce0 100644 --- a/src/components/mux.rs +++ b/src/components/mux.rs @@ -1,12 +1,33 @@ -use crate::common::{Component, Id, Input, OutputType, Ports, Simulator}; +use crate::common::{Component, Id, Input, InputId, OutputType, Ports, Simulator}; use log::*; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct Mux { pub id: Id, pub pos: (f32, f32), - pub select: Input, - pub m_in: Vec, + pub select: InputId, + pub m_in: Vec, +} + +impl Mux { + pub fn new(id: String, pos: (f32, f32), select: Input, m_in: Vec) -> Self { + let mut v = vec![]; + for (i, input) in m_in.iter().enumerate() { + v.push(InputId { + id: format!("in{}", i), + input: input.clone(), + }); + } + Mux { + id: id.clone(), + pos, + select: InputId { + id: String::from("select"), + input: select, + }, + m_in: v, + } + } } #[typetag::serde] @@ -33,9 +54,9 @@ impl Component for Mux { // propagate selected input value to output fn clock(&self, simulator: &mut Simulator) { // get input value - let select = simulator.get_input_val(&self.select) as usize; + let select = simulator.get_input_val(&self.select.input) as usize; trace!("select {}", select); - let value = simulator.get_input_val(&self.m_in[select]); + let value = simulator.get_input_val(&self.m_in[select].input); // set output simulator.set_out_val(&self.id, "out", value); diff --git a/src/components/probe.rs b/src/components/probe.rs index b24915d0..be746978 100644 --- a/src/components/probe.rs +++ b/src/components/probe.rs @@ -1,11 +1,11 @@ -use crate::common::{Component, Id, Input, OutputType, Ports}; +use crate::common::{Component, Id, Input, InputId, OutputType, Ports}; use log::*; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct Probe { pub id: Id, pub pos: (f32, f32), - pub input: Input, + pub input_id: InputId, // this is ugly... (egui) pub properties_window: bool, pub id_tmp: Id, @@ -16,7 +16,10 @@ impl Probe { Probe { id: id.clone(), pos, - input, + input_id: InputId { + id: String::from("in"), + input, + }, properties_window: false, id_tmp: id, } @@ -34,11 +37,18 @@ impl Component for Probe { self.id.clone(), Ports::new( // Probes take one input - vec![&self.input], + vec![&self.input_id], OutputType::Combinatorial, // No output value vec![], ), ) } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + "in" => self.input_id.input = new_input, + _ => (), + } + } } diff --git a/src/components/register.rs b/src/components/register.rs index 548815c1..991bd4e0 100644 --- a/src/components/register.rs +++ b/src/components/register.rs @@ -1,11 +1,11 @@ -use crate::common::{Component, Id, Input, OutputType, Ports, Simulator}; +use crate::common::{Component, Id, Input, InputId, OutputType, Ports, Simulator}; use log::*; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct Register { pub id: Id, pub pos: (f32, f32), - pub r_in: Input, + pub r_in: InputId, } #[typetag::serde] @@ -29,7 +29,7 @@ impl Component for Register { // propagate input value to output fn clock(&self, simulator: &mut Simulator) { // get input value - let value = simulator.get_input_val(&self.r_in); + let value = simulator.get_input_val(&self.r_in.input); // set output simulator.set_out_val(&self.id, "out", value); trace!("eval: register id {} in {}", self.id, value); diff --git a/src/components/sext.rs b/src/components/sext.rs index 0e7fbb46..f973f900 100644 --- a/src/components/sext.rs +++ b/src/components/sext.rs @@ -1,12 +1,14 @@ // use std::fmt::Alignment; -use crate::common::{Component, Id, Input, OutputType, Ports, Signal, SignedSignal, Simulator}; +use crate::common::{ + Component, Id, Input, InputId, OutputType, Ports, Signal, SignedSignal, Simulator, +}; use log::*; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct Sext { pub id: Id, pub pos: (f32, f32), - pub sext_in: Input, + pub sext_in: InputId, pub in_size: u32, pub out_size: u32, } @@ -36,7 +38,7 @@ impl Component for Sext { ); // get input values - let mut value = simulator.get_input_val(&self.sext_in); + let mut value = simulator.get_input_val(&self.sext_in.input); let to_sext = self.out_size - self.in_size; // Amount to be arithmetically shifted let to_shl = Signal::BITS - self.in_size; // To move input to MSB diff --git a/src/components/wire.rs b/src/components/wire.rs index 4a48e5b6..a8d7d85e 100644 --- a/src/components/wire.rs +++ b/src/components/wire.rs @@ -1,4 +1,4 @@ -use crate::common::{Component, Id, Input, OutputType, Ports}; +use crate::common::{Component, Id, Input, InputId, OutputType, Ports}; use log::*; use serde::{Deserialize, Serialize}; @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; pub struct Wire { pub id: Id, pub pos: Vec<(f32, f32)>, - pub input: Input, + pub input_id: InputId, // this is ugly... (egui) pub properties_window: bool, pub id_tmp: Id, @@ -17,7 +17,10 @@ impl Wire { Wire { id: id.clone(), pos, - input, + input_id: InputId { + id: String::from("in"), + input, + }, properties_window: false, id_tmp: id, } @@ -35,7 +38,7 @@ impl Component for Wire { self.id.clone(), Ports::new( // Wires take one input - vec![&self.input], + vec![&self.input_id], OutputType::Combinatorial, // No output value vec![], diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 6cd4dff2..a1c4df2b 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -111,10 +111,10 @@ impl EguiComponent for Add { } } if self.properties_window { - let mut a_in = self.a_in.id.clone(); - let mut b_in = self.b_in.id.clone(); - let mut a_in_field = self.a_in.field.clone(); - let mut b_in_field = self.b_in.field.clone(); + let mut a_in = self.a_in.input.id.clone(); + let mut b_in = self.b_in.input.id.clone(); + let mut a_in_field = self.a_in.input.field.clone(); + let mut b_in_field = self.b_in.input.field.clone(); let w_resp = Window::new(format!("Properties: {}", self.id)) .frame(Frame { inner_margin: Margin::same(10f32), @@ -218,10 +218,10 @@ impl EguiComponent for Add { } }); }); - self.a_in.id = a_in; - self.b_in.id = b_in; - self.a_in.field = a_in_field; - self.b_in.field = b_in_field; + self.a_in.input.id = a_in; + self.b_in.input.id = b_in; + self.a_in.input.field = a_in_field; + self.b_in.input.field = b_in_field; }); if w_resp.unwrap().response.clicked_elsewhere() { self.properties_window = false; @@ -255,10 +255,21 @@ impl EguiComponent for Add { (self.a_in.id.clone(), Pos2::new(-20f32, -20f32) + own_pos), (self.b_in.id.clone(), Pos2::new(-20f32, 20f32) + own_pos), (String::from("out"), Pos2::new(20f32, 0f32) + own_pos), + (String::from("overflow"), Pos2::new(0f32, -40f32) + own_pos), ] } fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + /* + fn set_port_to_input(input: crate::common::Input, field: crate::common::Id) { + match field { + "out" => self.a_in = + "overflow" => + _=> () + } + } + */ } diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 89246804..15f9cc0a 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -25,7 +25,7 @@ impl EguiComponent for Mux { // selector let select = match simulator { - Some(s) => s.get_input_val(&self.select), + Some(s) => s.get_input_val(&self.select.input), None => 0, }; diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index b7537a2d..0d586b65 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -21,9 +21,9 @@ impl EguiComponent for Probe { let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; - let input = self.input.clone(); + let input_id = self.input_id.clone(); let value = match simulator { - Some(s) => s.get_input_val(&input), + Some(s) => s.get_input_val(&input_id.input), None => 0, }; let area = Area::new(self.id.to_string()) @@ -86,8 +86,8 @@ impl EguiComponent for Probe { } if self.properties_window { - let mut input = self.input.id.clone(); - let mut input_field = self.input.field.clone(); + let mut input = self.input_id.input.id.clone(); + let mut input_field = self.input_id.input.field.clone(); let resp = Window::new(format!("Properties: {}", self.id)) .frame(Frame { inner_margin: Margin::same(10f32), @@ -149,7 +149,7 @@ impl EguiComponent for Probe { } let fields = match c.try_borrow_mut() { Ok(a) => a.get_id_ports().1.outputs, - Err(_) => vec![self.input.id.clone()], + Err(_) => vec![self.input_id.input.id.clone()], }; for field in fields { ui.selectable_value(&mut input_field, field.clone(), field); @@ -157,8 +157,8 @@ impl EguiComponent for Probe { } }); }); - self.input.id = input; - self.input.field = input_field; + self.input_id.input.id = input; + self.input_id.input.field = input_field; }); if resp.unwrap().response.clicked_elsewhere() { self.properties_window = false; @@ -188,7 +188,7 @@ impl EguiComponent for Probe { fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![(self.input.id.clone(), Pos2::new(-10f32, 0f32) + own_pos)] + vec![(self.input_id.id.clone(), Pos2::new(-10f32, 0f32) + own_pos)] } fn set_pos(&mut self, pos: (f32, f32)) { diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 550be36c..2af314ff 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -64,7 +64,7 @@ impl EguiComponent for Wire { ui.label(format!("Id: {}", self.id.clone())); match &simulator { Some(s) => { - ui.label(format!("{}", s.get_input_val(&self.input))); + ui.label(format!("{}", s.get_input_val(&self.input_id.input))); } _ => (), } @@ -102,7 +102,7 @@ impl EguiComponent for Wire { } } if self.properties_window { - let mut input = self.input.id.clone(); + let mut input = self.input_id.input.id.clone(); let resp = Window::new(format!("Properties: {}", self.id)) .frame(Frame { inner_margin: Margin::same(10f32), @@ -162,7 +162,7 @@ impl EguiComponent for Wire { ui.selectable_value(&mut input, id.clone(), id); } }); - self.input.id = input; + self.input_id.input.id = input; }); if resp.unwrap().response.clicked_elsewhere() { self.properties_window = false; diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 0c709066..9b3f0c8f 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -1,4 +1,4 @@ -use crate::common::{ComponentStore, Components, EditorMode, EguiComponent, Id, Input}; +use crate::common::{ComponentStore, Components, EditorMode, EguiComponent, Id, Input, InputId}; use crate::components::*; use crate::gui_egui::{ gui::Gui, @@ -39,7 +39,7 @@ pub struct CloseToComponent { pub comp: Rc>, pub pos: Pos2, pub dist: f32, - pub port: Id, + pub port_id: Id, } // todo: enum for input mode, wire, component, none @@ -194,37 +194,21 @@ impl Editor { let tcs = gui.simulator.ordered_components.clone(); let s = Editor::gui_to_editor(gui); - match s.editor_mode { - EditorMode::Wire | EditorMode::Input => { - for c in &s.component_store.store { - c.borrow_mut().render( - ui, - None, - s.offset_and_pan, - s.scale, - s.clip_rect, - s.editor_mode, - ); - } - } - EditorMode::Default => { - s.component_store.store.retain(|c| { - let delete = c - .borrow_mut() - .render_editor( - ui, - None, - s.offset_and_pan, - s.scale, - s.clip_rect, - &tcs, - s.editor_mode, - ) - .delete; - !delete - }); - } - } + s.component_store.store.retain(|c| { + let delete = c + .borrow_mut() + .render_editor( + ui, + None, + s.offset_and_pan, + s.scale, + s.clip_rect, + &tcs, + s.editor_mode, + ) + .delete; + !delete + }); }); let s = Editor::gui_to_editor(gui); diff --git a/src/gui_egui/editor_wire.rs b/src/gui_egui/editor_wire.rs index 42f4d8ea..be8dc60d 100644 --- a/src/gui_egui/editor_wire.rs +++ b/src/gui_egui/editor_wire.rs @@ -14,7 +14,7 @@ pub fn drag_started(ctx: &Context, e: &mut Editor, cpr: Response) { let origin = i.pointer.press_origin().unwrap(); e.wire_cursor_location = origin; - let offset_cursor_scale = offset_reverse_helper_pos2(origin, e.scale, e.offset); + let offset_cursor_scale = offset_reverse_helper_pos2(origin, e.scale, e.offset_and_pan); let (closest, closest_wire) = clicked_close_to_input_output(offset_cursor_scale, &e.component_store.store); let closest_uw = closest.clone().unwrap(); @@ -44,7 +44,8 @@ pub fn drag_started(ctx: &Context, e: &mut Editor, cpr: Response) { pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { let in_c = e.wire_start_comp_port.as_ref().unwrap(); let out_c = closest_uw; - let input = get_input_from_port(&in_c.port, &in_c.comp, &out_c.port, &out_c.comp); + let (field_name, input, is_comp_start) = + get_outputs_from_port(&in_c.port_id, &in_c.comp, &out_c.port_id, &out_c.comp); match input { Some(i) => { println!("Creating wire component"); @@ -64,7 +65,14 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { e.component_store .store - .push(Rc::new(RefCell::new(Wire::new(id, pos_v, i)))); + .push(Rc::new(RefCell::new(Wire::new(id, pos_v, i.clone())))); + + // Now actually set the input of the wired component + if is_comp_start { + in_c.comp.borrow_mut().set_id_port(field_name, i); + } else { + out_c.comp.borrow_mut().set_id_port(field_name, i); + } } None => { println!("Seems like you don't have an input at the start or end of the wire"); @@ -159,25 +167,34 @@ pub fn reset_wire_mode(e: &mut Editor) { e.wire_temp_positions = vec![]; } -pub fn get_input_from_port( - id_start: &Id, +/// returns an input made from the output +pub fn get_outputs_from_port( + port_id_start: &Id, comp_start: &Rc>, - id_end: &Id, + port_id_end: &Id, comp_end: &Rc>, -) -> Option { - let (_, ports_start) = comp_start.borrow().get_id_ports(); - for input in ports_start.inputs { - if input.id == *id_start { - return Some(input); +) -> (Id, Option, bool) { + let (id, ports_start) = comp_start.borrow().get_id_ports(); + for port_id in ports_start.outputs { + if port_id == *port_id_start { + return ( + port_id_end.clone(), + Some(Input { id, field: port_id }), + false, + ); } } - let (_, ports_end) = comp_end.borrow().get_id_ports(); - for input in ports_end.inputs { - if input.id == *id_end { - return Some(input); + let (id, ports_end) = comp_end.borrow().get_id_ports(); + for port_id in ports_end.outputs { + if port_id == *port_id_end { + return ( + port_id_start.clone(), + Some(Input { id, field: port_id }), + true, + ); } } - None + (String::new(), None, false) } /// returns (Component, Wire) @@ -194,7 +211,7 @@ pub fn clicked_close_to_input_output( SnapPriority::Wire => &mut closest_wire, _ => &mut closest, }; - for (port, pos) in ports { + for (port_id, pos) in ports { match clos.as_ref() { Some(c) => { let dist = clicked_pos.distance(pos); @@ -203,7 +220,7 @@ pub fn clicked_close_to_input_output( comp: comp.clone(), pos, dist, - port, + port_id, }) } } @@ -212,7 +229,7 @@ pub fn clicked_close_to_input_output( comp: comp.clone(), pos, dist: clicked_pos.distance(pos), - port, + port_id, }) } }; diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index a5987d2f..16565ea3 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -85,17 +85,13 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { let origin = i.pointer.press_origin().unwrap(); e.input_cursor_location = origin; }); - - //s.input_comp = Some( - //crate::gui_egui::library::reset_input_mode(s); - /* - */ } } padding.y = rect.max.y + 10f32; } } +// todo: This should really just copy the component that's in e.input_comp pub fn add_comp_to_editor(e: &mut Editor) { let pos = offset_reverse_helper_pos2(e.input_cursor_location, e.scale, e.offset); let mut comp: Rc> = match e diff --git a/src/simulator.rs b/src/simulator.rs index 10f05317..6619f166 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -87,7 +87,7 @@ impl Simulator { let to_node = id_node.get(to_id).unwrap(); let (_, ports) = c.borrow().get_id_ports(); for in_port in &ports.inputs { - let from_id = &in_port.id; + let from_id = &in_port.input.id; let from_node = id_node.get(from_id).unwrap(); graph.add_edge(*from_node, *to_node, ()); From 48580b41e8127eea1e373eba651b35648e9d0694 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sun, 23 Jul 2023 22:32:36 +0200 Subject: [PATCH 11/58] big ui rework for egui, a lot less code --- examples/add.rs | 3 +- src/common.rs | 7 +- src/components/add.rs | 15 +- src/components/constant.rs | 14 +- src/components/probe.rs | 14 +- src/components/sext.rs | 2 +- src/components/wire.rs | 15 +- src/gui_egui/component_ui.rs | 139 +++++++++++++++++++ src/gui_egui/components/add.rs | 164 +++------------------- src/gui_egui/components/constant.rs | 85 ++++-------- src/gui_egui/components/probe.rs | 123 ++++------------- src/gui_egui/components/wire.rs | 204 +++++++++++++++------------- src/gui_egui/mod.rs | 1 + 13 files changed, 355 insertions(+), 431 deletions(-) create mode 100644 src/gui_egui/component_ui.rs diff --git a/examples/add.rs b/examples/add.rs index c646a947..716084e6 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -49,7 +49,8 @@ fn main() { }; let path = PathBuf::from("add.json"); - //cs.save_file(&path); + ////cs.save_file(&path); + //let cs2 = ComponentStore::load_file(&path); #[cfg(feature = "gui-egui")] syncrim::gui_egui::gui(&cs, &path).ok(); diff --git a/src/common.rs b/src/common.rs index aa8a4cf8..a673756b 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,8 +1,6 @@ use petgraph::Graph; use serde::{Deserialize, Serialize}; -use std::cell::RefCell; -use std::collections::HashMap; -use std::rc::Rc; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; #[cfg(feature = "gui-vizia")] use vizia::prelude::*; @@ -37,7 +35,7 @@ pub struct Simulator { pub graph: Graph, } -//#[derive(Serialize, Deserialize)] +#[derive(Serialize)] pub struct ComponentStore { pub store: Components, } @@ -152,6 +150,7 @@ pub trait EguiComponent: Component { } #[cfg(feature = "gui-egui")] +#[derive(Serialize, Deserialize)] pub struct EguiExtra { pub properties_window: bool, pub id_tmp: String, diff --git a/src/components/add.rs b/src/components/add.rs index 830ccd79..b37344a4 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -1,5 +1,5 @@ use crate::common::{ - Component, Id, Input, InputId, OutputType, Ports, Signal, SignedSignal, Simulator, + Component, EguiExtra, Id, Input, InputId, OutputType, Ports, Signal, SignedSignal, Simulator, }; use log::*; use serde::{Deserialize, Serialize}; @@ -10,9 +10,10 @@ pub struct Add { pub pos: (f32, f32), pub a_in: InputId, pub b_in: InputId, - // this is ugly... (egui) - pub properties_window: bool, - pub id_tmp: Id, + + #[cfg(feature = "gui-egui")] + #[serde(skip_serializing)] + pub egui_x: EguiExtra, } impl Add { @@ -28,8 +29,10 @@ impl Add { id: String::from("b_in"), input: b_in, }, - properties_window: false, - id_tmp: id, + egui_x: EguiExtra { + properties_window: false, + id_tmp: id, + }, } } } diff --git a/src/components/constant.rs b/src/components/constant.rs index 02c04c4f..34ce8ea4 100644 --- a/src/components/constant.rs +++ b/src/components/constant.rs @@ -1,4 +1,4 @@ -use crate::common::{Component, Id, OutputType, Ports, Signal, Simulator}; +use crate::common::{Component, EguiExtra, Id, OutputType, Ports, Signal, Simulator}; use log::*; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] @@ -6,9 +6,9 @@ pub struct Constant { pub id: Id, pub pos: (f32, f32), pub value: Signal, - // this is ugly... (egui) - pub properties_window: bool, - pub id_tmp: Id, + #[cfg(feature = "gui-egui")] + #[serde(skip_serializing)] + pub egui_x: EguiExtra, } impl Constant { @@ -17,8 +17,10 @@ impl Constant { id: id.clone(), pos, value, - properties_window: false, - id_tmp: id, + egui_x: EguiExtra { + properties_window: false, + id_tmp: id, + }, } } } diff --git a/src/components/probe.rs b/src/components/probe.rs index be746978..c1179a20 100644 --- a/src/components/probe.rs +++ b/src/components/probe.rs @@ -1,4 +1,4 @@ -use crate::common::{Component, Id, Input, InputId, OutputType, Ports}; +use crate::common::{Component, EguiExtra, Id, Input, InputId, OutputType, Ports}; use log::*; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] @@ -6,9 +6,9 @@ pub struct Probe { pub id: Id, pub pos: (f32, f32), pub input_id: InputId, - // this is ugly... (egui) - pub properties_window: bool, - pub id_tmp: Id, + #[cfg(feature = "gui-egui")] + #[serde(skip_serializing)] + pub egui_x: EguiExtra, } impl Probe { @@ -20,8 +20,10 @@ impl Probe { id: String::from("in"), input, }, - properties_window: false, - id_tmp: id, + egui_x: EguiExtra { + properties_window: false, + id_tmp: id, + }, } } } diff --git a/src/components/sext.rs b/src/components/sext.rs index f973f900..e1b9877a 100644 --- a/src/components/sext.rs +++ b/src/components/sext.rs @@ -4,7 +4,7 @@ use crate::common::{ }; use log::*; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub struct Sext { pub id: Id, pub pos: (f32, f32), diff --git a/src/components/wire.rs b/src/components/wire.rs index a8d7d85e..b74a1637 100644 --- a/src/components/wire.rs +++ b/src/components/wire.rs @@ -1,4 +1,4 @@ -use crate::common::{Component, Id, Input, InputId, OutputType, Ports}; +use crate::common::{Component, EguiExtra, Id, Input, InputId, OutputType, Ports}; use log::*; use serde::{Deserialize, Serialize}; @@ -7,9 +7,10 @@ pub struct Wire { pub id: Id, pub pos: Vec<(f32, f32)>, pub input_id: InputId, - // this is ugly... (egui) - pub properties_window: bool, - pub id_tmp: Id, + + #[cfg(feature = "gui-egui")] + #[serde(skip_serializing)] + pub egui_x: EguiExtra, } impl Wire { @@ -21,8 +22,10 @@ impl Wire { id: String::from("in"), input, }, - properties_window: false, - id_tmp: id, + egui_x: EguiExtra { + properties_window: false, + id_tmp: id, + }, } } } diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs new file mode 100644 index 00000000..cc462cb7 --- /dev/null +++ b/src/gui_egui/component_ui.rs @@ -0,0 +1,139 @@ +use crate::common::{ + ComponentStore, Components, EditorMode, EditorRenderReturn, EguiComponent, InputId, Simulator, +}; +use crate::gui_egui::helper::{ + editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, +}; +use egui::{ + ComboBox, Frame, Id, InnerResponse, Margin, PointerButton, Pos2, Rect, Response, Rounding, Ui, + Window, +}; +use epaint::Shadow; + +pub fn rect_with_hover

( + rect: Rect, + clip_rect: Rect, + editor_mode: EditorMode, + ui: &mut Ui, + id: String, + f: P, +) -> Response +where + P: Fn(&mut Ui), +{ + let rect = out_of_bounds(rect, clip_rect); + let r = ui.allocate_rect(rect, editor_mode_to_sense(editor_mode)); + + if r.hovered() && !r.dragged() { + egui::containers::popup::show_tooltip_for(ui.ctx(), egui::Id::new(id), &rect, |ui| { + f(ui); + }); + } + r +} + +pub fn properties_window

( + ui: &mut Ui, + id: String, + resp: &Response, + properties_window: &mut bool, + mut f: P, +) where + P: FnMut(&mut Ui), +{ + if *properties_window { + let resp = Window::new(format!("Properties: {}", id)) + .frame(Frame { + inner_margin: Margin::same(10f32), + outer_margin: Margin::same(0f32), + rounding: Rounding::same(10f32), + shadow: Shadow::small_dark(), + fill: ui.visuals().panel_fill, + stroke: ui.visuals().window_stroke, + }) + .default_pos(Pos2 { + x: (resp.rect.min.x + resp.rect.max.x) / 2f32, + y: (resp.rect.min.y + resp.rect.max.y) / 2f32, + }) + .show(ui.ctx(), |ui| { + f(ui); + }); + if resp.unwrap().response.clicked_elsewhere() { + *properties_window = false; + } + } + if resp.clicked_by(PointerButton::Secondary) { + // Open properties window + *properties_window = true; + } +} + +pub fn pos_slider(ui: &mut Ui, pos: &mut (f32, f32)) { + ui.horizontal(|ui| { + ui.add( + egui::Slider::new(&mut (*pos).0, 0f32..=1000f32) + .text("pos x") + .clamp_to_range(false), + ); + ui.add( + egui::Slider::new(&mut (*pos).1, 0f32..=1000f32) + .text("pos y") + .clamp_to_range(false), + ); + }); +} +pub fn input_selector(ui: &mut Ui, input_id: &mut InputId, cs: &Components) { + let mut port_id = input_id.input.id.clone(); + let mut port_field = input_id.input.field.clone(); + let label_port_id = format!("{}.id", input_id.id.clone()); + let text_port_id = format!("{}", port_id); + let label_port_field = format!("{}.field", input_id.id.clone()); + let text_port_field = format!("{}", port_field); + ui.horizontal(|ui| { + ComboBox::from_label(label_port_id) + .selected_text(text_port_id) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => String::from("unknown_id"), + }; + ui.selectable_value(&mut port_id, id.clone(), id); + } + }); + ComboBox::from_label(label_port_field) + .selected_text(text_port_field) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => String::from("unknown_id"), + }; + if id != port_id { + continue; + } + let fields = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().1.outputs, + Err(_) => vec![], + }; + for field in fields { + ui.selectable_value(&mut port_field, field.clone(), field); + } + } + }); + }); + input_id.input.id = port_id; + input_id.input.field = port_field; +} + +pub fn input_id(ui: &mut Ui, id_tmp: &mut String, id: &mut String, cs: &Components) { + ui.horizontal(|ui| { + let id_label = ui.label("Id: "); + let r = ui + .text_edit_singleline(&mut *id_tmp) + .labelled_by(id_label.id); + if r.lost_focus() && *id_tmp != *id { + *id = unique_component_name(cs, (*id_tmp).as_str()); + } + }); +} diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index a1c4df2b..b95f4265 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,3 +1,6 @@ +use crate::gui_egui::component_ui::{ + input_id, input_selector, pos_slider, properties_window, rect_with_hover, +}; use crate::gui_egui::helper::{ editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, }; @@ -69,20 +72,10 @@ impl EguiComponent for Add { min: oh((-20f32, -40f32), s, o), max: oh((20f32, 40f32), s, o), }; - let rect = out_of_bounds(rect, clip_rect); - let r = ui.allocate_rect(rect, editor_mode_to_sense(editor_mode)); - - if r.hovered() && !r.dragged() { - egui::containers::popup::show_tooltip_for( - ui.ctx(), - egui::Id::new(self.id.clone()), - &rect, - |ui| { - ui.label(format!("Id: {}", self.id.clone())); - ui.label("ALU"); - }, - ); - } + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + ui.label("ALU"); + }); Some(vec![r]) } @@ -110,128 +103,19 @@ impl EguiComponent for Add { delete = true; } } - if self.properties_window { - let mut a_in = self.a_in.input.id.clone(); - let mut b_in = self.b_in.input.id.clone(); - let mut a_in_field = self.a_in.input.field.clone(); - let mut b_in_field = self.b_in.input.field.clone(); - let w_resp = Window::new(format!("Properties: {}", self.id)) - .frame(Frame { - inner_margin: Margin::same(10f32), - outer_margin: Margin::same(0f32), - rounding: Rounding::same(10f32), - shadow: Shadow::small_dark(), - fill: ui.visuals().panel_fill, - stroke: ui.visuals().window_stroke, - }) - .default_pos(Pos2 { - x: (resp.rect.min.x + resp.rect.max.x) / 2f32, - y: (resp.rect.min.y + resp.rect.max.y) / 2f32, - }) - .show(ui.ctx(), |ui| { - ui.horizontal(|ui| { - let id_label = ui.label("Id: "); - let r = ui - .text_edit_singleline(&mut self.id_tmp) - .labelled_by(id_label.id); - if r.lost_focus() && self.id_tmp != self.id { - self.id = unique_component_name(cs, self.id_tmp.as_str()); - } - }); - - ui.horizontal(|ui| { - ui.add( - egui::Slider::new(&mut self.pos.0, 0f32..=1000f32) - .text("pos x") - .clamp_to_range(false), - ); - ui.add( - egui::Slider::new(&mut self.pos.1, 0f32..=1000f32) - .text("pos y") - .clamp_to_range(false), - ); - }); - ui.horizontal(|ui| { - ComboBox::from_label("a_in.id") - .selected_text(format!("{}", a_in)) - .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => self.id.clone(), - }; - ui.selectable_value(&mut a_in, id.clone(), id); - } - }); - ComboBox::from_label("a_in.field") - .selected_text(format!("{}", a_in_field)) - .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => self.id.clone(), - }; - if id != a_in { - continue; - } - let fields = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().1.outputs, - Err(_) => vec![], - }; - for field in fields { - ui.selectable_value(&mut a_in_field, field.clone(), field); - } - } - }); - }); - - ui.horizontal(|ui| { - ComboBox::from_label("b_in.id") - .selected_text(format!("{}", b_in)) - .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => self.id.clone(), - }; - ui.selectable_value(&mut b_in, id.clone(), id); - } - }); - ComboBox::from_label("b_in.field") - .selected_text(format!("{}", b_in_field)) - .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => self.id.clone(), - }; - if id != b_in { - continue; - } - let fields = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().1.outputs, - Err(_) => vec![], - }; - for field in fields { - ui.selectable_value(&mut b_in_field, field.clone(), field); - } - } - }); - }); - self.a_in.input.id = a_in; - self.b_in.input.id = b_in; - self.a_in.input.field = a_in_field; - self.b_in.input.field = b_in_field; - }); - if w_resp.unwrap().response.clicked_elsewhere() { - self.properties_window = false; - } - } - if resp.clicked_by(PointerButton::Secondary) { - // Open properties window - self.properties_window = true; - } + properties_window( + ui, + self.id.clone(), + resp, + &mut self.egui_x.properties_window, + |ui| { + input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, cs); + pos_slider(ui, &mut self.pos); + input_selector(ui, &mut self.a_in, cs); + input_selector(ui, &mut self.b_in, cs); + }, + ); EditorRenderReturn { delete, @@ -262,14 +146,4 @@ impl EguiComponent for Add { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } - - /* - fn set_port_to_input(input: crate::common::Input, field: crate::common::Id) { - match field { - "out" => self.a_in = - "overflow" => - _=> () - } - } - */ } diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 6c78a2b8..c7078782 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,5 +1,6 @@ use crate::common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Simulator}; use crate::components::Constant; +use crate::gui_egui::component_ui::{input_id, pos_slider, properties_window, rect_with_hover}; use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; use egui::{ Align2, Area, Color32, Frame, Margin, Order, PointerButton, Pos2, Rect, RichText, Rounding, @@ -37,20 +38,17 @@ impl EguiComponent for Constant { ); //.on_hover_text(format!("{:#x}", self.value)); }); - let rect = area.response.rect; - let rect = out_of_bounds(rect, clip_rect); - let r = ui.allocate_rect(rect, editor_mode_to_sense(editor_mode)); - if r.hovered() && !r.dragged() { - egui::containers::popup::show_tooltip_for( - ui.ctx(), - egui::Id::new(self.id.clone()), - &rect, - |ui| { - ui.label(format!("Id: {}", self.id.clone())); - ui.label(self.value.to_string()); - }, - ); - } + let r = rect_with_hover( + area.response.rect, + clip_rect, + editor_mode, + ui, + self.id.clone(), + |ui| { + ui.label(format!("Id: {}", self.id.clone())); + ui.label(self.value.to_string()); + }, + ); Some(vec![r]) } @@ -78,54 +76,17 @@ impl EguiComponent for Constant { } } - if self.properties_window { - let resp = Window::new(format!("Properties: {}", self.id)) - .frame(Frame { - inner_margin: Margin::same(10f32), - outer_margin: Margin::same(0f32), - rounding: Rounding::same(10f32), - shadow: Shadow::small_dark(), - fill: ui.visuals().panel_fill, - stroke: ui.visuals().window_stroke, - }) - .default_pos(Pos2 { - x: (resp.rect.min.x + resp.rect.max.x) / 2f32, - y: (resp.rect.min.y + resp.rect.max.y) / 2f32, - }) - .show(ui.ctx(), |ui| { - ui.horizontal(|ui| { - let id_label = ui.label("Id: "); - let r = ui - .text_edit_singleline(&mut self.id_tmp) - .labelled_by(id_label.id); - if r.lost_focus() && self.id_tmp != self.id { - self.id = unique_component_name(cs, self.id_tmp.as_str()); - } - }); - - ui.horizontal(|ui| { - ui.add( - egui::Slider::new(&mut self.pos.0, 0f32..=1000f32) - .text("pos x") - .clamp_to_range(false), - ); - ui.add( - egui::Slider::new(&mut self.pos.1, 0f32..=1000f32) - .text("pos y") - .clamp_to_range(false), - ); - }); - ui.add(egui::Slider::new(&mut self.value, u32::MIN..=u32::MAX).text("value")); - }); - if resp.unwrap().response.clicked_elsewhere() { - self.properties_window = false; - } - } - - if resp.clicked_by(PointerButton::Secondary) { - // Open properties window - self.properties_window = true; - } + properties_window( + ui, + self.id.clone(), + resp, + &mut self.egui_x.properties_window, + |ui| { + input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, cs); + pos_slider(ui, &mut self.pos); + ui.add(egui::Slider::new(&mut self.value, u32::MIN..=u32::MAX).text("value")); + }, + ); EditorRenderReturn { delete, diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 0d586b65..20b70ad9 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -1,5 +1,8 @@ use crate::common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Simulator}; use crate::components::Probe; +use crate::gui_egui::component_ui::{ + input_id, input_selector, pos_slider, properties_window, rect_with_hover, +}; use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; use egui::{ Align2, Area, Color32, ComboBox, Frame, Margin, Order, PointerButton, Pos2, Rect, RichText, @@ -43,20 +46,17 @@ impl EguiComponent for Probe { .on_hover_text(format!("{:#x}", value)); }); - let rect = area.response.rect; - let rect = out_of_bounds(rect, clip_rect); - let r = ui.allocate_rect(rect, editor_mode_to_sense(editor_mode)); - if r.hovered() && !r.dragged() { - egui::containers::popup::show_tooltip_for( - ui.ctx(), - egui::Id::new(self.id.clone()), - &rect, - |ui| { - ui.label(format!("Id: {}", self.id.clone())); - ui.label(format!("{:?}", value)); - }, - ); - } + let r = rect_with_hover( + area.response.rect, + clip_rect, + editor_mode, + ui, + self.id.clone(), + |ui| { + ui.label(format!("Id: {}", self.id.clone())); + ui.label(format!("{:?}", value)); + }, + ); Some(vec![r]) } @@ -85,90 +85,17 @@ impl EguiComponent for Probe { } } - if self.properties_window { - let mut input = self.input_id.input.id.clone(); - let mut input_field = self.input_id.input.field.clone(); - let resp = Window::new(format!("Properties: {}", self.id)) - .frame(Frame { - inner_margin: Margin::same(10f32), - outer_margin: Margin::same(0f32), - rounding: Rounding::same(10f32), - shadow: Shadow::small_dark(), - fill: ui.visuals().panel_fill, - stroke: ui.visuals().window_stroke, - }) - .default_pos(Pos2 { - x: (resp.rect.min.x + resp.rect.max.x) / 2f32, - y: (resp.rect.min.y + resp.rect.max.y) / 2f32, - }) - .show(ui.ctx(), |ui| { - ui.horizontal(|ui| { - let id_label = ui.label("Id: "); - let r = ui - .text_edit_singleline(&mut self.id_tmp) - .labelled_by(id_label.id); - if r.lost_focus() && self.id_tmp != self.id { - self.id = unique_component_name(cs, self.id_tmp.as_str()); - } - }); - - ui.horizontal(|ui| { - ui.add( - egui::Slider::new(&mut self.pos.0, 0f32..=1000f32) - .text("pos x") - .clamp_to_range(false), - ); - ui.add( - egui::Slider::new(&mut self.pos.1, 0f32..=1000f32) - .text("pos y") - .clamp_to_range(false), - ); - }); - ui.horizontal(|ui| { - ComboBox::from_label("input") - .selected_text(format!("{}", input)) - .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => self.id.clone(), - }; - ui.selectable_value(&mut input, id.clone(), id); - } - }); - ComboBox::from_label("field") - .selected_text(format!("{}", input_field)) - .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => self.id.clone(), - }; - if id != input { - continue; - } - let fields = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().1.outputs, - Err(_) => vec![self.input_id.input.id.clone()], - }; - for field in fields { - ui.selectable_value(&mut input_field, field.clone(), field); - } - } - }); - }); - self.input_id.input.id = input; - self.input_id.input.field = input_field; - }); - if resp.unwrap().response.clicked_elsewhere() { - self.properties_window = false; - } - } - - if resp.clicked_by(PointerButton::Secondary) { - // Open properties window - self.properties_window = true; - } + properties_window( + ui, + self.id.clone(), + resp, + &mut self.egui_x.properties_window, + |ui| { + input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, cs); + pos_slider(ui, &mut self.pos); + input_selector(ui, &mut self.input_id, cs); + }, + ); EditorRenderReturn { delete, diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 2af314ff..72c4a33a 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -2,6 +2,9 @@ use crate::common::{ Components, EditorMode, EditorRenderReturn, EguiComponent, Simulator, SnapPriority, }; use crate::components::Wire; +use crate::gui_egui::component_ui::{ + input_id, input_selector, pos_slider, properties_window, rect_with_hover, +}; use crate::gui_egui::helper::{ editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, }; @@ -41,36 +44,30 @@ impl EguiComponent for Wire { let mut r_vec = vec![]; for (i, _) in line_vec[1..].iter().enumerate() { - let (line_top_left, line_bottom_right) = - if line_vec[i].x > line_vec[i + 1].x || line_vec[i].y > line_vec[i + 1].y { - (line_vec[i + 1], line_vec[i]) - } else { - (line_vec[i], line_vec[i + 1]) - }; + let (line_top, line_bottom) = if line_vec[i].x > line_vec[i + 1].x { + (line_vec[i + 1].x, line_vec[i].x) + } else { + (line_vec[i].x, line_vec[i + 1].x) + }; + let (line_left, line_right) = if line_vec[i].y > line_vec[i + 1].y { + (line_vec[i + 1].y, line_vec[i].y) + } else { + (line_vec[i].y, line_vec[i + 1].y) + }; let rect = Rect { - min: line_top_left, - max: line_bottom_right, - //min: line_vec[i], - //max: line_vec[i + 1], + min: Pos2::new(line_top, line_left), + max: Pos2::new(line_bottom, line_right), }; - let rect = out_of_bounds(rect, clip_rect); - let r = ui.allocate_rect(rect, editor_mode_to_sense(editor_mode)); - if r.hovered() && !r.dragged() { - containers::popup::show_tooltip_for( - ui.ctx(), - egui::Id::new(self.id.clone()), - &rect, - |ui| { - ui.label(format!("Id: {}", self.id.clone())); - match &simulator { - Some(s) => { - ui.label(format!("{}", s.get_input_val(&self.input_id.input))); - } - _ => (), - } - }, - ); - } + + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + match &simulator { + Some(s) => { + ui.label(format!("{}", s.get_input_val(&self.input_id.input))); + } + _ => (), + } + }); r_vec.push(r); } @@ -90,6 +87,7 @@ impl EguiComponent for Wire { let mut delete = false; let r_vec = Wire::render(self, ui, simulator, offset, scale, clip_rect, editor_mode).unwrap(); + for (i, resp) in r_vec.iter().enumerate() { if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta() / scale; @@ -101,78 +99,92 @@ impl EguiComponent for Wire { delete = true; } } - if self.properties_window { - let mut input = self.input_id.input.id.clone(); - let resp = Window::new(format!("Properties: {}", self.id)) - .frame(Frame { - inner_margin: Margin::same(10f32), - outer_margin: Margin::same(0f32), - rounding: Rounding::same(10f32), - shadow: Shadow::small_dark(), - fill: ui.visuals().panel_fill, - stroke: ui.visuals().window_stroke, - }) - .default_pos(Pos2 { - x: (resp.rect.min.x + resp.rect.max.x) / 2f32, - y: (resp.rect.min.y + resp.rect.max.y) / 2f32, - }) - .show(ui.ctx(), |ui| { - ui.horizontal(|ui| { - let id_label = ui.label("Id: "); - let r = ui - .text_edit_singleline(&mut self.id_tmp) - .labelled_by(id_label.id); - if r.lost_focus() && self.id_tmp != self.id { - self.id = unique_component_name(cs, self.id_tmp.as_str()); - } - }); - - ui.horizontal(|ui| { - ui.add( - Slider::new(&mut self.pos[i].0, 0f32..=1000f32) - .text("start x") - .clamp_to_range(false), - ); - ui.add( - Slider::new(&mut self.pos[i].1, 0f32..=1000f32) - .text("start y") - .clamp_to_range(false), - ); - }); - ui.horizontal(|ui| { - ui.add( - Slider::new(&mut self.pos[i + 1].0, 0f32..=1000f32) - .text("end x") - .clamp_to_range(false), - ); - ui.add( - Slider::new(&mut self.pos[i + 1].1, 0f32..=1000f32) - .text("end y") - .clamp_to_range(false), - ); - }); - let r = ComboBox::from_label("input") - .selected_text(format!("{}", input)) - .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => self.id.clone(), - }; - ui.selectable_value(&mut input, id.clone(), id); + properties_window( + ui, + self.id.clone(), + resp, + &mut self.egui_x.properties_window, + |ui| { + input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, cs); + pos_slider(ui, &mut self.pos[i]); + pos_slider(ui, &mut self.pos[i + 1]); + input_selector(ui, &mut self.input_id, cs); + }, + ); + /* + if self.egui_x.properties_window { + let mut input = self.input_id.input.id.clone(); + let resp = Window::new(format!("Properties: {}", self.id)) + .frame(Frame { + inner_margin: Margin::same(10f32), + outer_margin: Margin::same(0f32), + rounding: Rounding::same(10f32), + shadow: Shadow::small_dark(), + fill: ui.visuals().panel_fill, + stroke: ui.visuals().window_stroke, + }) + .default_pos(Pos2 { + x: (resp.rect.min.x + resp.rect.max.x) / 2f32, + y: (resp.rect.min.y + resp.rect.max.y) / 2f32, + }) + .show(ui.ctx(), |ui| { + ui.horizontal(|ui| { + let id_label = ui.label("Id: "); + let r = ui + .text_edit_singleline(&mut self.egui_x.id_tmp) + .labelled_by(id_label.id); + if r.lost_focus() && self.egui_x.id_tmp != self.id { + self.id = unique_component_name(cs, self.egui_x.id_tmp.as_str()); } }); - self.input_id.input.id = input; - }); - if resp.unwrap().response.clicked_elsewhere() { - self.properties_window = false; + + ui.horizontal(|ui| { + ui.add( + Slider::new(&mut self.pos[i].0, 0f32..=1000f32) + .text("start x") + .clamp_to_range(false), + ); + ui.add( + Slider::new(&mut self.pos[i].1, 0f32..=1000f32) + .text("start y") + .clamp_to_range(false), + ); + }); + ui.horizontal(|ui| { + ui.add( + Slider::new(&mut self.pos[i + 1].0, 0f32..=1000f32) + .text("end x") + .clamp_to_range(false), + ); + ui.add( + Slider::new(&mut self.pos[i + 1].1, 0f32..=1000f32) + .text("end y") + .clamp_to_range(false), + ); + }); + let r = ComboBox::from_label("input") + .selected_text(format!("{}", input)) + .show_ui(ui, |ui| { + for c in cs.iter() { + let id = match c.try_borrow_mut() { + Ok(a) => a.get_id_ports().0.clone(), + Err(e) => self.id.clone(), + }; + ui.selectable_value(&mut input, id.clone(), id); + } + }); + self.input_id.input.id = input; + }); + if resp.unwrap().response.clicked_elsewhere() { + self.egui_x.properties_window = false; + } } - } - if resp.clicked_by(PointerButton::Secondary) { - // Open properties window - self.properties_window = true; - } + if resp.clicked_by(PointerButton::Secondary) { + // Open properties window + self.egui_x.properties_window = true; + } + */ } EditorRenderReturn { diff --git a/src/gui_egui/mod.rs b/src/gui_egui/mod.rs index 23808d7b..4850f52c 100644 --- a/src/gui_egui/mod.rs +++ b/src/gui_egui/mod.rs @@ -1,3 +1,4 @@ +mod component_ui; mod editor; mod editor_wire; mod gui; From 5f21d01970041bc1571aa325c5d349b2da0fc0a9 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Mon, 24 Jul 2023 16:14:49 +0200 Subject: [PATCH 12/58] Removed the useage of refcell and enabled serialize and deserialize again --- examples/add.rs | 39 +++++------- src/common.rs | 26 +++++--- src/component_store.rs | 4 +- src/components/add.rs | 2 +- src/components/constant.rs | 2 +- src/components/probe.rs | 2 +- src/components/wire.rs | 2 +- src/gui_egui/component_ui.rs | 37 +++++------ src/gui_egui/components/add.rs | 14 ++-- src/gui_egui/components/constant.rs | 10 +-- src/gui_egui/components/mux.rs | 2 +- src/gui_egui/components/probe.rs | 12 ++-- src/gui_egui/components/probe_out.rs | 10 +-- src/gui_egui/components/register.rs | 4 +- src/gui_egui/components/sext.rs | 2 +- src/gui_egui/components/wire.rs | 12 ++-- src/gui_egui/editor.rs | 95 ++++++++++++++++------------ src/gui_egui/editor_wire.rs | 72 +++++++++++++-------- src/gui_egui/gui.rs | 14 ++-- src/gui_egui/helper.rs | 25 ++++---- src/gui_egui/keymap.rs | 24 +++---- src/gui_egui/library.rs | 65 ++++++++----------- src/simulator.rs | 16 ++--- 23 files changed, 263 insertions(+), 228 deletions(-) diff --git a/examples/add.rs b/examples/add.rs index 716084e6..352bc48d 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, path::PathBuf, rc::Rc}; +use std::{path::PathBuf, rc::Rc}; use syncrim::{ common::{ComponentStore, Input}, components::*, @@ -9,51 +9,42 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(RefCell::new(Add::new( + Rc::new(Add::new( "add".to_string(), (200.0, 120.0), Input::new("c1", "out"), Input::new("c2", "out"), - ))), - Rc::new(RefCell::new(Constant::new( - "c1".to_string(), - (100.0, 100.0), - 3, - ))), - Rc::new(RefCell::new(Constant::new( - "c2".to_string(), - (100.0, 140.0), - 4, - ))), - Rc::new(RefCell::new(Wire::new( + )), + Rc::new(Constant::new("c1".to_string(), (100.0, 100.0), 3)), + Rc::new(Constant::new("c2".to_string(), (100.0, 140.0), 4)), + Rc::new(Wire::new( "w1".to_string(), vec![(110.0, 100.0), (180.0, 100.0)], Input::new("c1", "out"), - ))), - Rc::new(RefCell::new(Wire::new( + )), + Rc::new(Wire::new( "w2".to_string(), vec![(110.0, 140.0), (180.0, 140.0)], Input::new("c2", "out"), - ))), - Rc::new(RefCell::new(Wire::new( + )), + Rc::new(Wire::new( "w3".to_string(), vec![(220.0, 120.0), (260.0, 120.0)], Input::new("add", "out"), - ))), - Rc::new(RefCell::new(Probe::new( + )), + Rc::new(Probe::new( "p1".to_string(), (270.0, 120.0), Input::new("add", "out"), - ))), + )), ], }; let path = PathBuf::from("add.json"); - ////cs.save_file(&path); - //let cs2 = ComponentStore::load_file(&path); + cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(&cs, &path); diff --git a/src/common.rs b/src/common.rs index a673756b..0a501917 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,6 +1,6 @@ use petgraph::Graph; use serde::{Deserialize, Serialize}; -use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use std::{collections::HashMap, rc::Rc}; #[cfg(feature = "gui-vizia")] use vizia::prelude::*; @@ -10,15 +10,15 @@ pub type SignedSignal = i32; pub type Id = String; #[cfg(not(any(feature = "gui-vizia", feature = "gui-egui")))] -type Components = Vec>>; +type Components = Vec>; #[cfg(feature = "gui-vizia")] -type Components = Vec>>; +type Components = Vec>; // todo: Probably make a separate ComponentsEditor type // so we don't have to use refcell everywhere #[cfg(feature = "gui-egui")] -pub type Components = Vec>>; +pub type Components = Vec>; #[cfg_attr(feature = "gui-vizia", derive(Lens))] #[derive(Clone)] @@ -35,7 +35,7 @@ pub struct Simulator { pub graph: Graph, } -#[derive(Serialize)] +#[derive(Deserialize, Serialize)] pub struct ComponentStore { pub store: Components, } @@ -109,7 +109,7 @@ pub trait EguiComponent: Component { fn render( &self, _ui: &mut egui::Ui, - _simulator: Option, + _simulator: Option<&mut Simulator>, _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, @@ -121,11 +121,11 @@ pub trait EguiComponent: Component { fn render_editor( &mut self, _ui: &mut egui::Ui, - _simulator: Option, + _simulator: Option<&mut Simulator>, _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, - _components: &Components, + _id_ports: &Vec<(Id, Ports)>, _editor_mode: EditorMode, ) -> EditorRenderReturn { EditorRenderReturn { @@ -156,6 +156,16 @@ pub struct EguiExtra { pub id_tmp: String, } +#[cfg(feature = "gui-egui")] +impl Default for EguiExtra { + fn default() -> Self { + EguiExtra { + properties_window: false, + id_tmp: String::new(), + } + } +} + #[derive(Debug, Clone)] pub struct Ports { pub inputs: Vec, diff --git a/src/component_store.rs b/src/component_store.rs index 342da35a..cf23cb9b 100644 --- a/src/component_store.rs +++ b/src/component_store.rs @@ -5,7 +5,6 @@ use std::{fs::File, io::prelude::*, path::PathBuf}; use log::*; impl ComponentStore { - /* pub fn load(json: &str) -> Self { serde_json::from_str(json).unwrap() } @@ -27,7 +26,6 @@ impl ComponentStore { } pub fn to_(&self) { - self.store.iter().for_each(|c| c.borrow().to_()); + self.store.iter().for_each(|c| c.to_()); } - */ } diff --git a/src/components/add.rs b/src/components/add.rs index b37344a4..dcad26bf 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -12,7 +12,7 @@ pub struct Add { pub b_in: InputId, #[cfg(feature = "gui-egui")] - #[serde(skip_serializing)] + #[serde(skip)] pub egui_x: EguiExtra, } diff --git a/src/components/constant.rs b/src/components/constant.rs index 34ce8ea4..56de59d7 100644 --- a/src/components/constant.rs +++ b/src/components/constant.rs @@ -7,7 +7,7 @@ pub struct Constant { pub pos: (f32, f32), pub value: Signal, #[cfg(feature = "gui-egui")] - #[serde(skip_serializing)] + #[serde(skip)] pub egui_x: EguiExtra, } diff --git a/src/components/probe.rs b/src/components/probe.rs index c1179a20..7f41ed4c 100644 --- a/src/components/probe.rs +++ b/src/components/probe.rs @@ -7,7 +7,7 @@ pub struct Probe { pub pos: (f32, f32), pub input_id: InputId, #[cfg(feature = "gui-egui")] - #[serde(skip_serializing)] + #[serde(skip)] pub egui_x: EguiExtra, } diff --git a/src/components/wire.rs b/src/components/wire.rs index b74a1637..92329040 100644 --- a/src/components/wire.rs +++ b/src/components/wire.rs @@ -9,7 +9,7 @@ pub struct Wire { pub input_id: InputId, #[cfg(feature = "gui-egui")] - #[serde(skip_serializing)] + #[serde(skip)] pub egui_x: EguiExtra, } diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index cc462cb7..ce008b98 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -1,5 +1,6 @@ use crate::common::{ - ComponentStore, Components, EditorMode, EditorRenderReturn, EguiComponent, InputId, Simulator, + ComponentStore, Components, EditorMode, EditorRenderReturn, EguiComponent, InputId, Ports, + Simulator, }; use crate::gui_egui::helper::{ editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, @@ -82,7 +83,11 @@ pub fn pos_slider(ui: &mut Ui, pos: &mut (f32, f32)) { ); }); } -pub fn input_selector(ui: &mut Ui, input_id: &mut InputId, cs: &Components) { +pub fn input_selector( + ui: &mut Ui, + input_id: &mut InputId, + id_ports: &Vec<(crate::common::Id, Ports)>, +) { let mut port_id = input_id.input.id.clone(); let mut port_field = input_id.input.field.clone(); let label_port_id = format!("{}.id", input_id.id.clone()); @@ -93,29 +98,20 @@ pub fn input_selector(ui: &mut Ui, input_id: &mut InputId, cs: &Components) { ComboBox::from_label(label_port_id) .selected_text(text_port_id) .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => String::from("unknown_id"), - }; + for c in id_ports { + let id = c.0.clone(); ui.selectable_value(&mut port_id, id.clone(), id); } }); ComboBox::from_label(label_port_field) .selected_text(text_port_field) .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => String::from("unknown_id"), - }; + for c in id_ports { + let id = c.0.clone(); if id != port_id { continue; } - let fields = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().1.outputs, - Err(_) => vec![], - }; + let fields = c.1.outputs.clone(); for field in fields { ui.selectable_value(&mut port_field, field.clone(), field); } @@ -126,14 +122,19 @@ pub fn input_selector(ui: &mut Ui, input_id: &mut InputId, cs: &Components) { input_id.input.field = port_field; } -pub fn input_id(ui: &mut Ui, id_tmp: &mut String, id: &mut String, cs: &Components) { +pub fn input_id( + ui: &mut Ui, + id_tmp: &mut String, + id: &mut String, + id_ports: &Vec<(crate::common::Id, Ports)>, +) { ui.horizontal(|ui| { let id_label = ui.label("Id: "); let r = ui .text_edit_singleline(&mut *id_tmp) .labelled_by(id_label.id); if r.lost_focus() && *id_tmp != *id { - *id = unique_component_name(cs, (*id_tmp).as_str()); + *id = unique_component_name(id_ports, (*id_tmp).as_str()); } }); } diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index b95f4265..a97c7e92 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -5,7 +5,7 @@ use crate::gui_egui::helper::{ editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, }; use crate::{ - common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Simulator}, + common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Ports, Simulator}, components::Add, }; use egui::{ @@ -19,7 +19,7 @@ impl EguiComponent for Add { fn render( &self, ui: &mut egui::Ui, - _simulator: Option, + _simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, @@ -82,11 +82,11 @@ impl EguiComponent for Add { fn render_editor( &mut self, ui: &mut egui::Ui, - simulator: Option, + simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - cs: &Components, + id_ports: &Vec<(crate::common::Id, Ports)>, editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; @@ -110,10 +110,10 @@ impl EguiComponent for Add { resp, &mut self.egui_x.properties_window, |ui| { - input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, cs); + input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); - input_selector(ui, &mut self.a_in, cs); - input_selector(ui, &mut self.b_in, cs); + input_selector(ui, &mut self.a_in, id_ports); + input_selector(ui, &mut self.b_in, id_ports); }, ); diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index c7078782..526f025b 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,4 +1,4 @@ -use crate::common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Simulator}; +use crate::common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Ports, Simulator}; use crate::components::Constant; use crate::gui_egui::component_ui::{input_id, pos_slider, properties_window, rect_with_hover}; use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; @@ -13,7 +13,7 @@ impl EguiComponent for Constant { fn render( &self, ui: &mut egui::Ui, - _simulator: Option, + _simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, clip_rect: Rect, @@ -55,11 +55,11 @@ impl EguiComponent for Constant { fn render_editor( &mut self, ui: &mut egui::Ui, - simulator: Option, + simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - cs: &Components, + id_ports: &Vec<(crate::common::Id, Ports)>, editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; @@ -82,7 +82,7 @@ impl EguiComponent for Constant { resp, &mut self.egui_x.properties_window, |ui| { - input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, cs); + input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); ui.add(egui::Slider::new(&mut self.value, u32::MIN..=u32::MAX).text("value")); }, diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 15f9cc0a..ede650e2 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -7,7 +7,7 @@ impl EguiComponent for Mux { fn render( &self, ui: &mut egui::Ui, - simulator: Option, + simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 20b70ad9..d60ce428 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -1,4 +1,4 @@ -use crate::common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Simulator}; +use crate::common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Ports, Simulator}; use crate::components::Probe; use crate::gui_egui::component_ui::{ input_id, input_selector, pos_slider, properties_window, rect_with_hover, @@ -15,7 +15,7 @@ impl EguiComponent for Probe { fn render( &self, ui: &mut egui::Ui, - simulator: Option, + simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, clip_rect: Rect, @@ -63,11 +63,11 @@ impl EguiComponent for Probe { fn render_editor( &mut self, ui: &mut egui::Ui, - simulator: Option, + simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - cs: &Components, + id_ports: &Vec<(crate::common::Id, Ports)>, editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; @@ -91,9 +91,9 @@ impl EguiComponent for Probe { resp, &mut self.egui_x.properties_window, |ui| { - input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, cs); + input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); - input_selector(ui, &mut self.input_id, cs); + input_selector(ui, &mut self.input_id, id_ports); }, ); diff --git a/src/gui_egui/components/probe_out.rs b/src/gui_egui/components/probe_out.rs index 6c14da19..41a7d343 100644 --- a/src/gui_egui/components/probe_out.rs +++ b/src/gui_egui/components/probe_out.rs @@ -6,11 +6,11 @@ use egui::Rect; impl EguiComponent for ProbeOut { fn render( &self, - ui: &mut egui::Ui, - _simulator: Option, - offset: egui::Vec2, - scale: f32, - clip_rect: Rect, + _ui: &mut egui::Ui, + _simulator: Option<&mut Simulator>, + _offset: egui::Vec2, + _scale: f32, + _clip_rect: Rect, _editor_mode: EditorMode, ) -> Option> { todo!(); diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index 261bae93..f5d7f4df 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -7,11 +7,11 @@ impl EguiComponent for Register { fn render( &self, ui: &mut egui::Ui, - _simulator: Option, + _simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, _clip_rect: egui::Rect, - editor_mode: EditorMode, + _editor_mode: EditorMode, ) -> Option> { // 21x41 // middle: 11x 21y (0 0) diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index fe3abc66..4e8ab0f0 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -6,7 +6,7 @@ impl EguiComponent for Sext { fn render( &self, _ui: &mut egui::Ui, - _simulator: Option, + _simulator: Option<&mut Simulator>, _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 72c4a33a..7a8ea838 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -1,5 +1,5 @@ use crate::common::{ - Components, EditorMode, EditorRenderReturn, EguiComponent, Simulator, SnapPriority, + Components, EditorMode, EditorRenderReturn, EguiComponent, Ports, Simulator, SnapPriority, }; use crate::components::Wire; use crate::gui_egui::component_ui::{ @@ -19,7 +19,7 @@ impl EguiComponent for Wire { fn render( &self, ui: &mut Ui, - simulator: Option, + simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, clip_rect: Rect, @@ -77,11 +77,11 @@ impl EguiComponent for Wire { fn render_editor( &mut self, ui: &mut Ui, - simulator: Option, + simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, clip_rect: Rect, - cs: &Components, + id_ports: &Vec<(crate::common::Id, Ports)>, editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; @@ -105,10 +105,10 @@ impl EguiComponent for Wire { resp, &mut self.egui_x.properties_window, |ui| { - input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, cs); + input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos[i]); pos_slider(ui, &mut self.pos[i + 1]); - input_selector(ui, &mut self.input_id, cs); + input_selector(ui, &mut self.input_id, id_ports); }, ); /* diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 9b3f0c8f..45152576 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -1,8 +1,13 @@ -use crate::common::{ComponentStore, Components, EditorMode, EguiComponent, Id, Input, InputId}; +use crate::common::{ + ComponentStore, Components, EditorMode, EguiComponent, Id, Input, InputId, Simulator, +}; use crate::components::*; use crate::gui_egui::{ gui::Gui, - helper::{offset_helper, offset_reverse_helper_pos2, unique_component_name}, + helper::{ + id_ports_of_all_components, offset_helper, offset_reverse_helper_pos2, + unique_component_name, + }, keymap, menu::Menu, }; @@ -10,10 +15,10 @@ use eframe::{egui, Frame}; use egui::{ Color32, Context, LayerId, PointerButton, Pos2, Rect, Response, Shape, Stroke, Style, Ui, Vec2, }; -use std::{cell::RefCell, path::PathBuf, rc::Rc}; +use std::{path::PathBuf, rc::Rc}; pub struct Editor { - pub component_store: ComponentStore, + pub components: Components, pub scale: f32, pub pan: Vec2, pub offset: Vec2, @@ -30,13 +35,13 @@ pub struct Editor { pub wire_cursor_location: Pos2, pub wire_start_comp_port: Option, pub wire_temp_positions: Vec<(f32, f32)>, - pub input_comp: Option>>, + pub input_comp: Option>, pub input_cursor_location: Pos2, } #[derive(Clone)] pub struct CloseToComponent { - pub comp: Rc>, + pub comp: Rc, pub pos: Pos2, pub dist: f32, pub port_id: Id, @@ -44,10 +49,10 @@ pub struct CloseToComponent { // todo: enum for input mode, wire, component, none impl Editor { - pub fn gui(cs: ComponentStore, _path: &PathBuf) -> Self { + pub fn gui(components: Components, _path: &PathBuf) -> Self { let dummy_input = Input::new("id", "field"); Editor { - component_store: cs, + components, scale: 1f32, pan: Vec2::new(0f32, 0f32), offset: Vec2::new(0f32, 0f32), @@ -63,18 +68,14 @@ impl Editor { ui_change: true, library: ComponentStore { store: vec![ - Rc::new(RefCell::new(Add::new( + Rc::new(Add::new( "add".to_string(), (0.0, 0.0), dummy_input.clone(), dummy_input.clone(), - ))), - Rc::new(RefCell::new(Constant::new("c".to_string(), (0.0, 0.0), 0))), - Rc::new(RefCell::new(Probe::new( - "p".to_string(), - (0.0, 0.0), - dummy_input.clone(), - ))), + )), + Rc::new(Constant::new("c".to_string(), (0.0, 0.0), 0)), + Rc::new(Probe::new("p".to_string(), (0.0, 0.0), dummy_input.clone())), ], }, dummy_input, @@ -192,34 +193,50 @@ impl Editor { layer_id = Some(ui.layer_id()); } - let tcs = gui.simulator.ordered_components.clone(); - let s = Editor::gui_to_editor(gui); - s.component_store.store.retain(|c| { - let delete = c - .borrow_mut() - .render_editor( - ui, - None, - s.offset_and_pan, - s.scale, - s.clip_rect, - &tcs, - s.editor_mode, - ) - .delete; - !delete - }); + let e = Editor::gui_to_editor(gui); + let id_ports = id_ports_of_all_components(&e.components); + // The reason we do this is because some of the input modes requires references to + // components, but that makes us unable to get the mutable reference to it + // (We can only get a mutable reference if only ONE reference to it exists) + match e.editor_mode { + EditorMode::Wire | EditorMode::Input => { + for c in &e.components { + c.render( + ui, + None, + e.offset + e.pan, + e.scale, + e.clip_rect, + e.editor_mode, + ); + } + } + _ => e.components.retain_mut(|mut c| { + let delete = (*Rc::get_mut(&mut c).unwrap()) + .render_editor( + ui, + None, + e.offset_and_pan, + e.scale, + e.clip_rect, + &id_ports, + e.editor_mode, + ) + .delete; + !delete + }), + } }); - let s = Editor::gui_to_editor(gui); + let e = Editor::gui_to_editor(gui); let cpr = central_panel.response.interact(egui::Sense::drag()); if cpr.dragged_by(PointerButton::Middle) { - s.pan += cpr.drag_delta(); - s.offset_and_pan = s.pan + s.offset; + e.pan += cpr.drag_delta(); + e.offset_and_pan = e.pan + e.offset; } - match s.editor_mode { - EditorMode::Wire => crate::gui_egui::editor_wire::wire_mode(ctx, s, cpr, layer_id), - EditorMode::Input => crate::gui_egui::library::input_mode(ctx, s, cpr, layer_id), + match e.editor_mode { + EditorMode::Wire => crate::gui_egui::editor_wire::wire_mode(ctx, e, cpr, layer_id), + EditorMode::Input => crate::gui_egui::library::input_mode(ctx, e, cpr, layer_id), EditorMode::Default => ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Default), } if central_panel.response.hovered() { diff --git a/src/gui_egui/editor_wire.rs b/src/gui_egui/editor_wire.rs index be8dc60d..e8545163 100644 --- a/src/gui_egui/editor_wire.rs +++ b/src/gui_egui/editor_wire.rs @@ -2,54 +2,57 @@ use crate::common::{Components, EguiComponent, Id, Input, SnapPriority}; use crate::components::Wire; use crate::gui_egui::editor::{CloseToComponent, Editor}; use crate::gui_egui::helper::{ - offset_helper, offset_reverse_helper, offset_reverse_helper_pos2, unique_component_name, + id_ports_of_all_components, offset_helper, offset_reverse_helper, offset_reverse_helper_pos2, + unique_component_name, }; use egui::{Color32, Context, CursorIcon, LayerId, PointerButton, Pos2, Response, Shape, Stroke}; -use std::{cell::RefCell, rc::Rc}; +use std::rc::Rc; -pub fn drag_started(ctx: &Context, e: &mut Editor, cpr: Response) { - // todo: Snap functionality should also apply here +pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { e.wire_mode_ended = false; ctx.input_mut(|i| { let origin = i.pointer.press_origin().unwrap(); e.wire_cursor_location = origin; let offset_cursor_scale = offset_reverse_helper_pos2(origin, e.scale, e.offset_and_pan); - let (closest, closest_wire) = - clicked_close_to_input_output(offset_cursor_scale, &e.component_store.store); - let closest_uw = closest.clone().unwrap(); + let (closest, _closest_wire) = + clicked_close_to_input_output(offset_cursor_scale, &e.components); + let closest_uw = closest.unwrap(); // First click ALWAYS has to start at a port so we force it if e.wire_temp_positions.len() == 0 { // requires at least one component on the canvas - e.wire_start_comp_port = closest; let new_pos = closest_uw.pos; + e.wire_start_comp_port = Some(closest_uw); let new_pos = offset_helper((new_pos.x, new_pos.y), e.scale, e.offset_and_pan); e.wire_temp_positions.push((new_pos.x, new_pos.y)); + // We clicked close to a port so this will be the last click done } else if e.wire_temp_positions.len() > 0 && closest_uw.dist <= 10.0f32 { // We should finish the component last_click(e, closest_uw); + // Click somewhere not near a component } else { let (wire1, wire2) = wire_split_into_two(*e.wire_temp_positions.last().unwrap(), (origin.x, origin.y)); e.wire_temp_positions.push(wire1); e.wire_temp_positions.push(wire2); - //e.wire_temp_positions.push((origin.x, origin.y)); } }); } pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { - let in_c = e.wire_start_comp_port.as_ref().unwrap(); + //let in_c = e.wire_start_comp_port.unwrap(); + let in_c = std::mem::replace(&mut e.wire_start_comp_port, None).unwrap(); let out_c = closest_uw; let (field_name, input, is_comp_start) = get_outputs_from_port(&in_c.port_id, &in_c.comp, &out_c.port_id, &out_c.comp); match input { Some(i) => { println!("Creating wire component"); - let id = unique_component_name(&e.component_store.store, "w"); + let id_ports = id_ports_of_all_components(&e.components); + let id = unique_component_name(&id_ports, "w"); let mut pos_v: Vec<(f32, f32)> = vec![]; for pos in &e.wire_temp_positions { @@ -63,15 +66,18 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { wire_split_into_two_vec((last_pos.x, last_pos.y), (out_c.pos.x, out_c.pos.y)); pos_v.append(&mut v); - e.component_store - .store - .push(Rc::new(RefCell::new(Wire::new(id, pos_v, i.clone())))); + e.components.push(Rc::new(Wire::new(id, pos_v, i.clone()))); // Now actually set the input of the wired component - if is_comp_start { - in_c.comp.borrow_mut().set_id_port(field_name, i); - } else { - out_c.comp.borrow_mut().set_id_port(field_name, i); + let comp = if is_comp_start { in_c } else { out_c }; + match get_component(&e.components, comp) { + Some(c) => { + println!("value: {}", c); + Rc::get_mut(&mut e.components[c]) + .unwrap() + .set_id_port(field_name, i) + } + None => println!("none!!!"), } } None => { @@ -81,6 +87,20 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { reset_wire_mode(e); } +pub fn get_component(components: &Components, comp: CloseToComponent) -> Option { + for (i, c) in components.iter().enumerate() { + println!( + "reference amount: {}", + Rc::strong_count(components.get(i).unwrap()) + ); + if Rc::ptr_eq(&c, &comp.comp) { + drop(comp); + return Some(i); + } + } + None +} + pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option) { ctx.output_mut(|o| o.cursor_icon = CursorIcon::Crosshair); @@ -99,8 +119,8 @@ pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option< }); let offset_cursor_scale = offset_reverse_helper_pos2(e.wire_cursor_location, e.scale, e.offset_and_pan); - let (closest, closest_wire) = - clicked_close_to_input_output(offset_cursor_scale, &e.component_store.store); + let (closest, _closest_wire) = + clicked_close_to_input_output(offset_cursor_scale, &e.components); let wire_shown_location = match closest { Some(c) => { @@ -170,11 +190,11 @@ pub fn reset_wire_mode(e: &mut Editor) { /// returns an input made from the output pub fn get_outputs_from_port( port_id_start: &Id, - comp_start: &Rc>, + comp_start: &Rc, port_id_end: &Id, - comp_end: &Rc>, + comp_end: &Rc, ) -> (Id, Option, bool) { - let (id, ports_start) = comp_start.borrow().get_id_ports(); + let (id, ports_start) = comp_start.get_id_ports(); for port_id in ports_start.outputs { if port_id == *port_id_start { return ( @@ -184,7 +204,7 @@ pub fn get_outputs_from_port( ); } } - let (id, ports_end) = comp_end.borrow().get_id_ports(); + let (id, ports_end) = comp_end.get_id_ports(); for port_id in ports_end.outputs { if port_id == *port_id_end { return ( @@ -205,8 +225,8 @@ pub fn clicked_close_to_input_output( let mut closest: Option = None; let mut closest_wire: Option = None; for comp in components { - let ports = comp.borrow_mut().ports_location(); - let prio = comp.borrow_mut().snap_priority(); + let ports = comp.ports_location(); + let prio = comp.snap_priority(); let clos: &mut Option = match prio { SnapPriority::Wire => &mut closest_wire, _ => &mut closest, diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index 4d91353e..6f59563e 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -2,9 +2,10 @@ use crate::common::{ComponentStore, EditorMode, Simulator}; use crate::gui_egui::{editor::Editor, keymap, keymap::Shortcuts, menu::Menu}; use eframe::egui; use std::path::PathBuf; +use std::rc::Rc; pub struct Gui { - pub simulator: Simulator, + pub simulator: Option, pub path: PathBuf, // History, acts like a stack pub history: Vec>, @@ -21,7 +22,7 @@ pub struct Gui { pub editor_use: bool, } -pub fn gui(cs: &ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { +pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { let mut clock = 0; let simulator = Simulator::new(cs, &mut clock); let options = eframe::NativeOptions::default(); @@ -30,7 +31,7 @@ pub fn gui(cs: &ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { let gui = Gui { clock, path, - simulator, + simulator: Some(simulator), history: vec![], scale: 1.0f32, ui_change: true, @@ -115,12 +116,13 @@ impl Gui { fn draw_area(&mut self, ctx: &egui::Context, frame: egui::Frame) { let central_panel = egui::CentralPanel::default().frame(frame).show(ctx, |ui| { + let sim = self.simulator.as_mut().unwrap(); ui.set_clip_rect(self.clip_rect); // Don't draw over the rest of the ui - for c in &self.simulator.ordered_components { - c.borrow().render( + for c in &sim.ordered_components.clone() { + c.render( ui, - Some(self.simulator.clone()), + Some(sim), self.offset + self.pan, self.scale, self.clip_rect, diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 3d72e012..2867507e 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -1,5 +1,7 @@ -use crate::common::{Components, EditorMode}; +use crate::common::{Components, EditorMode, EguiComponent, Ports}; +use crate::gui_egui::editor::CloseToComponent; use egui::{Pos2, Rect, Response, Sense, Vec2}; +use std::rc::Rc; pub fn offset_reverse_helper_pos2(xy: Pos2, scale: f32, offset: Vec2) -> Pos2 { egui::Pos2 { @@ -45,16 +47,13 @@ pub fn out_of_bounds(request: Rect, clip_rect: Rect) -> Rect { return rect; } -pub fn unique_component_name(cs: &Components, id: &str) -> String { +pub fn unique_component_name(id_ports: &Vec<(crate::common::Id, Ports)>, id: &str) -> String { let mut new_id: String = id.into(); let mut contains_id = true; while contains_id { contains_id = false; - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0, - Err(e) => String::from(""), - }; + for c in id_ports { + let id = c.0.clone(); if id == new_id { contains_id = true; // todo: make this fancier @@ -66,6 +65,14 @@ pub fn unique_component_name(cs: &Components, id: &str) -> String { String::from(new_id) } +pub fn id_ports_of_all_components(cs: &Components) -> Vec<(crate::common::Id, Ports)> { + let mut v = vec![]; + for c in cs.iter() { + v.push(c.get_id_ports()) + } + v +} + pub fn editor_mode_to_sense(editor_mode: EditorMode) -> Sense { match editor_mode { EditorMode::Wire => Sense { @@ -80,7 +87,3 @@ pub fn editor_mode_to_sense(editor_mode: EditorMode) -> Sense { }, } } - -// todo: Create the properties window the same way every time for the different components - -//pub fn diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 09545d11..5df9a95a 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -1,6 +1,7 @@ use crate::common::{ComponentStore, EditorMode, Simulator}; use crate::gui_egui::{editor::Editor, Gui}; use egui::{Key, KeyboardShortcut, Modifiers}; +use std::rc::Rc; #[derive(Copy, Clone)] pub struct Shortcuts { @@ -226,20 +227,21 @@ pub fn file_editor_toggle_fn(gui: &mut Gui) { gui.editor_use = false; match gui.editor.as_mut() { Some(e) => { - gui.simulator = Simulator::new(&e.component_store, &mut 0); + let components = e.components.clone(); + let simulator = + Simulator::new(ComponentStore { store: components }, &mut gui.clock); + gui.simulator = Some(simulator); } _ => (), } // todo: Make us swap back into simulator mode (create new simulator) } false => { - gui.editor.get_or_insert(Editor::gui( - ComponentStore { - store: gui.simulator.ordered_components.clone(), - }, - &gui.path, - )); - + let simulator = std::mem::replace(&mut gui.simulator, None); + let simulator = simulator.unwrap(); + let components = simulator.ordered_components.clone(); + drop(simulator); + let _ = gui.editor.insert(Editor::gui(components, &gui.path)); gui.editor_use = true; } } @@ -294,18 +296,18 @@ pub fn control_pause_fn(gui: &mut Gui) { } pub fn control_reset_fn(gui: &mut Gui) { if !gui.editor_use { - gui.simulator.reset(&mut gui.clock); + gui.simulator.as_mut().unwrap().reset(&mut gui.clock); gui.pause = true; } } pub fn control_step_forward_fn(gui: &mut Gui) { if !gui.editor_use { - gui.simulator.clock(&mut gui.clock); + gui.simulator.as_mut().unwrap().clock(&mut gui.clock); } } pub fn control_step_back_fn(gui: &mut Gui) { if !gui.editor_use { - gui.simulator.un_clock(&mut gui.clock); + gui.simulator.as_mut().unwrap().un_clock(&mut gui.clock); } } pub fn editor_wire_fn(gui: &mut Gui) { diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index 16565ea3..a37d6e87 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -2,10 +2,10 @@ use crate::common::{EditorMode, EguiComponent}; use crate::components::*; use crate::gui_egui::{ editor::Editor, - helper::{offset_reverse_helper_pos2, unique_component_name}, + helper::{id_ports_of_all_components, offset_reverse_helper_pos2, unique_component_name}, }; use egui::{Context, CursorIcon, LayerId, PointerButton, Pos2, Rect, Response, Ui, Vec2}; -use std::{cell::RefCell, path::PathBuf, rc::Rc}; +use std::{path::PathBuf, rc::Rc}; pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option) { let layer_id = layer_id.unwrap(); @@ -30,7 +30,7 @@ pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option clip_rect, Rect::EVERYTHING, ); - e.input_comp.as_ref().unwrap().borrow_mut().render( + e.input_comp.as_ref().unwrap().render( &mut ui, None, Vec2::new(e.input_cursor_location.x, e.input_cursor_location.y), @@ -69,10 +69,9 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { }, }; for c in e.library.store.iter() { - let size = c.borrow_mut().size(); + let size = c.size(); padding.y = padding.y - e.scale * size.min.y; let r_vec = c - .borrow_mut() .render(ui, None, padding, e.scale, clip_rect, e.editor_mode) .unwrap(); let rect = r_vec[0].rect.clone(); @@ -94,37 +93,29 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { // todo: This should really just copy the component that's in e.input_comp pub fn add_comp_to_editor(e: &mut Editor) { let pos = offset_reverse_helper_pos2(e.input_cursor_location, e.scale, e.offset); - let mut comp: Rc> = match e - .input_comp - .as_ref() + let id_ports = id_ports_of_all_components(&e.components); + let mut comp: Rc = + match e.input_comp.as_mut().unwrap().get_id_ports().0.as_str() { + "c" => { + let id = unique_component_name(&id_ports, "c"); + Rc::new(Constant::new(id, (0.0, 0.0), 0)) + } + "p" => { + let id = unique_component_name(&id_ports, "p"); + Rc::new(Probe::new(id, (0.0, 0.0), e.dummy_input.clone())) + } + "add" | _ => { + let id = unique_component_name(&id_ports, "add"); + Rc::new(Add::new( + id, + (0.0, 0.0), + e.dummy_input.clone(), + e.dummy_input.clone(), + )) + } + }; + Rc::::get_mut(&mut comp) .unwrap() - .borrow_mut() - .get_id_ports() - .0 - .as_str() - { - "c" => { - let id = unique_component_name(&e.component_store.store, "c"); - Rc::new(RefCell::new(Constant::new(id, (0.0, 0.0), 0))) - } - "p" => { - let id = unique_component_name(&e.component_store.store, "p"); - Rc::new(RefCell::new(Probe::new( - id, - (0.0, 0.0), - e.dummy_input.clone(), - ))) - } - "add" | _ => { - let id = unique_component_name(&e.component_store.store, "add"); - Rc::new(RefCell::new(Add::new( - id, - (0.0, 0.0), - e.dummy_input.clone(), - e.dummy_input.clone(), - ))) - } - }; - comp.borrow_mut().set_pos((pos.x, pos.y)); - e.component_store.store.push(comp); + .set_pos((pos.x, pos.y)); + e.components.push(comp); } diff --git a/src/simulator.rs b/src/simulator.rs index 6619f166..120bdfc2 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -19,7 +19,7 @@ pub struct IdComponent(pub HashMap>); // A solution is to evaluate register updates separately from other components // ... but not currently implemented ... impl Simulator { - pub fn new(component_store: &ComponentStore, clock: &mut usize) -> Self { + pub fn new(component_store: ComponentStore, clock: &mut usize) -> Self { let mut lens_values = vec![]; let mut id_start_index = HashMap::new(); @@ -31,7 +31,7 @@ impl Simulator { trace!("-- allocate storage for lensed outputs"); for c in &component_store.store { - let (id, ports) = c.borrow().get_id_ports(); + let (id, ports) = c.get_id_ports(); trace!("id {}, ports {:?}", id, ports); // start index for outputs related to component @@ -73,19 +73,19 @@ impl Simulator { trace!("\nid_node {:?}", id_node); for (node, c) in &node_comp { - trace!("node {:?}, comp_id {:?}", node, c.borrow().get_id_ports()); + trace!("node {:?}, comp_id {:?}", node, c.get_id_ports()); } // insert edges for (to_id, c) in &id_component { let to_component = id_component.get(to_id).unwrap(); - let (_, ports) = to_component.borrow().get_id_ports(); + let (_, ports) = to_component.get_id_ports(); trace!("to_id :{}, ports: {:?}", to_id, ports); if ports.out_type == OutputType::Combinatorial { let to_node = id_node.get(to_id).unwrap(); - let (_, ports) = c.borrow().get_id_ports(); + let (_, ports) = c.get_id_ports(); for in_port in &ports.inputs { let from_id = &in_port.input.id; @@ -117,7 +117,7 @@ impl Simulator { let component_ids: Vec = ordered_components .iter() - .map(|c| c.borrow().get_id_ports().0) + .map(|c| c.get_id_ports().0) .collect(); let mut simulator = Simulator { @@ -192,7 +192,7 @@ impl Simulator { let ordered_components = self.ordered_components.clone(); for component in ordered_components { - component.borrow().clock(self); + component.clock(self); } *clock = self.history.len(); } @@ -206,7 +206,7 @@ impl Simulator { let ordered_components = self.ordered_components.clone(); for component in ordered_components { - component.borrow().un_clock(); + component.un_clock(); } } *clock = self.history.len(); From f6847f12c0d18e746de77ff591001a0aa85c43ea Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Mon, 24 Jul 2023 17:48:01 +0200 Subject: [PATCH 13/58] Fixed bug with the tmp id not being set when default is made --- src/common.rs | 2 ++ src/components/add.rs | 16 ++++++++-------- src/gui_egui/components/add.rs | 4 ++++ src/gui_egui/components/constant.rs | 4 ++++ src/gui_egui/components/probe.rs | 4 ++++ src/gui_egui/components/wire.rs | 4 ++++ src/gui_egui/gui.rs | 2 ++ src/gui_egui/keymap.rs | 8 ++++++-- 8 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/common.rs b/src/common.rs index 6ee2f56b..0fb2418a 100644 --- a/src/common.rs +++ b/src/common.rs @@ -185,6 +185,8 @@ pub trait EguiComponent: Component { SnapPriority::Default } fn set_pos(&mut self, _pos: (f32, f32)) {} + + fn set_id_tmp(&mut self) {} } #[cfg(feature = "gui-egui")] diff --git a/src/components/add.rs b/src/components/add.rs index da432923..3304214c 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -82,6 +82,14 @@ impl Component for Add { simulator.set_out_val(&self.id, "out", value); simulator.set_out_val(&self.id, "overflow", overflow); } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + "a_in" => self.a_in.input = new_input, + "b_in" => self.b_in.input = new_input, + _ => (), + } + } } #[cfg(test)] @@ -156,12 +164,4 @@ mod test { (true as SignalUnsigned).into() ); } - - fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - match target_port_id.as_str() { - "a_in" => self.a_in.input = new_input, - "b_in" => self.b_in.input = new_input, - _ => (), - } - } } diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index a97c7e92..ed601d4d 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -146,4 +146,8 @@ impl EguiComponent for Add { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + fn set_id_tmp(&mut self) { + self.egui_x.id_tmp = self.id.clone(); + } } diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 2012260e..066c4443 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -129,4 +129,8 @@ impl EguiComponent for Constant { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + fn set_id_tmp(&mut self) { + self.egui_x.id_tmp = self.id.clone(); + } } diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index c800af95..84a975f5 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -130,4 +130,8 @@ impl EguiComponent for Probe { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + fn set_id_tmp(&mut self) { + self.egui_x.id_tmp = self.id.clone(); + } } diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index f685332f..994e36ef 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -222,4 +222,8 @@ impl EguiComponent for Wire { fn snap_priority(&self) -> SnapPriority { SnapPriority::Wire } + + fn set_id_tmp(&mut self) { + self.egui_x.id_tmp = self.id.clone(); + } } diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index 6f59563e..e3f709bd 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -28,6 +28,7 @@ pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { let options = eframe::NativeOptions::default(); let path = path.to_owned(); simulator.save_dot(&path); + let gui = Gui { clock, path, @@ -43,6 +44,7 @@ pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { editor: None, editor_use: false, }; + eframe::run_native("SyncRim", options, Box::new(|_cc| Box::new(gui))) } diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 32c6e50b..cb08ed47 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -1,7 +1,7 @@ use crate::common::{ComponentStore, EditorMode, Simulator}; use crate::gui_egui::{editor::Editor, Gui}; use egui::{Key, KeyboardShortcut, Modifiers}; -use std::path::PathBuf; +use std::{path::PathBuf, rc::Rc}; #[derive(Copy, Clone)] pub struct Shortcuts { @@ -253,8 +253,12 @@ pub fn file_editor_toggle_fn(gui: &mut Gui) { false => { let simulator = std::mem::replace(&mut gui.simulator, None); let simulator = simulator.unwrap(); - let components = simulator.ordered_components.clone(); + let mut components = simulator.ordered_components.clone(); drop(simulator); + + for mut c in components.iter_mut() { + (*Rc::get_mut(&mut c).unwrap()).set_id_tmp(); + } let _ = gui.editor.insert(Editor::gui(components, &gui.path)); gui.editor_use = true; } From e561f31cacd6a847dce92e5988e8cdbe3c05d348 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Mon, 24 Jul 2023 18:56:39 +0200 Subject: [PATCH 14/58] Fix almost all tests/examples --- examples/add_edit.rs | 51 +++---- examples/add_mux.rs | 192 +++++++++++++------------- examples/add_reg.rs | 114 +++++++-------- examples/add_reg_compound_wire.rs | 74 +++++----- examples/data_mem.rs | 146 +++++++++----------- examples/mux.rs | 116 +++++++--------- examples/probe_edit.rs | 12 +- examples/reg.rs | 38 +++-- examples/sext.rs | 42 +++--- src/common.rs | 2 +- src/components/add.rs | 23 +-- src/components/mem.rs | 112 ++++++++++----- src/components/mux.rs | 10 +- src/components/probe_edit.rs | 7 + src/components/register.rs | 18 +++ src/components/sext.rs | 50 +++++-- src/gui_egui/components/mod.rs | 1 + src/gui_egui/components/probe_edit.rs | 19 +++ src/main.rs | 4 +- src/simulator.rs | 19 ++- 20 files changed, 553 insertions(+), 497 deletions(-) create mode 100644 src/gui_egui/components/probe_edit.rs diff --git a/examples/add_edit.rs b/examples/add_edit.rs index 11761cb6..61f07625 100644 --- a/examples/add_edit.rs +++ b/examples/add_edit.rs @@ -9,35 +9,30 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Add { - id: "add".to_string(), - pos: (200.0, 120.0), - a_in: Input::new("c1", "out"), - - b_in: Input::new("c2", "out"), - }), + Rc::new(Add::new( + "add", + (200.0, 120.0), + Input::new("c1", "out"), + Input::new("c2", "out"), + )), Rc::new(ProbeEdit::new("c1", (60.0, 100.0))), Rc::new(ProbeEdit::new("c2", (60.0, 140.0))), - Rc::new(Wire { - id: "w1".to_string(), - pos: vec![(110.0, 100.0), (180.0, 100.0)], - input: Input::new("c1", "out"), - }), - Rc::new(Wire { - id: "w2".to_string(), - pos: vec![(110.0, 140.0), (180.0, 140.0)], - input: Input::new("c2", "out"), - }), - Rc::new(Wire { - id: "w3".to_string(), - pos: vec![(220.0, 120.0), (260.0, 120.0)], - input: Input::new("add", "out"), - }), - Rc::new(Probe { - id: "p1".to_string(), - pos: (270.0, 120.0), - input: Input::new("add", "out"), - }), + Rc::new(Wire::new( + "w1", + vec![(110.0, 100.0), (180.0, 100.0)], + Input::new("c1", "out"), + )), + Rc::new(Wire::new( + "w2", + vec![(110.0, 140.0), (180.0, 140.0)], + Input::new("c2", "out"), + )), + Rc::new(Wire::new( + "w3", + vec![(220.0, 120.0), (260.0, 120.0)], + Input::new("add", "out"), + )), + Rc::new(Probe::new("p1", (270.0, 120.0), Input::new("add", "out"))), ], }; @@ -45,7 +40,7 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(&cs, &path); diff --git a/examples/add_mux.rs b/examples/add_mux.rs index 0609d719..bd725215 100644 --- a/examples/add_mux.rs +++ b/examples/add_mux.rs @@ -9,113 +9,109 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Add { - id: "add".to_string(), - pos: (200.0, 120.0), - a_in: Input::new("c", "out"), - b_in: Input::new("r1", "out"), - }), + Rc::new(Add::new( + "add", + (200.0, 120.0), + Input::new("c", "out"), + Input::new("r1", "out"), + )), Constant::rc_new("c", (100.0, 100.0), 1), - Rc::new(Register { - id: "r1".to_string(), - pos: (100.0, 140.0), - r_in: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "w1".to_string(), - pos: vec![(110.0, 100.0), (180.0, 100.0)], - input: Input::new("c", "out"), - }), - Rc::new(Wire { - id: "w2".to_string(), - pos: vec![(110.0, 140.0), (180.0, 140.0)], - input: Input::new("r1", "out"), - }), - Rc::new(Wire { - id: "w3".to_string(), - pos: vec![(220.0, 120.0), (260.0, 120.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "w4".to_string(), - pos: vec![(260.0, 120.0), (260.0, 180.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "w5".to_string(), - pos: vec![(60.0, 180.0), (260.0, 180.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "w6".to_string(), - pos: vec![(60.0, 140.0), (60.0, 180.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "w7".to_string(), - pos: vec![(60.0, 140.0), (90.0, 140.0)], - input: Input::new("add", "out"), - }), - Rc::new(Probe { - id: "p_add".to_string(), - pos: (280.0, 120.0), - input: Input::new("add", "out"), - }), - Rc::new(Probe { - id: "p_reg".to_string(), - pos: (130.0, 120.0), - input: Input::new("r1", "out"), - }), - Rc::new(Mux { - id: "mux".to_string(), - pos: (270.0, 300.0), - select: Input::new("add", "out"), - m_in: vec![ + Rc::new(Register::new( + "r1", + (100.0, 140.0), + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "w1", + vec![(110.0, 100.0), (180.0, 100.0)], + Input::new("c", "out"), + )), + Rc::new(Wire::new( + "w2", + vec![(110.0, 140.0), (180.0, 140.0)], + Input::new("r1", "out"), + )), + Rc::new(Wire::new( + "w3", + vec![(220.0, 120.0), (260.0, 120.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "w4", + vec![(260.0, 120.0), (260.0, 180.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "w5", + vec![(60.0, 180.0), (260.0, 180.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "w6", + vec![(60.0, 140.0), (60.0, 180.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "w7", + vec![(60.0, 140.0), (90.0, 140.0)], + Input::new("add", "out"), + )), + Rc::new(Probe::new( + "p_add", + (280.0, 120.0), + Input::new("add", "out"), + )), + Rc::new(Probe::new("p_reg", (130.0, 120.0), Input::new("r1", "out"))), + Rc::new(Mux::new( + "mux", + (270.0, 300.0), + Input::new("add", "out"), + vec![ Input::new("mc1", "out"), Input::new("mc2", "out"), Input::new("mc3", "out"), Input::new("mc4", "out"), ], - }), + )), Constant::rc_new("mc1", (150.0, 270.0), 0), Constant::rc_new("mc2", (150.0, 290.0), 1), Constant::rc_new("mc3", (150.0, 310.0), 2), Constant::rc_new("mc4", (150.0, 330.0), 3), - Rc::new(Wire { - id: "wm_sel".to_string(), - pos: vec![(260.0, 180.0), (260.0, 250.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "wm1".to_string(), - pos: vec![(200.0, 270.0), (250.0, 270.0)], - input: Input::new("mc1", "out"), - }), - Rc::new(Wire { - id: "wm2".to_string(), - pos: vec![(200.0, 290.0), (250.0, 290.0)], - input: Input::new("mc2", "out"), - }), - Rc::new(Wire { - id: "wm3".to_string(), - pos: vec![(200.0, 310.0), (250.0, 310.0)], - input: Input::new("mc3", "out"), - }), - Rc::new(Wire { - id: "wm4".to_string(), - pos: vec![(200.0, 330.0), (250.0, 330.0)], - input: Input::new("mc4", "out"), - }), - Rc::new(Wire { - id: "wm_o0".to_string(), - pos: vec![(290.0, 300.0), (340.0, 300.0)], - input: Input::new("mux", "out"), - }), - Rc::new(Probe { - id: "p_mux".to_string(), - pos: (350.0, 300.0), - input: Input::new("mux", "out"), - }), + Rc::new(Wire::new( + "wm_sel", + vec![(260.0, 180.0), (260.0, 250.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "wm1", + vec![(200.0, 270.0), (250.0, 270.0)], + Input::new("mc1", "out"), + )), + Rc::new(Wire::new( + "wm2", + vec![(200.0, 290.0), (250.0, 290.0)], + Input::new("mc2", "out"), + )), + Rc::new(Wire::new( + "wm3", + vec![(200.0, 310.0), (250.0, 310.0)], + Input::new("mc3", "out"), + )), + Rc::new(Wire::new( + "wm4", + vec![(200.0, 330.0), (250.0, 330.0)], + Input::new("mc4", "out"), + )), + Rc::new(Wire::new( + "wm_o0", + vec![(290.0, 300.0), (340.0, 300.0)], + Input::new("mux", "out"), + )), + Rc::new(Probe::new( + "p_mux", + (350.0, 300.0), + Input::new("mux", "out"), + )), ], }; @@ -123,7 +119,7 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(&cs, &path); diff --git a/examples/add_reg.rs b/examples/add_reg.rs index 94eea5bd..75851220 100644 --- a/examples/add_reg.rs +++ b/examples/add_reg.rs @@ -9,63 +9,63 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Add { - id: "add".to_string(), - pos: (200.0, 120.0), - a_in: Input::new("c", "out"), - b_in: Input::new("reg", "out"), - }), + Rc::new(Add::new( + "add", + (200.0, 120.0), + Input::new("c", "out"), + Input::new("reg", "out"), + )), Constant::rc_new("c", (100.0, 100.0), 3), - Rc::new(Register { - id: "reg".to_string(), - pos: (100.0, 140.0), - r_in: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "w1".to_string(), - pos: vec![(110.0, 100.0), (180.0, 100.0)], - input: Input::new("c", "out"), - }), - Rc::new(Wire { - id: "w2".to_string(), - pos: vec![(110.0, 140.0), (180.0, 140.0)], - input: Input::new("reg", "out"), - }), - Rc::new(Wire { - id: "w3".to_string(), - pos: vec![(220.0, 120.0), (260.0, 120.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "w4".to_string(), - pos: vec![(260.0, 120.0), (260.0, 180.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "w5".to_string(), - pos: vec![(60.0, 180.0), (260.0, 180.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "w6".to_string(), - pos: vec![(60.0, 140.0), (60.0, 180.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "w7".to_string(), - pos: vec![(60.0, 140.0), (90.0, 140.0)], - input: Input::new("add", "out"), - }), - Rc::new(Probe { - id: "p_add".to_string(), - pos: (280.0, 120.0), - input: Input::new("add", "out"), - }), - Rc::new(Probe { - id: "p_reg".to_string(), - pos: (130.0, 120.0), - input: Input::new("reg", "out"), - }), + Rc::new(Register::new( + "reg", + (100.0, 140.0), + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "w1", + vec![(110.0, 100.0), (180.0, 100.0)], + Input::new("c", "out"), + )), + Rc::new(Wire::new( + "w2", + vec![(110.0, 140.0), (180.0, 140.0)], + Input::new("reg", "out"), + )), + Rc::new(Wire::new( + "w3", + vec![(220.0, 120.0), (260.0, 120.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "w4", + vec![(260.0, 120.0), (260.0, 180.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "w5", + vec![(60.0, 180.0), (260.0, 180.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "w6", + vec![(60.0, 140.0), (60.0, 180.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "w7", + vec![(60.0, 140.0), (90.0, 140.0)], + Input::new("add", "out"), + )), + Rc::new(Probe::new( + "p_add", + (280.0, 120.0), + Input::new("add", "out"), + )), + Rc::new(Probe::new( + "p_reg", + (130.0, 120.0), + Input::new("reg", "out"), + )), ], }; @@ -73,7 +73,7 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(&cs, &path); diff --git a/examples/add_reg_compound_wire.rs b/examples/add_reg_compound_wire.rs index b75f6089..21596e20 100644 --- a/examples/add_reg_compound_wire.rs +++ b/examples/add_reg_compound_wire.rs @@ -9,31 +9,31 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Add { - id: "add".to_string(), - pos: (200.0, 120.0), - a_in: Input::new("c", "out"), - b_in: Input::new("reg", "out"), - }), + Rc::new(Add::new( + "add", + (200.0, 120.0), + Input::new("c", "out"), + Input::new("reg", "out"), + )), Constant::rc_new("c", (100.0, 100.0), 3), - Rc::new(Register { - id: "reg".to_string(), - pos: (100.0, 140.0), - r_in: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "w1".to_string(), - pos: vec![(110.0, 100.0), (180.0, 100.0)], - input: Input::new("c", "out"), - }), - Rc::new(Wire { - id: "w2".to_string(), - pos: vec![(110.0, 140.0), (180.0, 140.0)], - input: Input::new("reg", "out"), - }), - Rc::new(Wire { - id: "w3".to_string(), - pos: vec![ + Rc::new(Register::new( + "reg", + (100.0, 140.0), + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "w1", + vec![(110.0, 100.0), (180.0, 100.0)], + Input::new("c", "out"), + )), + Rc::new(Wire::new( + "w2", + vec![(110.0, 140.0), (180.0, 140.0)], + Input::new("reg", "out"), + )), + Rc::new(Wire::new( + "w3", + vec![ (220.0, 120.0), (260.0, 120.0), (260.0, 180.0), @@ -41,18 +41,18 @@ fn main() { (60.0, 140.0), (90.0, 140.0), ], - input: Input::new("add", "out"), - }), - Rc::new(Probe { - id: "p_add".to_string(), - pos: (280.0, 120.0), - input: Input::new("add", "out"), - }), - Rc::new(Probe { - id: "p_reg".to_string(), - pos: (130.0, 120.0), - input: Input::new("reg", "out"), - }), + Input::new("add", "out"), + )), + Rc::new(Probe::new( + "p_add", + (280.0, 120.0), + Input::new("add", "out"), + )), + Rc::new(Probe::new( + "p_reg", + (130.0, 120.0), + Input::new("reg", "out"), + )), ], }; @@ -60,7 +60,7 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(&cs, &path); diff --git a/examples/data_mem.rs b/examples/data_mem.rs index d95f6abe..de0a58ad 100644 --- a/examples/data_mem.rs +++ b/examples/data_mem.rs @@ -9,94 +9,74 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Mem { - id: "mem".to_string(), - pos: (180.0, 200.0), - - width: 200.0, - height: 100.0, - + Rc::new(Mem::new( + "mem", + (180.0, 200.0), + 200.0, + 100.0, // configuration - big_endian: true, - + true, // ports - data: Input::new("data", "out"), - addr: Input::new("addr", "out"), - ctrl: Input::new("ctrl", "out"), - sign: Input::new("sext", "out"), - size: Input::new("size", "out"), - + Input::new("data", "out"), + Input::new("addr", "out"), + Input::new("ctrl", "out"), + Input::new("sext", "out"), + Input::new("size", "out"), // memory - memory: Memory::new(), + Memory::new(), // later history... tbd - }), - Rc::new(Constant { - id: "data".to_string(), - pos: (100.0, 100.0), - value: 3.into(), - }), - Rc::new(Constant { - id: "addr".to_string(), - pos: (120.0, 100.0), - value: 4.into(), - }), - Rc::new(Constant { - id: "ctrl".to_string(), - pos: (140.0, 100.0), - value: (MemCtrl::Write as SignalUnsigned).into(), - }), - Rc::new(Constant { - id: "sext".to_string(), - pos: (160.0, 100.0), - value: (false as SignalUnsigned).into(), - }), - Rc::new(Constant { - id: "size".to_string(), - pos: (180.0, 100.0), - value: 1.into(), // byte - }), + )), + Rc::new(Constant::new("data", (100.0, 100.0), 3)), + Rc::new(Constant::new("addr", (120.0, 100.0), 4)), + Rc::new(Constant::new( + "ctrl", + (140.0, 100.0), + MemCtrl::Write as SignalUnsigned, + )), + Rc::new(Constant::new( + "sext", + (160.0, 100.0), + false as SignalUnsigned, + )), + Rc::new(Constant::new( + "size", + (180.0, 100.0), + 1, // byte + )), // Wires - Rc::new(Wire { - id: "w1".to_string(), - pos: vec![(100.0, 110.0), (100.0, 150.0)], - input: Input::new("data", "out"), - }), - Rc::new(Wire { - id: "w2".to_string(), - pos: vec![(120.0, 110.0), (120.0, 150.0)], - input: Input::new("addr", "out"), - }), - Rc::new(Wire { - id: "w3".to_string(), - pos: vec![(140.0, 110.0), (140.0, 150.0)], - input: Input::new("sext", "out"), - }), - Rc::new(Wire { - id: "w4".to_string(), - pos: vec![(160.0, 110.0), (160.0, 150.0)], - input: Input::new("size", "out"), - }), - Rc::new(Wire { - id: "w5".to_string(), - pos: vec![(220.0, 110.0), (220.0, 150.0)], - input: Input::new("mem", "data"), - }), - Rc::new(Wire { - id: "w6".to_string(), - pos: vec![(240.0, 110.0), (240.0, 150.0)], - input: Input::new("mem", "err"), - }), + Rc::new(Wire::new( + "w1", + vec![(100.0, 110.0), (100.0, 150.0)], + Input::new("data", "out"), + )), + Rc::new(Wire::new( + "w2", + vec![(120.0, 110.0), (120.0, 150.0)], + Input::new("addr", "out"), + )), + Rc::new(Wire::new( + "w3", + vec![(140.0, 110.0), (140.0, 150.0)], + Input::new("sext", "out"), + )), + Rc::new(Wire::new( + "w4", + vec![(160.0, 110.0), (160.0, 150.0)], + Input::new("size", "out"), + )), + Rc::new(Wire::new( + "w5", + vec![(220.0, 110.0), (220.0, 150.0)], + Input::new("mem", "data"), + )), + Rc::new(Wire::new( + "w6", + vec![(240.0, 110.0), (240.0, 150.0)], + Input::new("mem", "err"), + )), // probes - Rc::new(Probe { - id: "out".to_string(), - pos: (220.0, 100.0), - input: Input::new("mem", "data"), - }), - Rc::new(Probe { - id: "err".to_string(), - pos: (240.0, 100.0), - input: Input::new("mem", "err"), - }), + Rc::new(Probe::new("out", (220.0, 100.0), Input::new("mem", "data"))), + Rc::new(Probe::new("err", (240.0, 100.0), Input::new("mem", "err"))), ], }; @@ -104,7 +84,7 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(&cs, &path); diff --git a/examples/mux.rs b/examples/mux.rs index adbcf345..7133a297 100644 --- a/examples/mux.rs +++ b/examples/mux.rs @@ -1,6 +1,6 @@ use std::{path::PathBuf, rc::Rc}; use syncrim::{ - common::{ComponentStore, Input}, + common::{ComponentStore, Input, SignalUnsigned}, components::*, fern::fern_setup, }; @@ -9,77 +9,57 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Mux { - id: "mux".to_string(), - pos: (200.0, 200.0), - select: Input::new("c0", "out"), - m_in: vec![ + Rc::new(Mux::new( + "mux", + (200.0, 200.0), + Input::new("c0", "out"), + vec![ Input::new("c1", "out"), Input::new("c2", "out"), Input::new("c3", "out"), Input::new("c4", "out"), ], - }), - Rc::new(Constant { - id: "c0".to_string(), - pos: (190.0, 100.0), - value: 3.into(), - }), - Rc::new(Wire { - id: "w0".to_string(), - pos: vec![(190.0, 110.0), (190.0, 150.0)], - input: Input::new("c0", "out"), - }), - Rc::new(Constant { - id: "c1".to_string(), - pos: (140.0, 170.0), - value: 0.into(), - }), - Rc::new(Constant { - id: "c2".to_string(), - pos: (140.0, 190.0), - value: 1.into(), - }), - Rc::new(Constant { - id: "c3".to_string(), - pos: (140.0, 210.0), - value: 2.into(), - }), - Rc::new(Constant { - id: "c4".to_string(), - pos: (140.0, 230.0), - value: 3.into(), - }), - Rc::new(Wire { - id: "w1".to_string(), - pos: vec![(150.0, 170.0), (180.0, 170.0)], - input: Input::new("c1", "out"), - }), - Rc::new(Wire { - id: "w2".to_string(), - pos: vec![(150.0, 190.0), (180.0, 190.0)], - input: Input::new("c2", "out"), - }), - Rc::new(Wire { - id: "w3".to_string(), - pos: vec![(150.0, 210.0), (180.0, 210.0)], - input: Input::new("c3", "out"), - }), - Rc::new(Wire { - id: "w4".to_string(), - pos: vec![(150.0, 230.0), (180.0, 230.0)], - input: Input::new("c4", "out"), - }), - Rc::new(Wire { - id: "w5".to_string(), - pos: vec![(220.0, 200.0), (250.0, 200.0)], - input: Input::new("mux", "out"), - }), - Rc::new(Probe { - id: "p_mux".to_string(), - pos: (260.0, 200.0), - input: Input::new("mux", "out"), - }), + )), + Rc::new(Constant::new("c0", (190.0, 100.0), 3)), + Rc::new(Wire::new( + "w0", + vec![(190.0, 110.0), (190.0, 150.0)], + Input::new("c0", "out"), + )), + Rc::new(Constant::new("c1", (140.0, 170.0), 0)), + Rc::new(Constant::new("c2", (140.0, 190.0), 1)), + Rc::new(Constant::new("c3", (140.0, 210.0), 2)), + Rc::new(Constant::new("c4", (140.0, 230.0), 3)), + Rc::new(Wire::new( + "w1", + vec![(150.0, 170.0), (180.0, 170.0)], + Input::new("c1", "out"), + )), + Rc::new(Wire::new( + "w2", + vec![(150.0, 190.0), (180.0, 190.0)], + Input::new("c2", "out"), + )), + Rc::new(Wire::new( + "w3", + vec![(150.0, 210.0), (180.0, 210.0)], + Input::new("c3", "out"), + )), + Rc::new(Wire::new( + "w4", + vec![(150.0, 230.0), (180.0, 230.0)], + Input::new("c4", "out"), + )), + Rc::new(Wire::new( + "w5", + vec![(220.0, 200.0), (250.0, 200.0)], + Input::new("mux", "out"), + )), + Rc::new(Probe::new( + "p_mux", + (260.0, 200.0), + Input::new("mux", "out"), + )), ], }; @@ -87,7 +67,7 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(&cs, &path); diff --git a/examples/probe_edit.rs b/examples/probe_edit.rs index 4dc9e0e2..50fed6ee 100644 --- a/examples/probe_edit.rs +++ b/examples/probe_edit.rs @@ -10,11 +10,11 @@ fn main() { let cs = ComponentStore { store: vec![ Rc::new(ProbeEdit::new("probe_edit", (100.0, 100.0))), - Rc::new(Probe { - id: "probe".to_string(), - pos: (250.0, 100.0), - input: Input::new("probe_edit", "out"), - }), + Rc::new(Probe::new( + "probe", + (250.0, 100.0), + Input::new("probe_edit", "out"), + )), ], }; @@ -22,7 +22,7 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(&cs, &path); diff --git a/examples/reg.rs b/examples/reg.rs index 40eae986..b48de2d2 100644 --- a/examples/reg.rs +++ b/examples/reg.rs @@ -10,26 +10,22 @@ fn main() { let cs = ComponentStore { store: vec![ Constant::rc_new("c", (150.0, 100.0), 3), - Rc::new(Register { - id: "reg".to_string(), - pos: (200.0, 100.0), - r_in: Input::new("c", "out"), - }), - Rc::new(Wire { - id: "w1".to_string(), - pos: vec![(160.0, 100.0), (190.0, 100.0)], - input: Input::new("c", "out"), - }), - Rc::new(Wire { - id: "w2".to_string(), - pos: vec![(210.0, 100.0), (240.0, 100.0)], - input: Input::new("reg", "out"), - }), - Rc::new(Probe { - id: "p_reg".to_string(), - pos: (250.0, 100.0), - input: Input::new("reg", "out"), - }), + Rc::new(Register::new("reg", (200.0, 100.0), Input::new("c", "out"))), + Rc::new(Wire::new( + "w1", + vec![(160.0, 100.0), (190.0, 100.0)], + Input::new("c", "out"), + )), + Rc::new(Wire::new( + "w2", + vec![(210.0, 100.0), (240.0, 100.0)], + Input::new("reg", "out"), + )), + Rc::new(Probe::new( + "p_reg", + (250.0, 100.0), + Input::new("reg", "out"), + )), ], }; @@ -37,7 +33,7 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(&cs, &path); diff --git a/examples/sext.rs b/examples/sext.rs index 3dd39156..b3f25b58 100644 --- a/examples/sext.rs +++ b/examples/sext.rs @@ -10,28 +10,24 @@ fn main() { let cs = ComponentStore { store: vec![ Constant::rc_new("c0", (100.0, 110.0), 32768), - Rc::new(Wire { - id: "w0".to_string(), - pos: vec![(110.0, 110.0), (140.0, 110.0)], - input: Input::new("c0", "out"), - }), - Rc::new(Sext { - id: "sxt0".to_string(), - pos: (180.0, 100.0), - sext_in: Input::new("c0", "out"), - in_size: 16, - out_size: 24, - }), - Rc::new(Wire { - id: "w1".to_string(), - pos: vec![(220.0, 100.0), (250.0, 100.0)], - input: Input::new("sxt0", "out"), - }), - Rc::new(Probe { - id: "p1".to_string(), - pos: (260.0, 100.0), - input: Input::new("sxt0", "out"), - }), + Rc::new(Wire::new( + "w0", + vec![(110.0, 110.0), (140.0, 110.0)], + Input::new("c0", "out"), + )), + Rc::new(Sext::new( + "sxt0", + (180.0, 100.0), + Input::new("c0", "out"), + 16, + 24, + )), + Rc::new(Wire::new( + "w1", + vec![(220.0, 100.0), (250.0, 100.0)], + Input::new("sxt0", "out"), + )), + Rc::new(Probe::new("p1", (260.0, 100.0), Input::new("sxt0", "out"))), ], }; @@ -39,7 +35,7 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(&cs, &path); diff --git a/src/common.rs b/src/common.rs index 0fb2418a..f032f109 100644 --- a/src/common.rs +++ b/src/common.rs @@ -190,7 +190,7 @@ pub trait EguiComponent: Component { } #[cfg(feature = "gui-egui")] -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub struct EguiExtra { pub properties_window: bool, pub id_tmp: String, diff --git a/src/components/add.rs b/src/components/add.rs index 3304214c..d52dfe3c 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -1,6 +1,6 @@ use crate::common::{ - Component, EguiExtra, Id, Input, InputId, OutputType, Ports, Signal, SignalSigned, - SignalUnsigned, Simulator, + Component, Id, Input, InputId, OutputType, Ports, Signal, SignalSigned, SignalUnsigned, + Simulator, }; use log::*; use serde::{Deserialize, Serialize}; @@ -14,7 +14,7 @@ pub struct Add { #[cfg(feature = "gui-egui")] #[serde(skip)] - pub egui_x: EguiExtra, + pub egui_x: crate::common::EguiExtra, } impl Add { @@ -30,7 +30,8 @@ impl Add { id: String::from("b_in"), input: b_in, }, - egui_x: EguiExtra::default(), + #[cfg(feature = "gui-egui")] + egui_x: crate::common::EguiExtra::default(), } } } @@ -108,16 +109,16 @@ mod test { store: vec![ Rc::new(ProbeOut::new("po1")), Rc::new(ProbeOut::new("po2")), - Rc::new(Add { - id: "add".to_string(), - pos: (0.0, 0.0), - a_in: Input::new("po1", "out"), - b_in: Input::new("po2", "out"), - }), + Rc::new(Add::new( + "add", + (0.0, 0.0), + Input::new("po1", "out"), + Input::new("po2", "out"), + )), ], }; let mut clock = 0; - let mut simulator = Simulator::new(&cs, &mut clock); + let mut simulator = Simulator::new(cs, &mut clock); assert_eq!(clock, 1); diff --git a/src/components/mem.rs b/src/components/mem.rs index dc5a5769..5ab17276 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -28,6 +28,9 @@ pub struct Mem { // memory pub memory: Memory, // later history... tbd + #[cfg(feature = "gui-egui")] + #[serde(skip)] + pub egui_x: crate::common::EguiExtra, } #[derive(Serialize, Deserialize, Debug)] @@ -41,6 +44,53 @@ impl Default for Memory { } } +impl Mem { + pub fn new( + id: &str, + pos: (f32, f32), + width: f32, + height: f32, + big_endian: bool, + data: Input, + addr: Input, + ctrl: Input, + sign: Input, + size: Input, + memory: Memory, + ) -> Self { + Mem { + id: id.to_string(), + pos, + width: 0f32, + height: 0f32, + big_endian, + data: InputId { + id: String::from("data"), + input: data, + }, + addr: InputId { + id: String::from("addr"), + input: addr, + }, + ctrl: InputId { + id: String::from("ctrl"), + input: ctrl, + }, + sign: InputId { + id: String::from("sign"), + input: sign, + }, + size: InputId { + id: String::from("size"), + input: size, + }, + memory, + #[cfg(feature = "gui-egui")] + egui_x: crate::common::EguiExtra::default(), + } + } +} + impl Memory { pub fn new() -> Self { Memory { @@ -263,32 +313,29 @@ mod test { Rc::new(ProbeOut::new("ctrl")), Rc::new(ProbeOut::new("size")), Rc::new(ProbeOut::new("sign")), - Rc::new(Mem { - id: "mem".into(), - pos: (0.0, 0.0), - width: 0.0, - height: 0.0, - + Rc::new(Mem::new( + "mem", + (0.0, 0.0), + 0.0, + 0.0, // configuration - big_endian: true, // i.e., big endian - + true, // i.e., big endian // ports - data: Input::new("data", "out"), - addr: Input::new("addr", "out"), - ctrl: Input::new("ctrl", "out"), - size: Input::new("size", "out"), - sign: Input::new("sign", "out"), - + Input::new("data", "out"), + Input::new("addr", "out"), + Input::new("ctrl", "out"), + Input::new("size", "out"), + Input::new("sign", "out"), // memory - memory: Memory { + Memory { bytes: RefCell::new(HashMap::new()), }, - }), + )), ], }; let mut clock = 0; - let mut simulator = Simulator::new(&cs, &mut clock); + let mut simulator = Simulator::new(cs, &mut clock); assert_eq!(clock, 1); @@ -444,33 +491,30 @@ mod test { Rc::new(ProbeOut::new("ctrl")), Rc::new(ProbeOut::new("size")), Rc::new(ProbeOut::new("sign")), - Rc::new(Mem { - id: "mem".into(), - pos: (0.0, 0.0), - width: 0.0, - height: 0.0, - + Rc::new(Mem::new( + "mem".into(), + (0.0, 0.0), + 0.0, + 0.0, // configuration - big_endian: false, // i.e., little endian - + false, // i.e., little endian // ports - data: Input::new("data", "out"), - addr: Input::new("addr", "out"), - ctrl: Input::new("ctrl", "out"), - size: Input::new("size", "out"), - sign: Input::new("sign", "out"), - + Input::new("data", "out"), + Input::new("addr", "out"), + Input::new("ctrl", "out"), + Input::new("size", "out"), + Input::new("sign", "out"), // memory - memory: Memory { + Memory { bytes: RefCell::new(HashMap::new()), }, // later history... tbd - }), + )), ], }; let mut clock = 0; - let mut simulator = Simulator::new(&cs, &mut clock); + let mut simulator = Simulator::new(cs, &mut clock); assert_eq!(clock, 1); diff --git a/src/components/mux.rs b/src/components/mux.rs index b0b2cd2d..150be594 100644 --- a/src/components/mux.rs +++ b/src/components/mux.rs @@ -9,10 +9,14 @@ pub struct Mux { pub pos: (f32, f32), pub select: InputId, pub m_in: Vec, + + #[cfg(feature = "gui-egui")] + #[serde(skip)] + pub egui_x: crate::common::EguiExtra, } impl Mux { - pub fn new(id: String, pos: (f32, f32), select: Input, m_in: Vec) -> Self { + pub fn new(id: &str, pos: (f32, f32), select: Input, m_in: Vec) -> Self { let mut v = vec![]; for (i, input) in m_in.iter().enumerate() { v.push(InputId { @@ -21,13 +25,15 @@ impl Mux { }); } Mux { - id: id.clone(), + id: id.to_string(), pos, select: InputId { id: String::from("select"), input: select, }, m_in: v, + #[cfg(feature = "gui-egui")] + egui_x: crate::common::EguiExtra::default(), } } } diff --git a/src/components/probe_edit.rs b/src/components/probe_edit.rs index b71705e2..97b373d5 100644 --- a/src/components/probe_edit.rs +++ b/src/components/probe_edit.rs @@ -8,6 +8,10 @@ pub struct ProbeEdit { pub id: Id, pub pos: (f32, f32), pub history: Arc>>, // will contain the next editable value + + #[cfg(feature = "gui-egui")] + #[serde(skip)] + pub egui_x: crate::common::EguiExtra, } #[derive(Serialize, Deserialize, Clone, Debug)] @@ -71,6 +75,9 @@ impl ProbeEdit { text: "0".to_string(), signal: Signal::Data(0), }])), + + #[cfg(feature = "gui-egui")] + egui_x: crate::common::EguiExtra::default(), } } } diff --git a/src/components/register.rs b/src/components/register.rs index 2460563a..be4390f4 100644 --- a/src/components/register.rs +++ b/src/components/register.rs @@ -6,6 +6,24 @@ pub struct Register { pub id: Id, pub pos: (f32, f32), pub r_in: InputId, + + #[cfg(feature = "gui-egui")] + #[serde(skip)] + pub egui_x: crate::common::EguiExtra, +} +impl Register { + pub fn new(id: &str, pos: (f32, f32), r_in: Input) -> Self { + Register { + id: id.to_string(), + pos, + r_in: InputId { + id: String::from("r_in"), + input: r_in, + }, + #[cfg(feature = "gui-egui")] + egui_x: crate::common::EguiExtra::default(), + } + } } #[typetag::serde] diff --git a/src/components/sext.rs b/src/components/sext.rs index 8395bab6..86010149 100644 --- a/src/components/sext.rs +++ b/src/components/sext.rs @@ -12,6 +12,26 @@ pub struct Sext { pub sext_in: InputId, pub in_size: u32, pub out_size: u32, + + #[cfg(feature = "gui-egui")] + #[serde(skip)] + pub egui_x: crate::common::EguiExtra, +} +impl Sext { + pub fn new(id: &str, pos: (f32, f32), sext_in: Input, in_size: u32, out_size: u32) -> Self { + Sext { + id: id.to_string(), + pos, + sext_in: InputId { + id: String::from("sext_in"), + input: sext_in, + }, + in_size, + out_size, + #[cfg(feature = "gui-egui")] + egui_x: crate::common::EguiExtra::default(), + } + } } #[typetag::serde] @@ -69,24 +89,24 @@ mod test { let cs = ComponentStore { store: vec![ Rc::new(ProbeOut::new("po")), - Rc::new(Sext { - id: "sext32".to_string(), - pos: (0.0, 0.0), - sext_in: Input::new("po", "out"), - in_size: 4, - out_size: 32, - }), - Rc::new(Sext { - id: "sext16".to_string(), - pos: (0.0, 0.0), - sext_in: Input::new("po", "out"), - in_size: 4, - out_size: 16, - }), + Rc::new(Sext::new( + "sext32", + (0.0, 0.0), + Input::new("po", "out"), + 4, + 32, + )), + Rc::new(Sext::new( + "sext16", + (0.0, 0.0), + Input::new("po", "out"), + 4, + 16, + )), ], }; let mut clock = 0; - let mut simulator = Simulator::new(&cs, &mut clock); + let mut simulator = Simulator::new(cs, &mut clock); assert_eq!(clock, 1); diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index f709494b..0cc21c5a 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -3,6 +3,7 @@ mod constant; mod mem; mod mux; mod probe; +mod probe_edit; mod probe_out; mod register; mod sext; diff --git a/src/gui_egui/components/probe_edit.rs b/src/gui_egui/components/probe_edit.rs new file mode 100644 index 00000000..ad77db1d --- /dev/null +++ b/src/gui_egui/components/probe_edit.rs @@ -0,0 +1,19 @@ +use crate::common::{EditorMode, EguiComponent, Simulator}; +use crate::components::ProbeEdit; +use egui::Rect; + +#[typetag::serde] +impl EguiComponent for ProbeEdit { + fn render( + &self, + _ui: &mut egui::Ui, + _simulator: Option<&mut Simulator>, + _offset: egui::Vec2, + _scale: f32, + _clip_rect: Rect, + _editor_mode: EditorMode, + ) -> Option> { + todo!(); + None + } +} diff --git a/src/main.rs b/src/main.rs index 40b6d47d..35e83efd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,10 +16,10 @@ fn main() { let args = Args::parse(); let _path = PathBuf::from(args.model); - let _cs = ComponentStore::load_file(&_path); + let cs = ComponentStore::load_file(&_path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&_cs, &_path).ok(); + syncrim::gui_egui::gui(cs, &_path).ok(); #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(&_cs, &_path); diff --git a/src/simulator.rs b/src/simulator.rs index 6c42b1ac..33e53066 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -241,11 +241,11 @@ mod test { #[test] fn test_define() { let cs = ComponentStore { - store: vec![Rc::new(RefCell::new(ProbeOut::new("po1")))], + store: vec![Rc::new(ProbeOut::new("po1"))], }; let mut clock = 0; - let _simulator = Simulator::new(&cs, &mut clock); + let _simulator = Simulator::new(cs, &mut clock); assert_eq!(clock, 1); } @@ -254,14 +254,11 @@ mod test { #[should_panic(expected = "Component identifier \"po1\" is defined twice")] fn test_redefined() { let cs = ComponentStore { - store: vec![ - Rc::new(RefCell::new(ProbeOut::new("po1"))), - Rc::new(RefCell::new(ProbeOut::new("po1"))), - ], + store: vec![Rc::new(ProbeOut::new("po1")), Rc::new(ProbeOut::new("po1"))], }; let mut clock = 0; - let _simulator = Simulator::new(&cs, &mut clock); + let _simulator = Simulator::new(cs, &mut clock); assert_eq!(clock, 1); } @@ -269,11 +266,11 @@ mod test { #[test] fn test_get_input_val() { let cs = ComponentStore { - store: vec![Rc::new(RefCell::new(ProbeOut::new("po1")))], + store: vec![Rc::new(ProbeOut::new("po1"))], }; let mut clock = 0; - let simulator = Simulator::new(&cs, &mut clock); + let simulator = Simulator::new(cs, &mut clock); assert_eq!(clock, 1); let _ = simulator.get_input_val(&Input::new("po1", "out")); @@ -283,11 +280,11 @@ mod test { #[should_panic(expected = "Component \"po1\", field \"missing\" not found.")] fn test_get_input_out_of_range() { let cs = ComponentStore { - store: vec![Rc::new(RefCell::new(ProbeOut::new("po1")))], + store: vec![Rc::new(ProbeOut::new("po1"))], }; let mut clock = 0; - let simulator = Simulator::new(&cs, &mut clock); + let simulator = Simulator::new(cs, &mut clock); assert_eq!(clock, 1); let _ = simulator.get_input_val(&Input::new("po1", "missing")); From 9a4854d5efbbf5f90e33a7d4a0d858f238b7fac0 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Mon, 24 Jul 2023 19:35:47 +0200 Subject: [PATCH 15/58] Fixed issues with vizia (doesn't compile still though for some reason) --- src/components/constant.rs | 5 +++-- src/components/probe.rs | 3 ++- src/components/wire.rs | 5 +++-- src/gui_vizia/components/mux.rs | 2 +- src/gui_vizia/components/probe.rs | 2 +- src/gui_vizia/gui.rs | 6 +++--- src/gui_vizia/popup.rs | 3 ++- src/gui_vizia/tooltip.rs | 3 ++- 8 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/components/constant.rs b/src/components/constant.rs index 2273c6f9..372ffe22 100644 --- a/src/components/constant.rs +++ b/src/components/constant.rs @@ -1,4 +1,4 @@ -use crate::common::{Component, EguiExtra, Id, OutputType, Ports, Signal, Simulator}; +use crate::common::{Component, Id, OutputType, Ports, Signal, Simulator}; use log::*; use serde::{Deserialize, Serialize}; use std::rc::Rc; @@ -41,7 +41,8 @@ impl Constant { id: id.to_string(), pos, value: value.into(), - egui_x: EguiExtra::default(), + #[cfg(feature = "gui-egui")] + egui_x: crate::common::EguiExtra::default(), } } diff --git a/src/components/probe.rs b/src/components/probe.rs index 3b86fa74..68748537 100644 --- a/src/components/probe.rs +++ b/src/components/probe.rs @@ -1,4 +1,4 @@ -use crate::common::{Component, EguiExtra, Id, Input, InputId, OutputType, Ports}; +use crate::common::{Component, Id, Input, InputId, OutputType, Ports}; use log::*; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] @@ -20,6 +20,7 @@ impl Probe { id: String::from("in"), input, }, + #[cfg(feature = "gui-egui")] egui_x: EguiExtra::default(), } } diff --git a/src/components/wire.rs b/src/components/wire.rs index df13f294..28e45701 100644 --- a/src/components/wire.rs +++ b/src/components/wire.rs @@ -1,4 +1,4 @@ -use crate::common::{Component, EguiExtra, Id, Input, InputId, OutputType, Ports}; +use crate::common::{Component, Id, Input, InputId, OutputType, Ports}; use log::*; use serde::{Deserialize, Serialize}; @@ -22,7 +22,8 @@ impl Wire { id: String::from("in"), input, }, - egui_x: EguiExtra::default(), + #[cfg(feature = "gui-egui")] + egui_x: crate::common::EguiExtra::default(), } } } diff --git a/src/gui_vizia/components/mux.rs b/src/gui_vizia/components/mux.rs index dcc48601..bf48df89 100644 --- a/src/gui_vizia/components/mux.rs +++ b/src/gui_vizia/components/mux.rs @@ -19,7 +19,7 @@ impl ViziaComponent for Mux { View::build( MuxView { - select: self.select.clone(), + select: self.select.input.clone(), select_max: self.m_in.len() as u8, }, cx, diff --git a/src/gui_vizia/components/probe.rs b/src/gui_vizia/components/probe.rs index d48efc89..63335895 100644 --- a/src/gui_vizia/components/probe.rs +++ b/src/gui_vizia/components/probe.rs @@ -17,7 +17,7 @@ impl ViziaComponent for Probe { fn view(&self, cx: &mut Context) { trace!("---- Create Probe View"); View::build(ProbeView {}, cx, |cx| { - let input = self.input.clone(); + let input = self.input_id.input.clone(); Binding::new(cx, crate::gui_vizia::GuiData::clock, move |cx, _| { Label::new(cx, { diff --git a/src/gui_vizia/gui.rs b/src/gui_vizia/gui.rs index 6c39671e..72847734 100644 --- a/src/gui_vizia/gui.rs +++ b/src/gui_vizia/gui.rs @@ -102,8 +102,8 @@ impl GuiData { fn open(&mut self) { // Re-Open model trace!("open path {:?}", self.path); - let cs = Box::new(ComponentStore::load_file(&self.path)); - let simulator = Simulator::new(&cs, &mut self.clock); + let cs = ComponentStore::load_file(&self.path); + let simulator = Simulator::new(cs, &mut self.clock); self.simulator = simulator; @@ -111,7 +111,7 @@ impl GuiData { } } -pub fn gui(cs: &ComponentStore, path: &PathBuf) { +pub fn gui(cs: ComponentStore, path: &PathBuf) { let mut clock = 0; let simulator = Simulator::new(cs, &mut clock); let path = path.to_owned(); diff --git a/src/gui_vizia/popup.rs b/src/gui_vizia/popup.rs index 97952a64..54dff43a 100644 --- a/src/gui_vizia/popup.rs +++ b/src/gui_vizia/popup.rs @@ -17,7 +17,8 @@ impl NewPopup { let (id, ports) = id_ports.clone(); Label::new(cx, &id); - for input in ports.inputs { + for input_id in ports.inputs { + let input = input_id.input; HStack::new(cx, |cx| { Label::new(cx, &input.id); Binding::new(cx, GuiData::clock, move |cx, _| { diff --git a/src/gui_vizia/tooltip.rs b/src/gui_vizia/tooltip.rs index 235dec44..13ea9290 100644 --- a/src/gui_vizia/tooltip.rs +++ b/src/gui_vizia/tooltip.rs @@ -6,7 +6,8 @@ pub fn new_component_tooltip(cx: &mut Context, component: &dyn Component) { let (id, ports) = component.get_id_ports(); Label::new(cx, &id); - for input in ports.inputs { + for input_id in ports.inputs { + let input = input_id.input; HStack::new(cx, |cx| { Label::new(cx, &input.id); Binding::new(cx, GuiData::clock, move |cx, _| { From 0cd13765814182951581a2aa1bbd6f759f6b04ab Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Mon, 24 Jul 2023 19:38:52 +0200 Subject: [PATCH 16/58] Forgot to readd the paths for EguiExtra --- src/components/constant.rs | 2 +- src/components/probe.rs | 4 ++-- src/components/wire.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/constant.rs b/src/components/constant.rs index 372ffe22..4854b7ca 100644 --- a/src/components/constant.rs +++ b/src/components/constant.rs @@ -9,7 +9,7 @@ pub struct Constant { pub value: Signal, #[cfg(feature = "gui-egui")] #[serde(skip)] - pub egui_x: EguiExtra, + pub egui_x: crate::common::EguiExtra, } #[typetag::serde] diff --git a/src/components/probe.rs b/src/components/probe.rs index 68748537..72fc1401 100644 --- a/src/components/probe.rs +++ b/src/components/probe.rs @@ -8,7 +8,7 @@ pub struct Probe { pub input_id: InputId, #[cfg(feature = "gui-egui")] #[serde(skip)] - pub egui_x: EguiExtra, + pub egui_x: crate::common::EguiExtra, } impl Probe { @@ -21,7 +21,7 @@ impl Probe { input, }, #[cfg(feature = "gui-egui")] - egui_x: EguiExtra::default(), + egui_x: crate::common::EguiExtra::default(), } } } diff --git a/src/components/wire.rs b/src/components/wire.rs index 28e45701..29f26f81 100644 --- a/src/components/wire.rs +++ b/src/components/wire.rs @@ -10,7 +10,7 @@ pub struct Wire { #[cfg(feature = "gui-egui")] #[serde(skip)] - pub egui_x: EguiExtra, + pub egui_x: crate::common::EguiExtra, } impl Wire { From e3bb2a4b63990d2b20d450ba072d65d2574aae71 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 08:20:27 +0200 Subject: [PATCH 17/58] Renamed InputId to InputPort --- src/common.rs | 18 ++++++++-------- src/components/add.rs | 14 ++++++------- src/components/mem.rs | 32 ++++++++++++++--------------- src/components/mux.rs | 14 ++++++------- src/components/probe.rs | 12 +++++------ src/components/register.rs | 8 ++++---- src/components/sext.rs | 8 ++++---- src/components/wire.rs | 10 ++++----- src/gui_egui/component_ui.rs | 18 ++++++++-------- src/gui_egui/components/add.rs | 14 +++++++++---- src/gui_egui/components/constant.rs | 4 ++-- src/gui_egui/components/probe.rs | 15 ++++++++------ src/gui_egui/components/wire.rs | 17 ++++++++------- src/gui_egui/editor.rs | 2 +- src/gui_egui/keymap.rs | 1 - src/gui_vizia/components/probe.rs | 2 +- src/gui_vizia/popup.rs | 4 ++-- src/gui_vizia/tooltip.rs | 4 ++-- 18 files changed, 103 insertions(+), 94 deletions(-) diff --git a/src/common.rs b/src/common.rs index f032f109..88f79fc9 100644 --- a/src/common.rs +++ b/src/common.rs @@ -53,8 +53,6 @@ type Components = Vec>; #[cfg(feature = "gui-vizia")] type Components = Vec>; -// todo: Probably make a separate ComponentsEditor type -// so we don't have to use refcell everywhere #[cfg(feature = "gui-egui")] pub type Components = Vec>; @@ -73,7 +71,7 @@ pub struct Simulator { pub graph: Graph, } -#[derive(Deserialize, Serialize)] +#[derive(Serialize, Deserialize)] pub struct ComponentStore { pub store: Components, } @@ -208,13 +206,13 @@ impl Default for EguiExtra { #[derive(Debug, Clone)] pub struct Ports { - pub inputs: Vec, + pub inputs: Vec, pub out_type: OutputType, pub outputs: Vec, } impl Ports { - pub fn new(inputs: Vec<&InputId>, out_type: OutputType, outputs: Vec<&str>) -> Self { + pub fn new(inputs: Vec<&InputPort>, out_type: OutputType, outputs: Vec<&str>) -> Self { Ports { inputs: inputs.into_iter().cloned().collect(), out_type, @@ -239,15 +237,15 @@ impl Input { } #[derive(Serialize, Deserialize, Clone, Debug)] -pub struct InputId { - pub id: Id, +pub struct InputPort { + pub port_id: Id, pub input: Input, } -impl InputId { +impl InputPort { pub fn new(id_self: &str, id: &str, field: &str) -> Self { - InputId { - id: id_self.into(), + InputPort { + port_id: id_self.into(), input: Input::new(id, field), } } diff --git a/src/components/add.rs b/src/components/add.rs index d52dfe3c..e4d05b79 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -1,5 +1,5 @@ use crate::common::{ - Component, Id, Input, InputId, OutputType, Ports, Signal, SignalSigned, SignalUnsigned, + Component, Id, Input, InputPort, OutputType, Ports, Signal, SignalSigned, SignalUnsigned, Simulator, }; use log::*; @@ -9,8 +9,8 @@ use serde::{Deserialize, Serialize}; pub struct Add { pub id: Id, pub pos: (f32, f32), - pub a_in: InputId, - pub b_in: InputId, + pub a_in: InputPort, + pub b_in: InputPort, #[cfg(feature = "gui-egui")] #[serde(skip)] @@ -22,12 +22,12 @@ impl Add { Add { id: id.to_string(), pos, - a_in: InputId { - id: String::from("a_in"), + a_in: InputPort { + port_id: String::from("a_in"), input: a_in, }, - b_in: InputId { - id: String::from("b_in"), + b_in: InputPort { + port_id: String::from("b_in"), input: b_in, }, #[cfg(feature = "gui-egui")] diff --git a/src/components/mem.rs b/src/components/mem.rs index 5ab17276..beed217c 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -1,5 +1,5 @@ use crate::common::{ - Component, Id, Input, InputId, OutputType, Ports, Signal, SignalSigned, SignalUnsigned, + Component, Id, Input, InputPort, OutputType, Ports, Signal, SignalSigned, SignalUnsigned, Simulator, }; use log::*; @@ -19,11 +19,11 @@ pub struct Mem { pub big_endian: bool, // ports - pub data: InputId, - pub addr: InputId, - pub ctrl: InputId, - pub sign: InputId, - pub size: InputId, + pub data: InputPort, + pub addr: InputPort, + pub ctrl: InputPort, + pub sign: InputPort, + pub size: InputPort, // memory pub memory: Memory, @@ -64,24 +64,24 @@ impl Mem { width: 0f32, height: 0f32, big_endian, - data: InputId { - id: String::from("data"), + data: InputPort { + port_id: String::from("data"), input: data, }, - addr: InputId { - id: String::from("addr"), + addr: InputPort { + port_id: String::from("addr"), input: addr, }, - ctrl: InputId { - id: String::from("ctrl"), + ctrl: InputPort { + port_id: String::from("ctrl"), input: ctrl, }, - sign: InputId { - id: String::from("sign"), + sign: InputPort { + port_id: String::from("sign"), input: sign, }, - size: InputId { - id: String::from("size"), + size: InputPort { + port_id: String::from("size"), input: size, }, memory, diff --git a/src/components/mux.rs b/src/components/mux.rs index 150be594..06fc6341 100644 --- a/src/components/mux.rs +++ b/src/components/mux.rs @@ -1,5 +1,5 @@ use crate::common::{ - Component, Id, Input, InputId, OutputType, Ports, Signal, SignalUnsigned, Simulator, + Component, Id, Input, InputPort, OutputType, Ports, Signal, SignalUnsigned, Simulator, }; use log::*; use serde::{Deserialize, Serialize}; @@ -7,8 +7,8 @@ use serde::{Deserialize, Serialize}; pub struct Mux { pub id: Id, pub pos: (f32, f32), - pub select: InputId, - pub m_in: Vec, + pub select: InputPort, + pub m_in: Vec, #[cfg(feature = "gui-egui")] #[serde(skip)] @@ -19,16 +19,16 @@ impl Mux { pub fn new(id: &str, pos: (f32, f32), select: Input, m_in: Vec) -> Self { let mut v = vec![]; for (i, input) in m_in.iter().enumerate() { - v.push(InputId { - id: format!("in{}", i), + v.push(InputPort { + port_id: format!("in{}", i), input: input.clone(), }); } Mux { id: id.to_string(), pos, - select: InputId { - id: String::from("select"), + select: InputPort { + port_id: String::from("select"), input: select, }, m_in: v, diff --git a/src/components/probe.rs b/src/components/probe.rs index 72fc1401..2316d890 100644 --- a/src/components/probe.rs +++ b/src/components/probe.rs @@ -1,11 +1,11 @@ -use crate::common::{Component, Id, Input, InputId, OutputType, Ports}; +use crate::common::{Component, Id, Input, InputPort, OutputType, Ports}; use log::*; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct Probe { pub id: Id, pub pos: (f32, f32), - pub input_id: InputId, + pub input_port: InputPort, #[cfg(feature = "gui-egui")] #[serde(skip)] pub egui_x: crate::common::EguiExtra, @@ -16,8 +16,8 @@ impl Probe { Probe { id: id.to_string(), pos, - input_id: InputId { - id: String::from("in"), + input_port: InputPort { + port_id: String::from("in"), input, }, #[cfg(feature = "gui-egui")] @@ -37,7 +37,7 @@ impl Component for Probe { self.id.clone(), Ports::new( // Probes take one input - vec![&self.input_id], + vec![&self.input_port], OutputType::Combinatorial, // No output value vec![], @@ -47,7 +47,7 @@ impl Component for Probe { fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { match target_port_id.as_str() { - "in" => self.input_id.input = new_input, + "in" => self.input_port.input = new_input, _ => (), } } diff --git a/src/components/register.rs b/src/components/register.rs index be4390f4..86867c58 100644 --- a/src/components/register.rs +++ b/src/components/register.rs @@ -1,11 +1,11 @@ -use crate::common::{Component, Id, Input, InputId, OutputType, Ports, Simulator}; +use crate::common::{Component, Id, Input, InputPort, OutputType, Ports, Simulator}; use log::*; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct Register { pub id: Id, pub pos: (f32, f32), - pub r_in: InputId, + pub r_in: InputPort, #[cfg(feature = "gui-egui")] #[serde(skip)] @@ -16,8 +16,8 @@ impl Register { Register { id: id.to_string(), pos, - r_in: InputId { - id: String::from("r_in"), + r_in: InputPort { + port_id: String::from("r_in"), input: r_in, }, #[cfg(feature = "gui-egui")] diff --git a/src/components/sext.rs b/src/components/sext.rs index 86010149..b4e458bb 100644 --- a/src/components/sext.rs +++ b/src/components/sext.rs @@ -1,6 +1,6 @@ // use std::fmt::Alignment; use crate::common::{ - Component, Id, Input, InputId, OutputType, Ports, Signal, SignalSigned, SignalUnsigned, + Component, Id, Input, InputPort, OutputType, Ports, Signal, SignalSigned, SignalUnsigned, Simulator, }; use log::*; @@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize}; pub struct Sext { pub id: Id, pub pos: (f32, f32), - pub sext_in: InputId, + pub sext_in: InputPort, pub in_size: u32, pub out_size: u32, @@ -22,8 +22,8 @@ impl Sext { Sext { id: id.to_string(), pos, - sext_in: InputId { - id: String::from("sext_in"), + sext_in: InputPort { + port_id: String::from("sext_in"), input: sext_in, }, in_size, diff --git a/src/components/wire.rs b/src/components/wire.rs index 29f26f81..17248fb6 100644 --- a/src/components/wire.rs +++ b/src/components/wire.rs @@ -1,4 +1,4 @@ -use crate::common::{Component, Id, Input, InputId, OutputType, Ports}; +use crate::common::{Component, Id, Input, InputPort, OutputType, Ports}; use log::*; use serde::{Deserialize, Serialize}; @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; pub struct Wire { pub id: Id, pub pos: Vec<(f32, f32)>, - pub input_id: InputId, + pub input_port: InputPort, #[cfg(feature = "gui-egui")] #[serde(skip)] @@ -18,8 +18,8 @@ impl Wire { Wire { id: id.to_string(), pos, - input_id: InputId { - id: String::from("in"), + input_port: InputPort { + port_id: String::from("in"), input, }, #[cfg(feature = "gui-egui")] @@ -39,7 +39,7 @@ impl Component for Wire { self.id.clone(), Ports::new( // Wires take one input - vec![&self.input_id], + vec![&self.input_port], OutputType::Combinatorial, // No output value vec![], diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index ce008b98..eb310963 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -1,5 +1,5 @@ use crate::common::{ - ComponentStore, Components, EditorMode, EditorRenderReturn, EguiComponent, InputId, Ports, + ComponentStore, Components, EditorMode, EditorRenderReturn, EguiComponent, InputPort, Ports, Simulator, }; use crate::gui_egui::helper::{ @@ -85,14 +85,14 @@ pub fn pos_slider(ui: &mut Ui, pos: &mut (f32, f32)) { } pub fn input_selector( ui: &mut Ui, - input_id: &mut InputId, + input_port: &mut InputPort, id_ports: &Vec<(crate::common::Id, Ports)>, ) { - let mut port_id = input_id.input.id.clone(); - let mut port_field = input_id.input.field.clone(); - let label_port_id = format!("{}.id", input_id.id.clone()); + let mut port_id = input_port.input.id.clone(); + let mut port_field = input_port.input.field.clone(); + let label_port_id = format!("{}.id", input_port.port_id.clone()); let text_port_id = format!("{}", port_id); - let label_port_field = format!("{}.field", input_id.id.clone()); + let label_port_field = format!("{}.field", input_port.port_id.clone()); let text_port_field = format!("{}", port_field); ui.horizontal(|ui| { ComboBox::from_label(label_port_id) @@ -118,11 +118,11 @@ pub fn input_selector( } }); }); - input_id.input.id = port_id; - input_id.input.field = port_field; + input_port.input.id = port_id; + input_port.input.field = port_field; } -pub fn input_id( +pub fn input_port( ui: &mut Ui, id_tmp: &mut String, id: &mut String, diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index ed601d4d..3916d064 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,5 +1,5 @@ use crate::gui_egui::component_ui::{ - input_id, input_selector, pos_slider, properties_window, rect_with_hover, + input_port, input_selector, pos_slider, properties_window, rect_with_hover, }; use crate::gui_egui::helper::{ editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, @@ -110,7 +110,7 @@ impl EguiComponent for Add { resp, &mut self.egui_x.properties_window, |ui| { - input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); + input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); input_selector(ui, &mut self.a_in, id_ports); input_selector(ui, &mut self.b_in, id_ports); @@ -136,8 +136,14 @@ impl EguiComponent for Add { fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { let own_pos = Vec2::new(self.pos.0, self.pos.1); vec![ - (self.a_in.id.clone(), Pos2::new(-20f32, -20f32) + own_pos), - (self.b_in.id.clone(), Pos2::new(-20f32, 20f32) + own_pos), + ( + self.a_in.port_id.clone(), + Pos2::new(-20f32, -20f32) + own_pos, + ), + ( + self.b_in.port_id.clone(), + Pos2::new(-20f32, 20f32) + own_pos, + ), (String::from("out"), Pos2::new(20f32, 0f32) + own_pos), (String::from("overflow"), Pos2::new(0f32, -40f32) + own_pos), ] diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 066c4443..8838dd60 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -3,7 +3,7 @@ use crate::common::{ Simulator, }; use crate::components::Constant; -use crate::gui_egui::component_ui::{input_id, pos_slider, properties_window, rect_with_hover}; +use crate::gui_egui::component_ui::{input_port, pos_slider, properties_window, rect_with_hover}; use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; use egui::{ Align2, Area, Color32, Frame, Margin, Order, PointerButton, Pos2, Rect, RichText, Rounding, @@ -91,7 +91,7 @@ impl EguiComponent for Constant { resp, &mut self.egui_x.properties_window, |ui| { - input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); + input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); // todo: Fix this /* diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 84a975f5..43d74fcd 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -4,7 +4,7 @@ use crate::common::{ }; use crate::components::Probe; use crate::gui_egui::component_ui::{ - input_id, input_selector, pos_slider, properties_window, rect_with_hover, + input_port, input_selector, pos_slider, properties_window, rect_with_hover, }; use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; use egui::{ @@ -27,9 +27,9 @@ impl EguiComponent for Probe { let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; - let input_id = self.input_id.clone(); + let input_port = self.input_port.clone(); let value = match simulator { - Some(s) => s.get_input_val(&input_id.input), + Some(s) => s.get_input_val(&input_port.input), None => Signal::Data(0), }; let area = Area::new(self.id.to_string()) @@ -100,9 +100,9 @@ impl EguiComponent for Probe { resp, &mut self.egui_x.properties_window, |ui| { - input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); + input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); - input_selector(ui, &mut self.input_id, id_ports); + input_selector(ui, &mut self.input_port, id_ports); }, ); @@ -124,7 +124,10 @@ impl EguiComponent for Probe { fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![(self.input_id.id.clone(), Pos2::new(-10f32, 0f32) + own_pos)] + vec![( + self.input_port.port_id.clone(), + Pos2::new(-10f32, 0f32) + own_pos, + )] } fn set_pos(&mut self, pos: (f32, f32)) { diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 994e36ef..9c1c974b 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -4,7 +4,7 @@ use crate::common::{ }; use crate::components::Wire; use crate::gui_egui::component_ui::{ - input_id, input_selector, pos_slider, properties_window, rect_with_hover, + input_port, input_selector, pos_slider, properties_window, rect_with_hover, }; use crate::gui_egui::helper::{ editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, @@ -65,7 +65,7 @@ impl EguiComponent for Wire { /* match &simulator { Some(s) => ui.label({ - let r: Result = self.input_id.try_into(); + let r: Result = self.input_port.try_into(); match r { Ok(data) => format!("{:#x}", data), _ => format!("{:?}", value), @@ -112,15 +112,15 @@ impl EguiComponent for Wire { resp, &mut self.egui_x.properties_window, |ui| { - input_id(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); + input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos[i]); pos_slider(ui, &mut self.pos[i + 1]); - input_selector(ui, &mut self.input_id, id_ports); + input_selector(ui, &mut self.input_port, id_ports); }, ); /* if self.egui_x.properties_window { - let mut input = self.input_id.input.id.clone(); + let mut input = self.input_port.input.id.clone(); let resp = Window::new(format!("Properties: {}", self.id)) .frame(Frame { inner_margin: Margin::same(10f32), @@ -180,7 +180,7 @@ impl EguiComponent for Wire { ui.selectable_value(&mut input, id.clone(), id); } }); - self.input_id.input.id = input; + self.input_port.input.id = input; }); if resp.unwrap().response.clicked_elsewhere() { self.egui_x.properties_window = false; @@ -214,7 +214,10 @@ impl EguiComponent for Wire { fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { let mut vec: Vec<(crate::common::Id, Pos2)> = vec![]; for (i, pos) in self.pos.iter().enumerate() { - vec.push((format!("{}", i), Pos2 { x: pos.0, y: pos.1 })); + vec.push(( + format!("{}-{}", self.input_port.port_id, i), + Pos2 { x: pos.0, y: pos.1 }, + )); } vec } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index e627ec06..ae33a73b 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -1,5 +1,5 @@ use crate::common::{ - ComponentStore, Components, EditorMode, EguiComponent, Id, Input, InputId, Simulator, + ComponentStore, Components, EditorMode, EguiComponent, Id, Input, InputPort, Simulator, }; use crate::components::*; use crate::gui_egui::{ diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index cb08ed47..706e7e14 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -248,7 +248,6 @@ pub fn file_editor_toggle_fn(gui: &mut Gui) { } _ => (), } - // todo: Make us swap back into simulator mode (create new simulator) } false => { let simulator = std::mem::replace(&mut gui.simulator, None); diff --git a/src/gui_vizia/components/probe.rs b/src/gui_vizia/components/probe.rs index 63335895..f6ca0496 100644 --- a/src/gui_vizia/components/probe.rs +++ b/src/gui_vizia/components/probe.rs @@ -17,7 +17,7 @@ impl ViziaComponent for Probe { fn view(&self, cx: &mut Context) { trace!("---- Create Probe View"); View::build(ProbeView {}, cx, |cx| { - let input = self.input_id.input.clone(); + let input = self.input_port.input.clone(); Binding::new(cx, crate::gui_vizia::GuiData::clock, move |cx, _| { Label::new(cx, { diff --git a/src/gui_vizia/popup.rs b/src/gui_vizia/popup.rs index 54dff43a..81a10d27 100644 --- a/src/gui_vizia/popup.rs +++ b/src/gui_vizia/popup.rs @@ -17,8 +17,8 @@ impl NewPopup { let (id, ports) = id_ports.clone(); Label::new(cx, &id); - for input_id in ports.inputs { - let input = input_id.input; + for input_port in ports.inputs { + let input = input_port.input; HStack::new(cx, |cx| { Label::new(cx, &input.id); Binding::new(cx, GuiData::clock, move |cx, _| { diff --git a/src/gui_vizia/tooltip.rs b/src/gui_vizia/tooltip.rs index 13ea9290..d1a1adc2 100644 --- a/src/gui_vizia/tooltip.rs +++ b/src/gui_vizia/tooltip.rs @@ -6,8 +6,8 @@ pub fn new_component_tooltip(cx: &mut Context, component: &dyn Component) { let (id, ports) = component.get_id_ports(); Label::new(cx, &id); - for input_id in ports.inputs { - let input = input_id.input; + for input_port in ports.inputs { + let input = input_port.input; HStack::new(cx, |cx| { Label::new(cx, &input.id); Binding::new(cx, GuiData::clock, move |cx, _| { From 1683a1b848c0b9bca08de39437e64ff03e2d4b41 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 09:21:34 +0200 Subject: [PATCH 18/58] Fixed warnings, renamed files/functions moved most editor struct enums to editor --- examples/mux.rs | 2 +- src/common.rs | 24 +---- src/components/mem.rs | 4 +- src/gui_egui/component_ui.rs | 15 +-- src/gui_egui/components/add.rs | 15 +-- src/gui_egui/components/constant.rs | 13 +-- src/gui_egui/components/mux.rs | 3 +- src/gui_egui/components/probe.rs | 13 +-- src/gui_egui/components/probe_edit.rs | 4 +- src/gui_egui/components/probe_out.rs | 9 +- src/gui_egui/components/register.rs | 3 +- src/gui_egui/components/sext.rs | 6 +- src/gui_egui/components/wire.rs | 92 +----------------- src/gui_egui/editor.rs | 80 ++++++++++------ .../{editor_wire.rs => editor_wire_mode.rs} | 95 +++++++++---------- src/gui_egui/gui.rs | 4 +- src/gui_egui/helper.rs | 7 +- src/gui_egui/keymap.rs | 20 ++-- src/gui_egui/library.rs | 32 ++++--- src/gui_egui/mod.rs | 4 +- src/simulator.rs | 2 +- 21 files changed, 172 insertions(+), 275 deletions(-) rename src/gui_egui/{editor_wire.rs => editor_wire_mode.rs} (76%) diff --git a/examples/mux.rs b/examples/mux.rs index 7133a297..6fb4b30f 100644 --- a/examples/mux.rs +++ b/examples/mux.rs @@ -1,6 +1,6 @@ use std::{path::PathBuf, rc::Rc}; use syncrim::{ - common::{ComponentStore, Input, SignalUnsigned}, + common::{ComponentStore, Input}, components::*, fern::fern_setup, }; diff --git a/src/common.rs b/src/common.rs index 88f79fc9..69dcd596 100644 --- a/src/common.rs +++ b/src/common.rs @@ -6,6 +6,9 @@ use std::{ rc::Rc, }; +#[cfg(feature = "gui-egui")] +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, SnapPriority}; + #[cfg(feature = "gui-vizia")] use vizia::prelude::*; @@ -117,27 +120,6 @@ pub trait ViziaComponent: Component { fn view(&self, _cx: &mut vizia::context::Context) {} } -// Specific structs for egui -#[cfg(feature = "gui-egui")] -pub enum SnapPriority { - Default, - Wire, -} - -#[cfg(feature = "gui-egui")] -#[derive(Debug, Clone, Copy)] -pub enum EditorMode { - Default, - Wire, - Input, -} - -#[cfg(feature = "gui-egui")] -pub struct EditorRenderReturn { - pub delete: bool, - pub resp: Option>, -} - // Specific functionality for EGui frontend #[cfg(feature = "gui-egui")] #[typetag::serde(tag = "type")] diff --git a/src/components/mem.rs b/src/components/mem.rs index beed217c..1945785b 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -61,8 +61,8 @@ impl Mem { Mem { id: id.to_string(), pos, - width: 0f32, - height: 0f32, + width, + height, big_endian, data: InputPort { port_id: String::from("data"), diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index eb310963..0ac71b5d 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -1,14 +1,7 @@ -use crate::common::{ - ComponentStore, Components, EditorMode, EditorRenderReturn, EguiComponent, InputPort, Ports, - Simulator, -}; -use crate::gui_egui::helper::{ - editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, -}; -use egui::{ - ComboBox, Frame, Id, InnerResponse, Margin, PointerButton, Pos2, Rect, Response, Rounding, Ui, - Window, -}; +use crate::common::{InputPort, Ports}; +use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; +use egui::{ComboBox, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, Ui, Window}; use epaint::Shadow; pub fn rect_with_hover

( diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 3916d064..947256eb 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,18 +1,13 @@ use crate::gui_egui::component_ui::{ input_port, input_selector, pos_slider, properties_window, rect_with_hover, }; -use crate::gui_egui::helper::{ - editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, -}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::helper::offset_helper; use crate::{ - common::{Components, EditorMode, EditorRenderReturn, EguiComponent, Ports, Simulator}, + common::{EguiComponent, Ports, Simulator}, components::Add, }; -use egui::{ - containers::{ComboBox, Window}, - Frame, Margin, PointerButton, Pos2, Rect, Rounding, Vec2, -}; -use epaint::Shadow; +use egui::{PointerButton, Pos2, Rect, Vec2}; #[typetag::serde] impl EguiComponent for Add { @@ -33,9 +28,7 @@ impl EguiComponent for Add { offset.y += self.pos.1 * scale; let s = scale; let o = offset; - //trace!("---- Create Add View"); // The shape - // 40x30 ui.painter().add(egui::Shape::closed_line( vec![ oh((-20f32, -40f32), s, o), diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 8838dd60..ef261f39 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,15 +1,8 @@ -use crate::common::{ - Components, EditorMode, EditorRenderReturn, EguiComponent, Ports, Signal, SignalUnsigned, - Simulator, -}; +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; use crate::components::Constant; use crate::gui_egui::component_ui::{input_port, pos_slider, properties_window, rect_with_hover}; -use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; -use egui::{ - Align2, Area, Color32, Frame, Margin, Order, PointerButton, Pos2, Rect, RichText, Rounding, - Sense, Vec2, Window, -}; -use epaint::Shadow; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Vec2}; #[typetag::serde] impl EguiComponent for Constant { diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 7dc2816b..4dc50b8c 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -1,5 +1,6 @@ -use crate::common::{EditorMode, EguiComponent, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, SignalUnsigned, Simulator}; use crate::components::Mux; +use crate::gui_egui::editor::EditorMode; use crate::gui_egui::helper::offset_helper; #[typetag::serde] diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 43d74fcd..9c47bd22 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -1,17 +1,10 @@ -use crate::common::{ - Components, EditorMode, EditorRenderReturn, EguiComponent, Ports, Signal, SignalUnsigned, - Simulator, -}; +use crate::common::{EguiComponent, Ports, Signal, SignalUnsigned, Simulator}; use crate::components::Probe; use crate::gui_egui::component_ui::{ input_port, input_selector, pos_slider, properties_window, rect_with_hover, }; -use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; -use egui::{ - Align2, Area, Color32, ComboBox, Frame, Margin, Order, PointerButton, Pos2, Rect, RichText, - Rounding, Vec2, Window, -}; -use epaint::Shadow; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Vec2}; #[typetag::serde] impl EguiComponent for Probe { diff --git a/src/gui_egui/components/probe_edit.rs b/src/gui_egui/components/probe_edit.rs index ad77db1d..0c0ce7a7 100644 --- a/src/gui_egui/components/probe_edit.rs +++ b/src/gui_egui/components/probe_edit.rs @@ -1,5 +1,6 @@ -use crate::common::{EditorMode, EguiComponent, Simulator}; +use crate::common::{EguiComponent, Simulator}; use crate::components::ProbeEdit; +use crate::gui_egui::editor::EditorMode; use egui::Rect; #[typetag::serde] @@ -14,6 +15,5 @@ impl EguiComponent for ProbeEdit { _editor_mode: EditorMode, ) -> Option> { todo!(); - None } } diff --git a/src/gui_egui/components/probe_out.rs b/src/gui_egui/components/probe_out.rs index 41a7d343..300f4154 100644 --- a/src/gui_egui/components/probe_out.rs +++ b/src/gui_egui/components/probe_out.rs @@ -1,5 +1,6 @@ -use crate::common::{EditorMode, EguiComponent, Simulator}; +use crate::common::{EguiComponent, Simulator}; use crate::components::ProbeOut; +use crate::gui_egui::editor::EditorMode; use egui::Rect; #[typetag::serde] @@ -14,11 +15,5 @@ impl EguiComponent for ProbeOut { _editor_mode: EditorMode, ) -> Option> { todo!(); - None } - /* - fn interactive_rect(&self, ui: &mut egui::Ui, offset: egui::Vec2, scale: f32) -> egui::Rect { - todo!() - } - */ } diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index f5d7f4df..bac6e6c4 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -1,5 +1,6 @@ -use crate::common::{EditorMode, EguiComponent, Simulator}; +use crate::common::{EguiComponent, Simulator}; use crate::components::Register; +use crate::gui_egui::editor::EditorMode; use crate::gui_egui::helper::offset_helper; #[typetag::serde] diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index 4e8ab0f0..f27359bd 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -1,5 +1,6 @@ -use crate::common::{EditorMode, EguiComponent, Simulator}; +use crate::common::{EguiComponent, Simulator}; use crate::components::Sext; +use crate::gui_egui::editor::EditorMode; #[typetag::serde] impl EguiComponent for Sext { @@ -12,7 +13,6 @@ impl EguiComponent for Sext { _clip_rect: egui::Rect, _editor_mode: EditorMode, ) -> Option> { - todo!("implement sext"); - None + todo!(); } } diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 9c1c974b..113722e7 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -1,26 +1,18 @@ -use crate::common::{ - Components, EditorMode, EditorRenderReturn, EguiComponent, Ports, SignalUnsigned, Simulator, - SnapPriority, -}; +use crate::common::{EguiComponent, Ports, Simulator}; use crate::components::Wire; use crate::gui_egui::component_ui::{ input_port, input_selector, pos_slider, properties_window, rect_with_hover, }; -use crate::gui_egui::helper::{ - editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, -}; -use egui::{ - containers, Color32, ComboBox, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, - Shape, Slider, Stroke, Ui, Vec2, Window, -}; -use epaint::Shadow; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, SnapPriority}; +use crate::gui_egui::helper::offset_helper; +use egui::{Color32, PointerButton, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Wire { fn render( &self, ui: &mut Ui, - simulator: Option<&mut Simulator>, + _simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, clip_rect: Rect, @@ -118,80 +110,6 @@ impl EguiComponent for Wire { input_selector(ui, &mut self.input_port, id_ports); }, ); - /* - if self.egui_x.properties_window { - let mut input = self.input_port.input.id.clone(); - let resp = Window::new(format!("Properties: {}", self.id)) - .frame(Frame { - inner_margin: Margin::same(10f32), - outer_margin: Margin::same(0f32), - rounding: Rounding::same(10f32), - shadow: Shadow::small_dark(), - fill: ui.visuals().panel_fill, - stroke: ui.visuals().window_stroke, - }) - .default_pos(Pos2 { - x: (resp.rect.min.x + resp.rect.max.x) / 2f32, - y: (resp.rect.min.y + resp.rect.max.y) / 2f32, - }) - .show(ui.ctx(), |ui| { - ui.horizontal(|ui| { - let id_label = ui.label("Id: "); - let r = ui - .text_edit_singleline(&mut self.egui_x.id_tmp) - .labelled_by(id_label.id); - if r.lost_focus() && self.egui_x.id_tmp != self.id { - self.id = unique_component_name(cs, self.egui_x.id_tmp.as_str()); - } - }); - - ui.horizontal(|ui| { - ui.add( - Slider::new(&mut self.pos[i].0, 0f32..=1000f32) - .text("start x") - .clamp_to_range(false), - ); - ui.add( - Slider::new(&mut self.pos[i].1, 0f32..=1000f32) - .text("start y") - .clamp_to_range(false), - ); - }); - ui.horizontal(|ui| { - ui.add( - Slider::new(&mut self.pos[i + 1].0, 0f32..=1000f32) - .text("end x") - .clamp_to_range(false), - ); - ui.add( - Slider::new(&mut self.pos[i + 1].1, 0f32..=1000f32) - .text("end y") - .clamp_to_range(false), - ); - }); - let r = ComboBox::from_label("input") - .selected_text(format!("{}", input)) - .show_ui(ui, |ui| { - for c in cs.iter() { - let id = match c.try_borrow_mut() { - Ok(a) => a.get_id_ports().0.clone(), - Err(e) => self.id.clone(), - }; - ui.selectable_value(&mut input, id.clone(), id); - } - }); - self.input_port.input.id = input; - }); - if resp.unwrap().response.clicked_elsewhere() { - self.egui_x.properties_window = false; - } - } - - if resp.clicked_by(PointerButton::Secondary) { - // Open properties window - self.egui_x.properties_window = true; - } - */ } EditorRenderReturn { diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index ae33a73b..bdfc1a49 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -1,20 +1,15 @@ -use crate::common::{ - ComponentStore, Components, EditorMode, EguiComponent, Id, Input, InputPort, Simulator, -}; +use crate::common::{ComponentStore, Components, EguiComponent, Id, Input}; use crate::components::*; use crate::gui_egui::{ + editor_wire_mode::WireMode, gui::Gui, - helper::{ - id_ports_of_all_components, offset_helper, offset_reverse_helper_pos2, - unique_component_name, - }, + helper::{id_ports_of_all_components, offset_helper}, keymap, + library::InputMode, menu::Menu, }; use eframe::{egui, Frame}; -use egui::{ - Color32, Context, LayerId, PointerButton, Pos2, Rect, Response, Shape, Stroke, Style, Ui, Vec2, -}; +use egui::{Color32, Context, LayerId, PointerButton, Pos2, Rect, Vec2}; use std::{path::PathBuf, rc::Rc}; pub struct Editor { @@ -29,14 +24,8 @@ pub struct Editor { pub library: ComponentStore, pub dummy_input: Input, pub editor_mode: EditorMode, - pub wire_mode_ended: bool, - pub wire_last_pos: Option, - pub wire_input: Option, - pub wire_cursor_location: Pos2, - pub wire_start_comp_port: Option, - pub wire_temp_positions: Vec<(f32, f32)>, - pub input_comp: Option>, - pub input_cursor_location: Pos2, + pub wm: WireMode, + pub im: InputMode, } #[derive(Clone)] @@ -46,7 +35,26 @@ pub struct CloseToComponent { pub dist: f32, pub port_id: Id, } -// todo: enum for input mode, wire, component, none + +#[derive(Debug, Clone, Copy)] +pub enum EditorMode { + Default, + Wire, + Input, +} + +#[cfg(feature = "gui-egui")] +pub struct EditorRenderReturn { + pub delete: bool, + pub resp: Option>, +} + +// Specific structs for egui +#[cfg(feature = "gui-egui")] +pub enum SnapPriority { + Default, + Wire, +} impl Editor { pub fn gui(components: Components, _path: &PathBuf) -> Self { @@ -80,18 +88,22 @@ impl Editor { }, dummy_input, editor_mode: EditorMode::Default, - wire_mode_ended: true, - wire_last_pos: None, - wire_input: None, - wire_cursor_location: Pos2::ZERO, - wire_start_comp_port: None, - wire_temp_positions: vec![], - input_comp: None, - input_cursor_location: Pos2::ZERO, + wm: WireMode { + mode_ended: true, + last_pos: None, + input: None, + cursor_location: Pos2::ZERO, + start_comp_port: None, + temp_positions: vec![], + }, + im: InputMode { + comp: None, + cursor_location: Pos2::ZERO, + }, } } - pub fn update(ctx: &Context, frame: &mut Frame, gui: &mut Gui) { + pub fn update(ctx: &Context, _frame: &mut Frame, gui: &mut Gui) { let frame = egui::Frame::none().fill(egui::Color32::WHITE); if Editor::gui_to_editor(gui).should_area_update(ctx) { @@ -235,7 +247,7 @@ impl Editor { e.offset_and_pan = e.pan + e.offset; } match e.editor_mode { - EditorMode::Wire => crate::gui_egui::editor_wire::wire_mode(ctx, e, cpr, layer_id), + EditorMode::Wire => crate::gui_egui::editor_wire_mode::wire_mode(ctx, e, cpr, layer_id), EditorMode::Input => crate::gui_egui::library::input_mode(ctx, e, cpr, layer_id), EditorMode::Default => ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Default), } @@ -254,3 +266,13 @@ impl Editor { gui.editor.as_mut().unwrap() } } + +pub fn get_component(components: &Components, comp: CloseToComponent) -> Option { + for (i, c) in components.iter().enumerate() { + if Rc::ptr_eq(&c, &comp.comp) { + drop(comp); + return Some(i); + } + } + None +} diff --git a/src/gui_egui/editor_wire.rs b/src/gui_egui/editor_wire_mode.rs similarity index 76% rename from src/gui_egui/editor_wire.rs rename to src/gui_egui/editor_wire_mode.rs index e88c6cc1..0a764aa3 100644 --- a/src/gui_egui/editor_wire.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -1,6 +1,7 @@ -use crate::common::{Components, EguiComponent, Id, Input, SnapPriority}; +use crate::common::{Components, EguiComponent, Id, Input}; use crate::components::Wire; -use crate::gui_egui::editor::{CloseToComponent, Editor}; +use crate::gui_egui::editor::SnapPriority; +use crate::gui_egui::editor::{get_component, CloseToComponent, Editor}; use crate::gui_egui::helper::{ id_ports_of_all_components, offset_helper, offset_reverse_helper, offset_reverse_helper_pos2, unique_component_name, @@ -8,11 +9,20 @@ use crate::gui_egui::helper::{ use egui::{Color32, Context, CursorIcon, LayerId, PointerButton, Pos2, Response, Shape, Stroke}; use std::rc::Rc; +pub struct WireMode { + pub mode_ended: bool, + pub last_pos: Option, + pub input: Option, + pub cursor_location: Pos2, + pub start_comp_port: Option, + pub temp_positions: Vec<(f32, f32)>, +} + pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { - e.wire_mode_ended = false; + e.wm.mode_ended = false; ctx.input_mut(|i| { let origin = i.pointer.press_origin().unwrap(); - e.wire_cursor_location = origin; + e.wm.cursor_location = origin; let offset_cursor_scale = offset_reverse_helper_pos2(origin, e.scale, e.offset_and_pan); let (closest, _closest_wire) = @@ -20,31 +30,30 @@ pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { let closest_uw = closest.unwrap(); // First click ALWAYS has to start at a port so we force it - if e.wire_temp_positions.len() == 0 { + if e.wm.temp_positions.len() == 0 { // requires at least one component on the canvas let new_pos = closest_uw.pos; - e.wire_start_comp_port = Some(closest_uw); + e.wm.start_comp_port = Some(closest_uw); let new_pos = offset_helper((new_pos.x, new_pos.y), e.scale, e.offset_and_pan); - e.wire_temp_positions.push((new_pos.x, new_pos.y)); + e.wm.temp_positions.push((new_pos.x, new_pos.y)); // We clicked close to a port so this will be the last click done - } else if e.wire_temp_positions.len() > 0 && closest_uw.dist <= 10.0f32 { + } else if e.wm.temp_positions.len() > 0 && closest_uw.dist <= 10.0f32 { // We should finish the component last_click(e, closest_uw); // Click somewhere not near a component } else { - let (wire1, wire2) = - wire_split_into_two(*e.wire_temp_positions.last().unwrap(), (origin.x, origin.y)); - e.wire_temp_positions.push(wire1); - e.wire_temp_positions.push(wire2); + let mut wires = + wire_split_into_two_vec(*e.wm.temp_positions.last().unwrap(), (origin.x, origin.y)); + e.wm.temp_positions.append(&mut wires) } }); } pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { - //let in_c = e.wire_start_comp_port.unwrap(); - let in_c = std::mem::replace(&mut e.wire_start_comp_port, None).unwrap(); + //let in_c = e.wm.start_comp_port.unwrap(); + let in_c = std::mem::replace(&mut e.wm.start_comp_port, None).unwrap(); let out_c = closest_uw; let (field_name, input, is_comp_start) = get_outputs_from_port(&in_c.port_id, &in_c.comp, &out_c.port_id, &out_c.comp); @@ -55,12 +64,12 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { let id = id.as_str(); let mut pos_v: Vec<(f32, f32)> = vec![]; - for pos in &e.wire_temp_positions { + for pos in &e.wm.temp_positions { let pos_2 = offset_reverse_helper(*pos, e.scale, e.offset_and_pan); pos_v.push((pos_2.x, pos_2.y)); } - let last_pos = *e.wire_temp_positions.last().unwrap(); + let last_pos = *e.wm.temp_positions.last().unwrap(); let last_pos = offset_reverse_helper(last_pos, e.scale, e.offset_and_pan); let mut v = wire_split_into_two_vec((last_pos.x, last_pos.y), (out_c.pos.x, out_c.pos.y)); @@ -81,17 +90,7 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { println!("Seems like you don't have an input at the start or end of the wire"); } } - reset_wire_mode(e); -} - -pub fn get_component(components: &Components, comp: CloseToComponent) -> Option { - for (i, c) in components.iter().enumerate() { - if Rc::ptr_eq(&c, &comp.comp) { - drop(comp); - return Some(i); - } - } - None + reset_wire_mode(&mut e.wm); } pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option) { @@ -103,15 +102,15 @@ pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option< if cpr.drag_started_by(PointerButton::Secondary) { // place wire end // This should also occur when pressing an input/output after the first one - reset_wire_mode(e); + reset_wire_mode(&mut e.wm); } - if !e.wire_mode_ended { + if !e.wm.mode_ended { ctx.input_mut(|i| { - e.wire_cursor_location += i.pointer.delta(); + e.wm.cursor_location += i.pointer.delta(); }); let offset_cursor_scale = - offset_reverse_helper_pos2(e.wire_cursor_location, e.scale, e.offset_and_pan); + offset_reverse_helper_pos2(e.wm.cursor_location, e.scale, e.offset_and_pan); let (closest, _closest_wire) = clicked_close_to_input_output(offset_cursor_scale, &e.components); @@ -121,23 +120,18 @@ pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option< // We are close enough to move the shown wire to here instead c.pos + e.offset_and_pan } else { - e.wire_cursor_location + e.wm.cursor_location } } - None => e.wire_cursor_location, + None => e.wm.cursor_location, }; let v = wire_split_into_two_vec( - *e.wire_temp_positions.last().unwrap(), + *e.wm.temp_positions.last().unwrap(), (wire_shown_location.x, wire_shown_location.y), ); - let mut draw_vec: Vec = vec![]; // = s.wire_temp_positions.clone(); - for (posx, posy) in e - .wire_temp_positions - .clone() - .into_iter() - .chain(v.into_iter()) - { + let mut draw_vec: Vec = vec![]; // = s.wm.temp_positions.clone(); + for (posx, posy) in e.wm.temp_positions.clone().into_iter().chain(v.into_iter()) { draw_vec.push(Pos2::new(posx, posy)) } @@ -151,6 +145,9 @@ pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option< } } } + +/// This will only occasionally split the wire into two parts in case needed (e.g. drawing a straight +/// line) pub fn wire_split_into_two_vec(prev: (f32, f32), current: (f32, f32)) -> Vec<(f32, f32)> { let mut v = vec![]; if f32::abs(current.0 - prev.0) < 0.1f32 && f32::abs(current.1 - prev.1) < 0.01f32 { @@ -164,20 +161,20 @@ pub fn wire_split_into_two_vec(prev: (f32, f32), current: (f32, f32)) -> Vec<(f3 } pub fn wire_split_into_two(prev: (f32, f32), current: (f32, f32)) -> ((f32, f32), (f32, f32)) { - if f32::abs(prev.0 - current.0) > f32::abs(prev.1 - current.1) { + if f32::abs(prev.0 - current.0) < f32::abs(prev.1 - current.1) { ((current.0, prev.1), (current.0, current.1)) } else { ((prev.0, current.1), (current.0, current.1)) } } -pub fn reset_wire_mode(e: &mut Editor) { - e.wire_mode_ended = true; - e.wire_last_pos = None; - e.wire_input = None; - e.wire_cursor_location = Pos2::ZERO; - e.wire_start_comp_port = None; - e.wire_temp_positions = vec![]; +pub fn reset_wire_mode(wm: &mut WireMode) { + wm.mode_ended = true; + wm.last_pos = None; + wm.input = None; + wm.cursor_location = Pos2::ZERO; + wm.start_comp_port = None; + wm.temp_positions = vec![]; } /// returns an input made from the output diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index e3f709bd..024e4bc7 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -1,8 +1,8 @@ -use crate::common::{ComponentStore, EditorMode, Simulator}; +use crate::common::{ComponentStore, Simulator}; +use crate::gui_egui::editor::EditorMode; use crate::gui_egui::{editor::Editor, keymap, keymap::Shortcuts, menu::Menu}; use eframe::egui; use std::path::PathBuf; -use std::rc::Rc; pub struct Gui { pub simulator: Option, diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 2867507e..cafb9066 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -1,7 +1,6 @@ -use crate::common::{Components, EditorMode, EguiComponent, Ports}; -use crate::gui_egui::editor::CloseToComponent; -use egui::{Pos2, Rect, Response, Sense, Vec2}; -use std::rc::Rc; +use crate::common::{Components, Ports}; +use crate::gui_egui::editor::EditorMode; +use egui::{Pos2, Rect, Sense, Vec2}; pub fn offset_reverse_helper_pos2(xy: Pos2, scale: f32, offset: Vec2) -> Pos2 { egui::Pos2 { diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 706e7e14..ec1b0a09 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -1,4 +1,5 @@ -use crate::common::{ComponentStore, EditorMode, Simulator}; +use crate::common::{ComponentStore, Simulator}; +use crate::gui_egui::editor::EditorMode; use crate::gui_egui::{editor::Editor, Gui}; use egui::{Key, KeyboardShortcut, Modifiers}; use std::{path::PathBuf, rc::Rc}; @@ -23,7 +24,7 @@ pub struct Shortcuts { pub control_reset: KeyboardShortcut, pub control_step_forward: KeyboardShortcut, pub control_step_back: KeyboardShortcut, - pub editor_wire: KeyboardShortcut, + pub editor_wire_mode: KeyboardShortcut, pub editor_escape: KeyboardShortcut, } @@ -142,7 +143,7 @@ impl Shortcuts { modifiers: shift, key: Key::F10, }, - editor_wire: KeyboardShortcut { + editor_wire_mode: KeyboardShortcut { modifiers: none, key: Key::W, }, @@ -208,8 +209,8 @@ impl Shortcuts { if ctx.input_mut(|i| i.consume_shortcut(&self.control_step_back)) { control_step_back_fn(gui); } - if ctx.input_mut(|i| i.consume_shortcut(&self.editor_wire)) { - editor_wire_fn(gui); + if ctx.input_mut(|i| i.consume_shortcut(&self.editor_wire_mode)) { + editor_wire_mode_fn(gui); } if ctx.input_mut(|i| i.consume_shortcut(&self.editor_escape)) { editor_escape_fn(gui); @@ -236,6 +237,7 @@ pub fn file_save_fn(gui: &mut Gui) { } pub fn file_save_as_fn(_gui: &mut Gui) {} pub fn file_editor_toggle_fn(gui: &mut Gui) { + // bug: Switching Editor -> Simulator -> Editor crashes match gui.editor_use { true => { gui.editor_use = false; @@ -327,7 +329,7 @@ pub fn control_step_back_fn(gui: &mut Gui) { gui.simulator.as_mut().unwrap().un_clock(&mut gui.clock); } } -pub fn editor_wire_fn(gui: &mut Gui) { +pub fn editor_wire_mode_fn(gui: &mut Gui) { if gui.editor_use { let editor = gui.editor.as_mut().unwrap(); match editor.editor_mode { @@ -338,14 +340,14 @@ pub fn editor_wire_fn(gui: &mut Gui) { editor.editor_mode = EditorMode::Default; } } - crate::gui_egui::editor_wire::reset_wire_mode(editor); + crate::gui_egui::editor_wire_mode::reset_wire_mode(&mut editor.wm); } } pub fn editor_escape_fn(gui: &mut Gui) { if gui.editor_use { let editor = gui.editor.as_mut().unwrap(); editor.editor_mode = EditorMode::Default; - crate::gui_egui::editor_wire::reset_wire_mode(editor); - crate::gui_egui::library::reset_input_mode(editor); + crate::gui_egui::editor_wire_mode::reset_wire_mode(&mut editor.wm); + crate::gui_egui::library::reset_input_mode(&mut editor.im); } } diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index 063964a3..749b30d3 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -1,17 +1,23 @@ -use crate::common::{EditorMode, EguiComponent}; +use crate::common::EguiComponent; use crate::components::*; +use crate::gui_egui::editor::EditorMode; use crate::gui_egui::{ editor::Editor, helper::{id_ports_of_all_components, offset_reverse_helper_pos2, unique_component_name}, }; use egui::{Context, CursorIcon, LayerId, PointerButton, Pos2, Rect, Response, Ui, Vec2}; -use std::{path::PathBuf, rc::Rc}; +use std::rc::Rc; + +pub struct InputMode { + pub comp: Option>, + pub cursor_location: Pos2, +} pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option) { let layer_id = layer_id.unwrap(); ctx.output_mut(|o| o.cursor_icon = CursorIcon::None); ctx.input_mut(|i| { - e.input_cursor_location += i.pointer.delta(); + e.im.cursor_location += i.pointer.delta(); }); let clip_rect = Rect { min: Pos2 { @@ -30,10 +36,10 @@ pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option clip_rect, Rect::EVERYTHING, ); - e.input_comp.as_ref().unwrap().render( + e.im.comp.as_ref().unwrap().render( &mut ui, None, - Vec2::new(e.input_cursor_location.x, e.input_cursor_location.y), + Vec2::new(e.im.cursor_location.x, e.im.cursor_location.y), e.scale, clip_rect, e.editor_mode, @@ -44,9 +50,9 @@ pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option } } -pub fn reset_input_mode(e: &mut Editor) { - e.input_comp = None; - e.input_cursor_location = Pos2::ZERO; +pub fn reset_input_mode(im: &mut InputMode) { + im.comp = None; + im.cursor_location = Pos2::ZERO; } pub fn show_library(e: &mut Editor, ui: &mut Ui) { @@ -75,11 +81,13 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { // Create new component if resp.drag_started_by(PointerButton::Primary) { e.editor_mode = EditorMode::Input; - e.input_comp = Some(c.clone()); + e.im.comp = Some(c.clone()); ui.input_mut(|i| { let origin = i.pointer.press_origin().unwrap(); - e.input_cursor_location = origin; + e.im.cursor_location = origin; }); + } else if resp.drag_started_by(PointerButton::Secondary) { + reset_input_mode(&mut e.im); } } padding.y = rect.max.y + 10f32; @@ -88,10 +96,10 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { // todo: This should really just copy the component that's in e.input_comp pub fn add_comp_to_editor(e: &mut Editor) { - let pos = offset_reverse_helper_pos2(e.input_cursor_location, e.scale, e.offset); + let pos = offset_reverse_helper_pos2(e.im.cursor_location, e.scale, e.offset); let id_ports = id_ports_of_all_components(&e.components); let mut comp: Rc = - match e.input_comp.as_mut().unwrap().get_id_ports().0.as_str() { + match e.im.comp.as_mut().unwrap().get_id_ports().0.as_str() { "c" => { let id = unique_component_name(&id_ports, "c"); Rc::new(Constant::new(id.as_str(), (0.0, 0.0), 0)) diff --git a/src/gui_egui/mod.rs b/src/gui_egui/mod.rs index 4850f52c..fa0565f2 100644 --- a/src/gui_egui/mod.rs +++ b/src/gui_egui/mod.rs @@ -1,6 +1,6 @@ mod component_ui; -mod editor; -mod editor_wire; +pub mod editor; +mod editor_wire_mode; mod gui; pub mod helper; mod keymap; diff --git a/src/simulator.rs b/src/simulator.rs index 33e53066..b7a25522 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -236,7 +236,7 @@ impl Simulator { mod test { use super::*; use crate::components::*; - use std::{cell::RefCell, rc::Rc}; + use std::rc::Rc; #[test] fn test_define() { From 63684b66167beaa4d197a5c687d1104c225de757 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 12:17:15 +0200 Subject: [PATCH 19/58] Fixed mem bug --- src/components/mem.rs | 12 ++++++------ src/main.rs | 6 +++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/mem.rs b/src/components/mem.rs index 1945785b..8550b5a0 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -54,8 +54,8 @@ impl Mem { data: Input, addr: Input, ctrl: Input, - sign: Input, size: Input, + sign: Input, memory: Memory, ) -> Self { Mem { @@ -76,14 +76,14 @@ impl Mem { port_id: String::from("ctrl"), input: ctrl, }, - sign: InputPort { - port_id: String::from("sign"), - input: sign, - }, size: InputPort { port_id: String::from("size"), input: size, }, + sign: InputPort { + port_id: String::from("sign"), + input: sign, + }, memory, #[cfg(feature = "gui-egui")] egui_x: crate::common::EguiExtra::default(), @@ -492,7 +492,7 @@ mod test { Rc::new(ProbeOut::new("size")), Rc::new(ProbeOut::new("sign")), Rc::new(Mem::new( - "mem".into(), + "mem", (0.0, 0.0), 0.0, 0.0, diff --git a/src/main.rs b/src/main.rs index 35e83efd..5bc7917a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,5 +22,9 @@ fn main() { syncrim::gui_egui::gui(cs, &_path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&_cs, &_path); + syncrim::gui_vizia::gui(cs, &_path); + + // run headless + #[cfg(not(any(feature = "gui-vizia", feature = "gui-egui")))] + syncrim::common::Simulator::new(cs, &mut 0); } From 9e2eb016339a4927c91c20d2248cfda17458c2ef Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 13:43:10 +0200 Subject: [PATCH 20/58] Fixed all clippy messages --- examples/add.rs | 2 +- examples/add_edit.rs | 2 +- examples/add_mux.rs | 2 +- examples/add_reg.rs | 2 +- examples/add_reg_compound_wire.rs | 2 +- examples/data_mem.rs | 2 +- examples/mux.rs | 2 +- examples/probe_edit.rs | 2 +- examples/reg.rs | 2 +- examples/sext.rs | 2 +- mips/examples/mips.rs | 154 ++++++++++++++-------------- mips/examples/reg_file.rs | 32 +++--- mips/src/components/instr_mem.rs | 19 +++- mips/src/components/reg_file.rs | 98 +++++++++++++----- mips/src/main.rs | 7 +- src/common.rs | 15 +-- src/components/mem.rs | 1 + src/components/probe.rs | 5 +- src/gui_egui/component_ui.rs | 12 +-- src/gui_egui/components/add.rs | 10 +- src/gui_egui/components/constant.rs | 10 +- src/gui_egui/components/probe.rs | 10 +- src/gui_egui/components/wire.rs | 10 +- src/gui_egui/editor.rs | 10 +- src/gui_egui/editor_wire_mode.rs | 14 ++- src/gui_egui/helper.rs | 16 +-- src/gui_egui/keymap.rs | 32 +++--- src/gui_egui/library.rs | 7 +- 28 files changed, 263 insertions(+), 219 deletions(-) diff --git a/examples/add.rs b/examples/add.rs index 9d117067..ea1ba898 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -43,5 +43,5 @@ fn main() { syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/add_edit.rs b/examples/add_edit.rs index 61f07625..8816e4f3 100644 --- a/examples/add_edit.rs +++ b/examples/add_edit.rs @@ -43,5 +43,5 @@ fn main() { syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/add_mux.rs b/examples/add_mux.rs index bd725215..16afb9df 100644 --- a/examples/add_mux.rs +++ b/examples/add_mux.rs @@ -122,5 +122,5 @@ fn main() { syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/add_reg.rs b/examples/add_reg.rs index 75851220..d8150f2a 100644 --- a/examples/add_reg.rs +++ b/examples/add_reg.rs @@ -76,5 +76,5 @@ fn main() { syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/add_reg_compound_wire.rs b/examples/add_reg_compound_wire.rs index 21596e20..c7c22bba 100644 --- a/examples/add_reg_compound_wire.rs +++ b/examples/add_reg_compound_wire.rs @@ -63,5 +63,5 @@ fn main() { syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/data_mem.rs b/examples/data_mem.rs index de0a58ad..e91de46e 100644 --- a/examples/data_mem.rs +++ b/examples/data_mem.rs @@ -87,5 +87,5 @@ fn main() { syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/mux.rs b/examples/mux.rs index 6fb4b30f..02c1d76f 100644 --- a/examples/mux.rs +++ b/examples/mux.rs @@ -70,5 +70,5 @@ fn main() { syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/probe_edit.rs b/examples/probe_edit.rs index 50fed6ee..c92712d4 100644 --- a/examples/probe_edit.rs +++ b/examples/probe_edit.rs @@ -25,5 +25,5 @@ fn main() { syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/reg.rs b/examples/reg.rs index b48de2d2..b30b1cf7 100644 --- a/examples/reg.rs +++ b/examples/reg.rs @@ -36,5 +36,5 @@ fn main() { syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/sext.rs b/examples/sext.rs index b3f25b58..8a750f9a 100644 --- a/examples/sext.rs +++ b/examples/sext.rs @@ -38,5 +38,5 @@ fn main() { syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/mips/examples/mips.rs b/mips/examples/mips.rs index efcbe0cf..5aa61293 100644 --- a/mips/examples/mips.rs +++ b/mips/examples/mips.rs @@ -12,85 +12,81 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Add { - id: "add".to_string(), - pos: (200.0, 120.0), - a_in: Input::new("c1", "out"), - b_in: Input::new("reg", "out"), - }), + Rc::new(Add::new( + "add", + (200.0, 120.0), + Input::new("c1", "out"), + Input::new("reg", "out"), + )), Constant::rc_new("c1", (100.0, 100.0), 4), - Rc::new(Register { - id: "reg".to_string(), - pos: (100.0, 140.0), - r_in: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "c1_to_add_a".to_string(), - pos: vec![(110.0, 100.0), (180.0, 100.0)], - input: Input::new("c1", "out"), - }), - Rc::new(Wire { - id: "reg_to_add_b".to_string(), - pos: vec![(110.0, 140.0), (180.0, 140.0)], - input: Input::new("reg", "out"), - }), - Rc::new(Wire { - id: "add_to_right".to_string(), - pos: vec![(220.0, 120.0), (260.0, 120.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "add_to_up".to_string(), - pos: vec![(260.0, 60.0), (260.0, 120.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "add_to_left".to_string(), - pos: vec![(60.0, 60.0), (260.0, 60.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "add_to_down".to_string(), - pos: vec![(60.0, 60.0), (60.0, 140.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "reg_in".to_string(), - pos: vec![(60.0, 140.0), (90.0, 140.0)], - input: Input::new("add", "out"), - }), - Rc::new(Wire { - id: "pc_to_down".to_string(), - pos: vec![(140.0, 140.0), (140.0, 180.0)], - input: Input::new("reg", "out"), - }), - Rc::new(Wire { - id: "pc_to_right".to_string(), - pos: vec![(140.0, 180.0), (350.0, 180.0)], - input: Input::new("reg", "out"), - }), - Rc::new(InstrMem { - id: "instr_mem".to_string(), - pos: (400.0, 150.0), - pc: Input::new("reg", "out"), + Rc::new(Register::new( + "reg", + (100.0, 140.0), + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "c1_to_add_a", + vec![(110.0, 100.0), (180.0, 100.0)], + Input::new("c1", "out"), + )), + Rc::new(Wire::new( + "reg_to_add_b", + vec![(110.0, 140.0), (180.0, 140.0)], + Input::new("reg", "out"), + )), + Rc::new(Wire::new( + "add_to_right", + vec![(220.0, 120.0), (260.0, 120.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "add_to_up", + vec![(260.0, 60.0), (260.0, 120.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "add_to_left", + vec![(60.0, 60.0), (260.0, 60.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "add_to_down", + vec![(60.0, 60.0), (60.0, 140.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "reg_in", + vec![(60.0, 140.0), (90.0, 140.0)], + Input::new("add", "out"), + )), + Rc::new(Wire::new( + "pc_to_down", + vec![(140.0, 140.0), (140.0, 180.0)], + Input::new("reg", "out"), + )), + Rc::new(Wire::new( + "pc_to_right", + vec![(140.0, 180.0), (350.0, 180.0)], + Input::new("reg", "out"), + )), + Rc::new(InstrMem::new( + "instr_mem", + (400.0, 150.0), + Input::new("reg", "out"), // fake instructions just to show the relation between input address and instruction - instr: vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], - }), - Rc::new(Wire { - id: "w8".to_string(), - pos: vec![(450.0, 120.0), (520.0, 120.0)], - input: Input::new("instr_mem", "out"), - }), - Rc::new(Probe { - id: "p1".to_string(), - pos: (280.0, 160.0), - input: Input::new("reg", "out"), - }), - Rc::new(Probe { - id: "p2".to_string(), - pos: (500.0, 100.0), - input: Input::new("instr_mem", "out"), - }), + vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + )), + Rc::new(Wire::new( + "w8", + vec![(450.0, 120.0), (520.0, 120.0)], + Input::new("instr_mem", "out"), + )), + Rc::new(Probe::new("p1", (280.0, 160.0), Input::new("reg", "out"))), + Rc::new(Probe::new( + "p2", + (500.0, 100.0), + Input::new("instr_mem", "out"), + )), ], }; @@ -98,8 +94,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/mips/examples/reg_file.rs b/mips/examples/reg_file.rs index 3da9690b..54dfff9d 100644 --- a/mips/examples/reg_file.rs +++ b/mips/examples/reg_file.rs @@ -17,23 +17,21 @@ fn main() { Constant::rc_new("c_write_addr", (100.0, 160.0), 4), Constant::rc_new("c_write_enable", (100.0, 180.0), true), // regfile - Rc::new(RegFile { - id: "reg_file".to_string(), - pos: (300.0, 200.0), - width: 200.0, - height: 300.0, - + Rc::new(RegFile::new( + "reg_file", + (300.0, 200.0), + 200.0, + 300.0, // ports - read_addr1: Input::new("c_read_reg_1", "out"), - read_addr2: Input::new("c_read_reg_2", "out"), - write_data: Input::new("c_write_data", "out"), - write_addr: Input::new("c_write_addr", "out"), - write_enable: Input::new("c_write_enable", "out"), - + Input::new("c_read_reg_1", "out"), + Input::new("c_read_reg_2", "out"), + Input::new("c_write_data", "out"), + Input::new("c_write_addr", "out"), + Input::new("c_write_enable", "out"), // data - registers: RegStore::new(), - history: RegHistory::new(), - }), + RegStore::new(), + RegHistory::new(), + )), ], }; @@ -41,8 +39,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/mips/src/components/instr_mem.rs b/mips/src/components/instr_mem.rs index 433b8ac6..4d87b82d 100644 --- a/mips/src/components/instr_mem.rs +++ b/mips/src/components/instr_mem.rs @@ -1,16 +1,29 @@ use serde::{Deserialize, Serialize}; -use syncrim::common::{Component, Input, OutputType, Ports, Simulator}; +use syncrim::common::{Component, Input, InputPort, OutputType, Ports, Simulator}; #[derive(Serialize, Deserialize)] pub struct InstrMem { pub id: String, pub pos: (f32, f32), + pub pc: InputPort, pub instr: Vec, - pub pc: Input, } use log::*; +impl InstrMem { + pub fn new(id: &str, pos: (f32, f32), pc: Input, instr: Vec) -> Self { + InstrMem { + id: id.to_string(), + pos, + pc: InputPort { + port_id: String::from("in"), + input: pc, + }, + instr, + } + } +} #[typetag::serde()] impl Component for InstrMem { fn to_(&self) { @@ -30,7 +43,7 @@ impl Component for InstrMem { fn clock(&self, simulator: &mut Simulator) { // get instr at pc/4 - let pc: u32 = simulator.get_input_val(&self.pc).try_into().unwrap(); + let pc: u32 = simulator.get_input_val(&self.pc.input).try_into().unwrap(); trace!("--- evaluate instr mem: pc {:?}", pc); let instr = self.instr[(pc / 4) as usize]; diff --git a/mips/src/components/reg_file.rs b/mips/src/components/reg_file.rs index 9fafa91f..e81ade03 100644 --- a/mips/src/components/reg_file.rs +++ b/mips/src/components/reg_file.rs @@ -3,7 +3,9 @@ use num_enum::TryFromPrimitive; use serde::{Deserialize, Serialize}; use std::ops::{Deref, Range}; use std::{cell::RefCell, rc::Rc}; -use syncrim::common::{Component, Input, OutputType, Ports, Signal, SignalUnsigned, Simulator}; +use syncrim::common::{ + Component, Input, InputPort, OutputType, Ports, Signal, SignalUnsigned, Simulator, +}; #[allow(non_camel_case_types)] #[rustfmt::skip] @@ -52,16 +54,60 @@ pub struct RegFile { pub height: f32, // ports - pub read_addr1: Input, - pub read_addr2: Input, - pub write_data: Input, - pub write_addr: Input, - pub write_enable: Input, + pub read_addr1: InputPort, + pub read_addr2: InputPort, + pub write_data: InputPort, + pub write_addr: InputPort, + pub write_enable: InputPort, // data pub registers: RegStore, pub history: RegHistory, } +impl RegFile { + pub fn new( + id: &str, + pos: (f32, f32), + width: f32, + height: f32, + read_addr1: Input, + read_addr2: Input, + write_data: Input, + write_addr: Input, + write_enable: Input, + registers: RegStore, + history: RegHistory, + ) -> Self { + RegFile { + id: id.to_string(), + pos, + width, + height, + read_addr1: InputPort { + port_id: "read_addr1".to_string(), + input: read_addr1, + }, + read_addr2: InputPort { + port_id: "read_addr2".to_string(), + input: read_addr2, + }, + write_data: InputPort { + port_id: "write_data".to_string(), + input: write_data, + }, + write_addr: InputPort { + port_id: "write_addr".to_string(), + input: write_addr, + }, + write_enable: InputPort { + port_id: "write_enable".to_string(), + input: write_enable, + }, + registers, + history, + } + } +} #[derive(Serialize, Deserialize, Clone)] pub struct RegOp { @@ -154,11 +200,11 @@ impl Component for RegFile { } fn clock(&self, simulator: &mut Simulator) { - if simulator.get_input_val(&self.write_enable) == (true as SignalUnsigned).into() { - let data = simulator.get_input_val(&self.write_data); + if simulator.get_input_val(&self.write_enable.input) == (true as SignalUnsigned).into() { + let data = simulator.get_input_val(&self.write_data.input); trace!("data {:?}", data); let write_addr: SignalUnsigned = simulator - .get_input_val(&self.write_addr) + .get_input_val(&self.write_addr.input) .try_into() .unwrap(); trace!("write_addr {}", write_addr); @@ -166,11 +212,11 @@ impl Component for RegFile { } // read after write - let reg_value_a = self.read_reg(simulator, &self.read_addr1); + let reg_value_a = self.read_reg(simulator, &self.read_addr1.input); trace!("reg_value {}", reg_value_a); simulator.set_out_val(&self.id, "reg_a", Signal::Data(reg_value_a)); - let reg_value_b = self.read_reg(simulator, &self.read_addr2); + let reg_value_b = self.read_reg(simulator, &self.read_addr2.input); trace!("reg_value {}", reg_value_b); simulator.set_out_val(&self.id, "reg_b", Signal::Data(reg_value_b)); } @@ -196,27 +242,25 @@ mod test { Rc::new(ProbeOut::new("write_addr")), Rc::new(ProbeOut::new("write_enable")), // regfile - Rc::new(RegFile { - id: "reg_file".to_string(), - pos: (200.0, 150.0), - width: 100.0, - height: 150.0, - + Rc::new(RegFile::new( + "reg_file", + (200.0, 150.0), + 100.0, + 150.0, // ports - read_addr1: Input::new("read_reg_1", "out"), - read_addr2: Input::new("read_reg_2", "out"), - write_data: Input::new("write_data", "out"), - write_addr: Input::new("write_addr", "out"), - write_enable: Input::new("write_enable", "out"), - + Input::new("read_reg_1", "out"), + Input::new("read_reg_2", "out"), + Input::new("write_data", "out"), + Input::new("write_addr", "out"), + Input::new("write_enable", "out"), // data - registers: RegStore::new(), - history: RegHistory::new(), - }), + RegStore::new(), + RegHistory::new(), + )), ], }; let mut clock = 0; - let mut simulator = Simulator::new(&cs, &mut clock); + let mut simulator = Simulator::new(cs, &mut clock); assert_eq!(clock, 1); diff --git a/mips/src/main.rs b/mips/src/main.rs index 0366ca74..bee6a090 100644 --- a/mips/src/main.rs +++ b/mips/src/main.rs @@ -6,8 +6,11 @@ fn main() { fern_setup(); let path = PathBuf::from("mips.json"); - let _cs = ComponentStore::load_file(&path); + let cs = ComponentStore::load_file(&path); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&_cs, &path); + syncrim::gui_vizia::gui(cs, &path); + + #[cfg(not(any(feature = "gui-vizia", feature = "gui-egui")))] + syncrim::common::Simulator::new(cs, &mut 0); } diff --git a/src/common.rs b/src/common.rs index 69dcd596..e00e2420 100644 --- a/src/common.rs +++ b/src/common.rs @@ -136,6 +136,7 @@ pub trait EguiComponent: Component { None } + #[allow(clippy::too_many_arguments)] fn render_editor( &mut self, _ui: &mut egui::Ui, @@ -143,7 +144,7 @@ pub trait EguiComponent: Component { _offset: egui::Vec2, _scale: f32, _clip_rect: egui::Rect, - _id_ports: &Vec<(Id, Ports)>, + _id_ports: &[(Id, Ports)], _editor_mode: EditorMode, ) -> EditorRenderReturn { EditorRenderReturn { @@ -170,22 +171,12 @@ pub trait EguiComponent: Component { } #[cfg(feature = "gui-egui")] -#[derive(Serialize, Deserialize, Clone)] +#[derive(Serialize, Deserialize, Clone, Default)] pub struct EguiExtra { pub properties_window: bool, pub id_tmp: String, } -#[cfg(feature = "gui-egui")] -impl Default for EguiExtra { - fn default() -> Self { - EguiExtra { - properties_window: false, - id_tmp: String::new(), - } - } -} - #[derive(Debug, Clone)] pub struct Ports { pub inputs: Vec, diff --git a/src/components/mem.rs b/src/components/mem.rs index 8550b5a0..e7a1dfff 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -45,6 +45,7 @@ impl Default for Memory { } impl Mem { + #[allow(clippy::too_many_arguments)] pub fn new( id: &str, pos: (f32, f32), diff --git a/src/components/probe.rs b/src/components/probe.rs index 2316d890..34a4582d 100644 --- a/src/components/probe.rs +++ b/src/components/probe.rs @@ -46,9 +46,8 @@ impl Component for Probe { } fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - match target_port_id.as_str() { - "in" => self.input_port.input = new_input, - _ => (), + if target_port_id.as_str() == "in" { + self.input_port.input = new_input } } } diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index 0ac71b5d..6316ac57 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -65,12 +65,12 @@ pub fn properties_window

( pub fn pos_slider(ui: &mut Ui, pos: &mut (f32, f32)) { ui.horizontal(|ui| { ui.add( - egui::Slider::new(&mut (*pos).0, 0f32..=1000f32) + egui::Slider::new(&mut pos.0, 0f32..=1000f32) .text("pos x") .clamp_to_range(false), ); ui.add( - egui::Slider::new(&mut (*pos).1, 0f32..=1000f32) + egui::Slider::new(&mut pos.1, 0f32..=1000f32) .text("pos y") .clamp_to_range(false), ); @@ -79,14 +79,14 @@ pub fn pos_slider(ui: &mut Ui, pos: &mut (f32, f32)) { pub fn input_selector( ui: &mut Ui, input_port: &mut InputPort, - id_ports: &Vec<(crate::common::Id, Ports)>, + id_ports: &[(crate::common::Id, Ports)], ) { let mut port_id = input_port.input.id.clone(); let mut port_field = input_port.input.field.clone(); let label_port_id = format!("{}.id", input_port.port_id.clone()); - let text_port_id = format!("{}", port_id); + let text_port_id = port_id.to_string(); let label_port_field = format!("{}.field", input_port.port_id.clone()); - let text_port_field = format!("{}", port_field); + let text_port_field = port_field.to_string(); ui.horizontal(|ui| { ComboBox::from_label(label_port_id) .selected_text(text_port_id) @@ -119,7 +119,7 @@ pub fn input_port( ui: &mut Ui, id_tmp: &mut String, id: &mut String, - id_ports: &Vec<(crate::common::Id, Ports)>, + id_ports: &[(crate::common::Id, Ports)], ) { ui.horizontal(|ui| { let id_label = ui.label("Id: "); diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 947256eb..7f0ecf27 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -79,7 +79,7 @@ impl EguiComponent for Add { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - id_ports: &Vec<(crate::common::Id, Ports)>, + id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; @@ -91,10 +91,10 @@ impl EguiComponent for Add { self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } - if resp.drag_released_by(PointerButton::Primary) { - if resp.interact_pointer_pos().unwrap().x < offset.x { - delete = true; - } + if resp.drag_released_by(PointerButton::Primary) + && resp.interact_pointer_pos().unwrap().x < offset.x + { + delete = true; } properties_window( diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index ef261f39..b7b52da5 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -61,7 +61,7 @@ impl EguiComponent for Constant { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - id_ports: &Vec<(crate::common::Id, Ports)>, + id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; @@ -72,10 +72,10 @@ impl EguiComponent for Constant { let delta = resp.drag_delta() / scale; self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } - if resp.drag_released_by(PointerButton::Primary) { - if resp.interact_pointer_pos().unwrap().x < offset.x { - delete = true; - } + if resp.drag_released_by(PointerButton::Primary) + && resp.interact_pointer_pos().unwrap().x < offset.x + { + delete = true; } properties_window( diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 9c47bd22..01e45ae5 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -69,7 +69,7 @@ impl EguiComponent for Probe { offset: egui::Vec2, scale: f32, clip_rect: egui::Rect, - id_ports: &Vec<(crate::common::Id, Ports)>, + id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; @@ -81,10 +81,10 @@ impl EguiComponent for Probe { self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } - if resp.drag_released_by(PointerButton::Primary) { - if resp.interact_pointer_pos().unwrap().x < offset.x { - delete = true; - } + if resp.drag_released_by(PointerButton::Primary) + && resp.interact_pointer_pos().unwrap().x < offset.x + { + delete = true; } properties_window( diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 113722e7..1eb14070 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -80,7 +80,7 @@ impl EguiComponent for Wire { offset: Vec2, scale: f32, clip_rect: Rect, - id_ports: &Vec<(crate::common::Id, Ports)>, + id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; @@ -93,10 +93,10 @@ impl EguiComponent for Wire { self.pos[i] = (self.pos[i].0 + delta.x, self.pos[i].1 + delta.y); self.pos[i + 1] = (self.pos[i + 1].0 + delta.x, self.pos[i + 1].1 + delta.y); } - if resp.drag_released_by(PointerButton::Primary) { - if resp.interact_pointer_pos().unwrap().x < offset.x { - delete = true; - } + if resp.drag_released_by(PointerButton::Primary) + && resp.interact_pointer_pos().unwrap().x < offset.x + { + delete = true; } properties_window( ui, diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index bdfc1a49..fe42d9f0 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -10,7 +10,7 @@ use crate::gui_egui::{ }; use eframe::{egui, Frame}; use egui::{Color32, Context, LayerId, PointerButton, Pos2, Rect, Vec2}; -use std::{path::PathBuf, rc::Rc}; +use std::{path::Path, rc::Rc}; pub struct Editor { pub components: Components, @@ -57,7 +57,7 @@ pub enum SnapPriority { } impl Editor { - pub fn gui(components: Components, _path: &PathBuf) -> Self { + pub fn gui(components: Components, _path: &Path) -> Self { let dummy_input = Input::new("id", "field"); Editor { components, @@ -223,8 +223,8 @@ impl Editor { ); } } - _ => e.components.retain_mut(|mut c| { - let delete = (*Rc::get_mut(&mut c).unwrap()) + _ => e.components.retain_mut(|c| { + let delete = (*Rc::get_mut(c).unwrap()) .render_editor( ui, None, @@ -269,7 +269,7 @@ impl Editor { pub fn get_component(components: &Components, comp: CloseToComponent) -> Option { for (i, c) in components.iter().enumerate() { - if Rc::ptr_eq(&c, &comp.comp) { + if std::ptr::eq(c, &comp.comp) { drop(comp); return Some(i); } diff --git a/src/gui_egui/editor_wire_mode.rs b/src/gui_egui/editor_wire_mode.rs index 0a764aa3..d3366c4c 100644 --- a/src/gui_egui/editor_wire_mode.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -30,7 +30,7 @@ pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { let closest_uw = closest.unwrap(); // First click ALWAYS has to start at a port so we force it - if e.wm.temp_positions.len() == 0 { + if e.wm.temp_positions.is_empty() { // requires at least one component on the canvas let new_pos = closest_uw.pos; e.wm.start_comp_port = Some(closest_uw); @@ -38,7 +38,7 @@ pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { e.wm.temp_positions.push((new_pos.x, new_pos.y)); // We clicked close to a port so this will be the last click done - } else if e.wm.temp_positions.len() > 0 && closest_uw.dist <= 10.0f32 { + } else if !e.wm.temp_positions.is_empty() && closest_uw.dist <= 10.0f32 { // We should finish the component last_click(e, closest_uw); @@ -52,8 +52,7 @@ pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { } pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { - //let in_c = e.wm.start_comp_port.unwrap(); - let in_c = std::mem::replace(&mut e.wm.start_comp_port, None).unwrap(); + let in_c = e.wm.start_comp_port.take().unwrap(); let out_c = closest_uw; let (field_name, input, is_comp_start) = get_outputs_from_port(&in_c.port_id, &in_c.comp, &out_c.port_id, &out_c.comp); @@ -79,11 +78,10 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { // Now actually set the input of the wired component let comp = if is_comp_start { in_c } else { out_c }; - match get_component(&e.components, comp) { - Some(c) => Rc::get_mut(&mut e.components[c]) + if let Some(c) = get_component(&e.components, comp) { + Rc::get_mut(&mut e.components[c]) .unwrap() - .set_id_port(field_name, i), - None => (), + .set_id_port(field_name, i); } } None => { diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index cafb9066..f258f96f 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -25,9 +25,11 @@ pub fn offset_helper(xy: (f32, f32), scale: f32, offset: Vec2) -> Pos2 { pub fn out_of_bounds(request: Rect, clip_rect: Rect) -> Rect { let mut rect = Rect::NOTHING; - if request.max.x < clip_rect.min.x || request.max.y < clip_rect.min.y { - return rect; - } else if request.min.x > clip_rect.max.x || request.min.y > clip_rect.max.y { + if request.max.x < clip_rect.min.x + || request.max.y < clip_rect.min.y + || request.min.x > clip_rect.max.x + || request.min.y > clip_rect.max.y + { return rect; } rect = request; @@ -43,10 +45,10 @@ pub fn out_of_bounds(request: Rect, clip_rect: Rect) -> Rect { if request.min.y < clip_rect.min.y { rect.min.y = clip_rect.min.y; } - return rect; + rect } -pub fn unique_component_name(id_ports: &Vec<(crate::common::Id, Ports)>, id: &str) -> String { +pub fn unique_component_name(id_ports: &[(crate::common::Id, Ports)], id: &str) -> String { let mut new_id: String = id.into(); let mut contains_id = true; while contains_id { @@ -56,12 +58,12 @@ pub fn unique_component_name(id_ports: &Vec<(crate::common::Id, Ports)>, id: &st if id == new_id { contains_id = true; // todo: make this fancier - new_id.push_str("1"); + new_id.push('1'); break; } } } - String::from(new_id) + new_id } pub fn id_ports_of_all_components(cs: &Components) -> Vec<(crate::common::Id, Ports)> { diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index ec1b0a09..af9f46c6 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -222,13 +222,14 @@ pub fn file_new_fn(_gui: &mut Gui) {} pub fn file_open_fn(_gui: &mut Gui) {} pub fn file_save_fn(gui: &mut Gui) { match gui.editor_use { - true => match gui.editor.as_mut() { - Some(e) => ComponentStore { - store: e.components.clone(), + true => { + if let Some(e) = gui.editor.as_mut() { + ComponentStore { + store: e.components.clone(), + } + .save_file(&PathBuf::from("file.json")) } - .save_file(&PathBuf::from("file.json")), - None => (), - }, + } false => ComponentStore { store: gui.simulator.clone().unwrap().ordered_components, } @@ -241,24 +242,21 @@ pub fn file_editor_toggle_fn(gui: &mut Gui) { match gui.editor_use { true => { gui.editor_use = false; - match gui.editor.as_mut() { - Some(e) => { - let components = e.components.clone(); - let simulator = - Simulator::new(ComponentStore { store: components }, &mut gui.clock); - gui.simulator = Some(simulator); - } - _ => (), + if let Some(e) = gui.editor.as_mut() { + let components = e.components.clone(); + let simulator = + Simulator::new(ComponentStore { store: components }, &mut gui.clock); + gui.simulator = Some(simulator); } } false => { - let simulator = std::mem::replace(&mut gui.simulator, None); + let simulator = gui.simulator.take(); let simulator = simulator.unwrap(); let mut components = simulator.ordered_components.clone(); drop(simulator); - for mut c in components.iter_mut() { - (*Rc::get_mut(&mut c).unwrap()).set_id_tmp(); + for c in components.iter_mut() { + (*Rc::get_mut(c).unwrap()).set_id_tmp(); } let _ = gui.editor.insert(Editor::gui(components, &gui.path)); gui.editor_use = true; diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index 749b30d3..82b1b9ec 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -72,11 +72,11 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { }; for c in e.library.store.iter() { let size = c.size(); - padding.y = padding.y - e.scale * size.min.y; + padding.y -= e.scale * size.min.y; let r_vec = c .render(ui, None, padding, e.scale, clip_rect, e.editor_mode) .unwrap(); - let rect = r_vec[0].rect.clone(); + let rect = r_vec[0].rect; for resp in r_vec { // Create new component if resp.drag_started_by(PointerButton::Primary) { @@ -108,7 +108,7 @@ pub fn add_comp_to_editor(e: &mut Editor) { let id = unique_component_name(&id_ports, "p"); Rc::new(Probe::new(id.as_str(), (0.0, 0.0), e.dummy_input.clone())) } - "add" | _ => { + "add" => { let id = unique_component_name(&id_ports, "add"); Rc::new(Add::new( id.as_str(), @@ -117,6 +117,7 @@ pub fn add_comp_to_editor(e: &mut Editor) { e.dummy_input.clone(), )) } + _ => todo!(), }; Rc::::get_mut(&mut comp) .unwrap() From db9c50cccd2979de8f3bd38154a9bc613215e593 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 14:10:39 +0200 Subject: [PATCH 21/58] Missed one merge conflict... --- src/gui_vizia/gui.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/gui_vizia/gui.rs b/src/gui_vizia/gui.rs index e957a9ed..928d6442 100644 --- a/src/gui_vizia/gui.rs +++ b/src/gui_vizia/gui.rs @@ -111,14 +111,8 @@ impl GuiData { } } -<<<<<<< HEAD pub fn gui(cs: ComponentStore, path: &PathBuf) { - let mut clock = 0; - let simulator = Simulator::new(cs, &mut clock); -======= -pub fn gui(cs: &ComponentStore, path: &PathBuf) { let simulator = Simulator::new(cs); ->>>>>>> upstream/master let path = path.to_owned(); simulator.save_dot(&path); From 79288e60233ec84137be4728e00e77c8f9b04440 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 14:33:07 +0200 Subject: [PATCH 22/58] apparently there was a new component added, but not for egui --- src/components/probe_stim.rs | 2 +- src/gui_egui/components/mod.rs | 1 + src/gui_egui/components/probe_stim.rs | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/gui_egui/components/probe_stim.rs diff --git a/src/components/probe_stim.rs b/src/components/probe_stim.rs index a49d0ee6..d1611f59 100644 --- a/src/components/probe_stim.rs +++ b/src/components/probe_stim.rs @@ -61,7 +61,7 @@ mod test { store: vec![ProbeStim::rc_new("stim", (0.0, 0.0), vec![0, 1, 2, 3])], }; - let mut simulator = Simulator::new(&cs); + let mut simulator = Simulator::new(cs); // output let out = &Input::new("stim", "out"); diff --git a/src/gui_egui/components/mod.rs b/src/gui_egui/components/mod.rs index 0cc21c5a..a03e894b 100644 --- a/src/gui_egui/components/mod.rs +++ b/src/gui_egui/components/mod.rs @@ -5,6 +5,7 @@ mod mux; mod probe; mod probe_edit; mod probe_out; +mod probe_stim; mod register; mod sext; mod wire; diff --git a/src/gui_egui/components/probe_stim.rs b/src/gui_egui/components/probe_stim.rs new file mode 100644 index 00000000..85caea58 --- /dev/null +++ b/src/gui_egui/components/probe_stim.rs @@ -0,0 +1,19 @@ +use crate::common::{EguiComponent, Simulator}; +use crate::components::ProbeStim; +use crate::gui_egui::editor::EditorMode; +use egui::Rect; + +#[typetag::serde] +impl EguiComponent for ProbeStim { + fn render( + &self, + _ui: &mut egui::Ui, + _simulator: Option<&mut Simulator>, + _offset: egui::Vec2, + _scale: f32, + _clip_rect: Rect, + _editor_mode: EditorMode, + ) -> Option> { + todo!(); + } +} From 21b0c4db44cff49e6708d114676ad05ba3be135b Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 14:47:13 +0200 Subject: [PATCH 23/58] ci :upside_down_smile: --- mips/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mips/src/main.rs b/mips/src/main.rs index bee6a090..3a4530c0 100644 --- a/mips/src/main.rs +++ b/mips/src/main.rs @@ -12,5 +12,5 @@ fn main() { syncrim::gui_vizia::gui(cs, &path); #[cfg(not(any(feature = "gui-vizia", feature = "gui-egui")))] - syncrim::common::Simulator::new(cs, &mut 0); + syncrim::common::Simulator::new(cs); } From ea3bd8b0add30bd560bfb103dbc9b587cfd91de8 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 16:50:45 +0200 Subject: [PATCH 24/58] Fixed various bugs --- src/fern.rs | 4 +++- src/gui_egui/editor.rs | 2 +- src/gui_egui/keymap.rs | 18 ++++++++++-------- src/gui_egui/library.rs | 3 +++ 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/fern.rs b/src/fern.rs index 0c24e37c..eedf3f78 100644 --- a/src/fern.rs +++ b/src/fern.rs @@ -31,7 +31,9 @@ pub fn fern_setup() { .level_for("async_io::driver", LevelFilter::Warn); #[cfg(feature = "gui-egui")] - let f = f.level_for("eframe::native::run", LevelFilter::Info); + let f = f + .level_for("eframe::native::run", LevelFilter::Info) + .level_for("async_io::driver", LevelFilter::Warn); f // Output to stdout, files, and other Dispatch configurations diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index fe42d9f0..21cb5e27 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -269,7 +269,7 @@ impl Editor { pub fn get_component(components: &Components, comp: CloseToComponent) -> Option { for (i, c) in components.iter().enumerate() { - if std::ptr::eq(c, &comp.comp) { + if Rc::ptr_eq(c, &comp.comp) { drop(comp); return Some(i); } diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index e7ffb298..826f008e 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -238,7 +238,6 @@ pub fn file_save_fn(gui: &mut Gui) { } pub fn file_save_as_fn(_gui: &mut Gui) {} pub fn file_editor_toggle_fn(gui: &mut Gui) { - // bug: Switching Editor -> Simulator -> Editor crashes match gui.editor_use { true => { gui.editor_use = false; @@ -249,15 +248,18 @@ pub fn file_editor_toggle_fn(gui: &mut Gui) { } } false => { - let simulator = gui.simulator.take(); - let simulator = simulator.unwrap(); - let mut components = simulator.ordered_components.clone(); - drop(simulator); + let editor_existed: bool = gui.editor.as_mut().is_some(); - for c in components.iter_mut() { - (*Rc::get_mut(c).unwrap()).set_id_tmp(); + let simulator = gui.simulator.take().unwrap(); + let mut components = simulator.ordered_components; + + if !editor_existed { + for c in components.iter_mut() { + (*Rc::get_mut(c).unwrap()).set_id_tmp(); + } + let _ = gui.editor.insert(Editor::gui(components, &gui.path)); } - let _ = gui.editor.insert(Editor::gui(components, &gui.path)); + gui.editor_use = true; } } diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index 82b1b9ec..2782f426 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -122,5 +122,8 @@ pub fn add_comp_to_editor(e: &mut Editor) { Rc::::get_mut(&mut comp) .unwrap() .set_pos((pos.x, pos.y)); + Rc::::get_mut(&mut comp) + .unwrap() + .set_id_tmp(); e.components.push(comp); } From 3244876e3a61e9d061c1934f67ad080b520ea1eb Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 17:13:25 +0200 Subject: [PATCH 25/58] Fixed properties window out of bounds clicking and clippy error --- src/gui_egui/component_ui.rs | 12 ++++++++---- src/gui_egui/components/add.rs | 6 ++++-- src/gui_egui/components/constant.rs | 1 + src/gui_egui/components/probe.rs | 4 +++- src/gui_egui/components/wire.rs | 4 +++- src/gui_egui/editor.rs | 3 +++ 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index 6316ac57..ca0e836b 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -33,8 +33,9 @@ pub fn properties_window

( properties_window: &mut bool, mut f: P, ) where - P: FnMut(&mut Ui), + P: FnMut(&mut Ui) -> bool, { + let mut clicked_dropdown = false; if *properties_window { let resp = Window::new(format!("Properties: {}", id)) .frame(Frame { @@ -50,9 +51,9 @@ pub fn properties_window

( y: (resp.rect.min.y + resp.rect.max.y) / 2f32, }) .show(ui.ctx(), |ui| { - f(ui); + clicked_dropdown = f(ui); }); - if resp.unwrap().response.clicked_elsewhere() { + if !clicked_dropdown && resp.unwrap().response.clicked_elsewhere() { *properties_window = false; } } @@ -80,7 +81,7 @@ pub fn input_selector( ui: &mut Ui, input_port: &mut InputPort, id_ports: &[(crate::common::Id, Ports)], -) { +) -> bool { let mut port_id = input_port.input.id.clone(); let mut port_field = input_port.input.field.clone(); let label_port_id = format!("{}.id", input_port.port_id.clone()); @@ -111,8 +112,11 @@ pub fn input_selector( } }); }); + let clicked_dropdown = input_port.input.id != port_id || input_port.input.field != port_field; + input_port.input.id = port_id; input_port.input.field = port_field; + clicked_dropdown } pub fn input_port( diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 7f0ecf27..21cd36de 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -103,10 +103,12 @@ impl EguiComponent for Add { resp, &mut self.egui_x.properties_window, |ui| { + let mut clicked_dropdown = false; input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); - input_selector(ui, &mut self.a_in, id_ports); - input_selector(ui, &mut self.b_in, id_ports); + clicked_dropdown |= input_selector(ui, &mut self.a_in, id_ports); + clicked_dropdown |= input_selector(ui, &mut self.b_in, id_ports); + clicked_dropdown }, ); diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index b7b52da5..6713da81 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -95,6 +95,7 @@ impl EguiComponent for Constant { _ => (), } */ + false }, ); diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 01e45ae5..d0d0a00e 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -93,9 +93,11 @@ impl EguiComponent for Probe { resp, &mut self.egui_x.properties_window, |ui| { + let mut clicked_dropdown = false; input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); - input_selector(ui, &mut self.input_port, id_ports); + clicked_dropdown |= input_selector(ui, &mut self.input_port, id_ports); + clicked_dropdown }, ); diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 1eb14070..694a118d 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -104,10 +104,12 @@ impl EguiComponent for Wire { resp, &mut self.egui_x.properties_window, |ui| { + let mut clicked_dropdown = false; input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos[i]); pos_slider(ui, &mut self.pos[i + 1]); - input_selector(ui, &mut self.input_port, id_ports); + clicked_dropdown |= input_selector(ui, &mut self.input_port, id_ports); + clicked_dropdown }, ); } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 21cb5e27..b89e314f 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -269,6 +269,9 @@ impl Editor { pub fn get_component(components: &Components, comp: CloseToComponent) -> Option { for (i, c) in components.iter().enumerate() { + // doing std::ptr::eq doesn't work and this works so I'm going to keep it + // even if clippy errors on it + #[deny(clippy::vtable_address_comparisons)] if Rc::ptr_eq(c, &comp.comp) { drop(comp); return Some(i); From d3978d72cdbce1a5c8f896c407860ac7a2c0fe9c Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 17:18:56 +0200 Subject: [PATCH 26/58] Auto-save when switching between editor and simulator mode --- src/gui_egui/keymap.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 826f008e..2cb6f2fd 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -238,6 +238,8 @@ pub fn file_save_fn(gui: &mut Gui) { } pub fn file_save_as_fn(_gui: &mut Gui) {} pub fn file_editor_toggle_fn(gui: &mut Gui) { + // Auto-save + file_save_fn(gui); match gui.editor_use { true => { gui.editor_use = false; From b809dad2f78eb182be2916adb840c594f6a35ff1 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 17:29:15 +0200 Subject: [PATCH 27/58] Fixed setting constant value, mixed up keyword for clippy so fixed it --- src/gui_egui/component_ui.rs | 1 + src/gui_egui/components/constant.rs | 12 +++--------- src/gui_egui/editor.rs | 2 +- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index ca0e836b..d25b4009 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -77,6 +77,7 @@ pub fn pos_slider(ui: &mut Ui, pos: &mut (f32, f32)) { ); }); } + pub fn input_selector( ui: &mut Ui, input_port: &mut InputPort, diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 6713da81..2b99b8db 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,4 +1,4 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Ports, Signal, SignalUnsigned, Simulator}; use crate::components::Constant; use crate::gui_egui::component_ui::{input_port, pos_slider, properties_window, rect_with_hover}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; @@ -86,15 +86,9 @@ impl EguiComponent for Constant { |ui| { input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); - // todo: Fix this - /* - match &mut self.value { - Signal::Data(d) => { - ui.add(egui::Slider::new(&mut d, u32::MIN..=u32::MAX).text("value")); - } - _ => (), + if let Signal::Data(d) = &mut self.value { + ui.add(egui::Slider::new(d, u32::MIN..=u32::MAX).text("value")); } - */ false }, ); diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index b89e314f..66dd2a38 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -271,7 +271,7 @@ pub fn get_component(components: &Components, comp: CloseToComponent) -> Option< for (i, c) in components.iter().enumerate() { // doing std::ptr::eq doesn't work and this works so I'm going to keep it // even if clippy errors on it - #[deny(clippy::vtable_address_comparisons)] + #[allow(clippy::vtable_address_comparisons)] if Rc::ptr_eq(c, &comp.comp) { drop(comp); return Some(i); From 5a5a04411e62b87fc945c491f9888f45e3303a3f Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 17:57:28 +0200 Subject: [PATCH 28/58] Added loading functionality --- src/gui_egui/keymap.rs | 36 ++++++++++++++++++++++++++++++------ src/gui_egui/menu.rs | 2 +- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 2cb6f2fd..d8c02132 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -1,7 +1,10 @@ use crate::common::{ComponentStore, Simulator}; -use crate::gui_egui::editor::EditorMode; -use crate::gui_egui::{editor::Editor, Gui}; +use crate::gui_egui::editor::{Editor, EditorMode}; +use crate::gui_egui::editor_wire_mode::reset_wire_mode; +use crate::gui_egui::library::reset_input_mode; +use crate::gui_egui::Gui; use egui::{Key, KeyboardShortcut, Modifiers}; +use rfd::FileDialog; use std::{path::PathBuf, rc::Rc}; #[derive(Copy, Clone)] @@ -219,7 +222,28 @@ impl Shortcuts { } pub fn file_new_fn(_gui: &mut Gui) {} -pub fn file_open_fn(_gui: &mut Gui) {} +pub fn file_open_fn(gui: &mut Gui) { + let files = FileDialog::new().add_filter("json", &["json"]).pick_file(); + let mut path = PathBuf::default(); + if let Some(path_buf) = files { + path = path_buf; + } + let cs = ComponentStore::load_file(&path); + match gui.editor_use { + true => { + if let Some(e) = gui.editor.as_mut() { + // Clear all references + reset_wire_mode(&mut e.wm); + reset_input_mode(&mut e.im); + e.components = cs.store; + } + } + false => { + let _ = gui.simulator.take(); + gui.simulator = Some(Simulator::new(cs)); + } + } +} pub fn file_save_fn(gui: &mut Gui) { match gui.editor_use { true => { @@ -341,14 +365,14 @@ pub fn editor_wire_mode_fn(gui: &mut Gui) { editor.editor_mode = EditorMode::Default; } } - crate::gui_egui::editor_wire_mode::reset_wire_mode(&mut editor.wm); + reset_wire_mode(&mut editor.wm); } } pub fn editor_escape_fn(gui: &mut Gui) { if gui.editor_use { let editor = gui.editor.as_mut().unwrap(); editor.editor_mode = EditorMode::Default; - crate::gui_egui::editor_wire_mode::reset_wire_mode(&mut editor.wm); - crate::gui_egui::library::reset_input_mode(&mut editor.im); + reset_wire_mode(&mut editor.wm); + reset_input_mode(&mut editor.im); } } diff --git a/src/gui_egui/menu.rs b/src/gui_egui/menu.rs index 7186439f..4141dc8f 100644 --- a/src/gui_egui/menu.rs +++ b/src/gui_egui/menu.rs @@ -59,7 +59,7 @@ fn btn(ui: &mut egui::Ui, name: &str, keys: egui::KeyboardShortcut) -> egui::Res fn shared_buttons_file(gui: &mut Gui, ui: &mut Ui) { ui.menu_button("File", |ui| { - if btn(ui, "File", gui.shortcuts.file_new).clicked() { + if btn(ui, "New", gui.shortcuts.file_new).clicked() { keymap::file_new_fn(gui); } if btn(ui, "Open", gui.shortcuts.file_open).clicked() { From db61e9b64813fdef709fb0a5b266f50d388130ff Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 25 Jul 2023 18:05:15 +0200 Subject: [PATCH 29/58] Added open/save/save as --- src/gui_egui/gui.rs | 2 -- src/gui_egui/keymap.rs | 15 ++++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index 3355de39..2e0abc16 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -8,7 +8,6 @@ pub struct Gui { pub simulator: Option, pub path: PathBuf, // History, acts like a stack - pub history: Vec>, pub scale: f32, // When the ui elements change size pub ui_change: bool, @@ -30,7 +29,6 @@ pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { let gui = Gui { path, simulator: Some(simulator), - history: vec![], scale: 1.0f32, ui_change: true, offset: egui::Vec2 { x: 0f32, y: 0f32 }, diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index d8c02132..7711345a 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -224,11 +224,10 @@ impl Shortcuts { pub fn file_new_fn(_gui: &mut Gui) {} pub fn file_open_fn(gui: &mut Gui) { let files = FileDialog::new().add_filter("json", &["json"]).pick_file(); - let mut path = PathBuf::default(); if let Some(path_buf) = files { - path = path_buf; + gui.path = path_buf; } - let cs = ComponentStore::load_file(&path); + let cs = ComponentStore::load_file(&gui.path); match gui.editor_use { true => { if let Some(e) = gui.editor.as_mut() { @@ -251,7 +250,7 @@ pub fn file_save_fn(gui: &mut Gui) { ComponentStore { store: e.components.clone(), } - .save_file(&PathBuf::from("file.json")) + .save_file(&gui.path) } } false => ComponentStore { @@ -260,7 +259,13 @@ pub fn file_save_fn(gui: &mut Gui) { .save_file(&PathBuf::from("file.json")), } } -pub fn file_save_as_fn(_gui: &mut Gui) {} +pub fn file_save_as_fn(gui: &mut Gui) { + let files = FileDialog::new().add_filter("json", &["json"]).save_file(); + if let Some(path_buf) = files { + gui.path = path_buf; + file_save_fn(gui); + } +} pub fn file_editor_toggle_fn(gui: &mut Gui) { // Auto-save file_save_fn(gui); From cb56b50612a7b20a258e279af56ca5875d57fa8c Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Wed, 26 Jul 2023 16:46:10 +0200 Subject: [PATCH 30/58] Fixed numerous issues with wires --- src/common.rs | 15 +- src/gui_egui/components/wire.rs | 23 +-- src/gui_egui/editor.rs | 11 +- src/gui_egui/editor_wire_mode.rs | 240 +++++++++++++++++++++---------- src/gui_egui/gui.rs | 6 +- src/gui_egui/helper.rs | 15 +- src/gui_egui/menu.rs | 4 +- 7 files changed, 212 insertions(+), 102 deletions(-) diff --git a/src/common.rs b/src/common.rs index f871d4a0..dc8b7fc0 100644 --- a/src/common.rs +++ b/src/common.rs @@ -101,7 +101,9 @@ pub trait Component { /// returns the (id, Ports) of the component fn get_id_ports(&self) -> (Id, Ports); - fn set_id_port(&mut self, _target_port_id: Id, _new_input: Input) {} + fn set_id_port(&mut self, _target_port_id: Id, _new_input: Input) { + todo!("Set set_id_port for this Component"); + } /// evaluate component based on current internal state fn clock(&self, _simulator: &mut Simulator) {} @@ -160,15 +162,20 @@ pub trait EguiComponent: Component { /// Get ports location relative to self, (inputs, outputs) fn ports_location(&self) -> Vec<(Id, egui::Pos2)> { - vec![] + todo!("Create ports_location for this EguiComponent"); } fn snap_priority(&self) -> SnapPriority { SnapPriority::Default } - fn set_pos(&mut self, _pos: (f32, f32)) {} - fn set_id_tmp(&mut self) {} + fn set_pos(&mut self, _pos: (f32, f32)) { + todo!("Create set_pos for this EguiComponent"); + } + + fn set_id_tmp(&mut self) { + todo!("Create set_id_tmp for this EguiComponent"); + } } #[cfg(feature = "gui-egui")] diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 694a118d..5eae5ebb 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -1,4 +1,4 @@ -use crate::common::{EguiComponent, Ports, Simulator}; +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; use crate::components::Wire; use crate::gui_egui::component_ui::{ input_port, input_selector, pos_slider, properties_window, rect_with_hover, @@ -12,7 +12,7 @@ impl EguiComponent for Wire { fn render( &self, ui: &mut Ui, - _simulator: Option<&mut Simulator>, + simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, clip_rect: Rect, @@ -54,18 +54,19 @@ impl EguiComponent for Wire { let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); - /* match &simulator { - Some(s) => ui.label({ - let r: Result = self.input_port.try_into(); - match r { - Ok(data) => format!("{:#x}", data), - _ => format!("{:?}", value), - } - }), + Some(s) => { + ui.label({ + let r: Result = + s.get_input_val(&self.input_port.input).try_into(); + match r { + Ok(data) => format!("{:#x}", data), + _ => format!("{:?}", r), + } + }); + } _ => (), } - */ }); r_vec.push(r); } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 66dd2a38..88d208cd 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -3,7 +3,7 @@ use crate::components::*; use crate::gui_egui::{ editor_wire_mode::WireMode, gui::Gui, - helper::{id_ports_of_all_components, offset_helper}, + helper::{id_ports_of_all_components_non_wires, offset_helper}, keymap, library::InputMode, menu::Menu, @@ -34,6 +34,7 @@ pub struct CloseToComponent { pub pos: Pos2, pub dist: f32, pub port_id: Id, + pub potential_actual_input: Option, } #[derive(Debug, Clone, Copy)] @@ -138,8 +139,10 @@ impl Editor { egui::TopBottomPanel::top("topBarEditor").show(ctx, |ui| { Menu::new_editor(ui, gui); }); - Editor::library(ctx, gui); - Editor::draw_area(ctx, gui, frame); + if gui.editor_use { + Editor::library(ctx, gui); + Editor::draw_area(ctx, gui, frame); + } } } @@ -206,7 +209,7 @@ impl Editor { } let e = Editor::gui_to_editor(gui); - let id_ports = id_ports_of_all_components(&e.components); + let id_ports = id_ports_of_all_components_non_wires(&e.components); // The reason we do this is because some of the input modes requires references to // components, but that makes us unable to get the mutable reference to it // (We can only get a mutable reference if only ONE reference to it exists) diff --git a/src/gui_egui/editor_wire_mode.rs b/src/gui_egui/editor_wire_mode.rs index d3366c4c..6979f6ab 100644 --- a/src/gui_egui/editor_wire_mode.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -1,4 +1,4 @@ -use crate::common::{Components, EguiComponent, Id, Input}; +use crate::common::{Components, Id, Input}; use crate::components::Wire; use crate::gui_egui::editor::SnapPriority; use crate::gui_egui::editor::{get_component, CloseToComponent, Editor}; @@ -6,7 +6,9 @@ use crate::gui_egui::helper::{ id_ports_of_all_components, offset_helper, offset_reverse_helper, offset_reverse_helper_pos2, unique_component_name, }; -use egui::{Color32, Context, CursorIcon, LayerId, PointerButton, Pos2, Response, Shape, Stroke}; +use egui::{ + Color32, Context, CursorIcon, LayerId, PointerButton, Pos2, Response, Shape, Stroke, Vec2, +}; use std::rc::Rc; pub struct WireMode { @@ -19,34 +21,37 @@ pub struct WireMode { } pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { - e.wm.mode_ended = false; ctx.input_mut(|i| { let origin = i.pointer.press_origin().unwrap(); e.wm.cursor_location = origin; let offset_cursor_scale = offset_reverse_helper_pos2(origin, e.scale, e.offset_and_pan); - let (closest, _closest_wire) = + let (closest, closest_wire) = clicked_close_to_input_output(offset_cursor_scale, &e.components); - let closest_uw = closest.unwrap(); - - // First click ALWAYS has to start at a port so we force it - if e.wm.temp_positions.is_empty() { - // requires at least one component on the canvas - let new_pos = closest_uw.pos; - e.wm.start_comp_port = Some(closest_uw); - let new_pos = offset_helper((new_pos.x, new_pos.y), e.scale, e.offset_and_pan); - e.wm.temp_positions.push((new_pos.x, new_pos.y)); - - // We clicked close to a port so this will be the last click done - } else if !e.wm.temp_positions.is_empty() && closest_uw.dist <= 10.0f32 { - // We should finish the component - last_click(e, closest_uw); - - // Click somewhere not near a component - } else { - let mut wires = - wire_split_into_two_vec(*e.wm.temp_positions.last().unwrap(), (origin.x, origin.y)); - e.wm.temp_positions.append(&mut wires) + + match get_closest_component_non_wire_prio(closest, closest_wire, 10f32) { + Some(closest_uw) => { + if e.wm.temp_positions.is_empty() { + // New Component + e.wm.mode_ended = false; + let new_pos = closest_uw.pos; + e.wm.start_comp_port = Some(closest_uw); + let new_pos = offset_helper((new_pos.x, new_pos.y), e.scale, e.offset_and_pan); + e.wm.temp_positions.push((new_pos.x, new_pos.y)); + } else { + // Continue existing component + last_click(e, closest_uw); + } + } + None => { + if !e.wm.temp_positions.is_empty() { + let mut wires = wire_split_into_two_vec( + *e.wm.temp_positions.last().unwrap(), + (origin.x, origin.y), + ); + e.wm.temp_positions.append(&mut wires) + } + } } }); } @@ -54,10 +59,9 @@ pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { let in_c = e.wm.start_comp_port.take().unwrap(); let out_c = closest_uw; - let (field_name, input, is_comp_start) = - get_outputs_from_port(&in_c.port_id, &in_c.comp, &out_c.port_id, &out_c.comp); - match input { - Some(i) => { + let (field_name, input_and_bool) = get_outputs_from_port(&in_c, &out_c); + match input_and_bool { + Some((i, is_input_in_comp_start)) => { let id_ports = id_ports_of_all_components(&e.components); let id = unique_component_name(&id_ports, "w"); let id = id.as_str(); @@ -74,18 +78,25 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { wire_split_into_two_vec((last_pos.x, last_pos.y), (out_c.pos.x, out_c.pos.y)); pos_v.append(&mut v); - e.components.push(Rc::new(Wire::new(id, pos_v, i.clone()))); - // Now actually set the input of the wired component - let comp = if is_comp_start { in_c } else { out_c }; - if let Some(c) = get_component(&e.components, comp) { - Rc::get_mut(&mut e.components[c]) - .unwrap() - .set_id_port(field_name, i); + #[allow(clippy::vtable_address_comparisons)] + if !Rc::ptr_eq(&in_c.comp, &out_c.comp) { + let comp = if is_input_in_comp_start { out_c } else { in_c }; + println!("comp: {:?}", comp.port_id); + e.components.push(Rc::new(Wire::new(id, pos_v, i.clone()))); + if let Some(c) = get_component(&e.components, comp) { + println!("setting id_port"); + + Rc::get_mut(&mut e.components[c]) + .unwrap() + .set_id_port(field_name, i); + } + } else { + println!("You cannot connect a wire to itself"); } } None => { - println!("Seems like you don't have an input at the start or end of the wire"); + println!("Seems like you don't exactly have one input at the start or end of the wire"); } } reset_wire_mode(&mut e.wm); @@ -98,8 +109,7 @@ pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option< drag_started(ctx, e, cpr); } else { if cpr.drag_started_by(PointerButton::Secondary) { - // place wire end - // This should also occur when pressing an input/output after the first one + // abort wire mode reset_wire_mode(&mut e.wm); } @@ -109,26 +119,23 @@ pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option< }); let offset_cursor_scale = offset_reverse_helper_pos2(e.wm.cursor_location, e.scale, e.offset_and_pan); - let (closest, _closest_wire) = + let (closest, closest_wire) = clicked_close_to_input_output(offset_cursor_scale, &e.components); - let wire_shown_location = match closest { - Some(c) => { - if c.dist <= 10.0f32 { - // We are close enough to move the shown wire to here instead - c.pos + e.offset_and_pan - } else { - e.wm.cursor_location - } - } - None => e.wm.cursor_location, - }; + // Here we prioritize component ports over wires in a 10f32 range + let wire_shown_location = get_location_of_port_or_wire_inside_radius( + closest, + closest_wire, + 10f32, + e.wm.cursor_location, + e.offset_and_pan, + ); let v = wire_split_into_two_vec( *e.wm.temp_positions.last().unwrap(), (wire_shown_location.x, wire_shown_location.y), ); - let mut draw_vec: Vec = vec![]; // = s.wm.temp_positions.clone(); + let mut draw_vec: Vec = vec![]; for (posx, posy) in e.wm.temp_positions.clone().into_iter().chain(v.into_iter()) { draw_vec.push(Pos2::new(posx, posy)) } @@ -140,6 +147,9 @@ pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option< color: Color32::BLACK, }, )); + } else { + // todo: Marker that you are potientially close to connecting to something to start a wire + // here, like a circle or similar over the port } } } @@ -177,32 +187,57 @@ pub fn reset_wire_mode(wm: &mut WireMode) { /// returns an input made from the output pub fn get_outputs_from_port( - port_id_start: &Id, - comp_start: &Rc, - port_id_end: &Id, - comp_end: &Rc, -) -> (Id, Option, bool) { - let (id, ports_start) = comp_start.get_id_ports(); - for port_id in ports_start.outputs { - if port_id == *port_id_start { - return ( - port_id_end.clone(), - Some(Input { id, field: port_id }), - false, - ); - } - } - let (id, ports_end) = comp_end.get_id_ports(); - for port_id in ports_end.outputs { - if port_id == *port_id_end { - return ( - port_id_start.clone(), - Some(Input { id, field: port_id }), - true, - ); - } + comp_start: &CloseToComponent, + comp_end: &CloseToComponent, +) -> (Id, Option<(Input, bool)>) { + let out_start: Option = match &comp_start.potential_actual_input { + Some(i) => Some(i.clone()), + None => match comp_start.potential_actual_input.clone() { + Some(s) => Some(s), + None => { + let mut o = None; + let (id, ports_start) = comp_start.comp.get_id_ports(); + for port_id in ports_start.outputs { + if port_id == *comp_start.port_id { + o = Some(Input { + id: id.clone(), + field: port_id, + }); + } + } + o + } + }, + }; + let out_end: Option = match &comp_end.potential_actual_input { + Some(i) => Some(i.clone()), + None => match comp_end.potential_actual_input.clone() { + Some(s) => Some(s), + None => { + let mut o = None; + let (id, ports_end) = comp_end.comp.get_id_ports(); + for port_id in ports_end.outputs { + if port_id == *comp_end.port_id { + o = Some(Input { + id: id.clone(), + field: port_id, + }); + } + } + o + } + }, + }; + match out_start { + Some(s) => match out_end { + Some(_) => (String::new(), None), + None => (comp_end.port_id.clone(), Some((s, true))), + }, + None => match out_end { + Some(e) => (comp_start.port_id.clone(), Some((e, false))), + None => (String::new(), None), + }, } - (String::new(), None, false) } /// returns (Component, Wire) @@ -220,15 +255,20 @@ pub fn clicked_close_to_input_output( _ => &mut closest, }; for (port_id, pos) in ports { + let dist = clicked_pos.distance(pos); + let potential_actual_input = match comp.snap_priority() { + SnapPriority::Wire => Some(comp.get_id_ports().1.inputs[0].input.clone()), + _ => None, + }; match clos.as_ref() { Some(c) => { - let dist = clicked_pos.distance(pos); if dist < c.dist { *clos = Some(CloseToComponent { comp: comp.clone(), pos, dist, port_id, + potential_actual_input, }) } } @@ -236,8 +276,9 @@ pub fn clicked_close_to_input_output( *clos = Some(CloseToComponent { comp: comp.clone(), pos, - dist: clicked_pos.distance(pos), + dist, port_id, + potential_actual_input, }) } }; @@ -246,3 +287,46 @@ pub fn clicked_close_to_input_output( (closest, closest_wire) } + +pub fn get_closest_component_non_wire_prio( + port: Option, + wire: Option, + distance: f32, +) -> Option { + fn is_wire_in_range(wire: Option, distance: f32) -> Option { + match wire { + Some(w) => { + if w.dist <= distance { + Some(w) + } else { + None + } + } + None => None, + } + } + + match port { + Some(p) => { + if p.dist <= distance { + Some(p) + } else { + is_wire_in_range(wire, distance) + } + } + None => None, + } +} + +pub fn get_location_of_port_or_wire_inside_radius( + port: Option, + wire: Option, + distance: f32, + cursor_location: Pos2, + offset: Vec2, +) -> Pos2 { + match get_closest_component_non_wire_prio(port, wire, distance) { + Some(c) => c.pos + offset, + None => cursor_location, + } +} diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index 2e0abc16..d741a7b6 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -80,8 +80,10 @@ impl eframe::App for Gui { egui::Context::request_repaint(ctx); } else { self.top_bar(ctx); - self.side_panel(ctx); - self.draw_area(ctx, frame); + if self.simulator.is_some() { + self.side_panel(ctx); + self.draw_area(ctx, frame); + } } } } diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index f258f96f..8badc906 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -1,5 +1,5 @@ use crate::common::{Components, Ports}; -use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::editor::{EditorMode, SnapPriority}; use egui::{Pos2, Rect, Sense, Vec2}; pub fn offset_reverse_helper_pos2(xy: Pos2, scale: f32, offset: Vec2) -> Pos2 { @@ -69,7 +69,18 @@ pub fn unique_component_name(id_ports: &[(crate::common::Id, Ports)], id: &str) pub fn id_ports_of_all_components(cs: &Components) -> Vec<(crate::common::Id, Ports)> { let mut v = vec![]; for c in cs.iter() { - v.push(c.get_id_ports()) + v.push(c.get_id_ports()); + } + v +} + +pub fn id_ports_of_all_components_non_wires(cs: &Components) -> Vec<(crate::common::Id, Ports)> { + let mut v = vec![]; + for c in cs.iter() { + match c.snap_priority() { + SnapPriority::Wire => (), + _ => v.push(c.get_id_ports()), + } } v } diff --git a/src/gui_egui/menu.rs b/src/gui_egui/menu.rs index 4141dc8f..0e16c2ce 100644 --- a/src/gui_egui/menu.rs +++ b/src/gui_egui/menu.rs @@ -32,7 +32,9 @@ impl Menu { if ui.button("⏸").clicked() { keymap::control_pause_fn(gui); } - ui.label(format!("Cycle #{}", gui.simulator.as_ref().unwrap().cycle)); + if let Some(s) = gui.simulator.as_ref() { + ui.label(format!("Cycle #{}", s.cycle)); + } }); } From 1f810715678beccbc82cd1f9de381f42f693c94f Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Wed, 26 Jul 2023 16:51:26 +0200 Subject: [PATCH 31/58] clippy --- src/gui_egui/components/wire.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 5eae5ebb..7cd9f976 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -54,18 +54,15 @@ impl EguiComponent for Wire { let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); - match &simulator { - Some(s) => { - ui.label({ - let r: Result = - s.get_input_val(&self.input_port.input).try_into(); - match r { - Ok(data) => format!("{:#x}", data), - _ => format!("{:?}", r), - } - }); - } - _ => (), + if let Some(s) = &simulator { + ui.label({ + let r: Result = + s.get_input_val(&self.input_port.input).try_into(); + match r { + Ok(data) => format!("{:#x}", data), + _ => format!("{:?}", r), + } + }); } }); r_vec.push(r); From 5cc773d3548e3f9a0cee23039598f346488fc01f Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Wed, 26 Jul 2023 21:04:30 +0200 Subject: [PATCH 32/58] Massve rework #3 or 4, don't remember --- examples/add.rs | 49 ++++--- examples/add_edit.rs | 53 +++---- examples/add_mux.rs | 190 +++++++++++++------------- examples/add_reg.rs | 112 +++++++-------- examples/add_reg_compound_wire.rs | 72 +++++----- examples/data_mem.rs | 144 ++++++++++--------- examples/mux.rs | 116 +++++++++------- examples/probe_edit.rs | 14 +- examples/reg.rs | 36 ++--- examples/sext.rs | 40 +++--- mips/examples/mips.rs | 154 +++++++++++---------- mips/examples/reg_file.rs | 32 +++-- mips/src/components/instr_mem.rs | 28 ++-- mips/src/components/reg_file.rs | 116 +++++++--------- src/common.rs | 17 ++- src/components/add.rs | 66 ++++----- src/components/constant.rs | 12 +- src/components/mem.rs | 168 +++++++++-------------- src/components/mux.rs | 58 +++----- src/components/probe.rs | 24 ++-- src/components/probe_edit.rs | 11 +- src/components/register.rs | 30 ++-- src/components/sext.rs | 68 ++++----- src/components/wire.rs | 28 +--- src/gui_egui/component_ui.rs | 22 +-- src/gui_egui/components/add.rs | 54 ++++++-- src/gui_egui/components/constant.rs | 33 +++-- src/gui_egui/components/mux.rs | 4 +- src/gui_egui/components/probe.rs | 39 ++++-- src/gui_egui/components/probe_edit.rs | 2 + src/gui_egui/components/probe_out.rs | 2 + src/gui_egui/components/probe_stim.rs | 2 + src/gui_egui/components/register.rs | 2 + src/gui_egui/components/sext.rs | 2 + src/gui_egui/components/wire.rs | 39 ++++-- src/gui_egui/editor.rs | 65 +++++---- src/gui_egui/editor_wire_mode.rs | 18 ++- src/gui_egui/gui.rs | 32 ++++- src/gui_egui/keymap.rs | 11 +- src/gui_egui/library.rs | 56 ++++++-- src/gui_egui/mod.rs | 2 +- src/gui_vizia/components/mux.rs | 2 +- src/gui_vizia/components/probe.rs | 2 +- src/main.rs | 1 - 44 files changed, 1057 insertions(+), 971 deletions(-) diff --git a/examples/add.rs b/examples/add.rs index ea1ba898..9525bb04 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -9,30 +9,35 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Add::new( - "add", - (200.0, 120.0), - Input::new("c1", "out"), - Input::new("c2", "out"), - )), + Rc::new(Add { + id: "add".to_string(), + pos: (200.0, 120.0), + a_in: Input::new("c1", "out"), + + b_in: Input::new("c2", "out"), + }), Constant::rc_new("c1", (60.0, 100.0), 3), Constant::rc_new("c2", (60.0, 140.0), 4), - Rc::new(Wire::new( - "w1", - vec![(110.0, 100.0), (180.0, 100.0)], - Input::new("c1", "out"), - )), - Rc::new(Wire::new( - "w2", - vec![(110.0, 140.0), (180.0, 140.0)], - Input::new("c2", "out"), - )), - Rc::new(Wire::new( - "w3", - vec![(220.0, 120.0), (260.0, 120.0)], - Input::new("add", "out"), - )), - Rc::new(Probe::new("p1", (270.0, 120.0), Input::new("add", "out"))), + Rc::new(Wire { + id: "w1".to_string(), + pos: vec![(110.0, 100.0), (180.0, 100.0)], + input: Input::new("c1", "out"), + }), + Rc::new(Wire { + id: "w2".to_string(), + pos: vec![(110.0, 140.0), (180.0, 140.0)], + input: Input::new("c2", "out"), + }), + Rc::new(Wire { + id: "w3".to_string(), + pos: vec![(220.0, 120.0), (260.0, 120.0)], + input: Input::new("add", "out"), + }), + Rc::new(Probe { + id: "p1".to_string(), + pos: (270.0, 120.0), + input: Input::new("add", "out"), + }), ], }; diff --git a/examples/add_edit.rs b/examples/add_edit.rs index 8816e4f3..11761cb6 100644 --- a/examples/add_edit.rs +++ b/examples/add_edit.rs @@ -9,30 +9,35 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Add::new( - "add", - (200.0, 120.0), - Input::new("c1", "out"), - Input::new("c2", "out"), - )), + Rc::new(Add { + id: "add".to_string(), + pos: (200.0, 120.0), + a_in: Input::new("c1", "out"), + + b_in: Input::new("c2", "out"), + }), Rc::new(ProbeEdit::new("c1", (60.0, 100.0))), Rc::new(ProbeEdit::new("c2", (60.0, 140.0))), - Rc::new(Wire::new( - "w1", - vec![(110.0, 100.0), (180.0, 100.0)], - Input::new("c1", "out"), - )), - Rc::new(Wire::new( - "w2", - vec![(110.0, 140.0), (180.0, 140.0)], - Input::new("c2", "out"), - )), - Rc::new(Wire::new( - "w3", - vec![(220.0, 120.0), (260.0, 120.0)], - Input::new("add", "out"), - )), - Rc::new(Probe::new("p1", (270.0, 120.0), Input::new("add", "out"))), + Rc::new(Wire { + id: "w1".to_string(), + pos: vec![(110.0, 100.0), (180.0, 100.0)], + input: Input::new("c1", "out"), + }), + Rc::new(Wire { + id: "w2".to_string(), + pos: vec![(110.0, 140.0), (180.0, 140.0)], + input: Input::new("c2", "out"), + }), + Rc::new(Wire { + id: "w3".to_string(), + pos: vec![(220.0, 120.0), (260.0, 120.0)], + input: Input::new("add", "out"), + }), + Rc::new(Probe { + id: "p1".to_string(), + pos: (270.0, 120.0), + input: Input::new("add", "out"), + }), ], }; @@ -40,8 +45,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path).ok(); + syncrim::gui_egui::gui(&cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(cs, &path); + syncrim::gui_vizia::gui(&cs, &path); } diff --git a/examples/add_mux.rs b/examples/add_mux.rs index 16afb9df..28cb52ea 100644 --- a/examples/add_mux.rs +++ b/examples/add_mux.rs @@ -9,109 +9,113 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Add::new( - "add", - (200.0, 120.0), - Input::new("c", "out"), - Input::new("r1", "out"), - )), + Rc::new(Add { + id: "add".to_string(), + pos: (200.0, 120.0), + a_in: Input::new("c", "out"), + b_in: Input::new("r1", "out"), + }), Constant::rc_new("c", (100.0, 100.0), 1), - Rc::new(Register::new( - "r1", - (100.0, 140.0), - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "w1", - vec![(110.0, 100.0), (180.0, 100.0)], - Input::new("c", "out"), - )), - Rc::new(Wire::new( - "w2", - vec![(110.0, 140.0), (180.0, 140.0)], - Input::new("r1", "out"), - )), - Rc::new(Wire::new( - "w3", - vec![(220.0, 120.0), (260.0, 120.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "w4", - vec![(260.0, 120.0), (260.0, 180.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "w5", - vec![(60.0, 180.0), (260.0, 180.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "w6", - vec![(60.0, 140.0), (60.0, 180.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "w7", - vec![(60.0, 140.0), (90.0, 140.0)], - Input::new("add", "out"), - )), - Rc::new(Probe::new( - "p_add", - (280.0, 120.0), - Input::new("add", "out"), - )), - Rc::new(Probe::new("p_reg", (130.0, 120.0), Input::new("r1", "out"))), - Rc::new(Mux::new( - "mux", - (270.0, 300.0), - Input::new("add", "out"), - vec![ + Rc::new(Register { + id: "r1".to_string(), + pos: (100.0, 140.0), + r_in: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "w1".to_string(), + pos: vec![(110.0, 100.0), (180.0, 100.0)], + input: Input::new("c", "out"), + }), + Rc::new(Wire { + id: "w2".to_string(), + pos: vec![(110.0, 140.0), (180.0, 140.0)], + input: Input::new("r1", "out"), + }), + Rc::new(Wire { + id: "w3".to_string(), + pos: vec![(220.0, 120.0), (260.0, 120.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "w4".to_string(), + pos: vec![(260.0, 120.0), (260.0, 180.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "w5".to_string(), + pos: vec![(60.0, 180.0), (260.0, 180.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "w6".to_string(), + pos: vec![(60.0, 140.0), (60.0, 180.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "w7".to_string(), + pos: vec![(60.0, 140.0), (90.0, 140.0)], + input: Input::new("add", "out"), + }), + Rc::new(Probe { + id: "p_add".to_string(), + pos: (280.0, 120.0), + input: Input::new("add", "out"), + }), + Rc::new(Probe { + id: "p_reg".to_string(), + pos: (130.0, 120.0), + input: Input::new("r1", "out"), + }), + Rc::new(Mux { + id: "mux".to_string(), + pos: (270.0, 300.0), + select: Input::new("add", "out"), + m_in: vec![ Input::new("mc1", "out"), Input::new("mc2", "out"), Input::new("mc3", "out"), Input::new("mc4", "out"), ], - )), + }), Constant::rc_new("mc1", (150.0, 270.0), 0), Constant::rc_new("mc2", (150.0, 290.0), 1), Constant::rc_new("mc3", (150.0, 310.0), 2), Constant::rc_new("mc4", (150.0, 330.0), 3), - Rc::new(Wire::new( - "wm_sel", - vec![(260.0, 180.0), (260.0, 250.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "wm1", - vec![(200.0, 270.0), (250.0, 270.0)], - Input::new("mc1", "out"), - )), - Rc::new(Wire::new( - "wm2", - vec![(200.0, 290.0), (250.0, 290.0)], - Input::new("mc2", "out"), - )), - Rc::new(Wire::new( - "wm3", - vec![(200.0, 310.0), (250.0, 310.0)], - Input::new("mc3", "out"), - )), - Rc::new(Wire::new( - "wm4", - vec![(200.0, 330.0), (250.0, 330.0)], - Input::new("mc4", "out"), - )), - Rc::new(Wire::new( - "wm_o0", - vec![(290.0, 300.0), (340.0, 300.0)], - Input::new("mux", "out"), - )), - Rc::new(Probe::new( - "p_mux", - (350.0, 300.0), - Input::new("mux", "out"), - )), + Rc::new(Wire { + id: "wm_sel".to_string(), + pos: vec![(260.0, 180.0), (260.0, 250.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "wm1".to_string(), + pos: vec![(200.0, 270.0), (250.0, 270.0)], + input: Input::new("mc1", "out"), + }), + Rc::new(Wire { + id: "wm2".to_string(), + pos: vec![(200.0, 290.0), (250.0, 290.0)], + input: Input::new("mc2", "out"), + }), + Rc::new(Wire { + id: "wm3".to_string(), + pos: vec![(200.0, 310.0), (250.0, 310.0)], + input: Input::new("mc3", "out"), + }), + Rc::new(Wire { + id: "wm4".to_string(), + pos: vec![(200.0, 330.0), (250.0, 330.0)], + input: Input::new("mc4", "out"), + }), + Rc::new(Wire { + id: "wm_o0".to_string(), + pos: vec![(290.0, 300.0), (340.0, 300.0)], + input: Input::new("mux", "out"), + }), + Rc::new(Probe { + id: "p_mux".to_string(), + pos: (350.0, 300.0), + input: Input::new("mux", "out"), + }), ], }; diff --git a/examples/add_reg.rs b/examples/add_reg.rs index d8150f2a..0223f337 100644 --- a/examples/add_reg.rs +++ b/examples/add_reg.rs @@ -9,63 +9,63 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Add::new( - "add", - (200.0, 120.0), - Input::new("c", "out"), - Input::new("reg", "out"), - )), + Rc::new(Add { + id: "add".to_string(), + pos: (200.0, 120.0), + a_in: Input::new("c", "out"), + b_in: Input::new("reg", "out"), + }), Constant::rc_new("c", (100.0, 100.0), 3), - Rc::new(Register::new( - "reg", - (100.0, 140.0), - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "w1", - vec![(110.0, 100.0), (180.0, 100.0)], - Input::new("c", "out"), - )), - Rc::new(Wire::new( - "w2", - vec![(110.0, 140.0), (180.0, 140.0)], - Input::new("reg", "out"), - )), - Rc::new(Wire::new( - "w3", - vec![(220.0, 120.0), (260.0, 120.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "w4", - vec![(260.0, 120.0), (260.0, 180.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "w5", - vec![(60.0, 180.0), (260.0, 180.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "w6", - vec![(60.0, 140.0), (60.0, 180.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "w7", - vec![(60.0, 140.0), (90.0, 140.0)], - Input::new("add", "out"), - )), - Rc::new(Probe::new( - "p_add", - (280.0, 120.0), - Input::new("add", "out"), - )), - Rc::new(Probe::new( - "p_reg", - (130.0, 120.0), - Input::new("reg", "out"), - )), + Rc::new(Register { + id: "reg".to_string(), + pos: (100.0, 140.0), + r_in: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "w1".to_string(), + pos: vec![(110.0, 100.0), (180.0, 100.0)], + input: Input::new("c", "out"), + }), + Rc::new(Wire { + id: "w2".to_string(), + pos: vec![(110.0, 140.0), (180.0, 140.0)], + input: Input::new("reg", "out"), + }), + Rc::new(Wire { + id: "w3".to_string(), + pos: vec![(220.0, 120.0), (260.0, 120.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "w4".to_string(), + pos: vec![(260.0, 120.0), (260.0, 180.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "w5".to_string(), + pos: vec![(60.0, 180.0), (260.0, 180.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "w6".to_string(), + pos: vec![(60.0, 140.0), (60.0, 180.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "w7".to_string(), + pos: vec![(60.0, 140.0), (90.0, 140.0)], + input: Input::new("add", "out"), + }), + Rc::new(Probe { + id: "p_add".to_string(), + pos: (280.0, 120.0), + input: Input::new("add", "out"), + }), + Rc::new(Probe { + id: "p_reg".to_string(), + pos: (130.0, 120.0), + input: Input::new("reg", "out"), + }), ], }; diff --git a/examples/add_reg_compound_wire.rs b/examples/add_reg_compound_wire.rs index c7c22bba..f2313948 100644 --- a/examples/add_reg_compound_wire.rs +++ b/examples/add_reg_compound_wire.rs @@ -9,31 +9,31 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Add::new( - "add", - (200.0, 120.0), - Input::new("c", "out"), - Input::new("reg", "out"), - )), + Rc::new(Add { + id: "add".to_string(), + pos: (200.0, 120.0), + a_in: Input::new("c", "out"), + b_in: Input::new("reg", "out"), + }), Constant::rc_new("c", (100.0, 100.0), 3), - Rc::new(Register::new( - "reg", - (100.0, 140.0), - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "w1", - vec![(110.0, 100.0), (180.0, 100.0)], - Input::new("c", "out"), - )), - Rc::new(Wire::new( - "w2", - vec![(110.0, 140.0), (180.0, 140.0)], - Input::new("reg", "out"), - )), - Rc::new(Wire::new( - "w3", - vec![ + Rc::new(Register { + id: "reg".to_string(), + pos: (100.0, 140.0), + r_in: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "w1".to_string(), + pos: vec![(110.0, 100.0), (180.0, 100.0)], + input: Input::new("c", "out"), + }), + Rc::new(Wire { + id: "w2".to_string(), + pos: vec![(110.0, 140.0), (180.0, 140.0)], + input: Input::new("reg", "out"), + }), + Rc::new(Wire { + id: "w3".to_string(), + pos: vec![ (220.0, 120.0), (260.0, 120.0), (260.0, 180.0), @@ -41,18 +41,18 @@ fn main() { (60.0, 140.0), (90.0, 140.0), ], - Input::new("add", "out"), - )), - Rc::new(Probe::new( - "p_add", - (280.0, 120.0), - Input::new("add", "out"), - )), - Rc::new(Probe::new( - "p_reg", - (130.0, 120.0), - Input::new("reg", "out"), - )), + input: Input::new("add", "out"), + }), + Rc::new(Probe { + id: "p_add".to_string(), + pos: (280.0, 120.0), + input: Input::new("add", "out"), + }), + Rc::new(Probe { + id: "p_reg".to_string(), + pos: (130.0, 120.0), + input: Input::new("reg", "out"), + }), ], }; diff --git a/examples/data_mem.rs b/examples/data_mem.rs index e91de46e..d1f4ea4a 100644 --- a/examples/data_mem.rs +++ b/examples/data_mem.rs @@ -9,74 +9,94 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Mem::new( - "mem", - (180.0, 200.0), - 200.0, - 100.0, + Rc::new(Mem { + id: "mem".to_string(), + pos: (180.0, 200.0), + + width: 200.0, + height: 100.0, + // configuration - true, + big_endian: true, + // ports - Input::new("data", "out"), - Input::new("addr", "out"), - Input::new("ctrl", "out"), - Input::new("sext", "out"), - Input::new("size", "out"), + data: Input::new("data", "out"), + addr: Input::new("addr", "out"), + ctrl: Input::new("ctrl", "out"), + sign: Input::new("sext", "out"), + size: Input::new("size", "out"), + // memory - Memory::new(), + memory: Memory::new(), // later history... tbd - )), - Rc::new(Constant::new("data", (100.0, 100.0), 3)), - Rc::new(Constant::new("addr", (120.0, 100.0), 4)), - Rc::new(Constant::new( - "ctrl", - (140.0, 100.0), - MemCtrl::Write as SignalUnsigned, - )), - Rc::new(Constant::new( - "sext", - (160.0, 100.0), - false as SignalUnsigned, - )), - Rc::new(Constant::new( - "size", - (180.0, 100.0), - 1, // byte - )), + }), + Rc::new(Constant { + id: "data".to_string(), + pos: (100.0, 100.0), + value: 3.into(), + }), + Rc::new(Constant { + id: "addr".to_string(), + pos: (120.0, 100.0), + value: 4.into(), + }), + Rc::new(Constant { + id: "ctrl".to_string(), + pos: (140.0, 100.0), + value: (MemCtrl::Write as SignalUnsigned).into(), + }), + Rc::new(Constant { + id: "sext".to_string(), + pos: (160.0, 100.0), + value: (false as SignalUnsigned).into(), + }), + Rc::new(Constant { + id: "size".to_string(), + pos: (180.0, 100.0), + value: 1.into(), // byte + }), // Wires - Rc::new(Wire::new( - "w1", - vec![(100.0, 110.0), (100.0, 150.0)], - Input::new("data", "out"), - )), - Rc::new(Wire::new( - "w2", - vec![(120.0, 110.0), (120.0, 150.0)], - Input::new("addr", "out"), - )), - Rc::new(Wire::new( - "w3", - vec![(140.0, 110.0), (140.0, 150.0)], - Input::new("sext", "out"), - )), - Rc::new(Wire::new( - "w4", - vec![(160.0, 110.0), (160.0, 150.0)], - Input::new("size", "out"), - )), - Rc::new(Wire::new( - "w5", - vec![(220.0, 110.0), (220.0, 150.0)], - Input::new("mem", "data"), - )), - Rc::new(Wire::new( - "w6", - vec![(240.0, 110.0), (240.0, 150.0)], - Input::new("mem", "err"), - )), + Rc::new(Wire { + id: "w1".to_string(), + pos: vec![(100.0, 110.0), (100.0, 150.0)], + input: Input::new("data", "out"), + }), + Rc::new(Wire { + id: "w2".to_string(), + pos: vec![(120.0, 110.0), (120.0, 150.0)], + input: Input::new("addr", "out"), + }), + Rc::new(Wire { + id: "w3".to_string(), + pos: vec![(140.0, 110.0), (140.0, 150.0)], + input: Input::new("sext", "out"), + }), + Rc::new(Wire { + id: "w4".to_string(), + pos: vec![(160.0, 110.0), (160.0, 150.0)], + input: Input::new("size", "out"), + }), + Rc::new(Wire { + id: "w5".to_string(), + pos: vec![(220.0, 110.0), (220.0, 150.0)], + input: Input::new("mem", "data"), + }), + Rc::new(Wire { + id: "w6".to_string(), + pos: vec![(240.0, 110.0), (240.0, 150.0)], + input: Input::new("mem", "err"), + }), // probes - Rc::new(Probe::new("out", (220.0, 100.0), Input::new("mem", "data"))), - Rc::new(Probe::new("err", (240.0, 100.0), Input::new("mem", "err"))), + Rc::new(Probe { + id: "out".to_string(), + pos: (220.0, 100.0), + input: Input::new("mem", "data"), + }), + Rc::new(Probe { + id: "err".to_string(), + pos: (240.0, 100.0), + input: Input::new("mem", "err"), + }), ], }; diff --git a/examples/mux.rs b/examples/mux.rs index 02c1d76f..adbcf345 100644 --- a/examples/mux.rs +++ b/examples/mux.rs @@ -9,57 +9,77 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Mux::new( - "mux", - (200.0, 200.0), - Input::new("c0", "out"), - vec![ + Rc::new(Mux { + id: "mux".to_string(), + pos: (200.0, 200.0), + select: Input::new("c0", "out"), + m_in: vec![ Input::new("c1", "out"), Input::new("c2", "out"), Input::new("c3", "out"), Input::new("c4", "out"), ], - )), - Rc::new(Constant::new("c0", (190.0, 100.0), 3)), - Rc::new(Wire::new( - "w0", - vec![(190.0, 110.0), (190.0, 150.0)], - Input::new("c0", "out"), - )), - Rc::new(Constant::new("c1", (140.0, 170.0), 0)), - Rc::new(Constant::new("c2", (140.0, 190.0), 1)), - Rc::new(Constant::new("c3", (140.0, 210.0), 2)), - Rc::new(Constant::new("c4", (140.0, 230.0), 3)), - Rc::new(Wire::new( - "w1", - vec![(150.0, 170.0), (180.0, 170.0)], - Input::new("c1", "out"), - )), - Rc::new(Wire::new( - "w2", - vec![(150.0, 190.0), (180.0, 190.0)], - Input::new("c2", "out"), - )), - Rc::new(Wire::new( - "w3", - vec![(150.0, 210.0), (180.0, 210.0)], - Input::new("c3", "out"), - )), - Rc::new(Wire::new( - "w4", - vec![(150.0, 230.0), (180.0, 230.0)], - Input::new("c4", "out"), - )), - Rc::new(Wire::new( - "w5", - vec![(220.0, 200.0), (250.0, 200.0)], - Input::new("mux", "out"), - )), - Rc::new(Probe::new( - "p_mux", - (260.0, 200.0), - Input::new("mux", "out"), - )), + }), + Rc::new(Constant { + id: "c0".to_string(), + pos: (190.0, 100.0), + value: 3.into(), + }), + Rc::new(Wire { + id: "w0".to_string(), + pos: vec![(190.0, 110.0), (190.0, 150.0)], + input: Input::new("c0", "out"), + }), + Rc::new(Constant { + id: "c1".to_string(), + pos: (140.0, 170.0), + value: 0.into(), + }), + Rc::new(Constant { + id: "c2".to_string(), + pos: (140.0, 190.0), + value: 1.into(), + }), + Rc::new(Constant { + id: "c3".to_string(), + pos: (140.0, 210.0), + value: 2.into(), + }), + Rc::new(Constant { + id: "c4".to_string(), + pos: (140.0, 230.0), + value: 3.into(), + }), + Rc::new(Wire { + id: "w1".to_string(), + pos: vec![(150.0, 170.0), (180.0, 170.0)], + input: Input::new("c1", "out"), + }), + Rc::new(Wire { + id: "w2".to_string(), + pos: vec![(150.0, 190.0), (180.0, 190.0)], + input: Input::new("c2", "out"), + }), + Rc::new(Wire { + id: "w3".to_string(), + pos: vec![(150.0, 210.0), (180.0, 210.0)], + input: Input::new("c3", "out"), + }), + Rc::new(Wire { + id: "w4".to_string(), + pos: vec![(150.0, 230.0), (180.0, 230.0)], + input: Input::new("c4", "out"), + }), + Rc::new(Wire { + id: "w5".to_string(), + pos: vec![(220.0, 200.0), (250.0, 200.0)], + input: Input::new("mux", "out"), + }), + Rc::new(Probe { + id: "p_mux".to_string(), + pos: (260.0, 200.0), + input: Input::new("mux", "out"), + }), ], }; @@ -67,8 +87,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path).ok(); + syncrim::gui_egui::gui(&cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(cs, &path); + syncrim::gui_vizia::gui(&cs, &path); } diff --git a/examples/probe_edit.rs b/examples/probe_edit.rs index c92712d4..4dc9e0e2 100644 --- a/examples/probe_edit.rs +++ b/examples/probe_edit.rs @@ -10,11 +10,11 @@ fn main() { let cs = ComponentStore { store: vec![ Rc::new(ProbeEdit::new("probe_edit", (100.0, 100.0))), - Rc::new(Probe::new( - "probe", - (250.0, 100.0), - Input::new("probe_edit", "out"), - )), + Rc::new(Probe { + id: "probe".to_string(), + pos: (250.0, 100.0), + input: Input::new("probe_edit", "out"), + }), ], }; @@ -22,8 +22,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path).ok(); + syncrim::gui_egui::gui(&cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(cs, &path); + syncrim::gui_vizia::gui(&cs, &path); } diff --git a/examples/reg.rs b/examples/reg.rs index b30b1cf7..dc4e0023 100644 --- a/examples/reg.rs +++ b/examples/reg.rs @@ -10,22 +10,26 @@ fn main() { let cs = ComponentStore { store: vec![ Constant::rc_new("c", (150.0, 100.0), 3), - Rc::new(Register::new("reg", (200.0, 100.0), Input::new("c", "out"))), - Rc::new(Wire::new( - "w1", - vec![(160.0, 100.0), (190.0, 100.0)], - Input::new("c", "out"), - )), - Rc::new(Wire::new( - "w2", - vec![(210.0, 100.0), (240.0, 100.0)], - Input::new("reg", "out"), - )), - Rc::new(Probe::new( - "p_reg", - (250.0, 100.0), - Input::new("reg", "out"), - )), + Rc::new(Register { + id: "reg".to_string(), + pos: (200.0, 100.0), + r_in: Input::new("c", "out"), + }), + Rc::new(Wire { + id: "w1".to_string(), + pos: vec![(160.0, 100.0), (190.0, 100.0)], + input: Input::new("c", "out"), + }), + Rc::new(Wire { + id: "w2".to_string(), + pos: vec![(210.0, 100.0), (240.0, 100.0)], + input: Input::new("reg", "out"), + }), + Rc::new(Probe { + id: "p_reg".to_string(), + pos: (250.0, 100.0), + input: Input::new("reg", "out"), + }), ], }; diff --git a/examples/sext.rs b/examples/sext.rs index 8a750f9a..eb9d0051 100644 --- a/examples/sext.rs +++ b/examples/sext.rs @@ -10,24 +10,28 @@ fn main() { let cs = ComponentStore { store: vec![ Constant::rc_new("c0", (100.0, 110.0), 32768), - Rc::new(Wire::new( - "w0", - vec![(110.0, 110.0), (140.0, 110.0)], - Input::new("c0", "out"), - )), - Rc::new(Sext::new( - "sxt0", - (180.0, 100.0), - Input::new("c0", "out"), - 16, - 24, - )), - Rc::new(Wire::new( - "w1", - vec![(220.0, 100.0), (250.0, 100.0)], - Input::new("sxt0", "out"), - )), - Rc::new(Probe::new("p1", (260.0, 100.0), Input::new("sxt0", "out"))), + Rc::new(Wire { + id: "w0".to_string(), + pos: vec![(110.0, 110.0), (140.0, 110.0)], + input: Input::new("c0", "out"), + }), + Rc::new(Sext { + id: "sxt0".to_string(), + pos: (180.0, 100.0), + sext_in: Input::new("c0", "out"), + in_size: 16, + out_size: 24, + }), + Rc::new(Wire { + id: "w1".to_string(), + pos: vec![(220.0, 100.0), (250.0, 100.0)], + input: Input::new("sxt0", "out"), + }), + Rc::new(Probe { + id: "p1".to_string(), + pos: (260.0, 100.0), + input: Input::new("sxt0", "out"), + }), ], }; diff --git a/mips/examples/mips.rs b/mips/examples/mips.rs index 5aa61293..efcbe0cf 100644 --- a/mips/examples/mips.rs +++ b/mips/examples/mips.rs @@ -12,81 +12,85 @@ fn main() { fern_setup(); let cs = ComponentStore { store: vec![ - Rc::new(Add::new( - "add", - (200.0, 120.0), - Input::new("c1", "out"), - Input::new("reg", "out"), - )), + Rc::new(Add { + id: "add".to_string(), + pos: (200.0, 120.0), + a_in: Input::new("c1", "out"), + b_in: Input::new("reg", "out"), + }), Constant::rc_new("c1", (100.0, 100.0), 4), - Rc::new(Register::new( - "reg", - (100.0, 140.0), - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "c1_to_add_a", - vec![(110.0, 100.0), (180.0, 100.0)], - Input::new("c1", "out"), - )), - Rc::new(Wire::new( - "reg_to_add_b", - vec![(110.0, 140.0), (180.0, 140.0)], - Input::new("reg", "out"), - )), - Rc::new(Wire::new( - "add_to_right", - vec![(220.0, 120.0), (260.0, 120.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "add_to_up", - vec![(260.0, 60.0), (260.0, 120.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "add_to_left", - vec![(60.0, 60.0), (260.0, 60.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "add_to_down", - vec![(60.0, 60.0), (60.0, 140.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "reg_in", - vec![(60.0, 140.0), (90.0, 140.0)], - Input::new("add", "out"), - )), - Rc::new(Wire::new( - "pc_to_down", - vec![(140.0, 140.0), (140.0, 180.0)], - Input::new("reg", "out"), - )), - Rc::new(Wire::new( - "pc_to_right", - vec![(140.0, 180.0), (350.0, 180.0)], - Input::new("reg", "out"), - )), - Rc::new(InstrMem::new( - "instr_mem", - (400.0, 150.0), - Input::new("reg", "out"), + Rc::new(Register { + id: "reg".to_string(), + pos: (100.0, 140.0), + r_in: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "c1_to_add_a".to_string(), + pos: vec![(110.0, 100.0), (180.0, 100.0)], + input: Input::new("c1", "out"), + }), + Rc::new(Wire { + id: "reg_to_add_b".to_string(), + pos: vec![(110.0, 140.0), (180.0, 140.0)], + input: Input::new("reg", "out"), + }), + Rc::new(Wire { + id: "add_to_right".to_string(), + pos: vec![(220.0, 120.0), (260.0, 120.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "add_to_up".to_string(), + pos: vec![(260.0, 60.0), (260.0, 120.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "add_to_left".to_string(), + pos: vec![(60.0, 60.0), (260.0, 60.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "add_to_down".to_string(), + pos: vec![(60.0, 60.0), (60.0, 140.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "reg_in".to_string(), + pos: vec![(60.0, 140.0), (90.0, 140.0)], + input: Input::new("add", "out"), + }), + Rc::new(Wire { + id: "pc_to_down".to_string(), + pos: vec![(140.0, 140.0), (140.0, 180.0)], + input: Input::new("reg", "out"), + }), + Rc::new(Wire { + id: "pc_to_right".to_string(), + pos: vec![(140.0, 180.0), (350.0, 180.0)], + input: Input::new("reg", "out"), + }), + Rc::new(InstrMem { + id: "instr_mem".to_string(), + pos: (400.0, 150.0), + pc: Input::new("reg", "out"), // fake instructions just to show the relation between input address and instruction - vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], - )), - Rc::new(Wire::new( - "w8", - vec![(450.0, 120.0), (520.0, 120.0)], - Input::new("instr_mem", "out"), - )), - Rc::new(Probe::new("p1", (280.0, 160.0), Input::new("reg", "out"))), - Rc::new(Probe::new( - "p2", - (500.0, 100.0), - Input::new("instr_mem", "out"), - )), + instr: vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + }), + Rc::new(Wire { + id: "w8".to_string(), + pos: vec![(450.0, 120.0), (520.0, 120.0)], + input: Input::new("instr_mem", "out"), + }), + Rc::new(Probe { + id: "p1".to_string(), + pos: (280.0, 160.0), + input: Input::new("reg", "out"), + }), + Rc::new(Probe { + id: "p2".to_string(), + pos: (500.0, 100.0), + input: Input::new("instr_mem", "out"), + }), ], }; @@ -94,8 +98,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path).ok(); + syncrim::gui_egui::gui(&cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(cs, &path); + syncrim::gui_vizia::gui(&cs, &path); } diff --git a/mips/examples/reg_file.rs b/mips/examples/reg_file.rs index 54dfff9d..3da9690b 100644 --- a/mips/examples/reg_file.rs +++ b/mips/examples/reg_file.rs @@ -17,21 +17,23 @@ fn main() { Constant::rc_new("c_write_addr", (100.0, 160.0), 4), Constant::rc_new("c_write_enable", (100.0, 180.0), true), // regfile - Rc::new(RegFile::new( - "reg_file", - (300.0, 200.0), - 200.0, - 300.0, + Rc::new(RegFile { + id: "reg_file".to_string(), + pos: (300.0, 200.0), + width: 200.0, + height: 300.0, + // ports - Input::new("c_read_reg_1", "out"), - Input::new("c_read_reg_2", "out"), - Input::new("c_write_data", "out"), - Input::new("c_write_addr", "out"), - Input::new("c_write_enable", "out"), + read_addr1: Input::new("c_read_reg_1", "out"), + read_addr2: Input::new("c_read_reg_2", "out"), + write_data: Input::new("c_write_data", "out"), + write_addr: Input::new("c_write_addr", "out"), + write_enable: Input::new("c_write_enable", "out"), + // data - RegStore::new(), - RegHistory::new(), - )), + registers: RegStore::new(), + history: RegHistory::new(), + }), ], }; @@ -39,8 +41,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(cs, &path).ok(); + syncrim::gui_egui::gui(&cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(cs, &path); + syncrim::gui_vizia::gui(&cs, &path); } diff --git a/mips/src/components/instr_mem.rs b/mips/src/components/instr_mem.rs index 4d87b82d..11517498 100644 --- a/mips/src/components/instr_mem.rs +++ b/mips/src/components/instr_mem.rs @@ -1,29 +1,20 @@ use serde::{Deserialize, Serialize}; use syncrim::common::{Component, Input, InputPort, OutputType, Ports, Simulator}; +pub const INSTR_MEM_PC_ID: &str = "pc"; + +pub const INSTR_MEM_OUT_ID: &str = "out"; + #[derive(Serialize, Deserialize)] pub struct InstrMem { pub id: String, pub pos: (f32, f32), - pub pc: InputPort, pub instr: Vec, + pub pc: Input, } use log::*; -impl InstrMem { - pub fn new(id: &str, pos: (f32, f32), pc: Input, instr: Vec) -> Self { - InstrMem { - id: id.to_string(), - pos, - pc: InputPort { - port_id: String::from("in"), - input: pc, - }, - instr, - } - } -} #[typetag::serde()] impl Component for InstrMem { fn to_(&self) { @@ -34,16 +25,19 @@ impl Component for InstrMem { ( self.id.clone(), Ports { - inputs: vec![self.pc.clone()], + inputs: vec![InputPort { + port_id: INSTR_MEM_PC_ID.to_string(), + input: self.pc.clone(), + }], out_type: OutputType::Combinatorial, - outputs: vec!["out".into()], + outputs: vec![INSTR_MEM_OUT_ID.to_string()], }, ) } fn clock(&self, simulator: &mut Simulator) { // get instr at pc/4 - let pc: u32 = simulator.get_input_val(&self.pc.input).try_into().unwrap(); + let pc: u32 = simulator.get_input_val(&self.pc).try_into().unwrap(); trace!("--- evaluate instr mem: pc {:?}", pc); let instr = self.instr[(pc / 4) as usize]; diff --git a/mips/src/components/reg_file.rs b/mips/src/components/reg_file.rs index 90d4c8ad..c8a6cd81 100644 --- a/mips/src/components/reg_file.rs +++ b/mips/src/components/reg_file.rs @@ -46,6 +46,15 @@ pub enum Reg { ra = 31, // Return address (used by function calls) } +pub const MEM_READ_ADDR1_ID: &str = "read_addr1"; +pub const MEM_READ_ADDR2_ID: &str = "read_addr2"; +pub const MEM_WRITE_DATA_ID: &str = "write_data"; +pub const MEM_WRITE_ADDR_ID: &str = "write_addr"; +pub const MEM_WRITE_ENABLE_ID: &str = "write_enable"; + +pub const MEM_REG_A_OUT: &str = "reg_a"; +pub const MEM_REG_B_OUT: &str = "reg_b"; + #[derive(Serialize, Deserialize)] pub struct RegFile { pub id: String, @@ -54,60 +63,16 @@ pub struct RegFile { pub height: f32, // ports - pub read_addr1: InputPort, - pub read_addr2: InputPort, - pub write_data: InputPort, - pub write_addr: InputPort, - pub write_enable: InputPort, + pub read_addr1: Input, + pub read_addr2: Input, + pub write_data: Input, + pub write_addr: Input, + pub write_enable: Input, // data pub registers: RegStore, pub history: RegHistory, } -impl RegFile { - pub fn new( - id: &str, - pos: (f32, f32), - width: f32, - height: f32, - read_addr1: Input, - read_addr2: Input, - write_data: Input, - write_addr: Input, - write_enable: Input, - registers: RegStore, - history: RegHistory, - ) -> Self { - RegFile { - id: id.to_string(), - pos, - width, - height, - read_addr1: InputPort { - port_id: "read_addr1".to_string(), - input: read_addr1, - }, - read_addr2: InputPort { - port_id: "read_addr2".to_string(), - input: read_addr2, - }, - write_data: InputPort { - port_id: "write_data".to_string(), - input: write_data, - }, - write_addr: InputPort { - port_id: "write_addr".to_string(), - input: write_addr, - }, - write_enable: InputPort { - port_id: "write_enable".to_string(), - input: write_enable, - }, - registers, - history, - } - } -} #[derive(Serialize, Deserialize, Clone)] pub struct RegOp { @@ -192,7 +157,16 @@ impl Component for RegFile { ( self.id.clone(), Ports { - inputs: vec![self.read_addr1.clone(), self.read_addr2.clone()], + inputs: vec![ + InputPort { + port_id: MEM_READ_ADDR1_ID.to_string(), + input: self.read_addr1.clone(), + }, + InputPort { + port_id: MEM_READ_ADDR2_ID.to_string(), + input: self.read_addr2.clone(), + }, + ], out_type: OutputType::Combinatorial, outputs: vec!["reg_a".into(), "reg_b".into()], }, @@ -200,11 +174,11 @@ impl Component for RegFile { } fn clock(&self, simulator: &mut Simulator) { - if simulator.get_input_val(&self.write_enable.input) == (true as SignalUnsigned).into() { - let data = simulator.get_input_val(&self.write_data.input); + if simulator.get_input_val(&self.write_enable) == (true as SignalUnsigned).into() { + let data = simulator.get_input_val(&self.write_data); trace!("data {:?}", data); let write_addr: SignalUnsigned = simulator - .get_input_val(&self.write_addr.input) + .get_input_val(&self.write_addr) .try_into() .unwrap(); trace!("write_addr {}", write_addr); @@ -212,13 +186,13 @@ impl Component for RegFile { } // read after write - let reg_value_a = self.read_reg(simulator, &self.read_addr1.input); + let reg_value_a = self.read_reg(simulator, &self.read_addr1); trace!("reg_value {}", reg_value_a); - simulator.set_out_val(&self.id, "reg_a", Signal::Data(reg_value_a)); + simulator.set_out_val(&self.id, MEM_REG_A_OUT, Signal::Data(reg_value_a)); - let reg_value_b = self.read_reg(simulator, &self.read_addr2.input); + let reg_value_b = self.read_reg(simulator, &self.read_addr2); trace!("reg_value {}", reg_value_b); - simulator.set_out_val(&self.id, "reg_b", Signal::Data(reg_value_b)); + simulator.set_out_val(&self.id, MEM_REG_B_OUT, Signal::Data(reg_value_b)); } } @@ -242,21 +216,23 @@ mod test { Rc::new(ProbeOut::new("write_addr")), Rc::new(ProbeOut::new("write_enable")), // regfile - Rc::new(RegFile::new( - "reg_file", - (200.0, 150.0), - 100.0, - 150.0, + Rc::new(RegFile { + id: "reg_file".to_string(), + pos: (200.0, 150.0), + width: 100.0, + height: 150.0, + // ports - Input::new("read_reg_1", "out"), - Input::new("read_reg_2", "out"), - Input::new("write_data", "out"), - Input::new("write_addr", "out"), - Input::new("write_enable", "out"), + read_addr1: Input::new("read_reg_1", "out"), + read_addr2: Input::new("read_reg_2", "out"), + write_data: Input::new("write_data", "out"), + write_addr: Input::new("write_addr", "out"), + write_enable: Input::new("write_enable", "out"), + // data - RegStore::new(), - RegHistory::new(), - )), + registers: RegStore::new(), + history: RegHistory::new(), + }), ], }; diff --git a/src/common.rs b/src/common.rs index dc8b7fc0..ccdca2f4 100644 --- a/src/common.rs +++ b/src/common.rs @@ -123,13 +123,18 @@ pub trait ViziaComponent: Component { fn view(&self, _cx: &mut vizia::context::Context) {} } +#[cfg(feature = "gui-egui")] +use crate::gui_egui::gui::EguiExtra; + // Specific functionality for EGui frontend #[cfg(feature = "gui-egui")] #[typetag::serde(tag = "type")] pub trait EguiComponent: Component { + #[allow(clippy::too_many_arguments)] fn render( &self, _ui: &mut egui::Ui, + _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, _offset: egui::Vec2, _scale: f32, @@ -143,6 +148,7 @@ pub trait EguiComponent: Component { fn render_editor( &mut self, _ui: &mut egui::Ui, + _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, _offset: egui::Vec2, _scale: f32, @@ -173,18 +179,11 @@ pub trait EguiComponent: Component { todo!("Create set_pos for this EguiComponent"); } - fn set_id_tmp(&mut self) { - todo!("Create set_id_tmp for this EguiComponent"); + fn set_id_tmp(&self, context: &mut EguiExtra) { + context.id_tmp = self.get_id_ports().0.clone(); } } -#[cfg(feature = "gui-egui")] -#[derive(Serialize, Deserialize, Clone, Default)] -pub struct EguiExtra { - pub properties_window: bool, - pub id_tmp: String, -} - #[derive(Debug, Clone)] pub struct Ports { pub inputs: Vec, diff --git a/src/components/add.rs b/src/components/add.rs index ebcb9ec1..66b6bfe1 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -5,35 +5,18 @@ use crate::common::{ use log::*; use serde::{Deserialize, Serialize}; +pub const ADD_A_IN_ID: &str = "a_in"; +pub const ADD_B_IN_ID: &str = "b_in"; + +pub const ADD_OUT_ID: &str = "out"; +pub const ADD_OVERFLOW_ID: &str = "overflow"; + #[derive(Serialize, Deserialize)] pub struct Add { pub id: Id, pub pos: (f32, f32), - pub a_in: InputPort, - pub b_in: InputPort, - - #[cfg(feature = "gui-egui")] - #[serde(skip)] - pub egui_x: crate::common::EguiExtra, -} - -impl Add { - pub fn new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input) -> Self { - Add { - id: id.to_string(), - pos, - a_in: InputPort { - port_id: String::from("a_in"), - input: a_in, - }, - b_in: InputPort { - port_id: String::from("b_in"), - input: b_in, - }, - #[cfg(feature = "gui-egui")] - egui_x: crate::common::EguiExtra::default(), - } - } + pub a_in: Input, + pub b_in: Input, } #[typetag::serde] @@ -46,9 +29,18 @@ impl Component for Add { ( self.id.clone(), Ports::new( - vec![&self.a_in, &self.b_in], + vec![ + &InputPort { + port_id: ADD_A_IN_ID.to_string(), + input: self.a_in.clone(), + }, + &InputPort { + port_id: ADD_B_IN_ID.to_string(), + input: self.b_in.clone(), + }, + ], OutputType::Combinatorial, - vec!["out", "overflow"], + vec![ADD_OUT_ID, ADD_OVERFLOW_ID], ), ) } @@ -56,8 +48,8 @@ impl Component for Add { // propagate addition to output fn clock(&self, simulator: &mut Simulator) { // get input values - let a_in = u32::try_from(simulator.get_input_val(&self.a_in.input)); - let b_in = u32::try_from(simulator.get_input_val(&self.b_in.input)); + let a_in = u32::try_from(simulator.get_input_val(&self.a_in)); + let b_in = u32::try_from(simulator.get_input_val(&self.b_in)); let (value, overflow) = match (&a_in, &b_in) { (Ok(a), Ok(b)) => { @@ -86,8 +78,8 @@ impl Component for Add { fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { match target_port_id.as_str() { - "a_in" => self.a_in.input = new_input, - "b_in" => self.b_in.input = new_input, + ADD_A_IN_ID => self.a_in = new_input, + ADD_B_IN_ID => self.b_in = new_input, _ => (), } } @@ -109,12 +101,12 @@ mod test { store: vec![ Rc::new(ProbeOut::new("po1")), Rc::new(ProbeOut::new("po2")), - Rc::new(Add::new( - "add", - (0.0, 0.0), - Input::new("po1", "out"), - Input::new("po2", "out"), - )), + Rc::new(Add { + id: "add".to_string(), + pos: (0.0, 0.0), + a_in: Input::new("po1", "out"), + b_in: Input::new("po2", "out"), + }), ], }; let mut simulator = Simulator::new(cs); diff --git a/src/components/constant.rs b/src/components/constant.rs index 4854b7ca..5cf8e087 100644 --- a/src/components/constant.rs +++ b/src/components/constant.rs @@ -2,14 +2,14 @@ use crate::common::{Component, Id, OutputType, Ports, Signal, Simulator}; use log::*; use serde::{Deserialize, Serialize}; use std::rc::Rc; + +pub const CONSTANT_OUT_ID: &str = "out"; + #[derive(Serialize, Deserialize)] pub struct Constant { pub id: Id, pub pos: (f32, f32), pub value: Signal, - #[cfg(feature = "gui-egui")] - #[serde(skip)] - pub egui_x: crate::common::EguiExtra, } #[typetag::serde] @@ -25,13 +25,13 @@ impl Component for Constant { // Constants do not take any inputs vec![], OutputType::Combinatorial, - vec!["out"], + vec![CONSTANT_OUT_ID], ), ) } fn clock(&self, simulator: &mut Simulator) { - simulator.set_out_val(&self.id, "out", self.value); + simulator.set_out_val(&self.id, CONSTANT_OUT_ID, self.value); } } @@ -41,8 +41,6 @@ impl Constant { id: id.to_string(), pos, value: value.into(), - #[cfg(feature = "gui-egui")] - egui_x: crate::common::EguiExtra::default(), } } diff --git a/src/components/mem.rs b/src/components/mem.rs index 25ec2054..a2a58270 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -8,6 +8,15 @@ use num_enum::TryFromPrimitive; use serde::{Deserialize, Serialize}; use std::{cell::RefCell, collections::HashMap, convert::TryFrom}; +pub const MEM_DATA_ID: &str = "data"; +pub const MEM_ADDR_ID: &str = "addr"; +pub const MEM_CTRL_ID: &str = "ctrl"; +pub const MEM_SIGN_ID: &str = "sign"; +pub const MEM_SIZE_ID: &str = "size"; + +pub const MEM_DATA_OUT: &str = "data"; +pub const MEM_ERR_OUT: &str = "err"; + #[derive(Serialize, Deserialize)] pub struct Mem { pub id: Id, @@ -19,18 +28,15 @@ pub struct Mem { pub big_endian: bool, // ports - pub data: InputPort, - pub addr: InputPort, - pub ctrl: InputPort, - pub sign: InputPort, - pub size: InputPort, + pub data: Input, + pub addr: Input, + pub ctrl: Input, + pub sign: Input, + pub size: Input, // memory pub memory: Memory, // later history... tbd - #[cfg(feature = "gui-egui")] - #[serde(skip)] - pub egui_x: crate::common::EguiExtra, } #[derive(Serialize, Deserialize, Debug)] @@ -44,54 +50,6 @@ impl Default for Memory { } } -impl Mem { - #[allow(clippy::too_many_arguments)] - pub fn new( - id: &str, - pos: (f32, f32), - width: f32, - height: f32, - big_endian: bool, - data: Input, - addr: Input, - ctrl: Input, - size: Input, - sign: Input, - memory: Memory, - ) -> Self { - Mem { - id: id.to_string(), - pos, - width, - height, - big_endian, - data: InputPort { - port_id: String::from("data"), - input: data, - }, - addr: InputPort { - port_id: String::from("addr"), - input: addr, - }, - ctrl: InputPort { - port_id: String::from("ctrl"), - input: ctrl, - }, - size: InputPort { - port_id: String::from("size"), - input: size, - }, - sign: InputPort { - port_id: String::from("sign"), - input: sign, - }, - memory, - #[cfg(feature = "gui-egui")] - egui_x: crate::common::EguiExtra::default(), - } - } -} - impl Memory { pub fn new() -> Self { Memory { @@ -243,34 +201,35 @@ impl Component for Mem { ( self.id.clone(), Ports::new( - vec![&self.data, &self.addr, &self.ctrl], + vec![ + &InputPort { + port_id: MEM_DATA_ID.to_string(), + input: self.data.clone(), + }, + &InputPort { + port_id: MEM_ADDR_ID.to_string(), + input: self.addr.clone(), + }, + &InputPort { + port_id: MEM_CTRL_ID.to_string(), + input: self.ctrl.clone(), + }, + ], OutputType::Combinatorial, - vec!["data", "err"], + vec![MEM_DATA_OUT, MEM_ERR_OUT], ), ) } fn clock(&self, simulator: &mut Simulator) { - let data = simulator.get_input_val(&self.data.input); - let addr: SignalUnsigned = simulator - .get_input_val(&self.addr.input) - .try_into() - .unwrap(); + let data = simulator.get_input_val(&self.data); + let addr: SignalUnsigned = simulator.get_input_val(&self.addr).try_into().unwrap(); let addr = addr as usize; - let ctrl: SignalUnsigned = simulator - .get_input_val(&self.ctrl.input) - .try_into() - .unwrap(); + let ctrl: SignalUnsigned = simulator.get_input_val(&self.ctrl).try_into().unwrap(); let ctrl = MemCtrl::try_from(ctrl as u8).unwrap(); - let size: SignalUnsigned = simulator - .get_input_val(&self.size.input) - .try_into() - .unwrap(); + let size: SignalUnsigned = simulator.get_input_val(&self.size).try_into().unwrap(); let size = size as usize; - let sign: SignalUnsigned = simulator - .get_input_val(&self.sign.input) - .try_into() - .unwrap(); + let sign: SignalUnsigned = simulator.get_input_val(&self.sign).try_into().unwrap(); let sign = sign != 0; match ctrl { @@ -297,7 +256,6 @@ impl Component for Mem { trace!("memory {:?}", self.memory); } } - #[cfg(test)] mod test { use super::*; @@ -314,24 +272,27 @@ mod test { Rc::new(ProbeOut::new("ctrl")), Rc::new(ProbeOut::new("size")), Rc::new(ProbeOut::new("sign")), - Rc::new(Mem::new( - "mem", - (0.0, 0.0), - 0.0, - 0.0, + Rc::new(Mem { + id: "mem".into(), + pos: (0.0, 0.0), + width: 0.0, + height: 0.0, + // configuration - true, // i.e., big endian + big_endian: true, // i.e., big endian + // ports - Input::new("data", "out"), - Input::new("addr", "out"), - Input::new("ctrl", "out"), - Input::new("size", "out"), - Input::new("sign", "out"), + data: Input::new("data", "out"), + addr: Input::new("addr", "out"), + ctrl: Input::new("ctrl", "out"), + size: Input::new("size", "out"), + sign: Input::new("sign", "out"), + // memory - Memory { + memory: Memory { bytes: RefCell::new(HashMap::new()), }, - )), + }), ], }; @@ -491,25 +452,28 @@ mod test { Rc::new(ProbeOut::new("ctrl")), Rc::new(ProbeOut::new("size")), Rc::new(ProbeOut::new("sign")), - Rc::new(Mem::new( - "mem", - (0.0, 0.0), - 0.0, - 0.0, + Rc::new(Mem { + id: "mem".into(), + pos: (0.0, 0.0), + width: 0.0, + height: 0.0, + // configuration - false, // i.e., little endian + big_endian: false, // i.e., little endian + // ports - Input::new("data", "out"), - Input::new("addr", "out"), - Input::new("ctrl", "out"), - Input::new("size", "out"), - Input::new("sign", "out"), + data: Input::new("data", "out"), + addr: Input::new("addr", "out"), + ctrl: Input::new("ctrl", "out"), + size: Input::new("size", "out"), + sign: Input::new("sign", "out"), + // memory - Memory { + memory: Memory { bytes: RefCell::new(HashMap::new()), }, // later history... tbd - )), + }), ], }; diff --git a/src/components/mux.rs b/src/components/mux.rs index 06fc6341..a0dfd7ec 100644 --- a/src/components/mux.rs +++ b/src/components/mux.rs @@ -3,39 +3,16 @@ use crate::common::{ }; use log::*; use serde::{Deserialize, Serialize}; +pub const MUX_SELECT_ID: &str = "select"; +pub const MUX_TEMPLATE_ID: &str = "in"; +pub const MUX_OUT_ID: &str = "out"; + #[derive(Serialize, Deserialize)] pub struct Mux { pub id: Id, pub pos: (f32, f32), - pub select: InputPort, - pub m_in: Vec, - - #[cfg(feature = "gui-egui")] - #[serde(skip)] - pub egui_x: crate::common::EguiExtra, -} - -impl Mux { - pub fn new(id: &str, pos: (f32, f32), select: Input, m_in: Vec) -> Self { - let mut v = vec![]; - for (i, input) in m_in.iter().enumerate() { - v.push(InputPort { - port_id: format!("in{}", i), - input: input.clone(), - }); - } - Mux { - id: id.to_string(), - pos, - select: InputPort { - port_id: String::from("select"), - input: select, - }, - m_in: v, - #[cfg(feature = "gui-egui")] - egui_x: crate::common::EguiExtra::default(), - } - } + pub select: Input, + pub m_in: Vec, } #[typetag::serde] @@ -45,16 +22,24 @@ impl Component for Mux { } fn get_id_ports(&self) -> (Id, Ports) { - let mut inputs = vec![self.select.clone()]; - let mut m = self.m_in.clone(); - inputs.append(&mut m); + let mut inputs: Vec = Vec::with_capacity(self.m_in.len() + 1); + inputs.push(InputPort { + port_id: MUX_SELECT_ID.to_string(), + input: self.select.clone(), + }); + for (i, item) in self.m_in.iter().enumerate() { + inputs.push(InputPort { + port_id: format!("{}{}", MUX_TEMPLATE_ID, i), + input: item.clone(), + }); + } ( self.id.clone(), Ports { inputs, out_type: OutputType::Combinatorial, - outputs: vec!["out".into()], + outputs: vec![MUX_OUT_ID.to_string()], }, ) } @@ -62,14 +47,11 @@ impl Component for Mux { // propagate selected input value to output fn clock(&self, simulator: &mut Simulator) { // get input value - let select: SignalUnsigned = simulator - .get_input_val(&self.select.input) - .try_into() - .unwrap(); + let select: SignalUnsigned = simulator.get_input_val(&self.select).try_into().unwrap(); let select = select as usize; trace!("select {}", select); let value = if select < self.m_in.len() { - simulator.get_input_val(&self.m_in[select].input) + simulator.get_input_val(&self.m_in[select]) } else { Signal::Unknown }; diff --git a/src/components/probe.rs b/src/components/probe.rs index d9747846..a84974ad 100644 --- a/src/components/probe.rs +++ b/src/components/probe.rs @@ -2,14 +2,14 @@ use crate::common::{Component, Id, Input, InputPort, OutputType, Ports}; use log::*; use serde::{Deserialize, Serialize}; use std::rc::Rc; + +pub const PROBE_IN_ID: &str = "in"; + #[derive(Serialize, Deserialize)] pub struct Probe { pub id: Id, pub pos: (f32, f32), - pub input_port: InputPort, - #[cfg(feature = "gui-egui")] - #[serde(skip)] - pub egui_x: crate::common::EguiExtra, + pub input: Input, } #[typetag::serde] @@ -23,7 +23,10 @@ impl Component for Probe { self.id.clone(), Ports::new( // Probes take one input - vec![&self.input_port], + vec![&InputPort { + port_id: PROBE_IN_ID.to_string(), + input: self.input.clone(), + }], OutputType::Combinatorial, // No output value vec![], @@ -32,8 +35,8 @@ impl Component for Probe { } fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - if target_port_id.as_str() == "in" { - self.input_port.input = new_input + if target_port_id.as_str() == PROBE_IN_ID { + self.input = new_input } } } @@ -43,12 +46,7 @@ impl Probe { Probe { id: id.to_string(), pos, - input_port: InputPort { - port_id: String::from("in"), - input, - }, - #[cfg(feature = "gui-egui")] - egui_x: crate::common::EguiExtra::default(), + input, } } diff --git a/src/components/probe_edit.rs b/src/components/probe_edit.rs index 97b373d5..52291ac2 100644 --- a/src/components/probe_edit.rs +++ b/src/components/probe_edit.rs @@ -3,15 +3,13 @@ use log::*; use serde::{Deserialize, Serialize}; use std::sync::{Arc, RwLock}; +pub const PROBE_EDIT_OUT_ID: &str = "out"; + #[derive(Serialize, Deserialize, Clone)] pub struct ProbeEdit { pub id: Id, pub pos: (f32, f32), pub history: Arc>>, // will contain the next editable value - - #[cfg(feature = "gui-egui")] - #[serde(skip)] - pub egui_x: crate::common::EguiExtra, } #[derive(Serialize, Deserialize, Clone, Debug)] @@ -34,7 +32,7 @@ impl Component for ProbeEdit { vec![], OutputType::Combinatorial, // Single output value - vec!["out"], + vec![PROBE_EDIT_OUT_ID], ), ) } @@ -75,9 +73,6 @@ impl ProbeEdit { text: "0".to_string(), signal: Signal::Data(0), }])), - - #[cfg(feature = "gui-egui")] - egui_x: crate::common::EguiExtra::default(), } } } diff --git a/src/components/register.rs b/src/components/register.rs index 86867c58..0d9a321d 100644 --- a/src/components/register.rs +++ b/src/components/register.rs @@ -1,29 +1,14 @@ use crate::common::{Component, Id, Input, InputPort, OutputType, Ports, Simulator}; use log::*; use serde::{Deserialize, Serialize}; + +pub const REGISTER_IN_ID: &str = "r_in"; + #[derive(Serialize, Deserialize)] pub struct Register { pub id: Id, pub pos: (f32, f32), - pub r_in: InputPort, - - #[cfg(feature = "gui-egui")] - #[serde(skip)] - pub egui_x: crate::common::EguiExtra, -} -impl Register { - pub fn new(id: &str, pos: (f32, f32), r_in: Input) -> Self { - Register { - id: id.to_string(), - pos, - r_in: InputPort { - port_id: String::from("r_in"), - input: r_in, - }, - #[cfg(feature = "gui-egui")] - egui_x: crate::common::EguiExtra::default(), - } - } + pub r_in: Input, } #[typetag::serde] @@ -37,7 +22,10 @@ impl Component for Register { self.id.clone(), Ports::new( // Vector of inputs - vec![&self.r_in], + vec![&InputPort { + port_id: REGISTER_IN_ID.to_string(), + input: self.r_in.clone(), + }], OutputType::Sequential, vec!["out"], ), @@ -47,7 +35,7 @@ impl Component for Register { // propagate input value to output fn clock(&self, simulator: &mut Simulator) { // get input value - let value = simulator.get_input_val(&self.r_in.input); + let value = simulator.get_input_val(&self.r_in); // set output simulator.set_out_val(&self.id, "out", value); trace!("eval: register id {} in {:?}", self.id, value); diff --git a/src/components/sext.rs b/src/components/sext.rs index 6d3eadf3..df429688 100644 --- a/src/components/sext.rs +++ b/src/components/sext.rs @@ -5,33 +5,16 @@ use crate::common::{ }; use log::*; use serde::{Deserialize, Serialize}; + +pub const SEXT_IN_ID: &str = "sext_in"; + #[derive(Serialize, Deserialize, Clone)] pub struct Sext { pub id: Id, pub pos: (f32, f32), - pub sext_in: InputPort, + pub sext_in: Input, pub in_size: u32, pub out_size: u32, - - #[cfg(feature = "gui-egui")] - #[serde(skip)] - pub egui_x: crate::common::EguiExtra, -} -impl Sext { - pub fn new(id: &str, pos: (f32, f32), sext_in: Input, in_size: u32, out_size: u32) -> Self { - Sext { - id: id.to_string(), - pos, - sext_in: InputPort { - port_id: String::from("sext_in"), - input: sext_in, - }, - in_size, - out_size, - #[cfg(feature = "gui-egui")] - egui_x: crate::common::EguiExtra::default(), - } - } } #[typetag::serde] @@ -43,7 +26,14 @@ impl Component for Sext { fn get_id_ports(&self) -> (Id, Ports) { ( self.id.clone(), - Ports::new(vec![&self.sext_in], OutputType::Combinatorial, vec!["out"]), + Ports::new( + vec![&InputPort { + port_id: SEXT_IN_ID.to_string(), + input: self.sext_in.clone(), + }], + OutputType::Combinatorial, + vec!["out"], + ), ) } @@ -59,10 +49,7 @@ impl Component for Sext { ); // get input values - let mut value: SignalUnsigned = simulator - .get_input_val(&self.sext_in.input) - .try_into() - .unwrap(); + let mut value: SignalUnsigned = simulator.get_input_val(&self.sext_in).try_into().unwrap(); let to_sext = self.out_size - self.in_size; // Amount to be arithmetically shifted let to_shl = SignalUnsigned::BITS - self.in_size; // To move input to MSB @@ -76,7 +63,6 @@ impl Component for Sext { simulator.set_out_val(&self.id, "out", Signal::Data(value)); } } - #[cfg(test)] mod test { @@ -89,20 +75,20 @@ mod test { let cs = ComponentStore { store: vec![ Rc::new(ProbeOut::new("po")), - Rc::new(Sext::new( - "sext32", - (0.0, 0.0), - Input::new("po", "out"), - 4, - 32, - )), - Rc::new(Sext::new( - "sext16", - (0.0, 0.0), - Input::new("po", "out"), - 4, - 16, - )), + Rc::new(Sext { + id: "sext32".to_string(), + pos: (0.0, 0.0), + sext_in: Input::new("po", "out"), + in_size: 4, + out_size: 32, + }), + Rc::new(Sext { + id: "sext16".to_string(), + pos: (0.0, 0.0), + sext_in: Input::new("po", "out"), + in_size: 4, + out_size: 16, + }), ], }; diff --git a/src/components/wire.rs b/src/components/wire.rs index 17248fb6..c336fab5 100644 --- a/src/components/wire.rs +++ b/src/components/wire.rs @@ -2,30 +2,13 @@ use crate::common::{Component, Id, Input, InputPort, OutputType, Ports}; use log::*; use serde::{Deserialize, Serialize}; +pub const WIRE_INPUT_ID: &str = "in"; + #[derive(Serialize, Deserialize)] pub struct Wire { pub id: Id, pub pos: Vec<(f32, f32)>, - pub input_port: InputPort, - - #[cfg(feature = "gui-egui")] - #[serde(skip)] - pub egui_x: crate::common::EguiExtra, -} - -impl Wire { - pub fn new(id: &str, pos: Vec<(f32, f32)>, input: Input) -> Self { - Wire { - id: id.to_string(), - pos, - input_port: InputPort { - port_id: String::from("in"), - input, - }, - #[cfg(feature = "gui-egui")] - egui_x: crate::common::EguiExtra::default(), - } - } + pub input: Input, } #[typetag::serde] @@ -39,7 +22,10 @@ impl Component for Wire { self.id.clone(), Ports::new( // Wires take one input - vec![&self.input_port], + vec![&InputPort { + port_id: WIRE_INPUT_ID.to_string(), + input: self.input.clone(), + }], OutputType::Combinatorial, // No output value vec![], diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index d25b4009..f5b87cf4 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -1,4 +1,4 @@ -use crate::common::{InputPort, Ports}; +use crate::common::{Input, Ports}; use crate::gui_egui::editor::EditorMode; use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; use egui::{ComboBox, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, Ui, Window}; @@ -80,14 +80,16 @@ pub fn pos_slider(ui: &mut Ui, pos: &mut (f32, f32)) { pub fn input_selector( ui: &mut Ui, - input_port: &mut InputPort, + input: &mut Input, + // Why is this marked as unused, it's clearly being used? + #[allow(unused_variables)] port_id: crate::common::Id, id_ports: &[(crate::common::Id, Ports)], ) -> bool { - let mut port_id = input_port.input.id.clone(); - let mut port_field = input_port.input.field.clone(); - let label_port_id = format!("{}.id", input_port.port_id.clone()); + let mut port_id = input.id.clone(); + let mut port_field = input.field.clone(); + let label_port_id = format!("{}.id", port_id.clone()); let text_port_id = port_id.to_string(); - let label_port_field = format!("{}.field", input_port.port_id.clone()); + let label_port_field = format!("{}.field", port_id.clone()); let text_port_field = port_field.to_string(); ui.horizontal(|ui| { ComboBox::from_label(label_port_id) @@ -113,14 +115,14 @@ pub fn input_selector( } }); }); - let clicked_dropdown = input_port.input.id != port_id || input_port.input.field != port_field; + let clicked_dropdown = input.id != port_id || input.field != port_field; - input_port.input.id = port_id; - input_port.input.field = port_field; + input.id = port_id; + input.field = port_field; clicked_dropdown } -pub fn input_port( +pub fn input_change_id( ui: &mut Ui, id_tmp: &mut String, id: &mut String, diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 21cd36de..4fffb8ae 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,7 +1,8 @@ use crate::gui_egui::component_ui::{ - input_port, input_selector, pos_slider, properties_window, rect_with_hover, + input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; use crate::{ common::{EguiComponent, Ports, Simulator}, @@ -14,6 +15,7 @@ impl EguiComponent for Add { fn render( &self, ui: &mut egui::Ui, + _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, @@ -75,6 +77,7 @@ impl EguiComponent for Add { fn render_editor( &mut self, ui: &mut egui::Ui, + context: &mut EguiExtra, simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, @@ -83,8 +86,17 @@ impl EguiComponent for Add { editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; - let r_vec = - Add::render(self, ui, simulator, offset, scale, clip_rect, editor_mode).unwrap(); + let r_vec = Add::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); let resp = &r_vec[0]; if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta() / scale; @@ -101,13 +113,23 @@ impl EguiComponent for Add { ui, self.id.clone(), resp, - &mut self.egui_x.properties_window, + &mut context.properties_window, |ui| { let mut clicked_dropdown = false; - input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); - clicked_dropdown |= input_selector(ui, &mut self.a_in, id_ports); - clicked_dropdown |= input_selector(ui, &mut self.b_in, id_ports); + clicked_dropdown |= input_selector( + ui, + &mut self.a_in, + crate::components::ADD_A_IN_ID.to_string(), + id_ports, + ); + clicked_dropdown |= input_selector( + ui, + &mut self.b_in, + crate::components::ADD_B_IN_ID.to_string(), + id_ports, + ); clicked_dropdown }, ); @@ -132,23 +154,25 @@ impl EguiComponent for Add { let own_pos = Vec2::new(self.pos.0, self.pos.1); vec![ ( - self.a_in.port_id.clone(), + crate::components::ADD_A_IN_ID.to_string(), Pos2::new(-20f32, -20f32) + own_pos, ), ( - self.b_in.port_id.clone(), + crate::components::ADD_B_IN_ID.to_string(), Pos2::new(-20f32, 20f32) + own_pos, ), - (String::from("out"), Pos2::new(20f32, 0f32) + own_pos), - (String::from("overflow"), Pos2::new(0f32, -40f32) + own_pos), + ( + crate::components::ADD_OUT_ID.to_string(), + Pos2::new(20f32, 0f32) + own_pos, + ), + ( + crate::components::ADD_OVERFLOW_ID.to_string(), + Pos2::new(0f32, -40f32) + own_pos, + ), ] } fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } - - fn set_id_tmp(&mut self) { - self.egui_x.id_tmp = self.id.clone(); - } } diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 2b99b8db..eb1ddfac 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,7 +1,10 @@ use crate::common::{EguiComponent, Ports, Signal, SignalUnsigned, Simulator}; use crate::components::Constant; -use crate::gui_egui::component_ui::{input_port, pos_slider, properties_window, rect_with_hover}; +use crate::gui_egui::component_ui::{ + input_change_id, pos_slider, properties_window, rect_with_hover, +}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::gui::EguiExtra; use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Vec2}; #[typetag::serde] @@ -9,6 +12,7 @@ impl EguiComponent for Constant { fn render( &self, ui: &mut egui::Ui, + _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, @@ -57,6 +61,7 @@ impl EguiComponent for Constant { fn render_editor( &mut self, ui: &mut egui::Ui, + context: &mut EguiExtra, simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, @@ -65,8 +70,17 @@ impl EguiComponent for Constant { editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; - let r_vec = - Constant::render(self, ui, simulator, offset, scale, clip_rect, editor_mode).unwrap(); + let r_vec = Constant::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); let resp = &r_vec[0]; if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta() / scale; @@ -82,9 +96,9 @@ impl EguiComponent for Constant { ui, self.id.clone(), resp, - &mut self.egui_x.properties_window, + &mut context.properties_window, |ui| { - input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); if let Signal::Data(d) = &mut self.value { ui.add(egui::Slider::new(d, u32::MIN..=u32::MAX).text("value")); @@ -111,14 +125,13 @@ impl EguiComponent for Constant { fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { let own_pos = Vec2::new(self.pos.0, self.pos.1); - vec![(String::from("out"), Pos2::new(10f32, 0f32) + own_pos)] + vec![( + crate::components::CONSTANT_OUT_ID.to_string(), + Pos2::new(10f32, 0f32) + own_pos, + )] } fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } - - fn set_id_tmp(&mut self) { - self.egui_x.id_tmp = self.id.clone(); - } } diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 4dc50b8c..0d174ca4 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -1,6 +1,7 @@ use crate::common::{EguiComponent, SignalUnsigned, Simulator}; use crate::components::Mux; use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; #[typetag::serde] @@ -8,6 +9,7 @@ impl EguiComponent for Mux { fn render( &self, ui: &mut egui::Ui, + _context: &mut EguiExtra, simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, @@ -26,7 +28,7 @@ impl EguiComponent for Mux { // selector, here we can treat Signal better (see Vizia counterpart) let select: SignalUnsigned = match simulator { - Some(s) => s.get_input_val(&self.select.input).try_into().unwrap(), + Some(s) => s.get_input_val(&self.select).try_into().unwrap(), None => 0, }; diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index d0d0a00e..a54d0e05 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -1,9 +1,10 @@ use crate::common::{EguiComponent, Ports, Signal, SignalUnsigned, Simulator}; use crate::components::Probe; use crate::gui_egui::component_ui::{ - input_port, input_selector, pos_slider, properties_window, rect_with_hover, + input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::gui::EguiExtra; use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Vec2}; #[typetag::serde] @@ -11,6 +12,7 @@ impl EguiComponent for Probe { fn render( &self, ui: &mut egui::Ui, + _context: &mut EguiExtra, simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, @@ -20,9 +22,9 @@ impl EguiComponent for Probe { let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; - let input_port = self.input_port.clone(); + let input = self.input.clone(); let value = match simulator { - Some(s) => s.get_input_val(&input_port.input), + Some(s) => s.get_input_val(&input), None => Signal::Data(0), }; let area = Area::new(self.id.to_string()) @@ -65,6 +67,7 @@ impl EguiComponent for Probe { fn render_editor( &mut self, ui: &mut egui::Ui, + context: &mut EguiExtra, simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, @@ -73,8 +76,17 @@ impl EguiComponent for Probe { editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; - let r_vec = - Probe::render(self, ui, simulator, offset, scale, clip_rect, editor_mode).unwrap(); + let r_vec = Probe::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); let resp = &r_vec[0]; if resp.dragged_by(egui::PointerButton::Primary) { let delta = resp.drag_delta() / scale; @@ -91,12 +103,17 @@ impl EguiComponent for Probe { ui, self.id.clone(), resp, - &mut self.egui_x.properties_window, + &mut context.properties_window, |ui| { let mut clicked_dropdown = false; - input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); - clicked_dropdown |= input_selector(ui, &mut self.input_port, id_ports); + clicked_dropdown |= input_selector( + ui, + &mut self.input, + crate::components::PROBE_IN_ID.to_string(), + id_ports, + ); clicked_dropdown }, ); @@ -120,7 +137,7 @@ impl EguiComponent for Probe { fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { let own_pos = Vec2::new(self.pos.0, self.pos.1); vec![( - self.input_port.port_id.clone(), + crate::components::PROBE_IN_ID.to_string(), Pos2::new(-10f32, 0f32) + own_pos, )] } @@ -128,8 +145,4 @@ impl EguiComponent for Probe { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } - - fn set_id_tmp(&mut self) { - self.egui_x.id_tmp = self.id.clone(); - } } diff --git a/src/gui_egui/components/probe_edit.rs b/src/gui_egui/components/probe_edit.rs index 0c0ce7a7..0cf764f0 100644 --- a/src/gui_egui/components/probe_edit.rs +++ b/src/gui_egui/components/probe_edit.rs @@ -1,6 +1,7 @@ use crate::common::{EguiComponent, Simulator}; use crate::components::ProbeEdit; use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::gui::EguiExtra; use egui::Rect; #[typetag::serde] @@ -8,6 +9,7 @@ impl EguiComponent for ProbeEdit { fn render( &self, _ui: &mut egui::Ui, + _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, _offset: egui::Vec2, _scale: f32, diff --git a/src/gui_egui/components/probe_out.rs b/src/gui_egui/components/probe_out.rs index 300f4154..24f324f7 100644 --- a/src/gui_egui/components/probe_out.rs +++ b/src/gui_egui/components/probe_out.rs @@ -1,6 +1,7 @@ use crate::common::{EguiComponent, Simulator}; use crate::components::ProbeOut; use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::gui::EguiExtra; use egui::Rect; #[typetag::serde] @@ -8,6 +9,7 @@ impl EguiComponent for ProbeOut { fn render( &self, _ui: &mut egui::Ui, + _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, _offset: egui::Vec2, _scale: f32, diff --git a/src/gui_egui/components/probe_stim.rs b/src/gui_egui/components/probe_stim.rs index 85caea58..53fcc07c 100644 --- a/src/gui_egui/components/probe_stim.rs +++ b/src/gui_egui/components/probe_stim.rs @@ -1,6 +1,7 @@ use crate::common::{EguiComponent, Simulator}; use crate::components::ProbeStim; use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::gui::EguiExtra; use egui::Rect; #[typetag::serde] @@ -8,6 +9,7 @@ impl EguiComponent for ProbeStim { fn render( &self, _ui: &mut egui::Ui, + _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, _offset: egui::Vec2, _scale: f32, diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index bac6e6c4..3f9733aa 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -1,6 +1,7 @@ use crate::common::{EguiComponent, Simulator}; use crate::components::Register; use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; #[typetag::serde] @@ -8,6 +9,7 @@ impl EguiComponent for Register { fn render( &self, ui: &mut egui::Ui, + _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, offset: egui::Vec2, scale: f32, diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index f27359bd..9c29cda5 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -1,12 +1,14 @@ use crate::common::{EguiComponent, Simulator}; use crate::components::Sext; use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::gui::EguiExtra; #[typetag::serde] impl EguiComponent for Sext { fn render( &self, _ui: &mut egui::Ui, + _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, _offset: egui::Vec2, _scale: f32, diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 7cd9f976..a58bf1ed 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -1,9 +1,8 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; use crate::components::Wire; -use crate::gui_egui::component_ui::{ - input_port, input_selector, pos_slider, properties_window, rect_with_hover, -}; +use crate::gui_egui::component_ui::*; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, SnapPriority}; +use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; use egui::{Color32, PointerButton, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; @@ -12,6 +11,7 @@ impl EguiComponent for Wire { fn render( &self, ui: &mut Ui, + _context: &mut EguiExtra, simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, @@ -57,7 +57,7 @@ impl EguiComponent for Wire { if let Some(s) = &simulator { ui.label({ let r: Result = - s.get_input_val(&self.input_port.input).try_into(); + s.get_input_val(&self.input).try_into(); match r { Ok(data) => format!("{:#x}", data), _ => format!("{:?}", r), @@ -74,6 +74,7 @@ impl EguiComponent for Wire { fn render_editor( &mut self, ui: &mut Ui, + context: &mut EguiExtra, simulator: Option<&mut Simulator>, offset: Vec2, scale: f32, @@ -82,8 +83,17 @@ impl EguiComponent for Wire { editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; - let r_vec = - Wire::render(self, ui, simulator, offset, scale, clip_rect, editor_mode).unwrap(); + let r_vec = Wire::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); for (i, resp) in r_vec.iter().enumerate() { if resp.dragged_by(PointerButton::Primary) { @@ -100,13 +110,18 @@ impl EguiComponent for Wire { ui, self.id.clone(), resp, - &mut self.egui_x.properties_window, + &mut context.properties_window, |ui| { let mut clicked_dropdown = false; - input_port(ui, &mut self.egui_x.id_tmp, &mut self.id, id_ports); + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos[i]); pos_slider(ui, &mut self.pos[i + 1]); - clicked_dropdown |= input_selector(ui, &mut self.input_port, id_ports); + clicked_dropdown |= input_selector( + ui, + &mut self.input, + crate::components::WIRE_INPUT_ID.to_string(), + id_ports, + ); clicked_dropdown }, ); @@ -133,7 +148,7 @@ impl EguiComponent for Wire { let mut vec: Vec<(crate::common::Id, Pos2)> = vec![]; for (i, pos) in self.pos.iter().enumerate() { vec.push(( - format!("{}-{}", self.input_port.port_id, i), + format!("{}-{}", crate::components::WIRE_INPUT_ID, i), Pos2 { x: pos.0, y: pos.1 }, )); } @@ -143,8 +158,4 @@ impl EguiComponent for Wire { fn snap_priority(&self) -> SnapPriority { SnapPriority::Wire } - - fn set_id_tmp(&mut self) { - self.egui_x.id_tmp = self.id.clone(); - } } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 88d208cd..d883e931 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -1,5 +1,6 @@ use crate::common::{ComponentStore, Components, EguiComponent, Id, Input}; use crate::components::*; +use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::{ editor_wire_mode::WireMode, gui::Gui, @@ -10,7 +11,7 @@ use crate::gui_egui::{ }; use eframe::{egui, Frame}; use egui::{Color32, Context, LayerId, PointerButton, Pos2, Rect, Vec2}; -use std::{path::Path, rc::Rc}; +use std::{collections::HashMap, path::Path, rc::Rc}; pub struct Editor { pub components: Components, @@ -26,6 +27,7 @@ pub struct Editor { pub editor_mode: EditorMode, pub wm: WireMode, pub im: InputMode, + pub contexts: HashMap, } #[derive(Clone)] @@ -60,7 +62,7 @@ pub enum SnapPriority { impl Editor { pub fn gui(components: Components, _path: &Path) -> Self { let dummy_input = Input::new("id", "field"); - Editor { + let mut e = Editor { components, scale: 1f32, pan: Vec2::new(0f32, 0f32), @@ -77,14 +79,22 @@ impl Editor { ui_change: true, library: ComponentStore { store: vec![ - Rc::new(Add::new( - "add", - (0.0, 0.0), - dummy_input.clone(), - dummy_input.clone(), - )), - Rc::new(Constant::new("c", (0.0, 0.0), 0)), - Rc::new(Probe::new("p", (0.0, 0.0), dummy_input.clone())), + Rc::new(Add { + id: "add".to_string(), + pos: (0.0, 0.0), + a_in: dummy_input.clone(), + b_in: dummy_input.clone(), + }), + Rc::new(Constant { + id: "c".to_string(), + pos: (0.0, 0.0), + value: 0.into(), + }), + Rc::new(Probe { + id: "p".to_string(), + pos: (0.0, 0.0), + input: dummy_input.clone(), + }), ], }, dummy_input, @@ -101,7 +111,10 @@ impl Editor { comp: None, cursor_location: Pos2::ZERO, }, - } + contexts: HashMap::new(), + }; + e.contexts = crate::gui_egui::gui::create_contexts(&e.components); + e } pub fn update(ctx: &Context, _frame: &mut Frame, gui: &mut Gui) { @@ -216,29 +229,35 @@ impl Editor { match e.editor_mode { EditorMode::Wire | EditorMode::Input => { for c in &e.components { + let old_key = c.as_ref().get_id_ports().0; + let mut context = e.contexts.remove(&old_key).unwrap(); c.render( ui, + &mut context, None, e.offset + e.pan, e.scale, e.clip_rect, e.editor_mode, ); + e.contexts.insert(context.id_tmp.clone(), context); } } _ => e.components.retain_mut(|c| { - let delete = (*Rc::get_mut(c).unwrap()) - .render_editor( - ui, - None, - e.offset_and_pan, - e.scale, - e.clip_rect, - &id_ports, - e.editor_mode, - ) - .delete; - !delete + let old_key = c.as_ref().get_id_ports().0; + let mut context = e.contexts.remove(&old_key).unwrap(); + let render_return = (*Rc::get_mut(c).unwrap()).render_editor( + ui, + &mut context, + None, + e.offset_and_pan, + e.scale, + e.clip_rect, + &id_ports, + e.editor_mode, + ); + e.contexts.insert(context.id_tmp.clone(), context); + !render_return.delete }), } }); diff --git a/src/gui_egui/editor_wire_mode.rs b/src/gui_egui/editor_wire_mode.rs index 6979f6ab..4997eb61 100644 --- a/src/gui_egui/editor_wire_mode.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -1,7 +1,7 @@ use crate::common::{Components, Id, Input}; use crate::components::Wire; -use crate::gui_egui::editor::SnapPriority; -use crate::gui_egui::editor::{get_component, CloseToComponent, Editor}; +use crate::gui_egui::editor::{get_component, CloseToComponent, Editor, SnapPriority}; +use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::{ id_ports_of_all_components, offset_helper, offset_reverse_helper, offset_reverse_helper_pos2, unique_component_name, @@ -83,7 +83,19 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { if !Rc::ptr_eq(&in_c.comp, &out_c.comp) { let comp = if is_input_in_comp_start { out_c } else { in_c }; println!("comp: {:?}", comp.port_id); - e.components.push(Rc::new(Wire::new(id, pos_v, i.clone()))); + e.components.push(Rc::new(Wire { + id: id.to_string(), + pos: pos_v, + input: i.clone(), + })); + e.contexts.insert( + id.to_string(), + EguiExtra { + properties_window: false, + id_tmp: id.to_string(), + }, + ); + if let Some(c) = get_component(&e.components, comp) { println!("setting id_port"); diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index d741a7b6..ac5be99d 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -1,7 +1,8 @@ -use crate::common::{ComponentStore, Simulator}; +use crate::common::{ComponentStore, Components, Simulator}; use crate::gui_egui::editor::EditorMode; use crate::gui_egui::{editor::Editor, keymap, keymap::Shortcuts, menu::Menu}; use eframe::egui; +use std::collections::HashMap; use std::path::PathBuf; pub struct Gui { @@ -18,13 +19,22 @@ pub struct Gui { pub pause: bool, pub editor: Option, pub editor_use: bool, + pub contexts: HashMap, +} + +#[derive(Clone, Default, Debug)] +pub struct EguiExtra { + pub properties_window: bool, + pub id_tmp: String, } pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { + let contexts = create_contexts(&cs.store); let simulator = Simulator::new(cs); let options = eframe::NativeOptions::default(); let path = path.to_owned(); simulator.save_dot(&path); + println!("contexts: {:?}", contexts); let gui = Gui { path, @@ -38,6 +48,7 @@ pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { pause: true, editor: None, editor_use: false, + contexts, }; eframe::run_native("SyncRim", options, Box::new(|_cc| Box::new(gui))) @@ -119,14 +130,18 @@ impl Gui { ui.set_clip_rect(self.clip_rect); // Don't draw over the rest of the ui for c in &sim.ordered_components.clone() { + let old_key = c.as_ref().get_id_ports().0; + let mut context = self.contexts.remove(&old_key).unwrap(); c.render( ui, + &mut context, Some(sim), self.offset + self.pan, self.scale, self.clip_rect, EditorMode::Default, ); + self.contexts.insert(context.id_tmp.clone(), context); } }); let cpr = central_panel.response.interact(egui::Sense::drag()); @@ -159,3 +174,18 @@ impl Gui { egui::TopBottomPanel::top("topBar").show(ctx, |ui| Menu::new(ui, self)); } } + +pub fn create_contexts(components: &Components) -> HashMap { + let mut contexts = HashMap::new(); + for c in &components.clone() { + let id = c.get_id_ports().0; + contexts.insert( + id.clone(), + EguiExtra { + properties_window: false, + id_tmp: id, + }, + ); + } + contexts +} diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 7711345a..5a541f92 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -1,11 +1,12 @@ use crate::common::{ComponentStore, Simulator}; use crate::gui_egui::editor::{Editor, EditorMode}; use crate::gui_egui::editor_wire_mode::reset_wire_mode; +use crate::gui_egui::gui::create_contexts; use crate::gui_egui::library::reset_input_mode; use crate::gui_egui::Gui; use egui::{Key, KeyboardShortcut, Modifiers}; use rfd::FileDialog; -use std::{path::PathBuf, rc::Rc}; +use std::path::PathBuf; #[derive(Copy, Clone)] pub struct Shortcuts { @@ -274,6 +275,7 @@ pub fn file_editor_toggle_fn(gui: &mut Gui) { gui.editor_use = false; if let Some(e) = gui.editor.as_mut() { let components = e.components.clone(); + gui.contexts = create_contexts(&components); let simulator = Simulator::new(ComponentStore { store: components }); gui.simulator = Some(simulator); } @@ -282,13 +284,10 @@ pub fn file_editor_toggle_fn(gui: &mut Gui) { let editor_existed: bool = gui.editor.as_mut().is_some(); let simulator = gui.simulator.take().unwrap(); - let mut components = simulator.ordered_components; + let components = simulator.ordered_components; if !editor_existed { - for c in components.iter_mut() { - (*Rc::get_mut(c).unwrap()).set_id_tmp(); - } - let _ = gui.editor.insert(Editor::gui(components, &gui.path)); + gui.editor = Some(Editor::gui(components, &gui.path)); } gui.editor_use = true; diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index 2782f426..479c9cd6 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -1,6 +1,7 @@ use crate::common::EguiComponent; use crate::components::*; use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::{ editor::Editor, helper::{id_ports_of_all_components, offset_reverse_helper_pos2, unique_component_name}, @@ -38,6 +39,7 @@ pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option ); e.im.comp.as_ref().unwrap().render( &mut ui, + &mut EguiExtra::default(), None, Vec2::new(e.im.cursor_location.x, e.im.cursor_location.y), e.scale, @@ -74,7 +76,18 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { let size = c.size(); padding.y -= e.scale * size.min.y; let r_vec = c - .render(ui, None, padding, e.scale, clip_rect, e.editor_mode) + .render( + ui, + &mut EguiExtra { + properties_window: false, + id_tmp: c.get_id_ports().0, + }, + None, + padding, + e.scale, + clip_rect, + e.editor_mode, + ) .unwrap(); let rect = r_vec[0].rect; for resp in r_vec { @@ -98,32 +111,45 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { pub fn add_comp_to_editor(e: &mut Editor) { let pos = offset_reverse_helper_pos2(e.im.cursor_location, e.scale, e.offset); let id_ports = id_ports_of_all_components(&e.components); + let id; let mut comp: Rc = match e.im.comp.as_mut().unwrap().get_id_ports().0.as_str() { "c" => { - let id = unique_component_name(&id_ports, "c"); - Rc::new(Constant::new(id.as_str(), (0.0, 0.0), 0)) + id = unique_component_name(&id_ports, "c"); + Rc::new(Constant { + id: id.clone(), + pos: (0.0, 0.0), + value: 0.into(), + }) } "p" => { - let id = unique_component_name(&id_ports, "p"); - Rc::new(Probe::new(id.as_str(), (0.0, 0.0), e.dummy_input.clone())) + id = unique_component_name(&id_ports, "p"); + Rc::new(Probe { + id: id.clone(), + pos: (0.0, 0.0), + input: e.dummy_input.clone(), + }) } "add" => { - let id = unique_component_name(&id_ports, "add"); - Rc::new(Add::new( - id.as_str(), - (0.0, 0.0), - e.dummy_input.clone(), - e.dummy_input.clone(), - )) + id = unique_component_name(&id_ports, "add"); + Rc::new(Add { + id: id.clone(), + pos: (0.0, 0.0), + a_in: e.dummy_input.clone(), + b_in: e.dummy_input.clone(), + }) } _ => todo!(), }; Rc::::get_mut(&mut comp) .unwrap() .set_pos((pos.x, pos.y)); - Rc::::get_mut(&mut comp) - .unwrap() - .set_id_tmp(); + e.contexts.insert( + id.clone(), + EguiExtra { + properties_window: false, + id_tmp: id, + }, + ); e.components.push(comp); } diff --git a/src/gui_egui/mod.rs b/src/gui_egui/mod.rs index fa0565f2..a0819435 100644 --- a/src/gui_egui/mod.rs +++ b/src/gui_egui/mod.rs @@ -1,7 +1,7 @@ mod component_ui; pub mod editor; mod editor_wire_mode; -mod gui; +pub mod gui; pub mod helper; mod keymap; mod library; diff --git a/src/gui_vizia/components/mux.rs b/src/gui_vizia/components/mux.rs index bf48df89..dcc48601 100644 --- a/src/gui_vizia/components/mux.rs +++ b/src/gui_vizia/components/mux.rs @@ -19,7 +19,7 @@ impl ViziaComponent for Mux { View::build( MuxView { - select: self.select.input.clone(), + select: self.select.clone(), select_max: self.m_in.len() as u8, }, cx, diff --git a/src/gui_vizia/components/probe.rs b/src/gui_vizia/components/probe.rs index 800664ea..04d854cc 100644 --- a/src/gui_vizia/components/probe.rs +++ b/src/gui_vizia/components/probe.rs @@ -17,7 +17,7 @@ impl ViziaComponent for Probe { fn view(&self, cx: &mut Context) { trace!("---- Create Probe View"); View::build(ProbeView {}, cx, |cx| { - let input = self.input_port.input.clone(); + let input = self.input.clone(); Binding::new( cx, diff --git a/src/main.rs b/src/main.rs index efe79744..59da71f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,6 @@ fn main() { #[cfg(feature = "gui-vizia")] syncrim::gui_vizia::gui(cs, &_path); - // run headless #[cfg(not(any(feature = "gui-vizia", feature = "gui-egui")))] syncrim::common::Simulator::new(cs); } From 53fd94e90d314dd261e510e94136f08bc0ded460 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Wed, 26 Jul 2023 21:06:31 +0200 Subject: [PATCH 33/58] Forgot to fix 3 examples --- examples/add_edit.rs | 4 ++-- examples/mux.rs | 4 ++-- examples/probe_edit.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/add_edit.rs b/examples/add_edit.rs index 11761cb6..b36f1b77 100644 --- a/examples/add_edit.rs +++ b/examples/add_edit.rs @@ -45,8 +45,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/mux.rs b/examples/mux.rs index adbcf345..17c56f3b 100644 --- a/examples/mux.rs +++ b/examples/mux.rs @@ -87,8 +87,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/probe_edit.rs b/examples/probe_edit.rs index 4dc9e0e2..e688d6df 100644 --- a/examples/probe_edit.rs +++ b/examples/probe_edit.rs @@ -22,8 +22,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } From c8c7657256e29ba50a419b0277da4114673f05ae Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Thu, 27 Jul 2023 14:23:36 +0200 Subject: [PATCH 34/58] Added sext and mem and fixed some stuff --- src/common.rs | 4 +- src/components/mem.rs | 17 ++- src/components/sext.rs | 10 +- src/gui_egui/component_ui.rs | 22 +-- src/gui_egui/components/add.rs | 54 ++++---- src/gui_egui/components/constant.rs | 33 ++--- src/gui_egui/components/mem.rs | 204 +++++++++++++++++++++++++++- src/gui_egui/components/probe.rs | 32 ++--- src/gui_egui/components/sext.rs | 151 ++++++++++++++++++-- src/gui_egui/components/wire.rs | 12 +- src/gui_egui/editor.rs | 65 ++++++--- src/gui_egui/editor_wire_mode.rs | 3 +- src/gui_egui/gui.rs | 66 ++++----- src/gui_egui/library.rs | 43 +++++- 14 files changed, 555 insertions(+), 161 deletions(-) diff --git a/src/common.rs b/src/common.rs index ccdca2f4..620dfe5d 100644 --- a/src/common.rs +++ b/src/common.rs @@ -162,8 +162,8 @@ pub trait EguiComponent: Component { } } - fn size(&self) -> egui::Rect { - egui::Rect::NOTHING + fn top_padding(&self) -> f32 { + todo!("Create top_padding for this EguiComponent"); } /// Get ports location relative to self, (inputs, outputs) diff --git a/src/components/mem.rs b/src/components/mem.rs index a2a58270..50512c52 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -14,8 +14,8 @@ pub const MEM_CTRL_ID: &str = "ctrl"; pub const MEM_SIGN_ID: &str = "sign"; pub const MEM_SIZE_ID: &str = "size"; -pub const MEM_DATA_OUT: &str = "data"; -pub const MEM_ERR_OUT: &str = "err"; +pub const MEM_DATA_OUT_ID: &str = "data"; +pub const MEM_ERR_OUT_ID: &str = "err"; #[derive(Serialize, Deserialize)] pub struct Mem { @@ -216,7 +216,7 @@ impl Component for Mem { }, ], OutputType::Combinatorial, - vec![MEM_DATA_OUT, MEM_ERR_OUT], + vec![MEM_DATA_OUT_ID, MEM_ERR_OUT_ID], ), ) } @@ -255,6 +255,17 @@ impl Component for Mem { trace!("memory {:?}", self.memory); } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + MEM_DATA_ID => self.data = new_input, + MEM_ADDR_ID => self.addr = new_input, + MEM_CTRL_ID => self.ctrl = new_input, + MEM_SIGN_ID => self.sign = new_input, + MEM_SIZE_ID => self.size = new_input, + _ => (), + } + } } #[cfg(test)] mod test { diff --git a/src/components/sext.rs b/src/components/sext.rs index df429688..dd3c02fb 100644 --- a/src/components/sext.rs +++ b/src/components/sext.rs @@ -8,6 +8,8 @@ use serde::{Deserialize, Serialize}; pub const SEXT_IN_ID: &str = "sext_in"; +pub const SEXT_OUT_ID: &str = "out"; + #[derive(Serialize, Deserialize, Clone)] pub struct Sext { pub id: Id, @@ -32,11 +34,17 @@ impl Component for Sext { input: self.sext_in.clone(), }], OutputType::Combinatorial, - vec!["out"], + vec![SEXT_OUT_ID], ), ) } + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + if target_port_id.as_str() == SEXT_IN_ID { + self.sext_in = new_input + } + } + // propagate sign extension to output // TODO: always extend to Signal size? (it should not matter and should be slightly cheaper) fn clock(&self, simulator: &mut Simulator) { diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index f5b87cf4..339e08b3 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -1,7 +1,10 @@ use crate::common::{Input, Ports}; use crate::gui_egui::editor::EditorMode; use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; -use egui::{ComboBox, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, Ui, Window}; +use egui::{ + containers, ComboBox, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, Slider, Ui, + Window, +}; use epaint::Shadow; pub fn rect_with_hover

( @@ -19,7 +22,7 @@ where let r = ui.allocate_rect(rect, editor_mode_to_sense(editor_mode)); if r.hovered() && !r.dragged() { - egui::containers::popup::show_tooltip_for(ui.ctx(), egui::Id::new(id), &rect, |ui| { + containers::popup::show_tooltip_for(ui.ctx(), egui::Id::new(id), &rect, |ui| { f(ui); }); } @@ -66,12 +69,12 @@ pub fn properties_window

( pub fn pos_slider(ui: &mut Ui, pos: &mut (f32, f32)) { ui.horizontal(|ui| { ui.add( - egui::Slider::new(&mut pos.0, 0f32..=1000f32) + Slider::new(&mut pos.0, 0f32..=1000f32) .text("pos x") .clamp_to_range(false), ); ui.add( - egui::Slider::new(&mut pos.1, 0f32..=1000f32) + Slider::new(&mut pos.1, 0f32..=1000f32) .text("pos y") .clamp_to_range(false), ); @@ -81,15 +84,15 @@ pub fn pos_slider(ui: &mut Ui, pos: &mut (f32, f32)) { pub fn input_selector( ui: &mut Ui, input: &mut Input, - // Why is this marked as unused, it's clearly being used? - #[allow(unused_variables)] port_id: crate::common::Id, + port_name: crate::common::Id, id_ports: &[(crate::common::Id, Ports)], + own_id: crate::common::Id, ) -> bool { let mut port_id = input.id.clone(); let mut port_field = input.field.clone(); - let label_port_id = format!("{}.id", port_id.clone()); + let label_port_id = format!("{}.id", port_name.clone()); let text_port_id = port_id.to_string(); - let label_port_field = format!("{}.field", port_id.clone()); + let label_port_field = format!("{}.field", port_name.clone()); let text_port_field = port_field.to_string(); ui.horizontal(|ui| { ComboBox::from_label(label_port_id) @@ -97,6 +100,9 @@ pub fn input_selector( .show_ui(ui, |ui| { for c in id_ports { let id = c.0.clone(); + if id == own_id { + continue; + } ui.selectable_value(&mut port_id, id.clone(), id); } }); diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 4fffb8ae..05b49c7d 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -8,30 +8,30 @@ use crate::{ common::{EguiComponent, Ports, Simulator}, components::Add, }; -use egui::{PointerButton, Pos2, Rect, Vec2}; +use egui::{Color32, PointerButton, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Add { fn render( &self, - ui: &mut egui::Ui, + ui: &mut Ui, _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, - offset: egui::Vec2, + offset: Vec2, scale: f32, - clip_rect: egui::Rect, + clip_rect: Rect, editor_mode: EditorMode, - ) -> Option> { + ) -> Option> { // 41x81 // middle: 21x 41y (0 0) - let oh: fn((f32, f32), f32, Vec2) -> egui::Pos2 = offset_helper; + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; let s = scale; let o = offset; // The shape - ui.painter().add(egui::Shape::closed_line( + ui.painter().add(Shape::closed_line( vec![ oh((-20f32, -40f32), s, o), oh((0f32, -40f32), s, o), @@ -43,27 +43,27 @@ impl EguiComponent for Add { oh((-10f32, 0f32), s, o), oh((-20f32, -20f32), s, o), ], - egui::Stroke { + Stroke { width: scale, - color: egui::Color32::RED, + color: Color32::RED, }, )); // plus sign - ui.painter().add(egui::Shape::line_segment( + ui.painter().add(Shape::line_segment( [oh((0f32, 0f32), s, o), oh((10f32, 0f32), s, o)], - egui::Stroke { + Stroke { width: scale, - color: egui::Color32::BLACK, + color: Color32::BLACK, }, )); - ui.painter().add(egui::Shape::line_segment( + ui.painter().add(Shape::line_segment( [oh((5f32, -5f32), s, o), oh((5f32, 5f32), s, o)], - egui::Stroke { + Stroke { width: scale, - color: egui::Color32::BLACK, + color: Color32::BLACK, }, )); - let rect = egui::Rect { + let rect = Rect { min: oh((-20f32, -40f32), s, o), max: oh((20f32, 40f32), s, o), }; @@ -76,12 +76,12 @@ impl EguiComponent for Add { fn render_editor( &mut self, - ui: &mut egui::Ui, + ui: &mut Ui, context: &mut EguiExtra, simulator: Option<&mut Simulator>, - offset: egui::Vec2, + offset: Vec2, scale: f32, - clip_rect: egui::Rect, + clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { @@ -123,12 +123,14 @@ impl EguiComponent for Add { &mut self.a_in, crate::components::ADD_A_IN_ID.to_string(), id_ports, + self.id.clone(), ); clicked_dropdown |= input_selector( ui, &mut self.b_in, crate::components::ADD_B_IN_ID.to_string(), id_ports, + self.id.clone(), ); clicked_dropdown }, @@ -140,16 +142,6 @@ impl EguiComponent for Add { } } - fn size(&self) -> Rect { - Rect { - min: Pos2 { - x: -20f32, - y: -40f32, - }, - max: Pos2 { x: 20f32, y: 40f32 }, - } - } - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { let own_pos = Vec2::new(self.pos.0, self.pos.1); vec![ @@ -172,6 +164,10 @@ impl EguiComponent for Add { ] } + fn top_padding(&self) -> f32 { + 40f32 + } + fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index eb1ddfac..68baaf20 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -5,20 +5,22 @@ use crate::gui_egui::component_ui::{ }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; -use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Vec2}; +use egui::{ + Align2, Area, Color32, Order, PointerButton, Pos2, Rect, Response, RichText, Slider, Ui, Vec2, +}; #[typetag::serde] impl EguiComponent for Constant { fn render( &self, - ui: &mut egui::Ui, + ui: &mut Ui, _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, - offset: egui::Vec2, + offset: Vec2, scale: f32, clip_rect: Rect, editor_mode: EditorMode, - ) -> Option> { + ) -> Option> { let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -60,12 +62,12 @@ impl EguiComponent for Constant { fn render_editor( &mut self, - ui: &mut egui::Ui, + ui: &mut Ui, context: &mut EguiExtra, simulator: Option<&mut Simulator>, - offset: egui::Vec2, + offset: Vec2, scale: f32, - clip_rect: egui::Rect, + clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { @@ -101,7 +103,7 @@ impl EguiComponent for Constant { input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); pos_slider(ui, &mut self.pos); if let Signal::Data(d) = &mut self.value { - ui.add(egui::Slider::new(d, u32::MIN..=u32::MAX).text("value")); + ui.add(Slider::new(d, u32::MIN..=u32::MAX).text("value")); } false }, @@ -113,16 +115,6 @@ impl EguiComponent for Constant { } } - fn size(&self) -> Rect { - Rect { - min: Pos2 { - x: -10f32, - y: -10f32, - }, - max: Pos2 { x: 10f32, y: 10f32 }, - } - } - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { let own_pos = Vec2::new(self.pos.0, self.pos.1); vec![( @@ -131,6 +123,11 @@ impl EguiComponent for Constant { )] } + fn top_padding(&self) -> f32 { + // todo: make this accurate? + 10f32 + } + fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } diff --git a/src/gui_egui/components/mem.rs b/src/gui_egui/components/mem.rs index 24704d24..85bfb4f3 100644 --- a/src/gui_egui/components/mem.rs +++ b/src/gui_egui/components/mem.rs @@ -1,5 +1,205 @@ -use crate::common::EguiComponent; +use crate::common::{EguiComponent, Ports, Simulator}; use crate::components::Mem; +use crate::gui_egui::component_ui::{ + input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{ + Color32, PointerButton, Pos2, Rect, Response, Rounding, Shape, Slider, Stroke, Ui, Vec2, +}; #[typetag::serde] -impl EguiComponent for Mem {} +impl EguiComponent for Mem { + fn render( + &self, + ui: &mut Ui, + _context: &mut EguiExtra, + _simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 201x101 + // middle: 101x 51y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + + // The shape + let rect = Rect { + min: oh((-self.width / 2f32, -self.height / 2f32), s, o), + max: oh((self.width / 2f32, self.height / 2f32), s, o), + }; + ui.painter().add(Shape::rect_stroke( + rect, + Rounding::none(), + Stroke { + width: scale, + color: Color32::BLACK, + }, + )); + + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + ui.label("mem"); + }); + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let mut delete = false; + let r_vec = Mem::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + context.size_rect = resp.rect; + if resp.dragged_by(PointerButton::Primary) { + let delta = resp.drag_delta() / scale; + self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); + } + + if resp.drag_released_by(PointerButton::Primary) + && resp.interact_pointer_pos().unwrap().x < offset.x + { + delete = true; + } + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_slider(ui, &mut self.pos); + ui.horizontal(|ui| { + ui.add(Slider::new(&mut self.width, 0f32..=400f32).text("width")); + ui.add(Slider::new(&mut self.height, 0f32..=400f32).text("height")); + }); + clicked_dropdown |= input_selector( + ui, + &mut self.data, + crate::components::MEM_DATA_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.addr, + crate::components::MEM_ADDR_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.ctrl, + crate::components::MEM_CTRL_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.sign, + crate::components::MEM_SIGN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown |= input_selector( + ui, + &mut self.size, + crate::components::MEM_SIZE_ID.to_string(), + id_ports, + self.id.clone(), + ); + // todo: something about memory? + clicked_dropdown + }, + ); + + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::MEM_DATA_ID.to_string(), + Pos2::new( + self.width / 10f32 * 1f32 - self.width / 2f32, + -self.height / 2f32, + ) + own_pos, + ), + ( + crate::components::MEM_ADDR_ID.to_string(), + Pos2::new( + self.width / 10f32 * 2f32 - self.width / 2f32, + -self.height / 2f32, + ) + own_pos, + ), + ( + crate::components::MEM_CTRL_ID.to_string(), + Pos2::new( + self.width / 10f32 * 3f32 - self.width / 2f32, + -self.height / 2f32, + ) + own_pos, + ), + ( + crate::components::MEM_SIGN_ID.to_string(), + Pos2::new( + self.width / 10f32 * 4f32 - self.width / 2f32, + -self.height / 2f32, + ) + own_pos, + ), + ( + crate::components::MEM_SIZE_ID.to_string(), + Pos2::new( + -self.width / 10f32 * 3f32 + self.width / 2f32, + -self.height / 2f32, + ) + own_pos, + ), + ( + crate::components::MEM_DATA_OUT_ID.to_string(), + Pos2::new( + -self.width / 10f32 * 2f32 + self.width / 2f32, + -self.height / 2f32, + ) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + self.height / 2f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } +} diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index a54d0e05..aa6fd488 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -5,20 +5,20 @@ use crate::gui_egui::component_ui::{ }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; -use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, RichText, Vec2}; +use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Probe { fn render( &self, - ui: &mut egui::Ui, + ui: &mut Ui, _context: &mut EguiExtra, simulator: Option<&mut Simulator>, - offset: egui::Vec2, + offset: Vec2, scale: f32, clip_rect: Rect, editor_mode: EditorMode, - ) -> Option> { + ) -> Option> { let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -66,12 +66,12 @@ impl EguiComponent for Probe { fn render_editor( &mut self, - ui: &mut egui::Ui, + ui: &mut Ui, context: &mut EguiExtra, simulator: Option<&mut Simulator>, - offset: egui::Vec2, + offset: Vec2, scale: f32, - clip_rect: egui::Rect, + clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { @@ -88,7 +88,7 @@ impl EguiComponent for Probe { ) .unwrap(); let resp = &r_vec[0]; - if resp.dragged_by(egui::PointerButton::Primary) { + if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta() / scale; self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } @@ -113,6 +113,7 @@ impl EguiComponent for Probe { &mut self.input, crate::components::PROBE_IN_ID.to_string(), id_ports, + self.id.clone(), ); clicked_dropdown }, @@ -124,16 +125,6 @@ impl EguiComponent for Probe { } } - fn size(&self) -> Rect { - Rect { - min: Pos2 { - x: -10f32, - y: -10f32, - }, - max: Pos2 { x: 10f32, y: 10f32 }, - } - } - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { let own_pos = Vec2::new(self.pos.0, self.pos.1); vec![( @@ -142,6 +133,11 @@ impl EguiComponent for Probe { )] } + fn top_padding(&self) -> f32 { + // todo: make this accurate? + 10f32 + } + fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index 9c29cda5..a0b8b7d0 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -1,20 +1,151 @@ -use crate::common::{EguiComponent, Simulator}; +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; use crate::components::Sext; -use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::component_ui::{ + input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; +use crate::gui_egui::helper::offset_helper; +use egui::{Color32, PointerButton, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Sext { fn render( &self, - _ui: &mut egui::Ui, + ui: &mut Ui, _context: &mut EguiExtra, - _simulator: Option<&mut Simulator>, - _offset: egui::Vec2, - _scale: f32, - _clip_rect: egui::Rect, - _editor_mode: EditorMode, - ) -> Option> { - todo!(); + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + // 81x41 + // middle: 41x 21y (0 0) + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let s = scale; + let o = offset; + // The shape + ui.painter().add(Shape::closed_line( + vec![ + oh((-40f32, 0f32), s, o), + oh((40f32, -20f32), s, o), + oh((40f32, 20f32), s, o), + oh((-40f32, 20f32), s, o), + ], + Stroke { + width: scale, + color: Color32::RED, + }, + )); + + let rect = Rect { + min: oh((-40f32, -20f32), s, o), + max: oh((40f32, 20f32), s, o), + }; + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + // todo: is this actually correct? + if let Some(s) = &simulator { + ui.label({ + let r: Result = + s.get_input_val(&self.sext_in).try_into(); + match r { + Ok(data) => format!("{:#x}", data), + _ => format!("{:?}", r), + } + }); + } + }); + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let mut delete = false; + let r_vec = Sext::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + if resp.dragged_by(PointerButton::Primary) { + let delta = resp.drag_delta() / scale; + self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); + } + + if resp.drag_released_by(PointerButton::Primary) + && resp.interact_pointer_pos().unwrap().x < offset.x + { + delete = true; + } + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_slider(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.sext_in, + crate::components::SEXT_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + ui.horizontal(|ui| { + ui.add(Slider::new(&mut self.in_size, 0..=32).text("in_size")); + ui.add(Slider::new(&mut self.out_size, self.in_size..=32).text("out_size")); + }); + clicked_dropdown + }, + ); + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::SEXT_IN_ID.to_string(), + Pos2::new(-40f32, 0f32) + own_pos, + ), + ( + crate::components::SEXT_OUT_ID.to_string(), + Pos2::new(40f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; } } diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index a58bf1ed..633f0b5f 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -121,6 +121,7 @@ impl EguiComponent for Wire { &mut self.input, crate::components::WIRE_INPUT_ID.to_string(), id_ports, + self.id.clone(), ); clicked_dropdown }, @@ -133,17 +134,6 @@ impl EguiComponent for Wire { } } - // This isn't really it's true size - fn size(&self) -> Rect { - Rect { - min: Pos2 { x: 0f32, y: 0f32 }, - max: Pos2 { - x: self.pos[1].0, - y: self.pos[1].1, - }, - } - } - fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { let mut vec: Vec<(crate::common::Id, Pos2)> = vec![]; for (i, pos) in self.pos.iter().enumerate() { diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index d883e931..464d0c8c 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -1,4 +1,4 @@ -use crate::common::{ComponentStore, Components, EguiComponent, Id, Input}; +use crate::common::{Components, EguiComponent, Id, Input}; use crate::components::*; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::{ @@ -22,7 +22,7 @@ pub struct Editor { pub clip_rect: Rect, pub side_panel_width: f32, pub ui_change: bool, - pub library: ComponentStore, + pub library: Components, pub dummy_input: Input, pub editor_mode: EditorMode, pub wm: WireMode, @@ -62,6 +62,45 @@ pub enum SnapPriority { impl Editor { pub fn gui(components: Components, _path: &Path) -> Self { let dummy_input = Input::new("id", "field"); + let library: Components = vec![ + Rc::new(Add { + id: "add".to_string(), + pos: (0.0, 0.0), + a_in: dummy_input.clone(), + b_in: dummy_input.clone(), + }), + Rc::new(Constant { + id: "c".to_string(), + pos: (0.0, 0.0), + value: 0.into(), + }), + Rc::new(Probe { + id: "p".to_string(), + pos: (0.0, 0.0), + input: dummy_input.clone(), + }), + Rc::new(Sext { + id: "sext".to_string(), + pos: (0.0, 0.0), + sext_in: dummy_input.clone(), + in_size: 16, + out_size: 24, + }), + Rc::new(Mem { + id: "mem".into(), + pos: (0.0, 0.0), + width: 100.0, + height: 50.0, + big_endian: true, + data: dummy_input.clone(), + addr: dummy_input.clone(), + ctrl: dummy_input.clone(), + size: dummy_input.clone(), + sign: dummy_input.clone(), + memory: Memory::new(), + }), + ]; + let library_contexts = crate::gui_egui::gui::create_contexts(&library); let mut e = Editor { components, scale: 1f32, @@ -77,26 +116,7 @@ impl Editor { }, side_panel_width: 400f32, ui_change: true, - library: ComponentStore { - store: vec![ - Rc::new(Add { - id: "add".to_string(), - pos: (0.0, 0.0), - a_in: dummy_input.clone(), - b_in: dummy_input.clone(), - }), - Rc::new(Constant { - id: "c".to_string(), - pos: (0.0, 0.0), - value: 0.into(), - }), - Rc::new(Probe { - id: "p".to_string(), - pos: (0.0, 0.0), - input: dummy_input.clone(), - }), - ], - }, + library, dummy_input, editor_mode: EditorMode::Default, wm: WireMode { @@ -110,6 +130,7 @@ impl Editor { im: InputMode { comp: None, cursor_location: Pos2::ZERO, + library_contexts, }, contexts: HashMap::new(), }; diff --git a/src/gui_egui/editor_wire_mode.rs b/src/gui_egui/editor_wire_mode.rs index 4997eb61..66f9b814 100644 --- a/src/gui_egui/editor_wire_mode.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -7,7 +7,7 @@ use crate::gui_egui::helper::{ unique_component_name, }; use egui::{ - Color32, Context, CursorIcon, LayerId, PointerButton, Pos2, Response, Shape, Stroke, Vec2, + Color32, Context, CursorIcon, LayerId, PointerButton, Pos2, Rect, Response, Shape, Stroke, Vec2, }; use std::rc::Rc; @@ -93,6 +93,7 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { EguiExtra { properties_window: false, id_tmp: id.to_string(), + size_rect: Rect::NAN, }, ); diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index ac5be99d..7ada56f7 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -2,6 +2,10 @@ use crate::common::{ComponentStore, Components, Simulator}; use crate::gui_egui::editor::EditorMode; use crate::gui_egui::{editor::Editor, keymap, keymap::Shortcuts, menu::Menu}; use eframe::egui; +use egui::{ + containers, CentralPanel, Color32, Context, PointerButton, Pos2, Rect, ScrollArea, Sense, + SidePanel, TopBottomPanel, Vec2, +}; use std::collections::HashMap; use std::path::PathBuf; @@ -12,9 +16,9 @@ pub struct Gui { pub scale: f32, // When the ui elements change size pub ui_change: bool, - pub offset: egui::Vec2, - pub pan: egui::Vec2, - pub clip_rect: egui::Rect, + pub offset: Vec2, + pub pan: Vec2, + pub clip_rect: Rect, pub shortcuts: Shortcuts, pub pause: bool, pub editor: Option, @@ -22,10 +26,11 @@ pub struct Gui { pub contexts: HashMap, } -#[derive(Clone, Default, Debug)] +#[derive(Clone, Debug)] pub struct EguiExtra { pub properties_window: bool, pub id_tmp: String, + pub size_rect: Rect, } pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { @@ -41,9 +46,9 @@ pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { simulator: Some(simulator), scale: 1.0f32, ui_change: true, - offset: egui::Vec2 { x: 0f32, y: 0f32 }, - pan: egui::Vec2 { x: 0f32, y: 0f32 }, - clip_rect: egui::Rect::NOTHING, + offset: Vec2 { x: 0f32, y: 0f32 }, + pan: Vec2 { x: 0f32, y: 0f32 }, + clip_rect: Rect::NOTHING, shortcuts: Shortcuts::new(), pause: true, editor: None, @@ -55,13 +60,13 @@ pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { } impl eframe::App for Gui { - fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { + fn update(&mut self, ctx: &Context, frame: &mut eframe::Frame) { self.shortcuts.inputs(ctx, self); if self.editor_use { crate::gui_egui::editor::Editor::update(ctx, frame, self); return; } - let frame = egui::Frame::none().fill(egui::Color32::WHITE); + let frame = egui::Frame::none().fill(Color32::WHITE); //let frame = egui::Frame::canvas(&(*ctx.style()).clone()); // For getting the correct offset for our drawing we need to get the top bar @@ -69,26 +74,24 @@ impl eframe::App for Gui { if self.should_area_update(ctx) { // todo: Implement proper light and dark mode? // for testing light and dark mode - //ctx.set_visuals(egui::Visuals::dark()); - //ctx.set_visuals(egui::Visuals::light()); + //ctx.set_visuals(Visuals::dark()); + //ctx.set_visuals(Visuals::light()); self.top_bar(ctx); self.side_panel(ctx); - let top = - egui::containers::panel::PanelState::load(ctx, egui::Id::from("topBar")).unwrap(); - let side = - egui::containers::panel::PanelState::load(ctx, egui::Id::from("leftGui")).unwrap(); - self.offset = egui::Vec2 { + let top = containers::panel::PanelState::load(ctx, egui::Id::from("topBar")).unwrap(); + let side = containers::panel::PanelState::load(ctx, egui::Id::from("leftGui")).unwrap(); + self.offset = Vec2 { x: side.rect.max.x, y: top.rect.max.y, }; - self.clip_rect = egui::Rect { + self.clip_rect = Rect { min: self.offset.to_pos2(), - max: egui::Pos2 { + max: Pos2 { x: f32::INFINITY, y: f32::INFINITY, }, }; - egui::Context::request_repaint(ctx); + Context::request_repaint(ctx); } else { self.top_bar(ctx); if self.simulator.is_some() { @@ -100,12 +103,12 @@ impl eframe::App for Gui { } impl Gui { - fn should_area_update(&mut self, ctx: &egui::Context) -> bool { + fn should_area_update(&mut self, ctx: &Context) -> bool { if self.ui_change { self.ui_change = false; true } else { - (egui::containers::panel::PanelState::load(ctx, egui::Id::from("topBar")) + (containers::panel::PanelState::load(ctx, egui::Id::from("topBar")) .unwrap() .rect .max @@ -113,7 +116,7 @@ impl Gui { - self.offset.y) .abs() > 0.1 - || (egui::containers::panel::PanelState::load(ctx, egui::Id::from("leftGui")) + || (containers::panel::PanelState::load(ctx, egui::Id::from("leftGui")) .unwrap() .rect .max @@ -124,8 +127,8 @@ impl Gui { } } - fn draw_area(&mut self, ctx: &egui::Context, frame: egui::Frame) { - let central_panel = egui::CentralPanel::default().frame(frame).show(ctx, |ui| { + fn draw_area(&mut self, ctx: &Context, frame: egui::Frame) { + let central_panel = CentralPanel::default().frame(frame).show(ctx, |ui| { let sim = self.simulator.as_mut().unwrap(); ui.set_clip_rect(self.clip_rect); // Don't draw over the rest of the ui @@ -144,8 +147,8 @@ impl Gui { self.contexts.insert(context.id_tmp.clone(), context); } }); - let cpr = central_panel.response.interact(egui::Sense::drag()); - if cpr.dragged_by(egui::PointerButton::Middle) { + let cpr = central_panel.response.interact(Sense::drag()); + if cpr.dragged_by(PointerButton::Middle) { self.pan += cpr.drag_delta(); } if central_panel.response.hovered() { @@ -159,9 +162,9 @@ impl Gui { } } - fn side_panel(&mut self, ctx: &egui::Context) { - egui::SidePanel::left("leftGui").show(ctx, |ui| { - egui::ScrollArea::vertical().show(ui, |ui| { + fn side_panel(&mut self, ctx: &Context) { + SidePanel::left("leftGui").show(ctx, |ui| { + ScrollArea::vertical().show(ui, |ui| { ui.horizontal(|ui| { ui.label("0x00000004\n0x00000008\n".repeat(100)); ui.label("100000\n20000\n".repeat(100)); @@ -170,8 +173,8 @@ impl Gui { }); } - fn top_bar(&mut self, ctx: &egui::Context) { - egui::TopBottomPanel::top("topBar").show(ctx, |ui| Menu::new(ui, self)); + fn top_bar(&mut self, ctx: &Context) { + TopBottomPanel::top("topBar").show(ctx, |ui| Menu::new(ui, self)); } } @@ -184,6 +187,7 @@ pub fn create_contexts(components: &Components) -> HashMap>, pub cursor_location: Pos2, + pub library_contexts: HashMap, } pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option) { @@ -39,7 +40,11 @@ pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option ); e.im.comp.as_ref().unwrap().render( &mut ui, - &mut EguiExtra::default(), + &mut EguiExtra { + properties_window: false, + id_tmp: String::new(), + size_rect: Rect::NAN, + }, None, Vec2::new(e.im.cursor_location.x, e.im.cursor_location.y), e.scale, @@ -72,15 +77,16 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { y: f32::INFINITY, }, }; - for c in e.library.store.iter() { - let size = c.size(); - padding.y -= e.scale * size.min.y; + for c in e.library.iter() { + let size = c.top_padding(); + padding.y += e.scale * size; let r_vec = c .render( ui, &mut EguiExtra { properties_window: false, id_tmp: c.get_id_ports().0, + size_rect: Rect::NAN, }, None, padding, @@ -139,6 +145,32 @@ pub fn add_comp_to_editor(e: &mut Editor) { b_in: e.dummy_input.clone(), }) } + "sext" => { + id = unique_component_name(&id_ports, "sext"); + Rc::new(Sext { + id: id.clone(), + pos: (0.0, 0.0), + sext_in: e.dummy_input.clone(), + in_size: 16, + out_size: 24, + }) + } + "mem" => { + id = unique_component_name(&id_ports, "mem"); + Rc::new(Mem { + id: id.clone(), + pos: (0.0, 0.0), + width: 100.0, + height: 50.0, + big_endian: true, + data: e.dummy_input.clone(), + addr: e.dummy_input.clone(), + ctrl: e.dummy_input.clone(), + size: e.dummy_input.clone(), + sign: e.dummy_input.clone(), + memory: Memory::new(), + }) + } _ => todo!(), }; Rc::::get_mut(&mut comp) @@ -149,6 +181,7 @@ pub fn add_comp_to_editor(e: &mut Editor) { EguiExtra { properties_window: false, id_tmp: id, + size_rect: Rect::NAN, }, ); e.components.push(comp); From 2ee6468587248a82ad5d7d056e2166f3c67fbf28 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Thu, 27 Jul 2023 15:32:31 +0200 Subject: [PATCH 35/58] Added mux --- src/components/mux.rs | 14 +++ src/gui_egui/components/mux.rs | 151 ++++++++++++++++++++++++++------- src/gui_egui/editor.rs | 8 +- src/gui_egui/library.rs | 9 ++ 4 files changed, 152 insertions(+), 30 deletions(-) diff --git a/src/components/mux.rs b/src/components/mux.rs index a0dfd7ec..753da750 100644 --- a/src/components/mux.rs +++ b/src/components/mux.rs @@ -59,4 +59,18 @@ impl Component for Mux { // set output simulator.set_out_val(&self.id, "out", value); } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + let target_port_id = target_port_id.as_str(); + if target_port_id == MUX_SELECT_ID { + self.select = new_input; + return; + } + for i in 0..=self.m_in.len() - 1 { + if target_port_id == format!("{}{}", MUX_TEMPLATE_ID, i) { + self.m_in[i] = new_input; + return; + } + } + } } diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 0d174ca4..762dd8d9 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -1,24 +1,28 @@ -use crate::common::{EguiComponent, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; use crate::components::Mux; -use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::component_ui::{ + input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; +use egui::{Color32, PointerButton, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Mux { fn render( &self, - ui: &mut egui::Ui, + ui: &mut Ui, _context: &mut EguiExtra, simulator: Option<&mut Simulator>, - offset: egui::Vec2, + offset: Vec2, scale: f32, - _clip_rect: egui::Rect, - _editor_mode: EditorMode, - ) -> Option> { + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { // 41x(20*ports + 11) // middle: 21x ((20*ports + 10)/2+1)y (0 0) - let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -33,7 +37,7 @@ impl EguiComponent for Mux { }; // The shape - ui.painter().add(egui::Shape::closed_line( + ui.painter().add(Shape::closed_line( vec![ oh((-20f32, pa * (-10f32) - 10f32), s, o), oh((0f32, pa * (-10f32) - 10f32), s, o), @@ -42,13 +46,13 @@ impl EguiComponent for Mux { oh((0f32, pa * (10f32) + 10f32), s, o), oh((-20f32, pa * (10f32) + 10f32), s, o), ], - egui::Stroke { + Stroke { width: scale, - color: egui::Color32::BLACK, + color: Color32::BLACK, }, )); // select line - ui.painter().add(egui::Shape::line_segment( + ui.painter().add(Shape::line_segment( [ oh( (-20f32, ((select as f32) * 20f32) - pa * 10f32 + 10f32), @@ -57,29 +61,118 @@ impl EguiComponent for Mux { ), oh((20f32, 0f32), s, o), ], - egui::Stroke { + Stroke { width: scale, - color: egui::Color32::RED, + color: Color32::RED, }, )); - None + let rect = Rect { + min: oh((-20f32, pa * (-10f32) - 10f32), s, o), + max: oh((20f32, pa * 10f32 + 10f32), s, o), + }; + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + ui.label("Mux"); + }); + Some(vec![r]) } - /* - fn interactive_rect(&self, ui: &mut egui::Ui, offset: egui::Vec2, scale: f32) -> egui::Rect { - // 41x(20*ports + 11) - // middle: 21x ((20*ports + 10)/2+1)y (0 0) - let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let mut delete = false; + let r_vec = Mux::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + if resp.dragged_by(PointerButton::Primary) { + let delta = resp.drag_delta() / scale; + self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); + } + + if resp.drag_released_by(PointerButton::Primary) + && resp.interact_pointer_pos().unwrap().x < offset.x + { + delete = true; + } + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_slider(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.select, + crate::components::MUX_SELECT_ID.to_string(), + id_ports, + self.id.clone(), + ); + for i in 0..=self.m_in.len() - 1 { + clicked_dropdown |= input_selector( + ui, + &mut self.m_in[i], + format!("{}{}", crate::components::MUX_TEMPLATE_ID, i), + id_ports, + self.id.clone(), + ); + } + clicked_dropdown + }, + ); + + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); let pa = self.m_in.len() as f32; - egui::Rect { - min: oh((-20f32, pa * (-10f32) - 10f32), s, o), - max: oh((20f32, pa * (10f32) + 10f32), s, o), + let top = -pa * 10f32 - 10f32; + let mut v = vec![( + crate::components::MUX_SELECT_ID.to_string(), + Pos2::new(-10f32, top) + own_pos, + )]; + for i in 0..=self.m_in.len() - 1 { + v.push(( + format!("{}{}", crate::components::MUX_TEMPLATE_ID, i), + Pos2::new(-20f32, top + i as f32 * 20f32 + 20f32) + own_pos, + )); } + v.push(( + crate::components::MUX_OUT_ID.to_string(), + Pos2::new(20f32, 0f32) + own_pos, + )); + v + } + + fn top_padding(&self) -> f32 { + self.m_in.len() as f32 * 10f32 + 5f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; } - */ } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 464d0c8c..df0aff55 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -87,7 +87,7 @@ impl Editor { out_size: 24, }), Rc::new(Mem { - id: "mem".into(), + id: "mem".to_string(), pos: (0.0, 0.0), width: 100.0, height: 50.0, @@ -99,6 +99,12 @@ impl Editor { sign: dummy_input.clone(), memory: Memory::new(), }), + Rc::new(Mux { + id: "mux".to_string(), + pos: (0.0, 0.0), + select: dummy_input.clone(), + m_in: vec![dummy_input.clone(), dummy_input.clone()], + }), ]; let library_contexts = crate::gui_egui::gui::create_contexts(&library); let mut e = Editor { diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index b77e0547..877673f3 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -171,6 +171,15 @@ pub fn add_comp_to_editor(e: &mut Editor) { memory: Memory::new(), }) } + "mux" => { + id = unique_component_name(&id_ports, "mux"); + Rc::new(Mux { + id: id.clone(), + pos: (0.0, 0.0), + select: e.dummy_input.clone(), + m_in: vec![e.dummy_input.clone(), e.dummy_input.clone()], + }) + } _ => todo!(), }; Rc::::get_mut(&mut comp) From 677597c49dc04e836bb8c657af4d037d6361e806 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Thu, 27 Jul 2023 15:50:21 +0200 Subject: [PATCH 36/58] Added reg --- src/components/register.rs | 14 ++- src/gui_egui/components/register.rs | 130 ++++++++++++++++++++++------ src/gui_egui/editor.rs | 5 ++ src/gui_egui/library.rs | 8 ++ 4 files changed, 128 insertions(+), 29 deletions(-) diff --git a/src/components/register.rs b/src/components/register.rs index 0d9a321d..352e10f6 100644 --- a/src/components/register.rs +++ b/src/components/register.rs @@ -2,7 +2,9 @@ use crate::common::{Component, Id, Input, InputPort, OutputType, Ports, Simulato use log::*; use serde::{Deserialize, Serialize}; -pub const REGISTER_IN_ID: &str = "r_in"; +pub const REGISTER_R_IN_ID: &str = "r_in"; + +pub const REGISTER_OUT_ID: &str = "out"; #[derive(Serialize, Deserialize)] pub struct Register { @@ -23,11 +25,11 @@ impl Component for Register { Ports::new( // Vector of inputs vec![&InputPort { - port_id: REGISTER_IN_ID.to_string(), + port_id: REGISTER_R_IN_ID.to_string(), input: self.r_in.clone(), }], OutputType::Sequential, - vec!["out"], + vec![REGISTER_OUT_ID], ), ) } @@ -40,4 +42,10 @@ impl Component for Register { simulator.set_out_val(&self.id, "out", value); trace!("eval: register id {} in {:?}", self.id, value); } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + if target_port_id == REGISTER_R_IN_ID { + self.r_in = new_input; + } + } } diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index 3f9733aa..1a9d09cf 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -1,24 +1,28 @@ -use crate::common::{EguiComponent, Simulator}; +use crate::common::{EguiComponent, Ports, Simulator}; use crate::components::Register; -use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::component_ui::{ + input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; +use egui::{Color32, PointerButton, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Register { fn render( &self, - ui: &mut egui::Ui, + ui: &mut Ui, _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, - offset: egui::Vec2, + offset: Vec2, scale: f32, - _clip_rect: egui::Rect, - _editor_mode: EditorMode, - ) -> Option> { + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { // 21x41 // middle: 11x 21y (0 0) - let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; + let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -26,7 +30,7 @@ impl EguiComponent for Register { let o = offset; // The shape - ui.painter().add(egui::Shape::line( + ui.painter().add(Shape::line( vec![ oh((-10f32, -20f32), s, o), oh((10f32, -20f32), s, o), @@ -36,28 +40,102 @@ impl EguiComponent for Register { oh((10f32, 20f32), s, o), oh((10f32, -20f32), s, o), ], - egui::Stroke { + Stroke { width: scale, - color: egui::Color32::BLACK, + color: Color32::BLACK, }, )); - None - } - - /* - fn interactive_rect(&self, ui: &mut egui::Ui, offset: egui::Vec2, scale: f32) -> egui::Rect { - // 21x41 - // middle: 11x 21y (0 0) - let oh: fn((f32, f32), f32, egui::Vec2) -> egui::Pos2 = offset_helper; - let mut offset = offset; - offset.x += self.pos.0 * scale; - offset.y += self.pos.1 * scale; - let s = scale; - let o = offset; - egui::Rect { + let rect = Rect { min: oh((-10f32, -20f32), s, o), max: oh((10f32, 20f32), s, o), + }; + let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { + ui.label(format!("Id: {}", self.id.clone())); + ui.label("Register"); + }); + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let mut delete = false; + let r_vec = Register::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + if resp.dragged_by(PointerButton::Primary) { + let delta = resp.drag_delta() / scale; + self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); } + + if resp.drag_released_by(PointerButton::Primary) + && resp.interact_pointer_pos().unwrap().x < offset.x + { + delete = true; + } + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let mut clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_slider(ui, &mut self.pos); + clicked_dropdown |= input_selector( + ui, + &mut self.r_in, + crate::components::REGISTER_R_IN_ID.to_string(), + id_ports, + self.id.clone(), + ); + clicked_dropdown + }, + ); + + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![ + ( + crate::components::REGISTER_R_IN_ID.to_string(), + Pos2::new(-10f32, 0f32) + own_pos, + ), + ( + crate::components::REGISTER_OUT_ID.to_string(), + Pos2::new(10f32, 0f32) + own_pos, + ), + ] + } + + fn top_padding(&self) -> f32 { + 20f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; } - */ } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index df0aff55..b080a061 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -105,6 +105,11 @@ impl Editor { select: dummy_input.clone(), m_in: vec![dummy_input.clone(), dummy_input.clone()], }), + Rc::new(Register { + id: "reg".to_string(), + pos: (0.0, 0.0), + r_in: dummy_input.clone(), + }), ]; let library_contexts = crate::gui_egui::gui::create_contexts(&library); let mut e = Editor { diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index 877673f3..817b66d9 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -180,6 +180,14 @@ pub fn add_comp_to_editor(e: &mut Editor) { m_in: vec![e.dummy_input.clone(), e.dummy_input.clone()], }) } + "reg" => { + id = unique_component_name(&id_ports, "reg"); + Rc::new(Register { + id: id.clone(), + pos: (0.0, 0.0), + r_in: e.dummy_input.clone(), + }) + } _ => todo!(), }; Rc::::get_mut(&mut comp) From 46156519cc608b3bd4516880f3c6ccef7a38f950 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Thu, 27 Jul 2023 16:11:02 +0200 Subject: [PATCH 37/58] mux removable/addable inputs --- src/gui_egui/component_ui.rs | 21 ++++++++++++++++++--- src/gui_egui/components/mux.rs | 23 ++++++++++++++++++----- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index 339e08b3..e81f20ac 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -81,19 +81,21 @@ pub fn pos_slider(ui: &mut Ui, pos: &mut (f32, f32)) { }); } -pub fn input_selector( +pub fn input_selector_removeable( ui: &mut Ui, input: &mut Input, port_name: crate::common::Id, id_ports: &[(crate::common::Id, Ports)], own_id: crate::common::Id, -) -> bool { + removable: bool, +) -> (bool, bool) { let mut port_id = input.id.clone(); let mut port_field = input.field.clone(); let label_port_id = format!("{}.id", port_name.clone()); let text_port_id = port_id.to_string(); let label_port_field = format!("{}.field", port_name.clone()); let text_port_field = port_field.to_string(); + let mut should_be_removed = false; ui.horizontal(|ui| { ComboBox::from_label(label_port_id) .selected_text(text_port_id) @@ -120,12 +122,25 @@ pub fn input_selector( } } }); + if removable && ui.button("🗙").clicked() { + should_be_removed = true; + } }); let clicked_dropdown = input.id != port_id || input.field != port_field; input.id = port_id; input.field = port_field; - clicked_dropdown + (clicked_dropdown, should_be_removed) +} + +pub fn input_selector( + ui: &mut Ui, + input: &mut Input, + port_name: crate::common::Id, + id_ports: &[(crate::common::Id, Ports)], + own_id: crate::common::Id, +) -> bool { + input_selector_removeable(ui, input, port_name, id_ports, own_id, false).0 } pub fn input_change_id( diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 762dd8d9..472deb72 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -1,7 +1,8 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Input, Ports, SignalUnsigned, Simulator}; use crate::components::Mux; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, + input_change_id, input_selector, input_selector_removeable, pos_slider, properties_window, + rect_with_hover, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -128,14 +129,26 @@ impl EguiComponent for Mux { id_ports, self.id.clone(), ); - for i in 0..=self.m_in.len() - 1 { - clicked_dropdown |= input_selector( + let mut i = 0; + //for i in 0..=self.m_in.len() - 1 { + self.m_in.retain_mut(|inp| { + let (clicked, delete) = input_selector_removeable( ui, - &mut self.m_in[i], + inp, format!("{}{}", crate::components::MUX_TEMPLATE_ID, i), id_ports, self.id.clone(), + i != 0, ); + i += 1; + clicked_dropdown |= clicked; + !delete + }); + if ui.button("+ Add new input").clicked() { + self.m_in.push(Input { + id: "id".to_string(), + field: "field".to_string(), + }); } clicked_dropdown }, From 329534de1685f6aa2b6984d488b5ee4f0a20d898 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Thu, 27 Jul 2023 16:19:22 +0200 Subject: [PATCH 38/58] right click to get out of wire and input mode --- src/gui_egui/editor_wire_mode.rs | 7 ++++++- src/gui_egui/library.rs | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/gui_egui/editor_wire_mode.rs b/src/gui_egui/editor_wire_mode.rs index 66f9b814..dbc70731 100644 --- a/src/gui_egui/editor_wire_mode.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -1,6 +1,6 @@ use crate::common::{Components, Id, Input}; use crate::components::Wire; -use crate::gui_egui::editor::{get_component, CloseToComponent, Editor, SnapPriority}; +use crate::gui_egui::editor::{get_component, CloseToComponent, Editor, EditorMode, SnapPriority}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::{ id_ports_of_all_components, offset_helper, offset_reverse_helper, offset_reverse_helper_pos2, @@ -117,6 +117,11 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option) { ctx.output_mut(|o| o.cursor_icon = CursorIcon::Crosshair); + if e.wm.mode_ended && cpr.drag_started_by(PointerButton::Secondary) { + e.editor_mode = EditorMode::Default; + reset_wire_mode(&mut e.wm); + return; + } if cpr.drag_started_by(PointerButton::Primary) { drag_started(ctx, e, cpr); diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index 817b66d9..a377ebbb 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -17,6 +17,11 @@ pub struct InputMode { pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option) { let layer_id = layer_id.unwrap(); + if cpr.drag_started_by(PointerButton::Secondary) { + e.editor_mode = EditorMode::Default; + reset_input_mode(&mut e.im); + return; + } ctx.output_mut(|o| o.cursor_icon = CursorIcon::None); ctx.input_mut(|i| { e.im.cursor_location += i.pointer.delta(); From 5e33d27ad75c1eee47e143c36a858791f3e85574 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Mon, 7 Aug 2023 16:45:46 +0200 Subject: [PATCH 39/58] Changed Slider into DragValue for positions and constants, fixed formatting --- src/components/add.rs | 17 ++++++++--------- src/components/mux.rs | 29 ++++++++++++++--------------- src/components/register.rs | 13 ++++++------- src/gui_egui/component_ui.rs | 20 +++++++------------- src/gui_egui/components/add.rs | 4 ++-- src/gui_egui/components/constant.rs | 28 ++++++++++++++++------------ src/gui_egui/components/mem.rs | 4 ++-- src/gui_egui/components/mux.rs | 4 ++-- src/gui_egui/components/probe.rs | 4 ++-- src/gui_egui/components/register.rs | 4 ++-- src/gui_egui/components/sext.rs | 4 ++-- src/gui_egui/components/wire.rs | 4 ++-- 12 files changed, 65 insertions(+), 70 deletions(-) diff --git a/src/components/add.rs b/src/components/add.rs index c74eee1e..ff9624d7 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -82,6 +82,14 @@ impl Component for Add { simulator.set_out_value(&self.id, "overflow", overflow); res } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + match target_port_id.as_str() { + ADD_A_IN_ID => self.a_in = new_input, + ADD_B_IN_ID => self.b_in = new_input, + _ => (), + } + } } impl Add { @@ -97,15 +105,6 @@ impl Add { pub fn rc_new(id: &str, pos: (f32, f32), a_in: Input, b_in: Input) -> Rc { Rc::new(Add::new(id, pos, a_in, b_in)) } - - #[allow(dead_code)] - fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - match target_port_id.as_str() { - ADD_A_IN_ID => self.a_in = new_input, - ADD_B_IN_ID => self.b_in = new_input, - _ => (), - } - } } #[cfg(test)] diff --git a/src/components/mux.rs b/src/components/mux.rs index 65d41fb0..84568c2f 100644 --- a/src/components/mux.rs +++ b/src/components/mux.rs @@ -73,6 +73,20 @@ impl Component for Mux { simulator.set_out_value(&self.id, "out", value); res } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + let target_port_id = target_port_id.as_str(); + if target_port_id == MUX_SELECT_ID { + self.select = new_input; + return; + } + for i in 0..=self.m_in.len() - 1 { + if target_port_id == format!("{}{}", MUX_TEMPLATE_ID, i) { + self.m_in[i] = new_input; + return; + } + } + } } impl Mux { @@ -88,19 +102,4 @@ impl Mux { pub fn rc_new(id: &str, pos: (f32, f32), select: Input, m_in: Vec) -> Rc { Rc::new(Mux::new(id, pos, select, m_in)) } - - #[allow(dead_code)] - fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - let target_port_id = target_port_id.as_str(); - if target_port_id == MUX_SELECT_ID { - self.select = new_input; - return; - } - for i in 0..=self.m_in.len() - 1 { - if target_port_id == format!("{}{}", MUX_TEMPLATE_ID, i) { - self.m_in[i] = new_input; - return; - } - } - } } diff --git a/src/components/register.rs b/src/components/register.rs index d75b29d1..827c8f0b 100644 --- a/src/components/register.rs +++ b/src/components/register.rs @@ -43,6 +43,12 @@ impl Component for Register { trace!("eval: register id {} in {:?}", self.id, value); Ok(()) } + + fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { + if target_port_id == REGISTER_R_IN_ID { + self.r_in = new_input; + } + } } impl Register { @@ -57,11 +63,4 @@ impl Register { pub fn rc_new(id: &str, pos: (f32, f32), r_in: Input) -> Rc { Rc::new(Register::new(id, pos, r_in)) } - - #[allow(dead_code)] - fn set_id_port(&mut self, target_port_id: Id, new_input: Input) { - if target_port_id == REGISTER_R_IN_ID { - self.r_in = new_input; - } - } } diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index e81f20ac..89b56237 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -2,8 +2,8 @@ use crate::common::{Input, Ports}; use crate::gui_egui::editor::EditorMode; use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; use egui::{ - containers, ComboBox, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, Slider, Ui, - Window, + containers, ComboBox, DragValue, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, + Ui, Window, }; use epaint::Shadow; @@ -66,18 +66,12 @@ pub fn properties_window

( } } -pub fn pos_slider(ui: &mut Ui, pos: &mut (f32, f32)) { +pub fn pos_drag_value(ui: &mut Ui, pos: &mut (f32, f32)) { ui.horizontal(|ui| { - ui.add( - Slider::new(&mut pos.0, 0f32..=1000f32) - .text("pos x") - .clamp_to_range(false), - ); - ui.add( - Slider::new(&mut pos.1, 0f32..=1000f32) - .text("pos y") - .clamp_to_range(false), - ); + ui.label("pos x"); + ui.add(DragValue::new(&mut pos.0)); + ui.label("pos y"); + ui.add(DragValue::new(&mut pos.1)); }); } diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 05b49c7d..6e15a287 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,5 +1,5 @@ use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, + input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -117,7 +117,7 @@ impl EguiComponent for Add { |ui| { let mut clicked_dropdown = false; input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_slider(ui, &mut self.pos); + pos_drag_value(ui, &mut self.pos); clicked_dropdown |= input_selector( ui, &mut self.a_in, diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index c8c47c13..0544c756 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,11 +1,14 @@ -use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; +use crate::common::{EguiComponent, Ports, SignalUnsigned, SignalValue, Simulator}; use crate::components::Constant; use crate::gui_egui::component_ui::{ - input_change_id, pos_slider, properties_window, rect_with_hover, + input_change_id, pos_drag_value, properties_window, rect_with_hover, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; -use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, Response, RichText, Ui, Vec2}; +use egui::{ + Align2, Area, Color32, DragValue, Order, PointerButton, Pos2, Rect, Response, RichText, Ui, + Vec2, +}; #[typetag::serde] impl EguiComponent for Constant { @@ -32,15 +35,15 @@ impl EguiComponent for Constant { .show(ui.ctx(), |ui| { ui.set_clip_rect(clip_rect); ui.label( - RichText::new(format!("{:?}", self.value)) + RichText::new(format!("{}", self.value)) .size(scale * 12f32) .background_color(Color32::LIGHT_GREEN), ) .on_hover_text({ let r: Result = self.value.try_into(); match r { - Ok(data) => format!("{:#x}", data), - _ => format!("{:?}", self.value), + Ok(data) => format!("{}", data), + _ => format!("{}", self.value), } }); }); @@ -99,12 +102,13 @@ impl EguiComponent for Constant { &mut context.properties_window, |ui| { input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_slider(ui, &mut self.pos); - /* - if let SignalValue::Data(d) = &mut self.value { - ui.add(Slider::new(d, u32::MIN..=u32::MAX).text("value")); - } - */ + pos_drag_value(ui, &mut self.pos); + let mut x = match self.value.get_value() { + SignalValue::Data(s) => s, + _ => 0, + }; + ui.add(DragValue::new(&mut x)); + self.value.set_value(SignalValue::Data(x)); false }, ); diff --git a/src/gui_egui/components/mem.rs b/src/gui_egui/components/mem.rs index d5e71580..426488a2 100644 --- a/src/gui_egui/components/mem.rs +++ b/src/gui_egui/components/mem.rs @@ -1,7 +1,7 @@ use crate::common::{EguiComponent, Ports, Simulator}; use crate::components::Mem; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, + input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -96,7 +96,7 @@ impl EguiComponent for Mem { |ui| { let mut clicked_dropdown = false; input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_slider(ui, &mut self.pos); + pos_drag_value(ui, &mut self.pos); ui.horizontal(|ui| { ui.add(Slider::new(&mut self.width, 0f32..=400f32).text("width")); ui.add(Slider::new(&mut self.height, 0f32..=400f32).text("height")); diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 0fc3abfe..c66dad53 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -1,7 +1,7 @@ use crate::common::{EguiComponent, Input, Ports, SignalUnsigned, Simulator}; use crate::components::Mux; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, input_selector_removeable, pos_slider, properties_window, + input_change_id, input_selector, input_selector_removeable, pos_drag_value, properties_window, rect_with_hover, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; @@ -121,7 +121,7 @@ impl EguiComponent for Mux { |ui| { let mut clicked_dropdown = false; input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_slider(ui, &mut self.pos); + pos_drag_value(ui, &mut self.pos); clicked_dropdown |= input_selector( ui, &mut self.select, diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index c215664d..c4dee218 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -1,7 +1,7 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, SignalValue, Simulator}; use crate::components::Probe; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, + input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -107,7 +107,7 @@ impl EguiComponent for Probe { |ui| { let mut clicked_dropdown = false; input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_slider(ui, &mut self.pos); + pos_drag_value(ui, &mut self.pos); clicked_dropdown |= input_selector( ui, &mut self.input, diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index 1a9d09cf..acc03a8c 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -1,7 +1,7 @@ use crate::common::{EguiComponent, Ports, Simulator}; use crate::components::Register; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, + input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -99,7 +99,7 @@ impl EguiComponent for Register { |ui| { let mut clicked_dropdown = false; input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_slider(ui, &mut self.pos); + pos_drag_value(ui, &mut self.pos); clicked_dropdown |= input_selector( ui, &mut self.r_in, diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index 9fb168a8..f328b934 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -1,7 +1,7 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; use crate::components::Sext; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_slider, properties_window, rect_with_hover, + input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -106,7 +106,7 @@ impl EguiComponent for Sext { |ui| { let mut clicked_dropdown = false; input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_slider(ui, &mut self.pos); + pos_drag_value(ui, &mut self.pos); clicked_dropdown |= input_selector( ui, &mut self.sext_in, diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index b0c43494..6af59711 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -114,8 +114,8 @@ impl EguiComponent for Wire { |ui| { let mut clicked_dropdown = false; input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_slider(ui, &mut self.pos[i]); - pos_slider(ui, &mut self.pos[i + 1]); + pos_drag_value(ui, &mut self.pos[i]); + pos_drag_value(ui, &mut self.pos[i + 1]); clicked_dropdown |= input_selector( ui, &mut self.input, From 8f877d86857d1ca80a8e20349f075a31c3cd6ae3 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Mon, 7 Aug 2023 16:51:13 +0200 Subject: [PATCH 40/58] Added wire mode button --- src/gui_egui/menu.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui_egui/menu.rs b/src/gui_egui/menu.rs index 0e16c2ce..30aeab06 100644 --- a/src/gui_egui/menu.rs +++ b/src/gui_egui/menu.rs @@ -52,6 +52,12 @@ impl Menu { editor(gui).scale = scale; shared_buttons_help(gui, ui); }); + ui.horizontal(|ui| { + let wire_button = ui.button("➖").on_hover_text("Wire mode"); + if wire_button.clicked() { + keymap::editor_wire_mode_fn(gui); + } + }); } } From 0b936c0c2c3f9cd3bb2f0a72d159b74cc985de6f Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Mon, 7 Aug 2023 18:30:23 +0200 Subject: [PATCH 41/58] Probe edit --- src/gui_egui/components/mem.rs | 2 +- src/gui_egui/components/probe_edit.rs | 174 ++++++++++++++++++++++++-- src/gui_egui/components/sext.rs | 1 + src/gui_egui/editor.rs | 6 +- src/gui_egui/gui.rs | 2 +- src/gui_egui/keymap.rs | 2 +- src/gui_egui/library.rs | 4 + 7 files changed, 176 insertions(+), 15 deletions(-) diff --git a/src/gui_egui/components/mem.rs b/src/gui_egui/components/mem.rs index 426488a2..d7dd3fd2 100644 --- a/src/gui_egui/components/mem.rs +++ b/src/gui_egui/components/mem.rs @@ -47,7 +47,7 @@ impl EguiComponent for Mem { let r = rect_with_hover(rect, clip_rect, editor_mode, ui, self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); - ui.label("mem"); + ui.label("Mem"); }); Some(vec![r]) } diff --git a/src/gui_egui/components/probe_edit.rs b/src/gui_egui/components/probe_edit.rs index 0cf764f0..cf9e2baa 100644 --- a/src/gui_egui/components/probe_edit.rs +++ b/src/gui_egui/components/probe_edit.rs @@ -1,21 +1,173 @@ -use crate::common::{EguiComponent, Simulator}; -use crate::components::ProbeEdit; -use crate::gui_egui::editor::EditorMode; +use crate::common::{EguiComponent, Ports, SignalSigned, SignalUnsigned, SignalValue, Simulator}; +use crate::components::{ProbeEdit, TextSignal}; +use crate::gui_egui::component_ui::{ + input_change_id, pos_drag_value, properties_window, rect_with_hover, +}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; -use egui::Rect; +use egui::{Align2, Area, DragValue, Order, PointerButton, Pos2, Rect, Response, Ui, Vec2}; #[typetag::serde] impl EguiComponent for ProbeEdit { fn render( &self, - _ui: &mut egui::Ui, + ui: &mut Ui, _context: &mut EguiExtra, _simulator: Option<&mut Simulator>, - _offset: egui::Vec2, - _scale: f32, - _clip_rect: Rect, - _editor_mode: EditorMode, - ) -> Option> { - todo!(); + offset: Vec2, + scale: f32, + clip_rect: Rect, + editor_mode: EditorMode, + ) -> Option> { + let mut offset = offset; + offset.x += self.pos.0 * scale; + offset.y += self.pos.1 * scale; + let interact = match editor_mode { + EditorMode::Simulator => true, + _ => false, + }; + let area = Area::new(self.id.to_string()) + .order(Order::Middle) + .current_pos(offset.to_pos2()) + .movable(false) + .enabled(true) + .interactable(interact) + .pivot(Align2::CENTER_CENTER) + .show(ui.ctx(), |ui| { + ui.set_clip_rect(clip_rect); + let hst = self.edit_history.clone(); + let x = hst.read().unwrap().last().unwrap().text.clone(); + let signal = parse_signal(x.as_str()); + let r = match signal { + SignalValue::Data(d) => { + let mut val = d; + // todo: Somehow make this scale... + let r = ui.add(DragValue::new(&mut val)); + *self.edit_history.write().unwrap().last_mut().unwrap() = TextSignal { + text: format!("{}", val), + signal: d.into(), + }; + r + } + SignalValue::Uninitialized => ui.label("Uninitialized"), + SignalValue::DontCare => ui.label("DontCare"), + SignalValue::Unknown => ui.label("Unknown"), + }; + r.on_hover_text(format!( + "{:?}", + parse_signal( + self.edit_history + .read() + .unwrap() + .last() + .unwrap() + .text + .as_str() + ) + )); + }); + + let r = rect_with_hover( + area.response.rect, + clip_rect, + editor_mode, + ui, + self.id.clone(), + |ui| { + ui.label(format!("Id: {}", self.id.clone())); + ui.label(format!( + "{}", + self.edit_history.read().unwrap().last().unwrap().text + )); + }, + ); + Some(vec![r]) + } + + fn render_editor( + &mut self, + ui: &mut Ui, + context: &mut EguiExtra, + simulator: Option<&mut Simulator>, + offset: Vec2, + scale: f32, + clip_rect: Rect, + id_ports: &[(crate::common::Id, Ports)], + editor_mode: EditorMode, + ) -> EditorRenderReturn { + let mut delete = false; + let r_vec = ProbeEdit::render( + self, + ui, + context, + simulator, + offset, + scale, + clip_rect, + editor_mode, + ) + .unwrap(); + let resp = &r_vec[0]; + if resp.dragged_by(PointerButton::Primary) { + let delta = resp.drag_delta() / scale; + self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); + } + + if resp.drag_released_by(PointerButton::Primary) + && resp.interact_pointer_pos().unwrap().x < offset.x + { + delete = true; + } + + properties_window( + ui, + self.id.clone(), + resp, + &mut context.properties_window, + |ui| { + let clicked_dropdown = false; + input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); + pos_drag_value(ui, &mut self.pos); + clicked_dropdown + }, + ); + + EditorRenderReturn { + delete, + resp: Some(r_vec), + } + } + + fn ports_location(&self) -> Vec<(crate::common::Id, Pos2)> { + let own_pos = Vec2::new(self.pos.0, self.pos.1); + vec![( + crate::components::PROBE_EDIT_OUT_ID.to_string(), + Pos2::new(-10f32, 0f32) + own_pos, + )] + } + + fn top_padding(&self) -> f32 { + // todo: make this accurate? + 10f32 + } + + fn set_pos(&mut self, pos: (f32, f32)) { + self.pos = pos; + } +} + +fn parse_signal(text: &str) -> SignalValue { + let text = text.trim(); + + if let Ok(signal) = text.parse::() { + (signal as SignalUnsigned).into() + } else if let Some(hex) = text.strip_prefix("0x") { + if let Ok(signal) = SignalUnsigned::from_str_radix(hex, 16) { + signal.into() + } else { + SignalValue::Unknown + } + } else { + SignalValue::Unknown } } diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index f328b934..03803e71 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -58,6 +58,7 @@ impl EguiComponent for Sext { _ => format!("{:?}", r), } }); + ui.label("Sign Extend"); } }); Some(vec![r]) diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 95f2a27b..8ec5f5e3 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -41,6 +41,7 @@ pub struct CloseToComponent { #[derive(Debug, Clone, Copy)] pub enum EditorMode { + Simulator, Default, Wire, Input, @@ -79,6 +80,7 @@ impl Editor { pos: (0.0, 0.0), input: dummy_input.clone(), }), + Rc::new(ProbeEdit::new("pe", (0.0, 0.0))), Rc::new(Sext { id: "sext".to_string(), pos: (0.0, 0.0), @@ -303,7 +305,9 @@ impl Editor { match e.editor_mode { EditorMode::Wire => crate::gui_egui::editor_wire_mode::wire_mode(ctx, e, cpr, layer_id), EditorMode::Input => crate::gui_egui::library::input_mode(ctx, e, cpr, layer_id), - EditorMode::Default => ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Default), + EditorMode::Default | EditorMode::Simulator => { + ctx.output_mut(|o| o.cursor_icon = egui::CursorIcon::Default) + } } if central_panel.response.hovered() { ctx.input_mut(|i| { diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index 7ada56f7..74c41a15 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -142,7 +142,7 @@ impl Gui { self.offset + self.pan, self.scale, self.clip_rect, - EditorMode::Default, + EditorMode::Simulator, ); self.contexts.insert(context.id_tmp.clone(), context); } diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 5a541f92..b4fce8a7 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -362,7 +362,7 @@ pub fn editor_wire_mode_fn(gui: &mut Gui) { if gui.editor_use { let editor = gui.editor.as_mut().unwrap(); match editor.editor_mode { - EditorMode::Default | EditorMode::Input => { + EditorMode::Default | EditorMode::Input | EditorMode::Simulator => { editor.editor_mode = EditorMode::Wire; } EditorMode::Wire => { diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index 66167db8..0eb3a107 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -141,6 +141,10 @@ pub fn add_comp_to_editor(e: &mut Editor) { input: e.dummy_input.clone(), }) } + "pe" => { + id = unique_component_name(&id_ports, "pe"); + Rc::new(ProbeEdit::new(id.as_str(), (0.0, 0.0))) + } "add" => { id = unique_component_name(&id_ports, "add"); Rc::new(Add { From 2470e3e177d46b9744ba66eec5d5ca2a4ff47421 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Tue, 8 Aug 2023 12:42:21 +0200 Subject: [PATCH 42/58] Visualize port locations, fix id change bug --- src/gui_egui/component_ui.rs | 45 ++++++++++++++++++++++++--- src/gui_egui/components/add.rs | 6 ++++ src/gui_egui/components/constant.rs | 26 +++++++++++----- src/gui_egui/components/mem.rs | 6 ++++ src/gui_egui/components/mux.rs | 7 ++++- src/gui_egui/components/probe.rs | 25 +++++++++++---- src/gui_egui/components/probe_edit.rs | 27 ++++++++++------ src/gui_egui/components/register.rs | 6 ++++ src/gui_egui/components/sext.rs | 6 ++++ src/gui_egui/components/wire.rs | 11 ++++++- src/gui_egui/editor.rs | 5 ++- src/gui_egui/editor_wire_mode.rs | 1 - 12 files changed, 139 insertions(+), 32 deletions(-) diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index 89b56237..ba770093 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -1,11 +1,13 @@ use crate::common::{Input, Ports}; use crate::gui_egui::editor::EditorMode; -use crate::gui_egui::helper::{editor_mode_to_sense, out_of_bounds, unique_component_name}; +use crate::gui_egui::helper::{ + editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, +}; use egui::{ - containers, ComboBox, DragValue, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, - Ui, Window, + containers, Color32, ComboBox, DragValue, Frame, Margin, PointerButton, Pos2, Rect, Response, + Rounding, Shape, Stroke, Ui, Vec2, Window, }; -use epaint::Shadow; +use epaint::{CircleShape, Shadow}; pub fn rect_with_hover

( rect: Rect, @@ -148,8 +150,41 @@ pub fn input_change_id( let r = ui .text_edit_singleline(&mut *id_tmp) .labelled_by(id_label.id); - if r.lost_focus() && *id_tmp != *id { + if (r.lost_focus() || r.clicked_elsewhere()) && *id_tmp != *id { *id = unique_component_name(id_ports, (*id_tmp).as_str()); } }); } + +pub fn visualize_ports( + ui: &mut Ui, + ports: Vec<(crate::common::Id, Pos2)>, + offset: Vec2, + scale: f32, + clip_rect: Rect, +) { + for (id, pos) in ports { + let pos = offset_helper((pos.x, pos.y), scale, offset); + let scalev2 = Vec2 { + x: scale * 2f32, + y: scale * 2f32, + }; + let circle = Shape::Circle(CircleShape { + center: pos, + radius: scale * 3f32, + fill: Color32::TRANSPARENT, + stroke: Stroke { + width: 1f32 * scale, + color: Color32::BLUE, + }, + }); + ui.painter().add(circle); + let rect = Rect { + min: pos - scalev2, + max: pos + scalev2, + }; + rect_with_hover(rect, clip_rect, EditorMode::Wire, ui, id.clone(), |ui| { + ui.label(format!("Port id: {}", id)); + }); + } +} diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 6e15a287..05cd8b39 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,5 +1,6 @@ use crate::gui_egui::component_ui::{ input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, + visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -25,6 +26,7 @@ impl EguiComponent for Add { // 41x81 // middle: 21x 41y (0 0) let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -71,6 +73,10 @@ impl EguiComponent for Add { ui.label(format!("Id: {}", self.id.clone())); ui.label("ALU"); }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } Some(vec![r]) } diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index 0544c756..db3d5231 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,7 +1,7 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, SignalValue, Simulator}; use crate::components::Constant; use crate::gui_egui::component_ui::{ - input_change_id, pos_drag_value, properties_window, rect_with_hover, + input_change_id, pos_drag_value, properties_window, rect_with_hover, visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -22,6 +22,7 @@ impl EguiComponent for Constant { clip_rect: Rect, editor_mode: EditorMode, ) -> Option> { + let offset_old = offset; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -34,11 +35,18 @@ impl EguiComponent for Constant { .pivot(Align2::CENTER_CENTER) .show(ui.ctx(), |ui| { ui.set_clip_rect(clip_rect); - ui.label( - RichText::new(format!("{}", self.value)) - .size(scale * 12f32) - .background_color(Color32::LIGHT_GREEN), - ) + match editor_mode { + EditorMode::Simulator => ui.label( + RichText::new(format!("{}", self.value)) + .size(scale * 12f32) + .background_color(Color32::LIGHT_GREEN), + ), + _ => ui.label( + RichText::new(format!("{}", self.value)) + .size(scale * 12f32) + .underline(), + ), + } .on_hover_text({ let r: Result = self.value.try_into(); match r { @@ -58,6 +66,10 @@ impl EguiComponent for Constant { ui.label(format!("{:?}", self.value)); }, ); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } Some(vec![r]) } @@ -123,7 +135,7 @@ impl EguiComponent for Constant { let own_pos = Vec2::new(self.pos.0, self.pos.1); vec![( crate::components::CONSTANT_OUT_ID.to_string(), - Pos2::new(10f32, 0f32) + own_pos, + Pos2::new(0f32, 0f32) + own_pos, )] } diff --git a/src/gui_egui/components/mem.rs b/src/gui_egui/components/mem.rs index d7dd3fd2..a6c87888 100644 --- a/src/gui_egui/components/mem.rs +++ b/src/gui_egui/components/mem.rs @@ -2,6 +2,7 @@ use crate::common::{EguiComponent, Ports, Simulator}; use crate::components::Mem; use crate::gui_egui::component_ui::{ input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, + visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -25,6 +26,7 @@ impl EguiComponent for Mem { // 201x101 // middle: 101x 51y (0 0) let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -49,6 +51,10 @@ impl EguiComponent for Mem { ui.label(format!("Id: {}", self.id.clone())); ui.label("Mem"); }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } Some(vec![r]) } diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index c66dad53..e8dcb898 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -2,7 +2,7 @@ use crate::common::{EguiComponent, Input, Ports, SignalUnsigned, Simulator}; use crate::components::Mux; use crate::gui_egui::component_ui::{ input_change_id, input_selector, input_selector_removeable, pos_drag_value, properties_window, - rect_with_hover, + rect_with_hover, visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -24,6 +24,7 @@ impl EguiComponent for Mux { // 41x(20*ports + 11) // middle: 21x ((20*ports + 10)/2+1)y (0 0) let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -75,6 +76,10 @@ impl EguiComponent for Mux { ui.label(format!("Id: {}", self.id.clone())); ui.label("Mux"); }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } Some(vec![r]) } diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index c4dee218..d84b0c41 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -2,6 +2,7 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, SignalValue, Simulator use crate::components::Probe; use crate::gui_egui::component_ui::{ input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, + visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -19,6 +20,7 @@ impl EguiComponent for Probe { clip_rect: Rect, editor_mode: EditorMode, ) -> Option> { + let offset_old = offset; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -36,11 +38,18 @@ impl EguiComponent for Probe { .pivot(Align2::CENTER_CENTER) .show(ui.ctx(), |ui| { ui.set_clip_rect(clip_rect); - ui.label( - RichText::new(format!("{:?}", value)) - .size(scale * 12f32) - .background_color(Color32::LIGHT_BLUE), - ) + match editor_mode { + EditorMode::Simulator => ui.label( + RichText::new(format!("{:?}", value)) + .size(scale * 12f32) + .background_color(Color32::LIGHT_BLUE), + ), + _ => ui.label( + RichText::new(format!("{:?}", value)) + .size(scale * 12f32) + .underline(), + ), + } .on_hover_text({ let r: Result = value.try_into(); match r { @@ -61,6 +70,10 @@ impl EguiComponent for Probe { ui.label(format!("{:?}", value)); }, ); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } Some(vec![r]) } @@ -129,7 +142,7 @@ impl EguiComponent for Probe { let own_pos = Vec2::new(self.pos.0, self.pos.1); vec![( crate::components::PROBE_IN_ID.to_string(), - Pos2::new(-10f32, 0f32) + own_pos, + Pos2::new(0f32, 0f32) + own_pos, )] } diff --git a/src/gui_egui/components/probe_edit.rs b/src/gui_egui/components/probe_edit.rs index cf9e2baa..013d732b 100644 --- a/src/gui_egui/components/probe_edit.rs +++ b/src/gui_egui/components/probe_edit.rs @@ -1,7 +1,7 @@ use crate::common::{EguiComponent, Ports, SignalSigned, SignalUnsigned, SignalValue, Simulator}; use crate::components::{ProbeEdit, TextSignal}; use crate::gui_egui::component_ui::{ - input_change_id, pos_drag_value, properties_window, rect_with_hover, + input_change_id, pos_drag_value, properties_window, rect_with_hover, visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -19,13 +19,11 @@ impl EguiComponent for ProbeEdit { clip_rect: Rect, editor_mode: EditorMode, ) -> Option> { + let offset_old = offset; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; - let interact = match editor_mode { - EditorMode::Simulator => true, - _ => false, - }; + let interact = matches!(editor_mode, EditorMode::Simulator); let area = Area::new(self.id.to_string()) .order(Order::Middle) .current_pos(offset.to_pos2()) @@ -75,12 +73,21 @@ impl EguiComponent for ProbeEdit { self.id.clone(), |ui| { ui.label(format!("Id: {}", self.id.clone())); - ui.label(format!( - "{}", - self.edit_history.read().unwrap().last().unwrap().text - )); + ui.label( + self.edit_history + .read() + .unwrap() + .last() + .unwrap() + .text + .to_string(), + ); }, ); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } Some(vec![r]) } @@ -142,7 +149,7 @@ impl EguiComponent for ProbeEdit { let own_pos = Vec2::new(self.pos.0, self.pos.1); vec![( crate::components::PROBE_EDIT_OUT_ID.to_string(), - Pos2::new(-10f32, 0f32) + own_pos, + Pos2::new(0f32, 0f32) + own_pos, )] } diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index acc03a8c..0fc0d4a9 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -2,6 +2,7 @@ use crate::common::{EguiComponent, Ports, Simulator}; use crate::components::Register; use crate::gui_egui::component_ui::{ input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, + visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -23,6 +24,7 @@ impl EguiComponent for Register { // 21x41 // middle: 11x 21y (0 0) let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -53,6 +55,10 @@ impl EguiComponent for Register { ui.label(format!("Id: {}", self.id.clone())); ui.label("Register"); }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } Some(vec![r]) } diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index 03803e71..26f9493c 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -2,6 +2,7 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; use crate::components::Sext; use crate::gui_egui::component_ui::{ input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, + visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -23,6 +24,7 @@ impl EguiComponent for Sext { // 81x41 // middle: 41x 21y (0 0) let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; let mut offset = offset; offset.x += self.pos.0 * scale; offset.y += self.pos.1 * scale; @@ -61,6 +63,10 @@ impl EguiComponent for Sext { ui.label("Sign Extend"); } }); + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } Some(vec![r]) } diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 6af59711..00b0ae99 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -1,6 +1,9 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; use crate::components::Wire; -use crate::gui_egui::component_ui::*; +use crate::gui_egui::component_ui::{ + input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, + visualize_ports, +}; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, SnapPriority}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; @@ -19,6 +22,7 @@ impl EguiComponent for Wire { editor_mode: EditorMode, ) -> Option> { let oh: fn((f32, f32), f32, Vec2) -> Pos2 = offset_helper; + let offset_old = offset; let offset = offset; let s = scale; let o = offset; @@ -68,6 +72,11 @@ impl EguiComponent for Wire { r_vec.push(r); } + match editor_mode { + EditorMode::Simulator => (), + _ => visualize_ports(ui, self.ports_location(), offset_old, scale, clip_rect), + } + Some(r_vec) } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 8ec5f5e3..801ab2a4 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -290,7 +290,10 @@ impl Editor { &id_ports, e.editor_mode, ); - e.contexts.insert(context.id_tmp.clone(), context); + // only reinsert if it's not getting deleted + if !render_return.delete { + e.contexts.insert(c.get_id_ports().0, context.clone()); + } !render_return.delete }), } diff --git a/src/gui_egui/editor_wire_mode.rs b/src/gui_egui/editor_wire_mode.rs index dbc70731..68bfd110 100644 --- a/src/gui_egui/editor_wire_mode.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -82,7 +82,6 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { #[allow(clippy::vtable_address_comparisons)] if !Rc::ptr_eq(&in_c.comp, &out_c.comp) { let comp = if is_input_in_comp_start { out_c } else { in_c }; - println!("comp: {:?}", comp.port_id); e.components.push(Rc::new(Wire { id: id.to_string(), pos: pos_v, From ee980c743e51332bd4133d6ff6ecb58a065d82d3 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Thu, 10 Aug 2023 13:03:31 +0200 Subject: [PATCH 43/58] Fixed scaling not taken into account when placing components --- src/gui_egui/helper.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index 8badc906..d4d23d15 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -4,15 +4,15 @@ use egui::{Pos2, Rect, Sense, Vec2}; pub fn offset_reverse_helper_pos2(xy: Pos2, scale: f32, offset: Vec2) -> Pos2 { egui::Pos2 { - x: (xy.x - offset.x) * scale, - y: (xy.y - offset.y) * scale, + x: (xy.x - offset.x) / scale, + y: (xy.y - offset.y) / scale, } } pub fn offset_reverse_helper(xy: (f32, f32), scale: f32, offset: Vec2) -> Pos2 { egui::Pos2 { - x: (xy.0 - offset.x) * scale, - y: (xy.1 - offset.y) * scale, + x: (xy.0 - offset.x) / scale, + y: (xy.1 - offset.y) / scale, } } From 9155b7ddf1e98bff1ce15a349c8c0af4aad78685 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Fri, 18 Aug 2023 12:33:23 +0200 Subject: [PATCH 44/58] Fixed wire properties ui, added possible to add/remove wire segments --- src/gui_egui/components/wire.rs | 71 ++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 00b0ae99..f56a7c41 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -1,13 +1,16 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; use crate::components::Wire; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, - visualize_ports, + input_change_id, input_selector, rect_with_hover, visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, SnapPriority}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{Color32, PointerButton, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; +use egui::{ + Color32, DragValue, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, Shape, + Stroke, Ui, Vec2, Window, +}; +use epaint::Shadow; #[typetag::serde] impl EguiComponent for Wire { @@ -104,6 +107,7 @@ impl EguiComponent for Wire { ) .unwrap(); + let mut properties_window_open = false; for (i, resp) in r_vec.iter().enumerate() { if resp.dragged_by(PointerButton::Primary) { let delta = resp.drag_delta() / scale; @@ -115,16 +119,25 @@ impl EguiComponent for Wire { { delete = true; } - properties_window( - ui, - self.id.clone(), - resp, - &mut context.properties_window, - |ui| { - let mut clicked_dropdown = false; + properties_window_open |= resp.clicked_by(PointerButton::Secondary); + } + let mut clicked_dropdown = false; + if properties_window_open || context.properties_window { + let resp = Window::new(format!("Properties: {}", self.id)) + .frame(Frame { + inner_margin: Margin::same(10f32), + outer_margin: Margin::same(0f32), + rounding: Rounding::same(10f32), + shadow: Shadow::small_dark(), + fill: ui.visuals().panel_fill, + stroke: ui.visuals().window_stroke, + }) + .default_pos(Pos2 { + x: self.pos[0].0, + y: self.pos[0].1, + }) + .show(ui.ctx(), |ui| { input_change_id(ui, &mut context.id_tmp, &mut self.id, id_ports); - pos_drag_value(ui, &mut self.pos[i]); - pos_drag_value(ui, &mut self.pos[i + 1]); clicked_dropdown |= input_selector( ui, &mut self.input, @@ -132,9 +145,37 @@ impl EguiComponent for Wire { id_ports, self.id.clone(), ); - clicked_dropdown - }, - ); + + let mut i = 0; + let mut first_item = true; + self.pos.retain_mut(|seg_pos| { + let mut delete = false; + ui.horizontal(|ui| { + ui.label(format!("Segment {}:", i)); + ui.label("pos x"); + ui.add(DragValue::new(&mut seg_pos.0)); + ui.label("pos y"); + ui.add(DragValue::new(&mut seg_pos.1)); + + if first_item { + first_item = false; + } else if ui.button("🗙").clicked() { + delete = true; + } + }); + i += 1; + !delete + }); + + if ui.button("+ Add new segment").clicked() { + self.pos.push(*self.pos.last().unwrap()); + } + }); + if !context.properties_window { + context.properties_window = true; + } else if !clicked_dropdown && resp.unwrap().response.clicked_elsewhere() { + context.properties_window = false; + } } EditorRenderReturn { From 29b0e14e14078773ab721e53f6d19e28d867f562 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Fri, 18 Aug 2023 15:51:44 +0200 Subject: [PATCH 45/58] Added grid --- src/gui_egui/editor.rs | 54 +++++++++++++++++++++++++++++++++++------ src/gui_egui/keymap.rs | 14 +++++++++++ src/gui_egui/library.rs | 4 +-- src/gui_egui/menu.rs | 48 ++++++++++++++++++++++++++++-------- 4 files changed, 100 insertions(+), 20 deletions(-) diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 801ab2a4..246365e4 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -10,7 +10,7 @@ use crate::gui_egui::{ menu::Menu, }; use eframe::{egui, Frame}; -use egui::{Color32, Context, LayerId, PointerButton, Pos2, Rect, Vec2}; +use egui::{Color32, Context, LayerId, PointerButton, Pos2, Rect, Shape, Vec2}; use std::{collections::HashMap, path::Path, rc::Rc}; pub struct Editor { @@ -22,6 +22,9 @@ pub struct Editor { pub clip_rect: Rect, pub side_panel_width: f32, pub ui_change: bool, + pub grid_enable: bool, + pub grid_size: f32, + pub grid_opacity: f32, pub library: Components, pub dummy_input: Input, pub editor_mode: EditorMode, @@ -129,6 +132,9 @@ impl Editor { }, side_panel_width: 400f32, ui_change: true, + grid_enable: true, + grid_size: 20f32, + grid_opacity: 0.5f32, library, dummy_input, editor_mode: EditorMode::Default, @@ -240,21 +246,53 @@ impl Editor { // draw a marker to show 0,0 { - let s = Editor::gui_to_editor(gui); - ui.painter().add(egui::Shape::line( + let e = Editor::gui_to_editor(gui); + ui.painter().add(Shape::line( vec![ - offset_helper((30f32, 0f32), s.scale, s.offset_and_pan), - offset_helper((0f32, 0f32), s.scale, s.offset_and_pan), - offset_helper((0f32, 30f32), s.scale, s.offset_and_pan), + offset_helper((30f32, 0f32), e.scale, e.offset_and_pan), + offset_helper((0f32, 0f32), e.scale, e.offset_and_pan), + offset_helper((0f32, 30f32), e.scale, e.offset_and_pan), ], egui::Stroke { - width: s.scale, - color: egui::Color32::BLACK, + width: e.scale, + color: Color32::BLACK, }, )); layer_id = Some(ui.layer_id()); } + // draw grid + if Editor::gui_to_editor(gui).grid_enable { + let e = Editor::gui_to_editor(gui); + let screen_rect = ui.ctx().screen_rect(); + let grid_scale = e.grid_size * e.scale; + let start = -(e.pan / e.scale / e.grid_size).floor(); + let end = + (Vec2::new(screen_rect.width(), screen_rect.height()) / e.scale / e.grid_size) + .ceil(); + + for y in (start.y as i32)..(end.y as i32) { + ui.painter().hline( + (start.x * grid_scale)..=(end.x * grid_scale), + y as f32 * grid_scale + e.offset_and_pan.y, + egui::Stroke { + width: e.scale * 0.5f32, + color: egui::Color32::BLACK.gamma_multiply(e.grid_opacity), + }, + ); + } + for x in (start.x as i32)..(end.x as i32) { + ui.painter().vline( + x as f32 * grid_scale + e.offset_and_pan.x, + (start.y * grid_scale)..=(end.y * grid_scale), + egui::Stroke { + width: e.scale * 0.5f32, + color: egui::Color32::BLACK.gamma_multiply(e.grid_opacity), + }, + ); + } + } + let e = Editor::gui_to_editor(gui); let id_ports = id_ports_of_all_components_non_wires(&e.components); // The reason we do this is because some of the input modes requires references to diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index b4fce8a7..6002cb62 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -22,6 +22,7 @@ pub struct Shortcuts { pub edit_paste: KeyboardShortcut, pub view_zoom_in: KeyboardShortcut, pub view_zoom_out: KeyboardShortcut, + pub view_grid_toggle: KeyboardShortcut, pub control_play_toggle: KeyboardShortcut, pub control_play: KeyboardShortcut, pub control_pause: KeyboardShortcut, @@ -117,6 +118,10 @@ impl Shortcuts { modifiers: ctrl, key: Key::Minus, }, + view_grid_toggle: KeyboardShortcut { + modifiers: ctrl, + key: Key::G, + }, control_play: KeyboardShortcut { modifiers: none, key: Key::F6, @@ -195,6 +200,9 @@ impl Shortcuts { if ctx.input_mut(|i| i.consume_shortcut(&self.view_zoom_out)) { view_zoom_out_fn(gui); } + if ctx.input_mut(|i| i.consume_shortcut(&self.view_grid_toggle)) { + view_grid_toggle_fn(gui); + } if ctx.input_mut(|i| i.consume_shortcut(&self.control_play_toggle)) { control_play_toggle_fn(gui); } @@ -327,6 +335,12 @@ pub fn view_zoom_out_fn(gui: &mut Gui) { _ => *scale = 0.1f32, } } +pub fn view_grid_toggle_fn(gui: &mut Gui) { + if gui.editor_use { + let editor = gui.editor.as_mut().unwrap(); + editor.grid_enable = !editor.grid_enable; + } +} pub fn control_play_toggle_fn(gui: &mut Gui) { if !gui.editor_use { gui.pause = !gui.pause; diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index 0eb3a107..2c0f18e6 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -84,7 +84,7 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { }; for c in e.library.iter() { let size = c.top_padding(); - padding.y += e.scale * size; + padding.y += size; let r_vec = c .render( ui, @@ -95,7 +95,7 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { }, None, padding, - e.scale, + 1.0f32, clip_rect, e.editor_mode, ) diff --git a/src/gui_egui/menu.rs b/src/gui_egui/menu.rs index 30aeab06..c2ad7d4f 100644 --- a/src/gui_egui/menu.rs +++ b/src/gui_egui/menu.rs @@ -1,17 +1,17 @@ use crate::gui_egui::{editor::Editor, gui::Gui, keymap}; -use egui::Ui; +use egui::{menu, Button, DragValue, KeyboardShortcut, Response, Ui}; pub(crate) struct Menu {} impl Menu { #[allow(clippy::new_ret_no_self)] - pub(crate) fn new(ui: &mut egui::Ui, gui: &mut Gui) { - egui::menu::bar(ui, |ui| { + pub(crate) fn new(ui: &mut Ui, gui: &mut Gui) { + menu::bar(ui, |ui| { shared_buttons_file(gui, ui); shared_buttons_edit(gui, ui); let mut scale = gui.scale; - shared_buttons_view(gui, ui, &mut scale); + shared_buttons_view(gui, ui, &mut scale, |_| {}); gui.scale = scale; shared_buttons_help(gui, ui); @@ -39,17 +39,41 @@ impl Menu { } #[allow(clippy::new_ret_no_self)] - pub(crate) fn new_editor(ui: &mut egui::Ui, gui: &mut Gui) { + pub(crate) fn new_editor(ui: &mut Ui, gui: &mut Gui) { fn editor(gui: &mut Gui) -> &mut Editor { gui.editor.as_mut().unwrap() } - egui::menu::bar(ui, |ui| { + menu::bar(ui, |ui| { shared_buttons_file(gui, ui); shared_buttons_edit(gui, ui); let mut scale = editor(gui).scale; - shared_buttons_view(gui, ui, &mut scale); + let mut grid_enable = editor(gui).grid_enable; + let mut grid_size = editor(gui).grid_size; + let mut grid_opacity = editor(gui).grid_opacity; + let view_grid_toggle = gui.shortcuts.view_grid_toggle.clone(); + shared_buttons_view(gui, ui, &mut scale, |ui| { + ui.horizontal(|ui| { + ui.checkbox(&mut grid_enable, "Grid Enable"); + ui.label(ui.ctx().format_shortcut(&view_grid_toggle)); + }); + ui.horizontal(|ui| { + ui.label("Grid Size:"); + ui.add(DragValue::new(&mut grid_size).clamp_range(5f32..=10000f32)); + }); + ui.horizontal(|ui| { + ui.label("Grid Opacity:"); + ui.add( + DragValue::new(&mut grid_opacity) + .clamp_range(0f32..=1f32) + .speed(0.02f32), + ); + }); + }); editor(gui).scale = scale; + editor(gui).grid_enable = grid_enable; + editor(gui).grid_size = grid_size; + editor(gui).grid_opacity = grid_opacity; shared_buttons_help(gui, ui); }); ui.horizontal(|ui| { @@ -61,8 +85,8 @@ impl Menu { } } -fn btn(ui: &mut egui::Ui, name: &str, keys: egui::KeyboardShortcut) -> egui::Response { - ui.add(egui::Button::new(name).shortcut_text(ui.ctx().format_shortcut(&keys))) +fn btn(ui: &mut Ui, name: &str, keys: KeyboardShortcut) -> Response { + ui.add(Button::new(name).shortcut_text(ui.ctx().format_shortcut(&keys))) } fn shared_buttons_file(gui: &mut Gui, ui: &mut Ui) { @@ -113,7 +137,10 @@ fn shared_buttons_edit(gui: &mut Gui, ui: &mut Ui) { }); } -fn shared_buttons_view(gui: &mut Gui, ui: &mut Ui, scale: &mut f32) { +fn shared_buttons_view

(gui: &mut Gui, ui: &mut Ui, scale: &mut f32, mut f: P) +where + P: FnMut(&mut Ui), +{ ui.menu_button("View", |ui| { if btn(ui, "Zoom In", gui.shortcuts.view_zoom_in).clicked() { keymap::view_zoom_in_fn(gui); @@ -147,6 +174,7 @@ fn shared_buttons_view(gui: &mut Gui, ui: &mut Ui, scale: &mut f32) { *scale = 2f32; } }); + f(ui); }); } From 13394f036fafe6c72cf6f6be30eb2210ae8142e0 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Fri, 18 Aug 2023 17:52:43 +0200 Subject: [PATCH 46/58] Added grid snapping for wires --- src/gui_egui/editor.rs | 6 +++ src/gui_egui/editor_wire_mode.rs | 89 +++++++++++++++++++++++++++----- src/gui_egui/helper.rs | 7 +++ src/gui_egui/keymap.rs | 20 +++++++ src/gui_egui/menu.rs | 15 +++++- 5 files changed, 124 insertions(+), 13 deletions(-) diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 246365e4..5fdb1682 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -22,9 +22,12 @@ pub struct Editor { pub clip_rect: Rect, pub side_panel_width: f32, pub ui_change: bool, + pub snap_distance: f32, pub grid_enable: bool, pub grid_size: f32, pub grid_opacity: f32, + pub grid_snap_enable: bool, + pub grid_snap_distance: f32, pub library: Components, pub dummy_input: Input, pub editor_mode: EditorMode, @@ -132,9 +135,12 @@ impl Editor { }, side_panel_width: 400f32, ui_change: true, + snap_distance: 10f32, grid_enable: true, grid_size: 20f32, grid_opacity: 0.5f32, + grid_snap_enable: true, + grid_snap_distance: 20f32, library, dummy_input, editor_mode: EditorMode::Default, diff --git a/src/gui_egui/editor_wire_mode.rs b/src/gui_egui/editor_wire_mode.rs index 68bfd110..d4016dd3 100644 --- a/src/gui_egui/editor_wire_mode.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -3,8 +3,8 @@ use crate::components::Wire; use crate::gui_egui::editor::{get_component, CloseToComponent, Editor, EditorMode, SnapPriority}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::{ - id_ports_of_all_components, offset_helper, offset_reverse_helper, offset_reverse_helper_pos2, - unique_component_name, + id_ports_of_all_components, offset_helper, offset_helper_pos2, offset_reverse_helper, + offset_reverse_helper_pos2, unique_component_name, }; use egui::{ Color32, Context, CursorIcon, LayerId, PointerButton, Pos2, Rect, Response, Shape, Stroke, Vec2, @@ -29,7 +29,7 @@ pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { let (closest, closest_wire) = clicked_close_to_input_output(offset_cursor_scale, &e.components); - match get_closest_component_non_wire_prio(closest, closest_wire, 10f32) { + match get_closest_component_non_wire_prio(closest, closest_wire, e.snap_distance) { Some(closest_uw) => { if e.wm.temp_positions.is_empty() { // New Component @@ -45,10 +45,27 @@ pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { } None => { if !e.wm.temp_positions.is_empty() { - let mut wires = wire_split_into_two_vec( - *e.wm.temp_positions.last().unwrap(), - (origin.x, origin.y), - ); + let mut wires = if e.grid_snap_enable { + match get_grid_snap(e.grid_snap_distance, offset_cursor_scale, e.grid_size) + { + Some(g) => { + let new_loc = offset_helper_pos2(g, e.scale, e.offset_and_pan); + wire_split_into_two_vec( + *e.wm.temp_positions.last().unwrap(), + (new_loc.x, new_loc.y), + ) + } + None => wire_split_into_two_vec( + *e.wm.temp_positions.last().unwrap(), + (origin.x, origin.y), + ), + } + } else { + wire_split_into_two_vec( + *e.wm.temp_positions.last().unwrap(), + (origin.x, origin.y), + ) + }; e.wm.temp_positions.append(&mut wires) } } @@ -139,13 +156,17 @@ pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option< let (closest, closest_wire) = clicked_close_to_input_output(offset_cursor_scale, &e.components); - // Here we prioritize component ports over wires in a 10f32 range - let wire_shown_location = get_location_of_port_or_wire_inside_radius( + // Here we prioritize component ports over wires in snap distance + let wire_shown_location = get_location_of_port_wire_grid_inside_radius( closest, closest_wire, - 10f32, + e.snap_distance, e.wm.cursor_location, e.offset_and_pan, + e.scale, + e.grid_enable, + e.grid_snap_distance, + e.grid_size, ); let v = wire_split_into_two_vec( @@ -335,15 +356,59 @@ pub fn get_closest_component_non_wire_prio( } } -pub fn get_location_of_port_or_wire_inside_radius( +pub fn get_location_of_port_wire_grid_inside_radius( port: Option, wire: Option, distance: f32, cursor_location: Pos2, offset: Vec2, + scale: f32, + grid_enable: bool, + grid_snap_distance: f32, + grid_size: f32, ) -> Pos2 { match get_closest_component_non_wire_prio(port, wire, distance) { Some(c) => c.pos + offset, - None => cursor_location, + None => { + if grid_enable { + match get_grid_snap( + grid_snap_distance, + offset_reverse_helper_pos2(cursor_location, scale, offset), + grid_size, + ) { + Some(s) => offset_helper_pos2(s, scale, offset), + None => cursor_location, + } + } else { + cursor_location + } + } + } +} + +pub fn get_grid_snap(distance: f32, clicked_pos: Pos2, grid_size: f32) -> Option { + let clicked_pos_v = clicked_pos.to_vec2(); + let top_left = (clicked_pos_v / grid_size).floor() * grid_size; + let top_right = Pos2::new(top_left.x + grid_size, top_left.y); + let bottom_left = Pos2::new(top_left.x, top_left.y + grid_size); + let bottom_right = Pos2::new(top_left.x + grid_size, top_left.y + grid_size); + let top_left = Pos2::new(top_left.x, top_left.y); + let mut closest: Option<(Pos2, f32)> = None; + for pos in vec![top_left, top_right, bottom_left, bottom_right] { + let d = pos.distance(clicked_pos); + if d <= distance { + match closest { + Some(s) => { + if s.1 > d { + closest = Some((pos, d)) + } + } + None => closest = Some((pos, d)), + } + } + } + match closest { + Some(s) => Some(s.0), + None => None, } } diff --git a/src/gui_egui/helper.rs b/src/gui_egui/helper.rs index d4d23d15..4ccb5520 100644 --- a/src/gui_egui/helper.rs +++ b/src/gui_egui/helper.rs @@ -16,6 +16,13 @@ pub fn offset_reverse_helper(xy: (f32, f32), scale: f32, offset: Vec2) -> Pos2 { } } +pub fn offset_helper_pos2(xy: Pos2, scale: f32, offset: Vec2) -> Pos2 { + egui::Pos2 { + x: xy.x * scale, + y: xy.y * scale, + } + offset +} + pub fn offset_helper(xy: (f32, f32), scale: f32, offset: Vec2) -> Pos2 { egui::Pos2 { x: xy.0 * scale, diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 6002cb62..3d006507 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -23,6 +23,7 @@ pub struct Shortcuts { pub view_zoom_in: KeyboardShortcut, pub view_zoom_out: KeyboardShortcut, pub view_grid_toggle: KeyboardShortcut, + pub view_grid_snap_toggle: KeyboardShortcut, pub control_play_toggle: KeyboardShortcut, pub control_play: KeyboardShortcut, pub control_pause: KeyboardShortcut, @@ -122,6 +123,16 @@ impl Shortcuts { modifiers: ctrl, key: Key::G, }, + view_grid_snap_toggle: KeyboardShortcut { + modifiers: Modifiers { + alt: false, + ctrl: true, + shift: true, + mac_cmd: false, + command: false, + }, + key: Key::G, + }, control_play: KeyboardShortcut { modifiers: none, key: Key::F6, @@ -203,6 +214,9 @@ impl Shortcuts { if ctx.input_mut(|i| i.consume_shortcut(&self.view_grid_toggle)) { view_grid_toggle_fn(gui); } + if ctx.input_mut(|i| i.consume_shortcut(&self.view_grid_snap_toggle)) { + view_grid_snap_toggle_fn(gui); + } if ctx.input_mut(|i| i.consume_shortcut(&self.control_play_toggle)) { control_play_toggle_fn(gui); } @@ -341,6 +355,12 @@ pub fn view_grid_toggle_fn(gui: &mut Gui) { editor.grid_enable = !editor.grid_enable; } } +pub fn view_grid_snap_toggle_fn(gui: &mut Gui) { + if gui.editor_use { + let editor = gui.editor.as_mut().unwrap(); + editor.grid_snap_enable = !editor.grid_snap_enable; + } +} pub fn control_play_toggle_fn(gui: &mut Gui) { if !gui.editor_use { gui.pause = !gui.pause; diff --git a/src/gui_egui/menu.rs b/src/gui_egui/menu.rs index c2ad7d4f..380d31ac 100644 --- a/src/gui_egui/menu.rs +++ b/src/gui_egui/menu.rs @@ -51,7 +51,10 @@ impl Menu { let mut grid_enable = editor(gui).grid_enable; let mut grid_size = editor(gui).grid_size; let mut grid_opacity = editor(gui).grid_opacity; - let view_grid_toggle = gui.shortcuts.view_grid_toggle.clone(); + let mut grid_snap_enable = editor(gui).grid_snap_enable; + let mut grid_snap_distance = editor(gui).grid_snap_distance; + let view_grid_toggle = gui.shortcuts.view_grid_toggle; + let view_grid_snap_toggle = gui.shortcuts.view_grid_snap_toggle; shared_buttons_view(gui, ui, &mut scale, |ui| { ui.horizontal(|ui| { ui.checkbox(&mut grid_enable, "Grid Enable"); @@ -69,11 +72,21 @@ impl Menu { .speed(0.02f32), ); }); + ui.horizontal(|ui| { + ui.checkbox(&mut grid_snap_enable, "Grid Snapping Enable"); + ui.label(ui.ctx().format_shortcut(&view_grid_snap_toggle)); + }); + ui.horizontal(|ui| { + ui.label("Grid Snap Distance:"); + ui.add(DragValue::new(&mut grid_snap_distance).clamp_range(0f32..=100f32)); + }); }); editor(gui).scale = scale; editor(gui).grid_enable = grid_enable; editor(gui).grid_size = grid_size; editor(gui).grid_opacity = grid_opacity; + editor(gui).grid_snap_enable = grid_snap_enable; + editor(gui).grid_snap_distance = grid_snap_distance; shared_buttons_help(gui, ui); }); ui.horizontal(|ui| { From 7fbf9d65d8f8400834d1b550d65964407daeb789 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 19 Aug 2023 12:59:57 +0200 Subject: [PATCH 47/58] Delete with del key --- src/gui_egui/component_ui.rs | 50 +++++++++++++++++++++++++-- src/gui_egui/components/add.rs | 18 +++------- src/gui_egui/components/constant.rs | 19 +++------- src/gui_egui/components/mem.rs | 20 +++-------- src/gui_egui/components/mux.rs | 18 +++------- src/gui_egui/components/probe.rs | 18 +++------- src/gui_egui/components/probe_edit.rs | 17 +++------ src/gui_egui/components/register.rs | 18 +++------- src/gui_egui/components/sext.rs | 18 +++------- 9 files changed, 80 insertions(+), 116 deletions(-) diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index ba770093..d03c2642 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -4,8 +4,8 @@ use crate::gui_egui::helper::{ editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, }; use egui::{ - containers, Color32, ComboBox, DragValue, Frame, Margin, PointerButton, Pos2, Rect, Response, - Rounding, Shape, Stroke, Ui, Vec2, Window, + containers, Color32, ComboBox, Context, DragValue, Frame, Key, KeyboardShortcut, Margin, + Modifiers, PointerButton, Pos2, Rect, Response, Rounding, Shape, Stroke, Ui, Vec2, Window, }; use epaint::{CircleShape, Shadow}; @@ -188,3 +188,49 @@ pub fn visualize_ports( }); } } + +/// Returns if the dragged object should be deleted +pub fn drag_logic( + ctx: &Context, + resp: &Response, + pos: &mut (f32, f32), + scale: f32, + offset: Vec2, +) -> bool { + let mut delete = false; + if resp.dragged_by(PointerButton::Primary) { + if ctx.input_mut(|i| { + i.consume_shortcut(&KeyboardShortcut { + modifiers: Modifiers { + alt: false, + ctrl: false, + shift: false, + mac_cmd: false, + command: false, + }, + key: Key::Delete, + }) + }) || ctx.input_mut(|i| { + i.consume_shortcut(&KeyboardShortcut { + modifiers: Modifiers { + alt: false, + ctrl: false, + shift: false, + mac_cmd: false, + command: false, + }, + key: Key::X, + }) + }) { + delete = true; + } + let delta = resp.drag_delta() / scale; + *pos = (pos.0 + delta.x, pos.1 + delta.y); + } + if resp.drag_released_by(PointerButton::Primary) + && resp.interact_pointer_pos().unwrap().x < offset.x + { + delete = true; + } + delete +} diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 05cd8b39..64069d0d 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -1,6 +1,6 @@ use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, - visualize_ports, + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; @@ -9,7 +9,7 @@ use crate::{ common::{EguiComponent, Ports, Simulator}, components::Add, }; -use egui::{Color32, PointerButton, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; +use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Add { @@ -91,7 +91,6 @@ impl EguiComponent for Add { id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { - let mut delete = false; let r_vec = Add::render( self, ui, @@ -104,16 +103,7 @@ impl EguiComponent for Add { ) .unwrap(); let resp = &r_vec[0]; - if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta() / scale; - self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); - } - - if resp.drag_released_by(PointerButton::Primary) - && resp.interact_pointer_pos().unwrap().x < offset.x - { - delete = true; - } + let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); properties_window( ui, diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index db3d5231..ea4b2355 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -1,14 +1,12 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, SignalValue, Simulator}; use crate::components::Constant; use crate::gui_egui::component_ui::{ - input_change_id, pos_drag_value, properties_window, rect_with_hover, visualize_ports, + drag_logic, input_change_id, pos_drag_value, properties_window, rect_with_hover, + visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; -use egui::{ - Align2, Area, Color32, DragValue, Order, PointerButton, Pos2, Rect, Response, RichText, Ui, - Vec2, -}; +use egui::{Align2, Area, Color32, DragValue, Order, Pos2, Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Constant { @@ -84,7 +82,6 @@ impl EguiComponent for Constant { id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { - let mut delete = false; let r_vec = Constant::render( self, ui, @@ -97,15 +94,7 @@ impl EguiComponent for Constant { ) .unwrap(); let resp = &r_vec[0]; - if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta() / scale; - self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); - } - if resp.drag_released_by(PointerButton::Primary) - && resp.interact_pointer_pos().unwrap().x < offset.x - { - delete = true; - } + let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); properties_window( ui, diff --git a/src/gui_egui/components/mem.rs b/src/gui_egui/components/mem.rs index a6c87888..722e2439 100644 --- a/src/gui_egui/components/mem.rs +++ b/src/gui_egui/components/mem.rs @@ -1,15 +1,13 @@ use crate::common::{EguiComponent, Ports, Simulator}; use crate::components::Mem; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, - visualize_ports, + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{ - Color32, PointerButton, Pos2, Rect, Response, Rounding, Shape, Slider, Stroke, Ui, Vec2, -}; +use egui::{Color32, Pos2, Rect, Response, Rounding, Shape, Slider, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Mem { @@ -69,7 +67,6 @@ impl EguiComponent for Mem { id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { - let mut delete = false; let r_vec = Mem::render( self, ui, @@ -83,16 +80,7 @@ impl EguiComponent for Mem { .unwrap(); let resp = &r_vec[0]; context.size_rect = resp.rect; - if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta() / scale; - self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); - } - - if resp.drag_released_by(PointerButton::Primary) - && resp.interact_pointer_pos().unwrap().x < offset.x - { - delete = true; - } + let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); properties_window( ui, diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index e8dcb898..982549d7 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -1,13 +1,13 @@ use crate::common::{EguiComponent, Input, Ports, SignalUnsigned, Simulator}; use crate::components::Mux; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, input_selector_removeable, pos_drag_value, properties_window, - rect_with_hover, visualize_ports, + drag_logic, input_change_id, input_selector, input_selector_removeable, pos_drag_value, + properties_window, rect_with_hover, visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{Color32, PointerButton, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; +use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Mux { @@ -94,7 +94,6 @@ impl EguiComponent for Mux { id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { - let mut delete = false; let r_vec = Mux::render( self, ui, @@ -107,16 +106,7 @@ impl EguiComponent for Mux { ) .unwrap(); let resp = &r_vec[0]; - if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta() / scale; - self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); - } - - if resp.drag_released_by(PointerButton::Primary) - && resp.interact_pointer_pos().unwrap().x < offset.x - { - delete = true; - } + let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); properties_window( ui, diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index d84b0c41..353eda48 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -1,12 +1,12 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, SignalValue, Simulator}; use crate::components::Probe; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, - visualize_ports, + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; -use egui::{Align2, Area, Color32, Order, PointerButton, Pos2, Rect, Response, RichText, Ui, Vec2}; +use egui::{Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Probe { @@ -88,7 +88,6 @@ impl EguiComponent for Probe { id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { - let mut delete = false; let r_vec = Probe::render( self, ui, @@ -101,16 +100,7 @@ impl EguiComponent for Probe { ) .unwrap(); let resp = &r_vec[0]; - if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta() / scale; - self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); - } - - if resp.drag_released_by(PointerButton::Primary) - && resp.interact_pointer_pos().unwrap().x < offset.x - { - delete = true; - } + let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); properties_window( ui, diff --git a/src/gui_egui/components/probe_edit.rs b/src/gui_egui/components/probe_edit.rs index 013d732b..5dd58b9f 100644 --- a/src/gui_egui/components/probe_edit.rs +++ b/src/gui_egui/components/probe_edit.rs @@ -1,11 +1,12 @@ use crate::common::{EguiComponent, Ports, SignalSigned, SignalUnsigned, SignalValue, Simulator}; use crate::components::{ProbeEdit, TextSignal}; use crate::gui_egui::component_ui::{ - input_change_id, pos_drag_value, properties_window, rect_with_hover, visualize_ports, + drag_logic, input_change_id, pos_drag_value, properties_window, rect_with_hover, + visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; -use egui::{Align2, Area, DragValue, Order, PointerButton, Pos2, Rect, Response, Ui, Vec2}; +use egui::{Align2, Area, DragValue, Order, Pos2, Rect, Response, Ui, Vec2}; #[typetag::serde] impl EguiComponent for ProbeEdit { @@ -102,7 +103,6 @@ impl EguiComponent for ProbeEdit { id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { - let mut delete = false; let r_vec = ProbeEdit::render( self, ui, @@ -115,16 +115,7 @@ impl EguiComponent for ProbeEdit { ) .unwrap(); let resp = &r_vec[0]; - if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta() / scale; - self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); - } - - if resp.drag_released_by(PointerButton::Primary) - && resp.interact_pointer_pos().unwrap().x < offset.x - { - delete = true; - } + let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); properties_window( ui, diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index 0fc0d4a9..b0680a3a 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -1,13 +1,13 @@ use crate::common::{EguiComponent, Ports, Simulator}; use crate::components::Register; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, - visualize_ports, + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{Color32, PointerButton, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; +use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Register { @@ -73,7 +73,6 @@ impl EguiComponent for Register { id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { - let mut delete = false; let r_vec = Register::render( self, ui, @@ -86,16 +85,7 @@ impl EguiComponent for Register { ) .unwrap(); let resp = &r_vec[0]; - if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta() / scale; - self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); - } - - if resp.drag_released_by(PointerButton::Primary) - && resp.interact_pointer_pos().unwrap().x < offset.x - { - delete = true; - } + let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); properties_window( ui, diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index 26f9493c..6eb564d2 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -1,13 +1,13 @@ use crate::common::{EguiComponent, Ports, SignalUnsigned, Simulator}; use crate::components::Sext; use crate::gui_egui::component_ui::{ - input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, - visualize_ports, + drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, + rect_with_hover, visualize_ports, }; use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; -use egui::{Color32, PointerButton, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; +use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; #[typetag::serde] impl EguiComponent for Sext { @@ -81,7 +81,6 @@ impl EguiComponent for Sext { id_ports: &[(crate::common::Id, Ports)], editor_mode: EditorMode, ) -> EditorRenderReturn { - let mut delete = false; let r_vec = Sext::render( self, ui, @@ -94,16 +93,7 @@ impl EguiComponent for Sext { ) .unwrap(); let resp = &r_vec[0]; - if resp.dragged_by(PointerButton::Primary) { - let delta = resp.drag_delta() / scale; - self.pos = (self.pos.0 + delta.x, self.pos.1 + delta.y); - } - - if resp.drag_released_by(PointerButton::Primary) - && resp.interact_pointer_pos().unwrap().x < offset.x - { - delete = true; - } + let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); properties_window( ui, From 1e7ee57f51fd25bebfe6b21d742a9eeecc5cc7bb Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 19 Aug 2023 13:29:02 +0200 Subject: [PATCH 48/58] Added snapping to grid with placing components --- src/gui_egui/component_ui.rs | 24 ++++++++++-------------- src/gui_egui/components/wire.rs | 29 +++++++++++++++++++++++++++-- src/gui_egui/editor_wire_mode.rs | 6 ++++-- src/gui_egui/library.rs | 28 ++++++++++++++++++++++++---- 4 files changed, 65 insertions(+), 22 deletions(-) diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index d03c2642..5830380b 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -199,26 +199,22 @@ pub fn drag_logic( ) -> bool { let mut delete = false; if resp.dragged_by(PointerButton::Primary) { + let mod_none = Modifiers { + alt: false, + ctrl: false, + shift: false, + mac_cmd: false, + command: false, + }; + if ctx.input_mut(|i| { i.consume_shortcut(&KeyboardShortcut { - modifiers: Modifiers { - alt: false, - ctrl: false, - shift: false, - mac_cmd: false, - command: false, - }, + modifiers: mod_none, key: Key::Delete, }) }) || ctx.input_mut(|i| { i.consume_shortcut(&KeyboardShortcut { - modifiers: Modifiers { - alt: false, - ctrl: false, - shift: false, - mac_cmd: false, - command: false, - }, + modifiers: mod_none, key: Key::X, }) }) { diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index f56a7c41..02877006 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -7,8 +7,8 @@ use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, SnapPriority}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; use egui::{ - Color32, DragValue, Frame, Margin, PointerButton, Pos2, Rect, Response, Rounding, Shape, - Stroke, Ui, Vec2, Window, + Color32, DragValue, Frame, Key, KeyboardShortcut, Margin, Modifiers, PointerButton, Pos2, Rect, + Response, Rounding, Shape, Stroke, Ui, Vec2, Window, }; use epaint::Shadow; @@ -110,6 +110,31 @@ impl EguiComponent for Wire { let mut properties_window_open = false; for (i, resp) in r_vec.iter().enumerate() { if resp.dragged_by(PointerButton::Primary) { + if ui.ctx().input_mut(|i| { + i.consume_shortcut(&KeyboardShortcut { + modifiers: Modifiers { + alt: false, + ctrl: false, + shift: false, + mac_cmd: false, + command: false, + }, + key: Key::Delete, + }) + }) || ui.ctx().input_mut(|i| { + i.consume_shortcut(&KeyboardShortcut { + modifiers: Modifiers { + alt: false, + ctrl: false, + shift: false, + mac_cmd: false, + command: false, + }, + key: Key::X, + }) + }) { + delete = true; + } let delta = resp.drag_delta() / scale; self.pos[i] = (self.pos[i].0 + delta.x, self.pos[i].1 + delta.y); self.pos[i + 1] = (self.pos[i + 1].0 + delta.x, self.pos[i + 1].1 + delta.y); diff --git a/src/gui_egui/editor_wire_mode.rs b/src/gui_egui/editor_wire_mode.rs index d4016dd3..07bebc1d 100644 --- a/src/gui_egui/editor_wire_mode.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -45,7 +45,7 @@ pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { } None => { if !e.wm.temp_positions.is_empty() { - let mut wires = if e.grid_snap_enable { + let mut wires = if e.grid_enable && e.grid_snap_enable { match get_grid_snap(e.grid_snap_distance, offset_cursor_scale, e.grid_size) { Some(g) => { @@ -165,6 +165,7 @@ pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option< e.offset_and_pan, e.scale, e.grid_enable, + e.grid_snap_enable, e.grid_snap_distance, e.grid_size, ); @@ -364,13 +365,14 @@ pub fn get_location_of_port_wire_grid_inside_radius( offset: Vec2, scale: f32, grid_enable: bool, + grid_snap_enable: bool, grid_snap_distance: f32, grid_size: f32, ) -> Pos2 { match get_closest_component_non_wire_prio(port, wire, distance) { Some(c) => c.pos + offset, None => { - if grid_enable { + if grid_enable && grid_snap_enable { match get_grid_snap( grid_snap_distance, offset_reverse_helper_pos2(cursor_location, scale, offset), diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index 2c0f18e6..3bdf5dc1 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -1,9 +1,9 @@ use crate::common::EguiComponent; use crate::components::*; -use crate::gui_egui::editor::EditorMode; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::{ - editor::Editor, + editor::{Editor, EditorMode}, + editor_wire_mode::get_grid_snap, helper::{id_ports_of_all_components, offset_reverse_helper_pos2, unique_component_name}, }; use egui::{Context, CursorIcon, LayerId, PointerButton, Pos2, Rect, Response, Ui, Vec2}; @@ -43,6 +43,18 @@ pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option clip_rect, Rect::EVERYTHING, ); + let pos = if e.grid_enable && e.grid_snap_enable { + match get_grid_snap( + e.grid_snap_distance, + offset_reverse_helper_pos2(e.im.cursor_location, e.scale, e.offset_and_pan), + e.grid_size, + ) { + Some(s) => Vec2::new(s.x, s.y) + e.offset_and_pan, + None => Vec2::new(e.im.cursor_location.x, e.im.cursor_location.y), + } + } else { + Vec2::new(e.im.cursor_location.x, e.im.cursor_location.y) + }; e.im.comp.as_ref().unwrap().render( &mut ui, &mut EguiExtra { @@ -51,7 +63,7 @@ pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option size_rect: Rect::NAN, }, None, - Vec2::new(e.im.cursor_location.x, e.im.cursor_location.y), + pos, e.scale, clip_rect, e.editor_mode, @@ -120,7 +132,15 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { // todo: This should really just copy the component that's in e.input_comp pub fn add_comp_to_editor(e: &mut Editor) { - let pos = offset_reverse_helper_pos2(e.im.cursor_location, e.scale, e.offset); + let mut pos = offset_reverse_helper_pos2(e.im.cursor_location, e.scale, e.offset_and_pan); + if e.grid_enable && e.grid_snap_enable { + match get_grid_snap(e.grid_snap_distance, pos, e.grid_size) { + Some(p) => { + pos = p; + } + None => (), + } + } let id_ports = id_ports_of_all_components(&e.components); let id; let mut comp: Rc = From 56e7d70dfdb324f361e65a4bbfb0ce155a8514eb Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 19 Aug 2023 14:08:30 +0200 Subject: [PATCH 49/58] Fixed grid --- src/gui_egui/editor.rs | 10 ++++++---- src/gui_egui/editor_wire_mode.rs | 14 ++++++-------- src/gui_egui/library.rs | 9 +++------ 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 5fdb1682..05afaf96 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -272,14 +272,16 @@ impl Editor { let e = Editor::gui_to_editor(gui); let screen_rect = ui.ctx().screen_rect(); let grid_scale = e.grid_size * e.scale; - let start = -(e.pan / e.scale / e.grid_size).floor(); + let start = -(e.pan / e.grid_size / e.scale).floor(); + let end = (Vec2::new(screen_rect.width(), screen_rect.height()) / e.scale / e.grid_size) - .ceil(); + .ceil() + + start; for y in (start.y as i32)..(end.y as i32) { ui.painter().hline( - (start.x * grid_scale)..=(end.x * grid_scale), + 0f32..=screen_rect.width(), y as f32 * grid_scale + e.offset_and_pan.y, egui::Stroke { width: e.scale * 0.5f32, @@ -290,7 +292,7 @@ impl Editor { for x in (start.x as i32)..(end.x as i32) { ui.painter().vline( x as f32 * grid_scale + e.offset_and_pan.x, - (start.y * grid_scale)..=(end.y * grid_scale), + 0f32..=screen_rect.height(), egui::Stroke { width: e.scale * 0.5f32, color: egui::Color32::BLACK.gamma_multiply(e.grid_opacity), diff --git a/src/gui_egui/editor_wire_mode.rs b/src/gui_egui/editor_wire_mode.rs index 07bebc1d..2d4ee021 100644 --- a/src/gui_egui/editor_wire_mode.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -357,6 +357,7 @@ pub fn get_closest_component_non_wire_prio( } } +#[allow(clippy::too_many_arguments)] pub fn get_location_of_port_wire_grid_inside_radius( port: Option, wire: Option, @@ -370,7 +371,7 @@ pub fn get_location_of_port_wire_grid_inside_radius( grid_size: f32, ) -> Pos2 { match get_closest_component_non_wire_prio(port, wire, distance) { - Some(c) => c.pos + offset, + Some(c) => offset_helper_pos2(c.pos, scale, offset), None => { if grid_enable && grid_snap_enable { match get_grid_snap( @@ -396,21 +397,18 @@ pub fn get_grid_snap(distance: f32, clicked_pos: Pos2, grid_size: f32) -> Option let bottom_right = Pos2::new(top_left.x + grid_size, top_left.y + grid_size); let top_left = Pos2::new(top_left.x, top_left.y); let mut closest: Option<(Pos2, f32)> = None; - for pos in vec![top_left, top_right, bottom_left, bottom_right] { + for pos in &[top_left, top_right, bottom_left, bottom_right] { let d = pos.distance(clicked_pos); if d <= distance { match closest { Some(s) => { if s.1 > d { - closest = Some((pos, d)) + closest = Some((*pos, d)) } } - None => closest = Some((pos, d)), + None => closest = Some((*pos, d)), } } } - match closest { - Some(s) => Some(s.0), - None => None, - } + closest.map(|s| s.0) } diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index 3bdf5dc1..a1659bf2 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -49,7 +49,7 @@ pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option offset_reverse_helper_pos2(e.im.cursor_location, e.scale, e.offset_and_pan), e.grid_size, ) { - Some(s) => Vec2::new(s.x, s.y) + e.offset_and_pan, + Some(s) => Vec2::new(s.x, s.y) * e.scale + e.offset + e.pan * e.scale, None => Vec2::new(e.im.cursor_location.x, e.im.cursor_location.y), } } else { @@ -134,11 +134,8 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { pub fn add_comp_to_editor(e: &mut Editor) { let mut pos = offset_reverse_helper_pos2(e.im.cursor_location, e.scale, e.offset_and_pan); if e.grid_enable && e.grid_snap_enable { - match get_grid_snap(e.grid_snap_distance, pos, e.grid_size) { - Some(p) => { - pos = p; - } - None => (), + if let Some(p) = get_grid_snap(e.grid_snap_distance, pos, e.grid_size) { + pos = p; } } let id_ports = id_ports_of_all_components(&e.components); From feb59249868674372f5107d694e10447c2146c19 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 19 Aug 2023 15:05:55 +0200 Subject: [PATCH 50/58] Fixed snapping when moving components --- src/common.rs | 7 ++++- src/gui_egui/component_ui.rs | 15 ++++++++-- src/gui_egui/components/add.rs | 17 ++++++++++-- src/gui_egui/components/constant.rs | 17 ++++++++++-- src/gui_egui/components/mem.rs | 17 ++++++++++-- src/gui_egui/components/mux.rs | 17 ++++++++++-- src/gui_egui/components/probe.rs | 17 ++++++++++-- src/gui_egui/components/probe_edit.rs | 17 ++++++++++-- src/gui_egui/components/register.rs | 17 ++++++++++-- src/gui_egui/components/sext.rs | 17 ++++++++++-- src/gui_egui/components/wire.rs | 7 ++++- src/gui_egui/editor.rs | 40 ++++++++++++++++----------- src/gui_egui/editor_wire_mode.rs | 27 ++++++++---------- src/gui_egui/gui.rs | 7 +++-- src/gui_egui/keymap.rs | 4 +-- src/gui_egui/library.rs | 19 +++++++------ src/gui_egui/menu.rs | 28 +++++++++++-------- 17 files changed, 216 insertions(+), 74 deletions(-) diff --git a/src/common.rs b/src/common.rs index 3c321f15..5840e1ff 100644 --- a/src/common.rs +++ b/src/common.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use std::{collections::HashMap, rc::Rc}; #[cfg(feature = "gui-egui")] -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, SnapPriority}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions, SnapPriority}; #[cfg(feature = "gui-vizia")] use vizia::prelude::*; @@ -118,6 +118,7 @@ pub trait EguiComponent: Component { _scale: f32, _clip_rect: egui::Rect, _id_ports: &[(Id, Ports)], + _grid: &GridOptions, _editor_mode: EditorMode, ) -> EditorRenderReturn { EditorRenderReturn { @@ -143,6 +144,10 @@ pub trait EguiComponent: Component { todo!("Create set_pos for this EguiComponent"); } + fn get_pos(&self) -> (f32, f32) { + todo!("Create get_pos for this EguiComponent"); + } + fn set_id_tmp(&self, context: &mut EguiExtra) { context.id_tmp = self.get_id_ports().0.clone(); } diff --git a/src/gui_egui/component_ui.rs b/src/gui_egui/component_ui.rs index 5830380b..7e199d00 100644 --- a/src/gui_egui/component_ui.rs +++ b/src/gui_egui/component_ui.rs @@ -1,5 +1,6 @@ use crate::common::{Input, Ports}; -use crate::gui_egui::editor::EditorMode; +use crate::gui_egui::editor::{EditorMode, GridOptions}; +use crate::gui_egui::editor_wire_mode::get_grid_snap; use crate::gui_egui::helper::{ editor_mode_to_sense, offset_helper, out_of_bounds, unique_component_name, }; @@ -194,8 +195,10 @@ pub fn drag_logic( ctx: &Context, resp: &Response, pos: &mut (f32, f32), + tmp_pos: &mut Pos2, scale: f32, offset: Vec2, + grid: &GridOptions, ) -> bool { let mut delete = false; if resp.dragged_by(PointerButton::Primary) { @@ -221,7 +224,15 @@ pub fn drag_logic( delete = true; } let delta = resp.drag_delta() / scale; - *pos = (pos.0 + delta.x, pos.1 + delta.y); + *tmp_pos += delta; + if grid.enable && grid.snap_enable { + match get_grid_snap(grid.snap_distance, *tmp_pos, grid.size) { + Some(p) => *pos = (p.x, p.y), + None => *pos = (pos.0 + delta.x, pos.1 + delta.y), + } + } else { + *pos = (pos.0 + delta.x, pos.1 + delta.y); + } } if resp.drag_released_by(PointerButton::Primary) && resp.interact_pointer_pos().unwrap().x < offset.x diff --git a/src/gui_egui/components/add.rs b/src/gui_egui/components/add.rs index 64069d0d..17eb2253 100644 --- a/src/gui_egui/components/add.rs +++ b/src/gui_egui/components/add.rs @@ -2,7 +2,7 @@ use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, visualize_ports, }; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; use crate::{ @@ -89,6 +89,7 @@ impl EguiComponent for Add { scale: f32, clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { let r_vec = Add::render( @@ -103,7 +104,15 @@ impl EguiComponent for Add { ) .unwrap(); let resp = &r_vec[0]; - let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); properties_window( ui, @@ -167,4 +176,8 @@ impl EguiComponent for Add { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } } diff --git a/src/gui_egui/components/constant.rs b/src/gui_egui/components/constant.rs index ea4b2355..88a70186 100644 --- a/src/gui_egui/components/constant.rs +++ b/src/gui_egui/components/constant.rs @@ -4,7 +4,7 @@ use crate::gui_egui::component_ui::{ drag_logic, input_change_id, pos_drag_value, properties_window, rect_with_hover, visualize_ports, }; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use egui::{Align2, Area, Color32, DragValue, Order, Pos2, Rect, Response, RichText, Ui, Vec2}; @@ -80,6 +80,7 @@ impl EguiComponent for Constant { scale: f32, clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { let r_vec = Constant::render( @@ -94,7 +95,15 @@ impl EguiComponent for Constant { ) .unwrap(); let resp = &r_vec[0]; - let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); properties_window( ui, @@ -136,4 +145,8 @@ impl EguiComponent for Constant { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } } diff --git a/src/gui_egui/components/mem.rs b/src/gui_egui/components/mem.rs index 722e2439..aa6abf4a 100644 --- a/src/gui_egui/components/mem.rs +++ b/src/gui_egui/components/mem.rs @@ -4,7 +4,7 @@ use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, visualize_ports, }; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; use egui::{Color32, Pos2, Rect, Response, Rounding, Shape, Slider, Stroke, Ui, Vec2}; @@ -65,6 +65,7 @@ impl EguiComponent for Mem { scale: f32, clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { let r_vec = Mem::render( @@ -80,7 +81,15 @@ impl EguiComponent for Mem { .unwrap(); let resp = &r_vec[0]; context.size_rect = resp.rect; - let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); properties_window( ui, @@ -196,4 +205,8 @@ impl EguiComponent for Mem { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } } diff --git a/src/gui_egui/components/mux.rs b/src/gui_egui/components/mux.rs index 982549d7..4b24b4ca 100644 --- a/src/gui_egui/components/mux.rs +++ b/src/gui_egui/components/mux.rs @@ -4,7 +4,7 @@ use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, input_selector_removeable, pos_drag_value, properties_window, rect_with_hover, visualize_ports, }; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; @@ -92,6 +92,7 @@ impl EguiComponent for Mux { scale: f32, clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { let r_vec = Mux::render( @@ -106,7 +107,15 @@ impl EguiComponent for Mux { ) .unwrap(); let resp = &r_vec[0]; - let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); properties_window( ui, @@ -183,4 +192,8 @@ impl EguiComponent for Mux { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } } diff --git a/src/gui_egui/components/probe.rs b/src/gui_egui/components/probe.rs index 353eda48..5d835140 100644 --- a/src/gui_egui/components/probe.rs +++ b/src/gui_egui/components/probe.rs @@ -4,7 +4,7 @@ use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, visualize_ports, }; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use egui::{Align2, Area, Color32, Order, Pos2, Rect, Response, RichText, Ui, Vec2}; @@ -86,6 +86,7 @@ impl EguiComponent for Probe { scale: f32, clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { let r_vec = Probe::render( @@ -100,7 +101,15 @@ impl EguiComponent for Probe { ) .unwrap(); let resp = &r_vec[0]; - let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); properties_window( ui, @@ -144,4 +153,8 @@ impl EguiComponent for Probe { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } } diff --git a/src/gui_egui/components/probe_edit.rs b/src/gui_egui/components/probe_edit.rs index 5dd58b9f..cadead9b 100644 --- a/src/gui_egui/components/probe_edit.rs +++ b/src/gui_egui/components/probe_edit.rs @@ -4,7 +4,7 @@ use crate::gui_egui::component_ui::{ drag_logic, input_change_id, pos_drag_value, properties_window, rect_with_hover, visualize_ports, }; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use egui::{Align2, Area, DragValue, Order, Pos2, Rect, Response, Ui, Vec2}; @@ -101,6 +101,7 @@ impl EguiComponent for ProbeEdit { scale: f32, clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { let r_vec = ProbeEdit::render( @@ -115,7 +116,15 @@ impl EguiComponent for ProbeEdit { ) .unwrap(); let resp = &r_vec[0]; - let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); properties_window( ui, @@ -152,6 +161,10 @@ impl EguiComponent for ProbeEdit { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } } fn parse_signal(text: &str) -> SignalValue { diff --git a/src/gui_egui/components/register.rs b/src/gui_egui/components/register.rs index b0680a3a..88b67e81 100644 --- a/src/gui_egui/components/register.rs +++ b/src/gui_egui/components/register.rs @@ -4,7 +4,7 @@ use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, visualize_ports, }; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; use egui::{Color32, Pos2, Rect, Response, Shape, Stroke, Ui, Vec2}; @@ -71,6 +71,7 @@ impl EguiComponent for Register { scale: f32, clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { let r_vec = Register::render( @@ -85,7 +86,15 @@ impl EguiComponent for Register { ) .unwrap(); let resp = &r_vec[0]; - let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); properties_window( ui, @@ -134,4 +143,8 @@ impl EguiComponent for Register { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } } diff --git a/src/gui_egui/components/sext.rs b/src/gui_egui/components/sext.rs index 6eb564d2..05ce6bee 100644 --- a/src/gui_egui/components/sext.rs +++ b/src/gui_egui/components/sext.rs @@ -4,7 +4,7 @@ use crate::gui_egui::component_ui::{ drag_logic, input_change_id, input_selector, pos_drag_value, properties_window, rect_with_hover, visualize_ports, }; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; use egui::{Color32, Pos2, Rect, Response, Shape, Slider, Stroke, Ui, Vec2}; @@ -79,6 +79,7 @@ impl EguiComponent for Sext { scale: f32, clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], + grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { let r_vec = Sext::render( @@ -93,7 +94,15 @@ impl EguiComponent for Sext { ) .unwrap(); let resp = &r_vec[0]; - let delete = drag_logic(ui.ctx(), resp, &mut self.pos, scale, offset); + let delete = drag_logic( + ui.ctx(), + resp, + &mut self.pos, + &mut context.pos_tmp, + scale, + offset, + grid, + ); properties_window( ui, @@ -145,4 +154,8 @@ impl EguiComponent for Sext { fn set_pos(&mut self, pos: (f32, f32)) { self.pos = pos; } + + fn get_pos(&self) -> (f32, f32) { + self.pos + } } diff --git a/src/gui_egui/components/wire.rs b/src/gui_egui/components/wire.rs index 02877006..2079a5d6 100644 --- a/src/gui_egui/components/wire.rs +++ b/src/gui_egui/components/wire.rs @@ -3,7 +3,7 @@ use crate::components::Wire; use crate::gui_egui::component_ui::{ input_change_id, input_selector, rect_with_hover, visualize_ports, }; -use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, SnapPriority}; +use crate::gui_egui::editor::{EditorMode, EditorRenderReturn, GridOptions, SnapPriority}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::offset_helper; use egui::{ @@ -92,6 +92,7 @@ impl EguiComponent for Wire { scale: f32, clip_rect: Rect, id_ports: &[(crate::common::Id, Ports)], + _grid: &GridOptions, editor_mode: EditorMode, ) -> EditorRenderReturn { let mut delete = false; @@ -223,4 +224,8 @@ impl EguiComponent for Wire { fn snap_priority(&self) -> SnapPriority { SnapPriority::Wire } + + fn get_pos(&self) -> (f32, f32) { + (0f32, 0f32) + } } diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 05afaf96..11828300 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -23,11 +23,7 @@ pub struct Editor { pub side_panel_width: f32, pub ui_change: bool, pub snap_distance: f32, - pub grid_enable: bool, - pub grid_size: f32, - pub grid_opacity: f32, - pub grid_snap_enable: bool, - pub grid_snap_distance: f32, + pub grid: GridOptions, pub library: Components, pub dummy_input: Input, pub editor_mode: EditorMode, @@ -66,6 +62,15 @@ pub enum SnapPriority { Wire, } +#[derive(Clone)] +pub struct GridOptions { + pub enable: bool, + pub size: f32, + pub opacity: f32, + pub snap_enable: bool, + pub snap_distance: f32, +} + impl Editor { pub fn gui(components: Components, _path: &Path) -> Self { let dummy_input = Input::new("id", "field"); @@ -136,11 +141,13 @@ impl Editor { side_panel_width: 400f32, ui_change: true, snap_distance: 10f32, - grid_enable: true, - grid_size: 20f32, - grid_opacity: 0.5f32, - grid_snap_enable: true, - grid_snap_distance: 20f32, + grid: GridOptions { + enable: true, + size: 20f32, + opacity: 0.5f32, + snap_enable: true, + snap_distance: 20f32, + }, library, dummy_input, editor_mode: EditorMode::Default, @@ -268,14 +275,14 @@ impl Editor { } // draw grid - if Editor::gui_to_editor(gui).grid_enable { + if Editor::gui_to_editor(gui).grid.enable { let e = Editor::gui_to_editor(gui); let screen_rect = ui.ctx().screen_rect(); - let grid_scale = e.grid_size * e.scale; - let start = -(e.pan / e.grid_size / e.scale).floor(); + let grid_scale = e.grid.size * e.scale; + let start = -(e.pan / e.grid.size / e.scale).floor(); let end = - (Vec2::new(screen_rect.width(), screen_rect.height()) / e.scale / e.grid_size) + (Vec2::new(screen_rect.width(), screen_rect.height()) / e.scale / e.grid.size) .ceil() + start; @@ -285,7 +292,7 @@ impl Editor { y as f32 * grid_scale + e.offset_and_pan.y, egui::Stroke { width: e.scale * 0.5f32, - color: egui::Color32::BLACK.gamma_multiply(e.grid_opacity), + color: egui::Color32::BLACK.gamma_multiply(e.grid.opacity), }, ); } @@ -295,7 +302,7 @@ impl Editor { 0f32..=screen_rect.height(), egui::Stroke { width: e.scale * 0.5f32, - color: egui::Color32::BLACK.gamma_multiply(e.grid_opacity), + color: egui::Color32::BLACK.gamma_multiply(e.grid.opacity), }, ); } @@ -334,6 +341,7 @@ impl Editor { e.scale, e.clip_rect, &id_ports, + &e.grid, e.editor_mode, ); // only reinsert if it's not getting deleted diff --git a/src/gui_egui/editor_wire_mode.rs b/src/gui_egui/editor_wire_mode.rs index 2d4ee021..5db82452 100644 --- a/src/gui_egui/editor_wire_mode.rs +++ b/src/gui_egui/editor_wire_mode.rs @@ -1,6 +1,8 @@ use crate::common::{Components, Id, Input}; use crate::components::Wire; -use crate::gui_egui::editor::{get_component, CloseToComponent, Editor, EditorMode, SnapPriority}; +use crate::gui_egui::editor::{ + get_component, CloseToComponent, Editor, EditorMode, GridOptions, SnapPriority, +}; use crate::gui_egui::gui::EguiExtra; use crate::gui_egui::helper::{ id_ports_of_all_components, offset_helper, offset_helper_pos2, offset_reverse_helper, @@ -45,8 +47,8 @@ pub fn drag_started(ctx: &Context, e: &mut Editor, _cpr: Response) { } None => { if !e.wm.temp_positions.is_empty() { - let mut wires = if e.grid_enable && e.grid_snap_enable { - match get_grid_snap(e.grid_snap_distance, offset_cursor_scale, e.grid_size) + let mut wires = if e.grid.enable && e.grid.snap_enable { + match get_grid_snap(e.grid.snap_distance, offset_cursor_scale, e.grid.size) { Some(g) => { let new_loc = offset_helper_pos2(g, e.scale, e.offset_and_pan); @@ -108,8 +110,9 @@ pub fn last_click(e: &mut Editor, closest_uw: CloseToComponent) { id.to_string(), EguiExtra { properties_window: false, - id_tmp: id.to_string(), size_rect: Rect::NAN, + id_tmp: id.to_string(), + pos_tmp: Pos2::ZERO, }, ); @@ -164,10 +167,7 @@ pub fn wire_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option< e.wm.cursor_location, e.offset_and_pan, e.scale, - e.grid_enable, - e.grid_snap_enable, - e.grid_snap_distance, - e.grid_size, + &e.grid, ); let v = wire_split_into_two_vec( @@ -365,19 +365,16 @@ pub fn get_location_of_port_wire_grid_inside_radius( cursor_location: Pos2, offset: Vec2, scale: f32, - grid_enable: bool, - grid_snap_enable: bool, - grid_snap_distance: f32, - grid_size: f32, + grid: &GridOptions, ) -> Pos2 { match get_closest_component_non_wire_prio(port, wire, distance) { Some(c) => offset_helper_pos2(c.pos, scale, offset), None => { - if grid_enable && grid_snap_enable { + if grid.enable && grid.snap_enable { match get_grid_snap( - grid_snap_distance, + grid.snap_distance, offset_reverse_helper_pos2(cursor_location, scale, offset), - grid_size, + grid.size, ) { Some(s) => offset_helper_pos2(s, scale, offset), None => cursor_location, diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index 74c41a15..0d2bd325 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -29,8 +29,9 @@ pub struct Gui { #[derive(Clone, Debug)] pub struct EguiExtra { pub properties_window: bool, - pub id_tmp: String, pub size_rect: Rect, + pub id_tmp: String, + pub pos_tmp: Pos2, } pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { @@ -182,12 +183,14 @@ pub fn create_contexts(components: &Components) -> HashMap Vec2::new(s.x, s.y) * e.scale + e.offset + e.pan * e.scale, None => Vec2::new(e.im.cursor_location.x, e.im.cursor_location.y), @@ -59,8 +59,9 @@ pub fn input_mode(ctx: &Context, e: &mut Editor, cpr: Response, layer_id: Option &mut ui, &mut EguiExtra { properties_window: false, - id_tmp: String::new(), size_rect: Rect::NAN, + id_tmp: String::new(), + pos_tmp: Pos2::ZERO, }, None, pos, @@ -102,8 +103,9 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { ui, &mut EguiExtra { properties_window: false, - id_tmp: c.get_id_ports().0, size_rect: Rect::NAN, + id_tmp: c.get_id_ports().0, + pos_tmp: Pos2::ZERO, }, None, padding, @@ -133,8 +135,8 @@ pub fn show_library(e: &mut Editor, ui: &mut Ui) { // todo: This should really just copy the component that's in e.input_comp pub fn add_comp_to_editor(e: &mut Editor) { let mut pos = offset_reverse_helper_pos2(e.im.cursor_location, e.scale, e.offset_and_pan); - if e.grid_enable && e.grid_snap_enable { - if let Some(p) = get_grid_snap(e.grid_snap_distance, pos, e.grid_size) { + if e.grid.enable && e.grid.snap_enable { + if let Some(p) = get_grid_snap(e.grid.snap_distance, pos, e.grid.size) { pos = p; } } @@ -223,8 +225,9 @@ pub fn add_comp_to_editor(e: &mut Editor) { id.clone(), EguiExtra { properties_window: false, - id_tmp: id, size_rect: Rect::NAN, + id_tmp: id, + pos_tmp: pos, }, ); e.components.push(comp); diff --git a/src/gui_egui/menu.rs b/src/gui_egui/menu.rs index 380d31ac..6155e0ba 100644 --- a/src/gui_egui/menu.rs +++ b/src/gui_egui/menu.rs @@ -1,4 +1,8 @@ -use crate::gui_egui::{editor::Editor, gui::Gui, keymap}; +use crate::gui_egui::{ + editor::{Editor, GridOptions}, + gui::Gui, + keymap, +}; use egui::{menu, Button, DragValue, KeyboardShortcut, Response, Ui}; pub(crate) struct Menu {} @@ -48,11 +52,11 @@ impl Menu { shared_buttons_file(gui, ui); shared_buttons_edit(gui, ui); let mut scale = editor(gui).scale; - let mut grid_enable = editor(gui).grid_enable; - let mut grid_size = editor(gui).grid_size; - let mut grid_opacity = editor(gui).grid_opacity; - let mut grid_snap_enable = editor(gui).grid_snap_enable; - let mut grid_snap_distance = editor(gui).grid_snap_distance; + let mut grid_enable = editor(gui).grid.enable; + let mut grid_size = editor(gui).grid.size; + let mut grid_opacity = editor(gui).grid.opacity; + let mut grid_snap_enable = editor(gui).grid.snap_enable; + let mut grid_snap_distance = editor(gui).grid.snap_distance; let view_grid_toggle = gui.shortcuts.view_grid_toggle; let view_grid_snap_toggle = gui.shortcuts.view_grid_snap_toggle; shared_buttons_view(gui, ui, &mut scale, |ui| { @@ -82,11 +86,13 @@ impl Menu { }); }); editor(gui).scale = scale; - editor(gui).grid_enable = grid_enable; - editor(gui).grid_size = grid_size; - editor(gui).grid_opacity = grid_opacity; - editor(gui).grid_snap_enable = grid_snap_enable; - editor(gui).grid_snap_distance = grid_snap_distance; + editor(gui).grid = GridOptions { + enable: grid_enable, + size: grid_size, + opacity: grid_opacity, + snap_enable: grid_snap_enable, + snap_distance: grid_snap_distance, + }; shared_buttons_help(gui, ui); }); ui.horizontal(|ui| { From 058aedd2ec770fcd35681993771fdb4b39ececec Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 19 Aug 2023 15:15:24 +0200 Subject: [PATCH 51/58] Fix merge errors --- src/gui_egui/editor.rs | 13 +++++++++++-- src/gui_egui/library.rs | 12 ++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/gui_egui/editor.rs b/src/gui_egui/editor.rs index 11828300..915d418b 100644 --- a/src/gui_egui/editor.rs +++ b/src/gui_egui/editor.rs @@ -11,7 +11,12 @@ use crate::gui_egui::{ }; use eframe::{egui, Frame}; use egui::{Color32, Context, LayerId, PointerButton, Pos2, Rect, Shape, Vec2}; -use std::{collections::HashMap, path::Path, rc::Rc}; +use std::{ + collections::{BTreeMap, HashMap}, + ops::Range, + path::Path, + rc::Rc, +}; pub struct Editor { pub components: Components, @@ -110,7 +115,11 @@ impl Editor { ctrl: dummy_input.clone(), size: dummy_input.clone(), sext: dummy_input.clone(), - memory: Memory::new(HashMap::new()), + range: Range { + start: 0, + end: 0x20, + }, + memory: Memory::new(BTreeMap::new()), }), Rc::new(Mux { id: "mux".to_string(), diff --git a/src/gui_egui/library.rs b/src/gui_egui/library.rs index cdfdc5bf..50f23c9e 100644 --- a/src/gui_egui/library.rs +++ b/src/gui_egui/library.rs @@ -7,7 +7,11 @@ use crate::gui_egui::{ helper::{id_ports_of_all_components, offset_reverse_helper_pos2, unique_component_name}, }; use egui::{Context, CursorIcon, LayerId, PointerButton, Pos2, Rect, Response, Ui, Vec2}; -use std::{collections::HashMap, rc::Rc}; +use std::{ + collections::{BTreeMap, HashMap}, + ops::Range, + rc::Rc, +}; pub struct InputMode { pub comp: Option>, @@ -196,7 +200,11 @@ pub fn add_comp_to_editor(e: &mut Editor) { ctrl: e.dummy_input.clone(), size: e.dummy_input.clone(), sext: e.dummy_input.clone(), - memory: Memory::new(HashMap::new()), + range: Range { + start: 0, + end: 0x20, + }, + memory: Memory::new(BTreeMap::new()), }) } "mux" => { From 38d7c577b304a0fd593561d470881f9c16418043 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 19 Aug 2023 15:17:01 +0200 Subject: [PATCH 52/58] Fixed linter error since I used github gui --- src/components/mem.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/mem.rs b/src/components/mem.rs index 27770fe5..c111a146 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -395,7 +395,6 @@ impl Deref for Memory { } } - #[cfg(test)] mod test { use super::*; From 6ce2e6f5f91a84f71963c4bcef96732d19fcf99a Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 26 Aug 2023 14:57:46 +0200 Subject: [PATCH 53/58] Simulator::new now returns result --- src/gui_egui/gui.rs | 2 +- src/gui_egui/keymap.rs | 20 +++++++++++++++++--- src/gui_vizia/gui.rs | 2 +- src/simulator.rs | 12 +++++++++--- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index 0d2bd325..9f2f12cd 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -36,7 +36,7 @@ pub struct EguiExtra { pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { let contexts = create_contexts(&cs.store); - let simulator = Simulator::new(cs); + let simulator = Simulator::new(cs).unwrap(); let options = eframe::NativeOptions::default(); let path = path.to_owned(); simulator.save_dot(&path); diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index a0c819a4..02234ec2 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -261,8 +261,16 @@ pub fn file_open_fn(gui: &mut Gui) { } } false => { - let _ = gui.simulator.take(); - gui.simulator = Some(Simulator::new(cs)); + let simulator = Simulator::new(cs); + match simulator { + Err(e) => { + println!("couldn't open file with simulator: {}", e); + } + Ok(s) => { + let _ = gui.simulator.take(); + gui.simulator = Some(s); + } + } } } } @@ -299,7 +307,13 @@ pub fn file_editor_toggle_fn(gui: &mut Gui) { let components = e.components.clone(); gui.contexts = create_contexts(&components); let simulator = Simulator::new(ComponentStore { store: components }); - gui.simulator = Some(simulator); + match simulator { + Err(e) => { + gui.editor_use = true; + println!("error: {}", e); + } + Ok(s) => gui.simulator = Some(s), + } } } false => { diff --git a/src/gui_vizia/gui.rs b/src/gui_vizia/gui.rs index 32d70c82..c3d5ae45 100644 --- a/src/gui_vizia/gui.rs +++ b/src/gui_vizia/gui.rs @@ -123,7 +123,7 @@ impl GuiData { } pub fn gui(cs: ComponentStore, path: &PathBuf) { - let simulator = Simulator::new(cs); + let simulator = Simulator::new(cs).unwrap(); let path = path.to_owned(); simulator.save_dot(&path); diff --git a/src/simulator.rs b/src/simulator.rs index aafa8a16..09fe1ab5 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -22,7 +22,7 @@ pub struct IdComponent(pub HashMap>); // A solution is to evaluate register updates separately from other components // ... but not currently implemented ... impl Simulator { - pub fn new(component_store: ComponentStore) -> Self { + pub fn new(component_store: ComponentStore) -> Result { let mut lens_values = vec![]; let mut id_start_index = HashMap::new(); @@ -91,7 +91,13 @@ impl Simulator { let (_, ports) = c.get_id_ports(); for in_port in &ports.inputs { let from_id = &in_port.input.id; - let from_node = id_node.get(from_id).unwrap(); + let from_node = id_node.get(from_id); + if from_node.is_none() { + println!("id: {} port {} is not connected", to_id, from_id); + return Err("A port left unconnected"); + } + let from_node = from_node.unwrap(); + graph.add_edge(*from_node, *to_node, ()); trace!( "add_edge {}:{:?} -> {}:{:?}", @@ -142,7 +148,7 @@ impl Simulator { trace!("sim_state {:?}", simulator.sim_state); simulator.clock(); - simulator + Ok(simulator) } /// get input by index From f64ca54acef7bc2592a25fbab67f8afc7f97ca1a Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 26 Aug 2023 15:22:05 +0200 Subject: [PATCH 54/58] Fixed simulator for vizia frontend --- src/gui_vizia/gui.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/gui_vizia/gui.rs b/src/gui_vizia/gui.rs index c3d5ae45..3a663db7 100644 --- a/src/gui_vizia/gui.rs +++ b/src/gui_vizia/gui.rs @@ -116,9 +116,13 @@ impl GuiData { trace!("open path {:?}", self.path); let cs = ComponentStore::load_file(&self.path); let simulator = Simulator::new(cs); - self.simulator = simulator; - - trace!("opened"); + match simulator { + Ok(s) => { + self.simulator = s; + trace!("opened"); + } + Err(e) => trace!("File failed to open due to errors with simulator {}", e), + } } } From 7bb3f58fdc312c9ac151be1492ddc16df9b91bad Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 26 Aug 2023 15:45:59 +0200 Subject: [PATCH 55/58] Fixed all tests broken previously --- examples/mux_edit.rs | 4 ++-- examples/probe_constant.rs | 4 ++-- examples/probe_stim.rs | 4 ++-- examples/probe_stim_assert.rs | 4 ++-- src/components/add.rs | 2 +- src/components/mem.rs | 4 ++-- src/components/probe_assert.rs | 4 ++-- src/components/probe_stim.rs | 2 +- src/components/sext.rs | 2 +- src/main.rs | 2 +- src/simulator.rs | 10 +++++----- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/examples/mux_edit.rs b/examples/mux_edit.rs index 61055fa1..124906aa 100644 --- a/examples/mux_edit.rs +++ b/examples/mux_edit.rs @@ -63,8 +63,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/probe_constant.rs b/examples/probe_constant.rs index 94a1885e..b9e20a71 100644 --- a/examples/probe_constant.rs +++ b/examples/probe_constant.rs @@ -15,8 +15,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/probe_stim.rs b/examples/probe_stim.rs index 843e04ce..2cd591a4 100644 --- a/examples/probe_stim.rs +++ b/examples/probe_stim.rs @@ -11,8 +11,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/examples/probe_stim_assert.rs b/examples/probe_stim_assert.rs index 194bc8c7..a2893cbb 100644 --- a/examples/probe_stim_assert.rs +++ b/examples/probe_stim_assert.rs @@ -23,8 +23,8 @@ fn main() { cs.save_file(&path); #[cfg(feature = "gui-egui")] - syncrim::gui_egui::gui(&cs, &path).ok(); + syncrim::gui_egui::gui(cs, &path).ok(); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&cs, &path); + syncrim::gui_vizia::gui(cs, &path); } diff --git a/src/components/add.rs b/src/components/add.rs index ff9624d7..d0fb5658 100644 --- a/src/components/add.rs +++ b/src/components/add.rs @@ -131,7 +131,7 @@ mod test { }), ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); diff --git a/src/components/mem.rs b/src/components/mem.rs index c111a146..c0fad12c 100644 --- a/src/components/mem.rs +++ b/src/components/mem.rs @@ -437,7 +437,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); @@ -620,7 +620,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); diff --git a/src/components/probe_assert.rs b/src/components/probe_assert.rs index 68342efb..00f94cac 100644 --- a/src/components/probe_assert.rs +++ b/src/components/probe_assert.rs @@ -102,7 +102,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); // output let out = &Input::new("stim", "out"); @@ -176,7 +176,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); // output let out = &Input::new("stim", "out"); diff --git a/src/components/probe_stim.rs b/src/components/probe_stim.rs index 682f469f..5f7bf807 100644 --- a/src/components/probe_stim.rs +++ b/src/components/probe_stim.rs @@ -73,7 +73,7 @@ mod test { store: vec![ProbeStim::rc_new("stim", (0.0, 0.0), vec![0, 1, 2, 3])], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); // output let out = &Input::new("stim", "out"); diff --git a/src/components/sext.rs b/src/components/sext.rs index 157af9a2..35f59bf2 100644 --- a/src/components/sext.rs +++ b/src/components/sext.rs @@ -127,7 +127,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); diff --git a/src/main.rs b/src/main.rs index 59da71f5..2729a80e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,5 +25,5 @@ fn main() { syncrim::gui_vizia::gui(cs, &_path); #[cfg(not(any(feature = "gui-vizia", feature = "gui-egui")))] - syncrim::common::Simulator::new(cs); + syncrim::common::Simulator::new(cs).unwrap(); } diff --git a/src/simulator.rs b/src/simulator.rs index 09fe1ab5..eab1ed2a 100644 --- a/src/simulator.rs +++ b/src/simulator.rs @@ -315,7 +315,7 @@ mod test { store: vec![Rc::new(ProbeOut::new("po1"))], }; - let simulator = Simulator::new(cs); + let simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); } @@ -327,7 +327,7 @@ mod test { store: vec![Rc::new(ProbeOut::new("po1")), Rc::new(ProbeOut::new("po1"))], }; - let simulator = Simulator::new(cs); + let simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); } @@ -338,7 +338,7 @@ mod test { store: vec![Rc::new(ProbeOut::new("po1"))], }; - let simulator = Simulator::new(cs); + let simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); let _ = simulator.get_input_value(&Input::new("po1", "out")); @@ -351,7 +351,7 @@ mod test { store: vec![Rc::new(ProbeOut::new("po1"))], }; - let simulator = Simulator::new(cs); + let simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); let _ = simulator.get_input_value(&Input::new("po1", "missing")); @@ -363,7 +363,7 @@ mod test { store: vec![Rc::new(Constant::new("c", (0.0, 0.0), 0))], }; - let simulator = Simulator::new(cs); + let simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); let _ = simulator.get_input_fmt(&Input::new("c", "out")); From 3f9ca1e01f958d4c89b42c04a9019fe9184178b6 Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Sat, 26 Aug 2023 16:06:35 +0200 Subject: [PATCH 56/58] Also fix mips and riscv tests --- mips/src/components/reg_file.rs | 2 +- riscv/src/components/alu.rs | 2 +- riscv/src/components/branch_logic.rs | 16 ++++++++-------- riscv/src/components/decoder.rs | 8 ++++---- riscv/src/components/instr_mem.rs | 2 +- riscv/src/components/lsb_zero.rs | 2 +- riscv/src/components/reg_file.rs | 2 +- riscv/src/components/sign_zero_ext.rs | 2 +- riscv/src/main.rs | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/mips/src/components/reg_file.rs b/mips/src/components/reg_file.rs index 53847bb4..56f849a4 100644 --- a/mips/src/components/reg_file.rs +++ b/mips/src/components/reg_file.rs @@ -305,7 +305,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); diff --git a/riscv/src/components/alu.rs b/riscv/src/components/alu.rs index 12cf2dc8..b36d9546 100644 --- a/riscv/src/components/alu.rs +++ b/riscv/src/components/alu.rs @@ -175,7 +175,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); // outputs diff --git a/riscv/src/components/branch_logic.rs b/riscv/src/components/branch_logic.rs index ebf3fef7..daafea63 100644 --- a/riscv/src/components/branch_logic.rs +++ b/riscv/src/components/branch_logic.rs @@ -186,7 +186,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); // outputs @@ -241,7 +241,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); // outputs @@ -296,7 +296,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); // outputs @@ -358,7 +358,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); // outputs @@ -420,7 +420,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); // outputs @@ -482,7 +482,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); // outputs @@ -551,7 +551,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); // outputs @@ -590,7 +590,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); // outputs diff --git a/riscv/src/components/decoder.rs b/riscv/src/components/decoder.rs index 3520d8c0..68822467 100644 --- a/riscv/src/components/decoder.rs +++ b/riscv/src/components/decoder.rs @@ -493,7 +493,7 @@ mod test { }), ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); // outputs let wb_mux = &Input::new("decoder", "wb_mux"); @@ -1089,7 +1089,7 @@ mod test { }), ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); // outputs let wb_mux = &Input::new("decoder", "wb_mux"); @@ -1608,7 +1608,7 @@ mod test { }), ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); // outputs let wb_mux = &Input::new("decoder", "wb_mux"); @@ -2151,7 +2151,7 @@ mod test { }), ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); // outputs let wb_mux = &Input::new("decoder", "wb_mux"); diff --git a/riscv/src/components/instr_mem.rs b/riscv/src/components/instr_mem.rs index e4b2e13b..3e1473f4 100644 --- a/riscv/src/components/instr_mem.rs +++ b/riscv/src/components/instr_mem.rs @@ -87,7 +87,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); // outputs diff --git a/riscv/src/components/lsb_zero.rs b/riscv/src/components/lsb_zero.rs index a0e2e469..3b9746a1 100644 --- a/riscv/src/components/lsb_zero.rs +++ b/riscv/src/components/lsb_zero.rs @@ -70,7 +70,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); // outputs diff --git a/riscv/src/components/reg_file.rs b/riscv/src/components/reg_file.rs index 566773e2..5ba75dce 100644 --- a/riscv/src/components/reg_file.rs +++ b/riscv/src/components/reg_file.rs @@ -253,7 +253,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); diff --git a/riscv/src/components/sign_zero_ext.rs b/riscv/src/components/sign_zero_ext.rs index 3df1b108..ae9470ee 100644 --- a/riscv/src/components/sign_zero_ext.rs +++ b/riscv/src/components/sign_zero_ext.rs @@ -99,7 +99,7 @@ mod test { ], }; - let mut simulator = Simulator::new(cs); + let mut simulator = Simulator::new(cs).unwrap(); assert_eq!(simulator.cycle, 1); let szext = &Input::new("szext", "out"); let val = 0b100000000000; diff --git a/riscv/src/main.rs b/riscv/src/main.rs index 78cd2b8a..030d00ba 100644 --- a/riscv/src/main.rs +++ b/riscv/src/main.rs @@ -8,5 +8,5 @@ fn main() { let _cs = ComponentStore::load_file(&path); #[cfg(feature = "gui-vizia")] - syncrim::gui_vizia::gui(&_cs, &path); + syncrim::gui_vizia::gui(_cs, &path); } From 2d9183647c7933b2123fc7254be2e9c411eb08ec Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Wed, 30 Aug 2023 10:32:54 +0200 Subject: [PATCH 57/58] Fix bug with open crashing egui --- src/gui_egui/gui.rs | 1 - src/gui_egui/keymap.rs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui_egui/gui.rs b/src/gui_egui/gui.rs index 9f2f12cd..34feb683 100644 --- a/src/gui_egui/gui.rs +++ b/src/gui_egui/gui.rs @@ -40,7 +40,6 @@ pub fn gui(cs: ComponentStore, path: &PathBuf) -> Result<(), eframe::Error> { let options = eframe::NativeOptions::default(); let path = path.to_owned(); simulator.save_dot(&path); - println!("contexts: {:?}", contexts); let gui = Gui { path, diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 02234ec2..3359295d 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -251,6 +251,7 @@ pub fn file_open_fn(gui: &mut Gui) { gui.path = path_buf; } let cs = ComponentStore::load_file(&gui.path); + gui.contexts = create_contexts(&cs.store); match gui.editor_use { true => { if let Some(e) = gui.editor.as_mut() { From ebd1d09ae0727993406399c7dca67b754e84217b Mon Sep 17 00:00:00 2001 From: vaneri-9 Date: Wed, 30 Aug 2023 11:40:21 +0200 Subject: [PATCH 58/58] Also fix crash for when opening in editor mode --- src/gui_egui/keymap.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui_egui/keymap.rs b/src/gui_egui/keymap.rs index 3359295d..c42735b6 100644 --- a/src/gui_egui/keymap.rs +++ b/src/gui_egui/keymap.rs @@ -251,7 +251,7 @@ pub fn file_open_fn(gui: &mut Gui) { gui.path = path_buf; } let cs = ComponentStore::load_file(&gui.path); - gui.contexts = create_contexts(&cs.store); + let contexts = create_contexts(&cs.store); match gui.editor_use { true => { if let Some(e) = gui.editor.as_mut() { @@ -259,10 +259,12 @@ pub fn file_open_fn(gui: &mut Gui) { reset_wire_mode(&mut e.wm); reset_input_mode(&mut e.im); e.components = cs.store; + e.contexts = contexts; } } false => { let simulator = Simulator::new(cs); + gui.contexts = contexts; match simulator { Err(e) => { println!("couldn't open file with simulator: {}", e);