# 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)
This commit is contained in:
2025-07-23 23:21:34 +02:00
parent 31a0c3656f
commit 87910b57de
31 changed files with 1085 additions and 276 deletions

View File

@ -130,11 +130,14 @@ void GfxC3D::BindTex(PD::Li::TexAddress addr) {
} }
void GfxC3D::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) { void GfxC3D::RenderDrawData(const std::vector<PD::Li::Command::Ref>& Commands) {
C3D_BindProgram(&Shader); // C3D_BindProgram(&Shader);
shaderProgramUse(&Shader);
C3D_SetAttrInfo(&ShaderInfo); C3D_SetAttrInfo(&ShaderInfo);
C3D_Mtx proj; C3D_Mtx proj;
Mtx_OrthoTilt(&proj, 0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f, false); Mtx_OrthoTilt(&proj, 0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f, false);
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, pLocProjection, &proj); C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, pLocProjection, &proj);
// Mat4 proj = Mat4::Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f);
// C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, pLocProjection, (C3D_Mtx*)&proj);
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL); C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL);
C3D_TexEnv* env = C3D_GetTexEnv(0); C3D_TexEnv* env = C3D_GetTexEnv(0);
C3D_TexEnvInit(env); C3D_TexEnvInit(env);

View File

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

View File

@ -36,7 +36,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 +103,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 +119,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,11 +151,14 @@ 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; CurrentIndex = 0;
@ -170,7 +178,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;
@ -207,6 +214,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),

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -52,6 +52,8 @@ class GfxDriver {
virtual void RenderDrawData(const std::vector<Command::Ref>& Commands) {} virtual void RenderDrawData(const std::vector<Command::Ref>& Commands) {}
void SetViewPort(const ivec2& vp) { ViewPort = vp; }
virtual Texture::Ref LoadTex( virtual 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, Texture::Type type = Texture::Type::RGBA32,
@ -90,6 +92,7 @@ class Gfx {
static void NewFrame() { pGfx->NewFrame(); } static void NewFrame() { pGfx->NewFrame(); }
static void BindTex(TexAddress addr) { pGfx->BindTex(addr); } static void BindTex(TexAddress addr) { pGfx->BindTex(addr); }
static void SetViewPort(const ivec2& vp) { pGfx->SetViewPort(vp); }
static void RenderDrawData(const std::vector<Command::Ref>& Commands) { static void RenderDrawData(const std::vector<Command::Ref>& Commands) {
pGfx->RenderDrawData(Commands); pGfx->RenderDrawData(Commands);

View File

@ -28,6 +28,14 @@ SOFTWARE.
namespace PD { namespace PD {
class HidDriver { class HidDriver {
public: public:
enum Flags : u32 {
Flags_None,
FLags_HasGamepad,
Flags_HasKeyboard,
Flags_HasTouch,
Flags_HasMouse,
};
// 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 +68,68 @@ class HidDriver {
Right = DRight | CPRight, ///< DPad or CPad Right Right = DRight | CPRight, ///< DPad or CPad Right
}; };
// Dont want to use some hardcoded bitset
// so lets use just numbers
enum KbKey : u8 {
Kb_No = 0,
Kb_Escape = 1,
Kb_Q = 2,
Kb_W = 3,
Kb_E = 4,
Kb_R = 5,
Kb_T = 6,
// Yes i use QWERTZ Keyboard
Kb_Z = 7,
Kb_U = 8,
Kb_I = 9,
Kb_O = 10,
Kb_P = 11,
Kb_A = 12,
Kb_S = 13,
Kb_D = 14,
Kb_F = 15,
Kb_G = 16,
Kb_H = 17,
Kb_J = 18,
Kb_K = 19,
Kb_L = 20,
Kb_Y = 21,
Kb_X = 22,
Kb_C = 23,
Kb_V = 24,
Kb_B = 25,
Kb_N = 26,
Kb_M = 27,
Kb_LShift = 28,
Kb_F1 = 29,
Kb_F2 = 30,
Kb_F3 = 31,
Kb_F4 = 32,
Kb_F5 = 33,
Kb_F6 = 34,
Kb_F7 = 35,
Kb_F8 = 36,
Kb_F9 = 37,
Kb_F10 = 38,
Kb_F11 = 39,
Kb_F12 = 40,
Kb_1 = 41,
Kb_2 = 42,
Kb_3 = 43,
Kb_4 = 44,
Kb_5 = 45,
Kb_6 = 46,
Kb_7 = 47,
Kb_8 = 48,
Kb_9 = 49,
Kb_0 = 50,
Kb_Backspace = 51,
Kb_Enter = 52,
};
/** 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 +158,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
@ -160,12 +229,19 @@ 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;
/** Swap Tabe Function */ /** Swap Tabe Function */
@ -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<u32, Event> 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 = HidDriver::KbKey;
using Event = HidDriver::Event; using Event = HidDriver::Event;
static void Init(HidDriver::Ref v = nullptr) { static void Init(HidDriver::Ref v = nullptr) {
@ -197,6 +276,7 @@ class Hid {
} }
static bool IsEvent(Event e, Key keys) { return pHid->IsEvent(e, keys); } static bool IsEvent(Event e, Key keys) { return pHid->IsEvent(e, keys); }
static bool IsEvent(Event e, KbKey key) { return pHid->IsEvent(e, key); }
static bool IsDown(Key keys) { return pHid->IsDown(keys); } static bool IsDown(Key keys) { return pHid->IsDown(keys); }
static bool IsUp(Key keys) { return pHid->IsUp(keys); } static bool IsUp(Key keys) { return pHid->IsUp(keys); }
static bool IsHeld(Key keys) { return pHid->IsHeld(keys); } static bool IsHeld(Key keys) { return pHid->IsHeld(keys); }
@ -208,6 +288,8 @@ class Hid {
static void Unlock() { pHid->Unlock(); } static void Unlock() { pHid->Unlock(); }
static bool Locked() { return pHid->Locked(); } static bool Locked() { return pHid->Locked(); }
static void Update() { pHid->Update(); } static void Update() { pHid->Update(); }
static u32 GetFlags() { return pHid->Flags; }
static void GetStrInput(std::string& str) { pHid->GetInputStr(str); }
static HidDriver::Ref pHid; static HidDriver::Ref pHid;
}; };

View File

@ -58,6 +58,9 @@ class PD_IMAGE_API Image {
int Height() const { return pHeight; } int Height() const { return pHeight; }
Format Fmt() const { return pFmt; } Format Fmt() const { return pFmt; }
void FlipVertical();
void FlipHorizontal();
u8& operator[](int idx) { return pBuffer[idx]; } u8& operator[](int idx) { return pBuffer[idx]; }
u8 operator[](int idx) const { return pBuffer[idx]; } u8 operator[](int idx) const { return pBuffer[idx]; }

View File

@ -102,7 +102,7 @@ class PD_UI7_API IO {
} }
ViewPort::Ref GetViewPort(const ID& id) { ViewPort::Ref GetViewPort(const ID& id) {
if (ViewPorts.count(id)) { if (!ViewPorts.count(id)) {
return nullptr; return nullptr;
} }
return ViewPorts[id]; return ViewPorts[id];

View File

@ -39,6 +39,7 @@ 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();

View File

@ -37,7 +37,7 @@ SOFTWARE.
* 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 0x00050001
namespace PD { namespace PD {
namespace UI7 { namespace UI7 {

View File

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

View File

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

View File

@ -5,6 +5,12 @@ 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 key) {
if (!KbKeyEvents[0].count(key)) {
return false;
}
return KbKeyEvents[0][key] == e;
}
void HidDriver::SwapTab() { void HidDriver::SwapTab() {
auto tkd = KeyEvents[1][Event_Down]; auto tkd = KeyEvents[1][Event_Down];

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;

View File

@ -25,4 +25,4 @@ else()
pd_add_lib(pd-ui7 SRC_FILES ${SRC}) pd_add_lib(pd-ui7 SRC_FILES ${SRC})
endif() endif()
target_link_libraries(pd-ui7 PUBLIC pd-core) target_link_libraries(pd-ui7 PUBLIC pd-lithium pd-core)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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