mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-19 01:18:27 +00:00
WIP
This commit is contained in:
parent
cf214ca397
commit
daf039c098
@ -15,4 +15,4 @@ glium = { version = "0.31", default-features = true }
|
||||
image = "0.23"
|
||||
imgui = { path = "../imgui", features = ["tables-api", "docking"] }
|
||||
imgui-glium-renderer = { path = "../imgui-glium-renderer" }
|
||||
imgui-winit-support = { path = "../imgui-winit-support" }
|
||||
imgui-winit-support = { path = "../imgui-winit-support", features=["viewports"] }
|
||||
|
||||
@ -3,7 +3,8 @@ use imgui::*;
|
||||
mod support;
|
||||
|
||||
fn main() {
|
||||
let system = support::init(file!());
|
||||
let mut system = support::init(file!());
|
||||
system.imgui.io_mut().config_flags.insert(ConfigFlags::VIEWPORTS_ENABLE);
|
||||
|
||||
let mut value = 0;
|
||||
let choices = ["test test this is 1", "test test this is 2"];
|
||||
|
||||
@ -43,6 +43,7 @@ pub fn init(title: &str) -> System {
|
||||
}
|
||||
|
||||
let mut platform = WinitPlatform::init(&mut imgui);
|
||||
WinitPlatform::init_viewports(&mut imgui, &event_loop);
|
||||
{
|
||||
let gl_window = display.gl_window();
|
||||
let window = gl_window.window();
|
||||
@ -123,7 +124,7 @@ impl System {
|
||||
} = self;
|
||||
let mut last_frame = Instant::now();
|
||||
|
||||
event_loop.run(move |event, _, control_flow| match event {
|
||||
event_loop.run(move |event, window_target, control_flow| match event {
|
||||
Event::NewEvents(_) => {
|
||||
let now = Instant::now();
|
||||
imgui.io_mut().update_delta_time(now - last_frame);
|
||||
@ -154,6 +155,9 @@ impl System {
|
||||
.render(&mut target, draw_data)
|
||||
.expect("Rendering failed");
|
||||
target.finish().expect("Failed to swap buffers");
|
||||
|
||||
imgui.update_platform_windows();
|
||||
platform.update_viewports(&mut imgui, window_target);
|
||||
}
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
@ -162,6 +166,7 @@ impl System {
|
||||
event => {
|
||||
let gl_window = display.gl_window();
|
||||
platform.handle_event(imgui.io_mut(), gl_window.window(), &event);
|
||||
platform.handle_viewport_event(&mut imgui, gl_window.window(), &event);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -20,9 +20,11 @@ winit-25 = { version = "0.25", package = "winit", default-features = false, opti
|
||||
winit-26 = { version = "0.26", package = "winit", default-features = false, optional = true }
|
||||
|
||||
[features]
|
||||
default = ["winit-26/default"]
|
||||
default = ["winit-26/default", "viewports"]
|
||||
test = ["winit-23/default", "winit-24/default", "winit-25/default", "winit-26/default"]
|
||||
|
||||
viewports = [ "imgui/docking" ]
|
||||
|
||||
# This is phrased as a negative (unlike most features) so that it needs to be
|
||||
# explicitly disabled (and `default-features = false` won't do it). To avoid
|
||||
# problems from this we don't expose this in the public API in any way, keeping
|
||||
|
||||
@ -189,7 +189,7 @@ use winit_20 as winit;
|
||||
use winit_19 as winit;
|
||||
|
||||
use imgui::{self, BackendFlags, ConfigFlags, Context, Io, Key, Ui};
|
||||
use std::cell::Cell;
|
||||
use std::{cell::Cell, collections::HashMap};
|
||||
use std::cmp::Ordering;
|
||||
use winit::dpi::{LogicalPosition, LogicalSize};
|
||||
|
||||
@ -342,6 +342,9 @@ pub struct WinitPlatform {
|
||||
hidpi_factor: f64,
|
||||
cursor_cache: Option<CursorSettings>,
|
||||
mouse_buttons: [Button; 5],
|
||||
|
||||
#[cfg(feature = "viewports")]
|
||||
windows: HashMap<imgui::Id, winit::window::Window>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
@ -444,6 +447,107 @@ impl HiDpiMode {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "viewports")]
|
||||
struct ViewportBackend {}
|
||||
|
||||
#[cfg(feature = "viewports")]
|
||||
impl imgui::PlatformViewportBackend for ViewportBackend {
|
||||
fn create_window(&mut self, viewport: &mut imgui::Viewport) {
|
||||
viewport.platform_user_data = Box::into_raw(Box::new(ViewportState {
|
||||
create: true,
|
||||
create_flags: viewport.flags,
|
||||
set_show: false,
|
||||
set_pos: None,
|
||||
set_size: None,
|
||||
set_focus: false,
|
||||
set_title: None,
|
||||
pos: [0.0, 0.0],
|
||||
size: [0.0, 0.0],
|
||||
focus: false,
|
||||
minimized: false,
|
||||
})) as *mut _;
|
||||
}
|
||||
|
||||
fn destroy_window(&mut self, viewport: &mut imgui::Viewport) {
|
||||
unsafe {
|
||||
Box::from_raw(viewport.platform_user_data as *mut ViewportState);
|
||||
}
|
||||
viewport.platform_user_data = std::ptr::null_mut();
|
||||
}
|
||||
|
||||
fn show_window(&mut self, viewport: &mut imgui::Viewport) {
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
state.set_show = true;
|
||||
}
|
||||
|
||||
fn set_window_pos(&mut self, viewport: &mut imgui::Viewport, pos: [f32; 2]) {
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
state.set_pos = Some(pos);
|
||||
}
|
||||
|
||||
fn get_window_pos(&mut self, viewport: &mut imgui::Viewport) -> [f32; 2] {
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
state.pos
|
||||
}
|
||||
|
||||
fn set_window_size(&mut self, viewport: &mut imgui::Viewport, size: [f32; 2]) {
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
state.set_size = Some(size);
|
||||
}
|
||||
|
||||
fn get_window_size(&mut self, viewport: &mut imgui::Viewport) -> [f32; 2] {
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
state.size
|
||||
}
|
||||
|
||||
fn set_window_focus(&mut self, viewport: &mut imgui::Viewport) {
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
state.set_focus = true;
|
||||
}
|
||||
|
||||
fn get_window_focus(&mut self, viewport: &mut imgui::Viewport) -> bool {
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
state.focus
|
||||
}
|
||||
|
||||
fn get_window_minimized(&mut self, viewport: &mut imgui::Viewport) -> bool {
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
state.focus
|
||||
}
|
||||
|
||||
fn set_window_title(&mut self, viewport: &mut imgui::Viewport, title: &str) {
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
state.set_title = Some(title.to_string());
|
||||
}
|
||||
|
||||
fn set_window_alpha(&mut self, _viewport: &mut imgui::Viewport, _alpha: f32) {}
|
||||
|
||||
fn update_window(&mut self, _viewport: &mut imgui::Viewport) {}
|
||||
|
||||
fn render_window(&mut self, _viewport: &mut imgui::Viewport) {}
|
||||
|
||||
fn swap_buffers(&mut self, _viewport: &mut imgui::Viewport) {}
|
||||
|
||||
fn create_vk_surface(&mut self, _viewport: &mut imgui::Viewport, _instance: u64, _out_surface: &mut u64) -> i32 { 0 }
|
||||
}
|
||||
|
||||
#[cfg(feature = "viewports")]
|
||||
struct ViewportState {
|
||||
create: bool,
|
||||
create_flags: imgui::ViewportFlags,
|
||||
|
||||
set_show: bool,
|
||||
set_pos: Option<[f32; 2]>,
|
||||
set_size: Option<[f32; 2]>,
|
||||
set_focus: bool,
|
||||
set_title: Option<String>,
|
||||
|
||||
pos: [f32; 2],
|
||||
size: [f32; 2],
|
||||
focus: bool,
|
||||
minimized: bool,
|
||||
}
|
||||
|
||||
impl WinitPlatform {
|
||||
/// Initializes a winit platform instance and configures imgui.
|
||||
///
|
||||
@ -489,8 +593,102 @@ impl WinitPlatform {
|
||||
hidpi_factor: 1.0,
|
||||
cursor_cache: None,
|
||||
mouse_buttons: [Button::INIT; 5],
|
||||
|
||||
#[cfg(feature = "viewports")]
|
||||
windows: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "viewports")]
|
||||
pub fn init_viewports<T>(imgui: &mut Context, event_loop: &winit::event_loop::EventLoop<T>) {
|
||||
let io = imgui.io_mut();
|
||||
|
||||
io.backend_flags.insert(BackendFlags::PLATFORM_HAS_VIEWPORTS);
|
||||
|
||||
imgui.set_platform_backend(ViewportBackend {});
|
||||
|
||||
let mut monitors = Vec::new();
|
||||
for monitor in event_loop.available_monitors() {
|
||||
monitors.push(imgui::PlatformMonitor {
|
||||
main_pos: [monitor.position().x as f32, monitor.position().y as f32],
|
||||
main_size: [monitor.size().width as f32, monitor.size().height as f32],
|
||||
work_pos: [monitor.position().x as f32, monitor.position().y as f32],
|
||||
work_size: [monitor.size().width as f32, monitor.size().height as f32],
|
||||
dpi_scale: 1.0,
|
||||
});
|
||||
}
|
||||
imgui.platform_io_mut().monitors.replace_from_slice(&monitors);
|
||||
|
||||
let main_viewport = imgui.main_viewport_mut();
|
||||
main_viewport.platform_user_data = Box::into_raw(Box::new(ViewportState {
|
||||
create: false,
|
||||
create_flags: imgui::ViewportFlags::empty(),
|
||||
set_show: false,
|
||||
set_pos: None,
|
||||
set_size: None,
|
||||
set_focus: false,
|
||||
set_title: None,
|
||||
pos: [0.0, 0.0],
|
||||
size: [0.0, 0.0],
|
||||
focus: true,
|
||||
minimized: false,
|
||||
})) as *mut _;
|
||||
}
|
||||
|
||||
#[cfg(feature = "viewports")]
|
||||
pub fn update_viewports<T>(&mut self, imgui: &mut Context, window_target: &winit::event_loop::EventLoopWindowTarget<T>) {
|
||||
// remove destroyed windows
|
||||
self.windows.retain(|id, _| {
|
||||
imgui.viewport_by_id(*id).is_some()
|
||||
});
|
||||
|
||||
// handle new viewports
|
||||
for viewport in imgui.viewports_mut() {
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
|
||||
if state.create {
|
||||
let window = winit::window::WindowBuilder::new()
|
||||
.with_always_on_top(state.create_flags.contains(imgui::ViewportFlags::TOP_MOST))
|
||||
// .with_decorations(!state.create_flags.contains(imgui::ViewportFlags::NO_DECORATION))
|
||||
.with_resizable(true)
|
||||
.with_visible(false)
|
||||
.build(window_target)
|
||||
.unwrap();
|
||||
|
||||
self.windows.insert(viewport.id, window);
|
||||
|
||||
state.create = false;
|
||||
}
|
||||
}
|
||||
|
||||
// handle other viewport events
|
||||
for (id, wnd) in &self.windows {
|
||||
let viewport = imgui.viewport_by_id_mut(*id).unwrap();
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
|
||||
if state.set_show {
|
||||
wnd.set_visible(true);
|
||||
state.set_show = false;
|
||||
}
|
||||
if let Some(pos) = &state.set_pos {
|
||||
wnd.set_outer_position(winit::dpi::LogicalPosition::new(pos[0], pos[1]));
|
||||
state.set_pos = None;
|
||||
}
|
||||
if let Some(size) = &state.set_size {
|
||||
wnd.set_inner_size(winit::dpi::LogicalSize::new(size[0], size[1]));
|
||||
state.set_size = None;
|
||||
}
|
||||
if state.set_focus {
|
||||
wnd.focus_window();
|
||||
state.set_focus = false;
|
||||
}
|
||||
if let Some(title) = &state.set_title {
|
||||
wnd.set_title(title);
|
||||
state.set_title = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Attaches the platform instance to a winit window.
|
||||
///
|
||||
/// This function configures imgui-rs in the following ways:
|
||||
@ -847,6 +1045,45 @@ impl WinitPlatform {
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "viewports")]
|
||||
pub fn handle_viewport_event<T>(&mut self, imgui: &mut imgui::Context, main_window: &Window, event: &Event<T>) {
|
||||
match *event {
|
||||
Event::WindowEvent { window_id, ref event } => {
|
||||
let viewport = {
|
||||
if window_id == main_window.id() {
|
||||
imgui.main_viewport_mut()
|
||||
} else {
|
||||
let imgui_id = self.windows.iter().find(|(id, wnd)| wnd.id() == window_id).map(|(id, wnd)| *id).unwrap();
|
||||
imgui.viewport_by_id_mut(imgui_id).unwrap()
|
||||
}
|
||||
};
|
||||
let state = unsafe{&mut *(viewport.platform_user_data as *mut ViewportState)};
|
||||
|
||||
match *event {
|
||||
WindowEvent::Resized(new_size) => {
|
||||
state.size = [new_size.width as f32, new_size.height as f32];
|
||||
},
|
||||
WindowEvent::Moved(new_pos) => {
|
||||
state.pos = [new_pos.x as f32, new_pos.y as f32];
|
||||
},
|
||||
WindowEvent::CloseRequested => {
|
||||
viewport.platform_request_close = true;
|
||||
},
|
||||
WindowEvent::Focused(focus) => {
|
||||
state.focus = focus;
|
||||
},
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
let mut pos = state.pos;
|
||||
pos[0] += position.x as f32;
|
||||
pos[1] += position.y as f32;
|
||||
imgui.io_mut().mouse_pos = pos;
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
#[cfg(all(
|
||||
not(any(
|
||||
feature = "winit-26",
|
||||
|
||||
@ -9,7 +9,7 @@ use crate::clipboard::{ClipboardBackend, ClipboardContext};
|
||||
use crate::fonts::atlas::{FontAtlas, FontId, SharedFontAtlas};
|
||||
use crate::io::Io;
|
||||
use crate::style::Style;
|
||||
use crate::{sys, DrawData, PlatformIo, PlatformViewportContext, RendererViewportContext, PlatformViewportBackend, RendererViewportBackend, Viewport};
|
||||
use crate::{sys, DrawData, PlatformIo, PlatformViewportContext, RendererViewportContext, PlatformViewportBackend, RendererViewportBackend, Viewport, Id};
|
||||
use crate::{MouseCursor, Ui};
|
||||
|
||||
/// An imgui-rs context.
|
||||
@ -569,16 +569,26 @@ impl Context {
|
||||
&mut *(sys::igGetMainViewport() as *mut Viewport)
|
||||
}
|
||||
}
|
||||
pub fn viewport_by_id(&self, id: *mut c_void) -> Option<&Viewport> {
|
||||
pub fn viewport_by_id(&self, id: Id) -> Option<&Viewport> {
|
||||
unsafe {
|
||||
let ptr = sys::igFindViewportByPlatformHandle(id) as *const Viewport;
|
||||
ptr.as_ref()
|
||||
(sys::igFindViewportByID(id.0) as *const Viewport).as_ref()
|
||||
}
|
||||
}
|
||||
pub fn viewport_by_id_mut(&mut self, id: *mut c_void) -> Option<&mut Viewport> {
|
||||
pub fn viewport_by_id_mut(&mut self, id: Id) -> Option<&mut Viewport> {
|
||||
unsafe {
|
||||
let ptr = sys::igFindViewportByPlatformHandle(id) as *mut Viewport;
|
||||
ptr.as_mut()
|
||||
(sys::igFindViewportByID(id.0) as *mut Viewport).as_mut()
|
||||
}
|
||||
}
|
||||
pub fn viewports(&self) -> impl Iterator<Item = &Viewport> {
|
||||
let slice = self.platform_io().viewports.as_slice();
|
||||
unsafe {
|
||||
slice.iter().map(|ptr| &**ptr)
|
||||
}
|
||||
}
|
||||
pub fn viewports_mut(&mut self) -> impl Iterator<Item = &mut Viewport> {
|
||||
let slice = self.platform_io_mut().viewports.as_slice();
|
||||
unsafe {
|
||||
slice.iter().map(|ptr| &mut **ptr)
|
||||
}
|
||||
}
|
||||
/// Returns an immutable reference to the user interface style
|
||||
|
||||
@ -284,7 +284,7 @@ impl Ui {
|
||||
/// Now, however, it is made from the `Ui` object directly, with a few
|
||||
/// deprecated helper methods here.
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, Hash)]
|
||||
pub struct Id(pub(crate) u32);
|
||||
|
||||
impl Id {
|
||||
|
||||
@ -334,7 +334,7 @@ impl RendererViewportContext {
|
||||
#[cfg(feature = "docking")]
|
||||
#[repr(C)]
|
||||
pub struct Viewport {
|
||||
pub(crate) id: crate::Id,
|
||||
pub id: crate::Id,
|
||||
pub flags: ViewportFlags,
|
||||
pub(crate) pos: [f32; 2],
|
||||
pub(crate) size: [f32; 2],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user