diff --git a/assets/voxygen/shaders/include/globals.glsl b/assets/voxygen/shaders/include/globals.glsl index 95420ce179..12996de625 100644 --- a/assets/voxygen/shaders/include/globals.glsl +++ b/assets/voxygen/shaders/include/globals.glsl @@ -10,4 +10,5 @@ uniform u_globals { vec4 screen_res; uvec4 light_shadow_count; uvec4 medium; + ivec4 select_pos; }; diff --git a/assets/voxygen/shaders/sprite-vert.glsl b/assets/voxygen/shaders/sprite-vert.glsl index 6e7a4c384a..fedbc0a749 100644 --- a/assets/voxygen/shaders/sprite-vert.glsl +++ b/assets/voxygen/shaders/sprite-vert.glsl @@ -27,6 +27,8 @@ void main() { inst_mat[2] = inst_mat2; inst_mat[3] = inst_mat3; + vec3 sprite_pos = (inst_mat * vec4(0, 0, 0, 1)).xyz; + f_pos = (inst_mat * vec4(v_pos * SCALE, 1)).xyz; // Wind waving @@ -40,6 +42,11 @@ void main() { f_col = srgb_to_linear(v_col) * srgb_to_linear(inst_col); + // Select glowing + if (select_pos.w > 0 && select_pos.xyz == floor(sprite_pos)) { + f_col *= 4.0; + } + f_light = 1.0; gl_Position = diff --git a/voxygen/src/menu/char_selection/scene.rs b/voxygen/src/menu/char_selection/scene.rs index c735e8b156..96f7f4594f 100644 --- a/voxygen/src/menu/char_selection/scene.rs +++ b/voxygen/src/menu/char_selection/scene.rs @@ -138,6 +138,7 @@ impl Scene { 0, 0, BlockKind::Air, + None, )], ) { error!("Renderer failed to update: {:?}", err); diff --git a/voxygen/src/render/pipelines/mod.rs b/voxygen/src/render/pipelines/mod.rs index cc73033257..1d25d2dc9b 100644 --- a/voxygen/src/render/pipelines/mod.rs +++ b/voxygen/src/render/pipelines/mod.rs @@ -30,6 +30,7 @@ gfx_defines! { screen_res: [f32; 4] = "screen_res", light_shadow_count: [u32; 4] = "light_shadow_count", medium: [u32; 4] = "medium", + select_pos: [i32; 4] = "select_pos", } constant Light { @@ -56,6 +57,7 @@ impl Globals { light_count: usize, shadow_count: usize, medium: BlockKind, + select_pos: Option>, ) -> Self { Self { view_mat: arr_to_mat(view_mat.into_col_array()), @@ -68,6 +70,10 @@ impl Globals { screen_res: Vec4::from(screen_res.map(|e| e as f32)).into_array(), light_shadow_count: [light_count as u32, shadow_count as u32, 0, 0], medium: [if medium.is_fluid() { 1 } else { 0 }; 4], + select_pos: select_pos + .map(|sp| Vec4::from(sp) + Vec4::unit_w()) + .unwrap_or(Vec4::zero()) + .into_array(), } } } @@ -86,6 +92,7 @@ impl Default for Globals { 0, 0, BlockKind::Air, + None, ) } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index d22886ab7d..b863015478 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -55,6 +55,7 @@ pub struct Scene { postprocess: PostProcess, terrain: Terrain, loaded_distance: f32, + select_pos: Option>, figure_mgr: FigureMgr, sound_mgr: SoundMgr, @@ -87,6 +88,8 @@ impl Scene { }, terrain: Terrain::new(renderer), loaded_distance: 0.0, + select_pos: None, + figure_mgr: FigureMgr::new(), sound_mgr: SoundMgr::new(), } @@ -107,6 +110,11 @@ impl Scene { &mut self.camera } + /// Set the block position that the player is interacting with + pub fn set_select_pos(&mut self, pos: Option>) { + self.select_pos = pos; + } + /// Handle an incoming user input event (e.g.: cursor moved, key pressed, window closed). /// /// If the event is handled, return true. @@ -257,6 +265,7 @@ impl Scene { .get(cam_pos.map(|e| e.floor() as i32)) .map(|b| b.kind()) .unwrap_or(BlockKind::Air), + self.select_pos, )], ) .expect("Failed to update global constants"); diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 6e81cf5f4b..7e1e8c754e 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -117,6 +117,27 @@ impl PlayState for SessionState { .compute_dependents(&self.client.borrow()); let cam_dir: Vec3 = Vec3::from(view_mat.inverted() * -Vec4::unit_z()); + // Check to see whether we're aiming at anything + let (build_pos, select_pos) = { + let client = self.client.borrow(); + let terrain = client.state().terrain(); + let ray = terrain + .ray(cam_pos, cam_pos + cam_dir * 100.0) + .until(|block| block.is_tangeable()) + .cast(); + let dist = ray.0; + if let Ok(Some(_)) = ray.1 { + // Hit something! + ( + Some((cam_pos + cam_dir * (dist - 0.001)).map(|e| e.floor() as i32)), + Some((cam_pos + cam_dir * dist).map(|e| e.floor() as i32)), + ) + } else { + (None, None) + } + }; + self.scene.set_select_pos(select_pos); + // Reset controller events self.controller.clear_events(); @@ -142,19 +163,8 @@ impl PlayState for SessionState { .get(client.entity()) .is_some() { - let (d, b) = { - let terrain = client.state().terrain(); - let ray = terrain - .ray(cam_pos, cam_pos + cam_dir * 100.0) - .until(|block| !block.is_air()) - .cast(); - (ray.0, if let Ok(Some(_)) = ray.1 { true } else { false }) - }; - - if b { - let pos = - (cam_pos + cam_dir * (d - 0.01)).map(|e| e.floor() as i32); - client.place_block(pos, self.selected_block); + if let Some(build_pos) = build_pos { + client.place_block(build_pos, self.selected_block); } } else { self.controller.primary = state @@ -166,21 +176,6 @@ impl PlayState for SessionState { let mut client = self.client.borrow_mut(); - let hit_pos = { - let terrain = client.state().terrain(); - let ray = terrain - .ray(cam_pos, cam_pos + cam_dir * 100.0) - .until(|block| block.is_tangeable()) - .cast(); - let dist = ray.0; - if let Ok(Some(_)) = ray.1 { - // Hit something! - Some((cam_pos + cam_dir * dist).map(|e| e.floor() as i32)) - } else { - None - } - }; - if state && client .state() @@ -188,8 +183,8 @@ impl PlayState for SessionState { .get(client.entity()) .is_some() { - if let Some(hit_pos) = hit_pos { - client.remove_block(hit_pos); + if let Some(select_pos) = select_pos { + client.remove_block(select_pos); } } else if client .state() @@ -200,8 +195,8 @@ impl PlayState for SessionState { { self.controller.secondary = state; } else { - if let Some(hit_pos) = hit_pos { - client.collect_block(hit_pos); + if let Some(select_pos) = select_pos { + client.collect_block(select_pos); } } } @@ -214,14 +209,10 @@ impl PlayState for SessionState { .is_some() { if state { - if let Ok(Some(block)) = client - .state() - .terrain() - .ray(cam_pos, cam_pos + cam_dir * 100.0) - .cast() - .1 + if let Some(block) = select_pos + .and_then(|sp| client.state().terrain().get(sp).ok().copied()) { - self.selected_block = *block; + self.selected_block = block; } } } else {