250 lines
6.8 KiB
C++
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
|
|
);
|
|
} |