From eb6dc3626664905c8285f50cf7b7e09c752bd98b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moon=20Dav=C3=A9?= Date: Sat, 14 Feb 2026 18:00:52 -0500 Subject: [PATCH 1/3] create_directional_light method --- crates/processing_pyo3/examples/lights.py | 26 +++++++++++++++++++++++ crates/processing_pyo3/src/graphics.rs | 21 ++++++++++++++++++ crates/processing_pyo3/src/lib.rs | 17 +++++++++++++-- 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 crates/processing_pyo3/examples/lights.py diff --git a/crates/processing_pyo3/examples/lights.py b/crates/processing_pyo3/examples/lights.py new file mode 100644 index 0000000..cfb1c45 --- /dev/null +++ b/crates/processing_pyo3/examples/lights.py @@ -0,0 +1,26 @@ +from processing import * + +angle = 0.0 + +def setup(): + size(800, 600) + mode_3d() + dir_light = create_directional_light(0.5, 0.24, 1.0, 1500.0) + +def draw(): + global angle + camera_position(100.0, 100.0, 300.0) + camera_look_at(0.0, 0.0, 0.0) + background(220) + + push_matrix() + rotate(angle) + draw_box(100.0, 100.0, 100.0) + pop_matrix() + + angle += 0.02 + + +# TODO: this should happen implicitly on module load somehow +run() + diff --git a/crates/processing_pyo3/src/graphics.rs b/crates/processing_pyo3/src/graphics.rs index 95bef31..6de33f8 100644 --- a/crates/processing_pyo3/src/graphics.rs +++ b/crates/processing_pyo3/src/graphics.rs @@ -23,6 +23,19 @@ impl Drop for Surface { } } +#[pyclass] +#[derive(Debug)] +pub struct Light { + entity: Entity, +} + +// TODO: implement `light_destroy` +// impl Drop for Light { +// fn drop(&mut self) { +// let _ = light_destroy(self.entity); +// } +// } + #[pyclass] #[derive(Debug)] pub struct Image { @@ -308,6 +321,14 @@ impl Graphics { graphics_ortho(self.entity, left, right, bottom, top, near, far) .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) } + + pub fn light_directional(&self, r: f32, g: f32, b: f32, illuminance: f32) -> PyResult { + let color = bevy::color::Color::srgb(r, g, b); + match light_create_directional(self.entity, color, illuminance) { + Ok(light) => Ok(Light { entity: light }), + Err(e) => Err(PyRuntimeError::new_err(format!("{e}"))), + } + } } // TODO: a real color type. or color parser? idk. color is confusing. let's think diff --git a/crates/processing_pyo3/src/lib.rs b/crates/processing_pyo3/src/lib.rs index 3985d24..b85ce90 100644 --- a/crates/processing_pyo3/src/lib.rs +++ b/crates/processing_pyo3/src/lib.rs @@ -11,7 +11,7 @@ mod glfw; mod graphics; -use graphics::{Geometry, Graphics, Image, Topology, get_graphics, get_graphics_mut}; +use graphics::{Geometry, Graphics, Image, Light, Topology, get_graphics, get_graphics_mut}; use pyo3::{exceptions::PyRuntimeError, prelude::*, types::PyTuple}; use std::env; @@ -20,7 +20,7 @@ use std::env; fn processing(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; - m.add_class::()?; + m.add_class::()?; m.add_class::()?; m.add_function(wrap_pyfunction!(size, m)?)?; m.add_function(wrap_pyfunction!(run, m)?)?; @@ -40,6 +40,7 @@ fn processing(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(rect, m)?)?; m.add_function(wrap_pyfunction!(image, m)?)?; m.add_function(wrap_pyfunction!(draw_geometry, m)?)?; + m.add_function(wrap_pyfunction!(create_directional_light, m)?)?; Ok(()) } @@ -223,3 +224,15 @@ fn rect( fn image(module: &Bound<'_, PyModule>, image_file: &str) -> PyResult { get_graphics(module)?.image(image_file) } + +#[pyfunction] +#[pyo3(pass_module, signature = (r, g, b, illuminance))] +fn create_directional_light( + module: &Bound<'_, PyModule>, + r: f32, + g: f32, + b: f32, + illuminance: f32, +) -> PyResult { + get_graphics(module)?.light_directional(r, g, b, illuminance) +} From d0285b9501355049797d770263b732052ae5e8bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moon=20Dav=C3=A9?= Date: Sat, 14 Feb 2026 18:31:45 -0500 Subject: [PATCH 2/3] add point and spot light methods --- crates/processing_pyo3/examples/lights.py | 9 +++++ crates/processing_pyo3/src/graphics.rs | 42 +++++++++++++++++++++++ crates/processing_pyo3/src/lib.rs | 32 +++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/crates/processing_pyo3/examples/lights.py b/crates/processing_pyo3/examples/lights.py index cfb1c45..293077d 100644 --- a/crates/processing_pyo3/examples/lights.py +++ b/crates/processing_pyo3/examples/lights.py @@ -5,8 +5,17 @@ def setup(): size(800, 600) mode_3d() + + # Directional Light dir_light = create_directional_light(0.5, 0.24, 1.0, 1500.0) + # Point Lights + point_light_a = create_point_light(1.0, 0.5, 0.25, 1000000.0, 200.0, 0.5) + point_light_b = create_point_light(0.0, 0.5, 0.75, 2000000.0, 200.0, 0.25) + + # Spot Light + spot_light = create_spot_light(0.25, 0.8, 0.19, 15.0 * 1000000.0, 200.0, 0.84, 0.0, 0.7854) + def draw(): global angle camera_position(100.0, 100.0, 300.0) diff --git a/crates/processing_pyo3/src/graphics.rs b/crates/processing_pyo3/src/graphics.rs index 6de33f8..b0d36e3 100644 --- a/crates/processing_pyo3/src/graphics.rs +++ b/crates/processing_pyo3/src/graphics.rs @@ -329,6 +329,48 @@ impl Graphics { Err(e) => Err(PyRuntimeError::new_err(format!("{e}"))), } } + + pub fn light_point( + &self, + r: f32, + g: f32, + b: f32, + intensity: f32, + range: f32, + radius: f32, + ) -> PyResult { + let color = bevy::color::Color::srgb(r, g, b); + match light_create_point(self.entity, color, intensity, range, radius) { + Ok(light) => Ok(Light { entity: light }), + Err(e) => Err(PyRuntimeError::new_err(format!("{e}"))), + } + } + + pub fn light_spot( + &self, + r: f32, + g: f32, + b: f32, + intensity: f32, + range: f32, + radius: f32, + inner_angle: f32, + outer_angle: f32, + ) -> PyResult { + let color = bevy::color::Color::srgb(r, g, b); + match light_create_spot( + self.entity, + color, + intensity, + range, + radius, + inner_angle, + outer_angle, + ) { + Ok(light) => Ok(Light { entity: light }), + Err(e) => Err(PyRuntimeError::new_err(format!("{e}"))), + } + } } // TODO: a real color type. or color parser? idk. color is confusing. let's think diff --git a/crates/processing_pyo3/src/lib.rs b/crates/processing_pyo3/src/lib.rs index b85ce90..d292b2f 100644 --- a/crates/processing_pyo3/src/lib.rs +++ b/crates/processing_pyo3/src/lib.rs @@ -41,6 +41,8 @@ fn processing(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(image, m)?)?; m.add_function(wrap_pyfunction!(draw_geometry, m)?)?; m.add_function(wrap_pyfunction!(create_directional_light, m)?)?; + m.add_function(wrap_pyfunction!(create_point_light, m)?)?; + m.add_function(wrap_pyfunction!(create_spot_light, m)?)?; Ok(()) } @@ -236,3 +238,33 @@ fn create_directional_light( ) -> PyResult { get_graphics(module)?.light_directional(r, g, b, illuminance) } + +#[pyfunction] +#[pyo3(pass_module, signature = (r, g, b, intensity, range, radius))] +fn create_point_light( + module: &Bound<'_, PyModule>, + r: f32, + g: f32, + b: f32, + intensity: f32, + range: f32, + radius: f32, +) -> PyResult { + get_graphics(module)?.light_point(r, g, b, intensity, range, radius) +} + +#[pyfunction] +#[pyo3(pass_module, signature = (r, g, b, intensity, range, radius, inner_angle, outer_angle))] +fn create_spot_light( + module: &Bound<'_, PyModule>, + r: f32, + g: f32, + b: f32, + intensity: f32, + range: f32, + radius: f32, + inner_angle: f32, + outer_angle: f32, +) -> PyResult { + get_graphics(module)?.light_spot(r, g, b, intensity, range, radius, inner_angle, outer_angle) +} From f632122fdd3586698baedf3a84f6f6dcd9b63723 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moon=20Dav=C3=A9?= Date: Sat, 14 Feb 2026 20:06:43 -0500 Subject: [PATCH 3/3] Added class methods `position` and `look_at` to `Light` --- crates/processing_pyo3/examples/lights.py | 7 +++++++ crates/processing_pyo3/src/graphics.rs | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/crates/processing_pyo3/examples/lights.py b/crates/processing_pyo3/examples/lights.py index 293077d..c5d51c6 100644 --- a/crates/processing_pyo3/examples/lights.py +++ b/crates/processing_pyo3/examples/lights.py @@ -11,10 +11,17 @@ def setup(): # Point Lights point_light_a = create_point_light(1.0, 0.5, 0.25, 1000000.0, 200.0, 0.5) + point_light_a.position(-25.0, 5.0, 51.0) + point_light_a.look_at(0.0, 0.0, 0.0) + point_light_b = create_point_light(0.0, 0.5, 0.75, 2000000.0, 200.0, 0.25) + point_light_b.position(0.0, 5.0, 50.5) + point_light_b.look_at(0.0, 0.0, 0.0) # Spot Light spot_light = create_spot_light(0.25, 0.8, 0.19, 15.0 * 1000000.0, 200.0, 0.84, 0.0, 0.7854) + spot_light.position(40.0, 0.0, 70.0) + spot_light.look_at(0.0, 0.0, 0.0) def draw(): global angle diff --git a/crates/processing_pyo3/src/graphics.rs b/crates/processing_pyo3/src/graphics.rs index b0d36e3..8bd1252 100644 --- a/crates/processing_pyo3/src/graphics.rs +++ b/crates/processing_pyo3/src/graphics.rs @@ -29,6 +29,18 @@ pub struct Light { entity: Entity, } +#[pymethods] +impl Light { + pub fn position(&self, x: f32, y: f32, z: f32) -> PyResult<()> { + transform_set_position(self.entity, x, y, z) + .map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + } + + pub fn look_at(&self, x: f32, y: f32, z: f32) -> PyResult<()> { + transform_look_at(self.entity, x, y, z).map_err(|e| PyRuntimeError::new_err(format!("{e}"))) + } +} + // TODO: implement `light_destroy` // impl Drop for Light { // fn drop(&mut self) {