diff --git a/src/Game.cpp b/src/Game.cpp index a5880e5..8350063 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -109,7 +109,7 @@ namespace FRG renderer.shaderManager.AddShaderFromFiles("defaultColor", "resources/shaders/defaultColor.vertex", "resources/shaders/defaultColor_desktop.fragment", CONST_ZIP_FILE); renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_desktop.fragment", CONST_ZIP_FILE); #endif - loadingTexture = renderer.textureManager.LoadFromPng("resources/loading.png", ""); + loadingTexture = renderer.textureManager.LoadFromPng("resources/loading003.png", ""); loadingProgressBarFrameTexture = renderer.textureManager.LoadFromPng( "resources/loadingProgressBarFrame.png", "", true); @@ -1013,127 +1013,126 @@ namespace FRG CheckGlError(__FILE__, __LINE__); } - void Game::drawLoading() - { - glClear(GL_DEPTH_BUFFER_BIT); + void Game::drawLoading() + { + glClear(GL_DEPTH_BUFFER_BIT); - renderer.shaderManager.PushShader(defaultShaderName); - renderer.RenderUniform1i(textureUniformName, 0); - renderer.RenderUniform1f("uAlpha", 1.0); + renderer.shaderManager.PushShader(defaultShaderName); + renderer.RenderUniform1i(textureUniformName, 0); + renderer.RenderUniform1f("uAlpha", 1.0); - float width = Environment::projectionWidth; - float height = Environment::projectionHeight; + float width = Environment::projectionWidth; + float height = Environment::projectionHeight; - renderer.PushProjectionMatrix( - -width * 0.5f, width * 0.5f, - -height * 0.5f, height * 0.5f, - -10, 10); + renderer.PushProjectionMatrix( + -width * 0.5f, width * 0.5f, + -height * 0.5f, height * 0.5f, + -10, 10); - renderer.PushMatrix(); - renderer.LoadIdentity(); + renderer.PushMatrix(); + renderer.LoadIdentity(); - if (showLoadingProgressBar == false) // Loading language screen - { - if (FRG::g_currentLanguage == FRG::Language::English) - { - glBindTexture(GL_TEXTURE_2D, menuManager.languageLoadingEn->getTexID()); - } - else if (FRG::g_currentLanguage == FRG::Language::Russian) - { - glBindTexture(GL_TEXTURE_2D, menuManager.languageLoadingRu->getTexID()); - } - else - { - glBindTexture(GL_TEXTURE_2D, loadingTexture->getTexID()); - } - } - else - { - glBindTexture(GL_TEXTURE_2D, loadingTexture->getTexID()); - } + if (showLoadingProgressBar == false) // Loading language screen + { + if (FRG::g_currentLanguage == FRG::Language::English) + { + glBindTexture(GL_TEXTURE_2D, menuManager.languageLoadingEn->getTexID()); + } + else if (FRG::g_currentLanguage == FRG::Language::Russian) + { + glBindTexture(GL_TEXTURE_2D, menuManager.languageLoadingRu->getTexID()); + } + else + { + glBindTexture(GL_TEXTURE_2D, loadingTexture->getTexID()); + } + } + else + { + glBindTexture(GL_TEXTURE_2D, loadingTexture->getTexID()); + } - renderer.DrawVertexRenderStruct(loadingMesh); + renderer.DrawVertexRenderStruct(loadingMesh); - renderer.PopMatrix(); - renderer.PopProjectionMatrix(); - renderer.shaderManager.PopShader(); + renderer.PopMatrix(); + renderer.PopProjectionMatrix(); + renderer.shaderManager.PopShader(); - if (showLoadingProgressBar && loadingProgressBarFrameTexture && loadingProgressBarTexture) { - const float W = Environment::projectionWidth; - const float H = Environment::projectionHeight; - static constexpr float kBarW = 400.0f; - static constexpr float kBarH = 40.0f; - const float barCenterY = -(H * 0.4f - 60.0f); - const float barLeft = -kBarW * 0.5f; - const float barBottom = barCenterY - kBarH * 0.5f; - const float barTop = barCenterY + kBarH * 0.5f; + if (showLoadingProgressBar && loadingProgressBarFrameTexture && loadingProgressBarTexture) { + const float W = Environment::projectionWidth; + const float H = Environment::projectionHeight; + static constexpr float kBarW = 400.0f; + static constexpr float kBarH = 40.0f; + const float barCenterY = -(H * 0.4f - 60.0f); + const float barLeft = -kBarW * 0.5f; + const float barBottom = barCenterY - kBarH * 0.5f; + const float barTop = barCenterY + kBarH * 0.5f; - // Rebuild frame mesh when projection dimensions change - if (W != loadingBarLastW || H != loadingBarLastH) { - loadingBarLastW = W; - loadingBarLastH = H; - VertexDataStruct frameData; - frameData.PositionData = { - {barLeft, barBottom, 4.f}, {barLeft, barTop, 4.f}, {barLeft+kBarW, barTop, 4.f}, - {barLeft+kBarW, barTop, 4.f}, {barLeft+kBarW, barBottom, 4.f}, {barLeft, barBottom, 4.f} - }; - frameData.TexCoordData = { - {0.f,0.f},{0.f,1.f},{1.f,1.f}, - {1.f,1.f},{1.f,0.f},{0.f,0.f} - }; - loadingProgressBarFrameMesh.data = std::move(frameData); - loadingProgressBarFrameMesh.RefreshVBO(); - loadingBarLastRenderedProgress = -1.0f; // force fill rebuild too - } + // Rebuild frame mesh when projection dimensions change + if (W != loadingBarLastW || H != loadingBarLastH) { + loadingBarLastW = W; + loadingBarLastH = H; + VertexDataStruct frameData; + frameData.PositionData = { + {barLeft, barBottom, 4.f}, {barLeft, barTop, 4.f}, {barLeft+kBarW, barTop, 4.f}, + {barLeft+kBarW, barTop, 4.f}, {barLeft+kBarW, barBottom, 4.f}, {barLeft, barBottom, 4.f} + }; + frameData.TexCoordData = { + {0.f,0.f},{0.f,1.f},{1.f,1.f}, + {1.f,1.f},{1.f,0.f},{0.f,0.f} + }; + loadingProgressBarFrameMesh.data = std::move(frameData); + loadingProgressBarFrameMesh.RefreshVBO(); + loadingBarLastRenderedProgress = -1.0f; // force fill rebuild too + } - // Rebuild fill mesh when progress changes - const float p = (std::min)(currentLoadingProgress(), 1.0f); - if (p != loadingBarLastRenderedProgress) { - loadingBarLastRenderedProgress = p; - if (p > 0.001f) { - const float fillRight = barLeft + kBarW * p; - VertexDataStruct fillData; - fillData.PositionData = { - {barLeft, barBottom, 4.f}, {barLeft, barTop, 4.f}, {fillRight, barTop, 4.f}, - {fillRight, barTop, 4.f}, {fillRight, barBottom, 4.f}, {barLeft, barBottom, 4.f} - }; - fillData.TexCoordData = { - {0.f,0.f},{0.f,1.f},{p,1.f}, - {p,1.f},{p,0.f},{0.f,0.f} - }; - loadingProgressBarFillMesh.data = std::move(fillData); - loadingProgressBarFillMesh.RefreshVBO(); - } - } + // Rebuild fill mesh when progress changes + const float p = (std::min)(currentLoadingProgress(), 1.0f); + if (p != loadingBarLastRenderedProgress) { + loadingBarLastRenderedProgress = p; + if (p > 0.001f) { + const float fillRight = barLeft + kBarW * p; + VertexDataStruct fillData; + fillData.PositionData = { + {barLeft, barBottom, 4.f}, {barLeft, barTop, 4.f}, {fillRight, barTop, 4.f}, + {fillRight, barTop, 4.f}, {fillRight, barBottom, 4.f}, {barLeft, barBottom, 4.f} + }; + fillData.TexCoordData = { + {0.f,0.f},{0.f,1.f},{p,1.f}, + {p,1.f},{p,0.f},{0.f,0.f} + }; + loadingProgressBarFillMesh.data = std::move(fillData); + loadingProgressBarFillMesh.RefreshVBO(); + } + } - renderer.shaderManager.PushShader(defaultShaderName); - renderer.RenderUniform1i(textureUniformName, 0); - renderer.RenderUniform1f("uAlpha", 1.0f); - renderer.PushProjectionMatrix(-W*0.5f, W*0.5f, -H*0.5f, H*0.5f, -10, 10); - renderer.PushMatrix(); - renderer.LoadIdentity(); + renderer.shaderManager.PushShader(defaultShaderName); + renderer.RenderUniform1i(textureUniformName, 0); + renderer.RenderUniform1f("uAlpha", 1.0f); + renderer.PushProjectionMatrix(-W*0.5f, W*0.5f, -H*0.5f, H*0.5f, -10, 10); + renderer.PushMatrix(); + renderer.LoadIdentity(); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, loadingProgressBarFrameTexture->getTexID()); - renderer.DrawVertexRenderStruct(loadingProgressBarFrameMesh); + glBindTexture(GL_TEXTURE_2D, loadingProgressBarFrameTexture->getTexID()); + renderer.DrawVertexRenderStruct(loadingProgressBarFrameMesh); - if (p > 0.001f) { - glBindTexture(GL_TEXTURE_2D, loadingProgressBarTexture->getTexID()); - renderer.DrawVertexRenderStruct(loadingProgressBarFillMesh); - } + if (p > 0.001f) { + glBindTexture(GL_TEXTURE_2D, loadingProgressBarTexture->getTexID()); + renderer.DrawVertexRenderStruct(loadingProgressBarFillMesh); + } - renderer.PopMatrix(); - renderer.PopProjectionMatrix(); - renderer.shaderManager.PopShader(); - } - - CheckGlError(__FILE__, __LINE__); - } + renderer.PopMatrix(); + renderer.PopProjectionMatrix(); + renderer.shaderManager.PopShader(); + } + CheckGlError(__FILE__, __LINE__); + } int64_t Game::getSyncTimeMs() { int64_t localNow = std::chrono::duration_cast( @@ -1189,6 +1188,35 @@ namespace FRG SDL_GL_SwapWindow(FRG::Environment::window); } + void Game::onWindowResized() { + const bool wasPortrait = Environment::width < Environment::height; + + if (Environment::isHighDPIEnabled) { + int drawW, drawH; + SDL_GL_GetDrawableSize(Environment::window, &drawW, &drawH); + Environment::width = drawW; + Environment::height = drawH; + } + else { + int winW, winH; + SDL_GetWindowSize(Environment::window, &winW, &winH); + Environment::width = winW / FRG::Environment::customDpiScale; + Environment::height = winH / FRG::Environment::customDpiScale; + } + + Environment::computeProjectionDimensions(); + + const bool isPortrait = Environment::width < Environment::height; + menuManager.uiManager.updateAllLayouts(); + menuManager.topUiManager.updateAllLayouts(); + + if (wasPortrait != isPortrait) { + menuManager.onOrientationChanged(); + } + + logger() << "Window resized (Render Size): " << Environment::width << "x" << Environment::height << std::endl; + } + void Game::update() { SDL_Event event; const bool mobileIsPortrait = loadingCompleted && (Environment::width < Environment::height); @@ -1201,51 +1229,16 @@ namespace FRG if (event.type == SDL_APP_WILLENTERBACKGROUND) { isAppActive = false; __android_log_print(ANDROID_LOG_INFO, "Game", "App moving to background, suspending loop"); - break; } if (event.type == SDL_APP_DIDENTERFOREGROUND) { isAppActive = true; __android_log_print(ANDROID_LOG_INFO, "Game", "App returned to foreground, resuming loop"); - break; } - /* - __android_log_print(ANDROID_LOG_ERROR, "Game", - "Game::update step 1 event type: %d", event.type); - */ #endif - if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) { - const bool wasPortrait = Environment::width < Environment::height; - FRG::logger() << "Window resized" << std::endl; - if (Environment::isHighDPIEnabled) { - // Если High DPI включен, запрашиваем реальное физическое разрешение буфера - int drawW, drawH; - SDL_GL_GetDrawableSize(Environment::window, &drawW, &drawH); - Environment::width = drawW; - Environment::height = drawH; - } - else { - // Если High DPI выключен, используем логические размеры из события - Environment::width = event.window.data1 / FRG::Environment::customDpiScale; - Environment::height = event.window.data2 / FRG::Environment::customDpiScale; - } - - Environment::computeProjectionDimensions(); - - const bool isPortrait = Environment::width < Environment::height; - menuManager.uiManager.updateAllLayouts(); - menuManager.topUiManager.updateAllLayouts(); - - if (wasPortrait != isPortrait) { - menuManager.onOrientationChanged(); - } - - logger() << "Window resized (Render Size): " << Environment::width << "x" << Environment::height << std::endl; - //space.clearTextRendererCache(); - } - - if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) { + if (event.type == SDL_WINDOWEVENT && (event.window.event == SDL_WINDOWEVENT_RESIZED || event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)) { + onWindowResized(); } // Suppress all input while portrait overlay is shown @@ -1384,6 +1377,20 @@ namespace FRG } } } + + // Fallback detection (proactive check) + int drawableW, drawableH; + SDL_GL_GetDrawableSize(Environment::window, &drawableW, &drawableH); + if (drawableW != lastDrawableW || drawableH != lastDrawableH) { + lastDrawableW = drawableW; + lastDrawableH = drawableH; + onWindowResized(); + } + +#ifdef __ANDROID__ + if (!isAppActive) return; +#endif + // Drain one loading step per frame so the window/tab keeps pumping events // and repainting between steps instead of freezing for the whole load. if (!loadingCompleted && !loadSteps.empty()) { diff --git a/src/Game.h b/src/Game.h index 87ee8ff..d45089e 100644 --- a/src/Game.h +++ b/src/Game.h @@ -39,6 +39,7 @@ namespace FRG { void setupPart2(); void update(); void render(); + void onWindowResized(); bool shouldExit() const { return Environment::exitGameLoop; } @@ -201,6 +202,9 @@ namespace FRG { int64_t newTickCount; int64_t lastTickCount; + int lastDrawableW = -1; + int lastDrawableH = -1; + static const size_t CONST_TIMER_INTERVAL = 10; static const size_t CONST_MAX_TIME_INTERVAL = 1000; }; diff --git a/src/main.cpp b/src/main.cpp index dfc43df..8ad905c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -267,34 +267,9 @@ int main(int argc, char* argv[]) { } while (!g_game->shouldExit()) { - SDL_Event event; - // Обрабатываем системные события Android до обновления кадра - /*while (SDL_PollEvent(&event)) { - // Перенаправляем событие в игру, чтобы сработал ваш внутренний цикл (память, ресайз и т.д.) - // Примечание: внутри Game::update у вас тоже стоит PollEvent. - // Чтобы события не терялись, лучше обрабатывать их в одном месте, - // но жизненно важные для ОС флаги перехватываем здесь: - if (event.type == SDL_QUIT) { - break; - } + g_game->update(); - // Сворачивание / Разворачивание приложения в Android - if (event.type == SDL_APP_WILLENTERBACKGROUND) { - isAppActive = false; - __android_log_print(ANDROID_LOG_INFO, "Game", "App moving to background, suspending loop"); - } - if (event.type == SDL_APP_DIDENTERFOREGROUND) { - isAppActive = true; - __android_log_print(ANDROID_LOG_INFO, "Game", "App returned to foreground, resuming loop"); - } - }*/ - - if (isAppActive) { - g_game->update(); - // На Android шаг кадров завязан на VSync (SwapInterval = 1). - // SDL_Delay(16) здесь не нужен, он будет вызывать микро-фризы (stuttering). - } - else { + if (!isAppActive) { // Если игра свернута — спим, чтобы не нагружать CPU/GPU SDL_Delay(100); }