aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--examples/render-quad/Cargo.toml7
-rw-r--r--examples/render-quad/src/data/shader.frag11
-rw-r--r--examples/render-quad/src/data/shader.vert16
-rw-r--r--examples/render-quad/src/draw_pass.rs335
-rw-r--r--examples/render-quad/src/level.rs79
-rw-r--r--examples/render-quad/src/main.rs252
-rw-r--r--examples/render-quad/src/system.rs73
-rw-r--r--stockton-contrib/Cargo.toml2
-rw-r--r--stockton-contrib/src/flycam.rs2
-rw-r--r--stockton-levels/Cargo.toml14
-rw-r--r--stockton-levels/src/features.rs21
-rw-r--r--stockton-levels/src/lib.rs20
-rw-r--r--stockton-levels/src/parts/entities.rs36
-rw-r--r--stockton-levels/src/parts/faces.rs43
-rw-r--r--stockton-levels/src/parts/mod.rs17
-rw-r--r--stockton-levels/src/parts/textures.rs83
-rw-r--r--stockton-levels/src/parts/vertices.rs155
-rw-r--r--stockton-levels/src/parts/visdata.rs8
-rw-r--r--stockton-levels/src/prelude.rs16
-rw-r--r--stockton-levels/src/types.rs67
-rw-r--r--stockton-render/Cargo.toml22
-rw-r--r--stockton-render/src/data/3d.frag15
-rw-r--r--stockton-render/src/data/3d.vert23
-rw-r--r--stockton-render/src/data/ui.frag15
-rw-r--r--stockton-render/src/data/ui.vert37
-rw-r--r--stockton-render/src/level.rs554
-rw-r--r--stockton-render/src/lib.rs8
-rw-r--r--stockton-render/src/ui.rs421
-rw-r--r--stockton-render/src/window.rs278
-rw-r--r--stockton-skeleton/src/builders/pipeline.rs1
-rw-r--r--stockton-skeleton/src/builders/shader.rs4
-rw-r--r--stockton-skeleton/src/context.rs2
-rw-r--r--stockton-skeleton/src/draw_passes/cons.rs4
-rw-r--r--stockton-skeleton/src/draw_passes/mod.rs4
-rw-r--r--stockton-skeleton/src/lib.rs17
-rw-r--r--stockton-skeleton/src/target.rs2
-rw-r--r--stockton-skeleton/src/texture/load.rs2
-rw-r--r--stockton-skeleton/src/texture/loader.rs3
39 files changed, 512 insertions, 2159 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 726fbc8..0a850e9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,8 +3,6 @@ members = [
"stockton-input",
"stockton-input-codegen",
"stockton-skeleton",
- "stockton-levels",
- "stockton-render",
"stockton-contrib",
"rendy-memory",
"rendy-descriptor",
diff --git a/examples/render-quad/Cargo.toml b/examples/render-quad/Cargo.toml
index 99cf38e..7e7f57c 100644
--- a/examples/render-quad/Cargo.toml
+++ b/examples/render-quad/Cargo.toml
@@ -6,15 +6,10 @@ edition = "2018"
[dependencies]
stockton-skeleton = { path = "../../stockton-skeleton", features = ["vulkan"] }
-stockton-input = { path = "../../stockton-input" }
-stockton-input-codegen = { path = "../../stockton-input-codegen" }
-stockton-levels = { path = "../../stockton-levels" }
-stockton-contrib = { path = "../../stockton-contrib", features = ["delta_time", "flycam"] }
-stockton-render = { path = "../../stockton-render" }
winit = "^0.21"
log = "0.4.0"
simplelog = "^0.10"
image = "0.23.2"
-egui = "^0.12"
legion = { version = "^0.3" }
anyhow = "1.0.40"
+gfx-hal = "^0.8.0"
diff --git a/examples/render-quad/src/data/shader.frag b/examples/render-quad/src/data/shader.frag
new file mode 100644
index 0000000..929073f
--- /dev/null
+++ b/examples/render-quad/src/data/shader.frag
@@ -0,0 +1,11 @@
+#version 450
+
+layout (location = 0) in vec2 frag_pos;
+layout (location = 1) in vec3 frag_color;
+
+layout (location = 0) out vec4 color;
+
+void main()
+{
+ color = vec4(frag_color, 1.0);
+} \ No newline at end of file
diff --git a/examples/render-quad/src/data/shader.vert b/examples/render-quad/src/data/shader.vert
new file mode 100644
index 0000000..5ca3090
--- /dev/null
+++ b/examples/render-quad/src/data/shader.vert
@@ -0,0 +1,16 @@
+#version 450
+
+layout (location = 0) in vec2 position;
+layout (location = 1) in vec3 color;
+
+out gl_PerVertex {
+ vec4 gl_Position;
+};
+layout (location = 1) out vec3 frag_color;
+
+
+void main()
+{
+ gl_Position = vec4(position, 0.5, 1.0);
+ frag_color = color;
+} \ No newline at end of file
diff --git a/examples/render-quad/src/draw_pass.rs b/examples/render-quad/src/draw_pass.rs
new file mode 100644
index 0000000..9b32fcb
--- /dev/null
+++ b/examples/render-quad/src/draw_pass.rs
@@ -0,0 +1,335 @@
+//! Minimal code for drawing any level, based on traits from stockton-levels
+
+use anyhow::{Context, Result};
+use hal::{
+ buffer::SubRange,
+ command::{ClearColor, ClearValue, RenderAttachmentInfo, SubpassContents},
+ format::Format,
+ image::Layout,
+ pass::Attachment,
+ pso::{
+ BlendDesc, BlendOp, BlendState, ColorBlendDesc, ColorMask, DepthStencilDesc, Face, Factor,
+ FrontFace, InputAssemblerDesc, LogicOp, PolygonMode, Primitive, Rasterizer, State,
+ VertexInputRate,
+ },
+};
+use legion::{Entity, IntoQuery};
+use std::{
+ array::IntoIter,
+ iter::{empty, once},
+};
+use stockton_skeleton::{
+ buffers::draw::DrawBuffers,
+ builders::{
+ AttachmentSpec, CompletePipeline, PipelineSpecBuilder, RenderpassSpec, ShaderDesc,
+ ShaderKind, VertexBufferSpec, VertexPrimitiveAssemblerSpec,
+ },
+ draw_passes::util::TargetSpecificResources,
+ mem::{DataPool, StagingPool},
+ queue_negotiator::QueueFamilyNegotiator,
+ types::*,
+ DrawPass, IntoDrawPass, PassPosition, RenderingContext, Session,
+};
+
+use crate::ExampleState;
+
+/// The vertices that go to the shader (XY + RGB)
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+struct Vertex(pub Vector2, pub Vector3);
+
+/// An example draw pass
+pub struct ExampleDrawPass<'a> {
+ /// Index and vertex buffer pair
+ draw_buffers: DrawBuffers<'a, Vertex, DataPool, StagingPool>,
+
+ /// Resources that depend on the surface. This is seperate so that we can deal with surface changes more easily.
+ surface_resources: SurfaceDependentResources,
+
+ /// Entity we get our state from
+ state_ent: Entity,
+}
+
+/// Config for our draw pass. This is turned into our drawpass using [`IntoDrawPass`]
+pub struct ExampleDrawPassConfig {
+ pub state_ent: Entity,
+}
+
+impl<'a, P: PassPosition> DrawPass<P> for ExampleDrawPass<'a> {
+ /// Called every frame to queue actual drawing.
+ fn queue_draw(
+ &mut self,
+ session: &Session,
+ img_view: &ImageViewT,
+ cmd_buffer: &mut CommandBufferT,
+ ) -> anyhow::Result<()> {
+ // Commit any changes to our vertex buffers
+ // We queue this first so that it's executed before any draw commands
+ self.draw_buffers
+ .vertex_buffer
+ .record_commit_cmds(cmd_buffer)?;
+ self.draw_buffers
+ .index_buffer
+ .record_commit_cmds(cmd_buffer)?;
+
+ // Get framebuffer
+ let fb = self.surface_resources.framebuffers.get_next();
+
+ // Get state
+ let (state,) = <(&ExampleState,)>::query().get(&session.world, self.state_ent)?;
+
+ // Begin render pass & bind everything needed
+ unsafe {
+ cmd_buffer.begin_render_pass(
+ &self.surface_resources.pipeline.renderpass,
+ fb,
+ self.surface_resources.pipeline.render_area,
+ vec![RenderAttachmentInfo {
+ image_view: img_view,
+ clear_value: ClearValue {
+ color: ClearColor {
+ float32: [0.0, 0.0, 0.0, 1.0],
+ },
+ },
+ }]
+ .into_iter(),
+ SubpassContents::Inline,
+ );
+ cmd_buffer.bind_graphics_pipeline(&self.surface_resources.pipeline.pipeline);
+
+ // Bind buffers
+ cmd_buffer.bind_vertex_buffers(
+ 0,
+ once((
+ self.draw_buffers.vertex_buffer.get_buffer(),
+ SubRange {
+ offset: 0,
+ size: None,
+ },
+ )),
+ );
+ cmd_buffer.bind_index_buffer(
+ self.draw_buffers.index_buffer.get_buffer(),
+ SubRange {
+ offset: 0,
+ size: None,
+ },
+ hal::IndexType::U16,
+ );
+ }
+
+ // Draw an example
+ self.draw_buffers.index_buffer[0] = (0, 1, 2);
+ self.draw_buffers.vertex_buffer[0] = Vertex(Vector2::new(0.5, 0.5), state.color());
+ self.draw_buffers.vertex_buffer[1] = Vertex(Vector2::new(0.0, -0.5), state.color());
+ self.draw_buffers.vertex_buffer[2] = Vertex(Vector2::new(-0.5, 0.5), state.color());
+
+ unsafe {
+ cmd_buffer.draw_indexed(0..3, 0, 0..1);
+ }
+
+ // Remember to clean up afterwards!
+ unsafe {
+ cmd_buffer.end_render_pass();
+ }
+
+ Ok(())
+ }
+
+ /// Destroy all our vulkan objects
+ fn deactivate(self, context: &mut RenderingContext) -> Result<()> {
+ self.draw_buffers.deactivate(context);
+ self.surface_resources.deactivate(context)?;
+
+ Ok(())
+ }
+
+ /// Deal with a surface change
+ fn handle_surface_change(
+ mut self,
+ _session: &Session,
+ context: &mut RenderingContext,
+ ) -> Result<Self> {
+ // We need to make sure there's never an invalid value for self.surface_resources,
+ // and that we deactivate everything in case of an error (since we'll be dropped in that case).
+ let new_resources = match SurfaceDependentResources::new::<P>(context) {
+ Ok(x) => x,
+ Err(e) => {
+ <Self as DrawPass<P>>::deactivate(self, context)?;
+
+ return Err(e);
+ }
+ };
+
+ let old_resources = self.surface_resources;
+ self.surface_resources = new_resources;
+
+ match old_resources.deactivate(context) {
+ Ok(_) => Ok(self),
+ Err(e) => {
+ <Self as DrawPass<P>>::deactivate(self, context)?;
+ Err(e)
+ }
+ }
+ }
+}
+
+impl<'a, P: PassPosition> IntoDrawPass<ExampleDrawPass<'a>, P> for ExampleDrawPassConfig {
+ /// Create our example draw pass
+ fn init(
+ self,
+ _session: &mut Session,
+ context: &mut RenderingContext,
+ ) -> Result<ExampleDrawPass<'a>> {
+ let surface_resources = SurfaceDependentResources::new::<P>(context)?;
+ let draw_buffers =
+ match DrawBuffers::from_context(context).context("Error creating draw buffers") {
+ Ok(x) => x,
+ Err(e) => {
+ surface_resources.deactivate(context)?;
+ return Err(e);
+ }
+ };
+
+ Ok(ExampleDrawPass {
+ draw_buffers,
+ surface_resources,
+ state_ent: self.state_ent,
+ })
+ }
+
+ fn find_aux_queues(
+ _adapter: &Adapter,
+ _queue_negotiator: &mut QueueFamilyNegotiator,
+ ) -> Result<()> {
+ // We don't need any queues, but we'd need code to find their families here if we did.
+ Ok(())
+ }
+}
+
+/// Used to store resources which depend on the surface, for convenience in handle_surface_change
+struct SurfaceDependentResources {
+ pub pipeline: CompletePipeline,
+ pub framebuffers: TargetSpecificResources<FramebufferT>,
+}
+
+impl SurfaceDependentResources {
+ pub fn new<P: PassPosition>(context: &mut RenderingContext) -> Result<Self> {
+ let (pipeline, framebuffers) = {
+ // Our graphics pipeline
+ // Vulkan has a lot of config, so this is basically always going to be a big builder block
+ let pipeline_spec = PipelineSpecBuilder::default()
+ .rasterizer(Rasterizer {
+ polygon_mode: PolygonMode::Fill,
+ cull_face: Face::NONE,
+ front_face: FrontFace::CounterClockwise,
+ depth_clamping: false,
+ depth_bias: None,
+ conservative: true,
+ line_width: State::Static(1.0),
+ })
+ .depth_stencil(DepthStencilDesc {
+ depth: None,
+ depth_bounds: false,
+ stencil: None,
+ })
+ .blender(BlendDesc {
+ logic_op: Some(LogicOp::Copy),
+ targets: vec![ColorBlendDesc {
+ mask: ColorMask::ALL,
+ blend: Some(BlendState {
+ color: BlendOp::Add {
+ src: Factor::SrcAlpha,
+ dst: Factor::OneMinusSrcAlpha,
+ },
+ alpha: BlendOp::Add {
+ src: Factor::SrcAlpha,
+ dst: Factor::OneMinusSrcAlpha,
+ },
+ }),
+ }],
+ })
+ .primitive_assembler(VertexPrimitiveAssemblerSpec::with_buffers(
+ InputAssemblerDesc::new(Primitive::TriangleList),
+ vec![VertexBufferSpec {
+ attributes: vec![Format::Rg32Sfloat, Format::Rgb32Sfloat],
+ rate: VertexInputRate::Vertex,
+ }],
+ ))
+ .shader_vertex(ShaderDesc {
+ source: include_str!("./data/shader.vert").to_string(),
+ entry: "main".to_string(),
+ kind: ShaderKind::Vertex,
+ })
+ .shader_fragment(ShaderDesc {
+ source: include_str!("./data/shader.frag").to_string(),
+ entry: "main".to_string(),
+ kind: ShaderKind::Fragment,
+ })
+ .renderpass(RenderpassSpec {
+ colors: vec![AttachmentSpec {
+ attachment: Attachment {
+ format: Some(context.properties().color_format),
+ samples: 1,
+ // Here we use PassPosition to get the proper operations
+ // Since, for example, the last pass needs to finish in present mode.
+ ops: P::attachment_ops(),
+ stencil_ops: P::attachment_ops(),
+ layouts: P::layout_as_range(),
+ },
+ // This is the layout we want to deal with in our `queue_draw` function.
+ // It's almost certainly `Layout::ColorAttachmentOptimal`
+ used_layout: Layout::ColorAttachmentOptimal,
+ }],
+ depth: None,
+ inputs: vec![],
+ resolves: vec![],
+ preserves: vec![],
+ })
+ .build()
+ .context("Error building pipeline")?;
+
+ // Lock our device to actually build it
+ // Try to lock the device for as little time as possible
+ let mut device = context.lock_device()?;
+
+ let pipeline = pipeline_spec
+ .build(&mut device, context.properties().extent, empty())
+ .context("Error building pipeline")?;
+
+ // Our framebuffers just have the swapchain framebuffer attachment
+ // TargetSpecificResources makes sure we use a different one each frame.
+ let fat = context.properties().swapchain_framebuffer_attachment();
+ let framebuffers = TargetSpecificResources::new(
+ || unsafe {
+ Ok(device.create_framebuffer(
+ &pipeline.renderpass,
+ IntoIter::new([fat.clone()]),
+ context.properties().extent,
+ )?)
+ },
+ context.properties().image_count as usize,
+ )?;
+
+ (pipeline, framebuffers)
+ };
+
+ Ok(Self {
+ pipeline,
+ framebuffers,
+ })
+ }
+
+ pub fn deactivate(self, context: &mut RenderingContext) -> Result<()> {
+ unsafe {
+ let mut device = context.lock_device()?;
+ for fb in self.framebuffers.dissolve() {
+ device.destroy_framebuffer(fb);
+ }
+
+ self.pipeline.deactivate(&mut device);
+ }
+
+ Ok(())
+ }
+}
diff --git a/examples/render-quad/src/level.rs b/examples/render-quad/src/level.rs
deleted file mode 100644
index 74d1cc3..0000000
--- a/examples/render-quad/src/level.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-use stockton_levels::parts::{
- data::{FaceRef, Geometry, TextureRef},
- HasFaces, HasTextures, HasVisData, IsFace, IsTexture,
-};
-use stockton_skeleton::components::{CameraSettings, Transform};
-
-pub struct DemoLevel {
- pub faces: Box<[Face]>,
- pub textures: Box<[Texture]>,
-}
-
-impl DemoLevel {
- fn face_idx(&self, search: &Face) -> FaceRef {
- for (idx, face) in self.faces.iter().enumerate() {
- if face == search {
- return idx as u32;
- }
- }
- panic!("face not in level")
- }
-}
-
-#[derive(Debug, Clone, PartialEq)]
-pub struct Face {
- pub geometry: Geometry,
- pub texture_idx: TextureRef,
-}
-
-impl HasFaces for DemoLevel {
- type Face = Face;
-
- fn get_face(&self, index: FaceRef) -> Option<&Self::Face> {
- self.faces.get(index as usize)
- }
-}
-
-impl IsFace<DemoLevel> for Face {
- fn index(&self, container: &DemoLevel) -> stockton_levels::parts::data::FaceRef {
- container.face_idx(self)
- }
-
- fn geometry(&self, _container: &DemoLevel) -> Geometry {
- self.geometry.clone()
- }
-
- fn texture_idx(&self, _container: &DemoLevel) -> TextureRef {
- self.texture_idx
- }
-}
-
-pub struct Texture {
- pub name: String,
-}
-
-impl HasTextures for DemoLevel {
- type Texture = Texture;
-
- fn get_texture(&self, idx: TextureRef) -> Option<&Self::Texture> {
- self.textures.get(idx as usize)
- }
-}
-
-impl IsTexture for Texture {
- fn name(&self) -> &str {
- &self.name
- }
-}
-
-impl<'a> HasVisData<'a> for DemoLevel {
- type Faces = std::ops::Range<FaceRef>;
-
- fn get_visible(
- &'a self,
- _transform: &Transform,
- _settings: &CameraSettings,
- ) -> Self::Faces {
- 0..self.faces.len() as u32
- }
-}
diff --git a/examples/render-quad/src/main.rs b/examples/render-quad/src/main.rs
index c5d52a9..1955b51 100644
--- a/examples/render-quad/src/main.rs
+++ b/examples/render-quad/src/main.rs
@@ -1,82 +1,29 @@
//! Renders ./example.bsp geometry: (), texture_idx: () geometry: (), texture_idx: ()
-#[macro_use]
-extern crate stockton_input_codegen;
+extern crate gfx_hal as hal;
#[macro_use]
extern crate legion;
-use std::{
- collections::BTreeMap,
- path::Path,
- sync::{Arc, RwLock},
-};
-
-use stockton_contrib::{delta_time::*, flycam::*};
-use stockton_input::{Axis, InputManager, Mouse};
-use stockton_levels::{
- parts::{data::{Geometry, Vertex}, FsResolver},
- types::Rgba,
-};
-use stockton_render::{
- level::{LevelDrawPass, LevelDrawPassConfig},
- ui::UiDrawPass,
- window::{process_window_events_system, UiState, WindowEvent, WindowFlow},
-};
-use stockton_skeleton::{
- draw_passes::ConsDrawPass, error::full_error_display, Renderer,
- Session, types::*,
- components::{CameraSettings, Transform},
-};
-
use anyhow::{Context, Result};
-use egui::{containers::CentralPanel, Frame};
use log::warn;
+use stockton_skeleton::{error::full_error_display, Renderer, Session};
use winit::{
- event::Event,
+ event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::WindowBuilder,
};
-mod level;
-use level::*;
-
-type Dp<'a> = ConsDrawPass<LevelDrawPass<'a, DemoLevel>, UiDrawPass<'a>>;
+mod draw_pass;
+mod system;
+use draw_pass::*;
+use system::*;
-#[derive(InputManager, Default, Clone, Debug)]
-struct MovementInputs {
- #[axis]
- x: Axis,
-
- #[axis]
- y: Axis,
-
- #[axis]
- z: Axis,
-}
-
-impl FlycamInput for MovementInputs {
- fn get_x_axis(&self) -> &Axis {
- &self.x
- }
- fn get_y_axis(&self) -> &Axis {
- &self.y
- }
- fn get_z_axis(&self) -> &Axis {
- &self.z
- }
-}
-
-#[system]
-fn hello_world(#[resource] ui: &mut UiState) {
- CentralPanel::default()
- .frame(Frame::none())
- .show(ui.ctx(), |ui| {
- ui.heading("Hello, World!");
- });
-}
+/// Alias for our drawpass
+type Dp<'a> = ExampleDrawPass<'a>;
fn main() {
+ // Wrap for full error display
if let Err(err) = try_main() {
eprintln!("{}", full_error_display(err));
}
@@ -101,165 +48,66 @@ fn try_main() -> Result<()> {
.build(&event_loop)
.context("Error creating window")?;
+ // Grab cursor
+ window.set_cursor_visible(false);
if window.set_cursor_grab(true).is_err() {
warn!("warning: cursor not grabbed");
}
- window.set_cursor_visible(false);
-
- // TODO: Parse the map file
- let map = Arc::new(RwLock::new(DemoLevel {
- faces: vec![Face {
- geometry: Geometry::Vertices(
- Vertex {
- position: Vector3::new(-128.0, 128.0, 128.0),
- tex: Vector2::new(0.0, 0.0),
- color: Rgba::from_slice(&[0, 0, 0, 1]),
- },
- Vertex {
- position: Vector3::new(-128.0, -128.0, 128.0),
- tex: Vector2::new(0.0, 1.0),
- color: Rgba::from_slice(&[0, 0, 0, 1]),
- },
- Vertex {
- position: Vector3::new(128.0, 128.0, 128.0),
- tex: Vector2::new(1.0, 0.0),
- color: Rgba::from_slice(&[0, 0, 0, 1]),
- },
- ),
- texture_idx: 0,
- }]
- .into_boxed_slice(),
- textures: vec![Texture {
- name: "example_texture".to_string(),
- }]
- .into_boxed_slice(),
- }));
-
- // Create the UI State
- let ui = UiState::default();
-
- // Create the input manager
- let manager = {
- use stockton_input::InputMutation::*;
- use MovementInputsFields::*;
-
- let mut actions = BTreeMap::new();
- actions.insert(17, (Z, PositiveAxis)); // W
- actions.insert(30, (X, NegativeAxis)); // A
- actions.insert(31, (Z, NegativeAxis)); // S
- actions.insert(32, (X, PositiveAxis)); // D
- actions.insert(29, (Y, NegativeAxis)); // Ctrl
- actions.insert(57, (Y, PositiveAxis)); // Space
-
- MovementInputsManager::new(actions)
- };
-
- // Load everything into the session
+ // Our game world
let mut session = Session::new(move |schedule| {
- schedule
- .add_system(update_deltatime_system())
- .add_system(process_window_events_system::<MovementInputsManager>())
- .flush()
- .add_system(hello_world_system())
- .add_system(flycam_move_system::<MovementInputsManager>());
+ schedule.add_system(mutate_state_system());
});
- session.resources.insert(map.clone());
- session.resources.insert(manager);
- session.resources.insert(Timing::default());
- session.resources.insert(Mouse::default());
- session.resources.insert(ui);
-
- // Add our player entity
- let player = session.world.push((
- Transform {
- position: Vector3::new(0.0, 0.0, 0.0),
- rotation: Vector3::new(0.0, 0.0, 0.0),
- },
- CameraSettings {
- far: 1024.0,
- fov: 90.0,
- near: 0.1,
- },
- FlycamControlled::new(512.0, 400.0),
- ));
+ // An entity to keep track of our state
+ let state_ent = session.world.push((ExampleState::default(),));
// Create the renderer
- let renderer = Renderer::<Dp<'static>>::new(
- &window,
- &mut session,
- (
- LevelDrawPassConfig {
- active_camera: player,
- tex_resolver: FsResolver::new(Path::new("./examples/render-quad/textures"), map),
- },
- (),
- ),
- )?;
-
- let new_control_flow = Arc::new(RwLock::new(ControlFlow::Poll));
- let (window_flow, tx) = WindowFlow::new(new_control_flow.clone());
- session.resources.insert(window_flow);
-
- // Populate the initial UI state
- {
- let ui = &mut session.resources.get_mut::<UiState>().unwrap();
- ui.populate_initial_state(&renderer);
- }
+ let renderer =
+ Renderer::<Dp<'static>>::new(&window, &mut session, ExampleDrawPassConfig { state_ent })?;
+ // We'll be moving it in/out of here, so we need an Option for safety.
let mut renderer = Some(renderer);
// Done loading - This is our main loop.
// It just communicates events to the session and continuously ticks
- event_loop.run(move |event, _, flow| {
- match event {
- Event::MainEventsCleared => {
- window.request_redraw();
- }
- Event::RedrawRequested(_) => {
- session.do_update();
- let r = renderer.take().unwrap();
- match r.render(&session) {
- Ok(r) => {
- renderer = Some(r);
- }
- Err(e) => {
- println!("Error drawing: {}", full_error_display(e));
-
- // TODO: Not really sound
- *(new_control_flow.write().unwrap()) = ControlFlow::Exit;
- }
+ event_loop.run(move |event, _, flow| match event {
+ Event::MainEventsCleared => {
+ window.request_redraw();
+ }
+ Event::RedrawRequested(_) => {
+ session.do_update();
+
+ // Render
+ let r = renderer.take().unwrap();
+ match r.render(&session) {
+ Ok(r) => {
+ renderer = Some(r);
}
- }
- _ => {
- if let Some(we) = WindowEvent::from(&event) {
- tx.send(we).unwrap();
+ Err(e) => {
+ println!("Error drawing: {}", full_error_display(e));
- if let WindowEvent::SizeChanged(_, _) = we {
- let r = renderer.take().unwrap();
- match r.recreate_surface(&session) {
- Ok(r) => {
- renderer = Some(r);
- }
- Err(e) => {
- println!("Error resizing: {}", full_error_display(e));
-
- // TODO: Not really sound
- *(new_control_flow.write().unwrap()) = ControlFlow::Exit;
- }
- }
- }
+ *flow = ControlFlow::Exit;
}
}
}
+ Event::WindowEvent {
+ window_id: _,
+ event: WindowEvent::Resized(_),
+ } => {
+ // (Attempt) resize
+ let r = renderer.take().unwrap();
+ match r.recreate_surface(&session) {
+ Ok(r) => {
+ renderer = Some(r);
+ }
+ Err(e) => {
+ println!("Error resizing: {}", full_error_display(e));
- // Update the control flow if the session has requested it.
- {
- let new_control_flow = new_control_flow.read().unwrap();
- if *new_control_flow != *flow {
- *flow = *new_control_flow;
+ *flow = ControlFlow::Exit;
+ }
}
- };
+ }
+ _ => (),
});
}
diff --git a/examples/render-quad/src/system.rs b/examples/render-quad/src/system.rs
new file mode 100644
index 0000000..3342774
--- /dev/null
+++ b/examples/render-quad/src/system.rs
@@ -0,0 +1,73 @@
+//! An example system that just alternates the colours of our triangle
+
+use stockton_skeleton::types::Vector3;
+
+/// RGB Channels
+#[derive(Debug, Clone, Copy)]
+enum ColorChannel {
+ Red,
+ Green,
+ Blue,
+}
+
+/// A component for our entity.
+#[derive(Debug, Clone, Copy)]
+pub struct ExampleState {
+ channel: ColorChannel,
+ falling: bool,
+ col_val: Vector3,
+}
+
+impl ExampleState {
+ pub fn color(&self) -> Vector3 {
+ self.col_val
+ }
+}
+
+impl Default for ExampleState {
+ fn default() -> Self {
+ Self {
+ channel: ColorChannel::Red,
+ falling: true,
+ col_val: Vector3::new(1.0, 1.0, 1.0),
+ }
+ }
+}
+
+/// The speed at which we change colour
+const TRANSITION_SPEED: f32 = 0.1;
+
+/// Keep changing the colour of any ExampleStates in our world.
+#[system(for_each)]
+pub fn mutate_state(state: &mut ExampleState) {
+ // Which value we're changing
+ let val = match state.channel {
+ ColorChannel::Red => &mut state.col_val.x,
+ ColorChannel::Green => &mut state.col_val.y,
+ ColorChannel::Blue => &mut state.col_val.z,
+ };
+
+ if state.falling {
+ *val -= TRANSITION_SPEED;
+
+ // Fall, then rise
+ if *val <= 0.0 {
+ *val = 0.0;
+ state.falling = false;
+ }
+ } else {
+ *val += TRANSITION_SPEED;
+
+ if *val >= 1.0 {
+ *val = 1.0;
+
+ // Rather than going back to falling, go to the next channel
+ state.falling = true;
+ state.channel = match state.channel {
+ ColorChannel::Red => ColorChannel::Green,
+ ColorChannel::Green => ColorChannel::Blue,
+ ColorChannel::Blue => ColorChannel::Red,
+ }
+ }
+ }
+}
diff --git a/stockton-contrib/Cargo.toml b/stockton-contrib/Cargo.toml
index c6630e2..ba7a70f 100644
--- a/stockton-contrib/Cargo.toml
+++ b/stockton-contrib/Cargo.toml
@@ -12,7 +12,7 @@ stockton-input = { path = "../stockton-input" }
legion = { version = "^0.3" }
[features]
-default = []
+default = ['delta_time']
delta_time = []
flycam = [] \ No newline at end of file
diff --git a/stockton-contrib/src/flycam.rs b/stockton-contrib/src/flycam.rs
index 42b80f6..b281a7a 100644
--- a/stockton-contrib/src/flycam.rs
+++ b/stockton-contrib/src/flycam.rs
@@ -1,7 +1,7 @@
use std::f32::consts::PI;
use stockton_input::{Axis, InputManager, Mouse};
-use stockton_skeleton::{types::Vector3, components::Transform};
+use stockton_skeleton::{components::Transform, types::Vector3};
use crate::delta_time::Timing;
diff --git a/stockton-levels/Cargo.toml b/stockton-levels/Cargo.toml
deleted file mode 100644
index 448a8ba..0000000
--- a/stockton-levels/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-name = "stockton-levels"
-version = "0.1.0"
-authors = ["Oscar <oscar.shrimpton.personal@gmail.com>"]
-description = "Traits relating to levels renderable by stockton."
-repository = "https://github.com/tcmal/stockton"
-homepage = "https://github.com/tcmal/stockton"
-edition = "2018"
-
-[dependencies]
-nalgebra = "^0.20"
-serde = { version = "1.0", features = ["derive"] }
-stockton-skeleton = { path = "../stockton-skeleton" }
-image = "0.23.11"
diff --git a/stockton-levels/src/features.rs b/stockton-levels/src/features.rs
deleted file mode 100644
index b4ddb99..0000000
--- a/stockton-levels/src/features.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// 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/>.
-//! Marker traits for different feature sets
-
-use crate::parts::*;
-
-pub trait MinRenderFeatures<'a>: HasFaces + HasTextures + HasVisData<'a> + Send + Sync {}
-impl<'a, T> MinRenderFeatures<'a> for T where
- T: HasFaces + HasTextures + HasVisData<'a> + Send + Sync
-{
-}
diff --git a/stockton-levels/src/lib.rs b/stockton-levels/src/lib.rs
deleted file mode 100644
index 49609c2..0000000
--- a/stockton-levels/src/lib.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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/>.
-//! Interfaces & Data structures stockton expects when rendering a level.
-
-extern crate nalgebra as na;
-
-pub mod features;
-pub mod parts;
-pub mod prelude;
-pub mod types;
diff --git a/stockton-levels/src/parts/entities.rs b/stockton-levels/src/parts/entities.rs
deleted file mode 100644
index 7a5ac74..0000000
--- a/stockton-levels/src/parts/entities.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-use std::iter::Iterator;
-
-pub type EntityRef = u32;
-
-/// A game entity
-pub trait IsEntity<C: HasEntities + ?Sized> {
- fn get_attr(&self, container: &C) -> Option<&str>;
-}
-
-pub trait HasEntities {
- type Entity: IsEntity<Self>;
-
- fn get_entity(&self, idx: EntityRef) -> Option<&Self::Entity>;
- fn iter_entities(&self) -> Entities<Self> {
- Entities {
- next: 0,
- container: self,
- }
- }
-}
-
-#[derive(Debug, Clone, Copy)]
-pub struct Entities<'a, T: HasEntities + ?Sized> {
- next: EntityRef,
- container: &'a T,
-}
-
-impl<'a, T: HasEntities> Iterator for Entities<'a, T> {
- type Item = &'a T::Entity;
-
- fn next(&mut self) -> Option<Self::Item> {
- let res = self.container.get_entity(self.next);
- self.next += 1;
- res
- }
-}
diff --git a/stockton-levels/src/parts/faces.rs b/stockton-levels/src/parts/faces.rs
deleted file mode 100644
index 1023af7..0000000
--- a/stockton-levels/src/parts/faces.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use super::{textures::TextureRef, vertices::Vertex};
-use serde::{Deserialize, Serialize};
-
-pub type FaceRef = u32;
-
-#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
-pub enum Geometry {
- Vertices(Vertex, Vertex, Vertex),
-}
-
-pub trait IsFace<C: HasFaces + ?Sized> {
- fn index(&self, container: &C) -> FaceRef;
- fn geometry(&self, container: &C) -> Geometry;
- fn texture_idx(&self, container: &C) -> TextureRef;
-}
-
-pub trait HasFaces {
- type Face: IsFace<Self>;
-
- fn get_face(&self, index: FaceRef) -> Option<&Self::Face>;
- fn iter_faces(&self) -> Faces<Self> {
- Faces {
- next: 0,
- container: self,
- }
- }
-}
-
-#[derive(Debug, Clone, Copy)]
-pub struct Faces<'a, T: HasFaces + ?Sized> {
- next: FaceRef,
- container: &'a T,
-}
-
-impl<'a, T: HasFaces> Iterator for Faces<'a, T> {
- type Item = &'a T::Face;
-
- fn next(&mut self) -> Option<Self::Item> {
- let res = self.container.get_face(self.next);
- self.next += 1;
- res
- }
-}
diff --git a/stockton-levels/src/parts/mod.rs b/stockton-levels/src/parts/mod.rs
deleted file mode 100644
index d164bc3..0000000
--- a/stockton-levels/src/parts/mod.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-mod entities;
-mod faces;
-mod textures;
-mod vertices;
-mod visdata;
-
-pub mod data {
- pub use super::entities::{Entities, EntityRef};
- pub use super::faces::{FaceRef, Faces, Geometry};
- pub use super::textures::{TextureRef, Textures};
- pub use super::vertices::{Vertex, VertexRef};
-}
-
-pub use entities::{HasEntities, IsEntity};
-pub use faces::{HasFaces, IsFace};
-pub use textures::{HasTextures, IsTexture, FsResolver};
-pub use visdata::HasVisData;
diff --git a/stockton-levels/src/parts/textures.rs b/stockton-levels/src/parts/textures.rs
deleted file mode 100644
index ae946fd..0000000
--- a/stockton-levels/src/parts/textures.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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 std::{iter::Iterator, path::Path, sync::{Arc, RwLock}};
-use image::{RgbaImage, io::Reader};
-use stockton_skeleton::texture::TextureResolver;
-
-pub type TextureRef = u32;
-
-pub trait IsTexture {
- fn name(&self) -> &str;
-}
-
-pub trait HasTextures {
- type Texture: IsTexture;
-
- fn get_texture(&self, idx: TextureRef) -> Option<&Self::Texture>;
- fn iter_textures(&self) -> Textures<Self> {
- Textures {
- next: 0,
- container: self,
- }
- }
-}
-
-#[derive(Debug, Clone, Copy)]
-pub struct Textures<'a, T: HasTextures + ?Sized> {
- next: TextureRef,
- container: &'a T,
-}
-
-impl<'a, T: HasTextures> Iterator for Textures<'a, T> {
- type Item = &'a T::Texture;
-
- fn next(&mut self) -> Option<Self::Item> {
- let res = self.container.get_texture(self.next);
- self.next += 1;
- res
- }
-}
-
-
-/// A basic filesystem resolver which gets the texture name from any HasTextures Object.
-pub struct FsResolver<'a, T: HasTextures> {
- path: &'a Path,
- map_lock: Arc<RwLock<T>>,
-}
-
-impl<'a, T: HasTextures> FsResolver<'a, T> {
- pub fn new(path: &'a Path, map_lock: Arc<RwLock<T>>) -> Self {
- FsResolver { path, map_lock }
- }
-}
-
-impl<'a, T: HasTextures> TextureResolver for FsResolver<'a, T> {
- type Image = RgbaImage;
-
- fn resolve(&mut self, tex: u32) -> Option<Self::Image> {
- let map = self.map_lock.read().unwrap();
- let tex = map.get_texture(tex)?;
- let path = self.path.join(&tex.name());
-
- if let Ok(file) = Reader::open(path) {
- if let Ok(guessed) = file.with_guessed_format() {
- if let Ok(decoded) = guessed.decode() {
- return Some(decoded.into_rgba8());
- }
- }
- }
-
- None
- }
-}
diff --git a/stockton-levels/src/parts/vertices.rs b/stockton-levels/src/parts/vertices.rs
deleted file mode 100644
index d797afd..0000000
--- a/stockton-levels/src/parts/vertices.rs
+++ /dev/null
@@ -1,155 +0,0 @@
-use crate::types::Rgba;
-use na::{Vector2, Vector3};
-use serde::de;
-use serde::de::{Deserializer, MapAccess, SeqAccess, Visitor};
-use serde::ser::{Serialize, SerializeStruct, Serializer};
-use serde::Deserialize;
-use std::fmt;
-
-pub type VertexRef = u32;
-
-/// A vertex, used to describe a face.
-#[derive(Debug, Clone, Copy, PartialEq)]
-pub struct Vertex {
- pub position: Vector3<f32>,
- pub tex: Vector2<f32>,
- pub color: Rgba,
-}
-
-impl Serialize for Vertex {
- fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
- let mut state = serializer.serialize_struct("Vertex", 5)?;
- state.serialize_field("pos_x", &self.position.x)?;
- state.serialize_field("pos_y", &self.position.y)?;
- state.serialize_field("pos_z", &self.position.z)?;
- state.serialize_field("tex_u", &self.tex.x)?;
- state.serialize_field("tex_v", &self.tex.y)?;
- state.serialize_field("color", &self.color)?;
-
- state.end()
- }
-}
-
-impl<'de> Deserialize<'de> for Vertex {
- fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
- #[derive(Deserialize)]
- #[serde(field_identifier, rename_all = "snake_case")]
- enum Field {
- PosX,
- PosY,
- PosZ,
- TexU,
- TexV,
- Color,
- }
- const FIELDS: &[&str] = &["pos_x", "pos_y", "pos_z", "tex_x", "tex_y", "color"];
-
- struct VertexVisitor;
-
- impl<'de> Visitor<'de> for VertexVisitor {
- type Value = Vertex;
-
- fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter.write_str("struct Vertex")
- }
-
- fn visit_seq<V>(self, mut seq: V) -> Result<Vertex, V::Error>
- where
- V: SeqAccess<'de>,
- {
- let pos_x = seq
- .next_element()?
- .ok_or_else(|| de::Error::invalid_length(0, &self))?;
- let pos_y = seq
- .next_element()?
- .ok_or_else(|| de::Error::invalid_length(1, &self))?;
- let pos_z = seq
- .next_element()?
- .ok_or_else(|| de::Error::invalid_length(2, &self))?;
- let tex_u = seq
- .next_element()?
- .ok_or_else(|| de::Error::invalid_length(3, &self))?;
- let tex_v = seq
- .next_element()?
- .ok_or_else(|| de::Error::invalid_length(4, &self))?;
- let color = seq
- .next_element()?
- .ok_or_else(|| de::Error::invalid_length(5, &self))?;
- Ok(Vertex {
- position: Vector3::new(pos_x, pos_y, pos_z),
- tex: Vector2::new(tex_u, tex_v),
- color,
- })
- }
-
- fn visit_map<V>(self, mut map: V) -> Result<Vertex, V::Error>
- where
- V: MapAccess<'de>,
- {
- let mut pos_x = None;
- let mut pos_y = None;
- let mut pos_z = None;
- let mut tex_u = None;
- let mut tex_v = None;
- let mut color = None;
- while let Some(key) = map.next_key()? {
- match key {
- Field::PosX => {
- if pos_x.is_some() {
- return Err(de::Error::duplicate_field("pos_x"));
- }
- pos_x = Some(map.next_value()?);
- }
- Field::PosY => {
- if pos_y.is_some() {
- return Err(de::Error::duplicate_field("pos_y"));
- }
- pos_y = Some(map.next_value()?);
- }
- Field::PosZ => {
- if pos_z.is_some() {
- return Err(de::Error::duplicate_field("pos_z"));
- }
- pos_z = Some(map.next_value()?);
- }
- Field::TexU => {
- if tex_u.is_some() {
- return Err(de::Error::duplicate_field("tex_u"));
- }
- tex_u = Some(map.next_value()?);
- }
- Field::TexV => {
- if tex_v.is_some() {
- return Err(de::Error::duplicate_field("tex_v"));
- }
- tex_v = Some(map.next_value()?);
- }
- Field::Color => {
- if color.is_some() {
- return Err(de::Error::duplicate_field("color"));
- }
- color = Some(map.next_value()?);
- }
- }
- }
- let position = Vector3::new(
- pos_x.ok_or_else(|| de::Error::missing_field("pos_x"))?,
- pos_y.ok_or_else(|| de::Error::missing_field("pos_y"))?,
- pos_z.ok_or_else(|| de::Error::missing_field("pos_z"))?,
- );
- let tex = Vector2::new(
- tex_u.ok_or_else(|| de::Error::missing_field("tex_u"))?,
- tex_v.ok_or_else(|| de::Error::missing_field("tex_v"))?,
- );
- let color = color.ok_or_else(|| de::Error::missing_field("nanos"))?;
- Ok(Vertex {
- position,
- tex,
- color,
- })
- }
- }
-
- deserializer.deserialize_struct("Vertex", FIELDS, VertexVisitor)
- }
-}
diff --git a/stockton-levels/src/parts/visdata.rs b/stockton-levels/src/parts/visdata.rs
deleted file mode 100644
index 3e58d4c..0000000
--- a/stockton-levels/src/parts/visdata.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-use super::faces::FaceRef;
-use std::iter::Iterator;
-use stockton_skeleton::components::{CameraSettings, Transform};
-
-pub trait HasVisData<'a> {
- type Faces: Iterator<Item = FaceRef>;
- fn get_visible(&'a self, transform: &Transform, settings: &CameraSettings) -> Self::Faces;
-}
diff --git a/stockton-levels/src/prelude.rs b/stockton-levels/src/prelude.rs
deleted file mode 100644
index 0da890b..0000000
--- a/stockton-levels/src/prelude.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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/>.
-//! Common traits, etc.
-
-pub use crate::features::*;
-pub use crate::parts::*;
diff --git a/stockton-levels/src/types.rs b/stockton-levels/src/types.rs
deleted file mode 100644
index dad824c..0000000
--- a/stockton-levels/src/types.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-//! Various types used in parsed BSP files.
-
-use serde::{Deserialize, Serialize};
-use std::convert::TryInto;
-
-/// RGBA Colour (0-255)
-#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
-pub struct Rgba {
- pub r: u8,
- pub g: u8,
- pub b: u8,
- pub a: u8,
-}
-
-impl Rgba {
- /// Interpret the given bytes as an RGBA colour.
- pub fn from_bytes(bytes: [u8; 4]) -> Rgba {
- Rgba {
- r: bytes[0],
- g: bytes[1],
- b: bytes[2],
- a: bytes[3],
- }
- }
-
- /// Convert a slice to an RGBA colour
- /// # Panics
- /// If slice is not 4 bytes long.
- pub fn from_slice(slice: &[u8]) -> Rgba {
- Rgba::from_bytes(slice.try_into().unwrap())
- }
-}
-
-/// RGB Colour (0-255)
-#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
-pub struct Rgb {
- pub r: u8,
- pub g: u8,
- pub b: u8,
-}
-
-impl Rgb {
- /// 255, 255, 255
- pub fn white() -> Rgb {
- Rgb {
- r: 255,
- g: 255,
- b: 255,
- }
- }
-
- /// Interpret the given bytes as an RGB colour.
- pub fn from_bytes(bytes: [u8; 3]) -> Rgb {
- Rgb {
- r: bytes[0],
- g: bytes[1],
- b: bytes[2],
- }
- }
-
- /// Convert a slice to an RGB colour
- /// # Panics
- /// If slice is not 3 bytes long.
- pub fn from_slice(slice: &[u8]) -> Rgb {
- Rgb::from_bytes(slice.try_into().unwrap())
- }
-}
diff --git a/stockton-render/Cargo.toml b/stockton-render/Cargo.toml
deleted file mode 100644
index 3ba8c01..0000000
--- a/stockton-render/Cargo.toml
+++ /dev/null
@@ -1,22 +0,0 @@
-[package]
-name = "stockton-render"
-version = "0.1.0"
-authors = ["tcmal <oscar.shrimpton.personal@gmail.com>"]
-edition = "2018"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-stockton-skeleton = { path = "../stockton-skeleton" }
-stockton-levels = { path = "../stockton-levels" }
-stockton-input = { path = "../stockton-input" }
-anyhow = "1.0.40"
-egui = "^0.12"
-epaint = "^0.12"
-gfx-hal = "^0.8.0"
-shaderc = "^0.7"
-legion = { version = "^0.3" }
-log = "0.4.0"
-winit = "^0.21"
-nalgebra-glm = "^0.6"
-thiserror = "1.0.25"
diff --git a/stockton-render/src/data/3d.frag b/stockton-render/src/data/3d.frag
deleted file mode 100644
index 336d9fe..0000000
--- a/stockton-render/src/data/3d.frag
+++ /dev/null
@@ -1,15 +0,0 @@
-#version 450
-
-// 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_tex;
-
-layout (location = 0) out vec4 color;
-
-void main()
-{
- color = texture(sampler2D(tex[frag_tex % 8], samp[frag_tex % 8]), frag_uv);
-} \ No newline at end of file
diff --git a/stockton-render/src/data/3d.vert b/stockton-render/src/data/3d.vert
deleted file mode 100644
index aaee1a5..0000000
--- a/stockton-render/src/data/3d.vert
+++ /dev/null
@@ -1,23 +0,0 @@
-#version 450
-
-// DescriptorSet 0 = Matrices
-layout (push_constant) uniform PushConsts {
- mat4 vp;
-} push;
-
-layout (location = 0) in vec3 position;
-layout (location = 1) in int tex;
-layout (location = 2) in vec2 uv;
-
-out gl_PerVertex {
- vec4 gl_Position;
-};
-layout (location = 1) out vec2 frag_uv;
-layout (location = 2) out flat int frag_tex;
-
-void main()
-{
- gl_Position = push.vp * vec4(position, 1.0);
- frag_uv = uv;
- frag_tex = tex;
-} \ No newline at end of file
diff --git a/stockton-render/src/data/ui.frag b/stockton-render/src/data/ui.frag
deleted file mode 100644
index c30c99e..0000000
--- a/stockton-render/src/data/ui.frag
+++ /dev/null
@@ -1,15 +0,0 @@
-#version 450
-#extension GL_ARB_separate_shader_objects : enable
-
-// 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 vec4 frag_col;
-
-layout (location = 0) out vec4 color;
-
-void main() {
- color = texture(sampler2D(tex[0], samp[0]), frag_uv) * frag_col;
-} \ No newline at end of file
diff --git a/stockton-render/src/data/ui.vert b/stockton-render/src/data/ui.vert
deleted file mode 100644
index 8912e96..0000000
--- a/stockton-render/src/data/ui.vert
+++ /dev/null
@@ -1,37 +0,0 @@
-#version 450
-
-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 vec4 col;
-
-out gl_PerVertex {
- vec4 gl_Position;
-};
-layout (location = 1) out vec2 frag_uv;
-layout (location = 2) out vec4 frag_col;
-
-vec3 linear_from_srgb(vec3 srgb) {
- bvec3 cutoff = lessThan(srgb, vec3(10.31475));
- vec3 lower = srgb / vec3(3294.6);
- vec3 higher = pow((srgb + vec3(14.025)) / vec3(269.025), vec3(2.4));
- return mix(higher, lower, cutoff);
-}
-
-vec4 linear_from_srgba(vec4 srgba) {
- return vec4(linear_from_srgb(srgba.rgb * 255.0), srgba.a);
-}
-
-void main() {
- gl_Position = vec4(
- 2.0 * pos.x / push.screen_size.x - 1.0,
- 2.0 * pos.y / push.screen_size.y - 1.0,
- 0.0,
- 1.0
- );
- frag_uv = uv;
- frag_col = linear_from_srgba(col);
-}
diff --git a/stockton-render/src/level.rs b/stockton-render/src/level.rs
deleted file mode 100644
index dd4d61a..0000000
--- a/stockton-render/src/level.rs
+++ /dev/null
@@ -1,554 +0,0 @@
-//! Minimal code for drawing any level, based on traits from stockton-levels
-
-use stockton_levels::{
- features::MinRenderFeatures,
- parts::{data::Geometry, IsFace},
-};
-use stockton_skeleton::{
- buffers::{
- draw::{DrawBuffers, INITIAL_INDEX_SIZE, INITIAL_VERT_SIZE},
- image::{BoundImageView, ImageSpec, DEPTH_RESOURCES},
- },
- builders::{
- AttachmentSpec, CompletePipeline, PipelineSpecBuilder, RenderpassSpec, ShaderDesc,
- VertexBufferSpec, VertexPrimitiveAssemblerSpec,
- },
- RenderingContext,
- Session,
- DrawPass, IntoDrawPass, PassPosition,
- draw_passes::{util::TargetSpecificResources},
- error::LockPoisoned,
- mem::{DataPool, DepthBufferPool, StagingPool, TexturesPool},
- queue_negotiator::QueueFamilyNegotiator,
- texture::{TextureResolver, TexLoadQueue, TextureLoadConfig, TextureRepo},
- types::*,
- components::{CameraSettings, Transform},
-};
-
-use anyhow::{Context, Result};
-use hal::{
- buffer::SubRange,
- command::{ClearColor, ClearDepthStencil, ClearValue, RenderAttachmentInfo, SubpassContents},
- format::Format,
- image::{Filter, FramebufferAttachment, Layout, Usage, ViewCapabilities, WrapMode},
- pass::{Attachment, AttachmentLoadOp, AttachmentOps, AttachmentStoreOp},
- pso::{
- BlendDesc, BlendOp, BlendState, ColorBlendDesc, ColorMask, Comparison, DepthStencilDesc,
- DepthTest, Face, Factor, FrontFace, InputAssemblerDesc, LogicOp, PolygonMode, Primitive,
- Rasterizer, ShaderStageFlags, State, VertexInputRate,
- },
-};
-use legion::{Entity, IntoQuery};
-use na::{look_at_lh, perspective_lh_zo};
-use shaderc::ShaderKind;
-use std::{
- array::IntoIter,
- convert::TryInto,
- iter::{empty, once},
- marker::PhantomData,
- sync::{Arc, RwLock},
-};
-use thiserror::Error;
-
-/// The Vertexes that go to the shader
-#[derive(Debug, Clone, Copy)]
-struct UvPoint(pub Vector3, pub i32, pub Vector2);
-
-/// Draw a level
-pub struct LevelDrawPass<'a, M> {
- repo: TextureRepo<TexturesPool, StagingPool>,
- active_camera: Entity,
- draw_buffers: DrawBuffers<'a, UvPoint, DataPool, StagingPool>,
- surface_resources: SurfaceDependentResources,
- _d: PhantomData<M>,
-}
-
-impl<'a, M, P: PassPosition> DrawPass<P> for LevelDrawPass<'a, M>
-where
- M: for<'b> MinRenderFeatures<'b> + 'static,
-{
- fn queue_draw(
- &mut self,
- session: &Session,
- img_view: &ImageViewT,
- cmd_buffer: &mut CommandBufferT,
- ) -> anyhow::Result<()> {
- // We might have loaded more textures
- self.repo.process_responses();
-
- // Make sure we update the vertex buffers after they're written to, but before they're read from.
- self.draw_buffers
- .vertex_buffer
- .record_commit_cmds(cmd_buffer)?;
- self.draw_buffers
- .index_buffer
- .record_commit_cmds(cmd_buffer)?;
-
- // Get level & camera
- let mut query = <(&Transform, &CameraSettings)>::query();
- let (camera_transform, camera_settings) = query
- .get(&session.world, self.active_camera)
- .context("Couldn't find camera components")?;
-
- let camera_vp = {
- let aspect_ratio = self.surface_resources.pipeline.render_area.w as f32
- / self.surface_resources.pipeline.render_area.h as f32;
-
- // Get look direction from euler angles
- let direction = euler_to_direction(&camera_transform.rotation);
-
- // Converts world space to camera space
- let view_matrix = look_at_lh(
- &camera_transform.position,
- &(camera_transform.position + direction),
- &Vector3::new(0.0, 1.0, 0.0),
- );
-
- // Converts camera space to screen space
- let projection_matrix = {
- let mut temp = perspective_lh_zo(
- aspect_ratio,
- camera_settings.fov,
- camera_settings.near,
- camera_settings.far,
- );
-
- // Vulkan's co-ord system is different from OpenGLs
- temp[(1, 1)] *= -1.0;
-
- temp
- };
-
- // Chain them together into a single matrix
- projection_matrix * view_matrix
- };
- let map_lock: Arc<RwLock<M>> = session.resources.get::<Arc<RwLock<M>>>().unwrap().clone();
- let map = map_lock.read().map_err(|_| LockPoisoned::Map)?;
-
- // Get framebuffer and depth buffer
- let fb = self.surface_resources.framebuffers.get_next();
- let db = self.surface_resources.depth_buffers.get_next();
-
- unsafe {
- cmd_buffer.begin_render_pass(
- &self.surface_resources.pipeline.renderpass,
- fb,
- self.surface_resources.pipeline.render_area,
- vec![
- RenderAttachmentInfo {
- image_view: img_view,
- clear_value: ClearValue {
- color: ClearColor {
- float32: [0.0, 0.0, 0.0, 1.0],
- },
- },
- },
- RenderAttachmentInfo {
- image_view: &*db.img_view(),
- clear_value: ClearValue {
- depth_stencil: ClearDepthStencil {
- depth: 1.0,
- stencil: 0,
- },
- },
- },
- ]
- .into_iter(),
- SubpassContents::Inline,
- );
- cmd_buffer.bind_graphics_pipeline(&self.surface_resources.pipeline.pipeline);
-
- // VP Matrix
- let vp = &*(camera_vp.data.as_slice() as *const [f32] as *const [u32]);
-
- cmd_buffer.push_graphics_constants(
- &self.surface_resources.pipeline.pipeline_layout,
- ShaderStageFlags::VERTEX,
- 0,
- vp,
- );
-
- // Bind buffers
- cmd_buffer.bind_vertex_buffers(
- 0,
- once((
- self.draw_buffers.vertex_buffer.get_buffer(),
- SubRange {
- offset: 0,
- size: None,
- },
- )),
- );
- cmd_buffer.bind_index_buffer(
- self.draw_buffers.index_buffer.get_buffer(),
- SubRange {
- offset: 0,
- size: None,
- },
- hal::IndexType::U16,
- );
- }
-
- // Get visible faces
- let mut faces = map.get_visible(camera_transform, camera_settings);
-
- // Iterate over faces, copying them in and drawing groups that use the same texture chunk all at once.
- let face = faces.next();
- if let Some(face) = face {
- let mut face = map.get_face(face).ok_or(LevelError::BadReference)?;
- let mut current_chunk = face.texture_idx(&map) as usize / 8;
- let mut chunk_start = 0;
-
- let mut curr_vert_idx: usize = 0;
- let mut curr_idx_idx: usize = 0;
- loop {
- if current_chunk != face.texture_idx(&map) as usize / 8 {
- // Last index was last of group, so draw it all if textures are loaded.
- self.draw_or_queue(
- current_chunk,
- cmd_buffer,
- chunk_start as u32,
- curr_idx_idx as u32,
- )?;
-
- // Next group of same-chunked faces starts here.
- chunk_start = curr_idx_idx;
- current_chunk = face.texture_idx(&map) as usize / 8;
- }
-
- match face.geometry(&map) {
- Geometry::Vertices(v1, v2, v3) => {
- for v in &[v1, v2, v3] {
- let uvp =
- UvPoint(v.position, face.texture_idx(&map).try_into()?, v.tex);
-
- self.draw_buffers.vertex_buffer[curr_vert_idx] = uvp;
- curr_vert_idx += 1;
- }
- self.draw_buffers.index_buffer[curr_idx_idx] = (
- curr_vert_idx as u16 - 3,
- curr_vert_idx as u16 - 2,
- curr_vert_idx as u16 - 1,
- );
- curr_idx_idx += 1;
- }
- }
-
- if curr_vert_idx >= INITIAL_VERT_SIZE.try_into()?
- || curr_idx_idx >= INITIAL_INDEX_SIZE.try_into()?
- {
- println!("out of vertex buffer space!");
- break;
- }
-
- match faces.next() {
- Some(x) => face = map.get_face(x).ok_or(LevelError::BadReference)?,
- None => break,
- };
- }
-
- // Draw the final group of chunks
- self.draw_or_queue(
- current_chunk,
- cmd_buffer,
- chunk_start as u32,
- curr_idx_idx as u32,
- )?;
- }
-
- unsafe {
- cmd_buffer.end_render_pass();
- }
-
- Ok(())
- }
-
- fn deactivate(self, context: &mut RenderingContext) -> Result<()> {
- self.draw_buffers.deactivate(context);
- self.surface_resources.deactivate(context)?;
- self.repo.deactivate(context);
-
- Ok(())
- }
-
- fn handle_surface_change(
- mut self,
- _session: &Session,
- context: &mut RenderingContext,
- ) -> Result<Self> {
- let new_resources =
- SurfaceDependentResources::new::<P>(context, &*self.repo.get_ds_layout()?)?;
- let old_resources = self.surface_resources;
- self.surface_resources = new_resources;
-
- match old_resources.deactivate(context) {
- Ok(_) => Ok(self),
- Err(e) => {
- <Self as DrawPass<P>>::deactivate(self, context)?;
- Err(e)
- }
- }
- }
-}
-
-impl<'a, M> LevelDrawPass<'a, M> {
- fn draw_or_queue(
- &mut self,
- current_chunk: usize,
- cmd_buffer: &mut CommandBufferT,
- chunk_start: u32,
- curr_idx_idx: u32,
- ) -> Result<()> {
- if let Some(ds) = self.repo.attempt_get_descriptor_set(current_chunk) {
- unsafe {
- cmd_buffer.bind_graphics_descriptor_sets(
- &*self.surface_resources.pipeline.pipeline_layout,
- 0,
- once(ds),
- empty(),
- );
- cmd_buffer.draw_indexed(chunk_start * 3..(curr_idx_idx * 3) + 1, 0, 0..1);
- }
- } else {
- self.repo.queue_load(current_chunk)?
- }
-
- Ok(())
- }
-}
-
-pub struct LevelDrawPassConfig<R> {
- pub active_camera: Entity,
- pub tex_resolver: R,
-}
-
-impl<'a, M, R, P> IntoDrawPass<LevelDrawPass<'a, M>, P> for LevelDrawPassConfig<R>
-where
- M: for<'b> MinRenderFeatures<'b> + 'static,
- R: TextureResolver + Send + Sync + 'static,
- P: PassPosition,
-{
- fn init(
- self,
- _session: &mut Session,
- context: &mut RenderingContext,
- ) -> Result<LevelDrawPass<'a, M>> {
- let repo = TextureRepo::new::<_, TexLoadQueue>(
- context,
- TextureLoadConfig {
- resolver: self.tex_resolver,
- filter: Filter::Linear,
- wrap_mode: WrapMode::Tile,
- },
- )
- .context("Error creating texture repo")?;
- let draw_buffers =
- DrawBuffers::from_context(context).context("Error creating draw buffers")?;
-
- let surface_resources =
- SurfaceDependentResources::new::<P>(context, &*repo.get_ds_layout()?)?;
-
- Ok(LevelDrawPass {
- repo,
- draw_buffers,
- active_camera: self.active_camera,
- surface_resources,
- _d: PhantomData,
- })
- }
-
- fn find_aux_queues(
- adapter: &Adapter,
- queue_negotiator: &mut QueueFamilyNegotiator,
- ) -> Result<()> {
- queue_negotiator.find(adapter, &TexLoadQueue, 1)?;
-
- Ok(())
- }
-}
-
-/// Indicates an issue with the level object being used
-#[derive(Debug, Error)]
-pub enum LevelError {
- #[error("Referential Integrity broken")]
- BadReference,
-}
-
-/// Used to store resources which depend on the surface, for convenience in handle_surface_change
-struct SurfaceDependentResources {
- pub pipeline: CompletePipeline,
- pub framebuffers: TargetSpecificResources<FramebufferT>,
- pub depth_buffers: TargetSpecificResources<BoundImageView<DepthBufferPool>>,
-}
-
-impl SurfaceDependentResources {
- pub fn new<P: PassPosition>(
- context: &mut RenderingContext,
- ds_layout: &DescriptorSetLayoutT,
- ) -> Result<Self> {
- let db_spec = ImageSpec {
- width: context.properties().extent.width,
- height: context.properties().extent.height,
- format: context.properties().depth_format,
- usage: Usage::DEPTH_STENCIL_ATTACHMENT,
- resources: DEPTH_RESOURCES,
- };
- let img_count = context.properties().image_count;
-
- let depth_buffers = TargetSpecificResources::new(
- || {
- BoundImageView::from_context(context, &db_spec)
- .context("Error creating depth buffer")
- },
- img_count as usize,
- )?;
-
- let (pipeline, framebuffers) = {
- let pipeline_spec = PipelineSpecBuilder::default()
- .rasterizer(Rasterizer {
- polygon_mode: PolygonMode::Fill,
- cull_face: Face::BACK,
- front_face: FrontFace::CounterClockwise,
- depth_clamping: false,
- depth_bias: None,
- conservative: true,
- line_width: State::Static(1.0),
- })
- .depth_stencil(DepthStencilDesc {
- depth: Some(DepthTest {
- fun: Comparison::Less,
- write: true,
- }),
- depth_bounds: false,
- stencil: None,
- })
- .blender(BlendDesc {
- logic_op: Some(LogicOp::Copy),
- targets: vec![ColorBlendDesc {
- mask: ColorMask::ALL,
- blend: Some(BlendState {
- color: BlendOp::Add {
- src: Factor::SrcAlpha,
- dst: Factor::OneMinusSrcAlpha,
- },
- alpha: BlendOp::Add {
- src: Factor::SrcAlpha,
- dst: Factor::OneMinusSrcAlpha,
- },
- }),
- }],
- })
- .primitive_assembler(VertexPrimitiveAssemblerSpec::with_buffers(
- InputAssemblerDesc::new(Primitive::TriangleList),
- vec![VertexBufferSpec {
- attributes: vec![Format::Rgb32Sfloat, Format::R32Sint, Format::Rg32Sfloat],
- rate: VertexInputRate::Vertex,
- }],
- ))
- .shader_vertex(ShaderDesc {
- source: include_str!("./data/3d.vert").to_string(),
- entry: "main".to_string(),
- kind: ShaderKind::Vertex,
- })
- .shader_fragment(ShaderDesc {
- source: include_str!("./data/3d.frag").to_string(),
- entry: "main".to_string(),
- kind: ShaderKind::Fragment,
- })
- .push_constants(vec![(ShaderStageFlags::VERTEX, 0..64)])
- .renderpass(RenderpassSpec {
- colors: vec![AttachmentSpec {
- attachment: Attachment {
- format: Some(context.properties().color_format),
- samples: 1,
- ops: P::attachment_ops(),
- stencil_ops: P::attachment_ops(),
- layouts: P::layout_as_range(),
- },
-
- used_layout: Layout::ColorAttachmentOptimal,
- }],
- depth: Some(AttachmentSpec {
- attachment: Attachment {
- format: Some(context.properties().depth_format),
- samples: 1,
- ops: AttachmentOps::new(
- AttachmentLoadOp::Clear,
- AttachmentStoreOp::DontCare,
- ),
- stencil_ops: AttachmentOps::new(
- AttachmentLoadOp::DontCare,
- AttachmentStoreOp::DontCare,
- ),
- layouts: Layout::Undefined..Layout::DepthStencilAttachmentOptimal,
- },
- used_layout: Layout::DepthStencilAttachmentOptimal,
- }),
- inputs: vec![],
- resolves: vec![],
- preserves: vec![],
- })
- .build()
- .context("Error building pipeline")?;
- let mut device = context.lock_device()?;
-
- let pipeline = pipeline_spec
- .build(&mut device, context.properties().extent, once(ds_layout))
- .context("Error building pipeline")?;
-
- let fat = context.properties().swapchain_framebuffer_attachment();
- let dat = FramebufferAttachment {
- usage: Usage::DEPTH_STENCIL_ATTACHMENT,
- format: context.properties().depth_format,
- view_caps: ViewCapabilities::empty(),
- };
-
- let framebuffers = TargetSpecificResources::new(
- || unsafe {
- Ok(device.create_framebuffer(
- &pipeline.renderpass,
- IntoIter::new([fat.clone(), dat.clone()]),
- context.properties().extent,
- )?)
- },
- context.properties().image_count as usize,
- )?;
-
- (pipeline, framebuffers)
- };
-
- Ok(Self {
- pipeline,
- framebuffers,
- depth_buffers,
- })
- }
-
- pub fn deactivate(self, context: &mut RenderingContext) -> Result<()> {
- for db in self.depth_buffers.dissolve() {
- db.deactivate_with_context(context);
- }
- unsafe {
- let mut device = context.lock_device()?;
- for fb in self.framebuffers.dissolve() {
- device.destroy_framebuffer(fb);
- }
-
- self.pipeline.deactivate(&mut device);
- }
-
- Ok(())
- }
-}
-
-fn euler_to_direction(euler: &Vector3) -> Vector3 {
- let pitch = euler.x;
- let yaw = euler.y;
- let _roll = euler.z; // TODO: Support camera roll
-
- Vector3::new(
- yaw.sin() * pitch.cos(),
- pitch.sin(),
- yaw.cos() * pitch.cos(),
- )
-}
diff --git a/stockton-render/src/lib.rs b/stockton-render/src/lib.rs
deleted file mode 100644
index 34f5117..0000000
--- a/stockton-render/src/lib.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#[macro_use]
-extern crate legion;
-extern crate gfx_hal as hal;
-extern crate nalgebra_glm as na;
-
-pub mod level;
-pub mod ui;
-pub mod window;
diff --git a/stockton-render/src/ui.rs b/stockton-render/src/ui.rs
deleted file mode 100644
index 981be02..0000000
--- a/stockton-render/src/ui.rs
+++ /dev/null
@@ -1,421 +0,0 @@
-//! Minimal code for drawing any level, based on traits from stockton-levels
-use crate::window::UiState;
-
-use stockton_skeleton::{
- buffers::draw::DrawBuffers,
- builders::{
- AttachmentSpec, CompletePipeline, PipelineSpecBuilder, RenderpassSpec, ShaderDesc,
- VertexBufferSpec, VertexPrimitiveAssemblerSpec,
- },
- RenderingContext,
- Session,
- draw_passes::{util::TargetSpecificResources, DrawPass, IntoDrawPass, PassPosition},
- mem::{DataPool, StagingPool, TexturesPool},
- queue_negotiator::QueueFamilyNegotiator,
- texture::{
- TextureResolver, LoadableImage, TexLoadQueue, TextureLoadConfig, TextureRepo,
- },
- types::*,
-};
-
-use std::{
- array::IntoIter,
- convert::TryInto,
- iter::{empty, once},
- sync::Arc,
-};
-
-use anyhow::{anyhow, Context, Result};
-use egui::{ClippedMesh, TextureId};
-use egui::{CtxRef, Texture};
-use hal::{
- buffer::SubRange,
- command::{ClearColor, ClearValue, RenderAttachmentInfo, SubpassContents},
- format::Format,
- image::Layout,
- pass::Attachment,
- pso::{
- BlendDesc, BlendOp, BlendState, ColorBlendDesc, ColorMask, DepthStencilDesc, Face, Factor,
- FrontFace, InputAssemblerDesc, LogicOp, PolygonMode, Primitive, Rasterizer, Rect,
- ShaderStageFlags, State, VertexInputRate,
- },
-};
-use shaderc::ShaderKind;
-
-#[derive(Debug)]
-pub struct UiPoint(pub Vector2, pub Vector2, pub [f32; 4]);
-
-/// Draw a Ui object
-pub struct UiDrawPass<'a> {
- repo: TextureRepo<TexturesPool, StagingPool>,
- draw_buffers: DrawBuffers<'a, UiPoint, DataPool, StagingPool>,
-
- surface_resources: SurfaceDependentResources,
-}
-
-impl<'a, P: PassPosition> DrawPass<P> for UiDrawPass<'a> {
- fn queue_draw(
- &mut self,
- session: &Session,
- img_view: &ImageViewT,
- cmd_buffer: &mut CommandBufferT,
- ) -> anyhow::Result<()> {
- // We might have loaded more textures
- self.repo.process_responses();
-
- // Make sure we update the vertex buffers after they're written to, but before they're read from.
- self.draw_buffers
- .vertex_buffer
- .record_commit_cmds(cmd_buffer)?;
- self.draw_buffers
- .index_buffer
- .record_commit_cmds(cmd_buffer)?;
-
- // Get level & camera
- let ui: &mut UiState = &mut session.resources.get_mut::<UiState>().unwrap();
-
- // Get framebuffer and depth buffer
- let fb = self.surface_resources.framebuffers.get_next();
- unsafe {
- cmd_buffer.begin_render_pass(
- &self.surface_resources.pipeline.renderpass,
- fb,
- self.surface_resources.pipeline.render_area,
- vec![RenderAttachmentInfo {
- image_view: img_view,
- clear_value: ClearValue {
- color: ClearColor {
- float32: [0.0, 0.0, 0.0, 1.0],
- },
- },
- }]
- .into_iter(),
- SubpassContents::Inline,
- );
- cmd_buffer.bind_graphics_pipeline(&self.surface_resources.pipeline.pipeline);
-
- // Bind buffers
- cmd_buffer.bind_vertex_buffers(
- 0,
- once((
- self.draw_buffers.vertex_buffer.get_buffer(),
- SubRange {
- offset: 0,
- size: None,
- },
- )),
- );
- cmd_buffer.bind_index_buffer(
- self.draw_buffers.index_buffer.get_buffer(),
- SubRange {
- offset: 0,
- size: None,
- },
- hal::IndexType::U16,
- );
- }
-
- let (_out, shapes) = ui.end_frame();
- let screen = ui
- .dimensions()
- .ok_or_else(|| anyhow!("UI not set up properly."))?;
- let shapes = ui.ctx().tessellate(shapes);
-
- let mut next_idx_idx = 0;
- let mut next_vert_idx = 0;
- for ClippedMesh(rect, tris) in shapes.iter() {
- assert!(tris.texture_id == TextureId::Egui);
-
- // Copy triangles/indicies
- for i in (0..tris.indices.len()).step_by(3) {
- self.draw_buffers.index_buffer[next_idx_idx + (i / 3)] = (
- tris.indices[i].try_into()?,
- tris.indices[i + 1].try_into()?,
- tris.indices[i + 2].try_into()?,
- );
- }
-
- for (i, vertex) in tris.vertices.iter().enumerate() {
- self.draw_buffers.vertex_buffer[next_vert_idx + i] = UiPoint(
- Vector2::new(vertex.pos.x, vertex.pos.y),
- Vector2::new(vertex.uv.x, vertex.uv.y),
- [
- vertex.color.r() as f32 / 255.0,
- vertex.color.g() as f32 / 255.0,
- vertex.color.b() as f32 / 255.0,
- vertex.color.a() as f32 / 255.0,
- ],
- );
- }
-
- // TODO: *Properly* deal with textures
- if let Some(ds) = self.repo.attempt_get_descriptor_set(0) {
- unsafe {
- cmd_buffer.push_graphics_constants(
- &self.surface_resources.pipeline.pipeline_layout,
- ShaderStageFlags::VERTEX,
- 0,
- &[screen.x.to_bits(), screen.y.to_bits()],
- );
-
- cmd_buffer.set_scissors(
- 0,
- IntoIter::new([Rect {
- x: rect.min.x as i16,
- y: rect.min.y as i16,
- w: rect.width() as i16,
- h: rect.height() as i16,
- }]),
- );
- cmd_buffer.bind_graphics_descriptor_sets(
- &self.surface_resources.pipeline.pipeline_layout,
- 0,
- IntoIter::new([ds]),
- empty(),
- );
- // Call draw
- cmd_buffer.draw_indexed(
- (next_idx_idx as u32 * 3)..((next_idx_idx * 3) + tris.indices.len()) as u32,
- next_vert_idx as i32,
- 0..1,
- );
- }
- } else {
- self.repo.queue_load(0)?;
- }
-
- next_idx_idx += tris.indices.len() / 3;
- next_vert_idx += tris.vertices.len();
- }
-
- unsafe {
- cmd_buffer.end_render_pass();
- }
-
- Ok(())
- }
-
- fn deactivate(self, context: &mut RenderingContext) -> Result<()> {
- self.draw_buffers.deactivate(context);
- self.surface_resources.deactivate(context)?;
- self.repo.deactivate(context);
-
- Ok(())
- }
-
- fn handle_surface_change(
- mut self,
- _session: &Session,
- context: &mut RenderingContext,
- ) -> Result<Self> {
- let new_surface_resources =
- SurfaceDependentResources::new::<P>(context, &*self.repo.get_ds_layout()?)?;
- let old_surface_resources = self.surface_resources;
- self.surface_resources = new_surface_resources;
-
- match old_surface_resources.deactivate(context) {
- Ok(_) => Ok(self),
- Err(e) => {
- <Self as DrawPass<P>>::deactivate(self, context)?;
- Err(e)
- }
- }
- }
-}
-
-impl<'a, P: PassPosition> IntoDrawPass<UiDrawPass<'a>, P> for () {
- fn init(self, session: &mut Session, context: &mut RenderingContext) -> Result<UiDrawPass<'a>> {
- let ui: &mut UiState = &mut session.resources.get_mut::<UiState>().unwrap();
- let repo = TextureRepo::new::<_, TexLoadQueue>(
- context,
- TextureLoadConfig {
- resolver: UiTextures::new(ui.ctx().clone()),
- filter: hal::image::Filter::Linear,
- wrap_mode: hal::image::WrapMode::Clamp,
- },
- )
- .context("Error creating texture repo")?;
-
- let draw_buffers =
- DrawBuffers::from_context(context).context("Error creating draw buffers")?;
-
- let surface_resources =
- SurfaceDependentResources::new::<P>(context, &*repo.get_ds_layout()?)?;
-
- Ok(UiDrawPass {
- repo,
- draw_buffers,
- surface_resources,
- })
- }
-
- fn find_aux_queues(
- adapter: &Adapter,
- queue_negotiator: &mut QueueFamilyNegotiator,
- ) -> Result<()> {
- queue_negotiator.find(adapter, &TexLoadQueue, 1)?;
-
- Ok(())
- }
-}
-
-pub struct UiTexture(Arc<Texture>);
-
-pub struct UiTextures {
- ctx: CtxRef,
-}
-
-impl TextureResolver for UiTextures {
- type Image = UiTexture;
- fn resolve(&mut self, tex: u32) -> Option<Self::Image> {
- if tex == 0 {
- Some(UiTexture(self.ctx.texture()))
- } else {
- None
- }
- }
-}
-
-impl UiTextures {
- pub fn new(ctx: CtxRef) -> Self {
- UiTextures { ctx }
- }
-}
-
-impl LoadableImage for UiTexture {
- fn width(&self) -> u32 {
- self.0.width as u32
- }
- fn height(&self) -> u32 {
- self.0.height as u32
- }
- unsafe fn copy_row(&self, y: u32, ptr: *mut u8) {
- let row_size = self.0.width as u32;
- let pixels = &self.0.pixels[(y * row_size) as usize..((y + 1) * row_size) as usize];
-
- for (i, x) in pixels.iter().enumerate() {
- *ptr.offset(i as isize * 4) = 255;
- *ptr.offset((i as isize * 4) + 1) = 255;
- *ptr.offset((i as isize * 4) + 2) = 255;
- *ptr.offset((i as isize * 4) + 3) = *x;
- }
- }
-}
-
-struct SurfaceDependentResources {
- pipeline: CompletePipeline,
- framebuffers: TargetSpecificResources<FramebufferT>,
-}
-
-impl SurfaceDependentResources {
- fn new<P: PassPosition>(
- context: &mut RenderingContext,
- ds_layout: &DescriptorSetLayoutT,
- ) -> Result<Self> {
- let mut device = context.lock_device()?;
-
- let spec = PipelineSpecBuilder::default()
- .rasterizer(Rasterizer {
- polygon_mode: PolygonMode::Fill,
- cull_face: Face::NONE,
- front_face: FrontFace::CounterClockwise,
- depth_clamping: false,
- depth_bias: None,
- conservative: true,
- line_width: State::Static(1.0),
- })
- .depth_stencil(DepthStencilDesc {
- depth: None,
- depth_bounds: false,
- stencil: None,
- })
- .blender(BlendDesc {
- logic_op: Some(LogicOp::Copy),
- targets: vec![ColorBlendDesc {
- mask: ColorMask::ALL,
- blend: Some(BlendState {
- color: BlendOp::Add {
- src: Factor::SrcAlpha,
- dst: Factor::OneMinusSrcAlpha,
- },
- alpha: BlendOp::Add {
- src: Factor::SrcAlpha,
- dst: Factor::OneMinusSrcAlpha,
- },
- }),
- }],
- })
- .primitive_assembler(VertexPrimitiveAssemblerSpec::with_buffers(
- InputAssemblerDesc::new(Primitive::TriangleList),
- vec![VertexBufferSpec {
- attributes: vec![Format::Rg32Sfloat, Format::Rg32Sfloat, Format::Rgba32Sfloat],
- rate: VertexInputRate::Vertex,
- }],
- ))
- .shader_vertex(ShaderDesc {
- source: include_str!("./data/ui.vert").to_string(),
- entry: "main".to_string(),
- kind: ShaderKind::Vertex,
- })
- .shader_fragment(ShaderDesc {
- source: include_str!("./data/ui.frag").to_string(),
- entry: "main".to_string(),
- kind: ShaderKind::Fragment,
- })
- .push_constants(vec![(ShaderStageFlags::VERTEX, 0..8)])
- .renderpass(RenderpassSpec {
- colors: vec![AttachmentSpec {
- attachment: Attachment {
- format: Some(context.properties().color_format),
- samples: 1,
- ops: P::attachment_ops(),
- stencil_ops: P::attachment_ops(),
- layouts: P::layout_as_range(),
- },
- used_layout: Layout::ColorAttachmentOptimal,
- }],
- depth: None,
- inputs: vec![],
- resolves: vec![],
- preserves: vec![],
- })
- .dynamic_scissor(true)
- .build()
- .context("Error building pipeline")?;
-
- let pipeline = spec
- .build(&mut device, context.properties().extent, once(ds_layout))
- .context("Error building pipeline")?;
-
- let fat = context.properties().swapchain_framebuffer_attachment();
-
- let framebuffers = TargetSpecificResources::new(
- || unsafe {
- Ok(device.create_framebuffer(
- &pipeline.renderpass,
- IntoIter::new([fat.clone()]),
- context.properties().extent,
- )?)
- },
- context.properties().image_count as usize,
- )?;
-
- Ok(Self {
- framebuffers,
- pipeline,
- })
- }
-
- fn deactivate(self, context: &mut RenderingContext) -> Result<()> {
- unsafe {
- let mut device = context.lock_device()?;
- self.pipeline.deactivate(&mut device);
-
- for fb in self.framebuffers.dissolve() {
- device.destroy_framebuffer(fb);
- }
- }
-
- Ok(())
- }
-}
diff --git a/stockton-render/src/window.rs b/stockton-render/src/window.rs
deleted file mode 100644
index 429a3c2..0000000
--- a/stockton-render/src/window.rs
+++ /dev/null
@@ -1,278 +0,0 @@
-use stockton_input::{Action as KBAction, InputManager, Mouse};
-use stockton_skeleton::{
- draw_passes::{DrawPass, Singular},
- Renderer,
-};
-
-use std::sync::{
- mpsc::{channel, Receiver, Sender},
- Arc, RwLock,
-};
-
-use egui::{CtxRef, Event, Modifiers, Output, Pos2, RawInput, Rect, Vec2};
-use epaint::ClippedShape;
-use legion::systems::Runnable;
-use log::debug;
-use winit::{
- event::{ElementState, Event as WinitEvent, MouseButton, WindowEvent as WinitWindowEvent},
- event_loop::ControlFlow,
-};
-
-#[derive(Debug, Clone, Copy)]
-pub enum WindowEvent {
- SizeChanged(u32, u32),
- CloseRequested,
- KeyboardAction(KBAction),
- MouseAction(KBAction),
- MouseMoved(f32, f32),
- MouseLeft,
-}
-
-impl WindowEvent {
- pub fn from(winit_event: &WinitEvent<()>) -> Option<WindowEvent> {
- // TODO
- match winit_event {
- WinitEvent::WindowEvent { event, .. } => match event {
- WinitWindowEvent::CloseRequested => Some(WindowEvent::CloseRequested),
- 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,
- ))),
- ElementState::Released => Some(WindowEvent::KeyboardAction(
- KBAction::KeyRelease(input.scancode),
- )),
- },
- WinitWindowEvent::CursorMoved { position, .. } => Some(WindowEvent::MouseMoved(
- 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,
- }
- }
-}
-
-pub struct UiState {
- ctx: CtxRef,
- raw_input: RawInput,
- frame_active: bool,
-
- modifiers: Modifiers,
- pointer_pos: Pos2,
-}
-
-impl UiState {
- pub fn populate_initial_state<T: DrawPass<Singular>>(&mut self, renderer: &Renderer<T>) {
- let props = renderer.context().properties();
- self.set_dimensions(props.extent.width, props.extent.height);
- self.set_pixels_per_point(Some(renderer.context().pixels_per_point()));
- debug!("{:?}", self.raw_input);
- }
-
- #[inline]
- pub fn ctx(&mut self) -> &CtxRef {
- if !self.frame_active {
- self.begin_frame()
- }
- &self.ctx
- }
-
- #[inline]
- fn begin_frame(&mut self) {
- #[allow(deprecated)]
- let new_raw_input = RawInput {
- scroll_delta: Vec2::new(0.0, 0.0),
- zoom_delta: 0.0,
- screen_size: self.raw_input.screen_size,
- screen_rect: self.raw_input.screen_rect,
- pixels_per_point: self.raw_input.pixels_per_point,
- time: self.raw_input.time,
- predicted_dt: self.raw_input.predicted_dt,
- modifiers: self.modifiers,
- events: Vec::new(),
- };
- self.ctx.begin_frame(self.raw_input.take());
- self.raw_input = new_raw_input;
- self.frame_active = true;
- }
-
- #[inline]
- pub(crate) fn end_frame(&mut self) -> (Output, Vec<ClippedShape>) {
- self.frame_active = false;
- self.ctx.end_frame()
- }
-
- #[inline]
- pub fn dimensions(&self) -> Option<egui::math::Vec2> {
- Some(self.raw_input.screen_rect?.size())
- }
-
- fn set_mouse_pos(&mut self, x: f32, y: f32) {
- self.raw_input
- .events
- .push(Event::PointerMoved(Pos2::new(x, y)));
-
- self.pointer_pos = Pos2::new(x, y);
- }
-
- fn set_mouse_left(&mut self) {
- self.raw_input.events.push(Event::PointerGone);
- }
-
- fn set_dimensions(&mut self, w: u32, h: u32) {
- self.raw_input.screen_rect =
- Some(Rect::from_x_y_ranges(0.0..=(w as f32), 0.0..=(h as f32)));
- }
- fn set_pixels_per_point(&mut self, ppp: Option<f32>) {
- debug!("Using {:?} pixels per point", ppp);
- self.raw_input.pixels_per_point = ppp;
- }
-
- fn handle_action(&mut self, action: KBAction) {
- // TODO
- match action {
- KBAction::MousePress(btn) => {
- self.raw_input.events.push(Event::PointerButton {
- pos: self.pointer_pos,
- button: match btn {
- stockton_input::MouseButton::Left => egui::PointerButton::Primary,
- stockton_input::MouseButton::Right => egui::PointerButton::Secondary,
- stockton_input::MouseButton::Middle => egui::PointerButton::Middle,
- stockton_input::MouseButton::Other(_) => todo!(),
- },
- pressed: true,
- modifiers: self.modifiers,
- });
- }
- KBAction::MouseRelease(btn) => {
- self.raw_input.events.push(Event::PointerButton {
- pos: self.pointer_pos,
- button: match btn {
- stockton_input::MouseButton::Left => egui::PointerButton::Primary,
- stockton_input::MouseButton::Right => egui::PointerButton::Secondary,
- stockton_input::MouseButton::Middle => egui::PointerButton::Middle,
- stockton_input::MouseButton::Other(_) => todo!(),
- },
- pressed: false,
- modifiers: self.modifiers,
- });
- }
- _ => (),
- }
- }
-}
-
-impl Default for UiState {
- fn default() -> Self {
- UiState {
- ctx: CtxRef::default(),
- raw_input: RawInput::default(),
- frame_active: false,
- modifiers: Default::default(),
- pointer_pos: Pos2::new(0.0, 0.0),
- }
- }
-}
-
-pub struct WindowFlow {
- window_events: Receiver<WindowEvent>,
- update_control_flow: Arc<RwLock<ControlFlow>>,
-}
-
-impl WindowFlow {
- pub fn new(update_control_flow: Arc<RwLock<ControlFlow>>) -> (Self, Sender<WindowEvent>) {
- let (tx, rx) = channel();
- (
- Self {
- window_events: rx,
- update_control_flow,
- },
- tx,
- )
- }
-}
-
-#[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] window_channel: &mut WindowFlow,
- #[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;
- let mut mouse_delta = mouse.abs;
-
- while let Ok(event) = window_channel.window_events.try_recv() {
- match event {
- WindowEvent::SizeChanged(w, h) => {
- ui_state.set_dimensions(w, h);
- }
- WindowEvent::CloseRequested => {
- let mut flow = window_channel.update_control_flow.write().unwrap();
- // TODO: Let everything know this is our last frame
- *flow = ControlFlow::Exit;
- }
- WindowEvent::KeyboardAction(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);
- }
- 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);
- }
- };
- }
-
- mouse.handle_frame(mouse_delta);
-
- manager.handle_frame(&actions_buf[0..actions_buf_cursor]);
-}
-
-pub fn process_window_events_system<T: 'static + InputManager>() -> impl Runnable {
- _process_window_events_system::<T>(Vec::with_capacity(4))
-}
diff --git a/stockton-skeleton/src/builders/pipeline.rs b/stockton-skeleton/src/builders/pipeline.rs
index 82673a2..af8d430 100644
--- a/stockton-skeleton/src/builders/pipeline.rs
+++ b/stockton-skeleton/src/builders/pipeline.rs
@@ -97,6 +97,7 @@ pub struct PipelineSpec {
#[builder(setter(strip_option), default)]
shader_tesselation: Option<(ShaderDesc, ShaderDesc)>,
+ #[builder(default = "vec![]")]
push_constants: Vec<(ShaderStageFlags, Range<u32>)>,
#[builder(default = "false")]
diff --git a/stockton-skeleton/src/builders/shader.rs b/stockton-skeleton/src/builders/shader.rs
index fde185d..be48951 100644
--- a/stockton-skeleton/src/builders/shader.rs
+++ b/stockton-skeleton/src/builders/shader.rs
@@ -1,8 +1,10 @@
use crate::types::*;
+pub use shaderc::ShaderKind;
+
use anyhow::{Context, Result};
use hal::pso::Specialization;
-use shaderc::{Compiler, ShaderKind};
+use shaderc::Compiler;
#[derive(Debug, Clone)]
pub struct ShaderDesc {
diff --git a/stockton-skeleton/src/context.rs b/stockton-skeleton/src/context.rs
index 943e0dc..6838fb6 100644
--- a/stockton-skeleton/src/context.rs
+++ b/stockton-skeleton/src/context.rs
@@ -34,8 +34,8 @@ use crate::{
error::{EnvironmentError, LockPoisoned, UsageError},
mem::MemoryPool,
queue_negotiator::{QueueFamilyNegotiator, QueueFamilySelector, SharedQueue},
+ session::Session,
types::*,
- session::Session
};
/// The actual data behind [`StatefulRenderingContext`]
diff --git a/stockton-skeleton/src/draw_passes/cons.rs b/stockton-skeleton/src/draw_passes/cons.rs
index f6c3d1b..9fb5d5d 100644
--- a/stockton-skeleton/src/draw_passes/cons.rs
+++ b/stockton-skeleton/src/draw_passes/cons.rs
@@ -2,7 +2,9 @@
//! Note that this can be extended to an arbitrary amount of draw passes.
use super::{Beginning, DrawPass, End, IntoDrawPass, Middle, Singular};
-use crate::{session::Session, context::RenderingContext, queue_negotiator::QueueFamilyNegotiator, types::*};
+use crate::{
+ context::RenderingContext, queue_negotiator::QueueFamilyNegotiator, session::Session, types::*,
+};
use anyhow::Result;
diff --git a/stockton-skeleton/src/draw_passes/mod.rs b/stockton-skeleton/src/draw_passes/mod.rs
index 9a13c73..17564fa 100644
--- a/stockton-skeleton/src/draw_passes/mod.rs
+++ b/stockton-skeleton/src/draw_passes/mod.rs
@@ -1,7 +1,9 @@
//! Traits and common draw passes.
use std::ops::Range;
-use crate::{context::RenderingContext, queue_negotiator::QueueFamilyNegotiator, types::*, session::Session};
+use crate::{
+ context::RenderingContext, queue_negotiator::QueueFamilyNegotiator, session::Session, types::*,
+};
use hal::{
image::Layout,
pass::{AttachmentLoadOp, AttachmentOps, AttachmentStoreOp},
diff --git a/stockton-skeleton/src/lib.rs b/stockton-skeleton/src/lib.rs
index d57c5f6..1e0d108 100644
--- a/stockton-skeleton/src/lib.rs
+++ b/stockton-skeleton/src/lib.rs
@@ -8,26 +8,26 @@ extern crate derive_builder;
pub mod buffers;
pub mod builders;
+pub mod components;
pub mod context;
pub mod draw_passes;
pub mod error;
pub mod mem;
pub mod queue_negotiator;
+pub mod session;
mod target;
pub mod texture;
pub mod types;
pub mod utils;
-pub mod components;
-pub mod session;
+pub use anyhow::Result;
pub use context::RenderingContext;
-pub use session::Session;
pub use draw_passes::{DrawPass, IntoDrawPass, PassPosition};
-pub use anyhow::Result;
+pub use session::Session;
+use anyhow::Context;
use draw_passes::Singular;
use std::mem::ManuallyDrop;
-use anyhow::{Context};
use winit::window::Window;
/// Renders a world to a window when you tell it to.
@@ -75,6 +75,7 @@ impl<DP: DrawPass<Singular>> Renderer<DP> {
}
Err((_e, c)) => {
// TODO: Try to detect if the error is actually surface related.
+
let c = c.attempt_recovery()?;
match c.draw_next_frame(session, &mut *self.draw_pass) {
Ok(c) => {
@@ -94,9 +95,11 @@ impl<DP: DrawPass<Singular>> Renderer<DP> {
// Safety: If this fails at any point, the ManuallyDrop won't be touched again, as Renderer will be dropped.
// Hence, we can always take from the ManuallyDrop
unsafe {
- let ctx = ManuallyDrop::take(&mut self.context).recreate_surface()?;
+ let ctx = ManuallyDrop::take(&mut self.context);
+ log::debug!("ctx");
+ let ctx = ctx.recreate_surface()?;
self.context = ManuallyDrop::new(ctx);
-
+ log::debug!("Finished resizing ctx");
let dp = ManuallyDrop::take(&mut self.draw_pass)
.handle_surface_change(session, &mut self.context)?;
self.draw_pass = ManuallyDrop::new(dp);
diff --git a/stockton-skeleton/src/target.rs b/stockton-skeleton/src/target.rs
index 23f56b9..68829b1 100644
--- a/stockton-skeleton/src/target.rs
+++ b/stockton-skeleton/src/target.rs
@@ -4,8 +4,8 @@
use crate::{
context::ContextProperties,
draw_passes::{DrawPass, Singular},
+ session::Session,
types::*,
- session::Session
};
use std::{
diff --git a/stockton-skeleton/src/texture/load.rs b/stockton-skeleton/src/texture/load.rs
index 80c332e..27498af 100644
--- a/stockton-skeleton/src/texture/load.rs
+++ b/stockton-skeleton/src/texture/load.rs
@@ -1,6 +1,6 @@
use std::sync::{Arc, RwLock};
-use super::{block::TexturesBlock, repo::BLOCK_SIZE, TextureResolver, LoadableImage};
+use super::{block::TexturesBlock, repo::BLOCK_SIZE, LoadableImage, TextureResolver};
use crate::{
buffers::{
image::{ImageSpec, SampledImage, COLOR_RESOURCES},
diff --git a/stockton-skeleton/src/texture/loader.rs b/stockton-skeleton/src/texture/loader.rs
index 6212492..0a98722 100644
--- a/stockton-skeleton/src/texture/loader.rs
+++ b/stockton-skeleton/src/texture/loader.rs
@@ -6,8 +6,7 @@ use super::{
load_image, QueuedLoad, TextureLoadConfig, TextureLoadError, FORMAT, LAYERS, RESOURCES,
},
repo::BLOCK_SIZE,
- TextureResolver,
- PIXEL_SIZE,
+ TextureResolver, PIXEL_SIZE,
};
use crate::{
buffers::image::SampledImage,