Basic logo impl

This commit is contained in:
Thinkofdeath 2015-09-21 21:11:30 +01:00
parent 64d0768fb4
commit 876e88ec95
5 changed files with 283 additions and 18 deletions

View File

@ -18,7 +18,7 @@ I blame Mojang
The logo is totally not ascii art rendered as textures
Look, it works on my machine.
Open Source! https://github.com/thinkofdeath/steven
Built with Go!
Built with Rust!
try { } catch (Exception e) { }
panic(recover())
// Abandon hope all ye who enter here
@ -50,3 +50,4 @@ No touchy the topic
Ceci n'est pas un splash.
Xor is not actually a cat.
The MD5 of md_5 is e14cfacdd442a953343ebd8529138680
I blame Scetch for this!

View File

@ -62,7 +62,7 @@ fn main() {
let mut last_frame = time::now();
let frame_time = (time::Duration::seconds(1).num_nanoseconds().unwrap() as f64) / 60.0;
let logo = ui::logo::Logo::new(resource_manager.clone(), &mut renderer, &mut ui_container);
let mut logo = ui::logo::Logo::new(resource_manager.clone(), &mut renderer, &mut ui_container);
while !window.should_close() {
{ resource_manager.write().unwrap().tick(); }
@ -71,6 +71,8 @@ fn main() {
last_frame = now;
let delta = (diff.num_nanoseconds().unwrap() as f64) / frame_time;
logo.tick(&mut renderer, &mut ui_container);
let (width, height) = window.get_framebuffer_size();
ui_container.tick(&mut renderer, delta, width as f64, height as f64);
renderer.tick(delta, width as u32, height as u32);

View File

@ -28,7 +28,7 @@ const UI_HEIGHT: f64 = 480.0;
pub struct UIState {
textures: Arc<RwLock<render::TextureManager>>,
resources: Arc<RwLock<resources::Manager>>,
version: usize,
pub version: usize,
data: Vec<u8>,
prev_size: usize,
@ -97,7 +97,7 @@ impl UIState {
pos += 1;
}
UIState {
let mut state = UIState {
textures: textures,
resources: res,
version: 0xFFFF,
@ -126,7 +126,9 @@ impl UIState {
char_map: char_map,
page_width: 0.0,
page_height: 0.0,
}
};
state.load_font();
state
}
pub fn tick(&mut self, width: u32, height: u32) {
@ -168,7 +170,6 @@ impl UIState {
gl::draw_elements(gl::TRIANGLES, self.count, self.index_type, 0);
}
gl::disable(gl::BLEND);
self.data.clear();
self.count = 0;
@ -176,7 +177,7 @@ impl UIState {
pub fn add_bytes(&mut self, data: &Vec<u8>) {
self.data.extend(data);
self.count += (data.len() / (28 + 4)) * 6;
self.count += (data.len() / (28 * 4)) * 6;
}
pub fn character_texture(&mut self, c: char) -> render::Texture {
@ -195,7 +196,7 @@ impl UIState {
let p = self.font_pages[page as usize].clone().unwrap();
let raw = if page == 0 {
self.char_map[&c] as u32
(*self.char_map.get(&c).unwrap_or(&c)) as u32
} else {
raw
};
@ -235,7 +236,7 @@ impl UIState {
}
let r = c as u32;
if r >> 8 == 0 {
let r = self.char_map[&c] as u32;
let r = (*self.char_map.get(&c).unwrap_or(&c)) as u32;
let info = self.font_character_info[r as usize];
let sw = self.page_width / 16.0;
return (((info.1 - info.0) as f64) / sw) * 16.0;
@ -315,7 +316,7 @@ impl UIState {
let page = raw >> 8;
if page == 0 {
raw = self.char_map[&ch] as u32;
raw = (*self.char_map.get(&ch).unwrap_or(&ch)) as u32;
}
let info = self.font_character_info[raw as usize];
let w = if page == 0 {

View File

@ -1,17 +1,37 @@
use std::sync::{Arc, RwLock};
use std::f64::consts;
use ui;
use render;
use resources;
use time;
use rand;
use rand::Rng;
pub struct Logo {
resources: Arc<RwLock<resources::Manager>>,
shadow: ui::ElementRef<ui::Batch>,
layer0: ui::ElementRef<ui::Batch>,
text: ui::ElementRef<ui::Text>,
text_base_scale: f64,
text_orig_x: f64,
text_index: isize,
text_strings: Vec<String>,
}
impl Logo {
pub fn new(resources: Arc<RwLock<resources::Manager>>, renderer: &mut render::Renderer, ui_container: &mut ui::Container) -> Logo {
let mut l = Logo {
resources: resources
resources: resources,
shadow: Default::default(),
layer0: Default::default(),
text: Default::default(),
text_base_scale: 0.0,
text_orig_x: 0.0,
text_index: -1,
text_strings: Vec::new(),
};
l.init(renderer, ui_container);
l
@ -77,8 +97,74 @@ impl Logo {
}
row += 1;
}
{
let mut splashes = res.open_all("minecraft", "texts/splashes.txt");
for file in &mut splashes {
let mut texts = String::new();
file.read_to_string(&mut texts).unwrap();
for line in texts.lines() {
self.text_strings.push(line.to_owned().replace("\r", ""));
}
}
let mut r: rand::XorShiftRng = rand::SeedableRng::from_seed([45, 64, 32, 12]);
r.shuffle(&mut self.text_strings[..]);
}
ui_container.add(shadow_batch);
ui_container.add(layer0);
shadow_batch.set_height(row as f64 * 8.0);
layer0.set_height(row as f64 * 8.0);
self.shadow = ui_container.add(shadow_batch);
self.layer0 = ui_container.add(layer0);
let mut txt = ui::Text::new(renderer, "", 0.0, -8.0, 255, 255, 0);
txt.set_h_attach(ui::HAttach::Right);
txt.set_v_attach(ui::VAttach::Bottom);
txt.set_parent(&self.shadow);
txt.set_rotation(-consts::PI / 8.0);
let width = txt.get_width();
self.text_base_scale = 300.0 / width;
if self.text_base_scale > 1.0 {
self.text_base_scale = 1.0;
}
txt.set_x((-width / 2.0) * self.text_base_scale);
self.text_orig_x = txt.get_x();
self.text = ui_container.add(txt);
}
pub fn tick(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
let now = time::now().to_timespec();
// Splash text
let text = ui_container.get_mut(&self.text);
let text_index = (now.sec / 15) as isize % self.text_strings.len() as isize;
if self.text_index != text_index {
self.text_index = text_index;
text.set_text(renderer, &self.text_strings[text_index as usize]);
let width = text.get_width();
self.text_base_scale = 300.0 / width;
if self.text_base_scale > 1.0 {
self.text_base_scale = 1.0;
}
text.set_x((-width / 2.0) * self.text_base_scale);
self.text_orig_x = text.get_x();
}
let timer = now.nsec as f64 / 1000000000.0;
let mut offset = timer / 0.5;
if offset > 1.0 {
offset = 2.0 - offset;
}
offset = ((offset * consts::PI).cos() + 1.0) / 2.0;
text.set_scale_x((0.7 + (offset / 3.0)) * self.text_base_scale);
text.set_scale_y((0.7 + (offset / 3.0)) * self.text_base_scale);
let scale = text.get_scale_x();
text.set_x(self.text_orig_x * scale * self.text_base_scale);
}
pub fn remove(self, ui_container: &mut ui::Container) {
ui_container.remove(&self.shadow);
ui_container.remove(&self.layer0);
ui_container.remove(&self.text);
}
}

View File

@ -25,6 +25,7 @@ const SCALED_HEIGHT: f64 = 480.0;
pub enum Element {
Image(Image),
Batch(Batch),
Text(Text),
None,
}
@ -70,7 +71,7 @@ impl Element {
fn get_size(&self) -> (f64, f64) {
match self {
$(
&Element::$name(ref val) => (val.width, val.height),
&Element::$name(ref val) => val.get_size(),
)+
_ => unimplemented!(),
}
@ -94,6 +95,15 @@ impl Element {
}
}
fn update(&mut self, renderer: &mut render::Renderer) {
match self {
$(
&mut Element::$name(ref mut val) => val.update(renderer),
)+
_ => unimplemented!(),
}
}
fn draw(&mut self, renderer: &mut render::Renderer, r: &Region, width: f64, height: f64, delta: f64) -> &Vec<u8>{
match self {
$(
@ -108,7 +118,8 @@ impl Element {
element_impl!(
Image,
Batch
Batch,
Text
);
pub enum Mode {
@ -160,6 +171,15 @@ struct ElementRefInner {
index: usize,
}
impl <T> Default for ElementRef<T> {
fn default() -> Self {
ElementRef {
inner: ElementRefInner{ index: 0 },
ty: PhantomData,
}
}
}
const SCREEN: Region = Region{x: 0.0, y: 0.0, w: SCALED_WIDTH, h: SCALED_HEIGHT};
pub struct Container {
@ -167,6 +187,7 @@ pub struct Container {
elements: HashMap<ElementRefInner, Element>,
// We need the order
elements_list: Vec<ElementRefInner>,
version: usize,
last_sw: f64,
last_sh: f64,
@ -180,6 +201,7 @@ impl Container {
mode: Mode::Scaled,
elements: HashMap::new(),
elements_list: Vec::new(),
version: 0xFFFF,
last_sw: 0.0,
last_sh: 0.0,
last_width: 0.0,
@ -219,14 +241,20 @@ impl Container {
Mode::Unscaled(scale) => (scale, scale),
};
if self.last_sw != sw || self.last_sh != sh || self.last_width != width || self.last_height != height {
if self.last_sw != sw || self.last_sh != sh
|| self.last_width != width || self.last_height != height
|| self.version != renderer.ui.version {
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);
if self.version != renderer.ui.version {
e.update(renderer);
}
}
self.version = renderer.ui.version;
}
// Borrow rules seem to prevent us from doing this in the first pass
@ -375,6 +403,8 @@ impl Image {
}
}
fn update(&mut self, renderer: &mut render::Renderer) {}
fn draw(&mut self, renderer: &mut render::Renderer, r: &Region, width: f64, height: f64, delta: f64) -> &Vec<u8> {
if self.dirty {
self.dirty = false;
@ -390,7 +420,11 @@ impl Image {
&self.data
}
pub fn set_parent<T: UIElement>(&mut self, other: ElementRef<T>) {
pub fn get_size(&self) -> (f64, f64) {
(self.width, self.height)
}
pub fn set_parent<T: UIElement>(&mut self, other: &ElementRef<T>) {
self.parent = Some(other.inner);
self.dirty = true;
}
@ -481,6 +515,10 @@ impl Batch {
}
}
fn update(&mut self, renderer: &mut render::Renderer) {
}
fn draw(&mut self, renderer: &mut render::Renderer, r: &Region, width: f64, height: f64, delta: f64) -> &Vec<u8> {
if self.dirty {
self.dirty = false;
@ -498,7 +536,11 @@ impl Batch {
&self.data
}
pub fn set_parent<T: UIElement>(&mut self, other: ElementRef<T>) {
pub fn get_size(&self) -> (f64, f64) {
(self.width, self.height)
}
pub fn set_parent<T: UIElement>(&mut self, other: &ElementRef<T>) {
self.parent = Some(other.inner);
self.dirty = true;
}
@ -536,3 +578,136 @@ impl UIElement for Batch {
}
}
}
pub struct Text {
dirty: bool,
data: Vec<u8>,
parent: Option<ElementRefInner>,
should_draw: bool,
layer: isize,
val: String,
x: f64,
y: f64,
width: f64,
height: f64,
v_attach: VAttach,
h_attach: HAttach,
scale_x: f64,
scale_y: f64,
rotation: f64,
r: u8,
g: u8,
b: u8,
a: u8,
}
impl Text {
pub fn new(renderer: &render::Renderer, val: &str, x: f64, y: f64, r: u8, g: u8, b: u8) -> Text {
Text {
dirty: true,
data: Vec::new(),
parent: None,
should_draw: true,
layer: 0,
val: val.to_owned(),
x: x,
y: y,
width: renderer.ui.size_of_string(val),
height: 18.0,
v_attach: VAttach::Top,
h_attach: HAttach::Left,
scale_x: 1.0,
scale_y: 1.0,
rotation: 0.0,
r: r,
g: g,
b: b,
a: 255,
}
}
fn update(&mut self, renderer: &mut render::Renderer) {
self.width = renderer.ui.size_of_string(&self.val);
}
fn draw(&mut self, renderer: &mut render::Renderer, r: &Region, width: f64, height: f64, delta: f64) -> &Vec<u8> {
if self.dirty {
self.dirty = false;
let sx = r.w / self.width;
let sy = r.h / self.height;
let mut text = if self.rotation == 0.0 {
renderer.ui.new_text_scaled(&self.val, r.x, r.y, sx*self.scale_x, sy*self.scale_y, self.r, self.g, self.b)
} else {
let c = self.rotation.cos();
let s = self.rotation.sin();
let tmpx = r.w / 2.0;
let tmpy = r.h / 2.0;
let w = (tmpx*c - tmpy*s).abs();
let h = (tmpy*c + tmpx*s).abs();
renderer.ui.new_text_rotated(&self.val, r.x+w-(r.w / 2.0), r.y+h-(r.h / 2.0), sx*self.scale_x, sy*self.scale_y, self.rotation, self.r, self.g, self.b)
};
for e in &mut text.elements {
e.a = self.a;
e.layer = self.layer;
}
self.data = text.bytes(width, height);
}
&self.data
}
pub fn get_size(&self) -> (f64, f64) {
((self.width + 2.0) * self.scale_x, self.height * self.scale_y)
}
pub fn set_parent<T: UIElement>(&mut self, other: &ElementRef<T>) {
self.parent = Some(other.inner);
self.dirty = true;
}
pub fn get_text(&self) -> &str {
&self.val
}
pub fn set_text(&mut self, renderer: &render::Renderer, val: &str) {
self.dirty = true;
self.val = val.to_owned();
self.width = renderer.ui.size_of_string(val);
}
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);
lazy_field!(scale_x, f64, get_scale_x, set_scale_x);
lazy_field!(scale_y, f64, get_scale_y, set_scale_y);
lazy_field!(rotation, f64, get_rotation, set_rotation);
lazy_field!(r, u8, get_r, set_r);
lazy_field!(g, u8, get_g, set_g);
lazy_field!(b, u8, get_b, set_b);
}
impl UIElement for Text {
fn wrap(self) -> Element {
Element::Text(self)
}
fn unwrap_ref<'a>(e: &'a Element) -> &'a Text {
match e {
&Element::Text(ref val) => val,
_ => panic!("Incorrect type"),
}
}
fn unwrap_ref_mut<'a>(e: &'a mut Element) -> &'a mut Text {
match e {
&mut Element::Text(ref mut val) => val,
_ => panic!("Incorrect type"),
}
}
}