diff --git a/CMakeLists.txt b/CMakeLists.txt index d7d0203..da7896d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,13 +36,13 @@ endif() execute_process( COMMAND git rev-parse --short HEAD - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_SHORT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ) # Set Project -project(palladium LANGUAGES C CXX VERSION 0.2.1) +project(palladium LANGUAGES C CXX VERSION 0.2.2) option(PD_BUILD_TESTS "Sets if TestApp and TestBench get build" OFF) @@ -62,6 +62,7 @@ source/core/common.cpp source/core/io.cpp source/core/strings.cpp source/core/sys.cpp +source/core/timer.cpp source/core/timetrace.cpp) add_pd_lib(pd-core SRC_FILES ${CORE_SRC}) @@ -85,7 +86,9 @@ add_pd_lib(pd-drivers SRC_FILES ${DRVS_SRC} DEPENDS pd-maths) set(L3DS_SRC source/lib3ds/gamepad_icons.cpp source/lib3ds/result_decoder.cpp -source/lib3ds/drv_hid.cpp) +source/lib3ds/drv_hid.cpp +source/lib3ds/hwinfo.cpp +source/lib3ds/os.cpp) add_pd_lib(pd-lib3ds SRC_FILES ${L3DS_SRC} DEPENDS pd-drivers) @@ -99,6 +102,11 @@ source/lithium/renderer.cpp) add_pd_lib(pd-lithium SRC_FILES ${LI_SRC} DEPENDS pd-maths pd-external citro3d) +set(SOUND_SRC +source/sound/mp3.cpp) + +add_pd_lib(pd-sound SRC_FILES ${SOUND_SRC} DEPENDS pd-core mpg123) + set(OVL_SRC source/overlays/keyboard.cpp source/overlays/message_mgr.cpp @@ -130,27 +138,24 @@ add_pd_lib(pd-ui7 SRC_FILES ${UI7_SRC} DEPENDS pd-drivers pd-lithium) add_library(palladium INTERFACE) target_link_libraries(palladium INTERFACE - pd-core - pd-maths - pd-external - pd-drivers - pd-lib3ds - pd-lithium - pd-overlays - pd-app - pd-ui7 +pd-core pd-maths pd-external pd-drivers pd-lib3ds +pd-lithium pd-overlays pd-app pd-ui7 ) add_dependencies(palladium - pd-core - pd-maths - pd-external - pd-drivers - pd-lib3ds - pd-lithium - pd-overlays - pd-app - pd-ui7 +pd-core pd-maths pd-external pd-drivers +pd-lib3ds pd-lithium pd-overlays pd-app pd-ui7 +) + +add_library(palladium-lite INTERFACE) +target_link_libraries(palladium-lite INTERFACE +pd-core pd-maths pd-external pd-drivers pd-lib3ds +pd-lithium +) + +add_dependencies(palladium-lite +pd-core pd-maths pd-external pd-drivers +pd-lib3ds pd-lithium ) if(PD_BUILD_TESTS) diff --git a/README.md b/README.md index 7d64131..f3c92fe 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,6 @@ **Framework / Engine to create Homebrew Apps / Games** -## Build types - -```bash -PD_EXTENDED_DEBUG=0 # Include things like ResultDecoder and Check for Memory usage -PD_DEBUG=0 # not yet -PD_NO_SAFE_CODE=0 # Remove All not important safetey checks -``` - ## Building Install Dependencies: @@ -23,8 +15,6 @@ Building: If you want to have the lib in a projects `libs` dir or so you can simply add `-DCMAKE_INSTALL_PREFIX=./res` to the cmake command and copy the dirs from res to you libs folder -For Debug build the Cmake Script generates a `libpalladiumd.a` - ```bash mkdir -p build cd build @@ -33,6 +23,22 @@ make make install ``` +## Libraries + +| Name | Last Updated | Platform | Depends | +|---|---|---|---| +| pd-core | 0.2.2 | multi | none | +| pd-maths | 0.2.0 | multi | pd-core | +| pd-external | 0.1.0 | multi | none | +| pd-drivers | 0.2.1 | multi | pd-core, pd-maths | +| pd-lib3ds | 0.2.2 | 3ds | pd-core, pd-maths, pd-drivers | +| pd-net | 0.2.2 | 3ds | pd-core, pd-lib3ds | +| pd-lithium | 0.2.1 | 3ds | pd-core, pd-maths pd-lib3ds, citro3d | +| pd-sound | 0.2.2 | 3ds | pd-core, mpg123 | +| pd-overlays | 0.2.1 | 3ds | pd-core, pd-maths, pd-lib3ds, pd-lithium, pd-ui7 | +| pd-ui7 | 0.2.2 | 3ds | pd-core, pd-maths, pd-lib3ds, pd-lithium | +| pd-app | 0.2.2 | 3ds | pd-core, pd-maths, pd-lib3ds, pd-lithium | + ## Credits | Icon | Username | Description | |---|---|---| diff --git a/include/pd.hpp b/include/pd.hpp index 7b1aa30..6b164d7 100644 --- a/include/pd.hpp +++ b/include/pd.hpp @@ -29,6 +29,7 @@ SOFTWARE. #include #include #include +#include #include // Graphics #include @@ -49,12 +50,15 @@ SOFTWARE. #include // UI7 #include - +// Lib3ds +#include +#include +#include +#include // App #include #include #include -#include /// Setup these as non Namespaced access by default #ifndef PD_MATH_NAMESPACED diff --git a/include/pd/app/app.hpp b/include/pd/app/app.hpp index b5c4939..f92816d 100644 --- a/include/pd/app/app.hpp +++ b/include/pd/app/app.hpp @@ -24,6 +24,7 @@ SOFTWARE. */ #include +#include #include #include #include @@ -46,15 +47,16 @@ class App { }; using AppInitFlags = u32; enum AppInitFlags_ { - AppInitFlags_None = 0, - AppInitFlags_MountRomfs = 1 << 0, - AppInitFlags_InitGraphics = 1 << 1, - AppInitFlags_New3dsMode = 1 << 2, - AppInitFlags_InitGraphicsNoC3D = 1 << 3, - AppInitFlags_InitLithium = 1 << 4, + AppInitFlags_None = 0, /// Do nothing (probably a useles ability) + AppInitFlags_MountRomfs = 1 << 0, /// Mount Romfs on PreInit + AppInitFlags_InitGraphics = 1 << 1, /// Default Init Graphics for GPU use + AppInitFlags_New3dsMode = 1 << 2, /// Enable New3DS Speedup + AppInitFlags_InitGraphicsNoC3D = 1 << 3, /// Init GFX for Buf Modification + AppInitFlags_InitLithium = 1 << 4, /// Init 2D Rendering Engine /// I dont have a name for this one yet /// It Inits Internal Directory structure AppInitFlags_UnnamedOption1 = 1 << 5, + AppInitFlags_InitHwInfo = 1 << 6, /// Init HwInfo from lib3ds AppInitFlags_Default = AppInitFlags_MountRomfs | AppInitFlags_InitGraphics | AppInitFlags_New3dsMode | AppInitFlags_InitLithium, }; @@ -95,6 +97,8 @@ class App { void FeatureDisable(AppFlags flags) { runtimeflags &= ~flags; } AppFlags& GetFeatureSet() { return runtimeflags; } + std::string GetDataDirectory(); + protected: Screen::Ref Top; Screen::Ref Bottom; @@ -110,8 +114,8 @@ class App { MessageMgr::Ref msg_mgr; OverlayMgr::Ref overlay_mgr; Hid::Ref input_mgr; + Timer::Ref app_time; u64 last_time; - float app_time; float fps; std::string name; diff --git a/include/pd/app/timer.hpp b/include/pd/core/timer.hpp similarity index 83% rename from include/pd/app/timer.hpp rename to include/pd/core/timer.hpp index ff9a36f..0298093 100644 --- a/include/pd/app/timer.hpp +++ b/include/pd/core/timer.hpp @@ -27,18 +27,21 @@ SOFTWARE. #include namespace PD { -class Timer { +class Timer : public SmartCtor { public: - Timer() {} + Timer(bool auto_start = true); ~Timer() {} - void Start() {} - void Pause() {} - void Update() {} - void Reset() { start_ = Sys::GetTime(); } - u64 Get() {} + void Rseume(); + void Pause(); + void Update(); + void Reset(); + bool IsRunning() const; + u64 Get(); + double GetSeconds(); private: - u64 start_; - u64 now_; + u64 start; + u64 now; + bool is_running = false; }; } // namespace PD \ No newline at end of file diff --git a/include/pd/lib3ds/hwinfo.hpp b/include/pd/lib3ds/hwinfo.hpp new file mode 100644 index 0000000..c7d5e7d --- /dev/null +++ b/include/pd/lib3ds/hwinfo.hpp @@ -0,0 +1,36 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2025 René Amthor (tobid7) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include + +namespace PD { +namespace HwInfo { +void Init(); +void Deinit(); +bool IsCharging(); +int GetBatteryPercentage(); +int GetWifiLevel(); +} // namespace HwInfo +} // namespace PD \ No newline at end of file diff --git a/include/pd/lib3ds/os.hpp b/include/pd/lib3ds/os.hpp new file mode 100644 index 0000000..f3ef0d5 --- /dev/null +++ b/include/pd/lib3ds/os.hpp @@ -0,0 +1,32 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2025 René Amthor (tobid7) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include + +namespace PD { +namespace Ctr { +std::string GetSystemLanguage(); +} // namespace Ctr +} // namespace PD \ No newline at end of file diff --git a/include/pd/net/net.hpp b/include/pd/net/net.hpp new file mode 100644 index 0000000..47c57cb --- /dev/null +++ b/include/pd/net/net.hpp @@ -0,0 +1,72 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2025 René Amthor (tobid7) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include +#include + +namespace PD { +class DownloadManager : public SmartCtor { + public: + using Error = u64; + enum Error_ { + Error_None, // Function Executed Successfully + Error_Memory, // Memory Allocation Error + Error_Write, // Unable to Write File + Error_StatusCode, // Error with Status Code + Error_Git, // Git Error + Error_CtrStatus, // 3ds Result Code + Error_Curl, // Curl Error + Error_Busy, // Another Download Taskl is already running + Error_Invalid, // Invalid Json struct + Error_NoWifi, // Console not connected to wifi + }; + DownloadManager() {} + ~DownloadManager() {} + + static Error_ GetErrorCode(Error err) { + return (Error_)u32(err & 0xffffffff); + } + static int GetStatusCode(Error err) { + Error_ c = GetErrorCode(err); + if (c != Error_StatusCode && c != Error_CtrStatus && c != Error_Curl) { + return 0; + } + return u32(err >> 32); + } + + Error Get(const std::string& url, std::string& res); + Error GetFile(const std::string& url, const std::string& res_path); + Error GetGitRelease(const std::string& url, const std::string& asset, + const std::string& path, bool pre); + Error GetAsJson(const std::string& url, nlohmann::json& res); + + u64 ProgressCurrent() const { return current; } + u64 ProgressTotal() const { return total; } + + private: + u64 current; + u64 total; +}; +} // namespace PD \ No newline at end of file diff --git a/include/pd/sound/decoder.hpp b/include/pd/sound/decoder.hpp new file mode 100644 index 0000000..fffa6e4 --- /dev/null +++ b/include/pd/sound/decoder.hpp @@ -0,0 +1,44 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2025 René Amthor (tobid7) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include + +namespace PD { +namespace Music { +class Decoder : public SmartCtor { + public: + Decoder() {} + virtual ~Decoder() {} + + virtual int Init(const std::string& path) = 0; + virtual void Deinit() = 0; + virtual u32 GetSampleRate() = 0; + virtual u8 GetChannels() = 0; + virtual size_t GetBufSize() = 0; + virtual u64 Decode(u16* buf_address) = 0; + virtual size_t GetFileSamples() = 0; +}; +} // namespace Music +} // namespace PD \ No newline at end of file diff --git a/include/pd/sound/metadata.hpp b/include/pd/sound/metadata.hpp new file mode 100644 index 0000000..1d2c89b --- /dev/null +++ b/include/pd/sound/metadata.hpp @@ -0,0 +1,62 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2025 René Amthor (tobid7) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include + +namespace PD { +namespace Music { +class MetaData { + public: + MetaData() {} + ~MetaData() {} + + std::string Name() const { return name; } + std::string Album() const { return album; } + std::string Year() const { return year; } + std::string Title() const { return title; } + std::string Artist() const { return artist; } + std::string Mdt() const { return mdt; } + std::string Path() const { return path; } + + void Name(const std::string &v) { name = v; } + void Album(const std::string &v) { album = v; } + void Year(const std::string &v) { year = v; } + void Title(const std::string &v) { title = v; } + void Artist(const std::string &v) { artist = v; } + void Mdt(const std::string &v) { mdt = v; } + void Path(const std::string &v) { path = v; } + + private: + const std::string unk = "Unknown"; + std::string title = unk; + std::string album = unk; + std::string year = unk; + std::string name = unk; + std::string path = unk; + std::string artist = unk; + std::string mdt = unk; +}; +} // namespace Music +} // namespace PD \ No newline at end of file diff --git a/include/pd/sound/mp3.hpp b/include/pd/sound/mp3.hpp new file mode 100644 index 0000000..a3365cb --- /dev/null +++ b/include/pd/sound/mp3.hpp @@ -0,0 +1,52 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2025 René Amthor (tobid7) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include + +#include + +namespace PD { +namespace Music { +class Mp3Decoder : public Decoder { + public: + Mp3Decoder() {} + ~Mp3Decoder() {} + + int Init(const std::string& path) override; + void Deinit() override; + u32 GetSampleRate() override; + u8 GetChannels() override; + size_t GetBufSize() override; + u64 Decode(u16* buf_address) override; + size_t GetFileSamples() override; + + private: + mpg123_handle* handle = nullptr; + size_t buf_size = 0; + u32 rate = 0; + u8 channels = 0; +}; +} // namespace Music +} // namespace PD \ No newline at end of file diff --git a/include/pd/sound/player.hpp b/include/pd/sound/player.hpp new file mode 100644 index 0000000..9857b5c --- /dev/null +++ b/include/pd/sound/player.hpp @@ -0,0 +1,52 @@ +#pragma once + +/* +MIT License +Copyright (c) 2024 - 2025 René Amthor (tobid7) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +#include +#include +#include + +namespace PD { +namespace Music { +class Player : public SmartCtor { + public: + Player() {} + ~Player() {} + + private: + MetaData meta; + size_t samples_total = 0; + size_t samples_played = 0; + size_t samples_per_sec = 0; + std::string file; + std::vector> buffers[2]; + ndspWaveBuf wave_buf[2] = {0}; + bool last_buf = false; + int ret = -1; + bool done = false; + bool playing = false; + bool stop = false; +}; +} // namespace Music +} // namespace PD \ No newline at end of file diff --git a/include/pd/ui7/container/container.hpp b/include/pd/ui7/container/container.hpp index c31ba34..af673b7 100644 --- a/include/pd/ui7/container/container.hpp +++ b/include/pd/ui7/container/container.hpp @@ -38,9 +38,9 @@ class Container : public SmartCtor { Container(const vec4& box) : pos(box.xy()), size(box.zw()) {} ~Container() {} - void Init(LI::Renderer::Ref r, UI7::DrawList::Ref l, UI7::Theme* lt) { + void Init(LI::Renderer::Ref r, UI7::DrawList::Ref l, UI7::Theme::Ref lt) { list = l; - linked_theme = lt; + theme = lt; ren = r; } @@ -50,6 +50,9 @@ class Container : public SmartCtor { vec2 GetPos() { return pos; } vec2 GetSize() { return size; } + void SetParent(Container::Ref v) { parent = v; } + Container::Ref GetParent() { return parent; } + bool Skippable() const { return skippable; } bool Removable() const { return rem; } @@ -72,8 +75,9 @@ class Container : public SmartCtor { vec2 pos; vec2 size; UI7::DrawList::Ref list; - UI7::Theme* linked_theme; + UI7::Theme::Ref theme; LI::Renderer::Ref ren; + Container::Ref parent; u32 id = 0; }; } // namespace UI7 diff --git a/include/pd/ui7/menu.hpp b/include/pd/ui7/menu.hpp index 3a4e09e..d88214e 100644 --- a/include/pd/ui7/menu.hpp +++ b/include/pd/ui7/menu.hpp @@ -34,8 +34,8 @@ namespace PD { namespace UI7 { class Menu : public SmartCtor { public: - Menu(ID id, Theme* tl, Hid::Ref h) { - linked_theme = tl; + Menu(ID id, Theme::Ref tl, Hid::Ref h) { + theme = tl; this->inp = h; this->id = id; this->name = id.GetName(); @@ -48,37 +48,97 @@ class Menu : public SmartCtor { }; ~Menu() {} - /// Objects + /// Objects /// + + /// @brief Render a Simple Label + /// @param label The text to draw void Label(const std::string& label); + /// @brief Render a Button + /// @param label The buttons text + /// @return if the button was pressed bool Button(const std::string& label); + /// @brief Render a Checkbox + /// @param label Label of the Checkbox + /// @param v A value to update void Checkbox(const std::string& label, bool& v); + /// @brief Render an Image + /// @param img Texture reference of the image + /// @param size a Custom Size if needed void Image(Texture::Ref img, vec2 size = 0.f); - /// Basic API + /// Basic API /// + + /// @brief Add the Next object to the same line void SameLine(); + /// @brief Add a Separator Line void Separator(); + /// @brief Render a Separator Line with a Text + /// @todo determinate text position by current alignment + /// @param label The Text to show void SeparatorText(const std::string& label); + /// @brief Put the last Added Object into the Joinlist void Join(); + /// @brief Add the Last element to the join list + /// and perform an alignment operation + /// @param a Alignment Oeration(s) void JoinAlign(UI7Align a); + /// @brief Align the Last Object + /// @param a Alignment Operation void AfterAlign(UI7Align a); + /// @brief Set a Temp alignment op for the next Object + /// @param a Alignment Operation void NextAlign(UI7Align a) { tmpalign = a; } + /// @brief Align Every Single Object by this operationset + /// @param a Alignment void PushAlignment(UI7Align a) { alignment = a; } + /// @brief Use default alignment void PopAlignment() { alignment = UI7Align_Default; } + /// @brief Get a New Position depending on the Alignment + /// @param pos Current Position + /// @param size Object size + /// @param view Viewport [position and size] + /// @param a Alignment Operations + /// @return new position based on the alignment static vec2 AlignPos(vec2 pos, vec2 size, vec4 view, UI7Align a); + /// @brief Returns a Reference to the theme + /// @return Reference to the base Theme of the context + Theme::Ref GetTheme() { return theme; } + /// @brief Directly return a Color by using the + /// m->ThemeColor(UI7Color_Text) for example + /// @param clr The Input UI7 Color + /// @return The 32bit color value + u32 ThemeColor(UI7Color clr) const { return theme->Get(clr); } /// API for Custom Objects + + /// @brief Handles the Position of Objects in Scrolling Menu + /// @note As Containers have their own FUnc to handle this, this + /// function is only useful to Render Live Objects whicch cannot be aligned + /// by the internal Alignment Api + /// @param pos position reference to write the new position to + /// @param size size of the Object + /// @return if the object can be skipped in rendering bool HandleScrolling(vec2& pos, const vec2& size); + /// @brief Get the Cursor Position + /// @return Cursor Pos vec2 Cursor() const { return cursor; } + /// @brief Set the Cursor position + /// @note The old Position can be restored with RestoreCursor + /// @param v New Position void Cursor(const vec2& v) { bcursor = cursor; cursor = v; } + /// @brief Restore to the last cursor Position void RestoreCursor() { cursor = bcursor; bcursor = vec2(); } + /// @brief Return if a Vertical Scrollbar exists bool HasVerticalScrollbar() { return scrollbar[1]; } + /// @brief Return if a Horizontal Scrollbar exists bool HasHorizontalScrollbar() { return scrollbar[0]; } + /// @brief Get the Titlebar height float TitleBarHeight() { return tbh; } /// @brief Set a Custom Titlebar heigt /// @note Could destroy some basic functionality @@ -86,39 +146,72 @@ class Menu : public SmartCtor { /// @brief Init the Cursor /// @note Useful when using with a Custom TitlebarHeight void CursorInit() { Cursor(vec2(5, tbh + 5)); } + /// @brief Move the Cursor for new Object + /// @param szs Size of the current Object void CursorMove(const vec2& szs); - + /// @brief Get the ViewArea of the Menu vec4 ViewArea() const { return view_area; } + /// @brief Get the Main Area of the Menu + /// (only relevant for input) vec4 MainArea() const { return main_area; } + /// @brief Set a MainArea for input + /// @param v Area where Objects can receive inputs void MainArea(const vec4& v) { main_area = v; } + /// @brief Get The Scrolling offset vec2 ScrollOffset() const { return scrolling_off; } + /// @brief Set a Scrolling offset + /// @param v Custom Scrolling offset void ScrollOffset(const vec2& v) { scrolling_off = v; } + /// @brief Get the Current Scrollmodification value vec2 ScrollMod() const { return scroll_mod; } + /// @brief Animated Scroll to Position + /// @param pos Destination Position void ScrollTo(vec2 pos) { scroll_anim.From(scrolling_off) .To(pos) .In(1.f) .As(scroll_anim.EaseInOutSine); } + /// @brief Check if Still in ScrollAnimation bool IsAnimatedScroll() { return !scroll_anim.IsFinished(); } - /// Objects API + /// Objects API /// + + /// @brief Push an object to the current ListHandler + /// @param obj Object reference to use + /// @return Reference to the Object (from a time + /// where ObjectPush(Container::New()) was used) Container::Ref ObjectPush(Container::Ref obj); + /// @brief Search for an Object by an id + /// @param id 32 Bit hash/id + /// @return the found Object or nullptr Container::Ref FindIDObj(u32 id); - /// Draw Lists + /// Draw Lists /// + + /// @brief Background Layer Drawlist DrawList::Ref BackList() { return back; } + /// @brief Setter for Background Layer Drawlist void BackList(DrawList::Ref v) { back = v; } + /// @brief Main Layer Drawlist DrawList::Ref MainList() { return main; } + /// @brief Setter for Main Layer Drawlist void MainList(DrawList::Ref v) { main = v; } + /// @brief Foreground Layer Drawlist DrawList::Ref FrontList() { return front; } + /// @brief Setter for Foreground Layer Drawlist void FrontList(DrawList::Ref v) { front = v; } - /// Advanced + /// Advanced /// + + /// @brief Display Debug Labels of the Menu void DebugLabels(); - /// Uneditable Stuff + /// Uneditable Stuff /// + + /// @brief Menu Name std::string GetName() const { return name; } + /// @brief Menu ID [Hash of the Name] u32 GetID() const { return id; } private: @@ -166,7 +259,7 @@ class Menu : public SmartCtor { bool scroll_allowed[2]; bool has_touch; - Menu::Ref submenu; + Container::Ref tmp_parent; /// Objects API std::vector objects; @@ -186,7 +279,7 @@ class Menu : public SmartCtor { vec2 last_size; // Theme - Theme* linked_theme; + Theme::Ref theme; // Input Reference Hid::Ref inp; diff --git a/include/pd/ui7/theme.hpp b/include/pd/ui7/theme.hpp index 15dd42a..959177e 100644 --- a/include/pd/ui7/theme.hpp +++ b/include/pd/ui7/theme.hpp @@ -48,7 +48,7 @@ enum UI7Color_ { namespace PD { namespace UI7 { /// @brief Theme Class -class Theme { +class Theme : public SmartCtor { public: public: Theme() { Default(*this); } diff --git a/include/pd/ui7/ui7.hpp b/include/pd/ui7/ui7.hpp index 946bf98..d9a4583 100644 --- a/include/pd/ui7/ui7.hpp +++ b/include/pd/ui7/ui7.hpp @@ -37,7 +37,7 @@ class Context : public SmartCtor { Context(LI::Renderer::Ref ren, Hid::Ref hid) { this->ren = ren; this->inp = hid; - Theme::Default(theme); + theme = Theme::New(); back = DrawList::New(ren); front = DrawList::New(ren); } @@ -48,8 +48,14 @@ class Context : public SmartCtor { Menu::Ref FindMenu(const ID& id); void EndMenu(); - /// Theme Management - Theme& GetTheme() { return theme; } + /// @brief Get Theme reference + /// @return Reference to the base Theme of the context + Theme::Ref GetTheme() { return theme; } + /// @brief Directly return a Color by using the + /// ctx->ThemeColor(UI7Color_Text) for example + /// @param clr The Input UI7 Color + /// @return The 32bit color value + u32 ThemeColor(UI7Color clr) const { return theme->Get(clr); } /// @brief Update Context (Render menus) /// @param delta deltatime @@ -85,7 +91,7 @@ class Context : public SmartCtor { DrawList::Ref front; DrawList::Ref back; // Theme - Theme theme; + Theme::Ref theme; // Promt Handler }; } // namespace UI7 diff --git a/source/app/app.cpp b/source/app/app.cpp index 9a4bc08..304d725 100644 --- a/source/app/app.cpp +++ b/source/app/app.cpp @@ -26,6 +26,7 @@ SOFTWARE. #include #include +#include namespace PD { int App::too; @@ -33,17 +34,17 @@ int App::too; void App::Run() { this->PreInit(); this->Init(); - last_time = Sys::GetTime(); + last_time = Sys::GetNanoTime(); while (aptMainLoop()) { input_mgr->Update(); u64 current = Sys::GetNanoTime(); float dt = static_cast(current - last_time) / 1000000.f; - app_time += dt / 1000.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)) { + if (!this->MainLoop(dt, app_time->GetSeconds())) { break; } PD::TT::End("App_MainLoop"); @@ -73,6 +74,12 @@ void App::Run() { 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; @@ -87,6 +94,9 @@ void App::PreInit() { if (InitFlags & AppInitFlags_MountRomfs) { romfsInit(); } + if (InitFlags & AppInitFlags_InitHwInfo) { + PD::HwInfo::Init(); + } if (InitFlags & AppInitFlags_UnnamedOption1) { std::filesystem::create_directories("sdmc:/palladium/apps/" + name); } @@ -103,6 +113,7 @@ void App::PreInit() { msg_mgr = MessageMgr::New(renderer); overlay_mgr = OverlayMgr::New(renderer, input_mgr); } + app_time = Timer::New(); } void App::PostDeinit() { @@ -116,6 +127,9 @@ void App::PostDeinit() { } gfxExit(); } + if (SafeInitFlags & AppInitFlags_InitHwInfo) { + PD::HwInfo::Deinit(); + } cfguExit(); if (SafeInitFlags & AppInitFlags_MountRomfs) { romfsExit(); diff --git a/source/core/timer.cpp b/source/core/timer.cpp new file mode 100644 index 0000000..ae01d32 --- /dev/null +++ b/source/core/timer.cpp @@ -0,0 +1,49 @@ +/* +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 + +namespace PD { +Timer::Timer(bool autostart) { + is_running = autostart; + Reset(); +} + +void Timer::Reset() { + start = Sys::GetTime(); + now = start; +} + +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; } +} // namespace PD \ No newline at end of file diff --git a/source/lib3ds/hwinfo.cpp b/source/lib3ds/hwinfo.cpp new file mode 100644 index 0000000..6217452 --- /dev/null +++ b/source/lib3ds/hwinfo.cpp @@ -0,0 +1,50 @@ +/* +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 + +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 +} // namespace PD \ No newline at end of file diff --git a/source/lib3ds/os.cpp b/source/lib3ds/os.cpp new file mode 100644 index 0000000..789dffc --- /dev/null +++ b/source/lib3ds/os.cpp @@ -0,0 +1,79 @@ +/* +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 + +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 \ No newline at end of file diff --git a/source/sound/mp3.cpp b/source/sound/mp3.cpp new file mode 100644 index 0000000..b4e83d6 --- /dev/null +++ b/source/sound/mp3.cpp @@ -0,0 +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 + +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 \ No newline at end of file diff --git a/source/ui7/container/button.cpp b/source/ui7/container/button.cpp index f3787bd..97e4eb4 100644 --- a/source/ui7/container/button.cpp +++ b/source/ui7/container/button.cpp @@ -48,12 +48,12 @@ void Button::HandleInput(Hid::Ref inp) { inp_done = true; } void Button::Draw() { - Assert(ren.get() && list.get() && linked_theme, + Assert(ren.get() && list.get() && theme, "Did you run Container::Init correctly?"); ren->OnScreen(screen); - list->AddRectangle(pos, size, linked_theme->Get(color)); + list->AddRectangle(pos, size, theme->Get(color)); list->AddText(pos + size * 0.5 - tdim * 0.5, label, - linked_theme->Get(UI7Color_Text)); + theme->Get(UI7Color_Text)); } } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/source/ui7/container/checkbox.cpp b/source/ui7/container/checkbox.cpp index a7777f0..ec367eb 100644 --- a/source/ui7/container/checkbox.cpp +++ b/source/ui7/container/checkbox.cpp @@ -47,15 +47,15 @@ void Checkbox::HandleInput(Hid::Ref inp) { inp_done = true; } void Checkbox::Draw() { - Assert(ren.get() && list.get() && linked_theme, + Assert(ren.get() && list.get() && theme, "Did you run Container::Init correctly?"); ren->OnScreen(screen); - list->AddRectangle(pos, cbs, linked_theme->Get(color)); + list->AddRectangle(pos, cbs, theme->Get(color)); if (usr_ref) { - list->AddRectangle(pos + 2, cbs - 4, linked_theme->Get(UI7Color_Checkmark)); + list->AddRectangle(pos + 2, cbs - 4, theme->Get(UI7Color_Checkmark)); } list->AddText(pos + vec2(cbs.x() + 5, cbs.y() * 0.5 - tdim.y() * 0.5), label, - linked_theme->Get(UI7Color_Text)); + theme->Get(UI7Color_Text)); } } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/source/ui7/container/image.cpp b/source/ui7/container/image.cpp index be23e31..2995f31 100644 --- a/source/ui7/container/image.cpp +++ b/source/ui7/container/image.cpp @@ -26,8 +26,7 @@ SOFTWARE. namespace PD { namespace UI7 { void Image::Draw() { - Assert(ren.get() && list.get() && linked_theme, - "Did you run Container::Init correctly?"); + Assert(ren.get() && list.get(), "Did you run Container::Init correctly?"); Assert(img.get(), "Image is nullptr!"); ren->OnScreen(screen); list->AddImage(pos, img); diff --git a/source/ui7/container/label.cpp b/source/ui7/container/label.cpp index 9c56da2..583590f 100644 --- a/source/ui7/container/label.cpp +++ b/source/ui7/container/label.cpp @@ -26,10 +26,10 @@ SOFTWARE. namespace PD { namespace UI7 { void Label::Draw() { - Assert(ren.get() && list.get() && linked_theme, + Assert(ren.get() && list.get() && theme, "Did you run Container::Init correctly?"); ren->OnScreen(screen); - list->AddText(pos, label, linked_theme->Get(UI7Color_Text)); + list->AddText(pos, label, theme->Get(UI7Color_Text)); } } // namespace UI7 } // namespace PD \ No newline at end of file diff --git a/source/ui7/menu.cpp b/source/ui7/menu.cpp index 34ae6fe..2a37ff5 100644 --- a/source/ui7/menu.cpp +++ b/source/ui7/menu.cpp @@ -32,7 +32,7 @@ void UI7::Menu::Label(const std::string& label) { ObjectPush(PD::New(label, Cursor(), this->back->ren)); r->SetPos(AlignPos(r->GetPos(), r->GetSize(), view_area, GetAlignment())); CursorMove(r->GetSize()); - r->Init(main->ren, main, linked_theme); + r->Init(main->ren, main, theme); r->HandleScrolling(scrolling_off, view_area); } @@ -43,7 +43,7 @@ bool UI7::Menu::Button(const std::string& label) { if (!r) { r = PD::New(label, Cursor(), this->back->ren); r->SetID(id); - r->Init(main->ren, main, linked_theme); + r->Init(main->ren, main, theme); } ObjectPush(r); r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment())); @@ -61,7 +61,7 @@ void UI7::Menu::Checkbox(const std::string& label, bool& v) { if (!r) { r = PD::New(label, Cursor(), v, this->back->ren); r->SetID(id); - r->Init(main->ren, main, linked_theme); + r->Init(main->ren, main, theme); } ObjectPush(r); r->SetPos(AlignPos(Cursor(), r->GetSize(), view_area, GetAlignment())); @@ -74,7 +74,7 @@ void UI7::Menu::Image(Texture::Ref img, vec2 size) { ObjectPush(PD::New(img, Cursor(), this->back->ren, size)); r->SetPos(AlignPos(r->GetPos(), r->GetSize(), view_area, GetAlignment())); CursorMove(r->GetSize()); - r->Init(main->ren, main, linked_theme); + r->Init(main->ren, main, theme); r->HandleScrolling(scrolling_off, view_area); } @@ -163,20 +163,19 @@ void UI7::Menu::PreHandler(UI7MenuFlags flags) { has_touch = main->GetRenderer()->CurrentScreen()->ScreenType() == Screen::Bottom; if (!(flags & UI7MenuFlags_NoBackground)) { - back->AddRectangle(0, view_area.zw(), - linked_theme->Get(UI7Color_Background)); + back->AddRectangle(0, view_area.zw(), theme->Get(UI7Color_Background)); } if (!(flags & UI7MenuFlags_NoTitlebar)) { tbh = front->GetRenderer()->TextScale() * 30.f; front->AddRectangle(0, vec2(view_area.z(), tbh), - linked_theme->Get(UI7Color_Header)); + theme->Get(UI7Color_Header)); vec2 tpos(5, tbh * 0.5 - front->ren->GetTextDimensions(name).y() * 0.5); LITextFlags tflags = LITextFlags_None; if (flags & UI7MenuFlags_CenterTitle) { tpos = 0; tflags = LITextFlags_AlignMid; } - front->AddText(tpos, this->name, linked_theme->Get(UI7Color_Text), tflags, + front->AddText(tpos, this->name, theme->Get(UI7Color_Text), tflags, vec2(view_area.z(), tbh)); main_area[1] = tbh; CursorInit(); @@ -287,12 +286,12 @@ void UI7::Menu::PostHandler() { /// Rendering Stage front->AddRectangle(vec2(screen_w - 12, tsp), vec2(slider_w * 2, szs), - linked_theme->Get(UI7Color_FrameBackground)); + theme->Get(UI7Color_FrameBackground)); front->AddRectangle(vec2(screen_w - 10, tsp + 2), vec2(slider_w, szs - 4), - linked_theme->Get(UI7Color_FrameBackgroundHovered)); + theme->Get(UI7Color_FrameBackgroundHovered)); front->AddRectangle(vec2(screen_w - 10, srpos + 2), vec2(slider_w, vslider_h), - linked_theme->Get(UI7Color_Button)); + theme->Get(UI7Color_Button)); } } TT::End("MUSR_" + name); @@ -310,7 +309,7 @@ void UI7::Menu::Separator() { if (HandleScrolling(pos, size)) { return; } - main->AddRectangle(pos, size, linked_theme->Get(UI7Color_TextDead)); + main->AddRectangle(pos, size, theme->Get(UI7Color_TextDead)); } void UI7::Menu::SeparatorText(const std::string& label) { @@ -326,11 +325,11 @@ void UI7::Menu::SeparatorText(const std::string& label) { vec2 lpos = pos + vec2((view_area.z() - 10) * 0.5 - tdim.x() * 0.5, 0); main->AddRectangle(pos + vec2(0, tdim.y() * 0.5), vec2(lpos.x() - pos.x() - 5, size.y()), - linked_theme->Get(UI7Color_TextDead)); + theme->Get(UI7Color_TextDead)); main->AddRectangle(pos + vec2(lpos.x() + tdim.x(), tdim.y() * 0.5), vec2(size.x() - (lpos.x() + tdim.x()), size.y()), - linked_theme->Get(UI7Color_TextDead)); - main->AddText(lpos, label, linked_theme->Get(UI7Color_Text), 0, + theme->Get(UI7Color_TextDead)); + main->AddText(lpos, label, theme->Get(UI7Color_Text), 0, vec2(view_area.z(), 20)); } @@ -346,6 +345,7 @@ bool UI7::Menu::HandleScrolling(vec2& pos, const vec2& size) { Container::Ref UI7::Menu::ObjectPush(Container::Ref obj) { this->objects.push_back(obj); + obj->SetParent(this->tmp_parent); return obj; } @@ -371,6 +371,10 @@ void UI7::Menu::JoinAlign(UI7Align a) { vec2 spos = join.front()->GetPos(); vec2 szs = join.back()->GetPos() + join.back()->GetSize() - spos; + for (auto it : join) { + szs.x() = + std::max(szs.x(), it->GetPos().x() + it->GetSize().x() - spos.x()); + } vec2 off; if (a & UI7Align_Center) { off[0] = (view_area[0] + view_area[2] * 0.5) - (spos[0] + szs[0] * 0.5); diff --git a/source/ui7/ui7.cpp b/source/ui7/ui7.cpp index e107265..211fcb9 100644 --- a/source/ui7/ui7.cpp +++ b/source/ui7/ui7.cpp @@ -31,7 +31,7 @@ bool UI7::Context::BeginMenu(const ID& id, UI7MenuFlags flags) { "Menu Name Already used or\nContext::Update not called!"); auto menu = this->menus.find(id); if (menu == this->menus.end()) { - this->menus[id] = Menu::New(id, &theme, inp); + this->menus[id] = Menu::New(id, theme, inp); menu = this->menus.find(id); } this->current = menu->second;