diff --git a/backends/3ds/source/bknd-gfx.cpp b/backends/3ds/source/bknd-gfx.cpp index 8191514..c391502 100755 --- a/backends/3ds/source/bknd-gfx.cpp +++ b/backends/3ds/source/bknd-gfx.cpp @@ -130,11 +130,14 @@ void GfxC3D::BindTex(PD::Li::TexAddress addr) { } void GfxC3D::RenderDrawData(const std::vector& Commands) { - C3D_BindProgram(&Shader); + // C3D_BindProgram(&Shader); + shaderProgramUse(&Shader); C3D_SetAttrInfo(&ShaderInfo); C3D_Mtx proj; Mtx_OrthoTilt(&proj, 0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f, false); 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_TexEnv* env = C3D_GetTexEnv(0); C3D_TexEnvInit(env); diff --git a/backends/desktop/include/pd-desktop/bknd-hid.hpp b/backends/desktop/include/pd-desktop/bknd-hid.hpp index 782171e..dda3873 100755 --- a/backends/desktop/include/pd-desktop/bknd-hid.hpp +++ b/backends/desktop/include/pd-desktop/bknd-hid.hpp @@ -37,9 +37,36 @@ class HidGLFW : public HidDriver { PD_SHARED(HidGLFW); 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 */ GLFWwindow* Window; int PrevState; + std::unordered_map PrevStates; + static std::string* pText; + bool pInTextMode = false; + PD::u64 pLastUpdate = 0; + std::unordered_map pTimings; }; } // namespace PD \ No newline at end of file diff --git a/backends/desktop/source/bknd-gfx.cpp b/backends/desktop/source/bknd-gfx.cpp index 550b806..d06c81b 100755 --- a/backends/desktop/source/bknd-gfx.cpp +++ b/backends/desktop/source/bknd-gfx.cpp @@ -36,7 +36,7 @@ const char* vertex_shader = R"( varying vec2 oUV; varying vec4 oColor; - // Probably forgot about this matric and + // Probably forgot about this matrix and // searched hours for why the rendering isn't working :/ uniform mat4 projection; @@ -103,17 +103,7 @@ GLuint createShaderProgram(const std::string& vertexShaderSource, return shaderProgram; } -/** 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); - +void SetupShaderAttribs(GLuint Shader) { GLint _pos = glGetAttribLocation(Shader, "pos"); GLint _uv = glGetAttribLocation(Shader, "uv"); GLint _color = glGetAttribLocation(Shader, "color"); @@ -129,6 +119,21 @@ void GfxGL2::Init() { sizeof(PD::Li::Vertex), (void*)offsetof(PD::Li::Vertex, 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); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); @@ -146,11 +151,14 @@ void GfxGL2::Deinit() { } void GfxGL2::NewFrame() { + /* glViewport(0, 0, ViewPort.x, ViewPort.y); glClearColor(ClearColor.x, ClearColor.y, ClearColor.z, ClearColor.w); 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); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CurrentIndex = 0; @@ -170,7 +178,6 @@ void GfxGL2::BindTex(PD::Li::TexAddress addr) { } void GfxGL2::RenderDrawData(const std::vector& Commands) { - glUseProgram(Shader); size_t index = 0; while (index < Commands.size()) { PD::Li::Texture::Ref Tex = Commands[index]->Tex; @@ -207,6 +214,9 @@ void GfxGL2::RenderDrawData(const std::vector& Commands) { glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, CurrentVertex * sizeof(PD::Li::Vertex), &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); glBufferData(GL_ELEMENT_ARRAY_BUFFER, CurrentIndex * sizeof(PD::u16), diff --git a/backends/desktop/source/bknd-hid.cpp b/backends/desktop/source/bknd-hid.cpp index eb3d9b3..a1761ee 100755 --- a/backends/desktop/source/bknd-hid.cpp +++ b/backends/desktop/source/bknd-hid.cpp @@ -23,19 +23,104 @@ SOFTWARE. */ #include - 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") { Window = win; + glfwSetCharCallback(Window, NullTextCB); + Flags |= Flags_HasKeyboard; + Flags |= Flags_HasMouse; 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() { + // 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; + } } + // 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); if (state == GLFW_PRESS) { if (PrevState == GLFW_RELEASE) { @@ -54,5 +139,28 @@ void HidGLFW::Update() { glfwGetCursorPos(Window, &x, &y); pMouse[1] = pMouse[0]; // Cycle pMouse pos 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 \ No newline at end of file diff --git a/include/pd/core/common.hpp b/include/pd/core/common.hpp index ad7daf5..50ac60a 100755 --- a/include/pd/core/common.hpp +++ b/include/pd/core/common.hpp @@ -23,6 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include #include #include #include @@ -33,6 +34,7 @@ SOFTWARE. #include #include #include +#include #include #include #include diff --git a/include/pd/core/fquat.hpp b/include/pd/core/fquat.hpp new file mode 100644 index 0000000..033e1bc --- /dev/null +++ b/include/pd/core/fquat.hpp @@ -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 +#include + +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 \ No newline at end of file diff --git a/include/pd/core/io.hpp b/include/pd/core/io.hpp index 4ec7cd1..b02f4eb 100755 --- a/include/pd/core/io.hpp +++ b/include/pd/core/io.hpp @@ -36,6 +36,12 @@ namespace IO { * @return 8Bit FileBuffer */ PD_CORE_API std::vector 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 * @param data 8Bit input Buffer diff --git a/include/pd/core/mat.hpp b/include/pd/core/mat.hpp index b78d825..0024d15 100755 --- a/include/pd/core/mat.hpp +++ b/include/pd/core/mat.hpp @@ -25,17 +25,118 @@ SOFTWARE. */ #include +#include namespace PD { -class PD_CORE_API Mat4 { - public: - Mat4() { Zeros(); } - ~Mat4() = default; +namespace Numbers { +constexpr float Tau = std::numbers::pi * 2.f; +} +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(); - void Ortho(float left, float right, float bottom, float top, float near, - float far); +struct PD_CORE_API Mat4 { + std::array m; + 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 \ No newline at end of file diff --git a/include/pd/core/vec2.hpp b/include/pd/core/vec2.hpp index f0f66eb..fbb3199 100755 --- a/include/pd/core/vec2.hpp +++ b/include/pd/core/vec2.hpp @@ -23,7 +23,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// This file is generated by lazyvec +// This file is generated by lazyvec 2.0.0 + #include namespace PD { @@ -33,20 +34,24 @@ class vec2 { T x; T y; - vec2() : x(0), y(0) {} + // Constructors + + constexpr vec2() : x(0), y(0) {} template - vec2(T1 v) { + constexpr vec2(T1 v) { x = (T)v; y = (T)v; } template - vec2(vec2 v) { + constexpr vec2(const vec2& v) { x = (T)v.x; 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 vec2& operator+=(T1 v) { @@ -144,14 +149,42 @@ class vec2 { return vec2(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; } - bool operator!=(const vec2& v) const { return !(*this == v); } + vec2 operator-() const { return vec2(-x, -y); } + template + bool operator==(const vec2& v) const { + return x == (T)v.x && y == (T)v.y; + } + template + bool operator!=(const vec2& v) const { + return !(*this == v); + } + + // Functions double Len() const { return std::sqrt(SqLen()); } double SqLen() const { return x * x + y * y; } + template + double Distance(const vec2& v) const { + return (*this - v).Len(); + } + + vec2 Normalize() const { + double l = Len(); + if (l == 0) { + return *this; + } + return *this / (T)l; + } + + template + T Dot(const vec2& v) const { + return x * (T)v.x + y * (T)v.y; + } + + // Swap Functions void SwapXY() { T t = x; x = y; @@ -159,6 +192,6 @@ class vec2 { } }; using fvec2 = vec2; -using dvec2 = vec2; using ivec2 = vec2; +using dvec2 = vec2; } // namespace PD diff --git a/include/pd/core/vec3.hpp b/include/pd/core/vec3.hpp index 739febe..8d6e245 100755 --- a/include/pd/core/vec3.hpp +++ b/include/pd/core/vec3.hpp @@ -23,8 +23,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// This file is generated by lazyvec +// This file is generated by lazyvec 2.0.0 + #include +// Extended includes (rename if you use other filenames/paths) +#include namespace PD { template @@ -34,22 +37,36 @@ class vec3 { T y; T z; - vec3() : x(0), y(0), z(0) {} + // Constructors + + constexpr vec3() : x(0), y(0), z(0) {} template - explicit vec3(T1 v) { + constexpr vec3(T1 v) { x = (T)v; y = (T)v; z = (T)v; } template - explicit vec3(vec3 v) { + constexpr vec3(const vec3& v) { x = (T)v.x; y = (T)v.y; 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 + constexpr explicit vec3(const vec2& xy, T1 z) { + { + x = (T)xy.x; + y = (T)xy.y; + this->z = (T)z; + } + } + + // Operations template vec3& operator+=(T1 v) { @@ -155,16 +172,47 @@ class vec3 { return vec3(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 { - return x == v.x && y == v.y && z == v.z; + vec3 operator-() const { return vec3(-x, -y, -z); } + template + bool operator==(const vec3& 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 + bool operator!=(const vec3& v) const { + return !(*this == v); + } + + // Functions double Len() const { return std::sqrt(SqLen()); } double SqLen() const { return x * x + y * y + z * z; } + template + double Distance(const vec3& v) const { + return (*this - v).Len(); + } + + vec3 Normalize() const { + double l = Len(); + if (l == 0) { + return *this; + } + return *this / (T)l; + } + + template + T Dot(const vec3& v) const { + return x * (T)v.x + y * (T)v.y + z * (T)v.z; + } + + template + vec3 Cross(const vec3& v) const { + return vec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); + } + + // Swap Functions void SwapXY() { T t = x; x = y; @@ -182,6 +230,6 @@ class vec3 { } }; using fvec3 = vec3; -using dvec3 = vec3; using ivec3 = vec3; +using dvec3 = vec3; } // namespace PD diff --git a/include/pd/core/vec4.hpp b/include/pd/core/vec4.hpp index 3ec12d4..dd31ae0 100755 --- a/include/pd/core/vec4.hpp +++ b/include/pd/core/vec4.hpp @@ -23,9 +23,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// This file is generated by lazyvec +// This file is generated by lazyvec 2.0.0 + #include -#include // Extended +// Extended includes (rename if you use other filenames/paths) +#include +#include namespace PD { template @@ -36,9 +39,11 @@ class vec4 { T z; T w; - vec4() : x(0), y(0), z(0), w(0) {} + // Constructors + + constexpr vec4() : x(0), y(0), z(0), w(0) {} template - explicit vec4(T1 v) { + constexpr vec4(T1 v) { x = (T)v; y = (T)v; z = (T)v; @@ -46,23 +51,37 @@ class vec4 { } template - explicit vec4(vec4 v) { + constexpr vec4(const vec4& v) { x = (T)v.x; y = (T)v.y; z = (T)v.z; 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 - explicit vec4(vec2 a, vec2 b) { - x = (T)a.x; - y = (T)a.y; - z = (T)b.x; - w = (T)b.y; + constexpr explicit vec4(const vec2& xy, const vec2& zw) { + { + x = (T)xy.x; + y = (T)xy.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 + constexpr explicit vec4(const vec3& xyz, T1 w) { + { + x = (T)xyz.x; + y = (T)xyz.y; + z = (T)xyz.z; + this->w = (T)w; + } + } + + // Operations template vec4& operator+=(T1 v) { @@ -176,16 +195,42 @@ class vec4 { return vec4(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 { - return x == v.x && y == v.y && z == v.z && w == v.w; + vec4 operator-() const { return vec4(-x, -y, -z, -w); } + template + bool operator==(const vec4& 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 + bool operator!=(const vec4& v) const { + return !(*this == v); + } + + // Functions double Len() const { return std::sqrt(SqLen()); } double SqLen() const { return x * x + y * y + z * z + w * w; } + template + double Distance(const vec4& v) const { + return (*this - v).Len(); + } + + vec4 Normalize() const { + double l = Len(); + if (l == 0) { + return *this; + } + return *this / (T)l; + } + + template + T Dot(const vec4& v) const { + return x * (T)v.x + y * (T)v.y + z * (T)v.z + w * (T)v.w; + } + + // Swap Functions void SwapXY() { T t = x; x = y; @@ -218,6 +263,6 @@ class vec4 { } }; using fvec4 = vec4; -using dvec4 = vec4; using ivec4 = vec4; +using dvec4 = vec4; } // namespace PD diff --git a/include/pd/drivers/gfx.hpp b/include/pd/drivers/gfx.hpp index 0fbd7ba..b308a3c 100755 --- a/include/pd/drivers/gfx.hpp +++ b/include/pd/drivers/gfx.hpp @@ -52,6 +52,8 @@ class GfxDriver { virtual void RenderDrawData(const std::vector& Commands) {} + void SetViewPort(const ivec2& vp) { ViewPort = vp; } + virtual Texture::Ref LoadTex( const std::vector& pixels, int w, int h, Texture::Type type = Texture::Type::RGBA32, @@ -90,6 +92,7 @@ class Gfx { static void NewFrame() { pGfx->NewFrame(); } static void BindTex(TexAddress addr) { pGfx->BindTex(addr); } + static void SetViewPort(const ivec2& vp) { pGfx->SetViewPort(vp); } static void RenderDrawData(const std::vector& Commands) { pGfx->RenderDrawData(Commands); diff --git a/include/pd/drivers/hid.hpp b/include/pd/drivers/hid.hpp index d4398e2..50c52f2 100755 --- a/include/pd/drivers/hid.hpp +++ b/include/pd/drivers/hid.hpp @@ -28,6 +28,14 @@ SOFTWARE. namespace PD { class HidDriver { public: + enum Flags : u32 { + Flags_None, + FLags_HasGamepad, + Flags_HasKeyboard, + Flags_HasTouch, + Flags_HasMouse, + }; + // Todo: Name to GpKey (GamepadKey) /** Key [Controller] */ enum Key : u32 { No = 0, ///< No Key @@ -60,8 +68,68 @@ class HidDriver { 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 */ enum Event { + Event_Null, Event_Down, ///< Key Pressed Event_Held, ///< Key Held Event_Up, ///< Key released @@ -90,6 +158,7 @@ class HidDriver { * @return if key(s) doing the requiested event */ bool IsEvent(Event e, Key keys); + bool IsEvent(Event e, KbKey key); /** * Check for Key Press Event * @param keys set of keys @@ -160,12 +229,19 @@ class HidDriver { * Template Update Function for a device specific driver */ virtual void Update() {} + /** + * Get Text from Keyboard + */ + virtual void GetInputStr(std::string& str) {} /** Data Section */ /** Backend Identification Name */ const std::string pName; + /** Flags */ + u32 Flags = 0; + /** Key Binds Map */ std::unordered_map pBinds; /** Swap Tabe Function */ @@ -176,6 +252,8 @@ class HidDriver { bool pLocked = false; /** Key Event Table Setup */ std::unordered_map KeyEvents[2]; + /** Keyboard Key Event Table Setup */ + std::unordered_map KbKeyEvents[2]; }; /** Static Hid Controller */ @@ -186,6 +264,7 @@ class Hid { /** Referenec to Drivers enums */ using Key = HidDriver::Key; + using KbKey = HidDriver::KbKey; using Event = HidDriver::Event; 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, KbKey key) { return pHid->IsEvent(e, key); } static bool IsDown(Key keys) { return pHid->IsDown(keys); } static bool IsUp(Key keys) { return pHid->IsUp(keys); } static bool IsHeld(Key keys) { return pHid->IsHeld(keys); } @@ -208,6 +288,8 @@ class Hid { static void Unlock() { pHid->Unlock(); } static bool Locked() { return pHid->Locked(); } static void Update() { pHid->Update(); } + static u32 GetFlags() { return pHid->Flags; } + static void GetStrInput(std::string& str) { pHid->GetInputStr(str); } static HidDriver::Ref pHid; }; diff --git a/include/pd/image/image.hpp b/include/pd/image/image.hpp index 1c5045f..69d8e08 100755 --- a/include/pd/image/image.hpp +++ b/include/pd/image/image.hpp @@ -58,6 +58,9 @@ class PD_IMAGE_API Image { int Height() const { return pHeight; } Format Fmt() const { return pFmt; } + void FlipVertical(); + void FlipHorizontal(); + u8& operator[](int idx) { return pBuffer[idx]; } u8 operator[](int idx) const { return pBuffer[idx]; } diff --git a/include/pd/ui7/io.hpp b/include/pd/ui7/io.hpp index 931b153..8ec4f7b 100755 --- a/include/pd/ui7/io.hpp +++ b/include/pd/ui7/io.hpp @@ -102,7 +102,7 @@ class PD_UI7_API IO { } ViewPort::Ref GetViewPort(const ID& id) { - if (ViewPorts.count(id)) { + if (!ViewPorts.count(id)) { return nullptr; } return ViewPorts[id]; diff --git a/include/pd/ui7/layout.hpp b/include/pd/ui7/layout.hpp index 1af1d2e..46aee23 100755 --- a/include/pd/ui7/layout.hpp +++ b/include/pd/ui7/layout.hpp @@ -39,6 +39,7 @@ class PD_UI7_API Layout { this->IO = io; DrawList = Li::DrawList::New(); DrawList->SetFont(IO->Font); + DrawList->SetFontScale(io->FontScale); Scrolling[0] = false; Scrolling[1] = false; CursorInit(); diff --git a/include/pd/ui7/ui7.hpp b/include/pd/ui7/ui7.hpp index 751e1e2..64c48dc 100755 --- a/include/pd/ui7/ui7.hpp +++ b/include/pd/ui7/ui7.hpp @@ -37,7 +37,7 @@ SOFTWARE. * Major Minor Patch Build * 0x01010000 -> 1.1.0-0 */ -#define UI7_VERSION 0x00050000 +#define UI7_VERSION 0x00050001 namespace PD { namespace UI7 { diff --git a/pd/core/source/io.cpp b/pd/core/source/io.cpp index 1f54ab2..5e32e3d 100755 --- a/pd/core/source/io.cpp +++ b/pd/core/source/io.cpp @@ -39,6 +39,20 @@ PD_CORE_API std::vector LoadFile2Mem(const std::string& path) { 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& data) { u32 hash = 4477; for (auto& it : data) { diff --git a/pd/core/source/mat.cpp b/pd/core/source/mat.cpp index 2bcd908..d000692 100755 --- a/pd/core/source/mat.cpp +++ b/pd/core/source/mat.cpp @@ -25,32 +25,98 @@ SOFTWARE. #include namespace PD { -PD_CORE_API void Mat4::Zeros() { - for (int i = 0; i < 16; i++) { - m[i] = 0.0f; - } +PD_CORE_API Mat4 Mat4::RotateX(float a) { + float c = std::cos(a); + 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, - float near, float far) { - m[0] = 2.0f / (right - left); - m[1] = 0.0f; - m[2] = 0.0f; - m[3] = -(right + left) / (right - left); +PD_CORE_API Mat4 Mat4::RotateY(float a) { + float c = std::cos(a); + float s = std::sin(a); + Mat4 ret = Identity(); + ret(0, 0) = c; + ret(0, 2) = s; + ret(2, 0) = -s; + ret(2, 2) = c; + return ret; +} - m[4] = 0.0f; - m[5] = 2.0f / (top - bottom); - m[6] = 0.0f; - m[7] = -(top + bottom) / (top - bottom); +PD_CORE_API Mat4 Mat4::RotateZ(float a) { + float c = std::cos(a); + float s = std::sin(a); + 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; - m[9] = 0.0f; - m[10] = -2.0f / (far - near); - m[11] = -(far + near) / (far - near); +PD_CORE_API Mat4 Mat4::Rotate(fvec3 axis, float a) { + float s = std::sin(a); + float c = std::cos(a); + 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; - m[13] = 0.0f; - m[14] = 0.0f; - m[15] = 1.0f; + ret(1, 0) = t * x * y + z * s; + ret(1, 1) = t * y * y + c; + ret(1, 2) = t * y * z - x * s; + + 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 \ No newline at end of file diff --git a/pd/drivers/source/hid.cpp b/pd/drivers/source/hid.cpp index 29ce9dd..df0b4fe 100755 --- a/pd/drivers/source/hid.cpp +++ b/pd/drivers/source/hid.cpp @@ -5,6 +5,12 @@ namespace PD { PD_DEF_EXP(HidDriver::Ref, Hid::pHid); 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() { auto tkd = KeyEvents[1][Event_Down]; diff --git a/pd/image/source/image.cpp b/pd/image/source/image.cpp index 20e5dbc..6b7f2a4 100755 --- a/pd/image/source/image.cpp +++ b/pd/image/source/image.cpp @@ -77,6 +77,46 @@ PD_IMAGE_API void Image::Copy(const std::vector& 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) { if (img->pFmt == dst) { return; diff --git a/pd/ui7/CMakeLists.txt b/pd/ui7/CMakeLists.txt index e401afc..a7ba558 100755 --- a/pd/ui7/CMakeLists.txt +++ b/pd/ui7/CMakeLists.txt @@ -25,4 +25,4 @@ else() pd_add_lib(pd-ui7 SRC_FILES ${SRC}) endif() -target_link_libraries(pd-ui7 PUBLIC pd-core) \ No newline at end of file +target_link_libraries(pd-ui7 PUBLIC pd-lithium pd-core) \ No newline at end of file diff --git a/tools/lazyvec/CMakeLists.txt b/tools/lazyvec/CMakeLists.txt index 851e945..66862e1 100755 --- a/tools/lazyvec/CMakeLists.txt +++ b/tools/lazyvec/CMakeLists.txt @@ -1,7 +1,18 @@ 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 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) diff --git a/tools/lazyvec/include/lazyvec.hpp b/tools/lazyvec/include/lazyvec.hpp new file mode 100644 index 0000000..900b066 --- /dev/null +++ b/tools/lazyvec/include/lazyvec.hpp @@ -0,0 +1,19 @@ +#pragma once + +/** Header for all source file functions */ + +#include // yes this tool requires at least c++ 20 +#include +#include +#include +#include + +namespace LVec { +const std::vector 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 \ No newline at end of file diff --git a/tools/lazyvec/source/lazyconstructors.cpp b/tools/lazyvec/source/lazyconstructors.cpp new file mode 100644 index 0000000..110ab81 --- /dev/null +++ b/tools/lazyvec/source/lazyconstructors.cpp @@ -0,0 +1,75 @@ +#include + +constexpr std::string_view _construct = R"text( + constexpr vec{0}() : {1} {{}} + template + constexpr vec{0}(T1 v) {{ + {2} + }} + + template + constexpr vec{0}(const vec{0}& v) {{ + {3} + }} + + constexpr explicit vec{0}({4}) : {5} {{}}{6} +)text"; + +constexpr std::string_view _extended3 = R"( + + // Extended Constructors + template + constexpr explicit vec3(const vec2& xy, T1 z) {{ + x = (T)xy.x; + y = (T)xy.y; + this->z = (T)z; + }} +)"; + +constexpr std::string_view _extended4 = R"( + + // Extended Constructors + template + constexpr explicit vec4(const vec2& xy, const vec2& zw) {{ + x = (T)xy.x; + y = (T)xy.y; + z = (T)zw.x; + w = (T)zw.y; + }} + + template + constexpr explicit vec4(const vec3& 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 \ No newline at end of file diff --git a/tools/lazyvec/source/lazyfuncs.cpp b/tools/lazyvec/source/lazyfuncs.cpp new file mode 100644 index 0000000..9da6a49 --- /dev/null +++ b/tools/lazyvec/source/lazyfuncs.cpp @@ -0,0 +1,50 @@ +#include + +constexpr std::string_view _funcs = R"text( + double Len() const {{ return std::sqrt(SqLen()); }} + double SqLen() const {{ return {1}; }} + + template + double Distance(const vec{0}& v) const {{ + return (*this - v).Len(); + }} + + vec{0} Normalize() const {{ + double l = Len(); + if(l == 0) {{ + return *this; + }} + return *this / (T)l; + }} + + template + T Dot(const vec{0}&v) const {{ + return {2}; + }} +)text"; + +constexpr std::string_view _cross = R"text( + template + vec3 Cross(const vec3& v) const { + return vec3(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 \ No newline at end of file diff --git a/tools/lazyvec/source/lazyoperation.cpp b/tools/lazyvec/source/lazyoperation.cpp new file mode 100644 index 0000000..dbf9bfb --- /dev/null +++ b/tools/lazyvec/source/lazyoperation.cpp @@ -0,0 +1,47 @@ +#include + +constexpr std::string_view _op_template = R"text( + template + vec{0}& operator{1}=(T1 v) {{ +{2} + return *this; + }} + + template + vec{0}& operator{1}=(const vec{0}& v) {{ +{3} + return *this; + }} + + template + vec{0} operator{1}(T1 v) const {{ + return vec{0}({4}); + }} + + template + vec{0} operator{1}(const vec{0}& v) const {{ + return vec{0}({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 \ No newline at end of file diff --git a/tools/lazyvec/source/lazyops.cpp b/tools/lazyvec/source/lazyops.cpp new file mode 100644 index 0000000..5a45530 --- /dev/null +++ b/tools/lazyvec/source/lazyops.cpp @@ -0,0 +1,30 @@ +#include + +/** + * 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 + bool operator==(const vec{0}& v) const {{ return {2}; }} + template + bool operator!=(const vec{0}& 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 \ No newline at end of file diff --git a/tools/lazyvec/source/lazyswap.cpp b/tools/lazyvec/source/lazyswap.cpp new file mode 100644 index 0000000..e978c4a --- /dev/null +++ b/tools/lazyvec/source/lazyswap.cpp @@ -0,0 +1,25 @@ +#include +#include + +namespace LVec { +std::string MakeSwap(int n) { + std::stringstream s; + std::unordered_set 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 \ No newline at end of file diff --git a/tools/lazyvec/source/lazytemplate.cpp b/tools/lazyvec/source/lazytemplate.cpp new file mode 100644 index 0000000..f3b4632 --- /dev/null +++ b/tools/lazyvec/source/lazytemplate.cpp @@ -0,0 +1,77 @@ +#include + +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 +{7} + +namespace PD {{ +template +class vec{0} {{ +public: +{1} + // Constructors +{2} + // Operations +{3} + // Generic Operations +{4} + // Functions +{5} + // Swap Functions +{6} +}}; +using fvec{0} = vec{0}; +using ivec{0} = vec{0}; +using dvec{0} = vec{0}; +}} // 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 " << std::endl; + if (n == 4) { + extended << "#include " << std::endl; + } + } + return std::format(_template, n, data.str(), MakeConstructors(n), ops.str(), + GenericOperations(n), MakeFunctions(n), MakeSwap(n), + extended.str()); +} +} // namespace LVec \ No newline at end of file diff --git a/tools/lazyvec/source/main.cpp b/tools/lazyvec/source/main.cpp index f0ce8ca..0a6eeaf 100755 --- a/tools/lazyvec/source/main.cpp +++ b/tools/lazyvec/source/main.cpp @@ -21,194 +21,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include -#include -#include -#include -#include - -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 elems = {"x", "y", "z", "w"}; - -void MakeOperationFor(std::fstream& off, char op, int n) { - off << " template \n"; - off << " vec" << n << "& 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 \n"; - off << " vec" << n << "& operator" << op << "=(const vec" << n - << "& 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 \n"; - off << " vec" << n << " operator" << op << "(T1 v) const {\n"; - off << " return vec" << n << "("; - for (int i = 0; i < n; i++) { - if (i > 0) off << ", "; - off << elems[i] << " " << op << " (T)v"; - } - off << ");\n }\n\n"; - - off << " template \n"; - off << " vec" << n << " operator" << op << "(const vec" << n - << "& v) const {\n"; - off << " return vec" << n << "("; - 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 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 " - "\n\n"; - off << "namespace PD {" << std::endl; - off << "template \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 \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 \n"; - off << " explicit vec" << n << "(vec" << n << " 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 << ";\n"; - off << "using dvec" << n << " = vec" << n << ";\n"; - off << "using ivec" << n << " = vec" << n << ";\n"; - off << "}\n"; - off.close(); -} - /** * Yet another Stupid Code generation tool * Why ? @@ -216,11 +28,21 @@ void GenerateVec(int n) { * manually writeup vec2 to vec4 */ +#include +#include + int main(int argc, char* argv[]) { if (argc != 2) { std::cout << argv[0] << " " << std::endl; return 0; } - GenerateVec(std::stoi(argv[1])); + int l = std::stoi(argv[1]); + if (l < 2 || l > 4) { + std::cout << argv[0] << " " << std::endl; + return 0; + } + std::ofstream f("vec" + std::to_string(l) + ".hpp"); + f << LVec::GenerateHeader(l); + f.close(); return 0; } \ No newline at end of file