diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 75 | ||||
-rw-r--r-- | src/support/clipboard.rs | 17 | ||||
-rw-r--r-- | src/support/mod.rs | 141 |
3 files changed, 233 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..df1a475 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,75 @@ +use imgui::*; +use rlua::{Lua, MultiValue}; + +mod support; + +#[derive(Default)] +struct State { + lua: Lua, + console: Vec<ImString>, + repl_input: ImString, +} + +impl State { + fn new() -> State { + State { + lua: Lua::new(), + console: Vec::new(), + repl_input: ImString::with_capacity(256), + } + } +} + +fn draw_console(_run: &mut bool, ui: &mut Ui, state: &mut State) { + let win = Window::new(im_str!("Lua Console")).size([400., 500.], Condition::Appearing); + + win.build(&ui, || { + ChildWindow::new("console") + .size([0., 400.]) + .scrollable(true) + .build(&ui, || { + for line in &state.console { + ui.text(line); + } + }); + + ui.separator(); + ui.input_text(im_str!("Lua"), &mut state.repl_input).build(); + ui.same_line(350.); + if ui.button(im_str!("Eval"), [0., 0.]) { + let input = state.repl_input.to_str().clone(); + let mut new_text = String::new(); + + state.lua.context(|ctx| { + match ctx.load(input).eval::<MultiValue>() { + Ok(values) => { + new_text.push_str( + &values + .iter() + .map(|value| format!("{:?}", value)) + .collect::<Vec<_>>() + .join("\t"), + ); + } + Err(e) => { + new_text.push_str(&e.to_string()); + } + }; + }); + + state.console.push(ImString::new(format!("> {}", input))); + state.console.push(ImString::new(new_text)); + state.repl_input.clear(); + } + }); +} + +fn main() { + let system = support::init(file!()); + let mut state = State::new(); + + system.main_loop(move |run, ui| { + ui.show_demo_window(run); + draw_console(run, ui, &mut state); + }); +} diff --git a/src/support/clipboard.rs b/src/support/clipboard.rs new file mode 100644 index 0000000..d970b29 --- /dev/null +++ b/src/support/clipboard.rs @@ -0,0 +1,17 @@ +use clipboard::{ClipboardContext, ClipboardProvider}; +use imgui::{ClipboardBackend, ImStr, ImString}; + +pub struct ClipboardSupport(ClipboardContext); + +pub fn init() -> Option<ClipboardSupport> { + ClipboardContext::new().ok().map(ClipboardSupport) +} + +impl ClipboardBackend for ClipboardSupport { + fn get(&mut self) -> Option<ImString> { + self.0.get_contents().ok().map(|text| text.into()) + } + fn set(&mut self, text: &ImStr) { + let _ = self.0.set_contents(text.to_str().to_owned()); + } +} diff --git a/src/support/mod.rs b/src/support/mod.rs new file mode 100644 index 0000000..af894ba --- /dev/null +++ b/src/support/mod.rs @@ -0,0 +1,141 @@ +use glium::glutin; +use glium::glutin::event::{Event, WindowEvent}; +use glium::glutin::event_loop::{ControlFlow, EventLoop}; +use glium::glutin::window::WindowBuilder; +use glium::{Display, Surface}; +use imgui::{Context, FontConfig, FontGlyphRanges, FontSource, Ui}; +use imgui_glium_renderer::Renderer; +use imgui_winit_support::{HiDpiMode, WinitPlatform}; +use std::path::Path; +use std::time::Instant; + +mod clipboard; + +pub struct System { + pub event_loop: EventLoop<()>, + pub display: glium::Display, + pub imgui: Context, + pub platform: WinitPlatform, + pub renderer: Renderer, + pub font_size: f32, +} + +pub fn init(title: &str) -> System { + let title = match Path::new(&title).file_name() { + Some(file_name) => file_name.to_str().unwrap(), + None => title, + }; + let event_loop = EventLoop::new(); + let context = glutin::ContextBuilder::new().with_vsync(true); + let builder = WindowBuilder::new() + .with_title(title.to_owned()) + .with_inner_size(glutin::dpi::LogicalSize::new(1024f64, 768f64)); + let display = + Display::new(builder, context, &event_loop).expect("Failed to initialize display"); + + let mut imgui = Context::create(); + imgui.set_ini_filename(None); + + if let Some(backend) = clipboard::init() { + imgui.set_clipboard_backend(Box::new(backend)); + } else { + eprintln!("Failed to initialize clipboard"); + } + + let mut platform = WinitPlatform::init(&mut imgui); + { + let gl_window = display.gl_window(); + let window = gl_window.window(); + platform.attach_window(imgui.io_mut(), window, HiDpiMode::Rounded); + } + + let hidpi_factor = platform.hidpi_factor(); + let font_size = (13.0 * hidpi_factor) as f32; + + // imgui.fonts().add_font(&[ + // FontSource::DefaultFontData { + // config: Some(FontConfig { + // size_pixels: font_size, + // ..FontConfig::default() + // }), + // }, + // FontSource::TtfData { + // data: include_bytes!("../../../resources/mplus-1p-regular.ttf"), + // size_pixels: font_size, + // config: Some(FontConfig { + // rasterizer_multiply: 1.75, + // glyph_ranges: FontGlyphRanges::japanese(), + // ..FontConfig::default() + // }), + // }, + // ]); + + imgui.io_mut().font_global_scale = (1.0 / hidpi_factor) as f32; + + let renderer = Renderer::init(&mut imgui, &display).expect("Failed to initialize renderer"); + + System { + event_loop, + display, + imgui, + platform, + renderer, + font_size, + } +} + +impl System { + pub fn main_loop<F: FnMut(&mut bool, &mut Ui) + 'static>(self, mut run_ui: F) { + let System { + event_loop, + display, + mut imgui, + mut platform, + mut renderer, + .. + } = self; + let mut last_frame = Instant::now(); + + event_loop.run(move |event, _, control_flow| match event { + Event::NewEvents(_) => { + let now = Instant::now(); + imgui.io_mut().update_delta_time(now - last_frame); + last_frame = now; + } + Event::MainEventsCleared => { + let gl_window = display.gl_window(); + platform + .prepare_frame(imgui.io_mut(), gl_window.window()) + .expect("Failed to prepare frame"); + gl_window.window().request_redraw(); + } + Event::RedrawRequested(_) => { + let mut ui = imgui.frame(); + + let mut run = true; + run_ui(&mut run, &mut ui); + if !run { + *control_flow = ControlFlow::Exit; + } + + let gl_window = display.gl_window(); + let mut target = display.draw(); + target.clear_color_srgb(0.7, 0.7, 0.7, 0.7); + platform.prepare_render(&ui, gl_window.window()); + let draw_data = ui.render(); + renderer + .render(&mut target, draw_data) + .expect("Rendering failed"); + target.finish().expect("Failed to swap buffers"); + } + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => *control_flow = ControlFlow::Exit, + event => { + let gl_window = display.gl_window(); + platform.handle_event(imgui.io_mut(), gl_window.window(), &event); + } + }) + } +} |