Skip to content

Commit bbdee3d

Browse files
committed
Swizzles.
1 parent 7cf60f5 commit bbdee3d

2 files changed

Lines changed: 76 additions & 27 deletions

File tree

crates/processing_pyo3/src/math.rs

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -302,31 +302,26 @@ macro_rules! impl_py_vec {
302302
let py = slf.py();
303303
let chars: Vec<char> = name.chars().collect();
304304
let len = chars.len();
305-
if !(2..=4).contains(&len) {
306-
return Err(PyAttributeError::new_err(format!(
305+
let attr_err = || {
306+
PyAttributeError::new_err(format!(
307307
"'{}' object has no attribute '{}'",
308308
$py_name, name
309-
)));
309+
))
310+
};
311+
if !(2..=4).contains(&len) {
312+
return Err(attr_err());
310313
}
311314
let mut vals = [0.0f32; 4];
312315
for (i, c) in chars.iter().enumerate() {
313-
let idx = match c {
314-
'x' => 0usize,
316+
let idx: usize = match c {
317+
'x' => 0,
315318
'y' => 1,
316319
'z' => 2,
317320
'w' => 3,
318-
_ => {
319-
return Err(PyAttributeError::new_err(format!(
320-
"'{}' object has no attribute '{}'",
321-
$py_name, name
322-
)));
323-
}
321+
_ => return Err(attr_err()),
324322
};
325323
if idx >= $n {
326-
return Err(PyAttributeError::new_err(format!(
327-
"'{}' object has no attribute '{}'",
328-
$py_name, name
329-
)));
324+
return Err(attr_err());
330325
}
331326
vals[i] = slf.0[idx];
332327
}
@@ -566,13 +561,6 @@ impl_py_vec!(PyVec3, "Vec3", 3, [(x, set_x, 0), (y, set_y, 1), (z, set_z, 2)], V
566561
fn truncate(&self) -> PyVec2 {
567562
PyVec2(self.0.truncate())
568563
}
569-
570-
#[getter]
571-
fn xy(&self) -> PyVec2 { PyVec2(self.0.xy()) }
572-
#[getter]
573-
fn xz(&self) -> PyVec2 { PyVec2(self.0.xz()) }
574-
#[getter]
575-
fn yz(&self) -> PyVec2 { PyVec2(self.0.yz()) }
576564
});
577565

578566
impl_py_vec!(
@@ -585,11 +573,6 @@ impl_py_vec!(
585573
fn truncate(&self) -> PyVec3 {
586574
PyVec3(self.0.truncate())
587575
}
588-
589-
#[getter]
590-
fn xy(&self) -> PyVec2 { PyVec2(self.0.xy()) }
591-
#[getter]
592-
fn xyz(&self) -> PyVec3 { PyVec3(self.0.xyz()) }
593576
}
594577
);
595578

tools/generate_stubs/src/main.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,72 @@
1+
use pyo3_introspection::model::{Argument, Arguments, Expr, Function, Module};
12
use pyo3_introspection::{introspect_cdylib, module_stub_files};
23
use std::path::{Path, PathBuf};
34
use std::{env, fs};
45

6+
const SWIZZLE_CHARS: [char; 4] = ['x', 'y', 'z', 'w'];
7+
8+
fn swizzle_props(dim: usize) -> Vec<Function> {
9+
let chars = &SWIZZLE_CHARS[..dim];
10+
let mut out = Vec::new();
11+
for length in 2..=4 {
12+
let count = chars.len().pow(length as u32);
13+
for n in 0..count {
14+
let mut name = String::with_capacity(length);
15+
let mut idx = n;
16+
for _ in 0..length {
17+
name.push(chars[idx % chars.len()]);
18+
idx /= chars.len();
19+
}
20+
out.push(Function {
21+
name,
22+
decorators: vec![Expr::Name {
23+
id: "property".into(),
24+
}],
25+
arguments: Arguments {
26+
positional_only_arguments: vec![Argument {
27+
name: "self".into(),
28+
default_value: None,
29+
annotation: None,
30+
}],
31+
arguments: vec![],
32+
vararg: None,
33+
keyword_only_arguments: vec![],
34+
kwarg: None,
35+
},
36+
returns: Some(Expr::Attribute {
37+
value: Box::new(Expr::Name {
38+
id: "mewnala.math".into(),
39+
}),
40+
attr: format!("Vec{length}"),
41+
}),
42+
is_async: false,
43+
docstring: None,
44+
});
45+
}
46+
}
47+
out
48+
}
49+
50+
fn inject_swizzles(module: &mut Module) {
51+
for math in module.modules.iter_mut().filter(|m| m.name == "math") {
52+
for cls in math.classes.iter_mut() {
53+
let dim = match cls.name.as_str() {
54+
"Vec2" => 2,
55+
"Vec3" => 3,
56+
"Vec4" => 4,
57+
_ => continue,
58+
};
59+
let existing: std::collections::HashSet<String> =
60+
cls.methods.iter().map(|m| m.name.clone()).collect();
61+
cls.methods.extend(
62+
swizzle_props(dim)
63+
.into_iter()
64+
.filter(|m| !existing.contains(&m.name)),
65+
);
66+
}
67+
}
68+
}
69+
570
fn workspace_root() -> &'static Path {
671
Path::new(env!("CARGO_MANIFEST_DIR"))
772
.parent()
@@ -45,6 +110,7 @@ fn main() {
45110
introspect_cdylib(&cdylib_path, "mewnala").expect("Failed to introspect cdylib");
46111

47112
module.incomplete = false;
113+
inject_swizzles(&mut module);
48114

49115
let stubs = module_stub_files(&module);
50116

0 commit comments

Comments
 (0)