Starting new VN Structure

This commit is contained in:
2023-04-18 09:55:11 -07:00
parent 26efdfe314
commit 1c21c15261
77 changed files with 929 additions and 27 deletions

View File

@ -0,0 +1,11 @@
# Copyright (c) 2022 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DAWN_TARGET_NAME}
PRIVATE
VisualNovelFader.cpp
VisualNovelTextbox.cpp
)

View File

@ -0,0 +1,25 @@
// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "VisualNovelFader.hpp"
using namespace Dawn;
VisualNovelFader::VisualNovelFader(UICanvas *canvas) : UISprite(canvas) {
}
VisualNovelFader * VisualNovelFader::create(UICanvas *canvas) {
assertNotNull(canvas);
auto item = canvas->addElement<VisualNovelFader>();
item->setTransform(
UI_COMPONENT_ALIGN_STRETCH, UI_COMPONENT_ALIGN_STRETCH,
glm::vec4(0, 0, 0, 0),
0.0f
);
item->color = COLOR_BLACK_TRANSPARENT;
return item;
}

View File

@ -0,0 +1,32 @@
// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "ui/UISprite.hpp"
#include "ui/UIEmpty.hpp"
namespace Dawn {
class VisualNovelFader : public UISprite {
private:
public:
/**
* Quickly create a visual novel fader.
*
* @param canvas Canvas the fader belongs to.
* @return Created VN Fader.
*/
static VisualNovelFader * create(UICanvas *canvas);
/**
* Construct a new Visual Novel Fader. VN Fader is just a sprite that is
* easily found by the VN Manager for the purpose of adding transitions to
* a VN scene.
*
* @param canvas Canvas for this component.
*/
VisualNovelFader(UICanvas *canvas);
};
}

View File

@ -0,0 +1,250 @@
// 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
);
}

View File

@ -0,0 +1,167 @@
// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "ui/UISprite.hpp"
#include "ui/UIBorder.hpp"
#include "ui/UILabel.hpp"
#include "ui/UIEmpty.hpp"
#include "util/mathutils.hpp"
#include "visualnovel/components/VisualNovelCharacter.hpp"
#define VISUAL_NOVEL_TEXTBOX_SPEED 25.0f
#define VISUAL_NOVEL_TEXTBOX_SPEED_FASTER 40.0f
namespace Dawn {
class VisualNovelManager;
class VisualNovelTextbox : public UIComponent {
private:
int32_t lineCurrent = 0;
glm::vec2 labelPadding = glm::vec2(0, 0);
UIEmpty selfParent;
float_t timeCharacter = 0.0f;
bool_t visible = false;
VisualNovelCharacter *character = nullptr;
AudioAsset *talkSound = nullptr;
void updatePositions() override;
std::vector<struct ShaderPassItem> getSelfPassItems(
glm::mat4 projection,
glm::mat4 view,
glm::mat4 transform
) override;
/**
* Listens for scene updates.
*/
void textboxOnSceneUpdate();
/**
* Returns the count of visible lines within the textbox. Mostly used for
* when we need to decide how to wrap.
*
* @return The count of visible lines.
*/
int32_t getCountOfVisibleLines();
public:
UIBorder border;
UILabel label;
Event<> eventCharacterRevealed;
Event<> eventCurrentCharactersRevealed;
Event<> eventNewPage;
Event<> eventAllCharactersRevealed;
Event<> eventHidden;
Event<> eventVisible;
/**
* Constructs a VN Textbox.
*
* @param canvas Canvas that this textbox belongs to.
*/
VisualNovelTextbox(UICanvas *canvas);
void show();
void hide();
bool_t isVisible();
/**
* Returns the visual novel manager (if applicable).
*
* @return Visual Novel Manager instance.
*/
VisualNovelManager * getVisualNovelManager();
/**
* Sets the font for this vn textbox. Passed to the underlying label.
*
* @param font Font to set for this textbox.
*/
void setFont(Font *font);
/**
* Sets the string (label) for this textbox.
*
* @param text Localized string key to set.
* @param fontSize Font size of the string.
*/
void setText(std::string key, float_t fontSize);
/**
* Sets the string (label) for this textbox.
*
* @param text Localized string key to set.
*/
void setText(std::string key);
/**
* Sets the VN Character for this text.
*
* @param character Character to set.
*/
void setCharacter(VisualNovelCharacter *character);
/**
* Set the sound to use whenever the text is scrolling to represent a
* character talking.
*
* @param sound Sound asset to use.
*/
void setTalkingSound(AudioAsset *sound);
/**
* Sets the font size to use.
*
* @param fontSize Font size to use.
*/
void setFontSize(float_t fontSize);
/**
* Returns the current font size.
*
* @return Font size.
*/
float_t getFontSize();
/**
* Sets the padding of the label. This will increase the spacing between
* the text and the border.
*
* @param padding Padding to set.
*/
void setLabelPadding(glm::vec2 padding);
/**
* Returns the current label padding.
*
* @return The current label padding.
*/
glm::vec2 getLabelPadding();
/**
* Returns true if all of the characters that can be made visible for the
* current textbox size have finished revealing, or false if not.
*
* @return True if above statement is met.
*/
bool_t hasRevealedAllCurrentCharacters();
/**
* Returns true only when every character passed previously in setText
* has been revealed by scrolling.
*
* @return True if above statement is true.
*/
bool_t hasRevealedAllCharacters();
/**
* Cleans the VN Textbox.
*/
~VisualNovelTextbox();
};
}