Complete the list of generated swizzle operators.

This commit is contained in:
Egor Larionov 2017-09-30 14:41:17 -07:00
parent 985db6b604
commit cc7047555d
3 changed files with 42 additions and 21 deletions

View file

@ -6,56 +6,63 @@ use std::string::String;
/// Generate the name of the swizzle function and what it returns. /// Generate the name of the swizzle function and what it returns.
/// NOTE: This function assumes that variables are in ASCII format /// NOTE: This function assumes that variables are in ASCII format
fn gen_swizzle_nth(variables: &'static str, mut i: usize) -> (String, String) { fn gen_swizzle_nth<'a>(variables: &'a str, mut i: usize) -> Option<(String, String)> {
debug_assert!(i > 0); // zeroth permutation is empty
let mut swizzle_impl = String::new(); let mut swizzle_impl = String::new();
let mut swizzle = String::new(); let mut swizzle = String::new();
let n = variables.len(); let n = variables.len()+1;
for _ in 0..n { for _ in 0..variables.len() {
let c = variables.as_bytes()[i%n] as char; if i == 0 { break; }
if i % n == 0 { return None; }
let c = variables.as_bytes()[i%n - 1] as char;
swizzle.push(c); swizzle.push(c);
swizzle_impl.push_str(&format!("self.{}, ", c)); swizzle_impl.push_str(&format!("self.{}, ", c));
i = i/n; i = i/n;
} }
(swizzle, swizzle_impl) Some((swizzle, swizzle_impl))
} }
/// This script generates the swizzle operators that are included in macros.rs
/// NOTE: This function assumes that variables are in ASCII format /// NOTE: This function assumes that variables are in ASCII format
fn gen_swizzle_functions(variables: &'static str) -> String { fn gen_swizzle_functions(variables: &'static str) -> String {
let n = variables.len(); let n = variables.len();
let vec_type = format!("$vector_type{}", n);
let mut result = String::new(); let mut result = String::new();
let nn = n.pow(n as u32); let nn = (n+1).pow(n as u32);
for i in 0..nn { for i in 1..nn {
let (swizzle_name, swizzle_impl) = gen_swizzle_nth(variables, i); if let Some((swizzle_name, swizzle_impl)) = gen_swizzle_nth(variables, i) {
result.push_str( let vec_type = format!("$vector_type{}", swizzle_name.len());
&format!(" #[inline] pub fn {0}(&self) -> {2}<$S> {{ {2}::new({1}) }}\n", result.push_str(
swizzle_name, swizzle_impl, vec_type)); &format!(" #[inline] pub fn {0}(&self) -> {2}<$S> {{ {2}::new({1}) }}\n",
swizzle_name, swizzle_impl, vec_type));
}
} }
result result
} }
/// This script generates the macro for building swizzle operators for multidimensional
/// vectors and points. This macro is included in macros.rs
fn main() { fn main() {
// The following scripts generates a macro for building swizzle operators for multidimensional // save the file to output directory
// vectors or points.
let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap();
let swizzle_file_path = Path::new(&out_dir).join("swizzle_operator_macro.rs"); let swizzle_file_path = Path::new(&out_dir).join("swizzle_operator_macro.rs");
// This is the string representing the generated macro
let data = format!( let data = format!(
"/// Generate glm/glsl style swizzle operators "/// Generate glm/glsl style swizzle operators
macro_rules! impl_swizzle_functions {{ macro_rules! impl_swizzle_functions {{
($vector_type2:ident, $S:ident, xy) => {{ ($vector_type1:ident, $S:ident, x) => {{
{x}
}};
($vector_type1:ident, $vector_type2:ident, $S:ident, xy) => {{
{xy} {xy}
}}; }};
($vector_type2:ident, $vector_type3:ident, $S:ident, xyz) => {{ ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $S:ident, xyz) => {{
impl_swizzle_functions!($vector_type2, $S, xy);
{xyz} {xyz}
}}; }};
($vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyzw) => {{ ($vector_type1:ident, $vector_type2:ident, $vector_type3:ident, $vector_type4:ident, $S:ident, xyzw) => {{
impl_swizzle_functions!($vector_type2, $vector_type3, $S, xyz);
{xyzw} {xyzw}
}}; }};
}}", xy=gen_swizzle_functions("xy"), }}", x=gen_swizzle_functions("x"),
xy=gen_swizzle_functions("xy"),
xyz=gen_swizzle_functions("xyz"), xyz=gen_swizzle_functions("xyz"),
xyzw=gen_swizzle_functions("xyzw")); xyzw=gen_swizzle_functions("xyzw"));
let mut f = File::create(swizzle_file_path) let mut f = File::create(swizzle_file_path)

View file

@ -69,6 +69,8 @@ impl<S: BaseNum> Point1<S> {
pub fn new(x: S) -> Point1<S> { pub fn new(x: S) -> Point1<S> {
Point1 { x: x } Point1 { x: x }
} }
impl_swizzle_functions!(Point1, S, x);
} }
impl<S: BaseNum> Point2<S> { impl<S: BaseNum> Point2<S> {
@ -76,6 +78,8 @@ impl<S: BaseNum> Point2<S> {
pub fn new(x: S, y: S) -> Point2<S> { pub fn new(x: S, y: S) -> Point2<S> {
Point2 { x: x, y: y } Point2 { x: x, y: y }
} }
impl_swizzle_functions!(Point1, Point2, S, xy);
} }
impl<S: BaseNum> Point3<S> { impl<S: BaseNum> Point3<S> {
@ -83,6 +87,8 @@ impl<S: BaseNum> Point3<S> {
pub fn new(x: S, y: S, z: S) -> Point3<S> { pub fn new(x: S, y: S, z: S) -> Point3<S> {
Point3 { x: x, y: y, z: z } Point3 { x: x, y: y, z: z }
} }
impl_swizzle_functions!(Point1, Point2, Point3, S, xyz);
} }
impl<S: BaseNum> Point3<S> { impl<S: BaseNum> Point3<S> {

View file

@ -605,6 +605,8 @@ impl<S: BaseNum> Vector1<S> {
pub fn unit_x() -> Vector1<S> { pub fn unit_x() -> Vector1<S> {
Vector1::new(S::one()) Vector1::new(S::one())
} }
impl_swizzle_functions!(Vector1, S, x);
} }
impl<S: BaseNum> Vector2<S> { impl<S: BaseNum> Vector2<S> {
@ -632,6 +634,8 @@ impl<S: BaseNum> Vector2<S> {
pub fn extend(self, z: S) -> Vector3<S> { pub fn extend(self, z: S) -> Vector3<S> {
Vector3::new(self.x, self.y, z) Vector3::new(self.x, self.y, z)
} }
impl_swizzle_functions!(Vector1, Vector2, S, xy);
} }
impl<S: BaseNum> Vector3<S> { impl<S: BaseNum> Vector3<S> {
@ -674,6 +678,8 @@ impl<S: BaseNum> Vector3<S> {
pub fn truncate(self) -> Vector2<S> { pub fn truncate(self) -> Vector2<S> {
Vector2::new(self.x, self.y) Vector2::new(self.x, self.y)
} }
impl_swizzle_functions!(Vector1, Vector2, Vector3, S, xyz);
} }
impl<S: BaseNum> Vector4<S> { impl<S: BaseNum> Vector4<S> {
@ -718,6 +724,8 @@ impl<S: BaseNum> Vector4<S> {
_ => panic!("{:?} is out of range", n), _ => panic!("{:?} is out of range", n),
} }
} }
impl_swizzle_functions!(Vector1, Vector2, Vector3, Vector4, S, xyzw);
} }
/// Dot product of two vectors. /// Dot product of two vectors.