2023-01-16 09:53:52 +00:00
|
|
|
//! `Displayable` is a property to display a background texture
|
|
|
|
|
|
|
|
use crate::prelude::*;
|
|
|
|
use anyhow::Result;
|
|
|
|
use assetpath::AssetPath;
|
2023-01-16 11:58:59 +00:00
|
|
|
use utilities::prelude::*;
|
|
|
|
use vulkan_rs::prelude::*;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
use cgmath::{vec2, vec4};
|
|
|
|
|
|
|
|
use super::texturedvertex::TexturedVertex;
|
|
|
|
|
|
|
|
use std::sync::{
|
|
|
|
atomic::{AtomicI32, Ordering::SeqCst},
|
|
|
|
{Arc, RwLock},
|
|
|
|
};
|
|
|
|
|
2024-03-25 11:33:56 +00:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum DisplayableType {
|
|
|
|
Path(AssetPath),
|
|
|
|
Descriptor(ElementDescriptor),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<AssetPath> for DisplayableType {
|
|
|
|
fn from(value: AssetPath) -> Self {
|
|
|
|
Self::Path(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ElementDescriptor> for DisplayableType {
|
|
|
|
fn from(value: ElementDescriptor) -> Self {
|
|
|
|
Self::Descriptor(value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-16 09:53:52 +00:00
|
|
|
/// `Displayable` gives the ability to display a texture as background image for an item
|
|
|
|
pub struct Displayable {
|
|
|
|
framable: Arc<Framable>,
|
|
|
|
|
2024-03-25 11:33:56 +00:00
|
|
|
descriptor_set: Arc<DescriptorSet>,
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
buffer: Arc<Buffer<TexturedVertex>>,
|
|
|
|
|
2024-03-25 11:33:56 +00:00
|
|
|
displayable_type: RwLock<DisplayableType>,
|
2023-01-19 12:05:48 +00:00
|
|
|
|
2023-01-16 09:53:52 +00:00
|
|
|
ui_layer: AtomicI32,
|
|
|
|
|
|
|
|
left_factor: RwLock<f32>,
|
|
|
|
right_factor: RwLock<f32>,
|
|
|
|
bottom_factor: RwLock<f32>,
|
|
|
|
top_factor: RwLock<f32>,
|
|
|
|
|
|
|
|
left_uv_factor: RwLock<f32>,
|
|
|
|
right_uv_factor: RwLock<f32>,
|
|
|
|
bottom_uv_factor: RwLock<f32>,
|
|
|
|
top_uv_factor: RwLock<f32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Displayable {
|
|
|
|
/// Factory method for `Displayable`, returns `Arc<Displayable>`
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
///
|
|
|
|
/// * `framable` is a `Arc<Framable>` instance
|
|
|
|
/// * `name` is the name for a png
|
2024-03-25 11:33:56 +00:00
|
|
|
pub fn new(
|
|
|
|
framable: Arc<Framable>,
|
|
|
|
displayable_type: impl Into<DisplayableType>,
|
|
|
|
) -> Result<Arc<Self>> {
|
|
|
|
let descriptor_set = framable.gui_handler().image_descriptor_set()?;
|
|
|
|
|
|
|
|
let displayable_type = displayable_type.into();
|
|
|
|
|
|
|
|
if let DisplayableType::Path(path) = &displayable_type {
|
|
|
|
let texture = framable
|
|
|
|
.gui_handler()
|
|
|
|
.displayable_image_from_path(path.clone())?;
|
|
|
|
descriptor_set.update(&[DescriptorWrite::combined_samplers(0, &[&texture])])?;
|
|
|
|
}
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
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 displayable = Arc::new(Displayable {
|
|
|
|
framable,
|
2024-03-25 11:33:56 +00:00
|
|
|
descriptor_set,
|
2023-01-16 09:53:52 +00:00
|
|
|
buffer,
|
|
|
|
|
2024-03-25 11:33:56 +00:00
|
|
|
displayable_type: RwLock::new(displayable_type),
|
2023-01-19 12:05:48 +00:00
|
|
|
|
2023-01-16 09:53:52 +00:00
|
|
|
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),
|
|
|
|
|
|
|
|
left_uv_factor: RwLock::new(0.0),
|
|
|
|
right_uv_factor: RwLock::new(1.0),
|
|
|
|
bottom_uv_factor: RwLock::new(1.0),
|
|
|
|
top_uv_factor: RwLock::new(0.0),
|
|
|
|
});
|
|
|
|
|
|
|
|
let displayable_clone = displayable.clone();
|
|
|
|
let weak_displayable = Arc::downgrade(&displayable);
|
|
|
|
|
|
|
|
displayable.framable.add_callback(
|
|
|
|
weak_displayable,
|
|
|
|
Box::new(move || displayable_clone.update_frame()),
|
|
|
|
);
|
|
|
|
|
|
|
|
Ok(displayable)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add method
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
///
|
|
|
|
/// * `displayable` is a `&Arc<Displayable>` instance that is going to be added
|
|
|
|
pub fn add(self: &Arc<Self>) -> Result<()> {
|
|
|
|
self.framable
|
|
|
|
.gui_handler()
|
|
|
|
.add_displayable(self.ui_layer.load(SeqCst), self.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Delete method, has to be explicitly called, otherwise it will remain in memory
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
///
|
|
|
|
/// * `displayable` is a `&Arc<Displayable>` instance that is going to be deleted
|
|
|
|
pub fn delete(self: &Arc<Self>) -> Result<()> {
|
|
|
|
self.framable
|
|
|
|
.gui_handler()
|
|
|
|
.delete_displayable(self.ui_layer.load(SeqCst), self)
|
|
|
|
}
|
|
|
|
|
2024-03-25 11:33:56 +00:00
|
|
|
pub fn inner_type(&self) -> DisplayableType {
|
|
|
|
self.displayable_type.read().unwrap().clone()
|
2023-01-19 12:05:48 +00:00
|
|
|
}
|
|
|
|
|
2023-01-16 09:53:52 +00:00
|
|
|
pub fn set_ui_layer(&self, ui_layer: i32) {
|
|
|
|
self.ui_layer.store(ui_layer, SeqCst);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clear_callback(self: &Arc<Self>) {
|
|
|
|
let weak_displayable = Arc::downgrade(self);
|
|
|
|
self.framable.remove_callback(weak_displayable);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Replaces the current background image
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
///
|
|
|
|
/// * `name` is the name of the texture in `gui/` without `.png` suffix
|
2024-03-25 11:33:56 +00:00
|
|
|
pub fn set_image(&self, displayable_type: impl Into<DisplayableType>) -> Result<()> {
|
|
|
|
let displayable_type = displayable_type.into();
|
|
|
|
|
|
|
|
let texture = match displayable_type.clone() {
|
|
|
|
DisplayableType::Path(path) => Some(
|
|
|
|
self.framable
|
|
|
|
.gui_handler()
|
|
|
|
.displayable_image_from_path(path)?,
|
|
|
|
),
|
|
|
|
DisplayableType::Descriptor(descriptor) => {
|
|
|
|
let width = (self.framable.right() - self.framable.left()) as u32;
|
|
|
|
let height = (self.framable.bottom() - self.framable.top()) as u32;
|
|
|
|
|
|
|
|
if width > 0 && height > 0 {
|
|
|
|
Some(
|
|
|
|
self.framable
|
|
|
|
.gui_handler()
|
|
|
|
.displayable_image_from_descriptor(width, height, descriptor)?,
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if let Some(texture) = texture {
|
|
|
|
self.descriptor_set
|
|
|
|
.update(&[DescriptorWrite::combined_samplers(0, &[&texture])])?;
|
|
|
|
}
|
|
|
|
|
|
|
|
*self.displayable_type.write().unwrap() = displayable_type;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the internal vulkan buffer
|
|
|
|
pub fn buffer(&self) -> &Arc<Buffer<TexturedVertex>> {
|
|
|
|
&self.buffer
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the internal vulkan descriptor set
|
|
|
|
pub fn descriptor_set(&self) -> Arc<DescriptorSet> {
|
2024-03-25 11:33:56 +00:00
|
|
|
self.descriptor_set.clone()
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_left_uv_factor(&self, factor: f32) {
|
|
|
|
*self.left_uv_factor.write().unwrap() = factor;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_right_uv_factor(&self, factor: f32) {
|
|
|
|
*self.right_uv_factor.write().unwrap() = factor;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_top_uv_factor(&self, factor: f32) {
|
|
|
|
*self.top_uv_factor.write().unwrap() = factor;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_bottom_uv_factor(&self, factor: f32) {
|
|
|
|
*self.bottom_uv_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;
|
|
|
|
|
2024-03-25 14:31:04 +00:00
|
|
|
if let DisplayableType::Descriptor(descriptor) = &*self.displayable_type.read().unwrap() {
|
|
|
|
if width > 0.0 && height > 0.0 {
|
|
|
|
let texture = self
|
|
|
|
.framable
|
|
|
|
.gui_handler()
|
|
|
|
.displayable_image_from_descriptor(
|
|
|
|
width as u32,
|
|
|
|
height as u32,
|
|
|
|
descriptor.clone(),
|
|
|
|
)?;
|
|
|
|
|
|
|
|
self.descriptor_set
|
|
|
|
.update(&[DescriptorWrite::combined_samplers(0, &[&texture])])?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-16 09:53:52 +00:00
|
|
|
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].position = self.framable.ortho() * vec4(left, bottom, 0.0, 1.0);
|
|
|
|
frame[1].position = self.framable.ortho() * vec4(right, bottom, 0.0, 1.0);
|
|
|
|
frame[2].position = self.framable.ortho() * vec4(right, top, 0.0, 1.0);
|
|
|
|
frame[3].position = self.framable.ortho() * vec4(right, top, 0.0, 1.0);
|
|
|
|
frame[4].position = self.framable.ortho() * vec4(left, top, 0.0, 1.0);
|
|
|
|
frame[5].position = self.framable.ortho() * vec4(left, bottom, 0.0, 1.0);
|
|
|
|
|
|
|
|
frame[0].texture_coordinates = vec2(
|
|
|
|
*self.left_uv_factor.read().unwrap(),
|
|
|
|
*self.bottom_uv_factor.read().unwrap(),
|
|
|
|
);
|
|
|
|
frame[1].texture_coordinates = vec2(
|
|
|
|
*self.right_uv_factor.read().unwrap(),
|
|
|
|
*self.bottom_uv_factor.read().unwrap(),
|
|
|
|
);
|
|
|
|
frame[2].texture_coordinates = vec2(
|
|
|
|
*self.right_uv_factor.read().unwrap(),
|
|
|
|
*self.top_uv_factor.read().unwrap(),
|
|
|
|
);
|
|
|
|
frame[3].texture_coordinates = vec2(
|
|
|
|
*self.right_uv_factor.read().unwrap(),
|
|
|
|
*self.top_uv_factor.read().unwrap(),
|
|
|
|
);
|
|
|
|
frame[4].texture_coordinates = vec2(
|
|
|
|
*self.left_uv_factor.read().unwrap(),
|
|
|
|
*self.top_uv_factor.read().unwrap(),
|
|
|
|
);
|
|
|
|
frame[5].texture_coordinates = vec2(
|
|
|
|
*self.left_uv_factor.read().unwrap(),
|
|
|
|
*self.bottom_uv_factor.read().unwrap(),
|
|
|
|
);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|