Implemented basic viewport support

This commit is contained in:
Robin Quint 2022-02-28 16:45:52 +01:00
parent 4b307a1bf7
commit 3a9cf40de3
9 changed files with 646 additions and 77 deletions

View File

@ -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| {

View File

@ -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,

View File

@ -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,

View File

@ -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:

View File

@ -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 {

View File

@ -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]

View File

@ -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>,

View File

@ -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
View 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);
}