Fixing minor stuff, working on Web version
This commit is contained in:
1 parent
5ecf5fb9d7
commit
7df68febca
38 files changed
+502
-167
No files matched your search
@@ -22,7 +22,6 @@ int Environment::width = CONST_DEFAULT_WIDTH;
|
||||
int Environment::height = CONST_DEFAULT_HEIGHT;
|
||||
float Environment::zoom = DEFAULT_ZOOM;
|
||||
|
||||
|
||||
bool Environment::enableLogging = true;
|
||||
|
||||
SDL_Window* Environment::window = nullptr;
|
||||
|
||||
@@ -1291,6 +1291,8 @@ namespace FRG
|
||||
menuManager.onOrientationChanged();
|
||||
}
|
||||
|
||||
menuManager.refreshFullScreenToggleButton();
|
||||
|
||||
logger() << "Window resized (Render Size): " << Environment::width << "x" << Environment::height << std::endl;
|
||||
}
|
||||
|
||||
|
||||
+57
-11
@@ -28,9 +28,12 @@ namespace FRG {
|
||||
static const std::string BACK_TO_MAIN_MENU_EN = "Back to Main Menu";
|
||||
|
||||
static const std::string MUSIC_DOWNLOAD_ERROR_RU = u8"Ошибка скачивания музыки";
|
||||
static const std::string MUSIC_DOWNLOAD_NOT_STARTED_RU = u8"Нажмите сюда, чтобы скачать и установить музыку (27 MB).";
|
||||
static const std::string MUSIC_DOWNLOAD_NOT_STARTED_RU = u8"Скачать пакет с музыкой (27 MB).";
|
||||
static const std::string MUSIC_DOWNLOAD_PROGRESS_PREFIX_RU = u8"Загрузка музыки: ";
|
||||
//static const std::string MUSIC_DOWNLOAD_COMPLETED_RU = u8"Музыка успешно загружена.";
|
||||
|
||||
static const std::string MUSIC_DOWNLOAD_ERROR_EN = u8"Music download error";
|
||||
static const std::string MUSIC_DOWNLOAD_NOT_STARTED_EN = u8"Download music package (27 MB).";
|
||||
static const std::string MUSIC_DOWNLOAD_PROGRESS_PREFIX_EN = u8"Music download: ";
|
||||
|
||||
|
||||
static int questStatusPriority(Quest::QuestStatus status) {
|
||||
@@ -246,7 +249,7 @@ namespace FRG {
|
||||
void MenuManager::loadUiRoots(const std::string& zipFile) {
|
||||
hudRoot = loadLocalizedUi("resources/w/ui/hud_step0.json", zipFile);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#if defined(__ANDROID__)
|
||||
hudStep1Root = loadLocalizedUi("resources/w/ui/hud_step1android.json", zipFile);
|
||||
hudStep2Root = loadLocalizedUi("resources/w/ui/hud_step2android.json", zipFile);
|
||||
#else
|
||||
@@ -288,7 +291,10 @@ namespace FRG {
|
||||
hudUniIntDarkFullRoot = loadLocalizedUi("resources/w/ui/hud_uni_int_dark_full.json", zipFile);
|
||||
hudUniExtDarkRoot = loadLocalizedUi("resources/w/ui/hud_uni_ext_dark.json", zipFile);
|
||||
|
||||
hudCutsceneRoot_ = loadLocalizedUi("resources/w/ui/hud_cutscene.json", zipFile);
|
||||
//hudCutsceneRoot_ = loadLocalizedUi("resources/w/ui/hud_cutscene.json", zipFile);
|
||||
hudCutsceneRoot_ = loadUiFromFile("resources/w/ui/hud_cutscene.json", renderer, zipFile);
|
||||
|
||||
|
||||
hudTopHintRoot_ = loadLocalizedUi("resources/w/ui/hud_top_hint01.json", zipFile);
|
||||
|
||||
phoneMainRoot = loadLocalizedUi("resources/w/ui/screen_phone.json", zipFile);
|
||||
@@ -329,12 +335,18 @@ namespace FRG {
|
||||
portraitQuestJournalListRoot = loadLocalizedUi("resources/w/ui/portrait_screen_journal.json", zipFile);
|
||||
portraitQuestJournalItemRoot = loadLocalizedUi("resources/w/ui/portrait_screen_journal_item.json", zipFile);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#if defined(__ANDROID__) || defined(__EMSCRIPTEN__)
|
||||
mainMenuRoot = loadLocalizedUi("resources/w/ui/screen_main_menu_android.json", zipFile);
|
||||
aboutScreenRoot = loadLocalizedUi("resources/w/ui/screen_about_android.json", zipFile);
|
||||
#else
|
||||
mainMenuRoot = loadLocalizedUi("resources/w/ui/screen_main_menu.json", zipFile);
|
||||
aboutScreenRoot = loadLocalizedUi("resources/w/ui/screen_about.json", zipFile);
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
aboutScreenRoot = loadLocalizedUi("resources/w/ui/screen_about_android.json", zipFile);
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
aboutScreenRoot = loadLocalizedUi("resources/w/ui/screen_about_web.json", zipFile);
|
||||
#else
|
||||
aboutScreenRoot = loadLocalizedUi("resources/w/ui/screen_about.json", zipFile);
|
||||
#endif
|
||||
|
||||
creditsScreenRoot = loadLocalizedUi("resources/w/ui/screen_credits.json", zipFile);
|
||||
@@ -615,13 +627,19 @@ namespace FRG {
|
||||
});
|
||||
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#ifdef __EMSCRIPTEN__
|
||||
uiManager.setTextButtonCallback("websiteButton", [this](const std::string&) {
|
||||
audioPlayer_.playSoundAsync("resources/audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
|
||||
SDL_OpenURL("https://shadowoverbishkek.com/");
|
||||
});
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
uiManager.setTextButtonCallback("reviewButton", [this](const std::string&) {
|
||||
audioPlayer_.playSoundAsync("resources/audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
|
||||
SDL_OpenURL("https://play.google.com/store/apps/details?id=fishrungames.shadowoverbishkek");
|
||||
});
|
||||
#endif
|
||||
uiManager.setTextButtonCallback("telegramButton", [this](const std::string&) {
|
||||
audioPlayer_.playSoundAsync("resources/audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
|
||||
SDL_OpenURL("https://telegram.me/fishrungames");
|
||||
@@ -838,6 +856,23 @@ namespace FRG {
|
||||
});
|
||||
}
|
||||
|
||||
void MenuManager::refreshFullScreenToggleButton()
|
||||
{
|
||||
// Localization
|
||||
if (g_currentLanguage == Language::English)
|
||||
{
|
||||
fullScreenToggleOn = "Full Screen: ON";
|
||||
fullScreenToggleOff = "Full Screen: OFF";
|
||||
}
|
||||
else if (g_currentLanguage == Language::Russian)
|
||||
{
|
||||
fullScreenToggleOn = u8"Полноэкранный режим: ВКЛ";
|
||||
fullScreenToggleOff = u8"Полноэкранный режим: ВЫКЛ";
|
||||
}
|
||||
|
||||
const bool on = Environment::isFullscreen;
|
||||
uiManager.setTextButtonText("fullScreenToggleButton", on ? fullScreenToggleOn : fullScreenToggleOff);
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
void MenuManager::showSettingsNoMusicWebScreen()
|
||||
@@ -863,23 +898,30 @@ namespace FRG {
|
||||
const float soundFrac = audioPlayer_.getSoundVolume() / 128.0f;
|
||||
uiManager.setSliderValue("soundVolumeSlider", soundFrac);
|
||||
|
||||
static std::string musicDownloadErrorString;// = MUSIC_DOWNLOAD_ERROR_RU;
|
||||
static std::string musicDownloadNotStartedString;// = MUSIC_DOWNLOAD_NOT_STARTED_RU;
|
||||
static std::string musicDownloadProgressPrefix;// = MUSIC_DOWNLOAD_PROGRESS_PREFIX_RU;
|
||||
|
||||
// Localization
|
||||
if (g_currentLanguage == Language::English)
|
||||
{
|
||||
soundVolumePrefix = "Sound volume: ";
|
||||
soundToggleOn = "Sound: ON";
|
||||
soundToggleOff = "Sound: OFF";
|
||||
musicDownloadErrorString = MUSIC_DOWNLOAD_ERROR_EN;
|
||||
musicDownloadNotStartedString = MUSIC_DOWNLOAD_NOT_STARTED_EN;
|
||||
musicDownloadProgressPrefix = MUSIC_DOWNLOAD_PROGRESS_PREFIX_EN;
|
||||
}
|
||||
else if (g_currentLanguage == Language::Russian)
|
||||
{
|
||||
soundVolumePrefix = u8"Громкость звука: ";
|
||||
soundToggleOn = u8"Звук: ВКЛ";
|
||||
soundToggleOff = u8"Звук: ВЫКЛ";
|
||||
musicDownloadErrorString = MUSIC_DOWNLOAD_ERROR_RU;
|
||||
musicDownloadNotStartedString = MUSIC_DOWNLOAD_NOT_STARTED_RU;
|
||||
musicDownloadProgressPrefix = MUSIC_DOWNLOAD_PROGRESS_PREFIX_RU;
|
||||
}
|
||||
|
||||
static std::string musicDownloadErrorString = u8"Ошибка скачивания музыки";
|
||||
static std::string musicDownloadNotStartedString = u8"Нажмите сюда, чтобы скачать\nи установить музыку (27 MB).";
|
||||
static std::string musicDownloadProgressPrefix = u8"Загрузка музыки: ";
|
||||
|
||||
// musicDownloadStarted = false;
|
||||
//musicDownloadError = false;
|
||||
@@ -969,13 +1011,17 @@ namespace FRG {
|
||||
});
|
||||
|
||||
uiManager.setTextButtonCallback("languageRussianButton", [this](const std::string&) {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
audioPlayer_.playSoundAsync("resources/audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
|
||||
#endif
|
||||
FRG::g_currentLanguage = FRG::Language::Russian;
|
||||
reloadLocalizedGameContent();
|
||||
saveSettings();
|
||||
});
|
||||
uiManager.setTextButtonCallback("languageEnglishButton", [this](const std::string&) {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
audioPlayer_.playSoundAsync("resources/audio/751089__smallconfusion__mechanical-plastic-click-11.ogg");
|
||||
#endif
|
||||
FRG::g_currentLanguage = FRG::Language::English;
|
||||
reloadLocalizedGameContent();
|
||||
saveSettings();
|
||||
|
||||
@@ -129,7 +129,14 @@ namespace FRG {
|
||||
std::shared_ptr<Texture> languageLoadingRu;
|
||||
std::shared_ptr<Texture> languageLoadingEn;
|
||||
|
||||
|
||||
void refreshFullScreenToggleButton();
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
bool shadowsEnabled = false;
|
||||
#else
|
||||
bool shadowsEnabled = true;
|
||||
#endif
|
||||
std::string lastMusicTrack;
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
@@ -189,6 +196,7 @@ namespace FRG {
|
||||
void showCreditsScreen();
|
||||
void showSettingsScreen();
|
||||
void showSettingsGraphicsScreen();
|
||||
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
void showSettingsNoMusicWebScreen();
|
||||
|
||||
+4
-4
@@ -798,14 +798,14 @@ namespace FRG {
|
||||
else {
|
||||
auto buf = readFileFromZIP(path, zipFile);
|
||||
if (buf.empty()) {
|
||||
std::cerr << "UiManager: failed to read " << path << " from zip " << zipFile << std::endl;
|
||||
logger() << "UiManager: failed to read " << path << " from zip " << zipFile << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
content.assign(buf.begin(), buf.end());
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "UiManager: failed to open " << path << " : " << e.what() << std::endl;
|
||||
logger() << "UiManager: failed to open " << path << " : " << e.what() << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
|
||||
@@ -814,12 +814,12 @@ namespace FRG {
|
||||
j = json::parse(content);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "UiManager: json parse error: " << e.what() << std::endl;
|
||||
logger() << "UiManager: json parse error: " << e.what() << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
|
||||
if (!j.contains("root") || !j["root"].is_object()) {
|
||||
std::cerr << "UiManager: root node missing or invalid" << std::endl;
|
||||
logger() << "UiManager: root node missing or invalid" << std::endl;
|
||||
throw std::runtime_error("Failed to load UI file: " + path);
|
||||
}
|
||||
|
||||
|
||||
+80
-59
@@ -20,15 +20,48 @@
|
||||
FRG::Game* g_game = nullptr;
|
||||
|
||||
|
||||
// Read the persisted fullscreen preference (if any) before creating the
|
||||
// window, so it opens directly in the right mode instead of flashing
|
||||
// windowed -> fullscreen once settings are loaded later during setupPart2().
|
||||
|
||||
void readSettings()
|
||||
{
|
||||
|
||||
const std::string settingsContent = FRG::readSavedTextFile("settings.json");
|
||||
if (!settingsContent.empty()) {
|
||||
try {
|
||||
const nlohmann::json settingsRoot = nlohmann::json::parse(settingsContent);
|
||||
if (settingsRoot.contains("fullscreen")) {
|
||||
FRG::Environment::isFullscreen = settingsRoot["fullscreen"].get<bool>();
|
||||
}
|
||||
|
||||
if (settingsRoot.contains("isHighDPIEnabled")) {
|
||||
FRG::Environment::isHighDPIEnabled = settingsRoot["isHighDPIEnabled"].get<bool>();
|
||||
}
|
||||
|
||||
if (settingsRoot.contains("enableLogging")) {
|
||||
FRG::Environment::enableLogging = settingsRoot["enableLogging"].get<bool>();
|
||||
}
|
||||
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "[settings] Failed to parse settings.json: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(EMSCRIPTEN)
|
||||
static SDL_GLContext glContext_x;
|
||||
static bool g_isFsLoaded = false; // Флаг готовности
|
||||
|
||||
static bool g_pendingFullscreenResize = false;
|
||||
|
||||
// Макрос EMSCRIPTEN_KEEPALIVE экспортирует функцию в глобальный объект Module
|
||||
extern "C" void EMSCRIPTEN_KEEPALIVE onFileSystemLoaded() {
|
||||
// 1. Файлы загружены. Теперь можно читать настройки и логи
|
||||
// Если функции readSettings() нет для Emscripten, форсируем логгер:
|
||||
FRG::Environment::enableLogging = true;
|
||||
//FRG::Environment::enableLogging = true;
|
||||
//readSettings();
|
||||
FRG::initLogger();
|
||||
|
||||
FRG::logger() << "[boot] File system is ready. Setting up game..." << std::endl;
|
||||
@@ -40,26 +73,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE onFileSystemLoaded() {
|
||||
// 3. Даем отмашку главному циклу
|
||||
g_isFsLoaded = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void MainLoop() {
|
||||
#if defined(EMSCRIPTEN)
|
||||
// Крутим цикл вхолостую, пока JS читает IndexedDB
|
||||
if (!g_isFsLoaded) return;
|
||||
#endif
|
||||
|
||||
g_game->update();
|
||||
}
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
|
||||
EM_BOOL onWebGLContextLost(int /*eventType*/, const void* /*reserved*/, void* /*userData*/) {
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
EM_BOOL onWebGLContextRestored(int /*eventType*/, const void* /*reserved*/, void* /*userData*/) {
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
static void applyResize(int logicalW, int logicalH) {
|
||||
// Получаем коэффициент плотности пикселей (например, 2.625 на Pixel или 3.0 на Samsung)
|
||||
@@ -92,22 +106,59 @@ static void applyResize(int logicalW, int logicalH) {
|
||||
<< " (physical: " << physicalW << "x" << physicalH
|
||||
<< ", DPR: " << dpr << ")" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
void MainLoop() {
|
||||
#if defined(EMSCRIPTEN)
|
||||
// Крутим цикл вхолостую, пока JS читает IndexedDB
|
||||
if (!g_isFsLoaded) return;
|
||||
|
||||
if (g_pendingFullscreenResize) {
|
||||
g_pendingFullscreenResize = false;
|
||||
|
||||
// Теперь DOM перестроен, можно забирать актуальные размеры.
|
||||
// Если canvas должен занимать все окно браузера:
|
||||
int canvasW = EM_ASM_INT({ return window.innerWidth; });
|
||||
int canvasH = EM_ASM_INT({ return window.innerHeight; });
|
||||
|
||||
applyResize(canvasW, canvasH);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_game->update();
|
||||
}
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
|
||||
|
||||
EM_BOOL onWebGLContextLost(int /*eventType*/, const void* /*reserved*/, void* /*userData*/) {
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
EM_BOOL onWebGLContextRestored(int /*eventType*/, const void* /*reserved*/, void* /*userData*/) {
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
|
||||
EM_BOOL onWindowResized(int /*eventType*/, const EmscriptenUiEvent* e, void* /*userData*/) {
|
||||
// Use the event's window dimensions — querying the canvas element would
|
||||
// return its old fixed size (e.g. 1280x720) before it has been resized.
|
||||
applyResize(e->windowInnerWidth, e->windowInnerHeight);
|
||||
double w, h;
|
||||
emscripten_get_element_css_size("window", &w, &h);
|
||||
|
||||
// Если "window" не поддерживается вашей версией SDK, используем данные из e:
|
||||
// int logicalW = e->windowInnerWidth;
|
||||
// int logicalH = e->windowInnerHeight;
|
||||
|
||||
applyResize(static_cast<int>(w), static_cast<int>(h));
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
EM_BOOL onFullscreenChanged(int /*eventType*/, const EmscriptenFullscreenChangeEvent* e, void* /*userData*/) {
|
||||
FRG::Environment::isFullscreen = e->isFullscreen;
|
||||
FRG::logger() << "onFullscreenChanged: isFullscreen = " << e->isFullscreen << std::endl;
|
||||
|
||||
// Браузер еще не обновил DOM. Ставим флаг, чтобы применить размеры в следующем кадре.
|
||||
g_pendingFullscreenResize = true;
|
||||
|
||||
// Вместо window.innerWidth, попробуйте запросить размер целевого элемента
|
||||
// так как после перехода в FS именно он растягивается на весь экран.
|
||||
double clientW, clientH;
|
||||
emscripten_get_element_css_size("#canvas", &clientW, &clientH);
|
||||
applyResize(clientW, clientH);
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
@@ -128,7 +179,7 @@ int main(int argc, char* argv[]) {
|
||||
emscripten_set_webglcontextrestored_callback("#canvas", nullptr, EM_TRUE, onWebGLContextRestored);
|
||||
|
||||
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, EM_FALSE, onWindowResized);
|
||||
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, EM_FALSE, onFullscreenChanged);
|
||||
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, EM_TRUE, onFullscreenChanged);
|
||||
|
||||
int canvasW = EM_ASM_INT({ return window.innerWidth; });
|
||||
int canvasH = EM_ASM_INT({ return window.innerHeight; });
|
||||
@@ -289,36 +340,6 @@ int main(int argc, char* argv[]) {
|
||||
#ifndef __ANDROID__
|
||||
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__linux__)
|
||||
|
||||
// Read the persisted fullscreen preference (if any) before creating the
|
||||
// window, so it opens directly in the right mode instead of flashing
|
||||
// windowed -> fullscreen once settings are loaded later during setupPart2().
|
||||
void readSettings()
|
||||
{
|
||||
|
||||
const std::string settingsContent = FRG::readSavedTextFile("settings.json");
|
||||
if (!settingsContent.empty()) {
|
||||
try {
|
||||
const nlohmann::json settingsRoot = nlohmann::json::parse(settingsContent);
|
||||
if (settingsRoot.contains("fullscreen")) {
|
||||
FRG::Environment::isFullscreen = settingsRoot["fullscreen"].get<bool>();
|
||||
}
|
||||
|
||||
if (settingsRoot.contains("isHighDPIEnabled")) {
|
||||
FRG::Environment::isHighDPIEnabled = settingsRoot["isHighDPIEnabled"].get<bool>();
|
||||
}
|
||||
|
||||
if (settingsRoot.contains("enableLogging")) {
|
||||
FRG::Environment::enableLogging = settingsRoot["enableLogging"].get<bool>();
|
||||
}
|
||||
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "[settings] Failed to parse settings.json: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
||||
SDL_GLContext ctx = nullptr;
|
||||
|
||||
@@ -509,8 +509,13 @@ namespace FRG
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
return g_androidStream;
|
||||
#else
|
||||
#ifdef __EMSCRIPTEN__
|
||||
return g_nullStream; //For web, remove all logging to browser console
|
||||
#else
|
||||
return std::cout;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user