6 Commits

Author SHA1 Message Date
3823f08bab Update Font System
- Add support for splitting glyphs over multiple textures
- Fix some casts in wrong places (like casting a float to float?)
- Add a break if stb truetype fails
- Fix a typo in FontRenderer Shaddow part (used .x twice)
- Use L' ' for the wstring chars

- TODO: Fix the space of tabs / space chars (currently hardcoded)

- WARNING
  - Spaces are broken (idk why)
2025-08-28 21:06:19 +02:00
decae031ae Small Fix
- Make target compile definitions private (cause its only for them

this fixes errors when using in projects that have c source files
2025-08-23 20:02:33 +02:00
da87c0f7c2 # Hotfix
- 3ds backend
   -probably i forgot to apply the changes of moving Gfx backends to the PD namespace to the 3ds backend :/
2025-08-15 22:14:33 +02:00
310b44caf5 # Changes -> 0.5.1
- 3ds
  - Remove Gfx values that are present in Backend Tamplate
  - Move to default Palladium Namespace
  - Set the Input Flags
- Desktop
  - Move to PD Namespace
  - Comment out old keyboard stuff
  - HidDriver needs a rewrite but is functional enough
- Core
  - Add u128 class (only used in input driver so far
- Drivers (Core)
  - Move Gfx to PD namespace
  - Move Vertex/Index Pos and Projection Mtx to Gfx template
  - Add Keyboard support with u128 to Hid
  - Add a Update func if no hiddriver is specified (to prevent crashes when requestign inputs)
- Image
   - Add RGBA -> BGRA support (used in windows bitmaps iirc)
- Lithium
  - Add Vertex/Index counters to drawlist
  - Add a LoadTTF from Mem func and let the loadfile func use PD::IO::LoadFile2Mem (looks cleaner)
  - Add LoadDefaultFont (which loads one of the integrated fonts if the PD_LI_INCLUDE_FONTS flag was passed on palaldium build) !!! Note that there are no fonts integrated yet due to i dont know how to handle licensing...
- UI7
  - Add MouseLeft support to Input handler
  - Use xy coords of the Viewport to create Menus inside it
  - Get num of Vertices/Indices out of FinalDrawList
  - Add some Palladium Info to metrics Menu
  - Readd Compiler string
- pdfm
  - New tool that creates fonts.cpp/fonts.hpp
2025-08-14 20:37:55 +02:00
87910b57de # Changes
3ds Backend:
  - switch to shaderProgramUse
Desktop Backend
  - Add Pre Alpha Text Input and Keyboard Support
  - Move Shader Attrib Setup into a function and callit every time we need a set up vbo
  - Move to Mat4 api
Core:
  - Add fquat support
  - Add LoadFile2Str
  - Move Mat4 Lib from Project     n73 to Palladium
  - Add full supprot for vec cross types
  - Add Normalize, Distance and Dot to all
  - Add Cross to vec3
Drivers:
  - Add a SetViewPort func to GFX
  - Add Keyboard keys and Flasg to Hid
Image:
  - Add Vertical Flipping
  - Add Horizontal flipping
UI7:
  - Fix Critical Bug in IO Viewport handler
  - Fix library list (error on MinGW for some reason)
Lazyvec:
  - Split into multiple source files
  - Generate new functions (see core updates)
2025-07-23 23:21:34 +02:00
31a0c3656f # Changes
- Remove () from vec formatter
 -Add Merge function to DrawList to Move Data into the Current DrawList
- Fix stupid bug in Rect.hpp which caused some problems in line rendering
- Remove some unused UI7 Flags
- io: Allocate FinalDrawList and add GetViewPort func
- Readd TreeNodes to Menu
- Add ABout/Style and Metrics Menu to Context
- Add some Variables for cliprects in ui7 container.hpp
- Add InputHandler functionality to DynObj
- Fix Menu Layout Render Order
- Add Better Menu Sorting to Context
# ppam
- Use stringview instead of hardcoded const char*
# Todos
- Work on the Lithium 3D System
- Fix UI7 Menu Order to Pop new Menus into the front instead of the background
- Add Scrolling support to menu (or integrate it into layout maybe)
2025-07-01 21:43:35 +02:00
68 changed files with 2314 additions and 522 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
build/ build/
.cache .cache
.vscode

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.22) cmake_minimum_required(VERSION 3.22)
# Set Project # Set Project
project(palladium LANGUAGES C CXX VERSION 0.5.0) project(palladium LANGUAGES C CXX VERSION 0.5.1)
# Required to add this Variable # Required to add this Variable
set(PD_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) set(PD_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)

View File

@ -40,8 +40,6 @@ class LinearAlloc : public Allocator<T> {
T* Allocate(size_t n) override { return (T*)linearAlloc(n * sizeof(T)); } T* Allocate(size_t n) override { return (T*)linearAlloc(n * sizeof(T)); }
void Deallocate(T* ptr) { linearFree(ptr); } void Deallocate(T* ptr) { linearFree(ptr); }
}; };
namespace Li {
class GfxC3D : public GfxDriver { class GfxC3D : public GfxDriver {
public: public:
GfxC3D() : GfxDriver("Citro3D") {} GfxC3D() : GfxDriver("Citro3D") {}
@ -61,18 +59,11 @@ class GfxC3D : public GfxDriver {
PD::Li::Texture::Filter filter = PD::Li::Texture::Filter filter =
PD::Li::Texture::Filter::LINEAR) override; PD::Li::Texture::Filter::LINEAR) override;
Vec<Vertex, LinearAlloc<Vertex>> VertexBuffer; Vec<Li::Vertex, LinearAlloc<Li::Vertex>> VertexBuffer;
Vec<u16, LinearAlloc<u16>> IndexBuffer; Vec<u16, LinearAlloc<u16>> IndexBuffer;
size_t CurrentVertex = 0;
size_t CurrentIndex = 0;
Mat4 Projection;
int pLocProjection = 0; int pLocProjection = 0;
DVLB_s* ShaderCode; DVLB_s* ShaderCode;
shaderProgram_s Shader; shaderProgram_s Shader;
C3D_AttrInfo ShaderInfo; C3D_AttrInfo ShaderInfo;
// Stats oder so IDNK zu lange her
PD::u32 NumVtx;
PD::u32 NumIdx;
}; };
} // namespace Li
} // namespace PD } // namespace PD

View File

@ -25,6 +25,9 @@ SOFTWARE.
#include <pd-3ds/bknd-gfx.hpp> #include <pd-3ds/bknd-gfx.hpp>
/// @brief Shader Code (Unused as i dont want to use libpicasso here (yet)) /// @brief Shader Code (Unused as i dont want to use libpicasso here (yet))
/// Update: Picasso breaks the linearRam or ram for somereason
/// as far as i found out loading anything into linear ram after
/// using libpicasso to compile a shader leads into a system freeze
const char* LIShaderCTR = R"( const char* LIShaderCTR = R"(
; LI7 Shader ; LI7 Shader
; Constants ; Constants
@ -70,22 +73,21 @@ unsigned char li_shader[] = {
size_t li_shader_size = 0x124; size_t li_shader_size = 0x124;
namespace PD { namespace PD {
namespace Li { GPU_TEXCOLOR GetTexFmt(Li::Texture::Type type) {
GPU_TEXCOLOR GetTexFmt(Texture::Type type) { if (type == Li::Texture::RGBA32)
if (type == Texture::RGBA32)
return GPU_RGBA8; return GPU_RGBA8;
else if (type == Texture::RGB24) else if (type == Li::Texture::RGB24)
return GPU_RGB8; return GPU_RGB8;
else if (type == Texture::A8) else if (type == Li::Texture::A8)
return GPU_A8; return GPU_A8;
return GPU_RGBA8; // Default return GPU_RGBA8; // Default
} }
int GetBPP(Texture::Type type) { int GetBPP(Li::Texture::Type type) {
if (type == Texture::RGBA32) if (type == Li::Texture::RGBA32)
return 4; return 4;
else if (type == Texture::RGB24) else if (type == Li::Texture::RGB24)
return 3; return 3;
else if (type == Texture::A8) else if (type == Li::Texture::A8)
return 1; return 1;
return 0; // Error return 0; // Error
} }
@ -119,10 +121,9 @@ void GfxC3D::NewFrame() {
CurrentIndex = 0; CurrentIndex = 0;
CurrentVertex = 0; CurrentVertex = 0;
FrameCounter++; FrameCounter++;
VertexCounter = NumVtx; /** Probably completly incorrect but just do it like that */
IndexCounter = NumIdx; VertexCounter = CurrentVertex;
NumVtx = 0; IndexCounter = CurrentIndex;
NumIdx = 0;
} }
void GfxC3D::BindTex(PD::Li::TexAddress addr) { void GfxC3D::BindTex(PD::Li::TexAddress addr) {
@ -130,11 +131,14 @@ void GfxC3D::BindTex(PD::Li::TexAddress addr) {
} }
void GfxC3D::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) { void GfxC3D::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) {
C3D_BindProgram(&Shader); // C3D_BindProgram(&Shader);
shaderProgramUse(&Shader);
C3D_SetAttrInfo(&ShaderInfo); C3D_SetAttrInfo(&ShaderInfo);
C3D_Mtx proj; C3D_Mtx proj;
Mtx_OrthoTilt(&proj, 0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f, false); Mtx_OrthoTilt(&proj, 0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f, false);
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, pLocProjection, &proj); C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, pLocProjection, &proj);
// Mat4 proj = Mat4::Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f);
// C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, pLocProjection, (C3D_Mtx*)&proj);
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL); C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL);
C3D_TexEnv* env = C3D_GetTexEnv(0); C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvInit(env); C3D_TexEnvInit(env);
@ -156,11 +160,9 @@ void GfxC3D::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) {
Commands[index]->ScissorRect == ScissorRect) { Commands[index]->ScissorRect == ScissorRect) {
auto c = Commands[index].get(); auto c = Commands[index].get();
for (size_t i = 0; i < c->IndexBuffer.Size(); i++) { for (size_t i = 0; i < c->IndexBuffer.Size(); i++) {
NumIdx++;
IndexBuffer[CurrentIndex++] = CurrentVertex + c->IndexBuffer.At(i); IndexBuffer[CurrentIndex++] = CurrentVertex + c->IndexBuffer.At(i);
} }
for (size_t i = 0; i < c->VertexBuffer.Size(); i++) { for (size_t i = 0; i < c->VertexBuffer.Size(); i++) {
NumVtx++;
VertexBuffer[CurrentVertex++] = c->VertexBuffer.At(i); VertexBuffer[CurrentVertex++] = c->VertexBuffer.At(i);
} }
index++; index++;
@ -177,7 +179,7 @@ void GfxC3D::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) {
BindTex(Tex->Address); BindTex(Tex->Address);
auto bufInfo = C3D_GetBufInfo(); auto bufInfo = C3D_GetBufInfo();
BufInfo_Init(bufInfo); BufInfo_Init(bufInfo);
BufInfo_Add(bufInfo, VertexBuffer.Data(), sizeof(Vertex), 3, 0x210); BufInfo_Add(bufInfo, VertexBuffer.Data(), sizeof(Li::Vertex), 3, 0x210);
C3D_DrawElements(GPU_TRIANGLES, CurrentIndex - StartIndex, C3D_DrawElements(GPU_TRIANGLES, CurrentIndex - StartIndex,
C3D_UNSIGNED_SHORT, IndexBuffer.Data() + StartIndex); C3D_UNSIGNED_SHORT, IndexBuffer.Data() + StartIndex);
@ -208,7 +210,7 @@ PD::Li::Texture::Ref GfxC3D::LoadTex(const std::vector<PD::u8>& pixels, int w,
1.0 - ((float)h / (float)tex_size.y)); 1.0 - ((float)h / (float)tex_size.y));
// Texture Setup // Texture Setup
auto fltr = (filter == Texture::NEAREST ? GPU_NEAREST : GPU_LINEAR); auto fltr = (filter == Li::Texture::NEAREST ? GPU_NEAREST : GPU_LINEAR);
auto tex_fmt = GetTexFmt(type); auto tex_fmt = GetTexFmt(type);
auto tex = new C3D_Tex; auto tex = new C3D_Tex;
C3D_TexInit(tex, (u16)tex_size.x, (u16)tex_size.y, tex_fmt); C3D_TexInit(tex, (u16)tex_size.x, (u16)tex_size.y, tex_fmt);
@ -240,11 +242,10 @@ PD::Li::Texture::Ref GfxC3D::LoadTex(const std::vector<PD::u8>& pixels, int w,
tex->border = 0x00000000; tex->border = 0x00000000;
C3D_TexSetWrap(tex, GPU_REPEAT, GPU_REPEAT); C3D_TexSetWrap(tex, GPU_REPEAT, GPU_REPEAT);
res->Address = (TexAddress)tex; res->Address = (Li::TexAddress)tex;
std::cout << std::format("Tex {:#08x} Addr {:#08X}", (TexAddress)res.get(), std::cout << std::format("Tex {:#08x} Addr {:#08X}",
res->Address) (Li::TexAddress)res.get(), res->Address)
<< std::endl; << std::endl;
return res; return res;
} }
} // namespace Li
} // namespace PD } // namespace PD

View File

@ -28,6 +28,8 @@ SOFTWARE.
namespace PD { namespace PD {
Hid3DS::Hid3DS() : HidDriver("Hid3DS") { Hid3DS::Hid3DS() : HidDriver("Hid3DS") {
this->Flags |= Flags_HasTouch;
this->Flags |= FLags_HasGamepad;
pBinds[KEY_A] = A; pBinds[KEY_A] = A;
pBinds[KEY_B] = B; pBinds[KEY_B] = B;
pBinds[KEY_X] = X; pBinds[KEY_X] = X;

View File

@ -30,7 +30,7 @@ void Init(void* data) {
// Dekstop Init Stage // Dekstop Init Stage
// First use default OS Driver // First use default OS Driver
PD::OS::Init(); PD::OS::Init();
PD::Li::Gfx::Init(PD::Li::GfxC3D::New()); PD::Gfx::Init(PD::GfxC3D::New());
PD::Hid::Init(PD::Hid3DS::New()); PD::Hid::Init(PD::Hid3DS::New());
} }
} // namespace PD } // namespace PD

View File

@ -33,7 +33,6 @@ SOFTWARE.
#include <pd/lithium/lithium.hpp> #include <pd/lithium/lithium.hpp>
namespace PD { namespace PD {
namespace Li {
class GfxGL2 : public GfxDriver { class GfxGL2 : public GfxDriver {
public: public:
GfxGL2() : GfxDriver("OpenGL2") {} GfxGL2() : GfxDriver("OpenGL2") {}
@ -53,18 +52,11 @@ class GfxGL2 : public GfxDriver {
PD::Li::Texture::Filter filter = PD::Li::Texture::Filter filter =
PD::Li::Texture::Filter::LINEAR) override; PD::Li::Texture::Filter::LINEAR) override;
PD::Vec<Vertex> VertexBuffer; PD::Vec<Li::Vertex> VertexBuffer;
PD::Vec<PD::u16> IndexBuffer; PD::Vec<PD::u16> IndexBuffer;
size_t CurrentVertex = 0;
size_t CurrentIndex = 0;
GLuint Shader; GLuint Shader;
GLuint pLocProjection; GLuint pLocProjection;
GLuint pLocTex; GLuint pLocTex;
Mat4 Projection;
GLuint VBO, IBO; GLuint VBO, IBO;
// Stats oder so IDNK zu lange her
PD::u32 NumVtx;
PD::u32 NumIdx;
}; };
} // namespace Li
} // namespace PD } // namespace PD

View File

@ -37,9 +37,36 @@ class HidGLFW : public HidDriver {
PD_SHARED(HidGLFW); PD_SHARED(HidGLFW);
void Update() override; void Update() override;
void GetInputStr(std::string& str) override;
void HandleTextOps();
bool pTimedHeld(KbKey k) {
if (pTimings.count(k)) {
if (IsEvent(Event_Up, k)) {
pTimings.erase(k);
return false;
}
return (PD::OS::GetTime() - pTimings[k]) > 50;
}
if (!IsEvent(Event_Held, k)) {
if (pTimings.count(k)) {
pTimings.erase(k);
return false;
}
}
if (IsEvent(Event_Held, k)) {
pTimings[k] = PD::OS::GetTime();
return true;
}
return false;
}
/** Data section */ /** Data section */
GLFWwindow* Window; GLFWwindow* Window;
int PrevState; int PrevState;
std::unordered_map<int, int> PrevStates;
static std::string* pText;
bool pInTextMode = false;
PD::u64 pLastUpdate = 0;
std::unordered_map<KbKey, u64> pTimings;
}; };
} // namespace PD } // namespace PD

View File

@ -25,7 +25,6 @@ SOFTWARE.
#include <pd-desktop/bknd-gfx.hpp> #include <pd-desktop/bknd-gfx.hpp>
namespace PD { namespace PD {
namespace Li {
const char* vertex_shader = R"( const char* vertex_shader = R"(
#version 120 #version 120
@ -36,7 +35,7 @@ const char* vertex_shader = R"(
varying vec2 oUV; varying vec2 oUV;
varying vec4 oColor; varying vec4 oColor;
// Probably forgot about this matric and // Probably forgot about this matrix and
// searched hours for why the rendering isn't working :/ // searched hours for why the rendering isn't working :/
uniform mat4 projection; uniform mat4 projection;
@ -103,17 +102,7 @@ GLuint createShaderProgram(const std::string& vertexShaderSource,
return shaderProgram; return shaderProgram;
} }
/** Actual Backend */ void SetupShaderAttribs(GLuint Shader) {
void GfxGL2::Init() {
VertexBuffer.Resize(4 * 8192);
IndexBuffer.Resize(6 * 8192);
Shader = createShaderProgram(vertex_shader, frag_shader);
glUseProgram(Shader);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
GLint _pos = glGetAttribLocation(Shader, "pos"); GLint _pos = glGetAttribLocation(Shader, "pos");
GLint _uv = glGetAttribLocation(Shader, "uv"); GLint _uv = glGetAttribLocation(Shader, "uv");
GLint _color = glGetAttribLocation(Shader, "color"); GLint _color = glGetAttribLocation(Shader, "color");
@ -129,6 +118,21 @@ void GfxGL2::Init() {
sizeof(PD::Li::Vertex), sizeof(PD::Li::Vertex),
(void*)offsetof(PD::Li::Vertex, Color)); (void*)offsetof(PD::Li::Vertex, Color));
glEnableVertexAttribArray(_color); glEnableVertexAttribArray(_color);
}
/** Actual Backend */
void GfxGL2::Init() {
VertexBuffer.Resize(4 * 8192);
IndexBuffer.Resize(6 * 8192);
Shader = createShaderProgram(vertex_shader, frag_shader);
glUseProgram(Shader);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// Attribs Setup
SetupShaderAttribs(Shader);
glGenBuffers(1, &IBO); glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
@ -146,20 +150,21 @@ void GfxGL2::Deinit() {
} }
void GfxGL2::NewFrame() { void GfxGL2::NewFrame() {
/*
glViewport(0, 0, ViewPort.x, ViewPort.y); glViewport(0, 0, ViewPort.x, ViewPort.y);
glClearColor(ClearColor.x, ClearColor.y, ClearColor.z, ClearColor.w); glClearColor(ClearColor.x, ClearColor.y, ClearColor.z, ClearColor.w);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
Projection.Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, -1.f, 1.f); */
glUniformMatrix4fv(pLocProjection, 1, GL_TRUE, Projection.m); Projection = Mat4::Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, -1.f, 1.f);
glUseProgram(Shader);
glUniformMatrix4fv(pLocProjection, 1, GL_FALSE, Projection.m.data());
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
CurrentIndex = 0;
CurrentVertex = 0;
FrameCounter++; FrameCounter++;
VertexCounter = NumVtx; VertexCounter = CurrentVertex;
IndexCounter = NumIdx; IndexCounter = CurrentIndex;
NumVtx = 0; CurrentVertex = 0;
NumIdx = 0; CurrentIndex = 0;
} }
void GfxGL2::BindTex(PD::Li::TexAddress addr) { void GfxGL2::BindTex(PD::Li::TexAddress addr) {
@ -170,7 +175,6 @@ void GfxGL2::BindTex(PD::Li::TexAddress addr) {
} }
void GfxGL2::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) { void GfxGL2::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) {
glUseProgram(Shader);
size_t index = 0; size_t index = 0;
while (index < Commands.size()) { while (index < Commands.size()) {
PD::Li::Texture::Ref Tex = Commands[index]->Tex; PD::Li::Texture::Ref Tex = Commands[index]->Tex;
@ -187,11 +191,9 @@ void GfxGL2::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) {
Commands[index]->ScissorRect == ScissorRect) { Commands[index]->ScissorRect == ScissorRect) {
auto c = Commands[index].get(); auto c = Commands[index].get();
for (size_t i = 0; i < c->IndexBuffer.Size(); i++) { for (size_t i = 0; i < c->IndexBuffer.Size(); i++) {
NumIdx++;
IndexBuffer[CurrentIndex++] = CurrentVertex + c->IndexBuffer.At(i); IndexBuffer[CurrentIndex++] = CurrentVertex + c->IndexBuffer.At(i);
} }
for (size_t i = 0; i < c->VertexBuffer.Size(); i++) { for (size_t i = 0; i < c->VertexBuffer.Size(); i++) {
NumVtx++;
VertexBuffer[CurrentVertex++] = c->VertexBuffer.At(i); VertexBuffer[CurrentVertex++] = c->VertexBuffer.At(i);
} }
index++; index++;
@ -207,6 +209,9 @@ void GfxGL2::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) {
glBindBuffer(GL_ARRAY_BUFFER, VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, CurrentVertex * sizeof(PD::Li::Vertex), glBufferData(GL_ARRAY_BUFFER, CurrentVertex * sizeof(PD::Li::Vertex),
&VertexBuffer[0], GL_DYNAMIC_DRAW); &VertexBuffer[0], GL_DYNAMIC_DRAW);
// For some reason we need to set these every frame for every buffer
// Found that out when creating My 3d Engine
SetupShaderAttribs(Shader);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, CurrentIndex * sizeof(PD::u16), glBufferData(GL_ELEMENT_ARRAY_BUFFER, CurrentIndex * sizeof(PD::u16),
@ -248,5 +253,4 @@ PD::Li::Texture::Ref GfxGL2::LoadTex(const std::vector<PD::u8>& pixels, int w,
auto res = PD::Li::Texture::New(texID, PD::ivec2(w, h)); auto res = PD::Li::Texture::New(texID, PD::ivec2(w, h));
return res; return res;
} }
} // namespace Li
} // namespace PD } // namespace PD

View File

@ -23,19 +23,104 @@ SOFTWARE.
*/ */
#include <pd-desktop/bknd-hid.hpp> #include <pd-desktop/bknd-hid.hpp>
namespace PD { namespace PD {
std::string* HidGLFW::pText;
// Default Call back (If no Text input is requsted)
void NullTextCB(GLFWwindow* win, unsigned int c) {}
// Text callback if requested
void TextCB(GLFWwindow* win, unsigned int c) {
if (!HidGLFW::pText) {
return;
}
*HidGLFW::pText += (char)c;
}
HidGLFW::HidGLFW(GLFWwindow* win) : HidDriver("HidGLFW") { HidGLFW::HidGLFW(GLFWwindow* win) : HidDriver("HidGLFW") {
Window = win; Window = win;
glfwSetCharCallback(Window, NullTextCB);
Flags |= Flags_HasKeyboard;
Flags |= Flags_HasMouse;
pBinds[GLFW_MOUSE_BUTTON_LEFT] = Touch; pBinds[GLFW_MOUSE_BUTTON_LEFT] = Touch;
/*pBinds[GLFW_KEY_F3] = Kb_3;
pBinds[GLFW_KEY_ESCAPE] = Kb_Escape;
pBinds[GLFW_KEY_F11] = Kb_F11;
pBinds[GLFW_KEY_ESCAPE] = Kb_Escape;
pBinds[GLFW_KEY_Q] = Kb_Q;
pBinds[GLFW_KEY_W] = Kb_W;
pBinds[GLFW_KEY_E] = Kb_E;
pBinds[GLFW_KEY_R] = Kb_R;
pBinds[GLFW_KEY_T] = Kb_T;
pBinds[GLFW_KEY_Z] = Kb_Z;
pBinds[GLFW_KEY_U] = Kb_U;
pBinds[GLFW_KEY_I] = Kb_I;
pBinds[GLFW_KEY_O] = Kb_O;
pBinds[GLFW_KEY_P] = Kb_P;
pBinds[GLFW_KEY_A] = Kb_A;
pBinds[GLFW_KEY_S] = Kb_S;
pBinds[GLFW_KEY_D] = Kb_D;
pBinds[GLFW_KEY_F] = Kb_F;
pBinds[GLFW_KEY_G] = Kb_G;
pBinds[GLFW_KEY_H] = Kb_H;
pBinds[GLFW_KEY_J] = Kb_J;
pBinds[GLFW_KEY_K] = Kb_K;
pBinds[GLFW_KEY_L] = Kb_L;
pBinds[GLFW_KEY_Y] = Kb_Y;
pBinds[GLFW_KEY_X] = Kb_X;
pBinds[GLFW_KEY_C] = Kb_C;
pBinds[GLFW_KEY_V] = Kb_V;
pBinds[GLFW_KEY_B] = Kb_B;
pBinds[GLFW_KEY_N] = Kb_N;
pBinds[GLFW_KEY_M] = Kb_M;
pBinds[GLFW_KEY_LEFT_SHIFT] = Kb_LShift;
pBinds[GLFW_KEY_F1] = Kb_F1;
pBinds[GLFW_KEY_F2] = Kb_F2;
pBinds[GLFW_KEY_F3] = Kb_F3;
pBinds[GLFW_KEY_F4] = Kb_F4;
pBinds[GLFW_KEY_F5] = Kb_F5;
pBinds[GLFW_KEY_F6] = Kb_F6;
pBinds[GLFW_KEY_F7] = Kb_F7;
pBinds[GLFW_KEY_F8] = Kb_F8;
pBinds[GLFW_KEY_F9] = Kb_F9;
pBinds[GLFW_KEY_F10] = Kb_F10;
pBinds[GLFW_KEY_F11] = Kb_F11;
pBinds[GLFW_KEY_F12] = Kb_F12;
pBinds[GLFW_KEY_1] = Kb_1;
pBinds[GLFW_KEY_2] = Kb_2;
pBinds[GLFW_KEY_3] = Kb_3;
pBinds[GLFW_KEY_4] = Kb_4;
pBinds[GLFW_KEY_5] = Kb_5;
pBinds[GLFW_KEY_6] = Kb_6;
pBinds[GLFW_KEY_7] = Kb_7;
pBinds[GLFW_KEY_8] = Kb_8;
pBinds[GLFW_KEY_9] = Kb_9;
pBinds[GLFW_KEY_0] = Kb_0;
pBinds[GLFW_KEY_BACKSPACE] = Kb_Backspace;
pBinds[GLFW_KEY_ENTER] = Kb_Enter;*/
} }
void HidGLFW::Update() { void HidGLFW::Update() {
// Clear States
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
KeyEvents[i][Event_Down] = 0; KeyEvents[i][Event_Down] = 0;
KeyEvents[i][Event_Held] = 0; KeyEvents[i][Event_Held] = 0;
KeyEvents[i][Event_Up] = 0; KeyEvents[i][Event_Up] = 0;
for (auto& it : KbKeyEvents[i]) {
it.second = Event_Null;
} }
}
// Keyboard Logic
/*for (auto& it : pBinds) {
int kbstate = glfwGetKey(Window, it.first);
if (kbstate == GLFW_PRESS) {
if (PrevStates[it.first] == GLFW_RELEASE) {
KbKeyEvents[0][it.second] = Event_Down;
}
KbKeyEvents[0][it.second] = Event_Held;
} else if (kbstate == GLFW_RELEASE && PrevStates[it.first] == GLFW_PRESS) {
KbKeyEvents[0][it.second] = Event_Up;
}
PrevStates[it.first] = kbstate;
}*/
// Mouse Logic (Todo: Support all mouse buttons)
int state = glfwGetMouseButton(Window, GLFW_MOUSE_BUTTON_LEFT); int state = glfwGetMouseButton(Window, GLFW_MOUSE_BUTTON_LEFT);
if (state == GLFW_PRESS) { if (state == GLFW_PRESS) {
if (PrevState == GLFW_RELEASE) { if (PrevState == GLFW_RELEASE) {
@ -54,5 +139,28 @@ void HidGLFW::Update() {
glfwGetCursorPos(Window, &x, &y); glfwGetCursorPos(Window, &x, &y);
pMouse[1] = pMouse[0]; // Cycle pMouse pos pMouse[1] = pMouse[0]; // Cycle pMouse pos
pMouse[0] = fvec2(x, y); pMouse[0] = fvec2(x, y);
if (pInTextMode && (PD::OS::GetTime() - pLastUpdate) > 50) {
pLastUpdate = PD::OS::GetTime();
HandleTextOps();
}
}
void HidGLFW::GetInputStr(std::string& str) {
pText = &str;
glfwSetCharCallback(Window, TextCB);
pInTextMode = true;
}
void HidGLFW::HandleTextOps() {
if (!pText) {
return;
}
/*if (pTimedHeld(Kb_Backspace)) {
if (!pText->empty()) {
pText->pop_back();
}
} else if (pTimedHeld(Kb_Enter)) {
*pText += '\n';
}*/
} }
} // namespace PD } // namespace PD

View File

@ -37,7 +37,7 @@ void Init(void* data) {
// Dekstop Init Stage // Dekstop Init Stage
// First use default OS Driver // First use default OS Driver
PD::OS::Init(); PD::OS::Init();
PD::Li::Gfx::Init(PD::Li::GfxGL2::New()); PD::Gfx::Init(PD::GfxGL2::New());
PD::Hid::Init(PD::HidGLFW::New(reinterpret_cast<GLFWwindow*>(data))); PD::Hid::Init(PD::HidGLFW::New(reinterpret_cast<GLFWwindow*>(data)));
} }
} // namespace PD } // namespace PD

View File

@ -37,13 +37,18 @@ function(pd_add_lib TARGET_NAME)
${PD_INCLUDE_DIR} ${PD_INCLUDE_DIR}
${DEVKITPRO}/portlibs/3ds/include ${DEVKITPRO}/portlibs/3ds/include
) )
target_compile_definitions(${TARGET_NAME} PUBLIC target_compile_definitions(${TARGET_NAME} PRIVATE
-D_GNU_SOURCE=1 -D_GNU_SOURCE=1
-DPALLADIUM_VERSION="${PROJECT_VERSION}" -DPALLADIUM_VERSION="${PROJECT_VERSION}"
-DPALLADIUM_GIT_COMMIT="${GIT_SHORT_HASH}" -DPALLADIUM_GIT_COMMIT="${GIT_SHORT_HASH}"
-DPALLADIUM_GIT_BRANCH="${GIT_BRANCH}" -DPALLADIUM_GIT_BRANCH="${GIT_BRANCH}"
-DBUILD_CTR=1 -DBUILD_CTR=1
) )
if(${CMAKE_SYSTEM_NAME} STREQUAL "Nintendo3DS")
target_compile_options(${TARGET_NAME} PRIVATE
-Wno-abi
)
endif()
### For the libs that depend on another ### For the libs that depend on another
if(ARG_DEPENDS) if(ARG_DEPENDS)
target_link_libraries(${TARGET_NAME} PUBLIC ${ARG_DEPENDS}) target_link_libraries(${TARGET_NAME} PUBLIC ${ARG_DEPENDS})

View File

@ -23,6 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <array>
#include <chrono> #include <chrono>
#include <cinttypes> #include <cinttypes>
#include <cmath> #include <cmath>
@ -33,6 +34,7 @@ SOFTWARE.
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <memory> #include <memory>
#include <numbers>
#include <sstream> #include <sstream>
#include <stack> #include <stack>
#include <string> #include <string>

55
include/pd/core/fquat.hpp Normal file
View File

@ -0,0 +1,55 @@
#pragma once
/*
MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// This file is based on fvec4
#include <pd/core/common.hpp>
#include <pd/core/vec4.hpp>
namespace PD {
class fquat : public fvec4 {
constexpr fquat() : fvec4(0.f, 0.f, 0.f, 1.f) {}
constexpr fquat(float x, float y, float z, float w) : fvec4(x, y, z, w) {}
constexpr fquat(const fvec4& v) : fvec4(v) {}
static fquat Identity() { return fquat(0.f, 0.f, 0.f, 1.f); }
constexpr fquat Conjugate() const { return fquat(-x, -y, -z, w); }
fquat Inverse() const {
float len = SqLen();
if (len == 0.0f) {
return fquat();
}
return Conjugate() / len;
}
fquat operator*(const fquat& v) const {
return fquat(w * v.x + x * v.w + y * v.z - z * v.y,
w * v.y - x * v.z + y * v.w + z * v.x,
w * v.z + x * v.y - y * v.x + z * v.w,
w * v.w - x * v.x - y * v.y - z * v.z);
}
};
} // namespace PD

View File

@ -36,6 +36,12 @@ namespace IO {
* @return 8Bit FileBuffer * @return 8Bit FileBuffer
*/ */
PD_CORE_API std::vector<u8> LoadFile2Mem(const std::string& path); PD_CORE_API std::vector<u8> LoadFile2Mem(const std::string& path);
/**
* Load a File into a std::string
* @param path Path to the File
* @return std::string file content
*/
PD_CORE_API std::string LoadFile2Str(const std::string& path);
/** /**
* Hash a 8Bit Memory Buffer * Hash a 8Bit Memory Buffer
* @param data 8Bit input Buffer * @param data 8Bit input Buffer

View File

@ -25,17 +25,118 @@ SOFTWARE.
*/ */
#include <pd/core/common.hpp> #include <pd/core/common.hpp>
#include <pd/core/vec3.hpp>
namespace PD { namespace PD {
class PD_CORE_API Mat4 { namespace Numbers {
public: constexpr float Tau = std::numbers::pi * 2.f;
Mat4() { Zeros(); } }
~Mat4() = default; constexpr float Radians(float v) { return v * (Numbers::Tau / 360.0f); }
/**
* Minimal Mtx4 Lib that precomputes
* basic stuff stuff at compiletime
*
* This Lib includes Patches for work with Citro3D as well
*
* @note That this is not a full Matrix Library
*/
void Zeros(); struct PD_CORE_API Mat4 {
void Ortho(float left, float right, float bottom, float top, float near, std::array<float, 16> m;
float far); constexpr Mat4() : m{} {}
constexpr static Mat4 Diagonal(float x, float y, float z, float w) {
Mat4 ret;
ret(0, 0) = x;
ret(1, 1) = y;
ret(2, 2) = z;
ret(3, 3) = w;
return ret;
}
constexpr static Mat4 Identity() { return Diagonal(1, 1, 1, 1); }
float m[16]; constexpr float* Ptr() { return m.data(); }
constexpr const float* Ptr() const { return m.data(); }
constexpr float& operator()(int row, int col) {
#ifdef __3DS__
// 3ds is full reverse order iirc
return m[row * 4 + (3 - col)];
#else
return m[col * 4 + row];
#endif
}
constexpr float operator()(int row, int col) const {
#ifdef __3DS__
// 3ds is full reverse order iirc
return m[row * 4 + (3 - col)];
#else
return m[col * 4 + row];
#endif
}
constexpr Mat4 operator*(const Mat4& v) const {
Mat4 ret;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
float t = 0.f;
for (int k = 0; k < 4; k++) {
t += (*this)(i, k) * v(k, j);
}
ret(i, j) = t;
}
}
return ret;
}
constexpr Mat4& operator*=(const Mat4& v) {
*this = *this * v;
return *this;
}
constexpr static Mat4 Translate(float x, float y, float z) {
Mat4 ret = Identity();
ret(0, 3) = x;
ret(1, 3) = y;
ret(2, 3) = z;
return ret;
}
constexpr static Mat4 Scale(float x, float y, float z) {
Mat4 ret;
ret(0, 0) = x;
ret(1, 1) = y;
ret(2, 2) = z;
ret(3, 3) = 1.f;
return ret;
}
constexpr static Mat4 Ortho(float l, float r, float b, float t, float n,
float f) {
Mat4 ret;
#ifdef __3DS__ // Patch to rotate the Matrix correctly
ret(0, 1) = 2.f / (t - b);
ret(0, 3) = (b + t) / (b - t);
ret(1, 0) = 2.f / (l - r);
ret(1, 3) = (l + r) / (r - l);
ret(2, 2) = 1.f / (n - f);
ret(2, 3) = 0.5f * (n + f) / (n - f) - 0.5f;
#else
ret(0, 0) = 2.0f / (r - l);
ret(0, 3) = -(r + l) / (r - l);
ret(1, 1) = 2.0f / (t - b);
ret(1, 3) = -(t + b) / (t - b);
ret(2, 2) = -2.0f / (f - n);
ret(2, 3) = -(f + n) / (f - n);
#endif
ret(3, 3) = 1.f;
return ret;
}
static Mat4 Rotate(fvec3 axis, float a);
static Mat4 RotateX(float a);
static Mat4 RotateY(float a);
static Mat4 RotateZ(float a);
static Mat4 Perspective(float fov, float aspect, float n, float f);
static Mat4 LookAt(const fvec3& pos, const fvec3& center, const fvec3& up);
}; };
} // namespace PD } // namespace PD

View File

@ -30,4 +30,5 @@ SOFTWARE.
#include <pd/core/sl/pair.hpp> #include <pd/core/sl/pair.hpp>
#include <pd/core/sl/stack.hpp> #include <pd/core/sl/stack.hpp>
#include <pd/core/sl/tools.hpp> #include <pd/core/sl/tools.hpp>
#include <pd/core/sl/u128.hpp>
#include <pd/core/sl/vector.hpp> #include <pd/core/sl/vector.hpp>

125
include/pd/core/sl/u128.hpp Normal file
View File

@ -0,0 +1,125 @@
#pragma once
#include <pd/core/common.hpp>
namespace PD {
/**
* 128 Bit support for all platforms probably
* only used for flag checks in Keyboard/Mouse Input driver
*/
class u128 {
public:
u64 pLow = 0;
u64 pHigh = 0;
constexpr u128() : pLow(0), pHigh(0) {}
constexpr u128(u64 l, u64 h = 0) : pLow(l), pHigh(h) {}
/**
* Best way so far to create flags that go over 63
* like `1 << 65` is just `u128::Flag(65)`
*/
constexpr static u128 Flag(u32 i) {
if (i < 64) {
return u128(1ULL << i, 0);
} else if (i < 128) {
return u128(0, 1ULL << (i - 64));
}
return u128();
}
u128 operator+(const u128& v) const {
u128 ret;
ret.pLow = pLow + v.pLow;
ret.pHigh = pHigh + v.pHigh + (ret.pLow < pLow);
return ret;
}
u128 operator&(const u128& v) const {
return u128(pLow & v.pLow, pHigh & v.pHigh);
}
u128 operator<<(u32 s) const {
if (s == 0) {
return *this;
}
if (s >= 128) {
return u128();
}
if (s >= 64) {
return u128(0, pLow << (s - 64));
}
return u128(pLow << s, (pHigh << s) | (pLow >> (64 - s)));
}
u128 operator>>(u32 s) const {
if (s == 0) {
return *this;
}
if (s >= 128) {
return u128();
}
if (s >= 64) {
return u128(pHigh >> (s - 64), 0);
}
return u128((pLow >> s) | (pHigh << (64 - s)), pHigh >> s);
}
u128& operator|=(const u128& v) {
pLow |= v.pLow;
pHigh |= v.pHigh;
return *this;
}
u128 operator|(const u128& v) const {
return u128(pLow | v.pLow, pHigh | v.pHigh);
}
u128& operator&=(const u128& v) {
pLow &= v.pLow;
pHigh &= v.pHigh;
return *this;
}
u128 operator~() const { return u128(~pLow, ~pHigh); }
/**
* Old why to make if checks possible
* Problem was that a operator& is required
* with u128 as result
*/
// bool operator&(const u128& v) const {
// return pLow & v.pLow || pHigh & v.pHigh;
// }
bool operator==(const u128& v) const {
return pLow == v.pLow && pHigh == v.pHigh;
}
/**
* Use explicit here to make sure it is only for checking and not for
* some error leading implicit bool assignments...
*/
explicit operator bool() const { return pLow != 0 || pHigh != 0; }
/** Deprecated way to handle `flag & SomeFlag` */
bool Has(const u128& v) const { return pLow & v.pLow || pHigh & v.pHigh; }
bool operator!=(const u128& v) const { return !(*this == v); }
};
} // namespace PD
namespace std {
/**
* Provide c++ STL support for unordered map to u128
*/
template <>
struct hash<PD::u128> {
size_t operator()(const PD::u128& k) const {
// just combine hashes of the parts usign simple xor op
size_t h0 = std::hash<PD::u64>{}(k.pLow);
size_t h1 = std::hash<PD::u64>{}(k.pHigh);
return h0 ^ (h1 << 1);
}
};
} // namespace std

View File

@ -39,7 +39,7 @@ template <typename T, typename CharT>
struct std::formatter<PD::vec2<T>, CharT> : std::formatter<T, CharT> { struct std::formatter<PD::vec2<T>, CharT> : std::formatter<T, CharT> {
template <typename FormatContext> template <typename FormatContext>
auto format(const PD::vec2<T>& v, FormatContext& ctx) const { auto format(const PD::vec2<T>& v, FormatContext& ctx) const {
return std::format_to(ctx.out(), "({}, {})", v.x, v.y); return std::format_to(ctx.out(), "{}, {}", v.x, v.y);
} }
}; };
@ -47,7 +47,7 @@ template <typename T, typename CharT>
struct std::formatter<PD::vec3<T>, CharT> : std::formatter<T, CharT> { struct std::formatter<PD::vec3<T>, CharT> : std::formatter<T, CharT> {
template <typename FormatContext> template <typename FormatContext>
auto format(const PD::vec3<T>& v, FormatContext& ctx) const { auto format(const PD::vec3<T>& v, FormatContext& ctx) const {
return std::format_to(ctx.out(), "({}, {}, {})", v.x, v.y, v.z); return std::format_to(ctx.out(), "{}, {}, {}", v.x, v.y, v.z);
} }
}; };
@ -55,6 +55,6 @@ template <typename T, typename CharT>
struct std::formatter<PD::vec4<T>, CharT> : std::formatter<T, CharT> { struct std::formatter<PD::vec4<T>, CharT> : std::formatter<T, CharT> {
template <typename FormatContext> template <typename FormatContext>
auto format(const PD::vec4<T>& v, FormatContext& ctx) const { auto format(const PD::vec4<T>& v, FormatContext& ctx) const {
return std::format_to(ctx.out(), "({}, {}, {}, {})", v.x, v.y, v.z, v.w); return std::format_to(ctx.out(), "{}, {}, {}, {}", v.x, v.y, v.z, v.w);
} }
}; };

View File

@ -23,7 +23,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
// This file is generated by lazyvec // This file is generated by lazyvec 2.0.0
#include <pd/core/common.hpp> #include <pd/core/common.hpp>
namespace PD { namespace PD {
@ -33,20 +34,24 @@ class vec2 {
T x; T x;
T y; T y;
vec2() : x(0), y(0) {} // Constructors
constexpr vec2() : x(0), y(0) {}
template <typename T1> template <typename T1>
vec2(T1 v) { constexpr vec2(T1 v) {
x = (T)v; x = (T)v;
y = (T)v; y = (T)v;
} }
template <typename T1> template <typename T1>
vec2(vec2<T1> v) { constexpr vec2(const vec2<T1>& v) {
x = (T)v.x; x = (T)v.x;
y = (T)v.y; y = (T)v.y;
} }
vec2(T x, T y) : x(x), y(y) {} constexpr explicit vec2(T x, T y) : x(x), y(y) {}
// Operations
template <typename T1> template <typename T1>
vec2<T>& operator+=(T1 v) { vec2<T>& operator+=(T1 v) {
@ -144,14 +149,42 @@ class vec2 {
return vec2<T>(x / (T)v.x, y / (T)v.y); return vec2<T>(x / (T)v.x, y / (T)v.y);
} }
vec2 operator-() const { return vec2(-x, -y); } // Generic Operations
bool operator==(const vec2& v) const { return x == v.x && y == v.y; } vec2 operator-() const { return vec2(-x, -y); }
bool operator!=(const vec2& v) const { return !(*this == v); } template <typename T1>
bool operator==(const vec2<T1>& v) const {
return x == (T)v.x && y == (T)v.y;
}
template <typename T1>
bool operator!=(const vec2<T1>& v) const {
return !(*this == v);
}
// Functions
double Len() const { return std::sqrt(SqLen()); } double Len() const { return std::sqrt(SqLen()); }
double SqLen() const { return x * x + y * y; } double SqLen() const { return x * x + y * y; }
template <typename T1>
double Distance(const vec2<T1>& v) const {
return (*this - v).Len();
}
vec2<T> Normalize() const {
double l = Len();
if (l == 0) {
return *this;
}
return *this / (T)l;
}
template <typename T1>
T Dot(const vec2<T1>& v) const {
return x * (T)v.x + y * (T)v.y;
}
// Swap Functions
void SwapXY() { void SwapXY() {
T t = x; T t = x;
x = y; x = y;
@ -159,6 +192,6 @@ class vec2 {
} }
}; };
using fvec2 = vec2<float>; using fvec2 = vec2<float>;
using dvec2 = vec2<double>;
using ivec2 = vec2<int>; using ivec2 = vec2<int>;
using dvec2 = vec2<double>;
} // namespace PD } // namespace PD

View File

@ -23,8 +23,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
// This file is generated by lazyvec // This file is generated by lazyvec 2.0.0
#include <pd/core/common.hpp> #include <pd/core/common.hpp>
// Extended includes (rename if you use other filenames/paths)
#include <pd/core/vec2.hpp>
namespace PD { namespace PD {
template <typename T> template <typename T>
@ -34,22 +37,36 @@ class vec3 {
T y; T y;
T z; T z;
vec3() : x(0), y(0), z(0) {} // Constructors
constexpr vec3() : x(0), y(0), z(0) {}
template <typename T1> template <typename T1>
explicit vec3(T1 v) { constexpr vec3(T1 v) {
x = (T)v; x = (T)v;
y = (T)v; y = (T)v;
z = (T)v; z = (T)v;
} }
template <typename T1> template <typename T1>
explicit vec3(vec3<T1> v) { constexpr vec3(const vec3<T1>& v) {
x = (T)v.x; x = (T)v.x;
y = (T)v.y; y = (T)v.y;
z = (T)v.z; z = (T)v.z;
} }
vec3(T x, T y, T z) : x(x), y(y), z(z) {} constexpr explicit vec3(T x, T y, T z) : x(x), y(y), z(z) {}
// Extended Constructors
template <typename T1>
constexpr explicit vec3(const vec2<T1>& xy, T1 z) {
{
x = (T)xy.x;
y = (T)xy.y;
this->z = (T)z;
}
}
// Operations
template <typename T1> template <typename T1>
vec3<T>& operator+=(T1 v) { vec3<T>& operator+=(T1 v) {
@ -155,16 +172,47 @@ class vec3 {
return vec3<T>(x / (T)v.x, y / (T)v.y, z / (T)v.z); return vec3<T>(x / (T)v.x, y / (T)v.y, z / (T)v.z);
} }
vec3 operator-() const { return vec3(-x, -y, -z); } // Generic Operations
bool operator==(const vec3& v) const { vec3 operator-() const { return vec3(-x, -y, -z); }
return x == v.x && y == v.y && z == v.z; template <typename T1>
bool operator==(const vec3<T1>& v) const {
return x == (T)v.x && y == (T)v.y && z == (T)v.z;
} }
bool operator!=(const vec3& v) const { return !(*this == v); } template <typename T1>
bool operator!=(const vec3<T1>& v) const {
return !(*this == v);
}
// Functions
double Len() const { return std::sqrt(SqLen()); } double Len() const { return std::sqrt(SqLen()); }
double SqLen() const { return x * x + y * y + z * z; } double SqLen() const { return x * x + y * y + z * z; }
template <typename T1>
double Distance(const vec3<T1>& v) const {
return (*this - v).Len();
}
vec3<T> Normalize() const {
double l = Len();
if (l == 0) {
return *this;
}
return *this / (T)l;
}
template <typename T1>
T Dot(const vec3<T1>& v) const {
return x * (T)v.x + y * (T)v.y + z * (T)v.z;
}
template <typename T1>
vec3<T> Cross(const vec3<T1>& v) const {
return vec3<T>(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
}
// Swap Functions
void SwapXY() { void SwapXY() {
T t = x; T t = x;
x = y; x = y;
@ -182,6 +230,6 @@ class vec3 {
} }
}; };
using fvec3 = vec3<float>; using fvec3 = vec3<float>;
using dvec3 = vec3<double>;
using ivec3 = vec3<int>; using ivec3 = vec3<int>;
using dvec3 = vec3<double>;
} // namespace PD } // namespace PD

View File

@ -23,9 +23,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
// This file is generated by lazyvec // This file is generated by lazyvec 2.0.0
#include <pd/core/common.hpp> #include <pd/core/common.hpp>
#include <pd/core/vec2.hpp> // Extended // Extended includes (rename if you use other filenames/paths)
#include <pd/core/vec2.hpp>
#include <pd/core/vec3.hpp>
namespace PD { namespace PD {
template <typename T> template <typename T>
@ -36,9 +39,11 @@ class vec4 {
T z; T z;
T w; T w;
vec4() : x(0), y(0), z(0), w(0) {} // Constructors
constexpr vec4() : x(0), y(0), z(0), w(0) {}
template <typename T1> template <typename T1>
explicit vec4(T1 v) { constexpr vec4(T1 v) {
x = (T)v; x = (T)v;
y = (T)v; y = (T)v;
z = (T)v; z = (T)v;
@ -46,23 +51,37 @@ class vec4 {
} }
template <typename T1> template <typename T1>
explicit vec4(vec4<T1> v) { constexpr vec4(const vec4<T1>& v) {
x = (T)v.x; x = (T)v.x;
y = (T)v.y; y = (T)v.y;
z = (T)v.z; z = (T)v.z;
w = (T)v.w; w = (T)v.w;
} }
/** Extended Constructor */ constexpr explicit vec4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {}
// Extended Constructors
template <typename T1> template <typename T1>
explicit vec4(vec2<T1> a, vec2<T1> b) { constexpr explicit vec4(const vec2<T1>& xy, const vec2<T1>& zw) {
x = (T)a.x; {
y = (T)a.y; x = (T)xy.x;
z = (T)b.x; y = (T)xy.y;
w = (T)b.y; z = (T)zw.x;
w = (T)zw.y;
}
} }
vec4(T x, T y, T z, T w) : x(x), y(y), z(z), w(w) {} template <typename T1>
constexpr explicit vec4(const vec3<T1>& xyz, T1 w) {
{
x = (T)xyz.x;
y = (T)xyz.y;
z = (T)xyz.z;
this->w = (T)w;
}
}
// Operations
template <typename T1> template <typename T1>
vec4<T>& operator+=(T1 v) { vec4<T>& operator+=(T1 v) {
@ -176,16 +195,42 @@ class vec4 {
return vec4<T>(x / (T)v.x, y / (T)v.y, z / (T)v.z, w / (T)v.w); return vec4<T>(x / (T)v.x, y / (T)v.y, z / (T)v.z, w / (T)v.w);
} }
vec4 operator-() const { return vec4(-x, -y, -z, -w); } // Generic Operations
bool operator==(const vec4& v) const { vec4 operator-() const { return vec4(-x, -y, -z, -w); }
return x == v.x && y == v.y && z == v.z && w == v.w; template <typename T1>
bool operator==(const vec4<T1>& v) const {
return x == (T)v.x && y == (T)v.y && z == (T)v.z && w == (T)v.w;
} }
bool operator!=(const vec4& v) const { return !(*this == v); } template <typename T1>
bool operator!=(const vec4<T1>& v) const {
return !(*this == v);
}
// Functions
double Len() const { return std::sqrt(SqLen()); } double Len() const { return std::sqrt(SqLen()); }
double SqLen() const { return x * x + y * y + z * z + w * w; } double SqLen() const { return x * x + y * y + z * z + w * w; }
template <typename T1>
double Distance(const vec4<T1>& v) const {
return (*this - v).Len();
}
vec4<T> Normalize() const {
double l = Len();
if (l == 0) {
return *this;
}
return *this / (T)l;
}
template <typename T1>
T Dot(const vec4<T1>& v) const {
return x * (T)v.x + y * (T)v.y + z * (T)v.z + w * (T)v.w;
}
// Swap Functions
void SwapXY() { void SwapXY() {
T t = x; T t = x;
x = y; x = y;
@ -218,6 +263,6 @@ class vec4 {
} }
}; };
using fvec4 = vec4<float>; using fvec4 = vec4<float>;
using dvec4 = vec4<double>;
using ivec4 = vec4<int>; using ivec4 = vec4<int>;
using dvec4 = vec4<double>;
} // namespace PD } // namespace PD

View File

@ -34,7 +34,6 @@ enum LiBackendFlags_ {
}; };
namespace PD { namespace PD {
namespace Li {
class GfxDriver { class GfxDriver {
public: public:
GfxDriver(const std::string& name = "NullGfx") : pName(name) {}; GfxDriver(const std::string& name = "NullGfx") : pName(name) {};
@ -48,25 +47,29 @@ class GfxDriver {
virtual void Deinit() {} virtual void Deinit() {}
virtual void NewFrame() {} virtual void NewFrame() {}
virtual void BindTex(TexAddress addr) {} virtual void BindTex(Li::TexAddress addr) {}
virtual void RenderDrawData(const std::vector<Command::Ref>& Commands) {} virtual void RenderDrawData(const std::vector<Li::Command::Ref>& Commands) {}
virtual Texture::Ref LoadTex( void SetViewPort(const ivec2& vp) { ViewPort = vp; }
virtual Li::Texture::Ref LoadTex(
const std::vector<u8>& pixels, int w, int h, const std::vector<u8>& pixels, int w, int h,
Texture::Type type = Texture::Type::RGBA32, Li::Texture::Type type = Li::Texture::Type::RGBA32,
Texture::Filter filter = Texture::Filter::LINEAR) { Li::Texture::Filter filter = Li::Texture::Filter::LINEAR) {
// Texture loading not supported (when this func not get override) // Texture loading not supported (when this func not get override)
return nullptr; return nullptr;
} }
Texture::Ref GetSolidTex() { return pSolid; } Li::Texture::Ref GetSolidTex() { return pSolid; }
const std::string pName = "NullGfx"; const std::string pName = "NullGfx";
LiBackendFlags Flags = 0; LiBackendFlags Flags = 0;
ivec2 ViewPort; ivec2 ViewPort;
fvec4 ClearColor; Mat4 Projection;
Texture::Ref pSolid; Li::Texture::Ref pSolid;
size_t CurrentVertex = 0;
size_t CurrentIndex = 0;
/** Debug Variables */ /** Debug Variables */
@ -89,23 +92,23 @@ class Gfx {
static void Deinit() { pGfx->Deinit(); } static void Deinit() { pGfx->Deinit(); }
static void NewFrame() { pGfx->NewFrame(); } static void NewFrame() { pGfx->NewFrame(); }
static void BindTex(TexAddress addr) { pGfx->BindTex(addr); } static void BindTex(Li::TexAddress addr) { pGfx->BindTex(addr); }
static void SetViewPort(const ivec2& vp) { pGfx->SetViewPort(vp); }
static void RenderDrawData(const std::vector<Command::Ref>& Commands) { static void RenderDrawData(const std::vector<Li::Command::Ref>& Commands) {
pGfx->RenderDrawData(Commands); pGfx->RenderDrawData(Commands);
} }
static LiBackendFlags Flags() { return pGfx->Flags; } static LiBackendFlags Flags() { return pGfx->Flags; }
static Texture::Ref LoadTex( static Li::Texture::Ref LoadTex(
const std::vector<u8>& pixels, int w, int h, const std::vector<u8>& pixels, int w, int h,
Texture::Type type = Texture::Type::RGBA32, Li::Texture::Type type = Li::Texture::Type::RGBA32,
Texture::Filter filter = Texture::Filter::LINEAR) { Li::Texture::Filter filter = Li::Texture::Filter::LINEAR) {
return pGfx->LoadTex(pixels, w, h, type, filter); return pGfx->LoadTex(pixels, w, h, type, filter);
} }
static Texture::Ref GetSolidTex() { return pGfx->GetSolidTex(); } static Li::Texture::Ref GetSolidTex() { return pGfx->GetSolidTex(); }
static GfxDriver::Ref pGfx; static GfxDriver::Ref pGfx;
}; };
} // namespace Li
} // namespace PD } // namespace PD

View File

@ -26,8 +26,72 @@ SOFTWARE.
#include <pd/core/core.hpp> #include <pd/core/core.hpp>
namespace PD { namespace PD {
/** Did not found a better solution yet sadly */
namespace HidKb {
// Lets use u128 here
using KbKey = u128;
constexpr static KbKey Kb_No = 0;
constexpr static KbKey Kb_Escape = KbKey::Flag(0);
constexpr static KbKey Kb_Q = KbKey::Flag(1);
constexpr static KbKey Kb_W = KbKey::Flag(2);
constexpr static KbKey Kb_E = KbKey::Flag(3);
constexpr static KbKey Kb_R = KbKey::Flag(4);
constexpr static KbKey Kb_T = KbKey::Flag(5);
constexpr static KbKey Kb_Z = KbKey::Flag(6);
constexpr static KbKey Kb_U = KbKey::Flag(7);
constexpr static KbKey Kb_I = KbKey::Flag(8);
constexpr static KbKey Kb_O = KbKey::Flag(9);
constexpr static KbKey Kb_P = KbKey::Flag(10);
constexpr static KbKey Kb_A = KbKey::Flag(11);
constexpr static KbKey Kb_S = KbKey::Flag(12);
constexpr static KbKey Kb_D = KbKey::Flag(13);
constexpr static KbKey Kb_F = KbKey::Flag(14);
constexpr static KbKey Kb_G = KbKey::Flag(15);
constexpr static KbKey Kb_H = KbKey::Flag(16);
constexpr static KbKey Kb_J = KbKey::Flag(17);
constexpr static KbKey Kb_K = KbKey::Flag(18);
constexpr static KbKey Kb_L = KbKey::Flag(19);
constexpr static KbKey Kb_Y = KbKey::Flag(20);
constexpr static KbKey Kb_X = KbKey::Flag(21);
constexpr static KbKey Kb_C = KbKey::Flag(22);
constexpr static KbKey Kb_V = KbKey::Flag(23);
constexpr static KbKey Kb_B = KbKey::Flag(24);
constexpr static KbKey Kb_N = KbKey::Flag(25);
constexpr static KbKey Kb_M = KbKey::Flag(26);
constexpr static KbKey Kb_1 = KbKey::Flag(27);
constexpr static KbKey Kb_2 = KbKey::Flag(28);
constexpr static KbKey Kb_3 = KbKey::Flag(29);
constexpr static KbKey Kb_4 = KbKey::Flag(30);
constexpr static KbKey Kb_5 = KbKey::Flag(31);
constexpr static KbKey Kb_6 = KbKey::Flag(32);
constexpr static KbKey Kb_7 = KbKey::Flag(33);
constexpr static KbKey Kb_8 = KbKey::Flag(34);
constexpr static KbKey Kb_9 = KbKey::Flag(35);
constexpr static KbKey Kb_0 = KbKey::Flag(36);
constexpr static KbKey Kb_F1 = KbKey::Flag(37);
constexpr static KbKey Kb_F2 = KbKey::Flag(38);
constexpr static KbKey Kb_F3 = KbKey::Flag(39);
constexpr static KbKey Kb_F4 = KbKey::Flag(40);
constexpr static KbKey Kb_F5 = KbKey::Flag(41);
constexpr static KbKey Kb_F6 = KbKey::Flag(42);
constexpr static KbKey Kb_F7 = KbKey::Flag(43);
constexpr static KbKey Kb_F8 = KbKey::Flag(44);
constexpr static KbKey Kb_F9 = KbKey::Flag(45);
constexpr static KbKey Kb_F10 = KbKey::Flag(46);
constexpr static KbKey Kb_F11 = KbKey::Flag(47);
constexpr static KbKey Kb_F12 = KbKey::Flag(48);
constexpr static KbKey Kb_MouseLeft = KbKey::Flag(120);
} // namespace HidKb
class HidDriver { class HidDriver {
public: public:
enum Flags : u32 {
Flags_None = 0,
FLags_HasGamepad = 1 << 0,
Flags_HasKeyboard = 1 << 1,
Flags_HasTouch = 1 << 2,
Flags_HasMouse = 1 << 3,
};
// Todo: Name to GpKey (GamepadKey)
/** Key [Controller] */ /** Key [Controller] */
enum Key : u32 { enum Key : u32 {
No = 0, ///< No Key No = 0, ///< No Key
@ -60,8 +124,11 @@ class HidDriver {
Right = DRight | CPRight, ///< DPad or CPad Right Right = DRight | CPRight, ///< DPad or CPad Right
}; };
using KbKey = HidKb::KbKey;
/** Event */ /** Event */
enum Event { enum Event {
Event_Null,
Event_Down, ///< Key Pressed Event_Down, ///< Key Pressed
Event_Held, ///< Key Held Event_Held, ///< Key Held
Event_Up, ///< Key released Event_Up, ///< Key released
@ -90,6 +157,7 @@ class HidDriver {
* @return if key(s) doing the requiested event * @return if key(s) doing the requiested event
*/ */
bool IsEvent(Event e, Key keys); bool IsEvent(Event e, Key keys);
bool IsEvent(Event e, KbKey key);
/** /**
* Check for Key Press Event * Check for Key Press Event
* @param keys set of keys * @param keys set of keys
@ -159,15 +227,23 @@ class HidDriver {
/** /**
* Template Update Function for a device specific driver * Template Update Function for a device specific driver
*/ */
virtual void Update() {} virtual void Update();
/**
* Get Text from Keyboard
*/
virtual void GetInputStr(std::string& str) {}
/** Data Section */ /** Data Section */
/** Backend Identification Name */ /** Backend Identification Name */
const std::string pName; const std::string pName;
/** Flags */
u32 Flags = 0;
/** Key Binds Map */ /** Key Binds Map */
std::unordered_map<u32, u32> pBinds; std::unordered_map<u32, u32> pBinds;
std::unordered_map<u128, u128> pKbBinds;
/** Swap Tabe Function */ /** Swap Tabe Function */
void SwapTab(); void SwapTab();
/** Using 2 Positions for Current and Last */ /** Using 2 Positions for Current and Last */
@ -176,6 +252,8 @@ class HidDriver {
bool pLocked = false; bool pLocked = false;
/** Key Event Table Setup */ /** Key Event Table Setup */
std::unordered_map<Event, u32> KeyEvents[2]; std::unordered_map<Event, u32> KeyEvents[2];
/** Keyboard Key Event Table Setup */
std::unordered_map<Event, u128> KbKeyEvents[2];
}; };
/** Static Hid Controller */ /** Static Hid Controller */
@ -186,6 +264,7 @@ class Hid {
/** Referenec to Drivers enums */ /** Referenec to Drivers enums */
using Key = HidDriver::Key; using Key = HidDriver::Key;
using KbKey = HidKb::KbKey;
using Event = HidDriver::Event; using Event = HidDriver::Event;
static void Init(HidDriver::Ref v = nullptr) { static void Init(HidDriver::Ref v = nullptr) {
@ -197,6 +276,7 @@ class Hid {
} }
static bool IsEvent(Event e, Key keys) { return pHid->IsEvent(e, keys); } static bool IsEvent(Event e, Key keys) { return pHid->IsEvent(e, keys); }
static bool IsEvent(Event e, KbKey key) { return pHid->IsEvent(e, key); }
static bool IsDown(Key keys) { return pHid->IsDown(keys); } static bool IsDown(Key keys) { return pHid->IsDown(keys); }
static bool IsUp(Key keys) { return pHid->IsUp(keys); } static bool IsUp(Key keys) { return pHid->IsUp(keys); }
static bool IsHeld(Key keys) { return pHid->IsHeld(keys); } static bool IsHeld(Key keys) { return pHid->IsHeld(keys); }
@ -208,6 +288,8 @@ class Hid {
static void Unlock() { pHid->Unlock(); } static void Unlock() { pHid->Unlock(); }
static bool Locked() { return pHid->Locked(); } static bool Locked() { return pHid->Locked(); }
static void Update() { pHid->Update(); } static void Update() { pHid->Update(); }
static u32 GetFlags() { return pHid->Flags; }
static void GetStrInput(std::string& str) { pHid->GetInputStr(str); }
static HidDriver::Ref pHid; static HidDriver::Ref pHid;
}; };

View File

@ -35,7 +35,8 @@ class PD_IMAGE_API Image {
RGB, // bpp == 3 RGB, // bpp == 3
RGB565, // bpp == 2 (not supported in laoding) RGB565, // bpp == 2 (not supported in laoding)
BGR, // bpp == 3 BGR, // bpp == 3
ABGR // bpp == 4 ABGR, // bpp == 4
BGRA, // bpp == 4
}; };
Image() = default; Image() = default;
Image(const std::string& path) { this->Load(path); } Image(const std::string& path) { this->Load(path); }
@ -58,6 +59,9 @@ class PD_IMAGE_API Image {
int Height() const { return pHeight; } int Height() const { return pHeight; }
Format Fmt() const { return pFmt; } Format Fmt() const { return pFmt; }
void FlipVertical();
void FlipHorizontal();
u8& operator[](int idx) { return pBuffer[idx]; } u8& operator[](int idx) { return pBuffer[idx]; }
u8 operator[](int idx) const { return pBuffer[idx]; } u8 operator[](int idx) const { return pBuffer[idx]; }

View File

@ -61,9 +61,17 @@ class PD_LITHIUM_API DrawList {
PD_SHARED(DrawList); PD_SHARED(DrawList);
/**
* Append an input drawlist on top of this one
* This Function will clear the Input list to make sure
* THat the moved memory blocks don't get used
* @param list DrawList to move into current
*/
void Merge(DrawList::Ref list);
Command::Ref PreGenerateCmd(); Command::Ref PreGenerateCmd();
void AddCommand(Command::Ref v) { pDrawList.push_back(std::move(v)); } void AddCommand(Command::Ref v);
void Clear() { pDrawList.clear(); } void Clear();
void SetFont(Font::Ref font) { pCurrentFont = font; } void SetFont(Font::Ref font) { pCurrentFont = font; }
void SetFontScale(float scale) { pFontScale = scale; } void SetFontScale(float scale) { pFontScale = scale; }
@ -186,6 +194,8 @@ class PD_LITHIUM_API DrawList {
Texture::Ref CurrentTex; Texture::Ref CurrentTex;
std::vector<Command::Ref> pDrawList; std::vector<Command::Ref> pDrawList;
PD::Vec<fvec2> pPath; PD::Vec<fvec2> pPath;
u32 pNumIndices = 0;
u32 pNumVertices = 0;
}; };
} // namespace Li } // namespace Li
} // namespace PD } // namespace PD

View File

@ -67,6 +67,18 @@ class PD_LITHIUM_API Font {
* @param px_height Pixelheight of the codepoints (limit by 64) * @param px_height Pixelheight of the codepoints (limit by 64)
*/ */
void LoadTTF(const std::string& path, int px_height = 32); void LoadTTF(const std::string& path, int px_height = 32);
/**
* Load a TTF File from Memory
* @param data File data
* @param px_height Pixelheight of the codepoints (limit by 64)
*/
void LoadTTF(const std::vector<u8>& data, int px_height = 32);
/**
* Function that loads a default integrated font...
* This will only work if PD_LI_INCLUDE_FONTS was set
* on lithium build cause otherwise the font data is not included
*/
void LoadDefaultFont(int id = 0, int pixel_height = 32);
/** /**
* Getter for Codepoint reference * Getter for Codepoint reference
* @return codepoint dataholder reference * @return codepoint dataholder reference
@ -83,6 +95,12 @@ class PD_LITHIUM_API Font {
void CmdTextEx(std::vector<Command::Ref>& cmds, const fvec2& pos, u32 color, void CmdTextEx(std::vector<Command::Ref>& cmds, const fvec2& pos, u32 color,
float scale, const std::string& text, LiTextFlags flags = 0, float scale, const std::string& text, LiTextFlags flags = 0,
const fvec2& box = 0); const fvec2& box = 0);
/**
* Utility function to create a font atlas
* During TTF loading (Internal and should not be called)
*/
void pMakeAtlas(bool final, std::vector<u8>& font_tex, int texszs,
PD::Li::Texture::Ref tex);
/** Data Section */ /** Data Section */
int PixelHeight; int PixelHeight;

View File

@ -0,0 +1,41 @@
#pragma once
/*
MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifdef PD_LI_INCLUDE_FONTS
#include <pd/core/common.hpp>
/** Generated with pdfm */
namespace PD {
struct FontFileData {
std::string Name;
u32 StartOff;
u32 Size;
};
extern FontFileData pFontData[];
extern size_t pNumFonts;
extern PD::u8 pFontsDataRaw[];
} // namespace PD
#endif

View File

@ -85,7 +85,7 @@ class Rect {
* Get the bottom-right corner position. * Get the bottom-right corner position.
* @return Bottom-right position as vec2. * @return Bottom-right position as vec2.
*/ */
fvec2 BotRight() const { return fvec2(Bot.z, Bot.y); } fvec2 BotRight() const { return fvec2(Bot.z, Bot.w); }
/** /**
* Set the top-left corner position. * Set the top-left corner position.

View File

@ -63,6 +63,11 @@ class PD_UI7_API Container {
// this->screen = io->Ren->CurrentScreen(); // this->screen = io->Ren->CurrentScreen();
} }
void SetClipRect(fvec4 clip) {
pClipRect = clip;
pCLipRectUsed = true;
}
/** Setter for Position */ /** Setter for Position */
void SetPos(const fvec2& pos) { this->pos = pos; } void SetPos(const fvec2& pos) { this->pos = pos; }
/** Setter for Size */ /** Setter for Size */
@ -161,6 +166,10 @@ class PD_UI7_API Container {
bool pPressed = false; bool pPressed = false;
/** Was Pressed Twice */ /** Was Pressed Twice */
bool pPressedTwice = false; bool pPressedTwice = false;
/** ClipRect */
fvec4 pClipRect;
/** Clip Rect used */
bool pCLipRectUsed = false;
}; };
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD

View File

@ -52,6 +52,10 @@ class PD_UI7_API DynObj : public Container {
PD_SHARED(DynObj); PD_SHARED(DynObj);
void AddInputHandler(std::function<void(UI7::IO::Ref, Container*)> inp) {
pInp = inp;
}
/** Return true if butten is pressed*/ /** Return true if butten is pressed*/
bool IsPressed() { return pressed; } bool IsPressed() { return pressed; }
/** /**
@ -72,6 +76,7 @@ class PD_UI7_API DynObj : public Container {
UI7Color color = UI7Color_Button; ///< current button color UI7Color color = UI7Color_Button; ///< current button color
bool pressed = false; ///< ispressed value bool pressed = false; ///< ispressed value
std::function<void(UI7::IO::Ref, Li::DrawList::Ref, Container*)> pRenFun; std::function<void(UI7::IO::Ref, Li::DrawList::Ref, Container*)> pRenFun;
std::function<void(UI7::IO::Ref, Container*)> pInp;
}; };
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD

View File

@ -31,8 +31,6 @@ using UI7Align = unsigned int;
using UI7IOFlags = unsigned int; using UI7IOFlags = unsigned int;
/** 32Bit Value for Layout Flags */ /** 32Bit Value for Layout Flags */
using UI7LayoutFlags = unsigned int; using UI7LayoutFlags = unsigned int;
/** 32Bit value for DrawFlags */
using UI7DrawFlags = unsigned int;
/** Menu Flags */ /** Menu Flags */
enum UI7MenuFlags_ { enum UI7MenuFlags_ {
@ -48,6 +46,9 @@ enum UI7MenuFlags_ {
UI7MenuFlags_NoResize = 1 << 8, ///< Disable Menu Resize UI7MenuFlags_NoResize = 1 << 8, ///< Disable Menu Resize
UI7MenuFlags_NoClose = 1 << 9, ///< Disable Close Button UI7MenuFlags_NoClose = 1 << 9, ///< Disable Close Button
UI7MenuFlags_NoScrollbar = 1 << 10, ///< Hide the Scrollbar UI7MenuFlags_NoScrollbar = 1 << 10, ///< Hide the Scrollbar
// POC
UI7MenuFlags_Maximize = 1 << 11, ///< Add a Maximize Button
UI7MenuFlags_Minimize = 1 << 12, ///< Add a Minimize Button
// Enable Horizontal and Vertical Scrolling // Enable Horizontal and Vertical Scrolling
UI7MenuFlags_Scrolling = UI7MenuFlags_HzScrolling | UI7MenuFlags_VtScrolling, UI7MenuFlags_Scrolling = UI7MenuFlags_HzScrolling | UI7MenuFlags_VtScrolling,
}; };
@ -58,12 +59,6 @@ enum UI7LayoutFlags_ {
UI7LayoutFlags_UseClipRect = 1 << 0, ///< Enable ClipRect UI7LayoutFlags_UseClipRect = 1 << 0, ///< Enable ClipRect
}; };
enum UI7DrawFlags_ {
UI7DrawFlags_None = 0,
UI7DrawFlags_Close = 1 << 0, ///< Close a PolyLine
UI7DrawFlags_AALines = 1 << 1, ///< Anti aliased Lines
};
/** UI7 Context Flags */ /** UI7 Context Flags */
enum UI7IOFlags_ { enum UI7IOFlags_ {
UI7IOFlags_None = 0, ///< No Additional Config available UI7IOFlags_None = 0, ///< No Additional Config available
@ -91,6 +86,11 @@ enum UI7LytAdd_ {
UI7LytAdd_Front = 1 << 2, ///< Add in front of the list UI7LytAdd_Front = 1 << 2, ///< Add in front of the list
}; };
/**
* Todo: Look at this
* Maybe proof of concept ???
* Didnt remember that this exists
*/
enum UI7ContainerFlags_ { enum UI7ContainerFlags_ {
UI7ContainerFlags_None = 0, UI7ContainerFlags_None = 0,
UI7ContainerFlags_EnableInternalInput = 1 << 0, UI7ContainerFlags_EnableInternalInput = 1 << 0,

View File

@ -58,7 +58,9 @@ class InputHandler {
// Get a Short define for touch pos // Get a Short define for touch pos
fvec2 p = Hid::MousePos(); fvec2 p = Hid::MousePos();
// Check if Drag starts in the area position // Check if Drag starts in the area position
if (Hid::IsDown(Hid::Key::Touch) && Li::Renderer::InBox(p, area)) { if ((Hid::IsDown(Hid::Key::Touch) ||
Hid::IsEvent(PD::Hid::Event::Event_Down, HidKb::Kb_MouseLeft)) &&
Li::Renderer::InBox(p, area)) {
// Set ID and iniatial Positions // Set ID and iniatial Positions
DraggedObject = id; DraggedObject = id;
DragSourcePos = p; DragSourcePos = p;
@ -69,11 +71,16 @@ class InputHandler {
DragTime->Reset(); DragTime->Reset();
DragTime->Rseume(); DragTime->Rseume();
return false; // To make sure the Object is "Dragged" return false; // To make sure the Object is "Dragged"
} else if (Hid::IsHeld(Hid::Key::Touch) && IsObjectDragged()) { } else if ((Hid::IsHeld(Hid::Key::Touch) ||
Hid::IsEvent(PD::Hid::Event::Event_Held,
HidKb::Kb_MouseLeft)) &&
IsObjectDragged()) {
// Update DragLast and DragPoisition // Update DragLast and DragPoisition
DragLastPosition = DragPosition; DragLastPosition = DragPosition;
DragPosition = p; DragPosition = p;
} else if (Hid::IsUp(Hid::Key::Touch) && IsObjectDragged()) { } else if ((Hid::IsUp(Hid::Key::Touch) ||
Hid::IsEvent(PD::Hid::Event::Event_Up, HidKb::Kb_MouseLeft)) &&
IsObjectDragged()) {
// Released... Everything gets reset // Released... Everything gets reset
DraggedObject = 0; DraggedObject = 0;
DragPosition = 0; DragPosition = 0;

View File

@ -40,10 +40,11 @@ class PD_UI7_API IO {
Theme = UI7::Theme::New(); Theme = UI7::Theme::New();
Back = Li::DrawList::New(); Back = Li::DrawList::New();
Front = Li::DrawList::New(); Front = Li::DrawList::New();
FDL = Li::DrawList::New();
DeltaStats = TimeStats::New(60); DeltaStats = TimeStats::New(60);
/** Probably not the best solution i guess */ /** Probably not the best solution i guess */
CurrentViewPort.z = PD::Li::Gfx::pGfx->ViewPort.x; CurrentViewPort.z = PD::Gfx::pGfx->ViewPort.x;
CurrentViewPort.w = PD::Li::Gfx::pGfx->ViewPort.y; CurrentViewPort.w = PD::Gfx::pGfx->ViewPort.y;
} }
~IO() {} ~IO() {}
@ -54,6 +55,12 @@ class PD_UI7_API IO {
*/ */
void Update(); void Update();
/**
* Final Draw List for PD::Li::Gfx::RednerDrawData
*
* Possible thanks to the DrawList::Merge Feature
*/
Li::DrawList::Ref FDL = nullptr;
ivec4 CurrentViewPort = ivec4(0, 0, 0, 0); ivec4 CurrentViewPort = ivec4(0, 0, 0, 0);
std::unordered_map<u32, ViewPort::Ref> ViewPorts; std::unordered_map<u32, ViewPort::Ref> ViewPorts;
float Framerate = 0.f; float Framerate = 0.f;
@ -94,6 +101,13 @@ class PD_UI7_API IO {
ViewPorts[id] = ViewPort::New(id, size); ViewPorts[id] = ViewPort::New(id, size);
} }
ViewPort::Ref GetViewPort(const ID& id) {
if (!ViewPorts.count(id)) {
return nullptr;
}
return ViewPorts[id];
}
UI7::InputHandler::Ref InputHandler; UI7::InputHandler::Ref InputHandler;
}; };
} // namespace UI7 } // namespace UI7

View File

@ -39,11 +39,13 @@ class PD_UI7_API Layout {
this->IO = io; this->IO = io;
DrawList = Li::DrawList::New(); DrawList = Li::DrawList::New();
DrawList->SetFont(IO->Font); DrawList->SetFont(IO->Font);
DrawList->SetFontScale(io->FontScale);
Scrolling[0] = false; Scrolling[0] = false;
Scrolling[1] = false; Scrolling[1] = false;
CursorInit(); CursorInit();
Pos = fvec2(0, 0); Pos = fvec2(io->CurrentViewPort.x, io->CurrentViewPort.y);
Size = fvec2(io->CurrentViewPort.z, io->CurrentViewPort.w); Size = fvec2(io->CurrentViewPort.z - io->CurrentViewPort.x,
io->CurrentViewPort.w - io->CurrentViewPort.y);
WorkRect = fvec4(IO->MenuPadding, Size - (fvec2(2) * IO->MenuPadding)); WorkRect = fvec4(IO->MenuPadding, Size - (fvec2(2) * IO->MenuPadding));
} }
~Layout() = default; ~Layout() = default;
@ -126,7 +128,8 @@ class PD_UI7_API Layout {
fvec2 MaxPosition; fvec2 MaxPosition;
fvec4 WorkRect; fvec4 WorkRect;
// Scrolling // Scrolling (Only theoretical)
// Rendering must be done by the Objective that uses the Lyt
fvec2 ScrollOffset; fvec2 ScrollOffset;
bool Scrolling[2]; bool Scrolling[2];

View File

@ -24,12 +24,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include "pd/ui7/container/dragdata.hpp"
#include <pd/core/core.hpp> #include <pd/core/core.hpp>
#include <pd/ui7/io.hpp> #include <pd/ui7/io.hpp>
#include <pd/ui7/layout.hpp> #include <pd/ui7/layout.hpp>
#include <pd/ui7/pd_p_api.hpp> #include <pd/ui7/pd_p_api.hpp>
#include "pd/ui7/container/dragdata.hpp"
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {
class PD_UI7_API Menu { class PD_UI7_API Menu {
@ -87,9 +88,11 @@ public:
} }
pLayout->AddObject(r); pLayout->AddObject(r);
} }
void Sameline() { pLayout->SameLine(); } void SameLine() { pLayout->SameLine(); }
void Separator(); void Separator();
void SeparatorText(const std::string &label); void SeparatorText(const std::string &label);
bool BeginTreeNode(const ID &id);
void EndTreeNode();
void HandleFocus(); void HandleFocus();
void HandleScrolling(); void HandleScrolling();
@ -106,6 +109,7 @@ public:
ID pID; ID pID;
bool *pIsShown = nullptr; bool *pIsShown = nullptr;
bool pIsOpen = true; bool pIsOpen = true;
std::unordered_map<u32, bool> pTreeNodes;
float TitleBarHeight = 0.f; float TitleBarHeight = 0.f;
}; };

View File

@ -24,19 +24,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include "pd/ui7/flags.hpp"
#include <pd/core/core.hpp> #include <pd/core/core.hpp>
#include <pd/ui7/io.hpp> #include <pd/ui7/io.hpp>
#include <pd/ui7/menu.hpp> #include <pd/ui7/menu.hpp>
#include <pd/ui7/pd_p_api.hpp> #include <pd/ui7/pd_p_api.hpp>
#include "pd/ui7/flags.hpp"
/** /**
* Declare UI7 Version * Declare UI7 Version
* Format: 00 00 00 00 * Format: 00 00 00 00
* Major Minor Patch Build * Major Minor Patch Build
* 0x01010000 -> 1.1.0-0 * 0x01010000 -> 1.1.0-0
*/ */
#define UI7_VERSION 0x00050000 #define UI7_VERSION 0x00050100
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {
@ -57,8 +58,13 @@ public:
void AddViewPort(const ID &id, const ivec4 &vp); void AddViewPort(const ID &id, const ivec4 &vp);
void UseViewPort(const ID &id); void UseViewPort(const ID &id);
void Update(); void Update();
bool BeginMenu(const ID &id, UI7MenuFlags flags, bool *pShow = nullptr); bool BeginMenu(const ID &id, UI7MenuFlags flags = 0, bool *pShow = nullptr);
void EndMenu(); void EndMenu();
void AboutMenu(bool *show = nullptr);
void MetricsMenu(bool *show = nullptr);
void StyleEditor(bool *show = nullptr);
Li::DrawList::Ref GetDrawData() { return pIO->FDL; }
Menu::Ref pGetOrCreateMenu(const ID &id) { Menu::Ref pGetOrCreateMenu(const ID &id) {
auto menu = pMenus.find(id); auto menu = pMenus.find(id);
@ -73,6 +79,7 @@ public:
/** Current Menu */ /** Current Menu */
Menu::Ref pCurrent = nullptr; Menu::Ref pCurrent = nullptr;
std::vector<u32> pCurrentMenus; std::vector<u32> pCurrentMenus;
std::vector<u32> pDFO; /** Debug Final Order */
std::unordered_map<u32, Menu::Ref> pMenus; std::unordered_map<u32, Menu::Ref> pMenus;
}; };
} // namespace UI7 } // namespace UI7

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.22) cmake_minimum_required(VERSION 3.22)
project(pd-core LANGUAGES CXX VERSION 0.5.0) project(pd-core LANGUAGES CXX VERSION 0.5.1)
set(SRC set(SRC
source/bit_util.cpp source/bit_util.cpp

View File

@ -39,6 +39,20 @@ PD_CORE_API std::vector<u8> LoadFile2Mem(const std::string& path) {
return res; return res;
} }
PD_CORE_API std::string LoadFile2Str(const std::string& path) {
std::ifstream iff(path, std::ios::binary);
if (!iff) {
return "";
}
std::string ret;
std::string line;
while (std::getline(iff, line)) {
ret += line;
}
iff.close();
return ret;
}
PD_CORE_API u32 HashMemory(const std::vector<u8>& data) { PD_CORE_API u32 HashMemory(const std::vector<u8>& data) {
u32 hash = 4477; u32 hash = 4477;
for (auto& it : data) { for (auto& it : data) {

View File

@ -25,32 +25,98 @@ SOFTWARE.
#include <pd/core/mat.hpp> #include <pd/core/mat.hpp>
namespace PD { namespace PD {
PD_CORE_API void Mat4::Zeros() { PD_CORE_API Mat4 Mat4::RotateX(float a) {
for (int i = 0; i < 16; i++) { float c = std::cos(a);
m[i] = 0.0f; float s = std::sin(a);
} Mat4 ret = Identity();
ret(1, 1) = c;
ret(1, 2) = -s;
ret(2, 1) = s;
ret(2, 2) = c;
return ret;
} }
PD_CORE_API void Mat4::Ortho(float left, float right, float bottom, float top, PD_CORE_API Mat4 Mat4::RotateY(float a) {
float near, float far) { float c = std::cos(a);
m[0] = 2.0f / (right - left); float s = std::sin(a);
m[1] = 0.0f; Mat4 ret = Identity();
m[2] = 0.0f; ret(0, 0) = c;
m[3] = -(right + left) / (right - left); ret(0, 2) = s;
ret(2, 0) = -s;
ret(2, 2) = c;
return ret;
}
m[4] = 0.0f; PD_CORE_API Mat4 Mat4::RotateZ(float a) {
m[5] = 2.0f / (top - bottom); float c = std::cos(a);
m[6] = 0.0f; float s = std::sin(a);
m[7] = -(top + bottom) / (top - bottom); Mat4 ret = Identity();
ret(0, 0) = c;
ret(0, 1) = -s;
ret(1, 0) = s;
ret(1, 1) = c;
return ret;
}
m[8] = 0.0f; PD_CORE_API Mat4 Mat4::Rotate(fvec3 axis, float a) {
m[9] = 0.0f; float s = std::sin(a);
m[10] = -2.0f / (far - near); float c = std::cos(a);
m[11] = -(far + near) / (far - near); float t = 1.f - c;
axis = axis.Normalize();
float x = axis.x;
float y = axis.y;
float z = axis.z;
Mat4 ret = Identity();
ret(0, 0) = t * x * x + c;
ret(0, 1) = t * x * y - z * s;
ret(0, 2) = t * x * z + y * s;
m[12] = 0.0f; ret(1, 0) = t * x * y + z * s;
m[13] = 0.0f; ret(1, 1) = t * y * y + c;
m[14] = 0.0f; ret(1, 2) = t * y * z - x * s;
m[15] = 1.0f;
ret(2, 0) = t * x * z - y * s;
ret(2, 1) = t * y * z + x * s;
ret(2, 2) = t * z * z + c;
return ret;
}
PD_CORE_API Mat4 Mat4::Perspective(float fov, float aspect, float n, float f) {
float _fov = std::tan(fov / 2.f);
Mat4 ret;
ret(0, 0) = 1.f / (aspect * _fov);
ret(1, 1) = 1.f / _fov;
#ifdef __3DS__
ret(2, 3) = f * n / (n - f);
ret(2, 2) = -(-1.f) * n / (n - f);
#else
ret(2, 2) = -(f + n) / (f - n);
ret(2, 3) = -(2.f * f * n) / (f - n);
#endif
ret(3, 2) = -1.f;
ret(3, 3) = 0.0f;
return ret;
}
PD_CORE_API Mat4 Mat4::LookAt(const fvec3& pos, const fvec3& center,
const fvec3& up) {
auto f = fvec3(center - pos).Normalize();
auto s = f.Cross(up).Normalize();
auto u = s.Cross(f);
Mat4 ret = Identity();
ret(0, 0) = s.x;
ret(0, 1) = s.y;
ret(0, 2) = s.z;
ret(1, 0) = u.x;
ret(1, 1) = u.y;
ret(1, 2) = u.z;
ret(2, 0) = -f.x;
ret(2, 1) = -f.y;
ret(2, 2) = -f.z;
ret(0, 3) = -s.Dot(pos);
ret(1, 3) = -u.Dot(pos);
ret(2, 3) = f.Dot(pos);
return ret;
} }
} // namespace PD } // namespace PD

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.22) cmake_minimum_required(VERSION 3.22)
## The Core Core Library ## The Core Core Library
project(pd-drivers LANGUAGES CXX VERSION 0.5.0) project(pd-drivers LANGUAGES CXX VERSION 0.5.1)
set(SRC set(SRC
source/hid.cpp source/hid.cpp

View File

@ -26,7 +26,6 @@ SOFTWARE.
#include <pd/drivers/pd_p_api.hpp> #include <pd/drivers/pd_p_api.hpp>
namespace PD { namespace PD {
namespace Li {
PD_DEF_EXP(GfxDriver::Ref, Gfx::pGfx); PD_DEF_EXP(GfxDriver::Ref, Gfx::pGfx);
void Gfx::Init(GfxDriver::Ref d) { void Gfx::Init(GfxDriver::Ref d) {
@ -42,5 +41,4 @@ void GfxDriver::PostInit() {
std::vector<PD::u8> white(16 * 16 * 4, 0xff); std::vector<PD::u8> white(16 * 16 * 4, 0xff);
pSolid = this->LoadTex(white, 16, 16); pSolid = this->LoadTex(white, 16, 16);
} }
} // namespace Li
} // namespace PD } // namespace PD

View File

@ -5,6 +5,9 @@ namespace PD {
PD_DEF_EXP(HidDriver::Ref, Hid::pHid); PD_DEF_EXP(HidDriver::Ref, Hid::pHid);
bool HidDriver::IsEvent(Event e, Key keys) { return KeyEvents[0][e] & keys; } bool HidDriver::IsEvent(Event e, Key keys) { return KeyEvents[0][e] & keys; }
bool HidDriver::IsEvent(Event e, KbKey keys) {
return KbKeyEvents[0][e].Has(keys);
}
void HidDriver::SwapTab() { void HidDriver::SwapTab() {
auto tkd = KeyEvents[1][Event_Down]; auto tkd = KeyEvents[1][Event_Down];
@ -17,4 +20,20 @@ void HidDriver::SwapTab() {
KeyEvents[0][Event_Held] = tkh; KeyEvents[0][Event_Held] = tkh;
KeyEvents[0][Event_Up] = tku; KeyEvents[0][Event_Up] = tku;
} }
/**
* If this func has no verride, still clear the stats
* cause if they are empty this leads to a crash
*/
void HidDriver::Update() {
// Clear States
for (int i = 0; i < 2; i++) {
KeyEvents[i][Event_Down] = 0;
KeyEvents[i][Event_Held] = 0;
KeyEvents[i][Event_Up] = 0;
for (auto& it : KbKeyEvents[i]) {
it.second = Event_Null;
}
}
}
} // namespace PD } // namespace PD

View File

@ -77,6 +77,46 @@ PD_IMAGE_API void Image::Copy(const std::vector<u8>& buf, int w, int h,
} }
} }
PD_IMAGE_API void Image::FlipHorizontal() {
/**
* Dont know if i am brain dead but i think this code
* should Horizpntal flip an image
* Probably this needs some optimisation like not always calling
* Fmt2Bpp and use `* 0.5` instead of `/ 2` i guess
*/
for (int i = 0; i < pWidth / 2; i++) {
for (int j = 0; j < pHeight; j++) {
int src = (j * pWidth + i) * Fmt2Bpp(pFmt);
int dst = (j * pWidth + (pWidth - 1 - i)) * Fmt2Bpp(pFmt);
for (int k = 0; k < Fmt2Bpp(pFmt); k++) {
PD::u8 tmp = pBuffer[dst + k];
pBuffer[dst + k] = pBuffer[src + k];
pBuffer[src + k] = tmp;
}
}
}
}
PD_IMAGE_API void Image::FlipVertical() {
/**
* Dont know if i am brain dead but i think this code
* should Vertical flip an image
* Probably this needs some optimisation like not always calling
* Fmt2Bpp and use `* 0.5` instead of `/ 2` i guess
*/
for (int i = 0; i < pWidth; i++) {
for (int j = 0; j < pHeight / 2; j++) {
int src = (j * pWidth + i) * Fmt2Bpp(pFmt);
int dst = ((pHeight - 1 - j) * pWidth + i) * Fmt2Bpp(pFmt);
for (int k = 0; k < Fmt2Bpp(pFmt); k++) {
PD::u8 tmp = pBuffer[dst + k];
pBuffer[dst + k] = pBuffer[src + k];
pBuffer[src + k] = tmp;
}
}
}
}
PD_IMAGE_API void Image::Convert(Image::Ref img, Image::Format dst) { PD_IMAGE_API void Image::Convert(Image::Ref img, Image::Format dst) {
if (img->pFmt == dst) { if (img->pFmt == dst) {
return; return;
@ -93,6 +133,12 @@ PD_IMAGE_API void Image::Convert(Image::Ref img, Image::Format dst) {
img->pBuffer.resize(img->pWidth * img->pHeight * 3); img->pBuffer.resize(img->pWidth * img->pHeight * 3);
ImgConvert::RGB32toRGBA24(img->pBuffer, cpy, img->pWidth, img->pHeight); ImgConvert::RGB32toRGBA24(img->pBuffer, cpy, img->pWidth, img->pHeight);
img->pFmt = RGB; img->pFmt = RGB;
} else if (img->pFmt == Image::RGBA && dst == Image::BGRA) {
for (int i = 0; i < (img->pWidth * img->pHeight * 4); i += 4) {
u8 _tmp = img->pBuffer[i + 0];
img->pBuffer[i + 0] = img->pBuffer[i + 2];
img->pBuffer[i + 2] = _tmp;
}
} else if (img->pFmt == Image::RGBA && dst == Image::RGB565) { } else if (img->pFmt == Image::RGBA && dst == Image::RGB565) {
Convert(img, Image::RGB); Convert(img, Image::RGB);
Convert(img, Image::RGB565); Convert(img, Image::RGB565);

View File

@ -1,10 +1,13 @@
cmake_minimum_required(VERSION 3.22) cmake_minimum_required(VERSION 3.22)
project(pd-lithium LANGUAGES CXX VERSION 0.5.0) project(pd-lithium LANGUAGES CXX VERSION 0.5.1)
option(PD_LI_INCLUDE_FONTS "Include Fonts" OFF)
set(SRC set(SRC
source/drawlist.cpp source/drawlist.cpp
source/font.cpp source/font.cpp
source/fonts.cpp
source/renderer.cpp source/renderer.cpp
) )
@ -14,4 +17,10 @@ else()
pd_add_lib(pd-lithium SRC_FILES ${SRC}) pd_add_lib(pd-lithium SRC_FILES ${SRC})
endif() endif()
if(${PD_LI_INCLUDE_FONTS})
target_compile_definitions(pd-lithium PUBLIC
-DPD_LI_INCLUDE_FONTS=1
)
endif()
target_link_libraries(pd-lithium PUBLIC pd-core) target_link_libraries(pd-lithium PUBLIC pd-core)

View File

@ -33,13 +33,35 @@ namespace PD {
namespace Li { namespace Li {
PD_LITHIUM_API void DrawList::DrawSolid() { CurrentTex = Gfx::GetSolidTex(); } PD_LITHIUM_API void DrawList::DrawSolid() { CurrentTex = Gfx::GetSolidTex(); }
PD_LITHIUM_API void DrawList::Clear() {
pNumIndices = 0;
pNumVertices = 0;
pDrawList.clear();
}
PD_LITHIUM_API void DrawList::AddCommand(Command::Ref v) {
pNumIndices += v->IndexBuffer.Size();
pNumVertices += v->VertexBuffer.Size();
pDrawList.push_back(std::move(v));
}
PD_LITHIUM_API void DrawList::Merge(DrawList::Ref list) {
for (size_t i = 0; i < list->pDrawList.size(); i++) {
pNumIndices += list->pDrawList[i]->IndexBuffer.Size();
pNumVertices += list->pDrawList[i]->VertexBuffer.Size();
pDrawList.push_back(std::move(list->pDrawList[i]));
}
/** Make sure The list gets cleared */
list->Clear();
}
PD_LITHIUM_API Command::Ref DrawList::PreGenerateCmd() { PD_LITHIUM_API Command::Ref DrawList::PreGenerateCmd() {
Command::Ref cmd = Command::New(); Command::Ref cmd = Command::New();
cmd->Layer = Layer; cmd->Layer = Layer;
cmd->Index = pDrawList.size(); cmd->Index = pDrawList.size();
cmd->Tex = CurrentTex; cmd->Tex = CurrentTex;
pClipCmd(cmd.get()); pClipCmd(cmd.get());
return std::move(cmd); return cmd;
} }
PD_LITHIUM_API void DrawList::pClipCmd(Command *cmd) { PD_LITHIUM_API void DrawList::pClipCmd(Command *cmd) {

View File

@ -32,80 +32,123 @@ SOFTWARE.
#include <pd/lithium/renderer.hpp> #include <pd/lithium/renderer.hpp>
#ifdef PD_LI_INCLUDE_FONTS
#include <pd/lithium/fonts.hpp>
#endif
namespace PD { namespace PD {
namespace Li { namespace Li {
PD_LITHIUM_API void Font::LoadDefaultFont(int id, int pixel_height) {
#ifdef PD_LI_INCLUDE_FONTS
if (id < pNumFonts) {
auto font = pFontData[id];
LoadTTF(std::vector<u8>(&pFontsDataRaw[font.StartOff],
&pFontsDataRaw[font.StartOff + font.Size]),
pixel_height);
}
#endif
}
PD_LITHIUM_API void Font::LoadTTF(const std::string &path, int height) { PD_LITHIUM_API void Font::LoadTTF(const std::string &path, int height) {
/**
* Just use LoadFile2Mem which looks way cleaner
* and helps not having the font loading code twice
* when adding LoadTTF with mem support
*/
TT::Scope st("LI_LoadTTF_" + path); TT::Scope st("LI_LoadTTF_" + path);
PixelHeight = height; // Set internel pixel height auto font = PD::IO::LoadFile2Mem(path);
// Use NextPow2 to be able to use sizes between for example 16 and 32 LoadTTF(font, height);
// before it only was possible to use 8, 16, 32, 64 as size }
int texszs = BitUtil::GetPow2(height * 16);
// Load stbtt PD_LITHIUM_API void Font::pMakeAtlas(bool final, std::vector<u8> &font_tex,
int texszs, PD::Li::Texture::Ref tex) {
auto t =
Gfx::LoadTex(font_tex, texszs, texszs, Texture::RGBA32, Texture::LINEAR);
tex->CopyFrom(t);
Textures.push_back(tex);
}
PD_LITHIUM_API void Font::LoadTTF(const std::vector<u8> &data, int height) {
/**
* Some additional Info:
* Removed the stbtt get bitmapbox as we dont need to place
* the glyps nicely in the tex. next step would be using the free
* space on the y axis to get mor glyphs inside
*/
PixelHeight = height;
int texszs = PD::BitUtil::GetPow2(height * 16);
if (texszs > 1024) {
texszs = 1024; // Max size
}
stbtt_fontinfo inf; stbtt_fontinfo inf;
std::ifstream loader(path, std::ios::binary); if (!stbtt_InitFont(&inf, data.data(), 0)) {
if (!loader.is_open()) return; return;
loader.seekg(0, std::ios::end); }
size_t len = loader.tellg();
loader.seekg(0, std::ios::beg);
unsigned char *buffer = new unsigned char[len];
loader.read(reinterpret_cast<char *>(buffer), len);
loader.close();
stbtt_InitFont(&inf, buffer, 0);
// clang-format off
// Disable clang here cause dont want a garbage looking line
std::vector<PD::u8> font_tex(texszs * texszs * 4); // Create font Texture
// clang-format on
float scale = stbtt_ScaleForPixelHeight(&inf, PixelHeight); float scale = stbtt_ScaleForPixelHeight(&inf, PixelHeight);
int ascent, descent, lineGap; int ascent, descent, lineGap;
stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap); stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap);
int baseline = static_cast<int>(ascent * scale); int baseline = static_cast<int>(ascent * scale);
std::map<u32, int> buf_cache; // Cache to not render same codepoint tex twice // Cache to not render same codepoint tex twice
std::map<u32, int> buf_cache;
/// Load Codepoints std::vector<u8> font_tex(texszs * texszs * 4, 0);
auto tex = Texture::New(); auto tex = Texture::New();
fvec2 off; fvec2 off;
for (u32 ii = 0x0000; ii < 0xFFFF; ii++) {
int i = stbtt_FindGlyphIndex(&inf, ii);
if (i == 0) {
continue;
}
if (stbtt_IsGlyphEmpty(&inf, i)) {
continue;
}
Codepoint c; bool empty = true;
for (u32 ii = 0x0000; ii <= 0xFFFF; ii++) {
int gi = stbtt_FindGlyphIndex(&inf, ii);
if (gi == 0) continue;
if (stbtt_IsGlyphEmpty(&inf, gi)) continue;
int w = 0, h = 0, xo = 0, yo = 0; int w = 0, h = 0, xo = 0, yo = 0;
unsigned char *bitmap = unsigned char *bitmap =
stbtt_GetCodepointBitmap(&inf, scale, scale, i, &w, &h, &xo, &yo); stbtt_GetCodepointBitmap(&inf, scale, scale, ii, &w, &h, &xo, &yo);
int x0, y0, x1, y1; if (!bitmap || w <= 0 || h <= 0) {
stbtt_GetCodepointBitmapBox(&inf, i, scale, scale, &x0, &y0, &x1, &y1); if (bitmap) free(bitmap);
continue;
}
// Check if Codepoint exists as hash and if it is use its already written
// data
u32 hashed_map = IO::HashMemory(std::vector<u8>(bitmap, bitmap + (w * h))); u32 hashed_map = IO::HashMemory(std::vector<u8>(bitmap, bitmap + (w * h)));
if (buf_cache.find(hashed_map) != buf_cache.end()) { if (buf_cache.find(hashed_map) != buf_cache.end()) {
c = GetCodepoint(buf_cache[hashed_map]); Codepoint c = GetCodepoint(buf_cache[hashed_map]);
c.pCodepoint = i; c.pCodepoint = ii;
CodeMap[i] = c; CodeMap[ii] = c;
free(bitmap); free(bitmap);
continue; continue;
} else { } else {
buf_cache[hashed_map] = i; buf_cache[hashed_map] = ii;
} }
// Next row
if (off.x + w > texszs) { if (off.x + w > texszs) {
off.y += PixelHeight; off.y += PixelHeight;
off.x = 0; off.x = 0.0f;
}
// Bake cause we go out of the tex
if (off.y + PixelHeight > texszs) {
pMakeAtlas(false, font_tex, texszs, tex);
tex = Texture::New();
off = 0;
std::fill(font_tex.begin(), font_tex.end(), 0);
empty = true;
} }
// Set UV Data // UVs & Codepoint
Codepoint c;
fvec4 uvs; fvec4 uvs;
uvs.x = static_cast<float>(off.x) / texszs; // cast the ints to floats and not the floats...
uvs.y = static_cast<float>(off.y) / texszs; // dont know where my mind was when creating the code
uvs.z = static_cast<float>((off.x + w) / texszs); uvs.x = off.x / static_cast<float>(texszs);
uvs.w = static_cast<float>((off.y + h) / texszs); uvs.y = off.y / static_cast<float>(texszs);
uvs.z = (off.x + w) / static_cast<float>(texszs);
uvs.w = (off.y + h) / static_cast<float>(texszs);
// Flip if needed
if (Gfx::Flags() & LiBackendFlags_FlipUV_Y) { if (Gfx::Flags() & LiBackendFlags_FlipUV_Y) {
uvs.y = 1.f - uvs.y; uvs.y = 1.f - uvs.y;
uvs.w = 1.f - uvs.w; uvs.w = 1.f - uvs.w;
@ -114,11 +157,13 @@ PD_LITHIUM_API void Font::LoadTTF(const std::string &path, int height) {
c.Tex = tex; c.Tex = tex;
c.Size = fvec2(w, h); c.Size = fvec2(w, h);
c.Offset = baseline + yo; c.Offset = baseline + yo;
c.pCodepoint = ii;
// Render glyph
for (int y = 0; y < h; ++y) { for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) { for (int x = 0; x < w; ++x) {
int map_pos = (((off.y + y) * texszs + (off.x + x))) * 4; int map_pos = ((static_cast<int>(off.y) + y) * texszs +
(static_cast<int>(off.x) + x)) *
4;
font_tex[map_pos + 0] = 255; font_tex[map_pos + 0] = 255;
font_tex[map_pos + 1] = 255; font_tex[map_pos + 1] = 255;
font_tex[map_pos + 2] = 255; font_tex[map_pos + 2] = 255;
@ -126,27 +171,18 @@ PD_LITHIUM_API void Font::LoadTTF(const std::string &path, int height) {
} }
} }
empty = false;
CodeMap[ii] = c;
free(bitmap); free(bitmap);
CodeMap[i] = c;
// Small Patch to avoid some possible artifacts // offset by 1 (prevents visual glitches i had)
off.x += w + 1; off.x += w + 1;
if (off.x + w > texszs) {
off.y += PixelHeight;
if (off.y + PixelHeight > texszs) {
break;
} }
off.x = 0;
if (!empty) {
pMakeAtlas(true, font_tex, texszs, tex);
} }
} }
// Load the Texture and append to list
{
auto t = Gfx::LoadTex(font_tex, texszs, texszs, Texture::RGBA32,
Texture::LINEAR);
tex->CopyFrom(t);
}
Textures.push_back(tex);
}
PD_LITHIUM_API Font::Codepoint &Font::GetCodepoint(u32 cp) { PD_LITHIUM_API Font::Codepoint &Font::GetCodepoint(u32 cp) {
// Check if codepoijt exist or return a static invalid one // Check if codepoijt exist or return a static invalid one
@ -170,7 +206,7 @@ PD_LITHIUM_API fvec2 Font::GetTextBounds(const std::string &text, float scale) {
float lh = (float)PixelHeight * cfs; float lh = (float)PixelHeight * cfs;
size_t index = 0; size_t index = 0;
for (auto &it : wtext) { for (auto &it : wtext) {
if (it == '\0') { if (it == L'\0') {
break; break;
} }
index++; index++;
@ -179,16 +215,16 @@ PD_LITHIUM_API fvec2 Font::GetTextBounds(const std::string &text, float scale) {
continue; continue;
} }
switch (it) { switch (it) {
case '\n': case L'\n':
res.y += lh; res.y += lh;
res.x = std::max(res.x, x); res.x = std::max(res.x, x);
x = 0.f; x = 0.f;
break; break;
case '\t': case L'\t':
x += 16 * cfs; x += 16 * cfs;
break; break;
case ' ': case L' ':
x += 2 * cfs; x += 16 * cfs;
// Fall trough here to get the same result as in // Fall trough here to get the same result as in
// TextCommand if/else Section // TextCommand if/else Section
default: default:
@ -242,7 +278,8 @@ PD_LITHIUM_API void Font::CmdTextEx(std::vector<Command::Ref> &cmds,
cmd->Tex = Tex; cmd->Tex = Tex;
for (auto &jt : wline) { for (auto &jt : wline) {
auto cp = GetCodepoint(jt); auto cp = GetCodepoint(jt);
if ((cp.pInvalid && jt != '\n' && jt != '\t') && jt != '\r') { if ((cp.pInvalid && jt != L' ' && jt != L'\n' && jt != L'\t') &&
jt != L'\r') {
continue; continue;
} }
if (Tex != cp.Tex) { if (Tex != cp.Tex) {
@ -251,14 +288,14 @@ PD_LITHIUM_API void Font::CmdTextEx(std::vector<Command::Ref> &cmds,
Tex = cp.Tex; Tex = cp.Tex;
cmd->Tex = Tex; cmd->Tex = Tex;
} }
if (jt == '\t') { if (jt == L'\t') {
off.x += 16 * cfs; off.x += 16 * cfs;
} else { } else {
if (jt != ' ') { if (jt != L' ') {
if (flags & LiTextFlags_Shaddow) { if (flags & LiTextFlags_Shaddow) {
// Draw // Draw
Rect rec = Renderer::PrimRect( Rect rec = Renderer::PrimRect(
rpos + vec2(off.x + 1, off.x + (cp.Offset * cfs)) + 1, rpos + vec2(off.x + 1, off.y + (cp.Offset * cfs)) + 1,
cp.Size * cfs, 0.f); cp.Size * cfs, 0.f);
Renderer::CmdQuad(cmd.get(), rec, cp.SimpleUV, 0xff111111); Renderer::CmdQuad(cmd.get(), rec, cp.SimpleUV, 0xff111111);
} }
@ -266,10 +303,10 @@ PD_LITHIUM_API void Font::CmdTextEx(std::vector<Command::Ref> &cmds,
Rect rec = Renderer::PrimRect( Rect rec = Renderer::PrimRect(
rpos + off + fvec2(0, (cp.Offset * cfs)), cp.Size * cfs, 0.f); rpos + off + fvec2(0, (cp.Offset * cfs)), cp.Size * cfs, 0.f);
Renderer::CmdQuad(cmd.get(), rec, cp.SimpleUV, color); Renderer::CmdQuad(cmd.get(), rec, cp.SimpleUV, color);
} else {
off.x += 2 * cfs;
}
off.x += cp.Size.x * cfs + 2 * cfs; off.x += cp.Size.x * cfs + 2 * cfs;
} else {
off.x += 16 * cfs;
}
} }
} }
cmds.push_back(std::move(cmd)); cmds.push_back(std::move(cmd));

View File

@ -0,0 +1,48 @@
/*
MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifdef PD_LI_INCLUDE_FONTS
#include <pd/lithium/fonts.hpp>
/** Generated with pdfm */
namespace PD {
FontFileData pFontData[] = {
{
"ComicNeue-Bold.ttf",
0,
1,
},
{
"Roboto-Regular.ttf",
0,
1,
},
};
size_t pNumFonts = 2;
// clang-format off
PD::u8 pFontsDataRaw[] = {
0x0
};
// clang-format on
} // namespace PD
#endif

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.22) cmake_minimum_required(VERSION 3.22)
project(pd-ui7 LANGUAGES CXX VERSION 0.5.0) project(pd-ui7 LANGUAGES CXX VERSION 0.5.1)
set(SRC set(SRC
source/theme.cpp source/theme.cpp
@ -25,4 +25,4 @@ else()
pd_add_lib(pd-ui7 SRC_FILES ${SRC}) pd_add_lib(pd-ui7 SRC_FILES ${SRC})
endif() endif()
target_link_libraries(pd-ui7 PUBLIC pd-core) target_link_libraries(pd-ui7 PUBLIC pd-lithium pd-core)

View File

@ -27,7 +27,13 @@ SOFTWARE.
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {
PD_UI7_API void DynObj::Draw() { pRenFun(io, list, this); } PD_UI7_API void DynObj::Draw() { pRenFun(io, list, this); }
PD_UI7_API void DynObj::HandleInput() {}
PD_UI7_API void DynObj::HandleInput() {
if (pInp) {
pInp(io, this);
}
}
PD_UI7_API void DynObj::Update() {} PD_UI7_API void DynObj::Update() {}
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD

View File

@ -28,7 +28,13 @@ namespace UI7 {
PD_UI7_API void Label::Draw() { PD_UI7_API void Label::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); // Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
if (pCLipRectUsed) {
list->PushClipRect(pClipRect);
}
list->DrawText(FinalPos(), label, io->Theme->Get(UI7Color_Text)); list->DrawText(FinalPos(), label, io->Theme->Get(UI7Color_Text));
if (pCLipRectUsed) {
list->PopClipRect();
}
} }
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD

View File

@ -26,6 +26,7 @@ SOFTWARE.
namespace PD { namespace PD {
PD_UI7_API void UI7::IO::Update() { PD_UI7_API void UI7::IO::Update() {
/** Todo: find out if we even still use the Drawlist regestry */
u64 current = OS::GetNanoTime(); u64 current = OS::GetNanoTime();
Delta = static_cast<float>(current - LastTime) / 1000000.f; Delta = static_cast<float>(current - LastTime) / 1000000.f;
LastTime = current; LastTime = current;
@ -37,5 +38,7 @@ PD_UI7_API void UI7::IO::Update() {
DrawListRegestry.PushFront( DrawListRegestry.PushFront(
Pair<UI7::ID, Li::DrawList::Ref>("CtxBackList", Back)); Pair<UI7::ID, Li::DrawList::Ref>("CtxBackList", Back));
// RegisterDrawList("CtxBackList", Back); // RegisterDrawList("CtxBackList", Back);
NumIndices = FDL->pNumIndices;
NumVertices = FDL->pNumVertices;
} }
} // namespace PD } // namespace PD

View File

@ -37,6 +37,7 @@ Menu::Menu(const ID &id, IO::Ref io) : pIO(io), pID(id) {
PD_UI7_API void Menu::Label(const std::string &label) { PD_UI7_API void Menu::Label(const std::string &label) {
// Layout API // Layout API
auto r = Label::New(label, pIO); auto r = Label::New(label, pIO);
r->SetClipRect(fvec4(pLayout->GetPosition(), pLayout->GetSize()));
pLayout->AddObject(r); pLayout->AddObject(r);
} }
@ -118,7 +119,8 @@ PD_UI7_API void Menu::HandleFocus() {
if (!pIsOpen) { if (!pIsOpen) {
newarea = fvec4(pLayout->Pos, fvec2(pLayout->Size.x, TitleBarHeight)); newarea = fvec4(pLayout->Pos, fvec2(pLayout->Size.x, TitleBarHeight));
} }
if (Hid::IsDown(Hid::Key::Touch) && if ((Hid::IsDown(Hid::Key::Touch) ||
Hid::IsEvent(Hid::Event::Event_Down, HidKb::Kb_MouseLeft)) &&
Li::Renderer::InBox(Hid::MousePos(), newarea) && Li::Renderer::InBox(Hid::MousePos(), newarea) &&
!Li::Renderer::InBox(Hid::MousePos(), !Li::Renderer::InBox(Hid::MousePos(),
pIO->InputHandler->FocusedMenuRect)) { pIO->InputHandler->FocusedMenuRect)) {
@ -128,7 +130,10 @@ PD_UI7_API void Menu::HandleFocus() {
pIO->InputHandler->FocusedMenuRect = newarea; pIO->InputHandler->FocusedMenuRect = newarea;
} }
} }
/** Todo: (func name is self describing) */
PD_UI7_API void Menu::HandleScrolling() {} PD_UI7_API void Menu::HandleScrolling() {}
PD_UI7_API void Menu::HandleTitlebarActions() { PD_UI7_API void Menu::HandleTitlebarActions() {
// Collapse // Collapse
if (!(Flags & UI7MenuFlags_NoCollapse)) { if (!(Flags & UI7MenuFlags_NoCollapse)) {
@ -157,6 +162,21 @@ PD_UI7_API void Menu::HandleTitlebarActions() {
// clr_close_btn = UI7Color_FrameBackgroundHovered; // clr_close_btn = UI7Color_FrameBackgroundHovered;
} }
} }
// Resize logic
if (!(Flags & UI7MenuFlags_NoResize)) {
vec2 cpos = pLayout->Pos + pLayout->Size - fvec2(20);
// clr_close_btn = UI7Color_FrameBackground;
if (pIO->InputHandler->DragObject(UI7::ID(pID.GetName() + "rszs"),
fvec4(cpos, fvec2(20)))) {
fvec2 szs = pLayout->Size + (pIO->InputHandler->DragPosition -
pIO->InputHandler->DragLastPosition);
if (szs.x < 30) szs.x = 30;
if (szs.y < 30) szs.y = 30;
pLayout->Size = szs;
// clr_close_btn = UI7Color_FrameBackgroundHovered;
}
}
// Menu Movement // Menu Movement
if (!(Flags & UI7MenuFlags_NoMove)) { if (!(Flags & UI7MenuFlags_NoMove)) {
if (pIO->InputHandler->DragObject( if (pIO->InputHandler->DragObject(
@ -167,13 +187,35 @@ PD_UI7_API void Menu::HandleTitlebarActions() {
} }
pLayout->Pos = pLayout->Pos + (pIO->InputHandler->DragPosition - pLayout->Pos = pLayout->Pos + (pIO->InputHandler->DragPosition -
pIO->InputHandler->DragLastPosition); pIO->InputHandler->DragLastPosition);
// Have no ViewPort Yet :( // Keep Window In Viewport
// pLayout->Pos = std::clamp(pLayout->Pos, fvec2(10), fvec2(1270, 710)); // Maybe i need to add some operators to vec
pLayout->Pos.x = std::clamp<float>(pLayout->Pos.x, -pLayout->Size.x + 10,
pIO->CurrentViewPort.z - 10);
pLayout->Pos.y = std::clamp<float>(pLayout->Pos.y, pIO->CurrentViewPort.y,
pIO->CurrentViewPort.w - 10);
} }
} }
} }
PD_UI7_API void Menu::DrawBaseLayout() { PD_UI7_API void Menu::DrawBaseLayout() {
if (pIsOpen) { if (pIsOpen) {
/** Resize Sym (Render on Top of Everything) */
if (!(Flags & UI7MenuFlags_NoResize)) {
Container::Ref r = DynObj::New(
[](IO::Ref io, Li::DrawList::Ref l, UI7::Container *self) {
l->Layer = 1;
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(0, 20));
l->PathAdd(self->FinalPos() + self->GetSize());
l->PathAdd(self->FinalPos() + self->GetSize() - fvec2(20, 0));
l->PathFill(io->Theme->Get(UI7Color_Button));
});
r->SetSize(
fvec2(pLayout->GetSize().x, pLayout->GetSize().y - TitleBarHeight));
r->SetPos(fvec2(0, TitleBarHeight));
pLayout->AddObjectEx(r,
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
}
/** Background */
Container::Ref r = DynObj::New([](IO::Ref io, Li::DrawList::Ref l, Container::Ref r = DynObj::New([](IO::Ref io, Li::DrawList::Ref l,
UI7::Container *self) { UI7::Container *self) {
l->Layer = 0; l->Layer = 0;
@ -254,6 +296,7 @@ PD_UI7_API void Menu::DrawBaseLayout() {
} }
} }
} }
PD_UI7_API void Menu::Update() { PD_UI7_API void Menu::Update() {
HandleFocus(); HandleFocus();
if (!(Flags & UI7MenuFlags_NoTitlebar)) { if (!(Flags & UI7MenuFlags_NoTitlebar)) {
@ -262,5 +305,62 @@ PD_UI7_API void Menu::Update() {
DrawBaseLayout(); DrawBaseLayout();
pLayout->Update(); pLayout->Update();
} }
PD_UI7_API bool Menu::BeginTreeNode(const ID &id) {
// As of some notes this should work:
auto n = pTreeNodes.find(id);
if (n == pTreeNodes.end()) {
pTreeNodes[id] = false;
n = pTreeNodes.find(id);
}
fvec2 pos = pLayout->Cursor;
fvec2 tdim = pIO->Font->GetTextBounds(id.GetName(), pIO->FontScale);
fvec2 szs = tdim + fvec2(pIO->ItemSpace.x + 10, 0);
if (n->second) {
pLayout->InitialCursorOffset += 10.f;
}
// Object
auto r =
DynObj::New([=, this](IO::Ref io, Li::DrawList::Ref l, Container *self) {
fvec2 ts = self->FinalPos() + fvec2(0, 7);
fvec2 pl[2] = {fvec2(10, 5), fvec2(0, 10)};
if (n->second) {
float t = pl[0].y;
pl[0].y = pl[1].x;
pl[1].x = t;
}
l->DrawTriangleFilled(ts, ts + pl[0], ts + pl[1],
io->Theme->Get(UI7Color_FrameBackground));
l->DrawText(self->FinalPos() + fvec2(10 + io->ItemSpace.x, 0),
id.GetName(), io->Theme->Get(UI7Color_Text));
});
/** Yes this new function handler was created for tree nodes */
r->AddInputHandler([=, this](IO::Ref io, Container *self) {
if (io->InputHandler->DragObject(
ID(pID.GetName() + id.GetName()),
fvec4(self->FinalPos(), self->GetSize()))) {
if (io->InputHandler->DragReleased) {
n->second = !n->second;
}
}
});
r->SetPos(pos);
r->SetSize(szs);
/** Use Add Object as it is faster */
pLayout->AddObject(r);
return n->second;
}
PD_UI7_API void UI7::Menu::EndTreeNode() {
pLayout->InitialCursorOffset.x -= 10.f;
pLayout->Cursor.x -= 10.f;
if (pLayout->InitialCursorOffset.x < 0.f) {
pLayout->InitialCursorOffset.x = 0.f;
}
}
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD

View File

@ -21,9 +21,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <pd/ui7/ui7.hpp>
#include "pd/ui7/flags.hpp" #include "pd/ui7/flags.hpp"
#include "pd/ui7/pd_p_api.hpp" #include "pd/ui7/pd_p_api.hpp"
#include <pd/ui7/ui7.hpp>
#define UI7DHX32(x) std::format("{}: {:#08x}", #x, x)
#define UI7DTF(x) PD::Strings::FormatNanos(x)
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {
@ -32,8 +36,7 @@ PD_UI7_API std::string GetVersion(bool show_build) {
s << ((UI7_VERSION >> 24) & 0xFF) << "."; s << ((UI7_VERSION >> 24) & 0xFF) << ".";
s << ((UI7_VERSION >> 16) & 0xFF) << "."; s << ((UI7_VERSION >> 16) & 0xFF) << ".";
s << ((UI7_VERSION >> 8) & 0xFF); s << ((UI7_VERSION >> 8) & 0xFF);
if (show_build) if (show_build) s << "-" << ((UI7_VERSION) & 0xFF);
s << "-" << ((UI7_VERSION) & 0xFF);
return s.str(); return s.str();
} }
@ -63,11 +66,289 @@ PD_UI7_API bool Context::BeginMenu(const ID &id, UI7MenuFlags flags,
} }
pCurrent = pGetOrCreateMenu(id); pCurrent = pGetOrCreateMenu(id);
this->pCurrent->pIsShown = pShow; this->pCurrent->pIsShown = pShow;
this->pIO->InputHandler->CurrentMenu = id; if (pCurrent->pIsShown != nullptr) {
if (!*pCurrent->pIsShown) {
pCurrent = nullptr;
return false;
}
}
/** Probably we dont even need Input Handling in this stage */
// this->pIO->InputHandler->CurrentMenu = id;
pCurrentMenus.push_back(id);
pCurrent->Flags = flags;
if (!pCurrent->pIsOpen) {
pCurrent = nullptr;
}
return pCurrent != nullptr; return pCurrent != nullptr;
} }
PD_UI7_API void Context::Update() { pIO->Update(); } PD_UI7_API void Context::EndMenu() {
/**
* Currently it would be a better wy to handle menus as follows
*
* The folowing context will generate a new menu as normally but instead
* of true or false we have m is false (nullptr) or true (some ptr returned)
* and after that it should simply out of scope
* (This would probably require some wrapper class to find out if m goes
* out of scope)
* ```cpp
* if(auto m = ui7->BeginMenu("Test")) {
* m->Label("Show some Text");
* }
* ```
*/
if (!pCurrent) {
return;
}
pCurrent = nullptr;
// pIO->InputHandler->CurrentMenu = 0;
}
PD_UI7_API void Context::Update() {
/**
* Cause Commenting each line looks carbage...
* This function simply clears the FinalDrawList, Searches for Menu ID's in
* The sorted menu List from last frame to insert them as same order into
* the final list. After that it adds new menus to the begin to 'add' new
* menus on top. As final step the focused menu gets add to begin
* Then the menus update their Input and DraeList Generation in List Order
* and the DrawLists get Merged into the FDL in reverse Order. At end the List
* gets cleanup and io gets updated
*
* Very simple ...
*/
pIO->FDL->Clear();
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(),
pIO->InputHandler->FocusedMenu) == pCurrentMenus.end()) {
pIO->InputHandler->FocusedMenu = 0;
pIO->InputHandler->FocusedMenuRect = fvec4(0);
}
std::vector<u32> FinalList;
for (auto it : pDFO) {
if (std::find(pCurrentMenus.begin(), pCurrentMenus.end(), it) !=
pCurrentMenus.end() &&
it != pIO->InputHandler->FocusedMenu) {
FinalList.push_back(it);
}
}
for (auto it : pCurrentMenus) {
if (std::find(FinalList.begin(), FinalList.end(), it) == FinalList.end() &&
it != pIO->InputHandler->FocusedMenu) {
FinalList.push_back(it);
}
}
if (pMenus.count(pIO->InputHandler->FocusedMenu)) {
FinalList.insert(FinalList.begin(), pIO->InputHandler->FocusedMenu);
}
pDFO = FinalList;
for (auto &it : FinalList) {
this->pIO->InputHandler->CurrentMenu = it;
pMenus[it]->Update(); /** Render */
this->pIO->InputHandler->CurrentMenu = 0;
}
for (int i = (int)FinalList.size() - 1; i >= 0; i--) {
pIO->FDL->Merge(pMenus[FinalList[i]]->pLayout->GetDrawList());
}
pCurrentMenus.clear();
pIO->Update();
}
PD_UI7_API void Context::AboutMenu(bool *show) {
if (BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
auto m = pCurrent;
m->Label("Palladium UI7 " + GetVersion());
m->Separator();
m->Label("(c) 2023-2025 René Amthor");
m->Label("UI7 is licensed under the MIT License.");
m->Label("See LICENSE for more information.");
static bool show_build;
m->Checkbox("Show Build Info", show_build);
if (show_build) {
m->SeparatorText("Build Info");
m->Label("Full Version -> " + GetVersion(true));
m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t)));
m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(Li::Vertex)));
m->Label("__cplusplus -> " + std::to_string(__cplusplus));
m->Label("Compiler -> " +
Strings::GetCompilerVersion()); // + LibInfo::CompiledWith());
}
EndMenu();
}
}
PD_UI7_API void Context::MetricsMenu(bool *show) {
if (BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) {
auto m = pCurrent;
m->Label("Palladium - UI7 " + GetVersion());
m->Separator();
m->Label(
std::format("Average {:.3f} ms/f ({:.1f} FPS)",
((float)pIO->DeltaStats->GetAverage() / 1000.f),
1000.f / ((float)pIO->DeltaStats->GetAverage() / 1000.f)));
m->Label(std::format("NumVertices: {}", pIO->NumVertices));
m->Label(std::format("NumIndices: {} -> {} Tris", pIO->NumIndices,
pIO->NumIndices / 3));
m->Label("Menus: " + std::to_string(pMenus.size()));
/** Section TimeTrace */
m->SeparatorText("TimeTrace");
if (m->BeginTreeNode("Traces (" + std::to_string(OS::GetTraceMap().size()) +
")")) {
for (auto &it : OS::GetTraceMap()) {
if (m->BeginTreeNode(it.second->GetID())) {
m->Label("Diff: " + UI7DTF(it.second->GetLastDiff()));
m->Label("Protocol Len: " +
std::to_string(it.second->GetProtocol()->GetLen()));
m->Label("Average: " +
UI7DTF(it.second->GetProtocol()->GetAverage()));
m->Label("Min: " + UI7DTF(it.second->GetProtocol()->GetMin()));
m->Label("Max: " + UI7DTF(it.second->GetProtocol()->GetMax()));
m->EndTreeNode();
}
}
m->EndTreeNode();
}
m->SeparatorText("Palladium Info");
m->Label("Renderer: " + PD::Gfx::pGfx->pName);
if (m->BeginTreeNode("Input: " + PD::Hid::pHid->pName)) {
if (PD::Hid::GetFlags() & PD::HidDriver::Flags_HasKeyboard) {
m->Label("- Keyboard Supported");
}
if (PD::Hid::GetFlags() & PD::HidDriver::Flags_HasMouse) {
m->Label("- Mouse Supported");
}
if (PD::Hid::GetFlags() & PD::HidDriver::Flags_HasTouch) {
m->Label("- Touch Supported");
}
if (PD::Hid::GetFlags() & PD::HidDriver::FLags_HasGamepad) {
m->Label("- Gamepad Supported");
}
m->EndTreeNode();
}
/** Section IO */
m->SeparatorText("IO");
if (m->BeginTreeNode("Menus (" + std::to_string(pMenus.size()) + ")")) {
for (auto &it : pMenus) {
if (m->BeginTreeNode(it.second->pID.GetName())) {
m->Label("Name: " + it.second->pID.GetName());
m->Label(std::format("Pos: {}", it.second->pLayout->GetPosition()));
m->Label(std::format("Size: {}", it.second->pLayout->GetSize()));
m->Label(std::format("WorkRect: {}", it.second->pLayout->WorkRect));
m->Label(std::format("Cursor: {}", it.second->pLayout->Cursor));
if (m->BeginTreeNode(
"ID Objects (" +
std::to_string(it.second->pLayout->IDObjects.size()) + ")")) {
for (auto &jt : it.second->pLayout->IDObjects) {
m->Label(std::format("{:08X}", jt->GetID()));
}
m->EndTreeNode();
}
m->EndTreeNode();
}
}
m->EndTreeNode();
}
if (m->BeginTreeNode("Active Menus (" +
std::to_string(pCurrentMenus.size()) + ")")) {
for (auto &it : pCurrentMenus) {
if (m->BeginTreeNode(pMenus[it]->pID.GetName())) {
m->Label("Name: " + pMenus[it]->pID.GetName());
m->Label(std::format("Pos: {}", pMenus[it]->pLayout->GetPosition()));
m->Label(std::format("Size: {}", pMenus[it]->pLayout->GetSize()));
m->Label(std::format("WorkRect: {}", pMenus[it]->pLayout->WorkRect));
m->Label(std::format("Cursor: {}", pMenus[it]->pLayout->Cursor));
if (m->BeginTreeNode(
"ID Objects (" +
std::to_string(pMenus[it]->pLayout->IDObjects.size()) +
")")) {
for (auto &jt : pMenus[it]->pLayout->IDObjects) {
m->Label(std::format("{:08X}", jt->GetID()));
}
m->EndTreeNode();
}
m->EndTreeNode();
}
}
m->EndTreeNode();
}
// Well this are Li Drawlists now and they do not count their stats (yet)
/*if (m->BeginTreeNode("DrawLists (" +
std::to_string(pIO->DrawListRegestry.Size()) + ")")) {
for (auto &it : pIO->DrawListRegestry) {
if (m->BeginTreeNode(it.First.GetName())) {
m->Label("Vertices: " + std::to_string(it.Second->NumVertices));
m->Label("Indices: " + std::to_string(it.Second->NumIndices));
m->Label("Base Layer: " + std::to_string(it.Second->Base));
m->EndTreeNode();
}
}
m->EndTreeNode();
}*/
m->Label("io->Time: " + Strings::FormatMillis(pIO->Time->Get()));
m->Label(std::format("Delta: {:.3f}", pIO->Delta));
m->Label(std::format("Framerate: {:.2f}", pIO->Framerate));
m->Label(
std::format("Focused Menu: {:08X}", pIO->InputHandler->FocusedMenu));
m->Label(std::format("Dragged Object: {:08X}",
pIO->InputHandler->DraggedObject));
m->Label(std::format("DragTime: {:.2f}s",
pIO->InputHandler->DragTime->GetSeconds()));
m->Label(std::format("DragDestination: [{}]",
pIO->InputHandler->DragDestination));
m->Label(std::format("DragSource: [{}]", pIO->InputHandler->DragSourcePos));
m->Label(std::format("DragPos: [{}]", pIO->InputHandler->DragPosition));
m->Label(
std::format("DragLastPos: [{}]", pIO->InputHandler->DragLastPosition));
EndMenu();
}
}
PD_UI7_API void UI7::Context::StyleEditor(bool *show) {
if (this->BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) {
auto m = pCurrent;
m->Label("Palladium - UI7 " + GetVersion() + " Style Editor");
m->Separator();
m->DragData("MenuPadding", (float *)&pIO->MenuPadding, 2, 0.f, 100.f);
m->DragData("FramePadding", (float *)&pIO->FramePadding, 2, 0.f, 100.f);
m->DragData("ItemSpace", (float *)&pIO->ItemSpace, 2, 0.f, 100.f);
m->DragData("MinSliderSize", (float *)&pIO->MinSliderDragSize, 2, 1.f,
100.f);
m->DragData("OverScroll Modifier", &pIO->OverScrollMod, 1, 0.01f,
std::numeric_limits<float>::max(), 0.01f, 2);
m->Checkbox("Menu Border", pIO->ShowMenuBorder);
m->Checkbox("Frame Border", pIO->ShowFrameBorder);
m->SeparatorText("Theme");
if (m->Button("Dark")) {
UI7::Theme::Default(*pIO->Theme.get());
}
m->SameLine();
if (m->Button("Flashbang")) {
UI7::Theme::Flashbang(*pIO->Theme.get());
}
/// Small trick to print without prefix
#define ts(x) m->ColorEdit(std::string(#x).substr(9), &pIO->Theme->GetRef(x));
#define ts2(x) \
m->DragData(std::string(#x).substr(9), (u8 *)&pIO->Theme->GetRef(x), 4, \
(u8)0, (u8)255);
ts2(UI7Color_Background);
ts2(UI7Color_Border);
ts2(UI7Color_Button);
ts2(UI7Color_ButtonDead);
ts2(UI7Color_ButtonActive);
ts2(UI7Color_ButtonHovered);
ts2(UI7Color_Text);
ts2(UI7Color_TextDead);
ts2(UI7Color_Header);
ts2(UI7Color_HeaderDead);
ts2(UI7Color_Selector);
ts2(UI7Color_Checkmark);
ts2(UI7Color_FrameBackground);
ts2(UI7Color_FrameBackgroundHovered);
ts2(UI7Color_Progressbar);
ts2(UI7Color_ListEven);
ts2(UI7Color_ListOdd);
this->EndMenu();
}
}
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD

View File

@ -17,6 +17,8 @@ void RoundedRect(PD::Li::DrawList::Ref l, PD::fvec2 p, PD::fvec2 s, PD::u32 clr,
} }
int v = 20; int v = 20;
int TheScale = 1;
bool AboutOderSo = true;
int main() { int main() {
void *PD_INIT_DATA = nullptr; void *PD_INIT_DATA = nullptr;
@ -55,7 +57,7 @@ int main() {
#endif #endif
List->SetFont(font); List->SetFont(font);
PD::Image::Convert(img, img->RGBA); PD::Image::Convert(img, img->RGBA);
auto tex = PD::Li::Gfx::LoadTex(img->pBuffer, img->pWidth, img->pHeight); auto tex = PD::Gfx::LoadTex(img->pBuffer, img->pWidth, img->pHeight);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
auto ui7 = PD::UI7::Context::New(); auto ui7 = PD::UI7::Context::New();
@ -63,16 +65,13 @@ int main() {
ui7->AddViewPort(VpTop, PD::ivec4(0, 0, 400, 240)); ui7->AddViewPort(VpTop, PD::ivec4(0, 0, 400, 240));
ui7->UseViewPort(VpTop); ui7->UseViewPort(VpTop);
ui7->pIO->Font = font; ui7->pIO->Font = font;
PD::UI7::Menu::Ref menu = PD::UI7::Menu::New("Test", ui7->pIO);
bool open_haxx = true;
menu->pIsShown = &open_haxx;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/** MainLoop */ /** MainLoop */
#ifndef __3DS__ #ifndef __3DS__
font->DefaultPixelHeight = 32; font->DefaultPixelHeight = 32;
while (!glfwWindowShouldClose(win)) { while (!glfwWindowShouldClose(win)) {
#else #else
PD::Li::Gfx::pGfx->ViewPort = PD::ivec2(400, 240); PD::Gfx::pGfx->ViewPort = PD::ivec2(400, 240);
while (aptMainLoop()) { while (aptMainLoop()) {
#endif #endif
PD::Hid::Update(); PD::Hid::Update();
@ -80,7 +79,11 @@ int main() {
/** Auto ViewPort Resize */ /** Auto ViewPort Resize */
int wx, wy; int wx, wy;
glfwGetWindowSize(win, &wx, &wy); glfwGetWindowSize(win, &wx, &wy);
PD::Li::Gfx::pGfx->ViewPort = PD::ivec2(wx, wy); PD::Gfx::pGfx->ViewPort = PD::ivec2(wx, wy);
glViewport(0, 0, wx, wy);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
// ui7->pIO->GetViewPort(VpTop)->pSize = PD::ivec4(0, 0, wx, wy);
#endif #endif
/** Rendering some stuff */ /** Rendering some stuff */
List->DrawSolid(); List->DrawSolid();
@ -90,7 +93,10 @@ int main() {
RoundedRect(List, PD::fvec2(200, 50), 100, 0xffffffff, RoundedRect(List, PD::fvec2(200, 50), 100, 0xffffffff,
((1 + std::sin(PD::OS::GetTime() / 1000.f)) * 0.5f) * 100.f); ((1 + std::sin(PD::OS::GetTime() / 1000.f)) * 0.5f) * 100.f);
List->DrawText(PD::fvec2(50, 190), "OK", 0xffffffff); List->DrawText(PD::fvec2(50, 190), "OK", 0xffffffff);
List->DrawLine(PD::fvec2(0), PD::fvec2(1000, 600), 0xffffffff); // List->DrawLine(PD::fvec2(0), PD::fvec2(1000, 600), 0xffffffff);
List->PathAdd(500);
List->PathAdd(550);
List->PathStroke(0xff00ffff, TheScale);
// List->DrawRectFilled(PD::fvec2(10, 10), PD::fvec2(1260, 700), // List->DrawRectFilled(PD::fvec2(10, 10), PD::fvec2(1260, 700),
// 0xffffffff); // 0xffffffff);
/** Draw text */ /** Draw text */
@ -103,10 +109,12 @@ int main() {
PD::Hid::MousePos()) + PD::Hid::MousePos()) +
"\nUI7 Version: " + PD::UI7::GetVersion(), "\nUI7 Version: " + PD::UI7::GetVersion(),
0xff000000); 0xff000000);
ui7->pIO->InputHandler->CurrentMenu = menu->pID; if (ui7->BeginMenu("Test")) {
if (menu->pIsOpen) { auto menu = ui7->pCurrent;
menu->Label("Hello"); menu->Label("Hello");
menu->Label("World!"); menu->Label("World!");
menu->Checkbox("About Menu", AboutOderSo);
menu->DragData("Line", &TheScale);
if (menu->Button("Test")) { if (menu->Button("Test")) {
break; break;
} }
@ -117,9 +125,49 @@ int main() {
menu->Label( menu->Label(
std::format("Left: {}", PD::Hid::IsHeld(PD::Hid::Key::Touch))); std::format("Left: {}", PD::Hid::IsHeld(PD::Hid::Key::Touch)));
menu->DragData("Value", &v, 1); menu->DragData("Value", &v, 1);
ui7->EndMenu();
} }
menu->Update(); if (ui7->BeginMenu("Yet another Window")) {
auto menu = ui7->pCurrent;
menu->Label(std::format("this->Pos: {}", menu->pLayout->GetPosition()));
menu->Label(std::format("Vertices: {}", PD::Gfx::pGfx->VertexCounter));
menu->Label(std::format("Indices: {}", PD::Gfx::pGfx->IndexCounter));
ui7->EndMenu();
}
if (ui7->BeginMenu("#Debug (UI7)")) {
auto menu = ui7->pCurrent;
menu->Label(std::format("Framerate: {:.1f} [{:.2f}]", ui7->pIO->Framerate,
ui7->pIO->Delta));
menu->SeparatorText("Input");
menu->Label(std::format("FocusedMenu: #{:08X}",
ui7->pIO->InputHandler->FocusedMenu));
menu->Label(std::format("FocusedMenuRect: {}",
ui7->pIO->InputHandler->FocusedMenuRect));
menu->SeparatorText("Menu Order");
for (auto &it : ui7->pDFO) {
menu->Label(std::format("{}", ui7->pMenus[it]->pID.GetName()));
}
ui7->EndMenu();
}
if (ui7->BeginMenu("NoDebug")) {
auto m = ui7->pCurrent;
if (m->BeginTreeNode("Test")) {
m->Label("Hello World!");
if (m->BeginTreeNode("AnotherNode")) {
m->Label("Another Label!");
m->EndTreeNode();
}
m->EndTreeNode();
}
m->Label("Yes another Label!");
ui7->EndMenu();
}
ui7->AboutMenu(&AboutOderSo);
ui7->MetricsMenu();
ui7->StyleEditor();
PD::TT::Beg("ui7->Update");
ui7->Update(); ui7->Update();
PD::TT::End("ui7->Update");
/** Render DrawData */ /** Render DrawData */
#ifdef __3DS__ #ifdef __3DS__
C3D_FrameBegin(C3D_FRAME_SYNCDRAW); C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
@ -127,12 +175,11 @@ int main() {
C3D_RenderTargetClear(Top, C3D_CLEAR_ALL, 0x00000000, 0); C3D_RenderTargetClear(Top, C3D_CLEAR_ALL, 0x00000000, 0);
#endif #endif
PD::TT::Beg("REN"); PD::TT::Beg("REN");
PD::Li::Gfx::NewFrame(); PD::Gfx::NewFrame();
PD::Li::Gfx::RenderDrawData(List->pDrawList); PD::Gfx::RenderDrawData(List->pDrawList);
PD::Li::Gfx::RenderDrawData(menu->pLayout->GetDrawList()->pDrawList); PD::Gfx::RenderDrawData(ui7->GetDrawData()->pDrawList);
/** Clear The List */ /** Clear The List */
List->Clear(); List->Clear();
menu->pLayout->GetDrawList()->pDrawList.clear();
PD::TT::End("REN"); PD::TT::End("REN");
#ifndef __3DS__ #ifndef __3DS__
/** Do OS Specifc Stuff (swapp buffers / window buttan events) */ /** Do OS Specifc Stuff (swapp buffers / window buttan events) */

View File

@ -3,3 +3,4 @@ cmake_minimum_required(VERSION 3.22)
add_subdirectory(lazyvec) add_subdirectory(lazyvec)
add_subdirectory(ppam) add_subdirectory(ppam)
add_subdirectory(pdlm) add_subdirectory(pdlm)
add_subdirectory(pdfm)

View File

@ -1,7 +1,18 @@
cmake_minimum_required(VERSION 3.22) cmake_minimum_required(VERSION 3.22)
project(lazyvec LANGUAGES CXX VERSION 1.0.0) project(lazyvec LANGUAGES CXX VERSION 2.0.0)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED true)
add_executable(lazyvec add_executable(lazyvec
source/main.cpp source/main.cpp
source/lazyconstructors.cpp
source/lazyfuncs.cpp
source/lazyops.cpp
source/lazyoperation.cpp
source/lazytemplate.cpp
source/lazyswap.cpp
) )
target_include_directories(lazyvec PUBLIC include)

View File

@ -0,0 +1,19 @@
#pragma once
/** Header for all source file functions */
#include <format> // yes this tool requires at least c++ 20
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
namespace LVec {
const std::vector<std::string> elems = {"x", "y", "z", "w"};
std::string GenerateHeader(int n);
std::string MakeOperationFor(char op, int n);
std::string GenericOperations(int n);
std::string MakeFunctions(int n);
std::string MakeSwap(int n);
std::string MakeConstructors(int n);
} // namespace LVec

View File

@ -0,0 +1,75 @@
#include <lazyvec.hpp>
constexpr std::string_view _construct = R"text(
constexpr vec{0}() : {1} {{}}
template <typename T1>
constexpr vec{0}(T1 v) {{
{2}
}}
template <typename T1>
constexpr vec{0}(const vec{0}<T1>& v) {{
{3}
}}
constexpr explicit vec{0}({4}) : {5} {{}}{6}
)text";
constexpr std::string_view _extended3 = R"(
// Extended Constructors
template <typename T1>
constexpr explicit vec3(const vec2<T1>& xy, T1 z) {{
x = (T)xy.x;
y = (T)xy.y;
this->z = (T)z;
}}
)";
constexpr std::string_view _extended4 = R"(
// Extended Constructors
template <typename T1>
constexpr explicit vec4(const vec2<T1>& xy, const vec2<T1>& zw) {{
x = (T)xy.x;
y = (T)xy.y;
z = (T)zw.x;
w = (T)zw.y;
}}
template <typename T1>
constexpr explicit vec4(const vec3<T1>& xyz, T1 w) {{
x = (T)xyz.x;
y = (T)xyz.y;
z = (T)xyz.z;
this->w = (T)w;
}}
)";
namespace LVec {
std::string MakeConstructors(int n) {
std::stringstream s1, s2, s3, s4, s5;
for (int i = 0; i < n; i++) {
s1 << elems[i] << "(0)";
s2 << " " << elems[i] << " = (T)v;";
s3 << " " << elems[i] << " = (T)v." << elems[i] << ";";
s4 << "T " << elems[i];
s5 << elems[i] << "(" << elems[i] << ")";
if (i != n - 1) {
s1 << ", ";
s2 << std::endl;
s3 << std::endl;
s4 << ", ";
s5 << ", ";
}
}
std::string extended;
if (n == 3) {
extended = _extended3;
} else if (n == 4) {
extended = _extended4;
}
return std::format(_construct, n, s1.str(), s2.str(), s3.str(), s4.str(),
s5.str(), extended);
}
} // namespace LVec

View File

@ -0,0 +1,50 @@
#include <lazyvec.hpp>
constexpr std::string_view _funcs = R"text(
double Len() const {{ return std::sqrt(SqLen()); }}
double SqLen() const {{ return {1}; }}
template <typename T1>
double Distance(const vec{0}<T1>& v) const {{
return (*this - v).Len();
}}
vec{0}<T> Normalize() const {{
double l = Len();
if(l == 0) {{
return *this;
}}
return *this / (T)l;
}}
template <typename T1>
T Dot(const vec{0}<T1>&v) const {{
return {2};
}}
)text";
constexpr std::string_view _cross = R"text(
template <typename T1>
vec3<T> Cross(const vec3<T1>& v) const {
return vec3<T>(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
}
)text";
namespace LVec {
std::string MakeFunctions(int n) {
std::stringstream s1, s2;
for (int i = 0; i < n; i++) {
s1 << elems[i] << " * " << elems[i];
s2 << elems[i] << " * (T)v." << elems[i];
if (i != n - 1) {
s1 << " + ";
s2 << " + ";
}
}
std::string ret = std::format(_funcs, n, s1.str(), s2.str());
if (n == 3) {
ret += _cross;
}
return ret;
}
} // namespace LVec

View File

@ -0,0 +1,47 @@
#include <lazyvec.hpp>
constexpr std::string_view _op_template = R"text(
template <typename T1>
vec{0}<T>& operator{1}=(T1 v) {{
{2}
return *this;
}}
template <typename T1>
vec{0}<T>& operator{1}=(const vec{0}<T1>& v) {{
{3}
return *this;
}}
template <typename T1>
vec{0}<T> operator{1}(T1 v) const {{
return vec{0}<T>({4});
}}
template <typename T1>
vec{0}<T> operator{1}(const vec{0}<T1>& v) const {{
return vec{0}<T>({5});
}}
)text";
namespace LVec {
std::string MakeOperationFor(char op, int n) {
const std::string& toff = " ";
// Create for streams for the operations functions
std::stringstream s1, s2, s3, s4;
for (int i = 0; i < n; i++) {
s1 << toff << elems[i] << " " << op << "= (T)v;";
s2 << toff << elems[i] << " " << op << "= (T)v." << elems[i] << ";";
s3 << elems[i] << " " << op << " (T)v";
s4 << elems[i] << " " << op << " (T)v." << elems[i];
if (i != n - 1) {
s1 << std::endl;
s2 << std::endl;
s3 << ", ";
s4 << ", ";
}
}
return std::format(_op_template, n, op, s1.str(), s2.str(), s3.str(),
s4.str());
}
} // namespace LVec

View File

@ -0,0 +1,30 @@
#include <lazyvec.hpp>
/**
* Diffrence between lazyoperation.cpp and lazyops.cpp ?
* One is for Operators with an input sym like +, -, * or /
* the other (this) is for generic operations
*/
constexpr std::string_view _generic_ops = R"text(
vec{0} operator-() const {{ return vec{0}({1}); }}
template <typename T1>
bool operator==(const vec{0}<T1>& v) const {{ return {2}; }}
template <typename T1>
bool operator!=(const vec{0}<T1>& v) const {{ return !(*this == v); }}
)text";
namespace LVec {
std::string GenericOperations(int n) {
std::stringstream s1, s2;
for (int i = 0; i < n; i++) {
s1 << "-" << elems[i];
s2 << elems[i] << " == (T)v." << elems[i];
if (i != n - 1) {
s1 << ", ";
s2 << " && ";
}
}
return std::format(_generic_ops, n, s1.str(), s2.str());
}
} // namespace LVec

View File

@ -0,0 +1,25 @@
#include <lazyvec.hpp>
#include <unordered_set>
namespace LVec {
std::string MakeSwap(int n) {
std::stringstream s;
std::unordered_set<std::string> done;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
std::string a = elems[i];
std::string b = elems[j];
/** Make sure we generate nothing twice */
if (a == b || done.count(b + a)) {
continue;
}
s << " void Swap" << (char)toupper(a[0]) << (char)toupper(b[0])
<< "() {\n";
s << " T t = " << a << ";\n " << a << " = " << b << ";\n";
s << " " << b << " = t;\n }\n";
done.insert(a + b);
}
}
return s.str();
}
} // namespace LVec

View File

@ -0,0 +1,77 @@
#include <lazyvec.hpp>
constexpr std::string_view _template = R"text(#pragma once
/*
MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// This file is generated by lazyvec 2.0.0
#include <pd/core/common.hpp>
{7}
namespace PD {{
template <typename T>
class vec{0} {{
public:
{1}
// Constructors
{2}
// Operations
{3}
// Generic Operations
{4}
// Functions
{5}
// Swap Functions
{6}
}};
using fvec{0} = vec{0}<float>;
using ivec{0} = vec{0}<int>;
using dvec{0} = vec{0}<double>;
}} // namespace PD
)text";
namespace LVec {
std::string GenerateHeader(int n) {
std::stringstream ops, data, extended;
for (int i = 0; i < n; i++) {
data << "T " << elems[i] << ";" << std::endl;
}
ops << MakeOperationFor('+', n);
ops << MakeOperationFor('-', n);
ops << MakeOperationFor('*', n);
ops << MakeOperationFor('/', n);
if (n > 2) {
extended << "// Extended includes (rename if you use other filenames/paths)"
<< std::endl;
extended << "#include <vec2.hpp>" << std::endl;
if (n == 4) {
extended << "#include <vec3.hpp>" << std::endl;
}
}
return std::format(_template, n, data.str(), MakeConstructors(n), ops.str(),
GenericOperations(n), MakeFunctions(n), MakeSwap(n),
extended.str());
}
} // namespace LVec

View File

@ -21,194 +21,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <fstream>
#include <iostream>
#include <string>
#include <unordered_set>
#include <vector>
const char* license_text = R"(/*
MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
)";
const std::vector<std::string> elems = {"x", "y", "z", "w"};
void MakeOperationFor(std::fstream& off, char op, int n) {
off << " template <typename T1>\n";
off << " vec" << n << "<T>& operator" << op << "=(T1 v) {\n";
for (int i = 0; i < n; i++) {
off << " " << elems[i] << " " << op << "= (T)v;\n";
}
off << " return *this;\n";
off << " }\n\n";
off << " template <typename T1>\n";
off << " vec" << n << "<T>& operator" << op << "=(const vec" << n
<< "<T1>& v) {\n";
for (int i = 0; i < n; i++) {
off << " " << elems[i] << " " << op << "= (T)v." << elems[i] << ";\n";
}
off << " return *this;\n";
off << " }\n\n";
off << " template <typename T1>\n";
off << " vec" << n << "<T> operator" << op << "(T1 v) const {\n";
off << " return vec" << n << "<T>(";
for (int i = 0; i < n; i++) {
if (i > 0) off << ", ";
off << elems[i] << " " << op << " (T)v";
}
off << ");\n }\n\n";
off << " template <typename T1>\n";
off << " vec" << n << "<T> operator" << op << "(const vec" << n
<< "<T1>& v) const {\n";
off << " return vec" << n << "<T>(";
for (int i = 0; i < n; i++) {
if (i > 0) off << ", ";
off << elems[i] << " " << op << " (T)v." << elems[i];
}
off << ");\n }\n\n";
}
void SwapHaxx(std::fstream& off, int n) {
std::unordered_set<std::string> done;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
std::string a = elems[i];
std::string b = elems[j];
/** Make sure we generate nothing twice */
if (a == b || done.count(b + a)) {
continue;
}
off << " void Swap" << (char)toupper(a[0]) << (char)toupper(b[0])
<< "() {\n";
off << " T t = " << a << ";\n " << a << " = " << b << ";\n";
off << " " << b << " = t;\n }\n";
done.insert(a + b);
}
}
}
void GenerateVec(int n) {
if (n < 2 || n > 4) {
std::cout << "Only 2 to 4 supported.\n";
return;
}
std::fstream off("vec" + std::to_string(n) + ".hpp", std::ios::out);
off << "#pragma once\n" << std::endl;
off << license_text << std::endl;
off << "// This file is generated by lazyvec\n#include "
"<pd/core/common.hpp>\n\n";
off << "namespace PD {" << std::endl;
off << "template <typename T>\nclass vec" << n << " {\npublic:\n";
for (int i = 0; i < n; i++) {
off << " T " << elems[i] << ";\n";
}
off << "\n";
off << " vec" << n << "(): ";
for (int i = 0; i < n; i++) {
if (i > 0) {
off << ", ";
}
off << elems[i] << "(0)";
}
off << " {}" << std::endl;
// Magic Construtor (support for anytype vec)
off << " template <typename T1>\n";
off << " explicit vec" << n << "(T1 v) {\n";
for (int i = 0; i < n; i++) {
off << " " << elems[i] << " = (T)v;\n";
}
off << " }\n\n";
// Magic Constructor 2
off << " template <typename T1>\n";
off << " explicit vec" << n << "(vec" << n << "<T1> v) {\n";
for (int i = 0; i < n; i++) {
off << " " << elems[i] << " = (T)v. " << elems[i] << ";\n";
}
off << " }\n\n";
off << " vec" << n << "(";
for (int i = 0; i < n; i++) {
if (i > 0) off << ", ";
off << "T " << elems[i];
}
off << ") : ";
for (int i = 0; i < n; i++) {
if (i > 0) off << ", ";
off << elems[i] << "(" << elems[i] << ")";
}
off << " {}\n\n";
MakeOperationFor(off, '+', n);
MakeOperationFor(off, '-', n);
MakeOperationFor(off, '*', n);
MakeOperationFor(off, '/', n);
off << " vec" << n << " operator-() const {return vec" << n << "(";
for (int i = 0; i < n; i++) {
off << "-" << elems[i];
if (i != n - 1) {
off << ", ";
}
}
off << ");}\n\n";
off << " bool operator==(const vec" << n << "& v) const { return ";
for (int i = 0; i < n; i++) {
off << elems[i] << " == v." << elems[i];
if (i != n - 1) {
off << " && ";
}
}
off << ";}\n";
off << " bool operator!=(const vec" << n
<< "&v) const { return !(*this == v); }\n\n";
off << " double Len() const {return std::sqrt(SqLen()); }\n";
off << " double SqLen() const { return ";
for (int i = 0; i < n; i++) {
off << elems[i] << " * " << elems[i];
if (i != n - 1) {
off << " + ";
}
}
off << "; }\n\n";
SwapHaxx(off, n);
off << "};\n";
off << "using fvec" << n << " = vec" << n << "<float>;\n";
off << "using dvec" << n << " = vec" << n << "<double>;\n";
off << "using ivec" << n << " = vec" << n << "<int>;\n";
off << "}\n";
off.close();
}
/** /**
* Yet another Stupid Code generation tool * Yet another Stupid Code generation tool
* Why ? * Why ?
@ -216,11 +28,21 @@ void GenerateVec(int n) {
* manually writeup vec2 to vec4 * manually writeup vec2 to vec4
*/ */
#include <iostream>
#include <lazyvec.hpp>
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (argc != 2) { if (argc != 2) {
std::cout << argv[0] << " <num (2 to 4)>" << std::endl; std::cout << argv[0] << " <num (2 to 4)>" << std::endl;
return 0; return 0;
} }
GenerateVec(std::stoi(argv[1])); int l = std::stoi(argv[1]);
if (l < 2 || l > 4) {
std::cout << argv[0] << " <num (2 to 4)>" << std::endl;
return 0;
}
std::ofstream f("vec" + std::to_string(l) + ".hpp");
f << LVec::GenerateHeader(l);
f.close();
return 0; return 0;
} }

11
tools/pdfm/CMakeLists.txt Normal file
View File

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.22)
project(pdfm LANGUAGES CXX VERSION 1.0.0)
### Requires C++ 20
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED true)
add_executable(pdfm
source/main.cpp
)

167
tools/pdfm/source/main.cpp Normal file
View File

@ -0,0 +1,167 @@
/*
MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// C++ 20 capable compiler required (eg. force use
// self compiled clang on debian based systems)
#include <filesystem>
#include <format>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
constexpr std::string_view pdfh_text = R"(#pragma once
/*
MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifdef PD_LI_INCLUDE_FONTS
#include <pd/core/common.hpp>
/** Generated with pdfm */
namespace PD {
struct FontFileData {
std::string Name;
u32 StartOff;
u32 Size;
};
extern FontFileData pFontData[];
extern size_t pNumFonts;
extern PD::u8 pFontsDataRaw[];
} // namespace PD
#endif
)";
constexpr std::string_view pdfs_text = R"(/*
MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifdef PD_LI_INCLUDE_FONTS
#include <pd/lithium/fonts.hpp>
/** Generated with pdfm */
namespace PD {{
FontFileData pFontData[] = {{{0}
}};
size_t pNumFonts = {1};
// clang-format off
PD::u8 pFontsDataRaw[] = {{
{2}
}};
// clang-format on
}} // namespace PD
#endif
)";
std::string File2HexSequence(const std::string& path) {
std::string ret;
std::ifstream iff(path, std::ios::binary);
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(iff), {});
iff.close();
for (size_t i = 0; i < buffer.size(); i++) {
ret += std::format("0x{:x},", (int)buffer[i]);
if ((i % 100) == 0 && i != 0) {
ret += '\n';
}
}
return ret;
}
std::string MakeEntry(const std::string& name, unsigned int off,
unsigned int size) {
std::string ret = "\n {\n";
ret += " \"" + name + "\",\n";
ret += " " + std::to_string(off) + ",\n";
ret += " " + std::to_string(size) + ",\n";
ret += " },";
return ret;
}
/**
* Tool to create in code embeded fonts
*/
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cout << argv[0] << " <file1> <file2>..." << std::endl;
return 0;
}
std::string entries;
std::string filez;
unsigned int pNumEntries = 0;
for (int i = 1; i < argc; i++) {
size_t off = filez.size();
std::string t = File2HexSequence(argv[i]);
filez += t;
entries += MakeEntry(std::filesystem::path(argv[i]).filename().string(),
off, t.size());
pNumEntries++;
}
std::fstream off("fonts.hpp", std::ios::out);
off << pdfh_text;
off.close();
off.open("fonts.cpp", std::ios::out);
off << std::format(pdfs_text, entries, pNumEntries, filez);
off.close();
return 0;
}

View File

@ -28,7 +28,9 @@ SOFTWARE.
#include <iostream> #include <iostream>
#include <string> #include <string>
const char* license_text = R"(/* constexpr std::string_view ppa_text = R"(#pragma once
/*
MIT License MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7) Copyright (c) 2024 - 2025 René Amthor (tobid7)
@ -50,35 +52,34 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
)";
constexpr std::string_view ppa_text = /** Generated with ppam */
"#pragma once\n\n{0}\n"
"/** Generated with ppam */\n\n" #ifdef _WIN32 // Windows (MSVC Tested)
"#ifdef _WIN32 // Windows (MSVC Tested)\n" #ifdef {0}_BUILD_SHARED
"#ifdef {1}_BUILD_SHARED\n" #define {0}_API __declspec(dllexport)
"#define {1}_API __declspec(dllexport)\n" #else
"#else\n" #define {0}_API __declspec(dllimport)
"#define {1}_API __declspec(dllimport)\n" #endif
"#endif\n" #elif defined(__APPLE__) // macOS (untested yet)
"#elif defined(__APPLE__) // macOS (untested yet)\n" #ifdef {0}_BUILD_SHARED
"#ifdef {1}_BUILD_SHARED\n" #define {0}_API __attribute__((visibility("default")))
"#define {1}_API __attribute__((visibility(\"default\")))\n" #else
"#else\n" #define {0}_API
"#define {1}_API\n" #endif
"#endif\n" #elif defined(__linux__) // Linux (untested yet)
"#elif defined(__linux__) // Linux (untested yet)\n" #ifdef {0}_BUILD_SHARED
"#ifdef {1}_BUILD_SHARED\n" #define {0}_API __attribute__((visibility("default")))
"#define {1}_API __attribute__((visibility(\"default\")))\n" #else
"#else\n" #define {0}_API
"#define {1}_API\n" #endif
"#endif\n" #elif defined(__3DS__) // 3ds Specific
"#elif defined(__3DS__) // 3ds Specific\n" // Only Static supported
"// Only Static supported\n" #define {0}_API
"#define {1}_API\n" #else
"#else\n" #define {0}_API
"#define {1}_API\n" #endif
"#endif\n"; )";
/** /**
* Tool to generate the `pd_p_api.hpp` (Palladium Platform Api) * Tool to generate the `pd_p_api.hpp` (Palladium Platform Api)
@ -91,7 +92,7 @@ int main(int argc, char* argv[]) {
return 0; return 0;
} }
std::fstream off("pd_p_api.hpp", std::ios::out); std::fstream off("pd_p_api.hpp", std::ios::out);
off << std::format(ppa_text, license_text, argv[1]); off << std::format(ppa_text, argv[1]);
off.close(); off.close();
return 0; return 0;
} }