wip: chunk spawner
parent
cf66379a23
commit
64c15be224
15
src/game.rs
15
src/game.rs
|
|
@ -2,9 +2,15 @@ use bevy::prelude::*;
|
||||||
use bevy_inspector_egui::*;
|
use bevy_inspector_egui::*;
|
||||||
use bevy_rapier2d::prelude::*;
|
use bevy_rapier2d::prelude::*;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
terrain2d::{Chunk2D, Terrain2D, Terrain2DPlugin},
|
||||||
|
util::Vector2I,
|
||||||
|
};
|
||||||
|
|
||||||
use self::{camera::GameCameraPlugin, kinematic::KinematicPlugin, player::PlayerPlugin};
|
use self::{camera::GameCameraPlugin, kinematic::KinematicPlugin, player::PlayerPlugin};
|
||||||
|
|
||||||
pub mod camera;
|
pub mod camera;
|
||||||
|
pub mod chunk;
|
||||||
pub mod kinematic;
|
pub mod kinematic;
|
||||||
pub mod player;
|
pub mod player;
|
||||||
|
|
||||||
|
|
@ -16,11 +22,20 @@ pub fn init() {
|
||||||
.add_plugin(WorldInspectorPlugin::new())
|
.add_plugin(WorldInspectorPlugin::new())
|
||||||
.add_plugin(KinematicPlugin)
|
.add_plugin(KinematicPlugin)
|
||||||
.add_plugin(GameCameraPlugin)
|
.add_plugin(GameCameraPlugin)
|
||||||
|
.add_plugin(Terrain2DPlugin)
|
||||||
// .add_plugin(PlayerPlugin)
|
// .add_plugin(PlayerPlugin)
|
||||||
// .add_startup_system(setup_debug_ground)
|
// .add_startup_system(setup_debug_ground)
|
||||||
|
.add_startup_system(setup_debug_terrain)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn setup_debug_terrain(mut terrain: ResMut<Terrain2D>) {
|
||||||
|
terrain.add_chunk(Vector2I { x: 0, y: 0 }, Chunk2D::new());
|
||||||
|
terrain.add_chunk(Vector2I { x: 1, y: 0 }, Chunk2D::new());
|
||||||
|
terrain.add_chunk(Vector2I { x: 0, y: 1 }, Chunk2D::new());
|
||||||
|
terrain.add_chunk(Vector2I { x: 1, y: 1 }, Chunk2D::new());
|
||||||
|
}
|
||||||
|
|
||||||
fn setup_debug_ground(mut commands: Commands) {
|
fn setup_debug_ground(mut commands: Commands) {
|
||||||
// Static ground
|
// Static ground
|
||||||
commands
|
commands
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use crate::terrain2d::ChunkIndex;
|
||||||
|
|
||||||
|
pub struct ChunkPlugin {}
|
||||||
|
|
||||||
|
#[derive(Reflect, Component, Default)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct Chunk {
|
||||||
|
pub index: ChunkIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Bundle)]
|
||||||
|
pub struct ChunkBundle {
|
||||||
|
pub chunk: Chunk,
|
||||||
|
pub sprite_bundle: SpriteBundle,
|
||||||
|
}
|
||||||
|
|
@ -17,8 +17,11 @@ pub struct Terrain2DPlugin;
|
||||||
|
|
||||||
impl Plugin for Terrain2DPlugin {
|
impl Plugin for Terrain2DPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.insert_resource(Terrain2D::new())
|
app.register_type::<Chunk2DIndex>()
|
||||||
.add_system(emit_terrain_events);
|
.insert_resource(Terrain2D::new())
|
||||||
|
.add_event::<TerrainEvent>()
|
||||||
|
.add_system(emit_terrain_events)
|
||||||
|
.add_system(chunk_spawner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,7 +48,7 @@ pub enum TerrainEvent {
|
||||||
|
|
||||||
#[derive(Default, Resource)]
|
#[derive(Default, Resource)]
|
||||||
pub struct Terrain2D {
|
pub struct Terrain2D {
|
||||||
chunk_map: HashMap<ChunkIndex, Chunk>,
|
chunk_map: HashMap<ChunkIndex, Chunk2D>,
|
||||||
events: Vec<TerrainEvent>,
|
events: Vec<TerrainEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,7 +60,7 @@ impl Terrain2D {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_chunk(&mut self, index: ChunkIndex, chunk: Chunk) {
|
pub fn add_chunk(&mut self, index: ChunkIndex, chunk: Chunk2D) {
|
||||||
self.chunk_map.insert(index, chunk);
|
self.chunk_map.insert(index, chunk);
|
||||||
self.events.push(TerrainEvent::ChunkAdded(index))
|
self.events.push(TerrainEvent::ChunkAdded(index))
|
||||||
}
|
}
|
||||||
|
|
@ -67,38 +70,38 @@ impl Terrain2D {
|
||||||
self.chunk_map.remove(&index);
|
self.chunk_map.remove(&index);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chunk_iter(&self) -> Iter<ChunkIndex, Chunk> {
|
pub fn chunk_iter(&self) -> Iter<ChunkIndex, Chunk2D> {
|
||||||
self.chunk_map.iter()
|
self.chunk_map.iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chunk_iter_mut(&mut self) -> IterMut<ChunkIndex, Chunk> {
|
pub fn chunk_iter_mut(&mut self) -> IterMut<ChunkIndex, Chunk2D> {
|
||||||
self.chunk_map.iter_mut()
|
self.chunk_map.iter_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index_to_chunk(&self, index: &ChunkIndex) -> Option<&Chunk> {
|
pub fn index_to_chunk(&self, index: &ChunkIndex) -> Option<&Chunk2D> {
|
||||||
self.chunk_map.get(index)
|
self.chunk_map.get(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index_to_chunk_mut(&mut self, index: &ChunkIndex) -> Option<&mut Chunk> {
|
pub fn index_to_chunk_mut(&mut self, index: &ChunkIndex) -> Option<&mut Chunk2D> {
|
||||||
self.chunk_map.get_mut(index)
|
self.chunk_map.get_mut(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_to_chunk(&self, global: &Vector2I) -> Option<&Chunk> {
|
pub fn global_to_chunk(&self, global: &Vector2I) -> Option<&Chunk2D> {
|
||||||
self.index_to_chunk(&global_to_chunk_index(global))
|
self.index_to_chunk(&global_to_chunk_index(global))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_to_chunk_mut(&mut self, global: &Vector2I) -> Option<&mut Chunk> {
|
pub fn global_to_chunk_mut(&mut self, global: &Vector2I) -> Option<&mut Chunk2D> {
|
||||||
self.index_to_chunk_mut(&global_to_chunk_index(global))
|
self.index_to_chunk_mut(&global_to_chunk_index(global))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_to_texel(&self, global: &Vector2I) -> Option<Texel> {
|
pub fn global_to_texel(&self, global: &Vector2I) -> Option<Texel2D> {
|
||||||
match self.global_to_chunk(global) {
|
match self.global_to_chunk(global) {
|
||||||
Some(chunk) => chunk.get_texel(&global_to_local(global)),
|
Some(chunk) => chunk.get_texel(&global_to_local(global)),
|
||||||
None => None,
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_to_texel_mut(&mut self, global: &Vector2I) -> Option<Texel> {
|
pub fn global_to_texel_mut(&mut self, global: &Vector2I) -> Option<Texel2D> {
|
||||||
match self.global_to_chunk(global) {
|
match self.global_to_chunk(global) {
|
||||||
Some(chunk) => chunk.get_texel(&global_to_local(global)),
|
Some(chunk) => chunk.get_texel(&global_to_local(global)),
|
||||||
None => None,
|
None => None,
|
||||||
|
|
@ -110,7 +113,7 @@ impl Terrain2D {
|
||||||
match self.index_to_chunk_mut(&index) {
|
match self.index_to_chunk_mut(&index) {
|
||||||
Some(chunk) => chunk.set_texel(&global_to_local(global), id),
|
Some(chunk) => chunk.set_texel(&global_to_local(global), id),
|
||||||
None => {
|
None => {
|
||||||
let mut chunk = Chunk::new();
|
let mut chunk = Chunk2D::new();
|
||||||
chunk.set_texel(&global_to_local(global), id);
|
chunk.set_texel(&global_to_local(global), id);
|
||||||
self.add_chunk(index, chunk);
|
self.add_chunk(index, chunk);
|
||||||
}
|
}
|
||||||
|
|
@ -121,35 +124,35 @@ impl Terrain2D {
|
||||||
pub fn local_to_texel_index(position: &Vector2I) -> Option<usize> {
|
pub fn local_to_texel_index(position: &Vector2I) -> Option<usize> {
|
||||||
match position.x >= 0
|
match position.x >= 0
|
||||||
&& position.y >= 0
|
&& position.y >= 0
|
||||||
&& position.x < Chunk::SIZE.x
|
&& position.x < Chunk2D::SIZE.x
|
||||||
&& position.y < Chunk::SIZE.y
|
&& position.y < Chunk2D::SIZE.y
|
||||||
{
|
{
|
||||||
true => Some(position.y as usize * Chunk::SIZE_X + position.x as usize),
|
true => Some(position.y as usize * Chunk2D::SIZE_X + position.x as usize),
|
||||||
false => None,
|
false => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn texel_index_to_local(i: usize) -> Vector2I {
|
pub fn texel_index_to_local(i: usize) -> Vector2I {
|
||||||
Vector2I {
|
Vector2I {
|
||||||
x: i as i32 % Chunk::SIZE.x,
|
x: i as i32 % Chunk2D::SIZE.x,
|
||||||
y: i as i32 / Chunk::SIZE.y,
|
y: i as i32 / Chunk2D::SIZE.y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_to_local(position: &Vector2I) -> Vector2I {
|
pub fn global_to_local(position: &Vector2I) -> Vector2I {
|
||||||
Vector2I {
|
Vector2I {
|
||||||
x: wrapping_remainder(position.x, Chunk::SIZE.x),
|
x: wrapping_remainder(position.x, Chunk2D::SIZE.x),
|
||||||
y: wrapping_remainder(position.y, Chunk::SIZE.y),
|
y: wrapping_remainder(position.y, Chunk2D::SIZE.y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_to_chunk_index(position: &Vector2I) -> ChunkIndex {
|
pub fn global_to_chunk_index(position: &Vector2I) -> ChunkIndex {
|
||||||
Vector2I {
|
Vector2I {
|
||||||
x: wrapping_quotient(position.x, Chunk::SIZE.x),
|
x: wrapping_quotient(position.x, Chunk2D::SIZE.x),
|
||||||
y: wrapping_quotient(position.y, Chunk::SIZE.y),
|
y: wrapping_quotient(position.y, Chunk2D::SIZE.y),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn chunk_index_to_global(chunk_pos: &ChunkIndex) -> Vector2I {
|
pub fn chunk_index_to_global(chunk_pos: &ChunkIndex) -> Vector2I {
|
||||||
*chunk_pos * Chunk::SIZE
|
*chunk_pos * Chunk2D::SIZE
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,18 @@
|
||||||
use super::{local_to_texel_index, Texel, TexelID, NEIGHBOUR_INDEX_MAP};
|
use super::{local_to_texel_index, Terrain2D, TerrainEvent, Texel2D, TexelID, NEIGHBOUR_INDEX_MAP};
|
||||||
use crate::util::Vector2I;
|
use crate::util::Vector2I;
|
||||||
|
use bevy::{prelude::*, render::render_resource::Extent3d};
|
||||||
|
|
||||||
|
#[derive(Reflect, Component, Default)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct Chunk2DIndex {
|
||||||
|
pub index: ChunkIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Bundle, Default)]
|
||||||
|
pub struct ChunkBundle {
|
||||||
|
pub chunk: Chunk2DIndex,
|
||||||
|
pub sprite_bundle: SpriteBundle,
|
||||||
|
}
|
||||||
|
|
||||||
pub type ChunkIndex = Vector2I;
|
pub type ChunkIndex = Vector2I;
|
||||||
|
|
||||||
|
|
@ -9,13 +22,13 @@ pub struct ChunkRect {
|
||||||
pub max: Vector2I,
|
pub max: Vector2I,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Chunk {
|
pub struct Chunk2D {
|
||||||
pub texels: [Texel; (Self::SIZE_X * Self::SIZE_Y) as usize],
|
pub texels: [Texel2D; (Self::SIZE_X * Self::SIZE_Y) as usize],
|
||||||
// TODO: handle multiple dirty rects
|
// TODO: handle multiple dirty rects
|
||||||
pub dirty_rect: Option<ChunkRect>,
|
pub dirty_rect: Option<ChunkRect>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Chunk {
|
impl Chunk2D {
|
||||||
pub const SIZE_X: usize = 64;
|
pub const SIZE_X: usize = 64;
|
||||||
pub const SIZE_Y: usize = 64;
|
pub const SIZE_Y: usize = 64;
|
||||||
pub const SIZE: Vector2I = Vector2I {
|
pub const SIZE: Vector2I = Vector2I {
|
||||||
|
|
@ -23,15 +36,15 @@ impl Chunk {
|
||||||
y: Self::SIZE_Y as i32,
|
y: Self::SIZE_Y as i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn new() -> Chunk {
|
pub fn new() -> Chunk2D {
|
||||||
Chunk {
|
Chunk2D {
|
||||||
texels: Self::new_texel_array(),
|
texels: Self::new_texel_array(),
|
||||||
dirty_rect: None,
|
dirty_rect: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_texel_array() -> [Texel; Self::SIZE_X * Self::SIZE_Y] {
|
pub fn new_texel_array() -> [Texel2D; Self::SIZE_X * Self::SIZE_Y] {
|
||||||
[Texel::default(); Self::SIZE_X * Self::SIZE_Y]
|
[Texel2D::default(); Self::SIZE_X * Self::SIZE_Y]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mark_all_dirty(&mut self) {
|
pub fn mark_all_dirty(&mut self) {
|
||||||
|
|
@ -58,11 +71,11 @@ impl Chunk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_texel(&self, position: &Vector2I) -> Option<Texel> {
|
pub fn get_texel(&self, position: &Vector2I) -> Option<Texel2D> {
|
||||||
local_to_texel_index(position).map(|i| self.texels[i])
|
local_to_texel_index(position).map(|i| self.texels[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_texel_option_mut(&mut self, position: &Vector2I) -> Option<&mut Texel> {
|
pub fn get_texel_option_mut(&mut self, position: &Vector2I) -> Option<&mut Texel2D> {
|
||||||
local_to_texel_index(position).map(|i| &mut self.texels[i])
|
local_to_texel_index(position).map(|i| &mut self.texels[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,7 +85,7 @@ impl Chunk {
|
||||||
self.mark_dirty(position);
|
self.mark_dirty(position);
|
||||||
}
|
}
|
||||||
let update_neighbours = self.texels[i].is_empty()
|
let update_neighbours = self.texels[i].is_empty()
|
||||||
!= (Texel {
|
!= (Texel2D {
|
||||||
id,
|
id,
|
||||||
..self.texels[i]
|
..self.texels[i]
|
||||||
})
|
})
|
||||||
|
|
@ -80,7 +93,7 @@ impl Chunk {
|
||||||
self.texels[i].id = id;
|
self.texels[i].id = id;
|
||||||
// Update neighbour mask
|
// Update neighbour mask
|
||||||
if update_neighbours {
|
if update_neighbours {
|
||||||
for offset in Texel::NEIGHBOUR_OFFSET_VECTORS {
|
for offset in Texel2D::NEIGHBOUR_OFFSET_VECTORS {
|
||||||
// Flip neighbour's bit
|
// Flip neighbour's bit
|
||||||
match self.get_texel_option_mut(&(*position + offset)) {
|
match self.get_texel_option_mut(&(*position + offset)) {
|
||||||
Some(mut neighbour) => {
|
Some(mut neighbour) => {
|
||||||
|
|
@ -92,3 +105,72 @@ impl Chunk {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn chunk_spawner(
|
||||||
|
mut commands: Commands,
|
||||||
|
mut terrain_events: EventReader<TerrainEvent>,
|
||||||
|
mut images: ResMut<Assets<Image>>,
|
||||||
|
terrain: Res<Terrain2D>,
|
||||||
|
chunk_query: Query<(Entity, &Chunk2DIndex)>,
|
||||||
|
) {
|
||||||
|
for terrain_event in terrain_events.iter() {
|
||||||
|
match terrain_event {
|
||||||
|
TerrainEvent::ChunkAdded(chunk_index) => {
|
||||||
|
let mut data = Vec::with_capacity(Chunk2D::SIZE_X * Chunk2D::SIZE_Y * 4);
|
||||||
|
for _y in 0..Chunk2D::SIZE_Y {
|
||||||
|
for _x in 0..Chunk2D::SIZE_X {
|
||||||
|
data.push(0x00);
|
||||||
|
data.push(0x00);
|
||||||
|
data.push(0x00);
|
||||||
|
data.push(0x00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let image = Image::new(
|
||||||
|
Extent3d {
|
||||||
|
width: Chunk2D::SIZE_X as u32,
|
||||||
|
height: Chunk2D::SIZE_Y as u32,
|
||||||
|
depth_or_array_layers: 1,
|
||||||
|
},
|
||||||
|
bevy::render::render_resource::TextureDimension::D2,
|
||||||
|
data,
|
||||||
|
bevy::render::render_resource::TextureFormat::Rgba8Unorm,
|
||||||
|
);
|
||||||
|
|
||||||
|
images.add(image);
|
||||||
|
|
||||||
|
let pos = Vec2::from(*chunk_index * Chunk2D::SIZE);
|
||||||
|
commands
|
||||||
|
.spawn(ChunkBundle {
|
||||||
|
chunk: Chunk2DIndex {
|
||||||
|
index: *chunk_index,
|
||||||
|
},
|
||||||
|
sprite_bundle: SpriteBundle {
|
||||||
|
sprite: Sprite {
|
||||||
|
color: Color::rgb(
|
||||||
|
0.25 + (chunk_index.x % 4) as f32 * 0.25,
|
||||||
|
0.25 + (chunk_index.y % 4) as f32 * 0.25,
|
||||||
|
0.75,
|
||||||
|
),
|
||||||
|
custom_size: Some(Vec2::from(Chunk2D::SIZE)),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
transform: Transform::from_translation(Vec3::new(pos.x, pos.y, 0.0)),
|
||||||
|
..default()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.insert(Name::new(format!(
|
||||||
|
"Chunk {},{}",
|
||||||
|
chunk_index.x, chunk_index.y
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
TerrainEvent::ChunkRemoved(chunk_index) => {
|
||||||
|
for (entity, chunk) in chunk_query.iter() {
|
||||||
|
if chunk.index == *chunk_index {
|
||||||
|
commands.entity(entity).despawn_recursive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TerrainEvent::TexelsUpdated(chunk_index, rect) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ pub use u8 as NeighbourMask;
|
||||||
use crate::util::Vector2I;
|
use crate::util::Vector2I;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Clone, Copy, Default)]
|
||||||
pub struct Texel {
|
pub struct Texel2D {
|
||||||
pub id: TexelID,
|
pub id: TexelID,
|
||||||
/// bitmask of empty/non-empty neighbours, see NEIGHBOUR_OFFSET_VECTORS for the order
|
/// bitmask of empty/non-empty neighbours, see NEIGHBOUR_OFFSET_VECTORS for the order
|
||||||
pub neighbour_mask: NeighbourMask,
|
pub neighbour_mask: NeighbourMask,
|
||||||
|
|
@ -16,14 +16,14 @@ pub struct Texel {
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref NEIGHBOUR_INDEX_MAP: HashMap<Vector2I, u8> = {
|
pub static ref NEIGHBOUR_INDEX_MAP: HashMap<Vector2I, u8> = {
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
for i in 0..Texel::NEIGHBOUR_OFFSET_VECTORS.len() {
|
for i in 0..Texel2D::NEIGHBOUR_OFFSET_VECTORS.len() {
|
||||||
map.insert(Texel::NEIGHBOUR_OFFSET_VECTORS[i], i as u8);
|
map.insert(Texel2D::NEIGHBOUR_OFFSET_VECTORS[i], i as u8);
|
||||||
}
|
}
|
||||||
map
|
map
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Texel {
|
impl Texel2D {
|
||||||
pub const EMPTY: TexelID = 0;
|
pub const EMPTY: TexelID = 0;
|
||||||
pub const NEIGHBOUR_OFFSET_VECTORS: [Vector2I; 4] = [
|
pub const NEIGHBOUR_OFFSET_VECTORS: [Vector2I; 4] = [
|
||||||
Vector2I { x: 0, y: 1 },
|
Vector2I { x: 0, y: 1 },
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
use core::{fmt, ops};
|
use core::{fmt, ops};
|
||||||
|
|
||||||
|
use bevy::reflect::Reflect;
|
||||||
|
|
||||||
pub trait VectorComponent:
|
pub trait VectorComponent:
|
||||||
Sized
|
Sized
|
||||||
+ Copy
|
+ Copy
|
||||||
+ Ord
|
+ Ord
|
||||||
|
+ Reflect
|
||||||
+ fmt::Display
|
+ fmt::Display
|
||||||
+ ops::Add<Output = Self>
|
+ ops::Add<Output = Self>
|
||||||
+ ops::Neg<Output = Self>
|
+ ops::Neg<Output = Self>
|
||||||
|
|
@ -17,6 +20,7 @@ impl<T> VectorComponent for T where
|
||||||
T: Sized
|
T: Sized
|
||||||
+ Copy
|
+ Copy
|
||||||
+ Ord
|
+ Ord
|
||||||
|
+ Reflect
|
||||||
+ fmt::Display
|
+ fmt::Display
|
||||||
+ ops::Neg<Output = T>
|
+ ops::Neg<Output = T>
|
||||||
+ ops::Add<Output = T>
|
+ ops::Add<Output = T>
|
||||||
|
|
@ -26,7 +30,7 @@ impl<T> VectorComponent for T where
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Copy, Default, Debug)]
|
#[derive(PartialEq, Eq, Hash, Clone, Copy, Default, Debug, Reflect)]
|
||||||
pub struct Vector2<T: VectorComponent> {
|
pub struct Vector2<T: VectorComponent> {
|
||||||
pub x: T,
|
pub x: T,
|
||||||
pub y: T,
|
pub y: T,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue