osb/source/frontend/StarRadioMessagePopup.cpp

168 lines
5.5 KiB
C++
Raw Normal View History

2023-06-20 04:33:09 +00:00
#include "StarRadioMessagePopup.hpp"
#include "StarGuiReader.hpp"
#include "StarLabelWidget.hpp"
#include "StarImageWidget.hpp"
#include "StarAssets.hpp"
#include "StarRoot.hpp"
#include "StarLogging.hpp"
#include "StarJsonExtra.hpp"
#include "StarInterpolation.hpp"
#include "StarLexicalCast.hpp"
#include "StarMixer.hpp"
#include "StarTextPainter.hpp"
namespace Star {
RadioMessagePopup::RadioMessagePopup() {
auto assets = Root::singleton().assets();
auto config = assets->json("/interface/radiomessage/radiomessage.config");
GuiReader reader;
reader.construct(config.get("paneLayout"), this);
m_messageLabel = fetchChild<LabelWidget>("lblMessage");
m_portraitImage = fetchChild<ImageWidget>("imgPortrait");
m_backgroundImage = config.getString("backgroundImage");
m_animateInTime = config.getFloat("animateInTime");
m_animateInImage = config.getString("animateInImage");
m_animateInFrames = config.getInt("animateInFrames");
m_animateOutTime = config.getFloat("animateOutTime");
m_animateOutImage = config.getString("animateOutImage");
m_animateOutFrames = config.getInt("animateOutFrames");
m_chatOffset = jsonToVec2I(config.get("chatOffset"));
m_chatStartPosition = m_chatOffset;
m_chatEndPosition = m_chatOffset;
m_slideTime = config.getFloat("slideTime");
m_slideTimer = m_slideTime;
updateAnchorOffset();
enterStage(PopupStage::Hidden);
}
void RadioMessagePopup::update(float dt) {
2023-06-20 04:33:09 +00:00
if (messageActive()) {
if (m_stageTimer.tick(dt))
2023-06-20 04:33:09 +00:00
nextPopupStage();
if (m_popupStage == PopupStage::AnimateIn) {
int frame = floor((1.0f - m_stageTimer.percent()) * m_animateInFrames);
2023-06-27 10:23:44 +00:00
setBG("", strf("{}:{}", m_animateInImage, frame), "");
2023-06-20 04:33:09 +00:00
} else if (m_popupStage == PopupStage::ScrollText) {
int frame =
int((m_stageTimer.timer / m_message.portraitSpeed) * m_message.portraitFrames) % m_message.portraitFrames;
m_portraitImage->setImage(m_message.portraitImage.replace("<frame>", toString(frame)));
int textLength = floor(Text::stripEscapeCodes(m_message.text).length() * (1.0f - m_stageTimer.percent()));
m_messageLabel->setTextCharLimit(textLength);
} else if (m_popupStage == PopupStage::Persist) {
// you're cool, just stay cool, cool person
} else if (m_popupStage == PopupStage::AnimateOut) {
int frame = floor((1.0f - m_stageTimer.percent()) * m_animateOutFrames);
2023-06-27 10:23:44 +00:00
setBG("", strf("{}:{}", m_animateOutImage, frame), "");
2023-06-20 04:33:09 +00:00
}
m_slideTimer = min(m_slideTimer + dt, m_slideTime);
2023-06-20 04:33:09 +00:00
updateAnchorOffset();
}
Pane::update(dt);
2023-06-20 04:33:09 +00:00
}
void RadioMessagePopup::dismissed() {
if (m_chatterSound)
m_chatterSound->stop();
Pane::dismissed();
}
bool RadioMessagePopup::messageActive() {
return m_popupStage != PopupStage::Hidden;
}
void RadioMessagePopup::setMessage(RadioMessage message) {
m_message = message;
if (!message.chatterSound.empty() && message.textSpeed > 0) {
if (m_chatterSound)
m_chatterSound->stop();
auto assets = Root::singleton().assets();
m_chatterSound = make_shared<AudioInstance>(*assets->audio(message.chatterSound));
m_chatterSound->setLoops(-1);
}
enterStage(PopupStage::AnimateIn);
updateAnchorOffset();
}
void RadioMessagePopup::setChatHeight(int chatHeight) {
auto endPosition = m_chatOffset + Vec2I(0, chatHeight);
if (endPosition != m_chatEndPosition) {
m_chatStartPosition = anchorOffset();
m_chatEndPosition = endPosition;
m_slideTimer = 0.0f;
}
}
void RadioMessagePopup::interrupt() {
if (m_popupStage != PopupStage::Hidden && m_popupStage != PopupStage::AnimateOut)
enterStage(PopupStage::AnimateOut);
}
void RadioMessagePopup::updateAnchorOffset() {
float slideRatio = m_slideTimer / m_slideTime;
setAnchorOffset(Vec2I(int(m_chatStartPosition[0] * (1 - slideRatio) + m_chatEndPosition[0] * slideRatio),
int(m_chatStartPosition[1] * (1 - slideRatio) + m_chatEndPosition[1] * slideRatio)));
}
void RadioMessagePopup::nextPopupStage() {
if (m_popupStage != PopupStage::Hidden)
enterStage((PopupStage)((int)m_popupStage + 1));
}
void RadioMessagePopup::enterStage(PopupStage newStage) {
m_popupStage = newStage;
if (m_popupStage == PopupStage::Hidden) {
m_portraitImage->hide();
m_messageLabel->hide();
2023-06-27 10:23:44 +00:00
setBG("", strf("{}:0", m_animateInImage), "");
2023-06-20 04:33:09 +00:00
} else if (m_popupStage == PopupStage::AnimateIn) {
m_stageTimer = GameTimer(m_animateInTime);
m_portraitImage->hide();
m_messageLabel->hide();
} else if (m_popupStage == PopupStage::ScrollText) {
if (m_message.textSpeed == 0) {
// skip this stage if text is instant
enterStage(PopupStage::Persist);
} else {
m_stageTimer = GameTimer(Text::stripEscapeCodes(m_message.text).length() / m_message.textSpeed);
m_portraitImage->show();
m_messageLabel->show();
m_messageLabel->setText(m_message.text);
m_messageLabel->setTextCharLimit(0);
setBG(m_backgroundImage);
if (m_chatterSound)
GuiContext::singleton().playAudio(m_chatterSound);
}
} else if (m_popupStage == PopupStage::Persist) {
m_stageTimer = GameTimer(m_message.persistTime);
m_portraitImage->show();
m_portraitImage->setImage(m_message.portraitImage.replace("<frame>", "0"));
m_messageLabel->show();
m_messageLabel->setText(m_message.text);
m_messageLabel->setTextCharLimit({});
setBG(m_backgroundImage);
if (m_chatterSound)
m_chatterSound->stop();
} else if (m_popupStage == PopupStage::AnimateOut) {
m_stageTimer = GameTimer(m_animateOutTime);
m_portraitImage->hide();
m_messageLabel->hide();
}
}
}