mirror of
https://github.com/eliasstepanik/imgui-rs.git
synced 2026-01-13 14:38:36 +00:00
Merge pull request #619 from Rob2309/main
Expose Viewport functionality
This commit is contained in:
commit
a2ad8dd955
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
rust: ["1.57"]
|
||||
rust: ["1.60"]
|
||||
|
||||
env:
|
||||
RUSTFLAGS: -D warnings
|
||||
@ -81,7 +81,7 @@ jobs:
|
||||
matrix:
|
||||
rust:
|
||||
- stable
|
||||
- "1.57"
|
||||
- "1.60"
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- macos-latest
|
||||
|
||||
@ -6,6 +6,7 @@ members = [
|
||||
"imgui-glow-renderer",
|
||||
"imgui-sdl2-support",
|
||||
"imgui-winit-support",
|
||||
"imgui-winit-glow-renderer-viewports",
|
||||
"imgui-examples",
|
||||
"xtask",
|
||||
]
|
||||
|
||||
@ -60,7 +60,7 @@ be applicable to usage with any backend/renderer.
|
||||
|
||||
## Minimum Support Rust Version (MSRV)
|
||||
|
||||
The MSRV for `imgui-rs` and all of the backend crates is **1.57**. We update our MSRV periodically, and issue a minor bump for it.
|
||||
The MSRV for `imgui-rs` and all of the backend crates is **1.60**. We update our MSRV periodically, and issue a minor bump for it.
|
||||
|
||||
## Choosing a backend platform and a renderer
|
||||
|
||||
|
||||
@ -4,8 +4,10 @@ mod support;
|
||||
|
||||
fn main() {
|
||||
let system = support::init(file!());
|
||||
|
||||
let mut value = 0;
|
||||
let choices = ["test test this is 1", "test test this is 2"];
|
||||
|
||||
system.main_loop(move |_, ui| {
|
||||
ui.window("Hello world")
|
||||
.size([300.0, 110.0], Condition::FirstUseEver)
|
||||
|
||||
@ -190,7 +190,7 @@ struct HumanData {
|
||||
}
|
||||
|
||||
impl HumanData {
|
||||
pub fn sort_humans(humans: &mut Vec<Self>, specs: Specs<'_>) {
|
||||
pub fn sort_humans(humans: &mut [Self], specs: Specs<'_>) {
|
||||
let spec = specs.iter().next().unwrap();
|
||||
if let Some(kind) = spec.sort_direction() {
|
||||
match kind {
|
||||
|
||||
16
imgui-winit-glow-renderer-viewports/Cargo.toml
Normal file
16
imgui-winit-glow-renderer-viewports/Cargo.toml
Normal file
@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "imgui-winit-glow-renderer-viewports"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
imgui = { version="0.10.0", path="../imgui", features=["docking"] }
|
||||
|
||||
glow = "0.11.2"
|
||||
glutin = "0.30.3"
|
||||
raw-window-handle = "0.5.0"
|
||||
winit = "0.27.5"
|
||||
thiserror = "1.0.38"
|
||||
glutin-winit = "0.2.1"
|
||||
162
imgui-winit-glow-renderer-viewports/examples/viewports_basic.rs
Normal file
162
imgui-winit-glow-renderer-viewports/examples/viewports_basic.rs
Normal file
@ -0,0 +1,162 @@
|
||||
use std::{ffi::CString, num::NonZeroU32, time::Instant};
|
||||
|
||||
use glow::{Context, HasContext};
|
||||
use glutin::{
|
||||
config::ConfigTemplateBuilder,
|
||||
context::ContextAttributesBuilder,
|
||||
display::GetGlDisplay,
|
||||
prelude::{
|
||||
GlDisplay, NotCurrentGlContextSurfaceAccessor, PossiblyCurrentContextGlSurfaceAccessor,
|
||||
},
|
||||
surface::{GlSurface, SurfaceAttributesBuilder, WindowSurface},
|
||||
};
|
||||
use glutin_winit::DisplayBuilder;
|
||||
use imgui::ConfigFlags;
|
||||
use imgui_winit_glow_renderer_viewports::Renderer;
|
||||
use raw_window_handle::HasRawWindowHandle;
|
||||
use winit::{dpi::LogicalSize, event::WindowEvent, event_loop::EventLoop, window::WindowBuilder};
|
||||
|
||||
fn main() {
|
||||
let event_loop = EventLoop::new();
|
||||
|
||||
let window_builder = WindowBuilder::new()
|
||||
.with_inner_size(LogicalSize::new(800.0, 600.0))
|
||||
.with_visible(true)
|
||||
.with_resizable(true)
|
||||
.with_title("Viewports example");
|
||||
|
||||
let template_builder = ConfigTemplateBuilder::new();
|
||||
let (window, gl_config) = DisplayBuilder::new()
|
||||
.with_window_builder(Some(window_builder))
|
||||
.build(&event_loop, template_builder, |mut configs| {
|
||||
configs.next().unwrap()
|
||||
})
|
||||
.expect("Failed to create main window");
|
||||
|
||||
let window = window.unwrap();
|
||||
|
||||
let context_attribs = ContextAttributesBuilder::new().build(Some(window.raw_window_handle()));
|
||||
let context = unsafe {
|
||||
gl_config
|
||||
.display()
|
||||
.create_context(&gl_config, &context_attribs)
|
||||
.expect("Failed to create main context")
|
||||
};
|
||||
|
||||
let size = window.inner_size();
|
||||
let surface_attribs = SurfaceAttributesBuilder::<WindowSurface>::new().build(
|
||||
window.raw_window_handle(),
|
||||
NonZeroU32::new(size.width).unwrap(),
|
||||
NonZeroU32::new(size.height).unwrap(),
|
||||
);
|
||||
let surface = unsafe {
|
||||
gl_config
|
||||
.display()
|
||||
.create_window_surface(&gl_config, &surface_attribs)
|
||||
.expect("Failed to create main surface")
|
||||
};
|
||||
|
||||
let context = context
|
||||
.make_current(&surface)
|
||||
.expect("Failed to make current");
|
||||
|
||||
let glow = unsafe {
|
||||
Context::from_loader_function(|name| {
|
||||
let name = CString::new(name).unwrap();
|
||||
context.display().get_proc_address(&name)
|
||||
})
|
||||
};
|
||||
|
||||
let mut imgui = imgui::Context::create();
|
||||
imgui
|
||||
.io_mut()
|
||||
.config_flags
|
||||
.insert(ConfigFlags::DOCKING_ENABLE);
|
||||
imgui
|
||||
.io_mut()
|
||||
.config_flags
|
||||
.insert(ConfigFlags::VIEWPORTS_ENABLE);
|
||||
imgui.set_ini_filename(None);
|
||||
|
||||
let mut renderer = Renderer::new(&mut imgui, &window, &glow).expect("Failed to init Renderer");
|
||||
|
||||
let mut last_frame = Instant::now();
|
||||
|
||||
event_loop.run(move |event, window_target, control_flow| {
|
||||
control_flow.set_poll();
|
||||
|
||||
renderer.handle_event(&mut imgui, &window, &event);
|
||||
|
||||
match event {
|
||||
winit::event::Event::NewEvents(_) => {
|
||||
let now = Instant::now();
|
||||
imgui.io_mut().update_delta_time(now - last_frame);
|
||||
last_frame = now;
|
||||
}
|
||||
winit::event::Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::CloseRequested,
|
||||
} if window_id == window.id() => {
|
||||
control_flow.set_exit();
|
||||
}
|
||||
winit::event::Event::WindowEvent {
|
||||
window_id,
|
||||
event: WindowEvent::Resized(new_size),
|
||||
} if window_id == window.id() => {
|
||||
surface.resize(
|
||||
&context,
|
||||
NonZeroU32::new(new_size.width).unwrap(),
|
||||
NonZeroU32::new(new_size.height).unwrap(),
|
||||
);
|
||||
}
|
||||
winit::event::Event::MainEventsCleared => {
|
||||
window.request_redraw();
|
||||
}
|
||||
winit::event::Event::RedrawRequested(_) => {
|
||||
let ui = imgui.frame();
|
||||
|
||||
ui.dockspace_over_main_viewport();
|
||||
|
||||
ui.show_demo_window(&mut true);
|
||||
ui.window("Style Editor").build(|| {
|
||||
ui.show_default_style_editor();
|
||||
});
|
||||
|
||||
ui.end_frame_early();
|
||||
|
||||
renderer.prepare_render(&mut imgui, &window);
|
||||
|
||||
imgui.update_platform_windows();
|
||||
renderer
|
||||
.update_viewports(&mut imgui, window_target, &glow)
|
||||
.expect("Failed to update viewports");
|
||||
|
||||
let draw_data = imgui.render();
|
||||
|
||||
if let Err(e) = context.make_current(&surface) {
|
||||
// For some reason make_current randomly throws errors on windows.
|
||||
// Until the reason for this is found, we just print it out instead of panicing.
|
||||
eprintln!("Failed to make current: {e}");
|
||||
}
|
||||
|
||||
unsafe {
|
||||
glow.disable(glow::SCISSOR_TEST);
|
||||
glow.clear(glow::COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
renderer
|
||||
.render(&window, &glow, draw_data)
|
||||
.expect("Failed to render main viewport");
|
||||
|
||||
surface
|
||||
.swap_buffers(&context)
|
||||
.expect("Failed to swap buffers");
|
||||
|
||||
renderer
|
||||
.render_viewports(&glow, &mut imgui)
|
||||
.expect("Failed to render viewports");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
}
|
||||
13
imgui-winit-glow-renderer-viewports/src/fragment_shader.glsl
Normal file
13
imgui-winit-glow-renderer-viewports/src/fragment_shader.glsl
Normal file
@ -0,0 +1,13 @@
|
||||
#version 330
|
||||
|
||||
in vec2 v2f_UV;
|
||||
in vec4 v2f_Color;
|
||||
|
||||
uniform sampler2D u_FontTexture;
|
||||
|
||||
layout(location = 0) out vec4 out_Color;
|
||||
|
||||
void main() {
|
||||
vec4 tex = texture(u_FontTexture, v2f_UV);
|
||||
out_Color = v2f_Color * tex;
|
||||
}
|
||||
1143
imgui-winit-glow-renderer-viewports/src/lib.rs
Normal file
1143
imgui-winit-glow-renderer-viewports/src/lib.rs
Normal file
File diff suppressed because it is too large
Load Diff
16
imgui-winit-glow-renderer-viewports/src/vertex_shader.glsl
Normal file
16
imgui-winit-glow-renderer-viewports/src/vertex_shader.glsl
Normal file
@ -0,0 +1,16 @@
|
||||
#version 330
|
||||
|
||||
layout(location = 0) in vec2 in_Position;
|
||||
layout(location = 1) in vec2 in_UV;
|
||||
layout(location = 2) in vec4 in_Color;
|
||||
|
||||
uniform mat4 u_Matrix;
|
||||
|
||||
out vec2 v2f_UV;
|
||||
out vec4 v2f_Color;
|
||||
|
||||
void main() {
|
||||
gl_Position = u_Matrix * vec4(in_Position, 0.0, 1.0);
|
||||
v2f_UV = in_UV;
|
||||
v2f_Color = in_Color;
|
||||
}
|
||||
@ -60,6 +60,13 @@ pub struct Context {
|
||||
// imgui a mutable pointer to it.
|
||||
clipboard_ctx: Box<UnsafeCell<ClipboardContext>>,
|
||||
|
||||
// we need to store an owning reference to our PlatformViewportBackend and PlatformRendererBackend,
|
||||
// so that it is ensured that PlatformIo::backend_platform_user_data and PlatformIo::backend_renderer_user_data remain valid
|
||||
#[cfg(feature = "docking")]
|
||||
platform_viewport_ctx: Box<UnsafeCell<crate::PlatformViewportContext>>,
|
||||
#[cfg(feature = "docking")]
|
||||
renderer_viewport_ctx: Box<UnsafeCell<crate::RendererViewportContext>>,
|
||||
|
||||
ui: Ui,
|
||||
}
|
||||
|
||||
@ -239,6 +246,14 @@ impl Context {
|
||||
platform_name: None,
|
||||
renderer_name: None,
|
||||
clipboard_ctx: Box::new(ClipboardContext::dummy().into()),
|
||||
#[cfg(feature = "docking")]
|
||||
platform_viewport_ctx: Box::new(UnsafeCell::new(
|
||||
crate::PlatformViewportContext::dummy(),
|
||||
)),
|
||||
#[cfg(feature = "docking")]
|
||||
renderer_viewport_ctx: Box::new(UnsafeCell::new(
|
||||
crate::RendererViewportContext::dummy(),
|
||||
)),
|
||||
ui: Ui {
|
||||
buffer: UnsafeCell::new(crate::string::UiBuffer::new(1024)),
|
||||
},
|
||||
@ -328,6 +343,14 @@ impl SuspendedContext {
|
||||
platform_name: None,
|
||||
renderer_name: None,
|
||||
clipboard_ctx: Box::new(ClipboardContext::dummy().into()),
|
||||
#[cfg(feature = "docking")]
|
||||
platform_viewport_ctx: Box::new(UnsafeCell::new(
|
||||
crate::PlatformViewportContext::dummy(),
|
||||
)),
|
||||
#[cfg(feature = "docking")]
|
||||
renderer_viewport_ctx: Box::new(UnsafeCell::new(
|
||||
crate::RendererViewportContext::dummy(),
|
||||
)),
|
||||
ui: Ui {
|
||||
buffer: UnsafeCell::new(crate::string::UiBuffer::new(1024)),
|
||||
},
|
||||
@ -568,3 +591,151 @@ impl Context {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
impl Context {
|
||||
/// Returns an immutable reference to the Context's [`PlatformIo`](crate::PlatformIo) object.
|
||||
pub fn platform_io(&self) -> &crate::PlatformIo {
|
||||
unsafe {
|
||||
// safe because PlatformIo is a transparent wrapper around sys::ImGuiPlatformIO
|
||||
// and &self ensures we have shared ownership of PlatformIo.
|
||||
&*(sys::igGetPlatformIO() as *const crate::PlatformIo)
|
||||
}
|
||||
}
|
||||
/// Returns a mutable reference to the Context's [`PlatformIo`](crate::PlatformIo) object.
|
||||
pub fn platform_io_mut(&mut self) -> &mut crate::PlatformIo {
|
||||
unsafe {
|
||||
// safe because PlatformIo is a transparent wrapper around sys::ImGuiPlatformIO
|
||||
// and &mut self ensures exclusive ownership of PlatformIo.
|
||||
&mut *(sys::igGetPlatformIO() as *mut crate::PlatformIo)
|
||||
}
|
||||
}
|
||||
/// Returns an immutable reference to the main [`Viewport`](crate::Viewport)
|
||||
pub fn main_viewport(&self) -> &crate::Viewport {
|
||||
unsafe {
|
||||
// safe because Viewport is a transparent wrapper around sys::ImGuiViewport
|
||||
// and &self ensures we have shared ownership.
|
||||
&*(sys::igGetMainViewport() as *mut crate::Viewport)
|
||||
}
|
||||
}
|
||||
/// Returns a mutable reference to the main [`Viewport`](crate::Viewport)
|
||||
pub fn main_viewport_mut(&mut self) -> &mut crate::Viewport {
|
||||
unsafe {
|
||||
// safe because Viewport is a transparent wrapper around sys::ImGuiViewport
|
||||
// and &mut self ensures we have exclusive ownership.
|
||||
&mut *(sys::igGetMainViewport() as *mut crate::Viewport)
|
||||
}
|
||||
}
|
||||
/// Tries to find and return a Viewport identified by `id`.
|
||||
///
|
||||
/// # Returns
|
||||
/// A [`Viewport`](crate::Viewport) with the given `id`
|
||||
/// or `None` if no [`Viewport`](crate::Viewport) exists.
|
||||
pub fn viewport_by_id(&self, id: crate::Id) -> Option<&crate::Viewport> {
|
||||
unsafe {
|
||||
// safe because Viewport is a transparent wrapper around sys::ImGuiViewport
|
||||
// and &self ensures shared ownership.
|
||||
(sys::igFindViewportByID(id.0) as *const crate::Viewport).as_ref()
|
||||
}
|
||||
}
|
||||
/// Tries to find and return a Viewport identified by `id`.
|
||||
///
|
||||
/// # Returns
|
||||
/// A [`Viewport`](crate::Viewport) with the given `id`
|
||||
/// or `None` if no [`Viewport`](crate::Viewport) exists.
|
||||
pub fn viewport_by_id_mut(&mut self, id: crate::Id) -> Option<&mut crate::Viewport> {
|
||||
unsafe {
|
||||
// safe because Viewport is a transparent wrapper around sys::ImGuiViewport
|
||||
// and &mut self ensures exclusive ownership.
|
||||
(sys::igFindViewportByID(id.0) as *mut crate::Viewport).as_mut()
|
||||
}
|
||||
}
|
||||
/// Returns an iterator containing every [`Viewport`](crate::Viewport) that currently exists.
|
||||
pub fn viewports(&self) -> impl Iterator<Item = &crate::Viewport> {
|
||||
let slice = self.platform_io().viewports.as_slice();
|
||||
// safe because &self ensures shared ownership
|
||||
unsafe { slice.iter().map(|ptr| &**ptr) }
|
||||
}
|
||||
/// Returns an iterator containing every [`Viewport`](crate::Viewport) that currently exists.
|
||||
pub fn viewports_mut(&mut self) -> impl Iterator<Item = &mut crate::Viewport> {
|
||||
let slice = self.platform_io_mut().viewports.as_slice();
|
||||
// safe because &mut self ensures exclusive ownership
|
||||
unsafe { slice.iter().map(|ptr| &mut **ptr) }
|
||||
}
|
||||
|
||||
/// Installs a [`PlatformViewportBackend`](crate::PlatformViewportBackend) that is used to
|
||||
/// create platform windows on demand if a window is dragged outside of the main viewport.
|
||||
pub fn set_platform_backend<T: crate::PlatformViewportBackend>(&mut self, backend: T) {
|
||||
let ctx = Box::new(UnsafeCell::new(crate::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);
|
||||
// since pio.platform_get_window_pos is not a C compatible function, cimgui provides an extra function to set it.
|
||||
unsafe {
|
||||
crate::platform_io::ImGuiPlatformIO_Set_Platform_GetWindowPos(
|
||||
pio,
|
||||
crate::platform_io::platform_get_window_pos,
|
||||
);
|
||||
}
|
||||
pio.platform_set_window_size = Some(crate::platform_io::platform_set_window_size);
|
||||
// since pio.platform_get_window_size is not a C compatible function, cimgui provides an extra function to set it.
|
||||
unsafe {
|
||||
crate::platform_io::ImGuiPlatformIO_Set_Platform_GetWindowSize(
|
||||
pio,
|
||||
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;
|
||||
}
|
||||
/// Installs a [`RendererViewportBackend`](crate::RendererViewportBackend) that is used to
|
||||
/// render extra viewports created by ImGui.
|
||||
pub fn set_renderer_backend<T: crate::RendererViewportBackend>(&mut self, backend: T) {
|
||||
let ctx = Box::new(UnsafeCell::new(crate::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;
|
||||
}
|
||||
/// Updates the extra Viewports created by ImGui.
|
||||
/// Has to be called every frame if Viewports are enabled.
|
||||
pub fn update_platform_windows(&mut self) {
|
||||
unsafe {
|
||||
sys::igUpdatePlatformWindows();
|
||||
}
|
||||
}
|
||||
/// Basically just calls the [`PlatformViewportBackend`](crate::PlatformViewportBackend) and [`RendererViewportBackend`](crate::RendererViewportBackend)
|
||||
/// functions. If you render your extra viewports manually this function is not needed at all.
|
||||
pub fn render_platform_windows_default(&mut self) {
|
||||
unsafe {
|
||||
sys::igRenderPlatformWindowsDefault(std::ptr::null_mut(), std::ptr::null_mut());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
15
imgui/src/dock_space.rs
Normal file
15
imgui/src/dock_space.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use std::ptr::null;
|
||||
|
||||
use crate::Ui;
|
||||
|
||||
impl Ui {
|
||||
pub fn dockspace_over_main_viewport(&self) {
|
||||
unsafe {
|
||||
sys::igDockSpaceOverViewport(
|
||||
sys::igGetMainViewport(),
|
||||
sys::ImGuiDockNodeFlags_PassthruCentralNode as i32,
|
||||
null(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
//! Internal raw utilities (don't use unless you know what you're doing!)
|
||||
|
||||
use std::slice;
|
||||
use std::{mem::size_of, slice};
|
||||
|
||||
/// A generic version of the raw imgui-sys ImVector struct types
|
||||
#[repr(C)]
|
||||
@ -15,6 +15,24 @@ impl<T> ImVector<T> {
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
unsafe { slice::from_raw_parts(self.data, self.size as usize) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice_mut(&mut self) -> &mut [T] {
|
||||
unsafe { slice::from_raw_parts_mut(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]
|
||||
|
||||
@ -55,6 +55,29 @@ bitflags! {
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
const DOCKING_ENABLE = sys::ImGuiConfigFlags_DockingEnable;
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
const VIEWPORTS_ENABLE = sys::ImGuiConfigFlags_ViewportsEnable;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
bitflags! {
|
||||
#[repr(transparent)]
|
||||
pub struct ViewportFlags: u32 {
|
||||
const IS_PLATFORM_WINDOW = sys::ImGuiViewportFlags_IsPlatformWindow;
|
||||
const IS_PLATFORM_MONITOR = sys::ImGuiViewportFlags_IsPlatformMonitor;
|
||||
const OWNED_BY_APP = sys::ImGuiViewportFlags_OwnedByApp;
|
||||
const NO_DECORATION = sys::ImGuiViewportFlags_NoDecoration;
|
||||
const NO_TASK_BAR_ICON = sys::ImGuiViewportFlags_NoTaskBarIcon;
|
||||
const NO_FOCUS_ON_APPEARING = sys::ImGuiViewportFlags_NoFocusOnAppearing;
|
||||
const NO_FOCUS_ON_CLICK = sys::ImGuiViewportFlags_NoFocusOnClick;
|
||||
const NO_INPUTS = sys::ImGuiViewportFlags_NoInputs;
|
||||
const NO_RENDERER_CLEAR = sys::ImGuiViewportFlags_NoRendererClear;
|
||||
const TOP_MOST = sys::ImGuiViewportFlags_TopMost;
|
||||
const MINIMIZED = sys::ImGuiViewportFlags_Minimized;
|
||||
const NO_AUTO_MERGE = sys::ImGuiViewportFlags_NoAutoMerge;
|
||||
const CAN_HOST_OTHER_WINDOWS = sys::ImGuiViewportFlags_CanHostOtherWindows;
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,6 +97,13 @@ bitflags! {
|
||||
///
|
||||
/// This enables output of large meshes (64K+ vertices) while still using 16-bits indices.
|
||||
const RENDERER_HAS_VTX_OFFSET = sys::ImGuiBackendFlags_RendererHasVtxOffset;
|
||||
|
||||
#[cfg(feature = "docking")]
|
||||
/// Set if the platform backend supports viewports.
|
||||
const PLATFORM_HAS_VIEWPORTS = sys::ImGuiBackendFlags_PlatformHasViewports;
|
||||
#[cfg(feature = "docking")]
|
||||
/// Set if the renderer backend supports viewports.
|
||||
const RENDERER_HAS_VIEWPORTS = sys::ImGuiBackendFlags_RendererHasViewports;
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,8 +264,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>,
|
||||
|
||||
@ -10,6 +10,8 @@ use std::os::raw::c_char;
|
||||
pub use self::clipboard::*;
|
||||
pub use self::color::ImColor32;
|
||||
pub use self::context::*;
|
||||
#[cfg(feature = "docking")]
|
||||
pub use self::dock_space::*;
|
||||
pub use self::drag_drop::{DragDropFlags, DragDropSource, DragDropTarget};
|
||||
pub use self::draw_list::{ChannelsSplit, DrawListMut};
|
||||
pub use self::fonts::atlas::*;
|
||||
@ -22,6 +24,8 @@ pub use self::input_widget::*;
|
||||
pub use self::io::*;
|
||||
pub use self::layout::*;
|
||||
pub use self::list_clipper::ListClipper;
|
||||
#[cfg(feature = "docking")]
|
||||
pub use self::platform_io::*;
|
||||
pub use self::plothistogram::PlotHistogram;
|
||||
pub use self::plotlines::PlotLines;
|
||||
pub use self::popups::*;
|
||||
@ -62,6 +66,8 @@ mod clipboard;
|
||||
pub mod color;
|
||||
mod columns;
|
||||
mod context;
|
||||
#[cfg(feature = "docking")]
|
||||
mod dock_space;
|
||||
pub mod drag_drop;
|
||||
pub mod draw_list;
|
||||
mod fonts;
|
||||
@ -72,6 +78,8 @@ mod io;
|
||||
mod layout;
|
||||
mod list_clipper;
|
||||
mod math;
|
||||
#[cfg(feature = "docking")]
|
||||
mod platform_io;
|
||||
mod plothistogram;
|
||||
mod plotlines;
|
||||
mod popups;
|
||||
@ -284,7 +292,8 @@ impl Ui {
|
||||
/// Previously, in v0.7, this was erroneously constructed with `From`
|
||||
/// implementations. Now, however, it is made from the `Ui` object
|
||||
/// directly, with a few deprecated helper methods here.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, Hash)]
|
||||
pub struct Id(pub(crate) u32);
|
||||
|
||||
impl Id {
|
||||
|
||||
558
imgui/src/platform_io.rs
Normal file
558
imgui/src/platform_io.rs
Normal file
@ -0,0 +1,558 @@
|
||||
use std::{
|
||||
ffi::{c_void, CStr},
|
||||
os::raw::{c_char, c_int},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
internal::{ImVector, RawCast},
|
||||
Io, ViewportFlags,
|
||||
};
|
||||
|
||||
/// Holds the information needed to enable multiple viewports.
|
||||
#[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)>,
|
||||
|
||||
/// Holds information about the available monitors.
|
||||
/// Should be initialized and updated by the [`PlatformViewportBackend`].
|
||||
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_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);
|
||||
}
|
||||
|
||||
/// Trait holding functions needed when the platform integration supports viewports.
|
||||
///
|
||||
/// Register it via [`Context::set_platform_backend()`](crate::context::Context::set_platform_backend())
|
||||
pub trait PlatformViewportBackend: 'static {
|
||||
/// Called by imgui when a new [`Viewport`] is created.
|
||||
///
|
||||
/// # Notes
|
||||
/// This function should initiate the creation of a platform window.
|
||||
/// The window should be invisible.
|
||||
fn create_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui when a [`Viewport`] is about to be destroyed.
|
||||
///
|
||||
/// # Notes
|
||||
/// This function should initiate the destruction of the platform window.
|
||||
fn destroy_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui to make a [`Viewport`] visible.
|
||||
fn show_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui to reposition a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// `pos` specifies the position of the windows content area (excluding title bar etc.)
|
||||
fn set_window_pos(&mut self, viewport: &mut Viewport, pos: [f32; 2]);
|
||||
/// Called by imgui to get the position of a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// You should return the position of the window's content area (excluding title bar etc.)
|
||||
fn get_window_pos(&mut self, viewport: &mut Viewport) -> [f32; 2];
|
||||
/// Called by imgui to set the size of a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// `size` specifies the size of the window's content area (excluding title bar etc.)
|
||||
fn set_window_size(&mut self, viewport: &mut Viewport, size: [f32; 2]);
|
||||
/// Called by imgui to get the size of a [`Viewport`].
|
||||
///
|
||||
/// # Notes
|
||||
/// you should return the size of the window's content area (excluding title bar etc.)
|
||||
fn get_window_size(&mut self, viewport: &mut Viewport) -> [f32; 2];
|
||||
/// Called by imgui to make a [`Viewport`] steal the focus.
|
||||
fn set_window_focus(&mut self, viewport: &mut Viewport);
|
||||
/// Called by imgui to query whether a [`Viewport`] is in focus.
|
||||
fn get_window_focus(&mut self, viewport: &mut Viewport) -> bool;
|
||||
/// Called by imgui to query whether a [`Viewport`] is minimized.
|
||||
fn get_window_minimized(&mut self, viewport: &mut Viewport) -> bool;
|
||||
/// Called by imgui to set a [`Viewport`] title.
|
||||
fn set_window_title(&mut self, viewport: &mut Viewport, title: &str);
|
||||
/// Called by imgui to set the opacity of an entire [`Viewport`].
|
||||
///
|
||||
/// If your backend does not support opactiy, it is safe to just do nothing in this function.
|
||||
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;
|
||||
}
|
||||
|
||||
/// Used to get the current Contexts [`PlatformViewportContext`].
|
||||
fn get_platform_ctx() -> &'static mut PlatformViewportContext {
|
||||
unsafe {
|
||||
// should be safe as it is impossible to call any imgui function on a non-active context.
|
||||
&mut *((*(sys::igGetIO() as *const Io)).backend_platform_user_data
|
||||
as *mut PlatformViewportContext)
|
||||
}
|
||||
}
|
||||
|
||||
/// Used to get the current Contexts [`RendererViewportContext`].
|
||||
fn get_renderer_ctx() -> &'static mut RendererViewportContext {
|
||||
unsafe {
|
||||
// should be safe as it is impossible to call any imgui function on a non-active context.
|
||||
&mut *((*(sys::igGetIO() as *const Io)).backend_renderer_user_data
|
||||
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,
|
||||
out_pos: *mut sys::ImVec2,
|
||||
) {
|
||||
let ctx = get_platform_ctx();
|
||||
let pos = ctx.backend.get_window_pos(unsafe { &mut *viewport });
|
||||
unsafe {
|
||||
*out_pos = 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,
|
||||
out_size: *mut sys::ImVec2,
|
||||
) {
|
||||
let ctx = get_platform_ctx();
|
||||
let size = ctx.backend.get_window_size(unsafe { &mut *viewport });
|
||||
unsafe {
|
||||
*out_size = 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
|
||||
})
|
||||
}
|
||||
|
||||
/// The default [`PlatformViewportBackend`], does nothing.
|
||||
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!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Just holds a [`PlatformViewportBackend`].
|
||||
pub(crate) struct PlatformViewportContext {
|
||||
pub(crate) backend: Box<dyn PlatformViewportBackend>,
|
||||
}
|
||||
|
||||
impl PlatformViewportContext {
|
||||
pub(crate) fn dummy() -> Self {
|
||||
Self {
|
||||
backend: Box::new(DummyPlatformViewportBackend {}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait that holds optional functions for a rendering backend to support multiple viewports.
|
||||
///
|
||||
/// It is completely fine to not use this Backend at all, as all functions are optional.
|
||||
pub trait RendererViewportBackend: 'static {
|
||||
/// Called after [`PlatformViewportBackend::create_window()`].
|
||||
fn create_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called before [`PlatformViewportBackend::destroy_window()`].
|
||||
fn destroy_window(&mut self, viewport: &mut Viewport);
|
||||
/// Called after [`PlatformViewportBackend::set_window_size()`].
|
||||
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 });
|
||||
}
|
||||
|
||||
/// The default [`RendererViewportBackend`], does nothing.
|
||||
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!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Just holds a [`RendererViewportBackend`].
|
||||
pub(crate) struct RendererViewportContext {
|
||||
pub(crate) backend: Box<dyn RendererViewportBackend>,
|
||||
}
|
||||
|
||||
impl RendererViewportContext {
|
||||
pub(crate) fn dummy() -> Self {
|
||||
Self {
|
||||
backend: Box::new(DummyRendererViewportBackend {}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes an ImGui Viewport.
|
||||
#[repr(C)]
|
||||
pub struct Viewport {
|
||||
/// The unique ID of this Viewport.
|
||||
pub id: crate::Id,
|
||||
/// Flags that describe how the Viewport should behave.
|
||||
pub flags: ViewportFlags,
|
||||
pub pos: [f32; 2],
|
||||
pub size: [f32; 2],
|
||||
pub work_pos: [f32; 2],
|
||||
pub work_size: [f32; 2],
|
||||
pub 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_window_created: bool,
|
||||
pub platform_request_move: bool,
|
||||
pub platform_request_resize: bool,
|
||||
pub platform_request_close: bool,
|
||||
}
|
||||
|
||||
impl Viewport {
|
||||
/// Returns the draw data of the respective Viewport.
|
||||
pub fn draw_data(&self) -> &crate::DrawData {
|
||||
unsafe { &*self.draw_data }
|
||||
}
|
||||
}
|
||||
|
||||
#[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_window_created, PlatformWindowCreated);
|
||||
assert_field_offset!(platform_request_move, PlatformRequestMove);
|
||||
assert_field_offset!(platform_request_resize, PlatformRequestResize);
|
||||
assert_field_offset!(platform_request_close, PlatformRequestClose);
|
||||
}
|
||||
|
||||
/// Describes a monitor that can be used by ImGui.
|
||||
#[repr(C)]
|
||||
pub struct PlatformMonitor {
|
||||
/// Position of the monitor on the virtual desktop.
|
||||
pub main_pos: [f32; 2],
|
||||
/// Size of the monitor on the virtual desktop.
|
||||
pub main_size: [f32; 2],
|
||||
/// Working position of the monitor, should exclude task bar etc.
|
||||
///
|
||||
/// Set to `main_pos` if not known.
|
||||
pub work_pos: [f32; 2],
|
||||
/// Working size of the monitor, should exclude task bar etc.
|
||||
///
|
||||
/// Set to `work_size` if not known.
|
||||
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);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub(crate) fn ImGuiPlatformIO_Set_Platform_GetWindowPos(
|
||||
pio: *mut PlatformIo,
|
||||
func: extern "C" fn(*mut Viewport, *mut sys::ImVec2),
|
||||
);
|
||||
pub(crate) fn ImGuiPlatformIO_Set_Platform_GetWindowSize(
|
||||
pio: *mut PlatformIo,
|
||||
func: extern "C" fn(*mut Viewport, *mut sys::ImVec2),
|
||||
);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user