aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-25 17:44:22 +0100
committertcmal <me@aria.rip>2024-08-25 17:44:22 +0100
commitb688a25810840c5ebf4bf2c18bbdae52c62f6b4d (patch)
tree923c81d1be62d1344694306d5fb8728841620b6f
parentbf9573764c695e65b1504419fafb76ccabb0322b (diff)
feat(render): WIP eGUI integration
-rw-r--r--examples/render-bsp/Cargo.toml2
-rw-r--r--examples/render-bsp/src/main.rs30
-rw-r--r--stockton-input/Cargo.toml3
-rw-r--r--stockton-input/src/manager.rs26
-rw-r--r--stockton-render/Cargo.toml5
-rw-r--r--stockton-render/src/draw/context.rs63
-rw-r--r--stockton-render/src/draw/draw_buffers.rs8
-rw-r--r--stockton-render/src/draw/macros.rs28
-rw-r--r--stockton-render/src/draw/render.rs2
-rw-r--r--stockton-render/src/draw/target.rs8
-rw-r--r--stockton-render/src/draw/ui/data/stockton.frag11
-rw-r--r--stockton-render/src/draw/ui/data/stockton.vert27
-rw-r--r--stockton-render/src/draw/ui/mod.rs8
-rw-r--r--stockton-render/src/draw/ui/pipeline.rs18
-rw-r--r--stockton-render/src/draw/ui/render.rs55
-rwxr-xr-xstockton-render/src/draw/ui/texture.rs54
-rw-r--r--stockton-render/src/lib.rs14
-rw-r--r--stockton-render/src/window.rs124
18 files changed, 421 insertions, 65 deletions
diff --git a/examples/render-bsp/Cargo.toml b/examples/render-bsp/Cargo.toml
index 90f5ef9..bbcaf1d 100644
--- a/examples/render-bsp/Cargo.toml
+++ b/examples/render-bsp/Cargo.toml
@@ -15,3 +15,5 @@ winit = "^0.21"
log = "0.4.0"
simple_logger = "^1.11"
image = "0.23.2"
+egui = "^0.2"
+legion = { version = "^0.3" }
diff --git a/examples/render-bsp/src/main.rs b/examples/render-bsp/src/main.rs
index 9332629..7622897 100644
--- a/examples/render-bsp/src/main.rs
+++ b/examples/render-bsp/src/main.rs
@@ -20,17 +20,21 @@
#[macro_use]
extern crate stockton_input_codegen;
+#[macro_use]
+extern crate legion;
+
use std::collections::BTreeMap;
use winit::{event::Event, event_loop::EventLoop, window::WindowBuilder};
use stockton_contrib::delta_time::*;
use stockton_contrib::flycam::*;
+
use stockton_input::{Axis, InputManager, Mouse};
use stockton_levels::{prelude::*, q3::Q3BSPFile};
-use stockton_render::{
- do_render_system, draw::calc_vp_matrix_system, window::process_window_events_system, Renderer,
- WindowEvent,
-};
+
+use stockton_render::systems::*;
+use stockton_render::{Renderer, UIState, WindowEvent};
+
use stockton_types::components::{CameraSettings, Transform};
use stockton_types::{Session, Vector3};
@@ -58,6 +62,21 @@ impl FlycamInput for MovementInputs {
}
}
+#[system]
+fn hello_world(#[resource] ui: &mut UIState, #[state] name: &mut String, #[state] age: &mut f32) {
+ let ui = ui.ui();
+ ui.heading("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ // ui.horizontal(|ui| {
+ // ui.label("Your name: ");
+ // ui.text_edit(name);
+ // });
+ // ui.add(egui::Slider::f32(age, 0.0..=120.0).text("age"));
+ // if ui.button("Click each year").clicked {
+ // *age += 1.0;
+ // }
+ // ui.label(format!("Hello '{}', age {}", name, age));
+}
+
fn main() {
// Initialise logger
simple_logger::SimpleLogger::new()
@@ -107,6 +126,7 @@ fn main() {
// Load everything into the session
let mut session = Session::new(
move |resources| {
+ resources.insert(UIState::new(&renderer));
resources.insert(renderer);
resources.insert(bsp);
resources.insert(manager);
@@ -117,6 +137,8 @@ fn main() {
schedule
.add_system(update_deltatime_system())
.add_system(process_window_events_system::<MovementInputsManager>())
+ .flush()
+ .add_system(hello_world_system("".to_string(), 0.0))
.add_system(flycam_move_system::<MovementInputsManager>())
.flush()
.add_system(calc_vp_matrix_system())
diff --git a/stockton-input/Cargo.toml b/stockton-input/Cargo.toml
index fa6507f..57ea6e1 100644
--- a/stockton-input/Cargo.toml
+++ b/stockton-input/Cargo.toml
@@ -5,4 +5,5 @@ authors = ["Oscar Shrimpton <oscar.shrimpton.personal@gmail.com>"]
edition = "2018"
[dependencies]
-stockton-types = { path = "../stockton-types" } \ No newline at end of file
+stockton-types = { path = "../stockton-types" }
+egui = "^0.2"
diff --git a/stockton-input/src/manager.rs b/stockton-input/src/manager.rs
index f0786b0..663b6b8 100644
--- a/stockton-input/src/manager.rs
+++ b/stockton-input/src/manager.rs
@@ -23,11 +23,32 @@ pub enum InputMutation {
PositiveAxis,
}
+#[derive(Debug, Clone, Copy)]
+pub enum MouseButton {
+ Left,
+ Right,
+ Middle,
+ Other(u8)
+}
+
+impl MouseButton {
+ fn keycode(&self) -> u32 {
+ u32::MAX - match self {
+ MouseButton::Left => 0,
+ MouseButton::Right => 1,
+ MouseButton::Middle => 2,
+ MouseButton::Other(x) => *x as u32
+ }
+ }
+}
+
/// A key being pressed or released
#[derive(Debug, Clone, Copy)]
pub enum Action {
KeyPress(u32),
KeyRelease(u32),
+ MousePress(MouseButton),
+ MouseRelease(MouseButton)
}
impl Action {
@@ -35,12 +56,17 @@ impl Action {
match self {
Action::KeyPress(x) => *x,
Action::KeyRelease(x) => *x,
+ Action::MousePress(x) => x.keycode(),
+ Action::MouseRelease(x) => x.keycode(),
+
}
}
pub fn is_down(&self) -> bool {
match self {
Action::KeyPress(_) => true,
+ Action::MousePress(_) => true,
Action::KeyRelease(_) => false,
+ Action::MouseRelease(_) => false,
}
}
}
diff --git a/stockton-render/Cargo.toml b/stockton-render/Cargo.toml
index e4f2153..7c69be6 100644
--- a/stockton-render/Cargo.toml
+++ b/stockton-render/Cargo.toml
@@ -12,10 +12,11 @@ winit = "^0.21"
gfx-hal = "^0.5"
arrayvec = "0.4.10"
nalgebra-glm = "^0.6"
-shaderc = "0.6.1"
+shaderc = "^0.7"
log = "0.4.0"
-image = "0.23.2"
+image = "0.23.11"
legion = { version = "^0.3" }
+egui = "^0.2"
[features]
default = ["vulkan"]
diff --git a/stockton-render/src/draw/context.rs b/stockton-render/src/draw/context.rs
index 94f1f0c..4d700e5 100644
--- a/stockton-render/src/draw/context.rs
+++ b/stockton-render/src/draw/context.rs
@@ -29,14 +29,14 @@ use winit::window::Window;
use super::{
buffer::ModifiableBuffer,
- draw_buffers::DrawBuffers,
+ draw_buffers::{DrawBuffers, UVPoint},
pipeline::CompletePipeline,
render::do_render,
target::{SwapchainProperties, TargetChain},
texture::TextureStore,
- ui::{do_render as do_render_ui, UIPipeline},
+ ui::{do_render as do_render_ui, ensure_textures as ensure_textures_ui, UIPipeline, UIPoint},
};
-use crate::{error, types::*};
+use crate::{error, types::*, window::UIState};
use stockton_levels::prelude::*;
/// Contains all the hal related stuff.
@@ -76,14 +76,19 @@ pub struct RenderingContext<'a> {
/// Texture store
texture_store: ManuallyDrop<TextureStore>,
+ /// Texture store for UI
+ ui_texture_store: ManuallyDrop<TextureStore>,
+
/// Buffers used for drawing
- draw_buffers: ManuallyDrop<DrawBuffers<'a>>,
+ draw_buffers: ManuallyDrop<DrawBuffers<'a, UVPoint>>,
/// Buffers used for drawing the UI
- ui_draw_buffers: ManuallyDrop<DrawBuffers<'a>>,
+ ui_draw_buffers: ManuallyDrop<DrawBuffers<'a, UIPoint>>,
/// View projection matrix
pub(crate) vp_matrix: Mat4,
+
+ pub(crate) pixels_per_point: f32,
}
impl<'a> RenderingContext<'a> {
@@ -156,9 +161,21 @@ impl<'a> RenderingContext<'a> {
file,
)?;
+ // Texture store for UI elements
+ let ui_texture_store = TextureStore::new_empty(
+ &mut device,
+ &mut adapter,
+ &mut queue_group.queues[0],
+ &mut cmd_pool,
+ 1, // TODO
+ )?;
+
let mut descriptor_set_layouts: ArrayVec<[_; 2]> = ArrayVec::new();
descriptor_set_layouts.push(texture_store.descriptor_set_layout.deref());
+ let mut ui_descriptor_set_layouts: ArrayVec<[_; 2]> = ArrayVec::new();
+ ui_descriptor_set_layouts.push(ui_texture_store.descriptor_set_layout.deref());
+
// Graphics pipeline
let pipeline = CompletePipeline::new(
&mut device,
@@ -172,7 +189,7 @@ impl<'a> RenderingContext<'a> {
&mut device,
swapchain_properties.extent,
&swapchain_properties,
- &[],
+ ui_descriptor_set_layouts,
)?;
// Swapchain and associated resources
@@ -207,7 +224,11 @@ impl<'a> RenderingContext<'a> {
draw_buffers: ManuallyDrop::new(draw_buffers),
ui_draw_buffers: ManuallyDrop::new(ui_draw_buffers),
+ ui_texture_store: ManuallyDrop::new(ui_texture_store),
+
vp_matrix: Mat4::identity(),
+
+ pixels_per_point: window.scale_factor() as f32,
})
}
@@ -241,7 +262,15 @@ impl<'a> RenderingContext<'a> {
// TODO: Recycle
ManuallyDrop::into_inner(read(&self.ui_pipeline)).deactivate(&mut self.device);
self.ui_pipeline = ManuallyDrop::new({
- UIPipeline::new(&mut self.device, properties.extent, &properties, &[])?
+ let mut descriptor_set_layouts: ArrayVec<[_; 1]> = ArrayVec::new();
+ descriptor_set_layouts.push(self.ui_texture_store.descriptor_set_layout.deref());
+
+ UIPipeline::new(
+ &mut self.device,
+ properties.extent,
+ &properties,
+ descriptor_set_layouts,
+ )?
});
let old_swapchain = ManuallyDrop::into_inner(read(&self.target_chain))
@@ -267,8 +296,19 @@ impl<'a> RenderingContext<'a> {
pub fn draw_vertices<M: MinBSPFeatures<VulkanSystem>>(
&mut self,
file: &M,
+ ui: &mut UIState,
faces: &[u32],
) -> Result<(), &'static str> {
+ // Ensure UI texture(s) are loaded
+ ensure_textures_ui(
+ &mut self.ui_texture_store,
+ ui,
+ &mut self.device,
+ &mut self.adapter,
+ &mut self.queue_group.queues[0],
+ &mut self.cmd_pool,
+ );
+
// 3D Pass
let cmd_buffer = self.target_chain.prep_next_target(
&mut self.device,
@@ -289,7 +329,13 @@ impl<'a> RenderingContext<'a> {
let cmd_buffer = self
.target_chain
.target_2d_pass(&mut self.ui_draw_buffers, &self.ui_pipeline)?;
- do_render_ui(cmd_buffer, &mut self.ui_draw_buffers);
+ do_render_ui(
+ cmd_buffer,
+ &self.ui_pipeline.pipeline_layout,
+ &mut self.ui_draw_buffers,
+ &mut self.ui_texture_store,
+ ui,
+ );
// Update our buffers before we actually start drawing
self.draw_buffers.vertex_buffer.commit(
@@ -334,6 +380,7 @@ impl<'a> core::ops::Drop for RenderingContext<'a> {
ManuallyDrop::into_inner(read(&self.draw_buffers)).deactivate(&mut self.device);
ManuallyDrop::into_inner(read(&self.ui_draw_buffers)).deactivate(&mut self.device);
ManuallyDrop::into_inner(read(&self.texture_store)).deactivate(&mut self.device);
+ ManuallyDrop::into_inner(read(&self.ui_texture_store)).deactivate(&mut self.device);
ManuallyDrop::into_inner(read(&self.target_chain))
.deactivate(&mut self.device, &mut self.cmd_pool);
diff --git a/stockton-render/src/draw/draw_buffers.rs b/stockton-render/src/draw/draw_buffers.rs
index a6e0996..837356a 100644
--- a/stockton-render/src/draw/draw_buffers.rs
+++ b/stockton-render/src/draw/draw_buffers.rs
@@ -31,13 +31,13 @@ pub const INITIAL_VERT_SIZE: u64 = 3 * 3000;
pub const INITIAL_INDEX_SIZE: u64 = 3000;
/// The buffers used for drawing, ie index and vertex buffer
-pub struct DrawBuffers<'a> {
- pub vertex_buffer: ManuallyDrop<StagedBuffer<'a, UVPoint>>,
+pub struct DrawBuffers<'a, T: Sized> {
+ pub vertex_buffer: ManuallyDrop<StagedBuffer<'a, T>>,
pub index_buffer: ManuallyDrop<StagedBuffer<'a, (u16, u16, u16)>>,
}
-impl<'a> DrawBuffers<'a> {
- pub fn new(device: &mut Device, adapter: &Adapter) -> Result<DrawBuffers<'a>, CreationError> {
+impl<'a, T> DrawBuffers<'a, T> {
+ pub fn new(device: &mut Device, adapter: &Adapter) -> Result<DrawBuffers<'a, T>, CreationError> {
let vert = StagedBuffer::new(device, &adapter, Usage::VERTEX, INITIAL_VERT_SIZE)?;
let index = StagedBuffer::new(device, &adapter, Usage::INDEX, INITIAL_INDEX_SIZE)?;
diff --git a/stockton-render/src/draw/macros.rs b/stockton-render/src/draw/macros.rs
index 9096958..e1ee515 100644
--- a/stockton-render/src/draw/macros.rs
+++ b/stockton-render/src/draw/macros.rs
@@ -29,6 +29,20 @@
/// ```
/// See the hal::pso::Format enum for possible types
macro_rules! pipeline_vb_attributes {
+ // Special case for single item
+ ( $binding:expr, $firstSize:expr; $firstType:ident ) => ({
+ vec![
+ AttributeDesc {
+ location: 0,
+ binding: $binding,
+ element: Element {
+ format: Format::$firstType,
+ offset: $firstSize as u32
+ }
+ }
+ ]
+ });
+
// Start of recursion
( $binding:expr,
$firstSize:expr; $firstType:ident,
@@ -55,20 +69,6 @@ macro_rules! pipeline_vb_attributes {
vec
});
- // Special case for single item
- ( $binding:expr; $firstSize:expr; $firstType:ident ) => ({
- vec![
- AttributeDesc {
- location: 0,
- binding: $binding,
- element: Element {
- format: Format::$firstType,
- offset: $firstSize as u32
- }
- }
- ]
- });
-
// Middle of recursion
( $vec:ident; $binding:expr; $location:expr; $prevSize:expr,
$firstSize:expr; $firstType:ident,
diff --git a/stockton-render/src/draw/render.rs b/stockton-render/src/draw/render.rs
index e73b569..093e257 100644
--- a/stockton-render/src/draw/render.rs
+++ b/stockton-render/src/draw/render.rs
@@ -31,7 +31,7 @@ use crate::types::*;
pub fn do_render<M: MinBSPFeatures<VulkanSystem>>(
cmd_buffer: &mut CommandBuffer,
- draw_buffers: &mut DrawBuffers,
+ draw_buffers: &mut DrawBuffers<UVPoint>,
texture_store: &TextureStore,
pipeline_layout: &PipelineLayout,
file: &M,
diff --git a/stockton-render/src/draw/target.rs b/stockton-render/src/draw/target.rs
index b47700f..daf9942 100644
--- a/stockton-render/src/draw/target.rs
+++ b/stockton-render/src/draw/target.rs
@@ -31,8 +31,8 @@ use hal::{
use na::Mat4;
use super::{
- buffer::ModifiableBuffer, draw_buffers::DrawBuffers, pipeline::CompletePipeline,
- texture::image::LoadedImage, ui::UIPipeline,
+ buffer::ModifiableBuffer, draw_buffers::{DrawBuffers, UVPoint}, pipeline::CompletePipeline,
+ texture::image::LoadedImage, ui::{UIPipeline, UIPoint},
};
use crate::types::*;
@@ -275,7 +275,7 @@ impl TargetChain {
pub fn prep_next_target<'a>(
&'a mut self,
device: &mut Device,
- draw_buffers: &mut DrawBuffers,
+ draw_buffers: &mut DrawBuffers<UVPoint>,
pipeline: &CompletePipeline,
vp: &Mat4,
) -> Result<&'a mut crate::types::CommandBuffer, &'static str> {
@@ -373,7 +373,7 @@ impl TargetChain {
pub fn target_2d_pass<'a>(
&'a mut self,
- draw_buffers: &mut DrawBuffers,
+ draw_buffers: &mut DrawBuffers<UIPoint>,
pipeline: &UIPipeline,
) -> Result<&'a mut CommandBuffer, &'static str> {
let target = &mut self.targets[self.last_image as usize];
diff --git a/stockton-render/src/draw/ui/data/stockton.frag b/stockton-render/src/draw/ui/data/stockton.frag
index 1a85ab6..e5b2b4d 100644
--- a/stockton-render/src/draw/ui/data/stockton.frag
+++ b/stockton-render/src/draw/ui/data/stockton.frag
@@ -1,8 +1,15 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
-layout(location = 0) out vec4 outColor;
+// DescriptorSet 0 = Textures
+layout(set = 0, binding = 0) uniform texture2D tex[8];
+layout(set = 0, binding = 1) uniform sampler samp[8];
+
+layout (location = 1) in vec2 frag_uv;
+layout (location = 2) in flat int frag_col;
+
+layout (location = 0) out vec4 color;
void main() {
- outColor = vec4(1.0, 0.0, 0.0, 1.0);
+ color = texture(sampler2D(tex[0], samp[0]), frag_uv);
} \ No newline at end of file
diff --git a/stockton-render/src/draw/ui/data/stockton.vert b/stockton-render/src/draw/ui/data/stockton.vert
index 1dd9477..7447fec 100644
--- a/stockton-render/src/draw/ui/data/stockton.vert
+++ b/stockton-render/src/draw/ui/data/stockton.vert
@@ -1,11 +1,26 @@
#version 450
-vec2 positions[3] = vec2[](
- vec2(0.0, -0.5),
- vec2(0.5, 0.5),
- vec2(-0.5, 0.5)
-);
+layout (push_constant) uniform PushConsts {
+ vec2 screen_size;
+} push;
+
+layout(location = 0) in vec2 pos;
+layout (location = 1) in vec2 uv;
+layout (location = 2) in int col; // rgba of u8s
+
+out gl_PerVertex {
+ vec4 gl_Position;
+};
+layout (location = 1) out vec2 frag_uv;
+layout (location = 2) out int frag_col;
void main() {
- gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
+ gl_Position = vec4(
+ ((pos.x / push.screen_size.x) * 2.0) - 1.0,
+ ((pos.y / push.screen_size.y) * 2.0) - 1.0,
+ 0.0,
+ 1.0
+ );
+ frag_uv = uv;
+ frag_col = col;
}
diff --git a/stockton-render/src/draw/ui/mod.rs b/stockton-render/src/draw/ui/mod.rs
index cd19362..bcf5f38 100644
--- a/stockton-render/src/draw/ui/mod.rs
+++ b/stockton-render/src/draw/ui/mod.rs
@@ -15,8 +15,16 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+use egui::paint::color::Srgba;
+
pub mod pipeline;
pub mod render;
+pub mod texture;
pub use pipeline::UIPipeline;
pub use render::do_render;
+use stockton_types::Vector2;
+pub use texture::ensure_textures;
+
+#[derive(Debug)]
+pub struct UIPoint(pub Vector2, pub Vector2, pub Srgba);
diff --git a/stockton-render/src/draw/ui/pipeline.rs b/stockton-render/src/draw/ui/pipeline.rs
index 378c558..3b643e4 100644
--- a/stockton-render/src/draw/ui/pipeline.rs
+++ b/stockton-render/src/draw/ui/pipeline.rs
@@ -62,7 +62,7 @@ impl UIPipeline {
set_layouts: T,
) -> Result<Self, error::CreationError>
where
- T: IntoIterator,
+ T: IntoIterator + std::fmt::Debug,
T::Item: Borrow<DescriptorSetLayout>,
{
use hal::format::Format;
@@ -125,7 +125,7 @@ impl UIPipeline {
.compile_into_spirv(
VERTEX_SOURCE,
shaderc::ShaderKind::Vertex,
- "vertex.vert",
+ "vertex_ui.vert",
ENTRY_NAME,
None,
)
@@ -135,7 +135,7 @@ impl UIPipeline {
.compile_into_spirv(
FRAGMENT_SOURCE,
shaderc::ShaderKind::Fragment,
- "fragment.frag",
+ "fragment_ui.frag",
ENTRY_NAME,
None,
)
@@ -180,13 +180,14 @@ impl UIPipeline {
// Vertex buffers
let vertex_buffers: Vec<VertexBufferDesc> = vec![VertexBufferDesc {
binding: 0,
- stride: (size_of::<f32>() * 5) as u32,
+ stride: ((size_of::<f32>() * 4) + (size_of::<u8>() * 4)) as u32,
rate: VertexInputRate::Vertex,
}];
let attributes: Vec<AttributeDesc> = pipeline_vb_attributes!(0,
size_of::<f32>() * 2; Rg32Sfloat,
- size_of::<f32>() * 3; Rgb32Sfloat
+ size_of::<f32>() * 2; Rg32Sfloat,
+ size_of::<u8>() * 4; Rgba8Uint
);
// Rasterizer
@@ -207,9 +208,12 @@ impl UIPipeline {
stencil: None,
};
+ log::debug!("ui set layouts: {:?}", set_layouts);
// Pipeline layout
- let layout = unsafe { device.create_pipeline_layout(set_layouts, &[]) }
- .map_err(|_| error::CreationError::OutOfMemoryError)?;
+ let layout = unsafe {
+ device.create_pipeline_layout(set_layouts, &[(ShaderStageFlags::VERTEX, 0..8)])
+ }
+ .map_err(|_| error::CreationError::OutOfMemoryError)?;
// Colour blending
let blender = {
diff --git a/stockton-render/src/draw/ui/render.rs b/stockton-render/src/draw/ui/render.rs
index b965a80..ad23dfb 100644
--- a/stockton-render/src/draw/ui/render.rs
+++ b/stockton-render/src/draw/ui/render.rs
@@ -15,14 +15,65 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+use crate::draw::texture::TextureStore;
+use arrayvec::ArrayVec;
+use egui::Pos2;
use hal::prelude::*;
+use hal::pso::ShaderStageFlags;
+use super::UIPoint;
use crate::draw::draw_buffers::DrawBuffers;
use crate::types::*;
+use crate::UIState;
+use std::convert::TryInto;
+use std::mem::transmute;
+use stockton_types::Vector2;
-pub fn do_render(cmd_buffer: &mut CommandBuffer, _draw_buffers: &mut DrawBuffers) {
+pub fn do_render(
+ cmd_buffer: &mut CommandBuffer,
+ pipeline_layout: &PipelineLayout,
+ draw_buffers: &mut DrawBuffers<UIPoint>,
+ texture_store: &mut TextureStore,
+ ui: &mut UIState,
+) {
// TODO: Actual UI Rendering
+ let (_out, paint) = ui.end_frame();
+ let screen = ui.dimensions();
+
unsafe {
- cmd_buffer.draw(0..3, 0..1);
+ cmd_buffer.push_graphics_constants(
+ &pipeline_layout,
+ ShaderStageFlags::VERTEX,
+ 0,
+ &[transmute(screen.x), transmute(screen.y)],
+ );
+ }
+
+ for (_rect, tris) in paint.iter() {
+ // Copy triangles/indicies
+ for i in (0..tris.indices.len()).step_by(3) {
+ draw_buffers.index_buffer[i / 3] = (
+ tris.indices[i].try_into().unwrap(),
+ tris.indices[i + 1].try_into().unwrap(),
+ tris.indices[i + 2].try_into().unwrap(),
+ );
+ }
+ for (i, vertex) in tris.vertices.iter().enumerate() {
+ draw_buffers.vertex_buffer[i] = UIPoint(
+ Vector2::new(vertex.pos.x, vertex.pos.y),
+ Vector2::new(vertex.uv.x, vertex.uv.y),
+ vertex.color,
+ );
+ }
+
+ // TODO: *Properly* deal with textures
+ let mut descriptor_sets: ArrayVec<[_; 1]> = ArrayVec::new();
+ descriptor_sets.push(texture_store.get_chunk_descriptor_set(0));
+
+ unsafe {
+ cmd_buffer.bind_graphics_descriptor_sets(pipeline_layout, 0, descriptor_sets, &[]);
+ // Call draw
+ cmd_buffer.draw_indexed(0..tris.indices.len() as u32, 0, 0..1);
+ }
}
}
diff --git a/stockton-render/src/draw/ui/texture.rs b/stockton-render/src/draw/ui/texture.rs
new file mode 100755
index 0000000..ce18f02
--- /dev/null
+++ b/stockton-render/src/draw/ui/texture.rs
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) Oscar Shrimpton 2020
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+use egui::Texture;
+use crate::types::*;
+use crate::draw::texture::{TextureStore, LoadableImage};
+use crate::UIState;
+
+impl LoadableImage for &Texture {
+ fn width(&self) -> u32 {
+ self.width as u32
+ }
+ fn height(&self) -> u32 {
+ self.height as u32
+ }
+ fn copy_row(&self, y: u32, ptr: *mut u8) -> () {
+ let row_size = self.width();
+ let pixels = &self.pixels[(y * row_size) as usize..((y + 1) * row_size) as usize];
+
+ for (i,x) in pixels.iter().enumerate() {
+ unsafe {
+ *ptr.offset(i as isize * 3) = *x;
+ *ptr.offset((i as isize * 3) + 1) = *x;
+ *ptr.offset((i as isize * 3) + 2) = *x;
+ }
+ }
+ }
+}
+
+pub fn ensure_textures(texture_store: &mut TextureStore, ui: &mut UIState,
+ device: &mut Device,
+ adapter: &mut Adapter,
+ command_queue: &mut CommandQueue,
+ command_pool: &mut CommandPool) {
+ let tex = ui.ctx.texture();
+
+ if tex.version != ui.last_tex_ver {
+ texture_store.put_texture(0, &*tex, device, adapter, command_queue, command_pool).unwrap(); // TODO
+ ui.last_tex_ver = tex.version;
+ }
+} \ No newline at end of file
diff --git a/stockton-render/src/lib.rs b/stockton-render/src/lib.rs
index 8bdca89..221bdd5 100644
--- a/stockton-render/src/lib.rs
+++ b/stockton-render/src/lib.rs
@@ -28,6 +28,7 @@ pub mod draw;
mod error;
mod types;
pub mod window;
+pub mod systems;
use culling::get_visible_faces;
use draw::RenderingContext;
@@ -36,7 +37,7 @@ use legion::IntoQuery;
use std::sync::mpsc::{Receiver, Sender};
use std::sync::Arc;
use std::sync::RwLock;
-pub use window::WindowEvent;
+pub use window::{WindowEvent, UIState};
use stockton_levels::prelude::*;
use stockton_types::components::{CameraSettings, Transform};
@@ -50,7 +51,7 @@ use std::sync::mpsc::channel;
/// Also takes ownership of the window and channels window events to be processed outside winit's event loop.
pub struct Renderer<'a> {
/// All the vulkan stuff
- context: RenderingContext<'a>,
+ pub(crate) context: RenderingContext<'a>,
/// For getting events from the winit event loop
pub window_events: Receiver<WindowEvent>,
@@ -79,16 +80,16 @@ impl<'a> Renderer<'a> {
}
/// Render a single frame of the given map.
- fn render<T: MinBSPFeatures<VulkanSystem>>(&mut self, map: &T, pos: Vector3) {
+ fn render<T: MinBSPFeatures<VulkanSystem>>(&mut self, map: &T, ui: &mut UIState, pos: Vector3) {
// Get visible faces
let faces = get_visible_faces(pos, map);
// Then draw them
- if self.context.draw_vertices(map, &faces).is_err() {
+ if self.context.draw_vertices(map, ui, &faces).is_err() {
unsafe { self.context.handle_surface_change().unwrap() };
// If it fails twice, then error
- self.context.draw_vertices(map, &faces).unwrap();
+ self.context.draw_vertices(map, ui, &faces).unwrap();
}
}
@@ -103,11 +104,12 @@ impl<'a> Renderer<'a> {
#[read_component(CameraSettings)]
pub fn do_render<T: 'static + MinBSPFeatures<VulkanSystem>>(
#[resource] renderer: &mut Renderer<'static>,
+ #[resource] ui: &mut UIState,
#[resource] map: &T,
world: &SubWorld,
) {
let mut query = <(&Transform, &CameraSettings)>::query();
for (transform, _) in query.iter(world) {
- renderer.render(map, transform.position);
+ renderer.render(map, ui, transform.position);
}
}
diff --git a/stockton-render/src/window.rs b/stockton-render/src/window.rs
index efb8030..e122dea 100644
--- a/stockton-render/src/window.rs
+++ b/stockton-render/src/window.rs
@@ -15,20 +15,27 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+use log::debug;
+use std::sync::Arc;
+use egui::Context;
use crate::Renderer;
use legion::systems::Runnable;
+use egui::{RawInput, Ui, Pos2, Output, PaintJobs};
+
use stockton_input::{Action as KBAction, InputManager, Mouse};
-use winit::event::{ElementState, Event as WinitEvent, WindowEvent as WinitWindowEvent};
+use winit::event::{ElementState, Event as WinitEvent, WindowEvent as WinitWindowEvent, MouseButton};
use winit::event_loop::ControlFlow;
#[derive(Debug, Clone, Copy)]
pub enum WindowEvent {
- SizeChanged,
+ SizeChanged (u32, u32),
CloseRequested,
KeyboardAction(KBAction),
+ MouseAction(KBAction),
MouseMoved(f32, f32),
+ MouseLeft
}
impl WindowEvent {
@@ -37,7 +44,7 @@ impl WindowEvent {
match winit_event {
WinitEvent::WindowEvent { event, .. } => match event {
WinitWindowEvent::CloseRequested => Some(WindowEvent::CloseRequested),
- WinitWindowEvent::Resized(_) => Some(WindowEvent::SizeChanged),
+ WinitWindowEvent::Resized(size) => Some(WindowEvent::SizeChanged (size.width, size.height)),
WinitWindowEvent::KeyboardInput { input, .. } => match input.state {
ElementState::Pressed => Some(WindowEvent::KeyboardAction(KBAction::KeyPress(
input.scancode,
@@ -50,6 +57,20 @@ impl WindowEvent {
position.x as f32,
position.y as f32,
)),
+ WinitWindowEvent::CursorLeft { .. } => Some(WindowEvent::MouseLeft),
+ WinitWindowEvent::MouseInput { button, state, .. } => {
+ let mb: stockton_input::MouseButton = match button {
+ MouseButton::Left => stockton_input::MouseButton::Left,
+ MouseButton::Right => stockton_input::MouseButton::Right,
+ MouseButton::Middle => stockton_input::MouseButton::Middle,
+ MouseButton::Other(x) => stockton_input::MouseButton::Other(*x)
+ };
+
+ match state {
+ ElementState::Pressed => Some(WindowEvent::MouseAction(KBAction::MousePress(mb))),
+ ElementState::Released => Some(WindowEvent::MouseAction(KBAction::MouseRelease(mb)))
+ }
+ },
_ => None,
},
_ => None,
@@ -57,12 +78,87 @@ impl WindowEvent {
}
}
+pub struct UIState {
+ pub(crate) ctx: Arc<Context>,
+ pub(crate) raw_input: RawInput,
+ ui: Option<Ui>,
+
+ pub(crate) last_tex_ver: u64,
+}
+
+impl UIState {
+ pub fn ui<'a>(&'a mut self) -> &'a mut Ui {
+ if self.ui.is_none() {
+ self.ui = Some(self.begin_frame());
+ }
+ self.ui.as_mut().unwrap()
+ }
+ fn begin_frame(&mut self) -> Ui {
+ self.ctx.begin_frame(self.raw_input.take())
+ }
+
+ pub fn end_frame(&mut self) -> (Output, PaintJobs) {
+ self.ui = None;
+ self.ctx.end_frame()
+ }
+
+ fn set_mouse_pos(&mut self, x: f32, y: f32) {
+ self.raw_input.mouse_pos = Some(Pos2 {x, y})
+ }
+
+ fn set_mouse_left(&mut self) {
+ self.raw_input.mouse_pos = None;
+ }
+ fn set_dimensions(&mut self, w: u32, h: u32) {
+ self.raw_input.screen_size = egui::math::Vec2 {
+ x: w as f32,
+ y: h as f32
+ }
+ }
+ fn set_pixels_per_point(&mut self, ppp: Option<f32>) {
+ self.raw_input.pixels_per_point = ppp;
+ }
+
+ pub fn dimensions(&self) -> egui::math::Vec2 {
+ self.raw_input.screen_size
+ }
+
+ fn handle_action(&mut self, action: KBAction) {
+ // TODO
+ match action {
+ KBAction::MousePress(stockton_input::MouseButton::Left) => {
+ self.raw_input.mouse_down = true;
+ }
+ KBAction::MouseRelease(stockton_input::MouseButton::Right) => {
+ self.raw_input.mouse_down = false;
+ }
+ _ => ()
+ }
+ }
+
+ pub fn new(renderer: &Renderer) -> Self {
+ let mut state = UIState {
+ ctx: Context::new(),
+ raw_input: RawInput::default(),
+ ui: None,
+ last_tex_ver: 0
+ };
+
+ let props = &renderer.context.target_chain.properties;
+ state.set_dimensions(props.extent.width, props.extent.height);
+ state.set_pixels_per_point(Some(renderer.context.pixels_per_point));
+ debug!("{:?}", state.raw_input);
+ state
+ }
+}
+
#[system]
/// A system to process the window events sent to renderer by the winit event loop.
pub fn _process_window_events<T: 'static + InputManager>(
#[resource] renderer: &mut Renderer<'static>,
#[resource] manager: &mut T,
#[resource] mouse: &mut Mouse,
+ #[resource] ui_state: &mut UIState,
#[state] actions_buf: &mut Vec<KBAction>,
) {
let mut actions_buf_cursor = 0;
@@ -70,7 +166,10 @@ pub fn _process_window_events<T: 'static + InputManager>(
while let Ok(event) = renderer.window_events.try_recv() {
match event {
- WindowEvent::SizeChanged => renderer.resize(),
+ WindowEvent::SizeChanged(w, h) => {
+ renderer.resize();
+ ui_state.set_dimensions(w, h);
+ },
WindowEvent::CloseRequested => {
let mut flow = renderer.update_control_flow.write().unwrap();
// TODO: Let everything know this is our last frame
@@ -83,10 +182,27 @@ pub fn _process_window_events<T: 'static + InputManager>(
actions_buf[actions_buf_cursor] = action;
}
actions_buf_cursor += 1;
+
+ ui_state.handle_action(action);
}
WindowEvent::MouseMoved(x, y) => {
mouse_delta.x = x;
mouse_delta.y = y;
+
+ ui_state.set_mouse_pos(x, y);
+ },
+ WindowEvent::MouseLeft => {
+ ui_state.set_mouse_left();
+ },
+ WindowEvent::MouseAction(action) => {
+ if actions_buf_cursor >= actions_buf.len() {
+ actions_buf.push(action);
+ } else {
+ actions_buf[actions_buf_cursor] = action;
+ }
+ actions_buf_cursor += 1;
+
+ ui_state.handle_action(action);
}
};
}