nightshade-editor 0.14.2

Interactive map editor for the Nightshade game engine
//! Temporary perf-benchmark harness. Gated behind the
//! `NIGHTSHADE_PERF_TEST` environment variable. When enabled, auto-loads
//! VirtualCity from the Khronos sample browser on startup, waits for the
//! model to finish loading, triggers `ShowAllCameras`, lets the workload
//! settle, then sets `should_exit` so a tracy capture finishes naturally.

use crate::ecs::EditorWorld;
use crate::systems::retained_ui::Action;
use nightshade::prelude::*;

const POST_GRID_HOLD_FRAMES: u32 = 600;

#[derive(Default, Clone, Copy, PartialEq, Eq)]
pub enum AutoStage {
    #[default]
    Idle,
    EnsureLoaded,
    AwaitEntries,
    AwaitModel,
    AwaitCameras {
        settle_frames: u32,
    },
    Hold {
        remaining_frames: u32,
    },
    Done,
}

#[derive(Default)]
pub struct AutoState {
    pub stage: AutoStage,
    pub initialized: bool,
}

pub fn poll(editor_world: &mut EditorWorld, world: &mut World) {
    if !editor_world.resources.perf_test.initialized {
        editor_world.resources.perf_test.initialized = true;
        let enabled = std::env::var("NIGHTSHADE_PERF_TEST")
            .map(|value| value != "0" && !value.is_empty())
            .unwrap_or(false);
        editor_world.resources.perf_test.stage = if enabled {
            AutoStage::EnsureLoaded
        } else {
            AutoStage::Done
        };
    }

    let stage = editor_world.resources.perf_test.stage;
    match stage {
        AutoStage::Idle | AutoStage::Done => {}
        AutoStage::EnsureLoaded => {
            editor_world
                .resources
                .browsers
                .sample_browser
                .ensure_loaded();
            editor_world.resources.perf_test.stage = AutoStage::AwaitEntries;
        }
        AutoStage::AwaitEntries => {
            let Some(entries) = editor_world.resources.browsers.sample_browser.entries() else {
                return;
            };
            let Some(entry) = entries
                .iter()
                .find(|entry| entry.name.eq_ignore_ascii_case("VirtualCity"))
            else {
                tracing::warn!("perf_test: VirtualCity entry not found");
                editor_world.resources.perf_test.stage = AutoStage::Done;
                return;
            };
            editor_world
                .resources
                .browsers
                .sample_browser
                .fetch_entry(entry);
            editor_world.resources.perf_test.stage = AutoStage::AwaitModel;
        }
        AutoStage::AwaitModel => {
            let model_name = editor_world
                .resources
                .loading
                .current_model_name
                .as_deref()
                .unwrap_or("");
            let normalized = model_name.replace([' ', '_', '-'], "").to_ascii_lowercase();
            if normalized.contains("virtualcity") {
                editor_world.resources.perf_test.stage =
                    AutoStage::AwaitCameras { settle_frames: 60 };
            }
        }
        AutoStage::AwaitCameras { settle_frames } => {
            if settle_frames > 0 {
                editor_world.resources.perf_test.stage = AutoStage::AwaitCameras {
                    settle_frames: settle_frames - 1,
                };
                return;
            }
            let camera_count = world
                .core
                .query_entities(nightshade::ecs::world::CAMERA)
                .count();
            tracing::info!(
                "perf_test: {} cameras present, triggering ShowAllCameras",
                camera_count
            );
            editor_world
                .resources
                .ui_interaction
                .actions
                .push(Action::ShowAllCameras);
            editor_world.resources.perf_test.stage = AutoStage::Hold {
                remaining_frames: POST_GRID_HOLD_FRAMES,
            };
        }
        AutoStage::Hold { remaining_frames } => {
            if remaining_frames > 0 {
                editor_world.resources.perf_test.stage = AutoStage::Hold {
                    remaining_frames: remaining_frames - 1,
                };
                return;
            }
            tracing::info!("perf_test: hold elapsed, requesting exit");
            world.resources.window.should_exit = true;
            editor_world.resources.perf_test.stage = AutoStage::Done;
        }
    }
}