| @@ -306,9 +306,9 @@ where | |||||
| } | } | ||||
| #[inline] | #[inline] | ||||
| pub fn multiply(&self, other: &Self) -> Self { | |||||
| pub fn multiply<M: Borrow<Self>>(&self, other: M) -> Self { | |||||
| let m1 = self; | let m1 = self; | ||||
| let m2 = other; | |||||
| let m2 = other.borrow(); | |||||
| macro_rules! mul { | macro_rules! mul { | ||||
| ($x:tt, $y:tt) => { | ($x:tt, $y:tt) => { | ||||
| @@ -440,9 +440,9 @@ where | |||||
| } | } | ||||
| #[inline] | #[inline] | ||||
| pub fn multiply(&self, other: &Self) -> Self { | |||||
| pub fn multiply<M: Borrow<Self>>(&self, other: M) -> Self { | |||||
| let m1 = self; | let m1 = self; | ||||
| let m2 = other; | |||||
| let m2 = other.borrow(); | |||||
| macro_rules! mul { | macro_rules! mul { | ||||
| ($x:tt, $y:tt) => { | ($x:tt, $y:tt) => { | ||||
| @@ -462,8 +462,9 @@ where | |||||
| } | } | ||||
| #[inline] | #[inline] | ||||
| pub fn transform(&self, v: &Vector4<T>) -> Vector4<T> { | |||||
| pub fn transform<V: Into<Vector4<T>>>(&self, v: V) -> Vector4<T> { | |||||
| let m = self; | let m = self; | ||||
| let v = V::into(v); | |||||
| macro_rules! mul { | macro_rules! mul { | ||||
| ($i:tt) => { | ($i:tt) => { | ||||
| @@ -629,7 +630,7 @@ macro_rules! impl_mul_mat4 { | |||||
| type Output = $output; | type Output = $output; | ||||
| fn mul(self, rhs: $input) -> Self::Output { | fn mul(self, rhs: $input) -> Self::Output { | ||||
| self.$func(&rhs) | |||||
| self.$func(rhs) | |||||
| } | } | ||||
| } | } | ||||
| @@ -640,7 +641,7 @@ macro_rules! impl_mul_mat4 { | |||||
| type Output = $output; | type Output = $output; | ||||
| fn mul(self, rhs: $input) -> Self::Output { | fn mul(self, rhs: $input) -> Self::Output { | ||||
| self.$func(&rhs) | |||||
| self.$func(rhs) | |||||
| } | } | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -649,7 +650,6 @@ macro_rules! impl_mul_mat4 { | |||||
| impl_mul_mat4!(Matrix4<T>, Matrix4<T>, multiply); | impl_mul_mat4!(Matrix4<T>, Matrix4<T>, multiply); | ||||
| impl_mul_mat4!(&Matrix4<T>, Matrix4<T>, multiply); | impl_mul_mat4!(&Matrix4<T>, Matrix4<T>, multiply); | ||||
| impl_mul_mat4!(Vector4<T>, Vector4<T>, transform); | impl_mul_mat4!(Vector4<T>, Vector4<T>, transform); | ||||
| impl_mul_mat4!(&Vector4<T>, Vector4<T>, transform); | |||||
| #[cfg(test)] | #[cfg(test)] | ||||
| mod tests { | mod tests { | ||||
| @@ -2,19 +2,45 @@ use glc::vector::{Angle, Vector2f, Vector4f}; | |||||
| use space_crush_common::{ | use space_crush_common::{ | ||||
| components::{Fleet, Position}, | components::{Fleet, Position}, | ||||
| constants::SHIP_ORBIT_DISTANCE_MAX, | constants::SHIP_ORBIT_DISTANCE_MAX, | ||||
| misc::LogResult, | |||||
| }; | }; | ||||
| use specs::{prelude::*, ReadStorage, System, World, WriteExpect}; | use specs::{prelude::*, ReadStorage, System, World, WriteExpect}; | ||||
| use crate::resources::Geometry; | |||||
| use crate::{ | |||||
| components::FleetInfo, | |||||
| misc::{HorizontalAlign, Text, TextManager, VerticalAlign}, | |||||
| resources::{Camera, Geometry}, | |||||
| Error, | |||||
| }; | |||||
| #[derive(Default)] | |||||
| pub struct Fleets; | |||||
| pub struct Fleets { | |||||
| text: Text, | |||||
| } | |||||
| #[derive(SystemData)] | #[derive(SystemData)] | ||||
| pub struct FleetData<'a> { | pub struct FleetData<'a> { | ||||
| geometry: WriteExpect<'a, Geometry>, | geometry: WriteExpect<'a, Geometry>, | ||||
| position: ReadStorage<'a, Position>, | |||||
| fleet: ReadStorage<'a, Fleet>, | |||||
| camera: ReadExpect<'a, Camera>, | |||||
| positions: ReadStorage<'a, Position>, | |||||
| fleets: ReadStorage<'a, Fleet>, | |||||
| fleet_infos: ReadStorage<'a, FleetInfo>, | |||||
| } | |||||
| impl Fleets { | |||||
| pub fn new(manager: &TextManager) -> Result<Self, Error> { | |||||
| let cache = manager.create_cache()?; | |||||
| let text = cache | |||||
| .new_text() | |||||
| .scale(20.0) | |||||
| .font("resources/fonts/DroidSansMono.ttf") | |||||
| .color(0.7, 0.7, 0.7, 1.0) | |||||
| .vert_align(VerticalAlign::Center) | |||||
| .horz_align(HorizontalAlign::Center) | |||||
| .text("") | |||||
| .build()?; | |||||
| Ok(Self { text }) | |||||
| } | |||||
| } | } | ||||
| impl<'a> System<'a> for Fleets { | impl<'a> System<'a> for Fleets { | ||||
| @@ -23,28 +49,47 @@ impl<'a> System<'a> for Fleets { | |||||
| fn run(&mut self, data: Self::SystemData) { | fn run(&mut self, data: Self::SystemData) { | ||||
| let FleetData { | let FleetData { | ||||
| mut geometry, | mut geometry, | ||||
| position, | |||||
| fleet, | |||||
| camera, | |||||
| positions, | |||||
| fleets, | |||||
| fleet_infos, | |||||
| } = data; | } = data; | ||||
| gl::enable(gl::BLEND); | gl::enable(gl::BLEND); | ||||
| gl::blend_func(gl::SRC_ALPHA, gl::ONE); | |||||
| for (p, f) in (&position, &fleet).join() { | |||||
| for (position, fleet, fleet_info) in (&positions, &fleets, &fleet_infos).join() { | |||||
| gl::blend_func(gl::SRC_ALPHA, gl::ONE); | |||||
| gl::blend_equation(gl::FUNC_ADD); | |||||
| geometry.render_lines( | geometry.render_lines( | ||||
| Vector4f::new(0.5, 0.5, 0.5, 0.05), | Vector4f::new(0.5, 0.5, 0.5, 0.05), | ||||
| &create_circle(p.pos, f.orbit_min), | |||||
| &create_circle(position.pos, fleet.orbit_min), | |||||
| ); | ); | ||||
| geometry.render_lines( | geometry.render_lines( | ||||
| Vector4f::new(0.5, 0.5, 0.5, 0.05), | Vector4f::new(0.5, 0.5, 0.5, 0.05), | ||||
| &create_circle(p.pos, f.orbit_max), | |||||
| &create_circle(position.pos, fleet.orbit_max), | |||||
| ); | ); | ||||
| geometry.render_lines( | geometry.render_lines( | ||||
| Vector4f::new(0.5, 0.5, 0.5, 0.05), | Vector4f::new(0.5, 0.5, 0.5, 0.05), | ||||
| &create_circle(p.pos, SHIP_ORBIT_DISTANCE_MAX * f.orbit_max), | |||||
| &create_circle(position.pos, SHIP_ORBIT_DISTANCE_MAX * fleet.orbit_max), | |||||
| ); | ); | ||||
| gl::blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); | |||||
| gl::blend_equation(gl::FUNC_SUBTRACT); | |||||
| self.text | |||||
| .update( | |||||
| 0, | |||||
| format!( | |||||
| "F:{}\nB:{}\nT:{}", | |||||
| fleet_info.count.fighter, | |||||
| fleet_info.count.bomber, | |||||
| fleet_info.count.transporter | |||||
| ), | |||||
| ) | |||||
| .panic("Unable to update text") | |||||
| .render_offset(&camera.world_to_window(position.pos)); | |||||
| } | } | ||||
| gl::blend_equation(gl::FUNC_ADD); | |||||
| gl::disable(gl::BLEND); | gl::disable(gl::BLEND); | ||||
| } | } | ||||
| } | } | ||||
| @@ -53,8 +53,8 @@ impl<'a, 'b> App<'a, 'b> { | |||||
| .with_thread_local(Asteroids::new(world)?) | .with_thread_local(Asteroids::new(world)?) | ||||
| .with_thread_local(Ships::new(world)?) | .with_thread_local(Ships::new(world)?) | ||||
| .with_thread_local(SelectFleet::new(world, &text_manager)?) | .with_thread_local(SelectFleet::new(world, &text_manager)?) | ||||
| // .with_thread_local(DebugShips::default()) | |||||
| // .with_thread_local(DebugFleets::default()) | |||||
| .with_thread_local(DebugShips::default()) | |||||
| .with_thread_local(DebugFleets::new(&text_manager)?) | |||||
| .with_thread_local(DebugSummary::new(&text_manager)?) | .with_thread_local(DebugSummary::new(&text_manager)?) | ||||
| .build(); | .build(); | ||||
| dispatcher.setup(world); | dispatcher.setup(world); | ||||
| @@ -83,7 +83,7 @@ fn create_world(world: &mut World, player_id: Entity) { | |||||
| .create_entity() | .create_entity() | ||||
| .marked::<<PersistWorld as Persistence>::Marker>() | .marked::<<PersistWorld as Persistence>::Marker>() | ||||
| .with(Position { | .with(Position { | ||||
| pos: Vector2f::new(500.0, -500.0), | |||||
| pos: Vector2f::new(1000.0, -1000.0), | |||||
| shape: Shape::Circle(100.0), | shape: Shape::Circle(100.0), | ||||
| }) | }) | ||||
| .with(Fleet { | .with(Fleet { | ||||
| @@ -100,7 +100,7 @@ fn create_world(world: &mut World, player_id: Entity) { | |||||
| .create_entity() | .create_entity() | ||||
| .marked::<<PersistWorld as Persistence>::Marker>() | .marked::<<PersistWorld as Persistence>::Marker>() | ||||
| .with(Position { | .with(Position { | ||||
| pos: Vector2f::new(500.0, 500.0), | |||||
| pos: Vector2f::new(1000.0, 1000.0), | |||||
| shape: Shape::Circle(100.0), | shape: Shape::Circle(100.0), | ||||
| }) | }) | ||||
| .with(Fleet { | .with(Fleet { | ||||
| @@ -129,7 +129,22 @@ fn create_world(world: &mut World, player_id: Entity) { | |||||
| .with(Planet {}) | .with(Planet {}) | ||||
| .build(); | .build(); | ||||
| for i in 0..10 { | |||||
| world | |||||
| .create_entity() | |||||
| .marked::<<PersistWorld as Persistence>::Marker>() | |||||
| .with(Position { | |||||
| pos: Vector2f::new(2000.0, 0.0), | |||||
| shape: Shape::Circle(250.0), | |||||
| }) | |||||
| .with(Fleet { | |||||
| orbit_min: 325.0, | |||||
| orbit_max: 425.0, | |||||
| }) | |||||
| .with(FleetInfo::default()) | |||||
| .with(Planet {}) | |||||
| .build(); | |||||
| for i in 0..30 { | |||||
| world | world | ||||
| .create_entity() | .create_entity() | ||||
| .marked::<<PersistWorld as Persistence>::Marker>() | .marked::<<PersistWorld as Persistence>::Marker>() | ||||
| @@ -513,11 +513,7 @@ impl SelectFleet { | |||||
| let text_offset = self.ring1 + FLEET_SELECT_TEXT_OFFSET / self.zoom.sqrt(); | let text_offset = self.ring1 + FLEET_SELECT_TEXT_OFFSET / self.zoom.sqrt(); | ||||
| let pos = fleet_pos + T::into(dir).normalize() * text_offset; | let pos = fleet_pos + T::into(dir).normalize() * text_offset; | ||||
| let mut pos = (d.camera.view() * pos.into_vec4()).into_vec2(); | |||||
| pos.x += d.input_state.resolution.0 as f32 / 2.0; | |||||
| pos.y = d.input_state.resolution.1 as f32 / 2.0 - pos.y; | |||||
| pos | |||||
| d.camera.world_to_window(pos) | |||||
| } | } | ||||
| } | } | ||||
| @@ -88,4 +88,12 @@ impl Camera { | |||||
| pub fn bind(&self, index: gl::GLuint) -> Result<(), Error> { | pub fn bind(&self, index: gl::GLuint) -> Result<(), Error> { | ||||
| Error::checked(|| self.buffer.bind_buffer_base(index)) | Error::checked(|| self.buffer.bind_buffer_base(index)) | ||||
| } | } | ||||
| pub fn world_to_window<T: Into<Vector2f>>(&self, pos: T) -> Vector2f { | |||||
| let mut pos = self.data.view.transform(T::into(pos)).into_vec2(); | |||||
| pos.x += self.data.size.x / 2.0; | |||||
| pos.y = self.data.size.y / 2.0 - pos.y; | |||||
| pos | |||||
| } | |||||
| } | } | ||||