rafx-plugins 0.0.16

Rendering framework built on an extensible asset pipeline
Documentation
use crate::shaders::tile_layer::tile_layer_frag;
use fnv::FnvHashMap;
use glam::Vec3;
use hydrate_base::handle::Handle;
use hydrate_base::LoadHandle;
use rafx::api::RafxResult;
use rafx::assets::{
    AssetManager, BufferAsset, DefaultAssetTypeHandler, DefaultAssetTypeLoadHandler, ImageAsset,
    MaterialInstanceAsset,
};
use rafx::framework::{BufferResource, DescriptorSetArc, ResourceArc};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use type_uuid::*;

pub type LevelUid = i64;
pub type TileSetUid = i64;

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct LdtkLayerDrawCallData {
    pub vertex_data_offset_in_bytes: u32,
    pub index_data_offset_in_bytes: u32,
    pub index_count: u32,
    pub z_pos: f32,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct LdtkLayerData {
    pub material_instance: Handle<MaterialInstanceAsset>,
    pub draw_call_data: Vec<LdtkLayerDrawCallData>,
    pub z_pos: f32,
    pub world_x_pos: i64,
    pub world_y_pos: i64,
    pub grid_width: i64,
    pub grid_height: i64,
    pub grid_size: i64,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct LdtkLevelData {
    pub layer_data: Vec<LdtkLayerData>,
    pub vertex_data: Option<Handle<BufferAsset>>,
    pub index_data: Option<Handle<BufferAsset>>,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct LdtkTileSet {
    pub image: Handle<ImageAsset>,
    pub material_instance: Handle<MaterialInstanceAsset>,
    pub image_width: u32,
    pub image_height: u32,
}

#[derive(TypeUuid, Serialize, Deserialize, Clone, Debug)]
#[uuid = "1eb04266-4a32-473a-a54a-70b4d1172877"]
pub struct LdtkAssetData {
    pub tilesets: FnvHashMap<TileSetUid, LdtkTileSet>,
    pub levels: FnvHashMap<LevelUid, LdtkLevelData>,
}

#[derive(Clone, Debug)]
pub struct LdtkLayer {
    pub per_layer_descriptor_set: DescriptorSetArc,
    pub width: i64,
    pub height: i64,
    pub center: Vec3,
}

#[derive(Clone, Debug)]
pub struct LdtkLevel {
    pub layers: Vec<LdtkLayer>,
    pub vertex_buffer: Option<ResourceArc<BufferResource>>,
    pub index_buffer: Option<ResourceArc<BufferResource>>,
}

#[derive(Debug)]
pub struct LdtkProjectAssetInner {
    pub data: LdtkAssetData,
    pub levels: FnvHashMap<LevelUid, LdtkLevel>,
}

#[derive(TypeUuid, Clone, Debug)]
#[uuid = "231e4fd5-add2-4024-a479-d8181b3e52a3"]
pub struct LdtkProjectAsset {
    pub inner: Arc<LdtkProjectAssetInner>,
}

pub struct LdtkLoadHandler;

impl DefaultAssetTypeLoadHandler<LdtkAssetData, LdtkProjectAsset> for LdtkLoadHandler {
    #[profiling::function]
    fn load(
        asset_manager: &mut AssetManager,
        ldtk_asset: LdtkAssetData,
        _load_handle: LoadHandle,
    ) -> RafxResult<LdtkProjectAsset> {
        let mut levels = FnvHashMap::<LevelUid, LdtkLevel>::default();
        for (&level_uid, level_data) in &ldtk_asset.levels {
            let mut layers = Vec::default();
            for layer_data in &level_data.layer_data {
                let material_instance = asset_manager
                    .latest_asset(&layer_data.material_instance)
                    .unwrap();
                let _material_pass = material_instance
                    .material
                    .get_single_material_pass()
                    .expect("tileset material must have a single pass for opaque phase");
                let material_pass_index = 0;
                let tileset_image_set_index = tile_layer_frag::TEX_DESCRIPTOR_SET_INDEX;
                let descriptor_set = material_instance.material_descriptor_sets
                    [material_pass_index][tileset_image_set_index]
                    .clone()
                    .unwrap();

                let width = layer_data.grid_width * layer_data.grid_size;
                let height = layer_data.grid_height * layer_data.grid_size;
                layers.push(LdtkLayer {
                    per_layer_descriptor_set: descriptor_set,
                    center: Vec3::new(
                        (layer_data.world_x_pos + (width / 2)) as f32,
                        (layer_data.world_y_pos + (height / 2)) as f32,
                        layer_data.z_pos,
                    ),
                    width,
                    height,
                });
            }

            let mut vertex_buffer = None;
            let mut index_buffer = None;

            if let (Some(vertex_data_handle), Some(index_data_handle)) =
                (&level_data.vertex_data, &level_data.index_data)
            {
                vertex_buffer = Some(
                    asset_manager
                        .latest_asset(&vertex_data_handle)
                        .unwrap()
                        .buffer
                        .clone(),
                );
                index_buffer = Some(
                    asset_manager
                        .latest_asset(&index_data_handle)
                        .unwrap()
                        .buffer
                        .clone(),
                );
            }

            levels.insert(
                level_uid,
                LdtkLevel {
                    layers,
                    vertex_buffer,
                    index_buffer,
                },
            );
        }

        let inner = LdtkProjectAssetInner {
            data: ldtk_asset,
            levels,
        };

        Ok(LdtkProjectAsset {
            inner: Arc::new(inner),
        })
    }
}

pub type LdtkAssetType = DefaultAssetTypeHandler<LdtkAssetData, LdtkProjectAsset, LdtkLoadHandler>;