diff --git a/Firmware/sdk/CMakeLists.txt b/Firmware/sdk/CMakeLists.txt index d8611bf..19b3d6c 100644 --- a/Firmware/sdk/CMakeLists.txt +++ b/Firmware/sdk/CMakeLists.txt @@ -4,7 +4,12 @@ project(sdk-top) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED YES) +if(NOT CMAKE_CROSSCOMPILING) + set(CBSDK_BACKEND_LIBRARY cbsdk_sfml) +endif () + add_subdirectory(library) + if (NOT CMAKE_CROSSCOMPILING) add_subdirectory(sfml-port) add_subdirectory(examples) diff --git a/Firmware/sdk/examples/CMakeLists.txt b/Firmware/sdk/examples/CMakeLists.txt index e69de29..8afdb7b 100644 --- a/Firmware/sdk/examples/CMakeLists.txt +++ b/Firmware/sdk/examples/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.10) + +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + # if (NOT DEFINED SANITIZE) + # set(SANITIZE YES) + # endif () +endif () + +if (SANITIZE STREQUAL "YES") + message(STATUS "Enabling sanitizers!") + add_compile_options(-Werror -O0 -Wall -Wextra -pedantic -Wno-unused-parameter -Wno-unused-variable + -Wno-error=unused-function + -Wshadow -Wformat=2 -Wfloat-equal -D_GLIBCXX_DEBUG -Wconversion) + add_compile_options(-fsanitize=address -fno-sanitize-recover) + add_link_options(-fsanitize=address -fno-sanitize-recover) +endif () + +if (CMAKE_BUILD_TYPE STREQUAL "Release") + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) +endif () + +if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + add_compile_options(-O3) + add_link_options(-O3) +endif () + +add_executable(main src/main.cpp) + +set(CBSDK_BACKEND_INTERFACE cbsdk_sfml) + +#target_include_directories(main PRIVATE include) +#target_include_directories(main PUBLIC include_public) +target_link_libraries(main PRIVATE SFML::Graphics) +target_link_libraries(main PUBLIC cbsdk) \ No newline at end of file diff --git a/Firmware/sdk/sfml-port/src/main.cpp b/Firmware/sdk/examples/src/main.cpp similarity index 68% rename from Firmware/sdk/sfml-port/src/main.cpp rename to Firmware/sdk/examples/src/main.cpp index ecae933..716b7a0 100644 --- a/Firmware/sdk/sfml-port/src/main.cpp +++ b/Firmware/sdk/examples/src/main.cpp @@ -13,40 +13,40 @@ int main() { EventLoop loop; std::latch barrier{1}; - SfmlSurface* surface_ptr; + SurfaceBase* surface_ptr; int i = 0; std::thread loop_thread{[&] { - SfmlSurface surface(&loop); + SurfaceBase surface(&loop); surface_ptr = &surface; barrier.count_down(); - surface.set_window>(); + surface.set_window>(); - GridWindow* window = - static_cast*>(surface.get_window()); - window->set_window, std::string>>(0, 0, &loop, "hello"); - window->set_window, std::string>>(0, 1, &loop, "hello1"); - window->set_window, 2, 2>>(1, 0); - GridWindow, 2, 2>* window2 = - static_cast, 2, 2>*>( + GridWindow* window = + static_cast*>(surface.get_window()); + window->set_window, std::string>>(0, 0, &loop, "hello"); + window->set_window, std::string>>(0, 1, &loop, "hello1"); + window->set_window, 2, 2>>(1, 0); + GridWindow, 2, 2>* window2 = + static_cast, 2, 2>*>( window->get_subsurface(1, 0).get_window()); - window->set_window, std::string>>(1, 1, &loop, "hello3"); + window->set_window, std::string>>(1, 1, &loop, "hello3"); - window2->set_window, std::string>>( + window2->set_window, std::string>>( 0, 0, &loop, "hello2"); - window2->set_window, std::string>>( + window2->set_window, std::string>>( 0, 1, &loop, "hello4"); - window2->set_window, std::string>>( + window2->set_window, std::string>>( 1, 0, &loop, "hello5"); - window2->set_window, std::string>>( + window2->set_window, std::string>>( 1, 1, &loop, "hello6"); loop.run([&] { surface._sf_window.clear(); surface._texture.update(surface._image); surface._sf_window.draw(surface._sprite); surface._sf_window.display(); - static_cast, std::string>*>( + static_cast, std::string>*>( window->get_subsurface(0, 0).get_window()) ->push(TextUpdateEvent{std::string("Hello, SFML!") + std::to_string(i++)}); }); diff --git a/Firmware/sdk/library/CMakeLists.txt b/Firmware/sdk/library/CMakeLists.txt index 1eac6a5..fe4ffae 100644 --- a/Firmware/sdk/library/CMakeLists.txt +++ b/Firmware/sdk/library/CMakeLists.txt @@ -1,5 +1,7 @@ cmake_minimum_required(VERSION 3.10) +add_subdirectory(backend_interface) + add_library(cbsdk src/Window.cpp include_public/Window.hpp @@ -12,11 +14,18 @@ add_library(cbsdk src/TextWindow.cpp include_public/TextWindow.hpp include_public/utils.hpp - include_public/SubSurface.hpp) + include_public/SubSurface.hpp + src/Surface.cpp) target_include_directories(cbsdk PUBLIC include_public) target_include_directories(cbsdk PRIVATE include) +if(NOT CBSDK_BACKEND_LIBRARY) + message(FATAL_ERROR "CBSDK_BACKEND_LIBRARY not set!") +endif () + +target_link_libraries(cbsdk PUBLIC cbsdk_backend_interface ${CBSDK_BACKEND_LIBRARY}) + if (NOT CMAKE_CROSSCOMPILING) add_subdirectory(test) endif () \ No newline at end of file diff --git a/Firmware/sdk/library/backend_interface/CMakeLists.txt b/Firmware/sdk/library/backend_interface/CMakeLists.txt new file mode 100644 index 0000000..eb56214 --- /dev/null +++ b/Firmware/sdk/library/backend_interface/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.10) + +add_library(cbsdk_backend_interface INTERFACE + include_public/backend_interface.hpp) + +target_include_directories(cbsdk_backend_interface INTERFACE include_public) + +#if (NOT CMAKE_CROSSCOMPILING) +# add_subdirectory(test) +#endif () \ No newline at end of file diff --git a/Firmware/sdk/library/backend_interface/include_public/backend_interface.hpp b/Firmware/sdk/library/backend_interface/include_public/backend_interface.hpp new file mode 100644 index 0000000..9707947 --- /dev/null +++ b/Firmware/sdk/library/backend_interface/include_public/backend_interface.hpp @@ -0,0 +1,15 @@ +// +// Created by stepus53 on 14.08.25. +// + +#ifndef SDK_TOP_BACKEND_INTERFACE_HPP +#define SDK_TOP_BACKEND_INTERFACE_HPP + +namespace SdkPort { + +struct Pixel; +class SurfaceBase; + +} // namespace SdkPort + +#endif // SDK_TOP_BACKEND_INTERFACE_HPP diff --git a/Firmware/sdk/library/include_public/Event.hpp b/Firmware/sdk/library/include_public/Event.hpp index 4643151..5cda8d9 100644 --- a/Firmware/sdk/library/include_public/Event.hpp +++ b/Firmware/sdk/library/include_public/Event.hpp @@ -15,6 +15,8 @@ #include #include +#include "utils.hpp" + enum class EventHandlingResult { DONE, IGNORE, CONTINUE }; class Event {}; @@ -37,6 +39,8 @@ template class EventHandler { public: EventHandler() { static_assert(HandlesAll); } + + using HandledTypes = type_list; }; class EventLoop; diff --git a/Firmware/sdk/library/include_public/GridWindow.hpp b/Firmware/sdk/library/include_public/GridWindow.hpp index a1f5881..9da1ccd 100644 --- a/Firmware/sdk/library/include_public/GridWindow.hpp +++ b/Firmware/sdk/library/include_public/GridWindow.hpp @@ -11,12 +11,10 @@ #include "Window.hpp" #include "utils.hpp" -template -class GridWindow : public Window { +template +class GridWindow : public Window { public: - using PixelType = typename SurfaceType::PixelType; - - explicit GridWindow(SurfaceType* owner) : Window(owner) { + explicit GridWindow(SubSurface* owner) : Window(owner) { for (int i = 0; i < nWidth; ++i) { for (int j = 0; j < nHeight; ++j) { _grid[i][j].emplace(owner); @@ -74,13 +72,9 @@ public: _cell_height = this->_owner->get_height() / nHeight; for (int i = 0; i < nWidth; ++i) { for (int j = 0; j < nHeight; ++j) { - if constexpr (is_specialization_of::value) { - _grid[i][j]->set_pos(this->_owner->get_x_offset() + i * _cell_width + 1, - this->_owner->get_y_offset() + j * _cell_height + 1, _cell_width - 2, - _cell_height - 2); - } else { - _grid[i][j]->set_pos(i * _cell_width + 1, j * _cell_height + 1, _cell_width - 2, _cell_height - 2); - } + _grid[i][j]->set_pos(this->_owner->get_x_offset() + i * _cell_width + 1, + this->_owner->get_y_offset() + j * _cell_height + 1, _cell_width - 2, + _cell_height - 2); } } refresh(); @@ -92,7 +86,7 @@ public: _grid[x][y]->template set_window(std::forward(args)...); } - SubSurface& get_subsurface(unsigned x, unsigned y) { + SubSurface& get_subsurface(unsigned x, unsigned y) { // assert(x >= nWidth && y >= nHeight); return *_grid[x][y]; } @@ -101,21 +95,16 @@ public: for (int i = 0; i < nWidth; ++i) { for (int j = 0; j < nHeight; ++j) { if (i == _current_focus_x && j == _current_focus_y) { - this->_owner->draw_rect(i * _cell_width, j * _cell_height, _cell_width, _cell_height, - PixelType(true)); + this->_owner->draw_rect(i * _cell_width, j * _cell_height, _cell_width, _cell_height, Pixel(true)); } else { - this->_owner->draw_rect(i * _cell_width, j * _cell_height, _cell_width, _cell_height, - PixelType(false)); + this->_owner->draw_rect(i * _cell_width, j * _cell_height, _cell_width, _cell_height, Pixel(false)); } } } } private: - using SubType = std::conditional_t::value, SurfaceType, - SubSurface>; - - std::array, nWidth>, nHeight> _grid; + std::array, nWidth>, nHeight> _grid; unsigned _cell_width = 0; unsigned _cell_height = 0; diff --git a/Firmware/sdk/library/include_public/Pixel.hpp b/Firmware/sdk/library/include_public/Pixel.hpp index 60a297c..eff32df 100644 --- a/Firmware/sdk/library/include_public/Pixel.hpp +++ b/Firmware/sdk/library/include_public/Pixel.hpp @@ -5,17 +5,8 @@ #ifndef PIXEL_HPP #define PIXEL_HPP -class Pixel { -}; +#include "port_pixel.hpp" -struct BwPixel : public Pixel { - bool on = false; - - BwPixel() = default; - BwPixel(bool on) : on(on) {} - - bool operator==(const BwPixel& other) const { return on == other.on; } - bool operator!=(const BwPixel& other) const { return !(*this == other); } -}; +using Pixel = SdkPort::Pixel; #endif //PIXEL_HPP diff --git a/Firmware/sdk/library/include_public/SubSurface.hpp b/Firmware/sdk/library/include_public/SubSurface.hpp index 010b00f..3603470 100644 --- a/Firmware/sdk/library/include_public/SubSurface.hpp +++ b/Firmware/sdk/library/include_public/SubSurface.hpp @@ -14,15 +14,12 @@ #include "Window.hpp" #include "utils.hpp" -template -class SubSurface : public Surface, typename SurfaceParent::PixelType> { +class SubSurface : public StandardEventHandler { public: - using PixelType = typename SurfaceParent::PixelType; + SubSurface(Surface* parent) : _parent(parent) {} + SubSurface(SubSurface* parent) : _parent(parent->_parent) {} - SubSurface(SurfaceParent* parent) : _parent(parent) {} - SubSurface(SubSurface* parent) : _parent(parent->_parent) {} - - void draw_pixel_impl(unsigned x, unsigned y, const PixelType& pixel) { + void draw_pixel_impl(unsigned x, unsigned y, const Pixel& pixel) { if (x >= _x_size || y >= _y_size) { assert(false); } @@ -46,13 +43,33 @@ public: this->handle(SurfaceResizeEvent(x_size, y_size)); } + template + EventHandlingResult handle(const T& event) { + if (_window.get()) + return _window->handle(event); + return EventHandlingResult::CONTINUE; + } + + template + void set_window(Args&&... args) { + _window = std::make_unique(std::forward(args)...); + } + + bool has_window() const { return _window != nullptr; } + + Window* get_window() { + assert(has_window()); + return _window.get(); + } + private: unsigned _x_offset = 0; unsigned _y_offset = 0; unsigned _x_size = 0; unsigned _y_size = 0; - SurfaceParent* _parent; + Surface* _parent; + std::unique_ptr _window; }; #endif // SUBSURFACE_HPP diff --git a/Firmware/sdk/library/include_public/Surface.hpp b/Firmware/sdk/library/include_public/Surface.hpp index 8b7d873..46d5e8b 100644 --- a/Firmware/sdk/library/include_public/Surface.hpp +++ b/Firmware/sdk/library/include_public/Surface.hpp @@ -12,19 +12,17 @@ #include "Pixel.hpp" #include "StandardEvents.hpp" #include "Window.hpp" +#include "backend_interface.hpp" #include "utils.hpp" -template - requires std::is_base_of_v -class Surface : public StandardEventHandler { +class SubSurface; + +class Surface : public StandardEventHandler, public SdkPort::SurfaceBase { public: - Surface() { static_assert(std::is_same_v); } + Surface(); + ~Surface(); - void draw_pixel(unsigned x, unsigned y, const BwPixel& pixel) { - static_cast(this)->draw_pixel_impl(x, y, pixel); - } - - void draw_rect(unsigned x, unsigned y, unsigned width, unsigned height, const BwPixel& pixel) { + void draw_rect(unsigned x, unsigned y, unsigned width, unsigned height, const Pixel& pixel) { for (unsigned i = 0; i < width; ++i) { draw_pixel(x + i, y, pixel); draw_pixel(x + i, y + height - 1, pixel); @@ -38,44 +36,17 @@ public: void clear() { for (unsigned x = 0; x < get_width(); x++) { for (unsigned y = 0; y < get_height(); y++) { - draw_pixel(x, y, PixelType()); + draw_pixel(x, y, Pixel()); } } } - int get_width() const { return static_cast(this)->get_width_impl(); } - - int get_height() const { return static_cast(this)->get_height_impl(); } - template - EventHandlingResult handle(const T& event) { - if (_window.get()) - return _window->handle(event); - return EventHandlingResult::CONTINUE; - } - - template - void set_window(Args&&... args) { - _window = std::make_unique(static_cast(this), std::forward(args)...); - } - - Surface(const Surface& other) = delete; - - Surface(Surface&& other) noexcept = delete; - - Surface& operator=(const Surface& other) = delete; - - Surface& operator=(Surface&& other) noexcept = delete; - - bool has_window() const { return _window != nullptr; } - - Window* get_window() { - assert(has_window()); - return _window.get(); - } + EventHandlingResult handle(const T& event); + SubSurface& get_subsurface(); protected: - std::unique_ptr> _window = nullptr; + SubSurface* _subsurface = nullptr; }; #endif // SURFACE_HPP diff --git a/Firmware/sdk/library/include_public/Window.hpp b/Firmware/sdk/library/include_public/Window.hpp index c6788b4..ae69d65 100644 --- a/Firmware/sdk/library/include_public/Window.hpp +++ b/Firmware/sdk/library/include_public/Window.hpp @@ -10,18 +10,12 @@ #include "Event.hpp" #include "Pixel.hpp" #include "StandardEvents.hpp" +#include "SubSurface.hpp" #include "utils.hpp" -template - requires std::is_base_of_v -class Surface; - -template -class Window : StandardEventHandler> { +class Window : StandardEventHandler { public: - using PixelType = typename SurfaceType::PixelType; - - explicit Window(SurfaceType* owner) : _owner(owner) { + explicit Window(SubSurface* owner) : _owner(owner) { // static_assert(is_specialization_of::value); } @@ -34,7 +28,7 @@ public: virtual EventHandlingResult handle_v(SurfaceResizeEvent) { return EventHandlingResult::CONTINUE; } protected: - SurfaceType* _owner = nullptr; + SubSurface* _owner = nullptr; }; #endif // SURFACE_HPP diff --git a/Firmware/sdk/library/include_public/utils.hpp b/Firmware/sdk/library/include_public/utils.hpp index e83ee0c..284894c 100644 --- a/Firmware/sdk/library/include_public/utils.hpp +++ b/Firmware/sdk/library/include_public/utils.hpp @@ -5,10 +5,32 @@ #ifndef UTILS_HPP #define UTILS_HPP +template +struct type_list {}; + template