nightshade 0.8.0

A cross-platform data-oriented game engine.
Documentation
use crate::ecs::world::World;
use crate::mcp::McpResponse;

pub(crate) fn mcp_spawn_hud_text(
    world: &mut World,
    request: crate::mcp::SpawnHudTextRequest,
) -> McpResponse {
    use crate::ecs::text::components::{HudAnchor, HudText, TextAlignment, TextProperties};
    use crate::ecs::world::{HUD_TEXT, NAME};

    if world.resources.entity_names.contains_key(&request.name) {
        return McpResponse::Error(format!("Entity '{}' already exists", request.name));
    }

    let text_index = world.resources.text_cache.add_text(request.text.clone());

    let anchor_enum = request
        .anchor
        .as_ref()
        .map(|a| match a.to_lowercase().as_str() {
            "top_left" => HudAnchor::TopLeft,
            "top_center" => HudAnchor::TopCenter,
            "top_right" => HudAnchor::TopRight,
            "center_left" => HudAnchor::CenterLeft,
            "center" => HudAnchor::Center,
            "center_right" => HudAnchor::CenterRight,
            "bottom_left" => HudAnchor::BottomLeft,
            "bottom_center" => HudAnchor::BottomCenter,
            "bottom_right" => HudAnchor::BottomRight,
            _ => HudAnchor::Center,
        })
        .unwrap_or(HudAnchor::Center);

    let text_alignment = request
        .alignment
        .as_ref()
        .map(|a| match a.to_lowercase().as_str() {
            "left" => TextAlignment::Left,
            "center" => TextAlignment::Center,
            "right" => TextAlignment::Right,
            _ => TextAlignment::Left,
        })
        .unwrap_or(TextAlignment::Left);

    let mut properties = TextProperties::default();
    if let Some(size) = request.font_size {
        properties.font_size = size;
    }
    if let Some(c) = request.color {
        properties.color = nalgebra_glm::Vec4::new(c[0], c[1], c[2], c[3]);
    }
    properties.alignment = text_alignment;
    if let Some(width) = request.outline_width {
        properties.outline_width = width;
    }
    if let Some(oc) = request.outline_color {
        properties.outline_color = nalgebra_glm::Vec4::new(oc[0], oc[1], oc[2], oc[3]);
    }

    let pos = request
        .position
        .map(|p| nalgebra_glm::Vec2::new(p[0], p[1]))
        .unwrap_or(nalgebra_glm::Vec2::zeros());

    let entity = world.spawn_entities(NAME | HUD_TEXT, 1)[0];
    world.set_name(
        entity,
        crate::ecs::name::components::Name(request.name.clone()),
    );
    world.set_hud_text(
        entity,
        HudText::new(text_index)
            .with_properties(properties)
            .with_position(pos)
            .with_anchor(anchor_enum),
    );

    world
        .resources
        .entity_names
        .insert(request.name.clone(), entity);
    McpResponse::Success(format!("Spawned HUD text '{}'", request.name))
}

pub(crate) fn mcp_set_hud_text(
    world: &mut World,
    request: crate::mcp::SetHudTextRequest,
) -> Result<McpResponse, McpResponse> {
    use crate::ecs::text::components::{HudAnchor, TextAlignment};

    let entity = super::resolve_entity(world, &request.name)?;

    if let Some(new_text) = request.text {
        let text_index = world.resources.text_cache.add_text(new_text);
        if let Some(hud_text) = world.get_hud_text_mut(entity) {
            hud_text.set_text_index(text_index);
        }
    }

    if let Some(hud_text) = world.get_hud_text_mut(entity) {
        if let Some(pos) = request.position {
            hud_text.set_position(nalgebra_glm::Vec2::new(pos[0], pos[1]));
        }
        if let Some(a) = request.anchor {
            let anchor_enum = match a.to_lowercase().as_str() {
                "top_left" => HudAnchor::TopLeft,
                "top_center" => HudAnchor::TopCenter,
                "top_right" => HudAnchor::TopRight,
                "center_left" => HudAnchor::CenterLeft,
                "center" => HudAnchor::Center,
                "center_right" => HudAnchor::CenterRight,
                "bottom_left" => HudAnchor::BottomLeft,
                "bottom_center" => HudAnchor::BottomCenter,
                "bottom_right" => HudAnchor::BottomRight,
                _ => HudAnchor::Center,
            };
            hud_text.set_anchor(anchor_enum);
        }
        if let Some(size) = request.font_size {
            hud_text.properties.font_size = size;
            hud_text.dirty = true;
        }
        if let Some(c) = request.color {
            hud_text.properties.color = nalgebra_glm::Vec4::new(c[0], c[1], c[2], c[3]);
            hud_text.dirty = true;
        }
        if let Some(a) = request.alignment {
            hud_text.properties.alignment = match a.to_lowercase().as_str() {
                "left" => TextAlignment::Left,
                "center" => TextAlignment::Center,
                "right" => TextAlignment::Right,
                _ => TextAlignment::Left,
            };
            hud_text.dirty = true;
        }
        if let Some(width) = request.outline_width {
            hud_text.properties.outline_width = width;
            hud_text.dirty = true;
        }
        if let Some(oc) = request.outline_color {
            hud_text.properties.outline_color = nalgebra_glm::Vec4::new(oc[0], oc[1], oc[2], oc[3]);
            hud_text.dirty = true;
        }
    } else {
        return Err(McpResponse::Error(format!(
            "Entity '{}' has no HUD text component",
            request.name
        )));
    }

    Ok(McpResponse::Success(format!(
        "Updated HUD text '{}'",
        request.name
    )))
}

pub(crate) fn mcp_spawn_3d_text(
    world: &mut World,
    request: crate::mcp::Spawn3dTextRequest,
) -> McpResponse {
    use crate::ecs::text::components::Text;
    use crate::ecs::transform::components::LocalTransform;
    use crate::ecs::world::{GLOBAL_TRANSFORM, LOCAL_TRANSFORM, LOCAL_TRANSFORM_DIRTY, NAME, TEXT};

    let font_size = request.font_size.unwrap_or(32.0);
    let color = request.color.unwrap_or([1.0, 1.0, 1.0, 1.0]);
    let billboard = request.billboard.unwrap_or(false);

    let text_index = world.resources.text_cache.add_text(&request.text);

    let entity = world
        .spawn_entities(
            NAME | LOCAL_TRANSFORM | LOCAL_TRANSFORM_DIRTY | GLOBAL_TRANSFORM | TEXT,
            1,
        )
        .into_iter()
        .next()
        .unwrap();

    let pos = nalgebra_glm::Vec3::new(
        request.position[0],
        request.position[1],
        request.position[2],
    );
    world.set_local_transform(entity, LocalTransform::from_translation(pos));

    let mut text_component = Text::new(text_index);
    text_component.billboard = billboard;
    text_component.properties.font_size = font_size;
    text_component.properties.color =
        nalgebra_glm::Vec4::new(color[0], color[1], color[2], color[3]);
    world.set_text(entity, text_component);
    world.set_name(
        entity,
        crate::ecs::name::components::Name(request.name.clone()),
    );
    world
        .resources
        .entity_names
        .insert(request.name.clone(), entity);

    McpResponse::Success(format!("Spawned 3D text '{}'", request.name))
}