Fixing localization bugs, working with graphics settings

This commit is contained in:
Vladislav Khorev 2026-07-12 16:02:09 +03:00
parent d4365728fe
commit 9d03b52c2a
14 changed files with 354 additions and 44 deletions

View File

@ -2254,6 +2254,11 @@
"key": "Прошу прощения Аида Дженибековна, я правда старался, но у меня возникли обстоятельства непреодолимой силы.", "key": "Прошу прощения Аида Дженибековна, я правда старался, но у меня возникли обстоятельства непреодолимой силы.",
"ru": "Прошу прощения Аида Дженибековна, я правда старался, но у меня возникли обстоятельства непреодолимой силы.", "ru": "Прошу прощения Аида Дженибековна, я правда старался, но у меня возникли обстоятельства непреодолимой силы.",
"en": "I apologize, Aida Dzhanybekovna, I really tried, but I encountered force majeure circumstances." "en": "I apologize, Aida Dzhanybekovna, I really tried, but I encountered force majeure circumstances."
},
{
"key": "Бекзат, я сейчас занята, не мешай мне!",
"ru": "Бекзат, я сейчас занята, не мешай мне!",
"en": "Bekzat, I'm busy now, don't disturb me!"
} }
] ]
} }

View File

@ -105,11 +105,11 @@
}, },
{ {
"type": "TextButton", "type": "TextButton",
"name": "fullScreenToggleButton", "name": "graphicsButton",
"width": 500, "width": 500,
"height": 60, "height": 60,
"text": "Полноэкранный режим: ВЫКЛ", "text": "Настройки графики",
"fontSize": 32, "fontSize": 40,
"textCentered": true, "textCentered": true,
"color": [1.0, 1.0, 1.0, 1.0] "color": [1.0, 1.0, 1.0, 1.0]
} }

View File

@ -0,0 +1,72 @@
{
"root": {
"type": "FrameLayout",
"width": "match_parent",
"height": "match_parent",
"children": [
{
"type": "StaticImage",
"name": "settingsBkg",
"width": 2992,
"height": 1632,
"horizontal_gravity": "center",
"vertical_gravity": "center",
"texture": "resources/w/ui/img/main/MenuBkg001_v001.png"
},
{
"type": "LinearLayout",
"orientation": "vertical",
"horizontal_gravity": "center",
"vertical_gravity": "center",
"horizontal_align": "left",
"width": 500,
"height": 600,
"spacing": 20,
"children": [
{
"type": "TextView",
"name": "settingsTitleText",
"width": 500,
"height": 60,
"text": "Настройки графики",
"fontSize": 40,
"textCentered": true,
"color": [1.0, 1.0, 1.0, 1.0]
},
{
"type": "TextButton",
"name": "fullScreenToggleButton",
"width": 500,
"height": 60,
"text": "Полноэкранный режим: ВЫКЛ",
"fontSize": 32,
"textCentered": true,
"color": [1.0, 1.0, 1.0, 1.0]
},
{
"type": "TextButton",
"name": "shadowToggleButton",
"width": 500,
"height": 60,
"text": "Тени: ВЫКЛ",
"fontSize": 32,
"textCentered": true,
"color": [1.0, 1.0, 1.0, 1.0]
}
]
},
{
"type": "TextButton",
"name": "settingsBackButton",
"horizontal_gravity": "center",
"vertical_gravity": "bottom",
"y": 40,
"width": 200,
"height": 60,
"text": "Назад",
"fontSize": 40,
"textCentered": true
}
]
}
}

View File

@ -105,11 +105,11 @@
}, },
{ {
"type": "TextButton", "type": "TextButton",
"name": "fullScreenToggleButton", "name": "graphicsButton",
"width": 500, "width": 500,
"height": 60, "height": 60,
"text": "", "text": "Graphics settings",
"fontSize": 32, "fontSize": 40,
"textCentered": true, "textCentered": true,
"color": [1.0, 1.0, 1.0, 1.0] "color": [1.0, 1.0, 1.0, 1.0]
} }

View File

@ -0,0 +1,72 @@
{
"root": {
"type": "FrameLayout",
"width": "match_parent",
"height": "match_parent",
"children": [
{
"type": "StaticImage",
"name": "settingsBkg",
"width": 2992,
"height": 1632,
"horizontal_gravity": "center",
"vertical_gravity": "center",
"texture": "resources/w/ui/img/main/MenuBkg001_v001.png"
},
{
"type": "LinearLayout",
"orientation": "vertical",
"horizontal_gravity": "center",
"vertical_gravity": "center",
"horizontal_align": "left",
"width": 500,
"height": 600,
"spacing": 20,
"children": [
{
"type": "TextView",
"name": "settingsTitleText",
"width": 500,
"height": 60,
"text": "Graphics settings",
"fontSize": 40,
"textCentered": true,
"color": [1.0, 1.0, 1.0, 1.0]
},
{
"type": "TextButton",
"name": "fullScreenToggleButton",
"width": 500,
"height": 60,
"text": "",
"fontSize": 32,
"textCentered": true,
"color": [1.0, 1.0, 1.0, 1.0]
},
{
"type": "TextButton",
"name": "shadowToggleButton",
"width": 500,
"height": 60,
"text": "",
"fontSize": 32,
"textCentered": true,
"color": [1.0, 1.0, 1.0, 1.0]
}
]
},
{
"type": "TextButton",
"name": "settingsBackButton",
"horizontal_gravity": "center",
"vertical_gravity": "bottom",
"y": 40,
"width": 200,
"height": 60,
"text": "Back",
"fontSize": 40,
"textCentered": true
}
]
}
}

View File

@ -31,6 +31,9 @@ bool Environment::isFullscreen = false;
bool Environment::isFullscreen = true; bool Environment::isFullscreen = true;
#endif #endif
bool Environment::isHighDPIEnabled = false;
int Environment::customDpiScale = 1;
bool Environment::showMouse = false; bool Environment::showMouse = false;
bool Environment::exitGameLoop = false; bool Environment::exitGameLoop = false;

View File

@ -33,6 +33,9 @@ public:
static bool isFullscreen; static bool isFullscreen;
static void setFullscreen(bool enable); static void setFullscreen(bool enable);
static bool isHighDPIEnabled;
static int customDpiScale;
static bool showMouse; static bool showMouse;
static bool exitGameLoop; static bool exitGameLoop;

View File

@ -292,6 +292,19 @@ namespace ZL
menuManager.onLoadGame = [this](int slot) { loadGame(slot); }; menuManager.onLoadGame = [this](int slot) { loadGame(slot); };
menuManager.getSlotInfoFunc = [this](int slot) { return readSlotInfo(slot); }; menuManager.getSlotInfoFunc = [this](int slot) { return readSlotInfo(slot); };
menuManager.shadowMapSettingsChangedFunc = [this](bool newValue) {
if (newValue)
{
createShadowMapAndProparateToLocations();
menuManager.shadowsEnabled = true;
}
else
{
destroyShadowMapAndProparateToLocations();
menuManager.shadowsEnabled = false;
}
};
// Lets MenuManager run a heavy operation (e.g. reloadLocalizedGameContent()) // Lets MenuManager run a heavy operation (e.g. reloadLocalizedGameContent())
// as a chunked sequence instead of one blocking call: the closures are // as a chunked sequence instead of one blocking call: the closures are
// drained one per frame by update(), with the loading screen shown for // drained one per frame by update(), with the loading screen shown for
@ -322,6 +335,14 @@ namespace ZL
audioPlayer->crossFadeMusicAsync("audio/main menu final.ogg"); audioPlayer->crossFadeMusicAsync("audio/main menu final.ogg");
}); });
/*loadSteps.push([this]() {
if (menshadowsEnabled)
{
createShadowMapAndProparateToLocations();
}
});*/
loadSteps.push([this]() { loadSteps.push([this]() {
loadingCompleted = true; loadingCompleted = true;
}); });
@ -730,6 +751,30 @@ namespace ZL
} }
} }
void Game::createShadowMapAndProparateToLocations()
{
if (shadowMap) {
std::cout << "Shadow map already exists, skipping creation" << std::endl;
return;
}
shadowMap = std::make_shared<ShadowMap>(2048, 40.0f, 0.1f, 100.0f);
shadowMap->setLightDirection(Eigen::Vector3f(-0.5f, -1.0f, -0.3f));
std::cout << "Shadow map initialized" << std::endl;
for (auto& [name, loc] : gameState.locations) {
loc->shadowMap = shadowMap;
}
}
void Game::destroyShadowMapAndProparateToLocations()
{
shadowMap.reset();
for (auto& [name, loc] : gameState.locations) {
loc->shadowMap.reset();
}
}
void Game::drawUI() void Game::drawUI()
{ {
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
@ -991,19 +1036,32 @@ namespace ZL
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) { if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) {
// Обновляем размеры и сбрасываем кеш текстов, т.к. меши хранятся в пикселях
const bool wasPortrait = Environment::width < Environment::height; const bool wasPortrait = Environment::width < Environment::height;
Environment::width = event.window.data1;
Environment::height = event.window.data2; 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 / ZL::Environment::customDpiScale;
Environment::height = event.window.data2 / ZL::Environment::customDpiScale;
}
Environment::computeProjectionDimensions(); Environment::computeProjectionDimensions();
const bool isPortrait = Environment::width < Environment::height; const bool isPortrait = Environment::width < Environment::height;
menuManager.uiManager.updateAllLayouts(); menuManager.uiManager.updateAllLayouts();
menuManager.topUiManager.updateAllLayouts(); menuManager.topUiManager.updateAllLayouts();
if (wasPortrait != isPortrait) { if (wasPortrait != isPortrait) {
menuManager.onOrientationChanged(); menuManager.onOrientationChanged();
} }
std::cout << "Window resized: " << Environment::width << "x" << Environment::height << std::endl;
std::cout << "Window resized (Render Size): " << Environment::width << "x" << Environment::height << std::endl;
//space.clearTextRendererCache(); //space.clearTextRendererCache();
} }

View File

@ -50,6 +50,8 @@ namespace ZL {
VertexRenderStruct loadingMesh; VertexRenderStruct loadingMesh;
bool loadingCompleted = false; bool loadingCompleted = false;
std::shared_ptr<ShadowMap> shadowMap;
// setupPart2() populates this queue with one closure per loading step instead of // setupPart2() populates this queue with one closure per loading step instead of
// running the work itself; Game::update() drains one step per frame so the window // running the work itself; Game::update() drains one step per frame so the window
// keeps pumping events / repainting (and, on Emscripten, the browser keeps the tab // keeps pumping events / repainting (and, on Emscripten, the browser keeps the tab
@ -117,6 +119,8 @@ namespace ZL {
void loadGame(int slot); void loadGame(int slot);
SaveSlotInfo readSlotInfo(int slot) const; SaveSlotInfo readSlotInfo(int slot) const;
void createLocations(); void createLocations();
void createShadowMapAndProparateToLocations();
void destroyShadowMapAndProparateToLocations();
// Reset entry point used by "Start New Game": loads resources/config/start_state.json // Reset entry point used by "Start New Game": loads resources/config/start_state.json
// into the existing Location objects if present, else falls back to performFullReset(). // into the existing Location objects if present, else falls back to performFullReset().

View File

@ -168,13 +168,6 @@ namespace ZL
loadTriggerZones(params.triggerZonesJsonPath, CONST_ZIP_FILE); loadTriggerZones(params.triggerZonesJsonPath, CONST_ZIP_FILE);
loadPointLights(params.lightsJsonPath, CONST_ZIP_FILE); loadPointLights(params.lightsJsonPath, CONST_ZIP_FILE);
//#ifndef EMSCRIPTEN
// Create shadow map (2048x2048, ortho size 40, near 0.1, far 100)
shadowMap = std::make_unique<ShadowMap>(2048, 40.0f, 0.1f, 100.0f);
shadowMap->setLightDirection(Eigen::Vector3f(-0.5f, -1.0f, -0.3f));
std::cout << "Shadow map initialized" << std::endl;
//#endif
setupNavigation(params.navigationJsonPaths); setupNavigation(params.navigationJsonPaths);
SDL_PumpEvents(); SDL_PumpEvents();

View File

@ -79,7 +79,7 @@ namespace ZL
std::vector<PathFinder> navigationMaps; std::vector<PathFinder> navigationMaps;
PathFinder* navigation = nullptr; PathFinder* navigation = nullptr;
std::unique_ptr<ShadowMap> shadowMap; std::shared_ptr<ShadowMap> shadowMap;
Eigen::Matrix4f cameraViewMatrix = Eigen::Matrix4f::Identity(); Eigen::Matrix4f cameraViewMatrix = Eigen::Matrix4f::Identity();
std::unique_ptr<TextRenderer> npcNameText; std::unique_ptr<TextRenderer> npcNameText;

View File

@ -12,7 +12,8 @@
namespace ZL { namespace ZL {
static const std::string EMPTY_LANGUAGE_RU = "(пусто)"; // Localization
static const std::string EMPTY_LANGUAGE_RU = u8"(пусто)";
static const std::string EMPTY_LANGUAGE_EN = "(empty)"; static const std::string EMPTY_LANGUAGE_EN = "(empty)";
@ -91,12 +92,12 @@ namespace ZL {
if (negative) result = "-" + result; if (negative) result = "-" + result;
//Localization
if (g_currentLanguage == Language::English) if (g_currentLanguage == Language::English)
{ {
return result + " som"; return result + " som";
} }
return result + " сом"; return result + u8" сом";
} }
static std::array<float, 4> questStatusColor(Quest::QuestStatus status) { static std::array<float, 4> questStatusColor(Quest::QuestStatus status) {
@ -113,13 +114,14 @@ namespace ZL {
gameState_(gameState), gameState_(gameState),
audioPlayer_(audioPlayer) audioPlayer_(audioPlayer)
{ {
localizedLocationName["uni_interior"][Language::Russian] = "Университет, 3 этаж"; //Localization
localizedLocationName["uni_interior"][Language::Russian] = u8"Университет, 3 этаж";
localizedLocationName["uni_interior"][Language::English] = "University, 3rd floor"; localizedLocationName["uni_interior"][Language::English] = "University, 3rd floor";
localizedLocationName["uni_exterior"][Language::Russian] = "Университет, двор"; localizedLocationName["uni_exterior"][Language::Russian] = u8"Университет, двор";
localizedLocationName["uni_exterior"][Language::English] = "University, exterior"; localizedLocationName["uni_exterior"][Language::English] = "University, exterior";
localizedLocationName["location_dorm"][Language::Russian] = "Общежитие, 1 этаж"; localizedLocationName["location_dorm"][Language::Russian] = u8"Общежитие, 1 этаж";
localizedLocationName["location_dorm"][Language::English] = "Dormitory, 1st floor"; localizedLocationName["location_dorm"][Language::English] = "Dormitory, 1st floor";
} }
@ -214,6 +216,7 @@ namespace ZL {
mainMenuRoot = loadLocalizedUi("resources/w/ui/screen_main_menu.json", zipFile); mainMenuRoot = loadLocalizedUi("resources/w/ui/screen_main_menu.json", zipFile);
aboutScreenRoot = loadLocalizedUi("resources/w/ui/screen_about.json", zipFile); aboutScreenRoot = loadLocalizedUi("resources/w/ui/screen_about.json", zipFile);
settingsScreenRoot = loadLocalizedUi("resources/w/ui/screen_settings.json", zipFile); settingsScreenRoot = loadLocalizedUi("resources/w/ui/screen_settings.json", zipFile);
settingsGraphicsScreenRoot = loadLocalizedUi("resources/w/ui/screen_settings_graphics.json", zipFile);
languageScreenRoot = loadLocalizedUi("resources/w/ui/screen_language.json", zipFile); languageScreenRoot = loadLocalizedUi("resources/w/ui/screen_language.json", zipFile);
loadSavedGameScreenRoot = loadLocalizedUi("resources/w/ui/screen_load.json", zipFile); loadSavedGameScreenRoot = loadLocalizedUi("resources/w/ui/screen_load.json", zipFile);
saveGameScreenRoot = loadLocalizedUi("resources/w/ui/screen_save.json", zipFile); saveGameScreenRoot = loadLocalizedUi("resources/w/ui/screen_save.json", zipFile);
@ -393,6 +396,11 @@ namespace ZL {
audioPlayer_.playSoundAsync("audio/751089__smallconfusion__mechanical-plastic-click-11.ogg"); audioPlayer_.playSoundAsync("audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
}); });
uiManager.setTextButtonCallback("graphicsButton", [this](const std::string&) {
showSettingsGraphicsScreen();
audioPlayer_.playSoundAsync("audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
});
// Set initial slider positions before registering callbacks so // Set initial slider positions before registering callbacks so
// setSliderValue does not fire an unregistered callback. // setSliderValue does not fire an unregistered callback.
const float musicFrac = audioPlayer_.getMusicVolume() / 128.0f; const float musicFrac = audioPlayer_.getMusicVolume() / 128.0f;
@ -400,6 +408,7 @@ namespace ZL {
uiManager.setSliderValue("musicVolumeSlider", musicFrac); uiManager.setSliderValue("musicVolumeSlider", musicFrac);
uiManager.setSliderValue("soundVolumeSlider", soundFrac); uiManager.setSliderValue("soundVolumeSlider", soundFrac);
// Localization
if (g_currentLanguage == Language::English) if (g_currentLanguage == Language::English)
{ {
musicVolumePrefix = "Music volume: "; musicVolumePrefix = "Music volume: ";
@ -408,19 +417,15 @@ namespace ZL {
musicToggleOff = "Music: OFF"; musicToggleOff = "Music: OFF";
soundToggleOn = "Sound: ON"; soundToggleOn = "Sound: ON";
soundToggleOff = "Sound: OFF"; soundToggleOff = "Sound: OFF";
fullScreenToggleOn = "Full Screen: ON";
fullScreenToggleOff = "Full Screen: OFF";
} }
else if (g_currentLanguage == Language::Russian) else if (g_currentLanguage == Language::Russian)
{ {
musicVolumePrefix = "Громкость музыки: "; musicVolumePrefix = u8"Громкость музыки: ";
soundVolumePrefix = "Громкость звука: "; soundVolumePrefix = u8"Громкость звука: ";
musicToggleOn = "Музыка: ВКЛ"; musicToggleOn = u8"Музыка: ВКЛ";
musicToggleOff = "Музыка: ВЫКЛ"; musicToggleOff = u8"Музыка: ВЫКЛ";
soundToggleOn = "Звук: ВКЛ"; soundToggleOn = u8"Звук: ВКЛ";
soundToggleOff = "Звук: ВЫКЛ"; soundToggleOff = u8"Звук: ВЫКЛ";
fullScreenToggleOn = "Полноэкранный режим: ВКЛ";
fullScreenToggleOff = "Полноэкранный режим: ВЫКЛ";
} }
uiManager.setText("musicVolumeText", uiManager.setText("musicVolumeText",
@ -458,17 +463,9 @@ namespace ZL {
? std::array<float, 4>{ 0.2f, 0.9f, 0.2f, 1.0f } ? std::array<float, 4>{ 0.2f, 0.9f, 0.2f, 1.0f }
: std::array<float, 4>{ 0.9f, 0.2f, 0.2f, 1.0f });*/ : std::array<float, 4>{ 0.9f, 0.2f, 0.2f, 1.0f });*/
}; };
auto refreshFullscreenToggle = [this]() {
const bool on = Environment::isFullscreen;
uiManager.setTextButtonText("fullScreenToggleButton", on ? fullScreenToggleOn : fullScreenToggleOff);
/*uiManager.setTextButtonColor("fullScreenToggleButton", on
? std::array<float, 4>{ 0.2f, 0.9f, 0.2f, 1.0f }
: std::array<float, 4>{ 0.9f, 0.2f, 0.2f, 1.0f });*/
};
refreshMusicToggle(); refreshMusicToggle();
refreshSoundToggle(); refreshSoundToggle();
refreshFullscreenToggle();
uiManager.setTextButtonCallback("musicToggleButton", [this](const std::string&) { uiManager.setTextButtonCallback("musicToggleButton", [this](const std::string&) {
audioPlayer_.setMusicEnabled(!audioPlayer_.isMusicEnabled()); audioPlayer_.setMusicEnabled(!audioPlayer_.isMusicEnabled());
@ -488,11 +485,59 @@ namespace ZL {
: std::array<float, 4>{ 0.9f, 0.2f, 0.2f, 1.0f });*/ : std::array<float, 4>{ 0.9f, 0.2f, 0.2f, 1.0f });*/
audioPlayer_.playSoundAsync("audio/751089__smallconfusion__mechanical-plastic-click-11.ogg"); audioPlayer_.playSoundAsync("audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
}); });
}
void MenuManager::showSettingsGraphicsScreen() {
uiManager.pushMenuFromSavedRoot(settingsGraphicsScreenRoot);
uiManager.setTextButtonCallback("settingsBackButton", [this](const std::string&) {
//saveSettings();
uiManager.popMenu();
audioPlayer_.playSoundAsync("audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
});
// Localization
if (g_currentLanguage == Language::English)
{
fullScreenToggleOn = "Full Screen: ON";
fullScreenToggleOff = "Full Screen: OFF";
shadowToggleOn = "Shadows: ON";
shadowToggleOff = "Shadows: OFF";
}
else if (g_currentLanguage == Language::Russian)
{
fullScreenToggleOn = u8"Полноэкранный режим: ВКЛ";
fullScreenToggleOff = u8"Полноэкранный режим: ВЫКЛ";
shadowToggleOn = u8"Тени: ВКЛ";
shadowToggleOff = u8"Тени: ВЫКЛ";
}
auto refreshFullscreenToggle = [this]() {
const bool on = Environment::isFullscreen;
uiManager.setTextButtonText("fullScreenToggleButton", on ? fullScreenToggleOn : fullScreenToggleOff);
};
auto refreshShadowToggle = [this]() {
const bool on = this->shadowsEnabled;
uiManager.setTextButtonText("shadowToggleButton", on ? shadowToggleOn : shadowToggleOff);
};
refreshFullscreenToggle();
refreshShadowToggle();
uiManager.setTextButtonCallback("fullScreenToggleButton", [this, refreshFullscreenToggle](const std::string&) { uiManager.setTextButtonCallback("fullScreenToggleButton", [this, refreshFullscreenToggle](const std::string&) {
Environment::setFullscreen(!Environment::isFullscreen); Environment::setFullscreen(!Environment::isFullscreen);
refreshFullscreenToggle(); refreshFullscreenToggle();
audioPlayer_.playSoundAsync("audio/751089__smallconfusion__mechanical-plastic-click-11.ogg"); audioPlayer_.playSoundAsync("audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
}); });
uiManager.setTextButtonCallback("shadowToggleButton", [this, refreshShadowToggle](const std::string&) {
bool newValue = !this->shadowsEnabled;
shadowMapSettingsChangedFunc(newValue);
refreshShadowToggle();
audioPlayer_.playSoundAsync("audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
});
} }
void MenuManager::showLanguageScreen() { void MenuManager::showLanguageScreen() {
@ -2099,6 +2144,7 @@ namespace ZL {
root["soundEnabled"] = audioPlayer_.isSoundEnabled(); root["soundEnabled"] = audioPlayer_.isSoundEnabled();
root["fullscreen"] = Environment::isFullscreen; root["fullscreen"] = Environment::isFullscreen;
root["language"] = ZL::languageToCode(ZL::g_currentLanguage); root["language"] = ZL::languageToCode(ZL::g_currentLanguage);
root["shadow"] = shadowsEnabled;
saveJsonToFile(root, "settings.json"); saveJsonToFile(root, "settings.json");
} }
@ -2130,6 +2176,19 @@ namespace ZL {
Environment::setFullscreen(root["fullscreen"].get<bool>()); Environment::setFullscreen(root["fullscreen"].get<bool>());
#endif #endif
} }
if (root.contains("shadow")) {
if (shadowMapSettingsChangedFunc)
{
shadowMapSettingsChangedFunc(root["shadow"].get<bool>());
}
}
else
{
if (shadowMapSettingsChangedFunc)
{
shadowMapSettingsChangedFunc(shadowsEnabled);
}
}
} catch (const std::exception& e) { } catch (const std::exception& e) {
std::cerr << "[settings] Failed to parse settings.json: " << e.what() << std::endl; std::cerr << "[settings] Failed to parse settings.json: " << e.what() << std::endl;
} }

View File

@ -78,6 +78,8 @@ namespace ZL {
std::function<void(int)> onSaveGame; std::function<void(int)> onSaveGame;
std::function<void(int)> onLoadGame; std::function<void(int)> onLoadGame;
std::function<SaveSlotInfo(int)> getSlotInfoFunc; std::function<SaveSlotInfo(int)> getSlotInfoFunc;
std::function<void(bool)> shadowMapSettingsChangedFunc;
// Set by Game: runs the given closures one per frame with the loading // Set by Game: runs the given closures one per frame with the loading
// screen shown (same mechanism as the initial resource load), so a heavy // screen shown (same mechanism as the initial resource load), so a heavy
@ -126,6 +128,9 @@ namespace ZL {
std::shared_ptr<Texture> languageLoadingRu; std::shared_ptr<Texture> languageLoadingRu;
std::shared_ptr<Texture> languageLoadingEn; std::shared_ptr<Texture> languageLoadingEn;
bool shadowsEnabled = true;
protected: protected:
Renderer& renderer; Renderer& renderer;
@ -168,6 +173,7 @@ namespace ZL {
void showAboutScreen(); void showAboutScreen();
void showSettingsScreen(); void showSettingsScreen();
void showSettingsGraphicsScreen();
void showLanguageScreen(); void showLanguageScreen();
void showLoadGameScreen(); void showLoadGameScreen();
void showSaveGameScreen(); void showSaveGameScreen();
@ -257,6 +263,7 @@ namespace ZL {
std::shared_ptr<UiNode> mainMenuRoot; std::shared_ptr<UiNode> mainMenuRoot;
std::shared_ptr<UiNode> aboutScreenRoot; std::shared_ptr<UiNode> aboutScreenRoot;
std::shared_ptr<UiNode> settingsScreenRoot; std::shared_ptr<UiNode> settingsScreenRoot;
std::shared_ptr<UiNode> settingsGraphicsScreenRoot;
std::shared_ptr<UiNode> languageScreenRoot; std::shared_ptr<UiNode> languageScreenRoot;
std::shared_ptr<UiNode> loadSavedGameScreenRoot; std::shared_ptr<UiNode> loadSavedGameScreenRoot;
std::shared_ptr<UiNode> saveGameScreenRoot; std::shared_ptr<UiNode> saveGameScreenRoot;
@ -328,6 +335,8 @@ namespace ZL {
std::string soundToggleOff; std::string soundToggleOff;
std::string fullScreenToggleOn; std::string fullScreenToggleOn;
std::string fullScreenToggleOff; std::string fullScreenToggleOff;
std::string shadowToggleOn;
std::string shadowToggleOff;
}; };

View File

@ -235,6 +235,8 @@ int main(int argc, char *argv[]) {
try try
{ {
SDL_SetHint(SDL_HINT_WINDOWS_DPI_AWARENESS, "permonitorv2");
//SDL_SetHint(SDL_HINT_WINDOWS_DPI_SCALING, "1");
constexpr int CONST_WIDTH = ZL::Environment::CONST_DEFAULT_WIDTH; constexpr int CONST_WIDTH = ZL::Environment::CONST_DEFAULT_WIDTH;
constexpr int CONST_HEIGHT = ZL::Environment::CONST_DEFAULT_HEIGHT; constexpr int CONST_HEIGHT = ZL::Environment::CONST_DEFAULT_HEIGHT;
@ -261,6 +263,9 @@ int main(int argc, char *argv[]) {
if (settingsRoot.contains("fullscreen")) { if (settingsRoot.contains("fullscreen")) {
ZL::Environment::isFullscreen = settingsRoot["fullscreen"].get<bool>(); ZL::Environment::isFullscreen = settingsRoot["fullscreen"].get<bool>();
} }
if (settingsRoot.contains("isHighDPIEnabled")) {
ZL::Environment::isHighDPIEnabled = settingsRoot["isHighDPIEnabled"].get<bool>();
}
} catch (const std::exception& e) { } catch (const std::exception& e) {
std::cerr << "[settings] Failed to parse settings.json: " << e.what() << std::endl; std::cerr << "[settings] Failed to parse settings.json: " << e.what() << std::endl;
} }
@ -272,10 +277,27 @@ int main(int argc, char *argv[]) {
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP; windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
} }
SDL_DisplayMode dm;
if (SDL_GetCurrentDisplayMode(0, &dm) == 0) {
std::cout << "Desktop resolution: " << dm.w << "x" << dm.h << " @ " << dm.refresh_rate << "Hz\n";
}
else {
SDL_Log("SDL_GetCurrentDisplayMode failed: %s", SDL_GetError());
}
int windowWidth = ZL::Environment::width;
int windowHeight = ZL::Environment::height;
//In case if the game is launched on a small screen
if (dm.w <= 1280 && dm.h <= 720) {
windowWidth = round(dm.w / 1.5);
windowHeight = round(dm.h / 1.5);
}
ZL::Environment::window = SDL_CreateWindow( ZL::Environment::window = SDL_CreateWindow(
"Shadow Over Bishkek", "Shadow Over Bishkek",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
ZL::Environment::width, ZL::Environment::height, windowWidth, windowHeight,
windowFlags windowFlags
); );
@ -285,11 +307,21 @@ int main(int argc, char *argv[]) {
// On HiDPI displays the drawable (physical) size is larger than the // On HiDPI displays the drawable (physical) size is larger than the
// logical window size. Use the drawable size so the GL framebuffer // logical window size. Use the drawable size so the GL framebuffer
// covers every physical pixel and the image stays sharp. // covers every physical pixel and the image stays sharp.
if (ZL::Environment::isHighDPIEnabled)
{ {
int drawW, drawH; int drawW, drawH;
SDL_GL_GetDrawableSize(ZL::Environment::window, &drawW, &drawH); SDL_GL_GetDrawableSize(ZL::Environment::window, &drawW, &drawH);
ZL::Environment::width = drawW; ZL::Environment::width = drawW;
ZL::Environment::height = drawH; ZL::Environment::height = drawH;
std::cout << "HiDPI enabled, drawable size: " << drawW << "x" << drawH << std::endl;
}
else
{
int winW, winH;
SDL_GetWindowSize(ZL::Environment::window, &winW, &winH);
ZL::Environment::width = winW;
ZL::Environment::height = winH;
std::cout << "HiDPI disabled, window size: " << winW << "x" << winH << std::endl;
} }
game.setup(); game.setup();