/* wearechat - generic multiplayer game with voip Copyright (C) 2025 metamuffin This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License only. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ use crate::{camera::Camera, download::Downloader, network::Network, renderer::Renderer}; use anyhow::{Context, Result}; use glam::{Vec2, Vec3}; use log::{info, warn}; use std::{net::TcpStream, time::Instant}; use weareshared::{store::ResourceStore, tree::SceneTree}; use winit::event::MouseButton; pub struct State<'a> { pub network: Network, pub downloader: Downloader, pub renderer: Renderer<'a>, pub tree: SceneTree, pub camera: Camera, pub delta: DeltaState, } pub struct DeltaState { time: Instant, pub move_dir: Vec3, pub mouse_acc: Vec2, pub cursor_pos: Vec2, } impl<'a> State<'a> { pub fn new(conn: TcpStream, window: &'a winit::window::Window) -> Result> { info!("new state"); Ok(Self { camera: Camera::new(), network: Network::new(conn), tree: SceneTree::default(), renderer: Renderer::new(window)?, downloader: Downloader::new(ResourceStore::new_memory()), delta: DeltaState { time: Instant::now(), move_dir: Vec3::ZERO, mouse_acc: Vec2::ZERO, cursor_pos: Vec2::ZERO, }, }) } pub fn draw(&mut self) { if let Err(e) = self.renderer.draw(&self.tree, &self.camera) { warn!("draw failed: {e:?}"); } } pub fn resize(&mut self, width: u32, height: u32) { self.renderer.resize(width, height); self.camera.aspect = width as f32 / height as f32; } pub fn click(&mut self, button: MouseButton, down: bool) { if !down || button != MouseButton::Right { return; } self.renderer .ui_renderer .add_surface(self.camera.new_ui_affine(), |ctx| { egui::Window::new("Funny window") .default_open(true) .show(ctx, |ui| { ui.label("world space ui actually kinda works now"); ui.label("Does input work?"); ui.button("Yes").clicked(); }); }); } pub fn update(&mut self) -> Result<()> { let now = Instant::now(); let dt = (now - self.delta.time).as_secs_f32(); self.delta.time = now; self.camera .update(self.delta.move_dir, self.delta.mouse_acc, dt); self.delta.mouse_acc = Vec2::ZERO; for p in self.network.packet_recv.try_iter() { self.downloader.packet(&p)?; self.tree.packet(&p); } self.downloader .update(&mut self.network) .context("downloader state")?; self.renderer .scene_prepare .update(&mut self.downloader) .context("scene preparation")?; Ok(()) } }