forked from processing/libprocessing
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlayout.rs
More file actions
117 lines (100 loc) · 3.33 KB
/
layout.rs
File metadata and controls
117 lines (100 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use bevy::prelude::*;
use super::BuiltinAttributes;
use processing_core::error::{ProcessingError, Result};
// bevy requires an attribute id for each unique vertex attribute. we don't really want to
// expose this to users, so we hash the attribute name to generate a unique id. in theory
// there could be collisions, but in practice this should be fine?
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash
const FNV1A_OFFSET_BASIS: u64 = 0xcbf29ce484222325;
const FNV1A_PRIME: u64 = 0x100000001b3;
pub const fn hash_attr_name(s: &str) -> u64 {
let bytes = s.as_bytes();
let mut hash = FNV1A_OFFSET_BASIS;
let mut i = 0;
while i < bytes.len() {
hash ^= bytes[i] as u64;
hash = hash.wrapping_mul(FNV1A_PRIME);
i += 1;
}
hash
}
#[derive(Component, Clone, Debug, Default)]
pub struct VertexLayout {
attributes: Vec<Entity>,
}
impl VertexLayout {
pub fn new() -> Self {
Self {
attributes: Vec::new(),
}
}
pub fn with_attributes(attrs: Vec<Entity>) -> Self {
Self { attributes: attrs }
}
pub fn attributes(&self) -> &[Entity] {
&self.attributes
}
pub fn push(&mut self, attr: Entity) {
if !self.attributes.contains(&attr) {
self.attributes.push(attr);
}
}
pub fn has_attribute(&self, attr_entity: Entity) -> bool {
self.attributes.contains(&attr_entity)
}
}
pub fn create(In(()): In<()>, mut commands: Commands) -> Entity {
commands.spawn(VertexLayout::new()).id()
}
pub fn create_default(world: &mut World) -> Entity {
let builtins = world.resource::<BuiltinAttributes>();
let attrs = vec![
builtins.position,
builtins.normal,
builtins.color,
builtins.uv,
];
world.spawn(VertexLayout::with_attributes(attrs)).id()
}
pub fn add_position(world: &mut World, entity: Entity) -> Result<()> {
let position = world.resource::<BuiltinAttributes>().position;
let mut layout = world
.get_mut::<VertexLayout>(entity)
.ok_or(ProcessingError::LayoutNotFound)?;
layout.push(position);
Ok(())
}
pub fn add_normal(world: &mut World, entity: Entity) -> Result<()> {
let normal = world.resource::<BuiltinAttributes>().normal;
let mut layout = world
.get_mut::<VertexLayout>(entity)
.ok_or(ProcessingError::LayoutNotFound)?;
layout.push(normal);
Ok(())
}
pub fn add_color(world: &mut World, entity: Entity) -> Result<()> {
let color = world.resource::<BuiltinAttributes>().color;
let mut layout = world
.get_mut::<VertexLayout>(entity)
.ok_or(ProcessingError::LayoutNotFound)?;
layout.push(color);
Ok(())
}
pub fn add_uv(world: &mut World, entity: Entity) -> Result<()> {
let uv = world.resource::<BuiltinAttributes>().uv;
let mut layout = world
.get_mut::<VertexLayout>(entity)
.ok_or(ProcessingError::LayoutNotFound)?;
layout.push(uv);
Ok(())
}
pub fn add_attribute(world: &mut World, layout_entity: Entity, attr_entity: Entity) -> Result<()> {
let mut layout = world
.get_mut::<VertexLayout>(layout_entity)
.ok_or(ProcessingError::LayoutNotFound)?;
layout.push(attr_entity);
Ok(())
}
pub fn destroy(In(entity): In<Entity>, mut commands: Commands) {
commands.entity(entity).despawn();
}