sailor 0.1.0

A sailing navigation application.
use std::sync::{
    Arc,
    RwLock,
};

use wgpu::*;

use crate::*;

pub struct VisibleTile {
    tile: Arc<RwLock<Tile>>,
    gpu_tile: Arc<RwLock<Option<LoadedGPUTile>>>,
    tile_collider: Arc<RwLock<TileCollider>>,
}

impl VisibleTile {
    pub fn new(tile: Arc<RwLock<Tile>>) -> Self {
        Self {
            tile: tile,
            gpu_tile: Arc::new(RwLock::new(None)),
            tile_collider: Arc::new(RwLock::new(TileCollider::new())),
        }
    }

    pub fn tile_id(&self) -> TileId {
        self.tile.read().unwrap().tile_id()
    }

    pub fn extent(&self) -> u16 {
        self.tile.read().unwrap().extent()
    }
    
    pub fn load_to_gpu(&self, device: &Device) {
        let read_tile = self.tile.read().unwrap();
        let mut write_gpu_tile = self.gpu_tile.write().unwrap();
        *write_gpu_tile = Some(LoadedGPUTile::load(device, &read_tile));
    }

    pub fn unload_from_gpu(&self) {
        let mut write_gpu_tile = self.gpu_tile.write().unwrap();
        *write_gpu_tile = None;
    }

    pub fn is_loaded_to_gpu(&self) -> bool {
        self.gpu_tile.read().unwrap().is_some()
    }

    pub fn load_collider(&mut self) {
        self.tile_collider.load(self.tile.clone());
    }

    pub fn paint(
        &self,
        render_pass: &mut RenderPass,
        blend_pipeline: &RenderPipeline,
        feature_collection: &FeatureCollection,
        tile_id: u32
    ) {
        if let Some(data) = self.gpu_tile.try_read().unwrap().as_ref() {
            render_pass.set_index_buffer(&data.index_buffer, 0);
            render_pass.set_vertex_buffers(0, &[(&data.vertex_buffer, 0)]);

            let features = {
                let read_tile = self.tile.read().unwrap();
                let mut features = read_tile.features().clone();
                features.sort_by(|a, b| {
                    feature_collection
                        .get_zindex(a.0)
                        .partial_cmp(&feature_collection.get_zindex(b.0)).unwrap()
                });
                features
            };

            let mut i = 0;
            render_pass.set_pipeline(blend_pipeline);
            for (id, range) in &features {
                if range.len() > 0 && feature_collection.is_visible(*id) {
                    render_pass.set_stencil_reference(i as u32);
                    i += 1;

                    let range_start = (tile_id << 1) | 1;
                    render_pass.draw_indexed(range.clone(), 0, 0 + range_start .. 1 + range_start);

                    if feature_collection.has_outline(*id) {
                        let range_start = tile_id << 1;
                        render_pass.draw_indexed(range.clone(), 0, 0 + range_start .. 1 + range_start);
                    }
                }
            }
        }
    }
}