#include #include #include #include #include #include #include #ifdef __SWITCH__ #include #endif namespace extra2d { /** * @brief 获取当前时间(秒) */ static double getTimeSeconds() { #ifdef __SWITCH__ struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return static_cast(ts.tv_sec) + static_cast(ts.tv_nsec) / 1000000000.0; #else using namespace std::chrono; auto now = steady_clock::now(); auto duration = now.time_since_epoch(); return duration_cast>(duration).count(); #endif } Application &Application::instance() { static Application instance; return instance; } Application::~Application() { shutdown(); } bool Application::init(const AppConfig &config) { if (initialized_) { E2D_LOG_WARN("Application already initialized"); return true; } config_ = config; PlatformType platform = config_.platform; if (platform == PlatformType::Auto) { #ifdef __SWITCH__ platform = PlatformType::Switch; #else platform = PlatformType::PC; #endif } if (platform == PlatformType::Switch) { #ifdef __SWITCH__ Result rc; rc = romfsInit(); if (R_SUCCEEDED(rc)) { E2D_LOG_INFO("RomFS initialized successfully"); } else { E2D_LOG_WARN("romfsInit failed: {:#08X}, will use regular filesystem", rc); } rc = socketInitializeDefault(); if (R_FAILED(rc)) { E2D_LOG_WARN( "socketInitializeDefault failed, nxlink will not be available"); } #endif } window_ = unique(); WindowConfig winConfig; winConfig.title = config.title; winConfig.width = config.width; winConfig.height = config.height; if (platform == PlatformType::Switch) { winConfig.fullscreen = true; winConfig.fullscreenDesktop = false; winConfig.resizable = false; winConfig.enableCursors = false; winConfig.enableDpiScale = false; } else { winConfig.fullscreen = config.fullscreen; winConfig.resizable = config.resizable; winConfig.enableCursors = config.enableCursors; winConfig.enableDpiScale = config.enableDpiScale; } winConfig.vsync = config.vsync; winConfig.msaaSamples = config.msaaSamples; if (!window_->create(winConfig)) { E2D_LOG_ERROR("Failed to create window"); return false; } timerManager_ = unique(); initialized_ = true; running_ = true; E2D_LOG_INFO("Application initialized successfully"); return true; } void Application::shutdown() { if (!initialized_) return; E2D_LOG_INFO("Shutting down application..."); timerManager_.reset(); if (window_) { window_->destroy(); window_.reset(); } PlatformType platform = config_.platform; if (platform == PlatformType::Auto) { #ifdef __SWITCH__ platform = PlatformType::Switch; #else platform = PlatformType::PC; #endif } if (platform == PlatformType::Switch) { #ifdef __SWITCH__ romfsExit(); socketExit(); #endif } initialized_ = false; running_ = false; E2D_LOG_INFO("Application shutdown complete"); } void Application::run() { if (!initialized_) { E2D_LOG_ERROR("Application not initialized"); return; } lastFrameTime_ = getTimeSeconds(); #ifdef __SWITCH__ while (running_ && !window_->shouldClose()) { mainLoop(); } #else while (running_ && !window_->shouldClose()) { mainLoop(); } #endif } void Application::quit() { shouldQuit_ = true; running_ = false; } void Application::pause() { if (!paused_) { paused_ = true; E2D_LOG_INFO("Application paused"); } } void Application::resume() { if (paused_) { paused_ = false; lastFrameTime_ = getTimeSeconds(); E2D_LOG_INFO("Application resumed"); } } void Application::mainLoop() { double currentTime = getTimeSeconds(); deltaTime_ = static_cast(currentTime - lastFrameTime_); lastFrameTime_ = currentTime; totalTime_ += deltaTime_; frameCount_++; fpsTimer_ += deltaTime_; if (fpsTimer_ >= 1.0f) { currentFps_ = frameCount_; frameCount_ = 0; fpsTimer_ -= 1.0f; } window_->pollEvents(); if (!paused_) { update(); } window_->swapBuffers(); if (!config_.vsync && config_.fpsLimit > 0) { double frameEndTime = getTimeSeconds(); double frameTime = frameEndTime - currentTime; double target = 1.0 / static_cast(config_.fpsLimit); if (frameTime < target) { auto sleepSeconds = target - frameTime; std::this_thread::sleep_for(std::chrono::duration(sleepSeconds)); } } } void Application::update() { if (timerManager_) { timerManager_->update(deltaTime_); } } Input &Application::input() { return *window_->getInput(); } TimerManager &Application::timers() { return *timerManager_; } } // namespace extra2d