From f49be0b90db9b91d89d2662c73c100fa99be9a55 Mon Sep 17 00:00:00 2001 From: Arkitu <85173315+Arkitu@users.noreply.github.com> Date: Thu, 26 Dec 2024 12:46:03 +0100 Subject: [PATCH] make wasm work + cleaning + fix mouse --- .cargo/config.toml | 6 +- Cargo.lock | 68 -------- Cargo.toml | 24 +-- src/camera.rs | 5 + src/graphics.rs | 331 ------------------------------------ src/graphics/texture.rs | 80 --------- src/lib.rs | 127 +------------- src/map.rs | 4 +- src/shader.wgsl | 52 ------ src/state.rs | 368 ---------------------------------------- src/state/entity.rs | 221 ------------------------ src/state/ui.rs | 48 ------ 12 files changed, 20 insertions(+), 1314 deletions(-) delete mode 100644 src/graphics.rs delete mode 100644 src/graphics/texture.rs delete mode 100644 src/shader.wgsl delete mode 100644 src/state.rs delete mode 100644 src/state/entity.rs delete mode 100644 src/state/ui.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 70eacf3..c302a44 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,2 @@ [target.wasm32-unknown-unknown] -runner = "wasm-server-runner" - -# [target.aarch64-unknown-linux-gnu] -# linker = "clang" -# rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold"] \ No newline at end of file +runner = "wasm-server-runner" \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 460179f..4fccc48 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -196,24 +196,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "arboard" -version = "3.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" -dependencies = [ - "clipboard-win", - "core-graphics", - "image", - "log", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "parking_lot", - "windows-sys 0.48.0", - "x11rb", -] - [[package]] name = "arrayref" version = "0.3.8" @@ -655,7 +637,6 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "954fbe8551af4b40767ea9390ec7d32fe1070a6ab55d524cf0868c17f8469a55" dependencies = [ - "arboard", "bevy_app", "bevy_asset", "bevy_derive", @@ -676,7 +657,6 @@ dependencies = [ "encase", "js-sys", "log", - "thread_local", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -1605,15 +1585,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "clipboard-win" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" -dependencies = [ - "error-code", -] - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -2161,12 +2132,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "error-code" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" - [[package]] name = "euclid" version = "0.22.11" @@ -2832,7 +2797,6 @@ dependencies = [ "byteorder-lite", "num-traits", "png", - "tiff", ] [[package]] @@ -2936,12 +2900,6 @@ dependencies = [ "libc", ] -[[package]] -name = "jpeg-decoder" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" - [[package]] name = "js-sys" version = "0.3.76" @@ -4438,17 +4396,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - [[package]] name = "tiny-keccak" version = "2.0.2" @@ -5007,12 +4954,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "weezl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" - [[package]] name = "wgpu" version = "22.1.0" @@ -5427,15 +5368,6 @@ dependencies = [ "windows-targets 0.42.2", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 5fa05b3..1c7bdcf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,10 +17,6 @@ path = "src/lib.rs" name = "forestiles" [dependencies] -# bevy = { version = "0.15", default-features = false, features = [ -# "bevy_color","bevy_core_pipeline","bevy_render","bevy_winit","bevy_window","multi_threaded","wayland","bevy_sprite", -# "bevy_picking","bevy_mesh_picking_backend","bevy_ui_picking_backend","bevy_sprite_picking_backend" -# ]} bevy = { version = "0.15", default-features = false, features = [ "android-native-activity", "android_shared_stdcxx", @@ -57,20 +53,16 @@ bevy = { version = "0.15", default-features = false, features = [ "webgl2", "wayland", ]} -bevy-inspector-egui = { version = "0.28" } -# winit = { version = "0.30", features = ["rwh_05", "android-native-activity"] } -# env_logger = "0.11" +bevy-inspector-egui = { version = "0.28", default-features = false, features = [ + "bevy_pbr", + "bevy_image", + "bevy_render", + "egui_open_url" +]} log = "0.4" -# wgpu = "22.1" -# cfg-if = "1" -# pollster = "0.3" -# bytemuck = { version = "1.18", features = [ "derive" ] } rand = { version = "0.8", features = ["small_rng"] } -# nalgebra = "0.33" voronoice = "0.2" noise = "0.9" -# lazy_static = "1.5" -# image = { version = "0.25", default-features = false, features = ["rayon", "png"]} [target.'cfg(target_arch = "wasm32")'.dependencies] console_error_panic_hook = "0.1.6" @@ -99,9 +91,9 @@ opt-level = 3 [package.metadata.android] package = "org.forestiles.example" apk_name = "forestiles" -# strip = "strip" +strip = "strip" # see https://github.com/rust-mobile/cargo-apk -# assets = "assets" +assets = "assets" build_targets = ["aarch64-linux-android", "armv7-linux-androideabi"] [package.metadata.android.sdk] diff --git a/src/camera.rs b/src/camera.rs index c4449c8..d7a264c 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -49,6 +49,7 @@ fn move_cam( // movement.y += delta.y*cam.scale.y/pressed_num as f32; // pointers.0.insert(**id, *new_pos); // } + let old_midpoint = pressed_on_map.iter().fold(Vec2::ZERO, |acc, (_, _, old_pos, _, _)| { acc + (old_pos/pressed_on_map.len() as f32) }); @@ -70,4 +71,8 @@ fn move_cam( cam.scale.x /= zoom; cam.scale.y /= zoom; } + + for (_, new_pos, _, id, _) in ps { + pointers.0.insert(*id, new_pos); + } } \ No newline at end of file diff --git a/src/graphics.rs b/src/graphics.rs deleted file mode 100644 index 9d93e9f..0000000 --- a/src/graphics.rs +++ /dev/null @@ -1,331 +0,0 @@ -use std::sync::Arc; - -use bytemuck::{Pod, Zeroable}; -use wgpu::{include_wgsl, util::DeviceExt, BindGroup, Buffer, Device, Queue, RenderPipeline, Surface, SurfaceConfiguration, VertexBufferLayout}; -use winit::{event::WindowEvent, window::Window}; - -use crate::state::State; - -mod texture; -use texture::{Texture, TEXTURE_DIMENSIONS}; - -#[repr(C)] -#[derive(Clone, Copy, Zeroable, Pod, Debug)] -pub struct Vertex { - pub pos: [f32; 2], - /// Rgba color by default but if texture flag is not set. - /// Else the first 2 f32 are texture coordinates and the 2 last are not used - pub color: [f32; 4], - /// Each bit is used as a flag : - /// - /// 1: Scaled and moved according to camera - /// - /// 2: Grayscale - /// - /// 4: Texture instead of color - /// - /// For example 0b001 corresponds to Scaled and 0b011 to Scaled and Grayscale - pub effect: u32, -} -impl Vertex { - const DESC: VertexBufferLayout<'static> = VertexBufferLayout { - array_stride: std::mem::size_of::() as wgpu::BufferAddress, - step_mode: wgpu::VertexStepMode::Vertex, - attributes: &wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x4, 2 => Uint32], - }; - pub const fn new_col(pos: [f32; 2], color: [f32; 4], effect: u32) -> Self { - Self { - pos, - color, - effect - } - } - pub const fn new_tex(pos: [f32; 2], tex_pos: [u16; 2], effect: u32) -> Self { - Self { - pos, - color: [tex_pos[0] as f32/TEXTURE_DIMENSIONS[0] as f32, tex_pos[1] as f32/TEXTURE_DIMENSIONS[1] as f32, 0., 0.], - effect: effect | 0b100 - } - } -} - -#[repr(C)] -#[derive(Clone, Copy, Zeroable, Pod, Debug)] -pub struct Uniforms { - pub camera: [f32; 2], - pub zooms: [f32; 2] -} -impl Default for Uniforms { - fn default() -> Self { - Self { - camera: [0., 0.], - zooms: [1., 1.] - } - } -} - -pub struct Graphics<'a> { - // window: &'a Window, - pub surface_config: SurfaceConfiguration, - surface: Surface<'a>, - device: Device, - render_pipeline: RenderPipeline, - queue: Queue, - vertex_buf: Buffer, - index_buf: Buffer, - uniforms_buf: Buffer, - uniforms_bind_group: BindGroup, - diffuse_bind_group: BindGroup, -} -impl<'a> Graphics<'a> { - pub async fn init(state: &State, window: Arc) -> Self { - let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { - backends: wgpu::Backends::PRIMARY, - dx12_shader_compiler: Default::default(), - ..Default::default() - }); - - let surface = instance.create_surface(window).unwrap(); - let adapter = instance - .request_adapter(&wgpu::RequestAdapterOptions { - power_preference: wgpu::PowerPreference::default(), - force_fallback_adapter: false, - // Request an adapter which can render to our surface - compatible_surface: Some(&surface), - }) - .await - .expect("Failed to find an appropriate adapter"); - - // Create the logical device and command queue - let (device, queue) = adapter - .request_device( - &wgpu::DeviceDescriptor { - label: None, - required_features: wgpu::Features::empty(), - // Make sure we use the texture resolution limits from the adapter, so we can support images the size of the swapchain. - required_limits: wgpu::Limits::default() - .using_resolution(adapter.limits()), - memory_hints: wgpu::MemoryHints::MemoryUsage, - }, - None, - ) - .await - .expect("Failed to create device"); - - let vertex_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Vertex Buffer"), - contents: &[bytemuck::cast_slice::(&state.vertices), &[0; 100000]].concat(), - usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, - }); - - let index_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Index Buffer"), - contents: &[bytemuck::cast_slice::(&state.indices), &[0; 100000]].concat(), - usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST, - }); - - let uniforms_buf = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Uniforms Buffer"), - contents: bytemuck::cast_slice(&[state.uniforms]), - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, - }); - let uniforms_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::VERTEX, - ty: wgpu::BindingType::Buffer { - ty: wgpu::BufferBindingType::Uniform, - has_dynamic_offset: false, - min_binding_size: None, - }, - count: None, - } - ], - label: Some("Uniforms Bind Group Layout"), - }); - let uniforms_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &uniforms_bind_group_layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: uniforms_buf.as_entire_binding(), - } - ], - label: Some("Uniforms Bind Group"), - }); - let texture_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - entries: &[ - wgpu::BindGroupLayoutEntry { - binding: 0, - visibility: wgpu::ShaderStages::FRAGMENT, - ty: wgpu::BindingType::Texture { - multisampled: false, - view_dimension: wgpu::TextureViewDimension::D2, - sample_type: wgpu::TextureSampleType::Float { filterable: true }, - }, - count: None, - }, - wgpu::BindGroupLayoutEntry { - binding: 1, - visibility: wgpu::ShaderStages::FRAGMENT, - // This should match the filterable field of the - // corresponding Texture entry above. - ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering), - count: None, - }, - ], - label: Some("texture_bind_group_layout"), - }); - - // Load the shaders from disk - let shader = device.create_shader_module(include_wgsl!("shader.wgsl")); - - let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - label: None, - bind_group_layouts: &[ - &uniforms_bind_group_layout, - &texture_bind_group_layout - ], - push_constant_ranges: &[], - }); - - let swapchain_capabilities = surface.get_capabilities(&adapter); - let swapchain_format = swapchain_capabilities.formats[0]; - - let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { - label: None, - layout: Some(&pipeline_layout), - vertex: wgpu::VertexState { - module: &shader, - entry_point: "vs_main", - buffers: &[ - Vertex::DESC - ], - compilation_options: Default::default(), - }, - fragment: Some(wgpu::FragmentState { - module: &shader, - entry_point: "fs_main", - compilation_options: Default::default(), - targets: &[Some(wgpu::ColorTargetState { - format: swapchain_format, - blend: Some(wgpu::BlendState { - color: wgpu::BlendComponent { - src_factor: wgpu::BlendFactor::SrcAlpha, - dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha, - operation: wgpu::BlendOperation::Add - }, - alpha: wgpu::BlendComponent { - src_factor: wgpu::BlendFactor::One, - dst_factor: wgpu::BlendFactor::One, - operation: wgpu::BlendOperation::Add - } - }), - write_mask: wgpu::ColorWrites::ALL, - })], - }), - primitive: wgpu::PrimitiveState::default(), - depth_stencil: None, - multisample: wgpu::MultisampleState::default(), - multiview: None, - cache: None, - }); - - let surface_config = surface - .get_default_config(&adapter, 1, 1) - .unwrap(); - surface.configure(&device, &surface_config); - - let diffuse_bytes = include_bytes!("../assets/texture.png"); - let diffuse_texture = Texture::from_bytes(&device, &queue, diffuse_bytes, "happy-tree.png"); - let diffuse_bind_group = device.create_bind_group( - &wgpu::BindGroupDescriptor { - layout: &texture_bind_group_layout, - entries: &[ - wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::TextureView(&diffuse_texture.view), - }, - wgpu::BindGroupEntry { - binding: 1, - resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler), - } - ], - label: Some("diffuse_bind_group"), - } - ); - - Self { - // window, - surface_config, - surface, - device, - render_pipeline, - queue, - vertex_buf, - index_buf, - uniforms_buf, - uniforms_bind_group, - diffuse_bind_group - } - } - pub fn window_event(&mut self, event: &WindowEvent, window: &Window) { - match event { - WindowEvent::Resized(new_size) => { - // Reconfigure the surface with the new size - self.surface_config.width = new_size.width; - self.surface_config.height = new_size.height; - self.surface.configure(&self.device, &self.surface_config); - // On macos the window needs to be redrawn manually after resizing - window.request_redraw(); - }, - _ => {} - } - } - pub fn render(&self, state: &State) { - let frame = self.surface - .get_current_texture() - .expect("Failed to acquire next swap chain texture"); - let view = frame - .texture - .create_view(&wgpu::TextureViewDescriptor::default()); - let mut encoder = - self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: None, - }); - { - let mut rpass = - encoder.begin_render_pass(&wgpu::RenderPassDescriptor { - label: None, - color_attachments: &[Some(wgpu::RenderPassColorAttachment { - view: &view, - resolve_target: None, - ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color::BLACK), - store: wgpu::StoreOp::Store, - }, - })], - depth_stencil_attachment: None, - timestamp_writes: None, - occlusion_query_set: None, - }); - rpass.set_pipeline(&self.render_pipeline); - rpass.set_bind_group(0, &self.uniforms_bind_group, &[]); - rpass.set_bind_group(1, &self.diffuse_bind_group, &[]); - rpass.set_vertex_buffer(0, self.vertex_buf.slice(..)); - rpass.set_index_buffer(self.index_buf.slice(..), wgpu::IndexFormat::Uint32); - rpass.draw_indexed(0..state.indices.len() as u32, 0, 0..1); - // rpass.draw(0..self.state.vertices.len() as u32, 0..1); - } - - self.queue.submit(Some(encoder.finish())); - frame.present(); - } - pub fn update(&mut self, state: &State) { - self.queue.write_buffer(&self.vertex_buf, 0, bytemuck::cast_slice(&state.vertices)); - self.queue.write_buffer(&self.index_buf, 0, bytemuck::cast_slice(&state.indices)); - self.queue.write_buffer(&self.uniforms_buf, 0, bytemuck::cast_slice(&[state.uniforms])); - } -} - diff --git a/src/graphics/texture.rs b/src/graphics/texture.rs deleted file mode 100644 index 914c49a..0000000 --- a/src/graphics/texture.rs +++ /dev/null @@ -1,80 +0,0 @@ -use image::GenericImageView; - -pub const TEXTURE_DIMENSIONS: [usize; 2] = [64, 64]; - -pub struct Texture { - pub texture: wgpu::Texture, - pub view: wgpu::TextureView, - pub sampler: wgpu::Sampler, -} - -impl Texture { - pub fn from_bytes( - device: &wgpu::Device, - queue: &wgpu::Queue, - bytes: &[u8], - label: &str - ) -> Self { - let img = image::load_from_memory(bytes).unwrap(); - Self::from_image(device, queue, &img, Some(label)) - } - - pub fn from_image( - device: &wgpu::Device, - queue: &wgpu::Queue, - img: &image::DynamicImage, - label: Option<&str> - ) -> Self { - let rgba = img.to_rgba8(); - let dimensions = img.dimensions(); - - let size = wgpu::Extent3d { - width: dimensions.0, - height: dimensions.1, - depth_or_array_layers: 1, - }; - let texture = device.create_texture( - &wgpu::TextureDescriptor { - label, - size, - mip_level_count: 1, - sample_count: 1, - dimension: wgpu::TextureDimension::D2, - format: wgpu::TextureFormat::Rgba8UnormSrgb, - usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, - view_formats: &[], - } - ); - - queue.write_texture( - wgpu::ImageCopyTexture { - aspect: wgpu::TextureAspect::All, - texture: &texture, - mip_level: 0, - origin: wgpu::Origin3d::ZERO, - }, - &rgba, - wgpu::ImageDataLayout { - offset: 0, - bytes_per_row: Some(4 * dimensions.0), - rows_per_image: Some(dimensions.1), - }, - size, - ); - - let view = texture.create_view(&wgpu::TextureViewDescriptor::default()); - let sampler = device.create_sampler( - &wgpu::SamplerDescriptor { - address_mode_u: wgpu::AddressMode::ClampToEdge, - address_mode_v: wgpu::AddressMode::ClampToEdge, - address_mode_w: wgpu::AddressMode::ClampToEdge, - mag_filter: wgpu::FilterMode::Nearest, - min_filter: wgpu::FilterMode::Nearest, - mipmap_filter: wgpu::FilterMode::Nearest, - ..Default::default() - } - ); - - Self { texture, view, sampler } - } -} diff --git a/src/lib.rs b/src/lib.rs index beba4e4..cc7a1f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,109 +1,12 @@ -// mod graphics; -// mod state; +use bevy::{prelude::*, diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}}; +use bevy_inspector_egui::quick::WorldInspectorPlugin; + pub mod map; pub mod camera; pub mod ui; -use std::{fmt::Debug, sync::Arc}; - -use log::debug; -// use state::State; -// use graphics::Graphics; -// use winit::{application::ApplicationHandler, dpi::PhysicalSize, event::{Event, WindowEvent}, event_loop::EventLoop, window::{Window, WindowAttributes}}; -use bevy::{prelude::*, diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}}; -use bevy_inspector_egui::quick::WorldInspectorPlugin; - -pub fn dbg(v: V) -> V { - debug!(target: "app", "{:?}", v); - v -} - -// struct App<'a> { -// // event_loop: EventLoop<()>, -// window: Option>, -// graphics: Option>, -// state: State -// } -// impl App<'_> { -// fn new() -> Self { -// Self { -// window: None, -// graphics: None, -// state: State::new() -// } -// } -// } - -// impl ApplicationHandler for App<'_> { -// fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { -// #[cfg(not(any(target_family = "wasm", target_os = "android")))] -// let window = event_loop.create_window( -// WindowAttributes::default() -// .with_inner_size(PhysicalSize::new(1080*2/5, 2000*2/5)) -// ).unwrap(); -// #[cfg(target_os = "android")] -// let window = event_loop.create_window( -// WindowAttributes::default() -// // .with_inner_size(PhysicalSize::new(1080*2/5, 2000*2/5)) -// ).unwrap(); -// self.window = Some(Arc::new(window)); -// self.graphics = Some(pollster::block_on(Graphics::init(&self.state, self.window.clone().unwrap()))); -// } -// fn window_event( -// &mut self, -// event_loop: &winit::event_loop::ActiveEventLoop, -// window_id: winit::window::WindowId, -// event: WindowEvent, -// ) { -// match &event { -// WindowEvent::CloseRequested => event_loop.exit(), -// WindowEvent::RedrawRequested => { -// if let Some(g) = &mut self.graphics { -// self.state.update_if_needed(); -// self.state.render(self.window.as_ref().unwrap().inner_size()); -// g.update(&self.state); -// g.render(&self.state); -// } -// }, -// WindowEvent::MouseWheel { delta, .. } => { -// dbg!(delta); -// }, -// _ => {} -// } -// self.graphics.as_mut().unwrap().window_event(&event, &self.window.as_ref().unwrap()); -// self.state.window_event(&event, &self.window.as_ref().unwrap()); -// } -// fn about_to_wait(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { -// if let Some(window) = self.window.as_ref() { -// window.request_redraw(); -// } -// } -// } - -// #[cfg(not(target_os = "android"))] #[bevy_main] pub fn main() { - - // #[cfg(target_family = "wasm")] - // let (event_loop, window) = { - // use winit::platform::web::WindowExtWebSys; - // std::panic::set_hook(Box::new(console_error_panic_hook::hook)); - // console_log::init().expect("could not initialize logger"); - - // let event_loop = winit::event_loop::EventLoop::new().unwrap(); - // let window = winit::window::WindowBuilder::new().build(&event_loop).unwrap(); - - // web_sys::window() - // .unwrap() - // .document() - // .unwrap() - // .body() - // .unwrap() - // .append_child(&window.canvas().unwrap()) - // .unwrap(); - // (event_loop, window) - // }; - App::new() .add_plugins(( DefaultPlugins, @@ -118,26 +21,4 @@ pub fn main() { } )) .run(); -} - -// #[cfg(target_os = "android")] -// #[no_mangle] -// fn android_main(app: winit::platform::android::activity::AndroidApp) { -// println!("test"); -// // use winit::platform::android::{EventLoopBuilderExtAndroid, activity::WindowManagerFlags}; - -// // android_logger::init_once( -// // android_logger::Config::default() -// // .with_max_level(log::LevelFilter::Debug) -// // .with_filter(android_logger::FilterBuilder::new().parse("app").build()) -// // ); - -// // app.set_window_flags(WindowManagerFlags::KEEP_SCREEN_ON | WindowManagerFlags::FULLSCREEN, WindowManagerFlags::empty()); - -// // let event_loop = winit::event_loop::EventLoopBuilder::new() -// // .with_android_app(app) -// // .build() -// // .unwrap(); - -// // event_loop.run_app(&mut App::new()).unwrap(); -// } \ No newline at end of file +} \ No newline at end of file diff --git a/src/map.rs b/src/map.rs index 28040a7..b1d6db1 100644 --- a/src/map.rs +++ b/src/map.rs @@ -85,8 +85,8 @@ fn setup( let mut colors = Vec::new(); let mut indices = Vec::new(); - for (c, mut cd) in voronoi.iter_cells().zip(cells_data.iter_mut()).filter(|(_,cd)| cd.kind != CellKind::Forest) { - let mut color = cd.color(); + for (c, cd) in voronoi.iter_cells().zip(cells_data.iter_mut()).filter(|(_,cd)| cd.kind != CellKind::Forest) { + let color = cd.color(); // if c.site() == selected_tile { // color[0] = (color[0]+0.4).clamp(0., 1.); // color[1] = (color[1]+0.4).clamp(0., 1.); diff --git a/src/shader.wgsl b/src/shader.wgsl deleted file mode 100644 index 8b8253b..0000000 --- a/src/shader.wgsl +++ /dev/null @@ -1,52 +0,0 @@ -struct Uniforms { - camera: vec2f, - zooms: vec2f -} -@group(0) @binding(0) var uniforms : Uniforms; - -struct VertexOutput { - @location(0) color: vec4f, - @location(1) effect: u32, - @builtin(position) pos: vec4f -} - -@vertex -fn vs_main( - @location(0) pos: vec2f, - @location(1) color: vec4f, - @location(2) effect: u32 -) -> VertexOutput { - var screen_pos: vec4f; - if (effect & 1) == 0 { - screen_pos = vec4f(pos, 0, 1); - } else { - screen_pos = vec4f((pos - uniforms.camera) * uniforms.zooms, 0, 1); - } - var out = VertexOutput( - color, - effect, - screen_pos - ); - return out; -} - -@group(1) @binding(0) -var t_diffuse: texture_2d; -@group(1) @binding(1) -var s_diffuse: sampler; - -@fragment -fn fs_main(in: VertexOutput) -> @location(0) vec4f { - var color: vec4f; - if (in.effect & 4) == 0 { - color = in.color; - } else { - color = textureSample(t_diffuse, s_diffuse, in.color.xy); - } - // Grayscale - if (in.effect & 2) != 0 { - var v = (color.r*0.299) + (color.g*0.587) + (color.b*0.114); - color = vec4f(v, v, v, color.a); - } - return color; -} diff --git a/src/state.rs b/src/state.rs deleted file mode 100644 index 6a15be6..0000000 --- a/src/state.rs +++ /dev/null @@ -1,368 +0,0 @@ -use std::{collections::{BTreeMap, HashMap}, time::{Duration, Instant}}; -use log::{debug, trace}; -use map::{CellKind, Map}; -use rand::prelude::*; -use voronoice::Point; -use winit::{dpi::{PhysicalPosition, PhysicalSize}, event::{DeviceEvent, Event, KeyEvent, MouseButton, MouseScrollDelta, Touch as WTouch, TouchPhase, WindowEvent}, keyboard::{KeyCode, PhysicalKey}, window::Window}; - -use crate::{dbg, graphics::{Uniforms, Vertex}}; - -mod entity; -mod map; -mod ui; -use entity::{Entity, EntityKind, ExternOp}; -use ui::{Kind, UI}; - -fn rgba_to_grayscale(c: [f32; 4]) -> [f32; 4] { - let v = (c[0]*0.299) + (c[1]*0.587) + (c[2]*0.114); - [v, v, v, c[3]] -} - -struct Touch { - pub pos: PhysicalPosition, - /// id=1000 is for mouse - pub id: u64, - pub start: Instant -} -impl PartialEq for Touch { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } -} -impl From for Touch { - fn from(value: WTouch) -> Self { - Self::new(value.location, value.id) - } -} -impl Touch { - pub fn new(pos: PhysicalPosition, id: u64) -> Self { - Self { - pos, - id, - start: Instant::now() - } - } -} - -pub struct State { - pub vertices: Vec, - pub indices: Vec, - pub uniforms: Uniforms, - zoom: f32, - map: Map, - ui: UI, - start: Instant, - last_frame: Instant, - t: usize, // Time in frames - selected_tile: usize, - framerate: f32, // Update per second - pub entities: BTreeMap, // entity id --> Entities - next_eid: usize, - pub cells_entities: HashMap>, // cell id --> entities id - /// Also acount for mouse - touches: Vec, - mouse_pos: Option> -} -impl State { - pub fn new() -> Self { - let mut s = Self { - vertices: vec![], - indices: vec![], - uniforms: Uniforms::default(), - zoom: 1., - start: Instant::now(), - last_frame: Instant::now(), - t: 0, - map: Map::new(0, 0), - ui: UI::new(), - selected_tile: 0, - framerate: 1., - entities: BTreeMap::new(), - next_eid: 0, - cells_entities: HashMap::new(), - touches: Vec::new(), - mouse_pos: None - }; - // Create vertices / indices to estimate vertex / index buffer size - s.render(PhysicalSize::new(1, 1)); - s - } - fn set_zoom(&mut self, v: f32) { - self.zoom = v.clamp(1., 10.); - } - fn update_zooms(&mut self, screen_size: PhysicalSize) { - self.uniforms.zooms = [ - (screen_size.height as f32 / screen_size.width as f32).max(1.) * self.zoom, - (screen_size.width as f32 / screen_size.height as f32).max(1.) * self.zoom - ]; - } - fn handle_click(&mut self, window: &Window, pos: &PhysicalPosition) { - - } - pub fn window_event(&mut self, event: &WindowEvent, window: &Window) { - match event { - WindowEvent::Touch(touch) => { - match touch.phase { - TouchPhase::Started => { - self.touches.push((*touch).into()); - }, - TouchPhase::Moved => { - let w_size = window.inner_size(); - let old_touch_n = self.touches.iter().position(|t| t.id == touch.id).unwrap(); - let old_touch = &self.touches[old_touch_n]; - let t = [ - touch.location.x as f32/w_size.width as f32 * Map::WIDTH / self.uniforms.zooms[0], - touch.location.y as f32/w_size.height as f32 * Map::HEIGHT / self.uniforms.zooms[1] - ]; - let old_t = [ - old_touch.pos.x as f32/w_size.width as f32 * Map::WIDTH / self.uniforms.zooms[0], - old_touch.pos.y as f32/w_size.height as f32 * Map::HEIGHT / self.uniforms.zooms[1] - ]; - // Handle pinch zoom - if self.touches.len() == 2 { - let old_touch2 = &self.touches[if old_touch_n == 0 {1} else {0}]; - let old_t2 = [ - old_touch2.pos.x as f32/w_size.width as f32 * Map::WIDTH / self.uniforms.zooms[0], - old_touch2.pos.y as f32/w_size.height as f32 * Map::HEIGHT / self.uniforms.zooms[1] - ]; - self.set_zoom(self.zoom + (((((t[0]-old_t2[0])*self.zoom).powi(2)+((t[0]-old_t2[0])*self.zoom).powi(2)).sqrt() - (((old_t[0]-old_t2[0])*self.zoom).powi(2)+((old_t[0]-old_t2[0])*self.zoom).powi(2)).sqrt())*4.)); - } - self.uniforms.camera[0] -= (t[0] - old_t[0]) / self.touches.len() as f32; - self.uniforms.camera[1] += (t[1] - old_t[1]) / self.touches.len() as f32; - dbg(&self.uniforms.camera); - self.touches[old_touch_n].pos = touch.location; - }, - TouchPhase::Ended => { - let old_touch_n = self.touches.iter().position(|t| t.id == touch.id).unwrap(); - let old_touch = &self.touches[old_touch_n]; - if old_touch.start.elapsed() < Duration::from_millis(500) { - self.handle_click(window, &touch.location); - } - self.touches.remove(self.touches.iter().position(|t| t.id == touch.id).unwrap()); - }, - TouchPhase::Cancelled => { - self.touches.remove(self.touches.iter().position(|t| t.id == touch.id).unwrap()); - } - } - } - WindowEvent::MouseInput { state, button, ..} => { - if state.is_pressed() { - match button { - MouseButton::Left => { - if !self.touches.iter().any(|t| t.id == 1000) { - if let Some(pos) = self.mouse_pos { - self.touches.push(Touch::new(pos, 1000)); - } - } - }, - MouseButton::Right => { - self.spawn_entity(self.selected_tile, Entity::new(EntityKind::Horse, self.selected_tile)); - }, - _ => {} - }; - } else { - match button { - MouseButton::Left => { - if let Some(i) = self.touches.iter().position(|t| t.id == 1000) { - self.touches.remove(i); - } - }, - _ => {} - } - } - }, - WindowEvent::CursorLeft { .. } => { - self.mouse_pos = None; - if let Some(i) = self.touches.iter().position(|t| t.id == 1000) { - self.touches.remove(i); - } - }, - WindowEvent::CursorMoved { position, .. } => { - self.mouse_pos = Some(*position); - let w_size = window.inner_size(); - self.update_zooms(w_size); - let pos = Point { - x: (((position.x / w_size.width as f64)*2.)-1.)/(self.uniforms.zooms[0] as f64) + self.uniforms.camera[0] as f64, - y: -(((position.y / w_size.height as f64)*2.)-1.)/(self.uniforms.zooms[1] as f64) + self.uniforms.camera[1] as f64 - }; - let c = self.map.voronoi.cell(self.selected_tile); - if let Some(i) = self.touches.iter().position(|t| t.id == 1000) { - self.touches[i].pos = *position; - for i in c.iter_path(pos.clone()) { - self.selected_tile = i; - let cd = &mut self.map.cells_data[self.selected_tile]; - if let CellKind::Dirt = cd.kind { - cd.kind = CellKind::Forest; - } - } - } else { - self.selected_tile = c.iter_path(pos).last().unwrap(); - } - }, - WindowEvent::KeyboardInput { event: KeyEvent { physical_key: PhysicalKey::Code(kc), state, .. }, .. } => { - if state.is_pressed() { - match kc { - KeyCode::KeyW => { - self.uniforms.camera[1] += 0.1 * self.zoom; - }, - KeyCode::KeyS => { - self.uniforms.camera[1] -= 0.1 / self.zoom; - }, - KeyCode::KeyA => { - self.uniforms.camera[0] -= 0.1 / self.zoom; - }, - KeyCode::KeyD => { - self.uniforms.camera[0] += 0.1 / self.zoom; - }, - KeyCode::KeyR => { - self.set_zoom(self.zoom + 0.1); - }, - KeyCode::KeyF => { - self.set_zoom(self.zoom - 0.1); - }, - _ => {} - } - self.update_zooms(window.inner_size()); - } - }, - WindowEvent::MouseWheel { delta, .. } => { - self.framerate -= match delta { - MouseScrollDelta::PixelDelta(pos) => pos.y as f32, - MouseScrollDelta::LineDelta(_, y) => *y - } * 0.1; - self.framerate = self.framerate.max(0.); - } - _ => {} - } - } - pub fn render(&mut self, screen_size: PhysicalSize) { - trace!("render"); - self.update_zooms(screen_size); - self.vertices = Vec::new(); - self.indices = Vec::new(); - - for (c, cd) in self.map.voronoi.iter_cells().zip(self.map.cells_data.iter()).filter(|(_,cd)| cd.kind != CellKind::Forest) { - let mut color = cd.color(); - if c.site() == self.selected_tile { - color[0] = (color[0]+0.4).clamp(0., 1.); - color[1] = (color[1]+0.4).clamp(0., 1.); - color[2] = (color[2]+0.4).clamp(0., 1.); - } - let vs = c.iter_vertices().collect::>(); - let i = self.vertices.len() as u32; - for v in vs.iter() { - self.vertices.push(Vertex::new_col([v.x as f32, v.y as f32], color, 1)); - } - for v in 1..(vs.len()-1) as u32 { - self.indices.push(i); - self.indices.push(i+v); - self.indices.push(i+v+1); - } - } - - for e in self.entities.values() { - e.render(&mut self.vertices, &mut self.indices, &self.map, ); - } - - for (c, cd) in self.map.voronoi.iter_cells().zip(self.map.cells_data.iter()).filter(|(_,cd)| cd.kind == CellKind::Forest) { - let mut color = cd.color(); - if c.site() == self.selected_tile { - color[0] = (color[0]+0.4).clamp(0., 1.); - color[1] = (color[1]+0.4).clamp(0., 1.); - color[2] = (color[2]+0.4).clamp(0., 1.); - } - let vs = c.iter_vertices().collect::>(); - let i = self.vertices.len() as u32; - for v in vs.iter() { - self.vertices.push(Vertex::new_col([v.x as f32, v.y as f32], color, 1)); - } - for v in 1..(vs.len()-1) as u32 { - self.indices.push(i); - self.indices.push(i+v); - self.indices.push(i+v+1); - } - } - - self.ui.render(&mut self.vertices, &mut self.indices, screen_size); - } - pub fn update_if_needed(&mut self) { - while self.last_frame.elapsed().as_secs_f32() > 1. / self.framerate { - self.update(); - } - } - pub fn update(&mut self) { - trace!("update"); - - self.last_frame = Instant::now(); - let mut rng = thread_rng(); - let mut new_kind = Vec::new(); - for cd in self.map.cells_data.iter_mut() { - cd.update(); - } - for cd in self.map.cells_data.iter() { - if cd.kind == CellKind::Forest || cd.kind == CellKind::Grass { - let r = rng.gen::(); - if r < (0.035*cd.moisture) { - let c = self.map.voronoi.cell(cd.cid); - let n = c.iter_neighbors().choose(&mut rng).unwrap(); - let k = if r < (0.005*cd.moisture) && (self.map.cells_data[n].kind == CellKind::Dirt || self.map.cells_data[n].kind == CellKind::Grass) && cd.kind == CellKind::Forest { - Some(CellKind::Forest) - } else if self.map.cells_data[n].kind == CellKind::Dirt { - Some(CellKind::Grass) - } else { - None - }; - if let Some(k) = k { - new_kind.push((n, k)); - } - } - } - } - for (n, k) in new_kind { - let cd = &mut self.map.cells_data[n]; - cd.kind = k; - cd.resource = 1.; - } - - // if Option is None remove the entity - let mut entities_to_move: Vec<(usize, Option)> = Vec::new(); - for (eid, e) in self.entities.iter_mut() { - match e.update(&mut self.map, self.t, &mut rng) { - Some(ExternOp::Move(cid)) => { - entities_to_move.push((*eid, Some(cid))); - }, - Some(ExternOp::Remove) => { - entities_to_move.push((*eid, None)); - }, - None => {} - } - } - for (eid, new_cid) in entities_to_move { - let entity = self.entities.get_mut(&eid).unwrap(); - let cell_entities = self.cells_entities.get_mut(&entity.cid).unwrap(); - cell_entities.remove(cell_entities.iter().position(|e| *e == eid).unwrap()); - match new_cid { - Some(new_cid) => { - entity.cid = new_cid; - match self.cells_entities.get_mut(&new_cid) { - Some(v) => v.push(eid), - None => {self.cells_entities.insert(new_cid, vec![eid]);} - } - }, - None => {self.entities.remove(&eid);} - } - } - - self.t += 1; - } - pub fn spawn_entity(&mut self, cid: usize, e: Entity) { - let eid = self.next_eid; - self.next_eid += 1; - self.entities.insert(eid, e); - if let Some(v) = self.cells_entities.get_mut(&cid) { - v.push(eid); - } else { - self.cells_entities.insert(cid, vec![eid]); - } - } -} diff --git a/src/state/entity.rs b/src/state/entity.rs deleted file mode 100644 index b90ede5..0000000 --- a/src/state/entity.rs +++ /dev/null @@ -1,221 +0,0 @@ -use std::time::Instant; - -use rand::{rngs::ThreadRng, seq::IteratorRandom, Rng}; - -use crate::graphics::Vertex; - -use super::{map::CellKind, Map}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum EntityKind { - Horse -} -impl EntityKind { - const fn is_herbivore(&self) -> bool { - match self { - Self::Horse => true - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum EntityState { - Walking(Instant), // Start of walk - Resting -} - -#[derive(Debug)] -pub enum ExternOp { - Remove, - Move(usize) -} - -#[derive(Debug)] -pub struct Entity { - pub cid: usize, - kind: EntityKind, - start: Instant, - state: EntityState, - health: f32 // between 0 and 1 -} -impl Entity { - pub fn new(kind: EntityKind, cid: usize, ) -> Self { - Self { - cid, - kind, - start: Instant::now(), - state: EntityState::Walking(Instant::now()), - health: 1. - } - } - pub fn set_health(&mut self, val: f32) { - self.health = val.clamp(0., 1.); - } - pub fn render(&self, vertices: &mut Vec, indices: &mut Vec, map: &Map) { - let pos = &map.voronoi.sites()[self.cid]; - match self.kind { - EntityKind::Horse => { - let color = [171./255. * self.health, 122./255. * self.health, 50./255. * self.health, 1.]; - let dark = [color[0]-0.3, color[1]-0.3, color[2]-0.3, 1.]; - let (vs, is) = match self.state { - EntityState::Walking(now) => { - let now = now.elapsed().as_secs_f32()*5.; - ( - [ - // back left leg - Vertex::new_col([-0.5, 0.3], dark, 1), - Vertex::new_col([-0.4 + (now.sin()*0.1), -0.7 + (now.cos().max(-0.5)*0.1)], dark, 1), - Vertex::new_col([-0.25, 0.1], dark, 1), - - // back right leg - Vertex::new_col([-0.5, 0.3], color, 1), - Vertex::new_col([-0.4 + ((now + 1.).sin()*0.1), -0.7 + ((now + 1.).cos().max(-0.5)*0.1)], color, 1), - Vertex::new_col([-0.25, 0.1], color, 1), - - // front left leg - Vertex::new_col([0.3, 0.2], dark, 1), - Vertex::new_col([0.4 + ((now-1.).sin()*0.1), -0.7 + ((now-1.).cos().max(-0.5)*0.1)], dark, 1), - Vertex::new_col([0.5, 0.3], dark, 1), - - // front right leg - Vertex::new_col([0.3, 0.2], color, 1), - Vertex::new_col([0.4 + ((now-2.).sin()*0.1), -0.7 + ((now-2.).cos().max(-0.5)*0.1)], color, 1), - Vertex::new_col([0.5, 0.3], color, 1), - - // body - // 3 - Vertex::new_col([-0.3, 0.], color, 1), - Vertex::new_col([0.4, -0.1], color, 1), - // 11 - Vertex::new_col([0.3, 0.4], color, 1), - ], - [ - 0,1,2, - 3,4,5, - 6,7,8, - 9,10,11, - 3,12,13, - 3,13,11, - 3,11,14 - ] - ) - }, - EntityState::Resting => { - ( - [ - // back left leg - Vertex::new_col([-0.5, 0.3], dark, 1), - Vertex::new_col([-0.4, -0.75], dark, 1), - Vertex::new_col([-0.25, 0.1], dark, 1), - - // back right leg - Vertex::new_col([-0.5, 0.3], color, 1), - Vertex::new_col([-0.4, -0.75], color, 1), - Vertex::new_col([-0.25, 0.1], color, 1), - - // front left leg - Vertex::new_col([0.3, 0.2], dark, 1), - Vertex::new_col([0.4, -0.75], dark, 1), - Vertex::new_col([0.5, 0.3], dark, 1), - - // front right leg - Vertex::new_col([0.3, 0.2], color, 1), - Vertex::new_col([0.4, -0.75], color, 1), - Vertex::new_col([0.5, 0.3], color, 1), - - // body - // 3 - Vertex::new_col([-0.3, 0.], color, 1), - Vertex::new_col([0.4, -0.1], color, 1), - // 11 - Vertex::new_col([0.3, 0.4], color, 1), - ], - [ - 0,1,2, - 3,4,5, - 6,7,8, - 9,10,11, - 3,12,13, - 3,13,11, - 3,11,14 - ] - ) - } - }; - - vertices.reserve(vs.len()); - let base = vertices.len() as u32; - for mut v in vs { - v.pos[0] = v.pos[0]/50. + pos.x as f32; - v.pos[1] = (v.pos[1] + 0.75)/50. + pos.y as f32; - vertices.push(v) - } - - indices.reserve(is.len()); - for i in is { - indices.push(base + i); - } - } - } - } - /// Returns new cell if entity moves - pub fn update(&mut self, map: &mut Map, t: usize, rng: &mut ThreadRng) -> Option { - // Let’s take 0.57 kg of grass / m2 - // Let’s take 7.5 kg of food / day for a horse - // Let’s say that a horse can survive up to 20 days without food - let cd = &mut map.cells_data[self.cid]; - if self.kind.is_herbivore() { - let food_needed: f32 = match self.kind { - EntityKind::Horse => 7.5 / (0.57 * Map::CELL_AREA) - }; // in cell resource fraction - match cd.kind { - CellKind::Forest => {}, // Infinite food in forests - CellKind::Grass => { - let food_eaten = food_needed.min(cd.resource); - self.set_health(self.health - ((((food_needed - food_eaten)/food_needed)-0.5)/20.)); - cd.set_resource(cd.resource-food_eaten, t); - }, - _ => { - self.set_health(self.health - 1./20.); - } - } - } - - if self.health == 0. { - return Some(ExternOp::Remove); - } - - let r = cd.resource; - if cd.kind != CellKind::Grass { - map.voronoi.cell(cd.cid).iter_neighbors().filter(|n| { - let cd = &map.cells_data[*n]; - cd.kind == CellKind::Grass - }).choose(rng).map(|c| ExternOp::Move(c)) - } else if r < 0.5 { - let cd = &map.cells_data[self.cid]; - Some(ExternOp::Move( - map.voronoi.cell(cd.cid) - .iter_neighbors() - .filter(|n| map.cells_data[*n].kind == CellKind::Grass) - .fold(cd, |acc, c| { - let cd = &map.cells_data[c]; - if acc.kind != CellKind::Grass { - cd - } else if cd.kind != CellKind::Grass { - acc - } else if acc.resource > cd.resource { - acc - } else if acc.resource < cd.resource { - cd - } else if rng.gen_bool(0.5) { - cd - } else { - acc - } - }).cid - )) - } else { - None - } - } -} diff --git a/src/state/ui.rs b/src/state/ui.rs deleted file mode 100644 index 4537163..0000000 --- a/src/state/ui.rs +++ /dev/null @@ -1,48 +0,0 @@ -use winit::{dpi::PhysicalSize, event::{Touch, TouchPhase, WindowEvent}}; -use crate::graphics::Vertex; - -const SECONDARY_COLOR: [f32; 4] = [84./255., 33./255., 32./255., 1.]; -const KIND_BUTTON_SIZE: f32 = 0.2; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Kind { - None, - Terrain, - Entities -} - -pub struct UI { - pub kind_selected: Kind -} -impl UI { - pub fn new() -> Self { - Self { - kind_selected: Kind::Entities - } - } - pub fn render(&self, vertices: &mut Vec, indices: &mut Vec, screen_size: PhysicalSize) { - let ratio = screen_size.height as f32/screen_size.width as f32; - let vs = [ - // Terrain - Vertex::new_tex([-1. + (0.02*ratio), -1. + (0.02+KIND_BUTTON_SIZE)], [0, 1], 0), - Vertex::new_tex([-1. + (0.02*ratio), -1. + 0.02], [0, 13], 0), - Vertex::new_tex([-1. + ((0.02+KIND_BUTTON_SIZE)*ratio), -1. + 0.02], [12, 13], 0), - Vertex::new_tex([-1. + ((0.02+KIND_BUTTON_SIZE)*ratio), -1. + (0.02+KIND_BUTTON_SIZE)], [12, 1], 0), - - // Entities - Vertex::new_tex([-1. + ((0.02+KIND_BUTTON_SIZE)*ratio)+(0.02*ratio), -1. + (0.02+KIND_BUTTON_SIZE)], [12, 1], 0), - Vertex::new_tex([-1. + ((0.02+KIND_BUTTON_SIZE)*ratio)+(0.02*ratio), -1. + 0.02], [12, 13], 0), - Vertex::new_tex([-1. + ((0.02+KIND_BUTTON_SIZE)*ratio)+((0.02+KIND_BUTTON_SIZE)*ratio), -1. + 0.02], [24, 13], 0), - Vertex::new_tex([-1. + ((0.02+KIND_BUTTON_SIZE)*ratio)+((0.02+KIND_BUTTON_SIZE)*ratio), -1. + (0.02+KIND_BUTTON_SIZE)], [24, 1], 0), - ]; - let ids = [ - 0,1,2, - 2,3,0, - 4,5,6, - 6,7,4 - ]; - let i = vertices.len() as u32; - vertices.extend_from_slice(&vs); - indices.extend_from_slice(&ids.map(|id| id+i)); - } -}