Initial Cross Platform Work
This commit is contained in:
@ -1,138 +0,0 @@
|
||||
/*
|
||||
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 <3ds.h>
|
||||
|
||||
#include <pd/app/app.hpp>
|
||||
#include <pd/core/sys.hpp>
|
||||
#include <pd/lib3ds/hwinfo.hpp>
|
||||
|
||||
namespace PD {
|
||||
int App::too;
|
||||
|
||||
void App::Run() {
|
||||
this->PreInit();
|
||||
this->Init();
|
||||
last_time = Sys::GetNanoTime();
|
||||
while (aptMainLoop()) {
|
||||
input_mgr->Update();
|
||||
u64 current = Sys::GetNanoTime();
|
||||
float dt = static_cast<float>(current - last_time) / 1000000.f;
|
||||
app_time->Update();
|
||||
last_time = current;
|
||||
fps = 1000.f / dt;
|
||||
if (runtimeflags & AppFLags_UserLoop) {
|
||||
PD::TT::Beg("App_MainLoop");
|
||||
if (!this->MainLoop(dt, app_time->GetSeconds())) {
|
||||
break;
|
||||
}
|
||||
PD::TT::End("App_MainLoop");
|
||||
}
|
||||
PD::TT::Beg("Ovl_Update");
|
||||
if (runtimeflags & AppFlags_HandleOverlays &&
|
||||
SafeInitFlags & AppInitFlags_InitLithium) {
|
||||
renderer->Layer(90);
|
||||
overlay_mgr->Update(dt);
|
||||
}
|
||||
if (runtimeflags & AppFlags_HandleMessageMgr &&
|
||||
SafeInitFlags & AppInitFlags_InitLithium) {
|
||||
/// Messages have their own special Layer
|
||||
renderer->Layer(93);
|
||||
msg_mgr->Update(dt);
|
||||
}
|
||||
PD::TT::End("Ovl_Update");
|
||||
if (runtimeflags & AppFlags_HandleRendering &&
|
||||
SafeInitFlags & AppInitFlags_InitLithium) {
|
||||
renderer->PrepareRender();
|
||||
renderer->Render(Top);
|
||||
renderer->Render(Bottom);
|
||||
renderer->FinalizeRender();
|
||||
}
|
||||
}
|
||||
this->Deinit();
|
||||
this->PostDeinit();
|
||||
}
|
||||
|
||||
std::string App::GetDataDirectory() {
|
||||
Assert(SafeInitFlags & AppInitFlags_UnnamedOption1,
|
||||
"Data Dir is not enabled!");
|
||||
return "sdmc:/palladium/apps/" + name;
|
||||
}
|
||||
|
||||
void App::PreInit() {
|
||||
/// Create a Copy that won't get edit
|
||||
SafeInitFlags = InitFlags;
|
||||
osSetSpeedupEnable(InitFlags & AppInitFlags_New3dsMode);
|
||||
if (InitFlags & AppInitFlags_InitGraphics) {
|
||||
gfxInitDefault();
|
||||
if (!(InitFlags & AppInitFlags_InitGraphicsNoC3D)) {
|
||||
C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
|
||||
}
|
||||
}
|
||||
cfguInit();
|
||||
if (InitFlags & AppInitFlags_MountRomfs) {
|
||||
romfsInit();
|
||||
}
|
||||
if (InitFlags & AppInitFlags_InitHwInfo) {
|
||||
PD::HwInfo::Init();
|
||||
}
|
||||
if (InitFlags & AppInitFlags_UnnamedOption1) {
|
||||
std::filesystem::create_directories("sdmc:/palladium/apps/" + name);
|
||||
}
|
||||
input_mgr = PD::New<CtrHid>();
|
||||
if (InitFlags & AppInitFlags_InitLithium) {
|
||||
Assert(!(InitFlags & AppInitFlags_InitGraphicsNoC3D),
|
||||
"InitGraphicsNoC3D is not compatible with InitLithium!");
|
||||
Top = Screen::New(Screen::Top);
|
||||
Bottom = Screen::New(Screen::Bottom);
|
||||
renderer = LI::Renderer::New();
|
||||
renderer->RegisterScreen(false, Top);
|
||||
renderer->RegisterScreen(true, Bottom);
|
||||
renderer->OnScreen(Top);
|
||||
msg_mgr = MessageMgr::New(renderer);
|
||||
overlay_mgr = OverlayMgr::New(renderer, input_mgr);
|
||||
}
|
||||
app_time = Timer::New();
|
||||
}
|
||||
|
||||
void App::PostDeinit() {
|
||||
renderer = nullptr;
|
||||
msg_mgr = nullptr;
|
||||
overlay_mgr = nullptr;
|
||||
input_mgr = nullptr;
|
||||
if (SafeInitFlags & AppInitFlags_InitGraphics) {
|
||||
if (!(SafeInitFlags & AppInitFlags_InitGraphicsNoC3D)) {
|
||||
C3D_Fini();
|
||||
}
|
||||
gfxExit();
|
||||
}
|
||||
if (SafeInitFlags & AppInitFlags_InitHwInfo) {
|
||||
PD::HwInfo::Deinit();
|
||||
}
|
||||
cfguExit();
|
||||
if (SafeInitFlags & AppInitFlags_MountRomfs) {
|
||||
romfsExit();
|
||||
}
|
||||
}
|
||||
} // namespace PD
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/app/lang.hpp>
|
||||
#include <pd/external/json.hpp>
|
||||
|
||||
namespace PD {
|
||||
void Lang::LoadFile(const std::string &path) {
|
||||
nlohmann::json js;
|
||||
std::fstream iff(path, std::ios::in);
|
||||
if (iff.is_open()) {
|
||||
js = nlohmann::json::parse(iff);
|
||||
iff.close();
|
||||
if (js.is_discarded()) {
|
||||
return;
|
||||
}
|
||||
if (!js.contains("ver") || !js.contains("id") || !js.contains("name") ||
|
||||
!js.contains("author") || !js.contains("keys")) {
|
||||
return;
|
||||
}
|
||||
if (js["ver"].get<int>() != ver) {
|
||||
return;
|
||||
}
|
||||
lang_id = js["id"];
|
||||
lang_name = js["name"];
|
||||
lang_author = js["author"];
|
||||
ltable.clear();
|
||||
for (auto k : js["keys"].items()) {
|
||||
ltable.insert(std::make_pair(k.key(), k.value().get<std::string>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::string &Lang::Get(const std::string &k) {
|
||||
auto e = ltable.find(k);
|
||||
if (e != ltable.end()) {
|
||||
return e->second;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
} // namespace PD
|
@ -24,8 +24,8 @@ SOFTWARE.
|
||||
#include <pd/core/bit_util.hpp>
|
||||
|
||||
namespace PD::BitUtil {
|
||||
bool IsSingleBit(u32 v) { return v && !(v & (v - 1)); }
|
||||
u32 GetPow2(u32 v) {
|
||||
PD_CORE_API bool IsSingleBit(u32 v) { return v && !(v & (v - 1)); }
|
||||
PD_CORE_API u32 GetPow2(u32 v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
|
@ -33,7 +33,7 @@ static const std::map<char, int> HEX_DEC = {
|
||||
{'c', 12}, {'d', 13}, {'e', 14}, {'f', 15}, {'A', 10}, {'B', 11},
|
||||
{'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}};
|
||||
|
||||
Color& Color::Hex(const std::string& hex) {
|
||||
PD_CORE_API Color& Color::Hex(const std::string& hex) {
|
||||
#ifdef PD_NO_SAFE_CODE
|
||||
/// Safetey check (not required if you programm well xd)
|
||||
if (hex.length() != 7 || hex.length() != 9 || hex.length() != 6 ||
|
||||
@ -58,7 +58,7 @@ Color& Color::Hex(const std::string& hex) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string Color::Hex(bool rgba) const {
|
||||
PD_CORE_API std::string Color::Hex(bool rgba) const {
|
||||
std::stringstream s;
|
||||
s << "#";
|
||||
s << std::hex << std::setw(2) << std::setfill('0') << m_r;
|
||||
|
@ -35,13 +35,21 @@ SOFTWARE.
|
||||
#define PALLADIUM_GIT_BRANCH "unknown"
|
||||
#endif
|
||||
|
||||
const std::string PD::LibInfo::CompiledWith() {
|
||||
PD_CORE_API const std::string PD::LibInfo::CompiledWith() {
|
||||
return Strings::GetCompilerVersion();
|
||||
}
|
||||
const std::string PD::LibInfo::CxxVersion() {
|
||||
PD_CORE_API const std::string PD::LibInfo::CxxVersion() {
|
||||
return "CPP: " + std::to_string(__cplusplus);
|
||||
}
|
||||
const std::string PD::LibInfo::BuildTime() { return __DATE__ " - " __TIME__; }
|
||||
const std::string PD::LibInfo::Version() { return PALLADIUM_VERSION; }
|
||||
const std::string PD::LibInfo::Commit() { return PALLADIUM_GIT_COMMIT; }
|
||||
const std::string PD::LibInfo::Branch() { return PALLADIUM_GIT_BRANCH; }
|
||||
PD_CORE_API const std::string PD::LibInfo::BuildTime() {
|
||||
return __DATE__ " - " __TIME__;
|
||||
}
|
||||
PD_CORE_API const std::string PD::LibInfo::Version() {
|
||||
return PALLADIUM_VERSION;
|
||||
}
|
||||
PD_CORE_API const std::string PD::LibInfo::Commit() {
|
||||
return PALLADIUM_GIT_COMMIT;
|
||||
}
|
||||
PD_CORE_API const std::string PD::LibInfo::Branch() {
|
||||
return PALLADIUM_GIT_BRANCH;
|
||||
}
|
@ -21,16 +21,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/drivers/hid.hpp>
|
||||
#include <pd/core/hid_driver.hpp>
|
||||
|
||||
/// Reform of the RenderD7 095 Hid Api
|
||||
/// Using Custom Keybindings for future
|
||||
/// Porting of the library
|
||||
|
||||
namespace PD {
|
||||
bool Hid::IsEvent(Event e, Key keys) { return key_events[0][e] & keys; }
|
||||
PD_CORE_API bool Hid::IsEvent(Event e, Key keys) {
|
||||
return key_events[0][e] & keys;
|
||||
}
|
||||
|
||||
void Hid::SwappyTable() {
|
||||
PD_CORE_API void Hid::SwappyTable() {
|
||||
auto tkd = key_events[1][Event_Down];
|
||||
auto tkh = key_events[1][Event_Held];
|
||||
auto tku = key_events[1][Event_Up];
|
@ -25,7 +25,7 @@ SOFTWARE.
|
||||
|
||||
namespace PD {
|
||||
namespace IO {
|
||||
std::vector<u8> LoadFile2Mem(const std::string& path) {
|
||||
PD_CORE_API std::vector<u8> LoadFile2Mem(const std::string& path) {
|
||||
std::ifstream iff(path, std::ios::binary);
|
||||
if (!iff) {
|
||||
return std::vector<u8>();
|
||||
@ -38,7 +38,7 @@ std::vector<u8> LoadFile2Mem(const std::string& path) {
|
||||
iff.close();
|
||||
return res;
|
||||
}
|
||||
u32 HashMemory(const std::vector<u8>& data) {
|
||||
PD_CORE_API u32 HashMemory(const std::vector<u8>& data) {
|
||||
u32 hash = 4477;
|
||||
for (auto& it : data) {
|
||||
hash = (hash * 33) + it;
|
||||
|
@ -1,50 +1,56 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#include <pd/app/error.hpp>
|
||||
|
||||
namespace PD {
|
||||
void Error(const std::string& msg) {
|
||||
gfxInitDefault();
|
||||
consoleInit(GFX_TOP, NULL);
|
||||
std::cout << "Palladium - ERROR MANAGER\n" << std::endl;
|
||||
std::cout << msg << std::endl << std::endl;
|
||||
std::cout << "Press Start to Exit" << std::endl;
|
||||
while (aptMainLoop()) {
|
||||
hidScanInput();
|
||||
if (hidKeysDown() & KEY_START) {
|
||||
break;
|
||||
}
|
||||
gfxSwapBuffers();
|
||||
}
|
||||
gfxExit();
|
||||
exit(0);
|
||||
}
|
||||
void Assert(bool v, const std::string& msg) {
|
||||
if (v == false) {
|
||||
Error("Assert Failed:\n" + msg);
|
||||
}
|
||||
}
|
||||
/*
|
||||
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/core/mat.hpp>
|
||||
|
||||
namespace PD {
|
||||
PD_CORE_API void Mat4::Zeros() {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
m[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
m[4] = 0.0f;
|
||||
m[5] = 2.0f / (top - bottom);
|
||||
m[6] = 0.0f;
|
||||
m[7] = -(top + bottom) / (top - bottom);
|
||||
|
||||
m[8] = 0.0f;
|
||||
m[9] = 0.0f;
|
||||
m[10] = -2.0f / (far - near);
|
||||
m[11] = -(far + near) / (far - near);
|
||||
|
||||
m[12] = 0.0f;
|
||||
m[13] = 0.0f;
|
||||
m[14] = 0.0f;
|
||||
m[15] = 1.0f;
|
||||
}
|
||||
} // namespace PD
|
@ -24,8 +24,8 @@ SOFTWARE.
|
||||
#include <pd/core/strings.hpp>
|
||||
|
||||
namespace PD::Strings {
|
||||
bool StringEndsWith(const std::string& str,
|
||||
const std::vector<std::string>& exts) {
|
||||
PD_CORE_API bool StringEndsWith(const std::string& str,
|
||||
const std::vector<std::string>& exts) {
|
||||
// Changed order to not do an substr on empty string
|
||||
if (str.empty()) {
|
||||
return false;
|
||||
@ -44,13 +44,48 @@ bool StringEndsWith(const std::string& str,
|
||||
return false;
|
||||
}
|
||||
|
||||
std::wstring MakeWstring(const std::string& s) {
|
||||
// As std::wstring(s.begin(), s.end()); doesn't convert it
|
||||
// Normally this should not be done like this but it works
|
||||
return std::filesystem::path(s).wstring();
|
||||
PD_CORE_API std::wstring MakeWstring(const std::string& s) {
|
||||
// Manually convert to wstring as they removed wstring_convert :(
|
||||
std::wstring result;
|
||||
size_t i = 0;
|
||||
while (i < s.size()) {
|
||||
uint8_t ch = static_cast<uint8_t>(s[i]);
|
||||
if (ch < 0x80) { // 1-byte chsr
|
||||
result += static_cast<wchar_t>(ch);
|
||||
i++;
|
||||
} else if ((ch >> 5) == 0b110) { // 2-byte char
|
||||
if (i + 1 >= s.size()) {
|
||||
return L""; // return empty if error
|
||||
}
|
||||
wchar_t wc = ((ch & 0x1F) << 6) | (s[i + 1] & 0x3F);
|
||||
result += wc;
|
||||
i += 2;
|
||||
} else if ((ch >> 4) == 0b1110) { // 3-byte char
|
||||
if (i + 2 >= s.size()) {
|
||||
return L""; // return empty if error
|
||||
}
|
||||
wchar_t wc =
|
||||
((ch & 0x0F) << 12) | ((s[i + 1] & 0x3F) << 6) | (s[i + 2] & 0x3F);
|
||||
result += wc;
|
||||
i += 3;
|
||||
} else if ((ch >> 3) == 0b11110) { // 4-byte char
|
||||
if (i + 3 >= s.size()) {
|
||||
return L""; // return empty if error
|
||||
}
|
||||
uint32_t codepoint = ((ch & 0x07) << 18) | ((s[i + 1] & 0x3F) << 12) |
|
||||
((s[i + 2] & 0x3F) << 6) | (s[i + 3] & 0x3F);
|
||||
codepoint -= 0x10000;
|
||||
result += static_cast<wchar_t>(0xD800 + (codepoint >> 10));
|
||||
result += static_cast<wchar_t>(0xDC00 + (codepoint & 0x3FF));
|
||||
i += 4;
|
||||
} else {
|
||||
return L"";
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::string FormatNanos(unsigned long long nanos) {
|
||||
PD_CORE_API const std::string FormatNanos(unsigned long long nanos) {
|
||||
// Based on some code of my minecraft plugins
|
||||
if (nanos < 1000) {
|
||||
return std::format("{}ns", nanos);
|
||||
@ -71,7 +106,7 @@ const std::string FormatNanos(unsigned long long nanos) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const std::string FormatMillis(unsigned long long millis) {
|
||||
PD_CORE_API const std::string FormatMillis(unsigned long long millis) {
|
||||
// Original Code can be found in some of my mv plugins
|
||||
if (millis < 1000) {
|
||||
return std::format("{}ms", millis);
|
||||
@ -86,7 +121,7 @@ const std::string FormatMillis(unsigned long long millis) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const std::string FormatBytes(unsigned long long bytes) {
|
||||
PD_CORE_API const std::string FormatBytes(unsigned long long bytes) {
|
||||
static const std::vector<std::string> endings = {
|
||||
"B", "KB", "MB", "GB", "TB", "Unk",
|
||||
};
|
||||
@ -102,8 +137,8 @@ const std::string FormatBytes(unsigned long long bytes) {
|
||||
return std::format("{:.1f} {}", b, endings[i]);
|
||||
}
|
||||
|
||||
const std::string GetFileName(const std::string& path,
|
||||
const std::string& saperators) {
|
||||
PD_CORE_API const std::string GetFileName(const std::string& path,
|
||||
const std::string& saperators) {
|
||||
auto pos = path.find_last_of(saperators);
|
||||
if (pos != path.npos) {
|
||||
return path.substr(pos + 1);
|
||||
@ -112,7 +147,7 @@ const std::string GetFileName(const std::string& path,
|
||||
return path;
|
||||
}
|
||||
|
||||
const std::string PathRemoveExtension(const std::string& path) {
|
||||
PD_CORE_API const std::string PathRemoveExtension(const std::string& path) {
|
||||
auto pos = path.find_last_of('.');
|
||||
if (pos != path.npos) {
|
||||
return path.substr(0, pos);
|
||||
@ -121,7 +156,7 @@ const std::string PathRemoveExtension(const std::string& path) {
|
||||
return path;
|
||||
}
|
||||
|
||||
u32 FastHash(const std::string& s) {
|
||||
PD_CORE_API u32 FastHash(const std::string& s) {
|
||||
u32 hash = 5381;
|
||||
for (auto& it : s) {
|
||||
hash = (hash * 33) + static_cast<u8>(it);
|
||||
|
@ -26,17 +26,17 @@ SOFTWARE.
|
||||
|
||||
namespace PD::Sys {
|
||||
TraceMap pd_sys_tm;
|
||||
u64 GetTime() {
|
||||
PD_CORE_API u64 GetTime() {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
u64 GetNanoTime() {
|
||||
PD_CORE_API u64 GetNanoTime() {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
TT::Res::Ref& GetTraceRef(const std::string& id) {
|
||||
PD_CORE_API TT::Res::Ref& GetTraceRef(const std::string& id) {
|
||||
// Auto Generate a New if doesnt exist
|
||||
if (pd_sys_tm.find(id) == pd_sys_tm.end()) {
|
||||
pd_sys_tm[id] = TT::Res::New();
|
||||
@ -44,8 +44,8 @@ TT::Res::Ref& GetTraceRef(const std::string& id) {
|
||||
}
|
||||
return pd_sys_tm[id];
|
||||
}
|
||||
bool TraceExist(const std::string& id) {
|
||||
PD_CORE_API bool TraceExist(const std::string& id) {
|
||||
return pd_sys_tm.find(id) != pd_sys_tm.end();
|
||||
}
|
||||
TraceMap& GetTraceMap() { return pd_sys_tm; }
|
||||
PD_CORE_API TraceMap& GetTraceMap() { return pd_sys_tm; }
|
||||
} // namespace PD::Sys
|
@ -25,25 +25,25 @@ SOFTWARE.
|
||||
#include <pd/core/timer.hpp>
|
||||
|
||||
namespace PD {
|
||||
Timer::Timer(bool autostart) {
|
||||
PD_CORE_API Timer::Timer(bool autostart) {
|
||||
is_running = autostart;
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Timer::Reset() {
|
||||
PD_CORE_API void Timer::Reset() {
|
||||
start = Sys::GetTime();
|
||||
now = start;
|
||||
}
|
||||
|
||||
void Timer::Update() {
|
||||
PD_CORE_API void Timer::Update() {
|
||||
if (is_running) {
|
||||
now = Sys::GetTime();
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::Pause() { is_running = false; }
|
||||
void Timer::Rseume() { is_running = true; }
|
||||
bool Timer::IsRunning() const { return is_running; }
|
||||
u64 Timer::Get() { return now - start; }
|
||||
double Timer::GetSeconds() { return double(Get()) / 1000.0; }
|
||||
PD_CORE_API void Timer::Pause() { is_running = false; }
|
||||
PD_CORE_API void Timer::Rseume() { is_running = true; }
|
||||
PD_CORE_API bool Timer::IsRunning() const { return is_running; }
|
||||
PD_CORE_API u64 Timer::Get() { return now - start; }
|
||||
PD_CORE_API double Timer::GetSeconds() { return double(Get()) / 1000.0; }
|
||||
} // namespace PD
|
@ -25,12 +25,12 @@ SOFTWARE.
|
||||
#include <pd/core/timetrace.hpp>
|
||||
|
||||
namespace PD::TT {
|
||||
void Beg(const std::string& id) {
|
||||
PD_CORE_API void Beg(const std::string& id) {
|
||||
auto trace = Sys::GetTraceRef(id);
|
||||
trace->SetStart(PD::Sys::GetNanoTime());
|
||||
}
|
||||
|
||||
void End(const std::string& id) {
|
||||
PD_CORE_API void End(const std::string& id) {
|
||||
auto trace = Sys::GetTraceRef(id);
|
||||
trace->SetEnd(PD::Sys::GetNanoTime());
|
||||
}
|
||||
|
6
source/external/stb.cpp
vendored
6
source/external/stb.cpp
vendored
@ -1,4 +1,4 @@
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <pd/external/stb_image.h>
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <pd/external/stb_image.h>
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include <pd/external/stb_truetype.h>
|
@ -22,6 +22,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef PD_IMAGE_BUILD_SHARED
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
#include <pd/external/stb_image.h>
|
||||
|
||||
#include <cstring>
|
||||
@ -30,31 +34,121 @@ SOFTWARE.
|
||||
#include <pd/image/img_convert.hpp>
|
||||
|
||||
namespace PD {
|
||||
void Image::Load(const std::string& path) {
|
||||
u8* img = stbi_load(path.c_str(), &w, &h, &fmt, 4);
|
||||
PD_IMAGE_API void Image::Load(const std::string& path) {
|
||||
u8* img = stbi_load(path.c_str(), &pWidth, &pHeight, &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<u8>(img, img + (w * h * 3)), w, h);
|
||||
} else {
|
||||
buffer.assign(img, img + (w * h * 4));
|
||||
img = stbi_load(path.c_str(), &pWidth, &pHeight, &fmt, 3);
|
||||
pBuffer = std::vector<PD::u8>(img, img + (pWidth * pHeight * 3));
|
||||
pFmt = RGB;
|
||||
stbi_image_free(img);
|
||||
} else if (fmt == 4) {
|
||||
pBuffer = std::vector<PD::u8>(img, img + (pWidth * pHeight * 4));
|
||||
pFmt = RGBA;
|
||||
stbi_image_free(img);
|
||||
}
|
||||
}
|
||||
void Image::Load(const std::vector<u8>& buf) {
|
||||
u8* img = stbi_load_from_memory(buf.data(), buf.size(), &w, &h, &fmt, 4);
|
||||
PD_IMAGE_API void Image::Load(const std::vector<u8>& buf) {
|
||||
u8* img =
|
||||
stbi_load_from_memory(buf.data(), buf.size(), &pWidth, &pHeight, &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<u8>(img, img + (w * h * 3)), w, h);
|
||||
} else {
|
||||
buffer.assign(img, img + (w * h * 4));
|
||||
img = stbi_load_from_memory(buf.data(), buf.size(), &pWidth, &pHeight, &fmt,
|
||||
3);
|
||||
pBuffer = std::vector<PD::u8>(img, img + (pWidth * pHeight * 3));
|
||||
pFmt = RGB;
|
||||
stbi_image_free(img);
|
||||
} else if (fmt == 4) {
|
||||
pBuffer = std::vector<PD::u8>(img, img + (pWidth * pHeight * 4));
|
||||
stbi_image_free(img);
|
||||
pFmt = RGBA;
|
||||
}
|
||||
}
|
||||
PD_IMAGE_API void Image::Copy(const std::vector<u8>& buf, int w, int h,
|
||||
int bpp) {
|
||||
this->fmt = bpp;
|
||||
if (buf.size() != (size_t)w * h * bpp) {
|
||||
// Size Error
|
||||
return;
|
||||
}
|
||||
this->pBuffer.resize(w * h * bpp);
|
||||
for (size_t i = 0; i < this->pBuffer.size(); i++) {
|
||||
pBuffer[i] = buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void Image::Convert(Image::Ref img, Image::Format dst) {
|
||||
if (img->Fmt() == dst) {
|
||||
return;
|
||||
} else if (img->Fmt() == Image::RGB && dst == Image::BGR) {
|
||||
ImgConvert::ReverseBuf(img->pBuffer, 3, img->pWidth, img->pHeight);
|
||||
} else if (img->Fmt() == Image::RGB && dst == Image::RGBA) {
|
||||
std::vector<PD::u8> cpy = img->pBuffer;
|
||||
img->pBuffer.resize(img->pWidth * img->pHeight * 4);
|
||||
ImgConvert::RGB24toRGBA32(img->pBuffer, cpy, img->pWidth, img->pHeight);
|
||||
} else if (img->Fmt() == Image::RGBA && dst == Image::RGB) {
|
||||
std::vector<PD::u8> cpy = img->pBuffer;
|
||||
img->pBuffer.resize(img->pWidth * img->pHeight * 3);
|
||||
ImgConvert::RGB32toRGBA24(img->pBuffer, cpy, img->pWidth, img->pHeight);
|
||||
} else if (img->Fmt() == Image::RGBA && dst == Image::RGB565) {
|
||||
Convert(img, Image::RGB);
|
||||
Convert(img, Image::RGB565);
|
||||
} else if (img->Fmt() == Image::RGB && dst == Image::RGB565) {
|
||||
auto f = [](u8 r, u8 g, u8 b) -> u16 {
|
||||
u16 _r = (r >> 3);
|
||||
u16 _g = (g >> 2);
|
||||
u16 _b = (b >> 3);
|
||||
return (_r << 11) | (_g << 5) | _b;
|
||||
};
|
||||
std::vector<PD::u8> cpy = img->pBuffer;
|
||||
img->pBuffer.resize(img->pWidth * img->pHeight * 2);
|
||||
for (int y = 0; y < img->pWidth; y++) {
|
||||
for (int x = 0; x < img->pHeight; x++) {
|
||||
int src = (y * img->pWidth + x) * 3;
|
||||
int dst = (y * img->pWidth + x) * 2;
|
||||
u16 new_px = f(cpy[src + 0], cpy[src + 1], cpy[src + 2]);
|
||||
img->pBuffer[dst + 0] = new_px >> 8;
|
||||
img->pBuffer[dst + 1] = new_px & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API int Image::Fmt2Bpp(Format fmt) {
|
||||
switch (fmt) {
|
||||
case RGBA:
|
||||
case ABGR:
|
||||
return 4;
|
||||
break;
|
||||
case RGB:
|
||||
case BGR:
|
||||
return 3;
|
||||
break;
|
||||
case RGB565:
|
||||
return 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void Image::ReTile(Image::Ref img,
|
||||
std::function<u32(int x, int y, int w)> src,
|
||||
std::function<u32(int x, int y, int w)> dst) {
|
||||
std::vector<PD::u8> cpy = img->pBuffer;
|
||||
/** could use fmt here but for 565 that woulnt work as it is not supported by
|
||||
* file loading where fmt is used */
|
||||
int bpp = Fmt2Bpp(img->pFmt);
|
||||
for (int y = 0; y < img->pHeight; y++) {
|
||||
for (int x = 0; x < img->pWidth; x++) {
|
||||
int src_idx = src(x, y, img->pWidth);
|
||||
int dst_idx = dst(x, y, img->pWidth);
|
||||
for (int i = 0; i < bpp; i++) {
|
||||
img->pBuffer[dst_idx + i] = cpy[src_idx + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void Image::Copy(const std::vector<u8>& buf, int w, int h, int fmt) {}
|
||||
} // namespace PD
|
@ -29,7 +29,7 @@ SOFTWARE.
|
||||
|
||||
namespace PD {
|
||||
namespace ImgBlur {
|
||||
std::vector<float> GaussianKernel(int r, float si) {
|
||||
PD_IMAGE_API std::vector<float> GaussianKernel(int r, float si) {
|
||||
/// Define radius as r to be shorter
|
||||
int size = 2 * r + 1;
|
||||
std::vector<float> kernel(size);
|
||||
@ -45,13 +45,15 @@ std::vector<float> GaussianKernel(int r, float si) {
|
||||
}
|
||||
return kernel;
|
||||
}
|
||||
void GaussianBlur(std::vector<u8> &buf, int w, int h, float radius, float si,
|
||||
std::function<int(int, int, int)> idxfn) {
|
||||
PD_IMAGE_API void GaussianBlur(std::vector<u8> &buf, int w, int h, float radius,
|
||||
float si,
|
||||
std::function<int(int, int, int)> idxfn) {
|
||||
GaussianBlur(buf.data(), w, h, 4, radius, si, idxfn);
|
||||
}
|
||||
|
||||
void GaussianBlur(void *buf, int w, int h, int bpp, float radius, float si,
|
||||
std::function<int(int, int, int)> idxfn) {
|
||||
PD_IMAGE_API void GaussianBlur(void *buf, int w, int h, int bpp, float radius,
|
||||
float si,
|
||||
std::function<int(int, int, int)> idxfn) {
|
||||
if (bpp != 4 && bpp != 3) {
|
||||
return;
|
||||
}
|
||||
|
@ -24,8 +24,9 @@ SOFTWARE.
|
||||
#include <pd/image/img_convert.hpp>
|
||||
|
||||
namespace PD::ImgConvert {
|
||||
void RGB24toRGBA32(std::vector<u8> &out, const std::vector<u8> &in,
|
||||
const int &w, const int &h) {
|
||||
|
||||
PD_IMAGE_API void RGB24toRGBA32(std::vector<u8> &out, const std::vector<u8> &in,
|
||||
const int &w, const int &h) {
|
||||
// Converts RGB24 to RGBA32
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
@ -38,7 +39,22 @@ void RGB24toRGBA32(std::vector<u8> &out, const std::vector<u8> &in,
|
||||
}
|
||||
}
|
||||
}
|
||||
void Reverse32(std::vector<u8> &buf, const int &w, const int &h) {
|
||||
|
||||
PD_IMAGE_API void RGB32toRGBA24(std::vector<u8> &out, const std::vector<u8> &in,
|
||||
const int &w, const int &h) {
|
||||
// Converts RGB24 to RGBA32
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int src = (y * w + x) * 4;
|
||||
int dst = (y * w + x) * 3;
|
||||
out[dst + 0] = in[src + 0];
|
||||
out[dst + 1] = in[src + 1];
|
||||
out[dst + 2] = in[src + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void Reverse32(std::vector<u8> &buf, const int &w, const int &h) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int i = y * w + x;
|
||||
@ -51,4 +67,71 @@ void Reverse32(std::vector<u8> &buf, const int &w, const int &h) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void ReverseBuf(std::vector<u8> &buf, size_t bpp, int w, int h) {
|
||||
std::vector<u8> cpy = buf;
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int pos = (y * w + x) * bpp;
|
||||
for (size_t i = 0; i < bpp; i++) {
|
||||
buf[pos + bpp - 1 - i] = cpy[pos + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void RGB24toRGBA32(PD::Vec<u8> &out, const PD::Vec<u8> &in,
|
||||
const int &w, const int &h) {
|
||||
// Converts RGB24 to RGBA32
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int src = (y * w + x) * 3;
|
||||
int dst = (y * w + x) * 4;
|
||||
out[dst + 0] = in[src + 0];
|
||||
out[dst + 1] = in[src + 1];
|
||||
out[dst + 2] = in[src + 2];
|
||||
out[dst + 3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void RGB32toRGBA24(PD::Vec<u8> &out, const PD::Vec<u8> &in,
|
||||
const int &w, const int &h) {
|
||||
// Converts RGB24 to RGBA32
|
||||
for (int y = 0; y < h; y++) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
int src = (y * w + x) * 4;
|
||||
int dst = (y * w + x) * 3;
|
||||
out[dst + 0] = in[src + 0];
|
||||
out[dst + 1] = in[src + 1];
|
||||
out[dst + 2] = in[src + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void Reverse32(PD::Vec<u8> &buf, const int &w, const int &h) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int i = y * w + x;
|
||||
u8 t0 = buf[i + 0];
|
||||
u8 t1 = buf[i + 1];
|
||||
buf[i + 0] = buf[i + 3];
|
||||
buf[i + 1] = buf[i + 2];
|
||||
buf[i + 3] = t0;
|
||||
buf[i + 2] = t1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PD_IMAGE_API void ReverseBuf(PD::Vec<u8> &buf, size_t bpp, int w, int h) {
|
||||
PD::Vec<u8> cpy = buf;
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int pos = (y * w + x) * bpp;
|
||||
for (size_t i = 0; i < bpp; i++) {
|
||||
buf[pos + bpp - 1 - i] = cpy[pos + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace PD::ImgConvert
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#include <pd/lib3ds/drv_hid.hpp>
|
||||
|
||||
/// Reform of the RenderD7 095 Hid Api
|
||||
/// Using Custom Keybindings for future
|
||||
/// Porting of the library
|
||||
|
||||
namespace PD {
|
||||
CtrHid::CtrHid() {
|
||||
binds[KEY_A] = A;
|
||||
binds[KEY_B] = B;
|
||||
binds[KEY_X] = X;
|
||||
binds[KEY_Y] = Y;
|
||||
binds[KEY_START] = Start;
|
||||
binds[KEY_SELECT] = Select;
|
||||
binds[KEY_L] = L;
|
||||
binds[KEY_R] = R;
|
||||
binds[KEY_DUP] = DUp;
|
||||
binds[KEY_DDOWN] = DDown;
|
||||
binds[KEY_DLEFT] = DLeft;
|
||||
binds[KEY_DRIGHT] = DRight;
|
||||
binds[KEY_CPAD_UP] = CPUp;
|
||||
binds[KEY_CPAD_DOWN] = CPDown;
|
||||
binds[KEY_CPAD_LEFT] = CPLeft;
|
||||
binds[KEY_CPAD_RIGHT] = CPRight;
|
||||
binds[KEY_CSTICK_UP] = CSUp;
|
||||
binds[KEY_CSTICK_DOWN] = CSDown;
|
||||
binds[KEY_CSTICK_LEFT] = CSLeft;
|
||||
binds[KEY_CSTICK_RIGHT] = CSRight;
|
||||
binds[KEY_ZL] = ZL;
|
||||
binds[KEY_ZR] = ZR;
|
||||
binds[KEY_TOUCH] = Touch;
|
||||
}
|
||||
void CtrHid::Update() {
|
||||
hidScanInput();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
key_events[i][Event_Down] = 0;
|
||||
key_events[i][Event_Held] = 0;
|
||||
key_events[i][Event_Up] = 0;
|
||||
}
|
||||
u32 kd = hidKeysDown();
|
||||
u32 kh = hidKeysHeld();
|
||||
u32 ku = hidKeysUp();
|
||||
for (auto &b : binds) {
|
||||
if (b.first & kd) {
|
||||
key_events[0][Event_Down] |= b.second;
|
||||
}
|
||||
if (b.first & kh) {
|
||||
key_events[0][Event_Held] |= b.second;
|
||||
}
|
||||
if (b.first & ku) {
|
||||
key_events[0][Event_Up] |= b.second;
|
||||
}
|
||||
}
|
||||
if (locked) {
|
||||
SwappyTable();
|
||||
}
|
||||
touchPosition t;
|
||||
hidTouchRead(&t);
|
||||
touch[1] = touch[0]; // Cycle touch pos
|
||||
touch[0] = vec2(t.px, t.py);
|
||||
}
|
||||
} // namespace PD
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/lib3ds/gamepad_icons.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace GamePadIcons {
|
||||
/// For Reference see docs at 3DBrew
|
||||
std::unordered_map<ID, std::string> gp_icons{
|
||||
{A, "\uE000"},
|
||||
{B, "\uE001"},
|
||||
{X, "\uE002"},
|
||||
{Y, "\uE003"},
|
||||
{L, "\uE004"},
|
||||
{R, "\uE005"},
|
||||
{Dpad, "\uE006"},
|
||||
{Start, "\uE045"},
|
||||
{Select, "\uE046"},
|
||||
{Home, "\uE073"},
|
||||
{Steps, "\uE074"},
|
||||
{PlayCoin, "\uE075"},
|
||||
{AnalogStick, "\uE077"},
|
||||
{Power3DS, "\uE078"},
|
||||
{DpadUp, "\uE079"},
|
||||
{DpadDown, "\uE07A"},
|
||||
{DpadLeft, "\uE07B"},
|
||||
{DpadRight, "\uE07C"},
|
||||
{DpadHorizontal, "\uE07D"},
|
||||
{DpadVertical, "\uE07E"},
|
||||
};
|
||||
std::unordered_map<Hid::Key, ID> gp_link{
|
||||
{Hid::A, ID::A},
|
||||
{Hid::B, ID::B},
|
||||
{Hid::X, ID::X},
|
||||
{Hid::Y, ID::Y},
|
||||
{Hid::L, ID::L},
|
||||
{Hid::R, ID::R},
|
||||
{Hid::Start, ID::Start},
|
||||
{Hid::Select, ID::Select},
|
||||
{Hid::DUp, ID::DpadUp},
|
||||
{Hid::DDown, ID::DpadDown},
|
||||
{Hid::DLeft, ID::DpadLeft},
|
||||
{Hid::DRight, ID::DpadRight},
|
||||
};
|
||||
std::string GetIcon(ID id) {
|
||||
auto e = gp_icons.find(id);
|
||||
if (e == gp_icons.end()) {
|
||||
return "";
|
||||
}
|
||||
return e->second;
|
||||
}
|
||||
std::string GetIcon(Hid::Key key) {
|
||||
auto e = gp_link.find(key);
|
||||
if (e == gp_link.end()) {
|
||||
return "";
|
||||
}
|
||||
return gp_icons[gp_link[key]];
|
||||
}
|
||||
} // namespace GamePadIcons
|
||||
} // namespace PD
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#include <pd/lib3ds/os.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace Ctr {
|
||||
std::string GetSystemLanguage() {
|
||||
u8 language = 0;
|
||||
Result res = CFGU_GetSystemLanguage(&language);
|
||||
if (R_FAILED(res)) {
|
||||
return "en";
|
||||
}
|
||||
switch (language) {
|
||||
case 0:
|
||||
return "jp"; // Japanese
|
||||
break;
|
||||
case 1:
|
||||
return "en"; // English
|
||||
break;
|
||||
case 2:
|
||||
return "fr"; // French
|
||||
break;
|
||||
case 3:
|
||||
return "de"; // German
|
||||
break;
|
||||
case 4:
|
||||
return "it"; // Italian
|
||||
break;
|
||||
case 5:
|
||||
return "es"; // Spanish
|
||||
break;
|
||||
case 6:
|
||||
return "zh-CN"; // Chinese (Simplified)
|
||||
break;
|
||||
case 7:
|
||||
return "ko"; // Korean
|
||||
break;
|
||||
case 8:
|
||||
return "nl"; // Dutch
|
||||
break;
|
||||
case 9:
|
||||
return "pt"; // Portuguese
|
||||
break;
|
||||
case 10:
|
||||
return "ru"; // Russian
|
||||
break;
|
||||
case 11:
|
||||
return "zh-TW"; // Chinese (Traditional)
|
||||
break;
|
||||
default:
|
||||
return "en"; // Fall back to English if missing
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // namespace Ctr
|
||||
} // namespace PD
|
@ -1,311 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifdef PD_EXTENDED_DEBUG
|
||||
#include <pd/lib3ds/result_decoder.hpp>
|
||||
|
||||
static const std::map<int, std::string> modules = {
|
||||
{0, "common"},
|
||||
{1, "kernel"},
|
||||
{2, "util"},
|
||||
{3, "file server"},
|
||||
{4, "loader server"},
|
||||
{5, "tcb"},
|
||||
{6, "os"},
|
||||
{7, "dbg"},
|
||||
{8, "dmnt"},
|
||||
{9, "pdn"},
|
||||
{10, "gsp"},
|
||||
{11, "i2c"},
|
||||
{12, "gpio"},
|
||||
{13, "dd"},
|
||||
{14, "codec"},
|
||||
{15, "spi"},
|
||||
{16, "pxi"},
|
||||
{17, "fs"},
|
||||
{18, "di"},
|
||||
{19, "hid"},
|
||||
{20, "cam"},
|
||||
{21, "pi"},
|
||||
{22, "pm"},
|
||||
{23, "pm_low"},
|
||||
{24, "fsi"},
|
||||
{25, "srv"},
|
||||
{26, "ndm"},
|
||||
{27, "nwm"},
|
||||
{28, "soc"},
|
||||
{29, "ldr"},
|
||||
{30, "acc"},
|
||||
{31, "romfs"},
|
||||
{32, "am"},
|
||||
{33, "hio"},
|
||||
{34, "updater"},
|
||||
{35, "mic"},
|
||||
{36, "fnd"},
|
||||
{37, "mp"},
|
||||
{38, "mpwl"},
|
||||
{39, "ac"},
|
||||
{40, "http"},
|
||||
{41, "dsp"},
|
||||
{42, "snd"},
|
||||
{43, "dlp"},
|
||||
{44, "hio_low"},
|
||||
{45, "csnd"},
|
||||
{46, "ssl"},
|
||||
{47, "am_low"},
|
||||
{48, "nex"},
|
||||
{49, "friends"},
|
||||
{50, "rdt"},
|
||||
{51, "applet"},
|
||||
{52, "nim"},
|
||||
{53, "ptm"},
|
||||
{54, "midi"},
|
||||
{55, "mc"},
|
||||
{56, "swc"},
|
||||
{57, "fatfs"},
|
||||
{58, "ngc"},
|
||||
{59, "card"},
|
||||
{60, "cardnor"},
|
||||
{61, "sdmc"},
|
||||
{62, "boss"},
|
||||
{63, "dbm"},
|
||||
{64, "config"},
|
||||
{65, "ps"},
|
||||
{66, "cec"},
|
||||
{67, "ir"},
|
||||
{68, "uds"},
|
||||
{69, "pl"},
|
||||
{70, "cup"},
|
||||
{71, "gyroscope"},
|
||||
{72, "mcu"},
|
||||
{73, "ns"},
|
||||
{74, "news"},
|
||||
{75, "ro"},
|
||||
{76, "gd"},
|
||||
{77, "card spi"},
|
||||
{78, "ec"},
|
||||
{79, "web browser"},
|
||||
{80, "test"},
|
||||
{81, "enc"},
|
||||
{82, "pia"},
|
||||
{83, "act"},
|
||||
{84, "vctl"},
|
||||
{85, "olv"},
|
||||
{86, "neia"},
|
||||
{87, "npns"},
|
||||
{90, "avd"},
|
||||
{91, "l2b"},
|
||||
{92, "mvd"},
|
||||
{93, "nfc"},
|
||||
{94, "uart"},
|
||||
{95, "spm"},
|
||||
{96, "qtm"},
|
||||
{97, "nfp"},
|
||||
{254, "application"},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> levels = {
|
||||
{0, "Success"}, {1, "Info"}, {25, "Status"},
|
||||
{26, "Temporary"}, {27, "Permanent"}, {28, "Usage"},
|
||||
{29, "Reinitialize"}, {30, "Reset"}, {31, "Fatal"},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> summaries = {
|
||||
{0, "Success"},
|
||||
{1, "Nothing happened"},
|
||||
{2, "Would block"},
|
||||
{3, "Out of resource"},
|
||||
{4, "Not found"},
|
||||
{5, "Invalid state"},
|
||||
{6, "Not supported"},
|
||||
{7, "Invalid argument"},
|
||||
{8, "Wrong argument"},
|
||||
{9, "Canceled"},
|
||||
{10, "Status changed"},
|
||||
{11, "Internal"},
|
||||
{63, "Invalid result value"},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> desccommon = {
|
||||
{0, "Success"},
|
||||
{1000, "Invalid selection"},
|
||||
{1001, "Too large"},
|
||||
{1002, "Not authorized"},
|
||||
{1003, "Already done"},
|
||||
{1004, "Invalid size"},
|
||||
{1005, "Invalid enum value"},
|
||||
{1006, "Invalid combination"},
|
||||
{1007, "No data"},
|
||||
{1008, "Busy"},
|
||||
{1009, "Misaligned address"},
|
||||
{1010, "Misaligned size"},
|
||||
{1011, "Out of memory"},
|
||||
{1012, "Not implemented"},
|
||||
{1013, "Invalid address"},
|
||||
{1014, "Invalid pointer"},
|
||||
{1015, "Invalid handle"},
|
||||
{1016, "Not initialized"},
|
||||
{1017, "Already initialized"},
|
||||
{1018, "Not found"},
|
||||
{1019, "Cancel requested"},
|
||||
{1020, "Already exists"},
|
||||
{1021, "Out of range"},
|
||||
{1022, "Timeout"},
|
||||
{1023, "Invalid result value"},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> desckernel = {
|
||||
{2, "Invalid memory permissions."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descos = {
|
||||
{10, "Not enough memory."},
|
||||
{26, "Session closed by remote."},
|
||||
{47, "Invalid command header."},
|
||||
};
|
||||
|
||||
// Need to Fix The Range based Values
|
||||
static const std::map<int, std::string> descfs = {
|
||||
{101, "Archive not mounted or mount-point not found."},
|
||||
{120, "Title or object not found."},
|
||||
{141, "Gamecard not inserted."},
|
||||
{230, "Invalid open flags or permissions."},
|
||||
{391, "NCCH hash check failed."},
|
||||
{302, "RSA or AES-MAC verification failed."},
|
||||
{395, "RomFS or Savedata hash check failed."},
|
||||
{630, "Command not allowed, or missing permissions."},
|
||||
{702, "Invalid path."},
|
||||
{761, "Incorrect ExeFS read size."},
|
||||
{100, "[Media] not found."},
|
||||
{180, "Exists already."},
|
||||
{200, "Not enough space."},
|
||||
{220, "Invalidated archive."},
|
||||
{230, "Unacceptable or write protected."},
|
||||
{340, "0x01"},
|
||||
{360, "Bad format."},
|
||||
{390, "Verification failure."},
|
||||
{400, "0x01"},
|
||||
{600, "Out of resources."},
|
||||
{630, "Access denied."},
|
||||
{661, "0x01"},
|
||||
{700, "Invalid argument."},
|
||||
{730, "Not initialized."},
|
||||
{750, "Already initialized."},
|
||||
{760, "Not supported."},
|
||||
{780, "0x01"},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descsrv = {
|
||||
{5,
|
||||
"Invalid string length (service name length is zero or longer than 8 "
|
||||
"chars)."},
|
||||
{6,
|
||||
"Access to service denied (requested a service the application does "
|
||||
"not have access to)."},
|
||||
{7,
|
||||
"String size does not match contents (service name contains unexpected "
|
||||
"null byte)."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descnwm = {
|
||||
{2,
|
||||
"This error usually indicates the wifi chipset in the console is dying "
|
||||
"or dead."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descam = {
|
||||
{4, "Invalid ticket version."},
|
||||
{32, "Empty CIA."},
|
||||
{37, "Invalid NCCH."},
|
||||
{39, "Invalid title version."},
|
||||
{43, "Database doesn\"t exist, or it failed to open."},
|
||||
{44, "Trying to uninstall system-app."},
|
||||
{106,
|
||||
"Invalid signature/CIA. Usually happens when developer UNITINFO is "
|
||||
"enabled in Luma3DS."},
|
||||
{393, "Invalid database."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> deschttp = {
|
||||
{105, "Request timed out."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descnim = {
|
||||
{1,
|
||||
"Invalid string IPC paramater (non null terminated at its indicated "
|
||||
"length)."},
|
||||
{12,
|
||||
"Invalid country code returned by CFG module reading config save "
|
||||
"0xB0000."},
|
||||
{13,
|
||||
"Zero string length console serial number or '000000000000000' "
|
||||
"returned by CFG's SecureInfoGetSerialNo."},
|
||||
{18,
|
||||
"General data reading error of NIM's .dat files from its system save, "
|
||||
"bad data or bad data lengths."},
|
||||
{22,
|
||||
"General invalid data or length of data returned from nintendo "
|
||||
"servers. (Only applicable for some operations)"},
|
||||
{25,
|
||||
"IntegrityVerificationSeed is waiting on servers to be synced into "
|
||||
"console. Can't processed with online services without sync being "
|
||||
"completed first over IPC request."},
|
||||
{26,
|
||||
"Unavailable/unaccessable IntegrityVerificationSeed on Nintendo "
|
||||
"servers. May happen if NIM is told to import "
|
||||
"IntegrityVerificationSeed from servers at any time other than after "
|
||||
"the successful System Transfer reboot."},
|
||||
{27,
|
||||
"Invalid country language code returned by CFG module reading config "
|
||||
"save 0xA0002."},
|
||||
{37,
|
||||
"Service is in Standby Mode. (eShop ban? General service is down? "
|
||||
"This caused by a server response flag on account information. "
|
||||
"Account is not referring to NNID.)"},
|
||||
{39, "HTTP Status non 200. (Only applicable for some operations)"},
|
||||
{40, "General XML read/write error while processing Auto Delivery XMLs."},
|
||||
{41,
|
||||
"General XML read/write error while processing Auto Delivery XMLs. "
|
||||
"(Stubbed virtual call was called)"},
|
||||
{58,
|
||||
"Invalid NPNS token returned by CFG module reading config save 0xF0006."},
|
||||
{67, "HTTP Status 404 while trying to download a game's seed."},
|
||||
{68, "HTTP Status 503 while trying to download a game's seed."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descmvd = {
|
||||
{271, "Invalid configuration."},
|
||||
};
|
||||
|
||||
static const std::map<int, std::string> descqtm = {
|
||||
{8, "Camera is already in use or busy."},
|
||||
};
|
||||
|
||||
// Need to Fix The Range based Values
|
||||
static const std::map<int, std::string> descapplication = {
|
||||
{0,
|
||||
"The application raised an error. Please consult the application's "
|
||||
"source code or ask the author for assistance with it."},
|
||||
{1024, "0x01"},
|
||||
};
|
||||
#endif
|
147
source/lithium/drawlist.cpp
Normal file
147
source/lithium/drawlist.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
#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 Command::Ref DrawList::PreGenerateCmd() {
|
||||
Command::Ref cmd = Command::New();
|
||||
cmd->Layer = Layer;
|
||||
cmd->Index = pDrawList.Size();
|
||||
cmd->Tex = CurrentTex;
|
||||
return cmd;
|
||||
}
|
||||
|
||||
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::PathRect(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 {
|
||||
PathArcToN(vec2(a.x + rounding, a.y + rounding), rounding, 4 * 6, 4 * 9,
|
||||
21);
|
||||
PathArcToN(vec2(b.x - rounding, a.y + rounding), rounding, 4 * 9, 4 * 12,
|
||||
21);
|
||||
PathArcToN(vec2(b.x - rounding, b.y - rounding), rounding, 4 * 0, 4 * 3,
|
||||
21);
|
||||
PathArcToN(vec2(a.x + rounding, b.y - rounding), rounding, 4 * 3, 4 * 6,
|
||||
21);
|
||||
}
|
||||
}
|
||||
|
||||
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& center, 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& center, 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;
|
||||
}
|
||||
CurrentTex = WhitePixel;
|
||||
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, line, vec4(0.f, 1.f, 1.f, 0.f), clr);
|
||||
}
|
||||
}
|
||||
AddCommand(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, points, clr, CurrentTex);
|
||||
AddCommand(cmd);
|
||||
}
|
||||
|
||||
PD_LITHIUM_API void DrawList::DrawText(const fvec2& pos,
|
||||
const std::string& text, u32 color) {
|
||||
if (!pCurrentFont) {
|
||||
return;
|
||||
}
|
||||
PD::Vec<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(cmds[i]);
|
||||
}
|
||||
}
|
||||
} // namespace LI
|
||||
} // namespace PD
|
@ -1,239 +1,278 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
#include <pd/external/stb_truetype.h>
|
||||
|
||||
#include <pd/core/bit_util.hpp>
|
||||
#include <pd/core/io.hpp>
|
||||
#include <pd/core/strings.hpp>
|
||||
#include <pd/core/sys.hpp>
|
||||
#include <pd/lithium/font.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace LI {
|
||||
void Font::LoadTTF(const std::string &path, int height) {
|
||||
sysfont = false; // Not using System Font
|
||||
TT::Scope st("LI_LoadTTF_" + path);
|
||||
pixel_height = height; // Set internel pixel height
|
||||
// Use NextPow2 to be able to use sizes between for example 16 and 32
|
||||
// before it only was possible to use 8, 16, 32, 64 as size
|
||||
int texszs = BitUtil::GetPow2(height * 16);
|
||||
// Load stbtt
|
||||
stbtt_fontinfo inf;
|
||||
std::ifstream loader(path, std::ios::binary);
|
||||
if (!loader.is_open()) return;
|
||||
loader.seekg(0, std::ios::end);
|
||||
size_t len = loader.tellg();
|
||||
loader.seekg(0, std::ios::beg);
|
||||
unsigned char *buffer = new unsigned char[len];
|
||||
loader.read(reinterpret_cast<char *>(buffer), len);
|
||||
loader.close();
|
||||
stbtt_InitFont(&inf, buffer, 0);
|
||||
std::vector<unsigned char> font_tex(texszs * texszs); // Create font Texture
|
||||
float scale = stbtt_ScaleForPixelHeight(&inf, pixel_height);
|
||||
|
||||
int ascent, descent, lineGap;
|
||||
stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap);
|
||||
int baseline = static_cast<int>(ascent * scale);
|
||||
|
||||
std::map<u32, int> buf_cache; // Cache to not render same codepoint tex twice
|
||||
|
||||
/// Load Codepoints
|
||||
auto tex = Texture::New();
|
||||
vec2 off;
|
||||
for (u32 ii = 0x0000; ii < 0xFFFF; ii++) {
|
||||
int i = stbtt_FindGlyphIndex(&inf, ii);
|
||||
if (i == 0) {
|
||||
continue;
|
||||
}
|
||||
if (stbtt_IsGlyphEmpty(&inf, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Codepoint c;
|
||||
int w = 0, h = 0, xo = 0, yo = 0;
|
||||
unsigned char *bitmap =
|
||||
stbtt_GetCodepointBitmap(&inf, scale, scale, i, &w, &h, &xo, &yo);
|
||||
int x0, y0, x1, y1;
|
||||
stbtt_GetCodepointBitmapBox(&inf, i, scale, scale, &x0, &y0, &x1, &y1);
|
||||
|
||||
// Check if Codepoint exists as hash and if it is use its already written
|
||||
// data
|
||||
u32 hashed_map = IO::HashMemory(std::vector<u8>(bitmap, bitmap + (w * h)));
|
||||
if (buf_cache.find(hashed_map) != buf_cache.end()) {
|
||||
c = GetCodepoint(buf_cache[hashed_map]);
|
||||
c.cp(i);
|
||||
cpmap[i] = c;
|
||||
free(bitmap);
|
||||
continue;
|
||||
} else {
|
||||
buf_cache[hashed_map] = i;
|
||||
}
|
||||
|
||||
if (off[0] + w > texszs) {
|
||||
off[1] += pixel_height;
|
||||
off[0] = 0;
|
||||
}
|
||||
|
||||
// Set UV Data
|
||||
vec4 uvs;
|
||||
uvs[0] = static_cast<float>(off.x() / (float)texszs);
|
||||
uvs[1] = static_cast<float>(1.f - (off.y() / (float)texszs));
|
||||
uvs[2] = static_cast<float>((float)(off.x() + w) / (float)texszs);
|
||||
uvs[3] = static_cast<float>(1.f - (float)(off.y() + h) / (float)texszs);
|
||||
c.uv(uvs);
|
||||
|
||||
c.tex(tex);
|
||||
c.size(vec2(w, h));
|
||||
c.off(baseline + yo);
|
||||
|
||||
// Render glyph
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
int map_pos = ((off[1] + y) * texszs + (off[0] + x));
|
||||
font_tex[map_pos] = bitmap[x + y * w];
|
||||
}
|
||||
}
|
||||
|
||||
free(bitmap);
|
||||
cpmap[i] = c;
|
||||
|
||||
// Small Patch to avoid some possible artifacts
|
||||
off[0] += w + 1;
|
||||
if (off[0] + w > texszs) {
|
||||
off[1] += pixel_height;
|
||||
if (off[1] + pixel_height > texszs) {
|
||||
break;
|
||||
}
|
||||
off[0] = 0;
|
||||
}
|
||||
}
|
||||
// Load the Texture and append to list
|
||||
tex->LoadPixels(font_tex, texszs, texszs, Texture::A8, Texture::LINEAR);
|
||||
textures.push_back(tex);
|
||||
}
|
||||
|
||||
Font::Codepoint &Font::GetCodepoint(u32 cp) {
|
||||
// Check if codepoijt exist or return a static invalid one
|
||||
auto res = cpmap.find(cp);
|
||||
if (res == cpmap.end()) {
|
||||
static Codepoint invalid;
|
||||
return invalid.invalid(true);
|
||||
}
|
||||
return res->second;
|
||||
}
|
||||
|
||||
void Font::LoadSystemFont() {
|
||||
TT::Scope st("LI_SystemFont"); // Trace loading time
|
||||
sysfont = true; // Set as System Font
|
||||
fontEnsureMapped(); // Call this to be sure the font is mapped
|
||||
// Get some const references for system font loading
|
||||
const auto fnt = fontGetSystemFont();
|
||||
const auto fnt_info = fontGetInfo(fnt);
|
||||
const auto glyph_info = fontGetGlyphInfo(fnt);
|
||||
// Resize the Texture list by the num of sysfont textures
|
||||
this->textures.resize(glyph_info->nSheets + 1);
|
||||
/// Modify the Pixel Height by 1.1f to fit the
|
||||
/// Size og ttf font Rendering
|
||||
pixel_height = glyph_info->cellHeight * 1.1f;
|
||||
// Load the Textures and make sure they don't auto unload
|
||||
for (size_t i = 0; i < glyph_info->nSheets; i++) {
|
||||
auto stex = Texture::New();
|
||||
auto tx = new C3D_Tex;
|
||||
tx->data = fontGetGlyphSheetTex(fnt, i);
|
||||
tx->fmt = (GPU_TEXCOLOR)glyph_info->sheetFmt;
|
||||
tx->size = glyph_info->sheetSize;
|
||||
tx->width = glyph_info->sheetWidth;
|
||||
tx->height = glyph_info->sheetHeight;
|
||||
tx->param = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) |
|
||||
GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) |
|
||||
GPU_TEXTURE_WRAP_S(GPU_REPEAT) | GPU_TEXTURE_WRAP_T(GPU_REPEAT);
|
||||
tx->border = 0xffffffff;
|
||||
tx->lodParam = 0;
|
||||
stex->LoadExternal(tx, vec2(tx->width, tx->height), vec4(0, 1, 1, 0));
|
||||
stex->AutoUnLoad(false);
|
||||
textures[i] = stex;
|
||||
}
|
||||
std::vector<unsigned int> charSet;
|
||||
// Write the Charset into a vector
|
||||
for (auto cmap = fnt_info->cmap; cmap; cmap = cmap->next) {
|
||||
if (cmap->mappingMethod == CMAP_TYPE_DIRECT) {
|
||||
if (cmap->codeEnd >= cmap->codeBegin) {
|
||||
charSet.reserve(charSet.size() + cmap->codeEnd - cmap->codeBegin + 1);
|
||||
for (auto i = cmap->codeBegin; i <= cmap->codeEnd; ++i) {
|
||||
if (cmap->indexOffset + (i - cmap->codeBegin) == 0xFFFF) break;
|
||||
charSet.emplace_back(i);
|
||||
}
|
||||
}
|
||||
} else if (cmap->mappingMethod == CMAP_TYPE_TABLE) {
|
||||
if (cmap->codeEnd >= cmap->codeBegin) {
|
||||
charSet.reserve(charSet.size() + cmap->codeEnd - cmap->codeBegin + 1);
|
||||
for (auto i = cmap->codeBegin; i <= cmap->codeEnd; ++i) {
|
||||
if (cmap->indexTable[i - cmap->codeBegin] == 0xFFFF) continue;
|
||||
charSet.emplace_back(i);
|
||||
}
|
||||
}
|
||||
} else if (cmap->mappingMethod == CMAP_TYPE_SCAN) {
|
||||
charSet.reserve(charSet.size() + cmap->nScanEntries);
|
||||
for (unsigned i = 0; i < cmap->nScanEntries; ++i) {
|
||||
if (cmap->scanEntries[i].code >= cmap->codeBegin &&
|
||||
cmap->scanEntries[i].code <= cmap->codeEnd) {
|
||||
if (cmap->scanEntries[i].glyphIndex != 0xFFFF) {
|
||||
charSet.emplace_back(cmap->scanEntries[i].code);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the charset and make sure all values are unique
|
||||
std::sort(charSet.begin(), charSet.end());
|
||||
charSet.erase(std::unique(charSet.begin(), charSet.end()));
|
||||
|
||||
// Setup the Codepoint map by the charset
|
||||
for (auto cp : charSet) {
|
||||
int gidx = fontGlyphIndexFromCodePoint(fnt, cp);
|
||||
if (gidx >= 0xFFFF) continue;
|
||||
Codepoint codepoint;
|
||||
fontGlyphPos_s dat;
|
||||
fontCalcGlyphPos(&dat, fnt, gidx, GLYPH_POS_CALC_VTXCOORD, 1.f, 1.f);
|
||||
|
||||
codepoint.cp(cp);
|
||||
codepoint.uv(vec4(dat.texcoord.left, dat.texcoord.top, dat.texcoord.right,
|
||||
dat.texcoord.bottom));
|
||||
|
||||
if (dat.sheetIndex < (int)textures.size()) {
|
||||
codepoint.tex(textures[dat.sheetIndex]);
|
||||
} else {
|
||||
codepoint.invalid(true);
|
||||
}
|
||||
codepoint.size(vec2(dat.vtxcoord.right, dat.vtxcoord.bottom));
|
||||
codepoint.off(0);
|
||||
cpmap[cp] = codepoint;
|
||||
}
|
||||
}
|
||||
} // namespace LI
|
||||
} // namespace PD
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifdef PD_LITHIUM_BUILD_SHARED
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#endif
|
||||
#include <pd/external/stb_truetype.h>
|
||||
|
||||
#include <pd/lithium/font.hpp>
|
||||
#include <pd/lithium/renderer.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace LI {
|
||||
PD_LITHIUM_API void Font::LoadTTF(const std::string &path, int height) {
|
||||
TT::Scope st("LI_LoadTTF_" + path);
|
||||
PixelHeight = height; // Set internel pixel height
|
||||
// Use NextPow2 to be able to use sizes between for example 16 and 32
|
||||
// before it only was possible to use 8, 16, 32, 64 as size
|
||||
int texszs = BitUtil::GetPow2(height * 16);
|
||||
// Load stbtt
|
||||
stbtt_fontinfo inf;
|
||||
std::ifstream loader(path, std::ios::binary);
|
||||
if (!loader.is_open()) return;
|
||||
loader.seekg(0, std::ios::end);
|
||||
size_t len = loader.tellg();
|
||||
loader.seekg(0, std::ios::beg);
|
||||
unsigned char *buffer = new unsigned char[len];
|
||||
loader.read(reinterpret_cast<char *>(buffer), len);
|
||||
loader.close();
|
||||
stbtt_InitFont(&inf, buffer, 0);
|
||||
// clang-format off
|
||||
// Disable clang here cause dont want a garbage looking line
|
||||
std::vector<PD::u8> font_tex(texszs * texszs * 4); // Create font Texture
|
||||
// clang-format on
|
||||
float scale = stbtt_ScaleForPixelHeight(&inf, PixelHeight);
|
||||
|
||||
int ascent, descent, lineGap;
|
||||
stbtt_GetFontVMetrics(&inf, &ascent, &descent, &lineGap);
|
||||
int baseline = static_cast<int>(ascent * scale);
|
||||
|
||||
std::map<u32, int> buf_cache; // Cache to not render same codepoint tex twice
|
||||
|
||||
/// Load Codepoints
|
||||
auto tex = Texture::New();
|
||||
fvec2 off;
|
||||
for (u32 ii = 0x0000; ii < 0xFFFF; ii++) {
|
||||
int i = stbtt_FindGlyphIndex(&inf, ii);
|
||||
if (i == 0) {
|
||||
continue;
|
||||
}
|
||||
if (stbtt_IsGlyphEmpty(&inf, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Codepoint c;
|
||||
int w = 0, h = 0, xo = 0, yo = 0;
|
||||
unsigned char *bitmap =
|
||||
stbtt_GetCodepointBitmap(&inf, scale, scale, i, &w, &h, &xo, &yo);
|
||||
int x0, y0, x1, y1;
|
||||
stbtt_GetCodepointBitmapBox(&inf, i, scale, scale, &x0, &y0, &x1, &y1);
|
||||
|
||||
// Check if Codepoint exists as hash and if it is use its already written
|
||||
// data
|
||||
u32 hashed_map = IO::HashMemory(std::vector<u8>(bitmap, bitmap + (w * h)));
|
||||
if (buf_cache.find(hashed_map) != buf_cache.end()) {
|
||||
c = GetCodepoint(buf_cache[hashed_map]);
|
||||
c.pCodepoint = i;
|
||||
CodeMap[i] = c;
|
||||
free(bitmap);
|
||||
continue;
|
||||
} else {
|
||||
buf_cache[hashed_map] = i;
|
||||
}
|
||||
|
||||
if (off.x + w > texszs) {
|
||||
off.y += PixelHeight;
|
||||
off.x = 0;
|
||||
}
|
||||
|
||||
// Set UV Data
|
||||
fvec4 uvs;
|
||||
uvs.x = static_cast<float>(off.x) / texszs;
|
||||
uvs.y = static_cast<float>(off.y) / texszs;
|
||||
uvs.z = static_cast<float>((off.x + w) / texszs);
|
||||
uvs.w = static_cast<float>((off.y + h) / texszs);
|
||||
if (pBackend->Flags & LIBackendFlags_FlipUV_Y) {
|
||||
uvs.y = 1.f - uvs.y;
|
||||
uvs.w = 1.f - uvs.w;
|
||||
}
|
||||
c.SimpleUV = uvs;
|
||||
c.Tex = tex;
|
||||
c.Size = fvec2(w, h);
|
||||
c.Offset = baseline + yo;
|
||||
|
||||
// Render glyph
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
int map_pos = (((off.y + y) * texszs + (off.x + x))) * 4;
|
||||
font_tex[map_pos + 0] = 255;
|
||||
font_tex[map_pos + 1] = 255;
|
||||
font_tex[map_pos + 2] = 255;
|
||||
font_tex[map_pos + 3] = bitmap[x + y * w];
|
||||
}
|
||||
}
|
||||
|
||||
free(bitmap);
|
||||
CodeMap[i] = c;
|
||||
|
||||
// Small Patch to avoid some possible artifacts
|
||||
off.x += w + 1;
|
||||
if (off.x + w > texszs) {
|
||||
off.y += PixelHeight;
|
||||
if (off.y + PixelHeight > texszs) {
|
||||
break;
|
||||
}
|
||||
off.x = 0;
|
||||
}
|
||||
}
|
||||
// Load the Texture and append to list
|
||||
{
|
||||
auto t = pBackend->LoadTexture(font_tex, texszs, texszs, Texture::RGBA32,
|
||||
Texture::LINEAR);
|
||||
tex->CopyOther(t);
|
||||
}
|
||||
Textures.push_back(tex);
|
||||
}
|
||||
|
||||
PD_LITHIUM_API Font::Codepoint &Font::GetCodepoint(u32 cp) {
|
||||
// Check if codepoijt exist or return a static invalid one
|
||||
auto res = CodeMap.find(cp);
|
||||
if (res == CodeMap.end()) {
|
||||
static Codepoint invalid;
|
||||
invalid.pInvalid = true;
|
||||
return invalid;
|
||||
}
|
||||
return res->second;
|
||||
}
|
||||
|
||||
PD_LITHIUM_API fvec2 Font::GetTextBounds(const std::string &text, float scale) {
|
||||
// Use wstring for exemple for german äöü
|
||||
auto wtext = Strings::MakeWstring(text);
|
||||
// Create a temp position and offset as [0, 0]
|
||||
fvec2 res;
|
||||
float x = 0;
|
||||
// Curent Font Scale
|
||||
float cfs = (DefaultPixelHeight * scale) / (float)PixelHeight;
|
||||
float lh = (float)PixelHeight * cfs;
|
||||
size_t index = 0;
|
||||
for (auto &it : wtext) {
|
||||
if (it == '\0') {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
auto cp = GetCodepoint(it);
|
||||
if (cp.pInvalid && it != '\n' && it != '\t' && it != ' ') {
|
||||
continue;
|
||||
}
|
||||
switch (it) {
|
||||
case '\n':
|
||||
res.y += lh;
|
||||
res.x = std::max(res.x, x);
|
||||
x = 0.f;
|
||||
break;
|
||||
case '\t':
|
||||
x += 16 * cfs;
|
||||
break;
|
||||
case ' ':
|
||||
x += 2 * cfs;
|
||||
// Fall trough here to get the same result as in
|
||||
// TextCommand if/else Section
|
||||
default:
|
||||
x += cp.Size.x * cfs;
|
||||
if (index != wtext.size()) {
|
||||
x += 2 * cfs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
res.x = std::max(res.x, x);
|
||||
res.y += lh;
|
||||
return res;
|
||||
}
|
||||
|
||||
PD_LITHIUM_API void Font::CmdTextEx(Vec<Command::Ref> &cmds, const fvec2 &pos,
|
||||
u32 color, float scale,
|
||||
const std::string &text, LITextFlags flags,
|
||||
const fvec2 &box) {
|
||||
fvec2 off;
|
||||
float cfs = (DefaultPixelHeight * scale) / (float)PixelHeight;
|
||||
float lh = (float)PixelHeight * cfs;
|
||||
fvec2 td;
|
||||
fvec2 rpos = pos;
|
||||
fvec2 rbox = box;
|
||||
if (flags & (LITextFlags_AlignMid | LITextFlags_AlignRight)) {
|
||||
td = GetTextBounds(text, scale);
|
||||
}
|
||||
if (flags & LITextFlags_AlignMid) {
|
||||
rpos = rbox * 0.5 - td * 0.5 + pos;
|
||||
}
|
||||
if (flags & LITextFlags_AlignRight) {
|
||||
rpos.x = rpos.x - td.x;
|
||||
}
|
||||
|
||||
std::vector<std::string> lines;
|
||||
std::istringstream iss(text);
|
||||
std::string tmp;
|
||||
while (std::getline(iss, tmp)) {
|
||||
lines.push_back(tmp);
|
||||
}
|
||||
|
||||
for (auto &it : lines) {
|
||||
/*if (flags & LITextFlags_Short) {
|
||||
fvec2 tmp_dim;
|
||||
it = ShortText(it, box.x() - pos.x(), tmp_dim);
|
||||
}*/
|
||||
auto wline = Strings::MakeWstring(it);
|
||||
auto cmd = Command::New();
|
||||
auto Tex = GetCodepoint(wline[0]).Tex;
|
||||
cmd->Tex = Tex;
|
||||
for (auto &jt : wline) {
|
||||
auto cp = GetCodepoint(jt);
|
||||
if (cp.pInvalid && jt != '\n' && jt != '\t') {
|
||||
continue;
|
||||
}
|
||||
if (Tex != cp.Tex) {
|
||||
cmds.Add(cmd);
|
||||
cmd = Command::New();
|
||||
Tex = cp.Tex;
|
||||
cmd->Tex = Tex;
|
||||
}
|
||||
if (jt == '\t') {
|
||||
off.x += 16 * cfs;
|
||||
} else {
|
||||
if (jt != ' ') {
|
||||
if (flags & LITextFlags_Shaddow) {
|
||||
// Draw
|
||||
Rect rec = Renderer::PrimRect(
|
||||
rpos + vec2(off.x + 1, off.x + (cp.Offset * cfs)) + 1,
|
||||
cp.Size * cfs, 0.f);
|
||||
Renderer::CmdQuad(cmd, rec, cp.SimpleUV, 0xff111111);
|
||||
}
|
||||
// Draw
|
||||
Rect rec = Renderer::PrimRect(
|
||||
rpos + off + fvec2(0, (cp.Offset * cfs)), cp.Size * cfs, 0.f);
|
||||
Renderer::CmdQuad(cmd, rec, cp.SimpleUV, color);
|
||||
} else {
|
||||
off.x += 2 * cfs;
|
||||
}
|
||||
off.x += cp.Size.x * cfs + 2 * cfs;
|
||||
}
|
||||
}
|
||||
cmds.Add(cmd);
|
||||
off.y += lh;
|
||||
off.x = 0;
|
||||
}
|
||||
}
|
||||
} // namespace LI
|
||||
} // namespace PD
|
||||
|
@ -1,34 +0,0 @@
|
||||
// THIS FILE WAS GENERATED BY build_shaders.py!!!
|
||||
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 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/li7_shader.hpp>
|
||||
|
||||
// clang-format off
|
||||
unsigned char li7_shader[] = {
|
||||
0x44, 0x56, 0x4c, 0x42, 0x1, 0x0, 0x0, 0x0, 0xa4, 0x0, 0x0, 0x0, 0x44, 0x56, 0x4c, 0x50, 0x0, 0x0, 0x0, 0x0, 0x28, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, 0x0, 0x0, 0x0, 0x9, 0x0, 0x0, 0x0, 0x98, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0x1, 0xf0, 0x7, 0x4e, 0x2, 0x8, 0x2, 0x8, 0x3, 0x18, 0x2, 0x8, 0x4, 0x28, 0x2, 0x8, 0x5, 0x38, 0x2, 0x8, 0x6, 0x10, 0x40, 0x4c, 0x7, 0xf1, 0x27, 0x22, 0x8, 0x10, 0x21, 0x4c, 0x0, 0x0, 0x0, 0x88, 0xac, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa1, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x68, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x62, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x61, 0xc3, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0xaf, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xd5, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x56, 0x4c, 0x45, 0x2, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x54, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x6c, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x74, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x2, 0x0, 0x5f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x0, 0x1, 0x1, 0x37, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, 0x2, 0x0, 0x1, 0x0, 0xf, 0x0, 0x0, 0x0, 0x3, 0x0, 0x2, 0x0, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x13, 0x0, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0, 0x0,
|
||||
};
|
||||
// clang-format on
|
||||
size_t li7_shader_size = 0x124;
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/external/stb_truetype.h>
|
||||
|
||||
#include <pd/core/io.hpp>
|
||||
#include <pd/core/strings.hpp>
|
||||
#include <pd/core/sys.hpp>
|
||||
#include <pd/lithium/font.hpp>
|
||||
#include <pd/lithium/renderer.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace LI {
|
||||
void StaticText::Setup(Renderer* ren, const vec2& pos, u32 clr,
|
||||
const std::string& text, LITextFlags flags,
|
||||
const vec2& box) {
|
||||
this->tdim = ren->GetTextDimensions(text);
|
||||
this->pos = pos;
|
||||
this->ren = ren;
|
||||
this->text = StaticObject::New();
|
||||
/// Ensure that it also renders Out of Screen i guess
|
||||
ren->TextCommand(this->text->List(), pos, clr, text,
|
||||
flags | LITextFlags_RenderOOS, box);
|
||||
Renderer::OptiCommandList(this->text->List());
|
||||
// Make sure to bring the text in edit mode
|
||||
// Fixes flickering problems in ui7
|
||||
this->text->ReCopy();
|
||||
}
|
||||
|
||||
void StaticText::Draw() {
|
||||
used = true;
|
||||
for (auto& it : text->List()) {
|
||||
ren->PushCommand(it);
|
||||
}
|
||||
text->ReCopy();
|
||||
}
|
||||
|
||||
void StaticText::SetColor(u32 col) { text->ReColor(col); }
|
||||
void StaticText::SetPos(const vec2& pos) { text->MoveIt(pos - this->pos); }
|
||||
|
||||
void StaticText::SetLayer(int layer) { text->ReLayer(layer); }
|
||||
} // namespace LI
|
||||
} // namespace PD
|
@ -1,601 +1,152 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
#include <pd/external/stb_truetype.h>
|
||||
|
||||
#include <pd/core/io.hpp>
|
||||
#include <pd/core/strings.hpp>
|
||||
#include <pd/core/sys.hpp>
|
||||
#include <pd/lithium/font.hpp>
|
||||
#include <pd/lithium/li7_shader.hpp>
|
||||
#include <pd/lithium/renderer.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace LI {
|
||||
Renderer::Renderer(LIRenderFlags flags) {
|
||||
vertex_buf.resize(4 * 4096, Vertex());
|
||||
index_buf.resize(6 * 4096, 0);
|
||||
|
||||
/// Use 3ds u32 here
|
||||
dvlb = DVLB_ParseFile((uint32_t*)li7_shader, li7_shader_size);
|
||||
shaderProgramInit(&shader);
|
||||
shaderProgramSetVsh(&shader, &dvlb->DVLE[0]);
|
||||
uLoc_projection =
|
||||
shaderInstanceGetUniformLocation(shader.vertexShader, "projection");
|
||||
|
||||
AttrInfo_Init(&attr);
|
||||
AttrInfo_AddLoader(&attr, 0, GPU_FLOAT, 2);
|
||||
AttrInfo_AddLoader(&attr, 1, GPU_FLOAT, 2);
|
||||
AttrInfo_AddLoader(&attr, 2, GPU_UNSIGNED_BYTE, 4);
|
||||
|
||||
// Precalculate Projection (Never changes)
|
||||
Mtx_OrthoTilt(&top_proj, 0.f, 400.f, 240.f, 0.f, 1.f, -1.f, false);
|
||||
Mtx_OrthoTilt(&bot_proj, 0.f, 320.f, 240.f, 0.f, 1.f, -1.f, false);
|
||||
|
||||
std::vector<u8> pixels(16 * 16 * 4, 255);
|
||||
white = Texture::New(pixels, 16, 16);
|
||||
UseTex(white);
|
||||
|
||||
// Not Loading as Systemfont is freezing
|
||||
// font = Font::New();
|
||||
// font->LoadSystemFont();
|
||||
}
|
||||
Renderer::~Renderer() {
|
||||
shaderProgramFree(&shader);
|
||||
DVLB_Free(dvlb);
|
||||
}
|
||||
|
||||
bool Renderer::InBox(const vec2& pos, const vec2& szs, const vec4& rect) {
|
||||
return (pos[0] + szs[0] >= rect[0] && pos[1] + szs[1] >= rect[1] &&
|
||||
pos[0] <= rect[2] && pos[1] <= rect[3]);
|
||||
}
|
||||
|
||||
bool Renderer::InBox(const vec2& pos, const vec4& rect) {
|
||||
return (pos.x() > rect.x() && pos.x() < rect.x() + rect.z() &&
|
||||
pos.y() > rect.y() && pos.y() < rect.y() + rect.w());
|
||||
}
|
||||
|
||||
bool Renderer::InBox(const vec2& alpha, const vec2& bravo, const vec2& charlie,
|
||||
const vec4& rect) {
|
||||
return ((alpha[0] < rect[2] && bravo[0] < rect[2] && charlie[0] < rect[2]) ||
|
||||
(alpha[1] < rect[3] && bravo[1] < rect[3] && charlie[1] < rect[3]) ||
|
||||
(alpha[0] > 0 && bravo[0] > 0 && charlie[0] > 0) ||
|
||||
(alpha[1] > 0 && bravo[1] > 0 && charlie[1] > 0));
|
||||
}
|
||||
|
||||
void Renderer::RotateCorner(vec2& v, float s, float c) {
|
||||
float x = v[0] * c - v[1] * s;
|
||||
float y = v[1] * c + v[0] * s;
|
||||
v = vec2(x, y);
|
||||
}
|
||||
|
||||
Rect Renderer::CreateRect(const vec2& pos, const vec2& size, float angle) {
|
||||
vec2 c = size * 0.5f; // Center
|
||||
vec2 corner[4] = {
|
||||
vec2(-c[0], -c[1]),
|
||||
vec2(-c[0] + size[0], -c[1]),
|
||||
vec2(-c[0], -c[1] + size[1]),
|
||||
vec2(-c[0] + size[0], -c[1] + size[1]),
|
||||
};
|
||||
|
||||
// Only rotate if required
|
||||
if (angle != 0.f) {
|
||||
float s = std::sin(angle);
|
||||
float co = std::cos(angle);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
RotateCorner(corner[i], s, co);
|
||||
}
|
||||
}
|
||||
|
||||
// Return Result
|
||||
return Rect(corner[0] + pos + c, corner[1] + pos + c, corner[2] + pos + c,
|
||||
corner[3] + pos + c);
|
||||
}
|
||||
|
||||
Rect Renderer::CreateLine(const vec2& a, const vec2& b, int t) {
|
||||
// Usin g th evec maths api makes the code as short as it is
|
||||
vec2 dir = a - b;
|
||||
float len = dir.len();
|
||||
vec2 unit_dir = dir / len;
|
||||
vec2 perpendicular(-unit_dir.y(), unit_dir.x());
|
||||
vec2 off = perpendicular * ((float)t * 0.5f);
|
||||
|
||||
return Rect(a + off, b + off, a - off, b - off);
|
||||
}
|
||||
|
||||
void Renderer::OptiCommandList(std::vector<Command::Ref>& list) {
|
||||
std::sort(list.begin(), list.end(), [](Command::Ref a, Command::Ref b) {
|
||||
if (a->Layer() == b->Layer()) {
|
||||
if (a->Tex() == b->Tex()) {
|
||||
return a->Index() < b->Index();
|
||||
}
|
||||
return a->Tex() < b->Tex(); // else
|
||||
}
|
||||
return a->Layer() < b->Layer(); // else
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::SetupCommand(Command::Ref cmd) {
|
||||
cmd->Index(cmd_idx++).Layer(current_layer).Tex(current_tex);
|
||||
}
|
||||
|
||||
void Renderer::QuadCommand(Command::Ref cmd, const Rect& quad, const Rect& uv,
|
||||
u32 col) {
|
||||
cmd->PushIndex(0).PushIndex(1).PushIndex(2);
|
||||
cmd->PushIndex(0).PushIndex(2).PushIndex(3);
|
||||
cmd->PushVertex(Vertex(quad.BotRight(), uv.BotRight(), col));
|
||||
cmd->PushVertex(Vertex(quad.TopRight(), uv.TopRight(), col));
|
||||
cmd->PushVertex(Vertex(quad.TopLeft(), uv.TopLeft(), col));
|
||||
cmd->PushVertex(Vertex(quad.BotLeft(), uv.BotLeft(), col));
|
||||
}
|
||||
|
||||
void Renderer::TriangleCommand(Command::Ref cmd, const vec2& a, const vec2& b,
|
||||
const vec2& c, u32 col) {
|
||||
cmd->PushIndex(2).PushIndex(1).PushIndex(0);
|
||||
cmd->PushVertex(Vertex(a, vec2(0.f, 1.f), col));
|
||||
cmd->PushVertex(Vertex(b, vec2(1.f, 1.f), col));
|
||||
cmd->PushVertex(Vertex(c, vec2(1.f, 0.f), col));
|
||||
}
|
||||
|
||||
void Renderer::TextCommand(std::vector<Command::Ref>& cmds, const vec2& pos,
|
||||
u32 color, const std::string& text,
|
||||
LITextFlags flags, const vec2& box) {
|
||||
if (!font) {
|
||||
return;
|
||||
}
|
||||
vec2 off;
|
||||
float cfs = (default_font_h * text_size) / (float)font->PixelHeight();
|
||||
float lh = (float)font->PixelHeight() * cfs;
|
||||
vec2 td;
|
||||
vec2 rpos = pos;
|
||||
vec2 rbox = box;
|
||||
if (flags & (LITextFlags_AlignMid | LITextFlags_AlignRight)) {
|
||||
td = GetTextDimensions(text);
|
||||
if (rbox[0] == 0.f) {
|
||||
rbox[0] = area_size.x();
|
||||
}
|
||||
if (rbox[1] == 0.f) {
|
||||
rbox[1] = area_size.y();
|
||||
}
|
||||
}
|
||||
if (flags & LITextFlags_AlignMid) {
|
||||
rpos = rbox * 0.5 - td * 0.5 + pos;
|
||||
}
|
||||
if (flags & LITextFlags_AlignRight) {
|
||||
rpos[0] = rpos[0] - td[0];
|
||||
}
|
||||
|
||||
std::vector<std::string> lines;
|
||||
std::istringstream iss(text);
|
||||
std::string tmp;
|
||||
while (std::getline(iss, tmp)) {
|
||||
lines.push_back(tmp);
|
||||
}
|
||||
|
||||
for (auto& it : lines) {
|
||||
if (flags & LITextFlags_Short) {
|
||||
vec2 tmp_dim;
|
||||
it = ShortText(it, box.x() - pos.x(), tmp_dim);
|
||||
}
|
||||
/// Well support OOS Rendering here as well
|
||||
/// Fixes UI7 Scroll back up bug
|
||||
if (rpos[1] + off[1] + lh < 0 && !(flags & LITextFlags_RenderOOS)) {
|
||||
off[1] += lh;
|
||||
continue;
|
||||
} else if (rpos[1] + off[1] > GetViewport().w() &&
|
||||
!(flags & LITextFlags_RenderOOS)) {
|
||||
// Break cause next lines would be out of screen
|
||||
break;
|
||||
}
|
||||
auto wline = Strings::MakeWstring(it);
|
||||
auto cmd = Command::New();
|
||||
current_tex = font->GetCodepoint(wline[0]).tex();
|
||||
SetupCommand(cmd);
|
||||
cmd->Rendermode(RenderMode_Font);
|
||||
for (auto& jt : wline) {
|
||||
auto cp = font->GetCodepoint(jt);
|
||||
if (cp.invalid() && jt != '\n' && jt != '\t') {
|
||||
continue;
|
||||
}
|
||||
if (current_tex != cp.tex()) {
|
||||
cmds.push_back(cmd);
|
||||
cmd = Command::New();
|
||||
current_tex = cp.tex();
|
||||
SetupCommand(cmd);
|
||||
cmd->Rendermode(RenderMode_Font);
|
||||
}
|
||||
if (jt == '\t') {
|
||||
off[0] += 16 * cfs;
|
||||
} else {
|
||||
if (jt != ' ') {
|
||||
int lr = current_layer;
|
||||
if (flags & LITextFlags_Shaddow) {
|
||||
// Draw
|
||||
Rect rec = CreateRect(
|
||||
rpos + vec2(off[0] + 1, off[1] + (cp.off() * cfs)) + 1,
|
||||
cp.size() * cfs, 0.f);
|
||||
QuadCommand(cmd, rec, cp.uv(), 0xff111111);
|
||||
current_layer++;
|
||||
}
|
||||
// Draw
|
||||
Rect rec = CreateRect(rpos + off + vec2(0, (cp.off() * cfs)),
|
||||
cp.size() * cfs, 0.f);
|
||||
QuadCommand(cmd, rec, cp.uv(), color);
|
||||
current_layer = lr;
|
||||
} else {
|
||||
if (!font->SystemFont()) {
|
||||
off[0] += 2 * cfs;
|
||||
}
|
||||
}
|
||||
off[0] += cp.size().x() * cfs + 2 * cfs;
|
||||
}
|
||||
}
|
||||
cmds.push_back(cmd);
|
||||
off[1] += lh;
|
||||
off[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 Renderer::GetViewport() { return vec4(vec2(), screen->GetSize()); }
|
||||
|
||||
std::string Renderer::ShortText(const std::string& text, int maxlen,
|
||||
vec2& newsize) {
|
||||
vec2 cdim;
|
||||
if (flags & LIRenderFlags_TMS) {
|
||||
auto e = tms.find(text);
|
||||
if (e != tms.end()) {
|
||||
e->second.TimeCreated(Sys::GetTime());
|
||||
if (e->second.Optional()) {
|
||||
return e->second.Text();
|
||||
}
|
||||
cdim = e->second.Size();
|
||||
}
|
||||
}
|
||||
cdim = this->GetTextDimensions(text);
|
||||
if (cdim[0] < (float)maxlen) {
|
||||
return text;
|
||||
}
|
||||
std::string ext;
|
||||
/// Forgot why i called this var ending cause
|
||||
/// Its more a placeholder for removed content
|
||||
std::string ending = "...";
|
||||
std::string cpy = text;
|
||||
std::string res;
|
||||
size_t extension = text.find_last_of('.');
|
||||
if (extension != text.npos) {
|
||||
ext = text.substr(extension);
|
||||
cpy = text.substr(0, extension);
|
||||
maxlen -= GetTextDimensions(ext).x();
|
||||
}
|
||||
maxlen -= GetTextDimensions(ending).x();
|
||||
for (auto& it : cpy) {
|
||||
if (GetTextDimensions(res).x() > (float)maxlen) {
|
||||
res += ending;
|
||||
res += ext;
|
||||
newsize = GetTextDimensions(res);
|
||||
if (flags & LIRenderFlags_TMS) {
|
||||
auto& tmp = tms[text];
|
||||
tmp.Text(res);
|
||||
tmp.Size(newsize);
|
||||
tmp.TimeCreated(Sys::GetTime());
|
||||
tmp.Optional(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
res += it;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string Renderer::WrapText(const std::string& text, int maxlen,
|
||||
vec2& newsize) {}
|
||||
|
||||
vec2 Renderer::GetTextDimensions(const std::string& text) {
|
||||
if (!font) {
|
||||
// No font no size (oder so)
|
||||
return vec2();
|
||||
}
|
||||
// Handle TextMapSystem
|
||||
if (flags & LIRenderFlags_TMS) {
|
||||
auto ref = tms.find(text);
|
||||
if (ref != tms.end()) {
|
||||
ref->second.TimeCreated(Sys::GetTime());
|
||||
return ref->second.Size();
|
||||
}
|
||||
}
|
||||
// Use wstring for exemple for german äöü
|
||||
auto wtext = Strings::MakeWstring(text);
|
||||
// Create a temp position and offset as [0, 0]
|
||||
vec2 res;
|
||||
float x = 0;
|
||||
// Curent Font Scale
|
||||
float cfs = (default_font_h * text_size) / (float)font->PixelHeight();
|
||||
float lh = (float)font->PixelHeight() * cfs;
|
||||
size_t index = 0;
|
||||
for (auto& it : wtext) {
|
||||
if (it == '\0') {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
auto cp = font->GetCodepoint(it);
|
||||
if (cp.invalid() && it != '\n' && it != '\t' && it != ' ') {
|
||||
continue;
|
||||
}
|
||||
switch (it) {
|
||||
case '\n':
|
||||
res[1] += lh;
|
||||
res[0] = std::max(res[0], x);
|
||||
x = 0.f;
|
||||
break;
|
||||
case '\t':
|
||||
x += 16 * cfs;
|
||||
break;
|
||||
case ' ':
|
||||
if (!font->SystemFont()) {
|
||||
x += 2 * cfs;
|
||||
}
|
||||
// Fall trough here to get the same result as in
|
||||
// TextCommand if/else Section
|
||||
default:
|
||||
x += cp.size().x() * cfs;
|
||||
if (index != wtext.size()) {
|
||||
x += 2 * cfs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
res[0] = std::max(res[0], x);
|
||||
res[1] += lh;
|
||||
if (flags & LIRenderFlags_TMS) {
|
||||
tms[text] = TextBox(res, Sys::GetTime());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void Renderer::UpdateRenderMode(const RenderMode& mode) {
|
||||
C3D_TexEnv* env = C3D_GetTexEnv(0);
|
||||
switch (mode) {
|
||||
case RenderMode_Font:
|
||||
/// Sets Only Alpha Using the Color and Replase RGB with vertex color
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_RGB, GPU_PRIMARY_COLOR);
|
||||
C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE);
|
||||
C3D_TexEnvSrc(env, C3D_Alpha, GPU_TEXTURE0);
|
||||
C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE);
|
||||
break;
|
||||
// Fall trough instead of defining twice
|
||||
case RenderMode_RGBA:
|
||||
default:
|
||||
/// Use Texture for RGBA and vertexcolor for visibility
|
||||
C3D_TexEnvInit(env);
|
||||
C3D_TexEnvSrc(env, C3D_Both, GPU_TEXTURE0);
|
||||
C3D_TexEnvFunc(env, C3D_Both, GPU_MODULATE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::PrepareRender() {
|
||||
if (font_update) {
|
||||
tms.clear();
|
||||
font_update = false;
|
||||
}
|
||||
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
|
||||
TT::Beg("LI_RenderAll");
|
||||
vertex_idx = 0;
|
||||
index_idx = 0;
|
||||
vertices = 0;
|
||||
indices = 0;
|
||||
commands = 0;
|
||||
drawcalls = 0;
|
||||
C3D_BindProgram(&shader);
|
||||
C3D_SetAttrInfo(&attr);
|
||||
}
|
||||
|
||||
void Renderer::FinalizeRender() {
|
||||
C3D_FrameEnd(0);
|
||||
TT::End("LI_RenderAll");
|
||||
current_layer = 0;
|
||||
cmd_idx = 0;
|
||||
rot = 0.f;
|
||||
UseTex();
|
||||
if (flags & LIRenderFlags_TMS) {
|
||||
std::vector<std::string> rem;
|
||||
for (auto& it : tms) {
|
||||
if (Sys::GetTime() - it.second.TimeCreated() > 5) rem.push_back(it.first);
|
||||
}
|
||||
for (auto it : rem) tms.erase(it);
|
||||
} else {
|
||||
tms.clear();
|
||||
}
|
||||
if (flags & LIRenderFlags_AST) {
|
||||
std::vector<u32> rem;
|
||||
for (auto it : ast) {
|
||||
if (!it.second->Used()) {
|
||||
rem.push_back(it.first);
|
||||
}
|
||||
it.second->SetUnused();
|
||||
}
|
||||
for (auto& it : rem) {
|
||||
ast.erase(it);
|
||||
}
|
||||
} else {
|
||||
ast.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::Render(Screen::Ref s) {
|
||||
Assert(s.get(), "Expected Screen Address but got nullptr!");
|
||||
s->Clear();
|
||||
s->Use();
|
||||
bool bot = s->ScreenType() == Screen::Bottom;
|
||||
C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection,
|
||||
(bot ? &bot_proj : &top_proj));
|
||||
C3D_DepthTest(false, GPU_GREATER, GPU_WRITE_ALL);
|
||||
UpdateRenderMode(RenderMode_RGBA);
|
||||
int total_vertices = 0;
|
||||
int total_indices = 0;
|
||||
auto& cmds = draw_list[Screen32(s)];
|
||||
commands += cmds.size();
|
||||
size_t index = 0;
|
||||
if (flags & LIRenderFlags_LRS) {
|
||||
OptiCommandList(cmds);
|
||||
}
|
||||
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]->GetScissorMode() == smode) {
|
||||
auto c = cmds[index];
|
||||
// Indices
|
||||
for (size_t i = 0; i < c->IndexList().size(); i++) {
|
||||
index_buf[index_idx++] = vertex_idx + c->IndexList().at(i);
|
||||
}
|
||||
// Vertices
|
||||
for (size_t i = 0; i < c->VertexList().size(); i++) {
|
||||
vertex_buf[vertex_idx++] = c->VertexList().at(i);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
C3D_TexBind(0, tex);
|
||||
|
||||
auto bufInfo = C3D_GetBufInfo();
|
||||
BufInfo_Init(bufInfo);
|
||||
BufInfo_Add(bufInfo, vertex_buf.data(), sizeof(Vertex), 3, 0x210);
|
||||
|
||||
C3D_DrawElements(GPU_TRIANGLES, index_idx - start_idx, C3D_UNSIGNED_SHORT,
|
||||
index_buf.data() + start_idx);
|
||||
|
||||
drawcalls++;
|
||||
total_vertices += vertex_idx - start_vtx;
|
||||
total_indices += index_idx - start_idx;
|
||||
}
|
||||
cmds.clear();
|
||||
C3D_DepthTest(true, GPU_GREATER, GPU_WRITE_ALL);
|
||||
vertices += total_vertices;
|
||||
indices += total_indices;
|
||||
}
|
||||
|
||||
void Renderer::DrawRect(const vec2& pos, const vec2& size, u32 color,
|
||||
const Rect& uv) {
|
||||
if (!InBox(pos, size, GetViewport())) {
|
||||
// Instand abort as it is out of screen
|
||||
return;
|
||||
}
|
||||
Rect rec = CreateRect(pos, size, rot);
|
||||
auto cmd = Command::New();
|
||||
SetupCommand(cmd);
|
||||
QuadCommand(cmd, rec, uv, color);
|
||||
draw_list[Screen32(screen)].push_back(cmd);
|
||||
}
|
||||
|
||||
void Renderer::DrawRectSolid(const vec2& pos, const vec2& size, u32 color) {
|
||||
UseTex();
|
||||
DrawRect(pos, size, color, vec4(0.f, 1.f, 1.f, 0.f));
|
||||
}
|
||||
|
||||
void Renderer::DrawTriangle(const vec2& a, const vec2& b, const vec2& c,
|
||||
u32 color) {
|
||||
if (!InBox(a, b, c, GetViewport())) {
|
||||
return;
|
||||
}
|
||||
UseTex();
|
||||
auto cmd = Command::New();
|
||||
SetupCommand(cmd);
|
||||
TriangleCommand(cmd, a, b, c, color);
|
||||
draw_list[Screen32(screen)].push_back(cmd);
|
||||
}
|
||||
|
||||
void Renderer::DrawCircle(const vec2& center_pos, float r, u32 color,
|
||||
int segments) {
|
||||
if (segments < 3) {
|
||||
return;
|
||||
}
|
||||
auto cmd = Command::New();
|
||||
cmd->Index(cmd_idx++).Layer(current_layer).Tex(current_tex);
|
||||
for (int i = 1; i < segments - 1; i++) {
|
||||
cmd->PushIndex(0);
|
||||
cmd->PushIndex(i + 1).PushIndex(i);
|
||||
}
|
||||
float as = 2.f * M_PI / segments;
|
||||
for (int i = 0; i < segments; i++) {
|
||||
float a = i * as;
|
||||
float x = center_pos.x() + r * std::cos(a);
|
||||
float y = center_pos.y() + r * std::sin(a);
|
||||
cmd->PushVertex(Vertex(
|
||||
vec2(x, y), vec2((std::cos(a) + 1.f) / 2.f, (std::sin(a) + 1.f) / 2.f),
|
||||
color));
|
||||
}
|
||||
draw_list[Screen32(screen)].push_back(cmd);
|
||||
}
|
||||
|
||||
void Renderer::DrawLine(const vec2& a, const vec2& b, u32 color, int t) {
|
||||
UseTex();
|
||||
Rect line = CreateLine(a, b, t);
|
||||
|
||||
auto cmd = Command::New();
|
||||
SetupCommand(cmd);
|
||||
QuadCommand(cmd, line, vec4(0.f, 1.f, 1.f, 0.f), color);
|
||||
draw_list[Screen32(screen)].push_back(cmd);
|
||||
}
|
||||
|
||||
void Renderer::DrawImage(const vec2& pos, Texture::Ref tex, const vec2& scale) {
|
||||
UseTex(tex);
|
||||
DrawRect(pos, tex->GetSize() * scale, 0xffffffff, tex->GetUV());
|
||||
}
|
||||
|
||||
void Renderer::DrawText(const vec2& pos, u32 color, const std::string& text,
|
||||
u32 flags, const vec2& ap) {
|
||||
if (!font) {
|
||||
return;
|
||||
}
|
||||
if (this->flags & LIRenderFlags_AST) {
|
||||
u32 id = Strings::FastHash(text);
|
||||
auto e = ast.find(id);
|
||||
if (e == ast.end()) {
|
||||
ast[id] = StaticText::New();
|
||||
e = ast.find(id);
|
||||
}
|
||||
if (!e->second->IsSetup() || e->second->Font() != font) {
|
||||
e->second->Setup(this, pos, color, text, flags, ap);
|
||||
e->second->Font(font);
|
||||
}
|
||||
e->second->SetPos(pos);
|
||||
e->second->SetColor(color);
|
||||
e->second->Draw();
|
||||
return;
|
||||
}
|
||||
TextCommand(draw_list[Screen32(screen)], pos, color, text, flags, ap);
|
||||
}
|
||||
} // namespace LI
|
||||
#include <pd/lithium/renderer.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace LI {
|
||||
PD_LITHIUM_API Renderer::Renderer(Backend::Ref backend) {
|
||||
pBackend = backend;
|
||||
std::vector<PD::u8> white(16 * 16 * 4, 0xff);
|
||||
WhitePixel = pBackend->LoadTexture(white, 16, 16);
|
||||
CurrentTex = WhitePixel; // Make sure to have a texture set
|
||||
}
|
||||
|
||||
PD_LITHIUM_API void Renderer::Render() {
|
||||
pBackend->NewFrame();
|
||||
pBackend->RenderDrawData(DrawList);
|
||||
DrawList.Clear();
|
||||
for (auto it = pDrawLists.Begin(); it != pDrawLists.End(); it++) {
|
||||
pBackend->RenderDrawData((*it)->pDrawList);
|
||||
(*it)->Clear();
|
||||
}
|
||||
pDrawLists.Clear();
|
||||
}
|
||||
|
||||
PD_LITHIUM_API bool Renderer::InBox(const fvec2& pos, const fvec2& szs,
|
||||
const fvec4& rect) {
|
||||
return (pos.x + szs.x >= rect.x && pos.y + szs.y >= rect.y &&
|
||||
pos.x <= rect.z && pos.y <= rect.w);
|
||||
}
|
||||
|
||||
PD_LITHIUM_API bool Renderer::InBox(const fvec2& pos, const fvec4& rect) {
|
||||
return (pos.x > rect.x && pos.x < rect.x + rect.z && pos.y > rect.y &&
|
||||
pos.y < rect.y + rect.w);
|
||||
}
|
||||
|
||||
PD_LITHIUM_API bool Renderer::InBox(const fvec2& alpha, const fvec2& bravo,
|
||||
const fvec2& charlie, const fvec4& rect) {
|
||||
return ((alpha.x < rect.z && bravo.x < rect.z && charlie.x < rect.z) ||
|
||||
(alpha.y < rect.w && bravo.y < rect.w && charlie.y < rect.w) ||
|
||||
(alpha.x > 0 && bravo.x > 0 && charlie.x > 0) ||
|
||||
(alpha.y > 0 && bravo.y > 0 && charlie.y > 0));
|
||||
}
|
||||
|
||||
PD_LITHIUM_API void Renderer::RotateCorner(fvec2& pos, float sinus,
|
||||
float cosinus) {
|
||||
float x = pos.x * cosinus - pos.y * sinus;
|
||||
float y = pos.y * cosinus - pos.x * sinus;
|
||||
pos = fvec2(x, y);
|
||||
}
|
||||
|
||||
PD_LITHIUM_API Rect Renderer::PrimRect(const fvec2& pos, const fvec2& size,
|
||||
float angle) {
|
||||
fvec2 c = size * 0.5f; // Center
|
||||
fvec2 corner[4] = {
|
||||
fvec2(-c.x, -c.y),
|
||||
fvec2(-c.x + size.x, -c.y),
|
||||
fvec2(-c.x, -c.y + size.y),
|
||||
fvec2(-c.x + size.x, -c.y + size.y),
|
||||
};
|
||||
|
||||
// Only rotate if required
|
||||
if (angle != 0.f) {
|
||||
float s = std::sin(angle);
|
||||
float co = std::cos(angle);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
RotateCorner(corner[i], s, co);
|
||||
}
|
||||
}
|
||||
|
||||
// Return Result
|
||||
return Rect(corner[0] + pos + c, corner[1] + pos + c, corner[2] + pos + c,
|
||||
corner[3] + pos + c);
|
||||
}
|
||||
|
||||
PD_LITHIUM_API Rect Renderer::PrimLine(const fvec2& a, const fvec2& b,
|
||||
int thickness) {
|
||||
// Using the vec maths api makes the code as short as it is
|
||||
vec2 dir = a - b;
|
||||
float len = dir.Len();
|
||||
vec2 unit_dir = dir / len;
|
||||
vec2 perpendicular(-unit_dir.y, unit_dir.x);
|
||||
vec2 off = perpendicular * ((float)thickness * 0.5f);
|
||||
|
||||
return Rect(a + off, b + off, a - off, b - off);
|
||||
}
|
||||
|
||||
PD_LITHIUM_API void Renderer::CmdQuad(Command::Ref cmd, const Rect& quad,
|
||||
const Rect& uv, u32 color) {
|
||||
cmd->AppendIndex(0).AppendIndex(1).AppendIndex(2);
|
||||
cmd->AppendIndex(0).AppendIndex(2).AppendIndex(3);
|
||||
cmd->AppendVertex(Vertex(quad.BotRight(), uv.BotRight(), color));
|
||||
cmd->AppendVertex(Vertex(quad.TopRight(), uv.TopRight(), color));
|
||||
cmd->AppendVertex(Vertex(quad.TopLeft(), uv.TopLeft(), color));
|
||||
cmd->AppendVertex(Vertex(quad.BotLeft(), uv.BotLeft(), color));
|
||||
}
|
||||
|
||||
PD_LITHIUM_API void Renderer::CmdTriangle(Command::Ref cmd, const fvec2 a,
|
||||
const fvec2 b, const fvec2 c,
|
||||
u32 clr) {
|
||||
cmd->AppendIndex(2).AppendIndex(1).AppendIndex(0);
|
||||
cmd->AppendVertex(Vertex(a, vec2(0.f, 1.f), clr));
|
||||
cmd->AppendVertex(Vertex(b, vec2(1.f, 1.f), clr));
|
||||
cmd->AppendVertex(Vertex(c, vec2(1.f, 0.f), clr));
|
||||
}
|
||||
|
||||
PD_LITHIUM_API Command::Ref Renderer::PreGenerateCmd() {
|
||||
Command::Ref res = Command::New();
|
||||
res->Index = DrawList.Size();
|
||||
res->Layer = Layer;
|
||||
res->Tex = CurrentTex;
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO: Don't render OOS (Probably make it with a define as it
|
||||
// would probably be faster to render out of screen than checking if
|
||||
// it could be skipped)
|
||||
PD_LITHIUM_API void Renderer::CmdConvexPolyFilled(Command::Ref cmd,
|
||||
const Vec<fvec2>& points,
|
||||
u32 clr, Texture::Ref tex) {
|
||||
if (points.Size() < 3 || tex == nullptr) {
|
||||
return; // Need at least three points
|
||||
}
|
||||
|
||||
// Support for Custom Textures (UV calculation)
|
||||
float minX = points[0].x, minY = points[0].y;
|
||||
float maxX = minX, maxY = minY;
|
||||
// Check for the max and min Positions
|
||||
for (auto it = points.Begin(); it != points.End(); it++) {
|
||||
if ((*it).x < minX) minX = (*it).x;
|
||||
if ((*it).y < minY) minY = (*it).y;
|
||||
if ((*it).x > maxX) maxX = (*it).x;
|
||||
if ((*it).y > maxY) maxY = (*it).y;
|
||||
}
|
||||
// Get Short defines for UV
|
||||
// (Bottom Right is not required)
|
||||
auto uv_tl = tex->UV.TopLeft();
|
||||
auto uv_tr = tex->UV.TopRight();
|
||||
auto uv_bl = tex->UV.BotLeft();
|
||||
|
||||
// Render
|
||||
for (int i = 2; i < (int)points.Size(); i++) {
|
||||
cmd->AppendIndex(0).AppendIndex(i).AppendIndex(i - 1);
|
||||
}
|
||||
for (int i = 0; i < (int)points.Size(); i++) {
|
||||
// Calculate U and V coords
|
||||
float u =
|
||||
uv_tl.x + ((points[i].x - minX) / (maxX - minX)) * (uv_tr.x - uv_tl.x);
|
||||
float v =
|
||||
uv_tl.y + ((points[i].y - minY) / (maxY - minY)) * (uv_bl.y - uv_tl.y);
|
||||
cmd->AppendVertex(LI::Vertex(points[i], fvec2(u, v), clr));
|
||||
}
|
||||
}
|
||||
} // namespace LI
|
||||
} // namespace PD
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/core/io.hpp>
|
||||
#include <pd/app/error.hpp>
|
||||
#include <pd/lithium/spritesheet.hpp>
|
||||
|
||||
namespace PD {
|
||||
SpriteSheet::~SpriteSheet() { textures.clear(); }
|
||||
|
||||
void SpriteSheet::LoadFile(const std::string& path) {
|
||||
auto file = IO::LoadFile2Mem(path);
|
||||
if (file.size() == 0) {
|
||||
Error("Unable to load file:\n" + path);
|
||||
}
|
||||
C3D_Tex* tex = new C3D_Tex;
|
||||
auto t3x =
|
||||
Tex3DS_TextureImport(file.data(), file.size(), tex, nullptr, false);
|
||||
if (!t3x) {
|
||||
Error("Unable to import:\n" + path);
|
||||
}
|
||||
tex->border = 0;
|
||||
C3D_TexSetWrap(tex, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER);
|
||||
C3D_TexSetFilter(tex, GPU_LINEAR, GPU_NEAREST);
|
||||
textures.reserve(Tex3DS_GetNumSubTextures(t3x) + 1);
|
||||
for (int i = 0; i < (int)Tex3DS_GetNumSubTextures(t3x); i++) {
|
||||
auto t = Texture::New();
|
||||
auto st = Tex3DS_GetSubTexture(t3x, i);
|
||||
LI::Rect uv(vec2(st->left, st->top), vec2(st->right, st->top),
|
||||
vec2(st->left, st->bottom), vec2(st->right, st->bottom));
|
||||
if (st->top < st->bottom) {
|
||||
uv.SwapVec2XY();
|
||||
}
|
||||
t->LoadExternal(tex, vec2(st->width, st->height), uv);
|
||||
textures.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
Texture::Ref SpriteSheet::Get(int idx) {
|
||||
if (idx >= (int)textures.size()) {
|
||||
Error("Trying to Access Texture " + std::to_string(idx + 1) + " of " +
|
||||
std::to_string(NumTextures()));
|
||||
}
|
||||
return textures[idx];
|
||||
}
|
||||
|
||||
int SpriteSheet::NumTextures() const { return textures.size(); }
|
||||
} // namespace PD
|
@ -1,168 +0,0 @@
|
||||
/*
|
||||
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 <3ds.h>
|
||||
#include <pd/external/stb_image.h>
|
||||
#include <tex3ds.h>
|
||||
|
||||
#include <pd/app/error.hpp>
|
||||
#include <pd/core/bit_util.hpp>
|
||||
#include <pd/core/io.hpp>
|
||||
#include <pd/core/timetrace.hpp>
|
||||
#include <pd/image/image.hpp>
|
||||
#include <pd/image/img_convert.hpp>
|
||||
#include <pd/lithium/texture.hpp>
|
||||
|
||||
namespace PD {
|
||||
GPU_TEXCOLOR GetTexFmt(Texture::Type type) {
|
||||
if (type == Texture::RGBA32)
|
||||
return GPU_RGBA8;
|
||||
else if (type == Texture::RGB24)
|
||||
return GPU_RGB8;
|
||||
else if (type == Texture::A8)
|
||||
return GPU_A8;
|
||||
return GPU_RGBA8; // Default
|
||||
}
|
||||
int GetBPP(Texture::Type type) {
|
||||
if (type == Texture::RGBA32)
|
||||
return 4;
|
||||
else if (type == Texture::RGB24)
|
||||
return 3;
|
||||
else if (type == Texture::A8)
|
||||
return 1;
|
||||
return 0; // Error
|
||||
}
|
||||
void Texture::MakeTex(std::vector<u8>& buf, int w, int h, Texture::Type type,
|
||||
Filter filter) {
|
||||
// Don't check here as check done before
|
||||
int bpp = GetBPP(type);
|
||||
vec2 tex_size(w, h);
|
||||
// Pow2
|
||||
if (!PD::BitUtil::IsSingleBit(w)) {
|
||||
tex_size.x() = PD::BitUtil::GetPow2((unsigned int)w);
|
||||
}
|
||||
if (!PD::BitUtil::IsSingleBit(h)) {
|
||||
tex_size.y() = PD::BitUtil::GetPow2((unsigned int)h);
|
||||
}
|
||||
|
||||
this->size.x() = (u16)w;
|
||||
this->size.y() = (u16)h;
|
||||
this->uv = vec4(0.f, 1.f, ((float)w / (float)tex_size.x()),
|
||||
1.0 - ((float)h / (float)tex_size.y()));
|
||||
|
||||
// Texture Setup
|
||||
auto fltr = (filter == NEAREST ? GPU_NEAREST : GPU_LINEAR);
|
||||
auto tex_fmt = GetTexFmt(type);
|
||||
tex = new C3D_Tex;
|
||||
C3D_TexInit(tex, (u16)tex_size.x(), (u16)tex_size.y(), tex_fmt);
|
||||
C3D_TexSetFilter(tex, fltr, fltr);
|
||||
|
||||
memset(tex->data, 0, tex->size);
|
||||
|
||||
/// Probably Remove this if statement in future
|
||||
/// This are the things confirmed as working
|
||||
if (bpp == 3 || bpp == 4 || bpp == 1) {
|
||||
for (int x = 0; x < w; x++) {
|
||||
for (int y = 0; y < h; y++) {
|
||||
int dst_pos = ((((y >> 3) * ((int)tex_size.x() >> 3) + (x >> 3)) << 6) +
|
||||
((x & 1) | ((y & 1) << 1) | ((x & 2) << 1) |
|
||||
((y & 2) << 2) | ((x & 4) << 2) | ((y & 4) << 3))) *
|
||||
bpp;
|
||||
int src_pos = (y * w + x) * bpp;
|
||||
/// Best idea i had
|
||||
for (int i = 0; i < bpp; i++) {
|
||||
((u8*)tex->data)[dst_pos + bpp - 1 - i] = buf[src_pos + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
C3D_TexFlush(tex);
|
||||
}
|
||||
|
||||
tex->border = 0x00000000;
|
||||
C3D_TexSetWrap(tex, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER);
|
||||
}
|
||||
|
||||
void Texture::Delete() {
|
||||
if (tex) {
|
||||
C3D_TexDelete(tex);
|
||||
delete tex;
|
||||
tex = nullptr;
|
||||
size = vec2();
|
||||
uv = vec4(0.f, 1.f, 1.f, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::LoadFile(const std::string& path) {
|
||||
PD::TT::Scope st("texldr-" + path);
|
||||
Delete();
|
||||
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;
|
||||
}
|
||||
MakeTex(img, img.Width(), img.Height());
|
||||
}
|
||||
|
||||
void Texture::LoadMemory(const std::vector<u8>& data) {
|
||||
Delete();
|
||||
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;
|
||||
}
|
||||
MakeTex(img, img.Width(), img.Height());
|
||||
}
|
||||
|
||||
void Texture::LoadPixels(const std::vector<u8>& pixels, int w, int h, Type type,
|
||||
Filter filter) {
|
||||
Delete();
|
||||
int bpp = GetBPP(type);
|
||||
if (w * h * bpp != (int)pixels.size()) {
|
||||
return;
|
||||
}
|
||||
std::vector<u8> cpy(pixels);
|
||||
MakeTex(cpy, w, h, type, filter);
|
||||
}
|
||||
|
||||
void Texture::LoadT3X(const std::string& path) {
|
||||
this->Delete();
|
||||
auto file = IO::LoadFile2Mem(path);
|
||||
if (file.size() == 0) {
|
||||
Error("Unable to load file:\n" + path);
|
||||
}
|
||||
this->tex = new C3D_Tex;
|
||||
auto t3x =
|
||||
Tex3DS_TextureImport(file.data(), file.size(), this->tex, nullptr, false);
|
||||
if (!t3x) {
|
||||
Error("Unable to import:\n" + path);
|
||||
}
|
||||
auto st = Tex3DS_GetSubTexture(t3x, 0);
|
||||
this->uv = vec4(st->left, st->top, st->right, st->bottom);
|
||||
this->size[0] = st->width;
|
||||
this->size[1] = st->height;
|
||||
Tex3DS_TextureFree(t3x);
|
||||
}
|
||||
} // namespace PD
|
68
source/net/socket.cpp
Normal file
68
source/net/socket.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
/** Need to outsource this into the backend */
|
||||
|
||||
#include <pd/net/backend.hpp>
|
||||
#include <pd/net/socket.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace Net {
|
||||
PD_NET_API bool Socket::Create() {
|
||||
pSocket = backend->NewSocket();
|
||||
return pSocket != backend->GetInvalidRef();
|
||||
}
|
||||
PD_NET_API bool Socket::Bind(u16 port) { return backend->Bind(pSocket, port); }
|
||||
|
||||
PD_NET_API bool Socket::Listen(int backlog) {
|
||||
return backend->Listen(pSocket, backlog);
|
||||
}
|
||||
|
||||
PD_NET_API bool Socket::Accept(Socket::Ref client) {
|
||||
return backend->Accept(pSocket, client);
|
||||
}
|
||||
|
||||
PD_NET_API bool Socket::Connect(const std::string& ip, u16 port) {
|
||||
return backend->Connect(pSocket, ip, port);
|
||||
}
|
||||
|
||||
PD_NET_API int Socket::Send(const std::string& data) {
|
||||
return backend->Send(pSocket, data);
|
||||
}
|
||||
|
||||
PD_NET_API int Socket::Receive(std::string& data, int size) {
|
||||
return backend->Receive(pSocket, data, size);
|
||||
}
|
||||
|
||||
PD_NET_API void Socket::Close() {
|
||||
if (IsValid()) {
|
||||
backend->Close(pSocket);
|
||||
pSocket = backend->GetInvalidRef();
|
||||
}
|
||||
}
|
||||
|
||||
PD_NET_API bool Socket::IsValid() const {
|
||||
return pSocket != backend->GetInvalidRef();
|
||||
}
|
||||
} // namespace Net
|
||||
} // namespace PD
|
@ -22,13 +22,12 @@ SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/external/json.hpp>
|
||||
#include <pd/core/color.hpp>
|
||||
#include <pd/overlays/keyboard.hpp>
|
||||
#include <pd/lib3ds/gamepad_icons.hpp>
|
||||
// #include <pd/lib3ds/gamepad_icons.hpp>
|
||||
|
||||
namespace PD {
|
||||
struct Key {
|
||||
Key(const std::string& key, const vec2& p, const vec2& s,
|
||||
Key(const std::string& key, const fvec2& p, const fvec2& s,
|
||||
Keyboard::KeyOperation o) {
|
||||
k = key;
|
||||
pos = p;
|
||||
@ -36,8 +35,8 @@ struct Key {
|
||||
op = o;
|
||||
}
|
||||
std::string k;
|
||||
vec2 pos;
|
||||
vec2 size;
|
||||
fvec2 pos;
|
||||
fvec2 size;
|
||||
Keyboard::KeyOperation op;
|
||||
};
|
||||
|
||||
@ -45,198 +44,198 @@ using Layout = std::vector<Key>;
|
||||
Layout layouts[3] = {
|
||||
{
|
||||
// 1st row
|
||||
Key("`", vec2(5, 0), 18, Keyboard::AppendSelf),
|
||||
Key("1", vec2(25, 0), 18, Keyboard::AppendSelf),
|
||||
Key("2", vec2(45, 0), 18, Keyboard::AppendSelf),
|
||||
Key("3", vec2(65, 0), 18, Keyboard::AppendSelf),
|
||||
Key("4", vec2(85, 0), 18, Keyboard::AppendSelf),
|
||||
Key("5", vec2(105, 0), 18, Keyboard::AppendSelf),
|
||||
Key("6", vec2(125, 0), 18, Keyboard::AppendSelf),
|
||||
Key("7", vec2(145, 0), 18, Keyboard::AppendSelf),
|
||||
Key("8", vec2(165, 0), 18, Keyboard::AppendSelf),
|
||||
Key("9", vec2(185, 0), 18, Keyboard::AppendSelf),
|
||||
Key("0", vec2(205, 0), 18, Keyboard::AppendSelf),
|
||||
Key("-", vec2(225, 0), 18, Keyboard::AppendSelf),
|
||||
Key("=", vec2(245, 0), 18, Keyboard::AppendSelf),
|
||||
Key("<---", vec2(265, 0), vec2(50, 18), Keyboard::Backspace),
|
||||
Key("`", fvec2(5, 0), 18, Keyboard::AppendSelf),
|
||||
Key("1", fvec2(25, 0), 18, Keyboard::AppendSelf),
|
||||
Key("2", fvec2(45, 0), 18, Keyboard::AppendSelf),
|
||||
Key("3", fvec2(65, 0), 18, Keyboard::AppendSelf),
|
||||
Key("4", fvec2(85, 0), 18, Keyboard::AppendSelf),
|
||||
Key("5", fvec2(105, 0), 18, Keyboard::AppendSelf),
|
||||
Key("6", fvec2(125, 0), 18, Keyboard::AppendSelf),
|
||||
Key("7", fvec2(145, 0), 18, Keyboard::AppendSelf),
|
||||
Key("8", fvec2(165, 0), 18, Keyboard::AppendSelf),
|
||||
Key("9", fvec2(185, 0), 18, Keyboard::AppendSelf),
|
||||
Key("0", fvec2(205, 0), 18, Keyboard::AppendSelf),
|
||||
Key("-", fvec2(225, 0), 18, Keyboard::AppendSelf),
|
||||
Key("=", fvec2(245, 0), 18, Keyboard::AppendSelf),
|
||||
Key("<---", fvec2(265, 0), fvec2(50, 18), Keyboard::Backspace),
|
||||
// 2nd row
|
||||
Key("Tab", vec2(5, 20), vec2(40, 18), Keyboard::Tab),
|
||||
Key("q", vec2(47, 20), 18, Keyboard::AppendSelf),
|
||||
Key("w", vec2(67, 20), 18, Keyboard::AppendSelf),
|
||||
Key("e", vec2(87, 20), 18, Keyboard::AppendSelf),
|
||||
Key("r", vec2(107, 20), 18, Keyboard::AppendSelf),
|
||||
Key("t", vec2(127, 20), 18, Keyboard::AppendSelf),
|
||||
Key("y", vec2(147, 20), 18, Keyboard::AppendSelf),
|
||||
Key("u", vec2(167, 20), 18, Keyboard::AppendSelf),
|
||||
Key("i", vec2(187, 20), 18, Keyboard::AppendSelf),
|
||||
Key("o", vec2(207, 20), 18, Keyboard::AppendSelf),
|
||||
Key("p", vec2(227, 20), 18, Keyboard::AppendSelf),
|
||||
Key("[", vec2(247, 20), 18, Keyboard::AppendSelf),
|
||||
Key("]", vec2(267, 20), 18, Keyboard::AppendSelf),
|
||||
Key("\\", vec2(287, 20), vec2(28, 18), Keyboard::AppendSelf),
|
||||
Key("Tab", fvec2(5, 20), fvec2(40, 18), Keyboard::Tab),
|
||||
Key("q", fvec2(47, 20), 18, Keyboard::AppendSelf),
|
||||
Key("w", fvec2(67, 20), 18, Keyboard::AppendSelf),
|
||||
Key("e", fvec2(87, 20), 18, Keyboard::AppendSelf),
|
||||
Key("r", fvec2(107, 20), 18, Keyboard::AppendSelf),
|
||||
Key("t", fvec2(127, 20), 18, Keyboard::AppendSelf),
|
||||
Key("y", fvec2(147, 20), 18, Keyboard::AppendSelf),
|
||||
Key("u", fvec2(167, 20), 18, Keyboard::AppendSelf),
|
||||
Key("i", fvec2(187, 20), 18, Keyboard::AppendSelf),
|
||||
Key("o", fvec2(207, 20), 18, Keyboard::AppendSelf),
|
||||
Key("p", fvec2(227, 20), 18, Keyboard::AppendSelf),
|
||||
Key("[", fvec2(247, 20), 18, Keyboard::AppendSelf),
|
||||
Key("]", fvec2(267, 20), 18, Keyboard::AppendSelf),
|
||||
Key("\\", fvec2(287, 20), fvec2(28, 18), Keyboard::AppendSelf),
|
||||
// 3rd row
|
||||
Key("Caps", vec2(5, 40), vec2(50, 18), Keyboard::Caps),
|
||||
Key("a", vec2(57, 40), 18, Keyboard::AppendSelf),
|
||||
Key("s", vec2(77, 40), 18, Keyboard::AppendSelf),
|
||||
Key("d", vec2(97, 40), 18, Keyboard::AppendSelf),
|
||||
Key("f", vec2(117, 40), 18, Keyboard::AppendSelf),
|
||||
Key("g", vec2(137, 40), 18, Keyboard::AppendSelf),
|
||||
Key("h", vec2(157, 40), 18, Keyboard::AppendSelf),
|
||||
Key("j", vec2(177, 40), 18, Keyboard::AppendSelf),
|
||||
Key("k", vec2(197, 40), 18, Keyboard::AppendSelf),
|
||||
Key("l", vec2(217, 40), 18, Keyboard::AppendSelf),
|
||||
Key(";", vec2(237, 40), 18, Keyboard::AppendSelf),
|
||||
Key("'", vec2(257, 40), 18, Keyboard::AppendSelf),
|
||||
Key("Enter", vec2(277, 40), vec2(38, 18), Keyboard::Enter),
|
||||
Key("Caps", fvec2(5, 40), fvec2(50, 18), Keyboard::Caps),
|
||||
Key("a", fvec2(57, 40), 18, Keyboard::AppendSelf),
|
||||
Key("s", fvec2(77, 40), 18, Keyboard::AppendSelf),
|
||||
Key("d", fvec2(97, 40), 18, Keyboard::AppendSelf),
|
||||
Key("f", fvec2(117, 40), 18, Keyboard::AppendSelf),
|
||||
Key("g", fvec2(137, 40), 18, Keyboard::AppendSelf),
|
||||
Key("h", fvec2(157, 40), 18, Keyboard::AppendSelf),
|
||||
Key("j", fvec2(177, 40), 18, Keyboard::AppendSelf),
|
||||
Key("k", fvec2(197, 40), 18, Keyboard::AppendSelf),
|
||||
Key("l", fvec2(217, 40), 18, Keyboard::AppendSelf),
|
||||
Key(";", fvec2(237, 40), 18, Keyboard::AppendSelf),
|
||||
Key("'", fvec2(257, 40), 18, Keyboard::AppendSelf),
|
||||
Key("Enter", fvec2(277, 40), fvec2(38, 18), Keyboard::Enter),
|
||||
// 4th row
|
||||
Key("Shift", vec2(5, 60), vec2(60, 18), Keyboard::Shift),
|
||||
Key("z", vec2(67, 60), 18, Keyboard::AppendSelf),
|
||||
Key("x", vec2(87, 60), 18, Keyboard::AppendSelf),
|
||||
Key("c", vec2(107, 60), 18, Keyboard::AppendSelf),
|
||||
Key("v", vec2(127, 60), 18, Keyboard::AppendSelf),
|
||||
Key("b", vec2(147, 60), 18, Keyboard::AppendSelf),
|
||||
Key("n", vec2(167, 60), 18, Keyboard::AppendSelf),
|
||||
Key("m", vec2(187, 60), 18, Keyboard::AppendSelf),
|
||||
Key(",", vec2(207, 60), 18, Keyboard::AppendSelf),
|
||||
Key(".", vec2(227, 60), 18, Keyboard::AppendSelf),
|
||||
Key("/", vec2(247, 60), 18, Keyboard::AppendSelf),
|
||||
Key("Shift", vec2(267, 60), vec2(48, 18), Keyboard::Shift),
|
||||
Key("Shift", fvec2(5, 60), fvec2(60, 18), Keyboard::Shift),
|
||||
Key("z", fvec2(67, 60), 18, Keyboard::AppendSelf),
|
||||
Key("x", fvec2(87, 60), 18, Keyboard::AppendSelf),
|
||||
Key("c", fvec2(107, 60), 18, Keyboard::AppendSelf),
|
||||
Key("v", fvec2(127, 60), 18, Keyboard::AppendSelf),
|
||||
Key("b", fvec2(147, 60), 18, Keyboard::AppendSelf),
|
||||
Key("n", fvec2(167, 60), 18, Keyboard::AppendSelf),
|
||||
Key("m", fvec2(187, 60), 18, Keyboard::AppendSelf),
|
||||
Key(",", fvec2(207, 60), 18, Keyboard::AppendSelf),
|
||||
Key(".", fvec2(227, 60), 18, Keyboard::AppendSelf),
|
||||
Key("/", fvec2(247, 60), 18, Keyboard::AppendSelf),
|
||||
Key("Shift", fvec2(267, 60), fvec2(48, 18), Keyboard::Shift),
|
||||
// 5th row
|
||||
Key("Cancel", vec2(5, 80), vec2(70, 18), Keyboard::OpCancel),
|
||||
Key("(X)", vec2(77, 80), vec2(23, 18), Keyboard::Op1),
|
||||
Key("Space", vec2(102, 80), vec2(108, 18), Keyboard::Space),
|
||||
Key("(!)", vec2(212, 80), vec2(23, 18), Keyboard::Op2),
|
||||
Key("Confirm", vec2(237, 80), vec2(78, 18), Keyboard::OpConfirm),
|
||||
Key("Cancel", fvec2(5, 80), fvec2(70, 18), Keyboard::OpCancel),
|
||||
Key("(X)", fvec2(77, 80), fvec2(23, 18), Keyboard::Op1),
|
||||
Key("Space", fvec2(102, 80), fvec2(108, 18), Keyboard::Space),
|
||||
Key("(!)", fvec2(212, 80), fvec2(23, 18), Keyboard::Op2),
|
||||
Key("Confirm", fvec2(237, 80), fvec2(78, 18), Keyboard::OpConfirm),
|
||||
},
|
||||
{
|
||||
// 1st row
|
||||
Key("`", vec2(5, 0), 18, Keyboard::AppendSelf),
|
||||
Key("1", vec2(25, 0), 18, Keyboard::AppendSelf),
|
||||
Key("2", vec2(45, 0), 18, Keyboard::AppendSelf),
|
||||
Key("3", vec2(65, 0), 18, Keyboard::AppendSelf),
|
||||
Key("4", vec2(85, 0), 18, Keyboard::AppendSelf),
|
||||
Key("5", vec2(105, 0), 18, Keyboard::AppendSelf),
|
||||
Key("6", vec2(125, 0), 18, Keyboard::AppendSelf),
|
||||
Key("7", vec2(145, 0), 18, Keyboard::AppendSelf),
|
||||
Key("8", vec2(165, 0), 18, Keyboard::AppendSelf),
|
||||
Key("9", vec2(185, 0), 18, Keyboard::AppendSelf),
|
||||
Key("0", vec2(205, 0), 18, Keyboard::AppendSelf),
|
||||
Key("-", vec2(225, 0), 18, Keyboard::AppendSelf),
|
||||
Key("=", vec2(245, 0), 18, Keyboard::AppendSelf),
|
||||
Key("<---", vec2(265, 0), vec2(50, 18), Keyboard::Backspace),
|
||||
Key("`", fvec2(5, 0), 18, Keyboard::AppendSelf),
|
||||
Key("1", fvec2(25, 0), 18, Keyboard::AppendSelf),
|
||||
Key("2", fvec2(45, 0), 18, Keyboard::AppendSelf),
|
||||
Key("3", fvec2(65, 0), 18, Keyboard::AppendSelf),
|
||||
Key("4", fvec2(85, 0), 18, Keyboard::AppendSelf),
|
||||
Key("5", fvec2(105, 0), 18, Keyboard::AppendSelf),
|
||||
Key("6", fvec2(125, 0), 18, Keyboard::AppendSelf),
|
||||
Key("7", fvec2(145, 0), 18, Keyboard::AppendSelf),
|
||||
Key("8", fvec2(165, 0), 18, Keyboard::AppendSelf),
|
||||
Key("9", fvec2(185, 0), 18, Keyboard::AppendSelf),
|
||||
Key("0", fvec2(205, 0), 18, Keyboard::AppendSelf),
|
||||
Key("-", fvec2(225, 0), 18, Keyboard::AppendSelf),
|
||||
Key("=", fvec2(245, 0), 18, Keyboard::AppendSelf),
|
||||
Key("<---", fvec2(265, 0), fvec2(50, 18), Keyboard::Backspace),
|
||||
// 2nd row
|
||||
Key("Tab", vec2(5, 20), vec2(40, 18), Keyboard::Tab),
|
||||
Key("Q", vec2(47, 20), 18, Keyboard::AppendSelf),
|
||||
Key("W", vec2(67, 20), 18, Keyboard::AppendSelf),
|
||||
Key("E", vec2(87, 20), 18, Keyboard::AppendSelf),
|
||||
Key("R", vec2(107, 20), 18, Keyboard::AppendSelf),
|
||||
Key("T", vec2(127, 20), 18, Keyboard::AppendSelf),
|
||||
Key("Y", vec2(147, 20), 18, Keyboard::AppendSelf),
|
||||
Key("U", vec2(167, 20), 18, Keyboard::AppendSelf),
|
||||
Key("I", vec2(187, 20), 18, Keyboard::AppendSelf),
|
||||
Key("O", vec2(207, 20), 18, Keyboard::AppendSelf),
|
||||
Key("P", vec2(227, 20), 18, Keyboard::AppendSelf),
|
||||
Key("[", vec2(247, 20), 18, Keyboard::AppendSelf),
|
||||
Key("]", vec2(267, 20), 18, Keyboard::AppendSelf),
|
||||
Key("\\", vec2(287, 20), vec2(28, 18), Keyboard::AppendSelf),
|
||||
Key("Tab", fvec2(5, 20), fvec2(40, 18), Keyboard::Tab),
|
||||
Key("Q", fvec2(47, 20), 18, Keyboard::AppendSelf),
|
||||
Key("W", fvec2(67, 20), 18, Keyboard::AppendSelf),
|
||||
Key("E", fvec2(87, 20), 18, Keyboard::AppendSelf),
|
||||
Key("R", fvec2(107, 20), 18, Keyboard::AppendSelf),
|
||||
Key("T", fvec2(127, 20), 18, Keyboard::AppendSelf),
|
||||
Key("Y", fvec2(147, 20), 18, Keyboard::AppendSelf),
|
||||
Key("U", fvec2(167, 20), 18, Keyboard::AppendSelf),
|
||||
Key("I", fvec2(187, 20), 18, Keyboard::AppendSelf),
|
||||
Key("O", fvec2(207, 20), 18, Keyboard::AppendSelf),
|
||||
Key("P", fvec2(227, 20), 18, Keyboard::AppendSelf),
|
||||
Key("[", fvec2(247, 20), 18, Keyboard::AppendSelf),
|
||||
Key("]", fvec2(267, 20), 18, Keyboard::AppendSelf),
|
||||
Key("\\", fvec2(287, 20), fvec2(28, 18), Keyboard::AppendSelf),
|
||||
// 3rd row
|
||||
Key("Caps", vec2(5, 40), vec2(50, 18), Keyboard::Caps),
|
||||
Key("A", vec2(57, 40), 18, Keyboard::AppendSelf),
|
||||
Key("S", vec2(77, 40), 18, Keyboard::AppendSelf),
|
||||
Key("D", vec2(97, 40), 18, Keyboard::AppendSelf),
|
||||
Key("F", vec2(117, 40), 18, Keyboard::AppendSelf),
|
||||
Key("G", vec2(137, 40), 18, Keyboard::AppendSelf),
|
||||
Key("H", vec2(157, 40), 18, Keyboard::AppendSelf),
|
||||
Key("J", vec2(177, 40), 18, Keyboard::AppendSelf),
|
||||
Key("K", vec2(197, 40), 18, Keyboard::AppendSelf),
|
||||
Key("L", vec2(217, 40), 18, Keyboard::AppendSelf),
|
||||
Key(";", vec2(237, 40), 18, Keyboard::AppendSelf),
|
||||
Key("'", vec2(257, 40), 18, Keyboard::AppendSelf),
|
||||
Key("Enter", vec2(277, 40), vec2(38, 18), Keyboard::Enter),
|
||||
Key("Caps", fvec2(5, 40), fvec2(50, 18), Keyboard::Caps),
|
||||
Key("A", fvec2(57, 40), 18, Keyboard::AppendSelf),
|
||||
Key("S", fvec2(77, 40), 18, Keyboard::AppendSelf),
|
||||
Key("D", fvec2(97, 40), 18, Keyboard::AppendSelf),
|
||||
Key("F", fvec2(117, 40), 18, Keyboard::AppendSelf),
|
||||
Key("G", fvec2(137, 40), 18, Keyboard::AppendSelf),
|
||||
Key("H", fvec2(157, 40), 18, Keyboard::AppendSelf),
|
||||
Key("J", fvec2(177, 40), 18, Keyboard::AppendSelf),
|
||||
Key("K", fvec2(197, 40), 18, Keyboard::AppendSelf),
|
||||
Key("L", fvec2(217, 40), 18, Keyboard::AppendSelf),
|
||||
Key(";", fvec2(237, 40), 18, Keyboard::AppendSelf),
|
||||
Key("'", fvec2(257, 40), 18, Keyboard::AppendSelf),
|
||||
Key("Enter", fvec2(277, 40), fvec2(38, 18), Keyboard::Enter),
|
||||
// 4th row
|
||||
Key("Shift", vec2(5, 60), vec2(60, 18), Keyboard::Shift),
|
||||
Key("Z", vec2(67, 60), 18, Keyboard::AppendSelf),
|
||||
Key("X", vec2(87, 60), 18, Keyboard::AppendSelf),
|
||||
Key("C", vec2(107, 60), 18, Keyboard::AppendSelf),
|
||||
Key("V", vec2(127, 60), 18, Keyboard::AppendSelf),
|
||||
Key("B", vec2(147, 60), 18, Keyboard::AppendSelf),
|
||||
Key("N", vec2(167, 60), 18, Keyboard::AppendSelf),
|
||||
Key("M", vec2(187, 60), 18, Keyboard::AppendSelf),
|
||||
Key(",", vec2(207, 60), 18, Keyboard::AppendSelf),
|
||||
Key(".", vec2(227, 60), 18, Keyboard::AppendSelf),
|
||||
Key("/", vec2(247, 60), 18, Keyboard::AppendSelf),
|
||||
Key("Shift", vec2(267, 60), vec2(48, 18), Keyboard::Shift),
|
||||
Key("Shift", fvec2(5, 60), fvec2(60, 18), Keyboard::Shift),
|
||||
Key("Z", fvec2(67, 60), 18, Keyboard::AppendSelf),
|
||||
Key("X", fvec2(87, 60), 18, Keyboard::AppendSelf),
|
||||
Key("C", fvec2(107, 60), 18, Keyboard::AppendSelf),
|
||||
Key("V", fvec2(127, 60), 18, Keyboard::AppendSelf),
|
||||
Key("B", fvec2(147, 60), 18, Keyboard::AppendSelf),
|
||||
Key("N", fvec2(167, 60), 18, Keyboard::AppendSelf),
|
||||
Key("M", fvec2(187, 60), 18, Keyboard::AppendSelf),
|
||||
Key(",", fvec2(207, 60), 18, Keyboard::AppendSelf),
|
||||
Key(".", fvec2(227, 60), 18, Keyboard::AppendSelf),
|
||||
Key("/", fvec2(247, 60), 18, Keyboard::AppendSelf),
|
||||
Key("Shift", fvec2(267, 60), fvec2(48, 18), Keyboard::Shift),
|
||||
// 5th row
|
||||
Key("Cancel", vec2(5, 80), vec2(70, 18), Keyboard::OpCancel),
|
||||
Key("(X)", vec2(77, 80), vec2(23, 18), Keyboard::Op1),
|
||||
Key("Space", vec2(102, 80), vec2(108, 18), Keyboard::Space),
|
||||
Key("(!)", vec2(212, 80), vec2(23, 18), Keyboard::Op2),
|
||||
Key("Confirm", vec2(237, 80), vec2(78, 18), Keyboard::OpConfirm),
|
||||
Key("Cancel", fvec2(5, 80), fvec2(70, 18), Keyboard::OpCancel),
|
||||
Key("(X)", fvec2(77, 80), fvec2(23, 18), Keyboard::Op1),
|
||||
Key("Space", fvec2(102, 80), fvec2(108, 18), Keyboard::Space),
|
||||
Key("(!)", fvec2(212, 80), fvec2(23, 18), Keyboard::Op2),
|
||||
Key("Confirm", fvec2(237, 80), fvec2(78, 18), Keyboard::OpConfirm),
|
||||
},
|
||||
{
|
||||
// 1st row
|
||||
Key("~", vec2(5, 0), 18, Keyboard::AppendSelf),
|
||||
Key("!", vec2(25, 0), 18, Keyboard::AppendSelf),
|
||||
Key("@", vec2(45, 0), 18, Keyboard::AppendSelf),
|
||||
Key("#", vec2(65, 0), 18, Keyboard::AppendSelf),
|
||||
Key("$", vec2(85, 0), 18, Keyboard::AppendSelf),
|
||||
Key("%", vec2(105, 0), 18, Keyboard::AppendSelf),
|
||||
Key("^", vec2(125, 0), 18, Keyboard::AppendSelf),
|
||||
Key("&", vec2(145, 0), 18, Keyboard::AppendSelf),
|
||||
Key("*", vec2(165, 0), 18, Keyboard::AppendSelf),
|
||||
Key("(", vec2(185, 0), 18, Keyboard::AppendSelf),
|
||||
Key(")", vec2(205, 0), 18, Keyboard::AppendSelf),
|
||||
Key("_", vec2(225, 0), 18, Keyboard::AppendSelf),
|
||||
Key("+", vec2(245, 0), 18, Keyboard::AppendSelf),
|
||||
Key("<---", vec2(265, 0), vec2(50, 18), Keyboard::Backspace),
|
||||
Key("~", fvec2(5, 0), 18, Keyboard::AppendSelf),
|
||||
Key("!", fvec2(25, 0), 18, Keyboard::AppendSelf),
|
||||
Key("@", fvec2(45, 0), 18, Keyboard::AppendSelf),
|
||||
Key("#", fvec2(65, 0), 18, Keyboard::AppendSelf),
|
||||
Key("$", fvec2(85, 0), 18, Keyboard::AppendSelf),
|
||||
Key("%", fvec2(105, 0), 18, Keyboard::AppendSelf),
|
||||
Key("^", fvec2(125, 0), 18, Keyboard::AppendSelf),
|
||||
Key("&", fvec2(145, 0), 18, Keyboard::AppendSelf),
|
||||
Key("*", fvec2(165, 0), 18, Keyboard::AppendSelf),
|
||||
Key("(", fvec2(185, 0), 18, Keyboard::AppendSelf),
|
||||
Key(")", fvec2(205, 0), 18, Keyboard::AppendSelf),
|
||||
Key("_", fvec2(225, 0), 18, Keyboard::AppendSelf),
|
||||
Key("+", fvec2(245, 0), 18, Keyboard::AppendSelf),
|
||||
Key("<---", fvec2(265, 0), fvec2(50, 18), Keyboard::Backspace),
|
||||
// 2nd row
|
||||
Key("Tab", vec2(5, 20), vec2(40, 18), Keyboard::Tab),
|
||||
Key("Q", vec2(47, 20), 18, Keyboard::AppendSelf),
|
||||
Key("W", vec2(67, 20), 18, Keyboard::AppendSelf),
|
||||
Key("E", vec2(87, 20), 18, Keyboard::AppendSelf),
|
||||
Key("R", vec2(107, 20), 18, Keyboard::AppendSelf),
|
||||
Key("T", vec2(127, 20), 18, Keyboard::AppendSelf),
|
||||
Key("Y", vec2(147, 20), 18, Keyboard::AppendSelf),
|
||||
Key("U", vec2(167, 20), 18, Keyboard::AppendSelf),
|
||||
Key("I", vec2(187, 20), 18, Keyboard::AppendSelf),
|
||||
Key("O", vec2(207, 20), 18, Keyboard::AppendSelf),
|
||||
Key("P", vec2(227, 20), 18, Keyboard::AppendSelf),
|
||||
Key("{", vec2(247, 20), 18, Keyboard::AppendSelf),
|
||||
Key("}", vec2(267, 20), 18, Keyboard::AppendSelf),
|
||||
Key("|", vec2(287, 20), vec2(28, 18), Keyboard::AppendSelf),
|
||||
Key("Tab", fvec2(5, 20), fvec2(40, 18), Keyboard::Tab),
|
||||
Key("Q", fvec2(47, 20), 18, Keyboard::AppendSelf),
|
||||
Key("W", fvec2(67, 20), 18, Keyboard::AppendSelf),
|
||||
Key("E", fvec2(87, 20), 18, Keyboard::AppendSelf),
|
||||
Key("R", fvec2(107, 20), 18, Keyboard::AppendSelf),
|
||||
Key("T", fvec2(127, 20), 18, Keyboard::AppendSelf),
|
||||
Key("Y", fvec2(147, 20), 18, Keyboard::AppendSelf),
|
||||
Key("U", fvec2(167, 20), 18, Keyboard::AppendSelf),
|
||||
Key("I", fvec2(187, 20), 18, Keyboard::AppendSelf),
|
||||
Key("O", fvec2(207, 20), 18, Keyboard::AppendSelf),
|
||||
Key("P", fvec2(227, 20), 18, Keyboard::AppendSelf),
|
||||
Key("{", fvec2(247, 20), 18, Keyboard::AppendSelf),
|
||||
Key("}", fvec2(267, 20), 18, Keyboard::AppendSelf),
|
||||
Key("|", fvec2(287, 20), fvec2(28, 18), Keyboard::AppendSelf),
|
||||
// 3rd row
|
||||
Key("Caps", vec2(5, 40), vec2(50, 18), Keyboard::Caps),
|
||||
Key("A", vec2(57, 40), 18, Keyboard::AppendSelf),
|
||||
Key("S", vec2(77, 40), 18, Keyboard::AppendSelf),
|
||||
Key("D", vec2(97, 40), 18, Keyboard::AppendSelf),
|
||||
Key("F", vec2(117, 40), 18, Keyboard::AppendSelf),
|
||||
Key("G", vec2(137, 40), 18, Keyboard::AppendSelf),
|
||||
Key("H", vec2(157, 40), 18, Keyboard::AppendSelf),
|
||||
Key("J", vec2(177, 40), 18, Keyboard::AppendSelf),
|
||||
Key("K", vec2(197, 40), 18, Keyboard::AppendSelf),
|
||||
Key("L", vec2(217, 40), 18, Keyboard::AppendSelf),
|
||||
Key(":", vec2(237, 40), 18, Keyboard::AppendSelf),
|
||||
Key("\"", vec2(257, 40), 18, Keyboard::AppendSelf),
|
||||
Key("Enter", vec2(277, 40), vec2(38, 18), Keyboard::Enter),
|
||||
Key("Caps", fvec2(5, 40), fvec2(50, 18), Keyboard::Caps),
|
||||
Key("A", fvec2(57, 40), 18, Keyboard::AppendSelf),
|
||||
Key("S", fvec2(77, 40), 18, Keyboard::AppendSelf),
|
||||
Key("D", fvec2(97, 40), 18, Keyboard::AppendSelf),
|
||||
Key("F", fvec2(117, 40), 18, Keyboard::AppendSelf),
|
||||
Key("G", fvec2(137, 40), 18, Keyboard::AppendSelf),
|
||||
Key("H", fvec2(157, 40), 18, Keyboard::AppendSelf),
|
||||
Key("J", fvec2(177, 40), 18, Keyboard::AppendSelf),
|
||||
Key("K", fvec2(197, 40), 18, Keyboard::AppendSelf),
|
||||
Key("L", fvec2(217, 40), 18, Keyboard::AppendSelf),
|
||||
Key(":", fvec2(237, 40), 18, Keyboard::AppendSelf),
|
||||
Key("\"", fvec2(257, 40), 18, Keyboard::AppendSelf),
|
||||
Key("Enter", fvec2(277, 40), fvec2(38, 18), Keyboard::Enter),
|
||||
// 4th row
|
||||
Key("Shift", vec2(5, 60), vec2(60, 18), Keyboard::Shift),
|
||||
Key("Z", vec2(67, 60), 18, Keyboard::AppendSelf),
|
||||
Key("X", vec2(87, 60), 18, Keyboard::AppendSelf),
|
||||
Key("C", vec2(107, 60), 18, Keyboard::AppendSelf),
|
||||
Key("V", vec2(127, 60), 18, Keyboard::AppendSelf),
|
||||
Key("B", vec2(147, 60), 18, Keyboard::AppendSelf),
|
||||
Key("N", vec2(167, 60), 18, Keyboard::AppendSelf),
|
||||
Key("M", vec2(187, 60), 18, Keyboard::AppendSelf),
|
||||
Key("<", vec2(207, 60), 18, Keyboard::AppendSelf),
|
||||
Key(">", vec2(227, 60), 18, Keyboard::AppendSelf),
|
||||
Key("?", vec2(247, 60), 18, Keyboard::AppendSelf),
|
||||
Key("Shift", vec2(267, 60), vec2(48, 18), Keyboard::Shift),
|
||||
Key("Shift", fvec2(5, 60), fvec2(60, 18), Keyboard::Shift),
|
||||
Key("Z", fvec2(67, 60), 18, Keyboard::AppendSelf),
|
||||
Key("X", fvec2(87, 60), 18, Keyboard::AppendSelf),
|
||||
Key("C", fvec2(107, 60), 18, Keyboard::AppendSelf),
|
||||
Key("V", fvec2(127, 60), 18, Keyboard::AppendSelf),
|
||||
Key("B", fvec2(147, 60), 18, Keyboard::AppendSelf),
|
||||
Key("N", fvec2(167, 60), 18, Keyboard::AppendSelf),
|
||||
Key("M", fvec2(187, 60), 18, Keyboard::AppendSelf),
|
||||
Key("<", fvec2(207, 60), 18, Keyboard::AppendSelf),
|
||||
Key(">", fvec2(227, 60), 18, Keyboard::AppendSelf),
|
||||
Key("?", fvec2(247, 60), 18, Keyboard::AppendSelf),
|
||||
Key("Shift", fvec2(267, 60), fvec2(48, 18), Keyboard::Shift),
|
||||
// 5th row
|
||||
Key("Cancel", vec2(5, 80), vec2(70, 18), Keyboard::OpCancel),
|
||||
Key("(X)", vec2(77, 80), vec2(23, 18), Keyboard::Op1),
|
||||
Key("Space", vec2(102, 80), vec2(108, 18), Keyboard::Space),
|
||||
Key("(!)", vec2(212, 80), vec2(23, 18), Keyboard::Op2),
|
||||
Key("Confirm", vec2(237, 80), vec2(78, 18), Keyboard::OpConfirm),
|
||||
Key("Cancel", fvec2(5, 80), fvec2(70, 18), Keyboard::OpCancel),
|
||||
Key("(X)", fvec2(77, 80), fvec2(23, 18), Keyboard::Op1),
|
||||
Key("Space", fvec2(102, 80), fvec2(108, 18), Keyboard::Space),
|
||||
Key("(!)", fvec2(212, 80), fvec2(23, 18), Keyboard::Op2),
|
||||
Key("Confirm", fvec2(237, 80), fvec2(78, 18), Keyboard::OpConfirm),
|
||||
},
|
||||
};
|
||||
|
||||
@ -248,10 +247,10 @@ void DumpLayout(const std::string& path) {
|
||||
for (size_t j = 0; j < layouts[0].size(); j++) {
|
||||
nlohmann::json key;
|
||||
key["display_char"] = layouts[i][j].k;
|
||||
key["pos_x"] = layouts[i][j].pos[0];
|
||||
key["pos_y"] = layouts[i][j].pos[1];
|
||||
key["size_x"] = layouts[i][j].size[0];
|
||||
key["size_y"] = layouts[i][j].size[1];
|
||||
key["pos_x"] = layouts[i][j].pos.x;
|
||||
key["pos_y"] = layouts[i][j].pos.y;
|
||||
key["size_x"] = layouts[i][j].size.x;
|
||||
key["size_y"] = layouts[i][j].size.y;
|
||||
key["op"] = layouts[i][j].op;
|
||||
l1.push_back(key);
|
||||
}
|
||||
@ -521,20 +520,20 @@ void Keyboard::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) {
|
||||
}
|
||||
if (flags & Flags_BlendTop) {
|
||||
ren->OnScreen(ren->GetScreen(false));
|
||||
ren->DrawRectSolid(0, vec2(400, 240), fade);
|
||||
ren->DrawRectSolid(0, fvec2(400, 240), fade);
|
||||
}
|
||||
if (flags & Flags_BlendBottom) {
|
||||
ren->OnScreen(ren->GetScreen(true));
|
||||
ren->DrawRectSolid(0, vec2(320, 240), fade);
|
||||
ren->DrawRectSolid(0, fvec2(320, 240), fade);
|
||||
}
|
||||
}
|
||||
/// Get the current start possition
|
||||
vec2 start = flymgr;
|
||||
// Draw head and Keyboard background
|
||||
ren->DrawRectSolid(
|
||||
vec2(0, start.y()), vec2(320, 125),
|
||||
fvec2(0, start.y()), fvec2(320, 125),
|
||||
PD::Color("#222222ff").a((flags & Flags_Transparency) ? 0xaa : 0xff));
|
||||
ren->DrawRectSolid(vec2(0, start.y()), vec2(320, 17), 0xaa000000);
|
||||
ren->DrawRectSolid(fvec2(0, start.y()), fvec2(320, 17), 0xaa000000);
|
||||
/// Grab the base layer and go one up for texts
|
||||
int l = ren->Layer();
|
||||
ren->Layer(l + 2);
|
||||
@ -548,11 +547,11 @@ void Keyboard::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) {
|
||||
// s << GamePadIcons::GetIcon(GamePadIcons::R) << " CAPS\n";
|
||||
// s << GamePadIcons::GetIcon(GamePadIcons::Dpad) << " Move ";
|
||||
// s << GamePadIcons::GetIcon(GamePadIcons::A) << " Select\n";
|
||||
// ren->DrawText(vec2(5, start.y() -
|
||||
// ren->DrawText(fvec2(5, start.y() -
|
||||
// ren->GetTextDimensions(s.str()).y()+16),
|
||||
// 0xffffffff, s.str());
|
||||
// }
|
||||
ren->DrawText(vec2(5, start.y()), 0xffffffff, "> " + *text);
|
||||
ren->DrawText(fvec2(5, start.y()), 0xffffffff, "> " + *text);
|
||||
ren->Layer(l + 1);
|
||||
/// Offset Keys start height by 22
|
||||
start[1] += 22;
|
||||
@ -592,7 +591,7 @@ void Keyboard::Update(float delta, LI::Renderer::Ref ren, Hid::Ref inp) {
|
||||
|
||||
if (raw_sel != -1) {
|
||||
ren->Layer(l);
|
||||
ren->DrawRectSolid(start + selector - vec2(1), vec2(sel_szs) + vec2(2),
|
||||
ren->DrawRectSolid(start + selector - fvec2(1), fvec2(sel_szs) + fvec2(2),
|
||||
0xaaffffff);
|
||||
ren->Layer(l);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ MessageMgr::Container::Container(const std::string& title,
|
||||
const std::string& msg) {
|
||||
this->title = title;
|
||||
this->msg = msg;
|
||||
size = vec2(150, 50);
|
||||
size = fvec2(150, 50);
|
||||
// Precalculate colors
|
||||
col_bg = PD::Color("#111111aa");
|
||||
col_text = PD::Color("#ffffff");
|
||||
@ -42,11 +42,11 @@ void MessageMgr::Container::Render(PD::LI::Renderer::Ref ren) {
|
||||
// result in the same we would waste a lot
|
||||
// of cpu performance which is a big issue
|
||||
// espeacilly on the Old3ds...
|
||||
vec2 tpos = pos;
|
||||
fvec2 tpos = pos;
|
||||
// Check if it goes out of screen
|
||||
// Instant kills cause it will never be on
|
||||
// Screen agains
|
||||
if (tpos[1] + size[1] < 0) {
|
||||
if (tpos.y + size.y < 0) {
|
||||
kill = true;
|
||||
}
|
||||
// If should be removed modify the color by fade
|
||||
@ -58,7 +58,7 @@ void MessageMgr::Container::Render(PD::LI::Renderer::Ref ren) {
|
||||
}
|
||||
// Create a backup Layer to Render
|
||||
// Text onto the next layer
|
||||
int l = ren->Layer();
|
||||
//int l = ren->Layer();
|
||||
ren->DrawRectSolid(tpos, size, col_bg);
|
||||
ren->Layer(l + 1);
|
||||
ren->DrawText(tpos + vec2(4, 2), col_text, title);
|
||||
|
@ -1,72 +1,72 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/sound/mp3.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace Music {
|
||||
int Mp3Decoder::Init(const std::string& path) {
|
||||
int ret = 0;
|
||||
int encoding = 0;
|
||||
if ((ret = mpg123_init() != MPG123_OK)) {
|
||||
return ret;
|
||||
}
|
||||
if ((handle = mpg123_new(nullptr, &ret)) == nullptr) {
|
||||
return ret;
|
||||
}
|
||||
int cnls = 0;
|
||||
long _rate = 0;
|
||||
if (mpg123_open(handle, path.c_str()) != MPG123_OK ||
|
||||
mpg123_getformat(handle, &_rate, &cnls, &encoding)) {
|
||||
return ret;
|
||||
}
|
||||
rate = _rate;
|
||||
channels = cnls;
|
||||
mpg123_format_none(handle);
|
||||
mpg123_format(handle, rate, channels, encoding);
|
||||
buf_size = mpg123_outblock(handle) * 16;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Mp3Decoder::Deinit() {
|
||||
mpg123_close(handle);
|
||||
mpg123_delete(handle);
|
||||
mpg123_exit();
|
||||
}
|
||||
|
||||
u32 Mp3Decoder::GetSampleRate() { return rate; }
|
||||
u8 Mp3Decoder::GetChannels() { return channels; }
|
||||
u64 Mp3Decoder::Decode(u16* buf_address) {
|
||||
size_t done = 0;
|
||||
mpg123_read(handle, buf_address, buf_size, &done);
|
||||
return done / sizeof(u16);
|
||||
}
|
||||
size_t Mp3Decoder::GetFileSamples() {
|
||||
off_t len = mpg123_length(handle);
|
||||
if (len != MPG123_ERR) {
|
||||
return len * size_t(channels);
|
||||
}
|
||||
return -1; // NotExist
|
||||
}
|
||||
} // namespace Music
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/sound/mp3.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace Music {
|
||||
int Mp3Decoder::Init(const std::string& path) {
|
||||
int ret = 0;
|
||||
int encoding = 0;
|
||||
if ((ret = mpg123_init() != MPG123_OK)) {
|
||||
return ret;
|
||||
}
|
||||
if ((handle = mpg123_new(nullptr, &ret)) == nullptr) {
|
||||
return ret;
|
||||
}
|
||||
int cnls = 0;
|
||||
long _rate = 0;
|
||||
if (mpg123_open(handle, path.c_str()) != MPG123_OK ||
|
||||
mpg123_getformat(handle, &_rate, &cnls, &encoding)) {
|
||||
return ret;
|
||||
}
|
||||
rate = _rate;
|
||||
channels = cnls;
|
||||
mpg123_format_none(handle);
|
||||
mpg123_format(handle, rate, channels, encoding);
|
||||
buf_size = mpg123_outblock(handle) * 16;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Mp3Decoder::Deinit() {
|
||||
mpg123_close(handle);
|
||||
mpg123_delete(handle);
|
||||
mpg123_exit();
|
||||
}
|
||||
|
||||
u32 Mp3Decoder::GetSampleRate() { return rate; }
|
||||
u8 Mp3Decoder::GetChannels() { return channels; }
|
||||
u64 Mp3Decoder::Decode(u16* buf_address) {
|
||||
size_t done = 0;
|
||||
mpg123_read(handle, buf_address, buf_size, &done);
|
||||
return done / sizeof(u16);
|
||||
}
|
||||
size_t Mp3Decoder::GetFileSamples() {
|
||||
off_t len = mpg123_length(handle);
|
||||
if (len != MPG123_ERR) {
|
||||
return len * size_t(channels);
|
||||
}
|
||||
return -1; // NotExist
|
||||
}
|
||||
} // namespace Music
|
||||
} // namespace PD
|
@ -1,64 +1,64 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/container/button.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void Button::HandleInput() {
|
||||
/// Ensure to only check input once
|
||||
if (inp_done) {
|
||||
return;
|
||||
}
|
||||
/// Ensure it gets sed to false and stays if not pressed
|
||||
pressed = false;
|
||||
color = UI7Color_Button;
|
||||
Assert(screen.get(), "Screen is not set up!");
|
||||
if (screen->ScreenType() == Screen::Bottom) {
|
||||
if (io->DragObject(this->GetID(), vec4(FinalPos(), size))) {
|
||||
if (io->DragReleased) {
|
||||
color = UI7Color_ButtonActive;
|
||||
pressed = true;
|
||||
} else {
|
||||
color = UI7Color_ButtonHovered;
|
||||
}
|
||||
}
|
||||
}
|
||||
inp_done = true;
|
||||
}
|
||||
void Button::Draw() {
|
||||
Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
|
||||
io->Ren->OnScreen(screen);
|
||||
list->AddRectangle(FinalPos(), size, io->Theme->Get(color));
|
||||
list->Layer(list->Layer() + 1);
|
||||
list->AddText(FinalPos() + size * 0.5 - tdim * 0.5, label,
|
||||
io->Theme->Get(UI7Color_Text));
|
||||
list->Layer(list->Layer() - 1);
|
||||
}
|
||||
|
||||
void Button::Update() {
|
||||
Assert(io.get(), "Did you run Container::Init correctly?");
|
||||
this->SetSize(tdim + io->FramePadding);
|
||||
}
|
||||
} // namespace UI7
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/container/button.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
PD_UI7_API void Button::HandleInput() {
|
||||
/// Ensure to only check input once
|
||||
if (inp_done) {
|
||||
return;
|
||||
}
|
||||
/// Ensure it gets sed to false and stays if not pressed
|
||||
pressed = false;
|
||||
color = UI7Color_Button;
|
||||
// Assert(screen.get(), "Screen is not set up!");
|
||||
// if (screen->ScreenType() == Screen::Bottom) {
|
||||
if (io->InputHandler->DragObject(this->GetID(), vec4(FinalPos(), size))) {
|
||||
if (io->InputHandler->DragReleased) {
|
||||
color = UI7Color_ButtonActive;
|
||||
pressed = true;
|
||||
} else {
|
||||
color = UI7Color_ButtonHovered;
|
||||
}
|
||||
}
|
||||
//}
|
||||
inp_done = true;
|
||||
}
|
||||
PD_UI7_API void Button::Draw() {
|
||||
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
|
||||
// io->Ren->OnScreen(screen);
|
||||
list->AddRectangle(FinalPos(), size, io->Theme->Get(color));
|
||||
list->Layer++;
|
||||
list->AddText(FinalPos() + size * 0.5 - tdim * 0.5, label,
|
||||
io->Theme->Get(UI7Color_Text));
|
||||
list->Layer--;
|
||||
}
|
||||
|
||||
PD_UI7_API void Button::Update() {
|
||||
// Assert(io.get(), "Did you run Container::Init correctly?");
|
||||
this->SetSize(tdim + io->FramePadding);
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -1,66 +1,66 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/container/checkbox.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void Checkbox::HandleInput() {
|
||||
/// Ensure to only check input once
|
||||
if (inp_done) {
|
||||
return;
|
||||
}
|
||||
color = UI7Color_FrameBackground;
|
||||
/// Ensure it gets sed to false and stays if not pressed
|
||||
Assert(screen.get(), "Screen is not set up!");
|
||||
if (screen->ScreenType() == Screen::Bottom) {
|
||||
if (io->DragObject(this->GetID(), vec4(FinalPos(), size))) {
|
||||
if (io->DragReleased) {
|
||||
color = UI7Color_FrameBackgroundHovered;
|
||||
usr_ref = !usr_ref;
|
||||
} else {
|
||||
color = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
}
|
||||
}
|
||||
inp_done = true;
|
||||
}
|
||||
void Checkbox::Draw() {
|
||||
Assert(list.get() && io.get(), "Did you run Container::Init correctly?");
|
||||
io->Ren->OnScreen(screen);
|
||||
list->AddRectangle(FinalPos(), cbs, io->Theme->Get(color));
|
||||
if (usr_ref) {
|
||||
list->AddRectangle(FinalPos() + 2, cbs - 4,
|
||||
io->Theme->Get(UI7Color_Checkmark));
|
||||
}
|
||||
list->AddText(FinalPos() + vec2(cbs.x() + io->ItemSpace.x(),
|
||||
cbs.y() * 0.5 - tdim.y() * 0.5),
|
||||
label, io->Theme->Get(UI7Color_Text));
|
||||
}
|
||||
|
||||
void Checkbox::Update() {
|
||||
Assert(io.get(), "Did you run Container::Init correctly?");
|
||||
this->SetSize(cbs + vec2(tdim.x() + io->ItemSpace.x(), 0));
|
||||
}
|
||||
} // namespace UI7
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/container/checkbox.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
PD_UI7_API void Checkbox::HandleInput() {
|
||||
/// Ensure to only check input once
|
||||
if (inp_done) {
|
||||
return;
|
||||
}
|
||||
color = UI7Color_FrameBackground;
|
||||
/// Ensure it gets sed to false and stays if not pressed
|
||||
// Assert(screen.get(), "Screen is not set up!");
|
||||
// if (screen->ScreenType() == Screen::Bottom) {
|
||||
if (io->InputHandler->DragObject(this->GetID(), vec4(FinalPos(), size))) {
|
||||
if (io->InputHandler->DragReleased) {
|
||||
color = UI7Color_FrameBackgroundHovered;
|
||||
usr_ref = !usr_ref;
|
||||
} else {
|
||||
color = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
}
|
||||
//}
|
||||
inp_done = true;
|
||||
}
|
||||
PD_UI7_API void Checkbox::Draw() {
|
||||
// Assert(list.get() && io.get(), "Did you run Container::Init correctly?");
|
||||
// io->Ren->OnScreen(screen);
|
||||
list->AddRectangle(FinalPos(), cbs, io->Theme->Get(color));
|
||||
if (usr_ref) {
|
||||
list->AddRectangle(FinalPos() + 2, cbs - 4,
|
||||
io->Theme->Get(UI7Color_Checkmark));
|
||||
}
|
||||
list->AddText(
|
||||
FinalPos() + fvec2(cbs.x + io->ItemSpace.x, cbs.y * 0.5 - tdim.y * 0.5),
|
||||
label, io->Theme->Get(UI7Color_Text));
|
||||
}
|
||||
|
||||
PD_UI7_API void Checkbox::Update() {
|
||||
// Assert(io.get(), "Did you run Container::Init correctly?");
|
||||
this->SetSize(cbs + fvec2(tdim.x + io->ItemSpace.x, 0));
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -1,65 +1,65 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/container/coloredit.hpp>
|
||||
#include <pd/ui7/container/label.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void ColorEdit::HandleInput() {
|
||||
/// Ensure to only check input once
|
||||
if (inp_done) {
|
||||
return;
|
||||
}
|
||||
Assert(screen.get(), "Screen is not set up!");
|
||||
if (screen->ScreenType() == Screen::Bottom) {
|
||||
if (io->DragObject(this->GetID(), vec4(FinalPos(), size))) {
|
||||
if (io->DragReleased) {
|
||||
is_shown = !is_shown;
|
||||
}
|
||||
}
|
||||
}
|
||||
inp_done = true;
|
||||
}
|
||||
void ColorEdit::Draw() {
|
||||
Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
|
||||
io->Ren->OnScreen(screen);
|
||||
list->AddRectangle(FinalPos(), vec2(20, 20), *color_ref);
|
||||
list->AddText(FinalPos() + vec2(io->ItemSpace.x() + 20, 0), label,
|
||||
io->Theme->Get(UI7Color_Text));
|
||||
if (is_shown) {
|
||||
if (!layout) {
|
||||
layout = Layout::New(GetID(), io);
|
||||
}
|
||||
layout->AddObject(PD::New<Label>("Hello World!", io->Ren));
|
||||
layout->Update();
|
||||
io->RegisterDrawList(GetID(), layout->GetDrawList());
|
||||
}
|
||||
}
|
||||
|
||||
void ColorEdit::Update() {
|
||||
Assert(io.get(), "Did you run Container::Init correctly?");
|
||||
this->SetSize(vec2(tdim.x() + io->ItemSpace.x() + 20, 20));
|
||||
}
|
||||
} // namespace UI7
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/container/coloredit.hpp>
|
||||
#include <pd/ui7/container/label.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
PD_UI7_API void ColorEdit::HandleInput() {
|
||||
/// Ensure to only check input once
|
||||
if (inp_done) {
|
||||
return;
|
||||
}
|
||||
// Assert(screen.get(), "Screen is not set up!");
|
||||
// if (screen->ScreenType() == Screen::Bottom) {
|
||||
if (io->InputHandler->DragObject(this->GetID(), vec4(FinalPos(), size))) {
|
||||
if (io->InputHandler->DragReleased) {
|
||||
is_shown = !is_shown;
|
||||
}
|
||||
}
|
||||
//}
|
||||
inp_done = true;
|
||||
}
|
||||
PD_UI7_API void ColorEdit::Draw() {
|
||||
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
|
||||
// io->Ren->OnScreen(screen);
|
||||
list->AddRectangle(FinalPos(), fvec2(20, 20), *color_ref);
|
||||
list->AddText(FinalPos() + fvec2(io->ItemSpace.x + 20, 0), label,
|
||||
io->Theme->Get(UI7Color_Text));
|
||||
if (is_shown) {
|
||||
if (!layout) {
|
||||
layout = Layout::New(GetID(), io);
|
||||
}
|
||||
layout->AddObject(PD::New<Label>("Hello World!", io));
|
||||
layout->Update();
|
||||
io->RegisterDrawList(GetID(), layout->GetDrawList());
|
||||
}
|
||||
}
|
||||
|
||||
PD_UI7_API void ColorEdit::Update() {
|
||||
// Assert(io.get(), "Did you run Container::Init correctly?");
|
||||
this->SetSize(fvec2(tdim.x + io->ItemSpace.x + 20, 20));
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -21,19 +21,24 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pd/core/sys.hpp>
|
||||
#include <pd/ui7/container/container.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void Container::HandleScrolling(vec2 scrolling, vec4 viewport) {
|
||||
PD_UI7_API void Container::HandleScrolling(fvec2 scrolling, fvec4 viewport) {
|
||||
if (last_use != 0 && Sys::GetTime() - last_use > 5000) {
|
||||
rem = true;
|
||||
}
|
||||
last_use = Sys::GetTime();
|
||||
pos -= vec2(0, scrolling.y());
|
||||
pos -= fvec2(0, scrolling.y);
|
||||
skippable = !LI::Renderer::InBox(
|
||||
pos, size, vec4(viewport.xy(), viewport.xy() + viewport.zw()));
|
||||
pos, size,
|
||||
fvec4(viewport.x, viewport.y, viewport.x + viewport.z,
|
||||
viewport.y + viewport.w));
|
||||
}
|
||||
|
||||
PD_UI7_API void Container::HandleInternalInput() {
|
||||
/** Requires Handle Scrolling First */
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -1,113 +1,115 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/container/dragdata.hpp>
|
||||
#include <pd/ui7/container/label.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
// Setup Supported Datatypes (Probably making this Object
|
||||
// header only to not care about datatype support)
|
||||
template class DragData<float>;
|
||||
template class DragData<int>;
|
||||
template class DragData<double>;
|
||||
template class DragData<u8>;
|
||||
template class DragData<u16>;
|
||||
template class DragData<u32>;
|
||||
template class DragData<u64>;
|
||||
template <typename T>
|
||||
void DragData<T>::HandleInput() {
|
||||
/// Ensure to only check input once
|
||||
if (inp_done) {
|
||||
return;
|
||||
}
|
||||
Assert(screen.get(), "Screen is not set up!");
|
||||
if (screen->ScreenType() == Screen::Bottom) {
|
||||
float off_x = 0;
|
||||
for (size_t i = 0; i < elm_count; i++) {
|
||||
std::string p;
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
p = std::format("{:.{}f}", data[i], precision);
|
||||
} else {
|
||||
p = std::format("{}", data[i]);
|
||||
}
|
||||
vec2 tdim = io->Ren->GetTextDimensions(p);
|
||||
// Unsafe but is the fastest solution
|
||||
if (io->DragObject(
|
||||
this->GetID() + i + 1,
|
||||
vec4(FinalPos() + vec2(off_x, 0), tdim + io->FramePadding))) {
|
||||
data[i] = std::clamp(T(data[i] + (step * (io->DragPosition[0] -
|
||||
io->DragLastPosition[0]))),
|
||||
this->min, this->max);
|
||||
}
|
||||
off_x += tdim.x() + io->ItemSpace.x() + io->FramePadding.x();
|
||||
}
|
||||
}
|
||||
inp_done = true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DragData<T>::Draw() {
|
||||
Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
|
||||
io->Ren->OnScreen(screen);
|
||||
float off_x = 0.f;
|
||||
for (size_t i = 0; i < elm_count; i++) {
|
||||
std::string p;
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
p = std::format("{:.{}f}", data[i], precision);
|
||||
} else {
|
||||
p = std::format("{}", data[i]);
|
||||
}
|
||||
vec2 td = io->Ren->GetTextDimensions(p);
|
||||
list->AddRectangle(FinalPos() + vec2(off_x, 0), td + io->FramePadding,
|
||||
io->Theme->Get(UI7Color_Button));
|
||||
list->Layer(list->Layer() + 1);
|
||||
list->AddText(FinalPos() + vec2(off_x, 0), p, io->Theme->Get(UI7Color_Text),
|
||||
LITextFlags_AlignMid, td + io->FramePadding);
|
||||
list->Layer(list->Layer() - 1);
|
||||
off_x += td.x() + io->ItemSpace.x() + io->FramePadding.x();
|
||||
}
|
||||
list->AddText(FinalPos() + vec2(off_x, io->FramePadding.y() * 0.5), label,
|
||||
io->Theme->Get(UI7Color_Text));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void DragData<T>::Update() {
|
||||
Assert(io.get(), "Did you run Container::Init correctly?");
|
||||
// Probably need to find a faster solution (caching sizes calculated here)
|
||||
float off_x = 0;
|
||||
for (size_t i = 0; i < elm_count; i++) {
|
||||
std::string p;
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
p = std::format("{:.{}f}", data[i], precision);
|
||||
} else {
|
||||
p = std::format("{}", data[i]);
|
||||
}
|
||||
vec2 tdim = io->Ren->GetTextDimensions(p);
|
||||
off_x += tdim.x() + io->ItemSpace.x() + io->FramePadding.x();
|
||||
}
|
||||
this->SetSize(vec2(tdim.x() + off_x, tdim.y() + io->FramePadding.y()));
|
||||
}
|
||||
} // namespace UI7
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/container/dragdata.hpp>
|
||||
#include <pd/ui7/container/label.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
// Setup Supported Datatypes (Probably making this Object
|
||||
// header only to not care about datatype support)
|
||||
template class PD_UI7_API DragData<float>;
|
||||
template class PD_UI7_API DragData<int>;
|
||||
template class PD_UI7_API DragData<double>;
|
||||
template class PD_UI7_API DragData<u8>;
|
||||
template class PD_UI7_API DragData<u16>;
|
||||
template class PD_UI7_API DragData<u32>;
|
||||
template class PD_UI7_API DragData<u64>;
|
||||
template <typename T>
|
||||
PD_UI7_API void DragData<T>::HandleInput() {
|
||||
/// Ensure to only check input once
|
||||
if (inp_done) {
|
||||
return;
|
||||
}
|
||||
// Assert(screen.get(), "Screen is not set up!");
|
||||
// if (screen->ScreenType() == Screen::Bottom) {
|
||||
float off_x = 0;
|
||||
for (size_t i = 0; i < elm_count; i++) {
|
||||
std::string p;
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
p = std::format("{:.{}f}", data[i], precision);
|
||||
} else {
|
||||
p = std::format("{}", data[i]);
|
||||
}
|
||||
vec2 tdim = io->Font->GetTextBounds(p, io->FontScale);
|
||||
// Unsafe but is the fastest solution
|
||||
if (io->InputHandler->DragObject(
|
||||
this->GetID() + i + 1,
|
||||
fvec4(FinalPos() + fvec2(off_x, 0), tdim + io->FramePadding))) {
|
||||
data[i] = std::clamp(
|
||||
T(data[i] + (step * (io->InputHandler->DragPosition.x -
|
||||
io->InputHandler->DragLastPosition.x))),
|
||||
this->min, this->max);
|
||||
}
|
||||
off_x += tdim.x + io->ItemSpace.x + io->FramePadding.x;
|
||||
}
|
||||
//}
|
||||
inp_done = true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PD_UI7_API void DragData<T>::Draw() {
|
||||
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
|
||||
// io->Ren->OnScreen(screen);
|
||||
float off_x = 0.f;
|
||||
for (size_t i = 0; i < elm_count; i++) {
|
||||
std::string p;
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
p = std::format("{:.{}f}", data[i], precision);
|
||||
} else {
|
||||
p = std::format("{}", data[i]);
|
||||
}
|
||||
vec2 td = io->Font->GetTextBounds(p, io->FontScale);
|
||||
list->AddRectangle(FinalPos() + fvec2(off_x, 0), td + io->FramePadding,
|
||||
io->Theme->Get(UI7Color_Button));
|
||||
list->Layer++;
|
||||
list->AddText(FinalPos() + fvec2(off_x, 0), p,
|
||||
io->Theme->Get(UI7Color_Text), LITextFlags_AlignMid,
|
||||
td + io->FramePadding);
|
||||
list->Layer--;
|
||||
off_x += td.x + io->ItemSpace.x + io->FramePadding.x;
|
||||
}
|
||||
list->AddText(FinalPos() + fvec2(off_x, io->FramePadding.y * 0.5), label,
|
||||
io->Theme->Get(UI7Color_Text));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PD_UI7_API void DragData<T>::Update() {
|
||||
// Assert(io.get(), "Did you run Container::Init correctly?");
|
||||
// Probably need to find a faster solution (caching sizes calculated here)
|
||||
float off_x = 0;
|
||||
for (size_t i = 0; i < elm_count; i++) {
|
||||
std::string p;
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
p = std::format("{:.{}f}", data[i], precision);
|
||||
} else {
|
||||
p = std::format("{}", data[i]);
|
||||
}
|
||||
vec2 tdim = io->Font->GetTextBounds(p, io->FontScale);
|
||||
off_x += tdim.x + io->ItemSpace.x + io->FramePadding.x;
|
||||
}
|
||||
this->SetSize(vec2(tdim.x + off_x, tdim.y + io->FramePadding.y));
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -1,50 +1,33 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <3ds.h>
|
||||
|
||||
#include <pd/lib3ds/hwinfo.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace HwInfo {
|
||||
void Init() {
|
||||
mcuHwcInit();
|
||||
ptmuInit();
|
||||
}
|
||||
void Deinit() {
|
||||
mcuHwcExit();
|
||||
ptmuExit();
|
||||
}
|
||||
bool IsCharging() {
|
||||
u8 v = 0;
|
||||
PTMU_GetBatteryChargeState(&v);
|
||||
return v == 1;
|
||||
}
|
||||
int GetBatteryPercentage() {
|
||||
u8 lvl = 0;
|
||||
MCUHWC_GetBatteryLevel(&lvl);
|
||||
return lvl;
|
||||
}
|
||||
int GetWifiLevel() { return osGetWifiStrength(); }
|
||||
} // namespace HwInfo
|
||||
/*
|
||||
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/ui7/container/dynobj.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
PD_UI7_API void DynObj::Draw() { pRenFun(io, list, this); }
|
||||
PD_UI7_API void DynObj::HandleInput() {}
|
||||
PD_UI7_API void DynObj::Update() {}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -25,11 +25,13 @@ SOFTWARE.
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void Image::Draw() {
|
||||
Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
|
||||
Assert(img.get(), "Image is nullptr!");
|
||||
io->Ren->OnScreen(screen);
|
||||
PD_UI7_API void Image::Draw() {
|
||||
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
|
||||
// Assert(img.get(), "Image is nullptr!");
|
||||
// io->Ren->OnScreen(screen);
|
||||
list->Layer++;
|
||||
list->AddImage(FinalPos(), img, newsize, this->cuv);
|
||||
list->Layer--;
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -25,9 +25,9 @@ SOFTWARE.
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void Label::Draw() {
|
||||
Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
|
||||
io->Ren->OnScreen(screen);
|
||||
PD_UI7_API void Label::Draw() {
|
||||
// Assert(io.get() && list.get(), "Did you run Container::Init correctly?");
|
||||
// io->Ren->OnScreen(screen);
|
||||
list->AddText(FinalPos(), label, io->Theme->Get(UI7Color_Text));
|
||||
}
|
||||
} // namespace UI7
|
||||
|
@ -1,263 +1,288 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/core/strings.hpp>
|
||||
#include <pd/ui7/drawlist.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void DrawList::PathArcToN(const vec2& 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);
|
||||
PathNext(vec2(c.x() + std::cos(a) * radius, c.y() + std::sin(a) * radius));
|
||||
}
|
||||
}
|
||||
|
||||
void DrawList::PathRect(vec2 a, vec2 b, float rounding, UI7DrawFlags flags) {
|
||||
if (rounding == 0.f) {
|
||||
PathNext(a);
|
||||
PathNext(vec2(b.x(), a.y()));
|
||||
PathNext(b);
|
||||
PathNext(vec2(a.x(), b.y()));
|
||||
} else {
|
||||
PathArcToN(vec2(a.x() + rounding, a.y() + rounding), rounding, 4*6, 4*9, 21);
|
||||
PathArcToN(vec2(b.x() - rounding, a.y() + rounding), rounding, 4*9, 4*12, 21);
|
||||
PathArcToN(vec2(b.x() - rounding, b.y() - rounding), rounding, 4*0, 4*3, 21);
|
||||
PathArcToN(vec2(a.x() + rounding, b.y() - rounding), rounding, 4*3, 4*6, 21);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawList::AddRect(const vec2& pos, const vec2& size, const UI7Color& clr,
|
||||
int thickness) {
|
||||
if (!ren->InBox(pos, size, ren->GetViewport())) {
|
||||
return;
|
||||
}
|
||||
ren->UseTex();
|
||||
PathRect(pos, pos + size);
|
||||
PathStroke(clr, thickness, UI7DrawFlags_Close);
|
||||
}
|
||||
void DrawList::AddRectangle(vec2 pos, vec2 szs, const UI7Color& clr) {
|
||||
if (!ren->InBox(pos, szs, ren->GetViewport())) {
|
||||
return;
|
||||
}
|
||||
ren->UseTex();
|
||||
PathRect(pos, pos + szs);
|
||||
PathFill(clr);
|
||||
}
|
||||
|
||||
void DrawList::AddTriangle(const vec2& a, const vec2& b, const vec2& c,
|
||||
const UI7Color& clr, int thickness) {
|
||||
ren->UseTex();
|
||||
PathNext(a);
|
||||
PathNext(b);
|
||||
PathNext(c);
|
||||
PathStroke(clr, thickness, UI7DrawFlags_Close);
|
||||
}
|
||||
|
||||
void DrawList::AddTriangleFilled(const vec2& a, const vec2& b, const vec2& c,
|
||||
const UI7Color& clr) {
|
||||
ren->UseTex();
|
||||
PathNext(a);
|
||||
PathNext(b);
|
||||
PathNext(c);
|
||||
PathFill(clr);
|
||||
}
|
||||
|
||||
void DrawList::AddCircle(const vec2& pos, float rad, UI7Color col,
|
||||
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(pos, rad, 0.f, am, num_segments);
|
||||
}
|
||||
ren->UseTex();
|
||||
PathStroke(col, thickness, UI7DrawFlags_Close);
|
||||
}
|
||||
|
||||
void DrawList::AddCircleFilled(const vec2& pos, float rad, UI7Color col,
|
||||
int num_segments) {
|
||||
if (num_segments <= 0) {
|
||||
// Auto Segment
|
||||
} else {
|
||||
float am = (M_PI * 2.0f) * ((float)num_segments) / (float)num_segments;
|
||||
PathArcToN(pos, rad, 0.f, am, num_segments);
|
||||
}
|
||||
ren->UseTex();
|
||||
PathFill(col);
|
||||
}
|
||||
|
||||
void DrawList::AddText(vec2 pos, const std::string& text, const UI7Color& clr,
|
||||
LITextFlags flags, vec2 box) {
|
||||
if (!ren->Font()) {
|
||||
return;
|
||||
}
|
||||
u32 id = Strings::FastHash(text);
|
||||
LI::StaticText::Ref e;
|
||||
auto f = static_text.find(id);
|
||||
if (static_text.find(id) == static_text.end()) {
|
||||
e = LI::StaticText::New();
|
||||
static_text[id] = e;
|
||||
} else {
|
||||
e = f->second;
|
||||
}
|
||||
if (!e->IsSetup() || e->Font() != ren->Font()) {
|
||||
int l = ren->Layer();
|
||||
ren->Layer(layer);
|
||||
e->Setup(ren.get(), pos, clr, text, flags, box);
|
||||
e->Font(ren->Font());
|
||||
ren->Layer(l);
|
||||
}
|
||||
e->SetPos(pos);
|
||||
e->SetColor(clr);
|
||||
e->SetLayer(layer);
|
||||
if (!clip_rects.empty()) {
|
||||
e->SetScissorMode(LI::ScissorMode_Normal);
|
||||
e->ScissorRect(clip_rects.top());
|
||||
}
|
||||
for (auto it : e->GetRawObject()->List()) {
|
||||
this->commands.push_back(std::make_pair(
|
||||
ren->CurrentScreen()->ScreenType() == Screen::Bottom, it));
|
||||
}
|
||||
e->GetRawObject()->ReCopy();
|
||||
}
|
||||
|
||||
void DrawList::AddImage(vec2 pos, Texture::Ref img, vec2 size, LI::Rect uv) {
|
||||
size = size == 0.f ? img->GetSize() : size;
|
||||
uv = (uv.Top() == 0.0f && uv.Bot() == 0.0f) ? img->GetUV() : uv;
|
||||
if (!ren->InBox(pos, size, ren->GetViewport())) {
|
||||
return;
|
||||
}
|
||||
auto rect = ren->CreateRect(pos, size, 0.f);
|
||||
auto cmd = LI::Command::New();
|
||||
ren->UseTex(img);
|
||||
ren->SetupCommand(cmd);
|
||||
cmd->Layer(layer);
|
||||
if (!clip_rects.empty()) {
|
||||
cmd->SetScissorMode(LI::ScissorMode_Normal);
|
||||
cmd->ScissorRect(clip_rects.top());
|
||||
}
|
||||
ren->QuadCommand(cmd, rect, uv, 0xffffffff);
|
||||
commands.push_back(std::make_pair(
|
||||
ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd));
|
||||
}
|
||||
|
||||
void DrawList::AddLine(const vec2& a, const vec2& b, const UI7Color& clr,
|
||||
int t) {
|
||||
if (!ren->InBox(a, ren->GetViewport()) &&
|
||||
!ren->InBox(b, ren->GetViewport())) {
|
||||
return;
|
||||
}
|
||||
ren->UseTex();
|
||||
PathNext(a);
|
||||
PathNext(b);
|
||||
PathStroke(clr, t);
|
||||
}
|
||||
|
||||
// TODO: Don't render OOS
|
||||
void DrawList::AddPolyLine(const std::vector<vec2>& points, const UI7Color& clr,
|
||||
UI7DrawFlags flags, int thickness) {
|
||||
if (points.size() < 2) {
|
||||
return;
|
||||
}
|
||||
auto cmd = LI::Command::New();
|
||||
ren->SetupCommand(cmd);
|
||||
cmd->Layer(layer);
|
||||
if (!clip_rects.empty()) {
|
||||
cmd->SetScissorMode(LI::ScissorMode_Normal);
|
||||
cmd->ScissorRect(clip_rects.top());
|
||||
}
|
||||
bool close = (flags & UI7DrawFlags_Close);
|
||||
int num_points = close ? (int)points.size() : (int)points.size() - 1;
|
||||
if (flags & UI7DrawFlags_AALines) {
|
||||
// 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 = ren->CreateLine(points[i], points[j], thickness);
|
||||
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));
|
||||
}
|
||||
|
||||
// TODO: Don't render OOS (Probably make it with a define as it
|
||||
// would probably be faster to render out of screen than checking if
|
||||
// it could be skipped)
|
||||
void DrawList::AddConvexPolyFilled(const std::vector<vec2>& points,
|
||||
const UI7Color& clr) {
|
||||
if (points.size() < 3) {
|
||||
return; // Need at least three points
|
||||
}
|
||||
auto cmd = LI::Command::New();
|
||||
ren->SetupCommand(cmd);
|
||||
cmd->Layer(layer);
|
||||
if (!clip_rects.empty()) {
|
||||
cmd->SetScissorMode(LI::ScissorMode_Normal);
|
||||
cmd->ScissorRect(clip_rects.top());
|
||||
}
|
||||
for (int i = 2; i < (int)points.size(); i++) {
|
||||
cmd->PushIndex(0).PushIndex(i).PushIndex(i - 1);
|
||||
}
|
||||
for (int i = 0; i < (int)points.size(); i++) {
|
||||
cmd->PushVertex(LI::Vertex(points[i], vec2(0, 0), clr));
|
||||
}
|
||||
commands.push_back(std::make_pair(
|
||||
ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd));
|
||||
}
|
||||
|
||||
void DrawList::Clear() { commands.clear(); }
|
||||
|
||||
void DrawList::Process() {
|
||||
num_vertices = 0;
|
||||
num_indices = 0;
|
||||
for (auto command : commands) {
|
||||
ren->OnScreen(ren->GetScreen(command.first));
|
||||
command.second->Layer(command.second->Layer() + base);
|
||||
ren->PushCommand(command.second);
|
||||
num_vertices += command.second->VertexList().size();
|
||||
num_indices += command.second->IndexList().size();
|
||||
}
|
||||
commands.clear();
|
||||
layer = 0;
|
||||
std::vector<u32> rem;
|
||||
for (auto it : static_text) {
|
||||
if (!it.second->Used()) {
|
||||
rem.push_back(it.first);
|
||||
}
|
||||
it.second->SetUnused();
|
||||
}
|
||||
for (auto& it : rem) {
|
||||
static_text.erase(it);
|
||||
}
|
||||
while (!clip_rects.empty()) {
|
||||
clip_rects.pop();
|
||||
}
|
||||
}
|
||||
} // namespace UI7
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/core/core.hpp>
|
||||
#include <pd/ui7/drawlist.hpp>
|
||||
#include <pd/ui7/io.hpp>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
PD_UI7_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);
|
||||
PathNext(vec2(c.x + std::cos(a) * radius, c.y + std::sin(a) * radius));
|
||||
}
|
||||
}
|
||||
|
||||
PD_UI7_API void DrawList::PathRect(fvec2 a, fvec2 b, float rounding,
|
||||
UI7DrawFlags flags) {
|
||||
if (rounding == 0.f) {
|
||||
PathNext(a);
|
||||
PathNext(vec2(b.x, a.y));
|
||||
PathNext(b);
|
||||
PathNext(vec2(a.x, b.y));
|
||||
} else {
|
||||
PathArcToN(vec2(a.x + rounding, a.y + rounding), rounding, 4 * 6, 4 * 9,
|
||||
21);
|
||||
PathArcToN(vec2(b.x - rounding, a.y + rounding), rounding, 4 * 9, 4 * 12,
|
||||
21);
|
||||
PathArcToN(vec2(b.x - rounding, b.y - rounding), rounding, 4 * 0, 4 * 3,
|
||||
21);
|
||||
PathArcToN(vec2(a.x + rounding, b.y - rounding), rounding, 4 * 3, 4 * 6,
|
||||
21);
|
||||
}
|
||||
}
|
||||
|
||||
PD_UI7_API void DrawList::AddRect(const fvec2& pos, const fvec2& size,
|
||||
const UI7Color& clr, int thickness) {
|
||||
PathRect(pos, pos + size);
|
||||
PathStroke(clr, thickness, UI7DrawFlags_Close);
|
||||
}
|
||||
PD_UI7_API void DrawList::AddRectangle(fvec2 pos, fvec2 szs,
|
||||
const UI7Color& clr) {
|
||||
PathRect(pos, pos + szs);
|
||||
PathFill(clr);
|
||||
}
|
||||
|
||||
PD_UI7_API void DrawList::AddTriangle(const fvec2& a, const fvec2& b,
|
||||
const fvec2& c, const UI7Color& clr,
|
||||
int thickness) {
|
||||
PathNext(a);
|
||||
PathNext(b);
|
||||
PathNext(c);
|
||||
PathStroke(clr, thickness, UI7DrawFlags_Close);
|
||||
}
|
||||
|
||||
PD_UI7_API void DrawList::AddTriangleFilled(const fvec2& a, const fvec2& b,
|
||||
const fvec2& c,
|
||||
const UI7Color& clr) {
|
||||
PathNext(a);
|
||||
PathNext(b);
|
||||
PathNext(c);
|
||||
PathFill(clr);
|
||||
}
|
||||
|
||||
PD_UI7_API void DrawList::AddCircle(const fvec2& pos, float rad, UI7Color col,
|
||||
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(pos, rad, 0.f, am, num_segments);
|
||||
}
|
||||
PathStroke(col, thickness, UI7DrawFlags_Close);
|
||||
}
|
||||
|
||||
PD_UI7_API void DrawList::AddCircleFilled(const fvec2& pos, float rad,
|
||||
UI7Color col, int num_segments) {
|
||||
if (num_segments <= 0) {
|
||||
// Auto Segment
|
||||
} else {
|
||||
float am = (M_PI * 2.0f) * ((float)num_segments) / (float)num_segments;
|
||||
PathArcToN(pos, rad, 0.f, am, num_segments);
|
||||
}
|
||||
PathFill(col);
|
||||
}
|
||||
|
||||
PD_UI7_API void DrawList::AddText(fvec2 pos, const std::string& text,
|
||||
const UI7Color& clr, u32 flags, fvec2 box) {
|
||||
Vec<LI::Command::Ref> cmds;
|
||||
pIO->Font->CmdTextEx(cmds, pos, clr, pIO->FontScale, text, flags, box);
|
||||
for (size_t i = 0; i < cmds.Size(); i++) {
|
||||
ClipCmd(cmds[i]);
|
||||
cmds[i]->Layer = Layer;
|
||||
cmds[i]->Index = Commands.Size();
|
||||
Commands.Add(cmds[i]);
|
||||
}
|
||||
// if (!IO->Ren->Font()) {
|
||||
// return;
|
||||
// }
|
||||
// u32 id = Strings::FastHash(text);
|
||||
// LI::StaticText::Ref e;
|
||||
// auto f = static_text.find(id);
|
||||
// if (static_text.find(id) == static_text.end()) {
|
||||
// e = LI::StaticText::New();
|
||||
// static_text[id] = e;
|
||||
// } else {
|
||||
// e = f->second;
|
||||
// }
|
||||
// if (!e->IsSetup() || e->Font() != IO->Ren->Font()) {
|
||||
// int l = IO->Ren->Layer();
|
||||
// IO->Ren->Layer(layer);
|
||||
// e->Setup(ren.get(), pos, clr, text, flags, box);
|
||||
// e->Font(IO->Ren->Font());
|
||||
// IO->Ren->Layer(l);
|
||||
// }
|
||||
// e->SetPos(pos);
|
||||
// e->SetColor(clr);
|
||||
// e->SetLayer(layer);
|
||||
// if (!clip_rects.empty()) {
|
||||
// e->SetScissorMode(LI::ScissorMode_Normal);
|
||||
// e->ScissorRect(clip_rects.top());
|
||||
// }
|
||||
// for (auto it : e->GetRawObject()->List()) {
|
||||
// this->commands.push_back(std::make_pair(
|
||||
// IO->Ren->CurrentScreen()->ScreenType() == Screen::Bottom, it));
|
||||
// }
|
||||
// e->GetRawObject()->ReCopy();
|
||||
}
|
||||
|
||||
PD_UI7_API void DrawList::AddImage(fvec2 pos, LI::Texture::Ref img, fvec2 size,
|
||||
LI::Rect uv) {
|
||||
size = size == 0.f ? fvec2(img->GetSize().x, img->GetSize().y) : size;
|
||||
uv = (uv.Top() == 0.0f && uv.Bot() == 0.0f) ? img->GetUV() : uv;
|
||||
LI::Command::Ref cmd = LI::Command::New();
|
||||
cmd->Layer = Layer;
|
||||
cmd->Index = Commands.Size();
|
||||
cmd->Tex = img;
|
||||
auto r = LI::Renderer::PrimRect(pos, size);
|
||||
LI::Renderer::CmdQuad(cmd, r, uv, 0xffffffff);
|
||||
// auto rect = IO->Ren->CreateRect(pos, size, 0.f);
|
||||
// auto cmd = LI::Command::New();
|
||||
// IO->Ren->UseTex(img);
|
||||
// IO->Ren->SetupCommand(cmd);
|
||||
// cmd->Layer(layer);
|
||||
// if (!clip_rects.empty()) {
|
||||
// cmd->SetScissorMode(LI::ScissorMode_Normal);
|
||||
// cmd->ScissorRect(clip_rects.top());
|
||||
// }
|
||||
// IO->Ren->QuadCommand(cmd, rect, uv, 0xffffffff);
|
||||
// commands.push_back(std::make_pair(
|
||||
// IO->Ren->CurrentScreen()->ScreenType() == Screen::Bottom, cmd));
|
||||
}
|
||||
|
||||
PD_UI7_API void DrawList::AddLine(const fvec2& a, const fvec2& b,
|
||||
const UI7Color& clr, int t) {
|
||||
PathNext(a);
|
||||
PathNext(b);
|
||||
PathStroke(clr, t);
|
||||
}
|
||||
|
||||
// TODO: Don't render OOS
|
||||
PD_UI7_API void DrawList::AddPolyLine(const Vec<fvec2>& points,
|
||||
const UI7Color& clr, UI7DrawFlags flags,
|
||||
int thickness) {
|
||||
if (points.Size() < 2) {
|
||||
return;
|
||||
}
|
||||
auto cmd = LI::Command::New();
|
||||
cmd->Index = Commands.Size();
|
||||
cmd->Layer = Layer;
|
||||
cmd->Tex = pIO->Ren->WhitePixel;
|
||||
ClipCmd(cmd);
|
||||
bool close = (flags & UI7DrawFlags_Close);
|
||||
int num_points = close ? (int)points.Size() : (int)points.Size() - 1;
|
||||
if (flags & UI7DrawFlags_AALines) {
|
||||
// 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 = LI::Renderer::PrimLine(points[i], points[j], thickness);
|
||||
LI::Renderer::CmdQuad(cmd, line, vec4(0.f, 1.f, 1.f, 0.f), clr);
|
||||
}
|
||||
}
|
||||
Commands.Add(cmd);
|
||||
}
|
||||
|
||||
PD_UI7_API void DrawList::ClipCmd(LI::Command::Ref cmd) {
|
||||
if (!pClipRects.IsEmpty()) {
|
||||
cmd->ScissorEnabled = true;
|
||||
fvec4 sr = pClipRects.Top();
|
||||
cmd->ScissorRect = ivec4(sr.x, sr.y, sr.z, sr.w);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Don't render OOS (Probably make it with a define as it
|
||||
// would probably be faster to render out of screen than checking if
|
||||
// it could be skipped)
|
||||
PD_UI7_API void DrawList::AddConvexPolyFilled(const Vec<fvec2>& points,
|
||||
const UI7Color& clr) {
|
||||
if (points.Size() < 3) {
|
||||
return; // Need at least three points
|
||||
}
|
||||
auto cmd = LI::Command::New();
|
||||
cmd->Index = Commands.Size();
|
||||
cmd->Layer = Layer;
|
||||
auto tex = CurrentTex;
|
||||
if (!tex) {
|
||||
tex = pIO->Ren->WhitePixel;
|
||||
}
|
||||
cmd->Tex = tex;
|
||||
ClipCmd(cmd);
|
||||
for (int i = 2; i < (int)points.Size(); i++) {
|
||||
cmd->AppendIndex(0).AppendIndex(i).AppendIndex(i - 1);
|
||||
}
|
||||
for (int i = 0; i < (int)points.Size(); i++) {
|
||||
cmd->AppendVertex(LI::Vertex(points[i], fvec2(0, 0), clr));
|
||||
}
|
||||
Commands.Add(cmd);
|
||||
}
|
||||
|
||||
PD_UI7_API void DrawList::Clear() { Commands.Clear(); }
|
||||
|
||||
/** Process [Render] the Drawlist */
|
||||
PD_UI7_API void DrawList::Process(LI::DrawList::Ref d) {
|
||||
std::sort(Commands.Begin(), Commands.End(),
|
||||
[](LI::Command::Ref a, LI::Command::Ref b) {
|
||||
/** Advanced (for saving Drawcalls)
|
||||
* - Probably could handle this by creating diffrent layers
|
||||
* for texts and solid objectives
|
||||
* if(a->Tex == b->Tex) { return a->Layer < b->Layer; }
|
||||
* return a->Tex < b->Tex;
|
||||
*/
|
||||
/** Simple */
|
||||
return a->Layer < b->Layer;
|
||||
});
|
||||
NumVertices = 0;
|
||||
NumIndices = 0;
|
||||
for (auto command = Commands.Begin(); command != Commands.End(); command++) {
|
||||
// IO->Ren->OnScreen(IO->Ren->GetScreen(command.first));
|
||||
(*command)->Layer = (*command)->Layer + Base;
|
||||
d->AddCommand(*command);
|
||||
NumVertices += (*command)->VertexBuffer.Size();
|
||||
NumIndices += (*command)->IndexBuffer.Size();
|
||||
}
|
||||
Commands.Clear();
|
||||
Layer = 0;
|
||||
std::vector<u32> rem;
|
||||
// for (auto it : static_text) {
|
||||
// if (!it.second->Used()) {
|
||||
// rem.push_back(it.first);
|
||||
// }
|
||||
// it.second->SetUnused();
|
||||
// }
|
||||
// for (auto& it : rem) {
|
||||
// static_text.erase(it);
|
||||
// }
|
||||
pClipRects.Clear();
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -1,42 +1,40 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/core/timetrace.hpp>
|
||||
#include <pd/ui7/io.hpp>
|
||||
|
||||
namespace PD {
|
||||
void UI7::IO::Update() {
|
||||
u64 current = Sys::GetNanoTime();
|
||||
Delta = static_cast<float>(current - LastTime) / 1000000.f;
|
||||
LastTime = current;
|
||||
DeltaStats->Add(Delta * 1000);
|
||||
Time->Update();
|
||||
DragTime->Update();
|
||||
DragReleased = false;
|
||||
DragReleasedAW = false;
|
||||
DragDoubleRelease = false;
|
||||
Framerate = 1000.f / Delta;
|
||||
DrawListRegestry.clear();
|
||||
RegisterDrawList("CtxBackList", Back);
|
||||
}
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/core/core.hpp>
|
||||
#include <pd/ui7/io.hpp>
|
||||
|
||||
namespace PD {
|
||||
PD_UI7_API void UI7::IO::Update() {
|
||||
u64 current = Sys::GetNanoTime();
|
||||
Delta = static_cast<float>(current - LastTime) / 1000000.f;
|
||||
LastTime = current;
|
||||
DeltaStats->Add(Delta * 1000);
|
||||
Time->Update();
|
||||
InputHandler->Update();
|
||||
Framerate = 1000.f / Delta;
|
||||
DrawListRegestry.Clear();
|
||||
DrawListRegestry.PushFront(Pair<UI7::ID, DrawList::Ref>("CtxBackList", Back));
|
||||
// RegisterDrawList("CtxBackList", Back);
|
||||
}
|
||||
} // namespace PD
|
@ -1,118 +1,140 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/layout.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void Layout::CursorInit() { Cursor = WorkRect.xy(); }
|
||||
|
||||
void Layout::SameLine() {
|
||||
BackupCursor = LastObjSize;
|
||||
Cursor = SamelineCursor;
|
||||
}
|
||||
|
||||
void Layout::CursorMove(const vec2& size) {
|
||||
LastObjSize = size;
|
||||
SamelineCursor = Cursor + vec2(size[0] + IO->ItemSpace[0], 0);
|
||||
if (BeforeSameLine[1]) {
|
||||
Cursor = vec2(IO->MenuPadding[0],
|
||||
Cursor[1] + BeforeSameLine[1] + IO->ItemSpace[1]);
|
||||
BeforeSameLine = 0.f;
|
||||
} else {
|
||||
Cursor = vec2(IO->MenuPadding[0] + InitialCursorOffset[0],
|
||||
Cursor[1] + size[1] + IO->ItemSpace[1]);
|
||||
}
|
||||
// Logical Issue here as x should use a max check
|
||||
MaxPosition = vec2(std::max(MaxPosition[0], SamelineCursor[0]), Cursor[1]);
|
||||
}
|
||||
|
||||
bool Layout::ObjectWorkPos(vec2& movpos) {
|
||||
if (Scrolling[1]) {
|
||||
movpos[1] -= ScrollOffset[1];
|
||||
if (!IO->Ren->InBox(movpos, LastObjSize,
|
||||
vec4(WorkRect.xy(), WorkRect.xy() + WorkRect.zw()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Layout::AddObject(Container::Ref obj) {
|
||||
obj->Init(IO, DrawList);
|
||||
obj->SetPos(AlignPosition(Cursor, obj->GetSize(), WorkRect, GetAlignment()));
|
||||
obj->Update();
|
||||
CursorMove(obj->GetSize());
|
||||
obj->HandleScrolling(ScrollOffset, WorkRect);
|
||||
Objects.push_back(obj);
|
||||
}
|
||||
|
||||
Container::Ref Layout::FindObject(u32 id) {
|
||||
for (auto& it : IDObjects) {
|
||||
if (it->GetID() == id) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vec2 Layout::AlignPosition(vec2 pos, vec2 size, vec4 area, UI7Align alignment) {
|
||||
vec2 p = pos;
|
||||
if (alignment & UI7Align_Center) {
|
||||
p[0] = (area[0] + area[2]) * 0.5 - (pos[0] - area[0] + size[0] * 0.5);
|
||||
} else if (alignment & UI7Align_Right) {
|
||||
}
|
||||
if (alignment & UI7Align_Mid) {
|
||||
p[1] = (area[1] + area[3]) * 0.5 - (pos[1] - area[1] + size[1] * 0.5);
|
||||
} else if (alignment & UI7Align_Bottom) {
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void Layout::Update() {
|
||||
for (auto& it : Objects) {
|
||||
if (it->GetID() != 0 && !FindObject(it->GetID())) {
|
||||
IDObjects.push_back(it);
|
||||
}
|
||||
if (!it->Skippable()) {
|
||||
it->SetPos(it->GetPos() + Pos);
|
||||
it->HandleInput();
|
||||
it->UnlockInput();
|
||||
it->Draw();
|
||||
}
|
||||
}
|
||||
std::vector<size_t> tbr;
|
||||
for (size_t i = 0; i < IDObjects.size(); i++) {
|
||||
if (IDObjects[i]->Removable()) {
|
||||
tbr.push_back(i);
|
||||
}
|
||||
}
|
||||
for (auto& it : tbr) {
|
||||
IDObjects.erase(IDObjects.begin() + it);
|
||||
}
|
||||
Objects.clear();
|
||||
WorkRect = vec4(WorkRect.xy(), Size - IO->MenuPadding);
|
||||
CursorInit();
|
||||
}
|
||||
} // namespace UI7
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/ui7/layout.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
PD_UI7_API void Layout::CursorInit() { Cursor = fvec2(WorkRect.x, WorkRect.y); }
|
||||
|
||||
PD_UI7_API void Layout::SameLine() {
|
||||
BackupCursor = LastObjSize;
|
||||
Cursor = SamelineCursor;
|
||||
}
|
||||
|
||||
PD_UI7_API void Layout::CursorMove(const fvec2& size) {
|
||||
LastObjSize = size;
|
||||
SamelineCursor = Cursor + fvec2(size.x + IO->ItemSpace.x, 0);
|
||||
if (BeforeSameLine.y) {
|
||||
Cursor =
|
||||
fvec2(IO->MenuPadding.x, Cursor.y + BeforeSameLine.y + IO->ItemSpace.y);
|
||||
BeforeSameLine = 0.f;
|
||||
} else {
|
||||
Cursor = fvec2(IO->MenuPadding.x + InitialCursorOffset.x,
|
||||
Cursor.y + size.y + IO->ItemSpace.y);
|
||||
}
|
||||
// Logical Issue here as x should use a max check
|
||||
MaxPosition = fvec2(std::max(MaxPosition.x, SamelineCursor.x), Cursor.y);
|
||||
}
|
||||
|
||||
PD_UI7_API bool Layout::ObjectWorkPos(fvec2& movpos) {
|
||||
if (Scrolling[1]) {
|
||||
movpos.y -= ScrollOffset.y;
|
||||
if (!IO->Ren->InBox(movpos, LastObjSize,
|
||||
fvec4(WorkRect.x, WorkRect.y, WorkRect.x + WorkRect.z,
|
||||
WorkRect.y + WorkRect.w))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
PD_UI7_API void Layout::AddObject(Container::Ref obj) {
|
||||
obj->Init(IO, DrawList);
|
||||
obj->SetPos(AlignPosition(Cursor, obj->GetSize(), WorkRect, GetAlignment()));
|
||||
obj->Update();
|
||||
CursorMove(obj->GetSize());
|
||||
obj->HandleScrolling(ScrollOffset, WorkRect);
|
||||
Objects.PushBack(obj);
|
||||
}
|
||||
|
||||
PD_UI7_API void Layout::AddObjectEx(Container::Ref obj, u32 flags) {
|
||||
obj->Init(IO, DrawList);
|
||||
if (!(flags & 1)) {
|
||||
obj->SetPos(
|
||||
AlignPosition(Cursor, obj->GetSize(), WorkRect, GetAlignment()));
|
||||
}
|
||||
obj->Update();
|
||||
if (!(flags & 1)) {
|
||||
CursorMove(obj->GetSize());
|
||||
}
|
||||
if (!(flags & 2)) {
|
||||
obj->HandleScrolling(ScrollOffset, WorkRect);
|
||||
}
|
||||
if (!(flags & 4)) {
|
||||
Objects.PushFront(obj);
|
||||
} else {
|
||||
Objects.PushBack(obj);
|
||||
}
|
||||
}
|
||||
|
||||
PD_UI7_API Container::Ref Layout::FindObject(u32 id) {
|
||||
for (auto& it : IDObjects) {
|
||||
if (it->GetID() == id) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PD_UI7_API fvec2 Layout::AlignPosition(fvec2 pos, fvec2 size, fvec4 area,
|
||||
UI7Align alignment) {
|
||||
vec2 p = pos;
|
||||
if (alignment & UI7Align_Center) {
|
||||
p.x = (area.x + area.z) * 0.5 - (pos.x - area.x + size.x * 0.5);
|
||||
} else if (alignment & UI7Align_Right) {
|
||||
}
|
||||
if (alignment & UI7Align_Mid) {
|
||||
p.y = (area.y + area.w) * 0.5 - (pos.y - area.y + size.y * 0.5);
|
||||
} else if (alignment & UI7Align_Bottom) {
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
PD_UI7_API void Layout::Update() {
|
||||
for (auto& it : Objects) {
|
||||
if (it->GetID() != 0 && !FindObject(it->GetID())) {
|
||||
IDObjects.push_back(it);
|
||||
}
|
||||
if (!it->Skippable()) {
|
||||
it->SetPos(it->GetPos() + Pos);
|
||||
it->HandleInput();
|
||||
it->UnlockInput();
|
||||
it->Draw();
|
||||
}
|
||||
}
|
||||
std::vector<size_t> tbr;
|
||||
for (size_t i = 0; i < IDObjects.size(); i++) {
|
||||
if (IDObjects[i]->Removable()) {
|
||||
tbr.push_back(i);
|
||||
}
|
||||
}
|
||||
for (auto& it : tbr) {
|
||||
IDObjects.erase(IDObjects.begin() + it);
|
||||
}
|
||||
Objects.Clear();
|
||||
WorkRect = fvec4(fvec2(WorkRect.x, WorkRect.y), Size - IO->MenuPadding);
|
||||
CursorInit();
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
1249
source/ui7/menu.cpp
1249
source/ui7/menu.cpp
File diff suppressed because it is too large
Load Diff
269
source/ui7/remenu.cpp
Normal file
269
source/ui7/remenu.cpp
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
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/ui7/containers.hpp>
|
||||
#include <pd/ui7/remenu.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
PD_UI7_API void UI7::ReMenu::Label(const std::string& label) {
|
||||
// Layout API
|
||||
auto r = PD::New<UI7::Label>(label, pIO);
|
||||
pLayout->AddObject(r);
|
||||
}
|
||||
|
||||
PD_UI7_API bool UI7::ReMenu::Button(const std::string& label) {
|
||||
bool ret = false;
|
||||
u32 id = Strings::FastHash("btn" + label +
|
||||
std::to_string(pLayout->Objects.Size()));
|
||||
Container::Ref r = pLayout->FindObject(id);
|
||||
if (!r) {
|
||||
r = PD::New<UI7::Button>(label, pIO);
|
||||
r->SetID(id);
|
||||
}
|
||||
pLayout->AddObject(r);
|
||||
if (!r->Skippable()) {
|
||||
ret = std::static_pointer_cast<UI7::Button>(r)->IsPressed();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*PD_UI7_API void UI7::ReMenu::DragFloat(const std::string& label, float* data,
|
||||
size_t num_elms) {
|
||||
u32 id = Strings::FastHash("dfl" + label + std::to_string(count_btn++));
|
||||
Container::Ref r = Layout->FindObject(id);
|
||||
if (!r) {
|
||||
r = PD::New<UI7::DragData<float>>(label, data, num_elms, io);
|
||||
r->SetID(id);
|
||||
}
|
||||
Layout->AddObject(r);
|
||||
}*/
|
||||
|
||||
PD_UI7_API void UI7::ReMenu::Checkbox(const std::string& label, bool& v) {
|
||||
u32 id = Strings::FastHash("cbx" + label +
|
||||
std::to_string(pLayout->Objects.Size()));
|
||||
Container::Ref r = pLayout->FindObject(id);
|
||||
if (!r) {
|
||||
r = PD::New<UI7::Checkbox>(label, v, pIO);
|
||||
r->SetID(id);
|
||||
}
|
||||
pLayout->AddObject(r);
|
||||
}
|
||||
|
||||
PD_UI7_API void UI7::ReMenu::Image(LI::Texture::Ref img, fvec2 size,
|
||||
LI::Rect uv) {
|
||||
Container::Ref r = PD::New<UI7::Image>(img, size, uv);
|
||||
pLayout->AddObject(r);
|
||||
}
|
||||
|
||||
PD_UI7_API void ReMenu::Separator() {
|
||||
// Dynamic Objects are very simple...
|
||||
Container::Ref r = PD::New<UI7::DynObj>(
|
||||
[=, this](UI7::IO::Ref io, UI7::DrawList::Ref l, UI7::Container* self) {
|
||||
l->AddRect(self->FinalPos(), self->GetSize(),
|
||||
pIO->Theme->Get(UI7Color_TextDead));
|
||||
});
|
||||
// Set size before pushing (cause Cursor Move will require it)
|
||||
r->SetSize(fvec2(pLayout->Size.x - 10, 1));
|
||||
pLayout->AddObject(r);
|
||||
}
|
||||
|
||||
PD_UI7_API void ReMenu::SeparatorText(const std::string& label) {
|
||||
// Also note to use [=] instead of [&] to not undefined access label
|
||||
Container::Ref r = PD::New<UI7::DynObj>(
|
||||
[=, this](UI7::IO::Ref io, UI7::DrawList::Ref l, UI7::Container* self) {
|
||||
fvec2 size = self->GetSize();
|
||||
fvec2 tdim = io->Font->GetTextBounds(label, io->FontScale);
|
||||
fvec2 pos = self->FinalPos();
|
||||
auto align = pLayout->GetAlignment();
|
||||
vec2 rpos = pLayout->AlignPosition(
|
||||
pos, tdim, fvec4(pLayout->Pos, pLayout->Size), align);
|
||||
if (!(align & UI7Align_Left)) {
|
||||
l->AddRectangle(fvec2(rpos.x + io->FramePadding.x, tdim.y * 0.5),
|
||||
fvec2(pos.x - rpos.x - io->MenuPadding.x, 1),
|
||||
io->Theme->Get(UI7Color_TextDead));
|
||||
}
|
||||
if (!(align & UI7Align_Right)) {
|
||||
l->AddRectangle(
|
||||
pos + fvec2(tdim.x + io->FramePadding.x, tdim.y * 0.5),
|
||||
fvec2(size.x - tdim.x - io->MenuPadding.x, 1),
|
||||
io->Theme->Get(UI7Color_TextDead));
|
||||
}
|
||||
l->AddText(rpos, label, io->Theme->Get(UI7Color_Text), 0,
|
||||
fvec2(pLayout->Size.x, self->GetSize().y));
|
||||
});
|
||||
// Set size before pushing (cause Cursor Move will require it)
|
||||
r->SetSize(
|
||||
fvec2(pLayout->Size.x - 10, pIO->Font->PixelHeight * pIO->FontScale));
|
||||
pLayout->AddObject(r);
|
||||
}
|
||||
PD_UI7_API void ReMenu::HandleFocus() {
|
||||
// Check if menu can be focused for Selective Menu Input API
|
||||
vec4 newarea = fvec4(pLayout->Pos, pLayout->Size);
|
||||
if (!pIsOpen) {
|
||||
newarea = fvec4(pLayout->Pos, fvec2(pLayout->Size.x, TitleBarHeight));
|
||||
}
|
||||
if (pIO->Inp->IsDown(pIO->Inp->Touch) &&
|
||||
pIO->Ren->InBox(pIO->Inp->TouchPos(), newarea) &&
|
||||
!pIO->Ren->InBox(pIO->Inp->TouchPos(),
|
||||
pIO->InputHandler->FocusedMenuRect)) {
|
||||
pIO->InputHandler->FocusedMenu = pID;
|
||||
}
|
||||
if (pIO->InputHandler->FocusedMenu == pID) {
|
||||
pIO->InputHandler->FocusedMenuRect = newarea;
|
||||
}
|
||||
}
|
||||
PD_UI7_API void ReMenu::HandleScrolling() {}
|
||||
PD_UI7_API void ReMenu::HandleTitlebarActions() {
|
||||
// Collapse
|
||||
if (!(Flags & UI7MenuFlags_NoCollapse)) {
|
||||
vec2 cpos = pLayout->Pos + pIO->FramePadding;
|
||||
// clr_collapse_tri = UI7Color_FrameBackground;
|
||||
if (pIO->InputHandler->DragObject(UI7::ID(pID.GetName() + "clbse"),
|
||||
fvec4(cpos, fvec2(18, TitleBarHeight)))) {
|
||||
if (pIO->InputHandler->DragReleased) {
|
||||
pIsOpen = !pIsOpen;
|
||||
}
|
||||
// clr_collapse_tri = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
}
|
||||
// Close Logic
|
||||
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown != nullptr) {
|
||||
vec2 cpos =
|
||||
fvec2(pLayout->Pos.x + pLayout->Size.x - 12 - pIO->FramePadding.x,
|
||||
pLayout->Pos.y + pIO->FramePadding.y);
|
||||
|
||||
// clr_close_btn = UI7Color_FrameBackground;
|
||||
if (pIO->InputHandler->DragObject(UI7::ID(pID.GetName() + "clse"),
|
||||
fvec4(cpos, fvec2(12)))) {
|
||||
if (pIO->InputHandler->DragReleased) {
|
||||
*pIsShown = !(*pIsShown);
|
||||
}
|
||||
// clr_close_btn = UI7Color_FrameBackgroundHovered;
|
||||
}
|
||||
}
|
||||
// Menu Movement
|
||||
if (!(Flags & UI7MenuFlags_NoMove)) {
|
||||
if (pIO->InputHandler->DragObject(
|
||||
pID.GetName() + "tmv",
|
||||
fvec4(pLayout->Pos, fvec2(pLayout->Size.x, TitleBarHeight)))) {
|
||||
if (pIO->InputHandler->DragDoubleRelease) {
|
||||
pIsOpen = !pIsOpen;
|
||||
}
|
||||
pLayout->Pos = pLayout->Pos + (pIO->InputHandler->DragPosition -
|
||||
pIO->InputHandler->DragLastPosition);
|
||||
// Have no ViewPort Yet :(
|
||||
// pLayout->Pos = std::clamp(pLayout->Pos, fvec2(10), fvec2(1270, 710));
|
||||
}
|
||||
}
|
||||
}
|
||||
PD_UI7_API void ReMenu::DrawBaseLayout() {
|
||||
if (pIsOpen) {
|
||||
Container::Ref r = PD::New<UI7::DynObj>(
|
||||
[](UI7::IO::Ref io, UI7::DrawList::Ref l, UI7::Container* self) {
|
||||
l->Layer = 0;
|
||||
l->AddRectangle(self->FinalPos(), self->GetSize(),
|
||||
io->Theme->Get(UI7Color_Background));
|
||||
});
|
||||
// Set size before pushing (cause Cursor Move will require it)
|
||||
r->SetSize(
|
||||
fvec2(pLayout->GetSize().x, pLayout->GetSize().y - TitleBarHeight));
|
||||
r->SetPos(fvec2(0, TitleBarHeight));
|
||||
pLayout->AddObjectEx(r, UI7LytAdd_NoCursorUpdate |
|
||||
UI7LytAdd_NoScrollHandle | UI7LytAdd_Front);
|
||||
}
|
||||
if (!(Flags & UI7MenuFlags_NoTitlebar)) {
|
||||
Container::Ref r = PD::New<UI7::DynObj>(
|
||||
[=, this](UI7::IO::Ref io, UI7::DrawList::Ref l, UI7::Container* self) {
|
||||
l->Layer = 20;
|
||||
/** Header Bar */
|
||||
l->AddRectangle(self->FinalPos(), self->GetSize(),
|
||||
io->Theme->Get(UI7Color_Header));
|
||||
l->Layer = 21;
|
||||
/** Inline if statement to shift the Text if collapse sym is shown */
|
||||
/** What the hell is this code btw (didn't found a better way) */
|
||||
l->AddText(self->FinalPos() +
|
||||
fvec2(Flags & UI7MenuFlags_NoClose
|
||||
? 0
|
||||
: (TitleBarHeight - pIO->FramePadding.y * 2 +
|
||||
(io->FramePadding.x * 2)),
|
||||
0),
|
||||
pID.GetName(), io->Theme->Get(UI7Color_Text));
|
||||
});
|
||||
r->SetSize(fvec2(pLayout->GetSize().x, TitleBarHeight));
|
||||
r->SetPos(0);
|
||||
pLayout->AddObjectEx(r,
|
||||
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
|
||||
|
||||
/** Collapse Sym */
|
||||
if (!(Flags & UI7MenuFlags_NoCollapse)) {
|
||||
r = PD::New<UI7::DynObj>([=, this](UI7::IO::Ref io, UI7::DrawList::Ref l,
|
||||
UI7::Container* self) {
|
||||
/** This sym actually requires layer 21 (i dont know why) */
|
||||
l->Layer = 21;
|
||||
/**
|
||||
* Symbol (Position Swapping set by pIsOpen ? openpos : closepos;)
|
||||
*/
|
||||
l->AddTriangleFilled(
|
||||
self->FinalPos(),
|
||||
self->FinalPos() +
|
||||
fvec2(self->GetSize().x, pIsOpen ? 0 : self->GetSize().y * 0.5),
|
||||
self->FinalPos() +
|
||||
fvec2(pIsOpen ? self->GetSize().x * 0.5 : 0, self->GetSize().y),
|
||||
io->Theme->Get(UI7Color_FrameBackground));
|
||||
});
|
||||
r->SetSize(TitleBarHeight - pIO->FramePadding.y * 2);
|
||||
r->SetPos(pIO->FramePadding);
|
||||
pLayout->AddObjectEx(r,
|
||||
UI7LytAdd_NoCursorUpdate | UI7LytAdd_NoScrollHandle);
|
||||
}
|
||||
/** Close Sym (only shown if pIsShown is not nullptr) */
|
||||
if (!(Flags & UI7MenuFlags_NoClose) && pIsShown) {
|
||||
fvec2 size = TitleBarHeight - pIO->FramePadding.y * 2; // Fixed quad size
|
||||
// Need to clamp this way as the math lib lacks a less and greater
|
||||
// operator in vec2 (don't checked if it would make sense yet)
|
||||
size.x = std::clamp(size.x, 5.f, std::numeric_limits<float>::max());
|
||||
size.y = std::clamp(size.y, 5.f, std::numeric_limits<float>::max());
|
||||
// Probably should fix the minsize to be locked on y
|
||||
fvec2 cpos =
|
||||
fvec2(pLayout->Pos.x + pLayout->Size.x - size.x - pIO->FramePadding.x,
|
||||
pLayout->Pos.y + pIO->FramePadding.y);
|
||||
pLayout->DrawList->AddLine(cpos, cpos + size,
|
||||
pIO->Theme->Get(UI7Color_FrameBackground), 2);
|
||||
pLayout->DrawList->AddLine(cpos + fvec2(0, size.y),
|
||||
cpos + fvec2(size.x, 0),
|
||||
pIO->Theme->Get(UI7Color_FrameBackground), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
PD_UI7_API void ReMenu::Update() {
|
||||
HandleFocus();
|
||||
if (!(Flags & UI7MenuFlags_NoTitlebar)) {
|
||||
HandleTitlebarActions();
|
||||
}
|
||||
DrawBaseLayout();
|
||||
pLayout->Update();
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -1,69 +1,69 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/core/color.hpp>
|
||||
#include <pd/ui7/theme.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
void Theme::Default(Theme& theme) {
|
||||
theme.Set(UI7Color_Text, Color("#FFFFFFFF"));
|
||||
theme.Set(UI7Color_TextDead, Color("#AAAAAAFF"));
|
||||
theme.Set(UI7Color_Background, Color("#222222ff"));
|
||||
theme.Set(UI7Color_Border, Color("#999999ff"));
|
||||
theme.Set(UI7Color_Button, Color("#111111FF"));
|
||||
theme.Set(UI7Color_ButtonDead, Color("#080808FF"));
|
||||
theme.Set(UI7Color_ButtonActive, Color("#2A2A2AFF"));
|
||||
theme.Set(UI7Color_ButtonHovered, Color("#222222FF"));
|
||||
theme.Set(UI7Color_Header, Color("#111111FF"));
|
||||
theme.Set(UI7Color_HeaderDead, Color("#080808FF"));
|
||||
theme.Set(UI7Color_Selector, Color("#222222FF"));
|
||||
theme.Set(UI7Color_Checkmark, Color("#2A2A2AFF"));
|
||||
theme.Set(UI7Color_FrameBackground, Color("#555555FF"));
|
||||
theme.Set(UI7Color_FrameBackgroundHovered, Color("#777777FF"));
|
||||
theme.Set(UI7Color_Progressbar, Color("#00FF00FF"));
|
||||
theme.Set(UI7Color_ListEven, Color("#CCCCCCFF"));
|
||||
theme.Set(UI7Color_ListOdd, Color("#BBBBBBFF"));
|
||||
}
|
||||
|
||||
void Theme::Flashbang(Theme& theme) {
|
||||
theme.Set(UI7Color_Text, Color("#000000FF"));
|
||||
theme.Set(UI7Color_TextDead, Color("#333333FF"));
|
||||
theme.Set(UI7Color_Background, Color("#eeeeeeFF"));
|
||||
theme.Set(UI7Color_Border, Color("#777777ff"));
|
||||
theme.Set(UI7Color_Button, Color("#ccccccFF"));
|
||||
theme.Set(UI7Color_ButtonDead, Color("#bbbbbbFF"));
|
||||
theme.Set(UI7Color_ButtonActive, Color("#ccccccFF"));
|
||||
theme.Set(UI7Color_ButtonHovered, Color("#acacacFF"));
|
||||
theme.Set(UI7Color_Header, Color("#ddddddFF"));
|
||||
theme.Set(UI7Color_HeaderDead, Color("#cdcdcdFF"));
|
||||
theme.Set(UI7Color_Selector, Color("#222222FF"));
|
||||
theme.Set(UI7Color_Checkmark, Color("#ccccccFF"));
|
||||
theme.Set(UI7Color_FrameBackground, Color("#aaaaaaFF"));
|
||||
theme.Set(UI7Color_FrameBackgroundHovered, Color("#909090FF"));
|
||||
theme.Set(UI7Color_Progressbar, Color("#00FF00FF"));
|
||||
theme.Set(UI7Color_ListEven, Color("#CCCCCCFF"));
|
||||
theme.Set(UI7Color_ListOdd, Color("#BBBBBBFF"));
|
||||
}
|
||||
} // namespace UI7
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/core/core.hpp>
|
||||
#include <pd/ui7/theme.hpp>
|
||||
|
||||
namespace PD {
|
||||
namespace UI7 {
|
||||
PD_UI7_API void Theme::Default(Theme& theme) {
|
||||
theme.Set(UI7Color_Text, Color("#FFFFFFFF"));
|
||||
theme.Set(UI7Color_TextDead, Color("#AAAAAAFF"));
|
||||
theme.Set(UI7Color_Background, Color("#222222ff"));
|
||||
theme.Set(UI7Color_Border, Color("#999999ff"));
|
||||
theme.Set(UI7Color_Button, Color("#111111FF"));
|
||||
theme.Set(UI7Color_ButtonDead, Color("#080808FF"));
|
||||
theme.Set(UI7Color_ButtonActive, Color("#2A2A2AFF"));
|
||||
theme.Set(UI7Color_ButtonHovered, Color("#222222FF"));
|
||||
theme.Set(UI7Color_Header, Color("#111111FF"));
|
||||
theme.Set(UI7Color_HeaderDead, Color("#080808FF"));
|
||||
theme.Set(UI7Color_Selector, Color("#222222FF"));
|
||||
theme.Set(UI7Color_Checkmark, Color("#2A2A2AFF"));
|
||||
theme.Set(UI7Color_FrameBackground, Color("#555555FF"));
|
||||
theme.Set(UI7Color_FrameBackgroundHovered, Color("#777777FF"));
|
||||
theme.Set(UI7Color_Progressbar, Color("#00FF00FF"));
|
||||
theme.Set(UI7Color_ListEven, Color("#CCCCCCFF"));
|
||||
theme.Set(UI7Color_ListOdd, Color("#BBBBBBFF"));
|
||||
}
|
||||
|
||||
PD_UI7_API void Theme::Flashbang(Theme& theme) {
|
||||
theme.Set(UI7Color_Text, Color("#000000FF"));
|
||||
theme.Set(UI7Color_TextDead, Color("#333333FF"));
|
||||
theme.Set(UI7Color_Background, Color("#eeeeeeFF"));
|
||||
theme.Set(UI7Color_Border, Color("#777777ff"));
|
||||
theme.Set(UI7Color_Button, Color("#ccccccFF"));
|
||||
theme.Set(UI7Color_ButtonDead, Color("#bbbbbbFF"));
|
||||
theme.Set(UI7Color_ButtonActive, Color("#ccccccFF"));
|
||||
theme.Set(UI7Color_ButtonHovered, Color("#acacacFF"));
|
||||
theme.Set(UI7Color_Header, Color("#ddddddFF"));
|
||||
theme.Set(UI7Color_HeaderDead, Color("#cdcdcdFF"));
|
||||
theme.Set(UI7Color_Selector, Color("#222222FF"));
|
||||
theme.Set(UI7Color_Checkmark, Color("#ccccccFF"));
|
||||
theme.Set(UI7Color_FrameBackground, Color("#aaaaaaFF"));
|
||||
theme.Set(UI7Color_FrameBackgroundHovered, Color("#909090FF"));
|
||||
theme.Set(UI7Color_Progressbar, Color("#00FF00FF"));
|
||||
theme.Set(UI7Color_ListEven, Color("#CCCCCCFF"));
|
||||
theme.Set(UI7Color_ListOdd, Color("#BBBBBBFF"));
|
||||
}
|
||||
} // namespace UI7
|
||||
} // namespace PD
|
@ -1,300 +1,367 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/core/timetrace.hpp>
|
||||
#include <pd/ui7/ui7.hpp>
|
||||
|
||||
// Helpers
|
||||
|
||||
#define UI7DV4(x) \
|
||||
std::format("{}: [{:.2f}, {:.2f}, {:.2f}, {:.2f}]", #x, x[0], x[1], x[2], \
|
||||
x[3])
|
||||
#define UI7DV4N(x) \
|
||||
std::format("[{:.2f}, {:.2f}, {:.2f}, {:.2f}]", x[0], x[1], x[2], x[3])
|
||||
#define UI7DV2(x) std::format("{}: [{:.2f}, {:.2f}]", #x, x[0], x[1])
|
||||
#define UI7DV2N(x) std::format("[{:.2f}, {:.2f}]", x[0], x[1])
|
||||
#define UI7DHX32(x) std::format("{}: {:#08x}", #x, x)
|
||||
#define UI7DTF(x) PD::Strings::FormatNanos(x)
|
||||
|
||||
namespace PD {
|
||||
std::string UI7::GetVersion(bool show_build) {
|
||||
std::stringstream s;
|
||||
s << ((UI7_VERSION >> 24) & 0xFF) << ".";
|
||||
s << ((UI7_VERSION >> 16) & 0xFF) << ".";
|
||||
s << ((UI7_VERSION >> 8) & 0xFF);
|
||||
if (show_build) s << "-" << ((UI7_VERSION) & 0xFF);
|
||||
return s.str();
|
||||
}
|
||||
bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags, bool* show) {
|
||||
Assert(!this->current, "You are already in another Menu!");
|
||||
Assert(std::find(amenus.begin(), amenus.end(), (u32)id) == amenus.end(),
|
||||
"Menu Name Already used or\nContext::Update not called!");
|
||||
if (show != nullptr) {
|
||||
if (!(*show)) {
|
||||
if (io->FocusedMenu == id) {
|
||||
io->FocusedMenu = 0;
|
||||
io->FocusedMenuRect = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
auto menu = this->menus.find(id);
|
||||
if (menu == this->menus.end()) {
|
||||
this->menus[id] = Menu::New(id, io);
|
||||
this->menus[id]->Layout->SetSize(io->Ren->GetViewport().zw());
|
||||
menu = this->menus.find(id);
|
||||
}
|
||||
this->current = menu->second;
|
||||
this->current->is_shown = show;
|
||||
this->io->CurrentMenu = this->current->id;
|
||||
io->RegisterDrawList(id, this->current->Layout->GetDrawList());
|
||||
this->current->PreHandler(flags);
|
||||
amenus.push_back(this->current->GetID());
|
||||
if (!this->current->is_open) {
|
||||
this->current = nullptr;
|
||||
}
|
||||
return this->current != nullptr;
|
||||
}
|
||||
|
||||
UI7::Menu::Ref UI7::Context::GetCurrentMenu() {
|
||||
Assert(current != nullptr, "Not in a Menu!");
|
||||
return current;
|
||||
}
|
||||
|
||||
UI7::Menu::Ref UI7::Context::FindMenu(const ID& id) {
|
||||
auto e = this->menus.find(id);
|
||||
if (e != this->menus.end()) {
|
||||
return e->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UI7::Context::EndMenu() {
|
||||
this->current->PostHandler();
|
||||
this->current = nullptr;
|
||||
this->io->CurrentMenu = 0;
|
||||
}
|
||||
|
||||
void UI7::Context::Update(float) {
|
||||
TT::Scope st("UI7_Update");
|
||||
Assert(current == nullptr, "Still in a Menu!");
|
||||
bool focused_exist = false;
|
||||
for (auto it : amenus) {
|
||||
auto m = menus[it];
|
||||
io->CurrentMenu = m->id;
|
||||
m->Update(io->Delta);
|
||||
io->CurrentMenu = 0;
|
||||
if (it == io->FocusedMenu) {
|
||||
focused_exist = true;
|
||||
}
|
||||
}
|
||||
if (!focused_exist) {
|
||||
io->FocusedMenu = 0;
|
||||
io->FocusedMenuRect = 0;
|
||||
}
|
||||
int list = 0;
|
||||
u32 vtx_counter = 0;
|
||||
u32 idx_counter = 0;
|
||||
// Render the Focused Menu Last
|
||||
std::sort(io->DrawListRegestry.begin(), io->DrawListRegestry.end(),
|
||||
[&](const auto& a, const auto& b) {
|
||||
return (a.first == io->FocusedMenu) <
|
||||
(b.first == io->FocusedMenu);
|
||||
});
|
||||
// Register Front List as last element
|
||||
io->RegisterDrawList("CtxFrontList", io->Front);
|
||||
for (auto it : io->DrawListRegestry) {
|
||||
it.second->BaseLayer(list * 30);
|
||||
it.second->Process();
|
||||
vtx_counter += it.second->num_vertices;
|
||||
idx_counter += it.second->num_indices;
|
||||
list++;
|
||||
}
|
||||
io->NumIndices = idx_counter;
|
||||
io->NumVertices = vtx_counter;
|
||||
this->amenus.clear();
|
||||
this->io->Update();
|
||||
}
|
||||
|
||||
void UI7::Context::AboutMenu(bool* show) {
|
||||
if (this->BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
|
||||
auto m = this->GetCurrentMenu();
|
||||
|
||||
m->Label("Palladium - UI7 " + GetVersion());
|
||||
m->Separator();
|
||||
m->Label("(c) 2023-2025 René Amthor");
|
||||
m->Label("UI7 is licensed under the MIT License.");
|
||||
m->Label("See LICENSE for more information.");
|
||||
static bool show_build;
|
||||
m->Checkbox("Show Build Info", show_build);
|
||||
if (show_build) {
|
||||
m->SeparatorText("Build Info");
|
||||
m->Label("Full Version -> " + GetVersion(true));
|
||||
m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t)));
|
||||
m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(LI::Vertex)));
|
||||
m->Label("__cplusplus -> " + std::to_string(__cplusplus));
|
||||
m->Label("Compiler -> " + LibInfo::CompiledWith());
|
||||
}
|
||||
this->EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void UI7::Context::MetricsMenu(bool* show) {
|
||||
if (this->BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) {
|
||||
auto m = this->GetCurrentMenu();
|
||||
|
||||
m->Label("Palladium - UI7 " + GetVersion());
|
||||
m->Separator();
|
||||
m->Label(
|
||||
std::format("Average {:.3f} ms/f ({:.1f} FPS)",
|
||||
((float)io->DeltaStats->GetAverage() / 1000.f),
|
||||
1000.f / ((float)io->DeltaStats->GetAverage() / 1000.f)));
|
||||
m->Label(std::format("NumVertices: {}", io->NumVertices));
|
||||
m->Label(std::format("NumIndices: {} -> {} Tris", io->NumIndices,
|
||||
io->NumIndices / 3));
|
||||
m->Label("Menus: " + std::to_string(menus.size()));
|
||||
if (m->BeginTreeNode("Font")) {
|
||||
for (u32 i = 0; i <= 0x00ff; i++) {
|
||||
auto& c = io->Ren->Font()->GetCodepoint(i);
|
||||
if (!c.invalid()) {
|
||||
m->Image(c.tex(), c.size(), c.uv());
|
||||
if ((i % 15) != 0 || i == 0) {
|
||||
m->SameLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->SeparatorText("TimeTrace");
|
||||
if (m->BeginTreeNode("Traces (" +
|
||||
std::to_string(Sys::GetTraceMap().size()) + ")")) {
|
||||
for (auto& it : Sys::GetTraceMap()) {
|
||||
if (m->BeginTreeNode(it.second->GetID())) {
|
||||
m->Label("Diff: " + UI7DTF(it.second->GetLastDiff()));
|
||||
m->Label("Protocol Len: " +
|
||||
std::to_string(it.second->GetProtocol()->GetLen()));
|
||||
m->Label("Average: " +
|
||||
UI7DTF(it.second->GetProtocol()->GetAverage()));
|
||||
m->Label("Min: " + UI7DTF(it.second->GetProtocol()->GetMin()));
|
||||
m->Label("Max: " + UI7DTF(it.second->GetProtocol()->GetMax()));
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->SeparatorText("IO");
|
||||
if (m->BeginTreeNode("Menus (" + std::to_string(menus.size()) + ")")) {
|
||||
for (auto& it : menus) {
|
||||
if (m->BeginTreeNode(it.second->name)) {
|
||||
m->Label("Name: " + it.second->name);
|
||||
m->Label("Pos: " + UI7DV2N(it.second->Layout->GetPosition()));
|
||||
m->Label("Size: " + UI7DV2N(it.second->Layout->GetSize()));
|
||||
m->Label("Work Rect: " + UI7DV4N(it.second->Layout->WorkRect));
|
||||
m->Label("Cursor: " + UI7DV2N(it.second->Layout->Cursor));
|
||||
if (m->BeginTreeNode(
|
||||
"ID Objects (" +
|
||||
std::to_string(it.second->Layout->IDObjects.size()) + ")")) {
|
||||
for (auto& jt : it.second->Layout->IDObjects) {
|
||||
m->Label(UI7DHX32(jt->GetID()));
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
if (m->BeginTreeNode("DrawLists (" +
|
||||
std::to_string(io->DrawListRegestry.size()) + ")")) {
|
||||
for (auto& it : io->DrawListRegestry) {
|
||||
if (m->BeginTreeNode(it.first.GetName())) {
|
||||
m->Label("Vertices: " + std::to_string(it.second->num_vertices));
|
||||
m->Label("Indices: " + std::to_string(it.second->num_indices));
|
||||
m->Label("Base Layer: " + std::to_string(it.second->base));
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->Label("io->Time: " + Strings::FormatMillis(io->Time->Get()));
|
||||
m->Label(std::format("io->Delta: {:.3f}", io->Delta));
|
||||
m->Label(std::format("io->Framerate: {:.2f}", io->Framerate));
|
||||
m->Label(UI7DHX32(io->FocusedMenu));
|
||||
m->Label(UI7DHX32(io->DraggedObject));
|
||||
m->Label(std::format("io->DragTime: {:.2f}s", io->DragTime->GetSeconds()));
|
||||
m->Label(UI7DV4(io->DragDestination));
|
||||
m->Label(UI7DV2(io->DragSourcePos));
|
||||
m->Label(UI7DV2(io->DragPosition));
|
||||
m->Label(UI7DV2(io->DragLastPosition));
|
||||
this->EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void UI7::Context::StyleEditor(bool* show) {
|
||||
if (this->BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) {
|
||||
auto m = this->GetCurrentMenu();
|
||||
|
||||
m->Label("Palladium - UI7 " + GetVersion() + " Style Editor");
|
||||
m->Separator();
|
||||
m->DragData("MenuPadding", (float*)&io->MenuPadding, 2, 0.f, 100.f);
|
||||
m->DragData("FramePadding", (float*)&io->FramePadding, 2, 0.f, 100.f);
|
||||
m->DragData("ItemSpace", (float*)&io->ItemSpace, 2, 0.f, 100.f);
|
||||
m->DragData("MinSliderSize", (float*)&io->MinSliderDragSize, 2, 1.f, 100.f);
|
||||
m->DragData("OverScroll Modifier", &io->OverScrollMod, 1, 0.01f,
|
||||
std::numeric_limits<float>::max(), 0.01f, 2);
|
||||
m->Checkbox("Menu Border", io->ShowMenuBorder);
|
||||
m->Checkbox("Frame Border", io->ShowFrameBorder);
|
||||
m->SeparatorText("Theme");
|
||||
if (m->Button("Dark")) {
|
||||
UI7::Theme::Default(*io->Theme.get());
|
||||
}
|
||||
m->SameLine();
|
||||
if (m->Button("Flashbang")) {
|
||||
UI7::Theme::Flashbang(*io->Theme.get());
|
||||
}
|
||||
/// Small trick to print without prefix
|
||||
#define ts(x) m->ColorEdit(std::string(#x).substr(9), &io->Theme->GetRef(x));
|
||||
#define ts2(x) \
|
||||
m->DragData(std::string(#x).substr(9), (u8*)&io->Theme->GetRef(x), 4, (u8)0, \
|
||||
(u8)255);
|
||||
ts2(UI7Color_Background);
|
||||
ts2(UI7Color_Border);
|
||||
ts2(UI7Color_Button);
|
||||
ts2(UI7Color_ButtonDead);
|
||||
ts2(UI7Color_ButtonActive);
|
||||
ts2(UI7Color_ButtonHovered);
|
||||
ts2(UI7Color_Text);
|
||||
ts2(UI7Color_TextDead);
|
||||
ts2(UI7Color_Header);
|
||||
ts2(UI7Color_HeaderDead);
|
||||
ts2(UI7Color_Selector);
|
||||
ts2(UI7Color_Checkmark);
|
||||
ts2(UI7Color_FrameBackground);
|
||||
ts2(UI7Color_FrameBackgroundHovered);
|
||||
ts2(UI7Color_Progressbar);
|
||||
ts2(UI7Color_ListEven);
|
||||
ts2(UI7Color_ListOdd);
|
||||
this->EndMenu();
|
||||
}
|
||||
}
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <pd/core/core.hpp>
|
||||
#include <pd/ui7/ui7.hpp>
|
||||
|
||||
// Helpers
|
||||
|
||||
std::string _UI7DV4(PD::vec4<float> v) {
|
||||
return std::format("[{:.2f}, {:.2f}, {:.2f}, {:.2f}]", v.x, v.y, v.z, v.w);
|
||||
}
|
||||
|
||||
std::string _UI7DV2(PD::vec2<float> v) {
|
||||
return std::format("[{:.2f}, {:.2f}]", v.x, v.y);
|
||||
}
|
||||
|
||||
#define UI7DV4(x) #x ": " + _UI7DV4(x)
|
||||
#define UI7DV4N(x) _UI7DV4(x)
|
||||
#define UI7DV2(x) #x ": " + _UI7DV2(x)
|
||||
#define UI7DV2N(x) _UI7DV2(x)
|
||||
#define UI7DHX32(x) std::format("{}: {:#08x}", #x, x)
|
||||
#define UI7DTF(x) PD::Strings::FormatNanos(x)
|
||||
|
||||
namespace PD {
|
||||
PD_UI7_API std::string UI7::GetVersion(bool show_build) {
|
||||
std::stringstream s;
|
||||
s << ((UI7_VERSION >> 24) & 0xFF) << ".";
|
||||
s << ((UI7_VERSION >> 16) & 0xFF) << ".";
|
||||
s << ((UI7_VERSION >> 8) & 0xFF);
|
||||
if (show_build) s << "-" << ((UI7_VERSION) & 0xFF);
|
||||
return s.str();
|
||||
}
|
||||
|
||||
PD_UI7_API bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags,
|
||||
bool* show) {
|
||||
// Assert(!this->current, "You are already in another Menu!");
|
||||
// Assert(std::find(amenus.begin(), amenus.end(), (u32)id) == amenus.end(),
|
||||
// "Menu Name Already used or\nContext::Update not called!");
|
||||
if (show != nullptr) {
|
||||
if (!(*show)) {
|
||||
if (io->InputHandler->FocusedMenu == id) {
|
||||
io->InputHandler->FocusedMenu = 0;
|
||||
io->InputHandler->FocusedMenuRect = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
auto menu = this->menus.find(id);
|
||||
if (menu == this->menus.end()) {
|
||||
this->menus[id] = Menu::New(id, io);
|
||||
// this->menus[id]->Layout->SetSize(io->Ren->GetViewport().zw());
|
||||
menu = this->menus.find(id);
|
||||
}
|
||||
this->current = menu->second;
|
||||
this->current->is_shown = show;
|
||||
this->io->InputHandler->CurrentMenu = this->current->id;
|
||||
io->RegisterDrawList(id, this->current->Layout->GetDrawList());
|
||||
this->current->PreHandler(flags);
|
||||
amenus.push_back(this->current->GetID());
|
||||
if (!this->current->is_open) {
|
||||
this->current = nullptr;
|
||||
}
|
||||
return this->current != nullptr;
|
||||
}
|
||||
|
||||
PD_UI7_API UI7::Menu::Ref UI7::Context::GetCurrentMenu() {
|
||||
// Assert(current != nullptr, "Not in a Menu!");
|
||||
return current;
|
||||
}
|
||||
|
||||
PD_UI7_API UI7::Menu::Ref UI7::Context::FindMenu(const ID& id) {
|
||||
auto e = this->menus.find(id);
|
||||
if (e != this->menus.end()) {
|
||||
return e->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PD_UI7_API void UI7::Context::EndMenu() {
|
||||
this->current->PostHandler();
|
||||
this->current = nullptr;
|
||||
this->io->InputHandler->CurrentMenu = 0;
|
||||
}
|
||||
|
||||
PD_UI7_API bool UI7::Context::DoMenuEx(
|
||||
const UI7::ID& id, UI7MenuFlags flags,
|
||||
std::function<void(UI7::ReMenu::Ref m)> f) {
|
||||
if (!Current) {
|
||||
Current = ReMenu::New(id, io);
|
||||
}
|
||||
// Current->pIsShown = show;
|
||||
io->InputHandler->CurrentMenu = Current->pID;
|
||||
io->RegisterDrawList(id, Current->pLayout->GetDrawList());
|
||||
if (Current->pIsOpen) {
|
||||
f(Current);
|
||||
}
|
||||
return Current != nullptr;
|
||||
}
|
||||
|
||||
PD_UI7_API void UI7::Context::Update(float) {
|
||||
TT::Scope st("UI7_Update");
|
||||
// Assert(current == nullptr, "Still in a Menu!");
|
||||
if (!io->InputHandler->FocusedMenu && amenus.size() > 0) {
|
||||
io->InputHandler->FocusedMenu = amenus[amenus.size() - 1];
|
||||
}
|
||||
bool focused_exist = false;
|
||||
if (aml.size() == 0) {
|
||||
aml = amenus;
|
||||
} else {
|
||||
std::vector<size_t> tbr;
|
||||
for (size_t i = 0; i < aml.size(); i++) {
|
||||
if (std::find(amenus.begin(), amenus.end(), aml[i]) == amenus.end()) {
|
||||
tbr.push_back(i);
|
||||
}
|
||||
}
|
||||
for (auto& it : tbr) {
|
||||
aml.erase(aml.begin() + it);
|
||||
}
|
||||
}
|
||||
for (auto& it : amenus) {
|
||||
if (std::find(aml.begin(), aml.end(), it) == aml.end()) {
|
||||
aml.push_back(it);
|
||||
}
|
||||
}
|
||||
auto ptf = std::find(aml.begin(), aml.end(), io->InputHandler->FocusedMenu);
|
||||
if (ptf != aml.end() && ptf != aml.begin()) {
|
||||
std::rotate(aml.begin(), ptf, ptf + 1);
|
||||
}
|
||||
for (auto it : aml) {
|
||||
auto m = menus[it];
|
||||
io->InputHandler->CurrentMenu = m->id;
|
||||
m->Update(io->Delta);
|
||||
io->InputHandler->CurrentMenu = 0;
|
||||
if (it == io->InputHandler->FocusedMenu) {
|
||||
focused_exist = true;
|
||||
}
|
||||
}
|
||||
io->InputHandler->CurrentMenu = Current->pID;
|
||||
Current->Update();
|
||||
/*if (!focused_exist && io->CurrentMenu != Current->pID) {
|
||||
io->FocusedMenu = 0;
|
||||
io->FocusedMenuRect = 0;
|
||||
}*/
|
||||
int list = 0;
|
||||
u32 vtx_counter = 0;
|
||||
u32 idx_counter = 0;
|
||||
// Register Front List as last element
|
||||
io->RegisterDrawList("CtxFrontList", io->Front);
|
||||
// io->DrawListRegestry.Reverse();
|
||||
for (auto it : io->DrawListRegestry) {
|
||||
it.Second->Base = list * 30;
|
||||
it.Second->Process(io->pRDL);
|
||||
vtx_counter += it.Second->NumVertices;
|
||||
idx_counter += it.Second->NumIndices;
|
||||
list++;
|
||||
}
|
||||
io->Ren->RegisterDrawList(io->pRDL);
|
||||
io->NumIndices = idx_counter;
|
||||
io->NumVertices = vtx_counter;
|
||||
this->amenus.clear();
|
||||
this->io->Update();
|
||||
}
|
||||
|
||||
PD_UI7_API void UI7::Context::AboutMenu(bool* show) {
|
||||
if (this->BeginMenu("About UI7", UI7MenuFlags_Scrolling, show)) {
|
||||
auto m = this->GetCurrentMenu();
|
||||
|
||||
m->Label("Palladium - UI7 " + GetVersion());
|
||||
m->Separator();
|
||||
m->Label("(c) 2023-2025 René Amthor");
|
||||
m->Label("UI7 is licensed under the MIT License.");
|
||||
m->Label("See LICENSE for more information.");
|
||||
static bool show_build;
|
||||
m->Checkbox("Show Build Info", show_build);
|
||||
if (show_build) {
|
||||
m->SeparatorText("Build Info");
|
||||
m->Label("Full Version -> " + GetVersion(true));
|
||||
m->Label("sizeof(size_t) -> " + std::to_string(sizeof(size_t)));
|
||||
m->Label("sizeof(LI::Vertex) -> " + std::to_string(sizeof(LI::Vertex)));
|
||||
m->Label("__cplusplus -> " + std::to_string(__cplusplus));
|
||||
m->Label("Compiler -> " + LibInfo::CompiledWith());
|
||||
}
|
||||
this->EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
PD_UI7_API void UI7::Context::MetricsMenu(bool* show) {
|
||||
if (this->BeginMenu("UI7 Metrics", UI7MenuFlags_Scrolling, show)) {
|
||||
auto m = this->GetCurrentMenu();
|
||||
|
||||
m->Label("Palladium - UI7 " + GetVersion());
|
||||
m->Separator();
|
||||
m->Label(
|
||||
std::format("Average {:.3f} ms/f ({:.1f} FPS)",
|
||||
((float)io->DeltaStats->GetAverage() / 1000.f),
|
||||
1000.f / ((float)io->DeltaStats->GetAverage() / 1000.f)));
|
||||
m->Label(std::format("NumVertices: {}", io->NumVertices));
|
||||
m->Label(std::format("NumIndices: {} -> {} Tris", io->NumIndices,
|
||||
io->NumIndices / 3));
|
||||
m->Label("Menus: " + std::to_string(menus.size()));
|
||||
/*if (m->BeginTreeNode("Font")) {
|
||||
for (u32 i = 0; i <= 0x00ff; i++) {
|
||||
auto& c = io->Ren->Font()->GetCodepoint(i);
|
||||
if (!c.invalid()) {
|
||||
m->Image(c.tex(), c.size(), c.uv());
|
||||
if ((i % 15) != 0 || i == 0) {
|
||||
m->SameLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}*/
|
||||
m->SeparatorText("TimeTrace");
|
||||
if (m->BeginTreeNode("Traces (" +
|
||||
std::to_string(Sys::GetTraceMap().size()) + ")")) {
|
||||
for (auto& it : Sys::GetTraceMap()) {
|
||||
if (m->BeginTreeNode(it.second->GetID())) {
|
||||
m->Label("Diff: " + UI7DTF(it.second->GetLastDiff()));
|
||||
m->Label("Protocol Len: " +
|
||||
std::to_string(it.second->GetProtocol()->GetLen()));
|
||||
m->Label("Average: " +
|
||||
UI7DTF(it.second->GetProtocol()->GetAverage()));
|
||||
m->Label("Min: " + UI7DTF(it.second->GetProtocol()->GetMin()));
|
||||
m->Label("Max: " + UI7DTF(it.second->GetProtocol()->GetMax()));
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->SeparatorText("IO");
|
||||
if (m->BeginTreeNode("Menus (" + std::to_string(menus.size()) + ")")) {
|
||||
for (auto& it : menus) {
|
||||
if (m->BeginTreeNode(it.second->name)) {
|
||||
m->Label("Name: " + it.second->name);
|
||||
/*m->Label("Pos: " + UI7DV2N(it.second->Layout->GetPosition()));
|
||||
m->Label("Size: " + UI7DV2N(it.second->Layout->GetSize()));
|
||||
m->Label("Work Rect: " + UI7DV4N(it.second->Layout->WorkRect));
|
||||
m->Label("Cursor: " + UI7DV2N(it.second->Layout->Cursor));*/
|
||||
if (m->BeginTreeNode(
|
||||
"ID Objects (" +
|
||||
std::to_string(it.second->Layout->IDObjects.size()) + ")")) {
|
||||
for (auto& jt : it.second->Layout->IDObjects) {
|
||||
m->Label(UI7DHX32(jt->GetID()));
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
if (m->BeginTreeNode("Active Menus (" + std::to_string(aml.size()) + ")")) {
|
||||
for (auto& it : aml) {
|
||||
if (m->BeginTreeNode(menus[it]->name)) {
|
||||
m->Label("Name: " + menus[it]->name);
|
||||
/*m->Label("Pos: " + UI7DV2N(it.second->Layout->Pos));
|
||||
m->Label("Size: " + UI7DV2N(it.second->Layout->GetSize()));
|
||||
m->Label("Work Rect: " + UI7DV4N(it.second->Layout->WorkRect));
|
||||
m->Label("Cursor: " + UI7DV2N(it.second->Layout->Cursor));*/
|
||||
if (m->BeginTreeNode(
|
||||
"ID Objects (" +
|
||||
std::to_string(menus[it]->Layout->IDObjects.size()) + ")")) {
|
||||
for (auto& jt : menus[it]->Layout->IDObjects) {
|
||||
m->Label(UI7DHX32(jt->GetID()));
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
if (m->BeginTreeNode("DrawLists (" +
|
||||
std::to_string(io->DrawListRegestry.Size()) + ")")) {
|
||||
for (auto& it : io->DrawListRegestry) {
|
||||
if (m->BeginTreeNode(it.First.GetName())) {
|
||||
m->Label("Vertices: " + std::to_string(it.Second->NumVertices));
|
||||
m->Label("Indices: " + std::to_string(it.Second->NumIndices));
|
||||
m->Label("Base Layer: " + std::to_string(it.Second->Base));
|
||||
m->EndTreeNode();
|
||||
}
|
||||
}
|
||||
m->EndTreeNode();
|
||||
}
|
||||
m->Label("io->Time: " + Strings::FormatMillis(io->Time->Get()));
|
||||
m->Label(std::format("io->Delta: {:.3f}", io->Delta));
|
||||
m->Label(std::format("io->Framerate: {:.2f}", io->Framerate));
|
||||
m->Label(UI7DHX32(io->InputHandler->FocusedMenu));
|
||||
m->Label(UI7DHX32(io->InputHandler->DraggedObject));
|
||||
m->Label(std::format("io->DragTime: {:.2f}s",
|
||||
io->InputHandler->DragTime->GetSeconds()));
|
||||
m->Label(UI7DV4(io->InputHandler->DragDestination));
|
||||
m->Label(UI7DV2(io->InputHandler->DragSourcePos));
|
||||
m->Label(UI7DV2(io->InputHandler->DragPosition));
|
||||
m->Label(UI7DV2(io->InputHandler->DragLastPosition));
|
||||
this->EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
PD_UI7_API void UI7::Context::StyleEditor(bool* show) {
|
||||
if (this->BeginMenu("UI7 Style Editor", UI7MenuFlags_Scrolling, show)) {
|
||||
auto m = this->GetCurrentMenu();
|
||||
|
||||
m->Label("Palladium - UI7 " + GetVersion() + " Style Editor");
|
||||
m->Separator();
|
||||
m->DragData("MenuPadding", (float*)&io->MenuPadding, 2, 0.f, 100.f);
|
||||
m->DragData("FramePadding", (float*)&io->FramePadding, 2, 0.f, 100.f);
|
||||
m->DragData("ItemSpace", (float*)&io->ItemSpace, 2, 0.f, 100.f);
|
||||
m->DragData("MinSliderSize", (float*)&io->MinSliderDragSize, 2, 1.f, 100.f);
|
||||
m->DragData("OverScroll Modifier", &io->OverScrollMod, 1, 0.01f,
|
||||
std::numeric_limits<float>::max(), 0.01f, 2);
|
||||
m->Checkbox("Menu Border", io->ShowMenuBorder);
|
||||
m->Checkbox("Frame Border", io->ShowFrameBorder);
|
||||
m->SeparatorText("Theme");
|
||||
if (m->Button("Dark")) {
|
||||
UI7::Theme::Default(*io->Theme.get());
|
||||
}
|
||||
m->SameLine();
|
||||
if (m->Button("Flashbang")) {
|
||||
UI7::Theme::Flashbang(*io->Theme.get());
|
||||
}
|
||||
/// Small trick to print without prefix
|
||||
#define ts(x) m->ColorEdit(std::string(#x).substr(9), &io->Theme->GetRef(x));
|
||||
#define ts2(x) \
|
||||
m->DragData(std::string(#x).substr(9), (u8*)&io->Theme->GetRef(x), 4, (u8)0, \
|
||||
(u8)255);
|
||||
ts2(UI7Color_Background);
|
||||
ts2(UI7Color_Border);
|
||||
ts2(UI7Color_Button);
|
||||
ts2(UI7Color_ButtonDead);
|
||||
ts2(UI7Color_ButtonActive);
|
||||
ts2(UI7Color_ButtonHovered);
|
||||
ts2(UI7Color_Text);
|
||||
ts2(UI7Color_TextDead);
|
||||
ts2(UI7Color_Header);
|
||||
ts2(UI7Color_HeaderDead);
|
||||
ts2(UI7Color_Selector);
|
||||
ts2(UI7Color_Checkmark);
|
||||
ts2(UI7Color_FrameBackground);
|
||||
ts2(UI7Color_FrameBackgroundHovered);
|
||||
ts2(UI7Color_Progressbar);
|
||||
ts2(UI7Color_ListEven);
|
||||
ts2(UI7Color_ListOdd);
|
||||
this->EndMenu();
|
||||
}
|
||||
}
|
||||
} // namespace PD
|
Reference in New Issue
Block a user