From bb2b0a2762b8cde66224fef8cad2afc1edd47657 Mon Sep 17 00:00:00 2001 From: maelstrom Date: Sat, 12 Jul 2025 20:52:57 +0200 Subject: [PATCH] feat(rendering): added messages and hints --- assets/icons/message.png | Bin 0 -> 413 bytes assets/shaders/generic2d.fs | 4 +-- core/src/objects/base/service.cpp | 2 +- core/src/objects/hint.cpp | 4 +++ core/src/objects/hint.h | 18 ++++++++++ core/src/objects/message.cpp | 5 +++ core/src/objects/message.h | 21 ++++++++++++ core/src/objects/meta.cpp | 4 +++ core/src/rendering/debug/debugrenderer.cpp | 18 ++-------- core/src/rendering/font.cpp | 18 ++++++++-- core/src/rendering/font.h | 4 ++- core/src/rendering/renderer.cpp | 38 +++++++++++++++++++-- 12 files changed, 112 insertions(+), 24 deletions(-) create mode 100644 assets/icons/message.png create mode 100644 core/src/objects/hint.cpp create mode 100644 core/src/objects/hint.h create mode 100644 core/src/objects/message.cpp create mode 100644 core/src/objects/message.h diff --git a/assets/icons/message.png b/assets/icons/message.png new file mode 100644 index 0000000000000000000000000000000000000000..7bc9233ea63c89d52a99494dd0f0735a29a3ec3b GIT binary patch literal 413 zcmV;O0b>4%P)i2vikyMR~)n*keF9=!Gc_n*K2@qsNT?}H4v4a974 z1ArVJApZ0B-@pGKzWw|E^3%Wn&p!V9|K$C@{}12&`+x7vzyG&i{r!LE6~yrB1;;^# zm?0Y=moxPMSn>r>N00000NkvXX Hu0mjf$^yWL literal 0 HcmV?d00001 diff --git a/assets/shaders/generic2d.fs b/assets/shaders/generic2d.fs index 00a5a26..a26820a 100644 --- a/assets/shaders/generic2d.fs +++ b/assets/shaders/generic2d.fs @@ -3,10 +3,10 @@ // I/O out vec4 fColor; -uniform vec3 aColor; +uniform vec4 aColor; // Main void main() { - fColor = vec4(aColor, 1.0); + fColor = aColor; } \ No newline at end of file diff --git a/core/src/objects/base/service.cpp b/core/src/objects/base/service.cpp index 3fd3474..54faaba 100644 --- a/core/src/objects/base/service.cpp +++ b/core/src/objects/base/service.cpp @@ -4,7 +4,7 @@ #include "panic.h" #include -Service::Service(const InstanceType* type) : Instance(type){} +Service::Service(const InstanceType* type) : Instance(type) {} // Fail if parented to non-datamodel, otherwise lock parent void Service::OnParentUpdated(std::optional> oldParent, std::optional> newParent) { diff --git a/core/src/objects/hint.cpp b/core/src/objects/hint.cpp new file mode 100644 index 0000000..fee3986 --- /dev/null +++ b/core/src/objects/hint.cpp @@ -0,0 +1,4 @@ +#include "hint.h" + +Hint::Hint(): Message(&TYPE) {} +Hint::~Hint() = default; \ No newline at end of file diff --git a/core/src/objects/hint.h b/core/src/objects/hint.h new file mode 100644 index 0000000..e1e09ed --- /dev/null +++ b/core/src/objects/hint.h @@ -0,0 +1,18 @@ +#pragma once + +#include "objects/annotation.h" +#include "objects/base/instance.h" +#include "objects/message.h" +#include + +// Dims the player's screen and displays some centered text +class DEF_INST_(explorer_icon="message") Hint : public Message { + AUTOGEN_PREAMBLE + +public: + Hint(); + ~Hint(); + + static inline std::shared_ptr New() { return std::make_shared(); }; + static inline std::shared_ptr Create() { return std::make_shared(); }; +}; \ No newline at end of file diff --git a/core/src/objects/message.cpp b/core/src/objects/message.cpp new file mode 100644 index 0000000..46bbe29 --- /dev/null +++ b/core/src/objects/message.cpp @@ -0,0 +1,5 @@ +#include "message.h" + +Message::Message(const InstanceType* type) : Instance(type) {} +Message::Message(): Instance(&TYPE) {} +Message::~Message() = default; \ No newline at end of file diff --git a/core/src/objects/message.h b/core/src/objects/message.h new file mode 100644 index 0000000..a27499e --- /dev/null +++ b/core/src/objects/message.h @@ -0,0 +1,21 @@ +#pragma once + +#include "objects/annotation.h" +#include "objects/base/instance.h" +#include + +// Dims the player's screen and displays some centered text +class DEF_INST_(explorer_icon="message") Message : public Instance { + AUTOGEN_PREAMBLE + +protected: + Message(const InstanceType* type); +public: + Message(); + ~Message(); + + DEF_PROP std::string text; + + static inline std::shared_ptr New() { return std::make_shared(); }; + static inline std::shared_ptr Create() { return std::make_shared(); }; +}; \ No newline at end of file diff --git a/core/src/objects/meta.cpp b/core/src/objects/meta.cpp index eec6931..704c0f2 100644 --- a/core/src/objects/meta.cpp +++ b/core/src/objects/meta.cpp @@ -1,9 +1,11 @@ #include "meta.h" #include "objects/folder.h" +#include "objects/hint.h" #include "objects/joint/jointinstance.h" #include "objects/joint/rotate.h" #include "objects/joint/rotatev.h" #include "objects/joint/weld.h" +#include "objects/message.h" #include "objects/service/jointsservice.h" #include "objects/model.h" #include "objects/part.h" @@ -27,6 +29,8 @@ std::map INSTANCE_MAP = { { "JointInstance", &JointInstance::TYPE }, { "Script", &Script::TYPE }, { "Model", &Model::TYPE }, + { "Message", &Message::TYPE }, + { "Hint", &Hint::TYPE }, // { "Folder", &Folder::TYPE }, // Services diff --git a/core/src/rendering/debug/debugrenderer.cpp b/core/src/rendering/debug/debugrenderer.cpp index 3da7764..0234eb7 100644 --- a/core/src/rendering/debug/debugrenderer.cpp +++ b/core/src/rendering/debug/debugrenderer.cpp @@ -11,6 +11,8 @@ extern Texture* debugFontTexture; extern Shader* debugFontShader; extern Shader* identityShader; +void drawRect(int x, int y, int width, int height, glm::vec4 color); + void drawChar(char c, int x, int y, float scale=1.f) { debugFontShader->use(); debugFontTexture->activate(1); @@ -41,22 +43,6 @@ void drawString(std::string str, int x, int y, float scale=1.f) { } } -void drawRect(int x, int y, int w, int h, glm::vec4 color) { - identityShader->use(); - identityShader->set("aColor", color); - - float x0 = 2*float(x)/viewportWidth-1, y0 = 2*float(y)/viewportHeight-1, x1 = 2*float(x + w)/viewportWidth-1, y1 = 2*float(y + h)/viewportHeight-1; - float tmp; - tmp = -y0, y0 = -y1, y1 = tmp; - - glBegin(GL_QUADS); - glVertex3f(x0, y0, 0); - glVertex3f(x1, y0, 0); - glVertex3f(x1, y1, 0); - glVertex3f(x0, y1, 0); - glEnd(); -} - static tu_time_t lastTime; extern tu_time_t renderTime; extern tu_time_t physTime; diff --git a/core/src/rendering/font.cpp b/core/src/rendering/font.cpp index e70fdc0..0161913 100644 --- a/core/src/rendering/font.cpp +++ b/core/src/rendering/font.cpp @@ -63,7 +63,8 @@ std::shared_ptr loadFont(std::string fontName) { std::shared_ptr font = std::make_shared(); - FT_Set_Pixel_Sizes(face, 0, 48); + FT_Set_Pixel_Sizes(face, 0, 16); + font->height = face->size->metrics.y_ppem; // Load each glyph glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -131,7 +132,7 @@ void drawText(std::shared_ptr font, std::string text, float x, float y, fl Character ch = font->characters[c]; float xpos = x + ch.bearing.x * scale; - float ypos = y - (ch.size.y - ch.bearing.y) * scale; + float ypos = viewportHeight - y - font->height - (ch.size.y - ch.bearing.y) * scale; float w = ch.size.x * scale; float h = ch.size.y * scale; @@ -159,4 +160,17 @@ void drawText(std::shared_ptr font, std::string text, float x, float y, fl x += (ch.advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64) } glBindTexture(GL_TEXTURE_2D, 0); +} + +float calcTextWidth(std::shared_ptr font, std::string text, float scale) { + float x = 0; + // iterate through all characters + for (size_t i = 0; i < text.size(); i++) { + unsigned char c = text[i]; + Character ch = font->characters[c]; + + x += (ch.advance >> 6) * scale; + } + + return x; } \ No newline at end of file diff --git a/core/src/rendering/font.h b/core/src/rendering/font.h index 4cd3709..2b732ca 100644 --- a/core/src/rendering/font.h +++ b/core/src/rendering/font.h @@ -14,10 +14,12 @@ struct Character { }; struct Font { + unsigned int height; Character characters[128]; }; void fontInit(); void fontFinish(); std::shared_ptr loadFont(std::string fontName); -void drawText(std::shared_ptr font, std::string text, float x, float y, float scale=1.f, glm::vec3 color = glm::vec3(1,1,1)); \ No newline at end of file +void drawText(std::shared_ptr font, std::string text, float x, float y, float scale=1.f, glm::vec3 color = glm::vec3(1,1,1)); +float calcTextWidth(std::shared_ptr font, std::string text, float scale = 1.f); \ No newline at end of file diff --git a/core/src/rendering/renderer.cpp b/core/src/rendering/renderer.cpp index fc2f802..d8e5c0b 100644 --- a/core/src/rendering/renderer.cpp +++ b/core/src/rendering/renderer.cpp @@ -20,6 +20,7 @@ #include "datatypes/vector.h" #include "handles.h" #include "math_helper.h" +#include "objects/hint.h" #include "objects/service/selection.h" #include "partassembly.h" #include "rendering/font.h" @@ -62,7 +63,8 @@ bool wireframeRendering = false; int viewportWidth, viewportHeight; void renderDebugInfo(); -void drawRect(int x, int y, int width, int height, glm::vec3 color); +void drawRect(int x, int y, int width, int height, glm::vec4 color); +inline void drawRect(int x, int y, int width, int height, glm::vec3 color) { return drawRect(x, y, width, height, glm::vec4(color, 1)); }; void renderInit(int width, int height) { viewportWidth = width, viewportHeight = height; @@ -649,6 +651,37 @@ void addDebugRenderCFrame(CFrame frame, Color3 color) { DEBUG_CFRAMES.push_back(std::make_pair(frame, color)); } +void renderMessages() { + glDisable(GL_DEPTH_TEST); + // glEnable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + // glEnable(GL_BLEND); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // Render hints + for (auto it = gWorkspace()->GetDescendantsStart(); it != gWorkspace()->GetDescendantsEnd(); it++) { + if (it->GetClass() != &Hint::TYPE) continue; + std::shared_ptr message = it->CastTo().expect(); + + drawRect(0, 0, viewportWidth, 20, glm::vec4(0,0,0,1)); + float textWidth = calcTextWidth(sansSerif, message->text); + drawText(sansSerif, message->text, (viewportWidth - textWidth) / 2, 0); + } + + // Render messages + for (auto it = gWorkspace()->GetDescendantsStart(); it != gWorkspace()->GetDescendantsEnd(); it++) { + if (it->GetClass() != &Message::TYPE) continue; + std::shared_ptr message = it->CastTo().expect(); + + // Don't draw if text is empty + if (message->text == "") continue; + + drawRect(0, 0, viewportWidth, viewportHeight, glm::vec4(0.5)); + float textWidth = calcTextWidth(sansSerif, message->text); + drawText(sansSerif, message->text, ((float)viewportWidth - textWidth) / 2, ((float)viewportHeight - sansSerif->height) / 2); + } +} + tu_time_t renderTime; void render() { tu_time_t startTime = tu_clock_micros(); @@ -668,13 +701,14 @@ void render() { renderWireframe(); if (debugRendererEnabled) renderDebugInfo(); + renderMessages(); // TODO: Make this a debug flag // renderAABB(); renderTime = tu_clock_micros() - startTime; } -void drawRect(int x, int y, int width, int height, glm::vec3 color) { +void drawRect(int x, int y, int width, int height, glm::vec4 color) { // GL_CULL_FACE has to be disabled as we are flipping the order of the vertices here, besides we don't really care about it glDisable(GL_CULL_FACE); glm::mat4 model(1.0f); // Same applies to this VV