feat: moved the ECS related functions to the App to remove unnecessary calling of the World struct inside App.

This commit is contained in:
lisk77 2025-02-23 16:51:31 +01:00
parent f07b829b7d
commit ee3d0bdb9e
7 changed files with 258 additions and 81 deletions

View file

@ -21,6 +21,7 @@ bytemuck = "1.18.0"
chrono = "0.4.0" chrono = "0.4.0"
winit_input_helper = "0.16.0" winit_input_helper = "0.16.0"
spin_sleep = "1.2.1" spin_sleep = "1.2.1"
crossbeam-channel = "0.5.14"
[dependencies.image] [dependencies.image]
version = "0.24" version = "0.24"

View file

@ -1,8 +1,10 @@
use std::any::{type_name, Any}; use std::any::{type_name, Any};
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use std::sync::atomic::AtomicBool;
use std::thread; use std::thread;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use comet_ecs::{Component, ComponentSet, Render, Transform2D, Transform3D, World}; use crossbeam_channel::bounded;
use comet_ecs::{Component, ComponentSet, Entity, Render, Transform2D, Transform3D, World};
use comet_resources::{ResourceManager, Vertex}; use comet_resources::{ResourceManager, Vertex};
use comet_renderer::renderer2d::Renderer2D; use comet_renderer::renderer2d::Renderer2D;
@ -17,6 +19,7 @@ use comet_ecs::math::Point3;
use comet_log::*; use comet_log::*;
use winit::dpi::{LogicalSize, PhysicalSize}; use winit::dpi::{LogicalSize, PhysicalSize};
use winit::event_loop::ControlFlow; use winit::event_loop::ControlFlow;
use winit::window::Fullscreen;
use winit_input_helper::WinitInputHelper; use winit_input_helper::WinitInputHelper;
use comet_input::input_handler::InputHandler; use comet_input::input_handler::InputHandler;
use comet_input::keyboard::Key; use comet_input::keyboard::Key;
@ -28,8 +31,15 @@ pub enum ApplicationType {
App3D App3D
} }
pub struct App<'a> { pub enum AppMessage {
title: &'a str, Resize(PhysicalSize<u32>),
Input(WinitInputHelper),
UpdateCompleted(f32),
Quit
}
pub struct App {
title: String,
icon: Option<Icon>, icon: Option<Icon>,
size: Option<LogicalSize<u32>>, size: Option<LogicalSize<u32>>,
clear_color: Option<LinearRgba>, clear_color: Option<LinearRgba>,
@ -42,10 +52,10 @@ pub struct App<'a> {
should_quit: bool should_quit: bool
} }
impl<'a> App<'a> { impl App {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
title: "Untitled", title: "Untitled".to_string(),
icon: None, icon: None,
size: None, size: None,
clear_color: None, clear_color: None,
@ -59,13 +69,13 @@ impl<'a> App<'a> {
} }
} }
pub fn with_title(mut self, title: &'a str) -> Self { pub fn with_title(mut self, title: impl Into<String>) -> Self {
self.title = title; self.title = title.into();
self self
} }
pub fn with_icon(mut self, path: &'a str) -> Self { pub fn with_icon(mut self, path: impl AsRef<std::path::Path>) -> Self {
self.icon = Some(Self::load_icon(std::path::Path::new(path)).unwrap()); self.icon = Self::load_icon(path.as_ref());
self self
} }
@ -99,7 +109,13 @@ impl<'a> App<'a> {
} }
fn load_icon(path: &std::path::Path) -> Option<Icon> { fn load_icon(path: &std::path::Path) -> Option<Icon> {
let image = image::open(path).expect("Failed to open icon image"); let image = match image::open(path) {
Ok(image) => image,
Err(e) => {
error!("Failed loading icon {}", path.display());
return None;
}
};
let rgba_image = image.to_rgba8(); let rgba_image = image.to_rgba8();
let (width, height) = rgba_image.dimensions(); let (width, height) = rgba_image.dimensions();
Some(Icon::from_rgba(rgba_image.into_raw(), width, height).unwrap()) Some(Icon::from_rgba(rgba_image.into_raw(), width, height).unwrap())
@ -113,14 +129,6 @@ impl<'a> App<'a> {
self.game_state.as_mut()?.downcast_mut::<T>() self.game_state.as_mut()?.downcast_mut::<T>()
} }
pub fn world(&self) -> &World {
&self.world
}
pub fn world_mut(&mut self) -> &mut World {
&mut self.world
}
pub fn input_manager(&self) -> &WinitInputHelper { pub fn input_manager(&self) -> &WinitInputHelper {
&self.input_manager &self.input_manager
} }
@ -137,6 +145,46 @@ impl<'a> App<'a> {
self.input_manager.key_released(key) self.input_manager.key_released(key)
} }
pub fn new_entity(&mut self) -> u32 {
self.world.new_entity()
}
pub fn delete_entity(&mut self, entity_id: usize) {
self.world.delete_entity(entity_id)
}
pub fn get_entity(&self, entity_id: usize) -> Option<&Entity> {
self.world.get_entity(entity_id)
}
pub fn get_entity_mut(&mut self, entity_id: usize) -> Option<&mut Entity> {
self.world.get_entity_mut(entity_id)
}
pub fn register_component<C: Component>(&mut self) {
self.world.register_component::<C>()
}
pub fn deregister_component<C: Component>(&mut self) {
self.world.deregister_component::<C>()
}
pub fn add_component<C: Component>(&mut self, entity_id: usize, component: C) {
self.world.add_component(entity_id, component)
}
pub fn remove_component<C: Component>(&mut self, entity_id: usize) {
self.world.remove_component::<C>(entity_id)
}
pub fn get_component<C: Component>(&self, entity_id: usize) -> Option<&C> {
self.world.get_component::<C>(entity_id)
}
pub fn get_component_mut<C: Component>(&mut self, entity_id: usize) -> Option<&mut C> {
self.world.get_component_mut::<C>(entity_id)
}
pub fn quit(&mut self) { pub fn quit(&mut self) {
self.should_quit = true; self.should_quit = true;
} }
@ -154,7 +202,7 @@ impl<'a> App<'a> {
self.update_timer = 1.0/update_rate as f32; self.update_timer = 1.0/update_rate as f32;
} }
fn create_window(app_title: &str, app_icon: &Option<Icon>, window_size: &Option<LogicalSize<u32>>, event_loop: &EventLoop<()>) -> Window { fn create_window(app_title: String, app_icon: &Option<Icon>, window_size: &Option<LogicalSize<u32>>, event_loop: &EventLoop<()>) -> Window {
let winit_window = winit::window::WindowBuilder::new() let winit_window = winit::window::WindowBuilder::new()
.with_title(app_title); .with_title(app_title);
@ -173,19 +221,103 @@ impl<'a> App<'a> {
winit_window.build(event_loop).unwrap() winit_window.build(event_loop).unwrap()
} }
/*pub fn run<R: Renderer>(mut self, setup: fn(&mut App, &mut R), update: fn(&mut App, &mut R, f32)) { /*pub fn run<R: Renderer + 'static>(mut self, setup: fn(&mut App, &mut R), update: fn(&mut App, &mut R, f32)) {
info!("Starting up {}!", self.title); info!("Starting up {}!", self.title);
pollster::block_on(async { pollster::block_on(async {
let event_loop = EventLoop::new().unwrap(); let event_loop = EventLoop::new().unwrap();
let window = Arc::new(Self::create_window(self.title, &self.icon, &self.size ,&event_loop)); let window = Arc::new(Self::create_window(self.title.clone(), &self.icon, &self.size, &event_loop));
let mut renderer = R::new(window.clone(), self.clear_color.clone()).await; let mut renderer = Arc::new(RwLock::new(R::new(window.clone(), self.clear_color.clone()).await));
info!("Renderer created! ({})", type_name::<R>()); info!("Renderer created! ({})", type_name::<R>());
window.set_maximized(true);
setup(&mut self, &mut renderer); let app = Arc::new(RwLock::new(self.clone()));
// Run setup with locked app
{
let mut app_lock = app.write().unwrap();
let mut renderer_lock = renderer.write().unwrap();
setup(&mut *app_lock, &mut *renderer_lock);
}
let (game_tx, game_rx) = bounded::<AppMessage>(10);
let (render_tx, render_rx) = bounded::<AppMessage>(10);
// Spawn game logic thread
let game_thread_app = Arc::clone(&app);
let game_thread_renderer = Arc::clone(&renderer);
thread::spawn(move || {
let mut time_stack = 0.0;
let mut last_update = Instant::now();
while !game_thread_app.read().unwrap().should_quit {
let now = Instant::now();
let delta = now.duration_since(last_update).as_secs_f32();
// Get a single write lock and use it for the entire update
let mut app_lock = game_thread_app.write().unwrap();
app_lock.delta_time = delta;
time_stack += delta;
let update_timer = app_lock.update_timer; // Store the timer value
while time_stack > update_timer {
let mut renderer_lock = game_thread_renderer.write().unwrap();
update(&mut *app_lock, &mut *renderer_lock, delta);
drop(renderer_lock);
time_stack -= update_timer;
render_tx.send(AppMessage::UpdateCompleted(delta)).unwrap();
}
// Lock is automatically released here
drop(app_lock);
last_update = now;
thread::sleep(Duration::from_millis(1));
}
});
// Main thread handles events and rendering
info!("Starting event loop!");
event_loop.run(move |event, elwt| {
// Get a single write lock for the entire input handling
let mut app_lock = app.write().unwrap();
if app_lock.should_quit {
elwt.exit();
}
app_lock.input_manager.update(&event);
drop(app_lock); // Explicitly drop the lock before event handling
match event {
Event::WindowEvent { ref event, .. } => {
match event {
WindowEvent::CloseRequested => {
app.write().unwrap().quit();
elwt.exit();
}
WindowEvent::Resized(size) => {
let mut renderer_lock = renderer.write().unwrap();
renderer_lock.resize(*size);
}
WindowEvent::RedrawRequested => {
while let Ok(AppMessage::UpdateCompleted(_)) = render_rx.try_recv() {
let mut renderer_lock = renderer.write().unwrap();
match renderer_lock.render() {
Ok(_) => window.request_redraw(),
Err(e) => error!("Error rendering: {}", e)
}
}
}
_ => {}
}
}
_ => {}
}
}).unwrap();
}); });
info!("Shutting down {}!", self.title); info!("Shutting down {}!", self.title.clone());
}*/ }*/
pub fn run<R: Renderer>(mut self, setup: fn(&mut App, &mut R), update: fn(&mut App, &mut R, f32)) { pub fn run<R: Renderer>(mut self, setup: fn(&mut App, &mut R), update: fn(&mut App, &mut R, f32)) {
@ -193,10 +325,10 @@ impl<'a> App<'a> {
pollster::block_on(async { pollster::block_on(async {
let event_loop = EventLoop::new().unwrap(); let event_loop = EventLoop::new().unwrap();
let window = Arc::new(Self::create_window(self.title, &self.icon, &self.size ,&event_loop)); let window = Arc::new(Self::create_window(self.title.clone(), &self.icon, &self.size ,&event_loop));
let mut renderer = R::new(window.clone(), self.clear_color.clone()).await; let mut renderer = R::new(window.clone(), self.clear_color.clone()).await;
info!("Renderer created! ({})", type_name::<R>()); info!("Renderer created! ({})", type_name::<R>());
window.set_maximized(true); //window.set_maximized(true);
info!("Setting up!"); info!("Setting up!");
setup(&mut self, &mut renderer); setup(&mut self, &mut renderer);

View file

@ -8,6 +8,7 @@ use crate::math::{
Vec3 Vec3
}; };
use component_derive::Component; use component_derive::Component;
use crate::Entity;
// ################################################## // ##################################################
// # BASIC # // # BASIC #
@ -48,6 +49,17 @@ pub struct Render2D {
scale: Vec2 scale: Vec2
} }
#[derive(Component)]
pub struct Camera2D {
left: f32,
right: f32,
bottom: f32,
top: f32,
near: f32,
far: f32,
zoom: f32
}
// ################################################## // ##################################################
// # BUNDLES # // # BUNDLES #
// ################################################## // ##################################################
@ -91,6 +103,10 @@ pub trait Render {
fn set_texture(&mut self, texture: &'static str); fn set_texture(&mut self, texture: &'static str);
} }
pub trait Camera {
fn get_visible_entities(&self) -> Vec<Entity>;
}
// ################################################## // ##################################################
// # IMPLS # // # IMPLS #
// ################################################## // ##################################################
@ -170,11 +186,9 @@ impl Rectangle2D {
pub fn position(&self) -> Position2D { pub fn position(&self) -> Position2D {
self.position self.position
} }
pub fn set_position(&mut self, position: Position2D) { pub fn set_position(&mut self, position: Position2D) {
self.position = position; self.position = position;
} }
pub fn size(&self) -> Vec2 { pub fn size(&self) -> Vec2 {
self.size self.size
} }
@ -262,3 +276,32 @@ impl Transform3D {
&mut self.rotation &mut self.rotation
} }
} }
impl Camera2D {
pub fn new(left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, zoom: f32) -> Self {
Self {
left,
right,
bottom,
top,
near,
far,
zoom
}
}
fn in_view_frustum(&self, camera_pos: Position2D, entity: Position2D) -> bool {
let left = camera_pos.x() - self.zoom;
let right = camera_pos.x() + self.zoom;
let bottom = camera_pos.y() - self.zoom;
let top = camera_pos.y() + self.zoom;
entity.x() < right && entity.x() > left && entity.y() < top && entity.y() > bottom
}
}
impl Camera for Camera2D {
fn get_visible_entities(&self) -> Vec<Entity> {
unimplemented!()
}
}

View file

@ -193,6 +193,9 @@ impl Drop for BlobVec {
} }
} }
unsafe impl Send for BlobVec {}
unsafe impl Sync for BlobVec {}
fn array_layout(layout: &Layout, n: usize) -> Option<Layout> { fn array_layout(layout: &Layout, n: usize) -> Option<Layout> {
let (array_layout, offset) = repeat_layout(layout, n)?; let (array_layout, offset) = repeat_layout(layout, n)?;
debug_assert_eq!(layout.size(), offset); debug_assert_eq!(layout.size(), offset);
@ -538,7 +541,7 @@ impl Hash for ComponentSet {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Archetypes { pub struct Archetypes {
archetypes: HashMap<ComponentSet, Vec<u32>> archetypes: HashMap<ComponentSet, Vec<u32>>
} }

View file

@ -13,6 +13,7 @@ use crate::{
}; };
use comet_log::*; use comet_log::*;
#[derive(Clone)]
pub struct World { pub struct World {
id_queue: IdQueue, id_queue: IdQueue,
next_id: u32, next_id: u32,
@ -23,17 +24,16 @@ pub struct World {
impl World { impl World {
pub fn new() -> Self { pub fn new() -> Self {
let mut component_storage = ComponentStorage::new();
Self { Self {
id_queue: IdQueue::new(), id_queue: IdQueue::new(),
next_id: 0, next_id: 0,
entities: Vec::new(), entities: Vec::new(),
components: component_storage, components: ComponentStorage::new(),
archetypes: Archetypes::new() archetypes: Archetypes::new()
} }
} }
/// Returns the number of how many entities exist in the current World.
pub fn active_entities(&self) -> u32 { pub fn active_entities(&self) -> u32 {
self.entities.len() as u32 - self.id_queue.size() self.entities.len() as u32 - self.id_queue.size()
} }
@ -48,48 +48,42 @@ impl World {
} }
} }
pub fn id_queue(&self) -> &IdQueue { /// Retuns the `Vec` of `Option<Entity>` which contains all the entities in the current World.
&self.id_queue
}
pub fn entities(&self) -> &Vec<Option<Entity>> { pub fn entities(&self) -> &Vec<Option<Entity>> {
&self.entities &self.entities
} }
pub fn components(&self) -> &ComponentStorage { /// Creates a new entity and returns its ID.
&self.components
}
pub fn components_mut(&mut self) -> &mut ComponentStorage {
&mut self.components
}
pub fn new_entity(&mut self) -> u32 { pub fn new_entity(&mut self) -> u32 {
let id = self.next_id; let id = self.next_id;
if (self.next_id as usize) >= self.entities.len() { if (self.next_id as usize) >= self.entities.len() {
self.entities.push(Some(Entity::new(self.next_id))); self.entities.push(Some(Entity::new(self.next_id)));
self.get_next_id(); self.get_next_id();
info!("Created entity! ID: {}", id);
return id; return id;
} }
self.entities[self.next_id as usize] = Some(Entity::new(self.next_id)); self.entities[self.next_id as usize] = Some(Entity::new(self.next_id));
self.get_next_id(); self.get_next_id();
info!("Created entity! ID: {}", id);
id id
} }
pub fn get_entity(&self, entity_id: usize) -> &Entity { /// Gets an immutable reference to an entity by its ID.
assert_ne!(self.entities.get(entity_id), None, "There is no entity with this ID ({}) in the world!", entity_id); pub fn get_entity(&self, entity_id: usize) -> Option<&Entity> {
self.entities.get(entity_id).unwrap().as_ref().unwrap() //assert_ne!(self.entities.get(entity_id), None, "There is no entity with this ID ({}) in the world!", entity_id);
self.entities.get(entity_id).unwrap().as_ref()
} }
pub fn get_entity_mut(&mut self, entity_id: usize) -> &mut Entity { /// Gets a mutable reference to an entity by its ID.
assert_ne!(self.entities.get(entity_id), None, "There is no entity with this ID ({}) in the world!", entity_id); pub fn get_entity_mut(&mut self, entity_id: usize) -> Option<&mut Entity> {
self.entities.get_mut(entity_id).unwrap().as_mut().unwrap() //assert_ne!(self.entities.get(entity_id), None, "There is no entity with this ID ({}) in the world!", entity_id);
self.entities.get_mut(entity_id).unwrap().as_mut()
//self.entities.get_mut(id).unwrap() //self.entities.get_mut(id).unwrap()
} }
/// Deletes an entity by its ID.
pub fn delete_entity(&mut self, entity_id: usize) { pub fn delete_entity(&mut self, entity_id: usize) {
self.entities[entity_id] = None; self.entities[entity_id] = None;
//self.get_entity(id);
for (key, value) in self.components.iter_mut() { for (key, value) in self.components.iter_mut() {
value.remove::<u8>(entity_id); value.remove::<u8>(entity_id);
} }
@ -154,55 +148,59 @@ impl World {
ComponentSet::from_ids(type_ids) ComponentSet::from_ids(type_ids)
} }
pub fn register_component<T: Component + 'static>(&mut self) { /// Registers a new component in the world.
self.components.register_component::<T>(self.entities.len()); pub fn register_component<C: Component + 'static>(&mut self) {
self.create_archetype(ComponentSet::from_ids(vec![T::type_id()])); self.components.register_component::<C>(self.entities.len());
info!("Registered component: {}", T::type_name()); self.create_archetype(ComponentSet::from_ids(vec![C::type_id()]));
info!("Registered component: {}", C::type_name());
} }
pub fn deregister_component<T: Component + 'static>(&mut self) { /// Deregisters a component from the world.
self.components.deregister_component::<T>(); pub fn deregister_component<C: Component + 'static>(&mut self) {
info!("Deregistered component: {}", T::type_name()); self.components.deregister_component::<C>();
info!("Deregistered component: {}", C::type_name());
} }
pub fn add_component<T: Component + 'static>(&mut self, entity_id: usize, component: T) { /// Adds a component to an entity by its ID and an instance of the component.
pub fn add_component<C: Component + 'static>(&mut self, entity_id: usize, component: C) {
assert_ne!(self.entities.get(entity_id), None, "There is no entity with this ID ({}) in the world!", entity_id); assert_ne!(self.entities.get(entity_id), None, "There is no entity with this ID ({}) in the world!", entity_id);
self.components.set_component(entity_id, component); self.components.set_component(entity_id, component);
let component_index = self.components.keys.iter_mut().position(|x| *x == T::type_id()).unwrap(); let component_index = self.components.keys.iter_mut().position(|x| *x == C::type_id()).unwrap();
self.get_entity_mut(entity_id).add_component(component_index); self.get_entity_mut(entity_id).unwrap().add_component(component_index);
if !self.archetypes.contains_archetype(&self.get_component_set(entity_id)) { if !self.archetypes.contains_archetype(&self.get_component_set(entity_id)) {
self.create_archetype(self.get_component_set(entity_id)); self.create_archetype(self.get_component_set(entity_id));
} }
self.add_entity_to_archetype(entity_id as u32, ComponentSet::from_ids(vec![T::type_id()])); self.add_entity_to_archetype(entity_id as u32, ComponentSet::from_ids(vec![C::type_id()]));
if self.get_component_set(entity_id) != ComponentSet::from_ids(vec![T::type_id()]) { if self.get_component_set(entity_id) != ComponentSet::from_ids(vec![C::type_id()]) {
self.add_entity_to_archetype(entity_id as u32, self.get_component_set(entity_id)); self.add_entity_to_archetype(entity_id as u32, self.get_component_set(entity_id));
} }
info!("Added component {} to entity {}", T::type_name(), entity_id); info!("Added component {} to entity {}", C::type_name(), entity_id);
} }
pub fn remove_component<T: Component + 'static>(&mut self, entity_id: usize) { /// Removes a component from an entity by its ID.
self.components.remove_component::<T>(entity_id); pub fn remove_component<C: Component + 'static>(&mut self, entity_id: usize) {
self.components.remove_component::<C>(entity_id);
self.remove_entity_from_archetype_subsets(entity_id as u32, self.get_component_set(entity_id)); self.remove_entity_from_archetype_subsets(entity_id as u32, self.get_component_set(entity_id));
info!("Removed component {} from entity {}", T::type_name(), entity_id); info!("Removed component {} from entity {}", C::type_name(), entity_id);
} }
pub fn get_component<T: Component + 'static>(&self, entity_id: usize) -> &T { /// Returns a reference to a component of an entity by its ID.
pub fn get_component<C: Component + 'static>(&self, entity_id: usize) -> Option<&C> {
//assert_ne!(self.entities.get(entity_id), None, "There is no entity with this ID ({}) in the world!", entity_id);
self.components.get_component::<C>(entity_id)
}
pub fn get_component_mut<C: Component + 'static>(&mut self, entity_id: usize) -> Option<&mut C> {
assert_ne!(self.entities.get(entity_id), None, "There is no entity with this ID ({}) in the world!", entity_id); assert_ne!(self.entities.get(entity_id), None, "There is no entity with this ID ({}) in the world!", entity_id);
//assert_ne!(self.components.get_component::<T>(entity_id), None, "There is no component {} bound to the entity {} in the world!", T::type_name(), entity_id); assert!(self.components.get_component::<C>(entity_id) != None, "There is no component {} bound to the entity {} in the world!", C::type_name(), entity_id);
self.components.get_component::<T>(entity_id).unwrap() self.components.get_component_mut::<C>(entity_id)
}
pub fn get_component_mut<T: Component + 'static>(&mut self, entity_id: usize) -> &mut T {
assert_ne!(self.entities.get(entity_id), None, "There is no entity with this ID ({}) in the world!", entity_id);
assert!(self.components.get_component::<T>(entity_id) != None, "There is no component {} bound to the entity {} in the world!", T::type_name(), entity_id);
self.components.get_component_mut::<T>(entity_id).unwrap()
} }
/// Returns a list of entities that have the given components.
pub fn get_entities_with(&self, components: ComponentSet) -> Vec<u32> { pub fn get_entities_with(&self, components: ComponentSet) -> Vec<u32> {
assert!(self.archetypes.contains_archetype(&components), "The given components {:?} are not registered in the world!", components); assert!(self.archetypes.contains_archetype(&components), "The given components {:?} are not registered in the world!", components);
//debug!(format!("Querying entities with components: {:?}", components));
self.archetypes.get_archetype(&components).unwrap().clone() self.archetypes.get_archetype(&components).unwrap().clone()
} }
} }

View file

@ -3,7 +3,7 @@ use winit::dpi::PhysicalSize;
use winit::window::Window; use winit::window::Window;
use comet_colors::LinearRgba; use comet_colors::LinearRgba;
pub trait Renderer: Sized { pub trait Renderer: Sized + Send + Sync {
async fn new(window: Arc<Window>, clear_color: Option<LinearRgba>) -> Self; async fn new(window: Arc<Window>, clear_color: Option<LinearRgba>) -> Self;
fn size(&self) -> PhysicalSize<u32>; fn size(&self) -> PhysicalSize<u32>;
fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>); fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>);

View file

@ -740,12 +740,12 @@ impl<'a> Renderer2D<'a> {
let renderer_component = world.get_component::<Render2D>(entity as usize); let renderer_component = world.get_component::<Render2D>(entity as usize);
let transform_component = world.get_component::<Transform2D>(entity as usize); let transform_component = world.get_component::<Transform2D>(entity as usize);
if renderer_component.is_visible() { if renderer_component.unwrap().is_visible() {
//renderer.draw_texture_at(renderer_component.get_texture(), Point3::new(transform_component.position().x(), transform_component.position().y(), 0.0)); //renderer.draw_texture_at(renderer_component.get_texture(), Point3::new(transform_component.position().x(), transform_component.position().y(), 0.0));
let mut position = transform_component.position().clone(); let mut position = transform_component.unwrap().position().clone();
position.set_x(position.x() / self.config().width as f32); position.set_x(position.x() / self.config().width as f32);
position.set_y(position.y() / self.config().height as f32); position.set_y(position.y() / self.config().height as f32);
let region = self.get_texture_region(renderer_component.get_texture().to_string()); let region = self.get_texture_region(renderer_component.unwrap().get_texture().to_string());
let (dim_x, dim_y) = region.dimensions(); let (dim_x, dim_y) = region.dimensions();
let (bound_x, bound_y) = let (bound_x, bound_y) =