q 0.1.1

Q is a Rust GDExtension crate for Godot, offering a Game Manager, Music Manager, Bevy ECS, and Tokio-powered multi-threading. It simplifies and enhances game development with efficient tools and scalable performance.
Documentation
use crate::data::shader_data::ShaderCache;
use dashmap::DashMap;
use godot::classes::{AudioStream, CanvasLayer, Control, Texture2D};
use godot::prelude::*;
use std::sync::Arc;

pub struct ResourceCache<T: GodotClass> {
    map: DashMap<String, Gd<T>>,
}

impl<T: GodotClass> ResourceCache<T> {
    pub fn new() -> Self {
        Self {
            map: DashMap::new(),
        }
    }

    pub fn insert(&self, key: &str, object: Gd<T>) {
        self.map.insert(key.to_string(), object);
    }

    pub fn get(&self, key: &str) -> Option<Gd<T>> {
        self.map.get(&key.to_string()).map(|r| r.value().clone())
    }

    pub fn get_arc(&self, key: &str) -> Option<Arc<Gd<T>>> {
        self.map
            .get(&key.to_string())
            .map(|r| Arc::new(r.value().clone()))
    }

    pub fn contains(&self, key: &str) -> bool {
        self.map.contains_key(&key.to_string())
    }

    pub fn insert_upcast<U>(&self, key: &str, object: Gd<U>)
    where
        U: Inherits<T> + GodotClass,
    {
        self.insert(key, object.upcast::<T>());
    }

    pub fn get_as<U>(&self, key: &str) -> Option<Gd<U>>
    where
        U: Inherits<T> + GodotClass,
    {
        self.get(key)?.try_cast::<U>().ok()
    }

    pub fn remove(&self, key: &str) -> Option<Gd<T>> {
        self.map.remove(&key.to_string()).map(|(_, v)| v)
    }
}

#[derive(GodotClass)]
#[class(base = Node)]
pub struct CacheManager {
    base: Base<Node>,
    texture_cache: ResourceCache<Texture2D>,
    canvas_layer_cache: ResourceCache<CanvasLayer>,
    ui_cache: ResourceCache<Control>,
    audio_cache: ResourceCache<AudioStream>,
    shader_cache: Gd<ShaderCache>,
}

#[godot_api]
impl INode for CacheManager {
    fn init(base: Base<Self::Base>) -> Self {
        let shader_cache = Gd::from_init_fn(ShaderCache::init);

        Self {
            base,
            texture_cache: ResourceCache::new(),
            canvas_layer_cache: ResourceCache::new(),
            ui_cache: ResourceCache::new(),
            audio_cache: ResourceCache::new(),
            shader_cache,
        }
    }

    fn ready(&mut self) {
        let shader_cache = self.shader_cache.clone();

        {
            let mut base = self.base_mut();
            base.add_child(&shader_cache.upcast::<Node>());
        }
    }
}

#[godot_api]
impl CacheManager {
    fn internal_canvas_layer_cache(&self) -> &ResourceCache<CanvasLayer> {
        &self.canvas_layer_cache
    }

    fn internal_ui_cache(&self) -> &ResourceCache<Control> {
        &self.ui_cache
    }

    fn internal_texture_cache(&self) -> &ResourceCache<Texture2D> {
        &self.texture_cache
    }

    pub fn internal_audio_cache(&self) -> &ResourceCache<AudioStream> {
        &self.audio_cache
    }

    fn internal_shader_cache(&self) -> &Gd<ShaderCache> {
        &self.shader_cache
    }

    fn internal_shader_cache_as_node(&self) -> Gd<Node> {
        self.shader_cache.clone().upcast::<Node>()
    }

    pub fn insert_texture(&self, key: &str, texture: Gd<Texture2D>) {
        self.texture_cache.insert(key, texture);
    }

    #[func]
    fn get_from_canvas_layer_cache(&self, key: GString) -> Option<Gd<CanvasLayer>> {
        self.canvas_layer_cache.get(key.to_string().as_str())
    }

    #[func]
    fn get_from_ui_cache(&self, key: GString) -> Option<Gd<Control>> {
        self.ui_cache.get(key.to_string().as_str())
    }

    #[func]
    pub fn get_from_texture_cache(&self, key: GString) -> Option<Gd<Texture2D>> {
        self.texture_cache.get(key.to_string().as_str())
    }

    #[func]
    pub fn insert_into_texture_cache(&self, key: GString, texture: Gd<Texture2D>) {
        self.texture_cache.insert(key.to_string().as_str(), texture);
    }

    #[func]
    pub fn get_from_audio_cache(&self, key: GString) -> Option<Gd<AudioStream>> {
        self.audio_cache.get(key.to_string().as_str())
    }

    #[func]
    pub fn obtain_shader_cache(&self) -> Gd<ShaderCache> {
        self.shader_cache.clone()
    }
}