Clean up UI, work on tutorial
This commit is contained in:
1 parent
cfbd29d5b1
commit
619de45221
79 files changed
+5122
-316
No files matched your search
+297
-11
@@ -100,20 +100,29 @@ namespace ZL {
|
||||
hudUniIntFullRoot = loadUiFromFile("resources/w/ui/hud_uni_int_full.json", renderer, zipFile);
|
||||
hudUniIntDarkFullRoot = loadUiFromFile("resources/w/ui/hud_uni_int_dark_full.json", renderer, zipFile);
|
||||
hudUniExtDarkRoot = loadUiFromFile("resources/w/ui/hud_uni_ext_dark.json", renderer, zipFile);
|
||||
|
||||
hudCutsceneRoot_ = loadUiFromFile("resources/w/ui/hud_cutscene.json", renderer, zipFile);
|
||||
hudTopHintRoot_ = loadUiFromFile("resources/w/ui/hud_top_hint01.json", renderer, zipFile);
|
||||
|
||||
phoneMainRoot = loadUiFromFile("resources/w/ui/screen_phone.json", renderer, zipFile);
|
||||
phoneMainHintARoot = loadUiFromFile("resources/w/ui/screen_phone_hint001.json", renderer, zipFile);
|
||||
phoneMainHintBRoot = loadUiFromFile("resources/w/ui/screen_phone_hint002.json", renderer, zipFile);
|
||||
phoneMainHintABRoot = loadUiFromFile("resources/w/ui/screen_phone_hint001_002.json", renderer, zipFile);
|
||||
|
||||
phoneBankRoot = loadUiFromFile("resources/w/ui/screen_phone_bank.json", renderer, zipFile);
|
||||
phoneVideoRoot = loadUiFromFile("resources/w/ui/screen_phone_video.json", renderer, zipFile);
|
||||
phoneMapDormRoot = loadUiFromFile("resources/w/ui/screen_phone_map_dorm.json", renderer, zipFile);
|
||||
phoneMapUniRoot = loadUiFromFile("resources/w/ui/screen_phone_map_uni.json", renderer, zipFile);
|
||||
phoneChatListRoot = loadUiFromFile("resources/w/ui/screen_phone_chat_list.json", renderer, zipFile);
|
||||
phoneChatListHintRoot = loadUiFromFile("resources/w/ui/screen_phone_chat_list_hint001.json", renderer, zipFile);
|
||||
phoneChat1Root = loadUiFromFile("resources/w/ui/screen_phone_chat1.json", renderer, zipFile);
|
||||
phoneChat2Root = loadUiFromFile("resources/w/ui/screen_phone_chat2.json", renderer, zipFile);
|
||||
phoneChat3Root = loadUiFromFile("resources/w/ui/screen_phone_chat3.json", renderer, zipFile);
|
||||
|
||||
newInventoryRoot = loadUiFromFile("resources/w/ui/screen_inventory.json", renderer, zipFile);
|
||||
questJournalRoot = loadUiFromFile("resources/w/ui/screen_journal.json", renderer, zipFile);
|
||||
newInventoryRoot = loadUiFromFile("resources/w/ui/screen_inventory.json", renderer, zipFile);
|
||||
questJournalRoot = loadUiFromFile("resources/w/ui/screen_journal.json", renderer, zipFile);
|
||||
mainMenuRoot = loadUiFromFile("resources/w/ui/screen_main_menu.json", renderer, zipFile);
|
||||
aboutScreenRoot = loadUiFromFile("resources/w/ui/screen_about.json", renderer, zipFile);
|
||||
|
||||
texObjectiveCompleted_ = renderer.textureManager.LoadFromPng("resources/w/ui/img/journal/quest_objective_completed.png", zipFile, true);
|
||||
texObjectiveBlank_ = renderer.textureManager.LoadFromPng("resources/w/ui/img/journal/quest_objective_blank.png", zipFile, true);
|
||||
@@ -122,6 +131,29 @@ namespace ZL {
|
||||
|
||||
questJournal.loadFromFile("resources/quests/quests.json", zipFile);
|
||||
|
||||
renderer.textureManager.LoadFromPng("resources/w/ui/img/toast/quest_new001.png", zipFile, true);
|
||||
renderer.textureManager.LoadFromPng("resources/w/ui/img/toast/quest_completed001.png", zipFile, true);
|
||||
renderer.textureManager.LoadFromPng("resources/w/ui/img/toast/quest_failed001.png", zipFile, true);
|
||||
|
||||
|
||||
questJournal.onQuestUnlocked = [this](const std::string& id) {
|
||||
const Quest::QuestState* q = questJournal.findQuest(id);
|
||||
if (q) showToast("resources/w/ui/img/toast/quest_new001.png", q->definition.title);
|
||||
};
|
||||
questJournal.onQuestCompleted = [this](const std::string& id) {
|
||||
const Quest::QuestState* q = questJournal.findQuest(id);
|
||||
if (q) showToast("resources/w/ui/img/toast/quest_completed001.png", q->definition.title);
|
||||
};
|
||||
questJournal.onQuestFailed = [this](const std::string& id) {
|
||||
const Quest::QuestState* q = questJournal.findQuest(id);
|
||||
if (q) showToast("resources/w/ui/img/toast/quest_failed001.png", q->definition.title);
|
||||
};
|
||||
/*
|
||||
questJournal.onObjectiveCompleted = [this](const std::string& id, const std::string&) {
|
||||
const Quest::QuestState* q = questJournal.findQuest(id);
|
||||
if (q) showToast("resources/w/ui/img/toast/objective_completed001.png", q->definition.title);
|
||||
};*/
|
||||
|
||||
const std::string imgDir = "resources/w/ui/img/phone/";
|
||||
texBubbleInCenter_ = renderer.textureManager.LoadFromPng(imgDir + "bubble_in_center.png", zipFile, true);
|
||||
texBubbleInLT_ = renderer.textureManager.LoadFromPng(imgDir + "bubble_in_corner_left_top.png", zipFile, true);
|
||||
@@ -134,12 +166,16 @@ namespace ZL {
|
||||
texBubbleOutRT_ = renderer.textureManager.LoadFromPng(imgDir + "bubble_out_corner_right_top.png", zipFile, true);
|
||||
texBubbleOutRB_ = renderer.textureManager.LoadFromPng(imgDir + "bubble_out_corner_right_bottom.png",zipFile, true);
|
||||
|
||||
enterGameplay();
|
||||
showMainMenu();
|
||||
}
|
||||
|
||||
void MenuManager::enterGameplay() {
|
||||
if (state == GameState::MainMenu && startGameFunc) startGameFunc();
|
||||
state = GameState::Gameplay;
|
||||
uiManager.replaceRoot(hudRoot);
|
||||
topUiManager.replaceRoot(hudTopHintRoot_);
|
||||
|
||||
|
||||
applyCurrentHealthBar();
|
||||
/*
|
||||
uiManager.setTextButtonCallback("inventory_button", [this](const std::string&) {
|
||||
@@ -156,6 +192,33 @@ namespace ZL {
|
||||
//openInventory()
|
||||
}
|
||||
|
||||
void MenuManager::showMainMenu() {
|
||||
state = GameState::MainMenu;
|
||||
uiManager.replaceRoot(mainMenuRoot);
|
||||
|
||||
uiManager.setTextButtonCallback("menuStartButton", [this](const std::string&) {
|
||||
enterGameplay();
|
||||
});
|
||||
uiManager.setTextButtonCallback("menuAboutButton", [this](const std::string&) {
|
||||
showAboutScreen();
|
||||
});
|
||||
|
||||
#ifndef EMSCRIPTEN
|
||||
uiManager.setTextButtonCallback("menuExitButton", [this](const std::string&) {
|
||||
Environment::exitGameLoop = true;
|
||||
});
|
||||
#else
|
||||
uiManager.setNodeVisible("menuExitButton", false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MenuManager::showAboutScreen() {
|
||||
uiManager.pushMenuFromSavedRoot(aboutScreenRoot);
|
||||
uiManager.setTextButtonCallback("aboutBackButton", [this](const std::string&) {
|
||||
uiManager.popMenu();
|
||||
});
|
||||
}
|
||||
|
||||
void MenuManager::openInventory() {
|
||||
state = GameState::Inventory;
|
||||
uiManager.pushMenuFromSavedRoot(newInventoryRoot);
|
||||
@@ -248,7 +311,9 @@ namespace ZL {
|
||||
void MenuManager::openQuestJournal() {
|
||||
state = GameState::QuestJournal;
|
||||
tutorialJournalScreenOpened = true;
|
||||
|
||||
uiManager.setNodeVisible("hint6b", false);
|
||||
uiManager.setNodeVisible("hint6barrow", false);
|
||||
uiManager.pushMenuFromSavedRoot(questJournalRoot);
|
||||
|
||||
uiManager.setButtonCallback("journalExitButton", [this](const std::string&) {
|
||||
@@ -294,10 +359,30 @@ namespace ZL {
|
||||
|
||||
void MenuManager::openPhoneScreen() {
|
||||
state = GameState::PhoneScreen;
|
||||
tutorialPhoneScreenOpened = true;
|
||||
uiManager.setNodeVisible("hint6a", false);
|
||||
uiManager.pushMenuFromSavedRoot(phoneMainRoot);
|
||||
|
||||
//uiManager.setNodeVisible("hint6a", false);
|
||||
//uiManager.setNodeVisible("hint6aarrow", false);
|
||||
|
||||
//tutorialPhoneScreenOpened = true;
|
||||
|
||||
|
||||
if (tutorialNeedOpenTaxiScreen && (tutorialPhoneChatScreenOpened == false))
|
||||
{
|
||||
uiManager.pushMenuFromSavedRoot(phoneMainHintABRoot);
|
||||
}
|
||||
else if (tutorialNeedOpenTaxiScreen)
|
||||
{
|
||||
uiManager.pushMenuFromSavedRoot(phoneMainHintBRoot);
|
||||
}
|
||||
else if (tutorialPhoneChatScreenOpened == false)
|
||||
{
|
||||
uiManager.pushMenuFromSavedRoot(phoneMainHintARoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiManager.pushMenuFromSavedRoot(phoneMainRoot);
|
||||
}
|
||||
|
||||
uiManager.setButtonCallback("phoneExitButton", [this](const std::string&) {
|
||||
closePhoneEntirely();
|
||||
});
|
||||
@@ -338,7 +423,16 @@ namespace ZL {
|
||||
}
|
||||
|
||||
void MenuManager::openPhoneMessenger() {
|
||||
uiManager.pushMenuFromSavedRoot(phoneChatListRoot);
|
||||
|
||||
if (tutorialPhoneChatScreenOpened)
|
||||
{
|
||||
uiManager.pushMenuFromSavedRoot(phoneChatListRoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiManager.pushMenuFromSavedRoot(phoneChatListHintRoot);
|
||||
}
|
||||
//uiManager.pushMenuFromSavedRoot(phoneChatListRoot);
|
||||
refreshChatUnreadIndicators();
|
||||
|
||||
uiManager.setButtonCallback("phoneExitButton", [this](const std::string&) {
|
||||
@@ -430,6 +524,12 @@ namespace ZL {
|
||||
uiManager.popMenu();
|
||||
});
|
||||
uiManager.setButtonCallback("mapGo", [this](const std::string&) {
|
||||
tutorialNeedOpenTaxiScreen = false;
|
||||
|
||||
if (callTaxiFunc)
|
||||
{
|
||||
callTaxiFunc();
|
||||
}
|
||||
money_ -= 500;
|
||||
closePhoneEntirely();
|
||||
if (startDialogueFunc) startDialogueFunc("dialog_taxi002");
|
||||
@@ -439,6 +539,7 @@ namespace ZL {
|
||||
void MenuManager::openPhoneChatFromList(int chatIndex, std::shared_ptr<UiNode> chatRoot) {
|
||||
activeChatIndex_ = chatIndex;
|
||||
phoneChatVisibleBubbles_.clear();
|
||||
tutorialPhoneChatScreenOpened = true;
|
||||
uiManager.pushMenuFromSavedRoot(chatRoot);
|
||||
|
||||
rebuildChatBubblesFromHistory(chatIndex);
|
||||
@@ -460,6 +561,14 @@ namespace ZL {
|
||||
activeChatIndex_ = -1;
|
||||
phoneChatVisibleBubbles_.clear();
|
||||
uiManager.popMenu();
|
||||
if (tutorialPhoneChatScreenOpened)
|
||||
{
|
||||
uiManager.setNodeVisible("hint_m002", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiManager.setNodeVisible("hint_m002", true);
|
||||
}
|
||||
refreshChatUnreadIndicators();
|
||||
}
|
||||
|
||||
@@ -469,6 +578,32 @@ namespace ZL {
|
||||
phoneChatVisibleBubbles_.clear();
|
||||
const int depth = uiManager.menuStackSize();
|
||||
for (int i = 0; i < depth; ++i) uiManager.popMenu();
|
||||
|
||||
if (tutorialNeedOpenTaxiScreen)
|
||||
{
|
||||
uiManager.setNodeVisible("hint7", true);
|
||||
uiManager.setNodeVisible("hint7arrow", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiManager.setNodeVisible("hint7", false);
|
||||
uiManager.setNodeVisible("hint7arrow", false);
|
||||
|
||||
if (tutorialPhoneChatScreenOpened)
|
||||
{
|
||||
uiManager.setNodeVisible("hint6a", false);
|
||||
uiManager.setNodeVisible("hint6aarrow", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiManager.setNodeVisible("hint6a", true);
|
||||
uiManager.setNodeVisible("hint6aarrow", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MenuManager::closePhoneScreenFromChat() {
|
||||
@@ -479,6 +614,21 @@ namespace ZL {
|
||||
closePhoneEntirely();
|
||||
}
|
||||
|
||||
void MenuManager::tutorialShowTaxiHint()
|
||||
{
|
||||
std::cout << "tutorialShowTaxiHint" << std::endl;
|
||||
tutorialNeedOpenTaxiScreen = true;
|
||||
if (state == GameState::Gameplay)
|
||||
{
|
||||
uiManager.setNodeVisible("hint6a", false);
|
||||
uiManager.setNodeVisible("hint6aarrow", false);
|
||||
|
||||
uiManager.setNodeVisible("hint7", true);
|
||||
uiManager.setNodeVisible("hint7arrow", true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Registers phoneButton / journalButton callbacks on the current HUD root
|
||||
// and hides any hints that have already been completed.
|
||||
// Called after every replaceRoot during step 5.
|
||||
@@ -498,9 +648,30 @@ namespace ZL {
|
||||
openQuestJournal();
|
||||
});
|
||||
}
|
||||
if (tutorialPhoneScreenOpened) uiManager.setNodeVisible("hint6a", false);
|
||||
if (tutorialJournalScreenOpened) uiManager.setNodeVisible("hint6b", false);
|
||||
if (tutorialPhoneScreenOpened && tutorialJournalScreenOpened) {
|
||||
if (tutorialNeedOpenTaxiScreen)
|
||||
{
|
||||
uiManager.setNodeVisible("hint6a", false);
|
||||
uiManager.setNodeVisible("hint6aarrow", false);
|
||||
|
||||
uiManager.setNodeVisible("hint7", true);
|
||||
uiManager.setNodeVisible("hint7arrow", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiManager.setNodeVisible("hint7", false);
|
||||
uiManager.setNodeVisible("hint7arrow", false);
|
||||
}
|
||||
|
||||
if (tutorialPhoneChatScreenOpened) {
|
||||
uiManager.setNodeVisible("hint6a", false);
|
||||
uiManager.setNodeVisible("hint6aarrow", false);
|
||||
}
|
||||
if (tutorialJournalScreenOpened)
|
||||
{
|
||||
uiManager.setNodeVisible("hint6b", false);
|
||||
uiManager.setNodeVisible("hint6barrow", false);
|
||||
}
|
||||
if (tutorialPhoneChatScreenOpened && tutorialJournalScreenOpened) {
|
||||
tutorialStep = TutorialStep::Step6;
|
||||
}
|
||||
}
|
||||
@@ -514,6 +685,8 @@ namespace ZL {
|
||||
uiManager.setButtonCallback("journalButton", [this](const std::string&) { openQuestJournal(); });
|
||||
if (uiManager.findButton("darklandsButton"))
|
||||
uiManager.setButtonCallback("darklandsButton", [this](const std::string&) { startDarklandsTransitionFunc(); });
|
||||
hideAllToastWidgets();
|
||||
applyToastsToUi();
|
||||
}
|
||||
|
||||
void MenuManager::onLocationChanged(const std::string& locationName) {
|
||||
@@ -541,6 +714,7 @@ namespace ZL {
|
||||
case TutorialStep::Step0:
|
||||
tutorialStep = TutorialStep::Step1;
|
||||
nextRoot = hudStep1Root;
|
||||
topUiManager.replaceRoot(nullptr);
|
||||
break;
|
||||
case TutorialStep::Step1:
|
||||
tutorialStep = TutorialStep::Step2;
|
||||
@@ -860,7 +1034,7 @@ namespace ZL {
|
||||
}
|
||||
uiManager.replaceRoot(root);
|
||||
applyCurrentHealthBar();
|
||||
setupGameplayHudCallbacks();
|
||||
setupGameplayHudCallbacks(); // already calls hideAllToastWidgets + applyToastsToUi
|
||||
}
|
||||
|
||||
void MenuManager::onPlayerStartedWalking()
|
||||
@@ -921,4 +1095,116 @@ namespace ZL {
|
||||
uiManager.setText("healthValue", hpText);
|
||||
}
|
||||
|
||||
// ---- Toast notification system ----
|
||||
|
||||
float MenuManager::ToastEntry::currentAlpha() const {
|
||||
switch (state) {
|
||||
case State::FadeIn: return min(timer / TOAST_FADE_MS, 1.0f);
|
||||
case State::Visible: return 1.0f;
|
||||
case State::FadeOut: return max(1.0f - timer / TOAST_FADE_MS, 0.0f);
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void MenuManager::showToast(const std::string& iconPath, const std::string& text) {
|
||||
if (activeToasts_.size() < 3) {
|
||||
ToastEntry e;
|
||||
e.iconPath = iconPath;
|
||||
e.text = text;
|
||||
activeToasts_.push_back(std::move(e));
|
||||
} else {
|
||||
toastQueue_.push_back({ iconPath, text });
|
||||
}
|
||||
applyToastsToUi();
|
||||
}
|
||||
|
||||
void MenuManager::updateToasts(float deltaMs) {
|
||||
if (activeToasts_.empty() && toastQueue_.empty()) return;
|
||||
|
||||
bool changed = false;
|
||||
|
||||
for (auto& e : activeToasts_) {
|
||||
e.timer += deltaMs;
|
||||
// Advance state machine
|
||||
if (e.state == ToastEntry::State::FadeIn && e.timer >= TOAST_FADE_MS) {
|
||||
e.state = ToastEntry::State::Visible;
|
||||
e.timer = 0.0f;
|
||||
changed = true;
|
||||
} else if (e.state == ToastEntry::State::Visible && e.timer >= TOAST_VISIBLE_MS) {
|
||||
e.state = ToastEntry::State::FadeOut;
|
||||
e.timer = 0.0f;
|
||||
changed = true;
|
||||
} else if (e.state == ToastEntry::State::FadeOut && e.timer >= TOAST_FADE_MS) {
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove finished entries (FadeOut complete)
|
||||
auto removed = std::remove_if(activeToasts_.begin(), activeToasts_.end(),
|
||||
[](const ToastEntry& e) {
|
||||
return e.state == ToastEntry::State::FadeOut && e.timer >= TOAST_FADE_MS;
|
||||
});
|
||||
if (removed != activeToasts_.end()) {
|
||||
activeToasts_.erase(removed, activeToasts_.end());
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// Pull queued messages into now-free slots (with FadeIn)
|
||||
while (!toastQueue_.empty() && activeToasts_.size() < 3) {
|
||||
ToastEntry e;
|
||||
e.iconPath = toastQueue_.front().iconPath;
|
||||
e.text = toastQueue_.front().text;
|
||||
toastQueue_.pop_front();
|
||||
activeToasts_.push_back(std::move(e));
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) applyToastsToUi();
|
||||
// Also refresh alpha smoothly every frame while any slot is fading
|
||||
else if (!activeToasts_.empty()) applyToastsToUi();
|
||||
}
|
||||
|
||||
void MenuManager::applyToastsToUi() {
|
||||
static const char* imgNames[3] = { "toast001", "toast002", "toast003" };
|
||||
static const char* txtNames[3] = { "toast001text", "toast002text", "toast003text" };
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (i < static_cast<int>(activeToasts_.size())) {
|
||||
const ToastEntry& e = activeToasts_[i];
|
||||
const float a = e.currentAlpha();
|
||||
|
||||
auto img = uiManager.findStaticImage(imgNames[i]);
|
||||
auto tv = uiManager.findTextView(txtNames[i]);
|
||||
|
||||
if (img) {
|
||||
img->texture = renderer.textureManager.LoadFromPng(e.iconPath, CONST_ZIP_FILE, true);
|
||||
img->alpha = a;
|
||||
}
|
||||
if (tv) {
|
||||
tv->color[3] = a;
|
||||
}
|
||||
uiManager.setText(txtNames[i], e.text);
|
||||
uiManager.setNodeVisible(imgNames[i], true);
|
||||
uiManager.setNodeVisible(txtNames[i], true);
|
||||
} else {
|
||||
uiManager.setNodeVisible(imgNames[i], false);
|
||||
uiManager.setNodeVisible(txtNames[i], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuManager::hideAllToastWidgets() {
|
||||
static const char* names[6] = {
|
||||
"toast001", "toast001text",
|
||||
"toast002", "toast002text",
|
||||
"toast003", "toast003text"
|
||||
};
|
||||
for (const char* name : names)
|
||||
uiManager.setNodeVisible(name, false);
|
||||
}
|
||||
|
||||
void MenuManager::update(float deltaMs) {
|
||||
updateToasts(deltaMs);
|
||||
}
|
||||
|
||||
} // namespace ZL
|
||||
Reference in new issue
Block a user