diff --git a/CMakeLists.txt b/CMakeLists.txt index d256c5b..9087b8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ else() endif() message("II SOLANACEAE_CRDTNOTES_STANDALONE " ${SOLANACEAE_CRDTNOTES_STANDALONE}) +option(SOLANACEAE_CRDTNOTES_BUILD_PLUGINS "Build the crdtnotes plugins" ${SOLANACEAE_CRDTNOTES_STANDALONE}) + if (SOLANACEAE_CRDTNOTES_STANDALONE) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -31,7 +33,7 @@ if (SOLANACEAE_CRDTNOTES_STANDALONE) endif() # external libs -add_subdirectory(./external) # before increasing warn levels, sad :( +add_subdirectory(./external EXCLUDE_FROM_ALL) # before increasing warn levels, sad :( if (SOLANACEAE_CRDTNOTES_STANDALONE) set(CMAKE_CXX_EXTENSIONS OFF) @@ -65,3 +67,7 @@ endif() add_subdirectory(./src) +if (SOLANACEAE_CRDTNOTES_BUILD_PLUGINS) + add_subdirectory(./plugins) +endif() + diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index fabd5a0..e7d526d 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -10,3 +10,53 @@ if (NOT TARGET crdt_version3) FetchContent_MakeAvailable(crdt_version3) endif() +if (NOT TARGET imgui) + FetchContent_Declare(imgui + GIT_REPOSITORY https://github.com/ocornut/imgui.git + GIT_TAG d4ddc46e7 + ) + + # imgui does not provide a cmake + #FetchContent_GetProperties(imgui_interface) + #if(NOT imgui_interface_POPULATED) + #FetchContent_Populate(imgui_interface) + + #add_library(imgui_interface INTERFACE + #${imgui_interface_SOURCE_DIR}/imgui.h + #${imgui_interface_SOURCE_DIR}/misc/cpp/imgui_stdlib.h + #) + #target_include_directories(imgui_interface INTERFACE ${imgui_interface_SOURCE_DIR}) + #endif() + FetchContent_GetProperties(imgui) + if(NOT imgui_POPULATED) + FetchContent_Populate(imgui) + + add_library(imgui STATIC + ${imgui_SOURCE_DIR}/imgui.h + ${imgui_SOURCE_DIR}/imgui_internal.h + + ${imgui_SOURCE_DIR}/imgui.cpp + ${imgui_SOURCE_DIR}/imgui_demo.cpp + ${imgui_SOURCE_DIR}/imgui_draw.cpp + ${imgui_SOURCE_DIR}/imgui_tables.cpp + ${imgui_SOURCE_DIR}/imgui_widgets.cpp + ${imgui_SOURCE_DIR}/imstb_rectpack.h + ${imgui_SOURCE_DIR}/imstb_textedit.h + ${imgui_SOURCE_DIR}/imstb_truetype.h + + ${imgui_SOURCE_DIR}/misc/cpp/imgui_stdlib.h + ${imgui_SOURCE_DIR}/misc/cpp/imgui_stdlib.cpp + ) + target_include_directories(imgui PUBLIC ${imgui_SOURCE_DIR}) + endif() + #FetchContent_MakeAvailable(imgui) +endif() + +if (NOT TARGET solanaceae_plugin) + FetchContent_Declare(solanaceae_plugin + GIT_REPOSITORY https://github.com/Green-Sky/solanaceae_plugin.git + GIT_TAG master + ) + FetchContent_MakeAvailable(solanaceae_plugin) +endif() + diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 0000000..d127b2c --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.24 FATAL_ERROR) + +add_library(plugin_crdtnotes SHARED + ./plugin_crdtnotes.cpp +) +target_compile_features(plugin_crdtnotes PUBLIC cxx_std_17) +target_link_libraries(plugin_crdtnotes PUBLIC + solanaceae_crdtnotes + solanaceae_plugin +) + +######################################## + +add_library(plugin_crdtnotes_imgui SHARED + ./plugin_crdtnotes_imgui.cpp +) +target_compile_features(plugin_crdtnotes_imgui PUBLIC cxx_std_17) +target_link_libraries(plugin_crdtnotes_imgui PUBLIC + solanaceae_crdtnotes_imgui + solanaceae_plugin +) + +######################################## + diff --git a/plugins/plugin_crdtnotes.cpp b/plugins/plugin_crdtnotes.cpp new file mode 100644 index 0000000..8e33465 --- /dev/null +++ b/plugins/plugin_crdtnotes.cpp @@ -0,0 +1,65 @@ +#include + +#include +//#include + +#include +#include + +#define RESOLVE_INSTANCE(x) static_cast(solana_api->resolveInstance(#x)) +#define PROVIDE_INSTANCE(x, p, v) solana_api->provideInstance(#x, p, static_cast(v)) + +static std::unique_ptr g_crdtn = nullptr; + +extern "C" { + +SOLANA_PLUGIN_EXPORT const char* solana_plugin_get_name(void) { + return "CRDTNotes"; +} + +SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_get_version(void) { + return SOLANA_PLUGIN_VERSION; +} + +SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api) { + std::cout << "PLUGIN CRDTN START()\n"; + + if (solana_api == nullptr) { + return 1; + } + + //ConfigModelI* conf = nullptr; + + { // make sure required types are loaded + //conf = RESOLVE_INSTANCE(ConfigModelI); + + //if (conf == nullptr) { + //std::cerr << "PLUGIN CRDTN missing ConfigModelI\n"; + //return 2; + //} + } + + // static store, could be anywhere tho + // construct with fetched dependencies + g_crdtn = std::make_unique(/**conf*/); + + // register types + PROVIDE_INSTANCE(CRDTNotes, "CRDTNotes", g_crdtn.get()); + + return 0; +} + +SOLANA_PLUGIN_EXPORT void solana_plugin_stop(void) { + std::cout << "PLUGIN CRDTN STOP()\n"; + + g_crdtn.reset(); +} + +SOLANA_PLUGIN_EXPORT void solana_plugin_tick(float delta) { + (void)delta; + //std::cout << "PLUGIN CRDTN TICK()\n"; + //g_crdtn->iterate(); +} + +} // extern C + diff --git a/plugins/plugin_crdtnotes_imgui.cpp b/plugins/plugin_crdtnotes_imgui.cpp new file mode 100644 index 0000000..66ee6a8 --- /dev/null +++ b/plugins/plugin_crdtnotes_imgui.cpp @@ -0,0 +1,82 @@ +#include + +#include +//#include +#include + +#include +#include + +#define RESOLVE_INSTANCE(x) static_cast(solana_api->resolveInstance(#x)) +#define PROVIDE_INSTANCE(x, p, v) solana_api->provideInstance(#x, p, static_cast(v)) + +static std::unique_ptr g_crdtn_imgui = nullptr; + +extern "C" { + +SOLANA_PLUGIN_EXPORT const char* solana_plugin_get_name(void) { + return "CRDTNIMGUIotesImGui"; +} + +SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_get_version(void) { + return SOLANA_PLUGIN_VERSION; +} + +SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api) { + std::cout << "PLUGIN CRDTNIMGUI START()\n"; + + if (solana_api == nullptr) { + return 1; + } + + //ConfigModelI* conf = nullptr; + CRDTNotes* crdtn = nullptr; + ImGuiContext* imguic = nullptr; + + { // make sure required types are loaded + //conf = RESOLVE_INSTANCE(ConfigModelI); + crdtn = RESOLVE_INSTANCE(CRDTNotes); + imguic = RESOLVE_INSTANCE(ImGuiContext); + + //if (conf == nullptr) { + //std::cerr << "PLUGIN CRDTNIMGUI missing ConfigModelI\n"; + //return 2; + //} + + if (crdtn == nullptr) { + std::cerr << "PLUGIN CRDTNIMGUI missing CRDTNotes\n"; + return 2; + } + + if (imguic == nullptr) { + std::cerr << "PLUGIN CRDTNIMGUI missing ImGuiContext\n"; + return 2; + } + } + + ImGui::SetCurrentContext(imguic); + + // static store, could be anywhere tho + // construct with fetched dependencies + g_crdtn_imgui = std::make_unique(*crdtn); + + // register types + PROVIDE_INSTANCE(CRDTNotesImGui, "CRDTNotesImGui", g_crdtn_imgui.get()); + + return 0; +} + +SOLANA_PLUGIN_EXPORT void solana_plugin_stop(void) { + std::cout << "PLUGIN CRDTNIMGUI STOP()\n"; + + g_crdtn_imgui.reset(); +} + +SOLANA_PLUGIN_EXPORT void solana_plugin_tick(float delta) { + (void)delta; + //std::cout << "PLUGIN CRDTNIMGUI TICK()\n"; + g_crdtn_imgui->render(); +} + +} // extern C + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9e32f5f..d71be19 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,3 +13,17 @@ target_link_libraries(solanaceae_crdtnotes PUBLIC ######################################## +add_library(solanaceae_crdtnotes_imgui + ./solanaceae/crdtnotes_imgui/crdtnotes_imgui.hpp + ./solanaceae/crdtnotes_imgui/crdtnotes_imgui.cpp +) +target_include_directories(solanaceae_crdtnotes_imgui PUBLIC .) +target_compile_features(solanaceae_crdtnotes_imgui PUBLIC cxx_std_17) +target_link_libraries(solanaceae_crdtnotes_imgui PUBLIC + solanaceae_crdtnotes + #imgui_interface + imgui + #solanaceae_util +) + +######################################## diff --git a/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.cpp b/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.cpp new file mode 100644 index 0000000..083eb5f --- /dev/null +++ b/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.cpp @@ -0,0 +1,60 @@ +#include "./crdtnotes_imgui.hpp" + +#include + +#include + +namespace detail { + uint8_t nib_from_hex(char c) { + assert((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')); + + if (c >= '0' && c <= '9') { + return static_cast(c) - '0'; + } else if (c >= 'a' && c <= 'f') { + return (static_cast(c) - 'a') + 10u; + } else { + return 0u; + } + } + char nib_to_hex(uint8_t c) { + assert((c & 0xf0) == 0x00); + + if (/*c >= 0x00 &&*/ c <= 0x09) { + return static_cast(c) + '0'; + } else if (c >= 0x0a && c <= 0x0f) { + return (static_cast(c) + 'a') - 10u; + } else { + return 0u; + } + } + + template + std::string to_hex(const Container& data) { + std::string res; + for (const uint8_t it : data) { + res += nib_to_hex(it << 4); + res += nib_to_hex(it & 0x0f); + } + return res; + } +} // detail + + +CRDTNotesImGui::CRDTNotesImGui(CRDTNotes& notes) : _notes(notes) { +} + +float CRDTNotesImGui::render(void) { + if (_show_global_list) { + if (ImGui::Begin("CRDTNotes - Global list")) { + const auto doclist = _notes.getDocList(); + for (const auto& docid : doclist) { + const auto docid_str = detail::to_hex(docid); + ImGui::TextUnformatted(docid_str.c_str()); + } + } + ImGui::End(); + } + + return 1.f; +} + diff --git a/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.hpp b/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.hpp new file mode 100644 index 0000000..8a6422d --- /dev/null +++ b/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +class CRDTNotesImGui { + CRDTNotes& _notes; + + bool _show_global_list {true}; + + public: + CRDTNotesImGui(CRDTNotes& notes); + + float render(void); +}; +