Full modal dialog functionality
This commit is contained in:
parent
25d3019d1a
commit
fc54a6e418
|
@ -1,71 +1,117 @@
|
||||||
|
modalDialog = nil
|
||||||
|
|
||||||
function init()
|
function init()
|
||||||
g_ui.importStyle('modaldialog')
|
g_ui.importStyle('modaldialog')
|
||||||
|
|
||||||
connect(g_game, { onModalDialog = onModalDialog,
|
connect(g_game, { onModalDialog = onModalDialog,
|
||||||
onGameEnd = destroy })
|
onGameEnd = destroyDialog })
|
||||||
|
|
||||||
|
local dialog = rootWidget:recursiveGetChildById('modalDialog')
|
||||||
|
if dialog then
|
||||||
|
modalDialog = dialog
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function terminate()
|
function terminate()
|
||||||
disconnect(g_game, { onModalDialog = onModalDialog,
|
disconnect(g_game, { onModalDialog = onModalDialog,
|
||||||
onGameEnd = destroy })
|
onGameEnd = destroyDialog })
|
||||||
|
|
||||||
destroy()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function destroy()
|
function destroyDialog()
|
||||||
if modalDialog then
|
if modalDialog then
|
||||||
modalDialog:destroy()
|
modalDialog:destroy()
|
||||||
modalDialog = nil
|
modalDialog = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function onModalDialog(id, title, message, enterId, enterText, escapeId, escapeText, choices)
|
function onModalDialog(id, title, message, buttons, enterButton, escapeButton, choices, priority)
|
||||||
if modalDialog then return end
|
-- priority parameter is unused, not sure what its use is.
|
||||||
|
if modalDialog then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
modalDialog = g_ui.createWidget('ModalDialog', rootWidget)
|
modalDialog = g_ui.createWidget('ModalDialog', rootWidget)
|
||||||
|
|
||||||
local enterButton = modalDialog:getChildById('enterButton')
|
|
||||||
local escapeButton = modalDialog:getChildById('escapeButton')
|
|
||||||
local messageLabel = modalDialog:getChildById('messageLabel')
|
local messageLabel = modalDialog:getChildById('messageLabel')
|
||||||
local choiceList = modalDialog:getChildById('choiceList')
|
local choiceList = modalDialog:getChildById('choiceList')
|
||||||
|
local choiceScrollbar = modalDialog:getChildById('choiceScrollBar')
|
||||||
|
local buttonList = modalDialog:getChildById('buttonList')
|
||||||
|
|
||||||
modalDialog:setText(title)
|
modalDialog:setText(title)
|
||||||
messageLabel:setText(message)
|
messageLabel:setText(message)
|
||||||
enterButton:setText(enterText)
|
|
||||||
escapeButton:setText(escapeText)
|
|
||||||
|
|
||||||
local focusLabel = nil
|
local horizontalPadding = modalDialog:getPaddingLeft() + modalDialog:getPaddingRight()
|
||||||
for k, v in pairs(choices) do
|
modalDialog:setWidth(math.min(modalDialog.maximumWidth, math.max(messageLabel:getWidth(), modalDialog.minimumWidth)))
|
||||||
local choiceId = v[1]
|
messageLabel:setWidth(math.min(modalDialog.maximumWidth, math.max(messageLabel:getWidth(), modalDialog.minimumWidth)) - horizontalPadding)
|
||||||
local choiceName = v[2]
|
|
||||||
|
local labelHeight = nil
|
||||||
|
for i = 1, #choices do
|
||||||
|
local choiceId = choices[i][1]
|
||||||
|
local choiceName = choices[i][2]
|
||||||
|
|
||||||
local label = g_ui.createWidget('ChoiceListLabel', choiceList)
|
local label = g_ui.createWidget('ChoiceListLabel', choiceList)
|
||||||
label.choiceId = choiceId
|
label.choiceId = choiceId
|
||||||
label:setText(choiceName)
|
label:setText(choiceName)
|
||||||
label:setPhantom(false)
|
label:setPhantom(false)
|
||||||
|
if not labelHeight then
|
||||||
|
labelHeight = label:getHeight()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
choiceList:focusNextChild()
|
||||||
|
|
||||||
if not focusLabel then
|
for i = 1, #buttons do
|
||||||
focusLabel = label
|
local buttonId = buttons[i][1]
|
||||||
|
local buttonText = buttons[i][2]
|
||||||
|
|
||||||
|
local button = g_ui.createWidget('ModalButton', buttonList)
|
||||||
|
button:setText(buttonText)
|
||||||
|
button.onClick = function(self)
|
||||||
|
local focusedChoice = choiceList:getFocusedChild()
|
||||||
|
local choice = 0xFF
|
||||||
|
if focusedChoice then
|
||||||
|
choice = focusedChoice.choiceId
|
||||||
|
end
|
||||||
|
g_game.answerModalDialog(id, buttonId, choice)
|
||||||
|
destroyDialog()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
choiceList:focusChild(focusLabel)
|
|
||||||
|
local additionalHeight = 0
|
||||||
|
if #choices > 0 then
|
||||||
|
choiceList:setVisible(true)
|
||||||
|
choiceScrollbar:setVisible(true)
|
||||||
|
|
||||||
|
additionalHeight = math.min(modalDialog.maximumChoices, math.max(modalDialog.minimumChoices, #choices)) * labelHeight
|
||||||
|
additionalHeight = additionalHeight + choiceList:getPaddingTop() + choiceList:getPaddingBottom()
|
||||||
|
end
|
||||||
|
modalDialog:setHeight(modalDialog:getHeight() + additionalHeight)
|
||||||
|
|
||||||
|
addEvent(function()
|
||||||
|
modalDialog:setHeight(modalDialog:getHeight() + messageLabel:getHeight() - 14)
|
||||||
|
end)
|
||||||
|
|
||||||
local enterFunc = function()
|
local enterFunc = function()
|
||||||
g_game.answerModalDialog(id, enterId, choiceList:getFocusedChild().choiceId)
|
local focusedChoice = choiceList:getFocusedChild()
|
||||||
destroy()
|
local choice = 0xFF
|
||||||
|
if focusedChoice then
|
||||||
|
choice = focusedChoice.choiceId
|
||||||
|
end
|
||||||
|
g_game.answerModalDialog(id, enterButton, choice)
|
||||||
|
destroyDialog()
|
||||||
end
|
end
|
||||||
|
|
||||||
local escapeFunc = function()
|
local escapeFunc = function()
|
||||||
g_game.answerModalDialog(id, escapeId, choiceList:getFocusedChild().choiceId)
|
local focusedChoice = choiceList:getFocusedChild()
|
||||||
destroy()
|
local choice = 0xFF
|
||||||
|
if focusedChoice then
|
||||||
|
choice = focusedChoice.choiceId
|
||||||
|
end
|
||||||
|
g_game.answerModalDialog(id, escapeButton, choice)
|
||||||
|
destroyDialog()
|
||||||
end
|
end
|
||||||
|
|
||||||
choiceList.onDoubleClick = enterFunc
|
choiceList.onDoubleClick = enterFunc
|
||||||
|
|
||||||
enterButton.onClick = enterFunc
|
|
||||||
modalDialog.onEnter = enterFunc
|
modalDialog.onEnter = enterFunc
|
||||||
|
|
||||||
escapeButton.onClick = escapeFunc
|
|
||||||
modalDialog.onEscape = escapeFunc
|
modalDialog.onEscape = escapeFunc
|
||||||
return
|
|
||||||
end
|
end
|
|
@ -8,52 +8,61 @@ ChoiceListLabel < Label
|
||||||
background-color: #ffffff22
|
background-color: #ffffff22
|
||||||
color: #ffffff
|
color: #ffffff
|
||||||
|
|
||||||
ModalDialog < MainWindow
|
ChoiceList < TextList
|
||||||
id: modalDialog
|
|
||||||
!text: tr('Title')
|
|
||||||
size: 280 230
|
|
||||||
@onEscape: self:destroy()
|
|
||||||
|
|
||||||
Label
|
|
||||||
id: messageLabel
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
text-align: left
|
|
||||||
text: Message
|
|
||||||
height: 60
|
|
||||||
|
|
||||||
TextList
|
|
||||||
id: choiceList
|
id: choiceList
|
||||||
vertical-scrollbar: choiceScrollBar
|
vertical-scrollbar: choiceScrollBar
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
anchors.bottom: next.top
|
anchors.bottom: next.top
|
||||||
margin-bottom: 10
|
|
||||||
margin-top: 10
|
|
||||||
padding: 1
|
padding: 1
|
||||||
|
margin-top: 4
|
||||||
|
margin-bottom: 10
|
||||||
focusable: false
|
focusable: false
|
||||||
|
visible: false
|
||||||
|
|
||||||
Button
|
ChoiceScrollBar < VerticalScrollBar
|
||||||
id: enterButton
|
|
||||||
!text: tr('Ok')
|
|
||||||
anchors.top: next.top
|
|
||||||
anchors.right: next.left
|
|
||||||
margin-right: 8
|
|
||||||
width: 60
|
|
||||||
|
|
||||||
Button
|
|
||||||
id: escapeButton
|
|
||||||
!text: tr('Cancel')
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.right: parent.right
|
|
||||||
margin-top: 10
|
|
||||||
width: 60
|
|
||||||
|
|
||||||
VerticalScrollBar
|
|
||||||
id: choiceScrollBar
|
id: choiceScrollBar
|
||||||
anchors.top: choiceList.top
|
anchors.top: choiceList.top
|
||||||
anchors.bottom: choiceList.bottom
|
anchors.bottom: choiceList.bottom
|
||||||
anchors.right: choiceList.right
|
anchors.right: choiceList.right
|
||||||
step: 14
|
step: 14
|
||||||
pixels-scroll: true
|
pixels-scroll: true
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
ModalButton < Button
|
||||||
|
width: 60
|
||||||
|
margin: 2
|
||||||
|
|
||||||
|
ModalDialog < MainWindow
|
||||||
|
id: modalDialog
|
||||||
|
size: 280 97
|
||||||
|
&minimumWidth: 200
|
||||||
|
&maximumWidth: 500
|
||||||
|
&minimumChoices: 4
|
||||||
|
&maximumChoices: 10
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: messageLabel
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
text-align: left
|
||||||
|
text-auto-resize: true
|
||||||
|
text-wrap: true
|
||||||
|
|
||||||
|
ChoiceList
|
||||||
|
|
||||||
|
HorizontalSeparator
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: next.top
|
||||||
|
|
||||||
|
Panel
|
||||||
|
id: buttonList
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
height: 24
|
||||||
|
layout: horizontalBox
|
||||||
|
align-right: true
|
||||||
|
|
||||||
|
ChoiceScrollBar
|
||||||
|
|
|
@ -506,9 +506,9 @@ void Game::processQuestLine(int questId, const std::vector<std::tuple<std::strin
|
||||||
g_lua.callGlobalField("g_game", "onQuestLine", questId, questMissions);
|
g_lua.callGlobalField("g_game", "onQuestLine", questId, questMissions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::processModalDialog(uint32 id, std::string title, std::string message, int enterId, std::string enterText, int escapeId, std::string escapeText, std::vector<std::tuple<int, std::string> > choiceList)
|
void Game::processModalDialog(uint32 id, std::string title, std::string message, std::vector<std::tuple<int, std::string> > buttonList, int enterButton, int escapeButton, std::vector<std::tuple<int, std::string> > choiceList, bool priority)
|
||||||
{
|
{
|
||||||
g_lua.callGlobalField("g_game", "onModalDialog", id, title, message, enterId, enterText, escapeId, escapeText, choiceList);
|
g_lua.callGlobalField("g_game", "onModalDialog", id, title, message, buttonList, enterButton, escapeButton, choiceList, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::processAttackCancel(uint seq)
|
void Game::processAttackCancel(uint seq)
|
||||||
|
|
|
@ -132,7 +132,7 @@ protected:
|
||||||
void processQuestLine(int questId, const std::vector<std::tuple<std::string, std::string> >& questMissions);
|
void processQuestLine(int questId, const std::vector<std::tuple<std::string, std::string> >& questMissions);
|
||||||
|
|
||||||
// modal dialogs >= 970
|
// modal dialogs >= 970
|
||||||
void processModalDialog(uint32 id, std::string title, std::string message, int enterId, std::string enterText, int escapeId, std::string escapeText, std::vector<std::tuple<int, std::string> > choiceList);
|
void processModalDialog(uint32 id, std::string title, std::string message, std::vector<std::tuple<int, std::string> > buttonList, int enterButton, int escapeButton, std::vector<std::tuple<int, std::string> > choiceList, bool priority);
|
||||||
|
|
||||||
friend class ProtocolGame;
|
friend class ProtocolGame;
|
||||||
friend class Map;
|
friend class Map;
|
||||||
|
|
|
@ -145,7 +145,7 @@ namespace Proto {
|
||||||
GameServerMarketLeave = 247, // 944
|
GameServerMarketLeave = 247, // 944
|
||||||
GameServerMarketDetail = 248, // 944
|
GameServerMarketDetail = 248, // 944
|
||||||
GameServerMarketBrowse = 249, // 944
|
GameServerMarketBrowse = 249, // 944
|
||||||
GameServerShowModalDialog = 250 // 960
|
GameServerModalDialog = 250 // 960
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ClientOpcodes : uint8
|
enum ClientOpcodes : uint8
|
||||||
|
|
|
@ -212,7 +212,7 @@ private:
|
||||||
void parseChannelEvent(const InputMessagePtr& msg);
|
void parseChannelEvent(const InputMessagePtr& msg);
|
||||||
void parseItemInfo(const InputMessagePtr& msg);
|
void parseItemInfo(const InputMessagePtr& msg);
|
||||||
void parsePlayerInventory(const InputMessagePtr& msg);
|
void parsePlayerInventory(const InputMessagePtr& msg);
|
||||||
void parseShowModalDialog(const InputMessagePtr& msg);
|
void parseModalDialog(const InputMessagePtr& msg);
|
||||||
void parseExtendedOpcode(const InputMessagePtr& msg);
|
void parseExtendedOpcode(const InputMessagePtr& msg);
|
||||||
void parseChangeMapAwareRange(const InputMessagePtr& msg);
|
void parseChangeMapAwareRange(const InputMessagePtr& msg);
|
||||||
void parseCreaturesMark(const InputMessagePtr& msg);
|
void parseCreaturesMark(const InputMessagePtr& msg);
|
||||||
|
|
|
@ -316,8 +316,8 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
|
||||||
parsePlayerInfo(msg);
|
parsePlayerInfo(msg);
|
||||||
break;
|
break;
|
||||||
// PROTOCOL>=970
|
// PROTOCOL>=970
|
||||||
case Proto::GameServerShowModalDialog:
|
case Proto::GameServerModalDialog:
|
||||||
parseShowModalDialog(msg);
|
parseModalDialog(msg);
|
||||||
break;
|
break;
|
||||||
// PROTOCOL>=980
|
// PROTOCOL>=980
|
||||||
case Proto::GameServerLoginSuccess:
|
case Proto::GameServerLoginSuccess:
|
||||||
|
@ -1596,18 +1596,18 @@ void ProtocolGame::parsePlayerInventory(const InputMessagePtr& msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolGame::parseShowModalDialog(const InputMessagePtr& msg)
|
void ProtocolGame::parseModalDialog(const InputMessagePtr& msg)
|
||||||
{
|
{
|
||||||
uint32 id = msg->getU32();
|
uint32 id = msg->getU32();
|
||||||
std::string title = msg->getString();
|
std::string title = msg->getString();
|
||||||
std::string message = msg->getString();
|
std::string message = msg->getString();
|
||||||
|
|
||||||
int sizeButtons = msg->getU8();
|
int sizeButtons = msg->getU8();
|
||||||
std::map<int, std::string > buttonList;
|
std::vector<std::tuple<int, std::string> > buttonList;
|
||||||
for(int i = 0; i < sizeButtons; ++i) {
|
for(int i = 0; i < sizeButtons; ++i) {
|
||||||
std::string value = msg->getString();
|
std::string value = msg->getString();
|
||||||
int id = msg->getU8();
|
int id = msg->getU8();
|
||||||
buttonList[id] = value;
|
buttonList.push_back(std::make_tuple(id, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
int sizeChoices = msg->getU8();
|
int sizeChoices = msg->getU8();
|
||||||
|
@ -1628,21 +1628,9 @@ void ProtocolGame::parseShowModalDialog(const InputMessagePtr& msg)
|
||||||
escapeButton = msg->getU8();
|
escapeButton = msg->getU8();
|
||||||
}
|
}
|
||||||
|
|
||||||
msg->getU8(); // popup value (no clue what it is for)
|
bool priority = msg->getU8() == 0x01;
|
||||||
|
|
||||||
std::map<int, std::string>::iterator itEnter = buttonList.find(enterButton);
|
g_game.processModalDialog(id, title, message, buttonList, enterButton, escapeButton, choiceList, priority);
|
||||||
if(itEnter == buttonList.end()) {
|
|
||||||
g_logger.info(stdext::format("Enter button does not exist for dialog id: %d", id));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<int, std::string >::iterator itEscape = buttonList.find(escapeButton);
|
|
||||||
if(itEscape == buttonList.end()) {
|
|
||||||
g_logger.info(stdext::format("Escape button does not exist for dialog id: %d", id));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_game.processModalDialog(id, title, message, itEnter->first, itEnter->second, itEscape->first, itEscape->second, choiceList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolGame::parseExtendedOpcode(const InputMessagePtr& msg)
|
void ProtocolGame::parseExtendedOpcode(const InputMessagePtr& msg)
|
||||||
|
|
Loading…
Reference in New Issue