Skip to content

Commit 986b079

Browse files
committed
Initial commit
0 parents  commit 986b079

File tree

6 files changed

+261
-0
lines changed

6 files changed

+261
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target
2+
Cargo.lock

Cargo.toml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "bevy_lyon"
3+
version = "0.1.0"
4+
authors = ["Matrixmage <[email protected]>"]
5+
edition = "2018"
6+
license = "MIT"
7+
8+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
9+
10+
[dependencies]
11+
bevy = "0.1.3"
12+
lyon = "0.16.0"
13+
smart-default = "0.6.0"

README.md

Whitespace-only changes.

src/lib.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
pub mod mesh_builder;
2+
pub mod shapes;
3+
4+
#[doc(inline)]
5+
pub use shapes::{
6+
LyonShapeBuilder
7+
};
8+
9+
#[doc(inline)]
10+
pub use mesh_builder::{
11+
BevyIndex,
12+
BevyVertex,
13+
BevyVertexBuffers,
14+
BevyBuffersBuilder,
15+
16+
LyonMeshBuilder,
17+
};

src/mesh_builder.rs

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
use bevy::render::{
2+
mesh::{
3+
VertexAttribute,
4+
Mesh
5+
},
6+
pipeline::PrimitiveTopology,
7+
};
8+
9+
use lyon::{
10+
math::{
11+
self,
12+
Point
13+
},
14+
tessellation as tess,
15+
};
16+
17+
use super::shapes::LyonShapeBuilder;
18+
19+
/// Type alias for the type of a mesh index in bevy.
20+
pub type BevyIndex = u32;
21+
/// Type alias for a `VertexBuffers` of `BevyVertex`'s and `BevyIndex`'s.
22+
pub type BevyVertexBuffers = tess::VertexBuffers<BevyVertex, BevyIndex>;
23+
/// Type alias for a buffer builder that contains the information to properly convert lyon points to `BevyVertex`'s and `BevyIndex`'s.
24+
pub type BevyBuffersBuilder<'a> = tess::BuffersBuilder<'a, BevyVertex, BevyIndex, BevyVertexConstructor>;
25+
26+
/// Builder that provides customizable functionality to create `lyon` tessellated meshes and build them so `bevy` can consume them.
27+
#[derive(Debug, Clone)]
28+
pub struct LyonMeshBuilder
29+
{
30+
geometry: BevyVertexBuffers
31+
}
32+
33+
impl LyonMeshBuilder
34+
{
35+
/// Create a new mesh builder.
36+
pub fn new() -> Self
37+
{
38+
LyonMeshBuilder {
39+
geometry: BevyVertexBuffers::new()
40+
}
41+
}
42+
43+
/// Finish the building and produce the final mesh.
44+
///
45+
/// Uses TriangleStrip as the default primitive topology.
46+
pub fn build(self) -> Mesh
47+
{
48+
self.build_with_topology(PrimitiveTopology::TriangleStrip)
49+
}
50+
51+
/// Finishes a mesh using a custom specified `PrimitiveTopology`.
52+
///
53+
/// Prefer using `build()` as its default works in the vast majority of cases.
54+
pub fn build_with_topology(self, topology: PrimitiveTopology) -> Mesh
55+
{
56+
Mesh {
57+
primitive_topology: topology,
58+
attributes: self.verts_to_attributes(),
59+
indices: Some(self.geometry.indices),
60+
}
61+
}
62+
63+
/// Adds a shape specified by its `LyonShapeBuilder` implementation to the mesh being constructed.
64+
pub fn with(mut self, shape: impl LyonShapeBuilder) -> Self
65+
{
66+
shape.build(&mut self.buffers_builder());
67+
self
68+
}
69+
70+
/// A convenience function that makes a new `LyonMeshBuilder` and builds it with only the single shape provided.
71+
pub fn only(shape: impl LyonShapeBuilder) -> Mesh
72+
{
73+
LyonMeshBuilder::new()
74+
.with(shape)
75+
.build()
76+
}
77+
78+
/// Internal utility function to simplify creation of an output buffer builder.
79+
fn buffers_builder(&mut self) -> tess::BuffersBuilder<BevyVertex, BevyIndex, BevyVertexConstructor>
80+
{
81+
tess::BuffersBuilder::new(&mut self.geometry, BevyVertexConstructor)
82+
}
83+
84+
/// Internal utility function that transforms an iterator of `BevyVertex`'s into the proper array of vertex attributes.
85+
fn verts_to_attributes(&self) -> Vec<VertexAttribute>
86+
{
87+
let mut positions = vec![];
88+
let mut normals = vec![];
89+
let mut uvs = vec![];
90+
91+
for vertex in &self.geometry.vertices
92+
{
93+
positions.push(vertex.pos);
94+
normals.push(vertex.norm);
95+
uvs.push(vertex.uv);
96+
}
97+
98+
vec![
99+
VertexAttribute::position(positions),
100+
VertexAttribute::normal(normals),
101+
VertexAttribute::uv(uvs),
102+
]
103+
}
104+
}
105+
106+
/// Utility type for containing the trait implementations that transforms a lyon point into a `BevyVertex`.
107+
pub struct BevyVertexConstructor;
108+
109+
// TODO: Figure out if uv mapping should be specific for this
110+
impl tess::BasicVertexConstructor<BevyVertex> for BevyVertexConstructor
111+
{
112+
fn new_vertex(&mut self, point: Point) -> BevyVertex
113+
{
114+
point.into()
115+
}
116+
}
117+
118+
// TODO: Figure out if uv mapping should be specific for this
119+
impl tess::FillVertexConstructor<BevyVertex> for BevyVertexConstructor
120+
{
121+
fn new_vertex(&mut self, point: Point, _: tess::FillAttributes) -> BevyVertex
122+
{
123+
point.into()
124+
}
125+
}
126+
127+
// TODO: Figure out if uv mapping should be specific for this
128+
impl tess::StrokeVertexConstructor<BevyVertex> for BevyVertexConstructor
129+
{
130+
fn new_vertex(&mut self, point: Point, _: tess::StrokeAttributes) -> BevyVertex
131+
{
132+
point.into()
133+
}
134+
}
135+
136+
/// Contains all the vertex information needed by bevy to correctly create a mesh.
137+
#[derive(Debug, Clone)]
138+
pub struct BevyVertex
139+
{
140+
pub pos: [f32; 3],
141+
pub norm: [f32; 3],
142+
pub uv: [f32; 2],
143+
}
144+
145+
/// Performs a trivial conversion from a lyon point into a `BevyVertex`
146+
impl From<math::Point> for BevyVertex
147+
{
148+
fn from(point: math::Point) -> Self
149+
{
150+
// In 2d, Z can just be 0
151+
BevyVertex {
152+
pos: [point.x, point.y, 0.0],
153+
norm: [0.0, 0.0, 1.0],
154+
uv: [point.x, point.y],
155+
}
156+
}
157+
}
158+

src/shapes.rs

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use smart_default::*;
2+
3+
use lyon::{
4+
math,
5+
tessellation::{
6+
self as tess,
7+
basic_shapes,
8+
},
9+
};
10+
11+
use super::mesh_builder::BevyBuffersBuilder;
12+
13+
/// Represents something capable of being built into a shape with the `LyonMeshBuilder`.
14+
pub trait LyonShapeBuilder
15+
{
16+
fn build(self, builder: &mut BevyBuffersBuilder);
17+
}
18+
19+
/// Allow all closures and functions that take in a mutable reference to a `BevyBuffersBuilder` to be considered a shape builder.
20+
///
21+
/// Permits ergonomically using a closure (or function) for complicated custom meshes.
22+
impl<F> LyonShapeBuilder for F
23+
where
24+
F: FnOnce(&mut BevyBuffersBuilder)
25+
{
26+
fn build(self, builder: &mut BevyBuffersBuilder) {
27+
self(builder);
28+
}
29+
}
30+
31+
#[derive(Debug, SmartDefault)]
32+
pub struct FillCircle<'a> {
33+
pub center: math::Point,
34+
#[default = 25.0]
35+
pub radius: f32,
36+
#[default(&tess::FillOptions::DEFAULT)]
37+
pub options: &'a tess::FillOptions
38+
}
39+
40+
impl LyonShapeBuilder for FillCircle<'_>
41+
{
42+
fn build(self, builder: &mut BevyBuffersBuilder) {
43+
let _ = basic_shapes::fill_circle(
44+
self.center,
45+
self.radius,
46+
self.options,
47+
builder
48+
);
49+
}
50+
}
51+
52+
#[derive(Debug, SmartDefault)]
53+
pub struct StrokeCircle<'a> {
54+
pub center: math::Point,
55+
#[default = 25.0]
56+
pub radius: f32,
57+
#[default(&tess::StrokeOptions::DEFAULT)]
58+
pub options: &'a tess::StrokeOptions
59+
}
60+
61+
impl LyonShapeBuilder for StrokeCircle<'_>
62+
{
63+
fn build(self, builder: &mut BevyBuffersBuilder) {
64+
let _ = basic_shapes::stroke_circle(
65+
self.center,
66+
self.radius,
67+
self.options,
68+
builder
69+
);
70+
}
71+
}

0 commit comments

Comments
 (0)