Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a basic GUI to Hypermine powered by yakui #395

Merged
merged 3 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ server = { path = "../server" }
tracing = "0.1.10"
ash = { version = "0.38.0", default-features = false, features = ["loaded", "debug", "std"] }
lahar = { git = "https://github.com/Ralith/lahar", rev = "7963ae5750ea61fa0a894dbb73d3be0ac77255d2" }
yakui = { git = "https://github.com/SecondHalfGames/yakui", rev = "273a4a1020803066b84ac69a7646893419c31385" }
yakui-vulkan = { git = "https://github.com/SecondHalfGames/yakui", rev = "273a4a1020803066b84ac69a7646893419c31385" }
winit = "0.29.10"
ash-window = "0.13"
raw-window-handle = "0.6"
Expand Down
10 changes: 2 additions & 8 deletions client/shaders/fog.frag
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ void main() {
float view_length = length(view_pos);
// Convert to true hyperbolic distance, taking care to respect atanh's domain
float dist = view_length >= 1.0 ? INFINITY : atanh(view_length);
if (dot(scaled_view_pos.xy, scaled_view_pos.xy) < 0.0001) {
// Temporary code to add a cursor in the center of the window for placing/breaking blocks
// TODO: Replace with a UI element when UI exists
fog = vec4(0.0, 0.0, 0.0, 0.0);
} else {
// Exponential^k fog
fog = vec4(0.5, 0.65, 0.9, exp(-pow(dist * fog_density, 5)));
}
// Exponential^k fog
fog = vec4(0.5, 0.65, 0.9, exp(-pow(dist * fog_density, 5)));
}
6 changes: 5 additions & 1 deletion client/src/graphics/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,11 @@ impl Base {
.queue_create_infos(&[vk::DeviceQueueCreateInfo::default()
.queue_family_index(queue_family_index)
.queue_priorities(&[1.0])])
.enabled_extension_names(&device_exts),
.enabled_extension_names(&device_exts)
.push_next(
&mut vk::PhysicalDeviceVulkan12Features::default()
.descriptor_binding_partially_bound(true),
),
None,
)
.unwrap(),
Expand Down
2 changes: 1 addition & 1 deletion client/src/graphics/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl Core {
.application_version(0)
.engine_name(name)
.engine_version(0)
.api_version(vk::make_api_version(0, 1, 1, 0));
.api_version(vk::make_api_version(0, 1, 2, 0));
let mut instance_info = vk::InstanceCreateInfo::default()
.application_info(&app_info)
.enabled_extension_names(&exts);
Expand Down
35 changes: 35 additions & 0 deletions client/src/graphics/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ pub struct Draw {
/// Reusable storage for barriers that prevent races between buffer upload and read
buffer_barriers: Vec<vk::BufferMemoryBarrier<'static>>,

/// Yakui Vulkan context
yakui_vulkan: yakui_vulkan::YakuiVulkan,

/// Miscellany
character_model: Asset<GltfScene>,
}
Expand Down Expand Up @@ -181,6 +184,17 @@ impl Draw {

gfx.save_pipeline_cache();

let mut yakui_vulkan_options = yakui_vulkan::Options::default();
yakui_vulkan_options.render_pass = gfx.render_pass;
yakui_vulkan_options.subpass = 1;
let mut yakui_vulkan = yakui_vulkan::YakuiVulkan::new(
&yakui_vulkan::VulkanContext::new(device, gfx.queue, gfx.memory_properties),
yakui_vulkan_options,
);
for _ in 0..PIPELINE_DEPTH {
yakui_vulkan.transfers_submitted();
}

let character_model = loader.load(
"character model",
super::GlbFile {
Expand Down Expand Up @@ -208,6 +222,8 @@ impl Draw {
buffer_barriers: Vec::new(),
image_barriers: Vec::new(),

yakui_vulkan,

character_model,
}
}
Expand Down Expand Up @@ -235,6 +251,12 @@ impl Draw {
let device = &*self.gfx.device;
let state = &mut self.states[self.next_state];
device.wait_for_fences(&[state.fence], true, !0).unwrap();
self.yakui_vulkan
.transfers_finished(&yakui_vulkan::VulkanContext::new(
device,
self.gfx.queue,
self.gfx.memory_properties,
));
state.in_flight = false;
}

Expand All @@ -253,9 +275,11 @@ impl Draw {
///
/// Submits commands that wait on `image_acquired` before writing to `framebuffer`'s color
/// attachment.
#[allow(clippy::too_many_arguments)] // Every argument is of a different type, making this less of a problem.
pub unsafe fn draw(
&mut self,
mut sim: Option<&mut Sim>,
yakui_paint_dom: &yakui::paint::PaintDom,
framebuffer: vk::Framebuffer,
depth_view: vk::ImageView,
extent: vk::Extent2D,
Expand All @@ -273,6 +297,9 @@ impl Draw {
let state = &mut self.states[self.next_state];
let cmd = state.cmd;

let yakui_vulkan_context =
yakui_vulkan::VulkanContext::new(device, self.gfx.queue, self.gfx.memory_properties);

// We're using this state again, so put the fence back in the unsignaled state and compute
// the next frame to use
device.reset_fences(&[state.fence]).unwrap();
Expand Down Expand Up @@ -340,6 +367,9 @@ impl Draw {
);
timestamp_index += 1;

self.yakui_vulkan
.transfer(yakui_paint_dom, &yakui_vulkan_context, cmd);

// Schedule transfer of uniform data. Note that we defer actually preparing the data to just
// before submitting the command buffer so time-sensitive values can be set with minimum
// latency.
Expand Down Expand Up @@ -470,6 +500,9 @@ impl Draw {

self.fog.draw(device, state.common_ds, cmd);

self.yakui_vulkan
.paint(yakui_paint_dom, &yakui_vulkan_context, cmd, extent);

// Finish up
device.cmd_end_render_pass(cmd);
device.cmd_write_timestamp(
Expand Down Expand Up @@ -512,6 +545,7 @@ impl Draw {
state.fence,
)
.unwrap();
self.yakui_vulkan.transfers_submitted();
state.used = true;
state.in_flight = true;
histogram!("frame.cpu").record(draw_started.elapsed());
Expand Down Expand Up @@ -546,6 +580,7 @@ impl Drop for Draw {
voxels.destroy(device);
}
}
self.yakui_vulkan.cleanup(&self.gfx.device);
device.destroy_command_pool(self.cmd_pool, None);
device.destroy_query_pool(self.timestamp_pool, None);
device.destroy_descriptor_pool(self.common_descriptor_pool, None);
Expand Down
40 changes: 40 additions & 0 deletions client/src/graphics/gui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use yakui::{
align, colored_box, colored_box_container, label, pad, widgets::Pad, Alignment, Color,
};

use crate::Sim;

pub struct GuiState {
show_gui: bool,
}

impl GuiState {
pub fn new() -> Self {
GuiState { show_gui: true }
}

/// Toggles whether the GUI is shown
pub fn toggle_gui(&mut self) {
self.show_gui = !self.show_gui;
}

/// Prepare the GUI for rendering. This should be called between
/// Yakui::start and Yakui::finish.
pub fn run(&self, sim: &Sim) {
if !self.show_gui {
return;
}

align(Alignment::CENTER, || {
colored_box(Color::BLACK.with_alpha(0.9), [5.0, 5.0]);
});

align(Alignment::TOP_LEFT, || {
pad(Pad::all(8.0), || {
colored_box_container(Color::BLACK.with_alpha(0.7), || {
label(format!("Selected material: {:?}", sim.selected_material()));
});
});
});
}
}
1 change: 1 addition & 0 deletions client/src/graphics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod draw;
mod fog;
mod frustum;
mod gltf_mesh;
mod gui;
mod meshes;
mod png_array;
pub mod voxels;
Expand Down
28 changes: 25 additions & 3 deletions client/src/graphics/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use winit::{
window::{CursorGrabMode, Window as WinitWindow, WindowBuilder},
};

use super::gui::GuiState;
use super::{Base, Core, Draw, Frustum};
use crate::Net;
use crate::{net, Config, Sim};
Expand Down Expand Up @@ -57,6 +58,8 @@ pub struct Window {
swapchain_needs_update: bool,
draw: Option<Draw>,
sim: Option<Sim>,
gui_state: GuiState,
yak: yakui::Yakui,
net: Net,
}

Expand Down Expand Up @@ -93,6 +96,8 @@ impl Window {
swapchain_needs_update: false,
draw: None,
sim: None,
gui_state: GuiState::new(),
yak: yakui::Yakui::new(),
net,
}
}
Expand Down Expand Up @@ -261,6 +266,9 @@ impl Window {
sim.toggle_no_clip();
}
}
KeyCode::F1 if state == ElementState::Pressed => {
self.gui_state.toggle_gui();
}
KeyCode::Escape => {
let _ = self.window.set_cursor_grab(CursorGrabMode::None);
self.window.set_cursor_visible(true);
Expand Down Expand Up @@ -345,16 +353,30 @@ impl Window {
}
}
};
let aspect_ratio =
swapchain.state.extent.width as f32 / swapchain.state.extent.height as f32;
let extent = swapchain.state.extent;
let aspect_ratio = extent.width as f32 / extent.height as f32;
let frame = &swapchain.state.frames[frame_id as usize];
let frustum = Frustum::from_vfov(f32::consts::FRAC_PI_4 * 1.2, aspect_ratio);
// Render the GUI
self.yak
.set_surface_size([extent.width as f32, extent.height as f32].into());
self.yak
.set_unscaled_viewport(yakui::geometry::Rect::from_pos_size(
Default::default(),
[extent.width as f32, extent.height as f32].into(),
));
self.yak.start();
if let Some(sim) = self.sim.as_ref() {
self.gui_state.run(sim);
}
self.yak.finish();
// Render the frame
draw.draw(
self.sim.as_mut(),
self.yak.paint(),
frame.buffer,
frame.depth_view,
swapchain.state.extent,
extent,
frame.present,
&frustum,
);
Expand Down
4 changes: 4 additions & 0 deletions client/src/sim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ impl Sim {
self.selected_material = *MATERIAL_PALETTE.get(idx).unwrap_or(&MATERIAL_PALETTE[0]);
}

pub fn selected_material(&self) -> Material {
self.selected_material
}

pub fn set_break_block_pressed_true(&mut self) {
self.break_block_pressed = true;
}
Expand Down
Loading