Extend parser with generator feature

This commit is contained in:
hodasemi 2024-03-25 12:33:56 +01:00
parent cfd079b370
commit 5f63f4115e
6 changed files with 137 additions and 49 deletions

View file

@ -7,6 +7,7 @@ edition = "2021"
[dependencies] [dependencies]
quick-xml = "0.31.0" quick-xml = "0.31.0"
serde = { version = "1.0.197", features = ["derive"] } serde = { version = "1.0.197", features = ["derive"] }
serde_json = { version = "1.0.114" }
vulkan-rs = { git = "https://gavania.de/hodasemi/vulkan_lib.git" } vulkan-rs = { git = "https://gavania.de/hodasemi/vulkan_lib.git" }
utilities = { git = "https://gavania.de/hodasemi/utilities.git" } utilities = { git = "https://gavania.de/hodasemi/utilities.git" }
paste = "1.0.14" paste = "1.0.14"

View file

@ -1,6 +1,7 @@
use crate::prelude::*; use crate::prelude::*;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use assetpath::AssetPath; use assetpath::AssetPath;
use serde_json::from_str;
use utilities::prelude::*; use utilities::prelude::*;
use quick_xml::{events::Event, Reader}; use quick_xml::{events::Event, Reader};
@ -514,7 +515,10 @@ pub fn cow_to_fill_type<'a>(cow: Cow<'a, [u8]>) -> FillTypeInfo {
match Color::try_from(text.as_str()) { match Color::try_from(text.as_str()) {
Ok(color) => FillTypeInfo::Color(color), Ok(color) => FillTypeInfo::Color(color),
Err(_) => FillTypeInfo::Image(AssetPath::from(text)), Err(_) => match from_str(text.as_str()) {
Ok(descriptor) => FillTypeInfo::Element(descriptor),
Err(_) => FillTypeInfo::Image(AssetPath::from(text)),
},
} }
} }

View file

@ -7,12 +7,13 @@ use std::{
}; };
use anyhow::Result; use anyhow::Result;
use serde::{Deserialize, Serialize};
use utilities::color::Color; use utilities::color::Color;
use vulkan_rs::prelude::*; use vulkan_rs::prelude::*;
use self::generator::Generator; use self::generator::Generator;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum ElementBorderThickness { pub enum ElementBorderThickness {
Pixel(u32), Pixel(u32),
Ratio(f32), Ratio(f32),
@ -30,7 +31,21 @@ impl From<f32> for ElementBorderThickness {
} }
} }
#[derive(Debug, Clone, Copy)] impl PartialEq for ElementBorderThickness {
fn eq(&self, other: &ElementBorderThickness) -> bool {
match (self, other) {
(ElementBorderThickness::Pixel(m), ElementBorderThickness::Pixel(o)) => m == o,
(ElementBorderThickness::Ratio(m), ElementBorderThickness::Ratio(o)) => m == o,
_ => false,
}
}
}
/// The serialized string looks like:
///
/// {"background_color":"White","border_color":"Black","border_thickness":{"Pixel":5}}
///
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct ElementDescriptor { pub struct ElementDescriptor {
background_color: Color, background_color: Color,
border_color: Color, border_color: Color,

View file

@ -1,4 +1,4 @@
use crate::prelude::*; use crate::{guihandler::gui::displayable::DisplayableType, prelude::*};
use anyhow::Result; use anyhow::Result;
use assetpath::AssetPath; use assetpath::AssetPath;
use utilities::prelude::*; use utilities::prelude::*;
@ -8,10 +8,11 @@ use std::sync::{
Arc, Arc,
}; };
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone)]
pub enum FillTypeInfo { pub enum FillTypeInfo {
Image(AssetPath), Image(AssetPath),
Color(Color), Color(Color),
Element(ElementDescriptor),
} }
impl From<Color> for FillTypeInfo { impl From<Color> for FillTypeInfo {
@ -52,6 +53,9 @@ pub(crate) enum InnerFillType {
impl InnerFillType { impl InnerFillType {
pub(crate) fn new(framable: Arc<Framable>, fill_type_info: FillTypeInfo) -> Result<Self> { pub(crate) fn new(framable: Arc<Framable>, fill_type_info: FillTypeInfo) -> Result<Self> {
match fill_type_info { match fill_type_info {
FillTypeInfo::Element(descriptor) => Ok(InnerFillType::Image(Displayable::new(
framable, descriptor,
)?)),
FillTypeInfo::Image(path) => { FillTypeInfo::Image(path) => {
Ok(InnerFillType::Image(Displayable::new(framable, path)?)) Ok(InnerFillType::Image(Displayable::new(framable, path)?))
} }
@ -149,7 +153,16 @@ impl PartialEq<FillTypeInfo> for FillType {
fn eq(&self, info: &FillTypeInfo) -> bool { fn eq(&self, info: &FillTypeInfo) -> bool {
match (&self.inner, info) { match (&self.inner, info) {
(InnerFillType::Image(inner_image), FillTypeInfo::Image(info_image)) => { (InnerFillType::Image(inner_image), FillTypeInfo::Image(info_image)) => {
inner_image.path() == info_image match inner_image.inner_type() {
DisplayableType::Path(path) => path == *info_image,
DisplayableType::Descriptor(_) => false,
}
}
(InnerFillType::Image(inner_image), FillTypeInfo::Element(info_descriptor)) => {
match inner_image.inner_type() {
DisplayableType::Path(_) => false,
DisplayableType::Descriptor(descriptor) => descriptor == *info_descriptor,
}
} }
(InnerFillType::Color(inner_color), FillTypeInfo::Color(info_color)) => { (InnerFillType::Color(inner_color), FillTypeInfo::Color(info_color)) => {
inner_color.color() == *info_color inner_color.color() == *info_color

View file

@ -15,15 +15,33 @@ use std::sync::{
{Arc, RwLock}, {Arc, RwLock},
}; };
#[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)
}
}
/// `Displayable` gives the ability to display a texture as background image for an item /// `Displayable` gives the ability to display a texture as background image for an item
pub struct Displayable { pub struct Displayable {
framable: Arc<Framable>, framable: Arc<Framable>,
descriptor_set: RwLock<Arc<DescriptorSet>>, descriptor_set: Arc<DescriptorSet>,
buffer: Arc<Buffer<TexturedVertex>>, buffer: Arc<Buffer<TexturedVertex>>,
path: AssetPath, displayable_type: RwLock<DisplayableType>,
ui_layer: AtomicI32, ui_layer: AtomicI32,
@ -45,8 +63,20 @@ impl Displayable {
/// ///
/// * `framable` is a `Arc<Framable>` instance /// * `framable` is a `Arc<Framable>` instance
/// * `name` is the name for a png /// * `name` is the name for a png
pub fn new(framable: Arc<Framable>, name: AssetPath) -> Result<Arc<Self>> { pub fn new(
let descriptor_set = framable.gui_handler().image_descriptor(name.clone())?; 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])])?;
}
let buffer = Buffer::builder() let buffer = Buffer::builder()
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) .set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
@ -56,10 +86,10 @@ impl Displayable {
let displayable = Arc::new(Displayable { let displayable = Arc::new(Displayable {
framable, framable,
descriptor_set: RwLock::new(descriptor_set), descriptor_set,
buffer, buffer,
path: name, displayable_type: RwLock::new(displayable_type),
ui_layer: AtomicI32::new(0), ui_layer: AtomicI32::new(0),
@ -107,8 +137,8 @@ impl Displayable {
.delete_displayable(self.ui_layer.load(SeqCst), self) .delete_displayable(self.ui_layer.load(SeqCst), self)
} }
pub fn path(&self) -> &AssetPath { pub fn inner_type(&self) -> DisplayableType {
&self.path self.displayable_type.read().unwrap().clone()
} }
pub fn set_ui_layer(&self, ui_layer: i32) { pub fn set_ui_layer(&self, ui_layer: i32) {
@ -125,10 +155,37 @@ impl Displayable {
/// # Arguments /// # Arguments
/// ///
/// * `name` is the name of the texture in `gui/` without `.png` suffix /// * `name` is the name of the texture in `gui/` without `.png` suffix
pub fn set_image(&self, name: AssetPath) -> Result<()> { pub fn set_image(&self, displayable_type: impl Into<DisplayableType>) -> Result<()> {
let descriptor_set = self.framable.gui_handler().image_descriptor(name)?; let displayable_type = displayable_type.into();
*self.descriptor_set.write().unwrap() = descriptor_set; 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;
Ok(()) Ok(())
} }
@ -140,7 +197,7 @@ impl Displayable {
/// Returns the internal vulkan descriptor set /// Returns the internal vulkan descriptor set
pub fn descriptor_set(&self) -> Arc<DescriptorSet> { pub fn descriptor_set(&self) -> Arc<DescriptorSet> {
self.descriptor_set.read().unwrap().clone() self.descriptor_set.clone()
} }
pub fn set_left_factor(&self, factor: f32) { pub fn set_left_factor(&self, factor: f32) {

View file

@ -83,13 +83,6 @@ struct GuiSeparator {
pipeline: Arc<Pipeline>, pipeline: Arc<Pipeline>,
} }
struct DisplayableTexture {
_descriptor_pool: Arc<DescriptorPool>,
_descriptor_set: Arc<DescriptorSet>,
_texture: Arc<Image>,
}
impl_reprc!( impl_reprc!(
struct ColorBuffer { struct ColorBuffer {
#[assume_reprc] #[assume_reprc]
@ -227,9 +220,11 @@ pub struct GuiHandler {
text_color_layout: Arc<DescriptorSetLayout>, text_color_layout: Arc<DescriptorSetLayout>,
internal_icons: RwLock<HashMap<AssetPath, Weak<Image>>>, internal_icons: RwLock<HashMap<AssetPath, Weak<Image>>>,
internal_textures: RwLock<HashMap<AssetPath, DisplayableTexture>>, internal_textures: RwLock<HashMap<AssetPath, Arc<Image>>>,
internal_colors: RwLock<HashMap<Color, TextableColor>>, internal_colors: RwLock<HashMap<Color, TextableColor>>,
element_creator: Mutex<ElementCreator>,
ortho: RwLock<cgmath::Matrix4<f32>>, ortho: RwLock<cgmath::Matrix4<f32>>,
icon_descriptor_layout: Arc<DescriptorSetLayout>, icon_descriptor_layout: Arc<DescriptorSetLayout>,
@ -377,6 +372,8 @@ impl GuiHandler {
internal_textures: RwLock::new(HashMap::new()), internal_textures: RwLock::new(HashMap::new()),
internal_colors: RwLock::new(HashMap::new()), internal_colors: RwLock::new(HashMap::new()),
element_creator: Mutex::new(ElementCreator::new(device.clone(), queue.clone())?),
icon_descriptor_layout, icon_descriptor_layout,
needs_update: AtomicBool::new(true), needs_update: AtomicBool::new(true),
@ -499,44 +496,45 @@ impl GuiHandler {
._descriptor_layout ._descriptor_layout
} }
pub(crate) fn image_descriptor(&self, mut path: AssetPath) -> Result<Arc<DescriptorSet>> { pub(crate) fn displayable_image_from_descriptor(
&self,
width: u32,
height: u32,
descriptor: ElementDescriptor,
) -> Result<Arc<Image>> {
self.element_creator
.lock()
.unwrap()
.get(width, height, descriptor)
}
pub(crate) fn image_descriptor_set(&self) -> Result<Arc<DescriptorSet>> {
let desc_pool = DescriptorPool::builder()
.set_layout(self.text_desc_layout().clone())
.build(self.device.clone())?;
DescriptorPool::prepare_set(&desc_pool).allocate()
}
pub(crate) fn displayable_image_from_path(&self, mut path: AssetPath) -> Result<Arc<Image>> {
if !path.has_prefix() { if !path.has_prefix() {
path.set_prefix(&self.resource_base_path.full_path()); path.set_prefix(&self.resource_base_path.full_path());
} }
if self.internal_textures.read().unwrap().contains_key(&path) { if self.internal_textures.read().unwrap().contains_key(&path) {
Ok(self.internal_textures.read().unwrap()[&path] Ok(self.internal_textures.read().unwrap()[&path].clone())
._descriptor_set
.clone())
} else { } else {
let texture = Image::from_file(path.clone())? let texture = Image::from_file(path.clone())?
.format(VK_FORMAT_R8G8B8A8_UNORM) .format(VK_FORMAT_R8G8B8A8_UNORM)
.attach_sampler(Sampler::nearest_sampler().build(&self.device)?) .attach_sampler(Sampler::nearest_sampler().build(&self.device)?)
.build(&self.device, &self.queue)?; .build(&self.device, &self.queue)?;
let desc_pool = DescriptorPool::builder()
.set_layout(self.text_desc_layout().clone())
.build(self.device.clone())?;
let descriptor_set = DescriptorPool::prepare_set(&desc_pool).allocate()?;
descriptor_set.update(&[DescriptorWrite::combined_samplers(0, &[&texture])])?;
let displayable_texture = DisplayableTexture {
_descriptor_pool: desc_pool,
_descriptor_set: descriptor_set,
_texture: texture,
};
self.internal_textures self.internal_textures
.write() .write()
.unwrap() .unwrap()
.insert(path.clone(), displayable_texture); .insert(path.clone(), texture.clone());
Ok(self.internal_textures.read().unwrap()[&path] Ok(texture.clone())
._descriptor_set
.clone())
} }
} }