Add rustfmt.toml and enable auto formatting (Fixes #7)

This commit is contained in:
Keavon Chambers
2020-07-12 16:20:28 -07:00
parent d616bfa8a1
commit 35ff5f55ea
20 changed files with 541 additions and 439 deletions

View File

@@ -1,14 +1,14 @@
use crate::color_palette::ColorPalette;
use crate::window_events;
use crate::pipeline::Pipeline;
use crate::texture::Texture;
use crate::resource_cache::ResourceCache;
use crate::layout_system::LayoutSystem;
use crate::gui_node::GuiNode;
use crate::layout_system::LayoutSystem;
use crate::pipeline::Pipeline;
use crate::resource_cache::ResourceCache;
use crate::texture::Texture;
use crate::window_events;
use futures::executor::block_on;
use winit::event::*;
use winit::event_loop::*;
use winit::window::Window;
use futures::executor::block_on;
pub struct Application {
pub surface: wgpu::Surface,
@@ -35,7 +35,8 @@ impl Application {
compatible_surface: Some(&surface),
},
wgpu::BackendBit::PRIMARY,
)).unwrap();
))
.unwrap();
// Requests the device and queue from the adapter
let requested_device = block_on(adapter.request_device(&wgpu::DeviceDescriptor {
@@ -48,7 +49,7 @@ impl Application {
// Represents the GPU command queue, to submit CommandBuffers
let queue = requested_device.1;
// Properties for the swap chain frame buffers
let swap_chain_descriptor = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
@@ -70,7 +71,11 @@ impl Application {
// Data structure maintaining the user interface
let gui_rect_pipeline = Pipeline::new(
&device, swap_chain_descriptor.format, Vec::new(), &mut shader_cache, ("shaders/shader.vert", "shaders/shader.frag"),
&device,
swap_chain_descriptor.format,
Vec::new(),
&mut shader_cache,
("shaders/shader.vert", "shaders/shader.frag"),
);
pipeline_cache.set("gui_rect", gui_rect_pipeline);
@@ -127,15 +132,13 @@ impl Application {
}
}
fn update_gui(&mut self) {
}
fn update_gui(&mut self) {}
// Render the queue of pipeline draw commands over the current window
fn render(&mut self) {
// Get a frame buffer to render on
let frame = self.swap_chain.get_next_texture().expect("Timeout getting frame buffer texture");
// Generates a render pass that commands are applied to, then generates a command buffer when finished
let mut command_encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("Render Encoder") });
@@ -144,21 +147,19 @@ impl Application {
// Recording of commands while in "rendering mode" that go into a command buffer
let mut render_pass = command_encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[
wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.view,
resolve_target: None,
load_op: wgpu::LoadOp::Clear,
store_op: wgpu::StoreOp::Store,
clear_color: wgpu::Color::BLACK,
}
],
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.view,
resolve_target: None,
load_op: wgpu::LoadOp::Clear,
store_op: wgpu::StoreOp::Store,
clear_color: wgpu::Color::BLACK,
}],
depth_stencil_attachment: None,
});
// Prepare a variable to reuse the pipeline based on its name
let mut pipeline_name = String::new();
// Turn the queue of pipelines each into a command buffer and submit it to the render queue
for i in 0..commands.len() {
// If the previously set pipeline can't be reused, send the GPU the new pipeline to draw with
@@ -179,7 +180,7 @@ impl Application {
// Draw call
render_pass.draw_indexed(0..commands[i].index_count, 0, 0..1);
};
}
// Done sending render pass commands so we can give up mutation rights to command_encoder
drop(render_pass);

View File

@@ -13,74 +13,29 @@ impl Color {
}
#[allow(dead_code)]
pub const TRANSPARENT: Self = Color {
r: 0.0,
g: 0.0,
b: 0.0,
a: 0.0,
};
pub const TRANSPARENT: Self = Color { r: 0.0, g: 0.0, b: 0.0, a: 0.0 };
#[allow(dead_code)]
pub const BLACK: Self = Color {
r: 0.0,
g: 0.0,
b: 0.0,
a: 1.0,
};
pub const BLACK: Self = Color { r: 0.0, g: 0.0, b: 0.0, a: 1.0 };
#[allow(dead_code)]
pub const WHITE: Self = Color {
r: 1.0,
g: 1.0,
b: 1.0,
a: 1.0,
};
pub const WHITE: Self = Color { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
#[allow(dead_code)]
pub const RED: Self = Color {
r: 1.0,
g: 0.0,
b: 0.0,
a: 1.0,
};
pub const RED: Self = Color { r: 1.0, g: 0.0, b: 0.0, a: 1.0 };
#[allow(dead_code)]
pub const YELLOW: Self = Color {
r: 1.0,
g: 1.0,
b: 0.0,
a: 1.0,
};
pub const YELLOW: Self = Color { r: 1.0, g: 1.0, b: 0.0, a: 1.0 };
#[allow(dead_code)]
pub const GREEN: Self = Color {
r: 0.0,
g: 1.0,
b: 0.0,
a: 1.0,
};
pub const GREEN: Self = Color { r: 0.0, g: 1.0, b: 0.0, a: 1.0 };
#[allow(dead_code)]
pub const CYAN: Self = Color {
r: 0.0,
g: 1.0,
b: 1.0,
a: 1.0,
};
pub const CYAN: Self = Color { r: 0.0, g: 1.0, b: 1.0, a: 1.0 };
#[allow(dead_code)]
pub const BLUE: Self = Color {
r: 0.0,
g: 0.0,
b: 1.0,
a: 1.0,
};
pub const BLUE: Self = Color { r: 0.0, g: 0.0, b: 1.0, a: 1.0 };
#[allow(dead_code)]
pub const MAGENTA: Self = Color {
r: 1.0,
g: 0.0,
b: 1.0,
a: 1.0,
};
}
pub const MAGENTA: Self = Color { r: 1.0, g: 0.0, b: 1.0, a: 1.0 };
}

View File

@@ -25,22 +25,22 @@ impl ColorPalette {
#[allow(dead_code)]
pub fn into_color_srgb(&self) -> Color {
let grayscale = match self {
ColorPalette::Black => 0 * 17, // #000000
ColorPalette::NearBlack => 1 * 17, // #111111
ColorPalette::MildBlack => 2 * 17, // #222222
ColorPalette::DarkGray => 3 * 17, // #333333
ColorPalette::DimGray => 4 * 17, // #444444
ColorPalette::DullGray => 5 * 17, // #555555
ColorPalette::LowerGray => 6 * 17, // #666666
ColorPalette::MiddleGray => 7 * 17, // #777777
ColorPalette::UpperGray => 8 * 17, // #888888
ColorPalette::PaleGray => 9 * 17, // #999999
ColorPalette::SoftGray => 10 * 17, // #aaaaaa
ColorPalette::LightGray => 11 * 17, // #bbbbbb
ColorPalette::Black => 0 * 17, // #000000
ColorPalette::NearBlack => 1 * 17, // #111111
ColorPalette::MildBlack => 2 * 17, // #222222
ColorPalette::DarkGray => 3 * 17, // #333333
ColorPalette::DimGray => 4 * 17, // #444444
ColorPalette::DullGray => 5 * 17, // #555555
ColorPalette::LowerGray => 6 * 17, // #666666
ColorPalette::MiddleGray => 7 * 17, // #777777
ColorPalette::UpperGray => 8 * 17, // #888888
ColorPalette::PaleGray => 9 * 17, // #999999
ColorPalette::SoftGray => 10 * 17, // #aaaaaa
ColorPalette::LightGray => 11 * 17, // #bbbbbb
ColorPalette::BrightGray => 12 * 17, // #cccccc
ColorPalette::MildWhite => 13 * 17, // #dddddd
ColorPalette::NearWhite => 14 * 17, // #eeeeee
ColorPalette::White => 15 * 17, // #ffffff
ColorPalette::MildWhite => 13 * 17, // #dddddd
ColorPalette::NearWhite => 14 * 17, // #eeeeee
ColorPalette::White => 15 * 17, // #ffffff
_ => -1,
};
@@ -51,7 +51,7 @@ impl ColorPalette {
let rgba = match self {
ColorPalette::Accent => (75, 121, 167, 255), // #4b79a7
_ => (0, 0, 0, 255), // Unimplemented returns black
_ => (0, 0, 0, 255), // Unimplemented returns black
};
Color::new(rgba.0 as f32 / 255.0, rgba.1 as f32 / 255.0, rgba.2 as f32 / 255.0, rgba.3 as f32 / 255.0)
@@ -88,4 +88,4 @@ impl ColorPalette {
_ => panic!("Invalid color lookup of `{}` from the color palette", name_in_palette),
}
}
}
}

View File

@@ -22,4 +22,4 @@ impl DrawCommand {
index_count,
}
}
}
}

View File

@@ -9,7 +9,12 @@ pub struct Corners<T> {
impl<T> Corners<T> {
pub fn new(top_left: T, top_right: T, bottom_right: T, bottom_left: T) -> Self {
Self { top_left, top_right, bottom_right, bottom_left }
Self {
top_left,
top_right,
bottom_right,
bottom_left,
}
}
}

View File

@@ -1,9 +1,9 @@
use crate::resource_cache::ResourceCache;
use crate::draw_command::DrawCommand;
use crate::color::Color;
use crate::texture::Texture;
use crate::pipeline::Pipeline;
use crate::draw_command::DrawCommand;
use crate::gui_attributes::*;
use crate::pipeline::Pipeline;
use crate::resource_cache::ResourceCache;
use crate::texture::Texture;
pub struct GuiNode {
pub form_factor: GuiNodeUniform,
@@ -18,7 +18,13 @@ impl GuiNode {
}
}
pub fn build_draw_commands_recursive(node: &rctree::Node<GuiNode>, device: &wgpu::Device, queue: &mut wgpu::Queue, pipeline_cache: &ResourceCache<Pipeline>, texture_cache: &mut ResourceCache<Texture>) -> Vec<DrawCommand> {
pub fn build_draw_commands_recursive(
node: &rctree::Node<GuiNode>,
device: &wgpu::Device,
queue: &mut wgpu::Queue,
pipeline_cache: &ResourceCache<Pipeline>,
texture_cache: &mut ResourceCache<Texture>,
) -> Vec<DrawCommand> {
let mut draw_commands: Vec<DrawCommand> = Vec::new();
for mut subnode in node.descendants() {
@@ -32,19 +38,11 @@ impl GuiNode {
}
pub fn build_draw_command(&mut self, device: &wgpu::Device, queue: &mut wgpu::Queue, pipeline: &Pipeline, texture_cache: &mut ResourceCache<Texture>) -> DrawCommand {
const VERTICES: &[[f32; 2]] = &[
[-0.5, 0.5],
[0.5, 0.5],
[0.5, 1.0],
[-0.5, 1.0],
];
const INDICES: &[u16] = &[
0, 1, 2,
0, 2, 3,
];
const VERTICES: &[[f32; 2]] = &[[-0.5, 0.5], [0.5, 0.5], [0.5, 1.0], [-0.5, 1.0]];
const INDICES: &[u16] = &[0, 1, 2, 0, 2, 3];
let bind_groups = self.build_bind_groups(device, queue, pipeline, texture_cache);
// Create a draw command with the vertex data then push it to the GPU command queue
DrawCommand::new(device, self.pipeline_name.clone(), bind_groups, VERTICES, INDICES)
}
@@ -57,15 +55,17 @@ impl GuiNode {
let binding_staging_buffer = Pipeline::build_binding_staging_buffer(device, &self.form_factor);
// Construct the bind group for this GUI node
let bind_group = Pipeline::build_bind_group(device, &pipeline.bind_group_layout, vec![
Pipeline::build_binding_resource(&binding_staging_buffer),
wgpu::BindingResource::TextureView(&texture.texture_view),
wgpu::BindingResource::Sampler(&texture.sampler),
]);
vec![
bind_group,
]
let bind_group = Pipeline::build_bind_group(
device,
&pipeline.bind_group_layout,
vec![
Pipeline::build_binding_resource(&binding_staging_buffer),
wgpu::BindingResource::TextureView(&texture.texture_view),
wgpu::BindingResource::Sampler(&texture.sampler),
],
);
vec![bind_group]
}
}

View File

@@ -1,4 +1,3 @@
use crate::layout_abstract_types::*;
#[derive(Debug)]
@@ -26,7 +25,11 @@ pub struct LayoutAbstractTag {
impl LayoutAbstractTag {
pub fn new(namespace: String, name: String) -> Self {
Self { namespace, name, attributes: Vec::new() }
Self {
namespace,
name,
attributes: Vec::new(),
}
}
pub fn add_attribute(&mut self, attribute: Attribute) {

View File

@@ -9,7 +9,11 @@ pub struct VariableParameter {
impl VariableParameter {
pub fn new(name: String, valid_types: Vec<Vec<TypeName>>, default: Vec<TypeValue>) -> Self {
Self { name, type_sequence_options: valid_types, type_sequence_default: default }
Self {
name,
type_sequence_options: valid_types,
type_sequence_default: default,
}
}
}

View File

@@ -1,7 +1,7 @@
use crate::layout_abstract_types::*;
use crate::layout_abstract_syntax::*;
use crate::color_palette::ColorPalette;
use crate::color::Color;
use crate::color_palette::ColorPalette;
use crate::layout_abstract_syntax::*;
use crate::layout_abstract_types::*;
pub struct AttributeParser {
capture_attribute_declaration_parameter_regex: regex::Regex,
@@ -17,8 +17,9 @@ impl AttributeParser {
pub fn new() -> Self {
let capture_attribute_declaration_parameter_regex: regex::Regex = regex::Regex::new(
// Parameter: ?: (?, ... | ...) = ?
r"^\s*(\w*)\s*(:)\s*(\()\s*((?:(?:\w+)(?:\s*,\s*\w+)*)(?:\s*\|\s*(?:(?:\w+)(?:\s*,\s*\w+)*))*)\s*(\))\s*(=)\s*([\s\w'\[\]@%\-.`,]*?)\s*$"
).unwrap();
r"^\s*(\w*)\s*(:)\s*(\()\s*((?:(?:\w+)(?:\s*,\s*\w+)*)(?:\s*\|\s*(?:(?:\w+)(?:\s*,\s*\w+)*))*)\s*(\))\s*(=)\s*([\s\w'\[\]@%\-.`,]*?)\s*$",
)
.unwrap();
let capture_attribute_type_sequences_regex: regex::Regex = regex::Regex::new(concat!(
// Argument: {{?}}
@@ -47,7 +48,8 @@ impl AttributeParser {
r#"^\s*([Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee])\s*$|"#,
// None: none
r#"^\s*([Nn][Oo][Nn][Ee])\s*$"#,
)).unwrap();
))
.unwrap();
let match_integer_regex = regex::Regex::new(r"^\s*(-?\d+)\s*$").unwrap();
@@ -69,15 +71,19 @@ impl AttributeParser {
pub fn parse_attribute_types(&self, input: &str) -> AttributeValue {
let attribute_types = input.split(",").map(|piece| piece.trim()).collect::<Vec<&str>>();
let list = attribute_types.iter().map(|attribute_type| self.parse_attribute_type(attribute_type)).collect::<Vec<TypeValueOrArgument>>();
let list = attribute_types
.iter()
.map(|attribute_type| self.parse_attribute_type(attribute_type))
.collect::<Vec<TypeValueOrArgument>>();
AttributeValue::TypeValue(list)
}
pub fn parse_attribute_type(&self, attribute_type: &str) -> TypeValueOrArgument {
// Match with the regular expression
let captures = self.capture_attribute_type_sequences_regex.captures(attribute_type).map(|captures|
captures.iter().skip(1).flat_map(|c| c).map(|c| c.as_str()).collect::<Vec<_>>()
);
let captures = self
.capture_attribute_type_sequences_regex
.captures(attribute_type)
.map(|captures| captures.iter().skip(1).flat_map(|c| c).map(|c| c.as_str()).collect::<Vec<_>>());
// Match against the captured values as a list of tokens
let tokens = captures.as_ref().map(|c| c.as_slice());
@@ -89,46 +95,50 @@ impl AttributeParser {
},
// Integer: ?
Some([value]) if self.match_integer_regex.is_match(value) => {
let integer = value.parse::<i64>().expect(&format!("Invalid value `{}` specified in the attribute type `{}` when parsing XML layout", value, attribute_type)[..]);
let integer = value
.parse::<i64>()
.expect(&format!("Invalid value `{}` specified in the attribute type `{}` when parsing XML layout", value, attribute_type)[..]);
TypeValueOrArgument::TypeValue(TypeValue::Integer(integer))
},
// Decimal: ?
Some([value]) if self.match_decimal_regex.is_match(value) => {
let decimal = value.parse::<f64>().expect(&format!("Invalid value `{}` specified in the attribute type `{}` when parsing XML layout", value, attribute_type)[..]);
let decimal = value
.parse::<f64>()
.expect(&format!("Invalid value `{}` specified in the attribute type `{}` when parsing XML layout", value, attribute_type)[..]);
TypeValueOrArgument::TypeValue(TypeValue::Decimal(decimal))
},
// AbsolutePx: px
Some([value, px]) if px.eq_ignore_ascii_case("px") => {
let pixels = value.parse::<f32>().expect(&format!("Invalid value `{}` specified in the attribute type`{}` when parsing XML layout", value, attribute_type)[..]);
let pixels = value
.parse::<f32>()
.expect(&format!("Invalid value `{}` specified in the attribute type`{}` when parsing XML layout", value, attribute_type)[..]);
TypeValueOrArgument::TypeValue(TypeValue::AbsolutePx(pixels))
},
// Percent: ?%
Some([value, "%"]) => {
let percent = value.parse::<f32>().expect(&format!("Invalid value `{}` specified in the attribute type `{}` when parsing XML layout", value, attribute_type)[..]);
let percent = value
.parse::<f32>()
.expect(&format!("Invalid value `{}` specified in the attribute type `{}` when parsing XML layout", value, attribute_type)[..]);
TypeValueOrArgument::TypeValue(TypeValue::Percent(percent))
},
// PercentRemainder: ?@
Some([value, "@"]) => {
let percent_remainder = value.parse::<f32>().expect(&format!("Invalid value `{}` specified in the attribute type `{}` when parsing XML layout", value, attribute_type)[..]);
let percent_remainder = value
.parse::<f32>()
.expect(&format!("Invalid value `{}` specified in the attribute type `{}` when parsing XML layout", value, attribute_type)[..]);
TypeValueOrArgument::TypeValue(TypeValue::PercentRemainder(percent_remainder))
},
// Inner: inner
Some([inner]) if inner.eq_ignore_ascii_case("inner") => {
TypeValueOrArgument::TypeValue(TypeValue::Inner)
},
Some([inner]) if inner.eq_ignore_ascii_case("inner") => TypeValueOrArgument::TypeValue(TypeValue::Inner),
// Width: width
Some([width]) if width.eq_ignore_ascii_case("width") => {
TypeValueOrArgument::TypeValue(TypeValue::Width)
},
Some([width]) if width.eq_ignore_ascii_case("width") => TypeValueOrArgument::TypeValue(TypeValue::Width),
// Height: height
Some([height]) if height.eq_ignore_ascii_case("height") => {
TypeValueOrArgument::TypeValue(TypeValue::Height)
},
Some([height]) if height.eq_ignore_ascii_case("height") => TypeValueOrArgument::TypeValue(TypeValue::Height),
// TemplateString: `? ... {{?}} ...`
Some(["`", string, "`"]) => {
let mut segments = Vec::<TemplateStringSegment>::new();
let mut is_template = false;
for part in self.split_by_string_templates_regex.split(string) {
let segment = match is_template {
true => TemplateStringSegment::String(String::from(part)),
@@ -144,14 +154,32 @@ impl AttributeParser {
Some(["[", color_name, "]"]) => {
let color = match self.capture_color_name_in_palette_regex.captures(color_name) {
Some(captures) => {
let palette_color = captures.get(1).expect(&format!("Invalid palette color name `{}` specified in the attribute type `{}` when parsing XML layout", color_name, attribute_type)[..]).as_str();
let palette_color = captures
.get(1)
.expect(
&format!(
"Invalid palette color name `{}` specified in the attribute type `{}` when parsing XML layout",
color_name, attribute_type
)[..],
)
.as_str();
ColorPalette::lookup_palette_color(palette_color).into_color_srgb()
}
},
None => {
let parsed = color_name.parse::<css_color_parser::Color>();
let css_color = parsed.expect(&format!("Invalid CSS color name `{}` specified in the attribute type `{}` when parsing XML layout", color_name, attribute_type)[..]);
Color::new(css_color.r as f32 / 255.0, css_color.g as f32 / 255.0, css_color.b as f32 / 255.0, css_color.a as f32 / 255.0)
}
let css_color = parsed.expect(
&format!(
"Invalid CSS color name `{}` specified in the attribute type `{}` when parsing XML layout",
color_name, attribute_type
)[..],
);
Color::new(
css_color.r as f32 / 255.0,
css_color.g as f32 / 255.0,
css_color.b as f32 / 255.0,
css_color.a as f32 / 255.0,
)
},
};
TypeValueOrArgument::TypeValue(TypeValue::Color(color))
@@ -162,9 +190,7 @@ impl AttributeParser {
TypeValueOrArgument::TypeValue(TypeValue::Bool(boolean))
},
// None: none
Some([none]) if none.eq_ignore_ascii_case("none") => {
TypeValueOrArgument::TypeValue(TypeValue::None)
},
Some([none]) if none.eq_ignore_ascii_case("none") => TypeValueOrArgument::TypeValue(TypeValue::None),
// Unrecognized type pattern
_ => panic!("Invalid attribute type `{}` when parsing XML layout", attribute_type),
}
@@ -172,9 +198,10 @@ impl AttributeParser {
pub fn parse_attribute_declaration(&self, attribute_declaration: &str) -> AttributeValue {
// Match with the regular expression
let captures = self.capture_attribute_declaration_parameter_regex.captures(attribute_declaration).map(|captures|
captures.iter().skip(1).flat_map(|c| c).map(|c| c.as_str()).collect::<Vec<_>>()
);
let captures = self
.capture_attribute_declaration_parameter_regex
.captures(attribute_declaration)
.map(|captures| captures.iter().skip(1).flat_map(|c| c).map(|c| c.as_str()).collect::<Vec<_>>());
// Match against the captured values as a list of tokens
let tokens = captures.as_ref().map(|c| c.as_slice());
@@ -183,43 +210,56 @@ impl AttributeParser {
Some([name, ":", "(", raw_types_list, ")", "=", default_value]) => {
// Variable name bound in the parameter
let name = String::from(*name);
// Split the type sequences up into a list of options separated by vertical bars
let type_sequence_options = String::from(*raw_types_list).split("|").map(|group| {
// Split each type sequence into individual types separated by commas
group.split(",").map(|individual_type| {
// Remove any whitespace around the type
let individual_type = individual_type.trim();
// Return the case-insensitive TypeName enum for the individual type
match &individual_type.to_ascii_lowercase()[..] {
// "xml" => TypeName::Xml, // TODO
"integer" => TypeName::Integer,
"decimal" => TypeName::Decimal,
"absolutepx" => TypeName::AbsolutePx,
"percent" => TypeName::Percent,
"percentremainder" => TypeName::PercentRemainder,
"inner" => TypeName::Inner,
"width" => TypeName::Width,
"height" => TypeName::Height,
"templatestring" => TypeName::TemplateString,
"color" => TypeName::Color,
"bool" => TypeName::Bool,
"none" => TypeName::None,
_ => panic!("Invalid type `{}` specified in the attribute type `{}` when parsing XML layout", individual_type, attribute_declaration),
}
}).collect::<Vec<TypeName>>()
}).collect::<Vec<Vec<TypeName>>>();
// Split the type sequences up into a list of options separated by vertical bars
let type_sequence_options = String::from(*raw_types_list)
.split("|")
.map(|group| {
// Split each type sequence into individual types separated by commas
group
.split(",")
.map(|individual_type| {
// Remove any whitespace around the type
let individual_type = individual_type.trim();
// Return the case-insensitive TypeName enum for the individual type
match &individual_type.to_ascii_lowercase()[..] {
// "xml" => TypeName::Xml, // TODO
"integer" => TypeName::Integer,
"decimal" => TypeName::Decimal,
"absolutepx" => TypeName::AbsolutePx,
"percent" => TypeName::Percent,
"percentremainder" => TypeName::PercentRemainder,
"inner" => TypeName::Inner,
"width" => TypeName::Width,
"height" => TypeName::Height,
"templatestring" => TypeName::TemplateString,
"color" => TypeName::Color,
"bool" => TypeName::Bool,
"none" => TypeName::None,
_ => panic!(
"Invalid type `{}` specified in the attribute type `{}` when parsing XML layout",
individual_type, attribute_declaration
),
}
})
.collect::<Vec<TypeName>>()
})
.collect::<Vec<Vec<TypeName>>>();
// Required default value for the variable parameter if not provided
let default_type_sequence = default_value.split(",").map(|individual_type|
match self.parse_attribute_type(individual_type) {
let default_type_sequence = default_value
.split(",")
.map(|individual_type| match self.parse_attribute_type(individual_type) {
TypeValueOrArgument::TypeValue(type_value) => type_value,
TypeValueOrArgument::VariableArgument(variable_value) => {
panic!("Found the default variable value `{:?}` in the attribute declaration `{}` which only allows typed values, when parsing XML layout", variable_value, attribute_declaration);
panic!(
"Found the default variable value `{:?}` in the attribute declaration `{}` which only allows typed values, when parsing XML layout",
variable_value, attribute_declaration
);
},
}
).collect::<Vec<TypeValue>>();
})
.collect::<Vec<TypeValue>>();
// Return the parameter
AttributeValue::VariableParameter(VariableParameter::new(name, type_sequence_options, default_type_sequence))

View File

@@ -1,12 +1,12 @@
// pub struct LayoutDomNode {
// pub namespace: String,
// pub name: String,
// pub placement:
// pub placement:
// // pub body: Vec<LayoutDomNode>
// }
// pub struct LayoutPlacement {
// pub width: f32,
// pub height: f32,
// pub x_align:
// }
// pub x_align:
// }

View File

@@ -1,9 +1,9 @@
use std::fs;
use std::io;
use std::collections::HashSet;
use crate::layout_abstract_syntax::*;
use crate::layout_attribute_parser::*;
use crate::resource_cache::ResourceCache;
use std::collections::HashSet;
use std::fs;
use std::io;
pub struct LayoutSystem {
// pub dom_tree: rctree::Node<
@@ -38,7 +38,7 @@ impl LayoutSystem {
fn explore_referenced_layouts(&mut self, layout_tree_root: &rctree::Node<LayoutAbstractNode>, already_loaded_layouts: &mut HashSet<String>) {
for child_tag in layout_tree_root.descendants() {
match & *child_tag.borrow() {
match &*child_tag.borrow() {
// Tags are references to other XML layouts that should be loaded and cached
LayoutAbstractNode::Tag(layout_abstract_tag) => {
// Cache key in form namespace:name
@@ -56,7 +56,7 @@ impl LayoutSystem {
// Keep track of it being loaded to prevent duplicate work
let key_copy = key.clone();
already_loaded_layouts.insert(key);
// Recursively explore the newly loaded layout's tags
self.explore_referenced_layouts(&new_loaded_layout, already_loaded_layouts);
@@ -107,7 +107,7 @@ impl LayoutSystem {
let mut current_opening_tag: Option<LayoutAbstractNode> = None;
// Top-level node that is popped from the stack when the closing tag is reached at the end of the XML document
let mut final_result: Option<rctree::Node<LayoutAbstractNode>> = None;
for token in parser {
match token.unwrap() {
// Beginning of an opening tag (<NAMESPACE:NAME ...)
@@ -133,7 +133,8 @@ impl LayoutSystem {
string.push(':');
string.push_str(slice);
string
} else {
}
else {
String::from(local.as_str())
};
// Set the value to an ordinary string slice of the given value
@@ -212,11 +213,13 @@ impl LayoutSystem {
xmlparser::Token::Text { text } => {
// Trim any whitespace from around the string
let text_string = String::from(text.as_str().trim());
// If the string isn't all whitespace, append a new text node to the parent
if !text_string.is_empty() {
// Get the tree node which contains this text
let parent_node = stack.last_mut().expect(&format!("Encountered text outside the root tag when parsing XML layout in file: {}", path)[..]);
let parent_node = stack
.last_mut()
.expect(&format!("Encountered text outside the root tag when parsing XML layout in file: {}", path)[..]);
// Construct an AST text node with the provided text
let abstract_text_node = LayoutAbstractNode::new_text(text_string);
@@ -227,10 +230,10 @@ impl LayoutSystem {
parent_node.append(new_tree_node);
}
},
_ => {}
_ => {},
}
}
match final_result {
None => panic!("Invalid syntax when parsing XML layout in file: {}", path),
Some(tree) => Ok(tree),
@@ -242,4 +245,4 @@ impl LayoutSystem {
println!("{:?}", node);
}
}
}
}

View File

@@ -1,19 +1,19 @@
mod application;
mod pipeline;
mod texture;
mod color;
mod color_palette;
mod resource_cache;
mod shader_stage;
mod draw_command;
mod gui_node;
mod gui_attributes;
mod window_events;
mod layout_system;
mod layout_abstract_types;
mod gui_node;
mod layout_abstract_syntax;
mod layout_abstract_types;
mod layout_attribute_parser;
mod layout_dom_node;
mod layout_system;
mod pipeline;
mod resource_cache;
mod shader_stage;
mod texture;
mod window_events;
use application::Application;
use winit::event_loop::EventLoop;

View File

@@ -1,6 +1,6 @@
use std::mem;
use crate::resource_cache::ResourceCache;
use crate::shader_stage;
use std::mem;
pub struct Pipeline {
pub bind_group_layout: wgpu::BindGroupLayout,
@@ -8,25 +8,34 @@ pub struct Pipeline {
}
impl Pipeline {
pub fn new(device: &wgpu::Device, swap_chain_color_format: wgpu::TextureFormat, extra_layouts: Vec<&wgpu::BindGroupLayout>, shader_cache: &mut ResourceCache<wgpu::ShaderModule>, shader_pair_path: (&str, &str)) -> Self {
pub fn new(
device: &wgpu::Device,
swap_chain_color_format: wgpu::TextureFormat,
extra_layouts: Vec<&wgpu::BindGroupLayout>,
shader_cache: &mut ResourceCache<wgpu::ShaderModule>,
shader_pair_path: (&str, &str),
) -> Self {
// Load the vertex and fragment shaders
let shader_pair = Pipeline::get_shader_pair(device, shader_cache, shader_pair_path);
// Prepare a bind group layout for the GUI element's texture and form factor data
let bind_group_layout = Pipeline::build_bind_group_layout(device, &vec![
wgpu::BindingType::UniformBuffer { dynamic: false },
wgpu::BindingType::SampledTexture {
dimension: wgpu::TextureViewDimension::D2,
component_type: wgpu::TextureComponentType::Float,
multisampled: false,
},
wgpu::BindingType::Sampler { comparison: false },
]);
let bind_group_layout = Pipeline::build_bind_group_layout(
device,
&vec![
wgpu::BindingType::UniformBuffer { dynamic: false },
wgpu::BindingType::SampledTexture {
dimension: wgpu::TextureViewDimension::D2,
component_type: wgpu::TextureComponentType::Float,
multisampled: false,
},
wgpu::BindingType::Sampler { comparison: false },
],
);
// Combine all bind group layouts
let mut bind_group_layouts = vec![&bind_group_layout];
bind_group_layouts.append(&mut extra_layouts.clone());
// Construct the pipeline
let render_pipeline = Pipeline::build_pipeline(device, swap_chain_color_format, bind_group_layouts, shader_pair);
Self {
@@ -35,7 +44,11 @@ impl Pipeline {
}
}
pub fn get_shader_pair<'a>(device: &wgpu::Device, shader_cache: &'a mut ResourceCache<wgpu::ShaderModule>, shader_pair_path: (&str, &str)) -> (&'a wgpu::ShaderModule, &'a wgpu::ShaderModule) {
pub fn get_shader_pair<'a>(
device: &wgpu::Device,
shader_cache: &'a mut ResourceCache<wgpu::ShaderModule>,
shader_pair_path: (&str, &str),
) -> (&'a wgpu::ShaderModule, &'a wgpu::ShaderModule) {
// If uncached, construct a vertex shader loaded from its source code file
if shader_cache.get(shader_pair_path.0).is_none() {
let vertex_shader_module = shader_stage::compile_from_glsl(device, shader_pair_path.0, glsl_to_spirv::ShaderType::Vertex).unwrap();
@@ -56,28 +69,31 @@ impl Pipeline {
}
pub fn build_bind_group_layouts(device: &wgpu::Device, bind_group_layouts: &Vec<Vec<wgpu::BindingType>>) -> Vec<wgpu::BindGroupLayout> {
bind_group_layouts.into_iter().map(|layout_entry| Self::build_bind_group_layout(device, layout_entry)).collect::<Vec<_>>()
bind_group_layouts
.into_iter()
.map(|layout_entry| Self::build_bind_group_layout(device, layout_entry))
.collect::<Vec<_>>()
}
pub fn build_bind_group_layout(device: &wgpu::Device, bind_group_layout: &Vec<wgpu::BindingType>) -> wgpu::BindGroupLayout {
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: None,
bindings: bind_group_layout.into_iter().enumerate().map(|(index, binding_type)|
wgpu::BindGroupLayoutEntry {
bindings: bind_group_layout
.into_iter()
.enumerate()
.map(|(index, binding_type)| wgpu::BindGroupLayoutEntry {
binding: index as u32,
visibility: wgpu::ShaderStage::all(),
ty: binding_type.clone(),
}
).collect::<Vec<_>>().as_slice(),
})
.collect::<Vec<_>>()
.as_slice(),
})
}
pub fn build_binding_staging_buffer<T: bytemuck::Pod>(device: &wgpu::Device, resource: &T) -> wgpu::Buffer {
// Construct a staging buffer with the binary uniform struct data
device.create_buffer_with_data(
bytemuck::cast_slice(&[*resource]),
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
)
device.create_buffer_with_data(bytemuck::cast_slice(&[*resource]), wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST)
}
pub fn build_binding_resource(resource_buffer: &wgpu::Buffer) -> wgpu::BindingResource {
@@ -89,12 +105,14 @@ impl Pipeline {
}
pub fn build_bind_group(device: &wgpu::Device, bind_group_layout: &wgpu::BindGroupLayout, binding_resources: Vec<wgpu::BindingResource>) -> wgpu::BindGroup {
let bindings = binding_resources.into_iter().enumerate().map(|(index, binding_resource)|
wgpu::Binding {
let bindings = binding_resources
.into_iter()
.enumerate()
.map(|(index, binding_resource)| wgpu::Binding {
binding: index as u32,
resource: binding_resource,
}
).collect::<Vec<_>>();
})
.collect::<Vec<_>>();
device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: bind_group_layout,
@@ -103,11 +121,16 @@ impl Pipeline {
})
}
pub fn build_pipeline(device: &wgpu::Device, swap_chain_color_format: wgpu::TextureFormat, bind_group_layouts: Vec<&wgpu::BindGroupLayout>, shader_pair: (&wgpu::ShaderModule, &wgpu::ShaderModule)) -> wgpu::RenderPipeline {
pub fn build_pipeline(
device: &wgpu::Device,
swap_chain_color_format: wgpu::TextureFormat,
bind_group_layouts: Vec<&wgpu::BindGroupLayout>,
shader_pair: (&wgpu::ShaderModule, &wgpu::ShaderModule),
) -> wgpu::RenderPipeline {
let render_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: bind_group_layouts.as_slice(),
});
let (vertex_shader, fragment_shader) = shader_pair;
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
layout: &render_pipeline_layout,

View File

@@ -21,10 +21,7 @@ impl<T> ResourceCache<T> {
let resources = Vec::new();
let name_to_id = HashMap::new();
Self {
resources,
name_to_id,
}
Self { resources, name_to_id }
}
#[allow(dead_code)]
@@ -49,4 +46,4 @@ impl<T> ResourceCache<T> {
},
}
}
}
}

View File

@@ -14,4 +14,4 @@ pub fn compile_from_glsl(device: &wgpu::Device, path: &str, shader_type: glsl_to
let shader = device.create_shader_module(&compiled);
Ok(shader)
}
}

View File

@@ -1,6 +1,6 @@
use std::fs;
use image::GenericImageView;
use crate::resource_cache::ResourceCache;
use image::GenericImageView;
use std::fs;
pub struct Texture {
pub texture: wgpu::Texture,
@@ -21,11 +21,11 @@ impl Texture {
pub fn from_filepath(device: &wgpu::Device, queue: &mut wgpu::Queue, path: &str) -> Result<Self, failure::Error> {
// Read the raw bytes from the specified file
let bytes = fs::read(path)?;
// Construct and return a Texture from the bytes
Texture::from_bytes(device, queue, &bytes[..])
}
pub fn from_bytes(device: &wgpu::Device, queue: &mut wgpu::Queue, bytes: &[u8]) -> Result<Self, failure::Error> {
// Create an image with the Image library
let image = image::load_from_memory(bytes)?;
@@ -67,7 +67,7 @@ impl Texture {
offset: 0,
bytes_per_row: 4 * dimensions.0,
rows_per_image: dimensions.1,
},
},
wgpu::TextureCopyView {
texture: &texture,
mip_level: 0,
@@ -96,7 +96,11 @@ impl Texture {
lod_max_clamp: 100.0,
compare: wgpu::CompareFunction::Always,
});
Ok(Self { texture, texture_view: view, sampler })
Ok(Self {
texture,
texture_view: view,
sampler,
})
}
}
}

View File

@@ -29,8 +29,16 @@ pub fn window_event(application: &mut Application, control_flow: &mut ControlFlo
fn keyboard_event(application: &mut Application, control_flow: &mut ControlFlow, input: &KeyboardInput) {
match input {
KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Escape), .. } => quit(control_flow),
KeyboardInput { state: ElementState::Pressed, virtual_keycode: Some(VirtualKeyCode::Space), .. } => {
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Escape),
..
} => quit(control_flow),
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Space),
..
} => {
// const VERTICES: &[[f32; 2]] = &[
// [-0.2, 0.0],
// [0.2, 0.0],