R crates/client/src/textures/autoplr_cfg.svg => crates/client/src/assets/autoplr_cfg.svg +0 -0
R crates/client/src/textures/autoplr_error.svg => crates/client/src/assets/autoplr_error.svg +0 -0
R crates/client/src/textures/autoplr_on.svg => crates/client/src/assets/autoplr_on.svg +0 -0
R crates/client/src/textures/cargo_off.svg => crates/client/src/assets/cargo_off.svg +0 -0
R crates/client/src/textures/cargo_on.svg => crates/client/src/assets/cargo_on.svg +0 -0
R crates/client/src/textures/earth.svg => crates/client/src/assets/earth.svg +0 -0
R crates/client/src/textures/earth_icon.svg => crates/client/src/assets/earth_icon.svg +0 -0
R crates/client/src/textures/ecothruster_on.svg => crates/client/src/assets/ecothruster_on.svg +0 -0
R crates/client/src/textures/editor_direction.svg => crates/client/src/assets/editor_direction.svg +0 -0
R crates/client/src/textures/f.png => crates/client/src/assets/f.png +0 -0
R crates/client/src/textures/happy-tree.png => crates/client/src/assets/happy-tree.png +0 -0
R crates/client/src/textures/hearty.svg => crates/client/src/assets/hearty.svg +0 -0
R crates/client/src/textures/hearty_ferris.svg => crates/client/src/assets/hearty_ferris.svg +0 -0
R crates/client/src/textures/hearty_party.svg => crates/client/src/assets/hearty_party.svg +0 -0
R crates/client/src/textures/hub_off.svg => crates/client/src/assets/hub_off.svg +0 -0
R crates/client/src/textures/hub_on.svg => crates/client/src/assets/hub_on.svg +0 -0
R crates/client/src/textures/landingleg.svg => crates/client/src/assets/landingleg.svg +0 -0
R crates/client/src/textures/landingthruster_off.svg => crates/client/src/assets/landingthruster_off.svg +0 -0
R crates/client/src/textures/landingthruster_on.svg => crates/client/src/assets/landingthruster_on.svg +0 -0
R crates/client/src/textures/mars.svg => crates/client/src/assets/mars.svg +0 -0
R crates/client/src/textures/mars_icon.svg => crates/client/src/assets/mars_icon.svg +0 -0
R crates/client/src/textures/missing.svg => crates/client/src/assets/missing.svg +0 -0
R crates/client/src/textures/moon.svg => crates/client/src/assets/moon.svg +0 -0
R crates/client/src/textures/moon_icon.svg => crates/client/src/assets/moon_icon.svg +0 -0
R crates/client/src/textures/powerhub_off.svg => crates/client/src/assets/powerhub_off.svg +0 -0
R crates/client/src/textures/powerhub_on.svg => crates/client/src/assets/powerhub_on.svg +0 -0
R crates/client/src/textures/starfield.svg => crates/client/src/assets/starfield.svg +0 -0
R crates/client/src/textures/starfield_dim.svg => crates/client/src/assets/starfield_dim.svg +0 -0
R crates/client/src/textures/starfield_transp.svg => crates/client/src/assets/starfield_transp.svg +0 -0
R crates/client/src/textures/sun.svg => crates/client/src/assets/sun.svg +0 -0
R crates/client/src/textures/sun_rings.svg => crates/client/src/assets/sun_rings.svg +0 -0
R crates/client/src/textures/superthruster_off.svg => crates/client/src/assets/superthruster_off.svg +0 -0
R crates/client/src/textures/superthruster_on.svg => crates/client/src/assets/superthruster_on.svg +0 -0
R crates/client/src/textures/thruster_off.svg => crates/client/src/assets/thruster_off.svg +0 -0
R crates/client/src/textures/thruster_on.svg => crates/client/src/assets/thruster_on.svg +0 -0
R crates/client/src/textures/trackindicator.svg => crates/client/src/assets/trackindicator.svg +0 -0
R crates/client/src/textures/uv.png => crates/client/src/assets/uv.png +0 -0
D crates/client/src/ecs.rs => crates/client/src/ecs.rs +0 -101
@@ 1,101 0,0 @@
-use bevy_ecs::bundle::Bundle;
-use bevy_ecs::component::Component;
-use bevy_ecs::event::Event;
-use bevy_ecs::system::Resource;
-use nalgebra::Matrix3;
-use starkingdoms_common::packet::Packet;
-use starkingdoms_common::PlanetType;
-
-#[derive(Component, Debug, Clone, Copy)]
-pub struct Translation {
- pub x: f32,
- pub y: f32,
-}
-impl Translation {
- pub fn as_matrix(&self) -> Matrix3<f32> {
- Matrix3::from_iterator([
- 1.0, 0.0, self.x,
- 0.0, 1.0, self.y,
- 0.0, 0.0, 1.0,
- ])
- }
-}
-
-#[derive(Component, Debug, Clone, Copy)]
-pub struct Shear {
- pub x: f32,
- pub y: f32,
-}
-impl Shear {
- pub fn as_matrix(&self) -> Matrix3<f32> {
- Matrix3::from_iterator([
- 1.0, self.x, 0.0,
- self.y, 1.0, 0.0,
- 0.0, 0.0, 1.0,
- ])
- }
-}
-
-#[derive(Component, Debug, Clone, Copy)]
-pub struct Scale {
- pub width: f32,
- pub height: f32,
-}
-impl Scale {
- pub fn as_matrix(&self) -> Matrix3<f32> {
- Matrix3::from_iterator([
- self.width, 0.0, 0.0,
- 0.0, self.height, 0.0,
- 0.0, 0.0, 1.0
- ])
- }
-}
-#[derive(Component, Debug, Clone, Copy)]
-pub struct Rotation {
- pub radians: f32
-}
-impl Rotation {
- pub fn as_matrix(&self) -> Matrix3<f32> {
- let x = self.radians.cos();
- let y = self.radians.sin();
- Matrix3::from_iterator([
- x, y, 0.0,
- -y, x, 0.0,
- 0.0, 0.0, 1.0
- ])
- }
-}
-
-#[derive(Component, Debug, Clone)]
-pub struct SpriteTexture {
- pub texture: String,
-}
-
-#[derive(Bundle)]
-pub struct SpriteBundle {
- pub position: Translation,
- pub shear: Shear,
- pub scale: Scale,
- pub texture: SpriteTexture,
- pub rotation: Rotation
-}
-
-#[derive(Resource, Debug)]
-pub struct Camera {
- pub x: f32,
- pub y: f32,
- pub shear_x: f32,
- pub shear_y: f32,
- pub zoom: f32,
-}
-
-#[derive(Component, Debug, Clone, Copy)]
-pub struct Player;
-
-#[derive(Component, Debug, Clone, Copy)]
-pub struct Planet(PlanetType);
-
-#[derive(Event, Clone, PartialEq)]
-pub struct SendPacket(pub Packet);
-#[derive(Event, Clone, PartialEq)]
-pub struct RecvPacket(pub Packet);
D crates/client/src/input.rs => crates/client/src/input.rs +0 -7
@@ 1,7 0,0 @@
-use bevy_ecs::event::Event;
-
-#[derive(Event, Debug, Copy, Clone)]
-pub enum MouseWheelEvent {
- Line { x: f64, y: f64 },
- Pixel { x: f64, y: f64 },
-}
M crates/client/src/lib.rs => crates/client/src/lib.rs +0 -170
@@ 1,18 1,4 @@
-use crate::ecs::{Camera, Translation, Rotation, Scale, SpriteBundle, SpriteTexture};
-use crate::input::MouseWheelEvent;
-use crate::rendering::ui::UiRenderable;
-use crate::rendering::App;
-use bevy_ecs::event::{EventReader, Events};
-use bevy_ecs::schedule::Schedule;
-use bevy_ecs::system::ResMut;
-use bevy_ecs::world::World;
-use ecs::{Player, RecvPacket, SendPacket, Shear};
-use egui::{Context, DragValue};
-use networking::ws::Ws;
-use rendering::assets::Assets;
-use starkingdoms_common::packet::Packet;
use tracing::info;
-use winit::event_loop::{ControlFlow, EventLoop};
#[cfg(target_arch = "wasm32")]
#[path = "wasm/mod.rs"]
@@ 21,11 7,6 @@ pub mod platform;
#[path = "native/mod.rs"]
pub mod platform;
-pub mod ecs;
-pub mod input;
-pub mod rendering;
-pub mod networking;
-
// Hi, you've found the real main function! This is called AFTER platform-specific initialization code.
pub fn start() {
info!(
@@ 39,155 20,4 @@ pub fn start() {
);
info!("Creating the ECS world...");
- let mut world = World::new();
-
- world.insert_resource::<Events<MouseWheelEvent>>(Events::default());
- world.insert_resource(Camera {
- x: 0.0,
- y: 0.0,
- shear_x: 0.0,
- shear_y: 0.0,
- zoom: 1.0,
- });
- world.insert_resource(Assets::new());
- world.insert_resource(Ws::new());
-
- let mut send_packet_events = Events::<SendPacket>::default();
- let recv_packet_events = Events::<RecvPacket>::default();
-
- let mut start_schedule = Schedule::default();
- // Add startup things here
- // Caution: This will run before there are things on-screen
- start_schedule.run(&mut world);
-
- let mut update_schedule = Schedule::default();
- // Add things to run every frame here
- // Caution: This will run once before there are things on screen
- update_schedule.add_systems(zoom_camera_on_mouse_events);
-
- send_packet_events.send(SendPacket(Packet::ClientLogin {
- username: String::new(),
- save: None,
- jwt: None,
- }));
-
- world.spawn((SpriteBundle {
- position: Translation {
- x: 100.0,
- y: 100.0
- },
- shear: Shear {
- x: 0.0,
- y: 0.0,
- },
- scale: Scale {
- width: 100.0,
- height: 100.0,
- },
- rotation: Rotation {
- radians: 0.0_f32.to_radians()
- },
- texture: SpriteTexture {
- texture: "hearty".to_string(),
- },
- }, Player));
-
- let event_loop = EventLoop::new().unwrap();
- event_loop.set_control_flow(ControlFlow::Poll);
- event_loop
- .run_app(&mut App::new(world, send_packet_events, recv_packet_events, update_schedule, Gui {}))
- .unwrap();
-}
-
-fn zoom_camera_on_mouse_events(mut events: EventReader<MouseWheelEvent>, mut camera: ResMut<Camera>) {
- for event in events.read() {
- let raw_delta = match event {
- MouseWheelEvent::Line { y, .. } => *y,
- MouseWheelEvent::Pixel { y, ..} => *y,
- } as f32;
-
- let delta = 1.1;
-
- if raw_delta < 0.0 {
- camera.zoom *= 1.0 / delta;
- } else {
- camera.zoom *= delta;
- }
- }
-}
-
-pub struct Gui {}
-impl UiRenderable for Gui {
- fn render(&mut self, ctx: &Context, world: &mut World) {
- egui::Window::new("Main Menu")
- .resizable(false)
- .show(ctx, |ui| {
- ui.heading("StarKingdoms.TK");
- ui.label("A game about floating through space");
- ui.separator();
-
- let mut sprites = world.query::<(&mut Translation, &mut Shear, &mut Scale, &SpriteTexture, &mut Rotation)>();
- /*for (mut pos, mut shear, mut scale, tex, mut rot) in sprites.iter_mut(world) {
- ui.heading(&tex.texture);
-
- egui::Grid::new("sprite_grid")
- .num_columns(2)
- .spacing([40.0, 4.0])
- .striped(true)
- .show(ui, |ui| {
- ui.label("X");
- ui.add(DragValue::new(&mut pos.x).speed(0.1));
- ui.end_row();
-
- ui.label("Y");
- ui.add(DragValue::new(&mut pos.y).speed(0.1));
- ui.end_row();
-
- ui.label("Shear X");
- ui.add(DragValue::new(&mut shear.x).speed(0.1));
- ui.end_row();
-
- ui.label("Shear Y");
- ui.add(DragValue::new(&mut shear.y).speed(0.1));
- ui.end_row();
-
- ui.label("Width");
- ui.add(DragValue::new(&mut scale.width).speed(0.1));
- ui.end_row();
-
- ui.label("Height");
- ui.add(DragValue::new(&mut scale.height).speed(0.1));
- ui.end_row();
-
- ui.label("Rotation");
- ui.add(DragValue::new(&mut rot.radians).speed(0.1));
- ui.end_row();
- });
- }
- let mut camera = world.resource_mut::<Camera>();
- egui::Grid::new("camera_grid")
- .num_columns(2)
- .spacing([40.0, 4.0])
- .show(ui, |ui| {
- ui.label("Camera X");
- ui.add(DragValue::new(&mut camera.x).speed(0.1));
- ui.end_row();
-
- ui.label("Camera Y");
- ui.add(DragValue::new(&mut camera.y).speed(0.1));
- ui.end_row();
-
- ui.label("Shear X");
- ui.add(DragValue::new(&mut camera.shear_x).speed(0.1));
- ui.end_row();
- ui.label("Shear Y");
- ui.add(DragValue::new(&mut camera.shear_y).speed(0.1));
- ui.end_row();
-
- ui.label("Camera Zoom");
- ui.add(DragValue::new(&mut camera.zoom).speed(0.1));
- ui.end_row();
- });*/
- });
- }
}
D crates/client/src/networking/mod.rs => crates/client/src/networking/mod.rs +0 -76
@@ 1,76 0,0 @@
-use std::collections::HashMap;
-
-use bevy_ecs::{entity::Entity, event::Events, query::With, world::World};
-use starkingdoms_common::{packet::Packet, PartType, PlanetType};
-
-use crate::ecs::{Camera, Planet, Player, RecvPacket, Rotation, Scale, SendPacket, Shear, SpriteBundle, SpriteTexture, Translation};
-
-#[cfg(target_arch = "wasm32")]
-#[path = "ws_wasm.rs"]
-pub mod ws;
-#[cfg(not(target_arch = "wasm32"))]
-#[path = "ws_native.rs"]
-pub mod ws;
-
-pub fn process_packets(
- world: &mut World,
- send_packet_events: &mut Events<SendPacket>,
- recv_packet_events: &mut Events<RecvPacket>,
- planet_types: &mut HashMap<PlanetType, (Entity, u32)>,
-) {
- use Packet::*;
- let mut recv_cursor = recv_packet_events.get_cursor();
- for recv in recv_cursor.read(&recv_packet_events) {
- match &recv.0 {
- PartPositions { parts } => {
- for (id, part) in parts {
- if part.part_type == PartType::Hearty {
- let mut player_query = world.query_filtered::<(&mut Translation, &mut Rotation), With<Player>>();
- let mut camera = world.resource_mut::<Camera>();
- camera.x = part.transform.x;
- camera.y = part.transform.y;
- tracing::info!("camera real {:?}", camera);
- for (mut translation, mut rotation) in player_query.iter_mut(world) {
- translation.x = part.transform.x;
- translation.y = part.transform.y;
- rotation.radians = part.transform.rot;
- tracing::info!("part real {:?}", translation);
- }
- tracing::info!("part {:?}", part.transform);
- }
- }
- }
- PlanetPositions { planets } => {
- for (server_id, planet) in planets {
- let mut planet_query = world.query_filtered::<(&mut Translation, &mut Rotation), With<Planet>>();
- if !planet_types.contains_key(&planet.planet_type) {
- let entity = world.spawn(SpriteBundle {
- position: Translation { x: planet.transform.x, y: planet.transform.y },
- shear: Shear { x: 0.0, y: 0.0 },
- rotation: Rotation { radians: planet.transform.rot },
- scale: Scale { width: planet.radius, height: planet.radius },
- texture: SpriteTexture {
- texture: match planet.planet_type {
- PlanetType::Sun => "sun",
- PlanetType::Mercury => "mercury",
- PlanetType::Venus => "venus",
- PlanetType::Earth => "earth",
- PlanetType::Moon => "moon",
- PlanetType::Mars => "mars",
- PlanetType::Jupiter => "jupiter",
- PlanetType::Saturn => "saturn",
- PlanetType::Uranus => "uranus",
- PlanetType::Neptune => "neptune",
- PlanetType::Pluto => "pluto",
- }.to_string()
- },
- });
- planet_types.insert(planet.planet_type, (entity.id(), *server_id));
- tracing::info!("{:?}", planet.transform);
- }
- }
- }
- _ => {}
- }
- }
-}
D crates/client/src/networking/ws_native.rs => crates/client/src/networking/ws_native.rs +0 -61
@@ 1,61 0,0 @@
-use std::{net::TcpStream, sync::{Arc, Mutex}};
-
-use bevy_ecs::system::Resource;
-use crossbeam::channel::{unbounded, Receiver, Sender};
-use starkingdoms_common::packet::{MsgFromError, Packet};
-use tungstenite::{connect, stream::MaybeTlsStream, Message, WebSocket};
-
-pub trait PacketMessageConvert {
- fn from_message(value: &Message) -> Result<Packet, MsgFromError>;
- fn into_message(&self) -> Message;
-}
-
-impl PacketMessageConvert for Packet {
- fn from_message(value: &Message) -> Result<Packet, MsgFromError> {
- match value {
- Message::Text(s) => serde_json::from_str(s).map_err(MsgFromError::JSONError),
- Message::Binary(b) => serde_json::from_slice(b).map_err(MsgFromError::JSONError),
- Message::Close(_) => Ok(Packet::_SpecialDisconnect {}),
- Message::Frame(_) | Message::Pong(_) | Message::Ping(_) => {
- Err(MsgFromError::InvalidMessageType)
- }
- }
- }
- fn into_message(&self) -> Message {
- Message::Text(serde_json::to_string(self).expect("failed to serialize packet to json").into())
- }
-}
-
-#[derive(Resource, Debug)]
-pub struct Ws {
- socket: Arc<Mutex<WebSocket<MaybeTlsStream<TcpStream>>>>,
- pub sender: Sender<Packet>,
- pub receiver: Receiver<Packet>,
- packet_receiver: Receiver<Packet>,
-}
-impl Ws {
- pub fn new() -> Self {
- let (socket, _) = connect("ws://localhost:3000").expect("Failed to connect to server");
- let socket = Arc::new(Mutex::new(socket));
- let (packet_sender, receiver) = unbounded();
- let (sender, packet_receiver) = unbounded();
- let socket_clone = socket.clone();
- std::thread::spawn(move || {
- let socket = socket_clone;
- loop {
- let message = socket.lock().unwrap().read().expect("Failed to reading message");
- let packet = Packet::from_message(&message).expect("Server sent invalid packet");
- packet_sender.send(packet).expect("Couldn't send packet to server");
- }
- });
- Ws {
- socket,
- sender,
- receiver,
- packet_receiver,
- }
- }
- pub fn send_packet(&mut self, packet: &Packet) {
- self.socket.lock().unwrap().send(packet.into_message()).expect("Couldn't send packet to server");
- }
-}
D crates/client/src/networking/ws_wasm.rs => crates/client/src/networking/ws_wasm.rs +0 -73
@@ 1,73 0,0 @@
-use std::thread::yield_now;
-
-use bevy_ecs::system::Resource;
-//use crossbeam::channel::{unbounded, Receiver, Sender};
-use futures::{channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, SinkExt};
-use wasm_bindgen::{prelude::Closure, JsCast, JsValue};
-use wasm_bindgen_futures::spawn_local;
-use web_sys::{MessageEvent, WebSocket};
-use starkingdoms_common::packet::Packet;
-
-use crate::ecs::RecvPacket;
-
-const PORT: u16 = 3000;
-
-#[derive(Debug)]
-pub struct Socket(WebSocket);
-unsafe impl Send for Socket {}
-unsafe impl Sync for Socket {}
-
-#[derive(Resource, Debug)]
-pub struct Ws {
- socket: Socket,
- pub sender: UnboundedSender<Packet>,
- pub receiver: UnboundedReceiver<Packet>,
- packet_receiver: UnboundedReceiver<Packet>,
-}
-
-impl Ws {
- pub fn new() -> Self {
- let window = web_sys::window().unwrap();
- let ws = WebSocket::new(&format!("ws://{}:{}",
- window.location().hostname().unwrap(), PORT)).expect("Couldn't connect to server");
- let (packet_sender, receiver) = unbounded();
- //let packet_sender = Rc::new(RwLock::new(packet_sender));
- let (sender, packet_receiver) = unbounded();
-
- /*let onopen_callback = Closure::<dyn FnMut()>::new(move || {
-
- });
- ws.set_onopen(Some(onopen_callback.as_ref().unchecked_ref()));
- onopen_callback.forget();*/
- let onmessage_callback = Closure::<dyn FnMut(_)>::new(move |e: MessageEvent| {
- //tracing::error!("{}", ws.ready_state());
- let data = e.data().as_string().expect("Expected string, found some other type");
- let data: Packet = serde_json::from_str(&data).expect("Received invalid json from server");
- let mut sender_clone = packet_sender.clone();
- spawn_local(async move {
- sender_clone.send(data).await.expect("Couldn't transmit packet to client");
- });
- });
- ws.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref()));
- onmessage_callback.forget();
- Ws {
- socket: Socket(ws),
- sender,
- receiver,
- packet_receiver,
- }
- }
- pub fn send_all_packets_from_channel(&mut self) {
- //for packet in self.packet_receiver.iter() {
- while let Ok(Some(packet)) = self.packet_receiver.try_next() {
- self.socket.0.send_with_str(&serde_json::to_string(&packet).expect("Couldn't convert packet to json")).expect("Couldn't send packet to server");
- }
- }
- pub fn send_packet(&mut self, packet: Packet) {
- let socket = self.socket.0.clone();
- spawn_local(async move {
- while socket.ready_state() != 1 { yield_now(); }
- socket.send_with_str(&serde_json::to_string(&packet).expect("Couldn't convert packet to json")).expect("Couldn't send packet to server");
- });
- }
-}
D crates/client/src/rendering/assets_native.rs => crates/client/src/rendering/assets_native.rs +0 -14
@@ 1,14 0,0 @@
-use bevy_ecs::system::Resource;
-
-#[derive(Resource)]
-pub struct Assets {
-
-}
-impl Assets {
- pub fn new() -> Self {
- Assets { }
- }
- pub fn get(&self, local_path: impl Into<String>) -> Option<Vec<u8>> {
- std::fs::read(format!("src/textures/{}", local_path.into())).ok()
- }
-}
D crates/client/src/rendering/assets_wasm.rs => crates/client/src/rendering/assets_wasm.rs +0 -123
@@ 1,123 0,0 @@
-use std::{collections::HashMap, fmt::Display, sync::{Arc, Mutex}, time::Duration};
-
-use bevy_ecs::system::Resource;
-use futures::channel::oneshot::Receiver;
-use image::EncodableLayout;
-use poll_promise::Promise;
-use resvg::{tiny_skia, usvg};
-use wasm_bindgen_futures::spawn_local;
-
-#[derive(Debug, Clone)]
-pub enum AssetError {
- AssetNotFound,
- ResponseNotOk(u16),
-}
-impl Display for AssetError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- AssetError::AssetNotFound => write!(f, "Asset not found"),
- AssetError::ResponseNotOk(code) => write!(f, "Server response was not ok {}", code),
- }
- }
-}
-impl std::error::Error for AssetError {}
-
-#[derive(Debug, Clone)]
-pub struct ImgData {
- pub bytes: Vec<u8>,
- pub width: u32,
- pub height: u32,
-}
-
-#[derive(Resource)]
-pub struct Assets {
- texture_promises: Arc<Mutex<HashMap<String, Promise<ImgData>>>>,
- textures: Arc<Mutex<HashMap<String, ImgData>>>,
-}
-
-impl Assets {
- pub fn new() -> Self {
- Assets {
- textures: Arc::new(Mutex::new(HashMap::new())),
- texture_promises: Arc::new(Mutex::new(HashMap::new())),
- }
- }
- pub fn get(&self, local_path: impl Into<String>) -> Option<ImgData> {
- let local_path = local_path.into();
- tracing::info!("contains texture");
- let contains_texture = {
- self.textures.lock().unwrap().contains_key(&local_path)
- };
- tracing::info!("contains texture promise");
- let contains_texture_promise = {
- self.texture_promises.lock().unwrap().contains_key(&local_path)
- };
- if !contains_texture && !contains_texture_promise {
- tracing::info!("insert receiver");
- let local_path_clone = local_path.clone();
- let request_promise = poll_promise::Promise::spawn_local(async move {
- tracing::info!("in spawn local");
- let window = web_sys::window().unwrap();
- tracing::info!("after window");
- let request = ehttp::Request::get(format!("{}/src/textures/{}", window.location().origin().unwrap(), local_path_clone));
- let response = match ehttp::fetch_async(request).await {
- Ok(resp) => resp,
- Err(e) => {
- panic!("{}", e);
- },
- };
- tracing::info!("after response");
- tracing::info!("texture received");
- if local_path_clone.ends_with(".svg") {
- let opt = usvg::Options {
- default_size: usvg::Size::from_wh(20.0, 20.0).unwrap(),
- ..Default::default()
- };
- let tree = usvg::Tree::from_data(&response.bytes, &opt).expect(&format!("Couldn't parse svg {}", local_path_clone));
- let tree_size = tree.size().to_int_size();
- let size = usvg::Size::from_wh(100.0, 100.0).unwrap().to_int_size();
- assert!(size.width() > 0 && size.height() > 0);
- let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height()).expect("Failed to construct pixmap");
- resvg::render(&tree, tiny_skia::Transform::from_scale((size.width() as f32)/(tree_size.height() as f32), (size.height() as f32)/(tree_size.height() as f32)), &mut pixmap.as_mut());
- let data = ImgData {
- bytes: pixmap.data().to_vec(),
- width: size.width(),
- height: size.height(),
- };
-
- data
- } else if local_path_clone.ends_with(".png") {
- let img = image::load_from_memory(&response.bytes).unwrap();
- let rgba = img.to_rgba8();
- let data = ImgData {
- bytes: rgba.as_bytes().to_vec(),
- width: rgba.width(),
- height: rgba.height(),
- };
- data
- } else {
- panic!("Unsupported sprite type");
- }
- });
- {
- self.texture_promises.lock().unwrap().insert(local_path.clone(), request_promise);
- }
- None
- } else if !contains_texture {
- tracing::info!("in contains texture");
- let mut texture_promises = self.texture_promises.lock().unwrap();
- tracing::info!("lock received");
- let promise = texture_promises.get_mut(&local_path).unwrap();
- tracing::info!("texture receiver gotten");
- let mut returned_value = None;
- if let Some(texture) = promise.ready() {
- self.textures.lock().unwrap().insert(local_path.clone(), texture.clone());
- returned_value = Some(texture.clone());
- texture_promises.remove(&local_path);
- }
- return returned_value
- } else {
- self.textures.lock().unwrap().get(&local_path).cloned()
- }
- }
-}
D crates/client/src/rendering/mipmap.rs => crates/client/src/rendering/mipmap.rs +0 -134
@@ 1,134 0,0 @@
-use crate::rendering::texture::Texture;
-use std::collections::HashMap;
-use tracing::debug;
-use wgpu::{
- include_wgsl, BindGroupDescriptor, BindGroupEntry, BindingResource, Color, ColorTargetState,
- ColorWrites, CommandEncoderDescriptor, Device, FilterMode, FragmentState, LoadOp, Operations,
- Queue, RenderPassColorAttachment, RenderPassDescriptor, RenderPipeline,
- RenderPipelineDescriptor, Sampler, SamplerDescriptor, ShaderModule, StoreOp, TextureFormat,
- TextureViewDescriptor, VertexState,
-};
-
-pub struct MipGenerator {
- shader: ShaderModule,
- sampler: Sampler,
- pipelines: HashMap<TextureFormat, RenderPipeline>,
-}
-impl MipGenerator {
- pub fn new(device: &Device) -> Self {
- debug!("initializing MipGenerator, compiling shader module");
- let shader = device.create_shader_module(include_wgsl!("../shaders/text_quad_mips.wgsl"));
- Self {
- shader,
- sampler: device.create_sampler(&SamplerDescriptor {
- min_filter: FilterMode::Linear,
- label: Some("MipGenerator sampler"),
- ..Default::default()
- }),
- pipelines: HashMap::new(),
- }
- }
-
- pub fn generate_mips(&mut self, texture: &Texture, device: &Device, queue: &Queue) {
- let pipeline = self
- .pipelines
- .entry(texture.texture.format())
- .or_insert_with(|| {
- device.create_render_pipeline(&RenderPipelineDescriptor {
- label: Some("MipGenerator format pipeline"),
- layout: None,
- vertex: VertexState {
- module: &self.shader,
- entry_point: Some("vs"),
- compilation_options: Default::default(),
- buffers: &[],
- },
- primitive: Default::default(),
- depth_stencil: None,
- multisample: Default::default(),
- fragment: Some(FragmentState {
- module: &self.shader,
- entry_point: Some("fs"),
- compilation_options: Default::default(),
- targets: &[Some(ColorTargetState {
- format: texture.texture.format(),
- blend: None,
- write_mask: ColorWrites::default(),
- })],
- }),
- multiview: None,
- cache: None,
- })
- });
-
- let mut encoder = device.create_command_encoder(&CommandEncoderDescriptor {
- label: Some("MipGenerator command encoder"),
- });
-
- let mut width = texture.texture.width();
- let mut height = texture.texture.height();
- let mut base_mip_level = 0;
-
- while width > 1 || height > 1 {
- width = 1.max(width / 2);
- height = 1.max(height / 2);
-
- let bind_group = device.create_bind_group(&BindGroupDescriptor {
- label: Some("MipGenerator bind group"),
- layout: &pipeline.get_bind_group_layout(0),
- entries: &[
- BindGroupEntry {
- binding: 0,
- resource: BindingResource::Sampler(&self.sampler),
- },
- BindGroupEntry {
- binding: 1,
- resource: BindingResource::TextureView(&texture.texture.create_view(
- &TextureViewDescriptor {
- base_mip_level,
- mip_level_count: Some(1),
- ..Default::default()
- },
- )),
- },
- ],
- });
-
- base_mip_level += 1;
-
- let texture_view = texture.texture.create_view(&TextureViewDescriptor {
- base_mip_level,
- mip_level_count: Some(1),
- ..Default::default()
- });
-
- let render_pass_descriptor = RenderPassDescriptor {
- label: Some("MipGenerator render pass"),
- color_attachments: &[Some(RenderPassColorAttachment {
- view: &texture_view,
- resolve_target: None,
- ops: Operations {
- load: LoadOp::Clear(Color {
- r: 0.0,
- g: 0.0,
- b: 0.0,
- a: 1.0,
- }),
- store: StoreOp::Store,
- },
- })],
- depth_stencil_attachment: None,
- timestamp_writes: None,
- occlusion_query_set: None,
- };
-
- let mut pass = encoder.begin_render_pass(&render_pass_descriptor);
- pass.set_pipeline(pipeline);
- pass.set_bind_group(0, Some(&bind_group), &[]);
- pass.draw(0..6, 0..1);
- }
-
- let command_buffer = encoder.finish();
- queue.submit(std::iter::once(command_buffer));
- }
-}
D crates/client/src/rendering/mod.rs => crates/client/src/rendering/mod.rs +0 -253
@@ 1,253 0,0 @@
-mod mipmap;
-mod renderer;
-mod texture;
-#[cfg(not(target_arch="wasm32"))]
-#[path = "assets_native.rs"]
-pub mod assets;
-#[cfg(target_arch="wasm32")]
-#[path = "assets_wasm.rs"]
-pub mod assets;
-pub mod ui;
-
-use crate::ecs::{RecvPacket, SendPacket};
-use crate::input::MouseWheelEvent;
-use crate::rendering::renderer::RenderInitRes::{Initialized, NotReadyYet};
-#[allow(unused_imports)]
-use crate::rendering::renderer::{Renderer, RenderInitRes};
-use crate::rendering::ui::UiRenderable;
-use bevy_ecs::event::Events;
-use bevy_ecs::schedule::Schedule;
-use bevy_ecs::world::World;
-use std::ops::Add;
-use std::process::exit;
-use std::sync::Arc;
-use std::time::Duration;
-use tracing::info;
-use web_time::Instant;
-use winit::application::ApplicationHandler;
-use winit::dpi::LogicalSize;
-use winit::event::{MouseScrollDelta, WindowEvent};
-use winit::event_loop::{ActiveEventLoop, ControlFlow};
-use winit::window::{Window, WindowId};
-
-pub struct App<T: UiRenderable> {
- window: Option<Arc<Window>>,
- renderer: Option<Renderer<T>>,
-
- #[cfg(target_arch = "wasm32")]
- renderer_rx: Option<futures::channel::oneshot::Receiver<RenderInitRes<T>>>,
-
- world: Option<World>,
- update_schedule: Option<Schedule>,
- ui_renderable: Option<T>,
- send_packet_events: Option<Events<SendPacket>>,
- recv_packet_events: Option<Events<RecvPacket>>,
-}
-
-impl<T: UiRenderable> App<T> {
- pub fn new(world: World, send_packet_events: Events<SendPacket>,
- recv_packet_events: Events<RecvPacket>, update_schedule: Schedule, ui_renderable: T) -> Self {
- Self {
- window: None,
- renderer: None,
- #[cfg(target_arch = "wasm32")]
- renderer_rx: None,
- world: Some(world),
- update_schedule: Some(update_schedule),
- ui_renderable: Some(ui_renderable),
- send_packet_events: Some(send_packet_events),
- recv_packet_events: Some(recv_packet_events),
- }
- }
-}
-impl<T: UiRenderable + 'static> ApplicationHandler for App<T> {
- fn resumed(&mut self, event_loop: &ActiveEventLoop) {
- if self.window.is_none() {
- let attributes = Window::default_attributes().with_title("StarKingdoms.TK");
-
- let window = Arc::new(event_loop.create_window(attributes).unwrap());
- self.window = Some(window.clone());
-
- let world = self.world.take().unwrap();
- let update_schedule = self.update_schedule.take().unwrap();
- let ui_renderable = self.ui_renderable.take().unwrap();
- let send_packet_events = self.send_packet_events.take().unwrap();
- let recv_packet_events = self.recv_packet_events.take().unwrap();
-
- #[cfg(not(target_arch = "wasm32"))]
- {
- let renderer = pollster::block_on(async move {
- Renderer::try_init(window.clone(), world,
- update_schedule, ui_renderable, send_packet_events, recv_packet_events).await
- });
- match renderer {
- Initialized(r) => {
- self.renderer = Some(r);
- }
- NotReadyYet(w, u, t, send, recv) => {
- self.world = Some(w);
- self.update_schedule = Some(u);
- self.ui_renderable = Some(t);
- self.send_packet_events = Some(send);
- self.recv_packet_events = Some(recv);
- }
- }
- }
- #[cfg(target_arch = "wasm32")]
- {
- use winit::platform::web::WindowExtWebSys;
- // Add it to the DOM
- web_sys::window()
- .unwrap()
- .document()
- .unwrap()
- .body()
- .unwrap()
- .append_child(&window.canvas().unwrap())
- .unwrap();
-
- let (tx, rx) = futures::channel::oneshot::channel();
- self.renderer_rx = Some(rx);
- wasm_bindgen_futures::spawn_local(async move {
- let renderer =
- Renderer::try_init(window.clone(), world,
- update_schedule, ui_renderable, send_packet_events, recv_packet_events).await;
- tx.send(renderer).unwrap();
- });
- }
- }
- }
-
- fn window_event(
- &mut self,
- event_loop: &ActiveEventLoop,
- _window_id: WindowId,
- event: WindowEvent,
- ) {
- if event == WindowEvent::CloseRequested {
- info!("Close requested by underlying event system");
- event_loop.exit();
- exit(1);
- }
- if let Some(renderer) = &mut self.renderer {
- let egui_response = renderer.gui_winit.on_window_event(&renderer.window, &event);
- if egui_response.consumed {
- return;
- }
- }
-
- match event {
- WindowEvent::Resized(new) => {
- if let Some(renderer) = &mut self.renderer {
- if new.width > 0 && new.height > 0 {
- renderer.size = new;
- renderer.scale_factor = renderer.window.scale_factor();
- renderer.logical_size =
- LogicalSize::from_physical(renderer.size, renderer.scale_factor);
-
- renderer.surface_configuration.width = new.width;
- renderer.surface_configuration.height = new.height;
- renderer
- .surface
- .configure(&renderer.device, &renderer.surface_configuration);
- }
- }
- }
- WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
- if let Some(renderer) = &mut self.renderer {
- renderer.scale_factor = scale_factor;
- renderer.logical_size =
- LogicalSize::from_physical(renderer.size, renderer.scale_factor);
- }
- }
- WindowEvent::MouseWheel { delta, .. } => {
- if let Some(renderer) = &mut self.renderer {
- renderer.world.send_event(match delta {
- MouseScrollDelta::PixelDelta(pos) => {
- MouseWheelEvent::Pixel { x: pos.x, y: pos.y }
- }
- MouseScrollDelta::LineDelta(x, y) => MouseWheelEvent::Line {
- x: x as f64,
- y: y as f64,
- },
- });
- }
- }
- _ => {}
- }
- }
-
- fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) {
- #[allow(unused_variables)]
- if let Some(window) = self.window.clone() {
- #[cfg(target_arch = "wasm32")]
- {
- let mut renderer_rxd = false;
- if let Some(rx) = self.renderer_rx.as_mut() {
- if let Ok(Some(renderer)) = rx.try_recv() {
- match renderer {
- Initialized(r) => {
- self.renderer = Some(r);
- renderer_rxd = true;
- }
- NotReadyYet(w, u, t, send, recv) => {
- let (tx, rx) = futures::channel::oneshot::channel();
- self.renderer_rx = Some(rx);
- wasm_bindgen_futures::spawn_local(async move {
- let renderer = Renderer::try_init(window.clone(), w, u, t, send, recv).await;
- tx.send(renderer).unwrap();
- });
- }
- }
- }
- }
- if renderer_rxd {
- self.renderer_rx = None;
- }
- }
-
- #[cfg(not(target_arch = "wasm32"))]
- {
- if self.renderer.is_none() {
- if let Some(window) = self.window.clone() {
- let world = self.world.take().unwrap();
- let update_schedule = self.update_schedule.take().unwrap();
- let ui_renderable = self.ui_renderable.take().unwrap();
- let send_packet_events = self.send_packet_events.take().unwrap();
- let recv_packet_events = self.recv_packet_events.take().unwrap();
-
- let renderer = pollster::block_on(async move {
- Renderer::try_init(window.clone(), world, update_schedule,
- ui_renderable, send_packet_events, recv_packet_events).await
- });
-
- match renderer {
- Initialized(r) => {
- self.renderer = Some(r);
- }
- NotReadyYet(w, u, t, send, recv) => {
- self.world = Some(w);
- self.update_schedule = Some(u);
- self.ui_renderable = Some(t);
- self.send_packet_events = Some(send);
- self.recv_packet_events = Some(recv);
- }
- }
-
- return;
- }
- }
- }
-
- let Some(renderer) = &mut self.renderer else {
- return;
- };
-
- renderer.render();
-
- event_loop.set_control_flow(ControlFlow::WaitUntil(
- Instant::now().add(Duration::from_secs_f64(1.0 / 60.0)),
- ));
- }
- }
-}
D crates/client/src/rendering/renderer.rs => crates/client/src/rendering/renderer.rs +0 -487
@@ 1,487 0,0 @@
-use crate::ecs::{Camera, RecvPacket, Rotation, Scale, SendPacket, Shear, SpriteTexture, Translation};
-use crate::networking::process_packets;
-use crate::networking::ws::Ws;
-use crate::rendering::assets::Assets;
-use crate::rendering::mipmap::MipGenerator;
-use crate::rendering::renderer::RenderInitRes::{Initialized, NotReadyYet};
-use crate::rendering::texture;
-use crate::rendering::ui::UiRenderable;
-use bevy_ecs::entity::Entity;
-use bevy_ecs::event::Events;
-use bevy_ecs::schedule::Schedule;
-use bevy_ecs::world::World;
-use egui::ViewportId;
-use starkingdoms_common::PlanetType;
-use std::collections::hash_map::Entry;
-use std::collections::{HashMap, HashSet};
-use std::fmt::{Debug, Formatter};
-use std::sync::Arc;
-use tracing::info;
-use web_time::Instant;
-use wgpu::{BlendState, SurfaceConfiguration};
-use wgpu::{
- include_wgsl, Adapter, Backends, BindGroupDescriptor, BindGroupEntry, BindingResource, Buffer,
- BufferDescriptor, BufferUsages, Color, ColorTargetState, CommandEncoderDescriptor, Device,
- DeviceDescriptor, Features, FragmentState, Instance, InstanceDescriptor, Limits, LoadOp,
- Operations, Queue, RenderPassColorAttachment, RenderPassDescriptor, RenderPipeline,
- RenderPipelineDescriptor, RequestAdapterOptions, ShaderModule, StoreOp, Surface,
- TextureViewDescriptor, VertexState,
-};
-use winit::dpi::{LogicalSize, PhysicalSize};
-use winit::window::Window;
-
-#[allow(unused_attributes, dead_code)]
-pub struct Renderer<T: UiRenderable> {
- pub last_frame_time: Instant,
-
- pub surface: Surface<'static>,
- pub surface_configuration: SurfaceConfiguration,
- pub device: Device,
- pub queue: Queue,
- pub adapter: Adapter,
-
- pub sprite_shader_module: ShaderModule,
- pub sprite_pipeline: RenderPipeline,
-
- pub world: World,
- pub update_schedule: Schedule,
- pub send_packet_events: Events<SendPacket>,
- pub recv_packet_events: Events<RecvPacket>,
-
- pub gui_ctx: egui::Context,
- pub gui_winit: egui_winit::State,
- pub gui_renderer: egui_wgpu::Renderer,
- pub gui_renderable: T,
-
- pub textures: HashMap<String, texture::Texture>,
- pub mip_generator: MipGenerator,
-
- pub frame_uniform: Buffer,
- pub local_uniform: Buffer,
- pub scale_factor: f64,
-
- pub window: Arc<Window>,
-
- pub size: PhysicalSize<u32>,
- pub logical_size: LogicalSize<u32>,
-
- pub planet_types: HashMap<PlanetType, (Entity, u32)>, // (world entity, server id)
-}
-
-#[allow(clippy::large_enum_variant)]
-pub enum RenderInitRes<T: UiRenderable> {
- Initialized(Renderer<T>),
- NotReadyYet(World, Schedule, T, Events<SendPacket>, Events<RecvPacket>),
-}
-impl<T: UiRenderable> Debug for RenderInitRes<T> {
- fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
- match self {
- Initialized(..) => write!(f, "[initialized renderer]"),
- NotReadyYet(..) => write!(f, "[pending initialization]"),
- }
- }
-}
-
-impl<T: UiRenderable> Renderer<T> {
- pub async fn try_init(
- window: Arc<Window>,
- world: World,
- update_schedule: Schedule,
- gui_renderable: T,
- send_packet_events: Events<SendPacket>,
- recv_packet_events: Events<RecvPacket>,
- ) -> RenderInitRes<T> {
- let size = window.inner_size();
- if size.width == 0 || size.height == 0 {
- return NotReadyYet(world, update_schedule, gui_renderable,
- send_packet_events, recv_packet_events);
- }
-
- // First, create an instance. This is our handle to wgpu, and is the equivalent of navigator.gpu in WebGPU
- let instance = Instance::new(InstanceDescriptor {
- backends: Backends::all(), // Select the appropriate backend for the HAL to use. Defined in the platform module, as it's platform-specific
- ..Default::default() // Other fields aren't relevant here
- });
-
- // Next, get our render surface
- let surface = instance.create_surface(window.clone()).unwrap();
-
- // Next, request out adapter
- let adapter = instance
- .request_adapter(&RequestAdapterOptions {
- power_preference: Default::default(), // Don't care
- force_fallback_adapter: false, // We want a real GPU
- compatible_surface: Some(&surface), // Find an adapter that is able to render to our window
- })
- .await
- .unwrap();
-
- let mut limits = Limits::downlevel_webgl2_defaults();
- limits.max_texture_dimension_1d = 8192;
- limits.max_texture_dimension_2d = 8192;
- limits.max_texture_dimension_3d = 2048;
- let (device, queue) = adapter
- .request_device(
- &DeviceDescriptor {
- label: Some("Basic render device"),
- required_features: Features::default(),
- required_limits: limits,
- memory_hints: Default::default(),
- },
- None,
- )
- .await
- .unwrap();
-
- let format = surface
- .get_default_config(&adapter, size.width, size.height)
- .unwrap();
-
- surface.configure(&device, &format);
-
- let sprite_shader_module =
- device.create_shader_module(include_wgsl!("../shaders/sprite.wgsl"));
- let sprite_pipeline = device.create_render_pipeline(&RenderPipelineDescriptor {
- label: Some("Sprite pipeline"),
- layout: None,
- vertex: VertexState {
- module: &sprite_shader_module,
- entry_point: Some("vs"),
- compilation_options: Default::default(),
- buffers: &[],
- },
- primitive: Default::default(),
- depth_stencil: None,
- multisample: Default::default(),
- fragment: Some(FragmentState {
- module: &sprite_shader_module,
- entry_point: Some("fs"),
- compilation_options: Default::default(),
- targets: &[Some(ColorTargetState {
- format: format.format,
- blend: Some(BlendState::PREMULTIPLIED_ALPHA_BLENDING),
- write_mask: Default::default(),
- })],
- }),
- multiview: None,
- cache: None,
- });
-
- let gui_context = egui::Context::default();
- let gui_winit = egui_winit::State::new(
- gui_context.clone(),
- ViewportId::ROOT,
- &window,
- Some(window.scale_factor() as f32),
- None,
- Some(device.limits().max_texture_dimension_2d as usize),
- );
- let gui_renderer = egui_wgpu::Renderer::new(&device, format.format, None, 1, false);
-
- let frame_uniform = device.create_buffer(&BufferDescriptor {
- label: Some("frame uniforms"),
- size: 48 + 16, // mat3x3f, vec2f
- usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
- mapped_at_creation: false,
- });
- let local_uniform = device.create_buffer(&BufferDescriptor {
- label: Some("local uniforms"),
- size: 48, // mat3x3f
- usage: BufferUsages::UNIFORM | BufferUsages::COPY_DST,
- mapped_at_creation: false,
- });
-
- Initialized(Self {
- mip_generator: MipGenerator::new(&device),
- textures: HashMap::new(),
- last_frame_time: Instant::now(),
- surface,
- device,
- queue,
- adapter,
- sprite_shader_module,
- sprite_pipeline,
- world,
- update_schedule,
- send_packet_events,
- recv_packet_events,
- gui_ctx: gui_context,
- gui_winit,
- gui_renderer,
- gui_renderable,
- logical_size: LogicalSize::from_physical(size, window.scale_factor()),
- scale_factor: window.scale_factor(),
- window,
- frame_uniform,
- local_uniform,
- size,
- surface_configuration: format,
- planet_types: HashMap::new(),
- })
- }
-
- pub fn render(&mut self) {
- let mut ws = self.world.get_resource_mut::<Ws>().expect("Failed to get Ws resource");
- #[cfg(target_arch = "wasm32")]
- while let Ok(Some(packet)) = ws.receiver.try_next() {
- self.recv_packet_events.send(RecvPacket(packet));
- }
- #[cfg(not(target_arch = "wasm32"))]
- for packet in ws.receiver.iter() {
- self.recv_packet_events.send(RecvPacket(packet));
- }
- // update the world
- self.update_schedule.run(&mut self.world);
- self.send_packet_events.update();
- self.recv_packet_events.update();
-
- process_packets(&mut self.world, &mut self.send_packet_events, &mut self.recv_packet_events, &mut self.planet_types);
- // update the UI
- let egui_output = self
- .gui_ctx
- .run(self.gui_winit.take_egui_input(&self.window), |ctx| {
- self.gui_renderable.render(ctx, &mut self.world)
- });
- self.gui_winit
- .handle_platform_output(&self.window, egui_output.platform_output);
-
- let output = self.surface.get_current_texture().unwrap();
- let view = output
- .texture
- .create_view(&TextureViewDescriptor::default());
-
- let render_pass_descriptor = RenderPassDescriptor {
- label: Some("basic render pass"),
- color_attachments: &[Some(RenderPassColorAttachment {
- view: &view,
- resolve_target: None,
- ops: Operations {
- load: LoadOp::Clear(Color {
- r: 0.3,
- g: 0.3,
- b: 0.3,
- a: 1.0,
- }),
- store: StoreOp::Store,
- },
- })],
- ..Default::default()
- };
- let mut encoder = self
- .device
- .create_command_encoder(&CommandEncoderDescriptor {
- label: Some("command encoder"),
- });
-
- let mut sprites_to_render: Vec<(Translation, Shear, Scale, SpriteTexture, Rotation)> = vec![];
-
- let mut things_to_render = self.world.query::<(&Translation, &Shear, &Scale, &SpriteTexture, &Rotation)>();
- for thing in things_to_render.iter_mut(&mut self.world) {
- sprites_to_render.push((*thing.0, *thing.1, *thing.2, thing.3.clone(), *thing.4));
- }
-
- let cam = self.world.resource::<Camera>();
-
- let x = -cam.x*cam.zoom + self.logical_size.width as f32/2.0;
- let y = -cam.y*cam.zoom + self.logical_size.height as f32/2.0;
-
- let mut frame_uniform = vec![];
- let frame_uniform_values = [
- cam.zoom, cam.shear_y,0.0, 0.0,
- cam.shear_x,cam.zoom, 0.0, 0.0,
- x, y, 1.0, 0.0,
- self.logical_size.width as f32, self.logical_size.height as f32, 0.0, 0.0];
- for i in frame_uniform_values {
- let mut bytes = i.to_ne_bytes().to_vec();
- frame_uniform.append(&mut bytes);
- }
-
- self.queue.write_buffer(&self.frame_uniform, 0, &frame_uniform);
-
- for (pos, shear, scale, sprite_tex, rot) in sprites_to_render {
- let tex = match self.textures.entry(sprite_tex.texture.clone()) {
- Entry::Occupied(entry) => entry.into_mut(),
- Entry::Vacant(entry) => {
- let assets = self.world.get_resource::<Assets>().unwrap();
- let b = match sprite_tex.texture.as_str() {
- "f" => match assets.get("f.png") {
- Some(b) => b,
- None => continue,
- }
- "happy-tree" => match assets.get("happy-tree.png") {
- Some(b) => b,
- None => continue,
- }
- "uv" => match assets.get("uv.png") {
- Some(b) => b,
- None => continue,
- }
- "hearty" => match assets.get("hearty.svg") {
- Some(b) => b,
- None => continue,
- }
- "sun" => match assets.get("sun.svg") {
- Some(b) => b,
- None => continue,
- }
- "mercury" => match assets.get("moon.svg") {
- Some(b) => b,
- None => continue,
- }
- "venus" => match assets.get("mars.svg") {
- Some(b) => b,
- None => continue,
- }
- "earth" => match assets.get("earth.svg") {
- Some(b) => b,
- None => continue,
- }
- "moon" => match assets.get("moon.svg") {
- Some(b) => b,
- None => continue,
- }
- "mars" => match assets.get("mars.svg") {
- Some(b) => b,
- None => continue,
- }
- "jupiter" => match assets.get("sun.svg") {
- Some(b) => b,
- None => continue,
- }
- "saturn" => match assets.get("moon.svg") {
- Some(b) => b,
- None => continue,
- }
- "uranus" => match assets.get("earth.svg") {
- Some(b) => b,
- None => continue,
- }
- "neptune" => match assets.get("moon.svg") {
- Some(b) => b,
- None => continue,
- }
- "pluto" => match assets.get("mars.svg") {
- Some(b) => b,
- None => continue,
- }
- u => panic!("unknown texture {u}, has it been added in rendering::renderer::<impl Renderer>::render()?")
- };
- entry.insert(texture::Texture::new(
- b,
- &sprite_tex.texture,
- &self.device,
- &self.queue,
- &mut self.mip_generator,
- ))
- }
- };
- tracing::info!("{} {:?} {:?}", sprite_tex.texture, pos, tex.texture);
- let xy_matrix = pos.as_matrix();
- let shear_matrix = shear.as_matrix();
- let rot_matrix = rot.as_matrix();
- let scale_matrix = scale.as_matrix();
-
- let transform_matrix = scale_matrix * shear_matrix * rot_matrix * xy_matrix;
-
-
- let mut local_buffer = vec![];
- let local_buffer_data = [
- transform_matrix.m11, transform_matrix.m12, transform_matrix.m13, 0.0,
- transform_matrix.m21, transform_matrix.m22, transform_matrix.m23, 0.0,
- transform_matrix.m31, transform_matrix.m32, transform_matrix.m33, 0.0,
- ];
- for i in local_buffer_data {
- let mut bytes = i.to_ne_bytes().to_vec();
- local_buffer.append(&mut bytes);
- }
-
- self.queue
- .write_buffer(&self.local_uniform, 0, &local_buffer);
-
- let bind_group = self.device.create_bind_group(&BindGroupDescriptor {
- label: Some("test_bind_group"),
- layout: &self.sprite_pipeline.get_bind_group_layout(0),
- entries: &[
- BindGroupEntry {
- binding: 0,
- resource: BindingResource::Sampler(&tex.sampler),
- },
- BindGroupEntry {
- binding: 1,
- resource: BindingResource::TextureView(
- &tex.texture.create_view(&TextureViewDescriptor::default()),
- ),
- },
- BindGroupEntry {
- binding: 2,
- resource: BindingResource::Buffer(
- self.frame_uniform.as_entire_buffer_binding(),
- ),
- },
- BindGroupEntry {
- binding: 3,
- resource: BindingResource::Buffer(
- self.local_uniform.as_entire_buffer_binding(),
- ),
- },
- ],
- });
- let mut pass = encoder.begin_render_pass(&render_pass_descriptor);
- pass.set_pipeline(&self.sprite_pipeline);
- pass.set_bind_group(0, Some(&bind_group), &[]);
- pass.draw(0..6, 0..1);
- }
- // main game rendering done
- // next up: egui UI rendering
- for (id, image_delta) in &egui_output.textures_delta.set {
- self.gui_renderer
- .update_texture(&self.device, &self.queue, *id, image_delta);
- }
- {
- let paint_jobs = self
- .gui_ctx
- .tessellate(egui_output.shapes, self.scale_factor as f32);
- let screen_descriptor = egui_wgpu::ScreenDescriptor {
- size_in_pixels: [self.size.width, self.size.height],
- pixels_per_point: self.scale_factor as f32,
- };
- self.gui_renderer.update_buffers(
- &self.device,
- &self.queue,
- &mut encoder,
- &paint_jobs,
- &screen_descriptor,
- );
- let render_pass = encoder.begin_render_pass(&RenderPassDescriptor {
- label: Some("ui render pass"),
- color_attachments: &[Some(RenderPassColorAttachment {
- view: &view,
- resolve_target: None,
- ops: Operations {
- load: LoadOp::Load,
- store: StoreOp::Store,
- },
- })],
- depth_stencil_attachment: None,
- timestamp_writes: None,
- occlusion_query_set: None,
- });
- let mut forgotten_render_pass = render_pass.forget_lifetime();
- self.gui_renderer
- .render(&mut forgotten_render_pass, &paint_jobs, &screen_descriptor);
- for id in egui_output.textures_delta.free {
- self.gui_renderer.free_texture(&id);
- }
- }
- let mut ws = self.world.get_resource_mut::<Ws>().expect("Failed to get Ws resource");
- let mut send_event_cursor = self.send_packet_events.get_cursor();
- for event in send_event_cursor.read(&self.send_packet_events) {
- ws.send_packet(event.0.clone());
- }
-
- let buffer = encoder.finish();
- self.queue.submit(std::iter::once(buffer));
-
- output.present();
- }
-}
D crates/client/src/rendering/texture.rs => crates/client/src/rendering/texture.rs +0 -76
@@ 1,76 0,0 @@
-use crate::rendering::mipmap::MipGenerator;
-use image::EncodableLayout;
-use wgpu::{
- Device, Extent3d, FilterMode, ImageCopyTexture, ImageDataLayout, Origin3d, Queue,
- SamplerDescriptor, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages,
-};
-
-use super::assets::ImgData;
-
-#[derive(Debug)]
-pub struct Texture {
- pub texture: wgpu::Texture,
- pub sampler: wgpu::Sampler,
-}
-impl Texture {
- pub fn new(
- rgba: ImgData,
- label: &str,
- device: &Device,
- queue: &Queue,
- mip_generator: &mut MipGenerator,
- ) -> Self {
- let max_size = rgba.width.max(rgba.height);
- let log_factor = if max_size == 0 { 0 } else { max_size.ilog2() };
- let optimal_mip_levels = 1 + log_factor;
-
- let texture = device.create_texture(&TextureDescriptor {
- label: Some(label),
- size: Extent3d {
- width: rgba.width,
- height: rgba.height,
- depth_or_array_layers: 1,
- },
- mip_level_count: optimal_mip_levels,
- sample_count: 1,
- dimension: TextureDimension::D2,
- format: TextureFormat::Rgba8UnormSrgb,
- usage: TextureUsages::TEXTURE_BINDING
- | TextureUsages::COPY_DST
- | TextureUsages::RENDER_ATTACHMENT,
- view_formats: &[TextureFormat::Rgba8UnormSrgb],
- });
- queue.write_texture(
- ImageCopyTexture {
- texture: &texture,
- mip_level: 0,
- origin: Origin3d::ZERO,
- aspect: Default::default(),
- },
- &rgba.bytes,
- ImageDataLayout {
- offset: 0,
- bytes_per_row: Some(rgba.width * 4),
- rows_per_image: Some(rgba.height),
- },
- Extent3d {
- width: rgba.width,
- height: rgba.height,
- depth_or_array_layers: 1,
- },
- );
-
- let sampler = device.create_sampler(&SamplerDescriptor {
- label: Some("test_sampler"),
- mag_filter: FilterMode::Linear,
- min_filter: FilterMode::Linear,
- ..Default::default()
- });
-
- let tex = Self { texture, sampler };
-
- //mip_generator.generate_mips(&tex, device, queue);
-
- tex
- }
-}
D crates/client/src/rendering/ui.rs => crates/client/src/rendering/ui.rs +0 -5
@@ 1,5 0,0 @@
-use bevy_ecs::world::World;
-
-pub trait UiRenderable {
- fn render(&mut self, ctx: &egui::Context, world: &mut World);
-}
D crates/client/src/shaders/sprite.wgsl => crates/client/src/shaders/sprite.wgsl +0 -56
@@ 1,56 0,0 @@
-struct VertexShaderOut {
- @builtin(position) position: vec4<f32>,
- @location(0) texcoord: vec2<f32>
-}
-
-struct FrameUniforms {
- camera_transform: mat3x3f,
- viewport_size: vec2f,
-}
-struct LocalUniforms {
- transform: mat3x3f,
-}
-@group(0) @binding(2) var<uniform> frame_uni: FrameUniforms;
-@group(0) @binding(3) var<uniform> local_uni: LocalUniforms;
-
-@vertex fn vs(
- @builtin(vertex_index) vertexIndex : u32
-) -> VertexShaderOut {
- let pos = array(
- vec2<f32>(-0.5, -0.5),
- vec2<f32>(0.5, -0.5),
- vec2<f32>(-0.5, 0.5),
- vec2<f32>(-0.5, 0.5),
- vec2<f32>(0.5, -0.5),
- vec2<f32>(0.5, 0.5)
- );
-
- var vsOutput: VertexShaderOut;
-
- let homogeneous_position = frame_uni.camera_transform * local_uni.transform * vec3f(pos[vertexIndex], 1);
- let position = homogeneous_position.xy / homogeneous_position.z;
- // convert from pixels to 0.0 to 1.0
- let zeroToOne = position / frame_uni.viewport_size;
- // convert from 0 - 1 to 0 - 2
- let zeroToTwo = zeroToOne * 2.0;
- // convert from 0 - 2 to -1 - +1 (clip space)
- let flippedClipSpace = zeroToTwo - 1.0;
- // flip Y
- let clipSpace = flippedClipSpace * vec2f(1, -1);
-
- vsOutput.position = vec4f(clipSpace, 0.0, 1.0);
- vsOutput.texcoord = pos[vertexIndex] + vec2f(0.5, 0.5);
-
- return vsOutput;
-}
-
-@group(0) @binding(0) var tex_sampler: sampler;
-@group(0) @binding(1) var tex: texture_2d<f32>;
-
-@fragment fn fs(fsInput: VertexShaderOut) -> @location(0) vec4<f32> {
- let texColor = textureSample(tex, tex_sampler, fsInput.texcoord);
- if (texColor.a < 0.1) {
- discard;
- }
- return texColor;
-}
D crates/client/src/shaders/text_quad_mips.wgsl => crates/client/src/shaders/text_quad_mips.wgsl +0 -26
@@ 1,26 0,0 @@
-struct VertexOutput {
- @builtin(position) position: vec4<f32>,
- @location(0) texcoord: vec2<f32>
-}
-@vertex fn vs(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
- let pos = array(
- vec2<f32>(0.0, 0.0),
- vec2<f32>(1.0, 0.0),
- vec2<f32>(0.0, 1.0),
- vec2<f32>(0.0, 1.0),
- vec2<f32>(1.0, 0.0),
- vec2<f32>(1.0, 1.0)
- );
- var out: VertexOutput;
- let xy = pos[vertexIndex];
- out.position = vec4<f32>(xy * 2.0 - 1.0, 0.0, 1.0);
- out.texcoord = vec2<f32>(xy.x, 1.0 - xy.y);
- return out;
-}
-
-@group(0) @binding(0) var texSampler: sampler;
-@group(0) @binding(1) var tex: texture_2d<f32>;
-
-@fragment fn fs(inp: VertexOutput) -> @location(0) vec4<f32> {
- return textureSample(tex, texSampler, inp.texcoord);
-}>
\ No newline at end of file