@@ -673,6 +673,19 @@ mod mewnala {
673673 #[ pymodule_export]
674674 use crate :: color:: PyColor ;
675675
676+ #[ pyfunction( name = "color" ) ]
677+ #[ pyo3( signature = ( * args) ) ]
678+ fn color_ctor ( py : Python < ' _ > , args : & Bound < ' _ , PyTuple > ) -> PyResult < PyColor > {
679+ let parent = py. import ( "mewnala.mewnala" ) ?;
680+ match get_graphics ( & parent) ? {
681+ Some ( g) => g. color ( args) ,
682+ None => {
683+ let mode = crate :: color:: ColorMode :: default ( ) ;
684+ crate :: color:: extract_color_with_mode ( args, & mode) . map ( PyColor :: from)
685+ }
686+ }
687+ }
688+
676689 #[ pyfunction]
677690 fn hex ( s : & str ) -> PyResult < PyColor > {
678691 PyColor :: hex ( s)
@@ -1011,7 +1024,7 @@ mod mewnala {
10111024 return Ok ( ( ) ) ;
10121025 }
10131026
1014- Python :: attach ( |py| {
1027+ let result : PyResult < ( ) > = Python :: attach ( |py| {
10151028 let builtins = PyModule :: import ( py, "builtins" ) ?;
10161029 let locals = builtins. getattr ( "locals" ) ?. call0 ( ) ?;
10171030
@@ -1132,7 +1145,13 @@ mod mewnala {
11321145 }
11331146
11341147 Ok ( ( ) )
1135- } )
1148+ } ) ;
1149+
1150+ // tear the app down here while the TLS is still alive; the eager
1151+ // TLS destructor aborts inside a Bevy resource drop
1152+ let _ = :: processing:: exit ( 0 ) ;
1153+
1154+ result
11361155 }
11371156
11381157 #[ pyfunction]
@@ -1290,21 +1309,6 @@ mod mewnala {
12901309 graphics ! ( module) . draw_geometry ( & * geometry. extract :: < PyRef < Geometry > > ( ) ?)
12911310 }
12921311
1293- #[ pyfunction( name = "color" ) ]
1294- #[ pyo3( pass_module, signature = ( * args) ) ]
1295- fn create_color (
1296- module : & Bound < ' _ , PyModule > ,
1297- args : & Bound < ' _ , PyTuple > ,
1298- ) -> PyResult < super :: color:: PyColor > {
1299- match get_graphics ( module) ? {
1300- Some ( g) => g. color ( args) ,
1301- None => {
1302- let mode = super :: color:: ColorMode :: default ( ) ;
1303- super :: color:: extract_color_with_mode ( args, & mode) . map ( super :: color:: PyColor :: from)
1304- }
1305- }
1306- }
1307-
13081312 #[ pyfunction]
13091313 #[ pyo3( pass_module, signature = ( * args) ) ]
13101314 fn background ( module : & Bound < ' _ , PyModule > , args : & Bound < ' _ , PyTuple > ) -> PyResult < ( ) > {
@@ -1484,46 +1488,75 @@ mod mewnala {
14841488 graphics. create_image ( width, height)
14851489 }
14861490
1491+ fn apply_light_transform (
1492+ light : & Light ,
1493+ position : Option < super :: math:: Vec3Like > ,
1494+ look_at : Option < super :: math:: Vec3Like > ,
1495+ ) -> PyResult < ( ) > {
1496+ if let Some ( p) = position {
1497+ :: processing:: prelude:: transform_set_position ( light. entity , p. into_vec3 ( ) )
1498+ . map_err ( |e| PyRuntimeError :: new_err ( format ! ( "{e}" ) ) ) ?;
1499+ }
1500+ if let Some ( la) = look_at {
1501+ :: processing:: prelude:: transform_look_at ( light. entity , la. into_vec3 ( ) )
1502+ . map_err ( |e| PyRuntimeError :: new_err ( format ! ( "{e}" ) ) ) ?;
1503+ }
1504+ Ok ( ( ) )
1505+ }
1506+
14871507 #[ pyfunction]
1488- #[ pyo3( pass_module) ]
1489- fn create_directional_light (
1508+ #[ pyo3( pass_module, signature = ( color , illuminance , * , position= None , look_at= None ) ) ]
1509+ fn directional_light (
14901510 module : & Bound < ' _ , PyModule > ,
14911511 color : super :: color:: ColorLike ,
14921512 illuminance : f32 ,
1513+ position : Option < super :: math:: Vec3Like > ,
1514+ look_at : Option < super :: math:: Vec3Like > ,
14931515 ) -> PyResult < Light > {
14941516 let graphics =
14951517 get_graphics ( module) ?. ok_or_else ( || PyRuntimeError :: new_err ( "call size() first" ) ) ?;
1496- graphics. light_directional ( color, illuminance)
1518+ let light = graphics. light_directional ( color, illuminance) ?;
1519+ apply_light_transform ( & light, position, look_at) ?;
1520+ Ok ( light)
14971521 }
14981522
14991523 #[ pyfunction]
1500- #[ pyo3( pass_module) ]
1501- fn create_point_light (
1524+ #[ pyo3( pass_module, signature = ( color , intensity , range , radius , * , position= None , look_at= None ) ) ]
1525+ fn point_light (
15021526 module : & Bound < ' _ , PyModule > ,
15031527 color : super :: color:: ColorLike ,
15041528 intensity : f32 ,
15051529 range : f32 ,
15061530 radius : f32 ,
1531+ position : Option < super :: math:: Vec3Like > ,
1532+ look_at : Option < super :: math:: Vec3Like > ,
15071533 ) -> PyResult < Light > {
15081534 let graphics =
15091535 get_graphics ( module) ?. ok_or_else ( || PyRuntimeError :: new_err ( "call size() first" ) ) ?;
1510- graphics. light_point ( color, intensity, range, radius)
1536+ let light = graphics. light_point ( color, intensity, range, radius) ?;
1537+ apply_light_transform ( & light, position, look_at) ?;
1538+ Ok ( light)
15111539 }
15121540
15131541 #[ pyfunction]
1514- #[ pyo3( pass_module) ]
1515- fn create_spot_light (
1542+ #[ pyo3( pass_module, signature = ( color , intensity , range , radius , inner_angle , outer_angle , * , position= None , look_at= None ) ) ]
1543+ fn spot_light (
15161544 module : & Bound < ' _ , PyModule > ,
15171545 color : super :: color:: ColorLike ,
15181546 intensity : f32 ,
15191547 range : f32 ,
15201548 radius : f32 ,
15211549 inner_angle : f32 ,
15221550 outer_angle : f32 ,
1551+ position : Option < super :: math:: Vec3Like > ,
1552+ look_at : Option < super :: math:: Vec3Like > ,
15231553 ) -> PyResult < Light > {
15241554 let graphics =
15251555 get_graphics ( module) ?. ok_or_else ( || PyRuntimeError :: new_err ( "call size() first" ) ) ?;
1526- graphics. light_spot ( color, intensity, range, radius, inner_angle, outer_angle)
1556+ let light =
1557+ graphics. light_spot ( color, intensity, range, radius, inner_angle, outer_angle) ?;
1558+ apply_light_transform ( & light, position, look_at) ?;
1559+ Ok ( light)
15271560 }
15281561
15291562 #[ pyfunction( name = "sphere" ) ]
0 commit comments