mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-11 21:48:36 +00:00
Implemented basic viewport support
This commit is contained in:
parent
4b307a1bf7
commit
3a9cf40de3
@ -3,7 +3,9 @@ use imgui::*;
|
||||
mod support;
|
||||
|
||||
fn main() {
|
||||
let system = support::init(file!());
|
||||
let mut system = support::init(file!());
|
||||
system.enable_viewports();
|
||||
|
||||
let mut value = 0;
|
||||
let choices = ["test test this is 1", "test test this is 2"];
|
||||
system.main_loop(move |_, ui| {
|
||||
|
||||
@ -3,10 +3,11 @@ 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::{Context, FontConfig, FontGlyphRanges, FontSource, Ui, ConfigFlags};
|
||||
use imgui_glium_renderer::Renderer;
|
||||
use imgui_winit_support::{HiDpiMode, WinitPlatform};
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
use std::time::Instant;
|
||||
|
||||
mod clipboard;
|
||||
@ -112,6 +113,11 @@ pub fn init(title: &str) -> System {
|
||||
}
|
||||
|
||||
impl System {
|
||||
pub fn enable_viewports(&mut self) {
|
||||
WinitPlatform::init_viewports(&mut self.imgui, &self.event_loop, self.display.gl_window().window());
|
||||
self.imgui.io_mut().config_flags.insert(ConfigFlags::VIEWPORTS_ENABLE);
|
||||
}
|
||||
|
||||
pub fn main_loop<F: FnMut(&mut bool, &mut Ui) + 'static>(self, mut run_ui: F) {
|
||||
let System {
|
||||
event_loop,
|
||||
|
||||
@ -150,6 +150,9 @@ impl Renderer {
|
||||
ctx.io_mut()
|
||||
.backend_flags
|
||||
.insert(BackendFlags::RENDERER_HAS_VTX_OFFSET);
|
||||
ctx.io_mut()
|
||||
.backend_flags
|
||||
.insert(BackendFlags::RENDERER_HAS_VIEWPORTS);
|
||||
Ok(Renderer {
|
||||
ctx: Rc::clone(facade.get_context()),
|
||||
program,
|
||||
|
||||
@ -188,8 +188,8 @@ use winit_20 as winit;
|
||||
))]
|
||||
use winit_19 as winit;
|
||||
|
||||
use imgui::{self, BackendFlags, ConfigFlags, Context, Io, Key, Ui};
|
||||
use std::cell::Cell;
|
||||
use imgui::{self, BackendFlags, ConfigFlags, Context, Io, Key, Ui, PlatformViewportBackend, ViewportFlags, PlatformMonitor, Viewport};
|
||||
use std::{cell::Cell, rc::Rc};
|
||||
use std::cmp::Ordering;
|
||||
use winit::dpi::{LogicalPosition, LogicalSize};
|
||||
|
||||
@ -444,6 +444,110 @@ impl HiDpiMode {
|
||||
}
|
||||
}
|
||||
|
||||
struct ViewportBackend {
|
||||
event_loop: *const winit::event_loop::EventLoopWindowTarget<()>,
|
||||
}
|
||||
|
||||
enum PlatformHandle {
|
||||
MainWindow(*const winit::window::Window),
|
||||
SecondaryWindow(winit::window::Window),
|
||||
}
|
||||
|
||||
impl PlatformHandle {
|
||||
fn get(&self) -> &winit::window::Window {
|
||||
match self {
|
||||
PlatformHandle::MainWindow(ptr) => unsafe { &**ptr },
|
||||
PlatformHandle::SecondaryWindow(wnd) => wnd,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformViewportBackend for ViewportBackend {
|
||||
fn create_window(&mut self, viewport: &mut imgui::Viewport) {
|
||||
let window = winit::window::WindowBuilder::new()
|
||||
.with_always_on_top(viewport.flags.contains(ViewportFlags::TOP_MOST))
|
||||
.with_decorations(!viewport.flags.contains(ViewportFlags::NO_DECORATION))
|
||||
.with_resizable(true)
|
||||
.with_visible(false)
|
||||
.build(unsafe{&*self.event_loop})
|
||||
.unwrap();
|
||||
|
||||
viewport.platform_handle = Box::into_raw(Box::new(PlatformHandle::SecondaryWindow(window))) as *mut _;
|
||||
}
|
||||
|
||||
fn destroy_window(&mut self, viewport: &mut imgui::Viewport) {
|
||||
unsafe {
|
||||
// drop window
|
||||
Box::from_raw(viewport.platform_handle as *mut PlatformHandle);
|
||||
}
|
||||
}
|
||||
|
||||
fn show_window(&mut self, viewport: &mut imgui::Viewport) {
|
||||
let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() };
|
||||
window.set_visible(true);
|
||||
}
|
||||
|
||||
fn set_window_pos(&mut self, viewport: &mut imgui::Viewport, pos: [f32; 2]) {
|
||||
let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() };
|
||||
window.set_outer_position(winit::dpi::LogicalPosition::new(pos[0], pos[1]));
|
||||
}
|
||||
|
||||
fn get_window_pos(&mut self, viewport: &mut imgui::Viewport) -> [f32; 2] {
|
||||
let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() };
|
||||
let pos = window.outer_position().unwrap();
|
||||
[pos.x as f32, pos.y as f32]
|
||||
}
|
||||
|
||||
fn set_window_size(&mut self, viewport: &mut imgui::Viewport, size: [f32; 2]) {
|
||||
let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() };
|
||||
window.set_inner_size(winit::dpi::LogicalSize::new(size[0], size[1]));
|
||||
}
|
||||
|
||||
fn get_window_size(&mut self, viewport: &mut imgui::Viewport) -> [f32; 2] {
|
||||
let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() };
|
||||
let size = window.inner_size();
|
||||
[size.width as f32, size.width as f32]
|
||||
}
|
||||
|
||||
fn set_window_focus(&mut self, viewport: &mut imgui::Viewport) {
|
||||
let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() };
|
||||
window.focus_window();
|
||||
}
|
||||
|
||||
fn get_window_focus(&mut self, viewport: &mut imgui::Viewport) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn get_window_minimized(&mut self, viewport: &mut imgui::Viewport) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn set_window_title(&mut self, viewport: &mut imgui::Viewport, title: &str) {
|
||||
let window = unsafe { (*(viewport.platform_handle as *const PlatformHandle)).get() };
|
||||
window.set_title(title);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl WinitPlatform {
|
||||
/// Initializes a winit platform instance and configures imgui.
|
||||
///
|
||||
@ -491,6 +595,32 @@ impl WinitPlatform {
|
||||
mouse_buttons: [Button::INIT; 5],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_viewports(imgui: &mut Context, event_loop: &winit::event_loop::EventLoopWindowTarget<()>, main_window: &winit::window::Window) {
|
||||
let io = imgui.io_mut();
|
||||
io.backend_flags.insert(BackendFlags::PLATFORM_HAS_VIEWPORTS);
|
||||
|
||||
imgui.set_platform_backend(ViewportBackend{
|
||||
event_loop: event_loop as *const _,
|
||||
});
|
||||
|
||||
let pio = imgui.platform_io_mut();
|
||||
let mut monitors = Vec::new();
|
||||
for monitor in main_window.available_monitors() {
|
||||
monitors.push(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,
|
||||
});
|
||||
}
|
||||
pio.monitors.replace_from_slice(&monitors);
|
||||
|
||||
let main_viewport = imgui.main_viewport_mut();
|
||||
main_viewport.platform_handle = Box::into_raw(Box::new(PlatformHandle::MainWindow(main_window as *const _))) as *mut _;
|
||||
}
|
||||
|
||||
/// Attaches the platform instance to a winit window.
|
||||
///
|
||||
/// This function configures imgui-rs in the following ways:
|
||||
|
||||
@ -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};
|
||||
use crate::{sys, DrawData, PlatformIo, PlatformViewportContext, RendererViewportContext, PlatformViewportBackend, RendererViewportBackend, Viewport};
|
||||
use crate::{MouseCursor, Ui};
|
||||
|
||||
/// An imgui-rs context.
|
||||
@ -60,6 +60,9 @@ pub struct Context {
|
||||
// imgui a mutable pointer to it.
|
||||
clipboard_ctx: Box<UnsafeCell<ClipboardContext>>,
|
||||
|
||||
platform_viewport_ctx: Box<UnsafeCell<PlatformViewportContext>>,
|
||||
renderer_viewport_ctx: Box<UnsafeCell<RendererViewportContext>>,
|
||||
|
||||
ui: Ui,
|
||||
}
|
||||
|
||||
@ -216,6 +219,51 @@ impl Context {
|
||||
io.clipboard_user_data = clipboard_ctx.get() as *mut _;
|
||||
self.clipboard_ctx = clipboard_ctx;
|
||||
}
|
||||
pub fn set_platform_backend<T: PlatformViewportBackend>(&mut self, backend: T) {
|
||||
let ctx = Box::new(UnsafeCell::new(PlatformViewportContext {
|
||||
backend: Box::new(backend),
|
||||
}));
|
||||
|
||||
let io = self.io_mut();
|
||||
io.backend_platform_user_data = ctx.get() as *mut _;
|
||||
|
||||
let pio = self.platform_io_mut();
|
||||
pio.platform_create_window = Some(crate::platform_io::platform_create_window);
|
||||
pio.platform_destroy_window = Some(crate::platform_io::platform_destroy_window);
|
||||
pio.platform_show_window = Some(crate::platform_io::platform_show_window);
|
||||
pio.platform_set_window_pos = Some(crate::platform_io::platform_set_window_pos);
|
||||
pio.platform_get_window_pos = Some(crate::platform_io::platform_get_window_pos);
|
||||
pio.platform_set_window_size = Some(crate::platform_io::platform_set_window_size);
|
||||
pio.platform_get_window_size = Some(crate::platform_io::platform_get_window_size);
|
||||
pio.platform_set_window_focus = Some(crate::platform_io::platform_set_window_focus);
|
||||
pio.platform_get_window_focus = Some(crate::platform_io::platform_get_window_focus);
|
||||
pio.platform_get_window_minimized = Some(crate::platform_io::platform_get_window_minimized);
|
||||
pio.platform_set_window_title = Some(crate::platform_io::platform_set_window_title);
|
||||
pio.platform_set_window_alpha = Some(crate::platform_io::platform_set_window_alpha);
|
||||
pio.platform_update_window = Some(crate::platform_io::platform_update_window);
|
||||
pio.platform_render_window = Some(crate::platform_io::platform_render_window);
|
||||
pio.platform_swap_buffers = Some(crate::platform_io::platform_swap_buffers);
|
||||
pio.platform_create_vk_surface = Some(crate::platform_io::platform_create_vk_surface);
|
||||
|
||||
self.platform_viewport_ctx = ctx;
|
||||
}
|
||||
pub fn set_renderer_backend<T: RendererViewportBackend>(&mut self, backend: T) {
|
||||
let ctx = Box::new(UnsafeCell::new(RendererViewportContext {
|
||||
backend: Box::new(backend),
|
||||
}));
|
||||
|
||||
let io = self.io_mut();
|
||||
io.backend_renderer_user_data = ctx.get() as *mut _;
|
||||
|
||||
let pio = self.platform_io_mut();
|
||||
pio.renderer_create_window = Some(crate::platform_io::renderer_create_window);
|
||||
pio.renderer_destroy_window = Some(crate::platform_io::renderer_destroy_window);
|
||||
pio.renderer_set_window_size = Some(crate::platform_io::renderer_set_window_size);
|
||||
pio.renderer_render_window = Some(crate::platform_io::renderer_render_window);
|
||||
pio.renderer_swap_buffers = Some(crate::platform_io::renderer_swap_buffers);
|
||||
|
||||
self.renderer_viewport_ctx = ctx;
|
||||
}
|
||||
fn create_internal(mut shared_font_atlas: Option<SharedFontAtlas>) -> Self {
|
||||
let _guard = CTX_MUTEX.lock();
|
||||
assert!(
|
||||
@ -239,6 +287,8 @@ impl Context {
|
||||
platform_name: None,
|
||||
renderer_name: None,
|
||||
clipboard_ctx: Box::new(ClipboardContext::dummy().into()),
|
||||
platform_viewport_ctx: Box::new(UnsafeCell::new(PlatformViewportContext::dummy())),
|
||||
renderer_viewport_ctx: Box::new(UnsafeCell::new(RendererViewportContext::dummy())),
|
||||
ui: Ui {
|
||||
buffer: UnsafeCell::new(crate::string::UiBuffer::new(1024)),
|
||||
},
|
||||
@ -328,6 +378,8 @@ impl SuspendedContext {
|
||||
platform_name: None,
|
||||
renderer_name: None,
|
||||
clipboard_ctx: Box::new(ClipboardContext::dummy().into()),
|
||||
platform_viewport_ctx: Box::new(UnsafeCell::new(PlatformViewportContext::dummy())),
|
||||
renderer_viewport_ctx: Box::new(UnsafeCell::new(RendererViewportContext::dummy())),
|
||||
ui: Ui {
|
||||
buffer: UnsafeCell::new(crate::string::UiBuffer::new(1024)),
|
||||
},
|
||||
@ -485,12 +537,22 @@ impl Context {
|
||||
&*(sys::igGetPlatformIO() as *const PlatformIo)
|
||||
}
|
||||
}
|
||||
pub fn platform_io_mut(&mut self) -> &PlatformIo {
|
||||
pub fn platform_io_mut(&mut self) -> &mut PlatformIo {
|
||||
unsafe {
|
||||
// safe because PlatformIo is a transparent wrapper around sys::ImGuiPlatformIO
|
||||
&mut *(sys::igGetPlatformIO() as *mut PlatformIo)
|
||||
}
|
||||
}
|
||||
pub fn main_viewport(&self) -> &Viewport {
|
||||
unsafe {
|
||||
&*(sys::igGetMainViewport() as *mut Viewport)
|
||||
}
|
||||
}
|
||||
pub fn main_viewport_mut(&mut self) -> &mut Viewport {
|
||||
unsafe {
|
||||
&mut *(sys::igGetMainViewport() as *mut Viewport)
|
||||
}
|
||||
}
|
||||
/// Returns an immutable reference to the user interface style
|
||||
#[doc(alias = "GetStyle")]
|
||||
pub fn style(&self) -> &Style {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//! Internal raw utilities (don't use unless you know what you're doing!)
|
||||
|
||||
use std::slice;
|
||||
use std::{slice, mem::size_of};
|
||||
|
||||
/// A generic version of the raw imgui-sys ImVector struct types
|
||||
#[repr(C)]
|
||||
@ -15,6 +15,19 @@ impl<T> ImVector<T> {
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
unsafe { slice::from_raw_parts(self.data, self.size as usize) }
|
||||
}
|
||||
|
||||
pub fn replace_from_slice(&mut self, data: &[T]) {
|
||||
unsafe {
|
||||
sys::igMemFree(self.data as *mut _);
|
||||
|
||||
let buffer_ptr = sys::igMemAlloc(size_of::<T>() * data.len()) as *mut T;
|
||||
buffer_ptr.copy_from_nonoverlapping(data.as_ptr(), data.len());
|
||||
|
||||
self.size = data.len() as i32;
|
||||
self.capacity = data.len() as i32;
|
||||
self.data = buffer_ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use bitflags::bitflags;
|
||||
use std::f32;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::os::raw::{c_char, c_void, c_int};
|
||||
use std::os::raw::{c_char, c_void};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::fonts::atlas::FontAtlas;
|
||||
@ -158,73 +158,6 @@ fn test_nav_input_variants() {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
#[repr(C)]
|
||||
pub struct PlatformIo {
|
||||
pub(crate) platform_create_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_destroy_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_show_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_set_window_pos: Option<unsafe extern "C" fn(*mut Viewport, sys::ImVec2)>,
|
||||
pub(crate) platform_get_window_pos: Option<unsafe extern "C" fn(*mut Viewport) -> sys::ImVec2>,
|
||||
pub(crate) platform_set_window_size: Option<unsafe extern "C" fn(*mut Viewport, sys::ImVec2)>,
|
||||
pub(crate) platform_get_window_size: Option<unsafe extern "C" fn(*mut Viewport) -> sys::ImVec2>,
|
||||
pub(crate) platform_set_window_focus: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_get_window_focus: Option<unsafe extern "C" fn(*mut Viewport) -> bool>,
|
||||
pub(crate) platform_get_window_minimized: Option<unsafe extern "C" fn(*mut Viewport) -> bool>,
|
||||
pub(crate) platform_set_window_title: Option<unsafe extern "C" fn(*mut Viewport, *const c_char)>,
|
||||
pub(crate) platform_set_window_alpha: Option<unsafe extern "C" fn(*mut Viewport, f32)>,
|
||||
pub(crate) platform_update_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_render_window: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
pub(crate) platform_swap_buffers: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
pub(crate) platform_get_window_dpi_scale: Option<unsafe extern "C" fn(*mut Viewport) -> f32>,
|
||||
pub(crate) platform_on_changed_viewport: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_create_vk_surface: Option<unsafe extern "C" fn(*mut Viewport, u64, *const c_void, *mut u64) -> c_int>,
|
||||
|
||||
pub(crate) renderer_create_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) renderer_destroy_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) renderer_set_window_size: Option<unsafe extern "C" fn(*mut Viewport, sys::ImVec2)>,
|
||||
pub(crate) renderer_render_window: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
pub(crate) renderer_swap_buffers: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
|
||||
pub(crate) monitors: ImVector<PlatformMonitor>,
|
||||
|
||||
pub(crate) viewports: ImVector<*mut Viewport>,
|
||||
}
|
||||
|
||||
unsafe impl RawCast<sys::ImGuiPlatformIO> for PlatformIo {}
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
#[repr(C)]
|
||||
pub struct Viewport {
|
||||
pub(crate) id: crate::Id,
|
||||
pub(crate) flags: ViewportFlags,
|
||||
pub(crate) pos: [f32; 2],
|
||||
pub(crate) size: [f32; 2],
|
||||
pub(crate) work_pos: [f32; 2],
|
||||
pub(crate) work_size: [f32; 2],
|
||||
pub(crate) dpi_scale: f32,
|
||||
pub(crate) parent_viewport_id: crate::Id,
|
||||
pub(crate) draw_data: *mut crate::DrawData,
|
||||
|
||||
pub(crate) renderer_user_data: *mut c_void,
|
||||
pub(crate) platform_user_data: *mut c_void,
|
||||
pub(crate) platform_handle: *mut c_void,
|
||||
pub(crate) platform_handle_raw: *mut c_void,
|
||||
pub(crate) platform_request_move: bool,
|
||||
pub(crate) platform_request_resize: bool,
|
||||
pub(crate) platform_request_close: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
#[repr(C)]
|
||||
pub struct PlatformMonitor {
|
||||
main_pos: [f32; 2],
|
||||
main_size: [f32; 2],
|
||||
work_pos: [f32; 2],
|
||||
work_size: [f32; 2],
|
||||
dpi_scale: f32,
|
||||
}
|
||||
|
||||
/// Settings and inputs/outputs for imgui-rs
|
||||
#[repr(C)]
|
||||
pub struct Io {
|
||||
@ -320,8 +253,8 @@ pub struct Io {
|
||||
|
||||
pub(crate) backend_platform_name: *const c_char,
|
||||
pub(crate) backend_renderer_name: *const c_char,
|
||||
backend_platform_user_data: *mut c_void,
|
||||
backend_renderer_user_data: *mut c_void,
|
||||
pub(crate) backend_platform_user_data: *mut c_void,
|
||||
pub(crate) backend_renderer_user_data: *mut c_void,
|
||||
backend_language_user_data: *mut c_void,
|
||||
pub(crate) get_clipboard_text_fn:
|
||||
Option<unsafe extern "C" fn(user_data: *mut c_void) -> *const c_char>,
|
||||
|
||||
@ -20,6 +20,7 @@ pub use self::input::keyboard::*;
|
||||
pub use self::input::mouse::*;
|
||||
pub use self::input_widget::*;
|
||||
pub use self::io::*;
|
||||
pub use self::platform_io::*;
|
||||
pub use self::layout::*;
|
||||
pub use self::list_clipper::ListClipper;
|
||||
pub use self::plothistogram::PlotHistogram;
|
||||
@ -68,6 +69,7 @@ mod input;
|
||||
mod input_widget;
|
||||
pub mod internal;
|
||||
mod io;
|
||||
mod platform_io;
|
||||
mod layout;
|
||||
mod list_clipper;
|
||||
mod math;
|
||||
|
||||
418
imgui/src/platform_io.rs
Normal file
418
imgui/src/platform_io.rs
Normal file
@ -0,0 +1,418 @@
|
||||
use std::{os::raw::{c_char, c_int}, ffi::{c_void, CStr}};
|
||||
|
||||
use crate::{internal::{ImVector, RawCast}, ViewportFlags};
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
#[repr(C)]
|
||||
pub struct PlatformIo {
|
||||
pub(crate) platform_create_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_destroy_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_show_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_set_window_pos: Option<unsafe extern "C" fn(*mut Viewport, sys::ImVec2)>,
|
||||
pub(crate) platform_get_window_pos: Option<unsafe extern "C" fn(*mut Viewport) -> sys::ImVec2>,
|
||||
pub(crate) platform_set_window_size: Option<unsafe extern "C" fn(*mut Viewport, sys::ImVec2)>,
|
||||
pub(crate) platform_get_window_size: Option<unsafe extern "C" fn(*mut Viewport) -> sys::ImVec2>,
|
||||
pub(crate) platform_set_window_focus: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_get_window_focus: Option<unsafe extern "C" fn(*mut Viewport) -> bool>,
|
||||
pub(crate) platform_get_window_minimized: Option<unsafe extern "C" fn(*mut Viewport) -> bool>,
|
||||
pub(crate) platform_set_window_title: Option<unsafe extern "C" fn(*mut Viewport, *const c_char)>,
|
||||
pub(crate) platform_set_window_alpha: Option<unsafe extern "C" fn(*mut Viewport, f32)>,
|
||||
pub(crate) platform_update_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_render_window: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
pub(crate) platform_swap_buffers: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
pub(crate) platform_get_window_dpi_scale: Option<unsafe extern "C" fn(*mut Viewport) -> f32>,
|
||||
pub(crate) platform_on_changed_viewport: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) platform_set_ime_input_pos: Option<unsafe extern "C" fn(*mut Viewport, sys::ImVec2)>,
|
||||
pub(crate) platform_create_vk_surface: Option<unsafe extern "C" fn(*mut Viewport, u64, *const c_void, *mut u64) -> c_int>,
|
||||
|
||||
pub(crate) renderer_create_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) renderer_destroy_window: Option<unsafe extern "C" fn(*mut Viewport)>,
|
||||
pub(crate) renderer_set_window_size: Option<unsafe extern "C" fn(*mut Viewport, sys::ImVec2)>,
|
||||
pub(crate) renderer_render_window: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
pub(crate) renderer_swap_buffers: Option<unsafe extern "C" fn(*mut Viewport, *mut c_void)>,
|
||||
|
||||
pub monitors: ImVector<PlatformMonitor>,
|
||||
|
||||
pub(crate) viewports: ImVector<*mut Viewport>,
|
||||
}
|
||||
|
||||
unsafe impl RawCast<sys::ImGuiPlatformIO> for PlatformIo {}
|
||||
|
||||
#[test]
|
||||
#[cfg(test)]
|
||||
fn test_platform_io_memory_layout() {
|
||||
use std::mem;
|
||||
assert_eq!(mem::size_of::<PlatformIo>(), mem::size_of::<sys::ImGuiPlatformIO>());
|
||||
assert_eq!(mem::align_of::<PlatformIo>(), mem::align_of::<sys::ImGuiPlatformIO>());
|
||||
use sys::ImGuiPlatformIO;
|
||||
macro_rules! assert_field_offset {
|
||||
($l:ident, $r:ident) => {
|
||||
assert_eq!(
|
||||
memoffset::offset_of!(PlatformIo, $l),
|
||||
memoffset::offset_of!(ImGuiPlatformIO, $r)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
assert_field_offset!(platform_create_window, Platform_CreateWindow);
|
||||
assert_field_offset!(platform_destroy_window, Platform_DestroyWindow);
|
||||
assert_field_offset!(platform_show_window, Platform_ShowWindow);
|
||||
assert_field_offset!(platform_set_window_pos, Platform_SetWindowPos);
|
||||
assert_field_offset!(platform_get_window_pos, Platform_GetWindowPos);
|
||||
assert_field_offset!(platform_set_window_size, Platform_SetWindowSize);
|
||||
assert_field_offset!(platform_get_window_size, Platform_GetWindowSize);
|
||||
assert_field_offset!(platform_set_window_focus, Platform_SetWindowFocus);
|
||||
assert_field_offset!(platform_get_window_focus, Platform_GetWindowFocus);
|
||||
assert_field_offset!(platform_get_window_minimized, Platform_GetWindowMinimized);
|
||||
assert_field_offset!(platform_set_window_title, Platform_SetWindowTitle);
|
||||
assert_field_offset!(platform_set_window_alpha, Platform_SetWindowAlpha);
|
||||
assert_field_offset!(platform_update_window, Platform_UpdateWindow);
|
||||
assert_field_offset!(platform_render_window, Platform_RenderWindow);
|
||||
assert_field_offset!(platform_swap_buffers, Platform_SwapBuffers);
|
||||
assert_field_offset!(platform_get_window_dpi_scale, Platform_GetWindowDpiScale);
|
||||
assert_field_offset!(platform_on_changed_viewport, Platform_OnChangedViewport);
|
||||
assert_field_offset!(platform_set_ime_input_pos, Platform_SetImeInputPos);
|
||||
assert_field_offset!(platform_create_vk_surface, Platform_CreateVkSurface);
|
||||
|
||||
assert_field_offset!(renderer_create_window, Renderer_CreateWindow);
|
||||
assert_field_offset!(renderer_destroy_window, Renderer_DestroyWindow);
|
||||
assert_field_offset!(renderer_set_window_size, Renderer_SetWindowSize);
|
||||
assert_field_offset!(renderer_render_window, Renderer_RenderWindow);
|
||||
assert_field_offset!(renderer_swap_buffers, Renderer_SwapBuffers);
|
||||
|
||||
assert_field_offset!(monitors, Monitors);
|
||||
assert_field_offset!(viewports, Viewports);
|
||||
}
|
||||
|
||||
pub trait PlatformViewportBackend: 'static {
|
||||
fn create_window(&mut self, viewport: &mut Viewport);
|
||||
fn destroy_window(&mut self, viewport: &mut Viewport);
|
||||
fn show_window(&mut self, viewport: &mut Viewport);
|
||||
fn set_window_pos(&mut self, viewport: &mut Viewport, pos: [f32; 2]);
|
||||
fn get_window_pos(&mut self, viewport: &mut Viewport) -> [f32; 2];
|
||||
fn set_window_size(&mut self, viewport: &mut Viewport, size: [f32; 2]);
|
||||
fn get_window_size(&mut self, viewport: &mut Viewport) -> [f32; 2];
|
||||
fn set_window_focus(&mut self, viewport: &mut Viewport);
|
||||
fn get_window_focus(&mut self, viewport: &mut Viewport) -> bool;
|
||||
fn get_window_minimized(&mut self, viewport: &mut Viewport) -> bool;
|
||||
fn set_window_title(&mut self, viewport: &mut Viewport, title: &str);
|
||||
fn set_window_alpha(&mut self, viewport: &mut Viewport, alpha: f32);
|
||||
|
||||
fn update_window(&mut self, viewport: &mut Viewport);
|
||||
fn render_window(&mut self, viewport: &mut Viewport);
|
||||
fn swap_buffers(&mut self, viewport: &mut Viewport);
|
||||
fn create_vk_surface(&mut self, viewport: &mut Viewport, instance: u64, out_surface: &mut u64) -> i32;
|
||||
}
|
||||
|
||||
fn get_platform_ctx() -> &'static mut PlatformViewportContext {
|
||||
unsafe {
|
||||
&mut *((*sys::igGetIO()).BackendPlatformUserData as *mut PlatformViewportContext)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_renderer_ctx() -> &'static mut RendererViewportContext {
|
||||
unsafe {
|
||||
&mut *((*sys::igGetIO()).BackendRendererUserData as *mut RendererViewportContext)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) extern "C" fn platform_create_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.create_window(unsafe{&mut *viewport});
|
||||
}
|
||||
pub(crate) extern "C" fn platform_destroy_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.destroy_window(unsafe{&mut *viewport});
|
||||
}
|
||||
pub(crate) extern "C" fn platform_show_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.show_window(unsafe{&mut *viewport});
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_pos(viewport: *mut Viewport, pos: sys::ImVec2) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.set_window_pos(unsafe{&mut *viewport}, [pos.x, pos.y]);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_pos(viewport: *mut Viewport) -> sys::ImVec2 {
|
||||
let ctx = get_platform_ctx();
|
||||
let pos = ctx.backend.get_window_pos(unsafe{&mut *viewport});
|
||||
sys::ImVec2::new(pos[0], pos[1])
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_size(viewport: *mut Viewport, size: sys::ImVec2) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.set_window_size(unsafe{&mut *viewport}, [size.x, size.y]);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_size(viewport: *mut Viewport) -> sys::ImVec2 {
|
||||
let ctx = get_platform_ctx();
|
||||
let size = ctx.backend.get_window_size(unsafe{&mut *viewport});
|
||||
sys::ImVec2::new(size[0], size[1])
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_focus(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.set_window_focus(unsafe{&mut *viewport});
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_focus(viewport: *mut Viewport) -> bool {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.get_window_focus(unsafe{&mut *viewport})
|
||||
}
|
||||
pub(crate) extern "C" fn platform_get_window_minimized(viewport: *mut Viewport) -> bool {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.get_window_minimized(unsafe{&mut *viewport})
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_title(viewport: *mut Viewport, title: *const c_char) {
|
||||
let ctx = get_platform_ctx();
|
||||
let title = unsafe { CStr::from_ptr(title).to_str().unwrap() };
|
||||
ctx.backend.set_window_title(unsafe{&mut *viewport}, title);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_set_window_alpha(viewport: *mut Viewport, alpha: f32) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.set_window_alpha(unsafe{&mut *viewport}, alpha);
|
||||
}
|
||||
pub(crate) extern "C" fn platform_update_window(viewport: *mut Viewport) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.update_window(unsafe{&mut *viewport});
|
||||
}
|
||||
pub(crate) extern "C" fn platform_render_window(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.render_window(unsafe{&mut *viewport});
|
||||
}
|
||||
pub(crate) extern "C" fn platform_swap_buffers(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.swap_buffers(unsafe{&mut *viewport});
|
||||
}
|
||||
pub(crate) extern "C" fn platform_create_vk_surface(viewport: *mut Viewport, instance: u64, _arg: *const c_void, out_surface: *mut u64) -> c_int {
|
||||
let ctx = get_platform_ctx();
|
||||
ctx.backend.create_vk_surface(unsafe{&mut *viewport}, instance, unsafe{&mut *out_surface})
|
||||
}
|
||||
|
||||
pub(crate) struct DummyPlatformViewportBackend {}
|
||||
impl PlatformViewportBackend for DummyPlatformViewportBackend {
|
||||
fn create_window(&mut self, viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn destroy_window(&mut self, viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn show_window(&mut self, viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_pos(&mut self, viewport: &mut Viewport, pos: [f32; 2]) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_pos(&mut self, viewport: &mut Viewport) -> [f32; 2] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_size(&mut self, viewport: &mut Viewport, size: [f32; 2]) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_size(&mut self, viewport: &mut Viewport) -> [f32; 2] {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_focus(&mut self, viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_focus(&mut self, viewport: &mut Viewport) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_window_minimized(&mut self, viewport: &mut Viewport) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_title(&mut self, viewport: &mut Viewport, title: &str) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_alpha(&mut self, viewport: &mut Viewport, alpha: f32) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn update_window(&mut self, viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn render_window(&mut self, viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn swap_buffers(&mut self, viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn create_vk_surface(&mut self, viewport: &mut Viewport, instance: u64, out_surface: &mut u64) -> i32 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct PlatformViewportContext {
|
||||
pub(crate) backend: Box<dyn PlatformViewportBackend>,
|
||||
}
|
||||
|
||||
impl PlatformViewportContext {
|
||||
pub(crate) fn dummy() -> Self {
|
||||
Self {
|
||||
backend: Box::new(DummyPlatformViewportBackend{}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RendererViewportBackend: 'static {
|
||||
fn create_window(&mut self, viewport: &mut Viewport);
|
||||
fn destroy_window(&mut self, viewport: &mut Viewport);
|
||||
fn set_window_size(&mut self, viewport: &mut Viewport, size: [f32; 2]);
|
||||
fn render_window(&mut self, viewport: &mut Viewport);
|
||||
fn swap_buffers(&mut self, viewport: &mut Viewport);
|
||||
}
|
||||
|
||||
pub(crate) extern "C" fn renderer_create_window(viewport: *mut Viewport) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.create_window(unsafe{&mut *viewport});
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_destroy_window(viewport: *mut Viewport) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.destroy_window(unsafe{&mut *viewport});
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_set_window_size(viewport: *mut Viewport, size: sys::ImVec2) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.set_window_size(unsafe{&mut *viewport}, [size.x, size.y]);
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_render_window(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.render_window(unsafe{&mut *viewport});
|
||||
}
|
||||
pub(crate) extern "C" fn renderer_swap_buffers(viewport: *mut Viewport, _arg: *mut c_void) {
|
||||
let ctx = get_renderer_ctx();
|
||||
ctx.backend.swap_buffers(unsafe{&mut *viewport});
|
||||
}
|
||||
|
||||
pub(crate) struct DummyRendererViewportBackend {}
|
||||
impl RendererViewportBackend for DummyRendererViewportBackend {
|
||||
fn create_window(&mut self, viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn destroy_window(&mut self, viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn set_window_size(&mut self, viewport: &mut Viewport, size: [f32; 2]) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn render_window(&mut self, viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn swap_buffers(&mut self, viewport: &mut Viewport) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RendererViewportContext {
|
||||
pub(crate) backend: Box<dyn RendererViewportBackend>,
|
||||
}
|
||||
|
||||
impl RendererViewportContext {
|
||||
pub(crate) fn dummy() -> Self {
|
||||
Self {
|
||||
backend: Box::new(DummyRendererViewportBackend{}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
#[repr(C)]
|
||||
pub struct Viewport {
|
||||
pub(crate) id: crate::Id,
|
||||
pub flags: ViewportFlags,
|
||||
pub(crate) pos: [f32; 2],
|
||||
pub(crate) size: [f32; 2],
|
||||
pub(crate) work_pos: [f32; 2],
|
||||
pub(crate) work_size: [f32; 2],
|
||||
pub(crate) dpi_scale: f32,
|
||||
pub(crate) parent_viewport_id: crate::Id,
|
||||
pub(crate) draw_data: *mut crate::DrawData,
|
||||
|
||||
pub renderer_user_data: *mut c_void,
|
||||
pub platform_user_data: *mut c_void,
|
||||
pub platform_handle: *mut c_void,
|
||||
pub platform_handle_raw: *mut c_void,
|
||||
pub platform_request_move: bool,
|
||||
pub platform_request_resize: bool,
|
||||
pub platform_request_close: bool,
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(test)]
|
||||
fn test_viewport_memory_layout() {
|
||||
use std::mem;
|
||||
assert_eq!(mem::size_of::<Viewport>(), mem::size_of::<sys::ImGuiViewport>());
|
||||
assert_eq!(mem::align_of::<Viewport>(), mem::align_of::<sys::ImGuiViewport>());
|
||||
use sys::ImGuiViewport;
|
||||
macro_rules! assert_field_offset {
|
||||
($l:ident, $r:ident) => {
|
||||
assert_eq!(
|
||||
memoffset::offset_of!(Viewport, $l),
|
||||
memoffset::offset_of!(ImGuiViewport, $r)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
assert_field_offset!(id, ID);
|
||||
assert_field_offset!(flags, Flags);
|
||||
assert_field_offset!(pos, Pos);
|
||||
assert_field_offset!(size, Size);
|
||||
assert_field_offset!(work_pos, WorkPos);
|
||||
assert_field_offset!(work_size, WorkSize);
|
||||
assert_field_offset!(dpi_scale, DpiScale);
|
||||
assert_field_offset!(parent_viewport_id, ParentViewportId);
|
||||
assert_field_offset!(draw_data, DrawData);
|
||||
|
||||
assert_field_offset!(renderer_user_data, RendererUserData);
|
||||
assert_field_offset!(platform_user_data, PlatformUserData);
|
||||
assert_field_offset!(platform_handle, PlatformHandle);
|
||||
assert_field_offset!(platform_handle_raw, PlatformHandleRaw);
|
||||
assert_field_offset!(platform_request_move, PlatformRequestMove);
|
||||
assert_field_offset!(platform_request_resize, PlatformRequestResize);
|
||||
assert_field_offset!(platform_request_close, PlatformRequestClose);
|
||||
}
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
#[repr(C)]
|
||||
pub struct PlatformMonitor {
|
||||
pub main_pos: [f32; 2],
|
||||
pub main_size: [f32; 2],
|
||||
pub work_pos: [f32; 2],
|
||||
pub work_size: [f32; 2],
|
||||
pub dpi_scale: f32,
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(test)]
|
||||
fn test_platform_monitor_memory_layout() {
|
||||
use std::mem;
|
||||
assert_eq!(mem::size_of::<PlatformMonitor>(), mem::size_of::<sys::ImGuiPlatformMonitor>());
|
||||
assert_eq!(mem::align_of::<PlatformMonitor>(), mem::align_of::<sys::ImGuiPlatformMonitor>());
|
||||
use sys::ImGuiPlatformMonitor;
|
||||
macro_rules! assert_field_offset {
|
||||
($l:ident, $r:ident) => {
|
||||
assert_eq!(
|
||||
memoffset::offset_of!(PlatformMonitor, $l),
|
||||
memoffset::offset_of!(ImGuiPlatformMonitor, $r)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
assert_field_offset!(main_pos, MainPos);
|
||||
assert_field_offset!(main_size, MainSize);
|
||||
assert_field_offset!(work_pos, WorkPos);
|
||||
assert_field_offset!(work_size, WorkSize);
|
||||
assert_field_offset!(dpi_scale, DpiScale);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user