diff --git a/src/gl/mod.rs b/src/gl/mod.rs index 08d23f2..38e8e3a 100644 --- a/src/gl/mod.rs +++ b/src/gl/mod.rs @@ -402,7 +402,7 @@ impl Attribute { pub fn vertex_pointer(&self, size: i32, ty: Type, normalized: bool, stride: i32, offset: i32) { unsafe { - gl::VertexAttribPointer(self.internal as u32, size, ty, if normalized { 1 } else { 0 }, stride, offset as *const gl::types::GLvoid); + gl::VertexAttribPointer(self.internal as u32, size, ty, normalized as u8, stride, offset as *const gl::types::GLvoid); } } diff --git a/src/main.rs b/src/main.rs index 3ac3c11..a78b2a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub mod bit; pub mod protocol; pub mod format; pub mod nbt; @@ -63,14 +62,7 @@ fn main() { let mut last_frame = time::now(); let frame_time = (time::Duration::seconds(1).num_nanoseconds().unwrap() as f64) / 60.0; - // Test stuff - let img = ui::Image::new( - render::Renderer::get_texture(renderer.get_textures_ref(), "steven:gui/cog"), - 50.0, 50.0, 100.0, 100.0, - 0.0, 0.0, 1.0, 1.0, - 255, 255, 255 - ); - let img_ref = ui_container.add(img); + let logo = ui::logo::Logo::new(resource_manager.clone(), &mut renderer, &mut ui_container); while !window.should_close() { { resource_manager.write().unwrap().tick(); } diff --git a/src/bit/map.rs b/src/types/bit/map.rs similarity index 100% rename from src/bit/map.rs rename to src/types/bit/map.rs diff --git a/src/bit/mod.rs b/src/types/bit/mod.rs similarity index 100% rename from src/bit/mod.rs rename to src/types/bit/mod.rs diff --git a/src/bit/set.rs b/src/types/bit/set.rs similarity index 100% rename from src/bit/set.rs rename to src/types/bit/set.rs diff --git a/src/types/mod.rs b/src/types/mod.rs index 681b872..034015f 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -17,3 +17,5 @@ pub use self::blockpos::*; mod metadata; pub use self::metadata::*; + +pub mod bit; \ No newline at end of file diff --git a/src/ui/logo.rs b/src/ui/logo.rs new file mode 100644 index 0000000..efd2f27 --- /dev/null +++ b/src/ui/logo.rs @@ -0,0 +1,84 @@ + +use std::sync::{Arc, RwLock}; +use ui; +use render; +use resources; + +pub struct Logo { + resources: Arc>, +} + +impl Logo { + pub fn new(resources: Arc>, renderer: &mut render::Renderer, ui_container: &mut ui::Container) -> Logo { + let mut l = Logo { + resources: resources + }; + l.init(renderer, ui_container); + l + } + + fn init(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) { + let res = self.resources.read().unwrap(); + + let mut logo = res.open("steven", "logo/logo.txt").unwrap(); + let mut logo_str = String::new(); + logo.read_to_string(&mut logo_str).unwrap(); + + let solid = render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid"); + let stone = render::Renderer::get_texture(renderer.get_textures_ref(), "blocks/planks_oak"); + + let mut shadow_batch = ui::Batch::new(0.0, 8.0, 100.0, 100.0); + let mut layer0 = ui::Batch::new(0.0, 8.0, 100.0, 100.0); + + shadow_batch.set_h_attach(ui::HAttach::Center); + layer0.set_h_attach(ui::HAttach::Center); + + let mut row = 0; + for line in logo_str.lines() { + if line.is_empty() { + continue; + } + let mut i = 0; + for c in line.chars() { + i += 1; + if c == ' ' { + continue; + } + let x = (i - 1) * 4; + let y = row * 8; + let (r, g, b) = if c == ':' { + (255, 255, 255) + } else { + (170, 170, 170) + }; + let mut shadow = ui::Image::new( + solid.clone(), + (x+2) as f64, (y+4) as f64, 4.0, 8.0, + 0.0, 0.0, 1.0, 1.0, + 0, 0, 0 + ); + shadow.set_a(100); + shadow_batch.add(shadow); + + + let img = ui::Image::new( + stone.clone(), + x as f64, y as f64, 4.0, 8.0, + (x%16) as f64 / 16.0, (y%16) as f64 / 16.0, 4.0/16.0, 8.0/16.0, + r, g, b + ); + layer0.add(img); + + let width = (x + 4) as f64; + if shadow_batch.get_width() < width { + shadow_batch.set_width(width); + layer0.set_width(width); + } + } + row += 1; + } + + ui_container.add(shadow_batch); + ui_container.add(layer0); + } +} \ No newline at end of file diff --git a/src/ui/mod.rs b/src/ui/mod.rs index cb0e19c..8dffdbb 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +pub mod logo; + use std::collections::HashMap; use std::marker::PhantomData; use rand; @@ -22,66 +24,92 @@ const SCALED_HEIGHT: f64 = 480.0; pub enum Element { Image(Image), + Batch(Batch), None, } +macro_rules! element_impl { + ($($name:ident),+) => ( impl Element { fn should_draw(&self) -> bool { match self { - &Element::Image(ref img) => img.should_draw, + $( + &Element::$name(ref val) => val.should_draw, + )+ _ => unimplemented!(), } } fn get_parent(&self) -> Option { match self { - &Element::Image(ref img) => img.parent, + $( + &Element::$name(ref val) => val.parent, + )+ _ => unimplemented!(), } } fn get_attachment(&self) -> (VAttach, HAttach) { match self { - &Element::Image(ref img) => (img.v_attach, img.h_attach), + $( + &Element::$name(ref val) => (val.v_attach, val.h_attach), + )+ _ => unimplemented!(), } } fn get_offset(&self) -> (f64, f64) { match self { - &Element::Image(ref img) => (img.x, img.y), + $( + &Element::$name(ref val) => (val.x, val.y), + )+ _ => unimplemented!(), } } fn get_size(&self) -> (f64, f64) { match self { - &Element::Image(ref img) => (img.width, img.height), + $( + &Element::$name(ref val) => (val.width, val.height), + )+ _ => unimplemented!(), } } fn is_dirty(&self) -> bool { match self { - &Element::Image(ref img) => img.dirty, + $( + &Element::$name(ref val) => val.dirty, + )+ _ => unimplemented!(), } } - fn set_dirty(&mut self, val: bool) { + fn set_dirty(&mut self, dirty: bool) { match self { - &mut Element::Image(ref mut img) => img.dirty = val, + $( + &mut Element::$name(ref mut val) => val.dirty = dirty, + )+ _ => unimplemented!(), } } - fn draw(&mut self, renderer: &mut render::Renderer, r: &Region, width: f64, height: f64, delta: f64) { + fn draw(&mut self, renderer: &mut render::Renderer, r: &Region, width: f64, height: f64, delta: f64) -> &Vec{ match self { - &mut Element::Image(ref mut img) => img.draw(renderer, r, width, height, delta), + $( + &mut Element::$name(ref mut val) => val.draw(renderer, r, width, height, delta), + )+ _ => unimplemented!(), } } } + ) +} + +element_impl!( + Image, + Batch +); pub enum Mode { Scaled, @@ -137,6 +165,13 @@ const SCREEN: Region = Region{x: 0.0, y: 0.0, w: SCALED_WIDTH, h: SCALED_HEIGHT} pub struct Container { pub mode: Mode, elements: HashMap, + // We need the order + elements_list: Vec, + + last_sw: f64, + last_sh: f64, + last_width: f64, + last_height: f64, } impl Container { @@ -144,6 +179,11 @@ impl Container { Container { mode: Mode::Scaled, elements: HashMap::new(), + elements_list: Vec::new(), + last_sw: 0.0, + last_sh: 0.0, + last_width: 0.0, + last_height: 0.0, } } @@ -153,6 +193,7 @@ impl Container { r = ElementRefInner{index: rand::random()}; } self.elements.insert(r, e.wrap()); + self.elements_list.push(r); ElementRef{inner: r, ty: PhantomData} } @@ -166,6 +207,10 @@ impl Container { pub fn remove(&mut self, r: &ElementRef) { self.elements.remove(&r.inner); + self.elements_list.iter() + .position(|&e| e.index == r.inner.index) + .map(|e| self.elements_list.remove(e)) + .unwrap(); } pub fn tick(&mut self, renderer: &mut render::Renderer, delta: f64, width: f64, height: f64) { @@ -174,16 +219,28 @@ impl Container { Mode::Unscaled(scale) => (scale, scale), }; + if self.last_sw != sw || self.last_sh != sh || self.last_width != width || self.last_height != height { + self.last_sw = sw; + self.last_sh = sh; + self.last_width = width; + self.last_height = height; + for (_, e) in &mut self.elements { + e.set_dirty(true); + } + } + // Borrow rules seem to prevent us from doing this in the first pass // so we split it. let regions = self.collect_elements(sw, sh); - for (re, e) in &mut self.elements { + for re in &mut self.elements_list { + let mut e = self.elements.get_mut(re).unwrap(); if !e.should_draw() { continue; } if let Some(&(ref r, ref dirty)) = regions.get(re) { e.set_dirty(*dirty); - e.draw(renderer, r, width, height, delta); + let data = e.draw(renderer, r, width, height, delta); + renderer.ui.add_bytes(data); } } } @@ -216,6 +273,10 @@ impl Container { Some(ref p) => self.get_draw_region(self.elements.get(p).unwrap(), sw, sh), None => SCREEN, }; + Container::get_draw_region_raw(e, sw, sh, &super_region) + } + + fn get_draw_region_raw(e: &Element, sw: f64, sh: f64, super_region: &Region) -> Region { let mut r = Region{x:0.0,y:0.0,w:0.0,h:0.0}; let (w, h) = e.get_size(); let (ox, oy) = e.get_offset(); @@ -314,7 +375,7 @@ impl Image { } } - fn draw(&mut self, renderer: &mut render::Renderer, r: &Region, width: f64, height: f64, delta: f64) { + fn draw(&mut self, renderer: &mut render::Renderer, r: &Region, width: f64, height: f64, delta: f64) -> &Vec { if self.dirty { self.dirty = false; self.texture = renderer.check_texture(self.texture.clone()); @@ -326,7 +387,7 @@ impl Image { e.layer = self.layer; self.data = e.bytes(width, height); } - renderer.ui.add_bytes(&self.data); + &self.data } pub fn set_parent(&mut self, other: ElementRef) { @@ -381,3 +442,97 @@ impl UIElement for Image { } } } + + +pub struct Batch { + dirty: bool, + data: Vec, + + parent: Option, + should_draw: bool, + layer: isize, + x: f64, + y: f64, + width: f64, + height: f64, + v_attach: VAttach, + h_attach: HAttach, + + elements: Vec, +} + +impl Batch { + pub fn new(x: f64, y: f64, w: f64, h: f64) -> Batch { + Batch { + dirty: true, + data: Vec::new(), + + parent: None, + should_draw: true, + layer: 0, + x: x, + y: y, + width: w, + height: h, + v_attach: VAttach::Top, + h_attach: HAttach::Left, + + elements: Vec::new(), + } + } + + fn draw(&mut self, renderer: &mut render::Renderer, r: &Region, width: f64, height: f64, delta: f64) -> &Vec { + if self.dirty { + self.dirty = false; + self.data.clear(); + + let sx = r.w / self.width; + let sy = r.h / self.height; + + for e in &mut self.elements { + let reg = Container::get_draw_region_raw(e, sx, sy, r); + e.set_dirty(true); + self.data.extend(e.draw(renderer, ®, width, height, delta)); + } + } + &self.data + } + + pub fn set_parent(&mut self, other: ElementRef) { + self.parent = Some(other.inner); + self.dirty = true; + } + + pub fn add(&mut self, e: T) { + self.elements.push(e.wrap()); + } + + lazy_field!(layer, isize, get_layer, set_layer); + lazy_field!(x, f64, get_x, set_x); + lazy_field!(y, f64, get_y, set_y); + lazy_field!(width, f64, get_width, set_width); + lazy_field!(height, f64, get_height, set_height); + lazy_field!(v_attach, VAttach, get_v_attach, set_v_attach); + lazy_field!(h_attach, HAttach, get_h_attach, set_h_attach); + +} + +impl UIElement for Batch { + fn wrap(self) -> Element { + Element::Batch(self) + } + + fn unwrap_ref<'a>(e: &'a Element) -> &'a Batch { + match e { + &Element::Batch(ref val) => val, + _ => panic!("Incorrect type"), + } + } + + fn unwrap_ref_mut<'a>(e: &'a mut Element) -> &'a mut Batch { + match e { + &mut Element::Batch(ref mut val) => val, + _ => panic!("Incorrect type"), + } + } +}