Rewrite the UI system (Closes #12)
This commit is contained in:
parent
b0c54a3561
commit
a7caa50b6f
|
@ -181,18 +181,25 @@ impl Vars {
|
|||
|
||||
pub struct Console {
|
||||
history: Vec<Component>,
|
||||
dirty: bool,
|
||||
|
||||
collection: ui::Collection,
|
||||
elements: Option<ConsoleElements>,
|
||||
active: bool,
|
||||
position: f64,
|
||||
}
|
||||
|
||||
struct ConsoleElements {
|
||||
background: ui::ImageRef,
|
||||
lines: Vec<ui::FormattedRef>,
|
||||
}
|
||||
|
||||
impl Console {
|
||||
pub fn new() -> Console {
|
||||
Console {
|
||||
history: vec![Component::Text(TextComponent::new("")); 200],
|
||||
dirty: false,
|
||||
|
||||
collection: ui::Collection::new(),
|
||||
elements: None,
|
||||
active: false,
|
||||
position: -220.0,
|
||||
}
|
||||
|
@ -208,14 +215,11 @@ impl Console {
|
|||
|
||||
pub fn tick(&mut self,
|
||||
ui_container: &mut ui::Container,
|
||||
renderer: &mut render::Renderer,
|
||||
renderer: &render::Renderer,
|
||||
delta: f64,
|
||||
width: f64) {
|
||||
// To make sure the console is always on top it constant removes and readds itself.
|
||||
// Its hacky but the console should never appear for normal users so its not really
|
||||
// a major issue.
|
||||
self.collection.remove_all(ui_container);
|
||||
if !self.active && self.position <= -220.0 {
|
||||
self.elements = None;
|
||||
return;
|
||||
}
|
||||
if self.active {
|
||||
|
@ -229,39 +233,48 @@ impl Console {
|
|||
} else {
|
||||
self.position = -220.0;
|
||||
}
|
||||
|
||||
let w = match ui_container.mode {
|
||||
ui::Mode::Scaled => width,
|
||||
ui::Mode::Unscaled(scale) => 854.0 / scale,
|
||||
};
|
||||
|
||||
let mut background = ui::Image::new(
|
||||
render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid"),
|
||||
0.0, self.position, w, 220.0,
|
||||
0.0, 0.0, 1.0, 1.0,
|
||||
0, 0, 0
|
||||
);
|
||||
background.set_a(180);
|
||||
let background = self.collection.add(ui_container.add(background));
|
||||
|
||||
let mut lines = Vec::new();
|
||||
let mut offset = 0.0;
|
||||
for line in self.history.iter().rev() {
|
||||
if offset >= 210.0 {
|
||||
break;
|
||||
}
|
||||
let mut fmt = ui::Formatted::with_width_limit(
|
||||
renderer,
|
||||
line.clone(),
|
||||
5.0, 5.0 + offset,
|
||||
w - 1.0
|
||||
);
|
||||
fmt.set_parent(&background);
|
||||
fmt.set_v_attach(ui::VAttach::Bottom);
|
||||
offset += fmt.get_height();
|
||||
lines.push(ui_container.add(fmt));
|
||||
if self.elements.is_none() {
|
||||
let background = ui::ImageBuilder::new()
|
||||
.texture("steven:solid")
|
||||
.position(0.0, self.position)
|
||||
.size(w, 220.0)
|
||||
.colour((0, 0, 0, 180))
|
||||
.draw_index(500)
|
||||
.create(ui_container);
|
||||
self.elements = Some(ConsoleElements {
|
||||
background: background,
|
||||
lines: vec![],
|
||||
});
|
||||
self.dirty = true;
|
||||
}
|
||||
for fmt in lines {
|
||||
self.collection.add(fmt);
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
let mut background = elements.background.borrow_mut();
|
||||
background.y = self.position;
|
||||
background.width = w;
|
||||
|
||||
if self.dirty {
|
||||
self.dirty = false;
|
||||
elements.lines.clear();
|
||||
|
||||
let mut offset = 0.0;
|
||||
for line in self.history.iter().rev() {
|
||||
if offset >= 210.0 {
|
||||
break;
|
||||
}
|
||||
let (_, height) = ui::Formatted::compute_size(renderer, line, w - 10.0);
|
||||
elements.lines.push(ui::FormattedBuilder::new()
|
||||
.text(line.clone())
|
||||
.position(5.0, 5.0 + offset)
|
||||
.max_width(w - 10.0)
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Left)
|
||||
.create(&mut *background));
|
||||
offset += height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,6 +327,7 @@ impl Console {
|
|||
Component::Text(TextComponent::new(&format!("{}", record.args())))
|
||||
]);
|
||||
self.history.push(Component::Text(msg));
|
||||
self.dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -494,7 +494,6 @@ struct MovementHandler {
|
|||
gamemode: ecs::Key<Gamemode>,
|
||||
position: ecs::Key<TargetPosition>,
|
||||
velocity: ecs::Key<Velocity>,
|
||||
game_info: ecs::Key<GameInfo>,
|
||||
bounds: ecs::Key<Bounds>,
|
||||
rotation: ecs::Key<Rotation>,
|
||||
}
|
||||
|
@ -518,7 +517,6 @@ impl MovementHandler {
|
|||
gamemode: m.get_key(),
|
||||
position: position,
|
||||
velocity: velocity,
|
||||
game_info: m.get_key(),
|
||||
bounds: bounds,
|
||||
rotation: rotation,
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#![recursion_limit="300"]
|
||||
#![feature(const_fn)]
|
||||
#![feature(rc_would_unwrap)]
|
||||
|
||||
extern crate sdl2;
|
||||
extern crate image;
|
||||
|
@ -243,7 +244,6 @@ fn main() {
|
|||
let delta = (diff.num_nanoseconds().unwrap() as f64) / frame_time;
|
||||
let (width, height) = window.drawable_size();
|
||||
|
||||
|
||||
let vsync_changed = *game.vars.get(settings::R_VSYNC);
|
||||
if vsync != vsync_changed {
|
||||
vsync = vsync_changed;
|
||||
|
@ -262,7 +262,7 @@ fn main() {
|
|||
game.console
|
||||
.lock()
|
||||
.unwrap()
|
||||
.tick(&mut ui_container, &mut game.renderer, delta, width as f64);
|
||||
.tick(&mut ui_container, &game.renderer, delta, width as f64);
|
||||
ui_container.tick(&mut game.renderer, delta, width as f64, height as f64);
|
||||
game.renderer.tick(&mut game.server.world, delta, width, height);
|
||||
|
||||
|
|
|
@ -1200,13 +1200,14 @@ impl TextureManager {
|
|||
height: height,
|
||||
};
|
||||
self.pending_uploads.push((tex.atlas, rect, data));
|
||||
let t = tex.relative(0.0, 0.0, (width as f32) / (tex.width as f32), (height as f32) / (tex.height as f32));
|
||||
let mut t = tex.relative(0.0, 0.0, (width as f32) / (tex.width as f32), (height as f32) / (tex.height as f32));
|
||||
let old_name = mem::replace(&mut tex.name, format!("steven-dynamic:{}", name));
|
||||
self.dynamic_textures.insert(name.to_owned(), (tex.clone(), img));
|
||||
// We need to rename the texture itself so that get_texture calls
|
||||
// work with the new name
|
||||
let mut old = self.textures.remove(&old_name).unwrap();
|
||||
old.name = format!("steven-dynamic:{}", name);
|
||||
t.name = old.name.clone();
|
||||
self.textures.insert(format!("steven-dynamic:{}", name), old);
|
||||
t
|
||||
} else {
|
||||
|
@ -1239,7 +1240,7 @@ struct AnimationFrame {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Texture {
|
||||
name: String,
|
||||
pub name: String,
|
||||
version: usize,
|
||||
pub atlas: i32,
|
||||
x: usize,
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
use ui;
|
||||
use render;
|
||||
use format::{self, Component, TextComponent};
|
||||
|
||||
pub struct Connecting {
|
||||
elements: Option<UIElements>,
|
||||
|
@ -23,7 +22,9 @@ pub struct Connecting {
|
|||
|
||||
struct UIElements {
|
||||
logo: ui::logo::Logo,
|
||||
elements: ui::Collection,
|
||||
_connect_msg: ui::TextRef,
|
||||
_msg: ui::TextRef,
|
||||
_disclaimer: ui::TextRef,
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,63 +39,48 @@ impl Connecting {
|
|||
|
||||
impl super::Screen for Connecting {
|
||||
fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
let logo = ui::logo::Logo::new(renderer.resources.clone(), renderer, ui_container);
|
||||
let mut elements = ui::Collection::new();
|
||||
let logo = ui::logo::Logo::new(renderer.resources.clone(), ui_container);
|
||||
|
||||
let mut connect_msg = ui::Formatted::new(
|
||||
renderer,
|
||||
Component::Text(TextComponent::new("Connecting to")),
|
||||
0.0, -16.0
|
||||
);
|
||||
connect_msg.set_v_attach(ui::VAttach::Middle);
|
||||
connect_msg.set_h_attach(ui::HAttach::Center);
|
||||
elements.add(ui_container.add(connect_msg));
|
||||
let connect_msg = ui::TextBuilder::new()
|
||||
.text("Connecting to")
|
||||
.position(0.0, -16.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
|
||||
let mut msg = TextComponent::new(&self.target);
|
||||
msg.modifier.color = Some(format::Color::Yellow);
|
||||
let mut server_msg = ui::Formatted::new(
|
||||
renderer,
|
||||
Component::Text(msg),
|
||||
0.0, 16.0
|
||||
);
|
||||
server_msg.set_v_attach(ui::VAttach::Middle);
|
||||
server_msg.set_h_attach(ui::HAttach::Center);
|
||||
elements.add(ui_container.add(server_msg));
|
||||
let msg = ui::TextBuilder::new()
|
||||
.text(self.target.clone())
|
||||
.position(0.0, 16.0)
|
||||
.colour((255, 255, 85, 255))
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
|
||||
// Disclaimer
|
||||
let mut warn = ui::Text::new(renderer,
|
||||
"Not affiliated with Mojang/Minecraft",
|
||||
5.0,
|
||||
5.0,
|
||||
255,
|
||||
200,
|
||||
200);
|
||||
warn.set_v_attach(ui::VAttach::Bottom);
|
||||
warn.set_h_attach(ui::HAttach::Right);
|
||||
elements.add(ui_container.add(warn));
|
||||
let disclaimer = ui::TextBuilder::new()
|
||||
.text("Not affiliated with Mojang/Minecraft")
|
||||
.position(5.0, 5.0)
|
||||
.colour((255, 200, 200, 255))
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Right)
|
||||
.create(ui_container);
|
||||
|
||||
self.elements = Some(UIElements {
|
||||
logo: logo,
|
||||
elements: elements,
|
||||
_disclaimer: disclaimer,
|
||||
_msg: msg,
|
||||
_connect_msg: connect_msg,
|
||||
});
|
||||
}
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, _ui_container: &mut ui::Container) {
|
||||
// Clean up
|
||||
{
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
elements.logo.remove(ui_container);
|
||||
elements.elements.remove_all(ui_container);
|
||||
}
|
||||
self.elements = None
|
||||
}
|
||||
|
||||
fn tick(&mut self,
|
||||
_delta: f64,
|
||||
renderer: &mut render::Renderer,
|
||||
ui_container: &mut ui::Container) -> Option<Box<super::Screen>>{
|
||||
_ui_container: &mut ui::Container) -> Option<Box<super::Screen>>{
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
|
||||
elements.logo.tick(renderer, ui_container);
|
||||
elements.logo.tick(renderer);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,11 @@ pub struct EditServerEntry {
|
|||
|
||||
struct UIElements {
|
||||
logo: ui::logo::Logo,
|
||||
elements: ui::Collection,
|
||||
|
||||
_name: ui::TextBoxRef,
|
||||
_address: ui::TextBoxRef,
|
||||
_done: ui::ButtonRef,
|
||||
_cancel: ui::ButtonRef,
|
||||
}
|
||||
|
||||
impl EditServerEntry {
|
||||
|
@ -77,104 +81,99 @@ impl EditServerEntry {
|
|||
|
||||
impl super::Screen for EditServerEntry {
|
||||
fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
let logo = ui::logo::Logo::new(renderer.resources.clone(), renderer, ui_container);
|
||||
let mut elements = ui::Collection::new();
|
||||
let logo = ui::logo::Logo::new(renderer.resources.clone(), ui_container);
|
||||
|
||||
// Name
|
||||
let mut server_name = ui::TextBox::new(
|
||||
renderer, self.entry_info.as_ref().map_or("", |v| &v.1),
|
||||
0.0, -20.0, 400.0, 40.0
|
||||
);
|
||||
server_name.set_v_attach(ui::VAttach::Middle);
|
||||
server_name.set_h_attach(ui::HAttach::Center);
|
||||
server_name.add_submit_func(|_, ui| {
|
||||
ui.cycle_focus();
|
||||
});
|
||||
let ure = ui_container.add(server_name);
|
||||
let mut server_name_label = ui::Text::new(renderer, "Name:", 0.0, -18.0, 255, 255, 255);
|
||||
server_name_label.set_parent(&ure);
|
||||
let server_name_txt = elements.add(ure);
|
||||
elements.add(ui_container.add(server_name_label));
|
||||
let server_name = ui::TextBoxBuilder::new()
|
||||
.input(self.entry_info.as_ref().map_or("", |v| &v.1))
|
||||
.position(0.0, -20.0)
|
||||
.size(400.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
ui::TextBuilder::new()
|
||||
.text("Name:")
|
||||
.position(0.0, -18.0)
|
||||
.attach(&mut *server_name.borrow_mut());
|
||||
|
||||
// Name
|
||||
let mut server_address = ui::TextBox::new(
|
||||
renderer, self.entry_info.as_ref().map_or("", |v| &v.2),
|
||||
0.0, 40.0, 400.0, 40.0
|
||||
);
|
||||
server_address.set_v_attach(ui::VAttach::Middle);
|
||||
server_address.set_h_attach(ui::HAttach::Center);
|
||||
server_address.add_submit_func(|_, ui| {
|
||||
ui.cycle_focus();
|
||||
});
|
||||
let ure = ui_container.add(server_address);
|
||||
let mut server_address_label = ui::Text::new(renderer, "Address:", 0.0, -18.0, 255, 255, 255);
|
||||
server_address_label.set_parent(&ure);
|
||||
let server_address_txt = elements.add(ure);
|
||||
elements.add(ui_container.add(server_address_label));
|
||||
// Address
|
||||
let server_address = ui::TextBoxBuilder::new()
|
||||
.input(self.entry_info.as_ref().map_or("", |v| &v.2))
|
||||
.position(0.0, 40.0)
|
||||
.size(400.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
ui::TextBuilder::new()
|
||||
.text("Address")
|
||||
.position(0.0, -18.0)
|
||||
.attach(&mut *server_address.borrow_mut());
|
||||
|
||||
// Done
|
||||
let (mut done, mut txt) = super::new_button_text(
|
||||
renderer, "Done",
|
||||
110.0, 100.0, 200.0, 40.0
|
||||
);
|
||||
done.set_v_attach(ui::VAttach::Middle);
|
||||
done.set_h_attach(ui::HAttach::Center);
|
||||
let re = ui_container.add(done);
|
||||
txt.set_parent(&re);
|
||||
let tre = ui_container.add(txt);
|
||||
|
||||
let index = self.entry_info.as_ref().map(|v| v.0);
|
||||
super::button_action(ui_container, re.clone(), Some(tre.clone()), move |game, uic| {
|
||||
Self::save_servers(
|
||||
index,
|
||||
&uic.get(&server_name_txt).get_input(),
|
||||
&uic.get(&server_address_txt).get_input()
|
||||
);
|
||||
game.screen_sys.replace_screen(Box::new(super::ServerList::new(None)));
|
||||
});
|
||||
elements.add(re);
|
||||
elements.add(tre);
|
||||
let done = ui::ButtonBuilder::new()
|
||||
.position(110.0, 100.0)
|
||||
.size(200.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut done = done.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Done")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *done);
|
||||
done.add_text(txt);
|
||||
let index = self.entry_info.as_ref().map(|v| v.0);
|
||||
let server_name = server_name.clone();
|
||||
let server_address = server_address.clone();
|
||||
done.add_click_func(move |_, game| {
|
||||
Self::save_servers(
|
||||
index,
|
||||
&server_name.borrow().input,
|
||||
&server_address.borrow().input,
|
||||
);
|
||||
game.screen_sys.replace_screen(Box::new(super::ServerList::new(None)));
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
// Cancel
|
||||
let (mut cancel, mut txt) = super::new_button_text(
|
||||
renderer, "Cancel",
|
||||
-110.0, 100.0, 200.0, 40.0
|
||||
);
|
||||
cancel.set_v_attach(ui::VAttach::Middle);
|
||||
cancel.set_h_attach(ui::HAttach::Center);
|
||||
let re = ui_container.add(cancel);
|
||||
txt.set_parent(&re);
|
||||
let tre = ui_container.add(txt);
|
||||
super::button_action(ui_container, re.clone(), Some(tre.clone()), |game, _| {
|
||||
game.screen_sys.replace_screen(Box::new(super::ServerList::new(None)));
|
||||
});
|
||||
elements.add(re);
|
||||
elements.add(tre);
|
||||
|
||||
let cancel = ui::ButtonBuilder::new()
|
||||
.position(-110.0, 100.0)
|
||||
.size(200.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut cancel = cancel.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Cancel")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *cancel);
|
||||
cancel.add_text(txt);
|
||||
cancel.add_click_func(|_, game| {
|
||||
game.screen_sys.replace_screen(Box::new(super::ServerList::new(None)));
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
self.elements = Some(UIElements {
|
||||
logo: logo,
|
||||
elements: elements,
|
||||
_name: server_name,
|
||||
_address: server_address,
|
||||
_done: done,
|
||||
_cancel: cancel,
|
||||
});
|
||||
}
|
||||
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, _ui_container: &mut ui::Container) {
|
||||
// Clean up
|
||||
{
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
elements.logo.remove(ui_container);
|
||||
elements.elements.remove_all(ui_container);
|
||||
}
|
||||
self.elements = None
|
||||
}
|
||||
|
||||
fn tick(&mut self,
|
||||
_delta: f64,
|
||||
renderer: &mut render::Renderer,
|
||||
ui_container: &mut ui::Container) -> Option<Box<super::Screen>> {
|
||||
_ui_container: &mut ui::Container) -> Option<Box<super::Screen>> {
|
||||
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
elements.logo.tick(renderer, ui_container);
|
||||
elements.logo.tick(renderer);
|
||||
None
|
||||
}
|
||||
|
||||
|
|
|
@ -33,13 +33,13 @@ pub struct Login {
|
|||
|
||||
struct UIElements {
|
||||
logo: ui::logo::Logo,
|
||||
elements: ui::Collection,
|
||||
|
||||
login_btn: ui::ElementRef<ui::Button>,
|
||||
login_btn_text: ui::ElementRef<ui::Text>,
|
||||
login_error: ui::ElementRef<ui::Text>,
|
||||
username_txt: ui::ElementRef<ui::TextBox>,
|
||||
password_txt: ui::ElementRef<ui::TextBox>,
|
||||
login_btn: ui::ButtonRef,
|
||||
login_btn_text: ui::TextRef,
|
||||
login_error: ui::TextRef,
|
||||
username_txt: ui::TextBoxRef,
|
||||
password_txt: ui::TextBoxRef,
|
||||
_disclaimer: ui::TextRef,
|
||||
try_login: Rc<Cell<bool>>,
|
||||
refresh: bool,
|
||||
login_res: Option<mpsc::Receiver<Result<mojang::Profile, protocol::Error>>>,
|
||||
|
@ -56,73 +56,76 @@ impl Login {
|
|||
|
||||
impl super::Screen for Login {
|
||||
fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
let logo = ui::logo::Logo::new(renderer.resources.clone(), renderer, ui_container);
|
||||
let mut elements = ui::Collection::new();
|
||||
let logo = ui::logo::Logo::new(renderer.resources.clone(), ui_container);
|
||||
|
||||
let try_login = Rc::new(Cell::new(false));
|
||||
|
||||
// Login
|
||||
let (mut login, mut txt) = super::new_button_text(renderer, "Login", 0.0, 100.0, 400.0, 40.0);
|
||||
login.set_v_attach(ui::VAttach::Middle);
|
||||
login.set_h_attach(ui::HAttach::Center);
|
||||
let re = ui_container.add(login);
|
||||
txt.set_parent(&re);
|
||||
let tre = ui_container.add(txt);
|
||||
let tl = try_login.clone();
|
||||
super::button_action(ui_container,
|
||||
re.clone(),
|
||||
Some(tre.clone()),
|
||||
move |_, _| {
|
||||
tl.set(true);
|
||||
});
|
||||
let login_btn = elements.add(re);
|
||||
let login_btn_text = elements.add(tre);
|
||||
let login_btn = ui::ButtonBuilder::new()
|
||||
.position(0.0, 100.0)
|
||||
.size(400.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
let login_btn_text = ui::TextBuilder::new()
|
||||
.text("Login")
|
||||
.position(0.0, 0.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *login_btn.borrow_mut());
|
||||
{
|
||||
let mut btn = login_btn.borrow_mut();
|
||||
btn.add_text(login_btn_text.clone());
|
||||
let tl = try_login.clone();
|
||||
btn.add_click_func(move |_, _| {
|
||||
tl.set(true);
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Login Error
|
||||
let mut login_error = ui::Text::new(renderer, "", 0.0, 150.0, 255, 50, 50);
|
||||
login_error.set_v_attach(ui::VAttach::Middle);
|
||||
login_error.set_h_attach(ui::HAttach::Center);
|
||||
let login_error = elements.add(ui_container.add(login_error));
|
||||
let login_error = ui::TextBuilder::new()
|
||||
.text("")
|
||||
.position(0.0, 150.0)
|
||||
.colour((255, 50, 50, 255))
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
|
||||
// Username
|
||||
let mut username = ui::TextBox::new(renderer, "", 0.0, -20.0, 400.0, 40.0);
|
||||
username.set_v_attach(ui::VAttach::Middle);
|
||||
username.set_h_attach(ui::HAttach::Center);
|
||||
username.add_submit_func(|_, ui| {
|
||||
ui.cycle_focus();
|
||||
});
|
||||
let ure = ui_container.add(username);
|
||||
let mut username_label = ui::Text::new(renderer, "Username/Email:", 0.0, -18.0, 255, 255, 255);
|
||||
username_label.set_parent(&ure);
|
||||
let username_txt = elements.add(ure);
|
||||
elements.add(ui_container.add(username_label));
|
||||
let username_txt = ui::TextBoxBuilder::new()
|
||||
.position(0.0, -20.0)
|
||||
.size(400.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
ui::TextBox::make_focusable(&username_txt, ui_container);
|
||||
ui::TextBuilder::new()
|
||||
.text("Username/Email:")
|
||||
.position(0.0, -18.0)
|
||||
.attach(&mut *username_txt.borrow_mut());
|
||||
|
||||
// Password
|
||||
let mut password = ui::TextBox::new(renderer, "", 0.0, 40.0, 400.0, 40.0);
|
||||
password.set_v_attach(ui::VAttach::Middle);
|
||||
password.set_h_attach(ui::HAttach::Center);
|
||||
password.set_password(true);
|
||||
let password_txt = ui::TextBoxBuilder::new()
|
||||
.position(0.0, 40.0)
|
||||
.size(400.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.password(true)
|
||||
.create(ui_container);
|
||||
ui::TextBox::make_focusable(&password_txt, ui_container);
|
||||
ui::TextBuilder::new()
|
||||
.text("Password:")
|
||||
.position(0.0, -18.0)
|
||||
.attach(&mut *password_txt.borrow_mut());
|
||||
let tl = try_login.clone();
|
||||
password.add_submit_func(move |_, _| {
|
||||
password_txt.borrow_mut().add_submit_func(move |_, _| {
|
||||
tl.set(true);
|
||||
});
|
||||
let pre = ui_container.add(password);
|
||||
let mut password_label = ui::Text::new(renderer, "Password:", 0.0, -18.0, 255, 255, 255);
|
||||
password_label.set_parent(&pre);
|
||||
let password_txt = elements.add(pre);
|
||||
elements.add(ui_container.add(password_label));
|
||||
|
||||
// Disclaimer
|
||||
let mut warn = ui::Text::new(renderer,
|
||||
"Not affiliated with Mojang/Minecraft",
|
||||
5.0,
|
||||
5.0,
|
||||
255,
|
||||
200,
|
||||
200);
|
||||
warn.set_v_attach(ui::VAttach::Bottom);
|
||||
warn.set_h_attach(ui::HAttach::Right);
|
||||
elements.add(ui_container.add(warn));
|
||||
let disclaimer = ui::TextBuilder::new()
|
||||
.text("Not affiliated with Mojang/Minecraft")
|
||||
.position(5.0, 5.0)
|
||||
.colour((255, 200, 200, 255))
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Right)
|
||||
.create(ui_container);
|
||||
|
||||
let profile = mojang::Profile {
|
||||
username: self.vars.get(auth::CL_USERNAME).clone(),
|
||||
|
@ -134,7 +137,6 @@ impl super::Screen for Login {
|
|||
|
||||
self.elements = Some(UIElements {
|
||||
logo: logo,
|
||||
elements: elements,
|
||||
profile: profile,
|
||||
login_btn: login_btn,
|
||||
login_btn_text: login_btn_text,
|
||||
|
@ -143,52 +145,37 @@ impl super::Screen for Login {
|
|||
refresh: refresh,
|
||||
login_res: None,
|
||||
|
||||
_disclaimer: disclaimer,
|
||||
|
||||
username_txt: username_txt,
|
||||
password_txt: password_txt,
|
||||
});
|
||||
}
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, _ui_container: &mut ui::Container) {
|
||||
// Clean up
|
||||
{
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
elements.logo.remove(ui_container);
|
||||
elements.elements.remove_all(ui_container);
|
||||
}
|
||||
self.elements = None
|
||||
}
|
||||
|
||||
fn tick(&mut self,
|
||||
_delta: f64,
|
||||
renderer: &mut render::Renderer,
|
||||
ui_container: &mut ui::Container) -> Option<Box<super::Screen>> {
|
||||
_ui_container: &mut ui::Container) -> Option<Box<super::Screen>> {
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
|
||||
if elements.try_login.get() && elements.login_res.is_none() {
|
||||
elements.try_login.set(false);
|
||||
let (tx, rx) = mpsc::channel();
|
||||
elements.login_res = Some(rx);
|
||||
{
|
||||
let btn = ui_container.get_mut(&elements.login_btn);
|
||||
btn.set_disabled(true);
|
||||
}
|
||||
{
|
||||
let txt = ui_container.get_mut(&elements.login_btn_text);
|
||||
txt.set_text(renderer, "Logging in...");
|
||||
}
|
||||
elements.login_btn.borrow_mut().disabled = true;
|
||||
elements.login_btn_text.borrow_mut().text = "Logging in...".into();
|
||||
let mut client_token = self.vars.get(auth::AUTH_CLIENT_TOKEN).clone();
|
||||
if client_token.is_empty() {
|
||||
client_token = rand::thread_rng().gen_ascii_chars().take(20).collect::<String>();
|
||||
self.vars.set(auth::AUTH_CLIENT_TOKEN, client_token);
|
||||
}
|
||||
let client_token = self.vars.get(auth::AUTH_CLIENT_TOKEN).clone();
|
||||
let username = {
|
||||
let txt = ui_container.get(&elements.username_txt);
|
||||
txt.get_input()
|
||||
};
|
||||
let password = {
|
||||
let txt = ui_container.get(&elements.password_txt);
|
||||
txt.get_input()
|
||||
};
|
||||
let username = elements.username_txt.borrow().input.clone();
|
||||
let password = elements.password_txt.borrow().input.clone();
|
||||
let refresh = elements.refresh;
|
||||
let profile = elements.profile.clone();
|
||||
thread::spawn(move || {
|
||||
|
@ -203,14 +190,8 @@ impl super::Screen for Login {
|
|||
if let Some(rx) = elements.login_res.as_ref() {
|
||||
if let Ok(res) = rx.try_recv() {
|
||||
done = true;
|
||||
{
|
||||
let btn = ui_container.get_mut(&elements.login_btn);
|
||||
btn.set_disabled(false);
|
||||
}
|
||||
{
|
||||
let txt = ui_container.get_mut(&elements.login_btn_text);
|
||||
txt.set_text(renderer, "Login");
|
||||
}
|
||||
elements.login_btn.borrow_mut().disabled = false;
|
||||
elements.login_btn_text.borrow_mut().text = "Login".into();
|
||||
match res {
|
||||
Ok(val) => {
|
||||
self.vars.set(auth::CL_USERNAME, val.username.clone());
|
||||
|
@ -220,8 +201,7 @@ impl super::Screen for Login {
|
|||
return Some(Box::new(super::ServerList::new(None)));
|
||||
},
|
||||
Err(err) => {
|
||||
let login_error = ui_container.get_mut(&elements.login_error);
|
||||
login_error.set_text(renderer, &format!("{}", err));
|
||||
elements.login_error.borrow_mut().text = format!("{}", err);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +210,7 @@ impl super::Screen for Login {
|
|||
elements.login_res = None;
|
||||
}
|
||||
|
||||
elements.logo.tick(renderer, ui_container);
|
||||
elements.logo.tick(renderer);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,11 +15,12 @@
|
|||
mod server_list;
|
||||
pub use self::server_list::*;
|
||||
mod login;
|
||||
pub mod settings_menu;
|
||||
|
||||
pub use self::login::*;
|
||||
|
||||
pub mod connecting;
|
||||
pub mod edit_server;
|
||||
|
||||
pub mod settings_menu;
|
||||
pub use self::settings_menu::{SettingsMenu, VideoSettingsMenu, AudioSettingsMenu};
|
||||
|
||||
use render;
|
||||
|
@ -148,40 +149,3 @@ impl ScreenSystem {
|
|||
current.screen.on_scroll(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_button_text(renderer: &mut render::Renderer,
|
||||
val: &str,
|
||||
x: f64,
|
||||
y: f64,
|
||||
w: f64,
|
||||
h: f64)
|
||||
-> (ui::Button, ui::Text) {
|
||||
let btn = ui::Button::new(x, y, w, h);
|
||||
let mut text = ui::Text::new(renderer, val, 0.0, 0.0, 255, 255, 255);
|
||||
text.set_v_attach(ui::VAttach::Middle);
|
||||
text.set_h_attach(ui::HAttach::Center);
|
||||
(btn, text)
|
||||
}
|
||||
|
||||
pub fn button_action<F: Fn(&mut ::Game, &mut ui::Container) + 'static>(ui_container: &mut ui::Container,
|
||||
btn: ui::ElementRef<ui::Button>,
|
||||
txt: Option<ui::ElementRef<ui::Text>>,
|
||||
click: F) {
|
||||
let button = ui_container.get_mut(&btn);
|
||||
button.add_hover_func(move |over, _, ui_container| {
|
||||
let disabled = {
|
||||
let button = ui_container.get_mut(&btn);
|
||||
button.is_disabled()
|
||||
};
|
||||
let txt = txt.clone();
|
||||
if let Some(txt) = txt {
|
||||
let text = ui_container.get_mut(&txt);
|
||||
text.set_b(if over && !disabled {
|
||||
160
|
||||
} else {
|
||||
255
|
||||
});
|
||||
}
|
||||
});
|
||||
button.add_click_func(click);
|
||||
}
|
||||
|
|
|
@ -40,22 +40,27 @@ pub struct ServerList {
|
|||
|
||||
struct UIElements {
|
||||
logo: ui::logo::Logo,
|
||||
elements: ui::Collection,
|
||||
servers: Vec<Server>,
|
||||
|
||||
_add_btn: ui::ButtonRef,
|
||||
_refresh_btn: ui::ButtonRef,
|
||||
_options_btn: ui::ButtonRef,
|
||||
_disclaimer: ui::TextRef,
|
||||
|
||||
_disconnected: Option<ui::ImageRef>,
|
||||
}
|
||||
|
||||
struct Server {
|
||||
collection: ui::Collection,
|
||||
back: ui::ElementRef<ui::Image>,
|
||||
back: ui::ImageRef,
|
||||
offset: f64,
|
||||
y: f64,
|
||||
|
||||
motd: ui::ElementRef<ui::Formatted>,
|
||||
ping: ui::ElementRef<ui::Image>,
|
||||
players: ui::ElementRef<ui::Text>,
|
||||
version: ui::ElementRef<ui::Formatted>,
|
||||
motd: ui::FormattedRef,
|
||||
ping: ui::ImageRef,
|
||||
players: ui::TextRef,
|
||||
version: ui::FormattedRef,
|
||||
|
||||
icon: ui::ElementRef<ui::Image>,
|
||||
icon: ui::ImageRef,
|
||||
icon_texture: Option<String>,
|
||||
|
||||
done_ping: bool,
|
||||
|
@ -98,10 +103,9 @@ impl ServerList {
|
|||
let elements = self.elements.as_mut().unwrap();
|
||||
*self.needs_reload.borrow_mut() = false;
|
||||
{
|
||||
// Clean up previous list entries and icons.
|
||||
// Clean up previous list icons.
|
||||
let mut tex = renderer.get_textures_ref().write().unwrap();
|
||||
for server in &mut elements.servers {
|
||||
server.collection.remove_all(ui_container);
|
||||
if let Some(ref icon) = server.icon_texture {
|
||||
tex.remove_dynamic(&icon);
|
||||
}
|
||||
|
@ -117,161 +121,139 @@ impl ServerList {
|
|||
let servers = servers_info.find("servers").unwrap().as_array().unwrap();
|
||||
let mut offset = 0.0;
|
||||
|
||||
// Default icon whilst we ping the servers or if the server doesn't provide one
|
||||
let default_icon = render::Renderer::get_texture(renderer.get_textures_ref(),
|
||||
"misc/unknown_server");
|
||||
// General gui icons
|
||||
let icons = render::Renderer::get_texture(renderer.get_textures_ref(), "gui/icons");
|
||||
|
||||
for (index, svr) in servers.iter().enumerate() {
|
||||
let name = svr.find("name").unwrap().as_string().unwrap().to_owned();
|
||||
let address = svr.find("address").unwrap().as_string().unwrap().to_owned();
|
||||
|
||||
let solid = render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid");
|
||||
|
||||
// Everything is attached to this
|
||||
let mut back = ui::Image::new(solid,
|
||||
0.0,
|
||||
offset * 100.0,
|
||||
700.0,
|
||||
100.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
back.set_a(100);
|
||||
back.set_v_attach(ui::VAttach::Middle);
|
||||
back.set_h_attach(ui::HAttach::Center);
|
||||
let back = ui::ImageBuilder::new()
|
||||
.texture("steven:solid")
|
||||
.position(0.0, offset * 100.0)
|
||||
.size(700.0, 100.0)
|
||||
.colour((0, 0, 0, 100))
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
|
||||
let (send, recv) = mpsc::channel::<PingInfo>();
|
||||
// Make whole entry interactable
|
||||
{
|
||||
let mut backr = back.borrow_mut();
|
||||
let address = address.clone();
|
||||
backr.add_hover_func(move |this, over, _| {
|
||||
this.colour.3 = if over {
|
||||
200
|
||||
} else {
|
||||
100
|
||||
};
|
||||
false
|
||||
});
|
||||
backr.add_click_func(move |_, game| {
|
||||
game.screen_sys.replace_screen(Box::new(super::connecting::Connecting::new(&address)));
|
||||
game.connect_to(&address);
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
// Server name
|
||||
ui::TextBuilder::new()
|
||||
.text(name.clone())
|
||||
.position(100.0, 5.0)
|
||||
.attach(&mut *back.borrow_mut());
|
||||
|
||||
// Server icon
|
||||
let icon = ui::ImageBuilder::new()
|
||||
.texture("misc/unknown_server")
|
||||
.position(5.0, 5.0)
|
||||
.size(90.0, 90.0)
|
||||
.attach(&mut *back.borrow_mut());
|
||||
|
||||
|
||||
// Ping indicator
|
||||
let ping = ui::ImageBuilder::new()
|
||||
.texture("gui/icons")
|
||||
.position(5.0, 5.0)
|
||||
.size(20.0, 16.0)
|
||||
.texture_coords((0.0, 56.0 / 256.0, 10.0 / 256.0, 8.0 / 256.0))
|
||||
.alignment(ui::VAttach::Top, ui::HAttach::Right)
|
||||
.attach(&mut *back.borrow_mut());
|
||||
|
||||
// Player count
|
||||
let players = ui::TextBuilder::new()
|
||||
.text("???")
|
||||
.position(30.0, 5.0)
|
||||
.alignment(ui::VAttach::Top, ui::HAttach::Right)
|
||||
.attach(&mut *back.borrow_mut());
|
||||
|
||||
// Server's message of the day
|
||||
let motd = ui::FormattedBuilder::new()
|
||||
.text(Component::Text(TextComponent::new("Connecting...")))
|
||||
.position(100.0, 23.0)
|
||||
.max_width(700.0 - (90.0 + 10.0 + 5.0))
|
||||
.attach(&mut *back.borrow_mut());
|
||||
|
||||
// Version information
|
||||
let version = ui::FormattedBuilder::new()
|
||||
.text(Component::Text(TextComponent::new("")))
|
||||
.position(100.0, 5.0)
|
||||
.max_width(700.0 - (90.0 + 10.0 + 5.0))
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Left)
|
||||
.attach(&mut *back.borrow_mut());
|
||||
|
||||
// Delete entry button
|
||||
let delete_entry = ui::ButtonBuilder::new()
|
||||
.position(0.0, 0.0)
|
||||
.size(25.0, 25.0)
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Right)
|
||||
.attach(&mut *back.borrow_mut());
|
||||
{
|
||||
let mut btn = delete_entry.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("X")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *btn);
|
||||
btn.add_text(txt);
|
||||
}
|
||||
|
||||
// Edit entry button
|
||||
let edit_entry = ui::ButtonBuilder::new()
|
||||
.position(25.0, 0.0)
|
||||
.size(25.0, 25.0)
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Right)
|
||||
.attach(&mut *back.borrow_mut());
|
||||
{
|
||||
let mut btn = edit_entry.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("E")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *btn);
|
||||
btn.add_text(txt);
|
||||
let index = index;
|
||||
let sname = name.clone();
|
||||
let saddr = address.clone();
|
||||
btn.add_click_func(move |_, game| {
|
||||
game.screen_sys.replace_screen(Box::new(super::edit_server::EditServerEntry::new(
|
||||
Some((index, sname.clone(), saddr.clone()))
|
||||
)));
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
let mut server = Server {
|
||||
collection: ui::Collection::new(),
|
||||
back: ui_container.add(back),
|
||||
back: back,
|
||||
offset: offset,
|
||||
y: 0.0,
|
||||
done_ping: false,
|
||||
recv: recv,
|
||||
|
||||
motd: Default::default(),
|
||||
ping: Default::default(),
|
||||
players: Default::default(),
|
||||
version: Default::default(),
|
||||
motd: motd,
|
||||
ping: ping,
|
||||
players: players,
|
||||
version: version,
|
||||
|
||||
icon: Default::default(),
|
||||
icon: icon,
|
||||
icon_texture: None,
|
||||
};
|
||||
server.collection.add(server.back.clone());
|
||||
server.update_position();
|
||||
// Make whole entry interactable
|
||||
{
|
||||
let back = ui_container.get_mut(&server.back);
|
||||
let back_ref = server.back.clone();
|
||||
let address = address.clone();
|
||||
back.add_hover_func(move |over, _, ui_container| {
|
||||
let back = ui_container.get_mut(&back_ref);
|
||||
back.set_a(if over {
|
||||
200
|
||||
} else {
|
||||
100
|
||||
});
|
||||
});
|
||||
|
||||
back.add_click_func(move |game, _| {
|
||||
game.screen_sys.replace_screen(Box::new(super::connecting::Connecting::new(&address)));
|
||||
game.connect_to(&address);
|
||||
});
|
||||
}
|
||||
|
||||
// Server name
|
||||
let mut text = ui::Text::new(renderer, &name, 100.0, 5.0, 255, 255, 255);
|
||||
text.set_parent(&server.back);
|
||||
server.collection.add(ui_container.add(text));
|
||||
|
||||
// Server icon
|
||||
let mut icon = ui::Image::new(
|
||||
default_icon.clone(),
|
||||
5.0, 5.0, 90.0, 90.0,
|
||||
0.0, 0.0, 1.0, 1.0,
|
||||
255, 255, 255
|
||||
);
|
||||
icon.set_parent(&server.back);
|
||||
server.icon = server.collection.add(ui_container.add(icon));
|
||||
|
||||
// Ping indicator
|
||||
let mut ping = ui::Image::new(
|
||||
icons.clone(),
|
||||
5.0, 5.0, 20.0, 16.0,
|
||||
0.0, 56.0 / 256.0, 10.0 / 256.0, 8.0 / 256.0,
|
||||
255, 255, 255
|
||||
);
|
||||
ping.set_h_attach(ui::HAttach::Right);
|
||||
ping.set_parent(&server.back);
|
||||
server.ping = server.collection.add(ui_container.add(ping));
|
||||
|
||||
// Player count
|
||||
let mut players = ui::Text::new(renderer, "???", 30.0, 5.0, 255, 255, 255);
|
||||
players.set_h_attach(ui::HAttach::Right);
|
||||
players.set_parent(&server.back);
|
||||
server.players = server.collection.add(ui_container.add(players));
|
||||
|
||||
// Server's message of the day
|
||||
let mut motd =
|
||||
ui::Formatted::with_width_limit(renderer,
|
||||
Component::Text(TextComponent::new("Connecting.\
|
||||
..")),
|
||||
100.0,
|
||||
23.0,
|
||||
700.0 - (90.0 + 10.0 + 5.0));
|
||||
motd.set_parent(&server.back);
|
||||
server.motd = server.collection.add(ui_container.add(motd));
|
||||
|
||||
// Version information
|
||||
let mut version =
|
||||
ui::Formatted::with_width_limit(renderer,
|
||||
Component::Text(TextComponent::new("")),
|
||||
100.0,
|
||||
5.0,
|
||||
700.0 - (90.0 + 10.0 + 5.0));
|
||||
version.set_v_attach(ui::VAttach::Bottom);
|
||||
version.set_parent(&server.back);
|
||||
server.version = server.collection.add(ui_container.add(version));
|
||||
|
||||
// Delete entry button
|
||||
let (mut del, mut txt) = super::new_button_text(renderer, "X", 0.0, 0.0, 25.0, 25.0);
|
||||
del.set_v_attach(ui::VAttach::Bottom);
|
||||
del.set_h_attach(ui::HAttach::Right);
|
||||
del.set_parent(&server.back);
|
||||
let re = ui_container.add(del);
|
||||
txt.set_parent(&re);
|
||||
let tre = ui_container.add(txt);
|
||||
super::button_action(ui_container, re.clone(), Some(tre.clone()), |_,_| {}); // TOOO: delete entry
|
||||
server.collection.add(re);
|
||||
server.collection.add(tre);
|
||||
|
||||
// Edit entry button
|
||||
let (mut edit, mut txt) = super::new_button_text(renderer, "E", 25.0, 0.0, 25.0, 25.0);
|
||||
edit.set_v_attach(ui::VAttach::Bottom);
|
||||
edit.set_h_attach(ui::HAttach::Right);
|
||||
edit.set_parent(&server.back);
|
||||
let re = ui_container.add(edit);
|
||||
txt.set_parent(&re);
|
||||
let tre = ui_container.add(txt);
|
||||
let index = index;
|
||||
let sname = name.clone();
|
||||
let saddr = address.clone();
|
||||
super::button_action(ui_container, re.clone(), Some(tre.clone()), move |game,_|{
|
||||
let sname = sname.clone();
|
||||
let saddr = saddr.clone();
|
||||
game.screen_sys.replace_screen(Box::new(super::edit_server::EditServerEntry::new(
|
||||
Some((index, sname, saddr))
|
||||
)));
|
||||
});
|
||||
server.collection.add(re);
|
||||
server.collection.add(tre);
|
||||
|
||||
elements.servers.push(server);
|
||||
offset += 1.0;
|
||||
|
||||
|
@ -304,7 +286,7 @@ impl ServerList {
|
|||
let e = format!("{}", err);
|
||||
let mut msg = TextComponent::new(&e);
|
||||
msg.modifier.color = Some(format::Color::Red);
|
||||
drop(send.send(PingInfo {
|
||||
let _ = send.send(PingInfo {
|
||||
motd: Component::Text(msg),
|
||||
ping: time::Duration::seconds(99999),
|
||||
exists: false,
|
||||
|
@ -313,7 +295,7 @@ impl ServerList {
|
|||
protocol_version: 0,
|
||||
protocol_name: "".to_owned(),
|
||||
favicon: None,
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -323,140 +305,129 @@ impl ServerList {
|
|||
|
||||
impl super::Screen for ServerList {
|
||||
fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
let logo = ui::logo::Logo::new(renderer.resources.clone(), renderer, ui_container);
|
||||
let mut elements = ui::Collection::new();
|
||||
let logo = ui::logo::Logo::new(renderer.resources.clone(), ui_container);
|
||||
|
||||
// Refresh the server list
|
||||
let (mut refresh, mut txt) = super::new_button_text(renderer,
|
||||
"Refresh",
|
||||
300.0,
|
||||
-50.0 - 15.0,
|
||||
100.0,
|
||||
30.0);
|
||||
refresh.set_v_attach(ui::VAttach::Middle);
|
||||
refresh.set_h_attach(ui::HAttach::Center);
|
||||
let re = ui_container.add(refresh);
|
||||
txt.set_parent(&re);
|
||||
let tre = ui_container.add(txt);
|
||||
let nr = self.needs_reload.clone();
|
||||
super::button_action(ui_container,
|
||||
re.clone(),
|
||||
Some(tre.clone()),
|
||||
move |_, _| {
|
||||
*nr.borrow_mut() = true;
|
||||
});
|
||||
elements.add(re);
|
||||
elements.add(tre);
|
||||
let refresh = ui::ButtonBuilder::new()
|
||||
.position(300.0, -50.0 - 15.0)
|
||||
.size(100.0, 30.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.draw_index(2)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut refresh = refresh.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Refresh")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *refresh);
|
||||
refresh.add_text(txt);
|
||||
let nr = self.needs_reload.clone();
|
||||
refresh.add_click_func(move |_, _| {
|
||||
*nr.borrow_mut() = true;
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
// Add a new server to the list
|
||||
let (mut add, mut txt) = super::new_button_text(
|
||||
renderer, "Add",
|
||||
200.0, -50.0 - 15.0, 100.0, 30.0
|
||||
);
|
||||
add.set_v_attach(ui::VAttach::Middle);
|
||||
add.set_h_attach(ui::HAttach::Center);
|
||||
let re = ui_container.add(add);
|
||||
txt.set_parent(&re);
|
||||
let tre = ui_container.add(txt);
|
||||
super::button_action(ui_container, re.clone(), Some(tre.clone()), |game, _|{
|
||||
game.screen_sys.replace_screen(Box::new(super::edit_server::EditServerEntry::new(
|
||||
None
|
||||
)));
|
||||
});
|
||||
elements.add(re);
|
||||
elements.add(tre);
|
||||
let add = ui::ButtonBuilder::new()
|
||||
.position(200.0, -50.0 - 15.0)
|
||||
.size(100.0, 30.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.draw_index(2)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut add = add.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Add")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *add);
|
||||
add.add_text(txt);
|
||||
add.add_click_func(move |_, game| {
|
||||
game.screen_sys.replace_screen(Box::new(super::edit_server::EditServerEntry::new(
|
||||
None
|
||||
)));
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
// Options menu
|
||||
let mut options = ui::Button::new(5.0, 25.0, 40.0, 40.0);
|
||||
options.set_v_attach(ui::VAttach::Bottom);
|
||||
options.set_h_attach(ui::HAttach::Right);
|
||||
let re = ui_container.add(options);
|
||||
let mut cog = ui::Image::new(render::Renderer::get_texture(renderer.get_textures_ref(),
|
||||
"steven:gui/cog"),
|
||||
0.0,
|
||||
0.0,
|
||||
40.0,
|
||||
40.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0,
|
||||
255,
|
||||
255,
|
||||
255);
|
||||
cog.set_parent(&re);
|
||||
cog.set_v_attach(ui::VAttach::Middle);
|
||||
cog.set_h_attach(ui::HAttach::Center);
|
||||
super::button_action(ui_container, re.clone(), None, | game, _ | {
|
||||
game.screen_sys.add_screen(Box::new(super::SettingsMenu::new(game.vars.clone(), false)));
|
||||
});
|
||||
elements.add(re);
|
||||
elements.add(ui_container.add(cog));
|
||||
let options = ui::ButtonBuilder::new()
|
||||
.position(5.0, 25.0)
|
||||
.size(40.0, 40.0)
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Right)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut options = options.borrow_mut();
|
||||
ui::ImageBuilder::new()
|
||||
.texture("steven:gui/cog")
|
||||
.position(0.0, 0.0)
|
||||
.size(40.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *options);
|
||||
options.add_click_func(|_, game| {
|
||||
game.screen_sys.add_screen(Box::new(super::SettingsMenu::new(game.vars.clone(), false)));
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
// Disclaimer
|
||||
let mut warn = ui::Text::new(renderer,
|
||||
"Not affiliated with Mojang/Minecraft",
|
||||
5.0,
|
||||
5.0,
|
||||
255,
|
||||
200,
|
||||
200);
|
||||
warn.set_v_attach(ui::VAttach::Bottom);
|
||||
warn.set_h_attach(ui::HAttach::Right);
|
||||
elements.add(ui_container.add(warn));
|
||||
let disclaimer = ui::TextBuilder::new()
|
||||
.text("Not affiliated with Mojang/Minecraft")
|
||||
.position(5.0, 5.0)
|
||||
.colour((255, 200, 200, 255))
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Right)
|
||||
.create(ui_container);
|
||||
|
||||
// If we are kicked from a server display the reason
|
||||
if let Some(ref disconnect_reason) = self.disconnect_reason {
|
||||
let mut dis_msg = ui::Text::new(renderer, "Disconnected", 0.0, 32.0, 255, 0, 0);
|
||||
dis_msg.set_h_attach(ui::HAttach::Center);
|
||||
let mut dis = ui::Formatted::with_width_limit(renderer,
|
||||
disconnect_reason.clone(),
|
||||
0.0,
|
||||
48.0,
|
||||
600.0);
|
||||
dis.set_h_attach(ui::HAttach::Center);
|
||||
let mut back =
|
||||
ui::Image::new(render::Renderer::get_texture(renderer.get_textures_ref(),
|
||||
"steven:solid"),
|
||||
0.0,
|
||||
30.0,
|
||||
dis.get_width().max(dis_msg.get_width()) + 4.0,
|
||||
dis.get_height() + 4.0 + 16.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
1.0,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
back.set_a(100);
|
||||
back.set_h_attach(ui::HAttach::Center);
|
||||
elements.add(ui_container.add(back));
|
||||
elements.add(ui_container.add(dis));
|
||||
elements.add(ui_container.add(dis_msg));
|
||||
}
|
||||
let disconnected = if let Some(ref disconnect_reason) = self.disconnect_reason {
|
||||
let (width, height) = ui::Formatted::compute_size(renderer, disconnect_reason, 600.0);
|
||||
let background = ui::ImageBuilder::new()
|
||||
.texture("steven:solid")
|
||||
.position(0.0, 3.0)
|
||||
.size(width.max(renderer.ui.size_of_string("Disconnected")) + 4.0, height + 4.0 + 16.0)
|
||||
.colour((0, 0, 0, 100))
|
||||
.alignment(ui::VAttach::Top, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
ui::TextBuilder::new()
|
||||
.text("Disconnected")
|
||||
.position(0.0, 2.0)
|
||||
.colour((255, 0, 0, 255))
|
||||
.alignment(ui::VAttach::Top, ui::HAttach::Center)
|
||||
.attach(&mut *background.borrow_mut());
|
||||
ui::FormattedBuilder::new()
|
||||
.text(disconnect_reason.clone())
|
||||
.position(0.0, 18.0)
|
||||
.max_width(600.0)
|
||||
.alignment(ui::VAttach::Top, ui::HAttach::Center)
|
||||
.attach(&mut *background.borrow_mut());
|
||||
Some(background)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
self.elements = Some(UIElements {
|
||||
logo: logo,
|
||||
elements: elements,
|
||||
servers: Vec::new(),
|
||||
|
||||
_add_btn: add,
|
||||
_refresh_btn: refresh,
|
||||
_options_btn: options,
|
||||
_disclaimer: disclaimer,
|
||||
|
||||
_disconnected: disconnected,
|
||||
});
|
||||
self.reload_server_list(renderer, ui_container);
|
||||
}
|
||||
fn on_deactive(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
fn on_deactive(&mut self, renderer: &mut render::Renderer, _ui_container: &mut ui::Container) {
|
||||
// Clean up
|
||||
{
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
elements.logo.remove(ui_container);
|
||||
elements.elements.remove_all(ui_container);
|
||||
let mut tex = renderer.get_textures_ref().write().unwrap();
|
||||
for server in &mut elements.servers {
|
||||
if let Some(ref icon) = server.icon_texture {
|
||||
tex.remove_dynamic(&icon);
|
||||
}
|
||||
server.collection.remove_all(ui_container);
|
||||
}
|
||||
elements.servers.clear();
|
||||
}
|
||||
self.elements = None
|
||||
}
|
||||
|
@ -470,18 +441,18 @@ impl super::Screen for ServerList {
|
|||
}
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
|
||||
elements.logo.tick(renderer, ui_container);
|
||||
elements.logo.tick(renderer);
|
||||
|
||||
for s in &mut elements.servers {
|
||||
// Animate the entries
|
||||
{
|
||||
let back = ui_container.get_mut(&s.back);
|
||||
let dy = s.y - back.get_y();
|
||||
let mut back = s.back.borrow_mut();
|
||||
let dy = s.y - back.y;
|
||||
if dy * dy > 1.0 {
|
||||
let y = back.get_y();
|
||||
back.set_y(y + delta * dy * 0.1);
|
||||
let y = back.y;
|
||||
back.y = y + delta * dy * 0.1;
|
||||
} else {
|
||||
back.set_y(s.y);
|
||||
back.y = s.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -491,45 +462,36 @@ impl super::Screen for ServerList {
|
|||
match s.recv.try_recv() {
|
||||
Ok(res) => {
|
||||
s.done_ping = true;
|
||||
{
|
||||
let motd = ui_container.get_mut(&s.motd);
|
||||
motd.set_component(renderer, res.motd);
|
||||
}
|
||||
{
|
||||
let ping = ui_container.get_mut(&s.ping);
|
||||
// Selects the icon for the given ping range
|
||||
let y = match res.ping.num_milliseconds() {
|
||||
_x @ 0 ... 75 => 16.0 / 256.0,
|
||||
_x @ 76 ... 150 => 24.0 / 256.0,
|
||||
_x @ 151 ... 225 => 32.0 / 256.0,
|
||||
_x @ 226 ... 350 => 40.0 / 256.0,
|
||||
_x @ 351 ... 999 => 48.0 / 256.0,
|
||||
_ => 56.0 / 256.0,
|
||||
};
|
||||
ping.set_t_y(y);
|
||||
}
|
||||
s.motd.borrow_mut().set_text(res.motd);
|
||||
// Selects the icon for the given ping range
|
||||
let y = match res.ping.num_milliseconds() {
|
||||
_x @ 0 ... 75 => 16.0 / 256.0,
|
||||
_x @ 76 ... 150 => 24.0 / 256.0,
|
||||
_x @ 151 ... 225 => 32.0 / 256.0,
|
||||
_x @ 226 ... 350 => 40.0 / 256.0,
|
||||
_x @ 351 ... 999 => 48.0 / 256.0,
|
||||
_ => 56.0 / 256.0,
|
||||
};
|
||||
s.ping.borrow_mut().texture_coords.1 = y;
|
||||
if res.exists {
|
||||
{
|
||||
let players = ui_container.get_mut(&s.players);
|
||||
let mut players = s.players.borrow_mut();
|
||||
let txt = if res.protocol_version == protocol::SUPPORTED_PROTOCOL {
|
||||
players.set_g(255);
|
||||
players.set_b(255);
|
||||
players.colour.1 = 255;
|
||||
players.colour.2 = 255;
|
||||
format!("{}/{}", res.online, res.max)
|
||||
} else {
|
||||
players.set_g(85);
|
||||
players.set_b(85);
|
||||
players.colour.1 = 85;
|
||||
players.colour.2 = 85;
|
||||
format!("Out of date {}/{}", res.online, res.max)
|
||||
};
|
||||
players.set_text(renderer, &txt);
|
||||
}
|
||||
{
|
||||
let version = ui_container.get_mut(&s.version);
|
||||
let mut txt = TextComponent::new(&res.protocol_name);
|
||||
txt.modifier.color = Some(format::Color::Yellow);
|
||||
let mut msg = Component::Text(txt);
|
||||
format::convert_legacy(&mut msg);
|
||||
version.set_component(renderer, msg);
|
||||
players.text = txt;
|
||||
}
|
||||
let mut txt = TextComponent::new(&res.protocol_name);
|
||||
txt.modifier.color = Some(format::Color::Yellow);
|
||||
let mut msg = Component::Text(txt);
|
||||
format::convert_legacy(&mut msg);
|
||||
s.version.borrow_mut().set_text(msg);
|
||||
}
|
||||
if let Some(favicon) = res.favicon {
|
||||
let name: String = rand::thread_rng()
|
||||
|
@ -541,16 +503,14 @@ impl super::Screen for ServerList {
|
|||
let icon_tex = tex.write()
|
||||
.unwrap()
|
||||
.put_dynamic(&name, favicon);
|
||||
let icon = ui_container.get_mut(&s.icon);
|
||||
icon.set_texture(icon_tex);
|
||||
s.icon.borrow_mut().texture = icon_tex.name;
|
||||
}
|
||||
}
|
||||
Err(mpsc::TryRecvError::Disconnected) => {
|
||||
s.done_ping = true;
|
||||
let motd = ui_container.get_mut(&s.motd);
|
||||
let mut txt = TextComponent::new("Channel dropped");
|
||||
txt.modifier.color = Some(format::Color::Red);
|
||||
motd.set_component(renderer, Component::Text(txt));
|
||||
s.motd.borrow_mut().set_text(Component::Text(txt));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -5,49 +5,13 @@ use settings;
|
|||
|
||||
use std::rc::Rc;
|
||||
|
||||
pub fn new_submenu_button(text: &str, renderer: &mut render::Renderer, ui_container: &mut ui::Container, x: f64, y: f64) -> (ui::ElementRef<ui::Button>, ui::ElementRef<ui::Text>) {
|
||||
let (mut btn, mut txt) = super::new_button_text(renderer, text, x, y, 300.0, 40.0);
|
||||
btn.set_v_attach(ui::VAttach::Middle);
|
||||
btn.set_h_attach(ui::HAttach::Center);
|
||||
let ui_btn = ui_container.add(btn);
|
||||
txt.set_parent(&ui_btn);
|
||||
(ui_btn, ui_container.add(txt))
|
||||
}
|
||||
|
||||
pub fn new_centered_button(text: &str, renderer: &mut render::Renderer, ui_container: &mut ui::Container, y: f64, vertical_attach: ui::VAttach) -> (ui::ElementRef<ui::Button>, ui::ElementRef<ui::Text>) {
|
||||
let (mut btn, mut txt) = super::new_button_text(renderer, text, 0.0, y, 400.0, 40.0);
|
||||
btn.set_v_attach(vertical_attach);
|
||||
btn.set_h_attach(ui::HAttach::Center);
|
||||
let ui_btn = ui_container.add(btn);
|
||||
txt.set_parent(&ui_btn);
|
||||
(ui_btn, ui_container.add(txt))
|
||||
}
|
||||
|
||||
macro_rules! get_bool_str {
|
||||
($fmt:expr, $val:expr, $val_true:expr, $val_false:expr) => (format!($fmt, if $val {
|
||||
$val_true
|
||||
} else {
|
||||
$val_false
|
||||
}).as_ref());
|
||||
($fmt:expr, $val:expr) => (get_bool_string!($fmt, $val, "true", "false"));
|
||||
}
|
||||
|
||||
macro_rules! get_matched_str {
|
||||
($fmt:expr, $val:expr, $($to_match:expr => $result:expr),*) => (
|
||||
format!($fmt, match $val {
|
||||
$($to_match => $result.to_owned(), )*
|
||||
_ => $val.to_string(),
|
||||
}).as_ref()
|
||||
)
|
||||
}
|
||||
|
||||
pub struct UIElements {
|
||||
elements: ui::Collection,
|
||||
background: ui::ElementRef<ui::Image>,
|
||||
background: ui::ImageRef,
|
||||
_buttons: Vec<ui::ButtonRef>,
|
||||
}
|
||||
|
||||
pub struct SettingsMenu {
|
||||
vars: Rc<console::Vars>,
|
||||
_vars: Rc<console::Vars>,
|
||||
elements: Option<UIElements>,
|
||||
show_disconnect_button: bool
|
||||
}
|
||||
|
@ -55,7 +19,7 @@ pub struct SettingsMenu {
|
|||
impl SettingsMenu {
|
||||
pub fn new(vars: Rc<console::Vars>, show_disconnect_button: bool) -> SettingsMenu {
|
||||
SettingsMenu {
|
||||
vars: vars,
|
||||
_vars: vars,
|
||||
elements: None,
|
||||
show_disconnect_button: show_disconnect_button
|
||||
}
|
||||
|
@ -63,77 +27,135 @@ impl SettingsMenu {
|
|||
}
|
||||
|
||||
impl super::Screen for SettingsMenu {
|
||||
fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
let mut elements = ui::Collection::new();
|
||||
fn on_active(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
let background = ui::ImageBuilder::new()
|
||||
.texture("steven:solid")
|
||||
.position(0.0, 0.0)
|
||||
.size(854.0, 480.0)
|
||||
.colour((0, 0, 0, 100))
|
||||
.create(ui_container);
|
||||
|
||||
let mut background = ui::Image::new(
|
||||
render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid"),
|
||||
0.0, 0.0, 854.0, 480.0,
|
||||
0.0, 0.0, 1.0, 1.0,
|
||||
0, 0, 0
|
||||
);
|
||||
background.set_a(100);
|
||||
let background = elements.add(ui_container.add(background));
|
||||
let mut buttons = vec![];
|
||||
|
||||
// From top and down
|
||||
let (btn_audio_settings, txt_audio_settings) = new_submenu_button("Audio settings...", renderer, ui_container, -160.0, -50.0);
|
||||
super::button_action(ui_container, btn_audio_settings.clone(), Some(txt_audio_settings.clone()), move |game, _| {
|
||||
game.screen_sys.add_screen(Box::new(AudioSettingsMenu::new(game.vars.clone())));
|
||||
});
|
||||
elements.add(btn_audio_settings);
|
||||
elements.add(txt_audio_settings);
|
||||
let audio_settings = ui::ButtonBuilder::new()
|
||||
.position(-160.0, -50.0)
|
||||
.size(300.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut audio_settings = audio_settings.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Audio settings...")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *audio_settings);
|
||||
audio_settings.add_text(txt);
|
||||
audio_settings.add_click_func(|_, game| {
|
||||
game.screen_sys.add_screen(Box::new(AudioSettingsMenu::new(game.vars.clone())));
|
||||
true
|
||||
});
|
||||
}
|
||||
buttons.push(audio_settings);
|
||||
|
||||
let (btn_video_settings, txt_video_settings) = new_submenu_button("Video settings...", renderer, ui_container, 160.0, -50.0);
|
||||
super::button_action(ui_container, btn_video_settings.clone(), Some(txt_video_settings.clone()), move |game, _| {
|
||||
game.screen_sys.add_screen(Box::new(VideoSettingsMenu::new(game.vars.clone())));
|
||||
});
|
||||
elements.add(btn_video_settings);
|
||||
elements.add(txt_video_settings);
|
||||
let video_settings = ui::ButtonBuilder::new()
|
||||
.position(160.0, -50.0)
|
||||
.size(300.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut video_settings = video_settings.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Video settings...")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *video_settings);
|
||||
video_settings.add_text(txt);
|
||||
video_settings.add_click_func(|_, game| {
|
||||
game.screen_sys.add_screen(Box::new(VideoSettingsMenu::new(game.vars.clone())));
|
||||
true
|
||||
});
|
||||
}
|
||||
buttons.push(video_settings);
|
||||
|
||||
let (btn_controls_settings, txt_controls_settings) = new_submenu_button("Controls...", renderer, ui_container, 160.0, 0.0);
|
||||
super::button_action(ui_container, btn_controls_settings.clone(), Some(txt_controls_settings.clone()), move |_, _| {
|
||||
// TODO: Implement this...
|
||||
});
|
||||
elements.add(btn_controls_settings);
|
||||
elements.add(txt_controls_settings);
|
||||
let controls_settings = ui::ButtonBuilder::new()
|
||||
.position(160.0, 0.0)
|
||||
.size(300.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut controls_settings = controls_settings.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Controls...")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *controls_settings);
|
||||
controls_settings.add_text(txt);
|
||||
}
|
||||
buttons.push(controls_settings);
|
||||
|
||||
let (btn_locale_settings, txt_locale_settings) = new_submenu_button("Language...", renderer, ui_container, -160.0, 0.0);
|
||||
super::button_action(ui_container, btn_locale_settings.clone(), Some(txt_locale_settings.clone()), move |_, _| {
|
||||
// TODO: Implement this...
|
||||
});
|
||||
elements.add(btn_locale_settings);
|
||||
elements.add(txt_locale_settings);
|
||||
let lang_settings = ui::ButtonBuilder::new()
|
||||
.position(-160.0, 0.0)
|
||||
.size(300.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut lang_settings = lang_settings.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Language...")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *lang_settings);
|
||||
lang_settings.add_text(txt);
|
||||
}
|
||||
buttons.push(lang_settings);
|
||||
|
||||
// Center bottom items
|
||||
let (btn_back_to_game, txt_back_to_game) = new_centered_button("Done", renderer, ui_container, 50.0, ui::VAttach::Bottom);
|
||||
super::button_action(ui_container, btn_back_to_game.clone(), Some(txt_back_to_game.clone()), move |game, _| {
|
||||
game.screen_sys.pop_screen();
|
||||
game.focused = true;
|
||||
});
|
||||
elements.add(btn_back_to_game);
|
||||
elements.add(txt_back_to_game);
|
||||
let done_button = ui::ButtonBuilder::new()
|
||||
.position(0.0, 50.0)
|
||||
.size(300.0, 40.0)
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut done_button = done_button.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Done")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *done_button);
|
||||
done_button.add_text(txt);
|
||||
done_button.add_click_func(|_, game| {
|
||||
game.screen_sys.pop_screen();
|
||||
game.focused = true;
|
||||
true
|
||||
});
|
||||
}
|
||||
buttons.push(done_button);
|
||||
|
||||
if self.show_disconnect_button {
|
||||
let (btn_exit_game, txt_exit_game) = new_centered_button("Disconnect", renderer, ui_container, 100.0, ui::VAttach::Bottom);
|
||||
super::button_action(ui_container, btn_exit_game.clone(), Some(txt_exit_game.clone()), move |game, _| {
|
||||
game.server.disconnect(None);
|
||||
game.screen_sys.replace_screen(Box::new(super::ServerList::new(None)));
|
||||
});
|
||||
elements.add(btn_exit_game);
|
||||
elements.add(txt_exit_game);
|
||||
let disconnect_button = ui::ButtonBuilder::new()
|
||||
.position(0.0, 100.0)
|
||||
.size(300.0, 40.0)
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut disconnect_button = disconnect_button.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Disconnect")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *disconnect_button);
|
||||
disconnect_button.add_text(txt);
|
||||
disconnect_button.add_click_func(|_, game| {
|
||||
game.server.disconnect(None);
|
||||
game.screen_sys.replace_screen(Box::new(super::ServerList::new(None)));
|
||||
true
|
||||
});
|
||||
}
|
||||
buttons.push(disconnect_button);
|
||||
}
|
||||
|
||||
self.elements = Some(UIElements {
|
||||
elements: elements,
|
||||
background: background,
|
||||
_buttons: buttons,
|
||||
});
|
||||
|
||||
}
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
{
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
elements.elements.remove_all(ui_container);
|
||||
}
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, _ui_container: &mut ui::Container) {
|
||||
self.elements = None;
|
||||
}
|
||||
|
||||
|
@ -142,15 +164,15 @@ impl super::Screen for SettingsMenu {
|
|||
let elements = self.elements.as_mut().unwrap();
|
||||
{
|
||||
let mode = ui_container.mode;
|
||||
let background = ui_container.get_mut(&elements.background);
|
||||
background.set_width(match mode {
|
||||
let mut background = elements.background.borrow_mut();
|
||||
background.width = match mode {
|
||||
ui::Mode::Unscaled(scale) => 854.0 / scale,
|
||||
ui::Mode::Scaled => renderer.width as f64,
|
||||
});
|
||||
background.set_height(match mode {
|
||||
};
|
||||
background.height = match mode {
|
||||
ui::Mode::Unscaled(scale) => 480.0 / scale,
|
||||
ui::Mode::Scaled => renderer.height as f64,
|
||||
});
|
||||
};
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -180,17 +202,15 @@ impl VideoSettingsMenu {
|
|||
}
|
||||
|
||||
impl super::Screen for VideoSettingsMenu {
|
||||
fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
let mut elements = ui::Collection::new();
|
||||
fn on_active(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
let background = ui::ImageBuilder::new()
|
||||
.texture("steven:solid")
|
||||
.position(0.0, 0.0)
|
||||
.size(854.0, 480.0)
|
||||
.colour((0, 0, 0, 100))
|
||||
.create(ui_container);
|
||||
|
||||
let mut background = ui::Image::new(
|
||||
render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid"),
|
||||
0.0, 0.0, 854.0, 480.0,
|
||||
0.0, 0.0, 1.0, 1.0,
|
||||
0, 0, 0
|
||||
);
|
||||
background.set_a(100);
|
||||
let background = elements.add(ui_container.add(background));
|
||||
let mut buttons = vec![];
|
||||
|
||||
// Load defaults
|
||||
let r_max_fps = *self.vars.get(settings::R_MAX_FPS);
|
||||
|
@ -199,42 +219,92 @@ impl super::Screen for VideoSettingsMenu {
|
|||
|
||||
// Setting buttons
|
||||
// TODO: Slider
|
||||
let (btn_fov, txt_fov) = new_submenu_button(get_matched_str!("FOV: {}", r_fov, 90 => "Normal", 110 => "Quake pro"), renderer, ui_container, -160.0, -50.0);
|
||||
elements.add(btn_fov);
|
||||
elements.add(txt_fov);
|
||||
let fov_setting = ui::ButtonBuilder::new()
|
||||
.position(160.0, -50.0)
|
||||
.size(300.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut fov_setting = fov_setting.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text(format!("FOV: {}", match r_fov {
|
||||
90 => "Normal".into(),
|
||||
110 => "Quake pro".into(),
|
||||
val => val.to_string(),
|
||||
}))
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *fov_setting);
|
||||
fov_setting.add_text(txt);
|
||||
}
|
||||
buttons.push(fov_setting);
|
||||
|
||||
let (btn_vsync, txt_vsync) = new_submenu_button(get_bool_str!("VSync: {}", r_vsync, "Enabled", "Disabled"), renderer, ui_container, -160.0, 0.0);
|
||||
elements.add(txt_vsync.clone());
|
||||
super::button_action(ui_container, btn_vsync.clone(), Some(txt_vsync.clone()), move | game, ui_container | {
|
||||
let r_vsync = !*game.vars.get(settings::R_VSYNC);
|
||||
let txt_vsync = ui_container.get_mut(&txt_vsync);
|
||||
txt_vsync.set_text(&game.renderer, get_bool_str!("VSync: {}", r_vsync, "Enabled", "Disabled"));
|
||||
game.vars.set(settings::R_VSYNC, r_vsync);
|
||||
});
|
||||
elements.add(btn_vsync);
|
||||
let vsync_setting = ui::ButtonBuilder::new()
|
||||
.position(-160.0, 0.0)
|
||||
.size(300.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut vsync_setting = vsync_setting.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text(format!("VSync: {}", if r_vsync { "Enabled" } else { "Disabled" }))
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *vsync_setting);
|
||||
let txt_vsync = txt.clone();
|
||||
vsync_setting.add_text(txt);
|
||||
vsync_setting.add_click_func(move |_, game| {
|
||||
let r_vsync = !*game.vars.get(settings::R_VSYNC);
|
||||
txt_vsync.borrow_mut().text = format!("VSync: {}", if r_vsync { "Enabled" } else { "Disabled" });
|
||||
game.vars.set(settings::R_VSYNC, r_vsync);
|
||||
true
|
||||
});
|
||||
}
|
||||
buttons.push(vsync_setting);
|
||||
|
||||
// TODO: Slider
|
||||
let (btn_fps_cap, txt_fps_cap) = new_submenu_button(get_matched_str!("FPS cap: {}", r_max_fps, 0 => "Unlimited", 15 => "Potato"), renderer, ui_container, 160.0, 0.0);
|
||||
elements.add(btn_fps_cap);
|
||||
elements.add(txt_fps_cap);
|
||||
let fps_setting = ui::ButtonBuilder::new()
|
||||
.position(160.0, 0.0)
|
||||
.size(300.0, 40.0)
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut fps_setting = fps_setting.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text(format!("FPS cap: {}", match r_max_fps {
|
||||
0 => "Unlimited".into(),
|
||||
val => val.to_string(),
|
||||
}))
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *fps_setting);
|
||||
fps_setting.add_text(txt);
|
||||
}
|
||||
buttons.push(fps_setting);
|
||||
|
||||
let (btn_done, txt_done) = new_centered_button("Done", renderer, ui_container, 50.0, ui::VAttach::Bottom);
|
||||
super::button_action(ui_container, btn_done.clone(), Some(txt_done.clone()), move | game, _ | {
|
||||
game.screen_sys.pop_screen();
|
||||
});
|
||||
elements.add(btn_done);
|
||||
elements.add(txt_done);
|
||||
let done_button = ui::ButtonBuilder::new()
|
||||
.position(0.0, 50.0)
|
||||
.size(300.0, 40.0)
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut done_button = done_button.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Done")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *done_button);
|
||||
done_button.add_text(txt);
|
||||
done_button.add_click_func(|_, game| {
|
||||
game.screen_sys.pop_screen();
|
||||
game.focused = true;
|
||||
true
|
||||
});
|
||||
}
|
||||
buttons.push(done_button);
|
||||
self.elements = Some(UIElements {
|
||||
elements: elements,
|
||||
background: background,
|
||||
_buttons: buttons,
|
||||
});
|
||||
|
||||
}
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
{
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
elements.elements.remove_all(ui_container);
|
||||
}
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, _ui_container: &mut ui::Container) {
|
||||
self.elements = None;
|
||||
}
|
||||
|
||||
|
@ -243,15 +313,15 @@ impl super::Screen for VideoSettingsMenu {
|
|||
let elements = self.elements.as_mut().unwrap();
|
||||
{
|
||||
let mode = ui_container.mode;
|
||||
let background = ui_container.get_mut(&elements.background);
|
||||
background.set_width(match mode {
|
||||
let mut background = elements.background.borrow_mut();
|
||||
background.width = match mode {
|
||||
ui::Mode::Unscaled(scale) => 854.0 / scale,
|
||||
ui::Mode::Scaled => renderer.width as f64,
|
||||
});
|
||||
background.set_height(match mode {
|
||||
};
|
||||
background.height = match mode {
|
||||
ui::Mode::Unscaled(scale) => 480.0 / scale,
|
||||
ui::Mode::Scaled => renderer.height as f64,
|
||||
});
|
||||
};
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -267,56 +337,59 @@ impl super::Screen for VideoSettingsMenu {
|
|||
}
|
||||
|
||||
pub struct AudioSettingsMenu {
|
||||
vars: Rc<console::Vars>,
|
||||
_vars: Rc<console::Vars>,
|
||||
elements: Option<UIElements>
|
||||
}
|
||||
|
||||
impl AudioSettingsMenu {
|
||||
pub fn new(vars: Rc<console::Vars>) -> AudioSettingsMenu {
|
||||
AudioSettingsMenu {
|
||||
vars: vars,
|
||||
_vars: vars,
|
||||
elements: None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl super::Screen for AudioSettingsMenu {
|
||||
fn on_active(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
let mut elements = ui::Collection::new();
|
||||
fn on_active(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
let background = ui::ImageBuilder::new()
|
||||
.texture("steven:solid")
|
||||
.position(0.0, 0.0)
|
||||
.size(854.0, 480.0)
|
||||
.colour((0, 0, 0, 100))
|
||||
.create(ui_container);
|
||||
|
||||
let mut background = ui::Image::new(
|
||||
render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid"),
|
||||
0.0, 0.0, 854.0, 480.0,
|
||||
0.0, 0.0, 1.0, 1.0,
|
||||
0, 0, 0
|
||||
);
|
||||
background.set_a(100);
|
||||
let background = elements.add(ui_container.add(background));
|
||||
let mut buttons = vec![];
|
||||
|
||||
let master_volume = *self.vars.get(settings::CL_MASTER_VOLUME);
|
||||
// TODO
|
||||
|
||||
let (btn_master_volume, txt_master_volume) = new_centered_button(&master_volume.to_string(), renderer, ui_container, -150.0, ui::VAttach::Middle);
|
||||
elements.add(btn_master_volume);
|
||||
elements.add(txt_master_volume);
|
||||
|
||||
let (btn_done, txt_done) = new_centered_button("Done", renderer, ui_container, 50.0, ui::VAttach::Bottom);
|
||||
super::button_action(ui_container, btn_done.clone(), Some(txt_done.clone()), move | game, _ | {
|
||||
game.screen_sys.pop_screen();
|
||||
});
|
||||
elements.add(btn_done);
|
||||
elements.add(txt_done);
|
||||
let done_button = ui::ButtonBuilder::new()
|
||||
.position(0.0, 50.0)
|
||||
.size(300.0, 40.0)
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
{
|
||||
let mut done_button = done_button.borrow_mut();
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("Done")
|
||||
.alignment(ui::VAttach::Middle, ui::HAttach::Center)
|
||||
.attach(&mut *done_button);
|
||||
done_button.add_text(txt);
|
||||
done_button.add_click_func(|_, game| {
|
||||
game.screen_sys.pop_screen();
|
||||
game.focused = true;
|
||||
true
|
||||
});
|
||||
}
|
||||
buttons.push(done_button);
|
||||
|
||||
self.elements = Some(UIElements {
|
||||
elements: elements,
|
||||
background: background,
|
||||
_buttons: buttons,
|
||||
});
|
||||
|
||||
}
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
{
|
||||
let elements = self.elements.as_mut().unwrap();
|
||||
elements.elements.remove_all(ui_container);
|
||||
}
|
||||
fn on_deactive(&mut self, _renderer: &mut render::Renderer, _ui_container: &mut ui::Container) {
|
||||
self.elements = None;
|
||||
}
|
||||
|
||||
|
@ -325,15 +398,15 @@ impl super::Screen for AudioSettingsMenu {
|
|||
let elements = self.elements.as_mut().unwrap();
|
||||
{
|
||||
let mode = ui_container.mode;
|
||||
let background = ui_container.get_mut(&elements.background);
|
||||
background.set_width(match mode {
|
||||
let mut background = elements.background.borrow_mut();
|
||||
background.width = match mode {
|
||||
ui::Mode::Unscaled(scale) => 854.0 / scale,
|
||||
ui::Mode::Scaled => renderer.width as f64,
|
||||
});
|
||||
background.set_height(match mode {
|
||||
};
|
||||
background.height = match mode {
|
||||
ui::Mode::Unscaled(scale) => 480.0 / scale,
|
||||
ui::Mode::Scaled => renderer.height as f64,
|
||||
});
|
||||
};
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
128
src/ui/batch.rs
128
src/ui/batch.rs
|
@ -1,128 +0,0 @@
|
|||
// Copyright 2016 Matthew Collins
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct BatchRef<T: UIElement> {
|
||||
index: usize,
|
||||
ty: PhantomData<T>,
|
||||
}
|
||||
|
||||
ui_element!(Batch {
|
||||
width: f64,
|
||||
height: f64,
|
||||
|
||||
elements: Vec<Element>,
|
||||
});
|
||||
|
||||
impl Batch {
|
||||
base_impl!();
|
||||
|
||||
pub fn new(x: f64, y: f64, w: f64, h: f64) -> Batch {
|
||||
ui_create!(Batch {
|
||||
x: x,
|
||||
y: y,
|
||||
width: w,
|
||||
height: h,
|
||||
|
||||
elements: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
fn update(&mut self, _: &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;
|
||||
self.data.clear();
|
||||
|
||||
let sx = r.w / self.width;
|
||||
let sy = r.h / self.height;
|
||||
|
||||
for e in &mut self.elements {
|
||||
let reg = e.get_draw_region(sx, sy, r);
|
||||
e.set_dirty(true);
|
||||
self.data.extend(e.draw(renderer, ®, width, height, delta));
|
||||
}
|
||||
}
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn add<T: UIElement>(&mut self, e: T) -> BatchRef<T> {
|
||||
self.elements.push(e.wrap());
|
||||
BatchRef {
|
||||
index: self.elements.len() - 1,
|
||||
ty: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get<T: UIElement>(&self, r: BatchRef<T>) -> &T {
|
||||
T::unwrap_ref(&self.elements[r.index])
|
||||
}
|
||||
|
||||
pub fn get_mut<T: UIElement>(&mut self, r: BatchRef<T>) -> &mut T {
|
||||
self.dirty = true;
|
||||
T::unwrap_ref_mut(&mut self.elements[r.index])
|
||||
}
|
||||
|
||||
pub fn get_mut_at<T: UIElement>(&mut self, index: usize) -> &mut T {
|
||||
self.dirty = true;
|
||||
T::unwrap_ref_mut(&mut self.elements[index])
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.elements.len()
|
||||
}
|
||||
|
||||
lazy_field!(width, f64, get_width, set_width);
|
||||
lazy_field!(height, f64, get_height, set_height);
|
||||
}
|
||||
|
||||
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"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_attachment(&self) -> (VAttach, HAttach) {
|
||||
(self.v_attach, self.h_attach)
|
||||
}
|
||||
|
||||
fn get_offset(&self) -> (f64, f64) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
|
||||
fn get_size(&self) -> (f64, f64) {
|
||||
(self.width, self.height)
|
||||
}
|
||||
}
|
144
src/ui/button.rs
144
src/ui/button.rs
|
@ -1,144 +0,0 @@
|
|||
// Copyright 2016 Matthew Collins
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2016 Matthew Collins
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
ui_element!(Button {
|
||||
width: f64,
|
||||
height: f64,
|
||||
disabled: bool,
|
||||
});
|
||||
|
||||
impl Button {
|
||||
base_impl!();
|
||||
|
||||
pub fn new(x: f64, y: f64, w: f64, h: f64) -> Button {
|
||||
let mut btn = ui_create!(Button {
|
||||
x: x,
|
||||
y: y,
|
||||
width: w,
|
||||
height: h,
|
||||
disabled: false,
|
||||
});
|
||||
btn.add_hover_func(|_,_,_|{}); // Force hover events to be called
|
||||
btn
|
||||
}
|
||||
|
||||
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;
|
||||
let sx = r.w / self.width;
|
||||
let sy = r.h / self.height;
|
||||
|
||||
let offset = match (self.disabled, self.hovered) {
|
||||
(true, _) => 46.0,
|
||||
(false, true) => 86.0,
|
||||
(false, false) => 66.0,
|
||||
};
|
||||
let texture = render::Renderer::get_texture(renderer.get_textures_ref(), "gui/widgets")
|
||||
.relative(0.0, offset / 256.0, 200.0 / 256.0, 20.0 / 256.0);
|
||||
self.data.clear();
|
||||
|
||||
self.data.extend(render::ui::UIElement::new(&texture, r.x, r.y, 4.0 * sx, 4.0 * sy, 0.0, 0.0, 2.0/200.0, 2.0/20.0).bytes(width, height));
|
||||
self.data.extend(render::ui::UIElement::new(&texture, r.x + r.w - 4.0 * sx, r.y, 4.0 * sx, 4.0 * sy, 198.0/200.0, 0.0, 2.0/200.0, 2.0/20.0).bytes(width, height));
|
||||
self.data.extend(render::ui::UIElement::new(&texture, r.x, r.y + r.h - 6.0 * sy, 4.0 * sx, 6.0 * sy, 0.0, 17.0/20.0, 2.0/200.0, 3.0/20.0).bytes(width, height));
|
||||
self.data.extend(render::ui::UIElement::new(&texture, r.x + r.w - 4.0 * sx, r.y + r.h - 6.0 * sy, 4.0 * sx, 6.0 * sy, 198.0/200.0, 17.0/20.0, 2.0/200.0, 3.0/20.0).bytes(width, height));
|
||||
|
||||
let w = ((r.w / sx)/2.0) - 4.0;
|
||||
self.data.extend(render::ui::UIElement::new(
|
||||
&texture.relative(2.0/200.0, 0.0, 196.0/200.0, 2.0/20.0),
|
||||
r.x+4.0*sx, r.y, r.w - 8.0 * sx, 4.0 * sy, 0.0, 0.0, w/196.0, 1.0).bytes(width, height)
|
||||
);
|
||||
self.data.extend(render::ui::UIElement::new(
|
||||
&texture.relative(2.0/200.0, 17.0/20.0, 196.0/200.0, 3.0/20.0),
|
||||
r.x+4.0*sx, r.y+r.h-6.0*sy, r.w - 8.0 * sx, 6.0 * sy, 0.0, 0.0, w/196.0, 1.0).bytes(width, height)
|
||||
);
|
||||
|
||||
let h = ((r.h / sy)/2.0) - 5.0;
|
||||
self.data.extend(render::ui::UIElement::new(
|
||||
&texture.relative(0.0/200.0, 2.0/20.0, 2.0/200.0, 15.0/20.0),
|
||||
r.x, r.y + 4.0*sy, 4.0 * sx, r.h - 10.0*sy, 0.0, 0.0, 1.0, h/16.0).bytes(width, height)
|
||||
);
|
||||
self.data.extend(render::ui::UIElement::new(
|
||||
&texture.relative(198.0/200.0, 2.0/20.0, 2.0/200.0, 15.0/20.0),
|
||||
r.x+r.w - 4.0 * sx, r.y + 4.0*sy, 4.0 * sx, r.h - 10.0*sy, 0.0, 0.0, 1.0, h/16.0).bytes(width, height)
|
||||
);
|
||||
|
||||
|
||||
self.data.extend(render::ui::UIElement::new(
|
||||
&texture.relative(2.0/200.0, 2.0/20.0, 196.0/200.0, 15.0/20.0),
|
||||
r.x+4.0*sx, r.y+4.0*sy, r.w - 8.0 * sx, r.h - 10.0 * sy, 0.0, 0.0, w/196.0, h/16.0).bytes(width, height)
|
||||
);
|
||||
}
|
||||
&self.data
|
||||
}
|
||||
|
||||
lazy_field!(width, f64, get_width, set_width);
|
||||
lazy_field!(height, f64, get_height, set_height);
|
||||
lazy_field!(disabled, bool, is_disabled, set_disabled);
|
||||
|
||||
}
|
||||
|
||||
impl UIElement for Button {
|
||||
fn wrap(self) -> Element {
|
||||
Element::Button(self)
|
||||
}
|
||||
|
||||
fn unwrap_ref<'a>(e: &'a Element) -> &'a Button {
|
||||
match e {
|
||||
&Element::Button(ref val) => val,
|
||||
_ => panic!("Incorrect type"),
|
||||
}
|
||||
}
|
||||
|
||||
fn unwrap_ref_mut<'a>(e: &'a mut Element) -> &'a mut Button {
|
||||
match e {
|
||||
&mut Element::Button(ref mut val) => val,
|
||||
_ => panic!("Incorrect type"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_attachment(&self) -> (VAttach, HAttach) {
|
||||
(self.v_attach, self.h_attach)
|
||||
}
|
||||
|
||||
fn get_offset(&self) -> (f64, f64) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
|
||||
fn get_size(&self) -> (f64, f64) {
|
||||
(self.width, self.height)
|
||||
}
|
||||
}
|
|
@ -1,237 +0,0 @@
|
|||
// Copyright 2016 Matthew Collins
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
ui_element!(Formatted {
|
||||
val: format::Component,
|
||||
width: f64,
|
||||
height: f64,
|
||||
scale_x: f64,
|
||||
scale_y: f64,
|
||||
|
||||
text: Vec<Element>,
|
||||
max_width: f64,
|
||||
lines: usize,
|
||||
});
|
||||
|
||||
impl Formatted {
|
||||
base_impl!();
|
||||
|
||||
pub fn new(renderer: &mut render::Renderer,
|
||||
val: format::Component,
|
||||
x: f64,
|
||||
y: f64)
|
||||
-> Formatted {
|
||||
let mut f = ui_create!(Formatted {
|
||||
val: val,
|
||||
x: x,
|
||||
y: y,
|
||||
width: 0.0,
|
||||
height: 18.0,
|
||||
scale_x: 1.0,
|
||||
scale_y: 1.0,
|
||||
|
||||
text: Vec::new(),
|
||||
max_width: -1.0,
|
||||
lines: 0,
|
||||
});
|
||||
f.init_component(renderer);
|
||||
f
|
||||
}
|
||||
|
||||
pub fn with_width_limit(renderer: &mut render::Renderer,
|
||||
val: format::Component,
|
||||
x: f64,
|
||||
y: f64,
|
||||
max_width: f64)
|
||||
-> Formatted {
|
||||
let mut f = ui_create!(Formatted {
|
||||
val: val,
|
||||
x: x,
|
||||
y: y,
|
||||
width: 0.0,
|
||||
height: 18.0,
|
||||
scale_x: 1.0,
|
||||
scale_y: 1.0,
|
||||
|
||||
text: Vec::new(),
|
||||
max_width: max_width,
|
||||
lines: 0,
|
||||
});
|
||||
f.init_component(renderer);
|
||||
f
|
||||
}
|
||||
|
||||
pub fn set_component(&mut self, renderer: &mut render::Renderer, val: format::Component) {
|
||||
self.val = val;
|
||||
self.init_component(renderer);
|
||||
}
|
||||
|
||||
fn init_component(&mut self, renderer: &mut render::Renderer) {
|
||||
self.text.clear();
|
||||
let mut state = FormatState {
|
||||
lines: 0,
|
||||
width: 0.0,
|
||||
offset: 0.0,
|
||||
text: Vec::new(),
|
||||
max_width: self.max_width,
|
||||
renderer: &renderer,
|
||||
};
|
||||
state.build(&self.val, format::Color::White);
|
||||
self.height = (state.lines + 1) as f64 * 18.0;
|
||||
self.width = state.width;
|
||||
self.lines = state.lines;
|
||||
self.text = state.text;
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
fn update(&mut self, renderer: &mut render::Renderer) {
|
||||
self.init_component(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;
|
||||
self.data.clear();
|
||||
let sx = r.w / self.width;
|
||||
let sy = r.h / self.height;
|
||||
|
||||
for e in &mut self.text {
|
||||
let reg = e.get_draw_region(sx, sy, r);
|
||||
e.set_dirty(true);
|
||||
self.data.extend(e.draw(renderer, ®, width, height, delta));
|
||||
}
|
||||
}
|
||||
&self.data
|
||||
}
|
||||
|
||||
lazy_field!(width, f64, get_width, set_width);
|
||||
lazy_field!(height, f64, get_height, set_height);
|
||||
lazy_field!(scale_x, f64, get_scale_x, set_scale_x);
|
||||
lazy_field!(scale_y, f64, get_scale_y, set_scale_y);
|
||||
|
||||
}
|
||||
|
||||
impl UIElement for Formatted {
|
||||
fn wrap(self) -> Element {
|
||||
Element::Formatted(self)
|
||||
}
|
||||
|
||||
fn unwrap_ref<'a>(e: &'a Element) -> &'a Formatted {
|
||||
match e {
|
||||
&Element::Formatted(ref val) => val,
|
||||
_ => panic!("Incorrect type"),
|
||||
}
|
||||
}
|
||||
|
||||
fn unwrap_ref_mut<'a>(e: &'a mut Element) -> &'a mut Formatted {
|
||||
match e {
|
||||
&mut Element::Formatted(ref mut val) => val,
|
||||
_ => panic!("Incorrect type"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_attachment(&self) -> (VAttach, HAttach) {
|
||||
(self.v_attach, self.h_attach)
|
||||
}
|
||||
|
||||
fn get_offset(&self) -> (f64, f64) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
|
||||
fn get_size(&self) -> (f64, f64) {
|
||||
((self.width + 2.0) * self.scale_x, self.height * self.scale_y)
|
||||
}
|
||||
}
|
||||
|
||||
struct FormatState<'a> {
|
||||
max_width: f64,
|
||||
lines: usize,
|
||||
offset: f64,
|
||||
width: f64,
|
||||
text: Vec<Element>,
|
||||
renderer: &'a render::Renderer,
|
||||
}
|
||||
|
||||
impl <'a> FormatState<'a> {
|
||||
fn build(&mut self, c: &format::Component, color: format::Color) {
|
||||
match c {
|
||||
&format::Component::Text(ref txt) => {
|
||||
let col = FormatState::get_color(&txt.modifier, color);
|
||||
self.append_text(&txt.text, col);
|
||||
let modi = &txt.modifier;
|
||||
if let Some(ref extra) = modi.extra {
|
||||
for e in extra {
|
||||
self.build(e, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn append_text(&mut self, txt: &str, color: format::Color) {
|
||||
let mut width = 0.0;
|
||||
let mut last = 0;
|
||||
for (i, c) in txt.char_indices() {
|
||||
let size = self.renderer.ui.size_of_char(c) + 2.0;
|
||||
if (self.max_width > 0.0 && self.offset + width + size > self.max_width) || c == '\n' {
|
||||
let (rr, gg, bb) = color.to_rgb();
|
||||
let text = Text::new(self.renderer,
|
||||
&txt[last..i],
|
||||
self.offset,
|
||||
(self.lines * 18 + 1) as f64,
|
||||
rr,
|
||||
gg,
|
||||
bb);
|
||||
self.text.push(text.wrap());
|
||||
last = i;
|
||||
if c == '\n' {
|
||||
last += 1;
|
||||
}
|
||||
self.offset = 0.0;
|
||||
self.lines += 1;
|
||||
width = 0.0;
|
||||
}
|
||||
width += size;
|
||||
if self.offset + width > self.width {
|
||||
self.width = self.offset + width;
|
||||
}
|
||||
}
|
||||
|
||||
if last != txt.len() {
|
||||
let (rr, gg, bb) = color.to_rgb();
|
||||
let text = Text::new(self.renderer,
|
||||
&txt[last..],
|
||||
self.offset,
|
||||
(self.lines * 18 + 1) as f64,
|
||||
rr,
|
||||
gg,
|
||||
bb);
|
||||
self.offset += text.width + 4.0; // TODO Why is this 4 not 2?
|
||||
self.text.push(text.wrap());
|
||||
if self.offset > self.width {
|
||||
self.width = self.offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_color(modi: &format::Modifier, color: format::Color) -> format::Color {
|
||||
modi.color.unwrap_or(color)
|
||||
}
|
||||
}
|
151
src/ui/image.rs
151
src/ui/image.rs
|
@ -1,151 +0,0 @@
|
|||
// Copyright 2016 Matthew Collins
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
ui_element!(Image {
|
||||
texture: render::Texture,
|
||||
width: f64,
|
||||
height: f64,
|
||||
|
||||
t_x: f64,
|
||||
t_y: f64,
|
||||
t_width: f64,
|
||||
t_height: f64,
|
||||
|
||||
r: u8,
|
||||
g: u8,
|
||||
b: u8,
|
||||
a: u8,
|
||||
});
|
||||
|
||||
impl Image {
|
||||
base_impl!();
|
||||
|
||||
pub fn new(texture: render::Texture,
|
||||
x: f64,
|
||||
y: f64,
|
||||
w: f64,
|
||||
h: f64,
|
||||
t_x: f64,
|
||||
t_y: f64,
|
||||
t_width: f64,
|
||||
t_height: f64,
|
||||
r: u8,
|
||||
g: u8,
|
||||
b: u8)
|
||||
-> Image {
|
||||
ui_create!(Image {
|
||||
texture: texture,
|
||||
x: x,
|
||||
y: y,
|
||||
width: w,
|
||||
height: h,
|
||||
|
||||
t_x: t_x,
|
||||
t_y: t_y,
|
||||
t_width: t_width,
|
||||
t_height: t_height,
|
||||
|
||||
r: r,
|
||||
g: g,
|
||||
b: b,
|
||||
a: 255,
|
||||
})
|
||||
}
|
||||
|
||||
fn update(&mut self, _: &mut render::Renderer) {
|
||||
}
|
||||
|
||||
fn draw(&mut self,
|
||||
renderer: &mut render::Renderer,
|
||||
r: &Region,
|
||||
width: f64,
|
||||
height: f64,
|
||||
_: f64)
|
||||
-> &Vec<u8> {
|
||||
if self.dirty {
|
||||
self.dirty = false;
|
||||
self.texture = renderer.check_texture(self.texture.clone());
|
||||
let mut e = render::ui::UIElement::new(&self.texture,
|
||||
r.x,
|
||||
r.y,
|
||||
r.w,
|
||||
r.h,
|
||||
self.t_x,
|
||||
self.t_y,
|
||||
self.t_width,
|
||||
self.t_height);
|
||||
e.r = self.r;
|
||||
e.g = self.g;
|
||||
e.b = self.b;
|
||||
e.a = self.a;
|
||||
e.layer = self.layer;
|
||||
self.data = e.bytes(width, height);
|
||||
}
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn get_texture(&self) -> render::Texture {
|
||||
self.texture.clone()
|
||||
}
|
||||
|
||||
pub fn set_texture(&mut self, val: render::Texture) {
|
||||
self.texture = val;
|
||||
self.dirty = true;
|
||||
}
|
||||
|
||||
lazy_field!(width, f64, get_width, set_width);
|
||||
lazy_field!(height, f64, get_height, set_height);
|
||||
|
||||
lazy_field!(t_x, f64, get_t_x, set_t_x);
|
||||
lazy_field!(t_y, f64, get_t_y, set_t_y);
|
||||
lazy_field!(t_width, f64, get_t_width, set_t_width);
|
||||
lazy_field!(t_height, f64, get_t_height, set_t_height);
|
||||
|
||||
lazy_field!(r, u8, get_r, set_r);
|
||||
lazy_field!(g, u8, get_g, set_g);
|
||||
lazy_field!(b, u8, get_b, set_b);
|
||||
lazy_field!(a, u8, get_a, set_a);
|
||||
}
|
||||
|
||||
impl UIElement for Image {
|
||||
fn wrap(self) -> Element {
|
||||
Element::Image(self)
|
||||
}
|
||||
|
||||
fn unwrap_ref<'a>(e: &'a Element) -> &'a Image {
|
||||
match e {
|
||||
&Element::Image(ref val) => val,
|
||||
_ => panic!("Incorrect type"),
|
||||
}
|
||||
}
|
||||
|
||||
fn unwrap_ref_mut<'a>(e: &'a mut Element) -> &'a mut Image {
|
||||
match e {
|
||||
&mut Element::Image(ref mut val) => val,
|
||||
_ => panic!("Incorrect type"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_attachment(&self) -> (VAttach, HAttach) {
|
||||
(self.v_attach, self.h_attach)
|
||||
}
|
||||
|
||||
fn get_offset(&self) -> (f64, f64) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
|
||||
fn get_size(&self) -> (f64, f64) {
|
||||
(self.width, self.height)
|
||||
}
|
||||
}
|
173
src/ui/logo.rs
173
src/ui/logo.rs
|
@ -9,12 +9,10 @@ use rand;
|
|||
use rand::Rng;
|
||||
|
||||
pub struct Logo {
|
||||
resources: Arc<RwLock<resources::Manager>>,
|
||||
_shadow: ui::BatchRef,
|
||||
_layer0: ui::BatchRef,
|
||||
|
||||
shadow: ui::ElementRef<ui::Batch>,
|
||||
layer0: ui::ElementRef<ui::Batch>,
|
||||
|
||||
text: ui::ElementRef<ui::Text>,
|
||||
text: ui::TextRef,
|
||||
text_base_scale: f64,
|
||||
text_orig_x: f64,
|
||||
text_index: isize,
|
||||
|
@ -23,40 +21,27 @@ pub struct Logo {
|
|||
|
||||
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,
|
||||
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
|
||||
}
|
||||
|
||||
fn init(&mut self, renderer: &mut render::Renderer, ui_container: &mut ui::Container) {
|
||||
let logo_str = {
|
||||
let res = self.resources.read().unwrap();
|
||||
let res = 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();
|
||||
logo_str
|
||||
};
|
||||
|
||||
let solid = render::Renderer::get_texture(renderer.get_textures_ref(), "steven:solid");
|
||||
let front = 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 shadow_batch = ui::BatchBuilder::new()
|
||||
.position(0.0, 8.0)
|
||||
.size(100.0, 100.0)
|
||||
.alignment(ui::VAttach::Top, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
let layer0 = ui::BatchBuilder::new()
|
||||
.position(0.0, 8.0)
|
||||
.size(100.0, 100.0)
|
||||
.draw_index(1)
|
||||
.alignment(ui::VAttach::Top, ui::HAttach::Center)
|
||||
.create(ui_container);
|
||||
|
||||
let mut row = 0;
|
||||
for line in logo_str.lines() {
|
||||
|
@ -74,96 +59,96 @@ impl Logo {
|
|||
} 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);
|
||||
ui::ImageBuilder::new()
|
||||
.texture("steven:solid")
|
||||
.position((x + 2) as f64, (y + 4) as f64)
|
||||
.size(4.0, 8.0)
|
||||
.colour((0, 0, 0, 100))
|
||||
.attach(&mut *shadow_batch.borrow_mut());
|
||||
|
||||
|
||||
let img = ui::Image::new(front.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);
|
||||
ui::ImageBuilder::new()
|
||||
.texture("minecraft:blocks/planks_oak")
|
||||
.position(x as f64, y as f64)
|
||||
.size(4.0, 8.0)
|
||||
.texture_coords((
|
||||
(x % 16) as f64 / 16.0, (y % 16) as f64 / 16.0,
|
||||
4.0 / 16.0, 8.0 / 16.0
|
||||
))
|
||||
.colour((r, g, b, 255))
|
||||
.attach(&mut *layer0.borrow_mut());
|
||||
|
||||
let width = (x + 4) as f64;
|
||||
if shadow_batch.get_width() < width {
|
||||
shadow_batch.set_width(width);
|
||||
layer0.set_width(width);
|
||||
if shadow_batch.borrow().width < width {
|
||||
shadow_batch.borrow_mut().width = width;
|
||||
layer0.borrow_mut().width = width;
|
||||
}
|
||||
}
|
||||
row += 1;
|
||||
}
|
||||
|
||||
shadow_batch.borrow_mut().height = row as f64 * 8.0;
|
||||
layer0.borrow_mut().height = row as f64 * 8.0;
|
||||
|
||||
let mut text_strings = vec![];
|
||||
{
|
||||
let res = self.resources.read().unwrap();
|
||||
let res = resources.read().unwrap();
|
||||
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", ""));
|
||||
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[..]);
|
||||
r.shuffle(&mut text_strings[..]);
|
||||
}
|
||||
|
||||
shadow_batch.set_height(row as f64 * 8.0);
|
||||
layer0.set_height(row as f64 * 8.0);
|
||||
let txt = ui::TextBuilder::new()
|
||||
.text("")
|
||||
.position(0.0, -8.0)
|
||||
.colour((255, 255, 0, 255))
|
||||
.rotation(-consts::PI / 8.0)
|
||||
.alignment(ui::VAttach::Bottom, ui::HAttach::Right)
|
||||
.draw_index(1)
|
||||
.create(&mut *layer0.borrow_mut());
|
||||
|
||||
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;
|
||||
let width = txt.borrow().width;
|
||||
let mut text_base_scale = 300.0 / width;
|
||||
if text_base_scale > 1.0 {
|
||||
text_base_scale = 1.0;
|
||||
}
|
||||
txt.borrow_mut().x = (-width / 2.0) * text_base_scale;
|
||||
let text_orig_x = txt.borrow().x;
|
||||
|
||||
Logo {
|
||||
_shadow: shadow_batch,
|
||||
_layer0: layer0,
|
||||
text: txt,
|
||||
text_base_scale: text_base_scale,
|
||||
text_orig_x: text_orig_x,
|
||||
text_index: -1,
|
||||
text_strings: text_strings,
|
||||
}
|
||||
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) {
|
||||
pub fn tick(&mut self, renderer: &mut render::Renderer) {
|
||||
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;
|
||||
let mut text = self.text.borrow_mut();
|
||||
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();
|
||||
text.text = self.text_strings[text_index as usize].clone();
|
||||
let width = (renderer.ui.size_of_string(&text.text) + 2.0) * text.scale_x;
|
||||
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();
|
||||
text.x =(-width / 2.0) * self.text_base_scale;
|
||||
self.text_orig_x = text.x;
|
||||
}
|
||||
|
||||
let timer = now.nsec as f64 / 1000000000.0;
|
||||
|
@ -172,15 +157,9 @@ impl Logo {
|
|||
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);
|
||||
text.scale_x = (0.7 + (offset / 3.0)) * self.text_base_scale;
|
||||
text.scale_y = (0.7 + (offset / 3.0)) * self.text_base_scale;
|
||||
let scale = text.scale_x;
|
||||
text.x =self.text_orig_x * scale * self.text_base_scale;
|
||||
}
|
||||
}
|
||||
|
|
1712
src/ui/mod.rs
1712
src/ui/mod.rs
File diff suppressed because it is too large
Load Diff
156
src/ui/text.rs
156
src/ui/text.rs
|
@ -1,156 +0,0 @@
|
|||
// Copyright 2016 Matthew Collins
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
ui_element!(Text {
|
||||
val: String,
|
||||
width: f64,
|
||||
height: f64,
|
||||
scale_x: f64,
|
||||
scale_y: f64,
|
||||
rotation: f64,
|
||||
r: u8,
|
||||
g: u8,
|
||||
b: u8,
|
||||
a: u8,
|
||||
});
|
||||
|
||||
impl Text {
|
||||
base_impl!();
|
||||
|
||||
pub fn new(renderer: &render::Renderer,
|
||||
val: &str,
|
||||
x: f64,
|
||||
y: f64,
|
||||
r: u8,
|
||||
g: u8,
|
||||
b: u8)
|
||||
-> Text {
|
||||
ui_create!(Text {
|
||||
val: val.to_owned(),
|
||||
x: x,
|
||||
y: y,
|
||||
width: renderer.ui.size_of_string(val),
|
||||
height: 18.0,
|
||||
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,
|
||||
_: 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_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!(width, f64, get_width, set_width);
|
||||
lazy_field!(height, f64, get_height, set_height);
|
||||
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"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_attachment(&self) -> (VAttach, HAttach) {
|
||||
(self.v_attach, self.h_attach)
|
||||
}
|
||||
|
||||
fn get_offset(&self) -> (f64, f64) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
|
||||
fn get_size(&self) -> (f64, f64) {
|
||||
((self.width + 2.0) * self.scale_x, self.height * self.scale_y)
|
||||
}
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
// Copyright 2016 Matthew Collins
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// Copyright 2016 Matthew Collins
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
ui_element!(TextBox {
|
||||
input: String,
|
||||
width: f64,
|
||||
height: f64,
|
||||
password: bool,
|
||||
button: Button,
|
||||
text: Text,
|
||||
cursor_tick: f64,
|
||||
was_focused: bool,
|
||||
submit_funcs: Vec<Rc<ClickFunc>>,
|
||||
});
|
||||
|
||||
impl TextBox {
|
||||
base_impl!();
|
||||
|
||||
pub fn new(renderer: &render::Renderer,
|
||||
input: &str,
|
||||
x: f64, y: f64, w: f64, h: f64
|
||||
) -> TextBox {
|
||||
let mut btn = Button::new(0.0, 0.0, w, h);
|
||||
btn.set_disabled(true);
|
||||
let mut txt = Text::new(renderer, input, 5.0, 0.0, 255, 255, 255);
|
||||
txt.set_v_attach(VAttach::Middle);
|
||||
let mut tbox = ui_create!(TextBox {
|
||||
input: input.to_owned(),
|
||||
x: x,
|
||||
y: y,
|
||||
width: w,
|
||||
height: h,
|
||||
password: false,
|
||||
button: btn,
|
||||
text: txt,
|
||||
cursor_tick: 0.0,
|
||||
was_focused: false,
|
||||
submit_funcs: vec![],
|
||||
});
|
||||
tbox.can_focus = true;
|
||||
tbox
|
||||
}
|
||||
|
||||
fn update(&mut self, renderer: &mut render::Renderer) {
|
||||
self.text.update(renderer);
|
||||
}
|
||||
|
||||
fn draw(&mut self,
|
||||
renderer: &mut render::Renderer,
|
||||
r: &Region,
|
||||
width: f64,
|
||||
height: f64,
|
||||
delta: f64)
|
||||
-> &Vec<u8> {
|
||||
if self.dirty || self.focused || self.was_focused {
|
||||
self.was_focused = self.focused;
|
||||
self.data.clear();
|
||||
self.dirty = false;
|
||||
|
||||
self.cursor_tick += delta;
|
||||
if self.cursor_tick > 3000.0 {
|
||||
self.cursor_tick -= 3000.0;
|
||||
}
|
||||
|
||||
let mut txt = self.transform_input();
|
||||
if self.focused && ((self.cursor_tick / 30.0) as i32) % 2 == 0 {
|
||||
txt.push('|');
|
||||
}
|
||||
self.text.set_text(renderer, &txt);
|
||||
|
||||
let sx = r.w / self.width;
|
||||
let sy = r.h / self.height;
|
||||
let reg = Container::get_draw_region_raw(&self.button, sx, sy, r);
|
||||
self.button.dirty = true;
|
||||
self.data.extend(self.button.draw(renderer, ®, width, height, delta));
|
||||
|
||||
let reg = Container::get_draw_region_raw(&self.text, sx, sy, r);
|
||||
self.text.dirty = true;
|
||||
self.data.extend(self.text.draw(renderer, ®, width, height, delta));
|
||||
}
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn get_input(&self) -> String {
|
||||
self.input.clone()
|
||||
}
|
||||
|
||||
pub fn set_input(&mut self, renderer: &render::Renderer, input: &str) {
|
||||
self.dirty = true;
|
||||
self.input = input.to_owned();
|
||||
let txt = self.transform_input();
|
||||
self.text.set_text(renderer, &txt);
|
||||
}
|
||||
|
||||
pub fn add_submit_func<F: Fn(&mut ::Game, &mut Container) + 'static>(&mut self, f: F) {
|
||||
self.submit_funcs.push(Rc::new(f));
|
||||
}
|
||||
|
||||
fn transform_input(&self) -> String {
|
||||
if self.password {
|
||||
::std::iter::repeat('*').take(self.input.len()).collect()
|
||||
} else {
|
||||
self.input.clone()
|
||||
}
|
||||
}
|
||||
|
||||
lazy_field!(width, f64, get_width, set_width);
|
||||
lazy_field!(height, f64, get_height, set_height);
|
||||
lazy_field!(password, bool, is_password, set_password);
|
||||
}
|
||||
|
||||
impl UIElement for TextBox {
|
||||
|
||||
fn key_press(&mut self, _game: &mut ::Game, key: Keycode, down: bool) -> Vec<Rc<ClickFunc>> {
|
||||
match (key, down) {
|
||||
(Keycode::Backspace, false) => {self.input.pop();},
|
||||
(Keycode::Return, false) => return self.submit_funcs.clone(),
|
||||
_ => {},
|
||||
}
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn key_type(&mut self, _game: &mut ::Game, c: char) -> Vec<Rc<ClickFunc>> {
|
||||
self.input.push(c);
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn wrap(self) -> Element {
|
||||
Element::TextBox(self)
|
||||
}
|
||||
|
||||
fn unwrap_ref<'a>(e: &'a Element) -> &'a TextBox {
|
||||
match e {
|
||||
&Element::TextBox(ref val) => val,
|
||||
_ => panic!("Incorrect type"),
|
||||
}
|
||||
}
|
||||
|
||||
fn unwrap_ref_mut<'a>(e: &'a mut Element) -> &'a mut TextBox {
|
||||
match e {
|
||||
&mut Element::TextBox(ref mut val) => val,
|
||||
_ => panic!("Incorrect type"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_attachment(&self) -> (VAttach, HAttach) {
|
||||
(self.v_attach, self.h_attach)
|
||||
}
|
||||
|
||||
fn get_offset(&self) -> (f64, f64) {
|
||||
(self.x, self.y)
|
||||
}
|
||||
|
||||
fn get_size(&self) -> (f64, f64) {
|
||||
(self.width, self.height)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue