24 Commits
Author SHA1 Message Date
tobid7 3575a6787d hotfix 2025-12-28 21:38:41 +01:00
tobid7 7fc7a2ecb9 QoL Changes
fix timetrace last diff
2025-12-27 23:35:23 +01:00
tobid7 03f65e069f Add TextMapSystem WIP 2025-12-24 18:17:58 +01:00
tobid7 c618c616fe Fix UI7 Crash by safe deleting the elements 2025-12-24 15:05:05 +01:00
tobid7 ac281dc7a9 Update
- Add data getter to DrawList
- Add NoOOS (Out Of screen Rendering) flag to text renderer (requires a textbox)
- UI7 Label Wrapping (optinal and beta)
2025-12-23 19:20:31 +01:00
tobid7 0cb5de882f Fixes and function additions
- Fixed Text pos at NoCollapse flag
- Fix Button Input Api (HandleScrolling after layout Update)
- Add getter for IO and Current Menu
- Add AdObject func wrappers to Menu
2025-12-20 19:25:20 +01:00
tobid7 b3d621a847 Add LayerOptimisation / QoL change 2025-12-19 21:08:32 +01:00
tobid7 4ad00cd2be pd-3ds: Add sysfont loader
- add support for Alpha only textures in rendering
2025-12-19 21:07:57 +01:00
tobid7 1e35dbd743 ReAdd text shorting 2025-12-18 21:51:48 +01:00
tobid7 803fa5cdb5 Remove custom standard lib
Why?? cause it was russian roulette with pointer access stuff etc
2025-12-17 10:02:05 +01:00
tobid7 66d3825481 bknd-3ds: implement libpicasso to load shader 2025-12-17 09:25:36 +01:00
tobid7 6c38aa6f21 Adding and fixing stuff
- Fix HexChar2Int
- Remove some devisions in tween engine
- Add PathAdd function for x, y seperated instead of fvec2
- Readd text wrapping (rd7-palladium maybe)
2025-12-15 22:16:19 +01:00
tobid7 f19c947fc3 Road to 0.6.0
- readd the c++ linear allocator for 3ds
- start switching from PD::Vec to std::vector
- Add Color::Hex as constexpr for compiletime color converts
- Add FNV Hasing functions
- Make UI7 ids be able to be generated at compile time
- Added a Throw Function (for whatever)
- Added HexCHar2Int (replaces the lookup table)
- Made u128 fully constexpr
2025-12-10 19:02:54 +01:00
tobid7 91754558f7 Fix the floating color bug :) 2025-12-06 22:30:37 +01:00
tobid7 8328181a2a Merge branch 'devel050' of https://dev.npid7.de/tobid7/palladium into devel050 2025-10-24 09:18:29 +02:00
tobid7 be230bef6b lithium: Fix text Spacing 2025-10-22 20:58:02 +02:00
tobid7 c2bff368d4 lithium: Fix text Spacing 2025-10-21 08:55:51 +02:00
tobid7 0ecf559fbb # Small Update
- Start some work on scrolling
2025-10-18 17:00:35 +02:00
tobid7 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
tobid7 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
tobid7 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
tobid7 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
tobid7 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
tobid7 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
96 changed files with 3051 additions and 1504 deletions
+1
View File
@@ -1,2 +1,3 @@
build/ build/
.cache .cache
.vscode
+3
View File
@@ -1,3 +1,6 @@
[submodule "backends/desktop/glfw"] [submodule "backends/desktop/glfw"]
path = backends/desktop/glfw path = backends/desktop/glfw
url = https://github.com/glfw/glfw url = https://github.com/glfw/glfw
[submodule "backends/3ds/libpicasso"]
path = backends/3ds/libpicasso
url = https://github.com/npid7/libpicasso
+1 -1
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.6.0)
# 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)
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2024 - 2025 tobid7 Copyright (c) 2024 - 2025 René Amthor tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+3 -3
View File
@@ -1,13 +1,13 @@
cmake_minimum_required(VERSION 3.22) cmake_minimum_required(VERSION 3.22)
project(pd-3ds LANGUAGES CXX VERSION 0.5.0) project(pd-3ds LANGUAGES CXX VERSION 0.6.0)
set(SRC set(SRC
source/bknd-gfx.cpp source/bknd-gfx.cpp
source/bknd-hid.cpp source/bknd-hid.cpp
source/pd-3ds.cpp source/pd-3ds.cpp
) )
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/libpicasso)
pd_add_lib(pd-3ds SRC_FILES ${SRC}) pd_add_lib(pd-3ds SRC_FILES ${SRC})
target_include_directories(pd-3ds PUBLIC include) target_include_directories(pd-3ds PUBLIC include)
target_link_libraries(pd-3ds PUBLIC m palladium ctru citro3d) target_link_libraries(pd-3ds PUBLIC m palladium ctru citro3d pica::pica)
+2 -1
View File
@@ -28,5 +28,6 @@ SOFTWARE.
#include <pd-3ds/bknd-hid.hpp> #include <pd-3ds/bknd-hid.hpp>
namespace PD { namespace PD {
PD::Li::Font::Ref LoadSystemFont();
void Init(void* data = nullptr); void Init(void* data = nullptr);
} } // namespace PD
+4 -21
View File
@@ -27,21 +27,10 @@ SOFTWARE.
#include <3ds.h> #include <3ds.h>
#include <citro3d.h> #include <citro3d.h>
#include <pd-3ds/linearAllocator.hpp>
#include <pd/lithium/lithium.hpp> #include <pd/lithium/lithium.hpp>
namespace PD { namespace PD {
template <typename T>
class LinearAlloc : public Allocator<T> {
public:
LinearAlloc() = default;
~LinearAlloc() = default;
/** Never forget the sizeof(T) again (most painful bug i created) */
T* Allocate(size_t n) override { return (T*)linearAlloc(n * sizeof(T)); }
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 +50,12 @@ 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; std::vector<Li::Vertex, LinearAllocator<Li::Vertex>> VertexBuffer;
Vec<u16, LinearAlloc<u16>> IndexBuffer; std::vector<u16, LinearAllocator<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 std::vector<u8> pRawShader;
PD::u32 NumVtx;
PD::u32 NumIdx;
}; };
} // namespace Li
} // namespace PD } // namespace PD
@@ -0,0 +1,49 @@
#pragma once
#include <3ds.h>
#include <pd/core/common.hpp>
// Custom C++ Allocator class to interface with libctru linear heap memory
// based on this guide:
// https://johnfarrier.com/custom-allocators-in-c-high-performance-memory-management/
namespace PD {
template <typename T>
class LinearAllocator {
public:
using value_type = T;
LinearAllocator() noexcept = default;
template <typename U>
constexpr LinearAllocator(const LinearAllocator<U>&) noexcept {}
T* allocate(std::size_t n) {
if (n > max_size()) {
throw std::runtime_error("[PD] LinearAllocator: Bad alloc!");
}
return static_cast<T*>(linearAlloc(n * sizeof(T)));
}
void deallocate(T* p, std::size_t) noexcept { linearFree(p); }
template <class U, class... Args>
void construct(U* p, Args&&... args) {
::new ((void*)p) U(std::forward<Args>(args)...);
}
template <class U>
void destroy(U* p) {
p->~U();
}
friend bool operator==(const LinearAllocator, const LinearAllocator) {
return true;
}
friend bool operator!=(const LinearAllocator, const LinearAllocator) {
return false;
}
// Use linearSpace free as max_size to not allocate out of bounds
// or to b eable to see a crash report screen.
size_t max_size() const noexcept { return linearSpaceFree(); }
};
} // namespace PD
+51 -43
View File
@@ -23,8 +23,8 @@ SOFTWARE.
*/ */
#include <pd-3ds/bknd-gfx.hpp> #include <pd-3ds/bknd-gfx.hpp>
#include <pica.hpp>
/// @brief Shader Code (Unused as i dont want to use libpicasso here (yet))
const char* LIShaderCTR = R"( const char* LIShaderCTR = R"(
; LI7 Shader ; LI7 Shader
; Constants ; Constants
@@ -62,41 +62,55 @@ const char* LIShaderCTR = R"(
.end .end
)"; )";
// clang-format off
unsigned char li_shader[] = {
0x44, 0x56, 0x4c, 0x42, 0x1, 0x0, 0x0, 0x0, 0xa4, 0x0, 0x0, 0x0, 0x44, 0x56, 0x4c, 0x50, 0x0, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x98, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x1, 0xf0, 0x7, 0x4e, 0x2, 0x8, 0x2, 0x8, 0x3, 0x18, 0x2, 0x8, 0x4, 0x28, 0x2, 0x8, 0x5, 0x38, 0x2, 0x8, 0x6, 0x10, 0x40, 0x4c, 0x7, 0xf1, 0x27, 0x22, 0x8, 0x10, 0x21, 0x4c, 0x0, 0x0, 0x0, 0x88, 0xac, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa1, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x62, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0xaf, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xd5, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x56, 0x4c, 0x45, 0x2, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x6c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x74, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x2, 0x0, 0x5f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x0, 0x1, 0x1, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1, 0x0, 0xf, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x13, 0x0, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0, 0x0,
};
// clang-format on
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
} }
void FragCfg(GPU_TEXCOLOR clr) {
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL);
C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvInit(env);
switch (clr) {
case GPU_A4:
case GPU_A8:
case GPU_L4:
case GPU_L8:
C3D_TexEnvSrc(env, C3D_Alpha, GPU_TEXTURE0);
C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE);
C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE);
break;
default:
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0);
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
break;
}
}
void GfxC3D::Init() { void GfxC3D::Init() {
VertexBuffer.Resize(4 * 8192); VertexBuffer.resize(4 * 8192);
IndexBuffer.Resize(6 * 8192); IndexBuffer.resize(6 * 8192);
Flags |= LiBackendFlags_FlipUV_Y; Flags |= LiBackendFlags_FlipUV_Y;
ShaderCode = DVLB_ParseFile((uint32_t*)li_shader, li_shader_size); pRawShader = Pica::AssembleCode(LIShaderCTR);
ShaderCode = DVLB_ParseFile((uint32_t*)&pRawShader[0], pRawShader.size());
shaderProgramInit(&Shader); shaderProgramInit(&Shader);
shaderProgramSetVsh(&Shader, &ShaderCode->DVLE[0]); shaderProgramSetVsh(&Shader, &ShaderCode->DVLE[0]);
pLocProjection = pLocProjection =
@@ -119,10 +133,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,16 +143,13 @@ 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); 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);
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL); // Mat4 proj = Mat4::Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f);
C3D_TexEnv* env = C3D_GetTexEnv(0); // C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, pLocProjection, (C3D_Mtx*)&proj);
C3D_TexEnvInit(env);
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0);
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
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;
@@ -155,13 +165,11 @@ void GfxC3D::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) {
Commands[index]->ScissorOn == ScissorEnabled && Commands[index]->ScissorOn == ScissorEnabled &&
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++;
} }
@@ -174,13 +182,14 @@ void GfxC3D::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) {
} else { } else {
C3D_SetScissor(GPU_SCISSOR_DISABLE, 0, 0, 0, 0); C3D_SetScissor(GPU_SCISSOR_DISABLE, 0, 0, 0, 0);
} }
FragCfg(((C3D_Tex*)Tex->Address)->fmt);
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);
} }
C3D_DepthTest(true, GPU_GREATER, GPU_WRITE_ALL); C3D_DepthTest(true, GPU_GREATER, GPU_WRITE_ALL);
} }
@@ -208,7 +217,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 +249,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
+2
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;
+97 -1
View File
@@ -22,15 +22,111 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <3ds.h>
#include <palladium> #include <palladium>
#include <pd-3ds.hpp> #include <pd-3ds.hpp>
namespace PD { namespace PD {
PD::Li::Font::Ref LoadSystemFont() {
TT::Scope st("LI_SystemFont"); // Trace loading time
Li::Font::Ref ret = Li::Font::New();
fontEnsureMapped(); // Call this to be sure the font is mapped
// Get some const references for system font loading
const auto fnt = fontGetSystemFont();
const auto fnt_info = fontGetInfo(fnt);
const auto glyph_info = fontGetGlyphInfo(fnt);
// Resize the Texture list by the num of sysfont textures
ret->Textures.resize(glyph_info->nSheets + 1);
/// Modify the Pixel Height by 1.1f to fit the
/// Size og ttf font Rendering
ret->PixelHeight = glyph_info->cellHeight;
// Load the Textures and make sure they don't auto unload
for (size_t i = 0; i < glyph_info->nSheets; i++) {
auto stex = Li::Texture::New();
auto tx = new C3D_Tex;
tx->data = fontGetGlyphSheetTex(fnt, i);
tx->fmt = (GPU_TEXCOLOR)glyph_info->sheetFmt;
tx->size = glyph_info->sheetSize;
tx->width = glyph_info->sheetWidth;
tx->height = glyph_info->sheetHeight;
tx->param = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) |
GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) |
GPU_TEXTURE_WRAP_S(GPU_REPEAT) | GPU_TEXTURE_WRAP_T(GPU_REPEAT);
tx->border = 0xffffffff;
tx->lodParam = 0;
stex->Address = (Li::TexAddress)tx;
stex->Size = fvec2(tx->width, tx->height);
stex->UV = fvec4(0, 1, 1, 0);
ret->Textures[i] = stex;
}
std::vector<unsigned int> charSet;
// Write the Charset into a vector
for (auto cmap = fnt_info->cmap; cmap; cmap = cmap->next) {
if (cmap->mappingMethod == CMAP_TYPE_DIRECT) {
if (cmap->codeEnd >= cmap->codeBegin) {
charSet.reserve(charSet.size() + cmap->codeEnd - cmap->codeBegin + 1);
for (auto i = cmap->codeBegin; i <= cmap->codeEnd; ++i) {
if (cmap->indexOffset + (i - cmap->codeBegin) == 0xFFFF) break;
charSet.emplace_back(i);
}
}
} else if (cmap->mappingMethod == CMAP_TYPE_TABLE) {
if (cmap->codeEnd >= cmap->codeBegin) {
charSet.reserve(charSet.size() + cmap->codeEnd - cmap->codeBegin + 1);
for (auto i = cmap->codeBegin; i <= cmap->codeEnd; ++i) {
if (cmap->indexTable[i - cmap->codeBegin] == 0xFFFF) continue;
charSet.emplace_back(i);
}
}
} else if (cmap->mappingMethod == CMAP_TYPE_SCAN) {
charSet.reserve(charSet.size() + cmap->nScanEntries);
for (unsigned i = 0; i < cmap->nScanEntries; ++i) {
if (cmap->scanEntries[i].code >= cmap->codeBegin &&
cmap->scanEntries[i].code <= cmap->codeEnd) {
if (cmap->scanEntries[i].glyphIndex != 0xFFFF) {
charSet.emplace_back(cmap->scanEntries[i].code);
}
}
}
} else {
continue;
}
}
// Sort the charset and make sure all values are unique
std::sort(charSet.begin(), charSet.end());
charSet.erase(std::unique(charSet.begin(), charSet.end()));
// Setup the Codepoint map by the charset
for (auto cp : charSet) {
int gidx = fontGlyphIndexFromCodePoint(fnt, cp);
if (gidx >= 0xFFFF) continue;
Li::Font::Codepoint codepoint;
fontGlyphPos_s dat;
fontCalcGlyphPos(&dat, fnt, gidx, GLYPH_POS_CALC_VTXCOORD, 1.f, 1.f);
codepoint.pCodepoint = cp;
codepoint.SimpleUV = fvec4(dat.texcoord.left, dat.texcoord.top,
dat.texcoord.right, dat.texcoord.bottom);
if (dat.sheetIndex < (int)ret->Textures.size()) {
codepoint.Tex = ret->Textures[dat.sheetIndex];
} else {
codepoint.pInvalid = true;
}
codepoint.Size = fvec2(dat.vtxcoord.right, dat.vtxcoord.bottom);
codepoint.Offset = 0;
ret->CodeMap[cp] = codepoint;
}
return ret;
}
void Init(void* data) { 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
@@ -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; std::vector<Li::Vertex> VertexBuffer;
PD::Vec<PD::u16> IndexBuffer; std::vector<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
@@ -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
+33 -29
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;
@@ -186,13 +190,11 @@ void GfxGL2::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) {
Commands[index]->ScissorOn == ScissorOn && Commands[index]->ScissorOn == ScissorOn &&
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
+109 -1
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
+1 -1
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
+6 -1
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})
+32 -15
View File
@@ -24,6 +24,7 @@ SOFTWARE.
*/ */
#include <pd/core/common.hpp> #include <pd/core/common.hpp>
#include <pd/core/strings.hpp>
namespace PD { namespace PD {
class PD_CORE_API Color { class PD_CORE_API Color {
@@ -59,24 +60,40 @@ class PD_CORE_API Color {
* @param a Optional Alpha Value (Defaults to 1.0f) * @param a Optional Alpha Value (Defaults to 1.0f)
* @note There is no Check if the number is between 0.0 and 1.0 * @note There is no Check if the number is between 0.0 and 1.0
*/ */
constexpr Color(float r, float g, float b, float a = 1.f) { constexpr Color(float r, float g, float b, float a = 1.f)
r = static_cast<u8>(255.f * r); : r(static_cast<u8>(255.f * r)),
g = static_cast<u8>(255.f * g); g(static_cast<u8>(255.f * g)),
b = static_cast<u8>(255.f * b); b(static_cast<u8>(255.f * b)),
a = static_cast<u8>(255.f * a); a(static_cast<u8>(255.f * a)) {}
}
/** /**
* Constructor for Hex Input * Constructor for Hex Input (is abel to run at compile time xD)
* @param hex Hex String in `#ffffff` or `#ffffffff` format * @param hex Hex String in `#ffffff` or `#ffffffff` format
*/ */
Color(const std::string& hex) { Hex(hex); } constexpr Color(const std::string_view& hex) { Hex(hex); }
/** /**
* Create Color Object by Hex String * Create Color Object by Hex String (at compile time btw)
* @param hex Hex String in `#ffffff` or `#ffffffff` format * @param hex Hex String in `#ffffff` or `#ffffffff` format
* @return Color class itself * @return Color class itself
*/ */
Color& Hex(const std::string& hex); constexpr Color& Hex(const std::string_view& hex) {
if (!(hex.length() == 7 || hex.length() == 9)) {
throw "[PD] Color: hex string is not rgb or rgba!";
}
r = PD::Strings::HexChar2Int(hex[1]) * 16 +
PD::Strings::HexChar2Int(hex[2]);
g = PD::Strings::HexChar2Int(hex[3]) * 16 +
PD::Strings::HexChar2Int(hex[4]);
b = PD::Strings::HexChar2Int(hex[5]) * 16 +
PD::Strings::HexChar2Int(hex[6]);
if (hex.length() == 9) {
a = PD::Strings::HexChar2Int(hex[7]) * 16 +
PD::Strings::HexChar2Int(hex[8]);
} else {
a = 255;
}
return *this;
}
/** /**
* Convert this Color Object to Hex string * Convert this Color Object to Hex string
* @param rgba [default false] sets if 8 or 6 digit color should be returned * @param rgba [default false] sets if 8 or 6 digit color should be returned
@@ -90,7 +107,7 @@ class PD_CORE_API Color {
* @param p Amount (supports -1.0 to 1.0 for use of sine) * @param p Amount (supports -1.0 to 1.0 for use of sine)
* @return Class Reference * @return Class Reference
*/ */
Color& Fade(const Color& color, float p) { constexpr Color& Fade(const Color& color, float p) {
a = static_cast<u8>((color.a - a) * ((p + 1.f) / 2)); a = static_cast<u8>((color.a - a) * ((p + 1.f) / 2));
b = static_cast<u8>((color.b - b) * ((p + 1.f) / 2)); b = static_cast<u8>((color.b - b) * ((p + 1.f) / 2));
g = static_cast<u8>((color.g - g) * ((p + 1.f) / 2)); g = static_cast<u8>((color.g - g) * ((p + 1.f) / 2));
@@ -102,12 +119,12 @@ class PD_CORE_API Color {
* Get 32Bit Color Value * Get 32Bit Color Value
* @return 32Bit Color Value (ABGR iirc) * @return 32Bit Color Value (ABGR iirc)
*/ */
u32 Get() const { return (a << 24) | (b << 16) | (g << 8) | r; } constexpr u32 Get() const { return (a << 24) | (b << 16) | (g << 8) | r; }
/** /**
* Get The Luminance of the Color * Get The Luminance of the Color
* @return luminance (from 0.0 to 1.0) * @return luminance (from 0.0 to 1.0)
*/ */
float Luminance() const { constexpr float Luminance() const {
// For Reference https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness // For Reference https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
return (0.3 * (r / 255.f) + 0.59 * (g / 255.f) + 0.11 * (b / 255.f)); return (0.3 * (r / 255.f) + 0.59 * (g / 255.f) + 0.11 * (b / 255.f));
} }
@@ -115,13 +132,13 @@ class PD_CORE_API Color {
* Check if the Color is Light or Dark * Check if the Color is Light or Dark
* @return true if light * @return true if light
*/ */
bool IsLight() const { return (Luminance() >= 0.5); } constexpr bool IsLight() const { return (Luminance() >= 0.5); }
/** /**
* Operator to cast Color to 32Bit Value * Operator to cast Color to 32Bit Value
* @return 32Bit Color Value * @return 32Bit Color Value
*/ */
operator u32() const { return Get(); } constexpr operator u32() const { return Get(); }
/** Public Access Data section */ /** Public Access Data section */
u8 r; u8 r;
+6
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>
@@ -31,8 +32,10 @@ SOFTWARE.
#include <fstream> #include <fstream>
#include <functional> #include <functional>
#include <iostream> #include <iostream>
#include <list>
#include <map> #include <map>
#include <memory> #include <memory>
#include <numbers>
#include <sstream> #include <sstream>
#include <stack> #include <stack>
#include <string> #include <string>
@@ -60,6 +63,9 @@ SOFTWARE.
#define PD_BIT(x) (1 << x) #define PD_BIT(x) (1 << x)
namespace PD { namespace PD {
[[noreturn]] inline void Throw(const std::string& str) {
throw std::runtime_error("[PD] " + str);
}
/** Types */ /** Types */
using u8 = unsigned char; using u8 = unsigned char;
using u16 = unsigned short; using u16 = unsigned short;
+2 -1
View File
@@ -25,11 +25,12 @@ SOFTWARE.
#include <pd/core/bit_util.hpp> #include <pd/core/bit_util.hpp>
#include <pd/core/color.hpp> #include <pd/core/color.hpp>
#include <pd/core/fnv.hpp>
#include <pd/core/io.hpp> #include <pd/core/io.hpp>
#include <pd/core/mat.hpp> #include <pd/core/mat.hpp>
#include <pd/core/sl/sl.hpp>
#include <pd/core/strings.hpp> #include <pd/core/strings.hpp>
#include <pd/core/timer.hpp> #include <pd/core/timer.hpp>
#include <pd/core/timetrace.hpp> #include <pd/core/timetrace.hpp>
#include <pd/core/tween.hpp> #include <pd/core/tween.hpp>
#include <pd/core/u128.hpp>
#include <pd/core/vec.hpp> #include <pd/core/vec.hpp>
+21 -19
View File
@@ -2,8 +2,7 @@
/* /*
MIT License MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Copyright (c) 2024 - 2025 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -28,24 +27,27 @@ SOFTWARE.
namespace PD { namespace PD {
/** /**
* Custom Allocator for Custom Vec and probably other stuff in future * FNV-1a 32Bit hasing function
* https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
*/ */
template <typename T> constexpr u32 FNV1A32(std::string_view str) {
class Allocator { u32 ret = 0x811c9dc5; // Offset basis
public: for (auto& it : str) {
Allocator() = default; ret ^= it;
~Allocator() = default; ret *= 0x01000193; // Prime
virtual T* Allocate(size_t n) { return new T[n]; }
virtual T* AllocateRaw(size_t n) {
return reinterpret_cast<T*>(::operator new(sizeof(T) * n));
} }
virtual void DeallocateRaw(T* ptr) { operator delete(ptr); } return ret;
virtual void Deallocate(T* ptr) { delete[] ptr; } }
template <typename... Args> /**
void Construct(T* ptr, Args&&... args) { * FNV-1a 64Bit hasing function
new (ptr) T(std::forward<Args>(args)...); * https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
*/
constexpr u64 FNV1A64(std::string_view str) {
u64 ret = 0xcbf29ce484222325; // Offset basis
for (auto& it : str) {
ret ^= it;
ret *= 0x00000100000001b3; // Prime
}
return ret;
} }
void Destroy(T* ptr) { ptr->~T(); }
};
} // namespace PD } // namespace PD
+20 -35
View File
@@ -2,8 +2,7 @@
/* /*
MIT License MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Copyright (c) 2024 - 2025 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -24,47 +23,33 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
// This file is based on fvec4
#include <pd/core/common.hpp> #include <pd/core/common.hpp>
#include <pd/core/sl/vector.hpp> #include <pd/core/vec4.hpp>
namespace PD { namespace PD {
/** class fquat : public fvec4 {
* Custom Stack class (caus std::stack ofsten lead to memory coruption) 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) {}
template <typename T, typename Alloc = Allocator<T>> constexpr fquat(const fvec4& v) : fvec4(v) {}
class Stack {
public:
Stack() = default;
explicit Stack(size_t cap) : pVec(cap) {}
void Push(const T& val) { pVec.Add(val); } static fquat Identity() { return fquat(0.f, 0.f, 0.f, 1.f); }
void Pop() { constexpr fquat Conjugate() const { return fquat(-x, -y, -z, w); }
if (pVec.Size() == 0) { fquat Inverse() const {
exit(1); float len = SqLen();
if (len == 0.0f) {
return fquat();
} }
pVec.PopBack(); return Conjugate() / len;
} }
T& Top() { fquat operator*(const fquat& v) const {
if (pVec.Size() == 0) { return fquat(w * v.x + x * v.w + y * v.z - z * v.y,
exit(1); 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);
} }
return pVec[pVec.Size() - 1];
}
const T& Top() const {
if (pVec.Size() == 0) {
exit(1);
}
return pVec[pVec.Size() - 1];
}
bool IsEmpty() const { return pVec.Size() == 0; }
size_t Size() const { return pVec.Size(); }
void Clear() { pVec.Clear(); }
private:
Vec<T, Alloc> pVec;
}; };
} // namespace PD } // namespace PD
+6
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
+109 -8
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
-71
View File
@@ -1,71 +0,0 @@
#pragma once
/*
MIT License
Copyright (c) 2024 - 2025 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.
*/
#include <pd/core/common.hpp>
#include <pd/core/sl/list.hpp>
#include <pd/core/sl/pair.hpp>
namespace PD {
template <typename K, typename V, size_t bucket_count = 10>
class HashMap {
public:
HashMap() {}
~HashMap() {}
void Insert(const K& k, const V& v) {
size_t idx = Hash(k);
auto& bukket = pBuckets[idx];
for (auto& it : bukket) {
if (it.First == k) {
it.Second = v;
return;
}
}
bukket.PushBack(Pair(k, v));
}
bool Contains(const K& k) const {
size_t idx = Hash(k);
auto& bukket = pBuckets[idx];
for (auto& it : bukket) {
if (it.First == k) {
return true;
}
}
return false;
}
void Clear() {
for (size_t i = 0; i < bucket_count; i++) {
pBuckets[i].Clear();
}
}
size_t Hash(const K& k) const { return std::hash<K>{}(k) % bucket_count; }
PD::List<PD::Pair<K, V>> pBuckets[bucket_count];
};
} // namespace PD
-210
View File
@@ -1,210 +0,0 @@
#pragma once
/*
MIT License
Copyright (c) 2024 - 2025 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.
*/
#include <pd/core/common.hpp>
namespace PD {
template <typename T>
class List {
public:
List() {}
~List() {}
struct Node {
Node(const T& v) : Data(v) {}
T Data;
Node* Prev = nullptr;
Node* Next = nullptr;
};
class Iterator {
public:
Iterator(Node* n) : pNode(n) {}
T& operator*() { return pNode->Data; }
Iterator& operator++() {
pNode = pNode->Next;
return *this;
}
bool operator!=(const Iterator& o) const { return pNode != o.pNode; }
Node* pNode = nullptr;
};
void PushFront(const T& val) {
Node* node = new Node(val);
// node->Data = val;
node->Prev = nullptr;
node->Next = pHead;
if (pHead) {
pHead->Prev = node;
}
pHead = node;
if (!pTail) {
pTail = node;
}
pSize++;
}
void PushBack(const T& val) {
Node* node = new Node(val);
// node->Data = val;
node->Prev = pTail;
node->Next = nullptr;
if (pTail) {
pTail->Next = node;
}
pTail = node;
if (!pHead) {
pHead = node;
}
pSize++;
}
void PopFront() {
if (!pHead) {
return;
}
Node* t = pHead;
pHead = pHead->Next;
if (pHead) {
pHead->Prev = nullptr;
} else {
pTail = nullptr;
}
delete t;
pSize--;
}
void PopBack() {
if (!pTail) {
return;
}
Node* t = pTail;
pTail = pTail->Prev;
if (pTail) {
pTail->Next = nullptr;
} else {
pHead = nullptr;
}
delete t;
pSize--;
}
void Clear() {
while (pHead) {
PopFront();
}
}
void Remove(const T& v) {
Node* s = pHead;
while (s) {
if (s->Data == v) {
if (s->Prev) {
s->Prev->Next = s->Next;
} else {
pHead = s->Next;
}
if (s->Next) {
s->Next->Prev = s->Prev;
} else {
pTail = s->Prev;
}
delete s;
pSize--;
return;
}
s = s->Next;
}
}
void Reverse() {
Node* cur = pHead;
while (cur) {
Node* temp = cur->Prev;
cur->Prev = cur->Next;
cur->Next = temp;
cur = cur->Prev;
}
Node* temp = pHead;
pHead = pTail;
pTail = temp;
}
T& Front() {
if (pHead) {
return pHead->Data;
}
// Need a List Empty Error Here (exceptions are disabled on 3ds)
exit(1);
}
const T& Front() const {
if (pHead) {
return pHead->Data;
}
// Need a List Empty Error Here (exceptions are disabled on 3ds)
exit(1);
}
T& Back() {
if (pTail) {
return pTail->Data;
}
// Need a List Empty Error Here (exceptions are disabled on 3ds)
exit(1);
}
const T& Back() const {
if (pTail) {
return pTail->Data;
}
// Need a List Empty Error Here (exceptions are disabled on 3ds)
exit(1);
}
size_t Size() const { return pSize; }
Iterator begin() { return Iterator(pHead); }
Iterator end() { return Iterator(nullptr); }
private:
Node* Find(const T& v) const {
Node* t = pHead;
while (t) {
if (t->Data == v) {
return t;
}
t = t->Next;
}
return nullptr;
}
Node* pHead = nullptr;
Node* pTail = nullptr;
size_t pSize = 0;
};
} // namespace PD
-165
View File
@@ -1,165 +0,0 @@
#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.
*/
#include <pd/core/common.hpp>
#include <pd/core/sl/allocator.hpp>
namespace PD {
/**
* Open Access Vector class (Alternative to std::vector)
*/
template <typename T, typename Alloc = Allocator<T>>
class Vec {
public:
Vec() {
pData = pAllocator.Allocate(2);
pCap = 2;
Clear();
pPos = 0;
};
Vec(const size_t& Size) {
pData = pAllocator.Allocate(Size + 2);
pCap = Size + 2;
Clear();
pPos = Size;
}
Vec(const size_t& Size, const T& v) {
pData = pAllocator.Allocate(Size + 2);
pCap = Size + 2;
Clear();
pPos = Size;
std::fill_n(pData, Size, v);
}
Vec(const T* s, const T* e) {
pData = pAllocator.Allocate(2);
pCap = 2;
Clear();
pPos = 0;
Resize(e - s);
std::copy_n(s, e - s, pData);
}
Vec(const Vec& v) {
pCap = v.pCap;
pPos = v.pPos;
pData = pAllocator.Allocate(pCap);
for (size_t i = 0; i < pPos; i++) {
pData[i] = v.pData[i];
}
}
~Vec() { pAllocator.Deallocate(pData); }
void Add(const T& v) {
if (pPos >= pCap) {
Reserve(pCap * 2);
}
pData[pPos++] = v;
}
void PopBack() {
if (pPos == 0) return;
pPos--;
}
T Pop() {
if (pPos == 0) {
// Todo: LOG
exit(1);
}
return pData[pPos--];
}
T& At(const size_t& Idx) {
if (Idx >= pPos) {
// Log
exit(1);
}
return pData[Idx];
}
const T& At(const size_t& Idx) const {
if (Idx >= pPos) {
// Log
exit(1);
}
return pData[Idx];
}
T& operator[](const size_t& Idx) { return At(Idx); }
const T& operator[](const size_t& Idx) const { return At(Idx); }
void operator+=(T v) { Add(v); }
T* Begin() { return pData; }
const T* Begin() const { return pData; }
T* End() { return pData + pPos; }
const T* End() const { return pData + pPos; }
// Support: `for(auto& it : Vec)` //
T* begin() { return pData; }
const T* begin() const { return pData; }
T* end() { return pData + pPos; }
const T* end() const { return pData + pPos; }
T* Data() { return pData; }
T* Data() const { return pData; }
size_t Size() const { return pPos; }
size_t Capacity() const { return pCap; }
void Clear() {
// Avoid memset to support std::string for now
// probably revert this decision based if it lacks performance
// or make it a setting
std::fill(pData, pData + pCap, T());
pPos = 0;
}
void Reserve(const size_t& Size) {
if (Size <= pCap) return;
T* tmp = pAllocator.Allocate(Size);
std::fill(tmp, tmp + Size, T());
std::copy(pData, pData + pCap, tmp);
pAllocator.Deallocate(pData);
pData = tmp;
pCap = Size;
}
void Resize(size_t Size) {
if (Size < pPos) {
pPos = Size;
} else if (Size > pCap) {
Reserve(Size);
}
std::fill(pData + pPos, pData + Size, T());
pPos = Size;
}
// Allocator
Alloc pAllocator;
// Data Reference Pointer
T* pData;
// Capacity
size_t pCap;
// Current Position (Size)
size_t pPos;
};
} // namespace PD
+7
View File
@@ -30,6 +30,13 @@ namespace PD {
* Set of String Utillity Functions * Set of String Utillity Functions
*/ */
namespace Strings { namespace Strings {
constexpr int HexChar2Int(char c) {
/** Imagine man hat ne lookup table dafür verwendet :/ */
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'a' && c <= 'f') return 10 + (c - 'a');
if (c >= 'A' && c <= 'F') return 10 + (c - 'A');
return -1; // Error
}
/** /**
* Check if a String ends with a specific extension * Check if a String ends with a specific extension
* @param str Input string * @param str Input string
+4 -1
View File
@@ -182,6 +182,7 @@ class Res {
*/ */
void SetEnd(u64 v) { void SetEnd(u64 v) {
end = v; end = v;
diff = end - start;
protocol->Add(GetLastDiff()); protocol->Add(GetLastDiff());
} }
/** /**
@@ -194,7 +195,7 @@ class Res {
* Get Last Diffrence between end and start * Get Last Diffrence between end and start
* @return end - start * @return end - start
*/ */
u64 GetLastDiff() { return end - start; } u64 GetLastDiff() { return diff; }
/** /**
* Get Protcol Reference * Get Protcol Reference
* @return Protocol Ref * @return Protocol Ref
@@ -208,6 +209,8 @@ class Res {
u64 start; u64 start;
/** End Time */ /** End Time */
u64 end; u64 end;
/** Last Diff */
u64 diff;
/** Protocol */ /** Protocol */
TimeStats::Ref protocol; TimeStats::Ref protocol;
}; };
+11 -11
View File
@@ -60,7 +60,7 @@ class Tween {
* @param delta deltatime * @param delta deltatime
*/ */
void Update(float delta) { void Update(float delta) {
time += delta / 1000.f; time += delta * 0.001f;
if (time > tend) { if (time > tend) {
finished = true; finished = true;
time = tend; time = tend;
@@ -162,10 +162,10 @@ class Tween {
return -(end - start) * t * (t - 2) + start; return -(end - start) * t * (t - 2) + start;
break; break;
case EaseInOutQuad: case EaseInOutQuad:
t = time / (tend / 2); t = time / (tend * 0.5f);
if (t < 1) return (end - start) / 2 * t * t + start; if (t < 1) return (end - start) * 0.5f * t * t + start;
t--; t--;
return -(end - start) / 2 * (t * (t - 2) - 1) + start; return -(end - start) * 0.5f * (t * (t - 2) - 1) + start;
break; break;
case EaseInCubic: case EaseInCubic:
t = time / tend; t = time / tend;
@@ -177,20 +177,20 @@ class Tween {
return (end - start) * (t * t * t + 1) + start; return (end - start) * (t * t * t + 1) + start;
break; break;
// case EaseInOutCubic: // case EaseInOutCubic:
// t = time / (tend / 2); // t = time / (tend *0.5f);
// if (t < 1) return (end - start) / 2 * t * t * t + start; // if (t < 1) return (end - start) *0.5f * t * t * t + start;
// t--; // t--;
// return (end - start) / 2 * (t * t * t * 2) + start; // return (end - start) *0.5f * (t * t * t * 2) + start;
// break; // break;
case EaseInSine: case EaseInSine:
return -(end - start) * cos(time / tend * (M_PI / 2)) + (end - start) + return -(end - start) * cos(time / tend * (M_PI * 0.5f)) +
start; (end - start) + start;
break; break;
case EaseOutSine: case EaseOutSine:
return (end - start) * sin(time / tend * (M_PI / 2)) + start; return (end - start) * sin(time / tend * (M_PI * 0.5f)) + start;
break; break;
case EaseInOutSine: case EaseInOutSine:
return -(end - start) / 2 * (cos(M_PI * time / tend) - 1) + start; return -(end - start) * 0.5f * (cos(M_PI * time / tend) - 1) + start;
break; break;
default: // Linear default: // Linear
+127
View File
@@ -0,0 +1,127 @@
#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();
}
constexpr u128 operator+(const u128& v) const {
u128 ret;
ret.pLow = pLow + v.pLow;
ret.pHigh = pHigh + v.pHigh + (ret.pLow < pLow);
return ret;
}
constexpr u128 operator&(const u128& v) const {
return u128(pLow & v.pLow, pHigh & v.pHigh);
}
constexpr 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)));
}
constexpr 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);
}
constexpr u128& operator|=(const u128& v) {
pLow |= v.pLow;
pHigh |= v.pHigh;
return *this;
}
constexpr u128 operator|(const u128& v) const {
return u128(pLow | v.pLow, pHigh | v.pHigh);
}
constexpr u128& operator&=(const u128& v) {
pLow &= v.pLow;
pHigh &= v.pHigh;
return *this;
}
constexpr 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;
// }
constexpr 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...
*/
constexpr explicit operator bool() const { return pLow != 0 || pHigh != 0; }
/** Deprecated way to handle `flag & SomeFlag` */
constexpr bool Has(const u128& v) const {
return pLow & v.pLow || pHigh & v.pHigh;
}
constexpr 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
+3 -3
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);
} }
}; };
+42 -9
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
+58 -10
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
+62 -17
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
+20 -16
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,24 @@ 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 SetViewPort(int w, int h) { pGfx->SetViewPort(PD::ivec2(w, h)); }
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
+83 -1
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;
}; };
+18 -16
View File
@@ -2,8 +2,7 @@
/* /*
MIT License MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Copyright (c) 2024 - 2025 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -24,20 +23,23 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <pd/core/common.hpp> #include <pd/core/core.hpp>
namespace PD { namespace PD {
/** class Snd {
* Function to get Arraysize for any type using modern c++ to public:
* get the size at compiletime instead of runtime Snd(const std::string& name = "NullSnd") : pName(name) {};
* @note this function only works for Arrays declared as ~Snd() = default;
* type arr[size] and not for pointer references.
* This function will precalculate the size at compile time PD_SHARED(Snd);
* while keeping the code clean to not hardcode arraysizes
* into functions like std::fill_n virtual void Init() {}
*/ virtual void Deinit() {}
template <typename T, size_t N> virtual bool Done(int buf_idx) {}
constexpr size_t ArraySize(T (&)[N]) noexcept { virtual void Update(int buf_idx, void* data) {}
return N; virtual bool IsChannelPlaying(int chn) {}
} virtual bool IsChannelPaused(int chn) {}
const std::string pName = "NullSnd";
};
} // namespace PD } // namespace PD
+5 -1
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]; }
-23
View File
@@ -55,28 +55,5 @@ void RGB32toRGBA24(std::vector<u8> &out, const std::vector<u8> &in,
*/ */
PD_IMAGE_API void Reverse32(std::vector<u8> &buf, const int &w, const int &h); PD_IMAGE_API void Reverse32(std::vector<u8> &buf, const int &w, const int &h);
PD_IMAGE_API void ReverseBuf(std::vector<u8> &buf, size_t bpp, int w, int h); PD_IMAGE_API void ReverseBuf(std::vector<u8> &buf, size_t bpp, int w, int h);
/**
* Convert RGB24 to RGBA32 by adding a 4th alpha value set to 255
* to every pixel
* @param out Result List
* @param in Input Buffer List (rgb24)
* @param w width of the image
* @param h height of the image
*/
PD_IMAGE_API
void RGB24toRGBA32(PD::Vec<u8> &out, const PD::Vec<u8> &in, const int &w,
const int &h);
PD_IMAGE_API
void RGB32toRGBA24(PD::Vec<u8> &out, const PD::Vec<u8> &in, const int &w,
const int &h);
/**
* Reverse 32 (RGBA -> ABGR || ABGR -> RGBA)
* @param buf Buffer to convert
* @param w width
* @param h height
*/
PD_IMAGE_API void Reverse32(PD::Vec<u8> &buf, const int &w, const int &h);
PD_IMAGE_API void ReverseBuf(PD::Vec<u8> &buf, size_t bpp, int w, int h);
} // namespace ImgConvert } // namespace ImgConvert
} // namespace PD } // namespace PD
+10 -4
View File
@@ -37,17 +37,23 @@ class Command {
PD_UNIQUE(Command); PD_UNIQUE(Command);
Command& AddIdx(const u16& idx) { Command& AddIdx(const u16& idx) {
IndexBuffer.Add(VertexBuffer.Size() + idx); IndexBuffer.push_back(VertexBuffer.size() + idx);
return *this;
}
Command& AddIdxs(const u16& a, const u16& b, const u16& c) {
IndexBuffer.push_back(VertexBuffer.size() + a);
IndexBuffer.push_back(VertexBuffer.size() + b);
IndexBuffer.push_back(VertexBuffer.size() + c);
return *this; return *this;
} }
Command& AddVtx(const Vertex& v) { Command& AddVtx(const Vertex& v) {
VertexBuffer.Add(std::move(v)); VertexBuffer.push_back(std::move(v));
return *this; return *this;
} }
PD::Vec<Vertex> VertexBuffer; std::vector<Vertex> VertexBuffer;
PD::Vec<u16> IndexBuffer; std::vector<u16> IndexBuffer;
ivec4 ScissorRect; ivec4 ScissorRect;
bool ScissorOn = false; bool ScissorOn = false;
int Layer; int Layer;
+51 -16
View File
@@ -61,9 +61,33 @@ 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);
/**
* Copy another drawlist to this drawist.
* This is important for static prerendered Drawlists
* @param list DrawList Reference to copy from
*/
void Copy(DrawList::Ref list);
/**
* Optimize a Drawlist to a more or less perfect order
* to reduce drawcall overhead... This function also uses
* the Layersystem to keep specific stuff in the correct order
*/
void Optimize();
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 Layer(int l) { this->pLayer = l; }
int Layer() { return this->pLayer; }
void LayerUp() { this->pLayer++; }
void LayerDown() { this->pLayer--; }
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; }
@@ -89,7 +113,7 @@ class PD_LITHIUM_API DrawList {
* Extended Draw Text Function * Extended Draw Text Function
*/ */
void DrawTextEx(const fvec2& p, const std::string& text, u32 color, void DrawTextEx(const fvec2& p, const std::string& text, u32 color,
LiTextFlags flags, fvec2 box = fvec2(0.f)); LiTextFlags flags, const fvec2& box = fvec2(0.f));
void DrawLine(const fvec2& a, const fvec2& b, u32 color, int t = 1); void DrawLine(const fvec2& a, const fvec2& b, u32 color, int t = 1);
/** /**
* Take list of points and display it as a line on screen * Take list of points and display it as a line on screen
@@ -98,7 +122,7 @@ class PD_LITHIUM_API DrawList {
* @param flags Additional Flags (Close for go back to starting point) * @param flags Additional Flags (Close for go back to starting point)
* @param thickness Thickness of the Line * @param thickness Thickness of the Line
*/ */
void DrawPolyLine(const Vec<fvec2>& points, u32 clr, u32 flags = 0, void DrawPolyLine(const std::vector<fvec2>& points, u32 clr, u32 flags = 0,
int thickness = 1); int thickness = 1);
/** /**
* Take a List ofpoints and display it as Filled Shape * Take a List ofpoints and display it as Filled Shape
@@ -106,7 +130,7 @@ class PD_LITHIUM_API DrawList {
* @param points List of Points * @param points List of Points
* @param clr Color of the shape * @param clr Color of the shape
*/ */
void DrawConvexPolyFilled(const Vec<fvec2>& points, u32 clr); void DrawConvexPolyFilled(const std::vector<fvec2>& points, u32 clr);
// SECTION: PATH API // // SECTION: PATH API //
@@ -116,20 +140,28 @@ class PD_LITHIUM_API DrawList {
* @param num_points Number of Positions you want to add * @param num_points Number of Positions you want to add
*/ */
void PathReserve(size_t num_points) { void PathReserve(size_t num_points) {
pPath.Reserve(pPath.Size() + num_points); pPath.reserve(pPath.size() + num_points);
} }
/** /**
* Clear current Path * Clear current Path
* @note PathStroke and PathFill will automatically clear * @note PathStroke and PathFill will automatically clear
*/ */
void PathClear() { pPath.Clear(); } void PathClear() { pPath.clear(); }
/** /**
* Add a Point to the Path * Add a Point to the Path
* @note Keep in mind that this function is used for * @note Keep in mind that this function is used for
* setting the starting point * setting the starting point
* @param v Position to add * @param v Position to add
*/ */
void PathAdd(const fvec2& v) { pPath.Add(v); } void PathAdd(const fvec2& v) { pPath.push_back(v); }
/**
* Add a Point to the Path
* @note Keep in mind that this function is used for
* setting the starting point
* @param x X Position to add
* @param y Y Position to add
*/
void PathAdd(float x, float y) { pPath.push_back(fvec2(x, y)); }
/** /**
* Path Stroke Create Line from point to point * Path Stroke Create Line from point to point
* @note For Primitives like Rect or Triangle mak sure to use * @note For Primitives like Rect or Triangle mak sure to use
@@ -140,7 +172,7 @@ class PD_LITHIUM_API DrawList {
*/ */
void PathStroke(u32 clr, int thickness = 1, u32 flags = 0) { void PathStroke(u32 clr, int thickness = 1, u32 flags = 0) {
DrawPolyLine(pPath, clr, flags, thickness); DrawPolyLine(pPath, clr, flags, thickness);
pPath.Clear(); pPath.clear();
} }
/** /**
* Fill a Path with a Color * Fill a Path with a Color
@@ -150,7 +182,7 @@ class PD_LITHIUM_API DrawList {
*/ */
void PathFill(u32 clr) { void PathFill(u32 clr) {
DrawConvexPolyFilled(pPath, clr); DrawConvexPolyFilled(pPath, clr);
pPath.Clear(); pPath.clear();
} }
void PathArcToN(const fvec2& c, float radius, float a_min, float a_max, void PathArcToN(const fvec2& c, float radius, float a_min, float a_max,
int segments); int segments);
@@ -167,25 +199,28 @@ class PD_LITHIUM_API DrawList {
/// @param flags DrawFlags (for special rounding rules) /// @param flags DrawFlags (for special rounding rules)
void PathRectEx(fvec2 a, fvec2 b, float rounding = 0.f, u32 flags = 0); void PathRectEx(fvec2 a, fvec2 b, float rounding = 0.f, u32 flags = 0);
void PushClipRect(const fvec4& cr) { pClipRects.Push(cr); } void PushClipRect(const fvec4& cr) { pClipRects.push(cr); }
void PopClipRect() { void PopClipRect() {
if (pClipRects.IsEmpty()) { if (pClipRects.empty()) {
return; return;
} }
pClipRects.Pop(); pClipRects.pop();
} }
const std::vector<Command::Ref>& Data() const { return pDrawList; }
/** One linear Clip rect Setup */ /** One linear Clip rect Setup */
void pClipCmd(Command* cmd); void pClipCmd(Command* cmd);
/** Data Section */ /** Data Section */
Stack<fvec4> pClipRects; std::stack<fvec4> pClipRects;
int Layer; int pLayer;
float pFontScale = 0.7f; float pFontScale = 0.7f;
Font::Ref pCurrentFont; Font::Ref pCurrentFont;
Texture::Ref CurrentTex; Texture::Ref CurrentTex;
std::vector<Command::Ref> pDrawList; std::vector<Command::Ref> pDrawList;
PD::Vec<fvec2> pPath; std::vector<fvec2> pPath;
u32 pNumIndices = 0;
u32 pNumVertices = 0;
}; };
} // namespace Li } // namespace Li
} // namespace PD } // namespace PD
+36
View File
@@ -39,6 +39,7 @@ enum LiTextFlags_ {
LiTextFlags_Wrap = 1 << 3, ///< Wrap Text: May be runs better with TMS LiTextFlags_Wrap = 1 << 3, ///< Wrap Text: May be runs better with TMS
LiTextFlags_Short = 1 << 4, ///< Short Text: May be runs better with TMS LiTextFlags_Short = 1 << 4, ///< Short Text: May be runs better with TMS
LiTextFlags_Scroll = 1 << 5, ///< Not implemented [scoll text if to long] LiTextFlags_Scroll = 1 << 5, ///< Not implemented [scoll text if to long]
LiTextFlags_NoOOS = 1 << 6, ///< No Out of Screen Rendering
}; };
namespace PD { namespace PD {
@@ -67,6 +68,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
@@ -84,6 +97,21 @@ class PD_LITHIUM_API Font {
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);
/**
* Garbage collection for TextMapSystem
*/
void CleanupTMS();
/**
* 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);
std::string pWrapText(const std::string& txt, float scale,
const PD::fvec2& max, PD::fvec2& dim);
std::string pShortText(const std::string& txt, float scale,
const PD::fvec2& max, PD::fvec2& dim);
/** Data Section */ /** Data Section */
int PixelHeight; int PixelHeight;
int DefaultPixelHeight = 24; int DefaultPixelHeight = 24;
@@ -93,6 +121,14 @@ class PD_LITHIUM_API Font {
* **Now using unordered map** * **Now using unordered map**
*/ */
std::unordered_map<u32, Codepoint> CodeMap; std::unordered_map<u32, Codepoint> CodeMap;
/** TMS */
struct TMELEM {
PD::u32 ID;
PD::fvec2 Size;
std::string Text;
u64 TimeStamp;
};
std::unordered_map<u32, TMELEM> pTMS;
}; };
} // namespace Li } // namespace Li
} // namespace PD } // namespace PD
+12 -12
View File
@@ -2,8 +2,7 @@
/* /*
MIT License MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Copyright (c) 2024 - 2025 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -24,18 +23,19 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#ifdef PD_LI_INCLUDE_FONTS
#include <pd/core/common.hpp> #include <pd/core/common.hpp>
/** Generated with pdfm */
namespace PD { namespace PD {
template <typename T1, typename T2> struct FontFileData {
class Pair { std::string Name;
public: u32 StartOff;
Pair() = default; u32 Size;
Pair(const T1& f, const T2& s) : First(f), Second(s) {}
Pair(T1&& f, T2&& s) : First(std::move(f)), Second(std::move(s)) {}
~Pair() = default;
T1 First;
T2 Second;
}; };
extern FontFileData pFontData[];
extern size_t pNumFonts;
extern PD::u8 pFontsDataRaw[];
} // namespace PD } // namespace PD
#endif
+1 -1
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.
+5 -4
View File
@@ -46,10 +46,11 @@ class PD_LITHIUM_API Renderer {
u32 color); u32 color);
static void CmdTriangle(Command* cmd, const fvec2 a, const fvec2 b, static void CmdTriangle(Command* cmd, const fvec2 a, const fvec2 b,
const fvec2 c, u32 clr); const fvec2 c, u32 clr);
static void CmdPolyLine(const Vec<fvec2>& points, u32 clr, u32 flags = 0, static void CmdPolyLine(const std::vector<fvec2>& points, u32 clr,
int thickness = 1); u32 flags = 0, int thickness = 1);
static void CmdConvexPolyFilled(Command* cmd, const Vec<fvec2>& points, static void CmdConvexPolyFilled(Command* cmd,
u32 clr, Texture::Ref tex); const std::vector<fvec2>& points, u32 clr,
Texture::Ref tex);
// SECTION: InBounds Checks // SECTION: InBounds Checks
+9
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
+5
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
+4
View File
@@ -51,6 +51,10 @@ class PD_UI7_API Label : public Container {
* @note This function is usally called by Menu::Update * @note This function is usally called by Menu::Update
* */ * */
void Draw() override; void Draw() override;
/**
* Override Update func to support Text modifications
*/
void Update() override;
private: private:
fvec2 tdim; ///< Text Size fvec2 tdim; ///< Text Size
+8 -8
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,
+7 -6
View File
@@ -45,8 +45,8 @@ class ID {
* used when directly placing a string istead of using ID("") * used when directly placing a string istead of using ID("")
* @param text Input String * @param text Input String
*/ */
ID(const char* text) { constexpr ID(const char* text) {
pID = PD::Strings::FastHash(text); pID = PD::FNV1A32(text);
pName = text; pName = text;
} }
/** /**
@@ -56,16 +56,17 @@ class ID {
~ID() = default; ~ID() = default;
/** Get The ID Initial Name */ /** Get The ID Initial Name */
const std::string& GetName() const { return pName; } constexpr const std::string_view& GetNameView() const { return pName; }
const std::string GetName() const { return std::string(pName); }
/** Getter for the raw 32bit int id */ /** Getter for the raw 32bit int id */
const u32& RawID() const { return pID; } constexpr const u32& RawID() const { return pID; }
/** Return the ID when casting to u32 */ /** Return the ID when casting to u32 */
operator u32() const { return pID; } constexpr operator u32() const { return pID; }
u32 pID; ///< Hash of the name u32 pID; ///< Hash of the name
std::string pName; ///< Name std::string_view pName; ///< Name
}; };
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD
+10 -3
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;
+21 -7
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;
@@ -70,21 +77,21 @@ class PD_UI7_API IO {
fvec2 MinSliderDragSize = 10.f; // Min height (Vt) and Min Width (Hz) fvec2 MinSliderDragSize = 10.f; // Min height (Vt) and Min Width (Hz)
bool ShowMenuBorder = true; bool ShowMenuBorder = true;
bool ShowFrameBorder = false; // not implemented yet bool ShowFrameBorder = false; // not implemented yet
bool WrapLabels = false; // Beta state
float OverScrollMod = 0.15f; float OverScrollMod = 0.15f;
u64 DoubleClickTime = 500; // Milliseconds u64 DoubleClickTime = 500; // Milliseconds
PD::List<Pair<UI7::ID, Li::DrawList::Ref>> DrawListRegestry; std::list<std::pair<UI7::ID, Li::DrawList::Ref>> DrawListRegestry;
// Short define for DrawKistRegestryLast // Short define for DrawKistRegestryLast
PD::List<Pair<UI7::ID, Li::DrawList::Ref>> pDLRL; std::list<std::pair<UI7::ID, Li::DrawList::Ref>> pDLRL;
// std::vector<std::pair<UI7::ID, Li::DrawList::Ref>> DrawListRegestry;
Li::DrawList::Ref Back; Li::DrawList::Ref Back;
Li::DrawList::Ref Front; Li::DrawList::Ref Front;
u32 NumVertices = 0; ///< Debug Vertices Num u32 NumVertices = 0; ///< Debug Vertices Num
u32 NumIndices = 0; ///< Debug Indices Num u32 NumIndices = 0; ///< Debug Indices Num
Vec<u32> MenuOrder; std::vector<u32> MenuOrder;
// DrawListApi // DrawListApi
void RegisterDrawList(const UI7::ID& id, Li::DrawList::Ref v) { void RegisterDrawList(const UI7::ID& id, Li::DrawList::Ref v) {
DrawListRegestry.PushBack(Pair(id, v)); DrawListRegestry.push_back(std::make_pair(id, v));
} }
void AddViewPort(const ID& id, const ivec4& size) { void AddViewPort(const ID& id, const ivec4& size) {
@@ -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
+11 -5
View File
@@ -39,18 +39,20 @@ 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;
PD_SHARED(Layout); PD_SHARED(Layout);
const std::string& GetName() const { return ID.GetName(); } const std::string GetName() const { return ID.GetName(); }
const UI7::ID& GetID() const { return this->ID; } const UI7::ID& GetID() const { return this->ID; }
const fvec2& GetPosition() const { return Pos; } const fvec2& GetPosition() const { return Pos; }
@@ -101,6 +103,8 @@ class PD_UI7_API Layout {
void Update(); void Update();
fvec2 DbgScrollOffset() { return ScrollOffset; }
private: private:
friend class Menu; friend class Menu;
friend class Context; friend class Context;
@@ -126,12 +130,14 @@ 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;
fvec2 ScrollStart;
bool Scrolling[2]; bool Scrolling[2];
// Objects // Objects
PD::List<Container::Ref> Objects; std::list<Container::Ref> Objects;
std::vector<Container::Ref> IDObjects; std::vector<Container::Ref> IDObjects;
}; };
} // namespace UI7 } // namespace UI7
+16 -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 {
@@ -44,6 +45,10 @@ public:
* @param label The text to draw * @param label The text to draw
*/ */
void Label(const std::string &label); void Label(const std::string &label);
template <typename... Args>
void Label(std::format_string<Args...> s, Args &&...args) {
Label(std::format(s, std::forward<Args>(args)...));
}
/** /**
* Render a Button * Render a Button
* @param label The buttons text * @param label The buttons text
@@ -87,15 +92,22 @@ 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();
void HandleTitlebarActions(); void HandleTitlebarActions();
void DrawBaseLayout(); void DrawBaseLayout();
void AddObject(PD::UI7::Container::Ref obj) { pLayout->AddObject(obj); }
void AddObjectEx(PD::UI7::Container::Ref obj, PD::u32 flags) {
pLayout->AddObjectEx(obj, flags);
}
void Update(); void Update();
/** Data Section */ /** Data Section */
@@ -106,6 +118,8 @@ public:
ID pID; ID pID;
bool *pIsShown = nullptr; bool *pIsShown = nullptr;
bool pIsOpen = true; bool pIsOpen = true;
std::unordered_map<u32, bool> pTreeNodes;
fvec2 TempScrollXY;
float TitleBarHeight = 0.f; float TitleBarHeight = 0.f;
}; };
+12 -3
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 0x00060000
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {
@@ -54,11 +55,18 @@ public:
PD_SHARED(Context); PD_SHARED(Context);
IO::Ref GetIO() { return pIO; }
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);
Menu::Ref CurrentMenu() { return pCurrent; }
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 +81,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
+1 -1
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.6.0)
set(SRC set(SRC
source/bit_util.cpp source/bit_util.cpp
+1 -34
View File
@@ -25,39 +25,6 @@ SOFTWARE.
#include <pd/core/color.hpp> #include <pd/core/color.hpp>
namespace PD { namespace PD {
// The Solution of the biggest performance issue
// A Simple Lookup table
static const std::map<char, int> HEX_DEC = {
{'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5},
{'6', 6}, {'7', 7}, {'8', 8}, {'9', 9}, {'a', 10}, {'b', 11},
{'c', 12}, {'d', 13}, {'e', 14}, {'f', 15}, {'A', 10}, {'B', 11},
{'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}};
PD_CORE_API Color& Color::Hex(const std::string& hex) {
#ifdef PD_NO_SAFE_CODE
/// Safetey check (not required if you programm well xd)
if (hex.length() != 7 || hex.length() != 9 || hex.length() != 6 ||
hex.length() != 8 || std::find_if(hex.begin(), hex.end(), [](char c) {
return !std::isxdigit(c);
}) != hex.end()) {
return *this;
}
#endif
int offset = ((hex.length() == 7 || hex.length() == 9) ? 1 : 0);
r = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
offset += 2;
g = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
offset += 2;
b = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
offset += 2;
if (hex.length() == 9) {
a = HEX_DEC.at(hex[offset]) * 16 + HEX_DEC.at(hex[offset + 1]);
} else {
a = 255;
}
return *this;
}
PD_CORE_API std::string Color::Hex(bool rgba) const { PD_CORE_API std::string Color::Hex(bool rgba) const {
/** Need to int cast (so it is used as num and not char...) */ /** Need to int cast (so it is used as num and not char...) */
std::stringstream s; std::stringstream s;
@@ -65,7 +32,7 @@ PD_CORE_API std::string Color::Hex(bool rgba) const {
s << std::hex << std::setw(2) << std::setfill('0') << (int)r; s << std::hex << std::setw(2) << std::setfill('0') << (int)r;
s << std::hex << std::setw(2) << std::setfill('0') << (int)g; s << std::hex << std::setw(2) << std::setfill('0') << (int)g;
s << std::hex << std::setw(2) << std::setfill('0') << (int)b; s << std::hex << std::setw(2) << std::setfill('0') << (int)b;
if (rgba) { if (rgba || a != 255) { // QoL change btw
s << std::hex << std::setw(2) << std::setfill('0') << (int)a; s << std::hex << std::setw(2) << std::setfill('0') << (int)a;
} }
return s.str(); return s.str();
+14
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) {
+88 -22
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
+1 -1
View File
@@ -46,5 +46,5 @@ PD_CORE_API void Timer::Pause() { pIsRunning = false; }
PD_CORE_API void Timer::Rseume() { pIsRunning = true; } PD_CORE_API void Timer::Rseume() { pIsRunning = true; }
PD_CORE_API bool Timer::IsRunning() const { return pIsRunning; } PD_CORE_API bool Timer::IsRunning() const { return pIsRunning; }
PD_CORE_API u64 Timer::Get() { return pNow - pStart; } PD_CORE_API u64 Timer::Get() { return pNow - pStart; }
PD_CORE_API double Timer::GetSeconds() { return double(Get()) / 1000.0; } PD_CORE_API double Timer::GetSeconds() { return (double)Get() / 1000.0; }
} // namespace PD } // namespace PD
+1 -1
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.6.0)
set(SRC set(SRC
source/hid.cpp source/hid.cpp
-2
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
+19
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
+46
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);
-55
View File
@@ -79,59 +79,4 @@ PD_IMAGE_API void ReverseBuf(std::vector<u8> &buf, size_t bpp, int w, int h) {
} }
} }
} }
PD_IMAGE_API void RGB24toRGBA32(PD::Vec<u8> &out, const PD::Vec<u8> &in,
const int &w, const int &h) {
// Converts RGB24 to RGBA32
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int src = (y * w + x) * 3;
int dst = (y * w + x) * 4;
out[dst + 0] = in[src + 0];
out[dst + 1] = in[src + 1];
out[dst + 2] = in[src + 2];
out[dst + 3] = 255;
}
}
}
PD_IMAGE_API void RGB32toRGBA24(PD::Vec<u8> &out, const PD::Vec<u8> &in,
const int &w, const int &h) {
// Converts RGB24 to RGBA32
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int src = (y * w + x) * 4;
int dst = (y * w + x) * 3;
out[dst + 0] = in[src + 0];
out[dst + 1] = in[src + 1];
out[dst + 2] = in[src + 2];
}
}
}
PD_IMAGE_API void Reverse32(PD::Vec<u8> &buf, const int &w, const int &h) {
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int i = y * w + x;
u8 t0 = buf[i + 0];
u8 t1 = buf[i + 1];
buf[i + 0] = buf[i + 3];
buf[i + 1] = buf[i + 2];
buf[i + 3] = t0;
buf[i + 2] = t1;
}
}
}
PD_IMAGE_API void ReverseBuf(PD::Vec<u8> &buf, size_t bpp, int w, int h) {
PD::Vec<u8> cpy = buf;
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int pos = (y * w + x) * bpp;
for (size_t i = 0; i < bpp; i++) {
buf[pos + bpp - 1 - i] = cpy[pos + i];
}
}
}
}
} // namespace PD::ImgConvert } // namespace PD::ImgConvert
+10 -1
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.6.0)
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)
+62 -17
View File
@@ -33,19 +33,64 @@ 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();
pPath.clear();
if (pCurrentFont) {
pCurrentFont->CleanupTMS();
}
while (!pClipRects.empty()) {
pClipRects.pop();
}
}
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 void DrawList::Optimize() {
#ifndef NDEBUG
PD::TT::Scope s("Optimize");
#endif
std::sort(pDrawList.begin(), pDrawList.end(),
[](const PD::Li::Command::Ref &a, const PD::Li::Command::Ref &b) {
if (a->Layer == b->Layer) { // Same layer
if (a->Tex == b->Tex) { // same tex
return a->Index < b->Index;
}
return a->Tex < b->Tex; // order by address
}
return a->Layer < b->Layer; // Order by layer
});
}
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 = pLayer;
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) {
if (!pClipRects.IsEmpty()) { if (!pClipRects.empty()) {
cmd->ScissorOn = true; cmd->ScissorOn = true;
cmd->ScissorRect = ivec4(pClipRects.Top()); cmd->ScissorRect = ivec4(pClipRects.top());
} }
} }
@@ -209,21 +254,21 @@ PD_LITHIUM_API void DrawList::DrawCircleFilled(const fvec2 &center, float rad,
} }
// TODO: Don't render OOS // TODO: Don't render OOS
PD_LITHIUM_API void DrawList::DrawPolyLine(const Vec<fvec2> &points, u32 clr, PD_LITHIUM_API void DrawList::DrawPolyLine(const std::vector<fvec2> &points,
u32 flags, int thickness) { u32 clr, u32 flags, int thickness) {
if (points.Size() < 2) { if (points.size() < 2) {
return; return;
} }
DrawSolid(); DrawSolid();
auto cmd = PreGenerateCmd(); auto cmd = PreGenerateCmd();
bool close = (flags & (1 << 0)); bool close = (flags & (1 << 0));
int num_points = close ? (int)points.Size() : (int)points.Size() - 1; int num_points = close ? (int)points.size() : (int)points.size() - 1;
if (flags & (1 << 1)) { if (flags & (1 << 1)) {
// TODO: Find a way to draw less garbage looking lines // TODO: Find a way to draw less garbage looking lines
} else { } else {
// Non antialiased lines look awful when rendering with thickness != 1 // Non antialiased lines look awful when rendering with thickness != 1
for (int i = 0; i < num_points; i++) { for (int i = 0; i < num_points; i++) {
int j = (i + 1) == (int)points.Size() ? 0 : (i + 1); int j = (i + 1) == (int)points.size() ? 0 : (i + 1);
auto line = Renderer::PrimLine(points[i], points[j], thickness); auto line = Renderer::PrimLine(points[i], points[j], thickness);
Renderer::CmdQuad(cmd.get(), line, vec4(0.f, 1.f, 1.f, 0.f), clr); Renderer::CmdQuad(cmd.get(), line, vec4(0.f, 1.f, 1.f, 0.f), clr);
} }
@@ -231,9 +276,9 @@ PD_LITHIUM_API void DrawList::DrawPolyLine(const Vec<fvec2> &points, u32 clr,
AddCommand(std::move(cmd)); AddCommand(std::move(cmd));
} }
PD_LITHIUM_API void DrawList::DrawConvexPolyFilled(const Vec<fvec2> &points, PD_LITHIUM_API void DrawList::DrawConvexPolyFilled(
u32 clr) { const std::vector<fvec2> &points, u32 clr) {
if (points.Size() < 3) { if (points.size() < 3) {
return; // Need at least three points return; // Need at least three points
} }
auto cmd = PreGenerateCmd(); auto cmd = PreGenerateCmd();
@@ -249,23 +294,23 @@ PD_LITHIUM_API void DrawList::DrawText(const fvec2 &pos,
std::vector<Command::Ref> cmds; std::vector<Command::Ref> cmds;
pCurrentFont->CmdTextEx(cmds, pos, color, pFontScale, text); pCurrentFont->CmdTextEx(cmds, pos, color, pFontScale, text);
for (size_t i = 0; i < cmds.size(); i++) { for (size_t i = 0; i < cmds.size(); i++) {
cmds[i]->Index = pDrawList.size(); cmds[i]->Index = pDrawList.size() + i;
cmds[i]->Layer = Layer; cmds[i]->Layer = pLayer;
AddCommand(std::move(cmds[i])); AddCommand(std::move(cmds[i]));
} }
} }
PD_LITHIUM_API void DrawList::DrawTextEx(const fvec2 &p, PD_LITHIUM_API void DrawList::DrawTextEx(const fvec2 &p,
const std::string &text, u32 color, const std::string &text, u32 color,
LiTextFlags flags, fvec2 box) { LiTextFlags flags, const fvec2 &box) {
if (!pCurrentFont) { if (!pCurrentFont) {
return; return;
} }
std::vector<Command::Ref> cmds; std::vector<Command::Ref> cmds;
pCurrentFont->CmdTextEx(cmds, p, color, pFontScale, text, flags, box); pCurrentFont->CmdTextEx(cmds, p, color, pFontScale, text, flags, box);
for (size_t i = 0; i < cmds.size(); i++) { for (size_t i = 0; i < cmds.size(); i++) {
cmds[i]->Index = pDrawList.size(); cmds[i]->Index = pDrawList.size() + i;
cmds[i]->Layer = Layer; cmds[i]->Layer = pLayer;
AddCommand(std::move(cmds[i])); AddCommand(std::move(cmds[i]));
} }
} }
+227 -77
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
@@ -160,6 +196,11 @@ PD_LITHIUM_API Font::Codepoint &Font::GetCodepoint(u32 cp) {
} }
PD_LITHIUM_API fvec2 Font::GetTextBounds(const std::string &text, float scale) { PD_LITHIUM_API fvec2 Font::GetTextBounds(const std::string &text, float scale) {
u32 id = PD::FNV1A32(text);
if (pTMS.find(id) != pTMS.end()) {
pTMS[id].TimeStamp = PD::OS::GetTime();
return pTMS[id].Size;
}
// Use wstring for exemple for german äöü // Use wstring for exemple for german äöü
auto wtext = Strings::MakeWstring(text); auto wtext = Strings::MakeWstring(text);
// Create a temp position and offset as [0, 0] // Create a temp position and offset as [0, 0]
@@ -170,7 +211,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 +220,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 += 4 * 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:
@@ -201,6 +242,9 @@ PD_LITHIUM_API fvec2 Font::GetTextBounds(const std::string &text, float scale) {
} }
res.x = std::max(res.x, x); res.x = std::max(res.x, x);
res.y += lh; res.y += lh;
pTMS[id].ID = id;
pTMS[id].Size = res;
pTMS[id].TimeStamp = PD::OS::GetTime();
return res; return res;
} }
@@ -214,6 +258,10 @@ PD_LITHIUM_API void Font::CmdTextEx(std::vector<Command::Ref> &cmds,
fvec2 td; fvec2 td;
fvec2 rpos = pos; fvec2 rpos = pos;
fvec2 rbox = box; fvec2 rbox = box;
std::string txt = text;
if (flags & LiTextFlags_Wrap) {
txt = pWrapText(txt, scale, box, td);
}
if (flags & (LiTextFlags_AlignMid | LiTextFlags_AlignRight)) { if (flags & (LiTextFlags_AlignMid | LiTextFlags_AlignRight)) {
td = GetTextBounds(text, scale); td = GetTextBounds(text, scale);
} }
@@ -225,24 +273,34 @@ PD_LITHIUM_API void Font::CmdTextEx(std::vector<Command::Ref> &cmds,
} }
std::vector<std::string> lines; std::vector<std::string> lines;
std::istringstream iss(text); std::istringstream iss(txt);
std::string tmp; std::string tmp;
while (std::getline(iss, tmp)) { while (std::getline(iss, tmp)) {
lines.push_back(tmp); lines.push_back(tmp);
} }
for (auto &it : lines) { for (auto &it : lines) {
/*if (flags & LITextFlags_Short) { if (flags & LiTextFlags_NoOOS) {
if (rpos.y + off.y + lh < 0) {
off.y += lh;
continue;
}
if (rpos.y + off.y > box.y && box.y != 0) {
break;
}
}
if (flags & LiTextFlags_Short) {
fvec2 tmp_dim; fvec2 tmp_dim;
it = ShortText(it, box.x() - pos.x(), tmp_dim); it = pShortText(it, scale, box - pos, tmp_dim);
}*/ }
auto wline = Strings::MakeWstring(it); auto wline = Strings::MakeWstring(it);
auto cmd = Command::New(); auto cmd = Command::New();
auto Tex = GetCodepoint(wline[0]).Tex; auto Tex = GetCodepoint(wline[0]).Tex;
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 +309,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 +324,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 += 4 * cfs;
}
} }
} }
cmds.push_back(std::move(cmd)); cmds.push_back(std::move(cmd));
@@ -278,5 +336,97 @@ PD_LITHIUM_API void Font::CmdTextEx(std::vector<Command::Ref> &cmds,
} }
} }
PD_LITHIUM_API std::string Font::pWrapText(const std::string &txt, float scale,
const PD::fvec2 &max,
PD::fvec2 &dim) {
u32 id = PD::FNV1A32(txt);
if (pTMS.find(id) != pTMS.end()) {
if (pTMS[id].Text.size()) {
dim = pTMS[id].Size;
pTMS[id].TimeStamp = PD::OS::GetTime();
return pTMS[id].Text;
}
}
std::string ret;
std::string line;
int lx = 0;
std::stringstream s(txt);
std::string tmp;
// Simply go over every word
while (s >> tmp) {
auto d = GetTextBounds(tmp, scale);
if (lx + d.x <= max.x) {
line += tmp + ' ';
lx += d.x;
} else {
ret += line + '\n';
line = tmp + ' ';
lx = GetTextBounds(line, scale).x;
}
}
ret += line;
dim = GetTextBounds(ret, scale);
pTMS[id].ID = id;
pTMS[id].Size = dim;
pTMS[id].Text = ret;
pTMS[id].TimeStamp = PD::OS::GetTime();
return ret;
}
PD_LITHIUM_API std::string Font::pShortText(const std::string &txt, float scale,
const PD::fvec2 &max,
PD::fvec2 &dim) {
u32 id = PD::FNV1A32(txt);
if (pTMS.find(id) != pTMS.end()) {
if (pTMS[id].Text.size()) {
dim = pTMS[id].Size;
pTMS[id].TimeStamp = PD::OS::GetTime();
return pTMS[id].Text;
}
}
auto test = GetTextBounds(txt, scale);
if (test.x < max.x) {
return txt;
}
std::string ext;
std::string ph = "(...)"; // placeholder
std::string tmp = txt;
std::string ret;
auto maxlen = max.x;
size_t ext_ = tmp.find_last_of('.');
if (ext_ != tmp.npos) {
ext = tmp.substr(ext_);
tmp = tmp.substr(0, ext_);
}
maxlen -= GetTextBounds(ext, scale).x;
maxlen -= GetTextBounds(ph, scale).x;
for (auto &it : tmp) {
if (GetTextBounds(ret, scale).x > maxlen) {
ret += ph;
ret += ext;
dim = GetTextBounds(ret, scale);
return ret;
}
ret += it;
}
pTMS[id].ID = id;
pTMS[id].Size = dim;
pTMS[id].Text = ret;
pTMS[id].TimeStamp = PD::OS::GetTime();
return ret;
}
PD_LITHIUM_API void Font::CleanupTMS() {
u64 t = PD::OS::GetTime();
for (auto it = pTMS.begin(); it != pTMS.end();) {
if (t - it->second.TimeStamp > 1000) {
it = pTMS.erase(it);
} else {
it++;
}
}
}
} // namespace Li } // namespace Li
} // namespace PD } // namespace PD
+26 -11
View File
@@ -1,9 +1,6 @@
#pragma once
/* /*
MIT License MIT License
Copyright (c) 2024 - 2025 René Amthor (tobid7)
Copyright (c) 2024 - 2025 tobid7
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -24,10 +21,28 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <pd/core/sl/allocator.hpp> #ifdef PD_LI_INCLUDE_FONTS
#include <pd/core/sl/hashmap.hpp> #include <pd/lithium/fonts.hpp>
#include <pd/core/sl/list.hpp>
#include <pd/core/sl/pair.hpp> /** Generated with pdfm */
#include <pd/core/sl/stack.hpp> namespace PD {
#include <pd/core/sl/tools.hpp> FontFileData pFontData[] = {
#include <pd/core/sl/vector.hpp> {
"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
+10 -11
View File
@@ -110,10 +110,9 @@ PD_LITHIUM_API void Renderer::CmdTriangle(Command* cmd, const fvec2 a,
// TODO: Don't render OOS (Probably make it with a define as it // TODO: Don't render OOS (Probably make it with a define as it
// would probably be faster to render out of screen than checking if // would probably be faster to render out of screen than checking if
// it could be skipped) // it could be skipped)
PD_LITHIUM_API void Renderer::CmdConvexPolyFilled(Command* cmd, PD_LITHIUM_API void Renderer::CmdConvexPolyFilled(
const Vec<fvec2>& points, Command* cmd, const std::vector<fvec2>& points, u32 clr, Texture::Ref tex) {
u32 clr, Texture::Ref tex) { if (points.size() < 3 || tex == nullptr) {
if (points.Size() < 3 || tex == nullptr) {
return; // Need at least three points return; // Need at least three points
} }
@@ -121,11 +120,11 @@ PD_LITHIUM_API void Renderer::CmdConvexPolyFilled(Command* cmd,
float minX = points[0].x, minY = points[0].y; float minX = points[0].x, minY = points[0].y;
float maxX = minX, maxY = minY; float maxX = minX, maxY = minY;
// Check for the max and min Positions // Check for the max and min Positions
for (auto it = points.Begin(); it != points.End(); it++) { for (const auto& it : points) {
if ((*it).x < minX) minX = (*it).x; if (it.x < minX) minX = it.x;
if ((*it).y < minY) minY = (*it).y; if (it.y < minY) minY = it.y;
if ((*it).x > maxX) maxX = (*it).x; if (it.x > maxX) maxX = it.x;
if ((*it).y > maxY) maxY = (*it).y; if (it.y > maxY) maxY = it.y;
} }
// Get Short defines for UV // Get Short defines for UV
// (Bottom Right is not required) // (Bottom Right is not required)
@@ -134,10 +133,10 @@ PD_LITHIUM_API void Renderer::CmdConvexPolyFilled(Command* cmd,
auto uv_bl = tex->UV.BotLeft(); auto uv_bl = tex->UV.BotLeft();
// Render // Render
for (int i = 2; i < (int)points.Size(); i++) { for (int i = 2; i < (int)points.size(); i++) {
cmd->AddIdx(0).AddIdx(i).AddIdx(i - 1); cmd->AddIdx(0).AddIdx(i).AddIdx(i - 1);
} }
for (int i = 0; i < (int)points.Size(); i++) { for (int i = 0; i < (int)points.size(); i++) {
// Calculate U and V coords // Calculate U and V coords
float u = float u =
uv_tl.x + ((points[i].x - minX) / (maxX - minX)) * (uv_tr.x - uv_tl.x); uv_tl.x + ((points[i].x - minX) / (maxX - minX)) * (uv_tr.x - uv_tl.x);
+2 -2
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.6.0)
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)
+2 -2
View File
@@ -50,10 +50,10 @@ PD_UI7_API void Button::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);
list->DrawRectFilled(FinalPos(), size, io->Theme->Get(color)); list->DrawRectFilled(FinalPos(), size, io->Theme->Get(color));
list->Layer++; list->pLayer++;
list->DrawText(FinalPos() + size * 0.5 - tdim * 0.5, label, list->DrawText(FinalPos() + size * 0.5 - tdim * 0.5, label,
io->Theme->Get(UI7Color_Text)); io->Theme->Get(UI7Color_Text));
list->Layer--; list->pLayer--;
} }
PD_UI7_API void Button::Update() { PD_UI7_API void Button::Update() {
+2 -2
View File
@@ -83,11 +83,11 @@ PD_UI7_API void DragData<T>::Draw() {
vec2 td = io->Font->GetTextBounds(p, io->FontScale); vec2 td = io->Font->GetTextBounds(p, io->FontScale);
list->DrawRectFilled(FinalPos() + fvec2(off_x, 0), td + io->FramePadding, list->DrawRectFilled(FinalPos() + fvec2(off_x, 0), td + io->FramePadding,
io->Theme->Get(UI7Color_Button)); io->Theme->Get(UI7Color_Button));
list->Layer++; list->pLayer++;
list->DrawTextEx(FinalPos() + fvec2(off_x, 0), p, list->DrawTextEx(FinalPos() + fvec2(off_x, 0), p,
io->Theme->Get(UI7Color_Text), LiTextFlags_AlignMid, io->Theme->Get(UI7Color_Text), LiTextFlags_AlignMid,
td + io->FramePadding); td + io->FramePadding);
list->Layer--; list->pLayer--;
off_x += td.x + io->ItemSpace.x + io->FramePadding.x; off_x += td.x + io->ItemSpace.x + io->FramePadding.x;
} }
list->DrawText(FinalPos() + fvec2(off_x, io->FramePadding.y * 0.5), label, list->DrawText(FinalPos() + fvec2(off_x, io->FramePadding.y * 0.5), label,
+7 -1
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
+2 -2
View File
@@ -29,11 +29,11 @@ PD_UI7_API void Image::Draw() {
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?"); // Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
// Assert(img.get(), "Image is nullptr!"); // Assert(img.get(), "Image is nullptr!");
// io->Ren->OnScreen(screen); // io->Ren->OnScreen(screen);
list->Layer++; list->pLayer++;
list->DrawTexture(img); list->DrawTexture(img);
list->DrawRectFilled(FinalPos(), newsize, 0xffffffff); list->DrawRectFilled(FinalPos(), newsize, 0xffffffff);
list->DrawSolid(); list->DrawSolid();
list->Layer--; list->pLayer--;
} }
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD
+24 -1
View File
@@ -28,7 +28,30 @@ 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);
list->DrawText(FinalPos(), label, io->Theme->Get(UI7Color_Text)); if (pCLipRectUsed) {
list->PushClipRect(pClipRect);
}
list->DrawTextEx(FinalPos(), label, io->Theme->Get(UI7Color_Text),
LiTextFlags_NoOOS, PD::fvec2(0, io->CurrentViewPort.w));
if (pCLipRectUsed) {
list->PopClipRect();
}
}
PD_UI7_API void Label::Update() {
/**
* Todo: This is a hacky workaround
* Needs proper optimisation
* Needs a max size (to support sligning dynaically by the window size)
*/
if (io->WrapLabels) {
this->label =
io->Font->pWrapText(this->label, io->FontScale,
PD::fvec2(io->CurrentViewPort.z - FinalPos().x * 4,
io->CurrentViewPort.w),
this->tdim);
SetSize(tdim);
}
} }
} // namespace UI7 } // namespace UI7
} // namespace PD } // namespace PD
+5 -3
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;
@@ -33,9 +34,10 @@ PD_UI7_API void UI7::IO::Update() {
Time->Update(); Time->Update();
InputHandler->Update(); InputHandler->Update();
Framerate = 1000.f / Delta; Framerate = 1000.f / Delta;
DrawListRegestry.Clear(); DrawListRegestry.clear();
DrawListRegestry.PushFront( DrawListRegestry.push_front(std::make_pair("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
+11 -11
View File
@@ -66,7 +66,7 @@ PD_UI7_API void Layout::AddObject(Container::Ref obj) {
obj->Update(); obj->Update();
CursorMove(obj->GetSize()); CursorMove(obj->GetSize());
obj->HandleScrolling(ScrollOffset, WorkRect); obj->HandleScrolling(ScrollOffset, WorkRect);
Objects.PushBack(obj); Objects.push_back(obj);
} }
PD_UI7_API void Layout::AddObjectEx(Container::Ref obj, u32 flags) { PD_UI7_API void Layout::AddObjectEx(Container::Ref obj, u32 flags) {
@@ -83,9 +83,9 @@ PD_UI7_API void Layout::AddObjectEx(Container::Ref obj, u32 flags) {
obj->HandleScrolling(ScrollOffset, WorkRect); obj->HandleScrolling(ScrollOffset, WorkRect);
} }
if (flags & UI7LytAdd_Front) { if (flags & UI7LytAdd_Front) {
Objects.PushFront(obj); Objects.push_front(obj);
} else { } else {
Objects.PushBack(obj); Objects.push_back(obj);
} }
} }
@@ -124,16 +124,16 @@ PD_UI7_API void Layout::Update() {
it->Draw(); it->Draw();
} }
} }
std::vector<size_t> tbr;
for (size_t i = 0; i < IDObjects.size(); i++) { for (auto it = IDObjects.begin(); it != IDObjects.end();) {
if (IDObjects[i]->Removable()) { if ((*it)->Removable()) {
tbr.push_back(i); it = IDObjects.erase(it);
} else {
it++;
} }
} }
for (auto& it : tbr) {
IDObjects.erase(IDObjects.begin() + it); Objects.clear();
}
Objects.Clear();
WorkRect = fvec4(fvec2(WorkRect.x, WorkRect.y), Size - IO->MenuPadding); WorkRect = fvec4(fvec2(WorkRect.x, WorkRect.y), Size - IO->MenuPadding);
CursorInit(); CursorInit();
} }
+164 -16
View File
@@ -37,13 +37,14 @@ 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);
} }
PD_UI7_API bool Menu::Button(const std::string& label) { PD_UI7_API bool Menu::Button(const std::string& label) {
bool ret = false; bool ret = false;
u32 id = Strings::FastHash("btn" + label + u32 id = Strings::FastHash("btn" + label +
std::to_string(pLayout->Objects.Size())); std::to_string(pLayout->Objects.size()));
Container::Ref r = pLayout->FindObject(id); Container::Ref r = pLayout->FindObject(id);
if (!r) { if (!r) {
r = Button::New(label, pIO); r = Button::New(label, pIO);
@@ -58,7 +59,7 @@ PD_UI7_API bool Menu::Button(const std::string &label) {
PD_UI7_API void Menu::Checkbox(const std::string& label, bool& v) { PD_UI7_API void Menu::Checkbox(const std::string& label, bool& v) {
u32 id = Strings::FastHash("cbx" + label + u32 id = Strings::FastHash("cbx" + label +
std::to_string(pLayout->Objects.Size())); std::to_string(pLayout->Objects.size()));
Container::Ref r = pLayout->FindObject(id); Container::Ref r = pLayout->FindObject(id);
if (!r) { if (!r) {
r = Checkbox::New(label, v, pIO); r = Checkbox::New(label, v, pIO);
@@ -80,7 +81,9 @@ PD_UI7_API void Menu::Separator() {
pIO->Theme->Get(UI7Color_TextDead)); pIO->Theme->Get(UI7Color_TextDead));
}); });
// Set size before pushing (cause Cursor Move will require it) // Set size before pushing (cause Cursor Move will require it)
r->SetSize(fvec2(pLayout->Size.x - 10, 1)); r->SetSize(fvec2(
pLayout->Size.x - pIO->MenuPadding.x * 2 - pLayout->InitialCursorOffset.x,
1));
pLayout->AddObject(r); pLayout->AddObject(r);
} }
@@ -108,8 +111,9 @@ PD_UI7_API void Menu::SeparatorText(const std::string &label) {
fvec2(pLayout->Size.x, self->GetSize().y)); fvec2(pLayout->Size.x, self->GetSize().y));
}); });
// Set size before pushing (cause Cursor Move will require it) // Set size before pushing (cause Cursor Move will require it)
r->SetSize( r->SetSize(fvec2(
fvec2(pLayout->Size.x - 10, pIO->Font->PixelHeight * pIO->FontScale)); pLayout->Size.x - pIO->MenuPadding.x * 2 - pLayout->InitialCursorOffset.x,
pIO->Font->PixelHeight * pIO->FontScale));
pLayout->AddObject(r); pLayout->AddObject(r);
} }
PD_UI7_API void Menu::HandleFocus() { PD_UI7_API void Menu::HandleFocus() {
@@ -118,7 +122,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 +133,46 @@ PD_UI7_API void Menu::HandleFocus() {
pIO->InputHandler->FocusedMenuRect = newarea; pIO->InputHandler->FocusedMenuRect = newarea;
} }
} }
PD_UI7_API void Menu::HandleScrolling() {}
/** Todo: (func name is self describing) */
PD_UI7_API void Menu::HandleScrolling() {
if (Flags & UI7MenuFlags_VtScrolling) {
bool allowed =
pLayout->MaxPosition.y > (pLayout->WorkRect.w - pLayout->WorkRect.y);
if (allowed) {
if (PD::Hid::IsDown(PD::Hid::Key::Touch)) {
pLayout->ScrollStart = pLayout->ScrollOffset;
}
if (pIO->InputHandler->DragObject(
"sbg" + pID.GetName(),
fvec4(pLayout->Pos, fvec2(0.f)) + pLayout->WorkRect)) {
if (pIO->InputHandler->DragReleasedAW) {
} else {
pLayout->ScrollOffset.y = std::clamp(
pLayout->ScrollStart.y + pIO->InputHandler->DragSourcePos.y -
pIO->InputHandler->DragPosition.y,
-20.f, pLayout->MaxPosition.y - 220);
}
}
} else {
pLayout->ScrollOffset.y = 0.f;
}
if (pLayout->ScrollOffset.y > pLayout->MaxPosition.y - 240) {
pLayout->ScrollOffset.y -= 1.5;
if (pLayout->ScrollOffset.y < pLayout->MaxPosition.y - 240) {
pLayout->ScrollOffset.y = pLayout->MaxPosition.y - 240;
}
}
if (pLayout->ScrollOffset.y < 0) {
pLayout->ScrollOffset.y += 1.5;
if (pLayout->ScrollOffset.y > 0) {
pLayout->ScrollOffset.y = 0;
}
}
}
}
PD_UI7_API void Menu::HandleTitlebarActions() { PD_UI7_API void Menu::HandleTitlebarActions() {
// Collapse // Collapse
if (!(Flags & UI7MenuFlags_NoCollapse)) { if (!(Flags & UI7MenuFlags_NoCollapse)) {
@@ -157,6 +201,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,16 +226,39 @@ 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->pLayer = 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->pLayer = 0;
l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f, l->PathRectEx(self->FinalPos(), self->FinalPos() + self->GetSize(), 10.f,
LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot); LiPathRectFlags_KeepTop | LiPathRectFlags_KeepBot);
l->PathFill(io->Theme->Get(UI7Color_Background)); l->PathFill(io->Theme->Get(UI7Color_Background));
@@ -193,19 +275,19 @@ PD_UI7_API void Menu::DrawBaseLayout() {
if (!(Flags & UI7MenuFlags_NoTitlebar)) { if (!(Flags & UI7MenuFlags_NoTitlebar)) {
Container::Ref r = DynObj::New( Container::Ref r = DynObj::New(
[=, this](UI7::IO::Ref io, Li::DrawList::Ref l, UI7::Container* self) { [=, this](UI7::IO::Ref io, Li::DrawList::Ref l, UI7::Container* self) {
l->Layer = 20; l->pLayer = 20;
/** Header Bar */ /** Header Bar */
l->DrawRectFilled(self->FinalPos(), self->GetSize(), l->DrawRectFilled(self->FinalPos(), self->GetSize(),
io->Theme->Get(UI7Color_Header)); io->Theme->Get(UI7Color_Header));
l->Layer = 21; l->pLayer = 21;
/** Inline if statement to shift the Text if collapse sym is shown */ /** Inline if statement to shift the Text if collapse sym is shown */
/** What the hell is this code btw (didn't found a better way) */ /** What the hell is this code btw (didn't found a better way) */
l->DrawText(self->FinalPos() + fvec2(Flags & UI7MenuFlags_NoClose l->DrawText(self->FinalPos() + fvec2((Flags & UI7MenuFlags_NoCollapse)
? 0 ? pIO->FramePadding.x
: (TitleBarHeight - : (TitleBarHeight -
pIO->FramePadding.y * 2 + pIO->FramePadding.y * 2 +
(io->FramePadding.x * 2)), (io->FramePadding.x * 2)),
0), 2),
pID.GetName(), io->Theme->Get(UI7Color_Text)); pID.GetName(), io->Theme->Get(UI7Color_Text));
}); });
r->SetSize(fvec2(pLayout->GetSize().x, TitleBarHeight)); r->SetSize(fvec2(pLayout->GetSize().x, TitleBarHeight));
@@ -218,7 +300,7 @@ PD_UI7_API void Menu::DrawBaseLayout() {
r = DynObj::New([=, this](UI7::IO::Ref io, Li::DrawList::Ref l, r = DynObj::New([=, this](UI7::IO::Ref io, Li::DrawList::Ref l,
UI7::Container* self) { UI7::Container* self) {
/** This sym actually requires layer 21 (i dont know why) */ /** This sym actually requires layer 21 (i dont know why) */
l->Layer = 21; l->pLayer = 21;
/** /**
* Symbol (Position Swapping set by pIsOpen ? openpos : closepos;) * Symbol (Position Swapping set by pIsOpen ? openpos : closepos;)
*/ */
@@ -254,13 +336,79 @@ 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)) {
TitleBarHeight = pIO->FontScale * 30.f;
pLayout->WorkRect.y = 5.f + TitleBarHeight;
HandleTitlebarActions(); HandleTitlebarActions();
} else {
TitleBarHeight = 0.f;
pLayout->WorkRect.y = 5.f;
} }
DrawBaseLayout(); DrawBaseLayout();
pLayout->Update(); pLayout->Update();
if (Flags & UI7MenuFlags_VtScrolling || Flags & UI7MenuFlags_HzScrolling) {
HandleScrolling();
}
}
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
+287 -6
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
+61 -14
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) */
+1
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)
+12 -1
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)
+19
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
+75
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
+50
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
+47
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
+30
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
+25
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
+77
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
+11 -189
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
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
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;
}
+31 -30
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;
} }