use crate::ecs::world::World;
use crate::mcp::McpResponse;
pub(crate) fn mcp_spawn_light(
world: &mut World,
request: crate::mcp::SpawnLightRequest,
) -> McpResponse {
use crate::ecs::light::components::{Light, LightType};
use crate::ecs::world::{
GLOBAL_TRANSFORM, LIGHT, LOCAL_TRANSFORM, LOCAL_TRANSFORM_DIRTY, NAME,
};
if world.resources.entity_names.contains_key(&request.name) {
return McpResponse::Error(format!("Entity '{}' already exists", request.name));
}
let light_type_enum = match request.light_type.to_lowercase().as_str() {
"point" => LightType::Point,
"spot" => LightType::Spot,
"directional" => LightType::Directional,
_ => {
return McpResponse::Error(format!("Unknown light type: {}", request.light_type));
}
};
let entity = world.spawn_entities(
NAME | LOCAL_TRANSFORM | LOCAL_TRANSFORM_DIRTY | GLOBAL_TRANSFORM | LIGHT,
1,
)[0];
world.core.set_name(
entity,
crate::ecs::name::components::Name(request.name.clone()),
);
world.core.set_local_transform(
entity,
crate::ecs::transform::components::LocalTransform {
translation: nalgebra_glm::Vec3::new(
request.position[0],
request.position[1],
request.position[2],
),
rotation: nalgebra_glm::Quat::identity(),
scale: nalgebra_glm::Vec3::new(1.0, 1.0, 1.0),
},
);
world.core.set_local_transform_dirty(
entity,
crate::ecs::transform::components::LocalTransformDirty,
);
world.core.set_global_transform(
entity,
crate::ecs::transform::components::GlobalTransform::default(),
);
let color_vec = request
.color
.map(|c| nalgebra_glm::Vec3::new(c[0], c[1], c[2]))
.unwrap_or(nalgebra_glm::Vec3::new(1.0, 1.0, 1.0));
world.core.set_light(
entity,
Light {
light_type: light_type_enum,
color: color_vec,
intensity: request.intensity.unwrap_or(5.0),
range: request.range.unwrap_or(100.0),
inner_cone_angle: request
.inner_cone_angle
.map(|a| a.to_radians())
.unwrap_or(std::f32::consts::PI / 6.0),
outer_cone_angle: request
.outer_cone_angle
.map(|a| a.to_radians())
.unwrap_or(std::f32::consts::PI / 4.0),
cast_shadows: request.cast_shadows.unwrap_or(false),
shadow_bias: 0.0005,
},
);
world
.resources
.entity_names
.insert(request.name.clone(), entity);
McpResponse::Success(format!(
"Spawned {} light '{}'",
request.light_type, request.name
))
}
pub(crate) fn mcp_set_light(
world: &mut World,
request: crate::mcp::SetLightRequest,
) -> Result<McpResponse, McpResponse> {
let entity = super::resolve_entity(world, &request.name)?;
let Some(light) = world.core.get_light_mut(entity) else {
return Err(McpResponse::Error(format!(
"Entity '{}' has no light component",
request.name
)));
};
if let Some(c) = request.color {
light.color = nalgebra_glm::Vec3::new(c[0], c[1], c[2]);
}
if let Some(i) = request.intensity {
light.intensity = i;
}
if let Some(r) = request.range {
light.range = r;
}
if let Some(angle) = request.inner_cone_angle {
light.inner_cone_angle = angle.to_radians();
}
if let Some(angle) = request.outer_cone_angle {
light.outer_cone_angle = angle.to_radians();
}
if let Some(shadows) = request.cast_shadows {
light.cast_shadows = shadows;
}
if let Some(bias) = request.shadow_bias {
light.shadow_bias = bias;
}
Ok(McpResponse::Success(format!(
"Updated light '{}'",
request.name
)))
}
pub(crate) fn mcp_set_camera(
world: &mut World,
request: crate::mcp::SetCameraRequest,
) -> McpResponse {
use crate::ecs::camera::components::Projection;
let Some(camera_entity) = world.resources.active_camera else {
return McpResponse::Error("No active camera".to_string());
};
if let Some(pos) = request.position
&& let Some(transform) = world.core.get_local_transform_mut(camera_entity)
{
transform.translation = nalgebra_glm::Vec3::new(pos[0], pos[1], pos[2]);
crate::ecs::transform::commands::mark_local_transform_dirty(world, camera_entity);
}
if let Some(target_pos) = request.target
&& let Some(transform) = world.core.get_local_transform_mut(camera_entity)
{
let eye = transform.translation;
let target = nalgebra_glm::Vec3::new(target_pos[0], target_pos[1], target_pos[2]);
let up = nalgebra_glm::Vec3::new(0.0, 1.0, 0.0);
let view = nalgebra_glm::look_at(&eye, &target, &up);
let rotation_matrix = view.fixed_view::<3, 3>(0, 0).transpose();
transform.rotation = nalgebra_glm::mat3_to_quat(&rotation_matrix);
crate::ecs::transform::commands::mark_local_transform_dirty(world, camera_entity);
}
if let Some(fov_degrees) = request.fov
&& let Some(camera) = world.core.get_camera_mut(camera_entity)
&& let Projection::Perspective(ref mut perspective) = camera.projection
{
perspective.y_fov_rad = fov_degrees.to_radians();
}
McpResponse::Success("Camera updated".to_string())
}