2024-06-08 21:00:40 +02:00
|
|
|
/**
|
|
|
|
* This file is part of RenderD7
|
|
|
|
* Copyright (C) 2021-2024 NPI-D7, tobid7
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <citro2d.h>
|
|
|
|
|
2024-06-08 16:30:01 +02:00
|
|
|
#include <renderd7/Render2.hpp>
|
2024-06-08 21:00:40 +02:00
|
|
|
#include <renderd7/internal_db.hpp>
|
2024-06-08 16:30:01 +02:00
|
|
|
|
|
|
|
namespace RenderD7 {
|
2024-06-08 21:00:40 +02:00
|
|
|
R2Base::R2Base() { this->font = Font::New(); }
|
|
|
|
|
|
|
|
void R2Base::SetFont(Font::Ref fnt) {
|
|
|
|
if (!fnt) return;
|
|
|
|
this->font = fnt;
|
2024-06-08 16:30:01 +02:00
|
|
|
}
|
2024-06-08 21:00:40 +02:00
|
|
|
|
|
|
|
Font::Ref R2Base::GetFont() { return this->font; }
|
|
|
|
|
|
|
|
void R2Base::DefaultFont() { this->font->Unload(); }
|
|
|
|
|
|
|
|
void R2Base::DrawNextLined() { this->next_lined = true; }
|
|
|
|
|
|
|
|
void R2Base::OnScreen(R2Screen screen) {
|
|
|
|
if (screen < 0 || screen > R2Screen_Top) return;
|
|
|
|
this->current_screen = screen;
|
|
|
|
}
|
|
|
|
|
|
|
|
void R2Base::SetTextSize(float szs) { text_size = szs; }
|
|
|
|
|
|
|
|
void R2Base::DefaultTextSize() { text_size = default_text_size; }
|
|
|
|
|
|
|
|
float R2Base::GetTextSize() { return text_size; }
|
|
|
|
|
|
|
|
R2Screen R2Base::GetCurrentScreen() { return current_screen; }
|
|
|
|
|
|
|
|
R7Vec2 R2Base::GetTextDimensions(const std::string& text) {
|
|
|
|
C2D_TextBufClear(rd7i_d2_dimbuf);
|
|
|
|
float w = 0, h = 0;
|
|
|
|
C2D_Text c2dtext;
|
|
|
|
C2D_TextFontParse(&c2dtext, font->Ptr(), rd7i_d2_dimbuf, text.c_str());
|
|
|
|
C2D_TextGetDimensions(&c2dtext, this->text_size, this->text_size, &w, &h);
|
|
|
|
return R7Vec2(w, h);
|
|
|
|
}
|
|
|
|
|
2024-06-15 15:12:06 +02:00
|
|
|
std::string R2Base::WrapText(const std ::string& in, int maxlen) {
|
|
|
|
std::string out;
|
|
|
|
std::string line;
|
|
|
|
int line_x = 0;
|
|
|
|
std::istringstream istream(in);
|
|
|
|
std::string temp;
|
|
|
|
|
|
|
|
while (istream >> temp) {
|
|
|
|
R7Vec2 dim = this->GetTextDimensions(line + temp);
|
|
|
|
if (line_x + dim.x <= maxlen) {
|
|
|
|
line += temp + ' ';
|
|
|
|
line_x += dim.x;
|
|
|
|
} else {
|
|
|
|
out += line + '\n';
|
|
|
|
line = temp + ' ';
|
|
|
|
line_x = dim.x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out += line;
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2024-06-16 22:28:16 +02:00
|
|
|
R7Vec2 R2Base::GetCurrentScreenSize() {
|
|
|
|
return R7Vec2(this->current_screen == R2Screen_Bottom ? 320 : 400, 240);
|
|
|
|
}
|
|
|
|
|
2024-06-08 21:00:40 +02:00
|
|
|
// Main Processing of Draw Calls
|
|
|
|
void R2Base::Process() {
|
|
|
|
for (auto& it : this->commands) {
|
2024-06-15 15:12:06 +02:00
|
|
|
if (it->type <= 0 || it->type > 5) {
|
2024-06-08 21:00:40 +02:00
|
|
|
// Skip
|
|
|
|
continue;
|
|
|
|
}
|
2024-06-15 15:12:06 +02:00
|
|
|
C2D_SceneBegin(it->Screen ? rd7_top : rd7_bottom);
|
|
|
|
if (it->type == 1) {
|
2024-06-08 21:00:40 +02:00
|
|
|
// Rect
|
2024-06-15 15:12:06 +02:00
|
|
|
if (it->lined) {
|
2024-06-16 22:28:16 +02:00
|
|
|
C2D_DrawLine(it->pos.x, it->pos.y, it->clr, it->pos.x + it->pszs.x,
|
|
|
|
it->pos.y, it->clr, 1.f, 0.5f);
|
|
|
|
C2D_DrawLine(it->pos.x, it->pos.y, it->clr, it->pos.x,
|
|
|
|
it->pos.y + it->pszs.y, it->clr, 1.f, 0.5f);
|
2024-06-15 15:12:06 +02:00
|
|
|
C2D_DrawLine(it->pos.x + it->pszs.x, it->pos.y, it->clr,
|
2024-06-16 22:28:16 +02:00
|
|
|
it->pos.x + it->pszs.x, it->pos.y + it->pszs.y, it->clr,
|
|
|
|
1.f, 0.5f);
|
2024-06-15 15:12:06 +02:00
|
|
|
C2D_DrawLine(it->pos.x, it->pos.y + it->pszs.y, it->clr,
|
2024-06-16 22:28:16 +02:00
|
|
|
it->pos.x + it->pszs.x, it->pos.y + it->pszs.y, it->clr,
|
|
|
|
1.f, 0.5f);
|
2024-06-08 21:00:40 +02:00
|
|
|
} else {
|
2024-06-15 15:12:06 +02:00
|
|
|
C2D_DrawRectSolid(it->pos.x, it->pos.y, 0.5, it->pszs.x, it->pszs.y,
|
|
|
|
it->clr);
|
2024-06-08 21:00:40 +02:00
|
|
|
}
|
2024-06-15 15:12:06 +02:00
|
|
|
} else if (it->type == 2) {
|
2024-06-08 21:00:40 +02:00
|
|
|
// Triangle
|
2024-06-15 15:12:06 +02:00
|
|
|
if (it->lined) {
|
2024-06-16 22:28:16 +02:00
|
|
|
C2D_DrawLine(it->pos.x, it->pos.y, it->clr, it->pszs.x, it->pszs.y,
|
|
|
|
it->clr, 1, 0.5f);
|
|
|
|
C2D_DrawLine(it->pos.x, it->pos.y, it->clr, it->ap.x, it->ap.y, it->clr,
|
2024-06-08 21:00:40 +02:00
|
|
|
1, 0.5f);
|
2024-06-16 22:28:16 +02:00
|
|
|
C2D_DrawLine(it->pszs.x, it->pszs.y, it->clr, it->ap.x, it->ap.y,
|
|
|
|
it->clr, 1, 0.5f);
|
2024-06-08 21:00:40 +02:00
|
|
|
} else {
|
2024-06-15 15:12:06 +02:00
|
|
|
C2D_DrawTriangle(it->pos.x, it->pos.y, it->clr, it->pszs.x, it->pszs.y,
|
|
|
|
it->clr, it->ap.x, it->ap.y, it->clr, 0.5);
|
2024-06-08 21:00:40 +02:00
|
|
|
}
|
2024-06-15 15:12:06 +02:00
|
|
|
} else if (it->type == 3) {
|
2024-06-08 21:00:40 +02:00
|
|
|
// Text
|
|
|
|
// little patch for a freeze
|
2024-06-15 15:12:06 +02:00
|
|
|
if (it->text.length() < 1) continue;
|
|
|
|
if (it->pszs.x == 0.0f) {
|
|
|
|
it->pszs.x = it->Screen == R2Screen_Top ? 400 : 320;
|
2024-06-08 21:00:40 +02:00
|
|
|
}
|
2024-06-15 15:12:06 +02:00
|
|
|
if (it->pszs.y == 0.0f) {
|
|
|
|
it->pszs.y = 240;
|
2024-06-08 21:00:40 +02:00
|
|
|
}
|
2024-06-15 15:12:06 +02:00
|
|
|
std::string edit_text = it->text;
|
|
|
|
if (edit_text.substr(it->text.length() - 1) != "\n")
|
2024-06-08 21:00:40 +02:00
|
|
|
edit_text.append("\n"); // Add \n to end if not exist
|
|
|
|
int line = 0;
|
|
|
|
|
2024-06-15 15:12:06 +02:00
|
|
|
if (it->flags & RD7TextFlags_Wrap) {
|
|
|
|
edit_text = WrapText(it->text, it->pszs.x - it->pos.x);
|
|
|
|
}
|
2024-06-08 21:00:40 +02:00
|
|
|
|
|
|
|
while (edit_text.find('\n') != edit_text.npos) {
|
|
|
|
std::string current_line = edit_text.substr(0, edit_text.find('\n'));
|
2024-06-15 15:12:06 +02:00
|
|
|
// if (it->flags & RD7TextFlags_Short)
|
|
|
|
// current_line = GetShortedText(current_line, it->pszs.x - it->pos.x);
|
|
|
|
R7Vec2 newpos = it->pos;
|
2024-06-08 21:00:40 +02:00
|
|
|
// Check Flags
|
|
|
|
R7Vec2 dim = this->GetTextDimensions(current_line);
|
2024-06-15 15:12:06 +02:00
|
|
|
if (it->flags & RD7TextFlags_AlignRight) newpos.x = newpos.x - dim.x;
|
|
|
|
if (it->flags & RD7TextFlags_AlignMid) // Offset by inpos
|
|
|
|
newpos.x = (it->pszs.x * 0.5) - (dim.x * 0.5) + it->pos.x;
|
|
|
|
if (it->flags & RD7TextFlags_Scroll) { // Scroll Text
|
2024-06-08 21:00:40 +02:00
|
|
|
// Look into Old Draw2 Code
|
|
|
|
// TODO: Create Code for this
|
|
|
|
}
|
|
|
|
if (rd7_debugging) {
|
|
|
|
this->DrawNextLined();
|
|
|
|
this->AddRect(newpos, dim, 0xff0000ff);
|
|
|
|
}
|
|
|
|
C2D_Text c2dtext;
|
|
|
|
C2D_TextFontParse(&c2dtext, font->Ptr(), rd7i_text_buffer,
|
|
|
|
current_line.c_str());
|
|
|
|
C2D_TextOptimize(&c2dtext);
|
|
|
|
|
2024-06-15 15:12:06 +02:00
|
|
|
if (it->flags & RD7TextFlags_Shaddow) // performance Killer xd
|
2024-06-08 21:00:40 +02:00
|
|
|
C2D_DrawText(&c2dtext, C2D_WithColor, newpos.x + 1 + (dim.y * line),
|
|
|
|
newpos.y + 1, 0.5, this->text_size, this->text_size,
|
|
|
|
RenderD7::ThemeActive()->Get(RD7Color_TextDisabled));
|
|
|
|
|
|
|
|
C2D_DrawText(&c2dtext, C2D_WithColor, newpos.x,
|
|
|
|
newpos.y + (dim.y * line), 0.5, this->text_size,
|
2024-06-15 15:12:06 +02:00
|
|
|
this->text_size, it->clr);
|
2024-06-08 21:00:40 +02:00
|
|
|
edit_text = edit_text.substr(edit_text.find('\n') + 1);
|
|
|
|
line++;
|
|
|
|
}
|
2024-06-15 15:12:06 +02:00
|
|
|
} else if (it->type == 4) {
|
|
|
|
if (it->img->Loadet()) {
|
|
|
|
C2D_DrawImageAt(it->img->Get(), it->pos.x, it->pos.y, 0.5f);
|
2024-06-14 20:55:55 +02:00
|
|
|
}
|
2024-06-15 15:12:06 +02:00
|
|
|
} else if (it->type == 5) {
|
2024-06-08 21:53:25 +02:00
|
|
|
// TODO: Move the Draw Func into this API
|
2024-06-15 15:12:06 +02:00
|
|
|
it->spr->Draw();
|
2024-06-08 21:00:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
this->commands.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void R2Base::AddRect(R7Vec2 pos, R7Vec2 size, RD7Color clr) {
|
2024-06-15 15:12:06 +02:00
|
|
|
auto cmd = R2Cmd::New();
|
|
|
|
cmd->pos = pos;
|
|
|
|
cmd->pszs = size;
|
|
|
|
cmd->clr = RenderD7::ThemeActive()->Get(clr);
|
|
|
|
cmd->type = 1; // Rect
|
2024-06-08 21:00:40 +02:00
|
|
|
// Just assign current screen as bottom is 0 (false)
|
|
|
|
// and Top and TopRight are !0 (true)
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->Screen = current_screen;
|
2024-06-08 21:00:40 +02:00
|
|
|
if (this->next_lined) {
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->lined = true;
|
2024-06-08 21:00:40 +02:00
|
|
|
this->next_lined = false;
|
|
|
|
}
|
|
|
|
this->commands.push_back(cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void R2Base::AddRect(R7Vec2 pos, R7Vec2 size, unsigned int clr) {
|
2024-06-15 15:12:06 +02:00
|
|
|
auto cmd = R2Cmd::New();
|
|
|
|
cmd->pos = pos;
|
|
|
|
cmd->pszs = size;
|
|
|
|
cmd->clr = clr;
|
|
|
|
cmd->type = 1; // Rect
|
2024-06-08 21:00:40 +02:00
|
|
|
// Just assign current screen as bottom is 0 (false)
|
|
|
|
// and Top and TopRight are !0 (true)
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->Screen = current_screen;
|
2024-06-08 21:00:40 +02:00
|
|
|
if (this->next_lined) {
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->lined = true;
|
2024-06-08 21:00:40 +02:00
|
|
|
this->next_lined = false;
|
|
|
|
}
|
|
|
|
this->commands.push_back(cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void R2Base::AddTriangle(R7Vec2 pos0, R7Vec2 pos1, R7Vec2 pos2, RD7Color clr) {
|
2024-06-15 15:12:06 +02:00
|
|
|
auto cmd = R2Cmd::New();
|
|
|
|
cmd->pos = pos0;
|
|
|
|
cmd->pszs = pos1;
|
|
|
|
cmd->ap = pos2;
|
|
|
|
cmd->clr = RenderD7::ThemeActive()->Get(clr);
|
|
|
|
cmd->type = 2; // Triangle
|
2024-06-08 21:00:40 +02:00
|
|
|
// Just assign current screen as bottom is 0 (false)
|
|
|
|
// and Top and TopRight are !0 (true)
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->Screen = current_screen;
|
2024-06-08 21:00:40 +02:00
|
|
|
if (this->next_lined) {
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->lined = true;
|
2024-06-08 21:00:40 +02:00
|
|
|
this->next_lined = false;
|
|
|
|
}
|
|
|
|
this->commands.push_back(cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void R2Base::AddTriangle(R7Vec2 pos0, R7Vec2 pos1, R7Vec2 pos2,
|
|
|
|
unsigned int clr) {
|
2024-06-15 15:12:06 +02:00
|
|
|
auto cmd = R2Cmd::New();
|
|
|
|
cmd->pos = pos0;
|
|
|
|
cmd->pszs = pos1;
|
|
|
|
cmd->ap = pos2;
|
|
|
|
cmd->clr = clr;
|
|
|
|
cmd->type = 2; // Triangle
|
2024-06-08 21:00:40 +02:00
|
|
|
// Just assign current screen as bottom is 0 (false)
|
|
|
|
// and Top and TopRight are !0 (true)
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->Screen = current_screen;
|
2024-06-08 21:00:40 +02:00
|
|
|
if (this->next_lined) {
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->lined = true;
|
2024-06-08 21:00:40 +02:00
|
|
|
this->next_lined = false;
|
|
|
|
}
|
|
|
|
this->commands.push_back(cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void R2Base::AddText(R7Vec2 pos, const std::string& text, RD7Color clr,
|
|
|
|
RD7TextFlags flags, R7Vec2 tmb) {
|
2024-06-15 15:12:06 +02:00
|
|
|
auto cmd = R2Cmd::New();
|
|
|
|
cmd->pos = pos;
|
|
|
|
cmd->pszs = tmb;
|
|
|
|
cmd->clr = RenderD7::ThemeActive()->Get(clr);
|
|
|
|
cmd->flags = flags;
|
|
|
|
cmd->text = text;
|
|
|
|
cmd->type = 3; // Text
|
2024-06-08 21:00:40 +02:00
|
|
|
// Just assign current screen as bottom is 0 (false)
|
|
|
|
// and Top and TopRight are !0 (true)
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->Screen = current_screen;
|
2024-06-08 21:00:40 +02:00
|
|
|
if (this->next_lined) {
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->lined = true;
|
2024-06-08 21:00:40 +02:00
|
|
|
this->next_lined = false;
|
|
|
|
}
|
|
|
|
this->commands.push_back(cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void R2Base::AddText(R7Vec2 pos, const std::string& text, unsigned int clr,
|
|
|
|
RD7TextFlags flags, R7Vec2 tmb) {
|
2024-06-15 15:12:06 +02:00
|
|
|
auto cmd = R2Cmd::New();
|
|
|
|
cmd->pos = pos;
|
|
|
|
cmd->pszs = tmb;
|
|
|
|
cmd->clr = clr;
|
|
|
|
cmd->flags = flags;
|
|
|
|
cmd->text = text;
|
|
|
|
cmd->type = 3; // Text
|
2024-06-08 21:00:40 +02:00
|
|
|
// Just assign current screen as bottom is 0 (false)
|
|
|
|
// and Top and TopRight are !0 (true)
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->Screen = current_screen;
|
2024-06-08 21:00:40 +02:00
|
|
|
if (this->next_lined) {
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->lined = true;
|
2024-06-08 21:00:40 +02:00
|
|
|
this->next_lined = false;
|
|
|
|
}
|
|
|
|
this->commands.push_back(cmd);
|
|
|
|
}
|
|
|
|
|
2024-06-08 21:53:25 +02:00
|
|
|
void R2Base::AddImage(R7Vec2 pos, Image::Ref img) {
|
2024-06-15 15:12:06 +02:00
|
|
|
auto cmd = R2Cmd::New();
|
|
|
|
cmd->pos = pos;
|
|
|
|
cmd->img = img;
|
|
|
|
cmd->type = 4; // Image
|
2024-06-08 21:53:25 +02:00
|
|
|
// Just assign current screen as bottom is 0 (false)
|
|
|
|
// and Top and TopRight are !0 (true)
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->Screen = current_screen;
|
2024-06-08 21:53:25 +02:00
|
|
|
if (this->next_lined) {
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->lined = true;
|
2024-06-08 21:53:25 +02:00
|
|
|
this->next_lined = false;
|
|
|
|
}
|
|
|
|
this->commands.push_back(cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void R2Base::AddSprite(Sprite::Ref spr) {
|
2024-06-15 15:12:06 +02:00
|
|
|
auto cmd = R2Cmd::New();
|
|
|
|
cmd->spr = spr;
|
|
|
|
cmd->type = 5; // Sprite
|
2024-06-08 21:53:25 +02:00
|
|
|
// Just assign current screen as bottom is 0 (false)
|
|
|
|
// and Top and TopRight are !0 (true)
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->Screen = current_screen;
|
2024-06-08 21:53:25 +02:00
|
|
|
if (this->next_lined) {
|
2024-06-15 15:12:06 +02:00
|
|
|
cmd->lined = true;
|
2024-06-08 21:53:25 +02:00
|
|
|
this->next_lined = false;
|
|
|
|
}
|
|
|
|
this->commands.push_back(cmd);
|
|
|
|
}
|
|
|
|
|
2024-06-08 16:30:01 +02:00
|
|
|
} // namespace RenderD7
|