Working on messenger
This commit is contained in:
parent
9221ab68ac
commit
1fc8120ee0
@ -47,7 +47,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Бекзат, сынок, мы c мамой тебе отправили немного денег, постарайся прожить на эти деньги до конца недели!",
|
||||
"next": "line_2",
|
||||
"bubbleSlot": "message01in"
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_2",
|
||||
@ -56,7 +56,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Спасибо!",
|
||||
"next": "end_1",
|
||||
"bubbleSlot": "message02out"
|
||||
"chatBubble": "out"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
@ -75,7 +75,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Жители Бишкека все чаще жалуются на депрессию и апатию. Смотрите свежее видео об этом на нашем канале!",
|
||||
"next": "end_1",
|
||||
"bubbleSlot": "message01in"
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "end_1",
|
||||
@ -94,7 +94,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Бекзат, помнишь мы скидывались на торт для Аиды Джаныбековой? Я тогда еще приносила скатерть, тарелки и нож для торта. И я до сих пор не получила назад ничего.",
|
||||
"next": "line_2",
|
||||
"bubbleSlot": "message01in"
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_2",
|
||||
@ -103,7 +103,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Скатерть и тарелки вроде бы лежат в студзоне.",
|
||||
"next": "line_3",
|
||||
"bubbleSlot": "message02out"
|
||||
"chatBubble": "out"
|
||||
},
|
||||
{
|
||||
"id": "line_3",
|
||||
@ -112,7 +112,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "А нож?",
|
||||
"next": "line_4",
|
||||
"bubbleSlot": "message03in"
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_4",
|
||||
@ -121,7 +121,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Нож, наверное, так и остался в учительской.",
|
||||
"next": "line_5",
|
||||
"bubbleSlot": "message04out"
|
||||
"chatBubble": "out"
|
||||
},
|
||||
{
|
||||
"id": "line_5",
|
||||
@ -130,7 +130,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "А давай не \"наверное\"?",
|
||||
"next": "line_6",
|
||||
"bubbleSlot": "message05in"
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_6",
|
||||
@ -139,7 +139,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "А давай ты приедешь в универ, зайдешь в учительскую, заберешь нож и отдашь мне?",
|
||||
"next": "line_7",
|
||||
"bubbleSlot": "message06in"
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_7",
|
||||
@ -148,7 +148,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "У вас сегодня как раз Аида ведет лекцию. После лекции попросишь у нее ключи от учительской и заберешь нож.",
|
||||
"next": "line_8",
|
||||
"bubbleSlot": "message07in"
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_8",
|
||||
@ -157,7 +157,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Почему ты сама не можешь забрать?",
|
||||
"next": "line_9",
|
||||
"bubbleSlot": "message08out"
|
||||
"chatBubble": "out"
|
||||
},
|
||||
{
|
||||
"id": "line_9",
|
||||
@ -166,7 +166,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Ты же знаешь, если я встречу Аиду, она 100% даст мне какое-нибудь сложное задание.",
|
||||
"next": "line_10",
|
||||
"bubbleSlot": "message09in"
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_10",
|
||||
@ -175,7 +175,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "И потом, это ты у меня брал нож, с чего я должна ходить искать его по всему универу?",
|
||||
"next": "line_11",
|
||||
"bubbleSlot": "message10in"
|
||||
"chatBubble": "in"
|
||||
},
|
||||
{
|
||||
"id": "line_11",
|
||||
@ -184,7 +184,7 @@
|
||||
"portrait": "resources/dialogue/portrait_phone.png",
|
||||
"text": "Так что жду тебя в универе! Не вздумай прогулять!",
|
||||
"next": "end_1",
|
||||
"bubbleSlot": "message11in",
|
||||
"chatBubble": "in",
|
||||
"questUnlock" : "aiperi_knife"
|
||||
},
|
||||
{
|
||||
|
||||
BIN
resources/w/ui/img/phone/bubble_in_center.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/phone/bubble_in_center.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/phone/bubble_in_corner_left_bottom.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/phone/bubble_in_corner_left_bottom.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/phone/bubble_in_corner_left_top.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/phone/bubble_in_corner_left_top.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/phone/bubble_in_corner_right_bottom.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/phone/bubble_in_corner_right_bottom.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/phone/bubble_in_corner_right_top.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/phone/bubble_in_corner_right_top.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/phone/bubble_out_center.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/phone/bubble_out_center.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/phone/bubble_out_corner_left_bottom.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/phone/bubble_out_corner_left_bottom.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/phone/bubble_out_corner_left_top.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/phone/bubble_out_corner_left_top.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/phone/bubble_out_corner_right_bottom.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/phone/bubble_out_corner_right_bottom.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
resources/w/ui/img/phone/bubble_out_corner_right_top.png
(Stored with Git LFS)
Normal file
BIN
resources/w/ui/img/phone/bubble_out_corner_right_top.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -35,152 +35,26 @@
|
||||
"pressed": "resources/w/ui/img/phone/PhoneChat001.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message01in",
|
||||
"width": 320.6,
|
||||
"height": 148.4,
|
||||
"x" : 430,
|
||||
"y" : 1097,
|
||||
"horizontal_gravity": "left",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat02_01in.png"
|
||||
{
|
||||
"type": "FrameLayout",
|
||||
"name": "chatMessagesContainer",
|
||||
"width": "match_parent",
|
||||
"height": "match_parent"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message02out",
|
||||
"width": 320.6,
|
||||
"height": 64.4,
|
||||
"x" : 430,
|
||||
"y" : 1022.6,
|
||||
"horizontal_gravity": "right",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat02_02out.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message03in",
|
||||
"width": 103.6,
|
||||
"height": 43.4,
|
||||
"x" : 430,
|
||||
"y" : 969.2,
|
||||
"horizontal_gravity": "left",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat02_03in.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message04out",
|
||||
"width": 320.6,
|
||||
"height": 64.4,
|
||||
"x" : 430,
|
||||
"y" : 894.8,
|
||||
"horizontal_gravity": "right",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat02_04out.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message05in",
|
||||
"width": 243.6,
|
||||
"height": 43.4,
|
||||
"x" : 430,
|
||||
"y" : 841.4,
|
||||
"horizontal_gravity": "left",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat02_05in.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message06in",
|
||||
"width": 320.6,
|
||||
"height": 85.4,
|
||||
"x" : 430,
|
||||
"y" : 746,
|
||||
"horizontal_gravity": "left",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat02_06in.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message07in",
|
||||
"width": 320.6,
|
||||
"height": 106.4,
|
||||
"x" : 430,
|
||||
"y" : 629.6,
|
||||
"horizontal_gravity": "left",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat02_07in.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message08out",
|
||||
"width": 320.6,
|
||||
"height": 64.4,
|
||||
"x" : 430,
|
||||
"y" : 555.2,
|
||||
"horizontal_gravity": "right",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat02_08out.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message09in",
|
||||
"width": 320.6,
|
||||
"height": 85.4,
|
||||
"x" : 430,
|
||||
"y" : 459.8,
|
||||
"horizontal_gravity": "left",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat02_09in.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message10in",
|
||||
"width": 320.6,
|
||||
"height": 85.4,
|
||||
"x" : 430,
|
||||
"y" : 364.4,
|
||||
"horizontal_gravity": "left",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat02_10in.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message11in",
|
||||
"width": 320.6,
|
||||
"height": 64.4,
|
||||
"x" : 430,
|
||||
"y" : 290,
|
||||
"horizontal_gravity": "left",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat02_11in.png"
|
||||
},
|
||||
{
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "chatTopCover",
|
||||
"width": 446.25,
|
||||
"height": 70.82,
|
||||
"x" : 0,
|
||||
"y" : -50.82,
|
||||
"horizontal_gravity": "center",
|
||||
"x": 0,
|
||||
"y": -50.82,
|
||||
"horizontal_gravity": "center",
|
||||
"texture": "resources/w/ui/img/phone/chat_top_cover001.png"
|
||||
},
|
||||
{
|
||||
"type": "TextButton",
|
||||
"name": "chatTitleButton",
|
||||
"horizontal_gravity": "center",
|
||||
"horizontal_gravity": "center",
|
||||
"x": 0.0,
|
||||
"y": 20.0,
|
||||
"width": 446.25,
|
||||
@ -193,12 +67,7 @@
|
||||
"textCentered": false,
|
||||
"topAligned": true,
|
||||
"wrap": true,
|
||||
"color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"color": [1.0, 1.0, 1.0, 1.0],
|
||||
"textures": {
|
||||
"normal": "resources/w/ui/img/phone/CharHeader001.png",
|
||||
"hover": "resources/w/ui/img/phone/CharHeader001.png",
|
||||
@ -207,4 +76,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,20 +35,26 @@
|
||||
"pressed": "resources/w/ui/img/phone/PhoneChat001.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
{
|
||||
"type": "FrameLayout",
|
||||
"name": "chatMessagesContainer",
|
||||
"width": "match_parent",
|
||||
"height": "match_parent"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "chatTopCover",
|
||||
"width": 446.25,
|
||||
"height": 70.82,
|
||||
"x" : 0,
|
||||
"y" : -50.82,
|
||||
"horizontal_gravity": "center",
|
||||
"x": 0,
|
||||
"y": -50.82,
|
||||
"horizontal_gravity": "center",
|
||||
"texture": "resources/w/ui/img/phone/chat_top_cover001.png"
|
||||
},
|
||||
{
|
||||
"type": "TextButton",
|
||||
"name": "chatTitleButton",
|
||||
"horizontal_gravity": "center",
|
||||
"horizontal_gravity": "center",
|
||||
"x": 0.0,
|
||||
"y": 20.0,
|
||||
"width": 446.25,
|
||||
@ -61,42 +67,13 @@
|
||||
"textCentered": false,
|
||||
"topAligned": true,
|
||||
"wrap": true,
|
||||
"color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"color": [1.0, 1.0, 1.0, 1.0],
|
||||
"textures": {
|
||||
"normal": "resources/w/ui/img/phone/CharHeader002.png",
|
||||
"hover": "resources/w/ui/img/phone/CharHeader002.png",
|
||||
"pressed": "resources/w/ui/img/phone/CharHeader002.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message01in",
|
||||
"width": 320.6,
|
||||
"height": 103.6,
|
||||
"x" : 430,
|
||||
"y" : 506.4,
|
||||
"horizontal_gravity": "left",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat01_01in.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message02out",
|
||||
"width": 116.2,
|
||||
"height": 43.4,
|
||||
"x" : 430,
|
||||
"y" : 453,
|
||||
"horizontal_gravity": "right",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat01_02out.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,10 +35,26 @@
|
||||
"pressed": "resources/w/ui/img/phone/PhoneChat001.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "FrameLayout",
|
||||
"name": "chatMessagesContainer",
|
||||
"width": "match_parent",
|
||||
"height": "match_parent"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "chatTopCover",
|
||||
"width": 446.25,
|
||||
"height": 70.82,
|
||||
"x": 0,
|
||||
"y": -50.82,
|
||||
"horizontal_gravity": "center",
|
||||
"texture": "resources/w/ui/img/phone/chat_top_cover001.png"
|
||||
},
|
||||
{
|
||||
"type": "TextButton",
|
||||
"name": "chatTitleButton",
|
||||
"horizontal_gravity": "center",
|
||||
"horizontal_gravity": "center",
|
||||
"x": 0.0,
|
||||
"y": 20.0,
|
||||
"width": 446.25,
|
||||
@ -51,40 +67,13 @@
|
||||
"textCentered": false,
|
||||
"topAligned": true,
|
||||
"wrap": true,
|
||||
"color": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"color": [1.0, 1.0, 1.0, 1.0],
|
||||
"textures": {
|
||||
"normal": "resources/w/ui/img/phone/CharHeader003.png",
|
||||
"hover": "resources/w/ui/img/phone/CharHeader003.png",
|
||||
"pressed": "resources/w/ui/img/phone/CharHeader003.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "chatTopCover",
|
||||
"width": 446.25,
|
||||
"height": 70.82,
|
||||
"x" : 0,
|
||||
"y" : -50.82,
|
||||
"horizontal_gravity": "center",
|
||||
"texture": "resources/w/ui/img/phone/chat_top_cover001.png"
|
||||
},
|
||||
{
|
||||
"type": "StaticImage",
|
||||
"name": "message01in",
|
||||
"width": 320.6,
|
||||
"height": 103.6,
|
||||
"x" : 430,
|
||||
"y" : 506.4,
|
||||
"horizontal_gravity": "left",
|
||||
"vertical_gravity": "bottom",
|
||||
"visible": false,
|
||||
"texture": "resources/w/ui/img/phone/chat03_01in.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,10 +423,10 @@ namespace ZL
|
||||
startNightTransition();
|
||||
};
|
||||
|
||||
// Wire bubble-slot callback so chat bubbles appear as dialogue lines are shown.
|
||||
// Wire chat-bubble callback so dynamic bubbles appear as dialogue lines are shown.
|
||||
for (auto& [name, loc] : locations) {
|
||||
loc->dialogueSystem.setOnBubbleSlotReady([this](const std::string& bubbleSlot) {
|
||||
menuManager.revealPhoneChatBubble(bubbleSlot);
|
||||
loc->dialogueSystem.setOnChatBubbleReady([this](const std::string& text, bool incoming) {
|
||||
menuManager.onChatBubbleReady(text, incoming);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -122,6 +122,18 @@ namespace ZL {
|
||||
|
||||
questJournal.loadFromFile("resources/quests/quests.json", zipFile);
|
||||
|
||||
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);
|
||||
texBubbleInLB_ = renderer.textureManager.LoadFromPng(imgDir + "bubble_in_corner_left_bottom.png", zipFile, true);
|
||||
texBubbleInRT_ = renderer.textureManager.LoadFromPng(imgDir + "bubble_in_corner_right_top.png", zipFile, true);
|
||||
texBubbleInRB_ = renderer.textureManager.LoadFromPng(imgDir + "bubble_in_corner_right_bottom.png",zipFile, true);
|
||||
texBubbleOutCenter_ = renderer.textureManager.LoadFromPng(imgDir + "bubble_out_center.png", zipFile, true);
|
||||
texBubbleOutLT_ = renderer.textureManager.LoadFromPng(imgDir + "bubble_out_corner_left_top.png", zipFile, true);
|
||||
texBubbleOutLB_ = renderer.textureManager.LoadFromPng(imgDir + "bubble_out_corner_left_bottom.png",zipFile, true);
|
||||
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();
|
||||
}
|
||||
|
||||
@ -335,15 +347,15 @@ namespace ZL {
|
||||
uiManager.setButtonCallback("phoneMain", [this](const std::string&) {});
|
||||
uiManager.setTextButtonCallback("chat1button", [this](const std::string&) {
|
||||
chatUnread_[0] = false;
|
||||
openPhoneChatFromList(phoneChat1Root, "dialog_chat_aiperi001");
|
||||
openPhoneChatFromList(0, phoneChat1Root, "dialog_chat_aiperi001");
|
||||
});
|
||||
uiManager.setTextButtonCallback("chat2button", [this](const std::string&) {
|
||||
chatUnread_[1] = false;
|
||||
openPhoneChatFromList(phoneChat2Root, "dialog_chat_parents001");
|
||||
openPhoneChatFromList(1, phoneChat2Root, "dialog_chat_parents001");
|
||||
});
|
||||
uiManager.setTextButtonCallback("chat3button", [this](const std::string&) {
|
||||
chatUnread_[2] = false;
|
||||
openPhoneChatFromList(phoneChat3Root, "dialog_chat_news001");
|
||||
openPhoneChatFromList(2, phoneChat3Root, "dialog_chat_news001");
|
||||
});
|
||||
}
|
||||
|
||||
@ -424,14 +436,14 @@ namespace ZL {
|
||||
});
|
||||
}
|
||||
|
||||
void MenuManager::openPhoneChatFromList(std::shared_ptr<UiNode> chatRoot, const std::string& dialogueId) {
|
||||
void MenuManager::openPhoneChatFromList(int chatIndex, std::shared_ptr<UiNode> chatRoot, const std::string& dialogueId) {
|
||||
activeChatIndex_ = chatIndex;
|
||||
phoneChatVisibleBubbles_.clear();
|
||||
uiManager.pushMenuFromSavedRoot(chatRoot);
|
||||
|
||||
const bool firstOpen = dialogueId.empty() || startedDialogues_.find(dialogueId) == startedDialogues_.end();
|
||||
if (firstOpen) {
|
||||
resetPhoneChatNodes();
|
||||
}
|
||||
|
||||
rebuildChatBubblesFromHistory(chatIndex);
|
||||
|
||||
uiManager.setButtonCallback("phoneExitButton", [this](const std::string&) {
|
||||
closePhoneScreenFromChat();
|
||||
@ -448,12 +460,14 @@ namespace ZL {
|
||||
}
|
||||
|
||||
void MenuManager::returnToPhoneChatList() {
|
||||
activeChatIndex_ = -1;
|
||||
phoneChatVisibleBubbles_.clear();
|
||||
uiManager.popMenu();
|
||||
refreshChatUnreadIndicators();
|
||||
}
|
||||
|
||||
void MenuManager::closePhoneEntirely() {
|
||||
activeChatIndex_ = -1;
|
||||
state = GameState::Gameplay;
|
||||
phoneChatVisibleBubbles_.clear();
|
||||
const int depth = uiManager.menuStackSize();
|
||||
@ -754,19 +768,59 @@ namespace ZL {
|
||||
uiManager.updateAllLayouts();
|
||||
}
|
||||
|
||||
void MenuManager::revealPhoneChatBubble(const std::string& slotName) {
|
||||
if (state != GameState::PhoneScreen) return;
|
||||
auto node = uiManager.findNode(slotName);
|
||||
if (!node) return;
|
||||
void MenuManager::rebuildChatBubblesFromHistory(int chatIndex) {
|
||||
uiManager.clearChatBubbles("chatMessagesContainer");
|
||||
phoneChatVisibleBubbles_.clear();
|
||||
|
||||
// Zero scale before making visible to avoid a one-frame flash at full size
|
||||
node->scaleX = 0.0f;
|
||||
node->scaleY = 0.0f;
|
||||
|
||||
phoneChatVisibleBubbles_.push_back({slotName, node->height});
|
||||
uiManager.setNodeVisible(slotName, true);
|
||||
if (chatIndex < 0 || chatIndex > 2) return;
|
||||
for (const auto& msg : chatHistory_[chatIndex]) {
|
||||
const bool inc = msg.incoming;
|
||||
const std::string nodeName = uiManager.addChatBubble(
|
||||
"chatMessagesContainer", msg.text, inc,
|
||||
inc ? texBubbleInCenter_ : texBubbleOutCenter_,
|
||||
inc ? texBubbleInLT_ : texBubbleOutLT_,
|
||||
inc ? texBubbleInLB_ : texBubbleOutLB_,
|
||||
inc ? texBubbleInRT_ : texBubbleOutRT_,
|
||||
inc ? texBubbleInRB_ : texBubbleOutRB_,
|
||||
renderer, "resources/fonts/DroidSans.ttf", 20, zipFile_);
|
||||
if (!nodeName.empty()) {
|
||||
auto n = uiManager.findNode(nodeName);
|
||||
phoneChatVisibleBubbles_.push_back({ nodeName, n ? n->height : 60.0f });
|
||||
}
|
||||
}
|
||||
recomputePhoneChatPositions();
|
||||
uiManager.startPopIn(slotName, 300.0f);
|
||||
}
|
||||
|
||||
void MenuManager::onChatBubbleReady(const std::string& text, bool incoming) {
|
||||
if (activeChatIndex_ < 0) return;
|
||||
|
||||
auto& history = chatHistory_[activeChatIndex_];
|
||||
if (static_cast<int>(history.size()) >= 5) {
|
||||
history.erase(history.begin());
|
||||
}
|
||||
history.push_back({ text, incoming });
|
||||
|
||||
if (state != GameState::PhoneScreen) return;
|
||||
|
||||
const std::string nodeName = uiManager.addChatBubble(
|
||||
"chatMessagesContainer", text, incoming,
|
||||
incoming ? texBubbleInCenter_ : texBubbleOutCenter_,
|
||||
incoming ? texBubbleInLT_ : texBubbleOutLT_,
|
||||
incoming ? texBubbleInLB_ : texBubbleOutLB_,
|
||||
incoming ? texBubbleInRT_ : texBubbleOutRT_,
|
||||
incoming ? texBubbleInRB_ : texBubbleOutRB_,
|
||||
renderer, "resources/fonts/DroidSans.ttf", 20, zipFile_);
|
||||
|
||||
if (nodeName.empty()) return;
|
||||
|
||||
auto node = uiManager.findNode(nodeName);
|
||||
if (node) {
|
||||
node->scaleX = 0.0f;
|
||||
node->scaleY = 0.0f;
|
||||
phoneChatVisibleBubbles_.push_back({ nodeName, node->height });
|
||||
}
|
||||
recomputePhoneChatPositions();
|
||||
uiManager.startPopIn(nodeName, 300.0f);
|
||||
}
|
||||
|
||||
void MenuManager::setDarklandsMode(bool enabled)
|
||||
|
||||
@ -58,7 +58,6 @@ namespace ZL {
|
||||
|
||||
void openPhoneScreen();
|
||||
void closePhoneScreen();
|
||||
void revealPhoneChatBubble(const std::string& slotName);
|
||||
bool isPhoneScreenOpen() const { return state == GameState::PhoneScreen; }
|
||||
void closePhoneEntirely();
|
||||
|
||||
@ -71,6 +70,9 @@ namespace ZL {
|
||||
std::function<void()> startDarklandsTransitionFunc;
|
||||
std::function<void()> startNightTransitionFunc;
|
||||
|
||||
// Called when a chat message bubble should be shown (text + direction)
|
||||
void onChatBubbleReady(const std::string& text, bool incoming);
|
||||
|
||||
void setDarklandsMode(bool enabled);
|
||||
void advanceTutorialStep();
|
||||
void onItemPickedUp(const std::string& itemId);
|
||||
@ -102,10 +104,11 @@ namespace ZL {
|
||||
void refreshChatUnreadIndicators();
|
||||
void resetPhoneChatNodes();
|
||||
void recomputePhoneChatPositions();
|
||||
void openPhoneChatFromList(std::shared_ptr<UiNode> chatRoot, const std::string& dialogueId);
|
||||
void openPhoneChatFromList(int chatIndex, std::shared_ptr<UiNode> chatRoot, const std::string& dialogueId);
|
||||
void returnToPhoneChatList();
|
||||
void closePhoneScreenFromChat();
|
||||
void applyUniIntHud();
|
||||
void rebuildChatBubblesFromHistory(int chatIndex);
|
||||
|
||||
GameState state = GameState::Gameplay;
|
||||
Inventory* inventory = nullptr;
|
||||
@ -176,6 +179,15 @@ namespace ZL {
|
||||
};
|
||||
std::vector<PhoneChatBubbleInfo> phoneChatVisibleBubbles_;
|
||||
|
||||
// Per-chat message history (max 5 messages each)
|
||||
struct StoredChatMessage { std::string text; bool incoming; };
|
||||
std::vector<StoredChatMessage> chatHistory_[3];
|
||||
int activeChatIndex_ = -1;
|
||||
|
||||
// Preloaded bubble textures
|
||||
std::shared_ptr<Texture> texBubbleInCenter_, texBubbleInLT_, texBubbleInLB_, texBubbleInRT_, texBubbleInRB_;
|
||||
std::shared_ptr<Texture> texBubbleOutCenter_, texBubbleOutLT_, texBubbleOutLB_, texBubbleOutRT_, texBubbleOutRB_;
|
||||
|
||||
static constexpr float CHAT_TOP_Y = 610.0f;
|
||||
static constexpr float CHAT_BOTTOM_Y = 290.0f;
|
||||
static constexpr float CHAT_SPACING = 10.0f;
|
||||
|
||||
@ -824,6 +824,107 @@ namespace ZL {
|
||||
return root;
|
||||
}
|
||||
|
||||
// ---- UiChatBubble helpers ----
|
||||
|
||||
static void buildQuadMesh(VertexRenderStruct& mesh, float x0, float y0, float x1, float y1) {
|
||||
mesh.data.PositionData.clear();
|
||||
mesh.data.TexCoordData.clear();
|
||||
mesh.data.PositionData.push_back({ x0, y0, 0 });
|
||||
mesh.data.TexCoordData.push_back({ 0, 0 });
|
||||
mesh.data.PositionData.push_back({ x0, y1, 0 });
|
||||
mesh.data.TexCoordData.push_back({ 0, 1 });
|
||||
mesh.data.PositionData.push_back({ x1, y1, 0 });
|
||||
mesh.data.TexCoordData.push_back({ 1, 1 });
|
||||
mesh.data.PositionData.push_back({ x0, y0, 0 });
|
||||
mesh.data.TexCoordData.push_back({ 0, 0 });
|
||||
mesh.data.PositionData.push_back({ x1, y1, 0 });
|
||||
mesh.data.TexCoordData.push_back({ 1, 1 });
|
||||
mesh.data.PositionData.push_back({ x1, y0, 0 });
|
||||
mesh.data.TexCoordData.push_back({ 1, 0 });
|
||||
mesh.RefreshVBO();
|
||||
}
|
||||
|
||||
float UiChatBubble::computeHeight() const {
|
||||
if (!textRenderer) return CORNER_SIZE * 2 + PAD_Y * 2 + static_cast<float>(fontSize);
|
||||
const float textW = MAX_WIDTH - CORNER_SIZE * 2.0f - PAD_X * 2.0f;
|
||||
const std::string wrapped = wrapTextByPixels(text, *textRenderer, textW, 1.0f);
|
||||
int lines = 1;
|
||||
for (char c : wrapped) if (c == '\n') ++lines;
|
||||
return CORNER_SIZE * 2.0f + PAD_Y * 2.0f + lines * static_cast<float>(fontSize) * 1.25f;
|
||||
}
|
||||
|
||||
void UiChatBubble::buildMeshes() {
|
||||
const float x = rect.x;
|
||||
const float y = rect.y;
|
||||
const float w = rect.w;
|
||||
const float h = rect.h;
|
||||
const float cs = CORNER_SIZE;
|
||||
|
||||
const float OFFSET = 0.5f;
|
||||
|
||||
// 1. Middle center (full width, between top and bottom corner rows)
|
||||
buildQuadMesh(meshMiddle, x, y + cs- OFFSET, x + w, y + h - cs +OFFSET);
|
||||
// 2. Top strip (between corners)
|
||||
buildQuadMesh(meshTopStrip, x + cs- OFFSET, y + h - cs, x + w - cs+ OFFSET, y + h);
|
||||
// 3. Bottom strip
|
||||
buildQuadMesh(meshBotStrip, x + cs- OFFSET, y, x + w - cs+ OFFSET, y + cs);
|
||||
// Corners
|
||||
buildQuadMesh(meshCornerLT, x, y + h - cs-OFFSET, x + cs, y + h);
|
||||
buildQuadMesh(meshCornerRT, x + w - cs, y + h - cs - OFFSET, x + w, y + h);
|
||||
buildQuadMesh(meshCornerLB, x, y, x + cs, y + cs);
|
||||
buildQuadMesh(meshCornerRB, x + w - cs, y, x + w, y + cs);
|
||||
}
|
||||
|
||||
void UiChatBubble::draw(Renderer& renderer, float nodeScaleX, float nodeScaleY) const {
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
|
||||
|
||||
// Corners with blending (semi-transparent rounded corners)
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
auto drawCorner = [&](const std::shared_ptr<Texture>& tex, const VertexRenderStruct& mesh) {
|
||||
if (tex) {
|
||||
glBindTexture(GL_TEXTURE_2D, tex->getTexID());
|
||||
renderer.DrawVertexRenderStruct(mesh);
|
||||
}
|
||||
};
|
||||
drawCorner(texCornerLT, meshCornerLT);
|
||||
drawCorner(texCornerRT, meshCornerRT);
|
||||
drawCorner(texCornerLB, meshCornerLB);
|
||||
drawCorner(texCornerRB, meshCornerRB);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
// Center parts (no blending needed — opaque fill)
|
||||
if (texCenter) {
|
||||
glBindTexture(GL_TEXTURE_2D, texCenter->getTexID());
|
||||
renderer.DrawVertexRenderStruct(meshMiddle);
|
||||
renderer.DrawVertexRenderStruct(meshTopStrip);
|
||||
renderer.DrawVertexRenderStruct(meshBotStrip);
|
||||
}
|
||||
|
||||
// Text — position is transformed around the bubble centre to match the renderer's
|
||||
// scale matrix (which scales meshes around the same centre point).
|
||||
if (textRenderer && !text.empty()) {
|
||||
const float textW = rect.w - CORNER_SIZE * 2.0f - PAD_X * 2.0f;
|
||||
const std::string wrapped = wrapTextByPixels(text, *textRenderer, textW, 1.0f);
|
||||
|
||||
const float tx0 = rect.x + CORNER_SIZE + PAD_X;
|
||||
const float ty0 = rect.y + rect.h - CORNER_SIZE - PAD_Y - static_cast<float>(fontSize);
|
||||
|
||||
// Scale around bubble centre, matching how the renderer's ScaleMatrix works
|
||||
const float cx = rect.x + rect.w * 0.5f;
|
||||
const float cy = rect.y + rect.h * 0.5f;
|
||||
const float tx = cx + (tx0 - cx) * nodeScaleX;
|
||||
const float ty = cy + (ty0 - cy) * nodeScaleY;
|
||||
|
||||
textRenderer->drawText(wrapped, tx, ty, nodeScaleX, false, { 1.f, 1.f, 1.f, 1.f });
|
||||
}
|
||||
}
|
||||
|
||||
// ---- end UiChatBubble helpers ----
|
||||
|
||||
void UiManager::replaceRoot(std::shared_ptr<UiNode> newRoot) {
|
||||
root = newRoot;
|
||||
layoutNode(
|
||||
@ -841,6 +942,7 @@ namespace ZL {
|
||||
textViews.clear();
|
||||
textFields.clear();
|
||||
staticImages.clear();
|
||||
chatBubbles.clear();
|
||||
pulsingNodes.clear();
|
||||
popInNodes.clear();
|
||||
collectButtonsAndSliders(root);
|
||||
@ -1052,6 +1154,12 @@ namespace ZL {
|
||||
node->staticImage->rect = node->screenRect;
|
||||
node->staticImage->buildMesh();
|
||||
}
|
||||
|
||||
// 6. Chat bubble
|
||||
if (node->chatBubble) {
|
||||
node->chatBubble->rect = node->screenRect;
|
||||
node->chatBubble->buildMeshes();
|
||||
}
|
||||
}
|
||||
|
||||
void UiManager::updateAllLayouts() {
|
||||
@ -1106,6 +1214,9 @@ namespace ZL {
|
||||
if (node->pulseEnabled && node->staticImage) {
|
||||
pulsingNodes.push_back(node);
|
||||
}
|
||||
if (node->chatBubble) {
|
||||
chatBubbles.push_back(node->chatBubble);
|
||||
}
|
||||
for (auto& c : node->children) collectButtonsAndSliders(c);
|
||||
}
|
||||
|
||||
@ -1215,6 +1326,7 @@ namespace ZL {
|
||||
prev.textViews = textViews;
|
||||
prev.textFields = textFields;
|
||||
prev.staticImages = staticImages;
|
||||
prev.chatBubbles = chatBubbles;
|
||||
prev.pulsingNodes = pulsingNodes;
|
||||
prev.pressedButtons = pressedButtons;
|
||||
prev.pressedTextButtons = pressedTextButtons;
|
||||
@ -1280,6 +1392,7 @@ namespace ZL {
|
||||
textViews = s.textViews;
|
||||
textFields = s.textFields;
|
||||
staticImages = s.staticImages;
|
||||
chatBubbles = s.chatBubbles;
|
||||
pulsingNodes = s.pulsingNodes;
|
||||
popInNodes = s.popInNodes;
|
||||
pressedButtons = s.pressedButtons;
|
||||
@ -1347,7 +1460,12 @@ namespace ZL {
|
||||
if (node->staticImage) {
|
||||
node->staticImage->draw(renderer);
|
||||
}
|
||||
|
||||
|
||||
// 1b. Chat bubble (composite widget)
|
||||
if (node->chatBubble) {
|
||||
node->chatBubble->draw(renderer, node->scaleX, node->scaleY);
|
||||
}
|
||||
|
||||
// 2. Потом кнопки
|
||||
if (node->button) {
|
||||
node->button->draw(renderer);
|
||||
@ -1994,4 +2112,86 @@ namespace ZL {
|
||||
if (!node) return false;
|
||||
return node->visible;
|
||||
}
|
||||
|
||||
std::string UiManager::addChatBubble(
|
||||
const std::string& parentNodeName,
|
||||
const std::string& text, bool incoming,
|
||||
std::shared_ptr<Texture> texCenter,
|
||||
std::shared_ptr<Texture> texLT, std::shared_ptr<Texture> texLB,
|
||||
std::shared_ptr<Texture> texRT, std::shared_ptr<Texture> texRB,
|
||||
Renderer& renderer, const std::string& fontPath, int fontSize,
|
||||
const std::string& zipFile)
|
||||
{
|
||||
if (!root) return "";
|
||||
auto parent = findNodeByName(root, parentNodeName);
|
||||
if (!parent) {
|
||||
std::cerr << "UiManager::addChatBubble: parent '" << parentNodeName << "' not found\n";
|
||||
return "";
|
||||
}
|
||||
|
||||
static int bubbleCounter = 0;
|
||||
const std::string nodeName = "chat_bubble_" + std::to_string(bubbleCounter++);
|
||||
|
||||
// Build the chat bubble component
|
||||
auto bubble = std::make_shared<UiChatBubble>();
|
||||
bubble->name = nodeName;
|
||||
bubble->text = text;
|
||||
bubble->incoming = incoming;
|
||||
bubble->fontSize = fontSize;
|
||||
bubble->texCenter = texCenter;
|
||||
bubble->texCornerLT = texLT;
|
||||
bubble->texCornerLB = texLB;
|
||||
bubble->texCornerRT = texRT;
|
||||
bubble->texCornerRB = texRB;
|
||||
|
||||
bubble->textRenderer = std::make_unique<TextRenderer>();
|
||||
if (!bubble->textRenderer->init(renderer, fontPath, fontSize, zipFile)) {
|
||||
std::cerr << "UiManager::addChatBubble: TextRenderer init failed\n";
|
||||
}
|
||||
|
||||
// Build the UiNode
|
||||
auto node = std::make_shared<UiNode>();
|
||||
node->name = nodeName;
|
||||
node->width = UiChatBubble::MAX_WIDTH;
|
||||
node->height = bubble->computeHeight();
|
||||
node->localX = 430.0f;
|
||||
node->localY = 0.0f;
|
||||
node->visible = true;
|
||||
node->chatBubble = bubble;
|
||||
|
||||
if (incoming) {
|
||||
node->layoutSettings.hGravity = HorizontalGravity::Left;
|
||||
} else {
|
||||
node->layoutSettings.hGravity = HorizontalGravity::Right;
|
||||
}
|
||||
// Bottom gravity means localY is used as-is for screenRect.y (no parentH transform).
|
||||
// The original static chat nodes all had "vertical_gravity": "bottom" for the same reason.
|
||||
node->layoutSettings.vGravity = VerticalGravity::Bottom;
|
||||
|
||||
parent->children.push_back(node);
|
||||
|
||||
// Re-layout and collect the new node
|
||||
updateAllLayouts();
|
||||
bubble->rect = node->screenRect;
|
||||
bubble->buildMeshes();
|
||||
chatBubbles.push_back(bubble);
|
||||
|
||||
return nodeName;
|
||||
}
|
||||
|
||||
void UiManager::clearChatBubbles(const std::string& parentNodeName) {
|
||||
if (!root) return;
|
||||
auto parent = findNodeByName(root, parentNodeName);
|
||||
if (!parent) return;
|
||||
|
||||
// Remove children that have a chatBubble component
|
||||
auto& ch = parent->children;
|
||||
ch.erase(std::remove_if(ch.begin(), ch.end(),
|
||||
[](const std::shared_ptr<UiNode>& n) { return n && n->chatBubble != nullptr; }),
|
||||
ch.end());
|
||||
|
||||
// Remove from chatBubbles collection
|
||||
chatBubbles.clear();
|
||||
}
|
||||
|
||||
} // namespace ZL
|
||||
@ -245,6 +245,45 @@ namespace ZL {
|
||||
void draw(Renderer& renderer) const;
|
||||
};
|
||||
|
||||
struct UiChatBubble {
|
||||
std::string name;
|
||||
UiRect rect;
|
||||
std::string text;
|
||||
bool incoming = true;
|
||||
|
||||
std::shared_ptr<Texture> texCenter;
|
||||
std::shared_ptr<Texture> texCornerLT;
|
||||
std::shared_ptr<Texture> texCornerLB;
|
||||
std::shared_ptr<Texture> texCornerRT;
|
||||
std::shared_ptr<Texture> texCornerRB;
|
||||
|
||||
static constexpr float CORNER_SIZE = 22.4f;
|
||||
static constexpr float MAX_WIDTH = 320.6f;
|
||||
//static constexpr float PAD_X = 7.0f;
|
||||
//static constexpr float PAD_Y = 5.0f;
|
||||
static constexpr float PAD_X = -15.0f;
|
||||
static constexpr float PAD_Y = -15.0f;
|
||||
|
||||
// 7 meshes: middle-center, top-strip, bottom-strip, LT, RT, LB, RB
|
||||
VertexRenderStruct meshMiddle;
|
||||
VertexRenderStruct meshTopStrip;
|
||||
VertexRenderStruct meshBotStrip;
|
||||
VertexRenderStruct meshCornerLT;
|
||||
VertexRenderStruct meshCornerRT;
|
||||
VertexRenderStruct meshCornerLB;
|
||||
VertexRenderStruct meshCornerRB;
|
||||
|
||||
std::unique_ptr<TextRenderer> textRenderer;
|
||||
int fontSize = 20;
|
||||
|
||||
// Must be called after rect is set and textRenderer is initialised
|
||||
float computeHeight() const;
|
||||
void buildMeshes();
|
||||
// nodeScaleX/Y: the owning UiNode's current scale (for pop-in / animations).
|
||||
// Text position and glyph size are transformed to match the renderer's scale matrix.
|
||||
void draw(Renderer& renderer, float nodeScaleX = 1.0f, float nodeScaleY = 1.0f) const;
|
||||
};
|
||||
|
||||
struct UiNode {
|
||||
std::string name;
|
||||
LayoutType layoutType = LayoutType::Frame;
|
||||
@ -290,6 +329,7 @@ namespace ZL {
|
||||
std::shared_ptr<UiTextView> textView;
|
||||
std::shared_ptr<UiTextField> textField;
|
||||
std::shared_ptr<UiStaticImage> staticImage;
|
||||
std::shared_ptr<UiChatBubble> chatBubble;
|
||||
|
||||
// Анимации
|
||||
struct AnimStep {
|
||||
@ -409,6 +449,19 @@ namespace ZL {
|
||||
void clearMenuStack();
|
||||
int menuStackSize() const;
|
||||
|
||||
// Dynamically create a chat bubble node and append it to a named parent node.
|
||||
// Returns the generated node name, or "" on failure.
|
||||
std::string addChatBubble(const std::string& parentNodeName,
|
||||
const std::string& text, bool incoming,
|
||||
std::shared_ptr<Texture> texCenter,
|
||||
std::shared_ptr<Texture> texLT, std::shared_ptr<Texture> texLB,
|
||||
std::shared_ptr<Texture> texRT, std::shared_ptr<Texture> texRB,
|
||||
Renderer& renderer, const std::string& fontPath, int fontSize,
|
||||
const std::string& zipFile);
|
||||
|
||||
// Remove all chat-bubble children from named parent and clear chatBubbles collection.
|
||||
void clearChatBubbles(const std::string& parentNodeName);
|
||||
|
||||
void update(float deltaMs);
|
||||
void startAnimation(const std::string& animName);
|
||||
bool startAnimationOnNode(const std::string& nodeName, const std::string& animName);
|
||||
@ -462,6 +515,7 @@ namespace ZL {
|
||||
std::vector<std::shared_ptr<UiTextView>> textViews;
|
||||
std::vector<std::shared_ptr<UiTextField>> textFields;
|
||||
std::vector<std::shared_ptr<UiStaticImage>> staticImages;
|
||||
std::vector<std::shared_ptr<UiChatBubble>> chatBubbles;
|
||||
std::vector<std::shared_ptr<UiNode>> pulsingNodes;
|
||||
std::vector<std::shared_ptr<UiNode>> popInNodes;
|
||||
|
||||
@ -483,6 +537,7 @@ namespace ZL {
|
||||
std::vector<std::shared_ptr<UiTextView>> textViews;
|
||||
std::vector<std::shared_ptr<UiTextField>> textFields;
|
||||
std::vector<std::shared_ptr<UiStaticImage>> staticImages;
|
||||
std::vector<std::shared_ptr<UiChatBubble>> chatBubbles;
|
||||
std::vector<std::shared_ptr<UiNode>> pulsingNodes;
|
||||
std::vector<std::shared_ptr<UiNode>> popInNodes;
|
||||
std::map<int64_t, std::shared_ptr<UiButton>> pressedButtons;
|
||||
|
||||
@ -105,7 +105,7 @@ Node DialogueDatabase::parseNode(const json& j) {
|
||||
node.falseNext = j.value("falseNext", "");
|
||||
node.cutsceneId = j.value("cutsceneId", "");
|
||||
node.luaCallback = j.value("luaCallback", "");
|
||||
node.bubbleSlot = j.value("bubbleSlot", "");
|
||||
node.chatBubble = j.value("chatBubble", "");
|
||||
node.questUnlock = j.value("questUnlock", "");
|
||||
node.questComplete = j.value("questComplete", "");
|
||||
node.questFail = j.value("questFail", "");
|
||||
|
||||
@ -87,8 +87,8 @@ void DialogueRuntime::setOnCutsceneFadeInComplete(std::function<void(const std::
|
||||
onCutsceneFadeInComplete = std::move(cb);
|
||||
}
|
||||
|
||||
void DialogueRuntime::setOnBubbleSlotReady(std::function<void(const std::string&)> cb) {
|
||||
onBubbleSlotReady = std::move(cb);
|
||||
void DialogueRuntime::setOnChatBubbleReady(std::function<void(const std::string&, bool)> cb) {
|
||||
onChatBubbleReady = std::move(cb);
|
||||
}
|
||||
|
||||
void DialogueRuntime::stop() {
|
||||
@ -466,8 +466,8 @@ void DialogueRuntime::presentLine(const Node& node) {
|
||||
if (!node.luaCallback.empty() && onDialogueLineStarted) {
|
||||
onDialogueLineStarted(node.luaCallback);
|
||||
}
|
||||
if (!node.bubbleSlot.empty() && onBubbleSlotReady) {
|
||||
onBubbleSlotReady(node.bubbleSlot);
|
||||
if (!node.chatBubble.empty() && onChatBubbleReady) {
|
||||
onChatBubbleReady(node.text, node.chatBubble == "in");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ public:
|
||||
void setOnDialogueLineStarted(std::function<void(const std::string&)> cb);
|
||||
void setOnCutsceneLineStarted(std::function<void(const std::string&)> cb);
|
||||
void setOnCutsceneFadeInComplete(std::function<void(const std::string&)> cb);
|
||||
void setOnBubbleSlotReady(std::function<void(const std::string&)> cb);
|
||||
void setOnChatBubbleReady(std::function<void(const std::string&, bool)> cb);
|
||||
void stop();
|
||||
|
||||
void update(int deltaMs);
|
||||
@ -60,7 +60,7 @@ private:
|
||||
std::function<void(const std::string&)> onDialogueLineStarted;
|
||||
std::function<void(const std::string&)> onCutsceneLineStarted;
|
||||
std::function<void(const std::string&)> onCutsceneFadeInComplete;
|
||||
std::function<void(const std::string&)> onBubbleSlotReady;
|
||||
std::function<void(const std::string&, bool)> onChatBubbleReady;
|
||||
std::string activeCutsceneId;
|
||||
bool fadeInCallbackFired = false;
|
||||
|
||||
|
||||
@ -140,8 +140,8 @@ void DialogueSystem::setOnCutsceneFadeInComplete(std::function<void(const std::s
|
||||
runtime.setOnCutsceneFadeInComplete(std::move(cb));
|
||||
}
|
||||
|
||||
void DialogueSystem::setOnBubbleSlotReady(std::function<void(const std::string&)> cb) {
|
||||
runtime.setOnBubbleSlotReady(std::move(cb));
|
||||
void DialogueSystem::setOnChatBubbleReady(std::function<void(const std::string&, bool)> cb) {
|
||||
runtime.setOnChatBubbleReady(std::move(cb));
|
||||
}
|
||||
|
||||
void DialogueSystem::stopDialogue() {
|
||||
|
||||
@ -28,7 +28,7 @@ public:
|
||||
void setOnDialogueLineStarted(std::function<void(const std::string&)> cb);
|
||||
void setOnCutsceneLineStarted(std::function<void(const std::string&)> cb);
|
||||
void setOnCutsceneFadeInComplete(std::function<void(const std::string&)> cb);
|
||||
void setOnBubbleSlotReady(std::function<void(const std::string&)> cb);
|
||||
void setOnChatBubbleReady(std::function<void(const std::string&, bool)> cb);
|
||||
void setOnDialogueAdvanced(std::function<void()> cb);
|
||||
void stopDialogue();
|
||||
|
||||
|
||||
@ -97,8 +97,8 @@ struct Node {
|
||||
// For CutsceneStart
|
||||
std::string cutsceneId;
|
||||
|
||||
// Name of the UI node (StaticImage) to reveal in the phone chat when this line is shown
|
||||
std::string bubbleSlot;
|
||||
// "in" or "out" — creates a dynamic chat bubble; empty = not a chat message
|
||||
std::string chatBubble;
|
||||
|
||||
// Quest actions fired when this line is presented (empty = no action)
|
||||
std::string questUnlock;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user