mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-04 17:38:10 +00:00
handle zoom only within imgui window
This commit is contained in:
1 parent
c2c9dbceed
commit
a06afdde38
6 files changed
+234
-39
No files matched your search
+41
-27
@@ -13,11 +13,18 @@ use point_cloud::point_cloud_visualiser::{ColorizationStrategy, PointCloudVisual
|
||||
use point_cloud::viewer_image::ViewerImage;
|
||||
use sensor_control::CaptureProvider;
|
||||
use webcam::WebcamWriter;
|
||||
use gui::enhanced_window::EnhancedWindow;
|
||||
|
||||
pub const ENABLE_WEBCAM: bool = false;
|
||||
|
||||
pub fn run(capture_provider: Arc<CaptureProvider>, calibration_data: k4a_sys::k4a_calibration_t) {
|
||||
|
||||
let mut webcam_writer = WebcamWriter::open_file("/dev/video0", 1280, 720, 3)
|
||||
.expect("should be able to create webcamwriter");
|
||||
let mut webcam_writer = None;
|
||||
|
||||
if ENABLE_WEBCAM {
|
||||
webcam_writer = Some(WebcamWriter::open_file("/dev/video0", 1280, 720, 3)
|
||||
.expect("should be able to create webcamwriter"));
|
||||
}
|
||||
|
||||
let sdl_arcball = Arc::new(Mutex::new(SdlArcball::new(1280, 720)));
|
||||
|
||||
@@ -47,6 +54,7 @@ pub fn run(capture_provider: Arc<CaptureProvider>, calibration_data: k4a_sys::k4
|
||||
|
||||
let mut imgui = imgui::Context::create();
|
||||
imgui.set_ini_filename(None);
|
||||
imgui.io_mut().config_windows_move_from_title_bar_only = true;
|
||||
|
||||
/*let gl_texture_n64 = load_texture("n64logo.png");
|
||||
let imgui_texture_n64 = TextureId::from(gl_texture_n64 as usize);
|
||||
@@ -96,10 +104,10 @@ pub fn run(capture_provider: Arc<CaptureProvider>, calibration_data: k4a_sys::k4
|
||||
use sdl2::event::Event;
|
||||
use sdl2::keyboard::Keycode;
|
||||
|
||||
let _rebinder = Rebinder::snapshot();
|
||||
|
||||
for event in event_pump.poll_iter() {
|
||||
imgui_sdl2.handle_event(&mut imgui, &event);
|
||||
|
||||
// TODO: This is how Imgui appears to tell SDL to ignore certain events.
|
||||
if imgui_sdl2.ignore_event(&event) { continue; }
|
||||
|
||||
match event {
|
||||
@@ -116,7 +124,6 @@ pub fn run(capture_provider: Arc<CaptureProvider>, calibration_data: k4a_sys::k4
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
imgui_sdl2.prepare_frame(imgui.io_mut(), &window, &event_pump.mouse_state());
|
||||
|
||||
let now = Instant::now();
|
||||
@@ -126,28 +133,14 @@ pub fn run(capture_provider: Arc<CaptureProvider>, calibration_data: k4a_sys::k4
|
||||
imgui.io_mut().delta_time = delta_s;
|
||||
|
||||
let ui = imgui.frame();
|
||||
//ui.show_demo_window(&mut true);
|
||||
|
||||
/*Window::new(im_str!("Loading Images"))
|
||||
.size([1500.0, 1500.0], Condition::FirstUseEver)
|
||||
.position([0.0, 0.0], Condition::FirstUseEver)
|
||||
.build(&ui, || {
|
||||
let mouse_pos = ui.io().mouse_pos;
|
||||
ui.text(format!(
|
||||
"Mouse Position: ({:.1},{:.1})",
|
||||
mouse_pos[0], mouse_pos[1]
|
||||
));
|
||||
ui.separator();
|
||||
Image::new(imgui_texture_n64, [100.0, 100.0]).build(&ui);
|
||||
ui.separator();
|
||||
Image::new(imgui_texture_snes, [200.0, 200.0]).build(&ui);
|
||||
ui.separator();
|
||||
});*/
|
||||
//ui.show_demo_window(&mut true);
|
||||
|
||||
const window_width : f32 = 1290.0;
|
||||
const window_height : f32 = 760.0;
|
||||
|
||||
Window::new(im_str!("Point Cloud Converter Depth Image"))
|
||||
.scrollable(true)
|
||||
.size([window_width, window_height], Condition::FirstUseEver)
|
||||
.position([0.0, 0.0], Condition::FirstUseEver)
|
||||
.build(&ui, || {
|
||||
@@ -169,6 +162,7 @@ pub fn run(capture_provider: Arc<CaptureProvider>, calibration_data: k4a_sys::k4
|
||||
Window::new(im_str!("Visualizer XYZ Texture"))
|
||||
.size([window_width, window_height], Condition::FirstUseEver)
|
||||
.position([window_width + 50.0, 0.0], Condition::FirstUseEver)
|
||||
.movable(false)
|
||||
.build(&ui, || {
|
||||
match imgui_visualizer_xyz_texture.as_ref() {
|
||||
None => {},
|
||||
@@ -177,16 +171,34 @@ pub fn run(capture_provider: Arc<CaptureProvider>, calibration_data: k4a_sys::k4
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
// NB: This is larger. The texture is 1280x1152.
|
||||
Window::new(&im_str!("Final Output: {:?}", colorization_strategy))
|
||||
EnhancedWindow::new(&im_str!("Final Output: {:?}", colorization_strategy))
|
||||
.size([window_width, window_height + 435.0], Condition::FirstUseEver)
|
||||
.position([window_width + 50.0, window_height + 50.0], Condition::FirstUseEver)
|
||||
.build(&ui, || {
|
||||
//Image::new(imgui_kinect_final_output, [1280.0, 1152.0]).build(&ui);
|
||||
//Image::new(imgui_kinect_final_output, [640.0, 480.0]).build(&ui);
|
||||
.mouse_inputs(true)
|
||||
.build(&ui, |window| {
|
||||
|
||||
if let Some(mouse_state) = window.get_window_bounded_mouse_state() {
|
||||
println!("\nwindow_helper.cursor_pos: {:?}", mouse_state);
|
||||
match sdl_arcball.lock() {
|
||||
Ok(mut arcball) => arcball.process_mouse_state(mouse_state),
|
||||
Err(_) => {},
|
||||
}
|
||||
}
|
||||
|
||||
/*println!("is_window_hovered: {:?}", ui.is_window_hovered());
|
||||
println!("cursor_pos: {:?}", ui.cursor_pos());
|
||||
println!("cursor_screen_pos: {:?}", ui.cursor_screen_pos());
|
||||
println!("window_pos: {:?}", ui.window_pos());
|
||||
println!("IO mouse pos: {:?}\n", ui.io().mouse_pos);*/
|
||||
|
||||
Image::new(imgui_kinect_final_output, [1280.0, 720.0]).build(&ui);
|
||||
});
|
||||
|
||||
//println!("imgui.cursor_pos: {:?}", ui.cursor_pos());
|
||||
//println!("imgui.cursor_screen_pos: {:?}", ui.cursor_screen_pos());
|
||||
|
||||
unsafe {
|
||||
gl::ClearColor(0.2, 0.2, 0.2, 1.0);
|
||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||
@@ -219,8 +231,10 @@ pub fn run(capture_provider: Arc<CaptureProvider>, calibration_data: k4a_sys::k4
|
||||
Err(_) => {},
|
||||
}
|
||||
|
||||
webcam_writer.write_current_frame_to_file(texture.texture_id())
|
||||
.expect("should write");
|
||||
if let Some(mut webcam) = webcam_writer.as_mut() {
|
||||
webcam.write_current_frame_to_file(texture.texture_id())
|
||||
.expect("should write");
|
||||
}
|
||||
|
||||
//let change_delta = last_frame - last_change;
|
||||
//if change_delta > Duration::from_millis(5_000) {
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/// A wrapper around `Imgui::Window` that adds window-scoped devices.
|
||||
pub struct EnhancedWindow <'a> {
|
||||
pub window: imgui::Window<'a>,
|
||||
}
|
||||
|
||||
impl <'a> EnhancedWindow <'a> {
|
||||
pub fn new(name: &'a imgui::ImStr) -> Self {
|
||||
let mut window = imgui::Window::new(name)
|
||||
.scrollable(true);
|
||||
|
||||
Self {
|
||||
window,
|
||||
}
|
||||
}
|
||||
|
||||
/// Enables/disables catching mouse input.
|
||||
///
|
||||
/// Enabled by default.
|
||||
/// Note: Hovering test will pass through when disabled
|
||||
#[inline]
|
||||
pub fn mouse_inputs(mut self, value: bool) -> Self {
|
||||
// NB: Builder API consumes window, so we have to move it.
|
||||
self.window = self.window.mouse_inputs(value);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the window position, which is applied based on the given condition value
|
||||
#[inline]
|
||||
pub fn position(mut self, position: [f32; 2], condition: imgui::Condition) -> Self {
|
||||
// NB: Builder API consumes window, so we have to move it.
|
||||
self.window = self.window.position(position, condition);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the window size, which is applied based on the given condition value
|
||||
#[inline]
|
||||
pub fn size(mut self, size: [f32; 2], condition: imgui::Condition) -> Self {
|
||||
// NB: Builder API consumes window, so we have to move it.
|
||||
self.window = self.window.size(size, condition);
|
||||
self
|
||||
}
|
||||
|
||||
/// Creates a window and runs a closure to construct the contents.
|
||||
///
|
||||
/// Note: the closure is not called if no window content is visible (e.g. window is collapsed
|
||||
/// or fully clipped).
|
||||
pub fn build<F>(self, ui: &imgui::Ui, f: F)
|
||||
where F: FnOnce(WindowScopedUi)
|
||||
{
|
||||
if let Some(window) = self.begin(ui) {
|
||||
let win_helper = WindowScopedUi::new(&ui);
|
||||
f(win_helper);
|
||||
window.end(ui);
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a window and starts appending to it.
|
||||
///
|
||||
/// Returns `Some(WindowToken)` if the window is visible. After content has been
|
||||
/// rendered, the token must be ended by calling `.end()`.
|
||||
///
|
||||
/// Returns `None` if the window is not visible and no content should be rendered.
|
||||
#[must_use]
|
||||
pub fn begin(self, ui: &imgui::Ui) -> Option<imgui::WindowToken> {
|
||||
self.window.begin(ui)
|
||||
}
|
||||
}
|
||||
|
||||
/// State for a mouse mapped to the dimensions of an `Imgui::Window`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CompleteMouseState {
|
||||
// Cursor position
|
||||
pub cursor_x: f32,
|
||||
pub cursor_y: f32,
|
||||
// Scroll wheel velocity (typically just '0', '1', or '-1').
|
||||
pub scroll_wheel: f32,
|
||||
pub scroll_wheel_h: f32,
|
||||
// Buttons
|
||||
pub left_button_down: bool,
|
||||
pub right_button_down: bool,
|
||||
pub middle_button_down: bool,
|
||||
pub extra_button_1_down: bool,
|
||||
pub extra_button_2_down: bool,
|
||||
}
|
||||
|
||||
/// Exposes some reusable calculations on top of `imgui::Ui` in the context of window usage.
|
||||
pub struct WindowScopedUi<'a> {
|
||||
ui: &'a imgui::Ui<'a>,
|
||||
}
|
||||
|
||||
impl <'a> WindowScopedUi<'a> {
|
||||
pub fn new(ui: &'a imgui::Ui) -> Self {
|
||||
Self {
|
||||
ui
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the current window is hovered
|
||||
#[inline]
|
||||
pub fn is_window_hovered(&self) -> bool {
|
||||
self.ui.is_window_hovered()
|
||||
}
|
||||
|
||||
/// Return the cursor position within the window.
|
||||
/// None is returned if the window isn't hovered, or the mouse is logically not within the drawn
|
||||
/// texture area.
|
||||
pub fn get_cursor(&self) -> Option<[f32; 2]> {
|
||||
if !self.is_window_hovered() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Global mouse coordinate
|
||||
let mouse_pos = self.ui.io().mouse_pos;
|
||||
// Anchor point of the window's top left corner
|
||||
let window_pos = self.ui.window_pos();
|
||||
// Start of textured data (padding offset created by title and window padding).
|
||||
let cursor_pos = self.ui.cursor_pos();
|
||||
|
||||
let x = mouse_pos[0] - window_pos[0] - cursor_pos[0];
|
||||
let y = mouse_pos[1] - window_pos[1] - cursor_pos[1];
|
||||
|
||||
if x.is_sign_negative() || y.is_sign_negative() {
|
||||
return None; // Outside of bounds (eg. cursor within title area)
|
||||
}
|
||||
|
||||
Some([x, y])
|
||||
}
|
||||
|
||||
/// Return the mouse scroll state. If the mouse is not hovering our window, None is returned.
|
||||
pub fn get_mouse_wheel(&self) -> Option<f32> {
|
||||
if self.get_cursor().is_none() {
|
||||
return None;
|
||||
}
|
||||
Some(self.ui.io().mouse_wheel)
|
||||
}
|
||||
|
||||
/// Mouse buttons: 0=left, 1=right, 2=middle + extras
|
||||
pub fn get_mouse_down(&self) -> Option<[bool; 5]> {
|
||||
if self.get_cursor().is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(self.ui.io().mouse_down)
|
||||
}
|
||||
|
||||
/// Get the current mouse state
|
||||
/// If the cursor isn't within the window, None is returned.
|
||||
pub fn get_window_bounded_mouse_state(&self) -> Option<CompleteMouseState> {
|
||||
self.get_cursor()
|
||||
.map(|cursor| {
|
||||
let io = self.ui.io();
|
||||
let mouse = io.mouse_down;
|
||||
|
||||
CompleteMouseState {
|
||||
cursor_x: cursor[0],
|
||||
cursor_y: cursor[1],
|
||||
scroll_wheel: io.mouse_wheel,
|
||||
scroll_wheel_h: io.mouse_wheel_h,
|
||||
left_button_down: mouse[0],
|
||||
right_button_down: mouse[1],
|
||||
middle_button_down: mouse[2],
|
||||
extra_button_1_down: mouse[3],
|
||||
extra_button_2_down: mouse[4],
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
//! This module will contain all the Imgui, SDL, mouse controls, etc. code
|
||||
pub mod enhanced_window;
|
||||
@@ -32,6 +32,7 @@ use sensor_control::{capture_thread, CaptureProvider};
|
||||
pub mod conversion;
|
||||
pub mod core_types;
|
||||
pub mod graphics_imgui;
|
||||
pub mod gui;
|
||||
pub mod imgui_support;
|
||||
pub mod k4a_sys_wrapper;
|
||||
pub mod mouse;
|
||||
|
||||
+22
-4
@@ -3,6 +3,7 @@ use cgmath::{Matrix4, Vector2};
|
||||
use cgmath::Vector3;
|
||||
use sdl2::event::Event;
|
||||
use sdl2::mouse::MouseButton;
|
||||
use gui::enhanced_window::CompleteMouseState;
|
||||
|
||||
const MIN_ZOOM : f32 = 1.0;
|
||||
const MAX_ZOOM : f32 = 120.0;
|
||||
@@ -67,15 +68,22 @@ impl SdlArcball {
|
||||
}
|
||||
|
||||
/// Process an SDL event.
|
||||
/// This is a bad idea in a multi-window Imgui setup since the SDL coordinates and events take up
|
||||
/// the entire process window and may be sequestered on a per-window level. That said, this is
|
||||
/// reasonable for single-window apps.
|
||||
pub fn process_event(&mut self, event: &Event) {
|
||||
match event {
|
||||
Event::MouseWheel { timestamp: _, window_id: _, which: _, x: _, y, direction: _ } => {
|
||||
self.mouse_wheel(*y);
|
||||
//println!("Mouse wheel event.");
|
||||
let y = *y as f32;
|
||||
self.mouse_wheel(y);
|
||||
},
|
||||
Event::MouseButtonDown { timestamp: _, window_id: _, which: _, mouse_btn, clicks: _, x: _, y: _ } => {
|
||||
//println!("Mouse button down event.");
|
||||
self.mouse_button_press(mouse_btn, true);
|
||||
},
|
||||
Event::MouseButtonUp { timestamp: _, window_id: _, which: _, mouse_btn, clicks: _, x: _, y: _ } => {
|
||||
//println!("Mouse button up event.");
|
||||
self.mouse_button_press(mouse_btn, false);
|
||||
},
|
||||
Event::MouseMotion { timestamp: _, window_id: _, which: _, mousestate: _, x, y, xrel: _, yrel: _ } => {
|
||||
@@ -89,6 +97,18 @@ impl SdlArcball {
|
||||
}
|
||||
}
|
||||
|
||||
/// Process Imgui window-scoped mouse state.
|
||||
/// Since we don't process individual events, we set all of the internal state at once.
|
||||
pub fn process_mouse_state(&mut self, mouse_state: CompleteMouseState) {
|
||||
// TODO: Cleanup
|
||||
self.right_mouse_active = mouse_state.right_button_down;
|
||||
self.left_mouse_active = mouse_state.left_button_down;
|
||||
self.mouse_motion(mouse_state.cursor_x, mouse_state.cursor_y);
|
||||
self.mouse_wheel(mouse_state.scroll_wheel);
|
||||
self.last_x = mouse_state.cursor_x;
|
||||
self.last_y = mouse_state.cursor_y;
|
||||
}
|
||||
|
||||
/// Get the view matrix
|
||||
pub fn get_view_matrix(&self) -> Matrix4<f32> {
|
||||
self.arcball.get_mat4()
|
||||
@@ -159,8 +179,7 @@ impl SdlArcball {
|
||||
self.animation_counter += 0.05;
|
||||
}
|
||||
|
||||
fn mouse_wheel(&mut self, y: i32) {
|
||||
let y = y as f32;
|
||||
fn mouse_wheel(&mut self, y: f32) {
|
||||
self.arcball.zoom(y, 0.16);
|
||||
|
||||
// NB: 'y' is a scroll amount, typically 1 or -1.
|
||||
@@ -169,7 +188,6 @@ impl SdlArcball {
|
||||
.min(MAX_ZOOM);
|
||||
|
||||
self.last_zoom = zoom;
|
||||
println!("Zoom: {}", zoom);
|
||||
}
|
||||
|
||||
fn mouse_button_press(&mut self, mouse_button: &MouseButton, down: bool) {
|
||||
|
||||
@@ -329,11 +329,6 @@ impl PointCloudRenderer {
|
||||
point_cloud_texture_index = gl::GetUniformLocation(program_id, POINT_CLOUD_PTR);
|
||||
}
|
||||
|
||||
println!("Uniform view location - view: {:?}", view_index);
|
||||
println!("Uniform projection location - view: {:?}", projection_index);
|
||||
println!("Uniform enable shading location - view: {:?}", enable_shading_index);
|
||||
println!("Uniform point cloud texture location - view: {:?}", point_cloud_texture_index);
|
||||
|
||||
let initial_view = [
|
||||
[-1.0, 0.0, 8.74228e-08, 0.0],
|
||||
[0.0, 1.0, 0.0, 0.0],
|
||||
@@ -373,8 +368,6 @@ impl PointCloudRenderer {
|
||||
/// Update the view matrices
|
||||
///
|
||||
pub fn update_view_projection(&mut self, view: [[f32; 4]; 4], projection: [[f32; 4]; 4]) {
|
||||
println!("\nView Matrix: {:?}", view);
|
||||
println!("Updated: {:?}", projection);
|
||||
self.view_matrix = view;
|
||||
//self.projection_matrix = projection;
|
||||
|
||||
@@ -387,7 +380,6 @@ impl PointCloudRenderer {
|
||||
|
||||
// Initial: [[1.41272, 0.0, 0.0, 0.0], [0.0, 1.56969, 0.0, 0.0], [0.0, 0.0, -1.002, -1.0], [0.0, 0.0, -0.2002, 0.0]]
|
||||
// Updated: [[0.88294804, 0.0, 0.0, 0.0], [0.0, 1.5696855, 0.0, 0.0], [0.0, 0.0, -1.002002, -0.2002002], [0.0, 0.0, -1.0, 0.0]]
|
||||
println!("Initial: {:?}", initial_projection);
|
||||
|
||||
self.projection_matrix = initial_projection;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user