Implement hotbar slot selection

This commit is contained in:
Sijmen 2021-06-02 01:25:12 +02:00
parent 032d527af3
commit 41099e3481
Signed by: vijfhoek
GPG key ID: 82D05C89B28B0DAE
6 changed files with 160 additions and 107 deletions

View file

@ -1,7 +1,6 @@
struct VertexInput {
[[location(0)]] position: vec3<f32>;
[[location(0)]] position: vec2<f32>;
[[location(1)]] texture_coordinates: vec2<f32>;
[[location(2)]] normal: vec3<f32>;
};
struct VertexOutput {
@ -13,7 +12,7 @@ struct VertexOutput {
fn main(model: VertexInput) -> VertexOutput {
var out: VertexOutput;
out.texture_coordinates = model.texture_coordinates;
out.clip_position = vec4<f32>(model.position, 1.0);
out.clip_position = vec4<f32>(model.position, 0.0, 1.0);
return out;
}

View file

@ -10,7 +10,7 @@ use crate::{
render_context::RenderContext,
text_renderer::{self, TextRenderer},
texture::Texture,
vertex::Vertex,
vertex::HudVertex,
};
const UI_SCALE_X: f32 = 0.0045;
@ -19,8 +19,8 @@ const UI_SCALE_Y: f32 = 0.008;
pub struct HudState {
texture_bind_group: wgpu::BindGroup,
render_pipeline: wgpu::RenderPipeline,
crosshair_vertex_buffer: wgpu::Buffer,
crosshair_index_buffer: wgpu::Buffer,
hud_vertex_buffer: wgpu::Buffer,
hud_index_buffer: wgpu::Buffer,
text_renderer: TextRenderer,
@ -35,6 +35,7 @@ pub struct HudState {
coordinates_index_buffer: wgpu::Buffer,
coordinates_index_count: usize,
coordinates_last: Vector3<f32>,
pub hotbar_cursor_position: i32,
}
impl HudState {
@ -44,24 +45,23 @@ impl HudState {
let render_pipeline =
Self::create_render_pipeline(render_context, &[&texture_bind_group_layout]);
let crosshair_vertex_buffer =
render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: Some("HUD crosshair vertex buffer"),
contents: bytemuck::cast_slice(&CROSSHAIR_VERTICES),
usage: wgpu::BufferUsage::VERTEX,
});
let crosshair_index_buffer =
render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: Some("HUD crosshair index buffer"),
contents: bytemuck::cast_slice(CROSSHAIR_INDICES),
usage: wgpu::BufferUsage::INDEX,
});
// HUD buffers
let hud_vertex_buffer = render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: Some("HUD crosshair vertex buffer"),
contents: bytemuck::cast_slice(HUD_VERTICES),
usage: wgpu::BufferUsage::VERTEX | wgpu::BufferUsage::COPY_DST,
});
let hud_index_buffer = render_context
.device
.create_buffer_init(&BufferInitDescriptor {
label: Some("HUD crosshair index buffer"),
contents: bytemuck::cast_slice(HUD_INDICES),
usage: wgpu::BufferUsage::INDEX,
});
// Text buffers
let text_renderer = TextRenderer::new(render_context).unwrap();
let (fps_vertex_buffer, fps_index_buffer, fps_index_count) =
text_renderer.string_to_buffers(&render_context, -0.98, 0.97, "");
@ -71,8 +71,8 @@ impl HudState {
Self {
texture_bind_group,
render_pipeline,
crosshair_vertex_buffer,
crosshair_index_buffer,
hud_vertex_buffer,
hud_index_buffer,
text_renderer,
fps_vertex_buffer,
@ -86,6 +86,8 @@ impl HudState {
coordinates_index_buffer,
coordinates_index_count,
coordinates_last: Vector3::new(0.0, 0.0, 0.0),
hotbar_cursor_position: 0,
}
}
@ -144,20 +146,20 @@ impl HudState {
});
render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_vertex_buffer(0, self.crosshair_vertex_buffer.slice(..));
render_pass.set_index_buffer(
self.crosshair_index_buffer.slice(..),
wgpu::IndexFormat::Uint16,
);
// Render the crosshair and hotbar
render_pass.set_vertex_buffer(0, self.hud_vertex_buffer.slice(..));
render_pass.set_index_buffer(self.hud_index_buffer.slice(..), wgpu::IndexFormat::Uint16);
render_pass.set_bind_group(0, &self.texture_bind_group, &[]);
render_pass.draw_indexed(0..CROSSHAIR_INDICES.len() as u32, 0, 0..1);
render_pass.draw_indexed(0..HUD_INDICES.len() as u32, 0, 0..1);
// Render the FPS text
render_pass.set_vertex_buffer(0, self.fps_vertex_buffer.slice(..));
render_pass.set_index_buffer(self.fps_index_buffer.slice(..), wgpu::IndexFormat::Uint16);
render_pass.set_bind_group(0, &self.text_renderer.bind_group, &[]);
render_pass.draw_indexed(0..self.fps_index_count as u32, 0, 0..1);
// Render the coordinates text
render_pass.set_vertex_buffer(0, self.coordinates_vertex_buffer.slice(..));
render_pass.set_index_buffer(
self.coordinates_index_buffer.slice(..),
@ -166,7 +168,35 @@ impl HudState {
render_pass.set_bind_group(0, &self.text_renderer.bind_group, &[]);
render_pass.draw_indexed(0..self.coordinates_index_count as u32, 0, 0..1);
Ok(CROSSHAIR_INDICES.len() / 3)
Ok(HUD_INDICES.len() / 3)
}
pub fn update_hotbar_cursor(&self, render_context: &RenderContext) {
let x = (-92 + 20 * self.hotbar_cursor_position) as f32;
#[rustfmt::skip]
let vertices = [
HudVertex { position: [UI_SCALE_X * (x ), -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 0.0 / 256.0, 22.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * (x + 24.0), -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 24.0 / 256.0, 22.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * (x + 24.0), -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 24.0 / 256.0, 46.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * (x ), -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 0.0 / 256.0, 46.0 / 256.0] },
];
render_context.queue.write_buffer(
&self.hud_vertex_buffer,
HudVertex::descriptor().array_stride * 8,
bytemuck::cast_slice(&vertices),
);
}
pub fn set_hotbar_cursor(&mut self, render_context: &RenderContext, i: i32) {
self.hotbar_cursor_position = i;
self.update_hotbar_cursor(render_context);
}
pub fn move_hotbar_cursor(&mut self, render_context: &RenderContext, delta: i32) {
self.hotbar_cursor_position = (self.hotbar_cursor_position + delta).rem_euclid(9);
self.update_hotbar_cursor(render_context);
}
fn create_textures(render_context: &RenderContext) -> (wgpu::BindGroupLayout, wgpu::BindGroup) {
@ -262,7 +292,7 @@ impl HudState {
vertex: wgpu::VertexState {
module,
entry_point: "main",
buffers: &[Vertex::desc()],
buffers: &[HudVertex::descriptor()],
},
fragment: Some(wgpu::FragmentState {
module,
@ -292,56 +322,38 @@ impl HudState {
}
}
pub const CROSSHAIR_VERTICES: &[Vertex] = &[
#[rustfmt::skip]
pub const HUD_VERTICES: &[HudVertex] = &[
// Crosshair
Vertex {
position: [-UI_SCALE_X * 8.0, UI_SCALE_Y * 8.0, 0.0],
texture_coordinates: [240.0 / 256.0, 0.0 / 256.0],
normal: [0.0, 0.0, 0.0],
},
Vertex {
position: [UI_SCALE_X * 8.0, UI_SCALE_Y * 8.0, 0.0],
texture_coordinates: [1.0, 0.0 / 256.0],
normal: [0.0, 0.0, 0.0],
},
Vertex {
position: [UI_SCALE_X * 8.0, -UI_SCALE_Y * 8.0, 0.0],
texture_coordinates: [1.0, 16.0 / 256.0],
normal: [0.0, 0.0, 0.0],
},
Vertex {
position: [-UI_SCALE_X * 8.0, -UI_SCALE_Y * 8.0, 0.0],
texture_coordinates: [240.0 / 256.0, 16.0 / 256.0],
normal: [0.0, 0.0, 0.0],
},
HudVertex { position: [UI_SCALE_X * -8.0, UI_SCALE_Y * 8.0], texture_coordinates: [240.0 / 256.0, 0.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * 8.0, UI_SCALE_Y * 8.0], texture_coordinates: [256.0 / 256.0, 0.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * 8.0, UI_SCALE_Y * -8.0], texture_coordinates: [256.0 / 256.0, 16.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -8.0, UI_SCALE_Y * -8.0], texture_coordinates: [240.0 / 256.0, 16.0 / 256.0] },
// Hotbar
Vertex {
position: [-UI_SCALE_X * 91.0, -1.0 + UI_SCALE_Y * 22.0, 0.0],
texture_coordinates: [0.0 / 256.0, 0.0 / 256.0],
normal: [0.0, 0.0, 0.0],
},
Vertex {
position: [UI_SCALE_X * 91.0, -1.0 + UI_SCALE_Y * 22.0, 0.0],
texture_coordinates: [182.0 / 256.0, 0.0 / 256.0],
normal: [0.0, 0.0, 0.0],
},
Vertex {
position: [UI_SCALE_X * 91.0, -1.0, 0.0],
texture_coordinates: [182.0 / 256.0, 22.0 / 256.0],
normal: [0.0, 0.0, 0.0],
},
Vertex {
position: [-UI_SCALE_X * 91.0, -1.0, 0.0],
texture_coordinates: [0.0 / 256.0, 22.0 / 256.0],
normal: [0.0, 0.0, 0.0],
},
HudVertex { position: [UI_SCALE_X * -91.0, -1.0 + UI_SCALE_Y * 22.0], texture_coordinates: [ 0.0 / 256.0, 0.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * 91.0, -1.0 + UI_SCALE_Y * 22.0], texture_coordinates: [182.0 / 256.0, 0.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * 91.0, -1.0 ], texture_coordinates: [182.0 / 256.0, 22.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -91.0, -1.0 ], texture_coordinates: [ 0.0 / 256.0, 22.0 / 256.0] },
// Hotbar cursor
HudVertex { position: [UI_SCALE_X * -92.0, -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 0.0 / 256.0, 22.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -68.0, -1.0 + UI_SCALE_Y * 23.0], texture_coordinates: [ 24.0 / 256.0, 22.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -68.0, -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 24.0 / 256.0, 46.0 / 256.0] },
HudVertex { position: [UI_SCALE_X * -92.0, -1.0 + UI_SCALE_Y * -1.0], texture_coordinates: [ 0.0 / 256.0, 46.0 / 256.0] },
];
#[rustfmt::skip]
pub const CROSSHAIR_INDICES: &[u16] = &[
pub const HUD_INDICES: &[u16] = &[
// Crosshair
1, 0, 3,
1, 3, 2,
// Hotbar
5, 4, 7,
5, 7, 6,
// Hotbar cursor
9, 8, 11,
9, 11, 10,
];

View file

@ -6,7 +6,7 @@ use std::time::Duration;
use cgmath::EuclideanSpace;
use winit::{
dpi::PhysicalSize,
event::{DeviceEvent, ElementState, KeyboardInput, VirtualKeyCode, WindowEvent},
event::{DeviceEvent, ElementState, MouseScrollDelta, VirtualKeyCode, WindowEvent},
window::Window,
};
@ -122,12 +122,23 @@ impl State {
);
}
fn input_keyboard(&mut self, key_code: &VirtualKeyCode, state: &ElementState) {
match key_code {
VirtualKeyCode::F1 if state == &ElementState::Pressed => {
self.world_state.toggle_wireframe(&self.render_context)
fn input_keyboard(&mut self, key_code: VirtualKeyCode, state: ElementState) {
if state == ElementState::Pressed {
match key_code {
VirtualKeyCode::F1 => self.world_state.toggle_wireframe(&self.render_context),
VirtualKeyCode::Key1 => self.hud_state.set_hotbar_cursor(&self.render_context, 0),
VirtualKeyCode::Key2 => self.hud_state.set_hotbar_cursor(&self.render_context, 1),
VirtualKeyCode::Key3 => self.hud_state.set_hotbar_cursor(&self.render_context, 2),
VirtualKeyCode::Key4 => self.hud_state.set_hotbar_cursor(&self.render_context, 3),
VirtualKeyCode::Key5 => self.hud_state.set_hotbar_cursor(&self.render_context, 4),
VirtualKeyCode::Key6 => self.hud_state.set_hotbar_cursor(&self.render_context, 5),
VirtualKeyCode::Key7 => self.hud_state.set_hotbar_cursor(&self.render_context, 6),
VirtualKeyCode::Key8 => self.hud_state.set_hotbar_cursor(&self.render_context, 7),
VirtualKeyCode::Key9 => self.hud_state.set_hotbar_cursor(&self.render_context, 8),
_ => self.world_state.input_keyboard(key_code, state),
}
_ => self.world_state.input_keyboard(key_code, state),
} else {
self.world_state.input_keyboard(key_code, state)
}
}
@ -139,15 +150,9 @@ impl State {
pub fn window_event(&mut self, event: &WindowEvent) {
match event {
WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(key),
state,
..
},
..
} => self.input_keyboard(key, state),
WindowEvent::KeyboardInput { input, .. } if input.virtual_keycode.is_some() => {
self.input_keyboard(input.virtual_keycode.unwrap(), input.state)
}
WindowEvent::MouseInput {
button,
@ -157,6 +162,13 @@ impl State {
.world_state
.input_mouse_button(button, &self.render_context),
WindowEvent::MouseWheel {
delta: MouseScrollDelta::LineDelta(_, delta),
..
} => self
.hud_state
.move_hotbar_cursor(&self.render_context, -*delta as i32),
_ => (),
}
}

View file

@ -481,15 +481,15 @@ impl WorldState {
}
}
pub fn input_keyboard(&mut self, key_code: &VirtualKeyCode, state: &ElementState) {
let pressed = state == &ElementState::Pressed;
pub fn input_keyboard(&mut self, key_code: VirtualKeyCode, state: ElementState) {
let pressed = state == ElementState::Pressed;
match key_code {
VirtualKeyCode::W => self.forward_pressed = pressed,
VirtualKeyCode::S => self.backward_pressed = pressed,
VirtualKeyCode::A => self.left_pressed = pressed,
VirtualKeyCode::D => self.right_pressed = pressed,
VirtualKeyCode::Space if state == &ElementState::Pressed => self.up_speed = 0.6,
VirtualKeyCode::LControl => self.sprinting = state == &ElementState::Pressed,
VirtualKeyCode::Space if state == ElementState::Pressed => self.up_speed = 0.6,
VirtualKeyCode::LControl => self.sprinting = state == ElementState::Pressed,
_ => (),
}
}

View file

@ -2,7 +2,7 @@ use std::convert::TryInto;
use wgpu::util::{BufferInitDescriptor, DeviceExt};
use crate::{render_context::RenderContext, texture::Texture, vertex::Vertex};
use crate::{render_context::RenderContext, texture::Texture, vertex::HudVertex};
pub const DX: f32 = 20.0 / 640.0;
pub const DY: f32 = 20.0 / 360.0;
@ -100,16 +100,16 @@ impl TextRenderer {
y: f32,
c: u8,
index_offset: u16,
) -> ([Vertex; 4], [u16; 6]) {
) -> ([HudVertex; 4], [u16; 6]) {
let (tx, ty) = Self::char_uv(c);
let s = 1.0 / 16.0;
#[rustfmt::skip]
let vertices = [
Vertex { position: [x, y, 0.0], texture_coordinates: [tx, ty ], ..Default::default() },
Vertex { position: [x + DX, y, 0.0], texture_coordinates: [tx + s, ty ], ..Default::default() },
Vertex { position: [x + DX, y - DY, 0.0], texture_coordinates: [tx + s, ty + s], ..Default::default() },
Vertex { position: [x, y - DY, 0.0], texture_coordinates: [tx, ty + s], ..Default::default() },
HudVertex { position: [x, y ], texture_coordinates: [tx, ty ] },
HudVertex { position: [x + DX, y ], texture_coordinates: [tx + s, ty ] },
HudVertex { position: [x + DX, y - DY], texture_coordinates: [tx + s, ty + s] },
HudVertex { position: [x, y - DY], texture_coordinates: [tx, ty + s] },
];
#[rustfmt::skip]
@ -121,7 +121,12 @@ impl TextRenderer {
(vertices, indices)
}
pub fn string_geometry(&self, mut x: f32, mut y: f32, string: &str) -> (Vec<Vertex>, Vec<u16>) {
pub fn string_geometry(
&self,
mut x: f32,
mut y: f32,
string: &str,
) -> (Vec<HudVertex>, Vec<u16>) {
let mut vertices = Vec::new();
let mut indices = Vec::new();

View file

@ -10,18 +10,43 @@ pub struct Vertex {
pub normal: [f32; 3],
}
const VERTEX_DESC: &[VertexAttribute] = &wgpu::vertex_attr_array![
const VERTEX_ATTRIBUTES: &[VertexAttribute] = &wgpu::vertex_attr_array![
0 => Float32x3,
1 => Float32x2,
2 => Float32x3,
];
impl Vertex {
pub fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
pub fn descriptor() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout {
array_stride: size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: VERTEX_DESC,
attributes: VERTEX_ATTRIBUTES,
}
}
}
/// Vertex used to represent HUD vertices.
///
/// A vertex with a 2D position and no normal, for representing UI elements.
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, bytemuck::Pod, bytemuck::Zeroable)]
pub struct HudVertex {
pub position: [f32; 2],
pub texture_coordinates: [f32; 2],
}
const HUD_VERTEX_ATTRIBUTES: &[VertexAttribute] = &wgpu::vertex_attr_array![
0 => Float32x2,
1 => Float32x2,
];
impl HudVertex {
pub fn descriptor() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout {
array_stride: size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: HUD_VERTEX_ATTRIBUTES,
}
}
}
@ -41,7 +66,7 @@ pub struct BlockVertex {
pub texture_id: i32,
}
const BLOCK_VERTEX_DESC: &[VertexAttribute] = &wgpu::vertex_attr_array![
const BLOCK_VERTEX_ATTRIBUTES: &[VertexAttribute] = &wgpu::vertex_attr_array![
0 => Float32x3,
1 => Float32x2,
2 => Float32x3,
@ -50,11 +75,11 @@ const BLOCK_VERTEX_DESC: &[VertexAttribute] = &wgpu::vertex_attr_array![
];
impl BlockVertex {
pub fn descriptor<'a>() -> wgpu::VertexBufferLayout<'a> {
pub fn descriptor() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout {
array_stride: size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Vertex,
attributes: BLOCK_VERTEX_DESC,
attributes: BLOCK_VERTEX_ATTRIBUTES,
}
}
}