nightshade-editor 0.14.2

Interactive map editor for the Nightshade game engine
use crate::ecs::{EditorMode, EditorWorld};
use nightshade::ecs::world::PREFAB_SOURCE;
use nightshade::prelude::*;

pub fn tick_mode(editor_world: &mut EditorWorld, world: &World, shell_active: bool) {
    if shell_active || crate::systems::input::ui_capturing(world) {
        editor_world.resources.mode.tab_was_pressed = false;
        return;
    }
    let pressed = world.resources.input.keyboard.is_key_pressed(KeyCode::Tab);
    let was_pressed = editor_world.resources.mode.tab_was_pressed;
    editor_world.resources.mode.tab_was_pressed = pressed;
    if !pressed || was_pressed {
        return;
    }
    let next = match editor_world.resources.mode.mode {
        EditorMode::Object => {
            let Some(selected) = editor_world.resources.ui.selected_entity else {
                return;
            };
            let Some(target) = nearest_prefab_instance(world, selected) else {
                return;
            };
            EditorMode::Edit { target }
        }
        EditorMode::Edit { .. } => EditorMode::Object,
    };
    editor_world.resources.mode.mode = next;
    crate::systems::picking::reset_cycle(editor_world);
    if let EditorMode::Edit { target } = next {
        crate::systems::selection::set_primary(editor_world, Some(target));
    }
}

pub fn nearest_prefab_instance(world: &World, entity: Entity) -> Option<Entity> {
    let mut current = entity;
    loop {
        if entity_has_prefab_instance(world, current) {
            return Some(current);
        }
        let parent = world.core.get_parent(current).and_then(|parent| parent.0)?;
        current = parent;
    }
}

pub fn is_descendant_of(world: &World, entity: Entity, ancestor: Entity) -> bool {
    if entity == ancestor {
        return true;
    }
    let mut current = entity;
    while let Some(parent) = world.core.get_parent(current).and_then(|parent| parent.0) {
        if parent == ancestor {
            return true;
        }
        current = parent;
    }
    false
}

fn entity_has_prefab_instance(world: &World, entity: Entity) -> bool {
    world.core.entity_has_components(entity, PREFAB_SOURCE)
}