//! `Colorable` is a property to simply fill an area with a color use crate::prelude::*; use anyhow::Result; use utilities::prelude::*; use vulkan_rs::prelude::*; use cgmath::{vec4, Vector4}; use std::sync::atomic::{AtomicI32, Ordering::SeqCst}; use std::sync::{Arc, RwLock}; /// `Colorable` gives the ability to fill an area with a color pub struct Colorable { framable: Arc, descriptor_set: RwLock>, buffer: Arc>>, color: RwLock, ui_layer: AtomicI32, left_factor: RwLock, right_factor: RwLock, bottom_factor: RwLock, top_factor: RwLock, } impl Colorable { /// Factory method for `Colorable`, returns `Arc`. pub fn new(framable: Arc, color: Color) -> Result> { let set = framable.gui_handler().color_descriptor(color)?; let buffer = Buffer::builder() .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) .set_memory_usage(MemoryUsage::CpuOnly) .set_size(6) .build(framable.gui_handler().device().clone())?; let colorable = Arc::new(Colorable { framable, descriptor_set: RwLock::new(set), buffer, color: RwLock::new(color), ui_layer: AtomicI32::new(0), left_factor: RwLock::new(0.0), right_factor: RwLock::new(1.0), bottom_factor: RwLock::new(1.0), top_factor: RwLock::new(0.0), }); let colorable_clone = colorable.clone(); let weak_colorable = Arc::downgrade(&colorable); colorable.framable.add_callback( weak_colorable, Box::new(move || colorable_clone.update_frame()), ); Ok(colorable) } /// Add method /// /// # Arguments /// /// * `colorable` is a `&Arc` instance that is going to be added pub fn add(self: &Arc) -> Result<()> { self.framable .gui_handler() .add_colorable(self.ui_layer.load(SeqCst), self.clone()) } /// Delete method, has to be explicitly called, otherwise it will remain in memory. /// /// # Arguments /// /// * `colorable` is a `&Arc` instance that is going to be deleted pub fn delete(self: &Arc) -> Result<()> { self.framable .gui_handler() .delete_colorable(self.ui_layer.load(SeqCst), self) } pub fn clear_callback(self: &Arc) { let weak_colorable = Arc::downgrade(self); self.framable.remove_callback(weak_colorable); } pub fn set_ui_layer(&self, ui_layer: i32) { self.ui_layer.store(ui_layer, SeqCst); } /// Changes text color /// /// # Arguments /// /// * `color` defines the color pub fn set_color(&self, color: Color) -> Result<()> { let set = self.framable.gui_handler().color_descriptor(color)?; *self.color.write().unwrap() = color; *self.descriptor_set.write().unwrap() = set; Ok(()) } pub fn color(&self) -> Color { *self.color.read().unwrap() } /// Returns the internal vulkan buffer pub fn buffer(&self) -> &Arc>> { &self.buffer } /// Returns the internal vulkan descriptor set pub fn descriptor_set(&self) -> Arc { self.descriptor_set.read().unwrap().clone() } pub fn set_left_factor(&self, factor: f32) { *self.left_factor.write().unwrap() = factor; } pub fn set_right_factor(&self, factor: f32) { *self.right_factor.write().unwrap() = factor; } pub fn set_top_factor(&self, factor: f32) { *self.top_factor.write().unwrap() = factor; } pub fn set_bottom_factor(&self, factor: f32) { *self.bottom_factor.write().unwrap() = factor; } /// Update frame method if the original frame is invalidated pub fn update_frame(&self) -> Result<()> { let mut frame = self.buffer.map_complete()?; let x_start = self.framable.left() as f32; let y_start = self.framable.top() as f32; let width = (self.framable.right() - self.framable.left()) as f32; let height = (self.framable.bottom() - self.framable.top()) as f32; let left = x_start + width * *self.left_factor.read().unwrap(); let right = x_start + width * *self.right_factor.read().unwrap(); let top = y_start + height * *self.top_factor.read().unwrap(); let bottom = y_start + height * *self.bottom_factor.read().unwrap(); frame[0] = self.framable.ortho() * vec4(left, bottom, 0.0, 1.0); frame[1] = self.framable.ortho() * vec4(right, bottom, 0.0, 1.0); frame[2] = self.framable.ortho() * vec4(right, top, 0.0, 1.0); frame[3] = self.framable.ortho() * vec4(right, top, 0.0, 1.0); frame[4] = self.framable.ortho() * vec4(left, top, 0.0, 1.0); frame[5] = self.framable.ortho() * vec4(left, bottom, 0.0, 1.0); Ok(()) } pub(crate) fn vertex_input_state() -> ( Vec, Vec, ) { let input_bindings = vec![VkVertexInputBindingDescription { binding: 0, stride: std::mem::size_of::>() as u32, inputRate: VK_VERTEX_INPUT_RATE_VERTEX, }]; let input_attributes = vec![VkVertexInputAttributeDescription { location: 0, binding: 0, format: VK_FORMAT_R32G32B32A32_SFLOAT, offset: 0, }]; (input_bindings, input_attributes) } }