Dawn/archive/visualnovel/ui/VisualNovelTextbox.cpp

250 lines
6.8 KiB
C++

// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "VisualNovelTextbox.hpp"
#include "game/DawnGame.hpp"
#include "visualnovel/VisualNovelManager.hpp"
using namespace Dawn;
VisualNovelTextbox::VisualNovelTextbox(UICanvas *canvas) :
UIComponent(canvas),
selfParent(canvas),
border(canvas),
label(canvas)
{
// Self Parent
this->selfParent.setTransform(
UI_COMPONENT_ALIGN_STRETCH, UI_COMPONENT_ALIGN_STRETCH,
glm::vec4(0, 0, 0, 0),
0.0f
);
// Border
this->selfParent.addChild(&this->border);
this->border.setTransform(
UI_COMPONENT_ALIGN_STRETCH, UI_COMPONENT_ALIGN_STRETCH,
glm::vec4(0, 0, 0, 0),
0.0f
);
// Label
this->selfParent.addChild(&this->label);
this->label.startQuad = 0;
this->label.quadCount = 0;
this->canvas->getScene()->eventSceneUnpausedUpdate.addListener(
this, &VisualNovelTextbox::textboxOnSceneUpdate
);
}
void VisualNovelTextbox::show() {
if(this->isVisible()) return;
this->visible = true;
this->addChild(&this->selfParent);
if(this->talkSound != nullptr) {
auto vnManager = this->getVisualNovelManager();
assertNotNull(vnManager);
assertNotNull(vnManager->audioCharacter);
vnManager->audioCharacter->stop();
vnManager->audioCharacter->setAudioData(this->talkSound);
vnManager->audioCharacter->loop = true;
vnManager->audioCharacter->play();
}
}
void VisualNovelTextbox::hide() {
if(!this->isVisible()) return;
if(this->talkSound != nullptr) {
auto vnManager = this->getVisualNovelManager();
assertNotNull(vnManager);
assertNotNull(vnManager->audioCharacter);
vnManager->audioCharacter->stop();
}
this->visible = false;
this->removeChild(&this->selfParent);
this->eventHidden.invoke();
}
bool_t VisualNovelTextbox::isVisible() {
return this->visible;
}
VisualNovelManager * VisualNovelTextbox::getVisualNovelManager() {
return this->getScene()->findComponent<VisualNovelManager>();
}
void VisualNovelTextbox::updatePositions() {
UIComponent::updatePositions();
this->lineCurrent = 0;
this->timeCharacter = 0;
this->label.setTransform(
UI_COMPONENT_ALIGN_STRETCH,
UI_COMPONENT_ALIGN_STRETCH,
glm::vec4(
this->border.getBorderSize() + this->labelPadding,
this->border.getBorderSize() + this->labelPadding
),
1.0f
);
this->label.startQuad = 0;
this->label.quadCount = 0;
}
void VisualNovelTextbox::textboxOnSceneUpdate() {
DawnGame *game = this->canvas->getGame();
if(this->hasRevealedAllCurrentCharacters()) {
if(this->hasRevealedAllCharacters()) {
if(game->inputManager.isPressed(INPUT_BIND_ACCEPT)) {
this->hide();
}
} else {
if(game->inputManager.isPressed(INPUT_BIND_ACCEPT)) {
this->lineCurrent += this->getCountOfVisibleLines();
this->label.startQuad = 0;
for(int32_t i = 0; i < this->lineCurrent; i++) {
this->label.startQuad += this->label.measure.getQuadsOnLine(i);
}
this->label.quadCount = 0;
this->timeCharacter = 0.0f;
this->label.setTransform(
UI_COMPONENT_ALIGN_STRETCH,
UI_COMPONENT_ALIGN_STRETCH,
glm::vec4(
glm::vec2(
this->border.getBorderSize().x + this->labelPadding.x,
this->border.getBorderSize().y + this->labelPadding.y -
this->label.measure.getHeightOfLineCount(this->lineCurrent)
),
this->border.getBorderSize() + this->labelPadding
),
5.0f
);
this->eventNewPage.invoke();
}
}
if(this->talkSound != nullptr) {
auto vnManager = this->getVisualNovelManager();
assertNotNull(vnManager);
assertNotNull(vnManager->audioCharacter);
vnManager->audioCharacter->stop();
}
return;
}
auto lastTimeCharacter = mathFloor<int32_t>(this->timeCharacter);
if(game->inputManager.isDown(INPUT_BIND_ACCEPT)) {
this->timeCharacter += game->timeManager.delta * VISUAL_NOVEL_TEXTBOX_SPEED_FASTER;
} else {
this->timeCharacter += game->timeManager.delta * VISUAL_NOVEL_TEXTBOX_SPEED;
}
auto newTimeCharacter = mathFloor<int32_t>(this->timeCharacter);
if(newTimeCharacter == lastTimeCharacter) return;
this->label.quadCount = newTimeCharacter;
this->eventCharacterRevealed.invoke();
}
int32_t VisualNovelTextbox::getCountOfVisibleLines() {
int32_t i = 1;
glm::vec2 innerSize = this->border.getInnerSize() - this->labelPadding;
for(i = this->label.measure.getLineCount(); i > 0; --i) {
if(innerSize.y >= this->label.measure.getHeightOfLineCount(i)) {
return i;
}
}
return this->label.measure.getLineCount();
}
std::vector<struct ShaderPassItem> VisualNovelTextbox::getSelfPassItems(
glm::mat4 projection,
glm::mat4 view,
glm::mat4 transform
) {
return std::vector<struct ShaderPassItem>();
}
void VisualNovelTextbox::setFont(Font *font) {
this->label.setFont(font);
this->label.updateMesh();
}
void VisualNovelTextbox::setText(std::string key, float_t fontSize) {
this->label.setText(key);
this->label.setFontSize(fontSize);
this->label.updateMesh();
}
void VisualNovelTextbox::setCharacter(VisualNovelCharacter *character) {
this->character = character;
this->talkSound = nullptr;
}
void VisualNovelTextbox::setTalkingSound(AudioAsset *asset) {
this->talkSound = asset;
}
void VisualNovelTextbox::setText(std::string key) {
this->label.setText(key);
this->label.updateMesh();
}
void VisualNovelTextbox::setFontSize(float_t fontSize) {
this->label.setFontSize(fontSize);
this->label.updateMesh();
}
float_t VisualNovelTextbox::getFontSize() {
return this->label.getFontSize();
}
void VisualNovelTextbox::setLabelPadding(glm::vec2 padding) {
this->labelPadding = padding;
this->updatePositions();
}
glm::vec2 VisualNovelTextbox::getLabelPadding() {
return this->labelPadding;
}
bool_t VisualNovelTextbox::hasRevealedAllCurrentCharacters() {
int32_t quadsTotal = 0;
for(
int32_t i = this->lineCurrent;
i < mathMin<int32_t>(
this->label.measure.getLineCount(),
this->lineCurrent + this->getCountOfVisibleLines()
);
i++
) {
quadsTotal += this->label.measure.getQuadsOnLine(i);
}
return mathFloor<int32_t>(this->timeCharacter) >= quadsTotal;
}
bool_t VisualNovelTextbox::hasRevealedAllCharacters() {
return (
this->lineCurrent + this->getCountOfVisibleLines() >=
this->label.measure.getLineCount()
);
}
VisualNovelTextbox::~VisualNovelTextbox() {
this->canvas->getScene()->eventSceneUnpausedUpdate.removeListener(
this, &VisualNovelTextbox::textboxOnSceneUpdate
);
}