diff --git a/CMakeLists.txt b/CMakeLists.txt index 454290c..b30c1ea 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,12 @@ set(PD_SOURCES source/lithium/font.cpp source/lithium/math.cpp source/lithium/pools.cpp + + # Ultra + source/ultra/canvas.cpp + source/ultra/layout.cpp + source/ultra/elems/rect.cpp + source/ultra/elems/text.cpp ) if(${PD_BUILD_SHARED}) diff --git a/include/pd/ultra/canvas.hpp b/include/pd/ultra/canvas.hpp new file mode 100644 index 0000000..30a2780 --- /dev/null +++ b/include/pd/ultra/canvas.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +using UltraAlignment = PD::u32; +enum UltraAlignment_ { + UltraAlignment_None = 0, + UltraAlignment_Top = 1 << 0, + UltraAlignment_Bot = 1 << 1, + UltraAlignment_Left = 1 << 2, + UltraAlignment_Right = 1 << 3, + UltraAlignment_TopLeft = UltraAlignment_Top | UltraAlignment_Left, + UltraAlignment_TopRight = UltraAlignment_Top | UltraAlignment_Right, + UltraAlignment_BotLeft = UltraAlignment_Bot | UltraAlignment_Left, + UltraAlignment_BotRight = UltraAlignment_Bot | UltraAlignment_Right, +}; + +namespace PD { +namespace Ultra { +class PD_API Canvas { + public: + Canvas(); + Canvas(const PD::fvec2& size); + ~Canvas(); + + void SetVirtualViewport(const PD::fvec2& size); + void SetViewport(const PD::fvec2& size); + + PD::fvec2 VTranslatePos(const PD::fvec2& p) const; + PD::fvec2 VTranslateAlignPos(const PD::fvec2& pos, const PD::fvec2& size, + UltraAlignment align) const; + PD::Li::Rect VTranslateObject(const PD::fvec2& pos, const PD::fvec2& size, + UltraAlignment align, bool size_modified = false) const; + PD::fvec2 TranslatePos(const PD::fvec2& p) const; + PD::fvec2 VTranslateSize(const PD::fvec2& s) const; + PD::fvec2 TranslateSize(const PD::fvec2& s) const; + float VTranslateFontscale(float f) const; + float TranslateFontscale(float f) const; + + private: + PD::fvec2 pViewport; + PD::fvec2 pVirtualViewPort; + float pVfactor = 0.f; + PD::fvec2 pVoff; +}; +} // namespace Ultra +} // namespace PD \ No newline at end of file diff --git a/include/pd/ultra/elems/element.hpp b/include/pd/ultra/elems/element.hpp new file mode 100644 index 0000000..29243bb --- /dev/null +++ b/include/pd/ultra/elems/element.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace PD { +namespace Ultra { +class ElementBase { + public: + ElementBase() {} + ~ElementBase() {} + + virtual void Draw(PD::Li::Drawlist& dl) = 0; + /** + * Reset Function (for PD::Pool::FastReset) + */ + virtual void Reset() {} + + private: +}; +} // namespace Ultra +} // namespace PD \ No newline at end of file diff --git a/include/pd/ultra/elems/rect.hpp b/include/pd/ultra/elems/rect.hpp new file mode 100644 index 0000000..dc94238 --- /dev/null +++ b/include/pd/ultra/elems/rect.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +namespace PD { +namespace Ultra { +class PD_API Rect : public ElementBase { + public: + Rect() {} + ~Rect() {} + + void Draw(PD::Li::Drawlist& l) override; + + void SetPosition(const PD::fvec2& pos) { pPos = pos; } + void SetPosition(float x, float y) { pPos = PD::fvec2(x, y); } + void SetSize(const PD::fvec2& size) { pSize = size; } + void SetSize(float w, float h) { pSize = PD::fvec2(w, h); } + void SetColor(const PD::Color& color) { pColor = color; } + void SetRounding(float r) { pRounding = r; } + + private: + PD::fvec2 pPos; + PD::fvec2 pSize; + PD::Color pColor; + float pRounding = 0.f; +}; +} // namespace Ultra + +} // namespace PD \ No newline at end of file diff --git a/include/pd/ultra/elems/text.hpp b/include/pd/ultra/elems/text.hpp new file mode 100644 index 0000000..abc1e30 --- /dev/null +++ b/include/pd/ultra/elems/text.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +namespace PD { +namespace Ultra { +class PD_API Text : public ElementBase { + public: + Text() {} + ~Text() {} + + void Draw(PD::Li::Drawlist& l) override; + + void SetPosition(const PD::fvec2& pos) { pPos = pos; } + void SetPosition(float x, float y) { pPos = PD::fvec2(x, y); } + void SetColor(const PD::Color& color) { pColor = color; } + void SetText(const std::string& text) { pText = text; } + + private: + PD::fvec2 pPos; + PD::Color pColor; + std::string pText; +}; +} // namespace Ultra + +} // namespace PD \ No newline at end of file diff --git a/include/pd/ultra/layout.hpp b/include/pd/ultra/layout.hpp new file mode 100644 index 0000000..5004eaa --- /dev/null +++ b/include/pd/ultra/layout.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +namespace PD { +namespace Ultra { +class PD_API Layout { + public: + Layout() {} + ~Layout() {} + + void Add(ElementBase& elem); + + void SetFont(PD::Li::Font& font); + + void Render(); + + const PD::Li::Drawlist& Data() const { return pList; } + Canvas& GetCanvas() { return pCanvas; } + const Canvas& GetCanvas() const { return pCanvas; } + + private: + Canvas pCanvas; + PD::Pool pElements; + PD::Li::Drawlist pList; +}; +} // namespace Ultra +} // namespace PD \ No newline at end of file diff --git a/source/ultra/canvas.cpp b/source/ultra/canvas.cpp new file mode 100644 index 0000000..aea5813 --- /dev/null +++ b/source/ultra/canvas.cpp @@ -0,0 +1,78 @@ +#include + +namespace PD { +namespace Ultra { +PD_API Canvas::Canvas() {} + +PD_API Canvas::Canvas(const PD::fvec2& size) : pViewport(size) {} + +PD_API Canvas::~Canvas() {} + +PD_API void Canvas::SetVirtualViewport(const PD::fvec2& size) { + pVirtualViewPort = size; + if (pVirtualViewPort.x && pVirtualViewPort.y) { + pVfactor = std::min(pViewport.x / pVirtualViewPort.x, + pViewport.y / pVirtualViewPort.y); + pVoff = (pViewport - (pVirtualViewPort * pVfactor)) * 0.5f; + } +} + +PD_API void Canvas::SetViewport(const PD::fvec2& size) { + pViewport = size; + SetVirtualViewport(pVirtualViewPort); // recalculate Vfactor +} + +PD_API PD::fvec2 Canvas::VTranslatePos(const PD::fvec2& p) const { + return p * pVfactor + pVoff; +} + +PD_API PD::fvec2 Canvas::TranslatePos(const PD::fvec2& p) const { + return p * pViewport; +} + +PD_API PD::fvec2 Canvas::VTranslateSize(const PD::fvec2& s) const { + return s * pVfactor; +} + +PD_API PD::fvec2 Canvas::TranslateSize(const PD::fvec2& s) const { + return s * pViewport.y; +} + +PD_API float Canvas::VTranslateFontscale(float f) const { return f * pVfactor; } + +PD_API float Canvas::TranslateFontscale(float f) const { + return f * pViewport.y; +} + +PD_API PD::Li::Rect Canvas::VTranslateObject(const PD::fvec2& pos, + const PD::fvec2& size, + UltraAlignment align, + bool size_modified) const { + PD::fvec2 nsize = size; + if (!size_modified) nsize *= pVfactor; + PD::fvec2 final; + if (align & UltraAlignment_Left) { + final.x = pos.x * pVfactor; + } else if (align & UltraAlignment_Right) { + final.x = pViewport.x - (pos.x * pVfactor) - nsize.x; + } else { + final.x = pVoff.x + (pos.x * pVfactor) - nsize.x * 0.5; + } + if (align & UltraAlignment_Top) { + final.y = pos.y * pVfactor; + } else if (align & UltraAlignment_Bot) { + final.y = pViewport.y - (pos.y * pVfactor) - nsize.y; + } else { + final.y = pVoff.y + (pos.y * pVfactor) - nsize.y * 0.5; + } + return PD::fvec4(final, final + nsize); +} + +PD_API PD::fvec2 Canvas::VTranslateAlignPos(const PD::fvec2& pos, + const PD::fvec2& size, + UltraAlignment align) const { + return VTranslateObject(pos, size, align).TopLeft(); +} + +} // namespace Ultra +} // namespace PD \ No newline at end of file diff --git a/source/ultra/elems/rect.cpp b/source/ultra/elems/rect.cpp new file mode 100644 index 0000000..12a7321 --- /dev/null +++ b/source/ultra/elems/rect.cpp @@ -0,0 +1,10 @@ +#include + +namespace PD { +namespace Ultra { +PD_API void Rect::Draw(PD::Li::Drawlist& l) { + l.PathRect(pPos, pPos + pSize, pRounding); + l.PathFill(pColor); +} +} // namespace Ultra +} // namespace PD \ No newline at end of file diff --git a/source/ultra/elems/text.cpp b/source/ultra/elems/text.cpp new file mode 100644 index 0000000..0b284af --- /dev/null +++ b/source/ultra/elems/text.cpp @@ -0,0 +1,9 @@ +#include + +namespace PD { +namespace Ultra { +PD_API void Text::Draw(PD::Li::Drawlist& l) { + l.DrawText(pPos, pText.c_str(), pColor); +} +} // namespace Ultra +} // namespace PD \ No newline at end of file diff --git a/source/ultra/layout.cpp b/source/ultra/layout.cpp new file mode 100644 index 0000000..c05894d --- /dev/null +++ b/source/ultra/layout.cpp @@ -0,0 +1,16 @@ +#include + +namespace PD { +namespace Ultra { +PD_API void Layout::Add(ElementBase& elem) { *pElements.Allocate() = &elem; } + +PD_API void Layout::SetFont(PD::Li::Font& font) { pList.SetFont(&font); } + +PD_API void Layout::Render() { + pList.Clear(); + for (auto& it : pElements) { + it->Draw(pList); + } +} +} // namespace Ultra +} // namespace PD \ No newline at end of file diff --git a/tests/gfx/source/main.cpp b/tests/gfx/source/main.cpp index 55b548a..f540640 100644 --- a/tests/gfx/source/main.cpp +++ b/tests/gfx/source/main.cpp @@ -3,6 +3,12 @@ #include #include +//// +#include +#include +#include +//// + PD::OsCtx* pOs = nullptr; const char* ResourcePath(const char* in) { @@ -15,6 +21,20 @@ const char* ResourcePath(const char* in) { #endif } +void DrawTextHaxxed(const char* text, PD::Li::Font& font, PD::Li::Drawlist& l, + const PD::Ultra::Canvas& c, const PD::fvec2& pos, + const PD::Color& color, UltraAlignment align) { + PD::fvec2 bounds = font.GetTextBounds(text, l.GetFontScale()); + PD::Li::Rect _b = c.VTranslateObject(pos, bounds, align, true); + l.UnbindTexture(); + l.PathRect(_b.TopLeft(), _b.BotRight()); + l.PathFill(0x30ff00ff); + l.PathRect(_b.TopLeft(), _b.BotRight()); + l.PathStroke(0xffff00ff, 1, LiDrawFlags_Close); + l.DrawText(c.VTranslateObject(pos, bounds, align, true).TopLeft(), text, + color); +} + int main(int argc, char** argv) { // PD::LogFilter(PD::LogLevel::Warning); Driver drv = Driver::OpenGL3; @@ -40,32 +60,55 @@ int main(int argc, char** argv) { PD::Image img(ResourcePath("icon.png")); auto pTex = PD::Gfx::LoadTexture(img, img.Width(), img.Height()); PD::Li::Font font; - font.LoadTTF(ResourcePath("default.ttf")); + font.LoadTTF(ResourcePath("default.ttf"), 64); pList.SetFont(&font); + PD::Ultra::Layout lyt; + lyt.GetCanvas().SetVirtualViewport(PD::fvec2(400, 240)); + lyt.SetFont(font); + PD::Ultra::Rect rr; + PD::Ultra::Text txt; + rr.SetPosition(12, 20); + rr.SetSize(90, 60); + rr.SetColor(PD::Color("#ff00ff")); + lyt.Add(rr); + txt.SetPosition(0); + txt.SetColor(0xffffffff); + txt.SetText("const std::string &text"); + lyt.Add(txt); while (pOs->Mainloop()) { + lyt.GetCanvas().SetViewport(pOs->GetViewport()); pOs->ClearViewPort(); PD::Li::ResetPools(); - pList.SetFontscale(pOs->SizeTranslate(PD::fvec2(0.0017)).x); - pList.PathRect(pOs->PositionTranslate(0.05), pOs->PositionTranslate(0.4f), - 10.f); + pList.SetFontscale(lyt.GetCanvas().VTranslateFontscale(0.7f)); + lyt.Render(); + /*auto t = lyt.GetCanvas().VTranslateObject( + PD::fvec2(5, 30), PD::fvec2(170, 110), UltraAlignment_TopLeft); + auto icnpos = lyt.GetCanvas().VTranslateObject( + PD::fvec2(5, 5), PD::fvec2(60), UltraAlignment_TopRight); + pList.PathRect(t.TopLeft(), t.BotRight(), + lyt.GetCanvas().VTranslateSize(10).x); pList.PathFill(0xff00ffff); pList.BindTexture(pTex); - pList.DrawRectFilled(pOs->PositionTranslate(PD::fvec2(0.02f, 0.5f)), - pOs->SizeTranslate(PD::fvec2(0.3)), 0xffffffff); - pList.DrawText(5, "Hello World!", 0xff0000ff); - pList.DrawText( - pOs->PositionTranslate(PD::fvec2(0.005, 0.9)), - std::format("VIDC: [{}, {}, {}, {}]\nGfxDriver: {}", - PD::Gfx::GetNumVertices(), PD::Gfx::GetNumIndices(), - PD::Gfx::GetNumDrawcalls(), PD::Gfx::GetNumCommands(), - PD::Gfx::GetDriverName()) + pList.PathRect(icnpos.TopLeft(), icnpos.BotRight()); + pList.PathFill(0xffffffff); + DrawTextHaxxed("Hello World!", font, pList, lyt.GetCanvas(), + PD::fvec2(5, 5), 0xff0000ff, UltraAlignment_TopLeft);*/ + DrawTextHaxxed( + std::format( + "Font Scale: {}\nVP: [{}]\nVIDC: [{}, {}, {}, {}]\nGfxDriver: {}", + pList.GetFontScale(), pOs->GetViewport(), PD::Gfx::GetNumVertices(), + PD::Gfx::GetNumIndices(), PD::Gfx::GetNumDrawcalls(), + PD::Gfx::GetNumCommands(), PD::Gfx::GetDriverName()) .c_str(), - PD::Color("#ffffff")); + font, pList, lyt.GetCanvas(), PD::fvec2(5, 5), 0xffffffff, + UltraAlignment_BotLeft); PD::Gfx::Reset(); PD::Gfx::Draw(pList); + PD::Gfx::Draw(lyt.Data()); pList.Clear(); pOs->SwapBuffers(); } + font.Delete(); PD::Gfx::DeleteTexture(pTex); PD::Gfx::Deinit(); pOs->Deinit();