initial imgui implementation

This commit is contained in:
Ben Wallis 2020-07-25 18:08:35 +01:00
parent d25508e2df
commit 4e4725d1ac
8 changed files with 162 additions and 12 deletions

54
Cargo.lock generated
View File

@ -71,9 +71,9 @@ checksum = "b8052e2d8aabbb8d556d6abbcce2a22b9590996c5f849b9c7ce4544a2e3b984e"
[[package]]
name = "ansi_term"
version = "0.11.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi 0.3.8",
]
@ -2053,6 +2053,49 @@ dependencies = [
"png",
]
[[package]]
name = "imgui"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fdb2bcc7e498e78137ce28705ae836d69e36ee2eac89d0d926cfabfcf550570"
dependencies = [
"bitflags",
"gfx",
"imgui-sys",
"lazy_static",
"parking_lot 0.10.2",
]
[[package]]
name = "imgui-gfx-renderer"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1865f465732ee450bcc8d1c45576b3099955caec163cee82318da763eb22df94"
dependencies = [
"gfx",
"imgui",
"winapi 0.3.8",
]
[[package]]
name = "imgui-sys"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72be9671d64dd0ed26bb708cd10060a431262ac90ae70cf7c5912feefe6849da"
dependencies = [
"cc",
]
[[package]]
name = "imgui-winit-support"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98171c35263e3eb0dfb66cb876e3efdb788d777c1b613c7d2592303d1276bb5"
dependencies = [
"imgui",
"winit",
]
[[package]]
name = "indexmap"
version = "1.4.0"
@ -4319,9 +4362,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.2.6"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04a11b459109e38ff6e1b580bafef4142a11d44889f5d07424cbce2fd2a2a119"
checksum = "e4f5dd7095c2481b7b3cbed71c8de53085fb3542bc3c2b4c73cba43e8f11c7ba"
dependencies = [
"ansi_term",
"chrono",
@ -4636,6 +4679,9 @@ dependencies = [
"guillotiere",
"hashbrown",
"image",
"imgui",
"imgui-gfx-renderer",
"imgui-winit-support",
"msgbox",
"num 0.2.1",
"old_school_gfx_glutin_ext",

View File

@ -13,4 +13,4 @@ server = { package = "veloren-server", path = "../server", default-features = fa
common = { package = "veloren-common", path = "../common" }
tracing = { version = "0.1", default-features = false }
tracing-subscriber = { version = "0.2.3", default-features = false, features = ["env-filter", "fmt", "chrono", "ansi", "smallvec"] }
tracing-subscriber = { version = "0.2.9", default-features = false, features = ["env-filter", "fmt", "chrono", "ansi", "smallvec"] }

View File

@ -18,7 +18,10 @@ fn main() {
.add_directive(LevelFilter::INFO.into());
for s in env.split(',').into_iter() {
match s.parse() {
Ok(d) => filter = filter.add_directive(d),
Ok(d) => {
println!("Adding filter directive: {}", d);
filter = filter.add_directive(d);
},
Err(err) => println!("WARN ignoring log directive: `{}`: {}", s, err),
};
}

View File

@ -32,6 +32,10 @@ conrod_core = { git = "https://gitlab.com/veloren/conrod.git" }
conrod_winit = { git = "https://gitlab.com/veloren/conrod.git" }
euc = { git = "https://github.com/zesterer/euc.git" }
imgui = "0.4.0"
imgui-gfx-renderer = "0.4.0"
imgui-winit-support = "0.4.0"
# ECS
specs = { git = "https://github.com/amethyst/specs.git", rev = "7a2e348ab2223818bad487695c66c43db88050a5" }
specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", branch = "specs-git" }

View File

@ -3,6 +3,9 @@
#![feature(bool_to_option)]
#![recursion_limit = "2048"]
#[macro_use]
extern crate imgui;
use veloren_voxygen::{
audio::{self, AudioFrontend},
i18n::{self, i18n_asset_key, VoxygenLocalization},

View File

@ -18,6 +18,10 @@ use gfx::{
use glsl_include::Context as IncludeContext;
use tracing::error;
use vek::*;
use imgui::{DrawData, Context, im_str, Window, Condition, ConfigFlags};
use imgui_winit_support::WinitPlatform;
use winit::event::Event;
use imgui::sys::ImGuiConfigFlags_NoMouseCursorChange;
/// Represents the format of the pre-processed color target.
pub type TgtColorFmt = gfx::format::Srgba8;
@ -52,10 +56,10 @@ pub type TgtColorRes = gfx::handle::ShaderResourceView<
/// kinds of models to the screen.
pub struct Renderer {
device: gfx_backend::Device,
encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
factory: gfx_backend::Factory,
pub encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
pub factory: gfx_backend::Factory,
win_color_view: WinColorView,
pub win_color_view: WinColorView,
win_depth_view: WinDepthView,
tgt_color_view: TgtColorView,
@ -81,6 +85,9 @@ pub struct Renderer {
aa_mode: AaMode,
cloud_mode: CloudMode,
fluid_mode: FluidMode,
pub imgui: Context,
pub imgui_platform: WinitPlatform,
pub imgui_renderer: imgui_gfx_renderer::Renderer<gfx::format::Srgba8, gfx_device_gl::Resources>
}
impl Renderer {
@ -94,6 +101,9 @@ impl Renderer {
aa_mode: AaMode,
cloud_mode: CloudMode,
fluid_mode: FluidMode,
imgui: Context,
imgui_platform: WinitPlatform,
imgui_renderer: imgui_gfx_renderer::Renderer<gfx::format::Srgba8, gfx_device_gl::Resources>
) -> Result<Self, RenderError> {
let mut shader_reload_indicator = ReloadIndicator::new();
@ -157,9 +167,43 @@ impl Renderer {
aa_mode,
cloud_mode,
fluid_mode,
imgui,
imgui_platform,
imgui_renderer
})
}
pub fn render_imgui(&mut self, window: &winit::window::Window) {
self.imgui_platform
.prepare_frame(self.imgui.io_mut(), window)
.expect("Failed to start frame");
self.imgui.io_mut().config_flags |= ConfigFlags::NO_MOUSE_CURSOR_CHANGE;
let ui = self.imgui.frame();
Window::new(im_str!("Test"))
.size([1000.0, 300.0], Condition::FirstUseEver)
.build(&ui, || {
ui.text(im_str!("Hello world!"));
ui.text(im_str!("こんにちは世界!"));
ui.text(im_str!("This...is...imgui-rs!"));
ui.separator();
let mouse_pos = ui.io().mouse_pos;
ui.text(format!(
"Mouse Position: ({:.1},{:.1})",
mouse_pos[0], mouse_pos[1]
));
});
self.imgui_platform.prepare_render(&ui, &window);
let draw_data = ui.render();
self.imgui_renderer.render(&mut self.factory, &mut self.encoder, &mut self.win_color_view, draw_data)
.expect("imgui rendering failed");
}
pub fn handle_imgui_events(&mut self, window: &winit::window::Window, event: &Event<()>) {
self.imgui_platform.handle_event(self.imgui.io_mut(), window, event);
}
/// Get references to the internal render target views that get rendered to
/// before post-processing.
#[allow(dead_code)]

View File

@ -26,6 +26,8 @@ pub fn run(mut global_state: GlobalState, event_loop: EventLoop) {
// Continously run loop since we handle sleeping
*control_flow = winit::event_loop::ControlFlow::Poll;
global_state.window.handle_imgui_events(&event);
// Get events for the ui.
if let Some(event) = ui::Event::try_from(&event, global_state.window.window()) {
global_state.window.send_event(Event::Ui(event));
@ -138,8 +140,13 @@ fn handle_main_events_cleared(
if let Some(last) = states.last_mut() {
global_state.window.renderer_mut().clear();
// Render the game
last.render(global_state.window.renderer_mut(), &global_state.settings);
// Finish the frame.
// Render imgui on top
global_state.window.render_imgui();
global_state.window.renderer_mut().flush();
global_state
.window

View File

@ -12,6 +12,9 @@ use serde_derive::{Deserialize, Serialize};
use std::fmt;
use tracing::{error, info, warn};
use vek::*;
use imgui_winit_support::{WinitPlatform, HiDpiMode};
use imgui::{Context, FontSource, FontConfig, FontGlyphRanges};
use imgui_gfx_renderer::Shaders;
/// Represents a key that the game recognises after input mapping.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
@ -490,7 +493,7 @@ pub struct Window {
message_receiver: channel::Receiver<String>,
// Used for screenshots & fullscreen toggle to deduplicate/postpone to after event handler
take_screenshot: bool,
toggle_fullscreen: bool,
toggle_fullscreen: bool
}
impl Window {
@ -512,7 +515,7 @@ impl Window {
false,
);
let (window, device, factory, win_color_view, win_depth_view) =
let (window, device, mut factory, win_color_view, win_depth_view) =
glutin::ContextBuilder::new()
.with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 2)))
.with_vsync(false)
@ -521,6 +524,35 @@ impl Window {
.map_err(|err| Error::BackendError(Box::new(err)))?
.init_gfx::<WinColorFmt, WinDepthFmt>();
let mut imgui = Context::create();
imgui.set_ini_filename(None);
let mut imgui_winit_platform = WinitPlatform::init(&mut imgui);
imgui_winit_platform.attach_window(imgui.io_mut(), window.window(), HiDpiMode::Rounded);
let hidpi_factor = imgui_winit_platform.hidpi_factor();
let font_size = (13.0 * hidpi_factor) as f32;
imgui.fonts().add_font(&[
FontSource::DefaultFontData {
config: Some(FontConfig {
size_pixels: font_size,
..FontConfig::default()
}),
},
FontSource::TtfData {
data: include_bytes!("resources/mplus-1p-regular.ttf"),
size_pixels: font_size,
config: Some(FontConfig {
rasterizer_multiply: 1.75,
glyph_ranges: FontGlyphRanges::japanese(),
..FontConfig::default()
}),
},
]);
imgui.io_mut().font_global_scale = (1.0 / hidpi_factor) as f32;
let imgui_renderer = imgui_gfx_renderer::Renderer::init(&mut imgui, &mut factory, Shaders::GlSl150)
.expect("Failed to initialize renderer");
let vendor = device.get_info().platform_name.vendor;
let renderer = device.get_info().platform_name.renderer;
let opengl_version = device.get_info().version;
@ -573,6 +605,9 @@ impl Window {
settings.graphics.aa_mode,
settings.graphics.cloud_mode,
settings.graphics.fluid_mode,
imgui,
imgui_winit_platform,
imgui_renderer
)?,
window,
cursor_grabbed: false,
@ -613,6 +648,10 @@ impl Window {
pub fn renderer_mut(&mut self) -> &mut Renderer { &mut self.renderer }
pub fn render_imgui(&mut self) {
self.renderer.render_imgui(&self.window.window());
}
pub fn resolve_deduplicated_events(&mut self, settings: &mut Settings) {
// Handle screenshots and toggling fullscreen
if self.take_screenshot {
@ -1094,6 +1133,10 @@ impl Window {
pub fn send_event(&mut self, event: Event) { self.events.push(event) }
pub fn handle_imgui_events(&mut self, event: &winit::event::Event<()>) {
self.renderer.handle_imgui_events(self.window.window(), event);
}
pub fn take_screenshot(&mut self, settings: &Settings) {
match self.renderer.create_screenshot() {
Ok(img) => {