Adapting MessageQueue for Tutorial (#4204)

* Make Script-Message more adaptable

* Highly WIP-TriggerMessage

This is commited for discussion, so it is far away from complete or good or anything else.

* One Place for the static Message!

* Fixing that clear() dont clear the static message.

* Discard Static Messages when Race is closed.

In Order to not leave StaticMessages if an Race is quit, now closing the race discard StaticMessages.

* Allow for co-existence of static and normal message

* Fix indentation and Enum Order

* Clean up used StaticMessages.

* Clean StaticMessages up Round 2
This commit is contained in:
CodedOre 2020-01-10 17:12:56 +01:00 committed by Benau
parent c7c5a54083
commit 13fca9a0eb
5 changed files with 224 additions and 38 deletions

1
.gitignore vendored
View File

@ -5,6 +5,7 @@ dependencies*/
CMakeFiles/
stk-editor/
.vscode/
tags.*
.config/
supertuxkart-64

View File

@ -37,6 +37,10 @@ namespace MessageQueue
// ============================================================================
/** The label widget used to show the current message. */
SkinWidgetContainer* g_container = NULL;
SkinWidgetContainer* g_static_container = NULL;
/** Stores the height of an static container to allow showing both. */
int s_msg_raise = 0;
// ============================================================================
/** A base class for any messages. */
@ -85,7 +89,7 @@ public:
/** A small helper class to store and sort text messages to be displayed. */
class TextMessage : public Message
{
private:
protected:
/** The type of the message. */
MessageQueue::MessageType m_message_type;
@ -98,10 +102,15 @@ private:
/** Drawing rectangle of text layout. */
core::recti m_text_rect;
/** A pointer to the Container for the Message */
SkinWidgetContainer* m_container;
public:
TextMessage(MessageQueue::MessageType mt, const core::stringw &message) :
Message(5.0f)
{
m_container = g_container;
m_message_type = mt;
m_message = message;
assert(mt != MessageQueue::MT_PROGRESS);
@ -181,6 +190,9 @@ public:
m_area = irr::core::recti(x, y, x + total_width, y + dim.Height);
m_text_rect = core::recti(x, y, x + left_icon_size + total_width,
y + dim.Height);
if (m_container == g_static_container)
s_msg_raise = int(dim.Height) + font->getHeightPerLine() / 10;
}
// ------------------------------------------------------------------------
/** Draw the message. */
@ -192,10 +204,13 @@ public:
return;
}
Message::draw(dt);
int pos_transform = 0;
if (m_container == g_container)
pos_transform = s_msg_raise;
core::position2di raise = core::position2di(0,
irr_driver->getDevice()->getOnScreenKeyboardHeight() -
irr_driver->getDevice()->getMovedHeight());
GUIEngine::getSkin()->drawMessage(g_container, m_area - raise,
irr_driver->getDevice()->getMovedHeight() + pos_transform);
GUIEngine::getSkin()->drawMessage(m_container, m_area - raise,
m_render_type);
GUIEngine::getFont()->draw(m_gls, m_text_rect - raise,
GUIEngine::getSkin()->getColor("text::neutral"), true/*hcenter*/);
@ -205,6 +220,39 @@ public:
}; // class TextMessage
class StaticTextMessage : public TextMessage
{
public:
StaticTextMessage(MessageQueue::MessageType mt, const core::stringw &message) :
TextMessage(mt, message)
{
m_container = g_static_container;
m_message_type = mt;
m_message = message;
assert(mt != MessageQueue::MT_PROGRESS);
if (mt == MessageQueue::MT_ACHIEVEMENT)
m_render_type = "achievement-message::neutral";
else if (mt == MessageQueue::MT_ERROR)
m_render_type = "error-message::neutral";
else if (mt == MessageQueue::MT_GENERIC)
m_render_type = "generic-message::neutral";
else
m_render_type = "friend-message::neutral";
} // Message
// ------------------------------------------------------------------------
~StaticTextMessage()
{
}
// ------------------------------------------------------------------------
/** Draw the message. */
virtual void draw(float dt)
{
TextMessage::draw(dt);
m_display_timer = 9999999.9f;
}
// ------------------------------------------------------------------------
};
// ============================================================================
/** A function class to compare messages, required for priority_queue. */
class CompareMessages
@ -224,6 +272,10 @@ public:
Synchronised<std::priority_queue<Message*, std::vector<Message*>,
CompareMessages> > g_all_messages;
// ============================================================================
/** The Storage for a Static Message */
StaticTextMessage* g_static_message = 0;
// ============================================================================
/** Add any message to the message queue.
* \param message Any message.
@ -313,14 +365,11 @@ ProgressBarMessage g_progress_bar_msg;
* position of the message. */
void updatePosition()
{
if (g_static_message != 0)
g_static_message->init();
g_all_messages.lock();
bool empty = g_all_messages.getData().empty();
if (empty)
{
g_all_messages.unlock();
return;
}
g_all_messages.getData().top()->init();
if (!g_all_messages.getData().empty())
g_all_messages.getData().top()->init();
g_all_messages.unlock();
} // updatePosition
@ -339,6 +388,23 @@ void add(MessageType mt, const irr::core::stringw &message)
#endif
} // add
// ----------------------------------------------------------------------------
/** Adds a Text message which has to be discarded or overridden manually.
* It is only possible to show one static Message at a time!
* \param mt The MessageType of the message.
* \param message The actual message.
*/
void addStatic(MessageType mt, const irr::core::stringw &message)
{
#ifndef SERVER_ONLY
if (ProfileWorld::isNoGraphics())
return;
delete g_static_message;
g_static_message = 0;
g_static_message = new StaticTextMessage(mt, message);
#endif
} // addStatic
// ----------------------------------------------------------------------------
/** Update function called from the GUIEngine to handle displaying of the
* messages. It will make sure that each message is shown for a certain
@ -353,23 +419,28 @@ void update(float dt)
return;
if (!g_container)
g_container = new SkinWidgetContainer();
g_all_messages.lock();
bool empty = g_all_messages.getData().empty();
if (empty)
{
g_all_messages.unlock();
return;
g_container = new SkinWidgetContainer();
}
if (!g_static_container)
{
g_static_container = new SkinWidgetContainer();
}
Message* current = g_all_messages.getData().top();
current->draw(dt);
if (g_static_message != 0)
g_static_message->draw(dt);
if (current->canBeRemoved())
g_all_messages.lock();
if (!g_all_messages.getData().empty())
{
g_all_messages.getData().pop();
current->remove();
Message* current = g_all_messages.getData().top();
current->draw(dt);
if (current->canBeRemoved())
{
g_all_messages.getData().pop();
current->remove();
}
}
g_all_messages.unlock();
#endif
@ -392,12 +463,26 @@ void showProgressBar(int progress, const core::stringw& msg)
#endif
} // showProgressBar
// ----------------------------------------------------------------------------
/** Remove the static Message from display.
*/
void discardStatic()
{
#ifndef SERVER_ONLY
delete g_static_message;
g_static_message = 0;
s_msg_raise = 0;
#endif
} // discardStatic
// ----------------------------------------------------------------------------
/** Clear all message, called when destroying the GUIEngine.
*/
void clear()
{
#ifndef SERVER_ONLY
delete g_static_message;
g_static_message = 0;
g_all_messages.lock();
while (!g_all_messages.getData().empty())
{

View File

@ -38,15 +38,17 @@ namespace MessageQueue
{
MT_FRIEND,
MT_ACHIEVEMENT,
MT_ERROR,
MT_GENERIC,
MT_ERROR,
MT_PROGRESS
};
void add(MessageType mt, const core::stringw &message);
void addStatic(MessageType mt, const core::stringw &message);
void showProgressBar(int progress, const core::stringw& msg);
void updatePosition();
void update(float dt);
void discardStatic();
void clear();
}; // namespace GUIEngine
#endif

View File

@ -27,6 +27,7 @@
#include "config/stk_config.hpp"
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "guiengine/message_queue.hpp"
#include "input/device_manager.hpp"
#include "input/input_manager.hpp"
#include "karts/abstract_kart.hpp"
@ -805,6 +806,8 @@ void RaceManager::exitRace(bool delete_world)
{
// Only display the grand prix result screen if all tracks
// were finished, and not when a race is aborted.
MessageQueue::discardStatic();
if ( m_major_mode==MAJOR_MODE_GRAND_PRIX &&
m_track_number==(int)m_tracks.size() )
{

View File

@ -24,6 +24,7 @@
#include "input/input_manager.hpp"
#include "modes/world.hpp"
#include "scriptengine/aswrappedcall.hpp"
#include "scriptengine/script_track.hpp"
#include "states_screens/dialogs/tutorial_message_dialog.hpp"
#include "tracks/track.hpp"
#include "tracks/track_object.hpp"
@ -52,6 +53,16 @@ namespace Scripting
RGT_ACCELEROMETER = 2,
RGT_GYROSCOPE = 3,
};
enum MsgType
{
MSG_FRIEND = 0,
MSG_ACHIEVEMENT = 1,
MSG_GENERIC = 2,
MSG_ERROR = 3
};
/** \addtogroup Scripting
* @{
*/
@ -77,20 +88,60 @@ namespace Scripting
new TutorialMessageDialog((out), true);
}
/** Display a Message using MessageQueue */
void displayGenericMessage(std::string* input)
/** Display a Message using MessageQueue (enum GUI::MsgType)*/
void displayMessage(std::string* input, int Enum_value)
{
irr::core::stringw msg = StringUtils::utf8ToWide(*input);
MessageQueue::MessageType type = MessageQueue::MT_GENERIC;
MessageQueue::add(type, msg);
irr::core::stringw msg = StringUtils::utf8ToWide(*input);
MsgType msg_type = (MsgType)Enum_value;
MessageQueue::MessageType type;
switch (msg_type)
{
case MSG_ERROR:
type = MessageQueue::MT_ERROR;
break;
case MSG_FRIEND:
type = MessageQueue::MT_FRIEND;
break;
case MSG_ACHIEVEMENT:
type = MessageQueue::MT_ACHIEVEMENT;
break;
default:
type = MessageQueue::MT_GENERIC;
break;
}
MessageQueue::add(type, msg);
}
/** Display a Error Message using MessageQueue */
void displayErrorMessage(std::string* input)
/** Displays an static Message. (enum GUI::MsgType)
* This Message has to be discarded by discardStaticMessage() manually.
* Otherwise it can be overridden.
*/
void displayStaticMessage(std::string* input, int Enum_value)
{
irr::core::stringw msg = StringUtils::utf8ToWide(*input);
MessageQueue::MessageType type = MessageQueue::MT_ERROR;
MessageQueue::add(type, msg);
irr::core::stringw msg = StringUtils::utf8ToWide(*input);
MsgType msg_type = (MsgType)Enum_value;
MessageQueue::MessageType type;
switch (msg_type)
{
case MSG_ERROR:
type = MessageQueue::MT_ERROR;
break;
case MSG_FRIEND:
type = MessageQueue::MT_FRIEND;
break;
case MSG_ACHIEVEMENT:
type = MessageQueue::MT_ACHIEVEMENT;
break;
default:
type = MessageQueue::MT_GENERIC;
break;
}
MessageQueue::addStatic(type, msg);
}
void discardStaticMessage()
{
MessageQueue::discardStatic();
}
void clearOverlayMessages()
@ -165,6 +216,31 @@ namespace Scripting
// documented function whose name is exposed in angelscript (these proxies exist so that
// angelscript can properly resolve overloads, but doxygen can still generate the right docs
/** \cond DOXYGEN_IGNORE */
void proxy_displayMessage(std::string* msgString)
{
return displayMessage(msgString, MSG_GENERIC);
}
void proxy_displayMessageAndInsertValues1(std::string* msgString, int msgType)
{
return displayMessage(msgString, msgType);
}
void proxy_displayStaticMessage(std::string* msgString)
{
return displayStaticMessage(msgString, MSG_GENERIC);
}
void proxy_displayStaticMessageAndInsertValues1(std::string* msgString, int msgType)
{
return displayStaticMessage(msgString, msgType);
}
void proxy_discardStaticMessage()
{
return discardStaticMessage();
}
std::string proxy_translate(std::string* formatString)
{
return translate(formatString);
@ -208,13 +284,27 @@ namespace Scripting
bool mp = strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY");
asDWORD call_conv = mp ? asCALL_GENERIC : asCALL_CDECL;
int r; // of type asERetCodes
r = engine->RegisterGlobalFunction("void displayGenericMessage(const string &in)",
mp ? WRAP_FN(displayGenericMessage) : asFUNCTION(displayGenericMessage),
r = engine->RegisterGlobalFunction("void displayMessage(const string &in)",
mp ? WRAP_FN(proxy_displayMessage) : asFUNCTION(proxy_displayMessage),
call_conv); assert(r >= 0);
r = engine->RegisterGlobalFunction("void displayErrorMessage(const string &in)",
mp ? WRAP_FN(displayErrorMessage) : asFUNCTION(displayErrorMessage),
r = engine->RegisterGlobalFunction("void displayMessage(const string &in, int MessageType)",
mp ? WRAP_FN(proxy_displayMessageAndInsertValues1)
: asFUNCTION(proxy_displayMessageAndInsertValues1),
call_conv); assert(r >= 0);
r = engine->RegisterGlobalFunction("void displayStaticMessage(const string &in)",
mp ? WRAP_FN(proxy_displayStaticMessage) : asFUNCTION(proxy_displayStaticMessage),
call_conv); assert(r >= 0);
r = engine->RegisterGlobalFunction("void displayStaticMessage(const string &in, int MessageType)",
mp ? WRAP_FN(proxy_displayStaticMessageAndInsertValues1)
: asFUNCTION(proxy_displayStaticMessageAndInsertValues1),
call_conv); assert(r >= 0);
r = engine->RegisterGlobalFunction("void discardStaticMessage()",
mp ? WRAP_FN(discardStaticMessage) : asFUNCTION(discardStaticMessage),
call_conv); assert(r >= 0);
r = engine->RegisterGlobalFunction("void displayModalMessage(const string &in)",
@ -284,6 +374,11 @@ namespace Scripting
engine->RegisterEnumValue("RaceGUIType", "STEERING_WHEEL", RGT_STEERING_WHEEL);
engine->RegisterEnumValue("RaceGUIType", "ACCELEROMETER", RGT_ACCELEROMETER);
engine->RegisterEnumValue("RaceGUIType", "GYROSCOPE", RGT_GYROSCOPE);
engine->RegisterEnum("MsgType");
engine->RegisterEnumValue("MsgType", "GENERIC", MSG_GENERIC);
engine->RegisterEnumValue("MsgType", "ERROR", MSG_ERROR);
engine->RegisterEnumValue("MsgType", "ACHIEVEMENT", MSG_ACHIEVEMENT);
engine->RegisterEnumValue("MsgType", "FRIEND", MSG_FRIEND);
}
}