diff --git a/assets/games/liminal/prefabs/VNTextbox.xml b/assets/games/liminal/prefabs/VNTextbox.xml
index 7ff6f64a..73a5db92 100644
--- a/assets/games/liminal/prefabs/VNTextbox.xml
+++ b/assets/games/liminal/prefabs/VNTextbox.xml
@@ -20,7 +20,23 @@
alignY="UI_COMPONENT_ALIGN_STRETCH"
ref="uiLabel"
>
- test1
+
+ Hello World
+ How are you today?
+ I'm doing great, thanks!
+ Thanks, me too!
+
+
+ Glad to hear it!
+ I'm glad to hear it too!
+ What a great day!
+ It sure is!
+ I'm glad we're friends!
+ Me too!
+ What are you up to?
+ Nothing much, just hanging out.
+ Cool, me too!
+
diff --git a/src/dawn/games/vn/components/VNTextboxScroller.cpp b/src/dawn/games/vn/components/VNTextboxScroller.cpp
index f4998f60..550a9a06 100644
--- a/src/dawn/games/vn/components/VNTextboxScroller.cpp
+++ b/src/dawn/games/vn/components/VNTextboxScroller.cpp
@@ -10,95 +10,83 @@ using namespace Dawn;
VNTextboxScroller::VNTextboxScroller(SceneItem *item) :
SceneItemComponent(item),
- label(nullptr)
+ label(nullptr),
+ visibleLines(4)
{
}
void VNTextboxScroller::onStart() {
- // assertNotNull(label);
+ assertNotNull(label);
- // std::function x = [&]{
- // this->lineCurrent = 0;
- // this->timeCharacter = 0;
- // this->label->startQuad = 0;
- // this->label->quadCount = 0;
- // this->readyToClose = false;
- // };
- // x();
+ std::function x = [&]{
+ this->lineCurrent = 0;
+ this->timeCharacter = 0;
+ this->label->quadStart = 0;
+ this->label->quadCount = 0;
+ this->readyToClose = false;
+ };
- // useEvent(x, this->label->eventTextChanged);
+ useEvent(x, this->label->eventTextChanged);
+ useEffect(x, visibleLines)();
- // useEvent([&](float_t delta){
- // auto game = this->getGame();
+ useEvent([&](float_t delta){
+ auto game = this->getGame();
- // this->timeCharacter += delta;
- // if(this->hasRevealedAllCurrentCharacters()) {
- // if(this->hasRevealedAllCharacters()) {
- // if(!this->readyToClose) {
- // this->readyToClose = true;
- // this->eventReadyToClose.invoke();
- // }
- // } 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;
- // }
- // }
- // return;
- // }
+ this->timeCharacter += delta;
+ if(this->hasRevealedAllCurrentCharacters()) {
+ if(this->hasRevealedAllCharacters()) {
+ if(!this->readyToClose) {
+ this->readyToClose = true;
+ this->eventReadyToClose.invoke();
+ }
+ } else {
+ if(game->inputManager.isPressed(INPUT_BIND_ACCEPT)) {
+ this->lineCurrent += this->visibleLines;
+ this->label->quadStart = this->label->lines[this->lineCurrent].quadStart;
+ this->label->quadCount = 0;
+ this->timeCharacter = 0.0f;
- // auto lastTimeCharacter = mathFloor(this->timeCharacter);
- // if(game->inputManager.isDown(INPUT_BIND_ACCEPT)) {
- // this->timeCharacter += game->timeManager.delta * VN_TEXTBOX_SPEED_FASTER;
- // } else {
- // this->timeCharacter += game->timeManager.delta * VN_TEXTBOX_SPEED;
- // }
+ this->label->textOffset = (
+ -this->label->lines[this->lineCurrent].position
+ );
+ }
+ }
+ return;
+ }
- // auto newCount = mathFloor(this->timeCharacter);
- // if(newCount == this->label->quadCount) return;
- // this->label->quadCount = mathFloor(this->timeCharacter);
- // this->eventCharacterRevealed.invoke();
- // }, getScene()->eventSceneUpdate);
- assertUnreachable();
-}
+ auto lastTimeCharacter = mathFloor(this->timeCharacter);
+ if(game->inputManager.isDown(INPUT_BIND_ACCEPT)) {
+ this->timeCharacter += game->timeManager.delta * VN_TEXTBOX_SPEED_FASTER;
+ } else {
+ this->timeCharacter += game->timeManager.delta * VN_TEXTBOX_SPEED;
+ }
-size_t VNTextboxScroller::getCountOfVisibleLines() {
- // float_t y = this->label->getHeight();
- // size_t i = 1;
- // for(i = this->label->measure.getLineCount(); i > 0; --i) {
- // if(y >= this->label->measure.getHeightOfLineCount(i)) {
- // return i;
- // }
- // }
- // return this->label->measure.getLineCount();
- assertUnreachable();
+ auto newCount = mathFloor(this->timeCharacter);
+ if(newCount == this->label->quadCount) return;
+ this->label->quadCount = mathFloor(this->timeCharacter);
+ this->eventCharacterRevealed.invoke();
+ }, getScene()->eventSceneUpdate);
}
bool_t VNTextboxScroller::hasRevealedAllCurrentCharacters() {
- // int32_t quadsTotal = 0;
- // for(
- // size_t i = this->lineCurrent;
- // i < mathMin(
- // this->label->measure.getLineCount(),
- // this->lineCurrent + this->getCountOfVisibleLines()
- // );
- // i++
- // ) {
- // quadsTotal += this->label->measure.getQuadsOnLine(i);
- // }
- // return mathFloor(this->timeCharacter) >= quadsTotal;
- assertUnreachable();
+ int32_t quadsTotal = 0;
+ for(
+ size_t i = this->lineCurrent;
+ i < mathMin(
+ this->label->lines.size(),
+ this->lineCurrent + this->visibleLines
+ );
+ i++
+ ) {
+ quadsTotal += this->label->lines[i].quadCount;
+ }
+ return mathFloor(this->timeCharacter) >= quadsTotal;
}
bool_t VNTextboxScroller::hasRevealedAllCharacters() {
- // return (
- // this->lineCurrent + this->getCountOfVisibleLines() >=
- // this->label->measure.getLineCount()
- // );
+ return (
+ this->lineCurrent + this->visibleLines >=
+ this->label->lines.size()
+ );
assertUnreachable();
}
\ No newline at end of file
diff --git a/src/dawn/games/vn/components/VNTextboxScroller.hpp b/src/dawn/games/vn/components/VNTextboxScroller.hpp
index d014bb2a..19562bd3 100644
--- a/src/dawn/games/vn/components/VNTextboxScroller.hpp
+++ b/src/dawn/games/vn/components/VNTextboxScroller.hpp
@@ -17,6 +17,9 @@ namespace Dawn {
// @optional
StateProperty label;
+ // @optional
+ StateProperty visibleLines;
+
StateEvent<> eventReadyToClose;
StateEvent<> eventCharacterRevealed;
@@ -28,14 +31,6 @@ namespace Dawn {
VNTextboxScroller(SceneItem *item);
virtual void onStart() override;
- /**
- * 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.
- */
- size_t getCountOfVisibleLines();
-
/**
* Returns true if all of the characters that can be made visible for the
* current textbox size have finished revealing, or false if not.
diff --git a/src/dawn/scene/components/ui/text/UILabel.cpp b/src/dawn/scene/components/ui/text/UILabel.cpp
index bb8f2577..f810dfaf 100644
--- a/src/dawn/scene/components/ui/text/UILabel.cpp
+++ b/src/dawn/scene/components/ui/text/UILabel.cpp
@@ -30,15 +30,19 @@ std::vector UILabel::getUIRenderPasses() {
auto canvas = this->getCanvas();
auto shader = getGame()->renderManager.fontShader;
+ glm::mat4 model = transform->getWorldTransform();
+ // Translate
+ model = glm::translate(model, glm::vec3(this->textOffset, 0.0f));
+
struct ShaderPassItem item;
item.shader = shader;
item.mesh = &this->mesh;
- item.matrixValues[shader->paramModel] = transform->getWorldTransform();
+ item.matrixValues[shader->paramModel] = model;
item.parameterBuffers[shader->bufferUiCanvas] = &canvas->shaderBuffer;
item.parameterBuffers[shader->bufferFont] = &this->shaderBuffer;
item.renderFlags = RENDER_MANAGER_RENDER_FLAG_BLEND;
- item.start = quadStart * QUAD_VERTICE_COUNT;
- item.count = quadCount == -1 ? -1 : quadCount * QUAD_VERTICE_COUNT;
+ item.start = quadStart * QUAD_INDICE_COUNT;
+ item.count = quadCount == -1 ? -1 : quadCount * QUAD_INDICE_COUNT;
// Map texture slots
auto it = textureMap.begin();
@@ -74,10 +78,22 @@ std::vector UILabel::getUIRenderPasses() {
}
float_t UILabel::getContentWidth() {
- return 1;
+ float_t w = 0;
+ auto it = lines.begin();
+ while(it != lines.end()) {
+ w = mathMax(w, it->width);
+ ++it;
+ }
+ return w;
}
float_t UILabel::getContentHeight() {
+ float_t h = 0;
+ auto it = lines.begin();
+ while(it != lines.end()) {
+ h += it->height;
+ ++it;
+ }
return 1;
}
@@ -103,6 +119,8 @@ void UILabel::rebufferQuads(const std::vector newTexts) {
// Prepare values shared across all text parts/styles
float_t lineWidth = 0;
struct UILabelLine currentLine;
+ currentLine.quadStart = quadCountTotal;
+ currentLine.position = position;
// Now generate quads
itText = newTexts.begin();
@@ -142,6 +160,8 @@ void UILabel::rebufferQuads(const std::vector newTexts) {
auto len = text.text.length();
float_t wordWidth = 0;
int32_t lastSpaceCharacter = -1;
+
+ currentLine.height = mathMax(currentLine.height, realText.style.size);
std::function fnInsertNewline = [&](int32_t i){
if(i != len) {
@@ -174,6 +194,12 @@ void UILabel::rebufferQuads(const std::vector newTexts) {
currentLine = UILabelLine();
currentLine.quadStart = quadCountTotal;
+ currentLine.position = position;
+ currentLine.height = realText.style.size;
+ // Here I subtract line height from the line position because we start
+ // by moving the text down by the initial line height, so we need to
+ // compensate for that.
+ currentLine.position.y -= realText.style.size;
};
// Now, iterate each character
@@ -303,4 +329,7 @@ void UILabel::rebufferQuads(const std::vector newTexts) {
// Update
textsBuffered = realNewTexts;
texts = newTexts;
+
+ // Event
+ this->eventTextChanged.invoke();
}
\ No newline at end of file
diff --git a/src/dawn/scene/components/ui/text/UILabel.hpp b/src/dawn/scene/components/ui/text/UILabel.hpp
index f36ef39c..c720e0eb 100644
--- a/src/dawn/scene/components/ui/text/UILabel.hpp
+++ b/src/dawn/scene/components/ui/text/UILabel.hpp
@@ -30,6 +30,8 @@ namespace Dawn {
struct UILabelLine {
float_t width = 0.0f;
+ float_t height = 0.0f;
+ glm::vec2 position;
int32_t quadStart = -1;
int32_t quadCount = 0;
};
@@ -45,9 +47,13 @@ namespace Dawn {
int32_t quadCount = -1;
int32_t quadCountTotal = -1;
+ glm::vec2 textOffset = glm::vec2(0.0f, 0.0f);
+
std::vector texts;
std::vector textsBuffered;
std::vector lines;
+
+ StateEvent<> eventTextChanged;
UILabel(SceneItem *item);