Fixing screen resize bugs
This commit is contained in:
parent
6406c4f258
commit
6a79e8e41e
289
src/Game.cpp
289
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("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);
|
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_desktop.fragment", CONST_ZIP_FILE);
|
||||||
#endif
|
#endif
|
||||||
loadingTexture = renderer.textureManager.LoadFromPng("resources/loading.png", "");
|
loadingTexture = renderer.textureManager.LoadFromPng("resources/loading003.png", "");
|
||||||
|
|
||||||
loadingProgressBarFrameTexture = renderer.textureManager.LoadFromPng(
|
loadingProgressBarFrameTexture = renderer.textureManager.LoadFromPng(
|
||||||
"resources/loadingProgressBarFrame.png", "", true);
|
"resources/loadingProgressBarFrame.png", "", true);
|
||||||
@ -1013,127 +1013,126 @@ namespace FRG
|
|||||||
CheckGlError(__FILE__, __LINE__);
|
CheckGlError(__FILE__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::drawLoading()
|
void Game::drawLoading()
|
||||||
{
|
{
|
||||||
glClear(GL_DEPTH_BUFFER_BIT);
|
glClear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
renderer.shaderManager.PushShader(defaultShaderName);
|
renderer.shaderManager.PushShader(defaultShaderName);
|
||||||
renderer.RenderUniform1i(textureUniformName, 0);
|
renderer.RenderUniform1i(textureUniformName, 0);
|
||||||
renderer.RenderUniform1f("uAlpha", 1.0);
|
renderer.RenderUniform1f("uAlpha", 1.0);
|
||||||
|
|
||||||
|
|
||||||
float width = Environment::projectionWidth;
|
float width = Environment::projectionWidth;
|
||||||
float height = Environment::projectionHeight;
|
float height = Environment::projectionHeight;
|
||||||
|
|
||||||
renderer.PushProjectionMatrix(
|
renderer.PushProjectionMatrix(
|
||||||
-width * 0.5f, width * 0.5f,
|
-width * 0.5f, width * 0.5f,
|
||||||
-height * 0.5f, height * 0.5f,
|
-height * 0.5f, height * 0.5f,
|
||||||
-10, 10);
|
-10, 10);
|
||||||
|
|
||||||
renderer.PushMatrix();
|
renderer.PushMatrix();
|
||||||
renderer.LoadIdentity();
|
renderer.LoadIdentity();
|
||||||
|
|
||||||
if (showLoadingProgressBar == false) // Loading language screen
|
if (showLoadingProgressBar == false) // Loading language screen
|
||||||
{
|
{
|
||||||
if (FRG::g_currentLanguage == FRG::Language::English)
|
if (FRG::g_currentLanguage == FRG::Language::English)
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, menuManager.languageLoadingEn->getTexID());
|
glBindTexture(GL_TEXTURE_2D, menuManager.languageLoadingEn->getTexID());
|
||||||
}
|
}
|
||||||
else if (FRG::g_currentLanguage == FRG::Language::Russian)
|
else if (FRG::g_currentLanguage == FRG::Language::Russian)
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, menuManager.languageLoadingRu->getTexID());
|
glBindTexture(GL_TEXTURE_2D, menuManager.languageLoadingRu->getTexID());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, loadingTexture->getTexID());
|
glBindTexture(GL_TEXTURE_2D, loadingTexture->getTexID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_2D, loadingTexture->getTexID());
|
glBindTexture(GL_TEXTURE_2D, loadingTexture->getTexID());
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.DrawVertexRenderStruct(loadingMesh);
|
renderer.DrawVertexRenderStruct(loadingMesh);
|
||||||
|
|
||||||
renderer.PopMatrix();
|
renderer.PopMatrix();
|
||||||
renderer.PopProjectionMatrix();
|
renderer.PopProjectionMatrix();
|
||||||
renderer.shaderManager.PopShader();
|
renderer.shaderManager.PopShader();
|
||||||
|
|
||||||
if (showLoadingProgressBar && loadingProgressBarFrameTexture && loadingProgressBarTexture) {
|
if (showLoadingProgressBar && loadingProgressBarFrameTexture && loadingProgressBarTexture) {
|
||||||
const float W = Environment::projectionWidth;
|
const float W = Environment::projectionWidth;
|
||||||
const float H = Environment::projectionHeight;
|
const float H = Environment::projectionHeight;
|
||||||
static constexpr float kBarW = 400.0f;
|
static constexpr float kBarW = 400.0f;
|
||||||
static constexpr float kBarH = 40.0f;
|
static constexpr float kBarH = 40.0f;
|
||||||
const float barCenterY = -(H * 0.4f - 60.0f);
|
const float barCenterY = -(H * 0.4f - 60.0f);
|
||||||
const float barLeft = -kBarW * 0.5f;
|
const float barLeft = -kBarW * 0.5f;
|
||||||
const float barBottom = barCenterY - kBarH * 0.5f;
|
const float barBottom = barCenterY - kBarH * 0.5f;
|
||||||
const float barTop = barCenterY + kBarH * 0.5f;
|
const float barTop = barCenterY + kBarH * 0.5f;
|
||||||
|
|
||||||
|
|
||||||
// Rebuild frame mesh when projection dimensions change
|
// Rebuild frame mesh when projection dimensions change
|
||||||
if (W != loadingBarLastW || H != loadingBarLastH) {
|
if (W != loadingBarLastW || H != loadingBarLastH) {
|
||||||
loadingBarLastW = W;
|
loadingBarLastW = W;
|
||||||
loadingBarLastH = H;
|
loadingBarLastH = H;
|
||||||
VertexDataStruct frameData;
|
VertexDataStruct frameData;
|
||||||
frameData.PositionData = {
|
frameData.PositionData = {
|
||||||
{barLeft, barBottom, 4.f}, {barLeft, barTop, 4.f}, {barLeft+kBarW, barTop, 4.f},
|
{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}
|
{barLeft+kBarW, barTop, 4.f}, {barLeft+kBarW, barBottom, 4.f}, {barLeft, barBottom, 4.f}
|
||||||
};
|
};
|
||||||
frameData.TexCoordData = {
|
frameData.TexCoordData = {
|
||||||
{0.f,0.f},{0.f,1.f},{1.f,1.f},
|
{0.f,0.f},{0.f,1.f},{1.f,1.f},
|
||||||
{1.f,1.f},{1.f,0.f},{0.f,0.f}
|
{1.f,1.f},{1.f,0.f},{0.f,0.f}
|
||||||
};
|
};
|
||||||
loadingProgressBarFrameMesh.data = std::move(frameData);
|
loadingProgressBarFrameMesh.data = std::move(frameData);
|
||||||
loadingProgressBarFrameMesh.RefreshVBO();
|
loadingProgressBarFrameMesh.RefreshVBO();
|
||||||
loadingBarLastRenderedProgress = -1.0f; // force fill rebuild too
|
loadingBarLastRenderedProgress = -1.0f; // force fill rebuild too
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rebuild fill mesh when progress changes
|
// Rebuild fill mesh when progress changes
|
||||||
const float p = (std::min)(currentLoadingProgress(), 1.0f);
|
const float p = (std::min)(currentLoadingProgress(), 1.0f);
|
||||||
if (p != loadingBarLastRenderedProgress) {
|
if (p != loadingBarLastRenderedProgress) {
|
||||||
loadingBarLastRenderedProgress = p;
|
loadingBarLastRenderedProgress = p;
|
||||||
if (p > 0.001f) {
|
if (p > 0.001f) {
|
||||||
const float fillRight = barLeft + kBarW * p;
|
const float fillRight = barLeft + kBarW * p;
|
||||||
VertexDataStruct fillData;
|
VertexDataStruct fillData;
|
||||||
fillData.PositionData = {
|
fillData.PositionData = {
|
||||||
{barLeft, barBottom, 4.f}, {barLeft, barTop, 4.f}, {fillRight, barTop, 4.f},
|
{barLeft, barBottom, 4.f}, {barLeft, barTop, 4.f}, {fillRight, barTop, 4.f},
|
||||||
{fillRight, barTop, 4.f}, {fillRight, barBottom, 4.f}, {barLeft, barBottom, 4.f}
|
{fillRight, barTop, 4.f}, {fillRight, barBottom, 4.f}, {barLeft, barBottom, 4.f}
|
||||||
};
|
};
|
||||||
fillData.TexCoordData = {
|
fillData.TexCoordData = {
|
||||||
{0.f,0.f},{0.f,1.f},{p,1.f},
|
{0.f,0.f},{0.f,1.f},{p,1.f},
|
||||||
{p,1.f},{p,0.f},{0.f,0.f}
|
{p,1.f},{p,0.f},{0.f,0.f}
|
||||||
};
|
};
|
||||||
loadingProgressBarFillMesh.data = std::move(fillData);
|
loadingProgressBarFillMesh.data = std::move(fillData);
|
||||||
loadingProgressBarFillMesh.RefreshVBO();
|
loadingProgressBarFillMesh.RefreshVBO();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.shaderManager.PushShader(defaultShaderName);
|
renderer.shaderManager.PushShader(defaultShaderName);
|
||||||
renderer.RenderUniform1i(textureUniformName, 0);
|
renderer.RenderUniform1i(textureUniformName, 0);
|
||||||
renderer.RenderUniform1f("uAlpha", 1.0f);
|
renderer.RenderUniform1f("uAlpha", 1.0f);
|
||||||
renderer.PushProjectionMatrix(-W*0.5f, W*0.5f, -H*0.5f, H*0.5f, -10, 10);
|
renderer.PushProjectionMatrix(-W*0.5f, W*0.5f, -H*0.5f, H*0.5f, -10, 10);
|
||||||
renderer.PushMatrix();
|
renderer.PushMatrix();
|
||||||
renderer.LoadIdentity();
|
renderer.LoadIdentity();
|
||||||
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, loadingProgressBarFrameTexture->getTexID());
|
glBindTexture(GL_TEXTURE_2D, loadingProgressBarFrameTexture->getTexID());
|
||||||
renderer.DrawVertexRenderStruct(loadingProgressBarFrameMesh);
|
renderer.DrawVertexRenderStruct(loadingProgressBarFrameMesh);
|
||||||
|
|
||||||
if (p > 0.001f) {
|
if (p > 0.001f) {
|
||||||
glBindTexture(GL_TEXTURE_2D, loadingProgressBarTexture->getTexID());
|
glBindTexture(GL_TEXTURE_2D, loadingProgressBarTexture->getTexID());
|
||||||
renderer.DrawVertexRenderStruct(loadingProgressBarFillMesh);
|
renderer.DrawVertexRenderStruct(loadingProgressBarFillMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.PopMatrix();
|
renderer.PopMatrix();
|
||||||
renderer.PopProjectionMatrix();
|
renderer.PopProjectionMatrix();
|
||||||
renderer.shaderManager.PopShader();
|
renderer.shaderManager.PopShader();
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckGlError(__FILE__, __LINE__);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
CheckGlError(__FILE__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
int64_t Game::getSyncTimeMs() {
|
int64_t Game::getSyncTimeMs() {
|
||||||
int64_t localNow = std::chrono::duration_cast<std::chrono::milliseconds>(
|
int64_t localNow = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
@ -1189,6 +1188,35 @@ namespace FRG
|
|||||||
SDL_GL_SwapWindow(FRG::Environment::window);
|
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() {
|
void Game::update() {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
const bool mobileIsPortrait = loadingCompleted && (Environment::width < Environment::height);
|
const bool mobileIsPortrait = loadingCompleted && (Environment::width < Environment::height);
|
||||||
@ -1201,51 +1229,16 @@ namespace FRG
|
|||||||
if (event.type == SDL_APP_WILLENTERBACKGROUND) {
|
if (event.type == SDL_APP_WILLENTERBACKGROUND) {
|
||||||
isAppActive = false;
|
isAppActive = false;
|
||||||
__android_log_print(ANDROID_LOG_INFO, "Game", "App moving to background, suspending loop");
|
__android_log_print(ANDROID_LOG_INFO, "Game", "App moving to background, suspending loop");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (event.type == SDL_APP_DIDENTERFOREGROUND) {
|
if (event.type == SDL_APP_DIDENTERFOREGROUND) {
|
||||||
isAppActive = true;
|
isAppActive = true;
|
||||||
__android_log_print(ANDROID_LOG_INFO, "Game", "App returned to foreground, resuming loop");
|
__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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
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)) {
|
||||||
const bool wasPortrait = Environment::width < Environment::height;
|
onWindowResized();
|
||||||
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) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Suppress all input while portrait overlay is shown
|
// 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
|
// Drain one loading step per frame so the window/tab keeps pumping events
|
||||||
// and repainting between steps instead of freezing for the whole load.
|
// and repainting between steps instead of freezing for the whole load.
|
||||||
if (!loadingCompleted && !loadSteps.empty()) {
|
if (!loadingCompleted && !loadSteps.empty()) {
|
||||||
|
|||||||
@ -39,6 +39,7 @@ namespace FRG {
|
|||||||
void setupPart2();
|
void setupPart2();
|
||||||
void update();
|
void update();
|
||||||
void render();
|
void render();
|
||||||
|
void onWindowResized();
|
||||||
|
|
||||||
bool shouldExit() const { return Environment::exitGameLoop; }
|
bool shouldExit() const { return Environment::exitGameLoop; }
|
||||||
|
|
||||||
@ -201,6 +202,9 @@ namespace FRG {
|
|||||||
int64_t newTickCount;
|
int64_t newTickCount;
|
||||||
int64_t lastTickCount;
|
int64_t lastTickCount;
|
||||||
|
|
||||||
|
int lastDrawableW = -1;
|
||||||
|
int lastDrawableH = -1;
|
||||||
|
|
||||||
static const size_t CONST_TIMER_INTERVAL = 10;
|
static const size_t CONST_TIMER_INTERVAL = 10;
|
||||||
static const size_t CONST_MAX_TIME_INTERVAL = 1000;
|
static const size_t CONST_MAX_TIME_INTERVAL = 1000;
|
||||||
};
|
};
|
||||||
|
|||||||
29
src/main.cpp
29
src/main.cpp
@ -267,34 +267,9 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!g_game->shouldExit()) {
|
while (!g_game->shouldExit()) {
|
||||||
SDL_Event event;
|
g_game->update();
|
||||||
// Обрабатываем системные события Android до обновления кадра
|
|
||||||
/*while (SDL_PollEvent(&event)) {
|
|
||||||
// Перенаправляем событие в игру, чтобы сработал ваш внутренний цикл (память, ресайз и т.д.)
|
|
||||||
// Примечание: внутри Game::update у вас тоже стоит PollEvent.
|
|
||||||
// Чтобы события не терялись, лучше обрабатывать их в одном месте,
|
|
||||||
// но жизненно важные для ОС флаги перехватываем здесь:
|
|
||||||
if (event.type == SDL_QUIT) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Сворачивание / Разворачивание приложения в Android
|
if (!isAppActive) {
|
||||||
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 {
|
|
||||||
// Если игра свернута — спим, чтобы не нагружать CPU/GPU
|
// Если игра свернута — спим, чтобы не нагружать CPU/GPU
|
||||||
SDL_Delay(100);
|
SDL_Delay(100);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user