From 43a73e525789679b0b0824329288fe4226a135e2 Mon Sep 17 00:00:00 2001 From: Imbris Date: Tue, 14 May 2019 02:43:07 -0400 Subject: [PATCH] ingame_ui Former-commit-id: 5e836043d58f9217d711462d9f700e3eb096a076 --- voxygen/shaders/ui.frag | 7 ++ voxygen/shaders/ui.vert | 18 ++- voxygen/src/hud/mod.rs | 52 +++++++-- voxygen/src/menu/char_selection/mod.rs | 2 +- voxygen/src/menu/char_selection/scene.rs | 4 + voxygen/src/menu/char_selection/ui.rs | 6 +- voxygen/src/menu/main/ui.rs | 2 +- voxygen/src/render/mod.rs | 3 +- voxygen/src/render/pipelines/ui.rs | 25 +++- voxygen/src/render/renderer.rs | 4 + voxygen/src/scene/mod.rs | 5 + voxygen/src/session.rs | 3 +- voxygen/src/ui/mod.rs | 139 ++++++++++++++++------- voxygen/src/ui/scale.rs | 4 + voxygen/src/ui/widgets/ingame.rs | 98 ++++++++++++++++ voxygen/src/ui/widgets/mod.rs | 1 + 16 files changed, 312 insertions(+), 61 deletions(-) create mode 100644 voxygen/src/ui/widgets/ingame.rs diff --git a/voxygen/shaders/ui.frag b/voxygen/shaders/ui.frag index 7ef02c68b5..2d77dd3ef7 100644 --- a/voxygen/shaders/ui.frag +++ b/voxygen/shaders/ui.frag @@ -1,9 +1,16 @@ #version 330 core +#include + in vec2 f_uv; in vec4 f_color; flat in uint f_mode; +layout (std140) +uniform u_locals { + vec4 w_pos; +}; + uniform sampler2D u_tex; out vec4 tgt_color; diff --git a/voxygen/shaders/ui.vert b/voxygen/shaders/ui.vert index ab90588fc3..54ab3c7a1e 100644 --- a/voxygen/shaders/ui.vert +++ b/voxygen/shaders/ui.vert @@ -1,10 +1,17 @@ #version 330 core +#include + in vec2 v_pos; in vec2 v_uv; in vec4 v_color; in uint v_mode; +layout (std140) +uniform u_locals { + vec4 w_pos; +}; + uniform sampler2D u_tex; out vec2 f_uv; @@ -14,6 +21,15 @@ out vec4 f_color; void main() { f_uv = v_uv; f_color = v_color; - gl_Position = vec4(v_pos, 0.0, 1.0); + + if (w_pos.w == 1.0) { + // In-game element + gl_Position = + proj_mat * + (view_mat * w_pos + vec4(v_pos, 0.0, 0.0)); + } else { + // Interface element + gl_Position = vec4(v_pos, 0.0, 1.0); + } f_mode = v_mode; } diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 9949bae1ae..4f06bb4673 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -23,17 +23,20 @@ use skillbar::Skillbar; use small_window::{SmallWindow, SmallWindowType}; use crate::{ - render::Renderer, + render::{Consts, Globals, Renderer}, settings::{ControlSettings, Settings}, - ui::{ScaleMode, Ui}, + ui::{Ingame, ScaleMode, Ui}, window::{Event as WinEvent, Key, Window}, GlobalState, }; +use client::Client; +use common::comp; use conrod_core::{ color, graph, widget::{self, Button, Image, Rectangle, Text}, widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, }; +use specs::Join; use std::collections::VecDeque; const XP_COLOR: Color = Color::Rgba(0.59, 0.41, 0.67, 1.0); @@ -43,7 +46,11 @@ const MANA_COLOR: Color = Color::Rgba(0.42, 0.41, 0.66, 1.0); widget_ids! { struct Ids { + // Character Names + name_tags[], + // Test + temp, bag_space_add, // Debug debug_bg, @@ -253,7 +260,7 @@ impl Hud { } } - fn update_layout(&mut self, global_state: &GlobalState, debug_info: DebugInfo) -> Vec { + fn update_layout(&mut self, client: &Client, global_state: &GlobalState, debug_info: DebugInfo) -> Vec { let mut events = Vec::new(); let ref mut ui_widgets = self.ui.set_widgets(); let version = env!("CARGO_PKG_VERSION"); @@ -263,6 +270,34 @@ impl Hud { return events; } + // Nametags + let ecs = client.state().ecs(); + /* { + let actor_read_storage = ecs.read_storage::(); + let pos_read_storage = ecs.read_storage::(); + let num = (&actor_read_storage, &pos_read_storage).join().count(); + self.ids + .name_tags + .resize(num, &mut ui_widgets.widget_id_generator()); + for (i, (name, pos)) in (&actor_read_storage, &pos_read_storage) + .join() + .map(|(actor, pos)| match actor { + comp::Actor::Character { name, .. } => (name, pos.0), + }) + .enumerate() + { + Ingame::from_primitive(pos, Text::new(&name)) + .set(self.ids.name_tags[i], ui_widgets); + } + }*/ + // test + Ingame::from_primitive( + [0.0, 25.0, 25.0].into(), + Rectangle::fill_with([1.0, 1.0], Color::Rgba(0.2, 0.0, 0.4, 1.0)), + ) + .x_y(0.0, 0.0) + .set(self.ids.temp, ui_widgets); + // Display debug window. if self.show.debug { // Alpha Version @@ -474,7 +509,9 @@ impl Hud { self.ui .widget_graph() .widget(id) - .and_then(graph::Container::unique_widget_state::) + .filter(|c| { + c.type_id == std::any::TypeId::of::<::State>() + }) .is_some() } else { false @@ -580,19 +617,20 @@ impl Hud { pub fn maintain( &mut self, + client: &Client, global_state: &mut GlobalState, debug_info: DebugInfo, ) -> Vec { if let Some(maybe_id) = self.to_focus.take() { self.ui.focus_widget(maybe_id); } - let events = self.update_layout(&global_state, debug_info); + let events = self.update_layout(client, global_state, debug_info); self.ui.maintain(&mut global_state.window.renderer_mut()); events } - pub fn render(&self, renderer: &mut Renderer) { - self.ui.render(renderer); + pub fn render(&self, renderer: &mut Renderer, globals: &Consts) { + self.ui.render(renderer, Some(globals)); } } diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index 85c93fce63..4a75a4b3ba 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -106,7 +106,7 @@ impl PlayState for CharSelectionState { // Draw the UI to the screen. self.char_selection_ui - .render(global_state.window.renderer_mut()); + .render(global_state.window.renderer_mut(), self.scene.globals()); // Tick the client (currently only to keep the connection alive). self.client diff --git a/voxygen/src/menu/char_selection/scene.rs b/voxygen/src/menu/char_selection/scene.rs index 7c9af72ac6..66e0d1ba1c 100644 --- a/voxygen/src/menu/char_selection/scene.rs +++ b/voxygen/src/menu/char_selection/scene.rs @@ -72,6 +72,10 @@ impl Scene { } } + pub fn globals(&self) -> &Consts { + &self.globals + } + pub fn maintain(&mut self, renderer: &mut Renderer, client: &Client) { self.camera.set_focus_pos(Vec3::unit_z() * 2.0); self.camera.update(client.state().get_time()); diff --git a/voxygen/src/menu/char_selection/ui.rs b/voxygen/src/menu/char_selection/ui.rs index 0dc08a092e..2246f01159 100644 --- a/voxygen/src/menu/char_selection/ui.rs +++ b/voxygen/src/menu/char_selection/ui.rs @@ -1,5 +1,5 @@ use crate::{ - render::Renderer, + render::{Consts, Globals, Renderer}, ui::{ self, img_ids::{ImageGraphic, VoxelGraphic}, @@ -1085,7 +1085,7 @@ impl CharSelectionUi { events } - pub fn render(&self, renderer: &mut Renderer) { - self.ui.render(renderer); + pub fn render(&self, renderer: &mut Renderer, globals: &Consts) { + self.ui.render(renderer, Some(globals)); } } diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs index 6f59a54c8d..9b62246b8b 100644 --- a/voxygen/src/menu/main/ui.rs +++ b/voxygen/src/menu/main/ui.rs @@ -513,6 +513,6 @@ impl MainMenuUi { } pub fn render(&self, renderer: &mut Renderer) { - self.ui.render(renderer); + self.ui.render(renderer, None); } } diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 9159b8d0aa..84379ac1c3 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -19,7 +19,8 @@ pub use self::{ skybox::{create_mesh as create_skybox_mesh, Locals as SkyboxLocals, SkyboxPipeline}, terrain::{Locals as TerrainLocals, TerrainPipeline}, ui::{ - create_quad as create_ui_quad, create_tri as create_ui_tri, Mode as UiMode, UiPipeline, + create_quad as create_ui_quad, create_tri as create_ui_tri, Locals as UiLocals, + Mode as UiMode, UiPipeline, }, Globals, }, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 2ebbcc3bcf..ac2433ffa1 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -1,6 +1,7 @@ -use super::super::{Pipeline, Quad, Tri, WinColorFmt, WinDepthFmt}; +use super::super::{Globals, Pipeline, Quad, Tri, WinColorFmt, WinDepthFmt}; use gfx::{ self, + gfx_constant_struct_meta, // Macros gfx_defines, gfx_impl_struct_meta, @@ -18,15 +19,21 @@ gfx_defines! { mode: u32 = "v_mode", } + constant Locals { + pos: [f32; 4] = "w_pos", + } + pipeline pipe { vbuf: gfx::VertexBuffer = (), + locals: gfx::ConstantBuffer = "u_locals", + globals: gfx::ConstantBuffer = "u_globals", tex: gfx::TextureSampler<[f32; 4]> = "u_tex", scissor: gfx::Scissor = (), tgt_color: gfx::BlendTarget = ("tgt_color", gfx::state::ColorMask::all(), gfx::preset::blend::ALPHA), - tgt_depth: gfx::DepthTarget = gfx::preset::depth::PASS_TEST, + tgt_depth: gfx::DepthTarget = gfx::preset::depth::LESS_EQUAL_WRITE, } } @@ -36,6 +43,20 @@ impl Pipeline for UiPipeline { type Vertex = Vertex; } +impl From> for Locals { + fn from(pos: Vec3) -> Self { + Self { + pos: [pos[0], pos[1], pos[2], 1.0], + } + } +} + +impl Default for Locals { + fn default() -> Self { + Self { pos: [0.0; 4] } + } +} + /// Draw text from the text cache texture `tex` in the fragment shader. pub const MODE_TEXT: u32 = 0; /// Draw an image from the texture at `tex` in the fragment shader. diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index fbd0397968..3c8c38d56b 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -423,6 +423,8 @@ impl Renderer { model: &Model, tex: &Texture, scissor: Aabr, + globals: &Consts, + locals: &Consts, ) { let Aabr { min, max } = scissor; self.encoder.draw( @@ -437,6 +439,8 @@ impl Renderer { h: max.y - min.y, }, tex: (tex.srv.clone(), tex.sampler.clone()), + locals: locals.buf.clone(), + globals: globals.buf.clone(), tgt_color: self.win_color_view.clone(), tgt_depth: self.win_depth_view.clone(), }, diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index dad88a7c03..8fcb143ada 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -68,6 +68,11 @@ impl Scene { } } + /// Get a reference to the scene's globals + pub fn globals(&self) -> &Consts { + &self.globals + } + /// Get a reference to the scene's camera. pub fn camera(&self) -> &Camera { &self.camera diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs index 7457f84448..3e6eeae16d 100644 --- a/voxygen/src/session.rs +++ b/voxygen/src/session.rs @@ -100,7 +100,7 @@ impl SessionState { // Render the screen using the global renderer self.scene.render(renderer, &mut self.client.borrow_mut()); // Draw the UI to the screen - self.hud.render(renderer); + self.hud.render(renderer, self.scene.globals()); // Finish the frame renderer.flush(); @@ -178,6 +178,7 @@ impl PlayState for SessionState { // extract HUD events ensuring the client borrow gets dropped let hud_events = self.hud.maintain( + &self.client.borrow(), global_state, DebugInfo { tps: clock.get_tps(), diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index 0ad8129663..889eae471f 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -12,12 +12,12 @@ mod font_ids; pub use event::Event; pub use graphic::Graphic; pub use scale::ScaleMode; -pub use widgets::{image_slider::ImageSlider, toggle_button::ToggleButton}; +pub use widgets::{image_slider::ImageSlider, ingame::Ingame, toggle_button::ToggleButton}; use crate::{ render::{ - create_ui_quad, create_ui_tri, DynamicModel, Mesh, RenderError, Renderer, UiMode, - UiPipeline, + create_ui_quad, create_ui_tri, Consts, DynamicModel, Globals, Mesh, RenderError, Renderer, + UiLocals, UiMode, UiPipeline, }, window::Window, Error, @@ -27,11 +27,11 @@ use common::assets; use conrod_core::{ event::Input, graph::Graph, - image::{Id as ImgId, Map}, + image::{self, Map}, input::{touch::Touch, Motion, Widget}, - render::Primitive, + render::{Primitive, PrimitiveKind}, text::{self, font}, - widget::{id::Generator, Id as WidgId}, + widget::{self, id::Generator}, Ui as CrUi, UiBuilder, UiCell, }; use graphic::Id as GraphicId; @@ -55,6 +55,7 @@ enum DrawKind { enum DrawCommand { Draw { kind: DrawKind, verts: Range }, Scissor(Aabr), + WorldPos(Option>), } impl DrawCommand { fn image(verts: Range) -> DrawCommand { @@ -88,6 +89,9 @@ pub struct Ui { draw_commands: Vec, // Model for drawing the ui model: DynamicModel, + // Consts for default ui drawing position (ie the interface) + interface_locals: Consts, + default_globals: Consts, // Window size for updating scaling window_resized: Option>, // Scaling of the ui @@ -99,12 +103,16 @@ impl Ui { let scale = Scale::new(window, ScaleMode::Absolute(1.0)); let win_dims = scale.scaled_window_size().into_array(); + let mut renderer = window.renderer_mut(); + Ok(Self { ui: UiBuilder::new(win_dims).build(), image_map: Map::new(), - cache: Cache::new(window.renderer_mut())?, + cache: Cache::new(renderer)?, draw_commands: vec![], - model: window.renderer_mut().create_dynamic_model(100)?, + model: renderer.create_dynamic_model(100)?, + interface_locals: renderer.create_consts(&[UiLocals::default()])?, + default_globals: renderer.create_consts(&[Globals::default()])?, window_resized: None, scale, }) @@ -118,7 +126,7 @@ impl Ui { self.ui.handle_event(Input::Resize(w, h)); } - pub fn add_graphic(&mut self, graphic: Graphic) -> ImgId { + pub fn add_graphic(&mut self, graphic: Graphic) -> image::Id { self.image_map.insert(self.cache.add_graphic(graphic)) } @@ -135,7 +143,7 @@ impl Ui { } // Accepts Option so widget can be unfocused. - pub fn focus_widget(&mut self, id: Option) { + pub fn focus_widget(&mut self, id: Option) { self.ui.keyboard_capture(match id { Some(id) => id, None => self.ui.window, @@ -143,7 +151,7 @@ impl Ui { } // Get id of current widget capturing keyboard. - pub fn widget_capturing_keyboard(&self) -> Option { + pub fn widget_capturing_keyboard(&self) -> Option { self.ui.global_input().current.widget_capturing_keyboard } @@ -189,7 +197,7 @@ impl Ui { } } - pub fn widget_input(&self, id: WidgId) -> Widget { + pub fn widget_input(&self, id: widget::Id) -> Widget { self.ui.widget_input(id) } @@ -216,6 +224,9 @@ impl Ui { let window_scissor = default_scissor(renderer); let mut current_scissor = window_scissor; + let mut in_world = None; + let mut p_scale_factor = self.scale.scale_factor_physical(); + // Switches to the `Plain` state and completes the previous `Command` if not already in the // `Plain` state. macro_rules! switch_to_plain_state { @@ -223,14 +234,12 @@ impl Ui { if let State::Image = current_state { self.draw_commands .push(DrawCommand::image(start..mesh.vertices().len())); - current_state = State::Plain; start = mesh.vertices().len(); + current_state = State::Plain; } }; } - let p_scale_factor = self.scale.scale_factor_physical(); - while let Some(prim) = primitives.next() { let Primitive { kind, @@ -272,9 +281,29 @@ impl Ui { self.draw_commands.push(DrawCommand::Scissor(new_scissor)); } + match in_world { + Some(0) => { + in_world = None; + p_scale_factor = self.scale.scale_factor_physical(); + // Finish current state + self.draw_commands.push(match current_state { + State::Plain => DrawCommand::plain(start..mesh.vertices().len()), + State::Image => DrawCommand::image(start..mesh.vertices().len()), + }); + start = mesh.vertices().len(); + // Push new position command + self.draw_commands.push(DrawCommand::WorldPos(None)); + } + Some(n) => in_world = Some(n - 1), + None => (), + } + // Functions for converting for conrod scalar coords to GL vertex coords (-1.0 to 1.0). - let ui_win_w = self.ui.win_w; - let ui_win_h = self.ui.win_h; + let (ui_win_w, ui_win_h) = if in_world.is_some() { + (2.0, 2.0) + } else { + (self.ui.win_w, self.ui.win_h) + }; let vx = |x: f64| (x / ui_win_w * 2.0) as f32; let vy = |y: f64| (y / ui_win_h * 2.0) as f32; let gl_aabr = |rect: conrod_core::Rect| { @@ -285,7 +314,6 @@ impl Ui { } }; - use conrod_core::render::PrimitiveKind; match kind { PrimitiveKind::Image { image_id, @@ -321,16 +349,17 @@ impl Ui { // Transform the source rectangle into uv coordinate. // TODO: Make sure this is right. let source_aabr = { - let (uv_l, uv_r, uv_b, uv_t) = (0.0, 1.0, 0.0, 1.0); /*match source_rect { - Some(src_rect) => { - let (l, r, b, t) = src_rect.l_r_b_t(); - ((l / image_w) as f32, - (r / image_w) as f32, - (b / image_h) as f32, - (t / image_h) as f32) - } - None => (0.0, 1.0, 0.0, 1.0), - };*/ + let (uv_l, uv_r, uv_b, uv_t) = (0.0, 1.0, 0.0, 1.0); + /*match source_rect { + Some(src_rect) => { + let (l, r, b, t) = src_rect.l_r_b_t(); + ((l / image_w) as f32, + (r / image_w) as f32, + (b / image_h) as f32, + (t / image_h) as f32) + } + None => (0.0, 1.0, 0.0, 1.0), + };*/ Aabr { min: Vec2::new(uv_l, uv_b), max: Vec2::new(uv_r, uv_t), @@ -371,13 +400,8 @@ impl Ui { font_id, } => { switch_to_plain_state!(); - // Get screen width and height. - let (screen_w, screen_h) = - renderer.get_resolution().map(|e| e as f32).into_tuple(); - // Calculate dpi factor. - let dpi_factor = screen_w / ui_win_w as f32; - let positioned_glyphs = text.positioned_glyphs(dpi_factor); + let positioned_glyphs = text.positioned_glyphs(p_scale_factor as f32); let (glyph_cache, cache_tex) = self.cache.glyph_cache_mut_and_tex(); // Queue the glyphs to be cached. for glyph in positioned_glyphs { @@ -410,12 +434,12 @@ impl Ui { }; let rect = Aabr { min: Vec2::new( - (screen_rect.min.x as f32 / screen_w - 0.5) * 2.0, - (screen_rect.max.y as f32 / screen_h - 0.5) * -2.0, + vx(screen_rect.min.x as f64 / p_scale_factor) - 1.0, + 1.0 - vy(screen_rect.max.y as f64 / p_scale_factor), ), max: Vec2::new( - (screen_rect.max.x as f32 / screen_w - 0.5) * 2.0, - (screen_rect.min.y as f32 / screen_h - 0.5) * -2.0, + vx(screen_rect.max.x as f64 / p_scale_factor) - 1.0, + 1.0 - vy(screen_rect.min.y as f64 / p_scale_factor), ), }; mesh.push_quad(create_ui_quad(rect, uv, color, UiMode::Text)); @@ -469,10 +493,32 @@ impl Ui { )); } } + PrimitiveKind::Other(container) => { + if container.type_id == std::any::TypeId::of::() { + // Retrieve world position + let pos = container + .state_and_style::() + .unwrap() + .state + .pos; + // Finish current state + self.draw_commands.push(match current_state { + State::Plain => DrawCommand::plain(start..mesh.vertices().len()), + State::Image => DrawCommand::image(start..mesh.vertices().len()), + }); + start = mesh.vertices().len(); + // Push new position command + self.draw_commands.push(DrawCommand::WorldPos(Some( + renderer.create_consts(&[pos.into()]).unwrap(), + ))); + + in_world = Some(1); + p_scale_factor = self.scale.dpi_factor(); + } + } _ => {} // TODO: Add this. //PrimitiveKind::TrianglesMultiColor {..} => {println!("primitive kind multicolor with id {:?}", id);} // Other unneeded for now. - //PrimitiveKind::Other {..} => {println!("primitive kind other with id {:?}", id);} } } // Enter the final command. @@ -506,12 +552,17 @@ impl Ui { } } - pub fn render(&self, renderer: &mut Renderer) { - let mut scissor_to_render = default_scissor(renderer); + pub fn render(&self, renderer: &mut Renderer, maybe_globals: Option<&Consts>) { + let mut scissor = default_scissor(renderer); + let globals = maybe_globals.unwrap_or(&self.default_globals); + let mut locals = &self.interface_locals; for draw_command in self.draw_commands.iter() { match draw_command { - DrawCommand::Scissor(scissor) => { - scissor_to_render = *scissor; + DrawCommand::Scissor(new_scissor) => { + scissor = *new_scissor; + } + DrawCommand::WorldPos(ref pos) => { + locals = pos.as_ref().unwrap_or(&self.interface_locals); } DrawCommand::Draw { kind, verts } => { let tex = match kind { @@ -519,7 +570,7 @@ impl Ui { DrawKind::Plain => self.cache.glyph_cache_tex(), }; let model = self.model.submodel(verts.clone()); - renderer.render_ui_element(&model, &tex, scissor_to_render); + renderer.render_ui_element(&model, &tex, scissor, globals, locals); } } } diff --git a/voxygen/src/ui/scale.rs b/voxygen/src/ui/scale.rs index 46c945fb52..9c096cf366 100644 --- a/voxygen/src/ui/scale.rs +++ b/voxygen/src/ui/scale.rs @@ -48,6 +48,10 @@ impl Scale { pub fn scale_factor_physical(&self) -> f64 { self.scale_factor_logical() * self.dpi_factor } + // Get the dpi factor (ratio between physical and logical coordinates) + pub fn dpi_factor(&self) -> f64 { + self.dpi_factor + } // Updates internal window size (and/or dpi_factor). pub fn window_resized(&mut self, new_dims: Vec2, renderer: &Renderer) { self.dpi_factor = renderer.get_resolution().x as f64 / new_dims.x; diff --git a/voxygen/src/ui/widgets/ingame.rs b/voxygen/src/ui/widgets/ingame.rs new file mode 100644 index 0000000000..0bdba32f06 --- /dev/null +++ b/voxygen/src/ui/widgets/ingame.rs @@ -0,0 +1,98 @@ +use conrod_core::{ + image, + position::Dimension, + widget::{self, button}, + widget_ids, Color, Position, Positionable, Rect, Sizeable, Ui, Widget, WidgetCommon, +}; +use vek::*; + +#[derive(Clone, WidgetCommon)] +pub struct Ingame +where + W: Widget, +{ + #[conrod(common_builder)] + common: widget::CommonBuilder, + widget: W, + pos: Vec3, +} + +// TODO: add convenience function to this trait +pub trait Primitive {} +impl Primitive for widget::Line {} +impl Primitive for widget::Image {} +impl Primitive for widget::PointPath {} +impl Primitive for widget::Circle {} +impl Primitive for widget::Oval {} +impl Primitive for widget::Polygon {} +impl Primitive for widget::Rectangle {} +impl Primitive for widget::Triangles {} +impl<'a> Primitive for widget::Text<'a> {} + +widget_ids! { + struct Ids { + prim, + } +} + +pub struct State { + ids: Ids, + pub pos: Vec3, +} + +pub type Style = (); + +impl Ingame { + pub fn from_primitive(pos: Vec3, widget: W) -> Self { + Self { + common: widget::CommonBuilder::default(), + pos, + widget, + } + } +} + +impl Widget for Ingame { + type State = State; + type Style = Style; + type Event = (); + + fn init_state(&self, id_gen: widget::id::Generator) -> Self::State { + State { + ids: Ids::new(id_gen), + pos: Vec3::default(), + } + } + + fn style(&self) -> Self::Style { + () + } + + fn update(self, args: widget::UpdateArgs) -> Self::Event { + let widget::UpdateArgs { id, state, ui, .. } = args; + let Ingame { widget, pos, .. } = self; + + // Update pos if it has changed + if state.pos != pos { + state.update(|s| s.pos = pos); + } + + widget + .graphics_for(ui.window) + .parent(id) // is this needed + .set(state.ids.prim, ui); + } + + fn default_x_position(&self, ui: &Ui) -> Position { + Position::Absolute(0.0) + } + fn default_y_position(&self, ui: &Ui) -> Position { + Position::Absolute(0.0) + } + fn default_x_dimension(&self, ui: &Ui) -> Dimension { + Dimension::Absolute(1.0) + } + fn default_y_dimension(&self, ui: &Ui) -> Dimension { + Dimension::Absolute(1.0) + } +} diff --git a/voxygen/src/ui/widgets/mod.rs b/voxygen/src/ui/widgets/mod.rs index 21f1c2656d..26420fc870 100644 --- a/voxygen/src/ui/widgets/mod.rs +++ b/voxygen/src/ui/widgets/mod.rs @@ -1,2 +1,3 @@ pub mod image_slider; +pub mod ingame; pub mod toggle_button;