diff --git a/CMakeLists.txt b/CMakeLists.txt index 380b969..3eb5d2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,7 @@ source/core/timetrace.cpp) ## Image Source Code set(IMAGE_SRC -source/image/img_edit.cpp +source/image/image.cpp source/image/img_blur.cpp source/image/img_convert.cpp) diff --git a/include/pd.hpp b/include/pd.hpp index 1406c42..0cd0a58 100644 --- a/include/pd.hpp +++ b/include/pd.hpp @@ -38,9 +38,9 @@ SOFTWARE. #include #include // Image +#include #include #include -#include // Drivers #include // Overlays diff --git a/include/pd/core/common.hpp b/include/pd/core/common.hpp index 046cbf9..ae1e5fb 100644 --- a/include/pd/core/common.hpp +++ b/include/pd/core/common.hpp @@ -34,6 +34,7 @@ SOFTWARE. #include #include #include +#include #include #include diff --git a/include/pd/image/img_edit.hpp b/include/pd/image/image.hpp similarity index 88% rename from include/pd/image/img_edit.hpp rename to include/pd/image/image.hpp index 8edaa9b..56c4298 100644 --- a/include/pd/image/img_edit.hpp +++ b/include/pd/image/image.hpp @@ -27,15 +27,15 @@ SOFTWARE. #include namespace PD { -class ImgEdit { +class Image { public: - ImgEdit() = default; - ImgEdit(const std::string& path) { this->Load(path); } - ImgEdit(const std::vector& buf) { this->Load(buf); } - ImgEdit(const std::vector& buf, int w, int h, int fmt = 4) { + Image() = default; + Image(const std::string& path) { this->Load(path); } + Image(const std::vector& buf) { this->Load(buf); } + Image(const std::vector& buf, int w, int h, int fmt = 4) { this->Copy(buf, w, h, fmt); } - ~ImgEdit() = default; + ~Image() = default; void Load(const std::string& path); void Load(const std::vector& buf); diff --git a/include/pd/lithium/command.hpp b/include/pd/lithium/command.hpp index 0427114..9b454bc 100644 --- a/include/pd/lithium/command.hpp +++ b/include/pd/lithium/command.hpp @@ -167,6 +167,24 @@ class Command : public SmartCtor { */ RenderMode Rendermode() const { return mode; } + /** Setter for Scissor Mode */ + Command& SetScissorMode(ScissorMode mode) { + scissor = mode; + return *this; + } + + /** Getter for Scissor Mode */ + ScissorMode GetScissorMode() const { return scissor; } + + /** Setter for Scissor Area */ + Command& ScissorRect(const vec4& v) { + scissor_area = v; + return *this; + } + + /** Getter for Scissor Area */ + vec4 ScissorRect() const { return scissor_area; } + private: /** * Vertex Buffer @@ -188,6 +206,10 @@ class Command : public SmartCtor { int index; /** RenderMode (Default to RenderMode_RGBA) */ RenderMode mode = RenderMode_RGBA; + /** Scissor Mode (for defined area to render) */ + ScissorMode scissor = ScissorMode_None; + /** scissor box (top left and bottom right) */ + vec4 scissor_area; }; } // namespace LI } // namespace PD \ No newline at end of file diff --git a/include/pd/lithium/flags.hpp b/include/pd/lithium/flags.hpp index f85c097..de5a1d0 100644 --- a/include/pd/lithium/flags.hpp +++ b/include/pd/lithium/flags.hpp @@ -61,5 +61,11 @@ enum RenderMode { RenderMode_RGBA, ///< RGBA [for textures or solid colors] RenderMode_Font, ///< A8 [for textures only crated by 1 color channel] }; +/** Scissor Mode (for ClipRect related rendering) */ +enum ScissorMode { + ScissorMode_None = 0, ///< No Scissor + ScissorMode_Inverted = 1, ///< Render Pixels outside the box + ScissorMode_Normal = 3, ///< Only render pixels inside the box +}; } // namespace LI } // namespace PD \ No newline at end of file diff --git a/include/pd/lithium/objects.hpp b/include/pd/lithium/objects.hpp index 57cf622..d052366 100644 --- a/include/pd/lithium/objects.hpp +++ b/include/pd/lithium/objects.hpp @@ -118,6 +118,26 @@ class StaticObject : public SmartCtor { } } + /** + * Set a Custom Scissor Mode for Object Copy List + * @param m New Mode to Set + */ + void ReSetScissorMode(ScissorMode m) { + for (auto& i : cpy) { + i->SetScissorMode(m); + } + } + + /** + * Set Custom Scissor Rect to All Objects + * @param v Scissor Rect to set + */ + void ReScissorRect(const vec4& v) { + for (auto& i : cpy) { + i->ScissorRect(v); + } + } + /** * Get a Reference to the Copy Commands List * @return command list reference @@ -296,6 +316,18 @@ class StaticText : public SmartCtor { */ Font::Ref Font() { return font; } + /** + * Set a Custom Scissor Mode Static Text + * @param m New Mode to Set + */ + void SetScissorMode(ScissorMode m) { text->ReSetScissorMode(m); } + + /** + * Set Custom Scissor Rect to Static Text + * @param v Scissor Rect to set + */ + void ScissorRect(const vec4& v) { text->ReScissorRect(v); } + private: /** Font */ Font::Ref font; diff --git a/include/pd/ui7/drawlist.hpp b/include/pd/ui7/drawlist.hpp index 14df16c..8db0efa 100644 --- a/include/pd/ui7/drawlist.hpp +++ b/include/pd/ui7/drawlist.hpp @@ -85,6 +85,12 @@ class DrawList : public SmartCtor { /** Process [Render] the Drawlist */ void Process(); + /** Push a Clip Rect */ + void PushClipRect(const vec4& v) { clip_rects.push(v); } + + /** Revert Last Clip Rect */ + void PopClipRect() { clip_rects.pop(); } + /** Getter for the Layer */ int Layer() const { return layer; } /** Setter fot the Layer */ @@ -100,9 +106,10 @@ class DrawList : public SmartCtor { friend class Menu; friend class Context; - int layer; ///< Current Layer - int base; ///< Base Layer - LI::Renderer::Ref ren; ///< Renderer Reference + int layer; ///< Current Layer + int base; ///< Base Layer + LI::Renderer::Ref ren; ///< Renderer Reference + std::stack clip_rects; ///< Stack containing Scissor Areas // Map for Auto Static Text std::unordered_map static_text; // List of Drawcommands generated diff --git a/source/image/img_edit.cpp b/source/image/image.cpp similarity index 54% rename from source/image/img_edit.cpp rename to source/image/image.cpp index 6c7de54..49c6408 100644 --- a/source/image/img_edit.cpp +++ b/source/image/image.cpp @@ -26,14 +26,35 @@ SOFTWARE. #include #include -#include +#include +#include namespace PD { -void ImgEdit::Load(const std::string& path) { - u8* buf = stbi_load(path.c_str(), &w, &h, &fmt, 4); - buffer.assign(buf, buf + (w * h * 4)); - stbi_image_free(buf); +void Image::Load(const std::string& path) { + u8* img = stbi_load(path.c_str(), &w, &h, &fmt, 4); + if (fmt == 3) { + stbi_image_free(img); + img = stbi_load(path.c_str(), &w, &h, &fmt, 3); + buffer.resize(w * h * 4); + PD::ImgConvert::RGB24toRGBA32( + buffer, std::vector(img, img + (w * h * 3)), w, h); + } else { + buffer.assign(img, img + (w * h * 4)); + stbi_image_free(img); + } } -void ImgEdit::Load(const std::vector& buf) {} -void ImgEdit::Copy(const std::vector& buf, int w, int h, int fmt) {} +void Image::Load(const std::vector& buf) { + u8* img = stbi_load_from_memory(buf.data(), buf.size(), &w, &h, &fmt, 4); + if (fmt == 3) { + stbi_image_free(img); + img = stbi_load_from_memory(buf.data(), buf.size(), &w, &h, &fmt, 3); + buffer.resize(w * h * 4); + PD::ImgConvert::RGB24toRGBA32( + buffer, std::vector(img, img + (w * h * 3)), w, h); + } else { + buffer.assign(img, img + (w * h * 4)); + stbi_image_free(img); + } +} +void Image::Copy(const std::vector& buf, int w, int h, int fmt) {} } // namespace PD \ No newline at end of file diff --git a/source/lithium/renderer.cpp b/source/lithium/renderer.cpp index df34408..757695d 100644 --- a/source/lithium/renderer.cpp +++ b/source/lithium/renderer.cpp @@ -465,11 +465,17 @@ void Renderer::Render(Screen::Ref s) { while (index < cmds.size()) { C3D_Tex* tex = cmds[index]->Tex()->GetTex(); auto mode = cmds[index]->Rendermode(); + auto smode = cmds[index]->GetScissorMode(); + auto spos = cmds[index]->ScissorRect(); + C3D_SetScissor((GPU_SCISSORMODE)smode, s->GetSize().y() - spos.w(), + s->GetSize().x() - spos.z(), s->GetSize().y() - spos.y(), + s->GetSize().x() - spos.x()); UpdateRenderMode(mode); u32 start_vtx = vertex_idx; u32 start_idx = index_idx; while (index < cmds.size() && cmds[index]->Tex()->GetTex() == tex && - cmds[index]->Rendermode() == mode) { + cmds[index]->Rendermode() == mode && + cmds[index]->GetScissorMode() == smode) { auto c = cmds[index]; // Indices for (size_t i = 0; i < c->IndexList().size(); i++) { diff --git a/source/lithium/texture.cpp b/source/lithium/texture.cpp index 30f7771..0d2854a 100644 --- a/source/lithium/texture.cpp +++ b/source/lithium/texture.cpp @@ -27,11 +27,12 @@ SOFTWARE. #include #include +#include #include #include -#include -#include +#include #include +#include namespace PD { GPU_TEXCOLOR GetTexFmt(Texture::Type type) { @@ -115,51 +116,24 @@ void Texture::Delete() { void Texture::LoadFile(const std::string& path) { PD::TT::Scope st("texldr-" + path); Delete(); - int w = 0, h = 0, c = 0; - u8* image = stbi_load(path.c_str(), &w, &h, &c, 4); - PD::Assert(image != nullptr, "Unable to load image: " + path); - if (w > 1024 || h > 1024) { - stbi_image_free(image); + PD::Image img(path); + PD::Assert(img.GetBuffer().size(), "Unable to load image: " + path); + if (img.Width() > 1024 || img.Height() > 1024) { PD::Error("Width or heigt is > 1024"); return; } - std::vector buf; - if (c == 3) { - stbi_image_free(image); - image = stbi_load(path.c_str(), &w, &h, &c, 3); - buf.resize(w * h * 4); - PD::ImgConvert::RGB24toRGBA32( - buf, std::vector(image, image + (w * h * 3)), w, h); - } else { - buf.assign(image, image + (w * h * 4)); - stbi_image_free(image); - } - MakeTex(buf, w, h); + MakeTex(img, img.Width(), img.Height()); } void Texture::LoadMemory(const std::vector& data) { Delete(); - int w, h, c; - u8* image = stbi_load_from_memory(data.data(), data.size(), &w, &h, &c, 4); - if (image == nullptr) { + PD::Image img(data); + PD::Assert(img.GetBuffer().size(), "Unable to load image from Memory!"); + if (img.Width() > 1024 || img.Height() > 1024) { + PD::Error("Width or heigt is > 1024"); return; } - if (w > 1024 || h > 1024) { - stbi_image_free(image); - return; - } - std::vector buf; - if (c == 3) { - stbi_image_free(image); - image = stbi_load_from_memory(data.data(), data.size(), &w, &h, &c, 3); - buf.resize(w * h * 4); - PD::ImgConvert::RGB24toRGBA32( - buf, std::vector(image, image + (w * h * 3)), w, h); - } else { - buf.assign(image, image + (w * h * 4)); - stbi_image_free(image); - } - MakeTex(buf, w, h); + MakeTex(img, img.Width(), img.Height()); } void Texture::LoadPixels(const std::vector& pixels, int w, int h, Type type, diff --git a/source/ui7/drawlist.cpp b/source/ui7/drawlist.cpp index 024a5b3..152e504 100644 --- a/source/ui7/drawlist.cpp +++ b/source/ui7/drawlist.cpp @@ -35,6 +35,10 @@ void DrawList::AddRectangle(vec2 pos, vec2 szs, const UI7Color& clr) { ren->UseTex(); ren->SetupCommand(cmd); cmd->Layer(base + layer); + if (!clip_rects.empty()) { + cmd->SetScissorMode(LI::ScissorMode_Normal); + cmd->ScissorRect(clip_rects.top()); + } ren->QuadCommand(cmd, rect, vec4(0.f, 1.f, 1.f, 0.f), clr); commands.push_back(std::make_pair( ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd)); @@ -49,6 +53,10 @@ void DrawList::AddTriangle(vec2 pos0, vec2 pos1, vec2 pos2, ren->UseTex(); ren->SetupCommand(cmd); cmd->Layer(base + layer); + if (!clip_rects.empty()) { + cmd->SetScissorMode(LI::ScissorMode_Normal); + cmd->ScissorRect(clip_rects.top()); + } ren->TriangleCommand(cmd, pos0, pos1, pos2, clr); commands.push_back(std::make_pair( ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd)); @@ -76,6 +84,10 @@ void DrawList::AddText(vec2 pos, const std::string& text, const UI7Color& clr, e->second->SetPos(pos); e->second->SetColor(clr); e->second->SetLayer(layer); + if (!clip_rects.empty()) { + e->second->SetScissorMode(LI::ScissorMode_Normal); + e->second->ScissorRect(clip_rects.top()); + } e->second->Draw(); ////// STILL LEAVING THE OLD CODE BELOW AS IT IS MAYBE NEEDED ////// @@ -107,6 +119,10 @@ void DrawList::AddImage(vec2 pos, Texture::Ref img, vec2 size) { ren->UseTex(img); ren->SetupCommand(cmd); cmd->Layer(base + layer); + if (!clip_rects.empty()) { + cmd->SetScissorMode(LI::ScissorMode_Normal); + cmd->ScissorRect(clip_rects.top()); + } ren->QuadCommand(cmd, rect, img->GetUV(), 0xffffffff); commands.push_back(std::make_pair( ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd)); @@ -123,6 +139,10 @@ void DrawList::AddLine(const vec2& a, const vec2& b, const UI7Color& clr, ren->UseTex(); ren->SetupCommand(cmd); cmd->Layer(base + layer); + if (!clip_rects.empty()) { + cmd->SetScissorMode(LI::ScissorMode_Normal); + cmd->ScissorRect(clip_rects.top()); + } ren->QuadCommand(cmd, line, vec4(0.f, 1.f, 1.f, 0.f), clr); commands.push_back(std::make_pair( ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd)); diff --git a/source/ui7/menu.cpp b/source/ui7/menu.cpp index 5bc335a..3e85f1f 100644 --- a/source/ui7/menu.cpp +++ b/source/ui7/menu.cpp @@ -108,6 +108,7 @@ void UI7::Menu::Update(float delta) { if (!scroll_anim.IsFinished()) { scrolling_off = scroll_anim; } + main->PushClipRect(vec4(5, tbh, view_area.z() - 12, view_area.w())); std::vector tbr; for (int i = 0; i < (int)objects.size(); i++) { auto& it = objects[i]; @@ -131,6 +132,7 @@ void UI7::Menu::Update(float delta) { for (auto it : tbr) { idobjs.erase(idobjs.begin() + it); } + main->PopClipRect(); this->back->Process(); this->main->Process(); this->front->Process();