mittens_engine/engine/ecs/system/
light_system.rs1use crate::engine::ecs::component::DirectionalLightComponent;
2use crate::engine::ecs::component::PointLightComponent;
3use crate::engine::ecs::component::{AmbientLightComponent, ColorComponent};
4use crate::engine::ecs::system::System;
5use crate::engine::ecs::system::TransformSystem;
6use crate::engine::ecs::{ComponentId, World};
7use crate::engine::graphics::VisualWorld;
8use crate::engine::user_input::InputState;
9
10#[derive(Debug, Default)]
14pub struct LightSystem;
15
16impl LightSystem {
17 pub fn new() -> Self {
18 Self
19 }
20
21 pub fn register_light(
22 &mut self,
23 world: &mut World,
24 visuals: &mut VisualWorld,
25 component: ComponentId,
26 ) {
27 let position_ws =
28 TransformSystem::world_position(world, component).unwrap_or([0.0, 0.0, 0.0]);
29
30 if let Some(light) = world.get_component_by_id_as::<PointLightComponent>(component) {
31 visuals.upsert_point_light(
32 component,
33 crate::engine::graphics::visual_world::VisualPointLight {
34 light_type: 1,
35 position_ws,
36 intensity: light.intensity,
37 distance: light.distance,
38 color: light.color,
39 },
40 );
41 return;
42 }
43
44 if let Some(light) = world.get_component_by_id_as::<DirectionalLightComponent>(component) {
45 let color = world
46 .children_of(component)
47 .iter()
48 .find_map(|&ch| {
49 world
50 .get_component_by_id_as::<ColorComponent>(ch)
51 .map(|c| [c.rgba[0], c.rgba[1], c.rgba[2]])
52 })
53 .unwrap_or(light.color);
54 visuals.upsert_point_light(
56 component,
57 crate::engine::graphics::visual_world::VisualPointLight {
58 light_type: 2,
59 position_ws,
60 intensity: light.intensity,
61 distance: 0.0,
62 color,
63 },
64 );
65 }
66 }
67
68 pub fn register_ambient_light(
69 &mut self,
70 world: &mut World,
71 visuals: &mut VisualWorld,
72 component: ComponentId,
73 ) {
74 let Some(ambient) = world.get_component_by_id_as::<AmbientLightComponent>(component) else {
75 return;
76 };
77
78 let rgb = world
80 .children_of(component)
81 .iter()
82 .find_map(|&ch| {
83 world
84 .get_component_by_id_as::<ColorComponent>(ch)
85 .map(|c| [c.rgba[0], c.rgba[1], c.rgba[2]])
86 })
87 .unwrap_or(ambient.rgb);
88
89 visuals.set_ambient_light(rgb);
91 }
92
93 pub fn transform_changed(
97 &mut self,
98 world: &mut World,
99 visuals: &mut VisualWorld,
100 component: ComponentId,
101 ) {
102 let mut _visited_nodes = 0usize;
103 let mut _updated_lights = 0usize;
104
105 let mut stack = vec![component];
106 while let Some(node) = stack.pop() {
107 _visited_nodes += 1;
108 for &child in world.children_of(node) {
109 stack.push(child);
110
111 let position_ws =
112 TransformSystem::world_position(world, child).unwrap_or([0.0, 0.0, 0.0]);
113
114 if let Some(light) = world.get_component_by_id_as::<PointLightComponent>(child) {
115 _updated_lights += 1;
116 visuals.upsert_point_light(
117 child,
118 crate::engine::graphics::visual_world::VisualPointLight {
119 light_type: 1,
120 position_ws,
121 intensity: light.intensity,
122 distance: light.distance,
123 color: light.color,
124 },
125 );
126 continue;
127 }
128
129 if let Some(light) =
130 world.get_component_by_id_as::<DirectionalLightComponent>(child)
131 {
132 _updated_lights += 1;
133 let color = world
134 .children_of(child)
135 .iter()
136 .find_map(|&ch| {
137 world
138 .get_component_by_id_as::<ColorComponent>(ch)
139 .map(|c| [c.rgba[0], c.rgba[1], c.rgba[2]])
140 })
141 .unwrap_or(light.color);
142 visuals.upsert_point_light(
143 child,
144 crate::engine::graphics::visual_world::VisualPointLight {
145 light_type: 2,
146 position_ws,
147 intensity: light.intensity,
148 distance: 0.0,
149 color,
150 },
151 );
152 }
153 }
154 }
155 }
156}
157
158impl System for LightSystem {
159 fn tick(
160 &mut self,
161 _world: &mut World,
162 _visuals: &mut VisualWorld,
163 _input: &InputState,
164 _dt_sec: f32,
165 ) {
166 }
168}