Add basic nameplates to players

This commit is contained in:
Thinkofname 2016-04-07 21:30:20 +01:00
parent ea23219993
commit 548c98edf8
4 changed files with 124 additions and 74 deletions

View File

@ -5,7 +5,7 @@ use shared::{Direction, Position};
use world;
use world::block::Block;
use render;
use render::model;
use render::model::{self, FormatState};
pub fn add_systems(m: &mut ecs::Manager) {
let sys = SignRenderer::new(m);
@ -139,18 +139,22 @@ impl ecs::System for SignRenderer {
}
for (i, line) in info.lines.iter().enumerate() {
const Y_SCALE: f32 = (6.0 / 16.0) / 4.0;
const X_SCALE: f32 = Y_SCALE / 16.0;
let mut state = FormatState {
line: i as f32,
width: 0.0,
offset: 0.0,
text: Vec::new(),
renderer: renderer,
y_scale: Y_SCALE,
x_scale: X_SCALE,
};
state.build(line, format::Color::Black);
let width = state.width;
// Center align text
for vert in &mut state.text {
vert.x += width * 0.5;
vert.y -= (Y_SCALE + 0.4/16.0) * (i as f32);
}
verts.extend_from_slice(&state.text);
}
@ -184,67 +188,3 @@ impl ecs::System for SignRenderer {
info.model = None;
}
}
struct FormatState<'a> {
line: f32,
offset: f32,
width: f32,
text: Vec<model::Vertex>,
renderer: &'a mut render::Renderer,
}
impl <'a> FormatState<'a> {
fn build(&mut self, c: &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) {
const Y_SCALE: f32 = (6.0 / 16.0) / 4.0;
const X_SCALE: f32 = Y_SCALE / 16.0;
let (rr, gg, bb) = color.to_rgb();
for ch in txt.chars() {
if ch == ' ' {
self.offset += 6.0 * X_SCALE;
continue;
}
let texture = self.renderer.ui.character_texture(ch);
let w = self.renderer.ui.size_of_char(ch) as f32;
for vert in ::model::BlockVertex::face_by_direction(Direction::North) {
self.text.push(model::Vertex {
x: vert.x * X_SCALE * w - (self.offset + w * X_SCALE),
y: vert.y * Y_SCALE - (Y_SCALE + 0.4/16.0) * self.line + 2.1 / 16.0,
z: -0.6 / 16.0,
texture: texture.clone(),
texture_x: vert.toffsetx as f64,
texture_y: vert.toffsety as f64,
r: rr,
g: gg,
b: bb,
a: 255,
id: 0,
});
}
self.offset += (w + 2.0) * X_SCALE;
}
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)
}
}

View File

@ -12,7 +12,7 @@ use super::{
};
use world;
use render;
use render::model;
use render::model::{self, FormatState};
use types::Gamemode;
use collision::{Aabb, Aabb3};
use cgmath::{self, Point3, Vector3, Matrix4, Decomposed, Rotation3, Rad, Angle, Quaternion};
@ -21,6 +21,7 @@ use std::hash::BuildHasherDefault;
use types::hash::FNVHash;
use sdl2::keyboard::Keycode;
use shared::Position as BPosition;
use format;
pub fn add_systems(m: &mut ecs::Manager) {
// Not actually rendering related but the faster
@ -43,11 +44,11 @@ pub fn create_local(m: &mut ecs::Manager) -> ecs::Entity {
Point3::new(-0.3, 0.0, -0.3),
Point3::new(0.3, 1.8, 0.3)
)));
m.add_component_direct(entity, PlayerModel::new(false, false, true));
m.add_component_direct(entity, PlayerModel::new("", false, false, true));
entity
}
pub fn create_remote(m: &mut ecs::Manager) -> ecs::Entity {
pub fn create_remote(m: &mut ecs::Manager, name: &str) -> ecs::Entity {
let entity = m.create_entity();
m.add_component_direct(entity, Position::new(0.0, 0.0, 0.0));
m.add_component_direct(entity, TargetPosition::new(0.0, 0.0, 0.0));
@ -58,7 +59,7 @@ pub fn create_remote(m: &mut ecs::Manager) -> ecs::Entity {
Point3::new(-0.3, 0.0, -0.3),
Point3::new(0.3, 1.8, 0.3)
)));
m.add_component_direct(entity, PlayerModel::new(true, true, false));
m.add_component_direct(entity, PlayerModel::new(name, true, true, false));
entity
}
@ -67,6 +68,7 @@ pub struct PlayerModel {
model: Option<model::ModelKey>,
skin_url: Option<String>,
dirty: bool,
name: String,
has_head: bool,
has_name_tag: bool,
@ -80,11 +82,12 @@ pub struct PlayerModel {
}
impl PlayerModel {
pub fn new(has_head: bool, has_name_tag: bool, first_person: bool) -> PlayerModel {
pub fn new(name: &str, has_head: bool, has_name_tag: bool, first_person: bool) -> PlayerModel {
PlayerModel {
model: None,
skin_url: None,
dirty: false,
name: name.to_owned(),
has_head: has_head,
has_name_tag: has_name_tag,
@ -137,8 +140,8 @@ enum PlayerModelPart {
LegRight = 3,
ArmLeft = 4,
ArmRight = 5,
Cape = 6,
NameTag = 7
NameTag = 6,
Cape = 7,
}
// TODO: Setup culling
@ -186,6 +189,16 @@ impl ecs::System for PlayerRenderer {
disp: offset,
});
// TODO This sucks
if player_model.has_name_tag {
let ang = (position.position.x - renderer.camera.pos.x).atan2(position.position.z - renderer.camera.pos.z) as f32;
mdl.matrix[PlayerModelPart::NameTag as usize] = Matrix4::from(Decomposed {
scale: 1.0,
rot: Quaternion::from_angle_y(Rad::new(ang)),
disp: offset + Vector3::new(0.0, (-24.0/16.0) - 0.6, 0.0),
});
}
mdl.matrix[PlayerModelPart::Head as usize] = offset_matrix * Matrix4::from(Decomposed {
scale: 1.0,
rot: Quaternion::from_angle_x(Rad::new(-rotation.pitch as f32)),
@ -354,6 +367,39 @@ impl ecs::System for PlayerRenderer {
]);
}
let mut name_verts = vec![];
if player_model.has_name_tag {
let mut state = FormatState {
width: 0.0,
offset: 0.0,
text: Vec::new(),
renderer: renderer,
y_scale: 0.16,
x_scale: 0.01,
};
let mut name = format::Component::Text(format::TextComponent::new(&player_model.name));
format::convert_legacy(&mut name);
state.build(&name, format::Color::Black);
let width = state.width;
// Center align text
for vert in &mut state.text {
vert.x += width * 0.5;
vert.r = 64;
vert.g = 64;
vert.b = 64;
}
name_verts.extend_from_slice(&state.text);
for vert in &mut state.text {
vert.x -= 0.01;
vert.y -= 0.01;
vert.z -= 0.05;
vert.r = 255;
vert.g = 255;
vert.b = 255;
}
name_verts.extend_from_slice(&state.text);
}
player_model.model = Some(renderer.model.create_model(
model::DEFAULT,
vec![
@ -363,6 +409,7 @@ impl ecs::System for PlayerRenderer {
part_verts[1].clone(),
part_verts[2].clone(),
part_verts[3].clone(),
name_verts
]
));
}

View File

@ -11,6 +11,7 @@ use types::hash::FNVHash;
use shared::Direction;
use byteorder::{WriteBytesExt, NativeEndian};
use model::BlockVertex;
use format::{self, Component};
pub struct Manager {
collections: Vec<Collection>,
@ -369,3 +370,65 @@ pub fn append_box_texture_scale(
}
}
}
pub struct FormatState<'a> {
pub offset: f32,
pub width: f32,
pub text: Vec<Vertex>,
pub renderer: &'a mut super::Renderer,
pub y_scale: f32,
pub x_scale: f32,
}
impl <'a> FormatState<'a> {
pub fn build(&mut self, c: &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 (rr, gg, bb) = color.to_rgb();
for ch in txt.chars() {
if ch == ' ' {
self.offset += 6.0 * self.x_scale;
continue;
}
let texture = self.renderer.ui.character_texture(ch);
let w = self.renderer.ui.size_of_char(ch) as f32;
for vert in ::model::BlockVertex::face_by_direction(Direction::North) {
self.text.push(Vertex {
x: vert.x * self.x_scale * w - (self.offset + w * self.x_scale),
y: vert.y * self.y_scale + 2.1 / 16.0,
z: -0.6 / 16.0,
texture: texture.clone(),
texture_x: vert.toffsetx as f64,
texture_y: vert.toffsety as f64,
r: rr,
g: gg,
b: bb,
a: 255,
id: 0,
});
}
self.offset += (w + 2.0) * self.x_scale;
}
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)
}
}

View File

@ -601,7 +601,7 @@ impl Server {
if let Some(entity) = self.entity_map.remove(&spawn.entity_id.0) {
self.entities.remove_entity(entity);
}
let entity = entity::player::create_remote(&mut self.entities);
let entity = entity::player::create_remote(&mut self.entities, self.players.get(&spawn.uuid).map_or("MISSING", |v| &v.name));
let position = self.entities.get_component_mut(entity, self.position).unwrap();
let target_position = self.entities.get_component_mut(entity, self.target_position).unwrap();
let rotation = self.entities.get_component_mut(entity, self.rotation).unwrap();