- 3ds - Remove Gfx values that are present in Backend Tamplate - Move to default Palladium Namespace - Set the Input Flags - Desktop - Move to PD Namespace - Comment out old keyboard stuff - HidDriver needs a rewrite but is functional enough - Core - Add u128 class (only used in input driver so far - Drivers (Core) - Move Gfx to PD namespace - Move Vertex/Index Pos and Projection Mtx to Gfx template - Add Keyboard support with u128 to Hid - Add a Update func if no hiddriver is specified (to prevent crashes when requestign inputs) - Image - Add RGBA -> BGRA support (used in windows bitmaps iirc) - Lithium - Add Vertex/Index counters to drawlist - Add a LoadTTF from Mem func and let the loadfile func use PD::IO::LoadFile2Mem (looks cleaner) - Add LoadDefaultFont (which loads one of the integrated fonts if the PD_LI_INCLUDE_FONTS flag was passed on palaldium build) !!! Note that there are no fonts integrated yet due to i dont know how to handle licensing... - UI7 - Add MouseLeft support to Input handler - Use xy coords of the Viewport to create Menus inside it - Get num of Vertices/Indices out of FinalDrawList - Add some Palladium Info to metrics Menu - Readd Compiler string - pdfm - New tool that creates fonts.cpp/fonts.hpp
		
			
				
	
	
		
			303 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			303 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| /*
 | |
| MIT License
 | |
| 
 | |
| Copyright (c) 2024 - 2025 tobid7
 | |
| 
 | |
| Permission is hereby granted, free of charge, to any person obtaining a copy
 | |
| of this software and associated documentation files (the "Software"), to deal
 | |
| in the Software without restriction, including without limitation the rights
 | |
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
| copies of the Software, and to permit persons to whom the Software is
 | |
| furnished to do so, subject to the following conditions:
 | |
| 
 | |
| The above copyright notice and this permission notice shall be included in all
 | |
| copies or substantial portions of the Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | |
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | |
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | |
| SOFTWARE.
 | |
|  */
 | |
| 
 | |
| #include <pd/lithium/drawlist.hpp>
 | |
| #include <pd/lithium/renderer.hpp>
 | |
| 
 | |
| #ifndef M_PI
 | |
| #define M_PI 3.14159265358979323846
 | |
| #endif
 | |
| 
 | |
| namespace PD {
 | |
| namespace Li {
 | |
| PD_LITHIUM_API void DrawList::DrawSolid() { CurrentTex = Gfx::GetSolidTex(); }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::Clear() {
 | |
|   pNumIndices = 0;
 | |
|   pNumVertices = 0;
 | |
|   pDrawList.clear();
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::AddCommand(Command::Ref v) {
 | |
|   pNumIndices += v->IndexBuffer.Size();
 | |
|   pNumVertices += v->VertexBuffer.Size();
 | |
|   pDrawList.push_back(std::move(v));
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::Merge(DrawList::Ref list) {
 | |
|   for (size_t i = 0; i < list->pDrawList.size(); i++) {
 | |
|     pNumIndices += list->pDrawList[i]->IndexBuffer.Size();
 | |
|     pNumVertices += list->pDrawList[i]->VertexBuffer.Size();
 | |
|     pDrawList.push_back(std::move(list->pDrawList[i]));
 | |
|   }
 | |
|   /** Make sure The list gets cleared */
 | |
|   list->Clear();
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API Command::Ref DrawList::PreGenerateCmd() {
 | |
|   Command::Ref cmd = Command::New();
 | |
|   cmd->Layer = Layer;
 | |
|   cmd->Index = pDrawList.size();
 | |
|   cmd->Tex = CurrentTex;
 | |
|   pClipCmd(cmd.get());
 | |
|   return cmd;
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::pClipCmd(Command *cmd) {
 | |
|   if (!pClipRects.IsEmpty()) {
 | |
|     cmd->ScissorOn = true;
 | |
|     cmd->ScissorRect = ivec4(pClipRects.Top());
 | |
|   }
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::PathArcToN(const fvec2 &c, float radius,
 | |
|                                          float a_min, float a_max,
 | |
|                                          int segments) {
 | |
|   // Path.push_back(c);
 | |
|   PathReserve(segments + 1);
 | |
|   for (int i = 0; i < segments; i++) {
 | |
|     float a = a_min + ((float)i / (float)segments) * (a_max - a_min);
 | |
|     PathAdd(vec2(c.x + std::cos(a) * radius, c.y + std::sin(a) * radius));
 | |
|   }
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::PathFastArcToN(const fvec2 &c, float r,
 | |
|                                              float amin, float amax, int s) {
 | |
|   /**
 | |
|    * Funcion with less division overhead
 | |
|    * Usefull for stuff where a lot of calculations are required
 | |
|    */
 | |
|   float d = (amax - amin) / s;
 | |
|   PathReserve(s + 1);
 | |
|   for (int i = 0; i <= s; i++) {
 | |
|     float a = amin + i * d;
 | |
|     PathAdd(fvec2(c.x + std::cos(a) * r, c.y + std::sin(a) * r));
 | |
|   }
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::PathRect(fvec2 a, fvec2 b, float rounding) {
 | |
|   if (rounding == 0.f) {
 | |
|     PathAdd(a);
 | |
|     PathAdd(vec2(b.x, a.y));
 | |
|     PathAdd(b);
 | |
|     PathAdd(vec2(a.x, b.y));
 | |
|   } else {
 | |
|     float r = std::min({rounding, (b.x - a.x) * 0.5f, (b.y - a.y) * 0.5f});
 | |
|     /** Calculate Optimal segment count automatically */
 | |
|     float corner = M_PI * 0.5f;
 | |
|     int segments = std::max(3, int(std::ceil(corner / (6.0f * M_PI / 180.0f))));
 | |
| 
 | |
|     /**
 | |
|      * To Correctly render filled shapes with Paths API
 | |
|      * The Commands need to be setup clockwise
 | |
|      */
 | |
|     /** Top Left */
 | |
|     PathAdd(vec2(a.x + r, a.y));
 | |
|     PathFastArcToN(vec2(b.x - r, a.y + r), r, -M_PI / 2.0f, 0.0f, segments);
 | |
|     /** Top Right */
 | |
|     PathAdd(vec2(b.x, b.y - r));
 | |
|     PathFastArcToN(vec2(b.x - r, b.y - r), r, 0.0f, M_PI / 2.0f, segments);
 | |
|     /** Bottom Right */
 | |
|     PathAdd(vec2(a.x + r, b.y));
 | |
|     PathFastArcToN(vec2(a.x + r, b.y - r), r, M_PI / 2.0f, M_PI, segments);
 | |
|     /** Bottom Left */
 | |
|     PathAdd(vec2(a.x, a.y + r));
 | |
|     PathFastArcToN(vec2(a.x + r, a.y + r), r, M_PI, 3.0f * M_PI / 2.0f,
 | |
|                    segments);
 | |
|   }
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::PathRectEx(fvec2 a, fvec2 b, float rounding,
 | |
|                                          u32 flags) {
 | |
|   if (rounding == 0.f) {
 | |
|     PathAdd(a);
 | |
|     PathAdd(vec2(b.x, a.y));
 | |
|     PathAdd(b);
 | |
|     PathAdd(vec2(a.x, b.y));
 | |
|   } else {
 | |
|     float r = std::min({rounding, (b.x - a.x) * 0.5f, (b.y - a.y) * 0.5f});
 | |
|     /** Calculate Optimal segment count automatically */
 | |
|     float corner = M_PI * 0.5f;
 | |
|     int segments = std::max(3, int(std::ceil(corner / (6.0f * M_PI / 180.0f))));
 | |
| 
 | |
|     /**
 | |
|      * To Correctly render filled shapes with Paths API
 | |
|      * The Commands need to be setup clockwise
 | |
|      */
 | |
|     /** Top Left */
 | |
|     if (flags & LiPathRectFlags_KeepTopLeft) {
 | |
|       PathAdd(a);
 | |
|     } else {
 | |
|       PathAdd(vec2(a.x + r, a.y));
 | |
|       PathFastArcToN(vec2(b.x - r, a.y + r), r, -M_PI / 2.0f, 0.0f, segments);
 | |
|     }
 | |
| 
 | |
|     /** Top Right */
 | |
|     if (flags & LiPathRectFlags_KeepTopRight) {
 | |
|       PathAdd(vec2(b.x, a.y));
 | |
|     } else {
 | |
|       PathAdd(vec2(b.x, b.y - r));
 | |
|       PathFastArcToN(vec2(b.x - r, b.y - r), r, 0.0f, M_PI / 2.0f, segments);
 | |
|     }
 | |
|     /** Bottom Right */
 | |
|     if (flags & LiPathRectFlags_KeepBotRight) {
 | |
|       PathAdd(b);
 | |
|     } else {
 | |
|       PathAdd(vec2(a.x + r, b.y));
 | |
|       PathFastArcToN(vec2(a.x + r, b.y - r), r, M_PI / 2.0f, M_PI, segments);
 | |
|     }
 | |
|     /** Bottom Left */
 | |
|     if (flags & LiPathRectFlags_KeepBotLeft) {
 | |
|       PathAdd(vec2(a.x, b.y));
 | |
|     } else {
 | |
|       PathAdd(vec2(a.x, a.y + r));
 | |
|       PathFastArcToN(vec2(a.x + r, a.y + r), r, M_PI, 3.0f * M_PI / 2.0f,
 | |
|                      segments);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::DrawRect(const fvec2 &pos, const fvec2 &size,
 | |
|                                        u32 color, int thickness) {
 | |
|   PathRect(pos, pos + size);
 | |
|   // Flags is currently hardcoded (1 = close)
 | |
|   PathStroke(color, thickness, 1);
 | |
| }
 | |
| void DrawList::DrawRectFilled(const fvec2 &pos, const fvec2 &size, u32 color) {
 | |
|   PathRect(pos, pos + size);
 | |
|   PathFill(color);
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::DrawTriangle(const fvec2 &a, const fvec2 &b,
 | |
|                                            const fvec2 &c, u32 color,
 | |
|                                            int thickness) {
 | |
|   PathAdd(a);
 | |
|   PathAdd(b);
 | |
|   PathAdd(c);
 | |
|   PathStroke(color, thickness, 1);
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::DrawTriangleFilled(const fvec2 &a, const fvec2 &b,
 | |
|                                                  const fvec2 &c, u32 color) {
 | |
|   PathAdd(a);
 | |
|   PathAdd(b);
 | |
|   PathAdd(c);
 | |
|   PathFill(color);
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::DrawCircle(const fvec2 ¢er, float rad,
 | |
|                                          u32 color, int num_segments,
 | |
|                                          int thickness) {
 | |
|   if (num_segments <= 0) {
 | |
|     // Auto Segment
 | |
|   } else {
 | |
|     float am = (M_PI * 2.0f) * ((float)num_segments) / (float)num_segments;
 | |
|     PathArcToN(center, rad, 0.f, am, num_segments);
 | |
|   }
 | |
|   DrawSolid();  // Only Solid Color Supported
 | |
|   PathStroke(color, thickness, (1 << 0));
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::DrawCircleFilled(const fvec2 ¢er, float rad,
 | |
|                                                u32 color, int num_segments) {
 | |
|   if (num_segments <= 0) {
 | |
|     // Auto Segment
 | |
|   } else {
 | |
|     float am = (M_PI * 2.0f) * ((float)num_segments) / (float)num_segments;
 | |
|     PathArcToN(center, rad, 0.f, am, num_segments);
 | |
|   }
 | |
|   PathFill(color);
 | |
| }
 | |
| 
 | |
| // TODO: Don't render OOS
 | |
| PD_LITHIUM_API void DrawList::DrawPolyLine(const Vec<fvec2> &points, u32 clr,
 | |
|                                            u32 flags, int thickness) {
 | |
|   if (points.Size() < 2) {
 | |
|     return;
 | |
|   }
 | |
|   DrawSolid();
 | |
|   auto cmd = PreGenerateCmd();
 | |
|   bool close = (flags & (1 << 0));
 | |
|   int num_points = close ? (int)points.Size() : (int)points.Size() - 1;
 | |
|   if (flags & (1 << 1)) {
 | |
|     // TODO: Find a way to draw less garbage looking lines
 | |
|   } else {
 | |
|     // Non antialiased lines look awful when rendering with thickness != 1
 | |
|     for (int i = 0; i < num_points; i++) {
 | |
|       int j = (i + 1) == (int)points.Size() ? 0 : (i + 1);
 | |
|       auto line = Renderer::PrimLine(points[i], points[j], thickness);
 | |
|       Renderer::CmdQuad(cmd.get(), line, vec4(0.f, 1.f, 1.f, 0.f), clr);
 | |
|     }
 | |
|   }
 | |
|   AddCommand(std::move(cmd));
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::DrawConvexPolyFilled(const Vec<fvec2> &points,
 | |
|                                                    u32 clr) {
 | |
|   if (points.Size() < 3) {
 | |
|     return;  // Need at least three points
 | |
|   }
 | |
|   auto cmd = PreGenerateCmd();
 | |
|   Renderer::CmdConvexPolyFilled(cmd.get(), points, clr, CurrentTex);
 | |
|   AddCommand(std::move(cmd));
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::DrawText(const fvec2 &pos,
 | |
|                                        const std::string &text, u32 color) {
 | |
|   if (!pCurrentFont) {
 | |
|     return;
 | |
|   }
 | |
|   std::vector<Command::Ref> cmds;
 | |
|   pCurrentFont->CmdTextEx(cmds, pos, color, pFontScale, text);
 | |
|   for (size_t i = 0; i < cmds.size(); i++) {
 | |
|     cmds[i]->Index = pDrawList.size();
 | |
|     cmds[i]->Layer = Layer;
 | |
|     AddCommand(std::move(cmds[i]));
 | |
|   }
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::DrawTextEx(const fvec2 &p,
 | |
|                                          const std::string &text, u32 color,
 | |
|                                          LiTextFlags flags, fvec2 box) {
 | |
|   if (!pCurrentFont) {
 | |
|     return;
 | |
|   }
 | |
|   std::vector<Command::Ref> cmds;
 | |
|   pCurrentFont->CmdTextEx(cmds, p, color, pFontScale, text, flags, box);
 | |
|   for (size_t i = 0; i < cmds.size(); i++) {
 | |
|     cmds[i]->Index = pDrawList.size();
 | |
|     cmds[i]->Layer = Layer;
 | |
|     AddCommand(std::move(cmds[i]));
 | |
|   }
 | |
| }
 | |
| 
 | |
| PD_LITHIUM_API void DrawList::DrawLine(const fvec2 &a, const fvec2 &b,
 | |
|                                        u32 color, int t) {
 | |
|   PathAdd(a);
 | |
|   PathAdd(b);
 | |
|   PathStroke(color, t);
 | |
| }
 | |
| }  // namespace Li
 | |
| }  // namespace PD
 |