diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 207649f8..7b758b8e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,7 +31,7 @@ jobs: run: | sudo apt update sudo apt upgrade -y - sudo apt install -y build-essential wget cmake libvpx-dev gcc-11 libgl1-mesa-glx libgl1-mesa-dev libglew-dev ninja-build python3-pip libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxcomposite-dev libxcursor-dev libxdamage-dev libxdmcp-dev libxext-dev libxfixes-dev libxft-dev libxi-dev libxinerama-dev libxkbfile-dev libxmu-dev libxmuu-dev libxpm-dev libxrandr-dev libxrender-dev libxres-dev libxss-dev libxt-dev libxtst-dev libxv-dev libxvmc-dev libxxf86vm-dev xtrans-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev xkb-data libxcb-dri3-dev uuid-dev libxcb-util-dev + sudo apt install -y build-essential wget cmake libssl-dev libvpx-dev gcc-11 libgl1-mesa-glx libgl1-mesa-dev libglew-dev ninja-build python3-pip libx11-dev libx11-xcb-dev libfontenc-dev libice-dev libsm-dev libxau-dev libxaw7-dev libxcomposite-dev libxcursor-dev libxdamage-dev libxdmcp-dev libxext-dev libxfixes-dev libxft-dev libxi-dev libxinerama-dev libxkbfile-dev libxmu-dev libxmuu-dev libxpm-dev libxrandr-dev libxrender-dev libxres-dev libxss-dev libxt-dev libxtst-dev libxv-dev libxvmc-dev libxxf86vm-dev xtrans-dev libxcb-render0-dev libxcb-render-util0-dev libxcb-xkb-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-randr0-dev libxcb-shape0-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-xinerama0-dev xkb-data libxcb-dri3-dev uuid-dev libxcb-util-dev - name: Restore cache id: cache @@ -40,7 +40,7 @@ jobs: path: | ./build ~/cpm-cache - key: host-${{ runner.os }}-${{ hashFiles('./CMakeLists.txt', './bass/CMakeLists.txt', './engine/CMakeLists.txt', './math/CMakeLists.txt', './render/CMakeLists.txt', './resources/CMakeLists.txt', './ui/CMakeLists.txt', './utils/CMakeLists.txt', './physics_3d/CMakeLists.txt', './physics_2d/CMakeLists.txt', './webm/CMakeLists.txt', './assimp/CMakeLists.txt') }} + key: host-${{ runner.os }}-${{ hashFiles('./CMakeLists.txt', './bass/CMakeLists.txt', './engine/CMakeLists.txt', './math/CMakeLists.txt', './render/CMakeLists.txt', './resources/CMakeLists.txt', './ui/CMakeLists.txt', './utils/CMakeLists.txt', './physics_3d/CMakeLists.txt', './physics_2d/CMakeLists.txt', './webm/CMakeLists.txt', './assimp/CMakeLists.txt', './scripting/CMakeLists.txt') }} - name: Build id: build @@ -58,7 +58,7 @@ jobs: path: | ./build ~/cpm-cache - key: host-${{ runner.os }}-${{ hashFiles('./CMakeLists.txt', './bass/CMakeLists.txt', './engine/CMakeLists.txt', './math/CMakeLists.txt', './render/CMakeLists.txt', './resources/CMakeLists.txt', './ui/CMakeLists.txt', './utils/CMakeLists.txt', './physics_3d/CMakeLists.txt', './physics_2d/CMakeLists.txt', './webm/CMakeLists.txt', './assimp/CMakeLists.txt') }} + key: host-${{ runner.os }}-${{ hashFiles('./CMakeLists.txt', './bass/CMakeLists.txt', './engine/CMakeLists.txt', './math/CMakeLists.txt', './render/CMakeLists.txt', './resources/CMakeLists.txt', './ui/CMakeLists.txt', './utils/CMakeLists.txt', './physics_3d/CMakeLists.txt', './physics_2d/CMakeLists.txt', './webm/CMakeLists.txt', './assimp/CMakeLists.txt', './scripting/CMakeLists.txt') }} - name: Run tests run: | diff --git a/.vscode/settings.json b/.vscode/settings.json index e6c4c723..2076808f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,6 +11,12 @@ "isTable", "isString", "json", - "fmt" + "fmt", + "printTable", + "scripting", + "stencil", + "http", + "curtime", + "BGFX_FRAME" ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index ff67011a..97c39237 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -55,7 +55,7 @@ { "label": "Clean project", "type": "shell", - "command": "rm -rf build bin .cache", + "command": "rm -rf build bin .cache bass/deps webm/deps", "group": "build", "options": { "cwd": "${workspaceFolder}" diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ca5cd62..aa7984af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ list(PREPEND CONAN_GENERATORS_FOLDER ${CMAKE_BINARY_DIR}) # --- # OPTIONS --- -option(BUILD_TESTING "Build tests" ON) +option(RAWRBOX_BUILD_TESTING "Build tests" ON) option(RAWRBOX_USE_WAYLAND "Use Wayland for linux" OFF) option(RAWRBOX_BUILD_SAMPLES "Build samples" ON) @@ -52,6 +52,7 @@ if(RAWRBOX_BUILD_RAWRBOX_3D_PHYSICS) endif() option(RAWRBOX_ENABLE_QHULL "Include QHull on utils" ON) +option(RAWRBOX_ENABLE_HTTP_REQUEST "Include HTTP requests on utils" ON) # ----- # OTHER SETTINGS ---- @@ -97,11 +98,7 @@ set(CMAKE_SKIP_RPATH TRUE) set(CMAKE_SKIP_BUILD_RPATH TRUE) # --------------------------------- -# SETUP CCACHE --- -CPMAddPackage("gh:TheLartians/Ccache.cmake@1.2.4") -# -------------- - -# PACKAGES ------ +# GLOBAL PACKAGES ------ CPMAddPackage("gh:fmtlib/fmt#10.0.0") if(fmt_ADDED) set_lib_runtime_mt(fmt) @@ -115,6 +112,22 @@ endif() if(NOT WIN32 AND RAWRBOX_USE_WAYLAND) CPMAddPackage("gl:wayland/weston@12.0.1") endif() + +CPMAddPackage( + NAME + nlohmann_json + VERSION + 3.11.2 + # the git repo is incredibly large, so we download the archived include directory + URL + https://github.com/nlohmann/json/releases/download/v3.11.2/include.zip + URL_HASH + SHA256=e5c7a9f49a16814be27e4ed0ee900ecd0092bfb7dbfca65b5a421b774dccaaed) + +if(nlohmann_json_ADDED) + add_library(nlohmann_json INTERFACE IMPORTED) + target_include_directories(nlohmann_json INTERFACE ${nlohmann_json_SOURCE_DIR}/include) +endif() # -------------------- add_subdirectory("math") @@ -164,6 +177,10 @@ if(RAWRBOX_BUILD_RAWRBOX_2D_PHYSICS) endif() if(RAWRBOX_BUILD_SAMPLES) - message(STATUS "Enabled SAMPLES building") - add_subdirectory("samples") + if(NOT RAWRBOX_BUILD_RAWRBOX_RESOURCES) + message(WARNING "Samples require RAWRBOX.RESOURCES to be enabled") + else() + message(STATUS "Enabled SAMPLES building") + add_subdirectory("samples") + endif() endif() diff --git a/README.md b/README.md index c410333f..73ce73d9 100644 --- a/README.md +++ b/README.md @@ -25,24 +25,26 @@ # FEATURES (so far) -- Model loading (animations, light, texture import) using assimp +- Model loading (animations, light, texture import) using [assimp](https://github.com/assimp/assimp) - Light support (point, spot, directional) -- Clustered rendering +- Clustered rendering & support for other type of rendering - 3D text - 2D stencil drawing -- Fonts -- Images (png, jpeg, tga, bitmap) -- Video (webm) -- Sounds (using BASS lib) +- Fonts (ttf) using [stb](https://github.com/nothings/stb) +- JSON loading using [nlohmann json](https://github.com/nlohmann/json) +- Images (png, jpeg, tga, bitmap, gif) using [stb](https://github.com/nothings/stb) +- Video ([webm](https://github.com/webmproject/libwebm)) +- Sounds (using [BASS](https://www.un4seen.com/) lib) - Custom UI - Material system (similar to unity) -- GIF loading & animation -- Vulkan / DirectX / OpenGL support +- Vulkan / DirectX / OpenGL support using [BGFX](https://github.com/bkaradzic/bgfx) - Linux Wayland support + steam deck support - 3D Physics system using [JoltPhysics](https://github.com/jrouwe/JoltPhysics) - 2D Physics system using [Muli](https://github.com/Sopiro/Muli) - Decal system -- Scripting / modding support with LUA +- Scripting / modding support with LUA using [sol2](https://github.com/ThePhD/sol2) and [luajit2](https://github.com/openresty/luajit2) +- Post-processing effects support +- HTTP / HTTPS requests using curl + [libcpr](https://github.com/libcpr/cpr) # TODO LIST @@ -79,7 +81,7 @@ | OPTION NAME | NOTE | | :------------------------------------------- | :------------------------------------------------------------------------------------------------- | -| `BUILD_TESTING` | Builds & enables project tests | +| `RAWRBOX_BUILD_TESTING` | Builds & enables project tests | | -- | -- | | `RAWRBOX_OUTPUT_BIN` | The output build folder. Default is `bin` | | `RAWRBOX_CONTENT_FOLDER` | The content folder to output resources. Default is `content` | @@ -87,6 +89,7 @@ | `RAWRBOX_USE_WAYLAND` | Enables WAYLAND compiling on LINUX | | -- | -- | | `RAWRBOX_ENABLE_QHULL` | Enables QHull util | +| `RAWRBOX_ENABLE_HTTP_REQUEST` | Enables HTTP / HTTPS requests util | | -- | -- | | `RAWRBOX_BUILD_SAMPLES` | Builds the project sample | | `RAWRBOX_BUILD_RAWRBOX_UI` | Builds and includes ui | @@ -124,6 +127,7 @@ | muli | ✖️ | Used for managing 2D physics | | webmlib & vpx | ✖️ | Used for loading webm | | lua & sol2 & luajit | ✖️ | Used for loading & managing lua scripting | +| curl + libcpr | ✖️ | Used for HTTP / HTTPS requests | # BUILDING @@ -160,7 +164,7 @@ ### 001-stencil - + ### 002-generated-models @@ -192,7 +196,7 @@ ### 009-physics - + ### 010-instancing diff --git a/assimp/CMakeLists.txt b/assimp/CMakeLists.txt index ecf937e1..d0f8dd55 100644 --- a/assimp/CMakeLists.txt +++ b/assimp/CMakeLists.txt @@ -3,39 +3,48 @@ project("RAWRBOX.ASSIMP" VERSION ${RAWRBOX_VERSION} DESCRIPTION "RawrBox - ASSIM set(output_target RAWRBOX.ASSIMP) # LIBS --- +find_package(ZLIB QUIET) +if(ZLIB_FOUND) + message(STATUS "Found zlib, turning off build zlib on assimp") + set(BUILD_ZLIB 0) + set(ZLIB_FOUND 0) # Because assimp will then try to install invalid targets +else() + set(BUILD_ZLIB 1) +endif() + CPMAddPackage( NAME assimp - VERSION - 5.2.5 + GIT_TAG + master GITHUB_REPOSITORY assimp/assimp OPTIONS - "BUILD_SHARED_LIBS OFF" - "ASSIMP_NO_EXPORT ON" - "ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT OFF" - "ASSIMP_INSTALL ON" - "ASSIMP_BUILD_ASSIMP_TOOLS OFF" - "ASSIMP_BUILD_TESTS OFF" - "ASSIMP_BUILD_SAMPLES OFF" - "ASSIMP_BUILD_DOCS OFF" - "USE_STATIC_CRT ON" - "ASSIMP_BUILD_ASSIMP_VIEW OFF" - "ASSIMP_BUILD_ZLIB TRUE" - "ASSIMP_WARNINGS_AS_ERRORS OFF" - "ASSIMP_INSTALL_PDB OFF" - "ASSIMP_BUILD_DRACO OFF" - "ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT OFF" - "ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT OFF" + "BUILD_SHARED_LIBS 0" + "ASSIMP_NO_EXPORT 1" + "ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT 0" + "ASSIMP_INSTALL 1" + "ASSIMP_BUILD_ASSIMP_TOOLS 0" + "ASSIMP_BUILD_TESTS 0" + "ASSIMP_BUILD_SAMPLES 0" + "ASSIMP_BUILD_DOCS 0" + "USE_STATIC_CRT 1" + "ASSIMP_BUILD_ASSIMP_VIEW 0" + "ASSIMP_BUILD_ZLIB ${BUILD_ZLIB}" + "ASSIMP_WARNINGS_AS_ERRORS 0" + "ASSIMP_INSTALL_PDB 0" + "ASSIMP_BUILD_DRACO 0" + "ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT 0" + "ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT 0" # IMPORT SUPPORTS - "ASSIMP_BUILD_OBJ_IMPORTER ON" - "ASSIMP_BUILD_FBX_IMPORTER ON" - "ASSIMP_BUILD_DAE_IMPORTER ON" - "ASSIMP_BUILD_STL_IMPORTER ON" - "ASSIMP_BUILD_GLTF_IMPORTER ON" - "ASSIMP_BUILD_3DS_IMPORTER ON" - # "ASSIMP_BUILD_MDL_IMPORTER ON" - "ASSIMP_BUILD_MD5_IMPORTER ON") + "ASSIMP_BUILD_OBJ_IMPORTER 1" + "ASSIMP_BUILD_FBX_IMPORTER 1" + "ASSIMP_BUILD_DAE_IMPORTER 1" + "ASSIMP_BUILD_STL_IMPORTER 1" + "ASSIMP_BUILD_GLTF_IMPORTER 1" + "ASSIMP_BUILD_3DS_IMPORTER 1" + # "ASSIMP_BUILD_MDL_IMPORTER 1" + "ASSIMP_BUILD_MD5_IMPORTER 1") # ---- # Grab source files @@ -44,14 +53,8 @@ file(GLOB_RECURSE RAWRBOX_ASSIMP_IMPORTS "src/*.cpp" "include/*.hpp") if(RAWRBOX_BUILD_RAWRBOX_RESOURCES) set(RAWRBOX_EXTRA_LIBS RAWRBOX.RESOURCES) else() - if(NOT RAWRBOX_BUILD_RAWRBOX_RESOURCES) - foreach(TMP_PATH ${RAWRBOX_ASSIMP_IMPORTS}) - string(FIND ${TMP_PATH} "/resources/" EXCLUDE_DIR_FOUND) - if(NOT ${EXCLUDE_DIR_FOUND} EQUAL -1) - list(REMOVE_ITEM RAWRBOX_ASSIMP_IMPORTS ${TMP_PATH}) - endif() - endforeach(TMP_PATH) - endif() + remove_folder("${RAWRBOX_ASSIMP_IMPORTS}" "/resources/") + set(RAWRBOX_ASSIMP_IMPORTS "${CLEAN_SOURCES}") endif() # ---- diff --git a/assimp/include/rawrbox/assimp/importer.hpp b/assimp/include/rawrbox/assimp/importer.hpp index 7e8e9aa1..0e261e59 100644 --- a/assimp/include/rawrbox/assimp/importer.hpp +++ b/assimp/include/rawrbox/assimp/importer.hpp @@ -46,15 +46,15 @@ namespace rawrbox { uint64_t blending = BGFX_STATE_BLEND_NORMAL; OptionalTexture diffuse = std::nullopt; - rawrbox::Colorf diffuseColor = rawrbox::Colors::White; + rawrbox::Colorf diffuseColor = rawrbox::Colors::White(); std::unique_ptr normal = nullptr; std::unique_ptr specular = nullptr; - rawrbox::Colorf specularColor = rawrbox::Colors::White; + rawrbox::Colorf specularColor = rawrbox::Colors::White(); float shininess = 25.F; std::unique_ptr emissive = nullptr; - rawrbox::Colorf emissionColor = rawrbox::Colors::White; + rawrbox::Colorf emissionColor = rawrbox::Colors::White(); float intensity = 1.F; explicit AssimpMaterial(std::string _name) : name(std::move(_name)){}; @@ -65,9 +65,9 @@ namespace rawrbox { std::string name = "light"; std::string parentID = ""; - rawrbox::Colorf diffuse = rawrbox::Colors::White; - rawrbox::Colorf specular = rawrbox::Colors::White; - rawrbox::Colorf ambient = rawrbox::Colors::Black; + rawrbox::Colorf diffuse = rawrbox::Colors::White(); + rawrbox::Colorf specular = rawrbox::Colors::White(); + rawrbox::Colorf ambient = rawrbox::Colors::Black(); rawrbox::Vector3f pos = {}; rawrbox::Vector3f direction = {}; diff --git a/bass/CMakeLists.txt b/bass/CMakeLists.txt index 70d01a39..6db7e0c4 100644 --- a/bass/CMakeLists.txt +++ b/bass/CMakeLists.txt @@ -18,14 +18,17 @@ file(GLOB_RECURSE RAWRBOX_BASS_SOURCES "src/*.cpp" "include/*.hpp") if(RAWRBOX_BUILD_RAWRBOX_RESOURCES) set(RAWRBOX_EXTRA_LIBS RAWRBOX.RESOURCES) else() - if(NOT RAWRBOX_BUILD_RAWRBOX_RESOURCES) - foreach(TMP_PATH ${RAWRBOX_BASS_SOURCES}) - string(FIND ${TMP_PATH} "/resources/" EXCLUDE_DIR_FOUND) - if(NOT ${EXCLUDE_DIR_FOUND} EQUAL -1) - list(REMOVE_ITEM RAWRBOX_BASS_SOURCES ${TMP_PATH}) - endif() - endforeach(TMP_PATH) + remove_folder("${RAWRBOX_BASS_SOURCES}" "/resources/") + set(RAWRBOX_BASS_SOURCES "${CLEAN_SOURCES}") +endif() + +if(RAWRBOX_BUILD_RAWRBOX_SCRIPTING) + if(NOT RAWRBOX_BUILD_RAWRBOX_RESOURCES) # RAWRBOX.RESOURCES already includes scripting if RAWRBOX_BUILD_RAWRBOX_SCRIPTING is enabled + list(APPEND RAWRBOX_EXTRA_LIBS RAWRBOX.SCRIPTING) endif() +else() + remove_folder("${RAWRBOX_BASS_SOURCES}" "/scripting/") + set(RAWRBOX_BASS_SOURCES "${CLEAN_SOURCES}") endif() # ---- @@ -56,6 +59,6 @@ target_compile_definitions(${output_target} PRIVATE _CRT_SECURE_NO_WARNINGS NOMI target_compile_definitions(${output_target} PUBLIC RAWRBOX_BASS) target_include_directories(${output_target} PUBLIC "include") target_compile_features(${output_target} PUBLIC cxx_std_${CMAKE_CXX_STANDARD}) -target_link_libraries(${output_target} PUBLIC RAWRBOX.ENGINE RAWRBOX.MATH ${RAWRBOX_EXTRA_LIBS} fmt::fmt BASS::BASS BASS::FX) +target_link_libraries(${output_target} PUBLIC RAWRBOX.ENGINE RAWRBOX.MATH ${RAWRBOX_EXTRA_LIBS} BASS::BASS BASS::FX) set_lib_runtime_mt(${output_target}) diff --git a/bass/include/rawrbox/bass/scripting/plugin.hpp b/bass/include/rawrbox/bass/scripting/plugin.hpp new file mode 100644 index 00000000..aac673a2 --- /dev/null +++ b/bass/include/rawrbox/bass/scripting/plugin.hpp @@ -0,0 +1,18 @@ +#pragma once +#include + +namespace rawrbox { + class BASSPlugin : public rawrbox::Plugin { + public: + void registerTypes(sol::state& lua) override { + } + + void registerGlobal(rawrbox::Mod* mod) override { + if (mod == nullptr) throw std::runtime_error("[RawrBox-BASSPlugin] Tried to register plugin on invalid mod!"); + } + + void loadLuaExtensions(rawrbox::Mod* mod) override { + if (mod == nullptr) throw std::runtime_error("[RawrBox-BASSPlugin] Tried to register plugin on invalid mod!"); + } + }; +} // namespace rawrbox diff --git a/bass/include/rawrbox/bass/scripting/wrapper/instance_wrapper.hpp b/bass/include/rawrbox/bass/scripting/wrapper/instance_wrapper.hpp new file mode 100644 index 00000000..1e3c546e --- /dev/null +++ b/bass/include/rawrbox/bass/scripting/wrapper/instance_wrapper.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include + +namespace rawrbox { + class SoundInstanceWrapper { + std::shared_ptr ref; + + public: + SoundInstanceWrapper(const std::shared_ptr& instance); + + /*bool getLooping() const; + void setLooping(bool loop); + + float getVolume() const; + void setVolume(float val); + + float getPitch() const; + void setPitch(float val); + + const mainframe::math::Vector2& getPosition() const; + void setPosition(const mainframe::math::Vector2& location); + + void set3D(float maxDistance); + void setBeatSettings(float bandwidth, float center_freq, float release_time); + + bool isValid(); + bool isPlaying(); + bool isHTTP(); + uint32_t id(); + + sol::table getFFT(int fft_length, sol::this_state lua); + + void stop(); + void play(); + + void onBEAT(sol::function callback); + void onEnd(sol::function callback);*/ + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/bass/include/rawrbox/bass/sound/instance.hpp b/bass/include/rawrbox/bass/sound/instance.hpp index f875935c..5fc4b36b 100644 --- a/bass/include/rawrbox/bass/sound/instance.hpp +++ b/bass/include/rawrbox/bass/sound/instance.hpp @@ -1,5 +1,9 @@ #pragma once +#ifdef RAWRBOX_SCRIPTING + #include +#endif + #include #include #include @@ -8,8 +12,12 @@ #include namespace rawrbox { - class SoundInstance { +#ifdef RAWRBOX_SCRIPTING + class SoundInstance : public std::enable_shared_from_this { +#else + class SoundInstance { +#endif protected: uint32_t _sample = 0; uint32_t _channel = 0; @@ -28,7 +36,11 @@ namespace rawrbox { bool _looping = false; bool _stream = false; - protected: +#ifdef RAWRBOX_SCRIPTING + sol::object _luaWrapper; + virtual void initializeLua(); +#endif + [[nodiscard]] uint32_t getNextAvailableChannel() const; public: @@ -36,44 +48,46 @@ namespace rawrbox { rawrbox::Event onBPM; rawrbox::Event<> onEnd; - SoundInstance() = default; SoundInstance(uint32_t audioSample, bool isStream, uint32_t flags); - - virtual ~SoundInstance(); SoundInstance(SoundInstance&&) = delete; SoundInstance& operator=(SoundInstance&&) = delete; SoundInstance(const SoundInstance&) = delete; SoundInstance& operator=(const SoundInstance&) = delete; + virtual ~SoundInstance(); - void play(); - void stop(); + virtual void play(); + virtual void stop(); // UTILS ---- - [[nodiscard]] uint32_t id() const; - [[nodiscard]] bool isValid() const; - [[nodiscard]] bool isCreated() const; - [[nodiscard]] bool is3D() const; + [[nodiscard]] virtual uint32_t id() const; + [[nodiscard]] virtual bool isValid() const; + [[nodiscard]] virtual bool isCreated() const; + [[nodiscard]] virtual bool is3D() const; - [[nodiscard]] float getTempo() const; - [[nodiscard]] float getVolume() const; - [[nodiscard]] double getSeek() const; + [[nodiscard]] virtual float getTempo() const; + [[nodiscard]] virtual float getVolume() const; + [[nodiscard]] virtual double getSeek() const; - [[nodiscard]] bool isLooping() const; - [[nodiscard]] bool isPlaying() const; - [[nodiscard]] bool isPaused() const; - [[nodiscard]] bool isHTTPStream() const; + [[nodiscard]] virtual bool isLooping() const; + [[nodiscard]] virtual bool isPlaying() const; + [[nodiscard]] virtual bool isPaused() const; + [[nodiscard]] virtual bool isHTTPStream() const; - [[nodiscard]] const std::vector getFFT(int bass_length) const; + [[nodiscard]] virtual const std::vector getFFT(int bass_length) const; - [[nodiscard]] const rawrbox::Vector3f& getPosition() const; + [[nodiscard]] virtual const rawrbox::Vector3f& getPosition() const; // ------------------ - void setBeatSettings(float bandwidth, float center_freq, float release_time); - void setVolume(float volume); - void setTempo(float tempo); - void seek(double seek); - void setLooping(bool loop); - void setPosition(const rawrbox::Vector3f& location); - void set3D(float maxDistance, float minDistance = 0.F); + virtual void setBeatSettings(float bandwidth, float center_freq, float release_time); + virtual void setVolume(float volume); + virtual void setTempo(float tempo); + virtual void seek(double seek); + virtual void setLooping(bool loop); + virtual void setPosition(const rawrbox::Vector3f& location); + virtual void set3D(float maxDistance, float minDistance = 0.F); + +#ifdef RAWRBOX_SCRIPTING + virtual sol::object& getScriptingWrapper(); +#endif }; } // namespace rawrbox diff --git a/bass/src/scripting/wrapper/instance_wrapper.cpp b/bass/src/scripting/wrapper/instance_wrapper.cpp new file mode 100644 index 00000000..b2b6bdf9 --- /dev/null +++ b/bass/src/scripting/wrapper/instance_wrapper.cpp @@ -0,0 +1,3 @@ +namespace rawrbox { + +} diff --git a/bass/src/sound/instance.cpp b/bass/src/sound/instance.cpp index 19c0b8f0..531de268 100644 --- a/bass/src/sound/instance.cpp +++ b/bass/src/sound/instance.cpp @@ -7,6 +7,10 @@ #include #include +#ifdef RAWRBOX_SCRIPTING + #include +#endif + namespace rawrbox { SoundInstance::SoundInstance(uint32_t audioSample, bool isStream, uint32_t flags) : _sample(audioSample), _flags(flags), _stream(isStream) { rawrbox::BASS::onBEAT.add(std::to_string(this->_sample), [this](std::pair data) { @@ -34,7 +38,23 @@ namespace rawrbox { // CLEANUP CALLBACKS rawrbox::BASS::onBEAT.remove(std::to_string(this->_sample)); rawrbox::BASS::onSoundEnd.remove(std::to_string(this->_sample)); + +#ifdef RAWRBOX_SCRIPTING + if (this->_luaWrapper.valid()) this->_luaWrapper.abandon(); +#endif + } + +#ifdef RAWRBOX_SCRIPTING + void SoundInstance::initializeLua() { + if (!SCRIPTING::initialized) return; + // this->_luaWrapper = sol::make_object(rawrbox::SCRIPTING::getLUA(), rawrbox::LightBaseWrapper(this)); + } + + sol::object& SoundInstance::getScriptingWrapper() { + if (!this->_luaWrapper.valid()) this->initializeLua(); + return this->_luaWrapper; } +#endif uint32_t SoundInstance::getNextAvailableChannel() const { if (!isValid()) return 0; @@ -106,7 +126,7 @@ namespace rawrbox { if (!this->isCreated()) return 0.; QWORD pos = BASS_ChannelGetPosition(this->_channel, BASS_POS_BYTE); - return pos != -1 ? BASS_ChannelBytes2Seconds(this->_channel, pos) : 0.; + return pos != -1. ? BASS_ChannelBytes2Seconds(this->_channel, pos) : 0.; } bool SoundInstance::isLooping() const { diff --git a/cmake/FindVPX.cmake b/cmake/FindVPX.cmake index cffa668a..5fb455ec 100644 --- a/cmake/FindVPX.cmake +++ b/cmake/FindVPX.cmake @@ -2,13 +2,13 @@ include(FindPackageHandleStandardArgs) -if(VPX_VERSION EQUAL 0) +if(NOT DEFINED VPX_VERSION) message(FATAL_ERROR "No VPX version selected, set `VPX_VERSION`") else() message("Selected VPX Version: ${VPX_VERSION}") endif() -if(VPX_MSC_VERSION EQUAL 0) +if(NOT DEFINED VPX_MSC_VERSION) message(STATUS "No MSC version selected, set `VPX_MSC_VERSION` to 17") set(VPX_MSC_VERSION 17) else() diff --git a/cmake/catch2.cmake b/cmake/catch2.cmake index 0a68eb39..542829d1 100644 --- a/cmake/catch2.cmake +++ b/cmake/catch2.cmake @@ -1,5 +1,5 @@ # Packages ---- -if(BUILD_TESTING) +if(RAWRBOX_BUILD_TESTING) message(STATUS "Enabled testing for ${output_target}") enable_testing() @@ -26,7 +26,7 @@ endif() # -------------- # TESTING ---- -if(BUILD_TESTING) +if(RAWRBOX_BUILD_TESTING) file(GLOB_RECURSE RAWRBOX_TESTS_IMPORTS "tests/*.spec.cpp") add_executable(${output_target}-TESTS ${RAWRBOX_TESTS_IMPORTS}) diff --git a/cmake/rawrbox_utils.cmake b/cmake/rawrbox_utils.cmake index c60a0483..89a340f4 100644 --- a/cmake/rawrbox_utils.cmake +++ b/cmake/rawrbox_utils.cmake @@ -7,3 +7,16 @@ function(set_lib_runtime_mt target) endif() endif() endfunction() + +# From : https://stackoverflow.com/questions/24491129/excluding-directory-somewhere-in-file-structure-from-cmake-sourcefile-list +function(remove_folder glob_sources folderName) + message(STATUS "Removing ${folderName} from sources") + + foreach(ITR ${glob_sources}) + if("${ITR}" MATCHES "(.*)${folderName}(.*)") + list(REMOVE_ITEM glob_sources ${ITR}) + endif("${ITR}" MATCHES "(.*)${folderName}(.*)") + endforeach(ITR) + + set(CLEAN_SOURCES "${glob_sources}" PARENT_SCOPE) +endfunction() diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 49648cb6..8394b6af 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -1,9 +1,5 @@ # Project setup -project( - "RAWRBOX.ENGINE" - VERSION ${RAWRBOX_VERSION} - DESCRIPTION "RawrBox - Engine lib" - LANGUAGES CXX) +project("RAWRBOX.ENGINE" VERSION ${RAWRBOX_VERSION} DESCRIPTION "RawrBox - Engine lib" LANGUAGES CXX) set(output_target RAWRBOX.ENGINE) # LIB ---- @@ -13,7 +9,7 @@ target_include_directories(${output_target} PUBLIC "include") target_compile_definitions(${output_target} PRIVATE _CRT_SECURE_NO_WARNINGS NOMINMAX) target_compile_definitions(${output_target} PUBLIC RAWRBOX_ENGINE) target_compile_features(${output_target} PUBLIC cxx_std_${CMAKE_CXX_STANDARD}) -target_link_libraries(${output_target} PUBLIC RAWRBOX.UTILS fmt::fmt) +target_link_libraries(${output_target} PUBLIC RAWRBOX.UTILS) set_lib_runtime_mt(${output_target}) # -------------- diff --git a/math/include/rawrbox/math/color.hpp b/math/include/rawrbox/math/color.hpp index 3c901c2d..4d5f6b8c 100644 --- a/math/include/rawrbox/math/color.hpp +++ b/math/include/rawrbox/math/color.hpp @@ -245,20 +245,89 @@ namespace rawrbox { using ColorType = Color_t; public: - inline const static ColorType Black = ColorType(0, 0, 0, 1); - inline const static ColorType White = ColorType(1, 1, 1, 1); + [[nodiscard]] static inline ColorType Black() { + if constexpr (std::is_same_v) { + return ColorType(0, 0, 0, 255); + } else { + return ColorType(0, 0, 0, 1); + } + } + + [[nodiscard]] static inline ColorType White() { + if constexpr (std::is_same_v) { + return ColorType(255, 255, 255, 255); + } else { + return ColorType(1, 1, 1, 1); + } + } + + [[nodiscard]] static inline ColorType Gray() { + if constexpr (std::is_same_v) { + return ColorType(206, 204, 191, 255); + } else { + return ColorType(0.81F, 0.8F, 0.75F, 1); + } + } + + [[nodiscard]] static inline ColorType DarkGray() { + if constexpr (std::is_same_v) { + return ColorType(130, 127, 119, 255); + } else { + return ColorType(0.51F, 0.50F, 0.47F, 1); + } + } + + [[nodiscard]] static inline ColorType Red() { + if constexpr (std::is_same_v) { + return ColorType(255, 82, 82, 255); + } else { + return ColorType(1, 0.32F, 0.32F, 1); + } + } - inline const static ColorType Gray = ColorType(0.81F, 0.8F, 0.75F, 1); - inline const static ColorType DarkGray = ColorType(0.51F, 0.50F, 0.47F, 1); + [[nodiscard]] static inline ColorType Green() { + if constexpr (std::is_same_v) { + return ColorType(36, 222, 128, 255); + } else { + return ColorType(0.14F, 0.87F, 0.50F, 1); + } + } + + [[nodiscard]] static inline ColorType Blue() { + if constexpr (std::is_same_v) { + return ColorType(51, 171, 222, 255); + } else { + return ColorType(0.2F, 0.67F, 0.87F, 1); + } + } + + [[nodiscard]] static inline ColorType Orange() { + if constexpr (std::is_same_v) { + return ColorType(255, 120, 61, 255); + } else { + return ColorType(1, 0.47F, 0.24F, 1); + } + } + + [[nodiscard]] static inline ColorType Yellow() { + if constexpr (std::is_same_v) { + return ColorType(255, 230, 64, 255); + } else { + return ColorType(1, 0.9F, 0.25F, 1); + } + } - inline const static ColorType Red = ColorType(1, 0.32F, 0.32F, 1); - inline const static ColorType Green = ColorType(0.14F, 0.87F, 0.50F, 1); - inline const static ColorType Blue = ColorType(0.2F, 0.67F, 0.87F, 1); - inline const static ColorType Orange = ColorType(1, 0.47F, 0.24F, 1); - inline const static ColorType Yellow = ColorType(1, 0.69F, 0.25F, 1); - inline const static ColorType Purple = ColorType(1.F, 0.F, 1.F, 1); + [[nodiscard]] static inline ColorType Purple() { + if constexpr (std::is_same_v) { + return ColorType(255, 0, 255, 255); + } else { + return ColorType(1.F, 0.F, 1.F, 1); + } + } - inline const static ColorType Transparent = ColorType(0, 0, 0, 0); + [[nodiscard]] static inline ColorType Transparent() { + return ColorType(0, 0, 0, 0); + } }; using Colorsf = Colors_t; diff --git a/math/tests/color.spec.cpp b/math/tests/color.spec.cpp index 03372df9..d612d18d 100644 --- a/math/tests/color.spec.cpp +++ b/math/tests/color.spec.cpp @@ -16,7 +16,7 @@ TEST_CASE("Color should behave as expected", "[rawrbox::Color]") { } SECTION("rawrbox::Colors") { - auto red = rawrbox::Colors::Red; + auto red = rawrbox::Colors::Red(); REQUIRE(red.r == 1.F); REQUIRE(red.g == 0.32F); @@ -25,7 +25,7 @@ TEST_CASE("Color should behave as expected", "[rawrbox::Color]") { } SECTION("rawrbox::Color::cast") { - auto red = rawrbox::Colors::Red.cast(); + auto red = rawrbox::Colors::Red().cast(); rawrbox::Colori col = rawrbox::Colori{255, 255, 0, 255}; auto clCast = col.cast(); diff --git a/rawrbox.code-workspace b/rawrbox.code-workspace index 9bef2f41..2cd2b6bd 100644 --- a/rawrbox.code-workspace +++ b/rawrbox.code-workspace @@ -48,8 +48,6 @@ "cmake.generator": "Ninja", "cmake.configureArgs": ["-Wno-dev"], "cmake.configureSettings": { - "DUSE_CCACHE": "YES", - "DCCACHE_OPTIONS": "CCACHE_CPP2=true;CCACHE_SLOPPINESS=clang_index_store", "DCMAKE_EXPORT_COMPILE_COMMANDS": "ON", "DRAWRBOX_OUTPUT_BIN": "bin" //"DCMAKE_CXX_INCLUDE_WHAT_YOU_USE": "../include-what-you-use.exe" diff --git a/render/CMakeLists.txt b/render/CMakeLists.txt index 59c0ec03..3b7c6fe9 100644 --- a/render/CMakeLists.txt +++ b/render/CMakeLists.txt @@ -58,12 +58,17 @@ file(GLOB_RECURSE RAWRBOX_RENDER_SOURCES "src/*.cpp" "src/*.c" "include/*.h" "in if(RAWRBOX_BUILD_RAWRBOX_RESOURCES) list(APPEND RAWRBOX_EXTRA_LIBS RAWRBOX.RESOURCES) else() - foreach(TMP_PATH ${RAWRBOX_RENDER_SOURCES}) - string(FIND ${TMP_PATH} "/resources/" EXCLUDE_DIR_FOUND) - if(NOT ${EXCLUDE_DIR_FOUND} EQUAL -1) - list(REMOVE_ITEM RAWRBOX_RENDER_SOURCES ${TMP_PATH}) - endif() - endforeach(TMP_PATH) + remove_folder("${RAWRBOX_RENDER_SOURCES}" "/resources/") + set(RAWRBOX_RENDER_SOURCES "${CLEAN_SOURCES}") +endif() + +if(RAWRBOX_BUILD_RAWRBOX_SCRIPTING) + if(NOT RAWRBOX_BUILD_RAWRBOX_RESOURCES) # RAWRBOX.RESOURCES already includes scripting if RAWRBOX_BUILD_RAWRBOX_SCRIPTING is enabled + list(APPEND RAWRBOX_EXTRA_LIBS RAWRBOX.SCRIPTING) + endif() +else() + remove_folder("${RAWRBOX_RENDER_SOURCES}" "/scripting/") + set(RAWRBOX_RENDER_SOURCES "${CLEAN_SOURCES}") endif() # ----------------- @@ -87,9 +92,13 @@ add_custom_target( COMMENT "Copying RENDERER resources into binary directory") # ------------------ +if(RAWRBOX_BUILD_RAWRBOX_SCRIPTING) + set(RAWRBOX_RENDER_DEPS copy_resources_lua) +endif() + # Project setup add_library(${output_target} ${RAWRBOX_LIBRARY_TYPE} ${RAWRBOX_RENDER_SOURCES}) -add_dependencies(${output_target} copy_resources_render) +add_dependencies(${output_target} copy_resources_render ${RAWRBOX_RENDER_DEPS}) target_compile_definitions(${output_target} PRIVATE _CRT_SECURE_NO_WARNINGS NOMINMAX) target_compile_definitions(${output_target} PUBLIC RAWRBOX_RENDER) target_include_directories(${output_target} PUBLIC "include") @@ -100,7 +109,6 @@ target_link_libraries( RAWRBOX.MATH RAWRBOX.ENGINE ${RAWRBOX_EXTRA_LIBS} - fmt::fmt magic_enum::magic_enum utf8cpp bgfx diff --git a/render/include/rawrbox/render/decals/manager.hpp b/render/include/rawrbox/render/decals/manager.hpp index cee02ab1..4f50a60b 100644 --- a/render/include/rawrbox/render/decals/manager.hpp +++ b/render/include/rawrbox/render/decals/manager.hpp @@ -14,8 +14,8 @@ namespace rawrbox { static void setAtlasTexture(rawrbox::TextureBase* atlas); // UTILS ----- - static void add(const rawrbox::Vector3f& pos, const rawrbox::Vector3f& scale = {1, 1, 1}, float direction = 0, const rawrbox::Colorf& color = rawrbox::Colors::White, uint16_t atlasId = 0); - static void remove(size_t i); + static bool add(const rawrbox::Vector3f& pos, const rawrbox::Vector3f& scale = {1, 1, 1}, float direction = 0, const rawrbox::Colorf& color = rawrbox::Colors::White(), uint16_t atlasId = 0); + static bool remove(size_t i); static const rawrbox::Instance& get(size_t i); static const rawrbox::Mesh& getTemplate(); static size_t count(); diff --git a/render/include/rawrbox/render/light/base.hpp b/render/include/rawrbox/render/light/base.hpp index e14c0e11..c945f67a 100644 --- a/render/include/rawrbox/render/light/base.hpp +++ b/render/include/rawrbox/render/light/base.hpp @@ -4,13 +4,16 @@ #include #include #include -#include #include namespace rawrbox { +#ifdef RAWRBOX_SCRIPTING + class LightBase : public std::enable_shared_from_this { +#else class LightBase { +#endif protected: bool _isOn = true; size_t _id = 0; @@ -19,15 +22,15 @@ namespace rawrbox { rawrbox::Vector3f _offset = {}; rawrbox::Vector3f _direction = {}; - rawrbox::Colorf _color = rawrbox::Colors::White; + rawrbox::Colorf _color = rawrbox::Colors::White(); float _radius = 5.F; public: LightBase(const rawrbox::Vector3f& pos, const rawrbox::Colorf& color, float radius); - LightBase(const LightBase&) = default; - LightBase(LightBase&&) = default; - LightBase& operator=(const LightBase&) = default; + LightBase(const LightBase&) = delete; + LightBase(LightBase&&) = delete; + LightBase& operator=(const LightBase&) = delete; LightBase& operator=(LightBase&&) = delete; virtual ~LightBase() = default; diff --git a/render/include/rawrbox/render/light/manager.hpp b/render/include/rawrbox/render/light/manager.hpp index 3bfb8a27..7d0c8bc1 100644 --- a/render/include/rawrbox/render/light/manager.hpp +++ b/render/include/rawrbox/render/light/manager.hpp @@ -36,7 +36,7 @@ namespace rawrbox { class LIGHTS { protected: - static std::vector> _lights; + static std::vector> _lights; static bgfx::DynamicVertexBufferHandle _buffer; static bgfx::UniformHandle _u_lightSettings; @@ -79,7 +79,7 @@ namespace rawrbox { // ---- // FOG - static void setFog(rawrbox::FOG_TYPE type, float end, float density, const rawrbox::Colorf& col = rawrbox::Colors::Black); + static void setFog(rawrbox::FOG_TYPE type, float end, float density, const rawrbox::Colorf& col = rawrbox::Colors::Black()); static rawrbox::FOG_TYPE getFogType(); static const rawrbox::Colorf& getFogColor(); @@ -95,12 +95,7 @@ namespace rawrbox { // Light ---- template static rawrbox::LightBase* addLight(CallbackArgs&&... args) { - if (_lights.size() >= rawrbox::MAX_LIGHTS) { - fmt::print("[RawrBox-LIGHTS] Could not add light, max lights limit hit!\n"); - return nullptr; - } - - auto light = _lights.emplace_back(std::make_unique(std::forward(args)...)).get(); + auto light = _lights.emplace_back(std::make_shared(std::forward(args)...)).get(); light->setId(++rawrbox::LIGHT_ID); rawrbox::__LIGHT_DIRTY__ = true; diff --git a/render/include/rawrbox/render/light/point.hpp b/render/include/rawrbox/render/light/point.hpp index a1bb61ac..de2ce6a2 100644 --- a/render/include/rawrbox/render/light/point.hpp +++ b/render/include/rawrbox/render/light/point.hpp @@ -7,9 +7,9 @@ namespace rawrbox { public: using rawrbox::LightBase::LightBase; - PointLight(const PointLight&) = default; + PointLight(const PointLight&) = delete; PointLight(PointLight&&) = delete; - PointLight& operator=(const PointLight&) = default; + PointLight& operator=(const PointLight&) = delete; PointLight& operator=(PointLight&&) = delete; ~PointLight() override = default; diff --git a/render/include/rawrbox/render/light/spot.hpp b/render/include/rawrbox/render/light/spot.hpp index fdb6968b..4e7a64a0 100644 --- a/render/include/rawrbox/render/light/spot.hpp +++ b/render/include/rawrbox/render/light/spot.hpp @@ -12,9 +12,9 @@ namespace rawrbox { this->_direction = direction.normalized(); }; - SpotLight(const SpotLight&) = default; + SpotLight(const SpotLight&) = delete; SpotLight(SpotLight&&) = delete; - SpotLight& operator=(const SpotLight&) = default; + SpotLight& operator=(const SpotLight&) = delete; SpotLight& operator=(SpotLight&&) = delete; ~SpotLight() override = default; diff --git a/render/include/rawrbox/render/model/base.hpp b/render/include/rawrbox/render/model/base.hpp index ffadc663..66c2eb5e 100644 --- a/render/include/rawrbox/render/model/base.hpp +++ b/render/include/rawrbox/render/model/base.hpp @@ -2,10 +2,20 @@ #include +#ifdef RAWRBOX_SCRIPTING + #include + #include + #include +#endif + namespace rawrbox { template +#ifdef RAWRBOX_SCRIPTING + class ModelBase : public std::enable_shared_from_this> { +#else class ModelBase { +#endif protected: bgfx::DynamicVertexBufferHandle _vbdh = BGFX_INVALID_HANDLE; // Vertices - Dynamic @@ -21,8 +31,19 @@ namespace rawrbox { bool _isDynamic = false; // ---- +#ifdef RAWRBOX_SCRIPTING + sol::object _luaWrapper; + + virtual void initializeLua() { + if (!SCRIPTING::initialized) return; + + auto ptr = std::dynamic_pointer_cast>(this->shared_from_this()); + this->_luaWrapper = sol::make_object(rawrbox::SCRIPTING::getLUA(), rawrbox::ModelBaseWrapper(ptr)); + } +#endif + virtual void updateBuffers() { - if (!this->isDynamicBuffer() || !this->isUploaded()) return; + if (!this->isDynamic() || !this->isUploaded()) return; const bgfx::Memory* vertMem = bgfx::makeRef(this->_mesh->vertices.data(), static_cast(this->_mesh->vertices.size()) * M::vLayout().getStride()); const bgfx::Memory* indexMem = bgfx::makeRef(this->_mesh->indices.data(), static_cast(this->_mesh->indices.size()) * sizeof(uint16_t)); @@ -45,6 +66,10 @@ namespace rawrbox { RAWRBOX_DESTROY(this->_ibdh); this->_mesh.reset(); + +#ifdef RAWRBOX_SCRIPTING + if (this->_luaWrapper.valid()) this->_luaWrapper.abandon(); +#endif } // UTIL --- @@ -71,12 +96,12 @@ namespace rawrbox { return this->_mesh->matrix; } - [[nodiscard]] virtual bool isDynamicBuffer() const { + [[nodiscard]] virtual bool isDynamic() const { return this->_isDynamic; } [[nodiscard]] virtual bool isUploaded() const { - if (this->isDynamicBuffer()) return bgfx::isValid(this->_ibdh) && bgfx::isValid(this->_vbdh); + if (this->isDynamic()) return bgfx::isValid(this->_ibdh) && bgfx::isValid(this->_vbdh); return bgfx::isValid(this->_ibh) && bgfx::isValid(this->_vbh); } @@ -114,5 +139,12 @@ namespace rawrbox { virtual void draw() { if (!this->isUploaded()) throw std::runtime_error("[RawrBox-Model] Failed to render model, vertex / index buffer is not uploaded"); } + +#ifdef RAWRBOX_SCRIPTING + virtual sol::object& getScriptingWrapper() { + if (!this->_luaWrapper.valid()) this->initializeLua(); + return this->_luaWrapper; + } +#endif }; } // namespace rawrbox diff --git a/render/include/rawrbox/render/model/defs.hpp b/render/include/rawrbox/render/model/defs.hpp index db45e977..5ae55e41 100644 --- a/render/include/rawrbox/render/model/defs.hpp +++ b/render/include/rawrbox/render/model/defs.hpp @@ -24,18 +24,18 @@ namespace rawrbox { VertexData() = default; explicit VertexData(const rawrbox::Vector3f& _pos, - const rawrbox::Vector4f& _uv = {}, const rawrbox::Color cl = rawrbox::Colors::White) : position(_pos), uv(_uv), abgr(cl.pack()) {} + const rawrbox::Vector4f& _uv = {}, const rawrbox::Color cl = rawrbox::Colors::White()) : position(_pos), uv(_uv), abgr(cl.pack()) {} explicit VertexData(const rawrbox::Vector3f& _pos, - const rawrbox::Vector2f& _uv = {}, const rawrbox::Color cl = rawrbox::Colors::White) : position(_pos), uv(_uv), abgr(cl.pack()) {} + const rawrbox::Vector2f& _uv = {}, const rawrbox::Color cl = rawrbox::Colors::White()) : position(_pos), uv(_uv), abgr(cl.pack()) {} explicit VertexData(const rawrbox::Vector3f& _pos, const rawrbox::Vector2f& _uv = {}, - const std::array& _normal = {}, const rawrbox::Color cl = rawrbox::Colors::White) : position(_pos), uv(_uv), abgr(cl.pack()), normal(_normal) {} + const std::array& _normal = {}, const rawrbox::Color cl = rawrbox::Colors::White()) : position(_pos), uv(_uv), abgr(cl.pack()), normal(_normal) {} explicit VertexData(const rawrbox::Vector3f& _pos, const rawrbox::Vector4f& _uv = {}, - const std::array& _normal = {}, const rawrbox::Color cl = rawrbox::Colors::White) : position(_pos), uv(_uv), abgr(cl.pack()), normal(_normal) {} + const std::array& _normal = {}, const rawrbox::Color cl = rawrbox::Colors::White()) : position(_pos), uv(_uv), abgr(cl.pack()), normal(_normal) {} static bgfx::VertexLayout vLayout(bool normals = false, bool bones = false) { bgfx::VertexLayout l; diff --git a/render/include/rawrbox/render/model/instanced.hpp b/render/include/rawrbox/render/model/instanced.hpp index 9143c20f..828aef71 100644 --- a/render/include/rawrbox/render/model/instanced.hpp +++ b/render/include/rawrbox/render/model/instanced.hpp @@ -7,10 +7,10 @@ namespace rawrbox { struct Instance { rawrbox::Matrix4x4 matrix = {}; - rawrbox::Colorf color = rawrbox::Colors::White; + rawrbox::Colorf color = rawrbox::Colors::White(); rawrbox::Vector4f extraData = {}; // AtlasID, etc.. - Instance(const rawrbox::Matrix4x4& mat, const rawrbox::Colorf& col = rawrbox::Colors::White, rawrbox::Vector4f data = {}) : matrix(mat), color(col), extraData(data) {} + Instance(const rawrbox::Matrix4x4& mat, const rawrbox::Colorf& col = rawrbox::Colors::White(), rawrbox::Vector4f data = {}) : matrix(mat), color(col), extraData(data) {} static bgfx::VertexLayout vLayout() { static bgfx::VertexLayout l; @@ -54,7 +54,7 @@ namespace rawrbox { if (mesh.empty()) throw std::runtime_error("[RawrBox-InstancedModel] Invalid mesh! Missing vertices / indices!"); this->_mesh = std::make_unique(mesh); - if (this->isUploaded() && this->isDynamicBuffer()) { + if (this->isUploaded() && this->isDynamic()) { this->updateBuffers(); } } @@ -108,7 +108,7 @@ namespace rawrbox { ModelBase::draw(); this->_material->process(*this->_mesh); // Set atlas - if (this->isDynamicBuffer()) { + if (this->isDynamic()) { bgfx::setVertexBuffer(0, this->_vbdh); bgfx::setIndexBuffer(this->_ibdh); } else { diff --git a/render/include/rawrbox/render/model/mesh.hpp b/render/include/rawrbox/render/model/mesh.hpp index 1b5ca66a..02d500ef 100644 --- a/render/include/rawrbox/render/model/mesh.hpp +++ b/render/include/rawrbox/render/model/mesh.hpp @@ -21,7 +21,7 @@ namespace rawrbox { class LightBase; class Mesh { - private: + protected: bool _canOptimize = true; rawrbox::Vector3f _scale = {1, 1, 1}; @@ -65,7 +65,7 @@ namespace rawrbox { // RENDERING --- rawrbox::Matrix4x4 matrix = {}; - rawrbox::Color color = rawrbox::Colors::White; + rawrbox::Color color = rawrbox::Colors::White(); bool wireframe = false; bool lineMode = false; diff --git a/render/include/rawrbox/render/model/model.hpp b/render/include/rawrbox/render/model/model.hpp index f9d47611..aa2bd254 100644 --- a/render/include/rawrbox/render/model/model.hpp +++ b/render/include/rawrbox/render/model/model.hpp @@ -10,6 +10,11 @@ #define BGFX_STATE_DEFAULT_3D (0 | BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A) +#ifdef RAWRBOX_SCRIPTING + #include + #include +#endif + namespace rawrbox { template @@ -206,6 +211,15 @@ namespace rawrbox { } } +#ifdef RAWRBOX_SCRIPTING + void initializeLua() override { + if (this->_luaWrapper.valid()) this->_luaWrapper.abandon(); + + auto ptr = std::dynamic_pointer_cast>(this->shared_from_this()); + this->_luaWrapper = sol::make_object(rawrbox::SCRIPTING::getLUA(), rawrbox::ModelWrapper(ptr)); + } +#endif + public: Model() = default; Model(const Model&) = delete; @@ -350,14 +364,14 @@ namespace rawrbox { ++it2; } - if (this->isUploaded() && this->isDynamicBuffer()) this->flattenMeshes(); // Already uploaded? And dynamic? Then update vertices + if (this->isUploaded() && this->isDynamic()) this->flattenMeshes(); // Already uploaded? And dynamic? Then update vertices } virtual void removeMesh(size_t index) { if (index >= this->_meshes.size()) return; this->_meshes.erase(this->_meshes.begin() + index); - if (this->isUploaded() && this->isDynamicBuffer()) this->flattenMeshes(); // Already uploaded? And dynamic? Then update vertices + if (this->isUploaded() && this->isDynamic()) this->flattenMeshes(); // Already uploaded? And dynamic? Then update vertices } virtual rawrbox::Mesh* addMesh(rawrbox::Mesh mesh) { @@ -365,7 +379,7 @@ namespace rawrbox { mesh.owner = this; auto& a = this->_meshes.emplace_back(std::make_unique(mesh)); - if (this->isUploaded() && this->isDynamicBuffer()) { + if (this->isUploaded() && this->isDynamic()) { this->flattenMeshes(); // Already uploaded? And dynamic? Then update vertices } @@ -451,7 +465,7 @@ namespace rawrbox { this->animate(*mesh); // --- - if (this->isDynamicBuffer()) { + if (this->isDynamic()) { bgfx::setVertexBuffer(0, this->_vbdh, mesh->baseVertex, mesh->totalVertex); bgfx::setIndexBuffer(this->_ibdh, mesh->baseIndex, mesh->totalIndex); } else { diff --git a/render/include/rawrbox/render/model/spline.hpp b/render/include/rawrbox/render/model/spline.hpp index 5a07f5c5..157ea811 100644 --- a/render/include/rawrbox/render/model/spline.hpp +++ b/render/include/rawrbox/render/model/spline.hpp @@ -108,7 +108,7 @@ namespace rawrbox { auto norm = rawrbox::Vector3f(this->_shape->normal[j].x, this->_shape->normal[j].y, 0.F); auto uv = rawrbox::Vector2f(this->_shape->u[j], path[i].vCoordinate); - buff[id] = rawrbox::VertexData(path[i].LocalToWorld(pos), uv, {rawrbox::PackUtils::packNormal(norm.x, norm.y, norm.z), 0}, rawrbox::Colors::White); + buff[id] = rawrbox::VertexData(path[i].LocalToWorld(pos), uv, {rawrbox::PackUtils::packNormal(norm.x, norm.y, norm.z), 0}, rawrbox::Colors::White()); } } @@ -144,7 +144,7 @@ namespace rawrbox { ModelBase::draw(); this->_material->process(*this->_mesh); - if (this->isDynamicBuffer()) { + if (this->isDynamic()) { bgfx::setVertexBuffer(0, this->_vbdh); bgfx::setIndexBuffer(this->_ibdh); } else { diff --git a/render/include/rawrbox/render/model/sprite.hpp b/render/include/rawrbox/render/model/sprite.hpp index d3a963a8..e24102df 100644 --- a/render/include/rawrbox/render/model/sprite.hpp +++ b/render/include/rawrbox/render/model/sprite.hpp @@ -43,7 +43,7 @@ namespace rawrbox { this->_material->process(*mesh); - if (this->isDynamicBuffer()) { + if (this->isDynamic()) { bgfx::setVertexBuffer(0, this->_vbdh, mesh->baseVertex, mesh->totalVertex); bgfx::setIndexBuffer(this->_ibdh, mesh->baseIndex, mesh->totalIndex); } else { diff --git a/render/include/rawrbox/render/model/text3D.hpp b/render/include/rawrbox/render/model/text3D.hpp index d44698e6..d8cc9ba3 100644 --- a/render/include/rawrbox/render/model/text3D.hpp +++ b/render/include/rawrbox/render/model/text3D.hpp @@ -23,7 +23,7 @@ namespace rawrbox { void setScaleMul(float mul); [[nodiscard]] float getScaleMul() const; - uint32_t addText(const rawrbox::Font& font, const std::string& text, const rawrbox::Vector3f& pos, const rawrbox::Colorf& cl = rawrbox::Colors::White, rawrbox::Alignment alignX = rawrbox::Alignment::Center, rawrbox::Alignment alignY = rawrbox::Alignment::Center, bool billboard = false); + uint32_t addText(const rawrbox::Font& font, const std::string& text, const rawrbox::Vector3f& pos, const rawrbox::Colorf& cl = rawrbox::Colors::White(), rawrbox::Alignment alignX = rawrbox::Alignment::Center, rawrbox::Alignment alignY = rawrbox::Alignment::Center, bool billboard = false); void removeText(uint32_t indx); // ---------- diff --git a/render/include/rawrbox/render/model/utils/mesh.hpp b/render/include/rawrbox/render/model/utils/mesh.hpp index 0790c65d..83c5ff84 100644 --- a/render/include/rawrbox/render/model/utils/mesh.hpp +++ b/render/include/rawrbox/render/model/utils/mesh.hpp @@ -84,7 +84,7 @@ namespace rawrbox { return mesh; } - static inline rawrbox::Mesh generatePlane(const rawrbox::Vector3f& pos, const rawrbox::Vector2f& size, const rawrbox::Colorf& cl = rawrbox::Colors::White) { + static inline rawrbox::Mesh generatePlane(const rawrbox::Vector3f& pos, const rawrbox::Vector2f& size, const rawrbox::Colorf& cl = rawrbox::Colors::White()) { rawrbox::Mesh mesh; mesh.setPos(pos); @@ -117,7 +117,7 @@ namespace rawrbox { return mesh; } - static inline rawrbox::Mesh generateCube(const rawrbox::Vector3f& pos, const rawrbox::Vector3f& size, const rawrbox::Colorf& cl = rawrbox::Colors::White) { + static inline rawrbox::Mesh generateCube(const rawrbox::Vector3f& pos, const rawrbox::Vector3f& size, const rawrbox::Colorf& cl = rawrbox::Colors::White()) { rawrbox::Mesh mesh; mesh.setPos(pos); @@ -208,9 +208,9 @@ namespace rawrbox { mesh.setPos(pos); float hSize = size / 2.F; - mesh.merge(generateCube(pos, {hSize * 2, 0.01F, 0.01F}, Colors::Red)); // x - mesh.merge(generateCube(pos, {0.01F, hSize * 2, 0.01F}, Colors::Green)); // y - mesh.merge(generateCube(pos, {0.01F, 0.01F, hSize * 2}, Colors::Blue)); // z + mesh.merge(generateCube(pos, {hSize * 2, 0.01F, 0.01F}, rawrbox::Colors::Red())); // x + mesh.merge(generateCube(pos, {0.01F, hSize * 2, 0.01F}, rawrbox::Colors::Green())); // y + mesh.merge(generateCube(pos, {0.01F, 0.01F, hSize * 2}, rawrbox::Colors::Blue())); // z // AABB --- mesh.bbox.m_min = {-hSize, -hSize, -hSize}; @@ -226,7 +226,7 @@ namespace rawrbox { // Adapted from https://github.com/bkaradzic/bgfx/blob/master/examples/common/debugdraw/debugdraw.cpp#L687 // Does not support UV :( / normals - static inline rawrbox::Mesh generateCone(const rawrbox::Vector3f& pos, const rawrbox::Vector3f& size, uint32_t ratio = 12, const rawrbox::Colorf& cl = rawrbox::Colors::White) { + static inline rawrbox::Mesh generateCone(const rawrbox::Vector3f& pos, const rawrbox::Vector3f& size, uint32_t ratio = 12, const rawrbox::Colorf& cl = rawrbox::Colors::White()) { rawrbox::Mesh mesh; mesh.setPos(pos); @@ -289,7 +289,7 @@ namespace rawrbox { // Adapted from https://github.com/bkaradzic/bgfx/blob/master/examples/common/debugdraw/debugdraw.cpp#L750 // Does not support UV :( / normals - static inline rawrbox::Mesh generateCylinder(const rawrbox::Vector3f& pos, const rawrbox::Vector3f& size, uint32_t ratio = 12, const rawrbox::Colorf& cl = rawrbox::Colors::White) { + static inline rawrbox::Mesh generateCylinder(const rawrbox::Vector3f& pos, const rawrbox::Vector3f& size, uint32_t ratio = 12, const rawrbox::Colorf& cl = rawrbox::Colors::White()) { rawrbox::Mesh mesh; mesh.setPos(pos); @@ -357,7 +357,7 @@ namespace rawrbox { // Adapted from https://github.com/bkaradzic/bgfx/blob/master/examples/common/debugdraw/debugdraw.cpp#L640 // Does not support UV :( / normals - static inline rawrbox::Mesh generateSphere(const rawrbox::Vector3f& pos, float size, uint32_t ratio = 1, const rawrbox::Colorf& cl = rawrbox::Colors::White) { + static inline rawrbox::Mesh generateSphere(const rawrbox::Vector3f& pos, float size, uint32_t ratio = 1, const rawrbox::Colorf& cl = rawrbox::Colors::White()) { rawrbox::Mesh mesh; mesh.setPos(pos); @@ -465,7 +465,7 @@ namespace rawrbox { return mesh; } - static inline rawrbox::Mesh generateMesh(const rawrbox::Vector3f& pos, uint32_t subDivs = 1, const rawrbox::Colorf& cl = rawrbox::Colors::White) { + static inline rawrbox::Mesh generateMesh(const rawrbox::Vector3f& pos, uint32_t subDivs = 1, const rawrbox::Colorf& cl = rawrbox::Colors::White()) { rawrbox::Mesh mesh; mesh.setPos(pos); @@ -508,7 +508,7 @@ namespace rawrbox { } // Adapted from : https://stackoverflow.com/questions/58494179/how-to-create-a-grid-in-opengl-and-drawing-it-with-lines - static inline rawrbox::Mesh generateGrid(uint16_t size, const rawrbox::Vector3f& pos, const rawrbox::Colorf& cl = rawrbox::Colors::DarkGray, const rawrbox::Colorf& borderCl = rawrbox::Colors::Transparent) { + static inline rawrbox::Mesh generateGrid(uint16_t size, const rawrbox::Vector3f& pos, const rawrbox::Colorf& cl = rawrbox::Colors::DarkGray(), const rawrbox::Colorf& borderCl = rawrbox::Colors::Transparent()) { rawrbox::Mesh mesh; mesh.setPos(pos); diff --git a/render/include/rawrbox/render/scripting/plugin.hpp b/render/include/rawrbox/render/scripting/plugin.hpp new file mode 100644 index 00000000..08d72463 --- /dev/null +++ b/render/include/rawrbox/render/scripting/plugin.hpp @@ -0,0 +1,97 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#ifdef RAWRBOX_RESOURCES + #include + #include +#endif +#include +#include +#include +#include +#include +#include + +namespace rawrbox { + class RenderPlugin : public rawrbox::Plugin { + protected: + rawrbox::Window* _window = nullptr; + + public: + RenderPlugin(rawrbox::Window* window) : rawrbox::Plugin(), _window(window){}; + + void registerTypes(sol::state& lua) override { + // GAME + rawrbox::WindowWrapper::registerLua(lua); + rawrbox::CameraWrapper::registerLua(lua); + rawrbox::StencilWrapper::registerLua(lua); + rawrbox::DecalsWrapper::registerLua(lua); + // ---- + + // MODEL -- + rawrbox::ModelBaseWrapper::registerLua(lua); + rawrbox::ModelWrapper::registerLua(lua); + rawrbox::MeshWrapper::registerLua(lua); + // ---- + + // TEXTURES ---- + rawrbox::TextureWrapper::registerLua(lua); + // ------ + + // LIGHT ---- + rawrbox::LightBaseWrapper::registerLua(lua); + rawrbox::LightsWrapper::registerLua(lua); + // ------ + + // FONT ---- + rawrbox::FontWrapper::registerLua(lua); + // ------ + +#ifdef RAWRBOX_RESOURCES + // RESOURCES --- + rawrbox::TextureLoaderWrapper::registerLua(lua); + rawrbox::FontLoaderWrapper::registerLua(lua); +// ------ +#endif + } + + void registerGlobal(rawrbox::Mod* mod) override { + if (mod == nullptr) throw std::runtime_error("[RawrBox-RenderPlugin] Tried to register plugin on invalid mod!"); + if (this->_window == nullptr) throw std::runtime_error("[RawrBox-RenderPlugin] Window not set!"); + + auto& env = mod->getEnvironment(); + + // Game singletons + env["camera"] = rawrbox::CameraWrapper(); + env["window"] = rawrbox::WindowWrapper(this->_window); + env["stencil"] = rawrbox::StencilWrapper(&this->_window->getStencil()); + + env["decals"] = rawrbox::DecalsWrapper(); + env["lights"] = rawrbox::LightsWrapper(); + +#ifdef RAWRBOX_RESOURCES + // Loaders ---- + env["texture"] = rawrbox::TextureLoaderWrapper(mod); + env["font"] = rawrbox::FontLoaderWrapper(mod); + //----- +#endif + + // Renderer statics --- + env["MAX_BONES_PER_VERTEX"] = rawrbox::MAX_BONES_PER_VERTEX; + env["MAX_BONES_PER_MODEL"] = rawrbox::MAX_BONES_PER_MODEL; + env["CURRENT_VIEW_ID"] = []() { return rawrbox::CURRENT_VIEW_ID; }; + env["BGFX_FRAME"] = []() { return rawrbox::BGFX_FRAME; }; + // ----- + } + + void loadLuaExtensions(rawrbox::Mod* mod) override { + if (mod == nullptr) throw std::runtime_error("[RawrBox-RenderPlugin] Tried to register plugin on invalid mod!"); + rawrbox::SCRIPTING::loadLuaFile("./lua/render_enums.lua", mod->getEnvironment()); + } + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/camera_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/camera_wrapper.hpp new file mode 100644 index 00000000..61096aca --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/camera_wrapper.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include + +namespace rawrbox { + class CameraWrapper { + public: + CameraWrapper() = default; + CameraWrapper(const CameraWrapper&) = default; + CameraWrapper(CameraWrapper&&) = default; + CameraWrapper& operator=(const CameraWrapper&) = default; + CameraWrapper& operator=(CameraWrapper&&) = default; + virtual ~CameraWrapper() = default; + + // UTILS ----- + virtual void setPos(const rawrbox::Vector3f& pos); + [[nodiscard]] virtual const rawrbox::Vector3f getPos() const; + + virtual void setAngle(const rawrbox::Vector4f& ang); + [[nodiscard]] virtual const rawrbox::Vector4f getAngle() const; + + [[nodiscard]] virtual rawrbox::Vector3f getForward() const; + [[nodiscard]] virtual rawrbox::Vector3f getRight() const; + [[nodiscard]] virtual rawrbox::Vector3f getUp() const; + + [[nodiscard]] virtual float getZFar() const; + [[nodiscard]] virtual float getZNear() const; + + [[nodiscard]] virtual const rawrbox::Matrix4x4 getViewMtx() const; + [[nodiscard]] virtual const rawrbox::Matrix4x4 getProjMtx() const; + [[nodiscard]] virtual const rawrbox::Matrix4x4 getProjViewMtx() const; + + [[nodiscard]] virtual const rawrbox::Vector3f worldToScreen(const rawrbox::Vector3f& pos) const; + [[nodiscard]] virtual const rawrbox::Vector3f screenToWorld(const rawrbox::Vector2f& screen_pos) const; + // ---------------- + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/decals_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/decals_wrapper.hpp new file mode 100644 index 00000000..cd6e6581 --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/decals_wrapper.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include + +namespace rawrbox { + class DecalsWrapper { + public: + DecalsWrapper() = default; + DecalsWrapper(const DecalsWrapper&) = default; + DecalsWrapper(DecalsWrapper&&) = default; + DecalsWrapper& operator=(const DecalsWrapper&) = default; + DecalsWrapper& operator=(DecalsWrapper&&) = default; + virtual ~DecalsWrapper() = default; + + // UTILS ----- + virtual bool add(const rawrbox::Vector3f& pos, const sol::optional scale, const sol::optional direction, const sol::optional color, const sol::optional atlasId); + virtual bool remove(size_t i); + virtual const rawrbox::Instance& get(size_t i); + virtual size_t count(); + // ----- + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/light/base_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/light/base_wrapper.hpp new file mode 100644 index 00000000..39fac81d --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/light/base_wrapper.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include + +#include + +namespace rawrbox { + class LightBaseWrapper { + protected: + std::weak_ptr _ref; + + public: + LightBaseWrapper(const std::shared_ptr& ref); + LightBaseWrapper(const LightBaseWrapper&) = default; + LightBaseWrapper(LightBaseWrapper&&) = default; + LightBaseWrapper& operator=(const LightBaseWrapper&) = default; + LightBaseWrapper& operator=(LightBaseWrapper&&) = default; + virtual ~LightBaseWrapper(); + + // UTILS ---- + [[nodiscard]] virtual const rawrbox::Colori getColor() const; + virtual void setColor(const rawrbox::Colori& col); + + [[nodiscard]] virtual const rawrbox::Vector4f getData() const; + + virtual void setRadius(float radius); + [[nodiscard]] virtual float getRadius() const; + + [[nodiscard]] virtual size_t id() const; + + [[nodiscard]] virtual bool isOn() const; + virtual void setStatus(bool on); + + [[nodiscard]] virtual const rawrbox::Vector3f& getPos() const; + virtual void setPos(const rawrbox::Vector3f& pos); + + [[nodiscard]] virtual const rawrbox::Vector3f& getOffsetPos() const; + virtual void setOffsetPos(const rawrbox::Vector3f& pos); + + [[nodiscard]] virtual const rawrbox::Vector3f getWorldPos() const; + [[nodiscard]] virtual rawrbox::LightType getType() const; + + [[nodiscard]] virtual const rawrbox::Vector3f& getDirection() const; + virtual void setDirection(const rawrbox::Vector3f& dir); + // ------ + + [[nodiscard]] virtual bool isValid() const; + [[nodiscard]] virtual rawrbox::LightBase* getRef() const; + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/light/manager_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/light/manager_wrapper.hpp new file mode 100644 index 00000000..2866a2e9 --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/light/manager_wrapper.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include +#include + +#include + +namespace rawrbox { + class LightsWrapper { + public: + LightsWrapper() = default; + LightsWrapper(const LightsWrapper&) = default; + LightsWrapper(LightsWrapper&&) = default; + LightsWrapper& operator=(const LightsWrapper&) = default; + LightsWrapper& operator=(LightsWrapper&&) = default; + virtual ~LightsWrapper() = default; + + // UTILS ---- + virtual void setEnabled(bool fb); + + // SUN + virtual void setSun(const rawrbox::Vector3f& dir, const rawrbox::Colori& col); + virtual const rawrbox::Colori getSunColor(); + virtual const rawrbox::Vector3f& getSunDir(); + // ---- + + // FOG + virtual void setFog(rawrbox::FOG_TYPE type, float end, float density, const sol::optional col); + + virtual rawrbox::FOG_TYPE getFogType(); + virtual const rawrbox::Colori getFogColor(); + virtual float getFogEnd(); + virtual float getFogDensity(); + // ---- + + // AMBIENT + virtual void setAmbient(const rawrbox::Colori& col); + virtual const rawrbox::Colori getAmbient(); + // ------- + + // Light ---- + void addPoint(const rawrbox::Vector3f& pos, const rawrbox::Colori& color, float radius); + void addSpot(const rawrbox::Vector3f& posMatrix, const rawrbox::Vector3f& direction, const rawrbox::Colori& color, float innerCone, float outerCone, float power); + + void removeLight(rawrbox::LightBaseWrapper& light); + // --------- + + // Light utils ---- + virtual rawrbox::LightBaseWrapper getLight(size_t indx); + virtual size_t count(); + // --------- + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/model/base_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/model/base_wrapper.hpp new file mode 100644 index 00000000..d0f58ba5 --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/model/base_wrapper.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include +#include + +#include + +namespace rawrbox { + template + class ModelBase; + + class ModelBaseWrapper { + protected: + std::weak_ptr> _ref; + + public: + ModelBaseWrapper(const std::shared_ptr>& ref); + ModelBaseWrapper(const ModelBaseWrapper&) = default; + ModelBaseWrapper(ModelBaseWrapper&&) = default; + ModelBaseWrapper& operator=(const ModelBaseWrapper&) = default; + ModelBaseWrapper& operator=(ModelBaseWrapper&&) = default; + virtual ~ModelBaseWrapper(); + + // UTILS ---- + [[nodiscard]] virtual const rawrbox::Vector3f getPos() const; + virtual void setPos(const rawrbox::Vector3f& pos); + + [[nodiscard]] virtual const rawrbox::Vector3f getScale() const; + virtual void setScale(const rawrbox::Vector3f& scale); + + [[nodiscard]] virtual const rawrbox::Vector4f getAngle() const; + virtual void setAngle(const rawrbox::Vector4f& ang); + + virtual void setEulerAngle(const rawrbox::Vector3f& ang); + + [[nodiscard]] virtual const rawrbox::Matrix4x4 getMatrix() const; + + [[nodiscard]] virtual bool isDynamic() const; + + [[nodiscard]] virtual bool isUploaded() const; + // ------ + + [[nodiscard]] bool isValid() const; + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/model/mesh_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/model/mesh_wrapper.hpp new file mode 100644 index 00000000..a7b40dff --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/model/mesh_wrapper.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +#include + +namespace rawrbox { + class MeshWrapper { + public: + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/model/model_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/model/model_wrapper.hpp new file mode 100644 index 00000000..a6cb4438 --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/model/model_wrapper.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace rawrbox { + class ModelWrapper : public rawrbox::ModelBaseWrapper { + + public: + ModelWrapper(const std::shared_ptr>& ref); + ModelWrapper(const ModelWrapper&) = default; + ModelWrapper(ModelWrapper&&) = default; + ModelWrapper& operator=(const ModelWrapper&) = default; + ModelWrapper& operator=(ModelWrapper&&) = default; + ~ModelWrapper() override = default; + + // ANIMS --- + virtual void playAnimation(const std::string& name, sol::optional loop, sol::optional speed); + virtual void stopAnimation(const std::string& name); + // --- + + // UTILS --- + virtual void setOptimizable(bool optimize); + virtual void optimize(); + + void setPos(const rawrbox::Vector3f& pos) override; + void setAngle(const rawrbox::Vector4f& angle) override; + void setEulerAngle(const rawrbox::Vector3f& angle) override; + void setScale(const rawrbox::Vector3f& size) override; + + [[nodiscard]] virtual const rawrbox::BBOX getBBOX() const; + [[nodiscard]] virtual size_t totalMeshes() const; + [[nodiscard]] virtual bool empty() const; + + virtual void removeMeshByName(const std::string& id); + virtual void removeMesh(size_t index); + + virtual rawrbox::Mesh* getMeshByName(const std::string& id); + virtual rawrbox::Mesh* getMesh(sol::optional id); + // --- + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/resources/font_loader_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/resources/font_loader_wrapper.hpp new file mode 100644 index 00000000..eb49e742 --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/resources/font_loader_wrapper.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +#include + +namespace rawrbox { + class FontLoaderWrapper { + rawrbox::Mod* _mod; + + public: + FontLoaderWrapper(rawrbox::Mod* mod_); + FontLoaderWrapper(const FontLoaderWrapper&) = default; + FontLoaderWrapper(FontLoaderWrapper&&) = default; + FontLoaderWrapper& operator=(const FontLoaderWrapper&) = default; + FontLoaderWrapper& operator=(FontLoaderWrapper&&) = default; + virtual ~FontLoaderWrapper() = default; + + virtual rawrbox::FontWrapper get(const std::string& path, sol::optional size); + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/resources/texture_loader_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/resources/texture_loader_wrapper.hpp new file mode 100644 index 00000000..d7679834 --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/resources/texture_loader_wrapper.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +#include + +namespace rawrbox { + class TextureLoaderWrapper { + rawrbox::Mod* _mod; + + public: + TextureLoaderWrapper(rawrbox::Mod* mod_); + TextureLoaderWrapper(const TextureLoaderWrapper&) = default; + TextureLoaderWrapper(TextureLoaderWrapper&&) = default; + TextureLoaderWrapper& operator=(const TextureLoaderWrapper&) = default; + TextureLoaderWrapper& operator=(TextureLoaderWrapper&&) = default; + virtual ~TextureLoaderWrapper() = default; + + virtual rawrbox::TextureWrapper get(const std::string& path, sol::optional loadFlags); + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/stencil_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/stencil_wrapper.hpp new file mode 100644 index 00000000..f0c95c94 --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/stencil_wrapper.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include + +#include + +namespace rawrbox { + class StencilWrapper { + protected: + rawrbox::Stencil* _stencil = nullptr; + + public: + StencilWrapper(rawrbox::Stencil* stencil); + StencilWrapper(const StencilWrapper&) = default; + StencilWrapper(StencilWrapper&&) = default; + StencilWrapper& operator=(const StencilWrapper&) = default; + StencilWrapper& operator=(StencilWrapper&&) = default; + virtual ~StencilWrapper() = default; + + // Draw ---- + // virtual void drawPolygon(rawrbox::Polygon poly); + virtual void drawTriangle(const rawrbox::Vector2f& a, const rawrbox::Vector2f& aUV, const rawrbox::Colori& colA, const rawrbox::Vector2f& b, const rawrbox::Vector2f& bUV, const rawrbox::Colori& colB, const rawrbox::Vector2f& c, const rawrbox::Vector2f& cUV, const rawrbox::Colori& colC); + virtual void drawBox(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, const sol::optional col); + virtual void drawTexture(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, const rawrbox::TextureWrapper& tex, const sol::optional col, const sol::optional uvStart, const sol::optional uvEnd); + virtual void drawCircle(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, const sol::optional col, const sol::optional roundness, const sol::optional angleStart, const sol::optional angleEnd); + virtual void drawLine(const rawrbox::Vector2& from, const rawrbox::Vector2& to, const sol::optional col); + virtual void drawText(const rawrbox::FontWrapper& font, const std::string& text, const rawrbox::Vector2f& pos, const sol::optional& col, const sol::optional alignX, const sol::optional alignY); + // ------ + + // Pop & Push ---- + virtual void pushOffset(const rawrbox::Vector2f& offset); + virtual void popOffset(); + + virtual void pushLocalOffset(); + virtual void popLocalOffset(); + + virtual void pushRotation(float _rotation, const rawrbox::Vector2f& _origin); + virtual void popRotation(); + + virtual void pushOutline(float thickness, float stipple = 0.F); + virtual void popOutline(); + + virtual void pushClipping(const rawrbox::AABB& rect); + virtual void popClipping(); + + virtual void pushScale(const rawrbox::Vector2f& scale); + virtual void popScale(); + + virtual void pushDisableCulling(); + virtual void popDisableCulling(); + // ------ + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/text/font_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/text/font_wrapper.hpp new file mode 100644 index 00000000..0af0d294 --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/text/font_wrapper.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include + +namespace rawrbox { + class FontWrapper { + rawrbox::Font* _ref = nullptr; + + public: + FontWrapper(rawrbox::Font* instance); + FontWrapper(const FontWrapper&) = default; + FontWrapper(FontWrapper&&) = default; + FontWrapper& operator=(const FontWrapper&) = default; + FontWrapper& operator=(FontWrapper&&) = default; + virtual ~FontWrapper() = default; + + [[nodiscard]] virtual rawrbox::Font* getRef() const; + + // UTILS ----- + [[nodiscard]] virtual bool isValid() const; + [[nodiscard]] virtual float getSize() const; + [[nodiscard]] virtual float getScale() const; + [[nodiscard]] virtual float getLineHeight() const; + + [[nodiscard]] virtual rawrbox::Vector2f getStringSize(const std::string& text) const; + [[nodiscard]] virtual bool hasGlyph(uint32_t codepoint) const; + // ------ + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/textures/base_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/textures/base_wrapper.hpp new file mode 100644 index 00000000..5eaed380 --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/textures/base_wrapper.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include + +namespace rawrbox { + class TextureWrapper { + protected: + rawrbox::TextureBase* _texture = nullptr; + + public: + TextureWrapper(rawrbox::TextureBase* texture); + TextureWrapper(const TextureWrapper&) = default; + TextureWrapper(TextureWrapper&&) = default; + TextureWrapper& operator=(const TextureWrapper&) = default; + TextureWrapper& operator=(TextureWrapper&&) = default; + virtual ~TextureWrapper() = default; + + [[nodiscard]] virtual rawrbox::TextureBase* getRef() const; + + // UTILS---- + [[nodiscard]] virtual bool hasTransparency() const; + [[nodiscard]] virtual const rawrbox::Vector2i getSize() const; + [[nodiscard]] virtual bool isValid() const; + + [[nodiscard]] virtual std::array getData() const; + // ----- + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/scripting/wrappers/window_wrapper.hpp b/render/include/rawrbox/render/scripting/wrappers/window_wrapper.hpp new file mode 100644 index 00000000..58649e7f --- /dev/null +++ b/render/include/rawrbox/render/scripting/wrappers/window_wrapper.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include + +namespace rawrbox { + class WindowWrapper { + protected: + rawrbox::Window* _window = nullptr; + + public: + WindowWrapper(rawrbox::Window* window); + WindowWrapper(const WindowWrapper&) = default; + WindowWrapper(WindowWrapper&&) = default; + WindowWrapper& operator=(const WindowWrapper&) = default; + WindowWrapper& operator=(WindowWrapper&&) = default; + virtual ~WindowWrapper() = default; + + // Utils ---- + virtual void setTitle(const std::string& title); + + virtual void hideCursor(bool hidden); + virtual void setCursor(uint32_t cursor); + + virtual void close(); + + [[nodiscard]] virtual rawrbox::Vector2i getSize() const; + [[nodiscard]] virtual float getAspectRatio() const; + + [[nodiscard]] virtual rawrbox::Vector2i getMousePos() const; + + [[nodiscard]] virtual bool isKeyDown(int key) const; + [[nodiscard]] virtual bool isMouseDown(int key) const; + // ------- + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/render/include/rawrbox/render/static.hpp b/render/include/rawrbox/render/static.hpp index a81bb823..2561f55d 100644 --- a/render/include/rawrbox/render/static.hpp +++ b/render/include/rawrbox/render/static.hpp @@ -28,7 +28,6 @@ namespace rawrbox { constexpr auto MAX_BONES_PER_VERTEX = 4; constexpr auto MAX_BONES_PER_MODEL = 200; - constexpr auto MAX_LIGHTS = 1000; extern bool BGFX_INITIALIZED; diff --git a/render/include/rawrbox/render/stencil.hpp b/render/include/rawrbox/render/stencil.hpp index d8efa9b6..184a9a41 100644 --- a/render/include/rawrbox/render/stencil.hpp +++ b/render/include/rawrbox/render/stencil.hpp @@ -33,11 +33,11 @@ namespace rawrbox { struct PolygonVertice { rawrbox::Vector2f pos = {}; rawrbox::Vector2f uv = {}; - rawrbox::Color col = rawrbox::Colors::White; + rawrbox::Color col = rawrbox::Colors::White(); }; struct Polygon { - std::vector verts = {}; + std::vector verts = {}; std::vector indices = {}; }; @@ -45,7 +45,7 @@ namespace rawrbox { bgfx::ProgramHandle stencilProgram = BGFX_INVALID_HANDLE; bgfx::TextureHandle textureHandle = BGFX_INVALID_HANDLE; - std::vector vertices = {}; + std::vector vertices = {}; std::vector indices = {}; uint64_t drawMode = 0; @@ -216,13 +216,13 @@ namespace rawrbox { virtual void resize(const rawrbox::Vector2i& size); // ------ UTILS - virtual void drawPolygon(rawrbox::Polygon poly); + virtual void drawPolygon(const rawrbox::Polygon& poly); virtual void drawTriangle(const rawrbox::Vector2f& a, const rawrbox::Vector2f& aUV, const rawrbox::Color& colA, const rawrbox::Vector2f& b, const rawrbox::Vector2f& bUV, const rawrbox::Color& colB, const rawrbox::Vector2f& c, const rawrbox::Vector2f& cUV, const rawrbox::Color& colC); - virtual void drawBox(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, const rawrbox::Color& col = rawrbox::Colors::White); - virtual void drawTexture(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, const rawrbox::TextureBase& tex, const rawrbox::Color& col = rawrbox::Colors::White, const rawrbox::Vector2f& uvStart = {0, 0}, const rawrbox::Vector2f& uvEnd = {1, 1}); - virtual void drawCircle(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, const rawrbox::Color& col = rawrbox::Colors::White, size_t roundness = 32, float angleStart = 0.F, float angleEnd = 360.F); - virtual void drawLine(const rawrbox::Vector2& from, const rawrbox::Vector2& to, const rawrbox::Color& col = rawrbox::Colors::White); - virtual void drawText(const rawrbox::Font& font, const std::string& text, const rawrbox::Vector2f& pos, const rawrbox::Color& col = rawrbox::Colors::White, rawrbox::Alignment alignX = rawrbox::Alignment::Left, rawrbox::Alignment alignY = rawrbox::Alignment::Left); + virtual void drawBox(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, const rawrbox::Color& col = rawrbox::Colors::White()); + virtual void drawTexture(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, const rawrbox::TextureBase& tex, const rawrbox::Color& col = rawrbox::Colors::White(), const rawrbox::Vector2f& uvStart = {0, 0}, const rawrbox::Vector2f& uvEnd = {1, 1}); + virtual void drawCircle(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, const rawrbox::Color& col = rawrbox::Colors::White(), size_t roundness = 32, float angleStart = 0.F, float angleEnd = 360.F); + virtual void drawLine(const rawrbox::Vector2& from, const rawrbox::Vector2& to, const rawrbox::Color& col = rawrbox::Colors::White()); + virtual void drawText(const rawrbox::Font& font, const std::string& text, const rawrbox::Vector2f& pos, const rawrbox::Color& col = rawrbox::Colors::White(), rawrbox::Alignment alignX = rawrbox::Alignment::Left, rawrbox::Alignment alignY = rawrbox::Alignment::Left); // -------------------- // ------ RENDERING diff --git a/render/include/rawrbox/render/text/font.hpp b/render/include/rawrbox/render/text/font.hpp index 6cf8880c..14fd379a 100644 --- a/render/include/rawrbox/render/text/font.hpp +++ b/render/include/rawrbox/render/text/font.hpp @@ -102,14 +102,14 @@ namespace rawrbox { rawrbox::FontInfo _info = {}; // INTERNAL --- - void loadFontInfo(); + virtual void loadFontInfo(); std::unique_ptr bakeGlyphAlpha(uint32_t codePoint); - void generateGlyph(uint32_t codePoint); + virtual void generateGlyph(uint32_t codePoint); // ---- public: - ~Font(); + virtual ~Font(); Font(const std::vector& buffer, uint32_t pixelHeight, int32_t fontIndex = 0, int16_t widthPadding = 6, int16_t heightPadding = 6); Font(Font&&) = delete; @@ -118,24 +118,24 @@ namespace rawrbox { Font& operator=(const Font&) = delete; // LOADING --- - void addChars(const std::string& chars); + virtual void addChars(const std::string& chars); // ---- // UTILS --- - [[nodiscard]] const rawrbox::FontInfo getFontInfo() const; + [[nodiscard]] virtual const rawrbox::FontInfo getFontInfo() const; - [[nodiscard]] bool hasGlyph(uint32_t codepoint) const; - [[nodiscard]] rawrbox::Glyph* getGlyph(uint32_t codepoint) const; + [[nodiscard]] virtual bool hasGlyph(uint32_t codepoint) const; + [[nodiscard]] virtual rawrbox::Glyph* getGlyph(uint32_t codepoint) const; - [[nodiscard]] float getSize() const; - [[nodiscard]] float getScale() const; - [[nodiscard]] float getLineHeight() const; - [[nodiscard]] float getKerning(uint32_t prevCodePoint, uint32_t nextCodePoint) const; + [[nodiscard]] virtual float getSize() const; + [[nodiscard]] virtual float getScale() const; + [[nodiscard]] virtual float getLineHeight() const; + [[nodiscard]] virtual float getKerning(uint32_t prevCodePoint, uint32_t nextCodePoint) const; - [[nodiscard]] rawrbox::Vector2f getStringSize(const std::string& text) const; - [[nodiscard]] rawrbox::TexturePack* getPackTexture(rawrbox::Glyph* g) const; + [[nodiscard]] virtual rawrbox::Vector2f getStringSize(const std::string& text) const; + [[nodiscard]] virtual rawrbox::TexturePack* getPackTexture(rawrbox::Glyph* g) const; - void render(const std::string& text, const rawrbox::Vector2f& pos, bool yIsUp, std::function render) const; + virtual void render(const std::string& text, const rawrbox::Vector2f& pos, bool yIsUp, std::function render) const; // ---- // GLOBAL UTILS --- diff --git a/render/include/rawrbox/render/texture/base.hpp b/render/include/rawrbox/render/texture/base.hpp index df0744b0..e5fae9aa 100644 --- a/render/include/rawrbox/render/texture/base.hpp +++ b/render/include/rawrbox/render/texture/base.hpp @@ -36,15 +36,15 @@ namespace rawrbox { // UTILS---- [[nodiscard]] virtual bool hasTransparency() const; - [[nodiscard]] const virtual rawrbox::Vector2i& getSize() const; - [[nodiscard]] virtual bool valid() const; - [[nodiscard]] const virtual bgfx::TextureHandle& getHandle() const; + [[nodiscard]] virtual const rawrbox::Vector2i& getSize() const; + [[nodiscard]] virtual bool isValid() const; + [[nodiscard]] virtual const bgfx::TextureHandle& getHandle() const; + [[nodiscard]] virtual std::array getData() const; // ----- virtual void setFlags(uint64_t flags); virtual void upload(bgfx::TextureFormat::Enum format = bgfx::TextureFormat::Count) = 0; virtual void update(); - virtual std::array getData(); }; } // namespace rawrbox diff --git a/render/include/rawrbox/render/texture/pack.hpp b/render/include/rawrbox/render/texture/pack.hpp index 0ba4d66a..206f1e20 100644 --- a/render/include/rawrbox/render/texture/pack.hpp +++ b/render/include/rawrbox/render/texture/pack.hpp @@ -20,7 +20,7 @@ namespace rawrbox { std::unique_ptr right = nullptr; bool canInsertNode(int insertedWidth, int insertedHeight); - std::optional> InsertNode(int width, int height); + std::optional> InsertNode(int width, int height); PackNode() = default; PackNode(int _x, int _y, int _w, int _h) : x(_x), y(_y), width(_w), height(_h){}; diff --git a/render/include/rawrbox/render/window.hpp b/render/include/rawrbox/render/window.hpp index 7bcd52f0..f9b57093 100644 --- a/render/include/rawrbox/render/window.hpp +++ b/render/include/rawrbox/render/window.hpp @@ -191,8 +191,6 @@ namespace rawrbox { // UTILS --------------- void close(); - [[nodiscard]] virtual bool getShouldClose() const; - virtual void setShouldClose(bool close) const; [[nodiscard]] virtual rawrbox::Vector2i getSize() const; [[nodiscard]] virtual float getAspectRatio() const; diff --git a/render/lua/render_enums.lua b/render/lua/render_enums.lua new file mode 100644 index 00000000..f9dbf3d0 --- /dev/null +++ b/render/lua/render_enums.lua @@ -0,0 +1,12 @@ +LightType = { + UNKNOWN = 0, + + POINT = 1, + SPOT = 2, + DIR = 3, +} + +FogType = { + FOG_LINEAR = 0, + FOG_EXP = 1 +} diff --git a/render/src/decals/manager.cpp b/render/src/decals/manager.cpp index d30a5e9c..56d930c1 100644 --- a/render/src/decals/manager.cpp +++ b/render/src/decals/manager.cpp @@ -15,18 +15,20 @@ namespace rawrbox { _model->getTemplate().setTexture(atlas); } - void DECALS::add(const rawrbox::Vector3f& pos, const rawrbox::Vector3f& scale, float direction, const rawrbox::Colorf& color, uint16_t atlasId) { - if (_model == nullptr) return; + bool DECALS::add(const rawrbox::Vector3f& pos, const rawrbox::Vector3f& scale, float direction, const rawrbox::Colorf& color, uint16_t atlasId) { + if (_model == nullptr) return false; rawrbox::Matrix4x4 m; m.mtxSRT(scale, rawrbox::Vector4f::toQuat({bx::toRad(direction), 0, 0}), pos); _model->addInstance({m, color, {static_cast(atlasId), 0, 0, 0}}); + return true; } - void DECALS::remove(size_t i) { - if (_model == nullptr) return; + bool DECALS::remove(size_t i) { + if (_model == nullptr) return false; _model->removeInstance(i); + return true; } const rawrbox::Instance& DECALS::get(size_t i) { diff --git a/render/src/light/manager.cpp b/render/src/light/manager.cpp index 8f5b9966..e3f43987 100644 --- a/render/src/light/manager.cpp +++ b/render/src/light/manager.cpp @@ -5,7 +5,7 @@ namespace rawrbox { // PRIVATE ---- - std::vector> LIGHTS::_lights = {}; + std::vector> LIGHTS::_lights = {}; bgfx::DynamicVertexBufferHandle LIGHTS::_buffer = BGFX_INVALID_HANDLE; bgfx::UniformHandle LIGHTS::_u_lightSettings = BGFX_INVALID_HANDLE; @@ -21,7 +21,7 @@ namespace rawrbox { rawrbox::Colorf LIGHTS::_ambient = {0.01F, 0.01F, 0.01F, 1.F}; // Sun -- - rawrbox::Colorf LIGHTS::_sun_color = rawrbox::Colors::Transparent; // No sun by default + rawrbox::Colorf LIGHTS::_sun_color = rawrbox::Colors::Transparent(); // No sun by default rawrbox::Vector3f LIGHTS::_sun_direction = {0, 0, 0}; // Fog -- diff --git a/render/src/materials/base.cpp b/render/src/materials/base.cpp index 3a53a061..11d94f30 100644 --- a/render/src/materials/base.cpp +++ b/render/src/materials/base.cpp @@ -36,7 +36,7 @@ namespace rawrbox { } void MaterialBase::process(const rawrbox::Mesh& mesh) { - if (mesh.texture != nullptr && mesh.texture->valid() && !mesh.lineMode && !mesh.wireframe) { + if (mesh.texture != nullptr && mesh.texture->isValid() && !mesh.lineMode && !mesh.wireframe) { mesh.texture->update(); // Update texture bgfx::setUniform(this->_u_tex_flags, mesh.texture->getData().data()); @@ -45,7 +45,7 @@ namespace rawrbox { bgfx::setTexture(rawrbox::SAMPLE_MAT_ALBEDO, this->_s_albedo, rawrbox::WHITE_TEXTURE->getHandle()); } - if (mesh.displacementTexture != nullptr && mesh.displacementTexture->valid()) { + if (mesh.displacementTexture != nullptr && mesh.displacementTexture->isValid()) { bgfx::setTexture(rawrbox::SAMPLE_MAT_DISPLACEMENT, this->_s_displacement, mesh.displacementTexture->getHandle()); } else { bgfx::setTexture(rawrbox::SAMPLE_MAT_DISPLACEMENT, this->_s_displacement, rawrbox::BLACK_TEXTURE->getHandle()); diff --git a/render/src/materials/lit.cpp b/render/src/materials/lit.cpp index a224ce08..c9578387 100644 --- a/render/src/materials/lit.cpp +++ b/render/src/materials/lit.cpp @@ -48,19 +48,19 @@ namespace rawrbox { } void MaterialLit::process(const rawrbox::Mesh& mesh) { - if (mesh.normalTexture != nullptr && mesh.normalTexture->valid() && !mesh.lineMode && !mesh.wireframe) { + if (mesh.normalTexture != nullptr && mesh.normalTexture->isValid() && !mesh.lineMode && !mesh.wireframe) { bgfx::setTexture(rawrbox::SAMPLE_MAT_NORMAL, this->_s_normal, mesh.normalTexture->getHandle()); } else { bgfx::setTexture(rawrbox::SAMPLE_MAT_NORMAL, this->_s_normal, rawrbox::NORMAL_TEXTURE->getHandle()); } - if (mesh.specularTexture != nullptr && mesh.specularTexture->valid() && !mesh.lineMode && !mesh.wireframe) { + if (mesh.specularTexture != nullptr && mesh.specularTexture->isValid() && !mesh.lineMode && !mesh.wireframe) { bgfx::setTexture(rawrbox::SAMPLE_MAT_SPECULAR, this->_s_specular, mesh.specularTexture->getHandle()); } else { bgfx::setTexture(rawrbox::SAMPLE_MAT_SPECULAR, this->_s_specular, rawrbox::BLACK_TEXTURE->getHandle()); } - if (mesh.emissionTexture != nullptr && mesh.emissionTexture->valid() && !mesh.lineMode && !mesh.wireframe) { + if (mesh.emissionTexture != nullptr && mesh.emissionTexture->isValid() && !mesh.lineMode && !mesh.wireframe) { bgfx::setTexture(rawrbox::SAMPLE_MAT_EMISSION, this->_s_emission, mesh.emissionTexture->getHandle()); } else { bgfx::setTexture(rawrbox::SAMPLE_MAT_EMISSION, this->_s_emission, rawrbox::BLACK_TEXTURE->getHandle()); diff --git a/render/src/model/text3D.cpp b/render/src/model/text3D.cpp index c8230757..5a765ca4 100644 --- a/render/src/model/text3D.cpp +++ b/render/src/model/text3D.cpp @@ -94,7 +94,7 @@ namespace rawrbox { bgfx::setTransform((this->getMatrix() * mesh->matrix).data()); - if (this->isDynamicBuffer()) { + if (this->isDynamic()) { bgfx::setVertexBuffer(0, this->_vbdh, mesh->baseVertex, mesh->totalVertex); bgfx::setIndexBuffer(this->_ibdh, mesh->baseIndex, mesh->totalIndex); } else { diff --git a/render/src/scripting/wrappers/camera_wrapper.cpp b/render/src/scripting/wrappers/camera_wrapper.cpp new file mode 100644 index 00000000..3d6ee82e --- /dev/null +++ b/render/src/scripting/wrappers/camera_wrapper.cpp @@ -0,0 +1,101 @@ +#include +#include + +namespace rawrbox { + + // UTILS ----- + void CameraWrapper::setPos(const rawrbox::Vector3f& pos) { + if (rawrbox::MAIN_CAMERA == nullptr) return; + rawrbox::MAIN_CAMERA->setPos(pos); + } + + const rawrbox::Vector3f CameraWrapper::getPos() const { + if (rawrbox::MAIN_CAMERA == nullptr) return {}; + return rawrbox::MAIN_CAMERA->getPos(); + } + + void CameraWrapper::setAngle(const rawrbox::Vector4f& ang) { + if (rawrbox::MAIN_CAMERA == nullptr) return; + rawrbox::MAIN_CAMERA->setAngle(ang); + } + + const rawrbox::Vector4f CameraWrapper::getAngle() const { + if (rawrbox::MAIN_CAMERA == nullptr) return {}; + return rawrbox::MAIN_CAMERA->getAngle(); + } + + rawrbox::Vector3f CameraWrapper::getForward() const { + if (rawrbox::MAIN_CAMERA == nullptr) return {}; + return rawrbox::MAIN_CAMERA->getForward(); + } + + rawrbox::Vector3f CameraWrapper::getRight() const { + if (rawrbox::MAIN_CAMERA == nullptr) return {}; + return rawrbox::MAIN_CAMERA->getRight(); + } + + rawrbox::Vector3f CameraWrapper::getUp() const { + if (rawrbox::MAIN_CAMERA == nullptr) return {}; + return rawrbox::MAIN_CAMERA->getUp(); + } + + float CameraWrapper::getZFar() const { + if (rawrbox::MAIN_CAMERA == nullptr) return 0; + return rawrbox::MAIN_CAMERA->getZFar(); + } + + float CameraWrapper::getZNear() const { + if (rawrbox::MAIN_CAMERA == nullptr) return 0; + return rawrbox::MAIN_CAMERA->getZNear(); + } + + const rawrbox::Matrix4x4 CameraWrapper::getViewMtx() const { + if (rawrbox::MAIN_CAMERA == nullptr) return {}; + return rawrbox::MAIN_CAMERA->getViewMtx(); + } + + const rawrbox::Matrix4x4 CameraWrapper::getProjMtx() const { + if (rawrbox::MAIN_CAMERA == nullptr) return {}; + return rawrbox::MAIN_CAMERA->getProjMtx(); + } + + const rawrbox::Matrix4x4 CameraWrapper::getProjViewMtx() const { + if (rawrbox::MAIN_CAMERA == nullptr) return {}; + return rawrbox::MAIN_CAMERA->getProjViewMtx(); + } + + const rawrbox::Vector3f CameraWrapper::worldToScreen(const rawrbox::Vector3f& pos) const { + if (rawrbox::MAIN_CAMERA == nullptr) return {}; + return rawrbox::MAIN_CAMERA->worldToScreen(pos); + } + + const rawrbox::Vector3f CameraWrapper::screenToWorld(const rawrbox::Vector2f& screen_pos) const { + if (rawrbox::MAIN_CAMERA == nullptr) return {}; + return rawrbox::MAIN_CAMERA->screenToWorld(screen_pos); + } + // ---------------- + + void CameraWrapper::registerLua(sol::state& lua) { + lua.new_usertype("Camera", + sol::no_constructor, + + "setPos", &CameraWrapper::setPos, + "getPos", &CameraWrapper::getPos, + "setAngle", &CameraWrapper::setAngle, + "getAngle", &CameraWrapper::getAngle, + + // UTILS ---- + "getForward", &CameraWrapper::getForward, + "getRight", &CameraWrapper::getRight, + "getUp", &CameraWrapper::getUp, + "getZFar", &CameraWrapper::getZFar, + "getZNear", &CameraWrapper::getZNear, + "getViewMtx", &CameraWrapper::getViewMtx, + "getProjMtx", &CameraWrapper::getProjMtx, + "getProjViewMtx", &CameraWrapper::getProjViewMtx, + "worldToScreen", &CameraWrapper::worldToScreen, + "screenToWorld", &CameraWrapper::screenToWorld + // --------- + ); + } +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/decals_wrapper.cpp b/render/src/scripting/wrappers/decals_wrapper.cpp new file mode 100644 index 00000000..34ee0959 --- /dev/null +++ b/render/src/scripting/wrappers/decals_wrapper.cpp @@ -0,0 +1,35 @@ +#include + +namespace rawrbox { + + // UTILS ----- + bool DecalsWrapper::add(const rawrbox::Vector3f& pos, const sol::optional scale, const sol::optional direction, const sol::optional color, const sol::optional atlasId) { + return rawrbox::DECALS::add(pos, scale.value_or(rawrbox::Vector3f::one()), direction.value_or(0.F), color.value_or(rawrbox::Colorsi::White()).cast(), atlasId.value_or(0)); + } + + bool DecalsWrapper::remove(size_t i) { + return rawrbox::DECALS::remove(i); + } + + const rawrbox::Instance& DecalsWrapper::get(size_t i) { + return rawrbox::DECALS::get(i); + } + + size_t DecalsWrapper::count() { + return rawrbox::DECALS::count(); + } + // ---------------- + + void DecalsWrapper::registerLua(sol::state& lua) { + lua.new_usertype("Decals", + sol::no_constructor, + + // UTILS ---- + "add", &DecalsWrapper::add, + "remove", &DecalsWrapper::remove, + "get", &DecalsWrapper::get, + "count", &DecalsWrapper::count + // --------- + ); + } +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/light/base_wrapper.cpp b/render/src/scripting/wrappers/light/base_wrapper.cpp new file mode 100644 index 00000000..c8217835 --- /dev/null +++ b/render/src/scripting/wrappers/light/base_wrapper.cpp @@ -0,0 +1,132 @@ + +#include + +namespace rawrbox { + LightBaseWrapper::LightBaseWrapper(const std::shared_ptr& ref) : _ref(ref) {} + LightBaseWrapper::~LightBaseWrapper() { this->_ref.reset(); } + + // UTILS ---- + const rawrbox::Colori LightBaseWrapper::getColor() const { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + return this->_ref.lock()->getColor().cast(); + } + + void LightBaseWrapper::setColor(const rawrbox::Colori& col) { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + this->_ref.lock()->setColor(col.cast()); + } + + const rawrbox::Vector4f LightBaseWrapper::getData() const { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + return this->_ref.lock()->getData(); + } + + void LightBaseWrapper::setRadius(float radius) { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + this->_ref.lock()->setRadius(radius); + } + + float LightBaseWrapper::getRadius() const { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + return this->_ref.lock()->getRadius(); + } + + size_t LightBaseWrapper::id() const { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + return this->_ref.lock()->id(); + } + + bool LightBaseWrapper::isOn() const { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + return this->_ref.lock()->isOn(); + } + + void LightBaseWrapper::setStatus(bool on) { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + this->_ref.lock()->setStatus(on); + } + + const rawrbox::Vector3f& LightBaseWrapper::getPos() const { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + return this->_ref.lock()->getPos(); + } + + void LightBaseWrapper::setPos(const rawrbox::Vector3f& pos) { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + this->_ref.lock()->setPos(pos); + } + + const rawrbox::Vector3f& LightBaseWrapper::getOffsetPos() const { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + return this->_ref.lock()->getOffsetPos(); + } + + void LightBaseWrapper::setOffsetPos(const rawrbox::Vector3f& pos) { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + this->_ref.lock()->setOffsetPos(pos); + } + + const rawrbox::Vector3f LightBaseWrapper::getWorldPos() const { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + return this->_ref.lock()->getWorldPos(); + } + + rawrbox::LightType LightBaseWrapper::getType() const { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + return this->_ref.lock()->getType(); + } + + const rawrbox::Vector3f& LightBaseWrapper::getDirection() const { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + return this->_ref.lock()->getDirection(); + } + + void LightBaseWrapper::setDirection(const rawrbox::Vector3f& dir) { + if (this->isValid()) throw std::runtime_error("[RawrBox-LightBase] Light reference not set!"); + this->_ref.lock()->setDirection(dir); + } + // ------ + + bool LightBaseWrapper::isValid() const { + return !this->_ref.expired(); + } + + rawrbox::LightBase* LightBaseWrapper::getRef() const { + return nullptr; + // return &_ref.lock(); + } + + void LightBaseWrapper::registerLua(sol::state& lua) { + lua.new_usertype("LightBase", + sol::no_constructor, + + // UTILS ---- + "getColor", &LightBaseWrapper::getColor, + "setColor", &LightBaseWrapper::setPos, + + "getData", &LightBaseWrapper::getData, + + "setRadius", &LightBaseWrapper::setRadius, + "getRadius", &LightBaseWrapper::getRadius, + + "id", &LightBaseWrapper::id, + + "isOn", &LightBaseWrapper::isOn, + "setStatus", &LightBaseWrapper::setStatus, + + "getPos", &LightBaseWrapper::getPos, + "setPos", &LightBaseWrapper::setPos, + + "getOffsetPos", &LightBaseWrapper::getOffsetPos, + "setOffsetPos", &LightBaseWrapper::setOffsetPos, + + "getWorldPos", &LightBaseWrapper::getWorldPos, + "getType", &LightBaseWrapper::getType, + + "getDirection", &LightBaseWrapper::getDirection, + "setDirection", &LightBaseWrapper::setDirection, + // -------------- + + "isValid", &LightBaseWrapper::isValid); + } +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/light/manager_wrapper.cpp b/render/src/scripting/wrappers/light/manager_wrapper.cpp new file mode 100644 index 00000000..6cebd4b0 --- /dev/null +++ b/render/src/scripting/wrappers/light/manager_wrapper.cpp @@ -0,0 +1,122 @@ +#include +#include +#include + +namespace rawrbox { + // UTILS ---- + void LightsWrapper::setEnabled(bool fb) { + rawrbox::LIGHTS::setEnabled(fb); + } + + // SUN + void LightsWrapper::setSun(const rawrbox::Vector3f& dir, const rawrbox::Colori& col) { + rawrbox::LIGHTS::setSun(dir, col.cast()); + } + + const rawrbox::Colori LightsWrapper::getSunColor() { + return rawrbox::LIGHTS::getSunColor().cast(); + } + + const rawrbox::Vector3f& LightsWrapper::getSunDir() { + return rawrbox::LIGHTS::getSunDir(); + } + // ---- + + // FOG + void LightsWrapper::setFog(rawrbox::FOG_TYPE type, float end, float density, const sol::optional col) { + rawrbox::LIGHTS::setFog(type, end, density, col.value_or(rawrbox::Colorsi::White()).cast()); + } + + rawrbox::FOG_TYPE LightsWrapper::getFogType() { + return rawrbox::LIGHTS::getFogType(); + } + + const rawrbox::Colori LightsWrapper::getFogColor() { + return rawrbox::LIGHTS::getFogColor().cast(); + } + + float LightsWrapper::getFogEnd() { + return rawrbox::LIGHTS::getFogEnd(); + } + + float LightsWrapper::getFogDensity() { + return rawrbox::LIGHTS::getFogDensity(); + } + // ---- + + // AMBIENT + void LightsWrapper::setAmbient(const rawrbox::Colori& col) { + rawrbox::LIGHTS::setAmbient(col.cast()); + } + + const rawrbox::Colori LightsWrapper::getAmbient() { + return rawrbox::LIGHTS::getAmbient().cast(); + } + // ------- + + // Light ---- + + void LightsWrapper::addPoint(const rawrbox::Vector3f& pos, const rawrbox::Colori& color, float radius) { + rawrbox::LIGHTS::addLight(pos, color.cast(), radius); + } + + void LightsWrapper::addSpot(const rawrbox::Vector3f& posMatrix, const rawrbox::Vector3f& direction, const rawrbox::Colori& color, float innerCone, float outerCone, float power) { + rawrbox::LIGHTS::addLight(posMatrix, direction, color.cast(), innerCone, outerCone, power); + } + + void LightsWrapper::removeLight(rawrbox::LightBaseWrapper& light) { + if (!light.isValid()) return; + rawrbox::LIGHTS::removeLight(light.getRef()); + } + // --------- + + // Light utils ---- + rawrbox::LightBaseWrapper LightsWrapper::getLight(size_t indx) { + // auto light = rawrbox::LIGHTS::getLight(indx); + // return {light}; + throw std::runtime_error("AAAAAAAAAAA"); + } + + size_t LightsWrapper::count() { + return rawrbox::LIGHTS::count(); + } + // --------- + + void LightsWrapper::registerLua(sol::state& lua) { + lua.new_usertype("Lights", + sol::no_constructor, + + // UTILS ---- + "setEnabled", &LightsWrapper::setEnabled, + // --------- + + // SUN + "setSun", &LightsWrapper::setFog, + "getSunColor", &LightsWrapper::getSunColor, + "getSunDir", &LightsWrapper::getSunDir, + // --------- + + // FOG + "setFog", &LightsWrapper::setFog, + "getFogType", &LightsWrapper::getFogType, + "getFogColor", &LightsWrapper::getFogColor, + "getFogEnd", &LightsWrapper::getFogEnd, + "getFogDensity", &LightsWrapper::getFogDensity, + // --------- + + // AMBIENT + "setAmbient", &LightsWrapper::setAmbient, + "getAmbient", &LightsWrapper::getAmbient, + // --------- + + // Light + "removeLight", &LightsWrapper::removeLight, + // --------- + + // Light utils + "getLight", &LightsWrapper::getLight, + "count", &LightsWrapper::count + // --------- + ); + } +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/model/base_wrapper.cpp b/render/src/scripting/wrappers/model/base_wrapper.cpp new file mode 100644 index 00000000..c3a4fe40 --- /dev/null +++ b/render/src/scripting/wrappers/model/base_wrapper.cpp @@ -0,0 +1,87 @@ + +#include +#include + +namespace rawrbox { + ModelBaseWrapper::ModelBaseWrapper(const std::shared_ptr>& ref) : _ref(ref) {} + ModelBaseWrapper::~ModelBaseWrapper() { this->_ref.reset(); } + + // UTILS ---- + const rawrbox::Vector3f ModelBaseWrapper::getPos() const { + if (!this->isValid()) return {}; + return this->_ref.lock()->getPos(); + } + + void ModelBaseWrapper::setPos(const rawrbox::Vector3f& pos) { + if (!this->isValid()) return; + this->_ref.lock()->setPos(pos); + } + + const rawrbox::Vector3f ModelBaseWrapper::getScale() const { + if (!this->isValid()) return {}; + return this->_ref.lock()->getScale(); + } + + void ModelBaseWrapper::setScale(const rawrbox::Vector3f& scale) { + if (!this->isValid()) return; + this->_ref.lock()->setScale(scale); + } + + const rawrbox::Vector4f ModelBaseWrapper::getAngle() const { + if (!this->isValid()) return {}; + return this->_ref.lock()->getAngle(); + } + + void ModelBaseWrapper::setAngle(const rawrbox::Vector4f& ang) { + if (!this->isValid()) return; + this->_ref.lock()->setAngle(ang); + } + + void ModelBaseWrapper::setEulerAngle(const rawrbox::Vector3f& ang) { + if (!this->isValid()) return; + this->_ref.lock()->setEulerAngle(ang); + } + + const rawrbox::Matrix4x4 ModelBaseWrapper::getMatrix() const { + if (!this->isValid()) return {}; + return this->_ref.lock()->getMatrix(); + } + + bool ModelBaseWrapper::isDynamic() const { + if (!this->isValid()) return false; + return this->_ref.lock()->isDynamic(); + } + + bool ModelBaseWrapper::isUploaded() const { + if (!this->isValid()) return false; + return this->_ref.lock()->isUploaded(); + } + // ------ + + bool ModelBaseWrapper::isValid() const { + return !this->_ref.expired(); + } + + void ModelBaseWrapper::registerLua(sol::state& lua) { + lua.new_usertype("ModelBase<>", + sol::no_constructor, + + // UTILS ---- + "getPos", &ModelBaseWrapper::getPos, + "setPos", &ModelBaseWrapper::setPos, + + "getScale", &ModelBaseWrapper::getScale, + "setScale", &ModelBaseWrapper::setScale, + + "getAngle", &ModelBaseWrapper::getAngle, + "setAngle", &ModelBaseWrapper::setAngle, + "setEulerAngle", &ModelBaseWrapper::setEulerAngle, + + "getMatrix", &ModelBaseWrapper::getMatrix, + "isDynamic", &ModelBaseWrapper::isDynamic, + "isUploaded", &ModelBaseWrapper::isUploaded, + // -------------- + + "isValid", &ModelBaseWrapper::isValid); + } +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/model/mesh_wrapper.cpp b/render/src/scripting/wrappers/model/mesh_wrapper.cpp new file mode 100644 index 00000000..f3be2396 --- /dev/null +++ b/render/src/scripting/wrappers/model/mesh_wrapper.cpp @@ -0,0 +1,67 @@ + +#include +#include + +namespace rawrbox { + void MeshWrapper::registerLua(sol::state& lua) { + lua.new_usertype("Mesh", + sol::constructors(), + + "getName", &Mesh::getName, + "setName", &Mesh::setName, + + // "getVertices", &Mesh::getVertices, + "getIndices", &Mesh::getIndices, + "getBBOX", &Mesh::getBBOX, + + "empty", &Mesh::empty, + + "getMatrix", &Mesh::getMatrix, + + "getPos", &Mesh::getPos, + "setPos", &Mesh::setPos, + + "getAngle", &Mesh::getAngle, + "setAngle", &Mesh::setAngle, + "setEulerAngle", &Mesh::setEulerAngle, + + "getScale", &Mesh::getScale, + "setScale", &Mesh::setScale, + + /* "getTexture", &Mesh::getTexture, + "setTexture", &Mesh::setTexture,*/ + + "getAtlasID", &Mesh::getAtlasID, + "setAtlasID", &Mesh::setAtlasID, + + /*"getNormalTexture", &Mesh::getNormalTexture, + "setNormalTexture", &Mesh::setNormalTexture, + "getDisplacementTexture", &Mesh::getDisplacementTexture, + "setDisplacementTexture", &Mesh::setDisplacementTexture, + "getEmissionTexture", &Mesh::getEmissionTexture, + "setEmissionTexture", &Mesh::setEmissionTexture, + "getSpecularTexture", &Mesh::getSpecularTexture, + "setSpecularTexture", &Mesh::setSpecularTexture,*/ + + "setVertexSnap", &Mesh::setVertexSnap, + "setWireframe", &Mesh::setWireframe, + "setCulling", &Mesh::setCulling, + "setDepthTest", &Mesh::setDepthTest, + "setBlend", &Mesh::setBlend, + "setRecieveDecals", &Mesh::setRecieveDecals, + "setColor", &Mesh::setColor, + + "addData", &Mesh::addData, + "getData", &Mesh::getData, + "hasData", &Mesh::hasData, + + //"getSkeleton", &Mesh::getSkeleton, + + "clear", &Mesh::clear, + + "merge", &Mesh::merge, + + "setOptimizable", &Mesh::setOptimizable, + "canOptimize", &Mesh::canOptimize); + } +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/model/model_wrapper.cpp b/render/src/scripting/wrappers/model/model_wrapper.cpp new file mode 100644 index 00000000..5273578c --- /dev/null +++ b/render/src/scripting/wrappers/model/model_wrapper.cpp @@ -0,0 +1,137 @@ + +#include +#include + +namespace rawrbox { + ModelWrapper::ModelWrapper(const std::shared_ptr>& ref) : rawrbox::ModelBaseWrapper(ref) {} + + // ANIMS --- + void ModelWrapper::playAnimation(const std::string& name, sol::optional loop, sol::optional speed) { + if (!this->isValid()) return; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + ptr.lock()->playAnimation(name, loop.value_or(true), speed.value_or(1.F)); + } + + void ModelWrapper::stopAnimation(const std::string& name) { + if (!this->isValid()) return; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + ptr.lock()->stopAnimation(name); + } + // --- + + // UTILS ---- + void ModelWrapper::setOptimizable(bool optimize) { + if (!this->isValid()) return; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + ptr.lock()->setOptimizable(optimize); + } + + void ModelWrapper::optimize() { + if (!this->isValid()) return; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + ptr.lock()->optimize(); + } + + void ModelWrapper::setPos(const rawrbox::Vector3f& pos) { + if (!this->isValid()) return; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + ptr.lock()->setPos(pos); + } + + void ModelWrapper::setAngle(const rawrbox::Vector4f& angle) { + if (!this->isValid()) return; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + ptr.lock()->setAngle(angle); + } + + void ModelWrapper::setEulerAngle(const rawrbox::Vector3f& angle) { + if (!this->isValid()) return; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + ptr.lock()->setEulerAngle(angle); + } + + void ModelWrapper::setScale(const rawrbox::Vector3f& size) { + if (!this->isValid()) return; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + ptr.lock()->setScale(size); + } + + const rawrbox::BBOX ModelWrapper::getBBOX() const { + if (!this->isValid()) return {}; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + return ptr.lock()->getBBOX(); + } + + size_t ModelWrapper::totalMeshes() const { + if (!this->isValid()) return 0; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + return ptr.lock()->totalMeshes(); + } + + bool ModelWrapper::empty() const { + if (!this->isValid()) return true; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + return ptr.lock()->empty(); + } + + void ModelWrapper::removeMeshByName(const std::string& id) { + if (!this->isValid()) return; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + return ptr.lock()->removeMeshByName(id); + } + + void ModelWrapper::removeMesh(size_t index) { + if (!this->isValid()) return; + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + return ptr.lock()->removeMesh(index); + } + + rawrbox::Mesh* ModelWrapper::getMeshByName(const std::string& id) { + if (!this->isValid()) return nullptr; + + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + auto mesh = ptr.lock()->getMeshByName(id); + if (mesh == nullptr) return nullptr; + + return mesh; + } + + rawrbox::Mesh* ModelWrapper::getMesh(sol::optional id) { + if (!this->isValid()) return nullptr; + + std::weak_ptr> ptr = std::dynamic_pointer_cast>(this->_ref.lock()); + auto mesh = ptr.lock()->getMesh(id.value_or(0)); + if (mesh == nullptr) return nullptr; + + return mesh; + } + // ------ + + void ModelWrapper::registerLua(sol::state& lua) { + lua.new_usertype("Model<>", + sol::no_constructor, + + // UTILS ---- + "setOptimizable", &ModelWrapper::setOptimizable, + "optimize", &ModelWrapper::optimize, + + "getBBOX", &ModelWrapper::getBBOX, + + "totalMeshes", &ModelWrapper::totalMeshes, + "empty", &ModelWrapper::empty, + + "removeMeshByName", &ModelWrapper::removeMeshByName, + "removeMesh", &ModelWrapper::removeMesh, + // ---- + + "getMeshByName", &ModelWrapper::getMeshByName, + "getMesh", &ModelWrapper::getMesh, + + // ANIMS --- + "playAnimation", &ModelWrapper::playAnimation, + "stopAnimation", &ModelWrapper::stopAnimation, + // ---- + + sol::base_classes, sol::bases()); + } +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/resources/font_loader_wrapper.cpp b/render/src/scripting/wrappers/resources/font_loader_wrapper.cpp new file mode 100644 index 00000000..971cac39 --- /dev/null +++ b/render/src/scripting/wrappers/resources/font_loader_wrapper.cpp @@ -0,0 +1,35 @@ + +#include +#include +#include +#include + +namespace rawrbox { + FontLoaderWrapper::FontLoaderWrapper(rawrbox::Mod* mod) : _mod(mod) {} + + rawrbox::FontWrapper FontLoaderWrapper::get(const std::string& path, sol::optional size) { + if (this->_mod == nullptr) throw std::runtime_error("[RawrBox-FontLoader] MOD not set!"); + auto fixedPath = rawrbox::LuaUtils::getContent(path, this->_mod->getFolder().generic_string()); + + if (!rawrbox::RESOURCES::isLoaded(fixedPath)) { + fmt::print("[Resources] Loading '{}' RUNTIME! You should load content on the 'MOD:onLoad' stage instead!", fixedPath); + + auto ptr = rawrbox::RESOURCES::loadFile(fixedPath, 0); + if (ptr == nullptr) throw std::runtime_error(fmt::format("[Resources] '{}' not found!", fixedPath)); + + return {ptr->getSize(size.value_or(12))}; + } else { + auto ptr = rawrbox::RESOURCES::getFile(fixedPath); + if (ptr == nullptr) throw std::runtime_error(fmt::format("[Resources] '{}' not found!", fixedPath)); + + return {ptr->getSize(size.value_or(12))}; + } + } + + void FontLoaderWrapper::registerLua(sol::state& lua) { + lua.new_usertype("fontLoader", + sol::no_constructor, + "get", &FontLoaderWrapper::get); + } + +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/resources/texture_loader_wrapper.cpp b/render/src/scripting/wrappers/resources/texture_loader_wrapper.cpp new file mode 100644 index 00000000..531bc062 --- /dev/null +++ b/render/src/scripting/wrappers/resources/texture_loader_wrapper.cpp @@ -0,0 +1,35 @@ + +#include +#include +#include +#include + +namespace rawrbox { + TextureLoaderWrapper::TextureLoaderWrapper(rawrbox::Mod* mod) : _mod(mod) {} + + rawrbox::TextureWrapper TextureLoaderWrapper::get(const std::string& path, sol::optional loadFlags) { + if (this->_mod == nullptr) throw std::runtime_error("[RawrBox-TextureLoader] MOD not set!"); + auto fixedPath = rawrbox::LuaUtils::getContent(path, this->_mod->getFolder().generic_string()); + + if (!rawrbox::RESOURCES::isLoaded(fixedPath)) { + fmt::print("[Resources] Loading '{}' RUNTIME! You should load content on the 'MOD:onLoad' stage instead!", fixedPath); + + auto ptr = rawrbox::RESOURCES::loadFile(fixedPath, loadFlags.value_or(0)); + if (ptr == nullptr) throw std::runtime_error(fmt::format("[Resources] '{}' not found!", fixedPath)); + + return {ptr->get()}; + } else { + auto ptr = rawrbox::RESOURCES::getFile(fixedPath); + if (ptr == nullptr) throw std::runtime_error(fmt::format("[Resources] '{}' not found!", fixedPath)); + + return {ptr->get()}; + } + } + + void TextureLoaderWrapper::registerLua(sol::state& lua) { + lua.new_usertype("textureLoader", + sol::no_constructor, + "get", &TextureLoaderWrapper::get); + } + +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/stencil_wrapper.cpp b/render/src/scripting/wrappers/stencil_wrapper.cpp new file mode 100644 index 00000000..53e96419 --- /dev/null +++ b/render/src/scripting/wrappers/stencil_wrapper.cpp @@ -0,0 +1,122 @@ +#include + +namespace rawrbox { + StencilWrapper::StencilWrapper(rawrbox::Stencil* stencil) : _stencil(stencil) {} + + // Draw ---- + void StencilWrapper::drawTriangle(const rawrbox::Vector2f& a, const rawrbox::Vector2f& aUV, const rawrbox::Colori& colA, const rawrbox::Vector2f& b, const rawrbox::Vector2f& bUV, const rawrbox::Colori& colB, const rawrbox::Vector2f& c, const rawrbox::Vector2f& cUV, const rawrbox::Colori& colC) { + if (this->_stencil == nullptr) return; + this->_stencil->drawTriangle(a, aUV, colA.cast(), b, bUV, colB.cast(), c, cUV, colC.cast()); + } + + void StencilWrapper::drawBox(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, sol::optional col) { + if (this->_stencil == nullptr) return; + this->_stencil->drawBox(pos, size, col.value_or(rawrbox::Colorsi::White()).cast()); + } + + void StencilWrapper::drawTexture(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, const rawrbox::TextureWrapper& tex, const sol::optional col, const sol::optional uvStart, const sol::optional uvEnd) { + if (this->_stencil == nullptr || !tex.isValid()) return; + this->_stencil->drawTexture(pos, size, *tex.getRef(), col.value_or(rawrbox::Colorsi::White()).cast(), uvStart.value_or(rawrbox::Vector2f{0, 0}), uvEnd.value_or(rawrbox::Vector2f{1, 1})); + } + + void StencilWrapper::drawCircle(const rawrbox::Vector2f& pos, const rawrbox::Vector2f& size, sol::optional col, sol::optional roundness, sol::optional angleStart, sol::optional angleEnd) { + if (this->_stencil == nullptr) return; + this->_stencil->drawCircle(pos, size, col.value_or(rawrbox::Colorsi::White()).cast(), roundness.value_or(32), angleEnd.value_or(0.F), angleStart.value_or(360.F)); + } + + void StencilWrapper::drawLine(const rawrbox::Vector2& from, const rawrbox::Vector2& to, const sol::optional col) { + if (this->_stencil == nullptr) return; + this->_stencil->drawLine(from, to, col.value_or(rawrbox::Colorsi::White()).cast()); + } + + void StencilWrapper::drawText(const rawrbox::FontWrapper& font, const std::string& text, const rawrbox::Vector2f& pos, const sol::optional& col, const sol::optional alignX, const sol::optional alignY) { + if (this->_stencil == nullptr || font.isValid()) return; + this->_stencil->drawText(*font.getRef(), text, pos, col.value_or(rawrbox::Colorsi::White()).cast(), alignX.value_or(rawrbox::Alignment::Center), alignY.value_or(rawrbox::Alignment::Center)); + } + // ------- + + // Pop & Push ---- + void StencilWrapper::pushOffset(const rawrbox::Vector2f& offset) { + if (this->_stencil != nullptr) this->_stencil->pushOffset(offset); + } + + void StencilWrapper::popOffset() { + if (this->_stencil != nullptr) this->_stencil->popOffset(); + } + + void StencilWrapper::pushLocalOffset() { + if (this->_stencil != nullptr) this->_stencil->pushLocalOffset(); + } + + void StencilWrapper::popLocalOffset() { + if (this->_stencil != nullptr) this->_stencil->popLocalOffset(); + } + + void StencilWrapper::pushRotation(float rotation, const rawrbox::Vector2f& origin) { + if (this->_stencil != nullptr) this->_stencil->pushRotation({rotation, origin}); + } + + void StencilWrapper::popRotation() { + if (this->_stencil != nullptr) this->_stencil->popRotation(); + } + + void StencilWrapper::pushOutline(float thickness, float stipple) { + if (this->_stencil != nullptr) this->_stencil->pushOutline({thickness, stipple}); + } + + void StencilWrapper::popOutline() { + if (this->_stencil != nullptr) this->_stencil->popOutline(); + } + + void StencilWrapper::pushClipping(const rawrbox::AABB& rect) { + if (this->_stencil != nullptr) this->_stencil->pushClipping(rect); + } + + void StencilWrapper::popClipping() { + if (this->_stencil != nullptr) this->_stencil->popClipping(); + } + + void StencilWrapper::pushScale(const rawrbox::Vector2f& scale) { + if (this->_stencil != nullptr) this->_stencil->pushScale(scale); + } + + void StencilWrapper::popScale() { + if (this->_stencil != nullptr) this->_stencil->popScale(); + } + + void StencilWrapper::pushDisableCulling() { + if (this->_stencil != nullptr) this->_stencil->pushDisableCulling(); + } + + void StencilWrapper::popDisableCulling() { + if (this->_stencil != nullptr) this->_stencil->popDisableCulling(); + } + // ---- + + void StencilWrapper::registerLua(sol::state& lua) { + lua.new_usertype("Stencil", + sol::no_constructor, + + // Draw + "drawTriangle", &StencilWrapper::drawTriangle, + "drawBox", &StencilWrapper::drawBox, + "drawCircle", &StencilWrapper::drawCircle, + "drawLine", &StencilWrapper::drawLine, + + // Pop & push + "pushOffset", &StencilWrapper::pushOffset, + "popOffset", &StencilWrapper::popOffset, + "pushLocalOffset", &StencilWrapper::pushLocalOffset, + "popLocalOffset", &StencilWrapper::popLocalOffset, + "pushRotation", &StencilWrapper::pushRotation, + "popRotation", &StencilWrapper::popRotation, + "pushOutline", &StencilWrapper::pushOutline, + "popOutline", &StencilWrapper::popOutline, + "pushClipping", &StencilWrapper::pushClipping, + "popClipping", &StencilWrapper::popClipping, + "pushScale", &StencilWrapper::pushScale, + "popScale", &StencilWrapper::popScale, + "pushDisableCulling", &StencilWrapper::pushDisableCulling, + "popDisableCulling", &StencilWrapper::popDisableCulling); + } +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/text/font_wrapper.cpp b/render/src/scripting/wrappers/text/font_wrapper.cpp new file mode 100644 index 00000000..6968e1da --- /dev/null +++ b/render/src/scripting/wrappers/text/font_wrapper.cpp @@ -0,0 +1,51 @@ + +#include + +namespace rawrbox { + FontWrapper::FontWrapper(rawrbox::Font* instance) : _ref(instance) {} + rawrbox::Font* FontWrapper::getRef() const { return this->_ref; } + + // UTILS ----- + bool FontWrapper::isValid() const { return this->_ref != nullptr; } + + float FontWrapper::getSize() const { + if (!this->isValid()) return 0.F; + return this->_ref->getSize(); + } + + float FontWrapper::getScale() const { + if (!this->isValid()) return 0.F; + return this->_ref->getScale(); + } + + float FontWrapper::getLineHeight() const { + if (!this->isValid()) return 0.F; + return this->_ref->getLineHeight(); + } + + rawrbox::Vector2f FontWrapper::getStringSize(const std::string& text) const { + if (!this->isValid()) return {}; + return this->_ref->getStringSize(text); + } + + bool FontWrapper::hasGlyph(uint32_t codepoint) const { + if (!this->isValid()) return false; + return this->_ref->hasGlyph(codepoint); + } + // ------ + + void FontWrapper::registerLua(sol::state& lua) { + lua.new_usertype("Font", + sol::no_constructor, + + // UTILS ----- + "isValid", &FontWrapper::isValid, + "getSize", &FontWrapper::getSize, + "getScale", &FontWrapper::getScale, + "getLineHeight", &FontWrapper::getLineHeight, + "getStringSize", &FontWrapper::getStringSize, + "hasGlyph", &FontWrapper::hasGlyph + // ------ + ); + } +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/textures/base_wrapper.cpp b/render/src/scripting/wrappers/textures/base_wrapper.cpp new file mode 100644 index 00000000..9c20f5af --- /dev/null +++ b/render/src/scripting/wrappers/textures/base_wrapper.cpp @@ -0,0 +1,42 @@ + +#include + +namespace rawrbox { + TextureWrapper::TextureWrapper(rawrbox::TextureBase* texture) : _texture(texture) {} + rawrbox::TextureBase* TextureWrapper::getRef() const { return this->_texture; } + + // UTILS---- + bool TextureWrapper::hasTransparency() const { + if (this->_texture == nullptr) return false; + return this->_texture->hasTransparency(); + } + + const rawrbox::Vector2i TextureWrapper::getSize() const { + if (this->_texture == nullptr) return {}; + return this->_texture->getSize(); + } + + bool TextureWrapper::isValid() const { + if (this->_texture == nullptr) return false; + return this->_texture->isValid(); + } + + std::array TextureWrapper::getData() const { + if (this->_texture == nullptr) return {}; + return this->_texture->getData(); + } + // ----- + + void TextureWrapper::registerLua(sol::state& lua) { + lua.new_usertype("TextureBase", + sol::no_constructor, + + // UTILS---- + "hasTransparency", &TextureWrapper::hasTransparency, + "getSize", &TextureWrapper::getSize, + "isValid", &TextureWrapper::isValid, + "getData", &TextureWrapper::getData + // ----- + ); + } +} // namespace rawrbox diff --git a/render/src/scripting/wrappers/window_wrapper.cpp b/render/src/scripting/wrappers/window_wrapper.cpp new file mode 100644 index 00000000..7eedb141 --- /dev/null +++ b/render/src/scripting/wrappers/window_wrapper.cpp @@ -0,0 +1,66 @@ +#include + +namespace rawrbox { + WindowWrapper::WindowWrapper(rawrbox::Window* window) : _window(window) {} + + // Utils ---- + void WindowWrapper::setTitle(const std::string& title) { + if (this->_window != nullptr) this->_window->setTitle(title); + } + + void WindowWrapper::hideCursor(bool hidden) { + if (this->_window != nullptr) this->_window->hideCursor(hidden); + } + + void WindowWrapper::setCursor(uint32_t cursor) { + if (this->_window != nullptr) this->_window->setCursor(cursor); + } + + void WindowWrapper::close() { + if (this->_window != nullptr) this->_window->close(); + } + + rawrbox::Vector2i WindowWrapper::getSize() const { + if (this->_window != nullptr) return this->_window->getSize(); + return {}; + } + + float WindowWrapper::getAspectRatio() const { + if (this->_window != nullptr) return this->_window->getAspectRatio(); + return 0.F; + } + + rawrbox::Vector2i WindowWrapper::getMousePos() const { + if (this->_window != nullptr) return this->_window->getMousePos(); + return {}; + } + + bool WindowWrapper::isKeyDown(int key) const { + if (this->_window != nullptr) return this->_window->isKeyDown(key); + return false; + } + + bool WindowWrapper::isMouseDown(int key) const { + if (this->_window != nullptr) return this->_window->isMouseDown(key); + return false; + } + // ------- + + void WindowWrapper::registerLua(sol::state& lua) { + lua.new_usertype("Window", + sol::no_constructor, + + // UTILS --- + "setTitle", &WindowWrapper::setTitle, + "hideCursor", &WindowWrapper::hideCursor, + "setCursor", &WindowWrapper::setCursor, + "close", &WindowWrapper::close, + "getSize", &WindowWrapper::getSize, + "getAspectRatio", &WindowWrapper::getAspectRatio, + "getMousePos", &WindowWrapper::getMousePos, + "isKeyDown", &WindowWrapper::isKeyDown, + "isMouseDown", &WindowWrapper::isMouseDown + // --- + ); + } +} // namespace rawrbox diff --git a/render/src/stencil.cpp b/render/src/stencil.cpp index e80bf05c..3a01471a 100644 --- a/render/src/stencil.cpp +++ b/render/src/stencil.cpp @@ -74,7 +74,7 @@ namespace rawrbox { this->_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Sampler); - this->_pixelTexture = std::make_unique(rawrbox::Vector2i(1, 1), Colors::White); + this->_pixelTexture = std::make_unique(rawrbox::Vector2i(1, 1), Colors::White()); this->_pixelTexture->upload(); } @@ -145,7 +145,7 @@ namespace rawrbox { // -------------------- // ------UTILS - void Stencil::drawPolygon(rawrbox::Polygon poly) { + void Stencil::drawPolygon(const rawrbox::Polygon& poly) { // Setup -------- bgfx::TextureHandle handl = BGFX_INVALID_HANDLE; if (this->_pixelTexture != nullptr) handl = this->_pixelTexture->getHandle(); diff --git a/render/src/texture/base.cpp b/render/src/texture/base.cpp index 6eefe15c..07a66aaa 100644 --- a/render/src/texture/base.cpp +++ b/render/src/texture/base.cpp @@ -7,13 +7,13 @@ namespace rawrbox { // UTILS --- bool TextureBase::hasTransparency() const { return false; } const rawrbox::Vector2i& TextureBase::getSize() const { return this->_size; } - bool TextureBase::valid() const { return bgfx::isValid(this->_handle); } + bool TextureBase::isValid() const { return bgfx::isValid(this->_handle); } const bgfx::TextureHandle& TextureBase::getHandle() const { return this->_handle; } // ---- void TextureBase::setFlags(uint64_t flags) { this->_flags = flags; } void TextureBase::update() {} - std::array TextureBase::getData() { return {static_cast(this->_textureUV)}; } + std::array TextureBase::getData() const { return {static_cast(this->_textureUV)}; } } // namespace rawrbox diff --git a/render/src/window.cpp b/render/src/window.cpp index 4578428d..20d640c7 100644 --- a/render/src/window.cpp +++ b/render/src/window.cpp @@ -272,10 +272,10 @@ namespace rawrbox { rawrbox::MISSING_TEXTURE = std::make_shared(); if (rawrbox::WHITE_TEXTURE == nullptr) - rawrbox::WHITE_TEXTURE = std::make_shared(rawrbox::Vector2i(2, 2), rawrbox::Colors::White); + rawrbox::WHITE_TEXTURE = std::make_shared(rawrbox::Vector2i(2, 2), rawrbox::Colors::White()); if (rawrbox::BLACK_TEXTURE == nullptr) - rawrbox::BLACK_TEXTURE = std::make_shared(rawrbox::Vector2i(2, 2), rawrbox::Colors::Black); + rawrbox::BLACK_TEXTURE = std::make_shared(rawrbox::Vector2i(2, 2), rawrbox::Colors::Black()); if (rawrbox::NORMAL_TEXTURE == nullptr) rawrbox::NORMAL_TEXTURE = std::make_shared(rawrbox::Vector2i(2, 2), rawrbox::Color::RGBHex(0xbcbcff)); @@ -414,16 +414,6 @@ namespace rawrbox { return {static_cast(std::floor(x)), static_cast(std::floor(y))}; } - bool Window::getShouldClose() const { - if (this->_handle == nullptr) return false; - return glfwWindowShouldClose(GLFWHANDLE); - } - - void Window::setShouldClose(bool close) const { - if (this->_handle == nullptr) return; - glfwSetWindowShouldClose(GLFWHANDLE, close ? 1 : 0); - } - uint32_t Window::getWindowFlags() const { return this->_windowFlags; } rawrbox::Stencil& Window::getStencil() const { return *this->_stencil; } diff --git a/render/tests/light_base.spec.cpp b/render/tests/light_base.spec.cpp index 0c1dc8a0..073c5d0f 100644 --- a/render/tests/light_base.spec.cpp +++ b/render/tests/light_base.spec.cpp @@ -6,7 +6,7 @@ #include TEST_CASE("Lights should behave as expected", "[rawrbox::LightBase]") { - auto base = std::make_shared(rawrbox::Vector3f{5, -10, 0}, rawrbox::Colors::Red, 0.F); + auto base = std::make_shared(rawrbox::Vector3f{5, -10, 0}, rawrbox::Colors::Red(), 0.F); SECTION("rawrbox::LightBase::isOn") { REQUIRE(base->isOn() == true); diff --git a/render/tests/mesh.spec.cpp b/render/tests/mesh.spec.cpp index 67fc3b56..4c2708d6 100644 --- a/render/tests/mesh.spec.cpp +++ b/render/tests/mesh.spec.cpp @@ -30,9 +30,9 @@ TEST_CASE("Mesh should behave as expected", "[rawrbox::Mesh]") { } SECTION("rawrbox::Mesh::setColor") { - REQUIRE(base.color == rawrbox::Colors::White); - base.setColor(rawrbox::Colors::Orange); - REQUIRE(base.color == rawrbox::Colors::Orange); + REQUIRE(base.color == rawrbox::Colors::White()); + base.setColor(rawrbox::Colors::Orange()); + REQUIRE(base.color == rawrbox::Colors::Orange()); } SECTION("rawrbox::Mesh::getBBOX") { diff --git a/render/tests/stencil.spec.cpp b/render/tests/stencil.spec.cpp index 19dcc8b3..df711a60 100644 --- a/render/tests/stencil.spec.cpp +++ b/render/tests/stencil.spec.cpp @@ -14,7 +14,7 @@ TEST_CASE("Stencil should behave as expected", "[rawrbox::Stencil]") { base.clear(); REQUIRE(base.getDrawCalls().size() == 0); - base.drawTriangle({0, 0}, {0, 0}, rawrbox::Colors::Black, {0, 10}, {0, 1}, rawrbox::Colors::Black, {10, 0}, {1, 0}, rawrbox::Colors::Black); + base.drawTriangle({0, 0}, {0, 0}, rawrbox::Colors::Black(), {0, 10}, {0, 1}, rawrbox::Colors::Black(), {10, 0}, {1, 0}, rawrbox::Colors::Black()); REQUIRE(base.getDrawCalls().size() == 1); REQUIRE(base.getDrawCalls().front().vertices.size() == 3); } @@ -23,7 +23,7 @@ TEST_CASE("Stencil should behave as expected", "[rawrbox::Stencil]") { base.clear(); REQUIRE(base.getDrawCalls().size() == 0); - base.drawCircle({0, 0}, {10, 10}, rawrbox::Colors::Black); + base.drawCircle({0, 0}, {10, 10}, rawrbox::Colors::Black()); REQUIRE(base.getDrawCalls().size() == 1); REQUIRE(base.getDrawCalls().front().vertices.size() == 96); } @@ -32,7 +32,7 @@ TEST_CASE("Stencil should behave as expected", "[rawrbox::Stencil]") { base.clear(); REQUIRE(base.getDrawCalls().size() == 0); - base.drawLine({0, 0}, {10, 10}, rawrbox::Colors::Black); + base.drawLine({0, 0}, {10, 10}, rawrbox::Colors::Black()); REQUIRE(base.getDrawCalls().size() == 1); REQUIRE(base.getDrawCalls().front().vertices.size() == 2); } @@ -43,7 +43,7 @@ TEST_CASE("Stencil should behave as expected", "[rawrbox::Stencil]") { REQUIRE(base.getDrawCalls().size() == 0); base.pushOutline({1.F}); // Draw box uses texture, so we need to draw outline instead, since bgfx is not active - base.drawBox({0, 0}, {10, 10}, rawrbox::Colors::Black); + base.drawBox({0, 0}, {10, 10}, rawrbox::Colors::Black()); base.popOutline(); REQUIRE(base.getDrawCalls().size() == 1); diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 697ce21b..17f5244e 100644 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -1,38 +1,23 @@ # Project setup -project( - "RAWRBOX.RESOURCES" - VERSION ${RAWRBOX_VERSION} - DESCRIPTION "RawrBox - Resources manager lib" - LANGUAGES CXX) +project("RAWRBOX.RESOURCES" VERSION ${RAWRBOX_VERSION} DESCRIPTION "RawrBox - Resources manager lib" LANGUAGES CXX) set(output_target RAWRBOX.RESOURCES) -# LIBS --- -CPMAddPackage( - NAME - nlohmann_json - VERSION - 3.11.2 - # the git repo is incredibly large, so we download the archived include directory - URL - https://github.com/nlohmann/json/releases/download/v3.11.2/include.zip - URL_HASH - SHA256=e5c7a9f49a16814be27e4ed0ee900ecd0092bfb7dbfca65b5a421b774dccaaed) - -if(nlohmann_json_ADDED) - add_library(nlohmann_json INTERFACE IMPORTED) - target_include_directories(nlohmann_json INTERFACE ${nlohmann_json_SOURCE_DIR}/include) -endif() -# ---- - # LIB ---- file(GLOB_RECURSE RAWRBOX_RESOURCES_IMPORTS "src/*.cpp" "include/*.hpp") +if(RAWRBOX_BUILD_RAWRBOX_SCRIPTING) + list(APPEND RAWRBOX_EXTRA_LIBS RAWRBOX.SCRIPTING) +else() + remove_folder("${RAWRBOX_RESOURCES_IMPORTS}" "/scripting/") + set(RAWRBOX_RESOURCES_IMPORTS "${CLEAN_SOURCES}") +endif() + add_library(${output_target} ${RAWRBOX_LIBRARY_TYPE} ${RAWRBOX_RESOURCES_IMPORTS}) target_include_directories(${output_target} PUBLIC "include") target_compile_features(${output_target} PUBLIC cxx_std_${CMAKE_CXX_STANDARD}) target_compile_definitions(${output_target} PRIVATE _CRT_SECURE_NO_WARNINGS NOMINMAX) target_compile_definitions(${output_target} PUBLIC RAWRBOX_RESOURCES) -target_link_libraries(${output_target} PUBLIC RAWRBOX.UTILS fmt::fmt nlohmann_json) +target_link_libraries(${output_target} PUBLIC RAWRBOX.UTILS nlohmann_json ${RAWRBOX_EXTRA_LIBS}) set_lib_runtime_mt(${output_target}) # -------------- diff --git a/resources/include/rawrbox/resources/manager.hpp b/resources/include/rawrbox/resources/manager.hpp index a2d13b37..4774ca73 100644 --- a/resources/include/rawrbox/resources/manager.hpp +++ b/resources/include/rawrbox/resources/manager.hpp @@ -15,6 +15,7 @@ namespace rawrbox { class RESOURCES { protected: + static std::vector _loadedFiles; static std::vector> _loaders; // LOADS --- @@ -63,6 +64,10 @@ namespace rawrbox { ret->upload(); ret->status = rawrbox::LoadStatus::LOADED; + // Add to the list for later on easy access + _loadedFiles.push_back(filePath); + // --- + return ret; } @@ -140,6 +145,18 @@ namespace rawrbox { } } + static void startPreLoadQueueAsync(std::function startLoad = nullptr, std::function endLoad = nullptr) { + for (auto& loader : _loaders) { + for (auto& file : loader->getPreload()) { + rawrbox::ASYNC::run([startLoad, &file, endLoad]() { + if (startLoad != nullptr) startLoad(file.first.generic_string(), file.second); + loadFile(file.first, file.second); + if (endLoad != nullptr) endLoad(file.first.generic_string(), file.second); + }); + } + } + } + static void startPreLoadQueue(std::function startLoad = nullptr, std::function endLoad = nullptr) { for (auto& loader : _loaders) { for (auto& file : loader->getPreload()) { @@ -150,6 +167,23 @@ namespace rawrbox { } } + static size_t getTotalPreload() { + size_t total = 0; + for (auto& loader : _loaders) { + total += loader->getPreload().size(); + } + + return total; + } + + static size_t filesLoaded() { + return _loadedFiles.size(); + } + + static bool isLoaded(const std::filesystem::path& filePath) { + return std::find(_loadedFiles.begin(), _loadedFiles.end(), filePath) != _loadedFiles.end(); + } + // ----- static void shutdown() { _loaders.clear(); diff --git a/resources/include/rawrbox/resources/scripting/plugin.hpp b/resources/include/rawrbox/resources/scripting/plugin.hpp new file mode 100644 index 00000000..7d6ee931 --- /dev/null +++ b/resources/include/rawrbox/resources/scripting/plugin.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace rawrbox { + class ResourcesPlugin : public rawrbox::Plugin { + public: + void registerTypes(sol::state& lua) override { + rawrbox::ResourcesWrapper::registerLua(lua); + } + + void registerGlobal(rawrbox::Mod* mod) override { + if (mod == nullptr) throw std::runtime_error("[RawrBox-ResourcesPlugin] Tried to register plugin on invalid mod!"); + + auto& env = mod->getEnvironment(); + env["resources"] = rawrbox::ResourcesWrapper(mod); + } + }; +} // namespace rawrbox diff --git a/resources/include/rawrbox/resources/scripting/resources_wrapper.hpp b/resources/include/rawrbox/resources/scripting/resources_wrapper.hpp new file mode 100644 index 00000000..c1fb2b78 --- /dev/null +++ b/resources/include/rawrbox/resources/scripting/resources_wrapper.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include + +namespace rawrbox { + class ResourcesWrapper { + rawrbox::Mod* _mod; + + public: + ResourcesWrapper(rawrbox::Mod* mod_); + + void preLoadFolder(const std::string& path); + void preLoad(const std::string& path, sol::optional loadFlags); + std::string getContent(sol::optional path); + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/resources/src/manager.cpp b/resources/src/manager.cpp index 5bce323a..dd8b7024 100644 --- a/resources/src/manager.cpp +++ b/resources/src/manager.cpp @@ -2,6 +2,7 @@ #include namespace rawrbox { + std::vector rawrbox::RESOURCES::_loadedFiles = {}; std::vector> rawrbox::RESOURCES::_loaders = [] { std::vector> defaults; defaults.push_back(std::make_unique()); diff --git a/resources/src/scripting/resources_wrapper.cpp b/resources/src/scripting/resources_wrapper.cpp new file mode 100644 index 00000000..2e8e24a0 --- /dev/null +++ b/resources/src/scripting/resources_wrapper.cpp @@ -0,0 +1,37 @@ + +#include +#include +#include + +namespace rawrbox { + + ResourcesWrapper::ResourcesWrapper(rawrbox::Mod* mod) : _mod(mod) {} + + void ResourcesWrapper::preLoadFolder(const std::string& path) { + if (this->_mod == nullptr) throw std::runtime_error("[RawrBox-Resources] MOD not set!"); + + auto fixedPath = rawrbox::LuaUtils::getContent(path, this->_mod->getFolder().generic_string()); + rawrbox::RESOURCES::preLoadFolder(fixedPath); + } + + void ResourcesWrapper::preLoad(const std::string& path, sol::optional loadFlags) { + if (this->_mod == nullptr) throw std::runtime_error("[RawrBox-Resources] MOD not set!"); + + auto fixedPath = rawrbox::LuaUtils::getContent(path, this->_mod->getFolder().generic_string()); + rawrbox::RESOURCES::preLoadFile(fixedPath, loadFlags.value_or(0)); + } + + std::string ResourcesWrapper::getContent(sol::optional path) { + return rawrbox::LuaUtils::getContent(path.value_or(""), this->_mod->getFolder().generic_string()); + } + + void ResourcesWrapper::registerLua(sol::state& lua) { + lua.new_usertype("resources", + sol::no_constructor, + "preLoad", &ResourcesWrapper::preLoad, + "preLoadFolder", &ResourcesWrapper::preLoadFolder, + + "getContent", &ResourcesWrapper::getContent); + } + +} // namespace rawrbox diff --git a/samples/001-stencil/src/game.cpp b/samples/001-stencil/src/game.cpp index 947f1759..b13d108f 100644 --- a/samples/001-stencil/src/game.cpp +++ b/samples/001-stencil/src/game.cpp @@ -128,11 +128,11 @@ namespace stencil { // Box + clipping -- stencil.pushRotation({this->_counter * 50.5F, {50, 50}}); stencil.pushClipping({-20, -20, 50, 140}); - stencil.drawBox({0, 0}, {100, 100}, rawrbox::Colors::Green); + stencil.drawBox({0, 0}, {100, 100}, rawrbox::Colors::Green()); stencil.popClipping(); stencil.pushClipping({50, -20, 50, 140}); - stencil.drawBox({0, 0}, {100, 100}, rawrbox::Colors::Red); + stencil.drawBox({0, 0}, {100, 100}, rawrbox::Colors::Red()); stencil.popClipping(); stencil.popRotation(); // -- @@ -140,7 +140,7 @@ namespace stencil { // Inverted box --- stencil.pushOffset({100, 0}); stencil.pushScale({1.F, -1.F}); - stencil.drawBox({0, 0}, {100, 100}, rawrbox::Colors::Red); + stencil.drawBox({0, 0}, {100, 100}, rawrbox::Colors::Red()); stencil.popScale(); stencil.popOffset(); // --- @@ -148,63 +148,63 @@ namespace stencil { // Outline box --- stencil.pushOffset({200, 0}); stencil.pushOutline({1.F, 2.F}); - stencil.drawBox({0, 0}, {100, 100}, rawrbox::Colors::Purple); + stencil.drawBox({0, 0}, {100, 100}, rawrbox::Colors::Purple()); stencil.popOutline(); stencil.pushOutline({2.F}); - stencil.drawBox({25, 25}, {50, 50}, rawrbox::Colors::Purple); + stencil.drawBox({25, 25}, {50, 50}, rawrbox::Colors::Purple()); stencil.popOutline(); stencil.popOffset(); // --- // Triangle --- stencil.pushOffset({300, 0}); - stencil.drawTriangle({0, 0}, {0, 0}, rawrbox::Colors::Blue, {0, 100}, {0, 1}, rawrbox::Colors::Blue, {100, 0}, {0, 1}, rawrbox::Colors::Blue); + stencil.drawTriangle({0, 0}, {0, 0}, rawrbox::Colors::Blue(), {0, 100}, {0, 1}, rawrbox::Colors::Blue(), {100, 0}, {0, 1}, rawrbox::Colors::Blue()); stencil.popOffset(); // --- // Outline triangle --- stencil.pushOffset({400, 0}); stencil.pushOutline({2.F}); - stencil.drawTriangle({15, 15}, {0, 0}, rawrbox::Colors::Blue, {15, 65}, {0, 1}, rawrbox::Colors::Blue, {65, 15}, {0, 1}, rawrbox::Colors::Blue); + stencil.drawTriangle({15, 15}, {0, 0}, rawrbox::Colors::Blue(), {15, 65}, {0, 1}, rawrbox::Colors::Blue(), {65, 15}, {0, 1}, rawrbox::Colors::Blue()); stencil.popOutline(); stencil.pushOutline({1.F, 1.F}); - stencil.drawTriangle({0, 0}, {0, 0}, rawrbox::Colors::Blue, {0, 100}, {0, 1}, rawrbox::Colors::Blue, {100, 0}, {0, 1}, rawrbox::Colors::Blue); + stencil.drawTriangle({0, 0}, {0, 0}, rawrbox::Colors::Blue(), {0, 100}, {0, 1}, rawrbox::Colors::Blue(), {100, 0}, {0, 1}, rawrbox::Colors::Blue()); stencil.popOutline(); stencil.popOffset(); // --- // Circle --- stencil.pushOffset({500, 0}); - stencil.drawCircle({0, 0}, {100, 100}, rawrbox::Colors::Orange, 16, 0, std::fmod(this->_counter * 50.5F, 360.F)); + stencil.drawCircle({0, 0}, {100, 100}, rawrbox::Colors::Orange(), 16, 0, std::fmod(this->_counter * 50.5F, 360.F)); stencil.popOffset(); // --- // Outline circle --- stencil.pushOffset({600, 0}); stencil.pushOutline({1.F, 0.25F}); - stencil.drawCircle({0, 0}, {100, 100}, rawrbox::Colors::Red, 16, 0.F, std::fmod(this->_counter * 50.5F, 360.F)); + stencil.drawCircle({0, 0}, {100, 100}, rawrbox::Colors::Red(), 16, 0.F, std::fmod(this->_counter * 50.5F, 360.F)); stencil.popOutline(); stencil.pushOutline({2.F}); - stencil.drawCircle({25, 25}, {50, 50}, rawrbox::Colors::Red, 32, 0.F, std::fmod(this->_counter * 50.5F, 360.F)); + stencil.drawCircle({25, 25}, {50, 50}, rawrbox::Colors::Red(), 32, 0.F, std::fmod(this->_counter * 50.5F, 360.F)); stencil.popOutline(); stencil.popOffset(); // --- // Line --- stencil.pushOffset({700, 0}); - stencil.drawLine({0, 0}, {100, 100}, rawrbox::Colors::Red); + stencil.drawLine({0, 0}, {100, 100}, rawrbox::Colors::Red()); // --- // Outline line --- stencil.pushOutline({1.F, 2.F}); - stencil.drawLine({100, 0}, {0, 100}, rawrbox::Colors::Blue); + stencil.drawLine({100, 0}, {0, 100}, rawrbox::Colors::Blue()); stencil.popOutline(); stencil.pushOutline({3.F, 2.F}); - stencil.drawLine({50, 0}, {50, 100}, rawrbox::Colors::Purple); + stencil.drawLine({50, 0}, {50, 100}, rawrbox::Colors::Purple()); stencil.popOutline(); stencil.popOffset(); // --- @@ -222,10 +222,10 @@ namespace stencil { // POLYGON --- rawrbox::Polygon poly; poly.verts = { - {{0, 0}, {0, 0}, rawrbox::Colors::White}, - {{0, 100}, {1, 0}, rawrbox::Colors::White}, - {{100, 0}, {0, 1}, rawrbox::Colors::White}, - {{80, 80}, {1, 1}, rawrbox::Colors::White}}; + {{0, 0}, {0, 0}, rawrbox::Colors::White()}, + {{0, 100}, {1, 0}, rawrbox::Colors::White()}, + {{100, 0}, {0, 1}, rawrbox::Colors::White()}, + {{80, 80}, {1, 1}, rawrbox::Colors::White()}}; poly.indices = {0, 1, 2, 1, 3, 2}; @@ -243,8 +243,8 @@ namespace stencil { // Z-INDEX TEST --- stencil.pushOffset({270, 260}); - stencil.drawBox({0, 0}, {100, 100}, rawrbox::Colors::Purple); - stencil.drawBox({25, 25}, {50, 50}, rawrbox::Colors::Red); + stencil.drawBox({0, 0}, {100, 100}, rawrbox::Colors::Purple()); + stencil.drawBox({25, 25}, {50, 50}, rawrbox::Colors::Red()); stencil.popOffset(); // ----- diff --git a/samples/002-generated-models/src/game.cpp b/samples/002-generated-models/src/game.cpp index f4ae5570..79f30d45 100644 --- a/samples/002-generated-models/src/game.cpp +++ b/samples/002-generated-models/src/game.cpp @@ -89,13 +89,13 @@ namespace model { rawrbox::Vector3f pos = {3.25F, -0.25F, 0}; rawrbox::Vector3f size = {0.5F, 0.5F, 0.F}; - auto mesh = rawrbox::MeshUtils::generateTriangle(pos, rawrbox::Vector3f{0, 0, 0}, {0, 0}, rawrbox::Colors::Red, rawrbox::Vector3f{size.x, size.y, 0}, {1, 0}, rawrbox::Colors::Green, rawrbox::Vector3f{0, size.y, 0}, {0, 1}, rawrbox::Colors::Blue); + auto mesh = rawrbox::MeshUtils::generateTriangle(pos, rawrbox::Vector3f{0, 0, 0}, {0, 0}, rawrbox::Colors::Red(), rawrbox::Vector3f{size.x, size.y, 0}, {1, 0}, rawrbox::Colors::Green(), rawrbox::Vector3f{0, size.y, 0}, {0, 1}, rawrbox::Colors::Blue()); this->_bboxes->addMesh(rawrbox::MeshUtils::generateBBOX(pos + size / 2, mesh.getBBOX())); this->_model->addMesh(mesh); } { - auto mesh = rawrbox::MeshUtils::generateCube({-2, 0, 0}, {0.5F, 0.5F, 0.5F}, rawrbox::Colors::White); + auto mesh = rawrbox::MeshUtils::generateCube({-2, 0, 0}, {0.5F, 0.5F, 0.5F}, rawrbox::Colors::White()); mesh.setTexture(texture); this->_bboxes->addMesh(rawrbox::MeshUtils::generateBBOX({-2, 0, 0}, mesh.getBBOX())); @@ -103,12 +103,12 @@ namespace model { } { - this->_model->addMesh(rawrbox::MeshUtils::generateCube({3.5F, 0, 2.5F}, {1.0F, 1.0F, 1.0F}, rawrbox::Colors::White)); - this->_model->addMesh(rawrbox::MeshUtils::generateCube({1.5F, 0, 2.5F}, {.5F, .5F, .5F}, rawrbox::Colors::White)); + this->_model->addMesh(rawrbox::MeshUtils::generateCube({3.5F, 0, 2.5F}, {1.0F, 1.0F, 1.0F}, rawrbox::Colors::White())); + this->_model->addMesh(rawrbox::MeshUtils::generateCube({1.5F, 0, 2.5F}, {.5F, .5F, .5F}, rawrbox::Colors::White())); } { - auto mesh = rawrbox::MeshUtils::generateCube({-3, 0, 0}, {0.5F, 0.5F, 0.5F}, rawrbox::Colors::White); + auto mesh = rawrbox::MeshUtils::generateCube({-3, 0, 0}, {0.5F, 0.5F, 0.5F}, rawrbox::Colors::White()); mesh.setTexture(texture); mesh.setVertexSnap(24.F); @@ -174,7 +174,7 @@ namespace model { // Displacement test ---- { - auto mesh = rawrbox::MeshUtils::generateMesh({0, 0, 0}, 64, rawrbox::Colors::White); + auto mesh = rawrbox::MeshUtils::generateMesh({0, 0, 0}, 64, rawrbox::Colors::White()); mesh.setTexture(texture3); mesh.setDisplacementTexture(texture3, 24.F); @@ -182,7 +182,7 @@ namespace model { } { - auto mesh = rawrbox::MeshUtils::generateMesh({0, 0.5F, 0}, 64, rawrbox::Colors::Black); + auto mesh = rawrbox::MeshUtils::generateMesh({0, 0.5F, 0}, 64, rawrbox::Colors::Black()); mesh.setDisplacementTexture(texture3, 24.F); mesh.lineMode = true; diff --git a/samples/004-light-support/src/game.cpp b/samples/004-light-support/src/game.cpp index 002cd6ac..8bb4c0ce 100644 --- a/samples/004-light-support/src/game.cpp +++ b/samples/004-light-support/src/game.cpp @@ -86,7 +86,7 @@ namespace light { // Setup { - auto mesh = rawrbox::MeshUtils::generatePlane({2.5F, 0.F, 0}, {3.F, 3.F}, rawrbox::Colors::White); + auto mesh = rawrbox::MeshUtils::generatePlane({2.5F, 0.F, 0}, {3.F, 3.F}, rawrbox::Colors::White()); mesh.setTexture(tex); mesh.setSpecularTexture(texSpec, 25.F); mesh.setEulerAngle({bx::toRad(90), 0, 0}); @@ -94,7 +94,7 @@ namespace light { } { - auto mesh = rawrbox::MeshUtils::generatePlane({-2.5F, 0.F, 0}, {3.F, 3.F}, rawrbox::Colors::White); + auto mesh = rawrbox::MeshUtils::generatePlane({-2.5F, 0.F, 0}, {3.F, 3.F}, rawrbox::Colors::White()); mesh.setTexture(tex); mesh.setSpecularTexture(texSpec, 25.F); mesh.setEulerAngle({bx::toRad(90), 0, 0}); @@ -112,8 +112,8 @@ namespace light { this->_text->addText(*this->_font, "SPOT LIGHT", {-2.5F, 0.5F, 0}); // ------ - rawrbox::LIGHTS::addLight(rawrbox::Vector3f{2.5F, 0.F, 0}, rawrbox::Colors::Blue, 6.2F); - rawrbox::LIGHTS::addLight(rawrbox::Vector3f{-2.5F, 0.F, 0}, rawrbox::Vector3f{0.F, -1.F, 0.F}, rawrbox::Colors::Red, 0.602F, 0.708F, 100.F); + rawrbox::LIGHTS::addLight(rawrbox::Vector3f{2.5F, 0.F, 0}, rawrbox::Colors::Blue(), 6.2F); + rawrbox::LIGHTS::addLight(rawrbox::Vector3f{-2.5F, 0.F, 0}, rawrbox::Vector3f{0.F, -1.F, 0.F}, rawrbox::Colors::Red(), 0.602F, 0.708F, 100.F); this->_model->upload(); this->_text->upload(); diff --git a/samples/005-post-process/src/game.cpp b/samples/005-post-process/src/game.cpp index 16f3a1e4..0fae2f6c 100644 --- a/samples/005-post-process/src/game.cpp +++ b/samples/005-post-process/src/game.cpp @@ -74,7 +74,7 @@ namespace post_process { // Setup { - auto mesh = rawrbox::MeshUtils::generateCube({0.F, 0.F, 0}, {3.F, 3.F, 3.F}, rawrbox::Colors::White); + auto mesh = rawrbox::MeshUtils::generateCube({0.F, 0.F, 0}, {3.F, 3.F, 3.F}, rawrbox::Colors::White()); mesh.setTexture(tex); this->_model->addMesh(mesh); } diff --git a/samples/008-ui/src/game.cpp b/samples/008-ui/src/game.cpp index 0e63222b..66094ffb 100644 --- a/samples/008-ui/src/game.cpp +++ b/samples/008-ui/src/game.cpp @@ -95,7 +95,7 @@ namespace ui_test { label->setPos({10, 18}); label->setFont("cour.ttf", 14); label->setText("Label: shadow mew!"); - label->setShadowColor(rawrbox::Colors::Black); + label->setShadowColor(rawrbox::Colors::Black()); label->sizeToContents(); } @@ -157,7 +157,7 @@ namespace ui_test { prog->setPos({10, 130}); prog->setSize({200, 16}); prog->setValue(50); - prog->setBarColor(rawrbox::Colors::Orange); + prog->setBarColor(rawrbox::Colors::Orange()); } { @@ -191,8 +191,8 @@ namespace ui_test { this->_graph = frame->createChild(); this->_graph->setPos({10, 10}); this->_graph->setSize({380, 160}); - this->_graph->addCategory("Cats /s", rawrbox::Colors::Orange); - this->_graph->addCategory("Meows /s", rawrbox::Colors::Purple); + this->_graph->addCategory("Cats /s", rawrbox::Colors::Orange()); + this->_graph->addCategory("Meows /s", rawrbox::Colors::Purple()); this->_graph->setAutoScale(true); this->_graph->setSmoothing(20); } diff --git a/samples/009-physics/CMakeLists.txt b/samples/009-physics-3d/CMakeLists.txt similarity index 92% rename from samples/009-physics/CMakeLists.txt rename to samples/009-physics-3d/CMakeLists.txt index a4b93001..8a7c852f 100644 --- a/samples/009-physics/CMakeLists.txt +++ b/samples/009-physics-3d/CMakeLists.txt @@ -1,10 +1,10 @@ -project("009-physics") +project("009-physics-3d") # Grab source files file(GLOB_RECURSE RAWRBOX_SAMPLE_SOURCES "include/*.hpp" "src/*.cpp") # Project setup -set(output_target 009-physics) +set(output_target 009-physics-3d) set(EXECUTABLE_OUTPUT_PATH ${CMAKE_HOME_DIRECTORY}/${RAWRBOX_OUTPUT_BIN}/${CMAKE_BUILD_TYPE}) add_executable(${output_target} ${RAWRBOX_SAMPLE_SOURCES}) diff --git a/samples/009-physics/icon.ico b/samples/009-physics-3d/icon.ico similarity index 100% rename from samples/009-physics/icon.ico rename to samples/009-physics-3d/icon.ico diff --git a/samples/009-physics/include/physics_test/game.hpp b/samples/009-physics-3d/include/physics_test/game.hpp similarity index 100% rename from samples/009-physics/include/physics_test/game.hpp rename to samples/009-physics-3d/include/physics_test/game.hpp diff --git a/samples/009-physics/src/game.cpp b/samples/009-physics-3d/src/game.cpp similarity index 97% rename from samples/009-physics/src/game.cpp rename to samples/009-physics-3d/src/game.cpp index 571f8aa3..8dbe2afb 100644 --- a/samples/009-physics/src/game.cpp +++ b/samples/009-physics-3d/src/game.cpp @@ -118,7 +118,7 @@ namespace physics_test { rawrbox::PHYSICS::optimize(); // Only need to be called after adding a lot of bodies in one go }); - this->_timer->setPaused(this->_paused); + this->_timer->pause(this->_paused); // -------- // BINDS ---- @@ -127,7 +127,7 @@ namespace physics_test { if (!isDown || button != MOUSE_BUTTON_1) return; this->_paused = !this->_paused; - if (this->_timer != nullptr) this->_timer->setPaused(this->_paused); + if (this->_timer != nullptr) this->_timer->pause(this->_paused); }; // ----- @@ -229,7 +229,7 @@ namespace physics_test { b->mdl->setPos(pos); b->mdl->setAngle(ang); - b->mdl->setColor(body->IsActive() ? rawrbox::Colors::White : rawrbox::Colors::DarkGray); + b->mdl->setColor(body->IsActive() ? rawrbox::Colors::White() : rawrbox::Colors::DarkGray()); b->mdl->draw(); } diff --git a/samples/009-physics/src/main.cpp b/samples/009-physics-3d/src/main.cpp similarity index 100% rename from samples/009-physics/src/main.cpp rename to samples/009-physics-3d/src/main.cpp diff --git a/samples/010-instancing/src/game.cpp b/samples/010-instancing/src/game.cpp index 78ef2a8a..a4f5dae6 100644 --- a/samples/010-instancing/src/game.cpp +++ b/samples/010-instancing/src/game.cpp @@ -80,7 +80,7 @@ namespace instance_test { for (int x = 0; x < total; x++) { rawrbox::Matrix4x4 m; m.mtxSRT({1.F, 1.F, 1.F}, rawrbox::Vector4f::toQuat({0, distRot(prng), 0}), {x * spacing, 0, z * spacing}); - this->_model->addInstance({m, rawrbox::Colors::White, {static_cast(dist(prng)), 0, 0, 0}}); + this->_model->addInstance({m, rawrbox::Colors::White(), {static_cast(dist(prng)), 0, 0, 0}}); } } diff --git a/samples/011-decals/src/game.cpp b/samples/011-decals/src/game.cpp index d2588b5d..31084976 100644 --- a/samples/011-decals/src/game.cpp +++ b/samples/011-decals/src/game.cpp @@ -79,23 +79,23 @@ namespace decal_test { std::uniform_real_distribution distRot(-1.5F, 1.5F); for (int i = 0; i < 30; i++) { - rawrbox::DECALS::add({distRot(prng), 0.F, distRot(prng) - 1.55F}, {1, 1, 1}, 90, rawrbox::Colors::Green, dist(prng)); - rawrbox::DECALS::add({distRot(prng), distRot(prng) + 1.25F, 0.F}, {1, 1, 1}, 0, rawrbox::Colors::Red, dist(prng)); + rawrbox::DECALS::add({distRot(prng), 0.F, distRot(prng) - 1.55F}, {1, 1, 1}, 90, rawrbox::Colors::Green(), dist(prng)); + rawrbox::DECALS::add({distRot(prng), distRot(prng) + 1.25F, 0.F}, {1, 1, 1}, 0, rawrbox::Colors::Red(), dist(prng)); } - rawrbox::LIGHTS::addLight(rawrbox::Vector3f{0, 1.F, -1.F}, rawrbox::Colors::Orange * 0.5F, 5.F); + rawrbox::LIGHTS::addLight(rawrbox::Vector3f{0, 1.F, -1.F}, rawrbox::Colors::Orange() * 0.5F, 5.F); // Setup this->_model->setOptimizable(false); { - auto mesh = rawrbox::MeshUtils::generateCube({0, 1.0F, 0}, {3.F, 2.F, 0.1F}, rawrbox::Colors::Gray); + auto mesh = rawrbox::MeshUtils::generateCube({0, 1.0F, 0}, {3.F, 2.F, 0.1F}, rawrbox::Colors::Gray()); mesh.setRecieveDecals(true); this->_model->addMesh(mesh); } { - auto mesh = rawrbox::MeshUtils::generateCube({0, 0.0F, -1.F}, {3.F, 2.F, 0.1F}, rawrbox::Colors::Gray); + auto mesh = rawrbox::MeshUtils::generateCube({0, 0.0F, -1.F}, {3.F, 2.F, 0.1F}, rawrbox::Colors::Gray()); mesh.setRecieveDecals(true); mesh.setEulerAngle({bx::toRad(90), 0, 0}); diff --git a/samples/013-physics-2d/src/game.cpp b/samples/013-physics-2d/src/game.cpp index 456bb5b6..717ccd8f 100644 --- a/samples/013-physics-2d/src/game.cpp +++ b/samples/013-physics-2d/src/game.cpp @@ -85,7 +85,7 @@ namespace phys_2d_test { // TIMER --- this->_timer = rawrbox::Timer::create( 600, 25, [this]() { this->createBox({0, 5, 0}, {0.5F, 0.5F}); }); - this->_timer->setPaused(this->_paused); + this->_timer->pause(this->_paused); // -------- // BINDS ---- @@ -94,7 +94,7 @@ namespace phys_2d_test { if (!isDown || button != MOUSE_BUTTON_1) return; this->_paused = !this->_paused; - if (this->_timer != nullptr) this->_timer->setPaused(this->_paused); + if (this->_timer != nullptr) this->_timer->pause(this->_paused); }; // ----- @@ -183,7 +183,7 @@ namespace phys_2d_test { b->mdl->setPos(pos); b->mdl->setEulerAngle({0, 0, body->GetAngle()}); - b->mdl->setColor(body->IsSleeping() ? rawrbox::Colors::DarkGray : rawrbox::Colors::White); + b->mdl->setColor(body->IsSleeping() ? rawrbox::Colors::DarkGray() : rawrbox::Colors::White()); b->mdl->draw(); } diff --git a/samples/014-scripting/include/scripting_test/game.hpp b/samples/014-scripting/include/scripting_test/game.hpp index 7a9dc2c5..c47331cf 100644 --- a/samples/014-scripting/include/scripting_test/game.hpp +++ b/samples/014-scripting/include/scripting_test/game.hpp @@ -3,15 +3,13 @@ #include #include #include -#include #include namespace scripting_test { class Game : public rawrbox::Engine { std::unique_ptr _window = nullptr; - std::unique_ptr> _model = std::make_unique>(); - std::unique_ptr _script; + std::shared_ptr> _model = std::make_shared>(); std::atomic _loadingFiles = 0; bool _ready = false; @@ -32,6 +30,7 @@ namespace scripting_test { ~Game() override = default; void drawWorld(); + void drawOverlay(); void printFrames(); void loadContent(); diff --git a/samples/014-scripting/mods/test-mod-2/init.lua b/samples/014-scripting/mods/test-mod-2/init.lua new file mode 100644 index 00000000..1d3e14f1 --- /dev/null +++ b/samples/014-scripting/mods/test-mod-2/init.lua @@ -0,0 +1,29 @@ +function TEST() + print("You called test! On test-mod-2") + + --[[http:request("https://ams3.digitaloceanspaces.com/failcake/public/badapple/caw.txt", HTTP.GET, {}, + function(err, data) + if err then + print("ERROR: ", data) + return + end + end)]] +end + +function MOD:drawOverlay() + stencil:drawBox(Vector2:new(0, 0), Vector2:new(10, 10), Color:new(255, 0, 0, 255)) +end + +function MOD:update() + local mdl = test_model() + if mdl:isValid() then + local mesh1 = mdl:getMesh(0) + if not mesh1 then return end + + local p = mesh1:getPos() + p.x = math.cos(BGFX_FRAME() * 0.01) * 2. + p.z = math.sin(BGFX_FRAME() * 0.01) * 2. + + mesh1:setPos(p) + end +end diff --git a/samples/014-scripting/mods/test-mod/init.lua b/samples/014-scripting/mods/test-mod/init.lua index e25705b8..5b97eeb0 100644 --- a/samples/014-scripting/mods/test-mod/init.lua +++ b/samples/014-scripting/mods/test-mod/init.lua @@ -1,25 +1,15 @@ +include("./src/test.lua") + function MOD:init() if type(jit) == 'table' then print(jit.version) end - print("\nTEST Mod initialized!\n") - local v2 = Vector2:new(23, 43) - print(string.fmt("test vector2 | x: '{}' y: '{}'", v2.x, v2.y)) - - local v3 = Vector3:new(23, 43, 53) - print(string.fmt("test vector3 | x: '{}' y: '{}' z: '{}'", v3.x, v3.y, v3.z)) - - local v4 = Vector4:new(23, 43, 53, 12) - print(string.fmt("test vector4 | x: '{}' y: '{}' z: '{}' w: '{}'", v4.x, v4.y, v4.z, v4.w)) - - local c = Color:new(255, 0, 0, 255) - print(string.fmt("test color | r: '{}' g: '{}' b: '{}' a: '{}'", c.r, c.g, c.b, c.a)) + testRawrbox() - local m = Matrix:new() - print("test matrix") - for i = 0, 15 do - print(string.fmt("[{}] = {}", i, m[i])) - end + -- ACCESS ENV ON MOD 2 + local mod2 = scripting:getMod("test-mod-2") + if not mod2 then return end + mod2:getENV().TEST() end print(test:hello("hot reload")) diff --git a/samples/014-scripting/mods/test-mod/src/test.lua b/samples/014-scripting/mods/test-mod/src/test.lua new file mode 100644 index 00000000..b01be777 --- /dev/null +++ b/samples/014-scripting/mods/test-mod/src/test.lua @@ -0,0 +1,20 @@ +function testRawrbox() + local v2 = Vector2:new(23, 43) + print(string.fmt("test vector2 | x: '{}' y: '{}'", v2.x, v2.y)) + + local v3 = Vector3:new(23, 43, 53) + print(string.fmt("test vector3 | x: '{}' y: '{}' z: '{}'", v3.x, v3.y, v3.z)) + + local v4 = Vector4:new(23, 43, 53, 12) + print(string.fmt("test vector4 | x: '{}' y: '{}' z: '{}' w: '{}'", v4.x, v4.y, v4.z, v4.w)) + + local c = Color:new(255, 0, 0, 255) + print(string.fmt("test color | r: '{}' g: '{}' b: '{}' a: '{}'", c.r, c.g, c.b, c.a)) + + local m = Matrix:new() + print("test matrix") + + for i = 0, 15 do + print(string.fmt("[{}] = {}", i, m[i])) + end +end diff --git a/samples/014-scripting/src/game.cpp b/samples/014-scripting/src/game.cpp index dad9e621..4a848438 100644 --- a/samples/014-scripting/src/game.cpp +++ b/samples/014-scripting/src/game.cpp @@ -2,8 +2,11 @@ #include #include #include +#include #include #include +#include +#include #include #include @@ -16,7 +19,7 @@ namespace scripting_test { this->_window->setMonitor(-1); this->_window->setTitle("SCRIPTING TEST"); this->_window->setRenderer<>( - bgfx::RendererType::Count, []() {}, [this]() { this->drawWorld(); }); + bgfx::RendererType::Count, [this]() { this->drawOverlay(); }, [this]() { this->drawWorld(); }); this->_window->create(1024, 768, rawrbox::WindowFlags::Debug::TEXT | rawrbox::WindowFlags::Debug::PROFILER | rawrbox::WindowFlags::Window::WINDOWED | rawrbox::WindowFlags::Features::MULTI_THREADED); this->_window->onWindowClose += [this](auto& /*w*/) { this->shutdown(); }; } @@ -35,6 +38,30 @@ namespace scripting_test { rawrbox::RESOURCES::addLoader(); // ---------- + // Setup scripting + rawrbox::SCRIPTING::registerPlugin(this->_window.get()); + rawrbox::SCRIPTING::registerPlugin(); + + // Custom non-plugin --- + rawrbox::SCRIPTING::registerType(); + rawrbox::SCRIPTING::onRegisterGlobals += [this](rawrbox::Mod* mod) { + mod->getEnvironment()["test"] = rawrbox::TestWrapper(); + mod->getEnvironment()["test_model"] = [this]() -> sol::object { + if (this->_model == nullptr) return sol::nil; + return this->_model->getScriptingWrapper(); + }; + }; + // ---- + + rawrbox::SCRIPTING::init(2000); // Check files every 2 seconds + + // Load lua mods + rawrbox::SCRIPTING::load(); + rawrbox::SCRIPTING::call("init"); + // ----- + + // ---- + // Load content --- this->loadContent(); // ----- @@ -44,41 +71,37 @@ namespace scripting_test { std::array initialContentFiles = { std::make_pair("./content/textures/crate_hl1.png", 0)}; - this->_loadingFiles = static_cast(initialContentFiles.size()); for (auto& f : initialContentFiles) { - rawrbox::RESOURCES::loadFileAsync(f.first, f.second, [this]() { - this->_loadingFiles--; - if (this->_loadingFiles <= 0) { - rawrbox::runOnRenderThread([this]() { this->contentLoaded(); }); - } - }); + rawrbox::RESOURCES::preLoadFile(f.first, f.second); } - // Setup scripting - this->_script = std::make_unique(2000); // Check files every 2 seconds - this->_script->registerType(); - this->_script->onRegisterGlobals += [](rawrbox::Mod* mod) { - mod->getEnvironment()["test"] = rawrbox::TestWrapper(); - }; - // ----- - - // Load lua mods - this->_script->load(); - this->_script->call("init"); + // Load pre-content mod stuff --- + rawrbox::SCRIPTING::call("load"); + // --- + + // Start loading ---- + this->_loadingFiles = static_cast(rawrbox::RESOURCES::getTotalPreload()); + rawrbox::RESOURCES::startPreLoadQueueAsync(nullptr, [this](std::string f, uint32_t) { + fmt::print("Loaded {}!\n", f); + this->_loadingFiles--; + if (this->_loadingFiles <= 0) { + rawrbox::runOnRenderThread([this]() { this->contentLoaded(); }); + } + }); // ----- this->_window->upload(); } void Game::contentLoaded() { - // auto tex = rawrbox::RESOURCES::getFile("./content/textures/crate_hl1.png")->get(); + auto tex = rawrbox::RESOURCES::getFile("./content/textures/crate_hl1.png")->get(); this->_model->setOptimizable(false); - /*{ - auto mesh = rawrbox::MeshUtils::generatePlane({0.F, 4.0F, 0.F}, {4.F, 3.F}); + { + auto mesh = rawrbox::MeshUtils::generateCube({0.F, 1.0F, 0.F}, {1.F, 1.F, 1.F}); mesh.setTexture(tex); this->_model->addMesh(mesh); - }*/ + } { auto mesh = rawrbox::MeshUtils::generateGrid(12, {0.F, 0.F, 0.F}); @@ -95,6 +118,7 @@ namespace scripting_test { rawrbox::RESOURCES::shutdown(); rawrbox::ASYNC::shutdown(); + rawrbox::SCRIPTING::shutdown(); this->_model.reset(); @@ -110,6 +134,9 @@ namespace scripting_test { void Game::update() { if (this->_window == nullptr) return; this->_window->update(); + + if (!this->_ready) return; + rawrbox::SCRIPTING::call("update"); } void Game::printFrames() { @@ -121,11 +148,19 @@ namespace scripting_test { bgfx::dbgTextPrintf(1, 8, 0x5f, fmt::format("DRAW CALLS: {}", stats->numDraw).c_str()); bgfx::dbgTextPrintf(1, 9, 0x5f, fmt::format("COMPUTE CALLS: {}", stats->numCompute).c_str()); } + void Game::drawWorld() { if (!this->_ready) return; if (this->_model != nullptr) this->_model->draw(); } + void Game::drawOverlay() { + if (!this->_ready) return; + + rawrbox::SCRIPTING::call("drawOverlay"); + this->_window->getStencil().render(); + } + void Game::draw() { if (this->_window == nullptr) return; diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 58a8f249..60a64ba4 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -26,7 +26,7 @@ if(RAWRBOX_BUILD_RAWRBOX_UI) endif() if(RAWRBOX_BUILD_RAWRBOX_3D_PHYSICS) - add_subdirectory("009-physics") + add_subdirectory("009-physics-3d") endif() add_subdirectory("010-instancing") diff --git a/scripting/CMakeLists.txt b/scripting/CMakeLists.txt index d82f2990..0977d79d 100644 --- a/scripting/CMakeLists.txt +++ b/scripting/CMakeLists.txt @@ -2,9 +2,18 @@ project("RAWRBOX.SCRIPTING" VERSION ${RAWRBOX_VERSION} DESCRIPTION "RawrBox - SCRIPTING lib" LANGUAGES C CXX) set(output_target RAWRBOX.SCRIPTING) -## LIBS --- +# LIBS --- if(RAWRBOX_BUILD_RAWRBOX_SCRIPTING_USE_LUAJIT) message(STATUS "Enabled LuaJIT support") + + #CPMAddPackage(NAME luajit GITHUB_REPOSITORY WohlSoft/LuaJIT GIT_TAG v2.1) + #if(luajit_ADDED) + # set_lib_runtime_mt(luajit) + # set_lib_runtime_mt(libluajit) + # list(APPEND RAWRBOX_SCRIPTING_EXTRA_LIB libluajit) + # set(SOL2_LUA_VERSION "LuaJIT" CACHE STRING "" FORCE) + #endif() + CPMAddPackage( NAME luajit @@ -22,6 +31,7 @@ if(RAWRBOX_BUILD_RAWRBOX_SCRIPTING_USE_LUAJIT) set(SOL2_LUA_VERSION "LuaJIT" CACHE STRING "" FORCE) endif() else() + message(STATUS "LuaJIT support disabled, using normal LUA") CPMAddPackage( NAME lua @@ -33,17 +43,15 @@ else() YES) if(lua_ADDED) - file(GLOB lua_sources ${lua_SOURCE_DIR}/*.c) - list(REMOVE_ITEM lua_sources "${lua_SOURCE_DIR}/lua.c" "${lua_SOURCE_DIR}/luac.c") - + FILE(GLOB lua_sources ${lua_SOURCE_DIR}/*.c) + list(REMOVE_ITEM lua_sources "${lua_SOURCE_DIR}/lua.c" "${lua_SOURCE_DIR}/luac.c" "${lua_SOURCE_DIR}/onelua.c") add_library(lua STATIC ${lua_sources}) - target_include_directories(lua SYSTEM PUBLIC $) + target_include_directories(lua PUBLIC $) set_lib_runtime_mt(lua) endif() - set(RAWRBOX_SCRIPTING_EXTRA_LIB lua) - set(RAWRBOX_SCRIPTING_EXTRA_DEFS SOL_LUAJIT=1) + list(APPEND RAWRBOX_SCRIPTING_EXTRA_LIB lua) endif() # SOL ----------- @@ -67,10 +75,14 @@ add_library(${output_target} ${RAWRBOX_LIBRARY_TYPE} ${RAWRBOX_SCRIPTING_IMPORTS add_dependencies(${output_target} copy_resources_lua) target_compile_definitions(${output_target} PRIVATE _CRT_SECURE_NO_WARNINGS NOMINMAX) -target_compile_definitions(${output_target} PUBLIC RAWRBOX_SCRIPTING SOL_ALL_SAFETIES_ON=1 ${RAWRBOX_SCRIPTING_EXTRA_DEFS}) -target_include_directories(${output_target} PUBLIC "include") +target_compile_definitions(${output_target} PUBLIC RAWRBOX_SCRIPTING SOL_ALL_SAFETIES_ON=1) +if(RAWRBOX_BUILD_RAWRBOX_SCRIPTING_USE_LUAJIT) + target_compile_definitions(${output_target} PUBLIC RAWRBOX_SCRIPTING_LUAJIT SOL_LUAJIT=1) +endif() + +target_include_directories(${output_target} PUBLIC "include" ${luajit_SOURCE_DIR}/src) target_compile_features(${output_target} PUBLIC cxx_std_${CMAKE_CXX_STANDARD}) -target_link_libraries(${output_target} PUBLIC RAWRBOX.ENGINE RAWRBOX.MATH ${RAWRBOX_SCRIPTING_EXTRA_LIB} sol2::sol2) +target_link_libraries(${output_target} PUBLIC RAWRBOX.ENGINE RAWRBOX.MATH ${RAWRBOX_SCRIPTING_EXTRA_LIB} sol2::sol2 nlohmann_json) set_lib_runtime_mt(${output_target}) # -------------- diff --git a/scripting/include/rawrbox/scripting/hooks.hpp b/scripting/include/rawrbox/scripting/hooks.hpp new file mode 100644 index 00000000..bfed3cf9 --- /dev/null +++ b/scripting/include/rawrbox/scripting/hooks.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include + +#include + +#include +#include +#include + +namespace rawrbox { + struct Hook { + std::string name; + sol::function func; + + Hook(std::string name_, sol::function func_) : name(std::move(name_)), func(std::move(func_)) {} + }; + + class Hooks { + std::unordered_map> hooks; + + public: + template + void call(const std::string& name, CallbackArgs... args) { + for (auto& hook : hooks[name]) { + rawrbox::LuaUtils::runCallback(hook.func, std::forward(args)...); + } + } + + void listen(const std::string& id, const std::string& name, sol::function func); + void remove(const std::string& id, const std::string& name); + + // Utils --- + [[nodiscard]] size_t count() const; + [[nodiscard]] bool empty() const; + // ---- + }; +} // namespace rawrbox diff --git a/scripting/include/rawrbox/scripting/mod.hpp b/scripting/include/rawrbox/scripting/mod.hpp index e52c0147..ff00ace6 100644 --- a/scripting/include/rawrbox/scripting/mod.hpp +++ b/scripting/include/rawrbox/scripting/mod.hpp @@ -14,8 +14,6 @@ namespace rawrbox { sol::environment _environment; sol::table _modTable; - rawrbox::Scripting* _scripting = nullptr; - std::filesystem::path _folder; std::string _id; @@ -29,7 +27,7 @@ namespace rawrbox { Mod& operator=(Mod&&) = delete; virtual ~Mod(); - virtual void init(Scripting& scripting_); + virtual void init(); virtual bool load(); virtual void preLoad(); @@ -38,7 +36,6 @@ namespace rawrbox { [[nodiscard]] virtual const std::string getEntryFilePath() const; [[nodiscard]] virtual const std::filesystem::path& getFolder() const; - [[nodiscard]] virtual const rawrbox::Scripting& getScripting() const; virtual sol::environment& getEnvironment(); // ----- diff --git a/scripting/include/rawrbox/scripting/plugin.hpp b/scripting/include/rawrbox/scripting/plugin.hpp new file mode 100644 index 00000000..12224e29 --- /dev/null +++ b/scripting/include/rawrbox/scripting/plugin.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include + +namespace rawrbox { + class Mod; + + class Plugin { + public: + Plugin() = default; + Plugin(const Plugin &) = default; + Plugin(Plugin &&) = default; + Plugin &operator=(const Plugin &) = default; + Plugin &operator=(Plugin &&) = default; + virtual ~Plugin() = default; + + virtual void registerTypes(sol::state & /*_lua*/) {} + virtual void registerGlobal(rawrbox::Mod * /*_mod*/) {} + virtual void loadLuaExtensions(rawrbox::Mod * /*_mod*/) {} + }; +} // namespace rawrbox diff --git a/scripting/include/rawrbox/scripting/scripting.hpp b/scripting/include/rawrbox/scripting/scripting.hpp index d521c4a4..9d91fc6e 100644 --- a/scripting/include/rawrbox/scripting/scripting.hpp +++ b/scripting/include/rawrbox/scripting/scripting.hpp @@ -1,12 +1,16 @@ #pragma once +#include #include +#include #include #include +#include #include #include +#include #include #include @@ -17,68 +21,79 @@ namespace rawrbox { { T::registerLua(lua) }; }; - class Scripting { + class SCRIPTING { protected: - std::unordered_map> _mods = {}; - std::unordered_map> _loadedLuaFiles = {}; + static std::unordered_map> _mods; + static std::unordered_map> _loadedLuaFiles; - std::unique_ptr _watcher = nullptr; - std::unique_ptr _lua = nullptr; + static std::unique_ptr _watcher; + static std::unique_ptr _hooks; + static std::unique_ptr _lua; - bool _hotReloadEnabled = false; + static std::vector> _plugins; + + static bool _hotReloadEnabled; // LOAD ---- - virtual void loadLibraries(); - virtual void loadTypes(); - virtual void loadLuaExtensions(rawrbox::Mod* mod); - virtual void loadGlobals(rawrbox::Mod* mod); + static void loadLibraries(); + static void loadTypes(); + static void loadLuaExtensions(rawrbox::Mod* mod); + static void loadGlobals(rawrbox::Mod* mod); // ---- - virtual void registerLoadedFile(const std::string& modId, const std::string& filePath); - virtual void hotReload(const std::string& filePath); + static void registerLoadedFile(const std::string& modId, const std::string& filePath); + static void hotReload(const std::string& filePath); public: - Scripting(int hotReloadMs = 0); - Scripting(const Scripting&) = delete; - Scripting(Scripting&&) = delete; - Scripting& operator=(const Scripting&) = delete; - Scripting& operator=(Scripting&&) = delete; - virtual ~Scripting(); + static bool initialized; + + static void init(int hotReloadMs = 0); + static void shutdown(); // EVENTS ---- - rawrbox::Event<> onRegisterTypes; - rawrbox::Event onRegisterGlobals; - rawrbox::Event onLoadExtensions; - rawrbox::Event onModHotReload; + static rawrbox::Event<> onRegisterTypes; + static rawrbox::Event onRegisterGlobals; + static rawrbox::Event onLoadExtensions; + static rawrbox::Event onModHotReload; // ------- + // PLUGINS --- + template + static void registerPlugin(CallbackArgs&&... args) { + auto plugin = std::make_unique(std::forward(args)...); + + fmt::print("[RawrBox-Scripting] Registered lua plugin '{}'\n", rawrbox::StrUtils::replace(typeid(T).name(), "class rawrbox::", "")); + _plugins.push_back(std::move(plugin)); + } + // ----- + // LOAD ----- - virtual void load(); - virtual bool loadLuaFile(const std::string& path, const sol::environment& env, sol::state& lua); - [[nodiscard]] virtual bool isLuaFileMounted(const std::string& path) const; + static void load(); + static bool loadLuaFile(const std::string& path, const sol::environment& env); + [[nodiscard]] static bool isLuaFileMounted(const std::string& path); //------ // UTILS ----- - [[nodiscard]] virtual sol::state& getLua(); - [[nodiscard]] virtual const std::unordered_map>& getMods() const; - [[nodiscard]] virtual const std::vector getModsIds() const; + [[nodiscard]] static sol::state& getLUA(); + [[nodiscard]] static const std::unordered_map>& getMods(); + [[nodiscard]] static const std::vector getModsIds(); - [[nodiscard]] bool hotReloadEnabled() const; + [[nodiscard]] static bool hotReloadEnabled(); template - void registerType() { - if (this->_lua == nullptr) throw std::runtime_error("[RawrBox-Scripting] LUA is not set! Reference got destroyed?"); + static void registerType() { + if (_lua == nullptr) throw std::runtime_error("[RawrBox-Scripting] LUA is not set! Reference got destroyed?"); if constexpr (isLuaType) { - T::registerLua(*this->_lua); + T::registerLua(*_lua); } else { throw std::runtime_error("[RawrBox-Scripting] Type missing 'registerLua'"); } } template - void call(const std::string& hookName, CallbackArgs&&... args) { - for (auto& mod : this->_mods) { + static void call(const std::string& hookName, CallbackArgs&&... args) { + for (auto& mod : _mods) { mod.second->call(hookName, args...); } } diff --git a/scripting/include/rawrbox/scripting/utils/lua.hpp b/scripting/include/rawrbox/scripting/utils/lua.hpp index 6c206ac0..6fa6f8d5 100644 --- a/scripting/include/rawrbox/scripting/utils/lua.hpp +++ b/scripting/include/rawrbox/scripting/utils/lua.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -49,9 +50,13 @@ namespace rawrbox { return arr; } + static sol::object jsonToLuaObject(const nlohmann::json j, sol::state& lua); + static sol::object jsonToLuaObject(const nlohmann::json j, sol::state_view& lua); + static nlohmann::json luaToJsonObject(const sol::object& l, bool filterNull = false); + // @/ == Root content // @cats/ == `cats` mod // normal_path == current mod - static std::string getContent(const std::string& path, const std::string& modName = ""); + static std::string getContent(const std::filesystem::path& path, const std::string& modPath = ""); }; } // namespace rawrbox diff --git a/scripting/include/rawrbox/scripting/wrappers/hooks_wrapper.hpp b/scripting/include/rawrbox/scripting/wrappers/hooks_wrapper.hpp new file mode 100644 index 00000000..a0dafa48 --- /dev/null +++ b/scripting/include/rawrbox/scripting/wrappers/hooks_wrapper.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace rawrbox { + class Hooks; + + class HooksWrapper { + protected: + rawrbox::Hooks* _hooks = nullptr; + + public: + HooksWrapper(rawrbox::Hooks* hooks_); + HooksWrapper(const HooksWrapper&) = default; + HooksWrapper(HooksWrapper&&) = default; + HooksWrapper& operator=(const HooksWrapper&) = default; + HooksWrapper& operator=(HooksWrapper&&) = default; + virtual ~HooksWrapper() = default; + + virtual void listen(const std::string& hook, const std::string& name, sol::function callback); + virtual void call(const std::string& hook, sol::variadic_args args); + virtual void remove(const std::string& hook, const std::string& id); + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/scripting/include/rawrbox/scripting/wrappers/http_wrapper.hpp b/scripting/include/rawrbox/scripting/wrappers/http_wrapper.hpp new file mode 100644 index 00000000..1f4b9f96 --- /dev/null +++ b/scripting/include/rawrbox/scripting/wrappers/http_wrapper.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include + +namespace rawrbox { + class HTTPWrapper { + public: + HTTPWrapper() = default; + HTTPWrapper(const HTTPWrapper&) = default; + HTTPWrapper(HTTPWrapper&&) = default; + HTTPWrapper& operator=(const HTTPWrapper&) = default; + HTTPWrapper& operator=(HTTPWrapper&&) = default; + virtual ~HTTPWrapper() = default; + + // UTILS ----- + virtual void request(const std::string& url, const rawrbox::HTTPMethod method, sol::table headers, sol::function callback, sol::optional timeout); + // ---------------- + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/scripting/include/rawrbox/scripting/wrappers/math/bbox_wrapper.hpp b/scripting/include/rawrbox/scripting/wrappers/math/bbox_wrapper.hpp new file mode 100644 index 00000000..a5c057c2 --- /dev/null +++ b/scripting/include/rawrbox/scripting/wrappers/math/bbox_wrapper.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace rawrbox { + class BBOXWrapper { + public: + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/scripting/include/rawrbox/scripting/wrappers/mod_wrapper.hpp b/scripting/include/rawrbox/scripting/wrappers/mod_wrapper.hpp new file mode 100644 index 00000000..6649625c --- /dev/null +++ b/scripting/include/rawrbox/scripting/wrappers/mod_wrapper.hpp @@ -0,0 +1,25 @@ + +#pragma once +#include + +namespace rawrbox { + class ModWrapper { + protected: + rawrbox::Mod* _mod = nullptr; + + public: + ModWrapper(rawrbox::Mod* mod); + ModWrapper(const ModWrapper&) = default; + ModWrapper(ModWrapper&&) = default; + ModWrapper& operator=(const ModWrapper&) = default; + ModWrapper& operator=(ModWrapper&&) = default; + virtual ~ModWrapper() = default; + + [[nodiscard]] virtual sol::environment getENV() const; + [[nodiscard]] virtual std::string getID() const; + [[nodiscard]] virtual std::string getFolder() const; + [[nodiscard]] virtual std::string getEntryFilePath() const; + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/scripting/include/rawrbox/scripting/wrappers/scripting_wrapper.hpp b/scripting/include/rawrbox/scripting/wrappers/scripting_wrapper.hpp new file mode 100644 index 00000000..fbf671bb --- /dev/null +++ b/scripting/include/rawrbox/scripting/wrappers/scripting_wrapper.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace rawrbox { + class ScriptingWrapper { + public: + ScriptingWrapper() = default; + ScriptingWrapper(const ScriptingWrapper&) = default; + ScriptingWrapper(ScriptingWrapper&&) = default; + ScriptingWrapper& operator=(const ScriptingWrapper&) = default; + ScriptingWrapper& operator=(ScriptingWrapper&&) = default; + virtual ~ScriptingWrapper() = default; + + virtual sol::object getMod(const std::string& id, sol::this_state lua); + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/scripting/include/rawrbox/scripting/wrappers/timer_wrapper.hpp b/scripting/include/rawrbox/scripting/wrappers/timer_wrapper.hpp new file mode 100644 index 00000000..6927af09 --- /dev/null +++ b/scripting/include/rawrbox/scripting/wrappers/timer_wrapper.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +namespace rawrbox { + class TimerWrapper { + public: + TimerWrapper() = default; + TimerWrapper(const TimerWrapper&) = default; + TimerWrapper(TimerWrapper&&) = default; + TimerWrapper& operator=(const TimerWrapper&) = default; + TimerWrapper& operator=(TimerWrapper&&) = default; + virtual ~TimerWrapper() = default; + + // CREATE --- + virtual bool create(const std::string& id, int reps, uint64_t delay, sol::function callback, sol::function onComplete); + virtual bool simple(const std::string& id, uint64_t delay, sol::function callback, sol::function onComplete); + // ---- + + // UTILS --- + virtual bool destroy(const std::string& id); + virtual bool exists(const std::string& id); + virtual bool pause(const std::string& id, bool pause); + // ---- + + static void registerLua(sol::state& lua); + }; +} // namespace rawrbox diff --git a/scripting/lua/http.lua b/scripting/lua/http.lua new file mode 100644 index 00000000..75e683c9 --- /dev/null +++ b/scripting/lua/http.lua @@ -0,0 +1,7 @@ +HTTP = { + GET = 0, + POST = 1, + PUT = 2, + DELETE = 3, + OPTIONS = 4 +} diff --git a/scripting/src/hooks.cpp b/scripting/src/hooks.cpp new file mode 100644 index 00000000..0be137cb --- /dev/null +++ b/scripting/src/hooks.cpp @@ -0,0 +1,28 @@ +#include + +namespace rawrbox { + void Hooks::listen(const std::string& id, const std::string& name, sol::function func) { + hooks[id].emplace_back(name, func); + } + + void Hooks::remove(const std::string& id, const std::string& name) { + auto nameMap = hooks.find(id); + if (nameMap == hooks.end()) return; + + auto& arr = nameMap->second; + auto hook = std::find_if(arr.begin(), arr.end(), [&](auto& elem) { + return elem.name == name; + }); + + if (hook == arr.end()) return; + arr.erase(hook); + + if (arr.empty()) hooks.erase(id); + } + + // Utils --- + size_t Hooks::count() const { return this->hooks.size(); } + bool Hooks::empty() const { return this->hooks.empty(); } + // ---- + +} // namespace rawrbox diff --git a/scripting/src/mod.cpp b/scripting/src/mod.cpp index 679a1d31..cda32014 100644 --- a/scripting/src/mod.cpp +++ b/scripting/src/mod.cpp @@ -8,19 +8,16 @@ namespace rawrbox { Mod::Mod(std::string id, std::filesystem::path folderPath) : _folder(std::move(folderPath)), _id(std::move(id)) {} Mod::~Mod() { - this->_scripting = nullptr; this->_environment.reset(); } - void Mod::init(rawrbox::Scripting& scripting_) { - this->_scripting = &scripting_; - - auto& lua = this->_scripting->getLua(); + void Mod::init() { + auto& lua = rawrbox::SCRIPTING::getLUA(); this->_environment = {lua, sol::create, lua.globals()}; } bool Mod::load() { - auto& lua = this->_scripting->getLua(); + auto& lua = rawrbox::SCRIPTING::getLUA(); this->_modTable = lua.create_table(); this->_environment["MOD"] = this->_modTable; @@ -28,7 +25,7 @@ namespace rawrbox { // Load init script auto pth = this->getEntryFilePath(); if (std::filesystem::exists(pth)) { - if (!this->_scripting->loadLuaFile(pth, this->_environment, lua)) { + if (!rawrbox::SCRIPTING::loadLuaFile(pth, this->_environment)) { return false; } } else { @@ -47,7 +44,6 @@ namespace rawrbox { const std::string Mod::getEntryFilePath() const { return fmt::format("{}/init.lua", this->_folder.generic_string()); } const std::filesystem::path& Mod::getFolder() const { return this->_folder; } - const rawrbox::Scripting& Mod::getScripting() const { return *this->_scripting; } sol::environment& Mod::getEnvironment() { return this->_environment; } // ----- } // namespace rawrbox diff --git a/scripting/src/scripting.cpp b/scripting/src/scripting.cpp index 3b7dc38b..6094bcb4 100644 --- a/scripting/src/scripting.cpp +++ b/scripting/src/scripting.cpp @@ -2,53 +2,85 @@ #include #include #include +#include +#include #include #include +#include #include #include #include #include #include +#include +#include +#include #include #include #include namespace rawrbox { - Scripting::Scripting(int hotReloadMs) : _hotReloadEnabled(hotReloadMs > 0) { - this->_lua = std::make_unique(); + // PROTECTED ----- + std::unordered_map> SCRIPTING::_mods = {}; + std::unordered_map> SCRIPTING::_loadedLuaFiles = {}; - if (this->hotReloadEnabled()) { + std::unique_ptr SCRIPTING::_watcher = nullptr; + std::unique_ptr SCRIPTING::_hooks = std::make_unique(); + std::unique_ptr SCRIPTING::_lua = std::make_unique(); + + std::vector> SCRIPTING::_plugins = {}; + + bool SCRIPTING::_hotReloadEnabled = false; + // ----- + + // PUBLIC ---- + rawrbox::Event<> SCRIPTING::onRegisterTypes; + rawrbox::Event SCRIPTING::onRegisterGlobals; + rawrbox::Event SCRIPTING::onLoadExtensions; + rawrbox::Event SCRIPTING::onModHotReload; + + bool SCRIPTING::initialized = false; + // ------ + + void SCRIPTING::init(int hotReloadMs) { + _hotReloadEnabled = hotReloadMs > 0; + if (hotReloadEnabled()) { fmt::print("[RawrBox-Scripting] Enabled lua hot-reloading\n └── Delay: {}ms\n", hotReloadMs); - this->_watcher = std::make_unique( - [this](std::filesystem::path pth, rawrbox::FileStatus status) { + _watcher = std::make_unique( + [](std::filesystem::path pth, rawrbox::FileStatus status) { if (status != rawrbox::FileStatus::modified) return; - this->hotReload(pth.generic_string()); + hotReload(pth.generic_string()); }, std::chrono::milliseconds(hotReloadMs)); - this->_watcher->start(); + _watcher->start(); } - this->_mods.clear(); + _mods.clear(); // Loading initial libs --- - // NOLINTBEGIN(clang-analyzer-optin.cplusplus.VirtualCall) - this->loadLibraries(); - this->loadTypes(); - // NOLINTEND(clang-analyzer-optin.cplusplus.VirtualCall) + loadLibraries(); + loadTypes(); // ---- + + initialized = true; } - Scripting::~Scripting() { - this->_watcher.reset(); - this->_mods.clear(); + void SCRIPTING::shutdown() { + _watcher.reset(); + _hooks.reset(); + + _mods.clear(); + _plugins.clear(); - this->_lua->collect_garbage(); - this->_lua.reset(); + _lua->collect_garbage(); + _lua.reset(); } - void Scripting::load() { + // LOAD --- + void SCRIPTING::load() { + if (!std::filesystem::exists("./mods")) throw std::runtime_error("[RawrBox-Scripting] Failed to locate folder './mods'"); // TODO: Do we need mod load ordering? @@ -60,51 +92,57 @@ namespace rawrbox { // Done auto mod = std::make_unique(id, folderPath); - this->_mods.emplace(id, std::move(mod)); + _mods.emplace(id, std::move(mod)); } // Initialize - for (auto& mod : this->_mods) { - mod.second->init(*this); + for (auto& mod : _mods) { + mod.second->init(); - this->loadLuaExtensions(mod.second.get()); - this->loadGlobals(mod.second.get()); + loadLuaExtensions(mod.second.get()); + loadGlobals(mod.second.get()); if (!mod.second->load()) { fmt::print("[RawrBox-Scripting] Failed to load mod '{}'\n", mod.first); } else { // Register file for hot-reloading - this->registerLoadedFile(mod.first, mod.second->getEntryFilePath()); + registerLoadedFile(mod.first, mod.second->getEntryFilePath()); // ---- } } // ----- } - void Scripting::loadGlobals(rawrbox::Mod* mod) { + void SCRIPTING::loadGlobals(rawrbox::Mod* mod) { if (mod == nullptr) return; auto& env = mod->getEnvironment(); - env["print"] = [this](sol::variadic_args va) { + env["print"] = [](sol::variadic_args va) { auto vars = std::vector(va.begin(), va.end()); std::vector prtData; for (auto& var : vars) { - prtData.push_back((*this->_lua)["tostring"](var)); + prtData.push_back((*_lua)["tostring"](var)); } if (prtData.empty()) return; fmt::print("{}\n", fmt::join(prtData, " ")); }; - env["include"] = [&env, &mod, this](const std::string& path) { + env["printTable"] = [](sol::table table) { + auto json = rawrbox::LuaUtils::luaToJsonObject(table); + fmt::print("{}\n", json.dump(1, ' ', false)); + }; + + env["include"] = [&env, &mod](const std::string& path) { auto modFolder = mod->getFolder().generic_string(); + auto fixedPath = LuaUtils::getContent(path, modFolder); - bool loaded = loadLuaFile(LuaUtils::getContent(path, modFolder), env, this->getLua()); - if (!loaded) fmt::print("[RawrBox-Scripting] Failed to load '{}'\n", path); + bool loaded = loadLuaFile(fixedPath, env); + if (!loaded) fmt::print("[RawrBox-Scripting] Failed to load '{}'\n", fixedPath); // Register file for hot-reloading - this->registerLoadedFile(mod->getID(), path); + registerLoadedFile(mod->getID(), fixedPath); // ---- return loaded ? 1 : 0; @@ -144,102 +182,130 @@ namespace rawrbox { // Global types ------------------------------------ env["fmt"] = rawrbox::FMTWrapper(); env["io"] = rawrbox::IOWrapper(); + env["hooks"] = rawrbox::HooksWrapper(_hooks.get()); + env["scripting"] = rawrbox::ScriptingWrapper(); + env["http"] = rawrbox::HTTPWrapper(); + env["timer"] = rawrbox::TimerWrapper(); // ------------------- - // Custom global types --- - this->onRegisterGlobals(mod); + // Register plugins env types --- + for (auto& p : _plugins) + p->registerGlobal(mod); + // ----- + + // Custom global env types --- + onRegisterGlobals(mod); // ---- } - void Scripting::registerLoadedFile(const std::string& modId, const std::string& filePath) { - auto mdFnd = this->_loadedLuaFiles.find(modId); - if (mdFnd != this->_loadedLuaFiles.end()) { + void SCRIPTING::registerLoadedFile(const std::string& modId, const std::string& filePath) { + auto mdFnd = _loadedLuaFiles.find(modId); + if (mdFnd != _loadedLuaFiles.end()) { auto fileFnd = std::find(mdFnd->second.begin(), mdFnd->second.end(), filePath); if (fileFnd != mdFnd->second.end()) return; // Already registered mdFnd->second.push_back(filePath); } else { - this->_loadedLuaFiles[modId] = {filePath}; + _loadedLuaFiles[modId] = {filePath}; } - if (this->hotReloadEnabled()) { - this->_watcher->watchFile(filePath); + if (hotReloadEnabled()) { + _watcher->watchFile(filePath); } } - void Scripting::hotReload(const std::string& filePath) { + void SCRIPTING::hotReload(const std::string& filePath) { // Find the owner - for (auto& pt : this->_loadedLuaFiles) { + for (auto& pt : _loadedLuaFiles) { auto fnd = std::find(pt.second.begin(), pt.second.end(), filePath) != pt.second.end(); if (!fnd) continue; - auto md = this->_mods.find(pt.first); - if (md == this->_mods.end()) return; + auto md = _mods.find(pt.first); + if (md == _mods.end()) return; fmt::print("[RawrBox-Scripting] Hot-reloading lua file '{}'\n", filePath); - this->loadLuaFile(filePath, md->second->getEnvironment(), this->getLua()); - this->onModHotReload(md->second.get()); + loadLuaFile(filePath, md->second->getEnvironment()); + onModHotReload(md->second.get()); break; }; } // LOAD ----- - void Scripting::loadLibraries() { - if (this->_lua == nullptr) throw std::runtime_error("[RawrBox-Scripting] LUA is not set! Reference got destroyed?"); - - this->_lua->open_libraries(sol::lib::base); - this->_lua->open_libraries(sol::lib::package); - this->_lua->open_libraries(sol::lib::math); - this->_lua->open_libraries(sol::lib::table); - this->_lua->open_libraries(sol::lib::debug); - this->_lua->open_libraries(sol::lib::string); - this->_lua->open_libraries(sol::lib::coroutine); - this->_lua->open_libraries(sol::lib::bit32); - - this->_lua->open_libraries(sol::lib::jit); + void SCRIPTING::loadLibraries() { + if (_lua == nullptr) throw std::runtime_error("[RawrBox-Scripting] LUA is not set! Reference got destroyed?"); + + _lua->open_libraries(sol::lib::base); + _lua->open_libraries(sol::lib::package); + _lua->open_libraries(sol::lib::math); + _lua->open_libraries(sol::lib::table); + _lua->open_libraries(sol::lib::debug); + _lua->open_libraries(sol::lib::string); + _lua->open_libraries(sol::lib::coroutine); + _lua->open_libraries(sol::lib::bit32); + +#ifdef RAWRBOX_SCRIPTING_LUAJIT + _lua->open_libraries(sol::lib::jit); +#endif } - void Scripting::loadTypes() { - if (this->_lua == nullptr) throw std::runtime_error("[RawrBox-Scripting] LUA is not set! Reference got destroyed?"); + void SCRIPTING::loadTypes() { + if (_lua == nullptr) throw std::runtime_error("[RawrBox-Scripting] LUA is not set! Reference got destroyed?"); - // Default ---- - rawrbox::IOWrapper::registerLua(*this->_lua); - rawrbox::FMTWrapper::registerLua(*this->_lua); + // Math ---- + rawrbox::AABBWrapper::registerLua(*_lua); + rawrbox::BBOXWrapper::registerLua(*_lua); + rawrbox::ColorWrapper::registerLua(*_lua); + rawrbox::MatrixWrapper::registerLua(*_lua); + rawrbox::Vector2Wrapper::registerLua(*_lua); + rawrbox::Vector3Wrapper::registerLua(*_lua); + rawrbox::Vector4Wrapper::registerLua(*_lua); // ---- - // Math ---- - rawrbox::AABBWrapper::registerLua(*this->_lua); - rawrbox::ColorWrapper::registerLua(*this->_lua); - rawrbox::MatrixWrapper::registerLua(*this->_lua); - rawrbox::Vector2Wrapper::registerLua(*this->_lua); - rawrbox::Vector3Wrapper::registerLua(*this->_lua); - rawrbox::Vector4Wrapper::registerLua(*this->_lua); + // Default ---- + rawrbox::IOWrapper::registerLua(*_lua); + rawrbox::FMTWrapper::registerLua(*_lua); + rawrbox::ScriptingWrapper::registerLua(*_lua); + rawrbox::ModWrapper::registerLua(*_lua); + rawrbox::HooksWrapper::registerLua(*_lua); + rawrbox::HTTPWrapper::registerLua(*_lua); + rawrbox::TimerWrapper::registerLua(*_lua); // ---- + // Register plugins types --- + for (auto& p : _plugins) + p->registerTypes(*_lua); + // ----- + // Custom ---- - this->onRegisterTypes(); + onRegisterTypes(); // ---- } - void Scripting::loadLuaExtensions(rawrbox::Mod* mod) { - if (this->_lua == nullptr) throw std::runtime_error("[RawrBox-Scripting] LUA is not set! Reference got destroyed?"); + void SCRIPTING::loadLuaExtensions(rawrbox::Mod* mod) { + if (_lua == nullptr) throw std::runtime_error("[RawrBox-Scripting] LUA is not set! Reference got destroyed?"); if (mod == nullptr) return; auto& env = mod->getEnvironment(); - this->loadLuaFile("./lua/table.lua", env, *this->_lua); - this->loadLuaFile("./lua/string.lua", env, *this->_lua); - this->loadLuaFile("./lua/math.lua", env, *this->_lua); - this->loadLuaFile("./lua/json.lua", env, *this->_lua); - this->loadLuaFile("./lua/sha2.lua", env, *this->_lua); - this->loadLuaFile("./lua/util.lua", env, *this->_lua); - this->loadLuaFile("./lua/input.lua", env, *this->_lua); + loadLuaFile("./lua/table.lua", env); + loadLuaFile("./lua/string.lua", env); + loadLuaFile("./lua/math.lua", env); + loadLuaFile("./lua/json.lua", env); + loadLuaFile("./lua/sha2.lua", env); + loadLuaFile("./lua/util.lua", env); + loadLuaFile("./lua/input.lua", env); + loadLuaFile("./lua/http.lua", env); + + // Register plugins types --- + for (auto& p : _plugins) + p->loadLuaExtensions(mod); + // ----- // Custom ---- - this->onLoadExtensions(mod); + onLoadExtensions(mod); // ---- } - bool Scripting::loadLuaFile(const std::string& path, const sol::environment& env, sol::state& lua) { + bool SCRIPTING::loadLuaFile(const std::string& path, const sol::environment& env) { if (!std::filesystem::exists(path)) { fmt::print("[RawrBox-Scripting] Failed to load lua : {}\n", path); return false; @@ -247,26 +313,23 @@ namespace rawrbox { std::string errStr; // try to load the file while handling exceptions - try { - auto ret = lua.safe_script_file(path, env, sol::load_mode::text); - if (!ret.valid()) { - sol::error err = ret; - errStr = err.what(); - } - - } catch (const std::exception& err) { - errStr = err.what(); - } + auto ret = _lua->safe_script_file( + path, env, [&errStr](lua_State*, sol::protected_function_result pfr) { + sol::error err = pfr; + errStr = err.what(); + return pfr; + }, + sol::load_mode::text); // check if we loaded the file if (errStr.empty()) return true; - fmt::print("[RawrBox-Scripting] Failed to load '{}'\n └── Lua error : {}\n", path, errStr); + fmt::print("[RawrBox-Scripting] Failed to load '{}'\n └── Lua error : {}\n", path, errStr); return false; } - bool Scripting::isLuaFileMounted(const std::string& path) const { - for (auto& pt : this->_loadedLuaFiles) { + bool SCRIPTING::isLuaFileMounted(const std::string& path) { + for (auto& pt : _loadedLuaFiles) { auto fnd = std::find(pt.second.begin(), pt.second.end(), path) != pt.second.end(); if (fnd) return true; }; @@ -276,25 +339,23 @@ namespace rawrbox { // ----- // UTILS ----- - sol::state& Scripting::getLua() { - return *this->_lua; - } + sol::state& SCRIPTING::getLUA() { return *_lua; } - const std::unordered_map>& Scripting::getMods() const { - return this->_mods; + const std::unordered_map>& SCRIPTING::getMods() { + return _mods; } - const std::vector Scripting::getModsIds() const { + const std::vector SCRIPTING::getModsIds() { std::vector modNames = {}; - for (auto& mod : this->_mods) { + for (auto& mod : _mods) { modNames.push_back(mod.second->getID()); } return modNames; } - bool Scripting::hotReloadEnabled() const { - return this->_hotReloadEnabled; + bool SCRIPTING::hotReloadEnabled() { + return _hotReloadEnabled; } // ----- diff --git a/scripting/src/utils/lua.cpp b/scripting/src/utils/lua.cpp index b46e097a..37ae43c3 100644 --- a/scripting/src/utils/lua.cpp +++ b/scripting/src/utils/lua.cpp @@ -1,22 +1,119 @@ #include +#include #include namespace rawrbox { + sol::object LuaUtils::jsonToLuaObject(const nlohmann::json j, sol::state_view& lua) { + if (j.is_null()) { + return sol::nil; + } else if (j.is_boolean()) { + return sol::make_object(lua, j.get()); + } else if (j.is_number_integer()) { + return sol::make_object(lua, j.get()); + } else if (j.is_number_unsigned()) { + return sol::make_object(lua, j.get()); + } else if (j.is_number_float()) { + return sol::make_object(lua, j.get()); + } else if (j.is_string()) { + return sol::make_object(lua, j.get().c_str()); + } else if (j.is_object()) { + auto obj = lua.create_table(); + for (nlohmann::json::const_iterator it = j.begin(); it != j.end(); ++it) { + obj[it.key().c_str()] = jsonToLuaObject(*it, lua); + } + + return obj.as(); + } else if (j.is_array()) { + auto obj = lua.create_table(); + unsigned long i = 1; + + for (const auto& it : j) { + obj[i++] = jsonToLuaObject(it, lua); + } + + return obj; + } + + return sol::nil; + } + + sol::object LuaUtils::jsonToLuaObject(const nlohmann::json j, sol::state& lua) { + // NOLINTBEGIN(cppcoreguidelines-slicing) + sol::state_view view = lua; + // NOLINTEND(cppcoreguidelines-slicing) + return jsonToLuaObject(j, view); + } + + nlohmann::json LuaUtils::luaToJsonObject(const sol::object& l, bool filterNull) { + switch (l.get_type()) { + case sol::type::nil: return {}; + case sol::type::boolean: return l.as(); + case sol::type::number: + if (l.is()) return l.as(); + if (l.is()) return l.as(); + if (l.is()) return l.as(); + case sol::type::string: return l.as(); + case sol::type::table: + { + bool isArray = true; + int index = 0; + + for (auto& entry : l.as()) { + if (entry.first.get_type() != sol::type::number || entry.first.as() != ++index) { + isArray = false; + break; + } + } + + if (isArray) { + auto arr = nlohmann::json::array(); + for (auto& entry : l.as()) { + auto val = luaToJsonObject(entry.second); + if (filterNull && val.empty()) continue; + + arr.push_back(val); + } + + return arr; + } else { + auto obj = nlohmann::json::object(); + for (auto& entry : l.as()) { + auto type = entry.first.get_type(); + if (type != sol::type::number && type != sol::type::string) continue; + + auto val = luaToJsonObject(entry.second); + if (filterNull && val.empty()) continue; + + if (type == sol::type::number) + obj[std::to_string(entry.first.as())] = val; + else if (type == sol::type::string) + obj[entry.first.as()] = val; + } + + return obj; + } + } + default: + return {}; + } + } + // @/ == Root content // @cats/ == `cats` mod // normal_path == current mod - std::string LuaUtils::getContent(const std::string& path, const std::string& modName) { - if (path.empty()) return modName; - if (path.starts_with("mods/")) return path; // Already has the mod + std::string LuaUtils::getContent(const std::filesystem::path& path, const std::string& modPath) { + if (path.empty()) return modPath; // Invalid path + if (path.generic_string().starts_with("mods/")) return modPath; // Already has the mod - std::string fixedPath = path; - std::replace(fixedPath.begin(), fixedPath.end(), '\\', '/'); // Fix windows + auto fixedPath = path.generic_string(); + fixedPath = rawrbox::StrUtils::replace(fixedPath, "./", ""); + fixedPath = rawrbox::StrUtils::replace(fixedPath, "../", ""); // content/blabalba.png = my current mod - if (!modName.empty() && fixedPath.front() != '@') { - return std::filesystem::path(fmt::format("{}/{}", modName, fixedPath)).string(); // Becomes mods/mymod/content/blabalba.png + if (!modPath.empty() && fixedPath.front() != '@') { + return std::filesystem::path(fmt::format("{}/{}", modPath, fixedPath)).string(); // Becomes mods/mymod/content/blabalba.png } else if (fixedPath.front() == '@') { auto slashPos = fixedPath.find("/"); // Find the first / std::string cleanPath = fixedPath.substr(slashPos + 1); @@ -29,7 +126,7 @@ namespace rawrbox { } } - return path; + return fixedPath; } } // namespace rawrbox diff --git a/scripting/src/wrappers/hooks_wrapper.cpp b/scripting/src/wrappers/hooks_wrapper.cpp new file mode 100644 index 00000000..fb9544e2 --- /dev/null +++ b/scripting/src/wrappers/hooks_wrapper.cpp @@ -0,0 +1,26 @@ +#include +#include + +namespace rawrbox { + HooksWrapper::HooksWrapper(rawrbox::Hooks* hooks_) : _hooks(hooks_) {} + + void HooksWrapper::listen(const std::string& hook, const std::string& name, sol::function callback) { + this->_hooks->listen(hook, name, callback); + } + + void HooksWrapper::call(const std::string& hook, sol::variadic_args args) { + this->_hooks->call(hook, args); + } + + void HooksWrapper::remove(const std::string& hook, const std::string& id) { + this->_hooks->remove(hook, id); + } + + void HooksWrapper::registerLua(sol::state& lua) { + lua.new_usertype("hooks", + sol::no_constructor, + "add", &HooksWrapper::listen, + "call", &HooksWrapper::call, + "remove", &HooksWrapper::remove); + } +} // namespace rawrbox diff --git a/scripting/src/wrappers/http_wrapper.cpp b/scripting/src/wrappers/http_wrapper.cpp new file mode 100644 index 00000000..d089bc7e --- /dev/null +++ b/scripting/src/wrappers/http_wrapper.cpp @@ -0,0 +1,55 @@ +#include +#include +#include + +namespace rawrbox { + void HTTPWrapper::request(const std::string& url, const rawrbox::HTTPMethod method, sol::table headers, sol::function callback, sol::optional timeout) { + if (url.empty()) { + rawrbox::LuaUtils::runCallback(callback, true, "URL cannot be empty"); + return; + } + + // Setup headers ------- + std::map headerMap = {}; + for (auto& pair : headers) { + std::string nameCheck = pair.first.as(); + std::transform(nameCheck.begin(), nameCheck.end(), nameCheck.begin(), ::toupper); + + std::string name = pair.first.as(); + std::string value = pair.second.as(); + + if (nameCheck.compare("METHOD") == 0 || nameCheck.compare("USER-AGENT") == 0) continue; // Remove these + headerMap[name] = value; + } + // ------------------ + + rawrbox::HTTP::request( + url, method, headerMap, [callback](int code, std::map headerResp, std::string resp) { + if (code == 0) { + rawrbox::LuaUtils::runCallback(callback, true, resp); // curl error + return; + } + + auto& lua = rawrbox::SCRIPTING::getLUA(); + sol::table tbl = lua.create_table(); + sol::table headerTbl = lua.create_table(); + + for (auto& pair : headerResp) { + headerTbl[pair.first] = pair.second; + } + + tbl["status"] = code; + tbl["data"] = resp; + tbl["headers"] = headerTbl; + + rawrbox::LuaUtils::runCallback(callback, false, tbl); + }, + timeout.value_or(5000)); + } + + void HTTPWrapper::registerLua(sol::state& lua) { + lua.new_usertype("HTTP", + sol::no_constructor, + "request", &HTTPWrapper::request); + } +} // namespace rawrbox diff --git a/scripting/src/wrappers/math/aabb_wrapper.cpp b/scripting/src/wrappers/math/aabb_wrapper.cpp index 76ec3e5e..86d41e23 100644 --- a/scripting/src/wrappers/math/aabb_wrapper.cpp +++ b/scripting/src/wrappers/math/aabb_wrapper.cpp @@ -3,20 +3,20 @@ namespace rawrbox { void AABBWrapper::registerLua(sol::state& lua) { - lua.new_usertype("AABB", - sol::constructors(), + lua.new_usertype("AABB", + sol::constructors(), - "top", &AABBf::top, - "left", &AABBf::left, - "bottom", &AABBf::bottom, - "right", &AABBf::right, + "top", &AABB::top, + "left", &AABB::left, + "bottom", &AABB::bottom, + "right", &AABB::right, - "empty", &AABBf::empty, - "contains", &AABBf::contains, + "empty", &AABB::empty, + "contains", &AABB::contains, - "surfaceArea", &AABBf::surfaceArea, + "surfaceArea", &AABB::surfaceArea, - sol::meta_function::equal_to, &rawrbox::AABBf::operator==, - sol::meta_function::multiplication, &rawrbox::AABBf::operator*); + sol::meta_function::equal_to, &rawrbox::AABB::operator==, + sol::meta_function::multiplication, &rawrbox::AABB::operator*); } } // namespace rawrbox diff --git a/scripting/src/wrappers/math/bbox_wrapper.cpp b/scripting/src/wrappers/math/bbox_wrapper.cpp new file mode 100644 index 00000000..0404b84d --- /dev/null +++ b/scripting/src/wrappers/math/bbox_wrapper.cpp @@ -0,0 +1,12 @@ +#include +#include + +namespace rawrbox { + void BBOXWrapper::registerLua(sol::state& lua) { + lua.new_usertype("BBOX", + sol::constructors(), + "combine", &BBOXf::combine, + + sol::meta_function::equal_to, &rawrbox::BBOX::operator==); + } +} // namespace rawrbox diff --git a/scripting/src/wrappers/mod_wrapper.cpp b/scripting/src/wrappers/mod_wrapper.cpp new file mode 100644 index 00000000..8feb385d --- /dev/null +++ b/scripting/src/wrappers/mod_wrapper.cpp @@ -0,0 +1,36 @@ + +#include + +namespace rawrbox { + ModWrapper::ModWrapper(rawrbox::Mod* mod_) : _mod(mod_) {} + + sol::environment ModWrapper::getENV() const { + if (this->_mod == nullptr) return sol::nil; + return this->_mod->getEnvironment(); + } + + std::string ModWrapper::getID() const { + if (this->_mod == nullptr) return ""; + return this->_mod->getID(); + } + + std::string ModWrapper::getFolder() const { + if (this->_mod == nullptr) return ""; + return this->_mod->getFolder().generic_string(); + } + + std::string ModWrapper::getEntryFilePath() const { + if (this->_mod == nullptr) return ""; + return this->_mod->getEntryFilePath(); + } + + void ModWrapper::registerLua(sol::state& lua) { + lua.new_usertype("Mod", + sol::no_constructor, + + "getENV", &ModWrapper::getENV, + "getID", &ModWrapper::getID, + "getFolder", &ModWrapper::getFolder, + "getEntryFilePath", &ModWrapper::getEntryFilePath); + } +} // namespace rawrbox diff --git a/scripting/src/wrappers/scripting_wrapper.cpp b/scripting/src/wrappers/scripting_wrapper.cpp new file mode 100644 index 00000000..2b5c8ef6 --- /dev/null +++ b/scripting/src/wrappers/scripting_wrapper.cpp @@ -0,0 +1,20 @@ + +#include +#include + +namespace rawrbox { + sol::object ScriptingWrapper::getMod(const std::string& id, sol::this_state lua) { + auto& mods = rawrbox::SCRIPTING::getMods(); + + auto fnd = mods.find(id); + if (fnd == mods.end()) return sol::nil; + + return sol::make_object(lua, rawrbox::ModWrapper(fnd->second.get())); + } + + void ScriptingWrapper::registerLua(sol::state& lua) { + lua.new_usertype("Scripting", + sol::no_constructor, + "getMod", &ScriptingWrapper::getMod); + } +} // namespace rawrbox diff --git a/scripting/src/wrappers/timer_wrapper.cpp b/scripting/src/wrappers/timer_wrapper.cpp new file mode 100644 index 00000000..30e70965 --- /dev/null +++ b/scripting/src/wrappers/timer_wrapper.cpp @@ -0,0 +1,53 @@ +#include +#include +#include + +namespace rawrbox { + // CREATE --- + bool TimerWrapper::create(const std::string& id, int reps, uint64_t delay, sol::function callback, sol::function onComplete) { + auto timer = rawrbox::Timer::create( + id, reps, delay, [callback]() { rawrbox::LuaUtils::runCallback(callback); }, + [onComplete]() { + rawrbox::LuaUtils::runCallback(onComplete); + }); + + return timer != nullptr; + } + + bool TimerWrapper::simple(const std::string& id, uint64_t delay, sol::function callback, sol::function onComplete) { + auto timer = rawrbox::Timer::simple( + id, delay, [callback]() { rawrbox::LuaUtils::runCallback(callback); }, + [onComplete]() { + rawrbox::LuaUtils::runCallback(onComplete); + }); + + return timer != nullptr; + } + // ---- + + // UTILS --- + bool TimerWrapper::destroy(const std::string& id) { + return rawrbox::Timer::destroy(id); + } + + bool TimerWrapper::exists(const std::string& id) { + return rawrbox::Timer::exists(id); + } + + bool TimerWrapper::pause(const std::string& id, bool pause) { + return rawrbox::Timer::pause(id, pause); + } + // ---- + + void TimerWrapper::registerLua(sol::state& lua) { + lua.new_usertype("Timer", + sol::no_constructor, + // CREATE ----- + "create", &TimerWrapper::create, + "simple", &TimerWrapper::simple, + // ---- + "destroy", &TimerWrapper::destroy, + "exists", &TimerWrapper::exists, + "pause", &TimerWrapper::pause); + } +} // namespace rawrbox diff --git a/scripting/tests/hook.spec.cpp b/scripting/tests/hook.spec.cpp new file mode 100644 index 00000000..65119969 --- /dev/null +++ b/scripting/tests/hook.spec.cpp @@ -0,0 +1,23 @@ +#include + +#include + +#include + +TEST_CASE("Hook should behave as expected", "[rawrbox::Hook]") { + std::unique_ptr hooks = std::make_unique(); + + SECTION("rawrbox::Hook") { + REQUIRE(hooks->empty() == true); + REQUIRE(hooks->count() == 0); + + REQUIRE_NOTHROW(hooks->listen("test", "test-hook", {})); + REQUIRE(hooks->count() == 1); + + REQUIRE_NOTHROW(hooks->remove("test34", "test-hoo23k")); + REQUIRE(hooks->count() == 1); + + REQUIRE_NOTHROW(hooks->remove("test", "test-hook")); + REQUIRE(hooks->count() == 0); + } +} diff --git a/scripting/tests/scripting.spec.cpp b/scripting/tests/scripting.spec.cpp index 6b78e65f..d02c586b 100644 --- a/scripting/tests/scripting.spec.cpp +++ b/scripting/tests/scripting.spec.cpp @@ -5,26 +5,26 @@ #include TEST_CASE("Scripting should behave as expected", "[rawrbox::Scripting]") { - std::unique_ptr script = std::make_unique(); - SECTION("rawrbox::Scripting::init") { - REQUIRE(script->getMods().empty() == true); - REQUIRE(script->getModsIds().empty() == true); + REQUIRE_NOTHROW(rawrbox::SCRIPTING::init()); + + REQUIRE(rawrbox::SCRIPTING::getMods().empty() == true); + REQUIRE(rawrbox::SCRIPTING::getModsIds().empty() == true); - REQUIRE(static_cast(script->getLua().script("return true")) == true); + REQUIRE(static_cast(rawrbox::SCRIPTING::getLUA().script("return true")) == true); - REQUIRE(script->isLuaFileMounted("./test.lua") == false); + REQUIRE(rawrbox::SCRIPTING::isLuaFileMounted("./test.lua") == false); - REQUIRE_NOTHROW(script->getLua().script("local t = Vector2:new(23, 43)")); - REQUIRE_NOTHROW(script->getLua().script("local t = Vector3:new(23, 43, 53)")); - REQUIRE_NOTHROW(script->getLua().script("local t = Vector4:new(23, 43, 53, 12)")); - REQUIRE_NOTHROW(script->getLua().script("local t = Color:new(255, 0, 0, 255)")); - REQUIRE_NOTHROW(script->getLua().script("local t = Matrix:new()")); + REQUIRE_NOTHROW(rawrbox::SCRIPTING::getLUA().script("local t = Vector2:new(23, 43)")); + REQUIRE_NOTHROW(rawrbox::SCRIPTING::getLUA().script("local t = Vector3:new(23, 43, 53)")); + REQUIRE_NOTHROW(rawrbox::SCRIPTING::getLUA().script("local t = Vector4:new(23, 43, 53, 12)")); + REQUIRE_NOTHROW(rawrbox::SCRIPTING::getLUA().script("local t = Color:new(255, 0, 0, 255)")); + REQUIRE_NOTHROW(rawrbox::SCRIPTING::getLUA().script("local t = Matrix:new()")); - REQUIRE_THROWS(script->getLua().script("local t = Vector6:new(23, 43)")); + REQUIRE_THROWS(rawrbox::SCRIPTING::getLUA().script("local t = Vector6:new(23, 43)")); } SECTION("rawrbox::Scripting::load") { - REQUIRE_THROWS(script->load()); + REQUIRE_THROWS(rawrbox::SCRIPTING::load()); } } diff --git a/ui/include/rawrbox/ui/elements/button.hpp b/ui/include/rawrbox/ui/elements/button.hpp index 2c9c8311..045109af 100644 --- a/ui/include/rawrbox/ui/elements/button.hpp +++ b/ui/include/rawrbox/ui/elements/button.hpp @@ -12,7 +12,7 @@ namespace rawrbox { class UIButton : public rawrbox::UIContainer { rawrbox::Color _backgroundColor = rawrbox::Color::RGBHex(0x36393f); rawrbox::Color _textColor = rawrbox::Color::RGBHex(0xf5f6fa); - rawrbox::Color _textureColor = rawrbox::Colors::White; + rawrbox::Color _textureColor = rawrbox::Colors::White(); std::string _text; rawrbox::Vector2 _textureSize = {12, 12}; diff --git a/ui/include/rawrbox/ui/elements/frame.hpp b/ui/include/rawrbox/ui/elements/frame.hpp index 822a1632..20bbd524 100644 --- a/ui/include/rawrbox/ui/elements/frame.hpp +++ b/ui/include/rawrbox/ui/elements/frame.hpp @@ -13,7 +13,7 @@ namespace rawrbox { float _titleSize = 18.F; std::string _title; - rawrbox::Color _titleColor = rawrbox::Colors::White; + rawrbox::Color _titleColor = rawrbox::Colors::White(); bool _draggable = true; bool _closable = true; diff --git a/ui/include/rawrbox/ui/elements/graph.hpp b/ui/include/rawrbox/ui/elements/graph.hpp index adc33396..14bfe584 100644 --- a/ui/include/rawrbox/ui/elements/graph.hpp +++ b/ui/include/rawrbox/ui/elements/graph.hpp @@ -30,7 +30,7 @@ namespace rawrbox { size_t id = 0; std::string name = ""; size_t smoothSize = 0; - rawrbox::Color color = rawrbox::Colors::White; + rawrbox::Color color = rawrbox::Colors::White(); std::array entries = {0}; std::array smoothed = {0}; @@ -67,9 +67,9 @@ namespace rawrbox { bool _showLegend = false; rawrbox::UIGraphStyle _style = rawrbox::UIGraphStyle::BLOCK; - rawrbox::Color _textLineColor = rawrbox::Colors::Gray; - rawrbox::Color _textColor = rawrbox::Colors::White; - rawrbox::Color _textShadowColor = rawrbox::Colors::Black; + rawrbox::Color _textLineColor = rawrbox::Colors::Gray(); + rawrbox::Color _textColor = rawrbox::Colors::White(); + rawrbox::Color _textShadowColor = rawrbox::Colors::Black(); rawrbox::Vector2f _textShadow = {1, 1}; // RESOURCES --- diff --git a/ui/include/rawrbox/ui/elements/image.hpp b/ui/include/rawrbox/ui/elements/image.hpp index d81ee1c8..ea3d4317 100644 --- a/ui/include/rawrbox/ui/elements/image.hpp +++ b/ui/include/rawrbox/ui/elements/image.hpp @@ -10,7 +10,7 @@ namespace rawrbox { protected: rawrbox::TextureBase* _texture = nullptr; - rawrbox::Color _color = rawrbox::Colors::White; + rawrbox::Color _color = rawrbox::Colors::White(); bool _isAnimated = false; public: diff --git a/ui/include/rawrbox/ui/elements/input.hpp b/ui/include/rawrbox/ui/elements/input.hpp index 68effc5c..bc8acc23 100644 --- a/ui/include/rawrbox/ui/elements/input.hpp +++ b/ui/include/rawrbox/ui/elements/input.hpp @@ -11,8 +11,8 @@ namespace rawrbox { class UIInput : public rawrbox::UIContainer { rawrbox::Color _backgroundColor = {0.15F, 0.15F, 0.15F, 1.F}; - rawrbox::Color _border = rawrbox::Colors::Transparent; - rawrbox::Color _textColor = rawrbox::Colors::White; + rawrbox::Color _border = rawrbox::Colors::Transparent(); + rawrbox::Color _textColor = rawrbox::Colors::White(); // RESOURCES --- rawrbox::Font* _font = nullptr; diff --git a/ui/include/rawrbox/ui/elements/label.hpp b/ui/include/rawrbox/ui/elements/label.hpp index 7e731299..141690c6 100644 --- a/ui/include/rawrbox/ui/elements/label.hpp +++ b/ui/include/rawrbox/ui/elements/label.hpp @@ -8,8 +8,8 @@ namespace rawrbox { class UILabel : public rawrbox::UIContainer { - rawrbox::Color _color = rawrbox::Colors::White; - rawrbox::Color _shadowColor = rawrbox::Colors::Transparent; + rawrbox::Color _color = rawrbox::Colors::White(); + rawrbox::Color _shadowColor = rawrbox::Colors::Transparent(); // RESOURCES --- rawrbox::Font* _font = nullptr; diff --git a/ui/include/rawrbox/ui/elements/virtual_list.hpp b/ui/include/rawrbox/ui/elements/virtual_list.hpp index aeaec490..a30a94e5 100644 --- a/ui/include/rawrbox/ui/elements/virtual_list.hpp +++ b/ui/include/rawrbox/ui/elements/virtual_list.hpp @@ -22,7 +22,7 @@ namespace rawrbox { int maxYOffset = 0; // ---- - rawrbox::Color backgroundColor = rawrbox::Colors::Transparent; + rawrbox::Color backgroundColor = rawrbox::Colors::Transparent(); public: UIVirtualList() = default; diff --git a/ui/src/elements/frame.cpp b/ui/src/elements/frame.cpp index 9ce1bfb9..5ff2780c 100644 --- a/ui/src/elements/frame.cpp +++ b/ui/src/elements/frame.cpp @@ -19,10 +19,10 @@ namespace rawrbox { this->_closeButton->setSize({30, this->_titleSize - 1}); this->_closeButton->setPos({size.x - 30, -this->_titleSize}); this->_closeButton->setTextureSize({8, 8}); - this->_closeButton->setTextureColor(Colors::Black); + this->_closeButton->setTextureColor(Colors::Black()); this->_closeButton->setEnabled(true); this->_closeButton->setBorder(false); - this->_closeButton->setBackgroundColor(Colors::Transparent); + this->_closeButton->setBackgroundColor(Colors::Transparent()); this->_closeButton->setVisible(this->_closable); this->_closeButton->initialize(); diff --git a/ui/src/elements/graph.cpp b/ui/src/elements/graph.cpp index d761f28d..38e99685 100644 --- a/ui/src/elements/graph.cpp +++ b/ui/src/elements/graph.cpp @@ -149,7 +149,7 @@ namespace rawrbox { auto size = this->getSize(); // BG --- - stencil.drawBox({}, size, rawrbox::Colors::DarkGray * 0.2F); + stencil.drawBox({}, size, rawrbox::Colors::DarkGray() * 0.2F); //--- if (_showLegend) { diff --git a/ui/src/elements/progress_bar.cpp b/ui/src/elements/progress_bar.cpp index 6e6fcaa1..562df804 100644 --- a/ui/src/elements/progress_bar.cpp +++ b/ui/src/elements/progress_bar.cpp @@ -49,7 +49,7 @@ namespace rawrbox { // BORDER-- stencil.pushOutline({1}); - stencil.drawBox({0, 0}, {size.x, size.y}, rawrbox::Colors::Black); + stencil.drawBox({0, 0}, {size.x, size.y}, rawrbox::Colors::Black()); stencil.popOutline(); //---- } diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 6df9ac99..e6612bd8 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -5,6 +5,7 @@ set(output_target RAWRBOX.UTILS) # Grab source files file(GLOB_RECURSE RAWRBOX_UTILS_IMPORTS "src/*.c" "src/*.cpp" "include/*.hpp" "include/*.h") +# LIBS --- if(NOT RAWRBOX_ENABLE_QHULL) list(REMOVE_ITEM RAWRBOX_UTILS_IMPORTS "include/rawrbox/utils/qhull.h") list(REMOVE_ITEM RAWRBOX_UTILS_IMPORTS "tests/qhull.spec.cpp") @@ -63,14 +64,36 @@ else() target_link_libraries(${qhull_STATICR} m) endif(UNIX) - set(EXTRA_UTIL_LIBS ${qhull_STATICR}) + list(APPEND EXTRA_UTIL_LIBS ${qhull_STATICR}) set(EXTRA_UTIL_INCLUDES "${qhull_SOURCE_DIR}/src/libqhull_r") set_lib_runtime_mt(${qhull_STATICR}) endif() endif() -# LIBS --- +if(NOT RAWRBOX_ENABLE_HTTP_REQUEST) + list(REMOVE_ITEM RAWRBOX_UTILS_IMPORTS "include/rawrbox/utils/http.hpp") + list(REMOVE_ITEM RAWRBOX_UTILS_IMPORTS "tests/http.spec.cpp") +else() + SET(CURL_ZLIB OFF CACHE STRING "" FORCE) + CPMAddPackage( + NAME + libcpr + GIT_TAG + 1.10.4 + GITHUB_REPOSITORY + libcpr/cpr + OPTIONS + "BUILD_SHARED_LIBS 0" + "CPR_ENABLE_SSL 1" + "CPR_ENABLE_CURL_HTTP_ONLY 1" + "CURL_ZLIB 0") + + list(APPEND EXTRA_UTIL_LIBS cpr::cpr) + set_lib_runtime_mt(libcurl) + set_lib_runtime_mt(cpr) +endif() + CPMAddPackage("gh:bshoshany/thread-pool@3.5.0") if(thread-pool_ADDED) add_library(thread-pool INTERFACE IMPORTED) diff --git a/utils/include/rawrbox/utils/http.hpp b/utils/include/rawrbox/utils/http.hpp new file mode 100644 index 00000000..3fce632c --- /dev/null +++ b/utils/include/rawrbox/utils/http.hpp @@ -0,0 +1,21 @@ + +#pragma once + +#include + +#include + +namespace rawrbox { + enum class HTTPMethod { + GET = 0, + POST, + PUT, + ERASE, // because DELETED + OPTIONS + }; + + class HTTP { + public: + static void request(const std::string& url, const HTTPMethod method, const std::map& headers, std::function, std::string)> callback, int timeout = 5000); + }; +} // namespace rawrbox diff --git a/utils/include/rawrbox/utils/string.hpp b/utils/include/rawrbox/utils/string.hpp index fef2480a..7b0ac789 100644 --- a/utils/include/rawrbox/utils/string.hpp +++ b/utils/include/rawrbox/utils/string.hpp @@ -8,6 +8,7 @@ namespace rawrbox { public: static std::string toLower(std::string str); static std::string toUpper(std::string str); + static std::string replace(std::string str, const std::string& find, const std::string& replace); static bool isNumeric(const std::string& str); static std::string extractNumbers(std::string str); diff --git a/utils/include/rawrbox/utils/timer.hpp b/utils/include/rawrbox/utils/timer.hpp index 99a479d2..6da2d146 100644 --- a/utils/include/rawrbox/utils/timer.hpp +++ b/utils/include/rawrbox/utils/timer.hpp @@ -8,7 +8,7 @@ namespace rawrbox { class Timer { protected: - uint32_t _id = 0; + std::string _id = ""; uint64_t _nextTick = 0; uint64_t _msDelay = 0; @@ -23,20 +23,27 @@ namespace rawrbox { bool _paused = false; bool _infinite = false; + static rawrbox::Timer* init(const std::string& id, int reps, uint64_t msDelay, std::function func, std::function onComplete = nullptr); + public: static uint32_t ID; - static std::unordered_map> timers; + static std::unordered_map> timers; // STATIC ---- static void update(); + + static rawrbox::Timer* simple(const std::string& id, uint64_t msDelay, std::function func, std::function onComplete = nullptr); static rawrbox::Timer* simple(uint64_t msDelay, std::function func, std::function onComplete = nullptr); + static rawrbox::Timer* create(const std::string& id, int reps, uint64_t msDelay, std::function func, std::function onComplete = nullptr); static rawrbox::Timer* create(int reps, uint64_t msDelay, std::function func, std::function onComplete = nullptr); - static bool isRunning(uint32_t id); + + static bool destroy(const std::string& id); + static bool pause(const std::string& id, bool pause); + static bool exists(const std::string& id); static void clear(); // ---- - void stop(); - void start(); - void setPaused(bool pause); + void destroy(); + void pause(bool pause); }; } // namespace rawrbox diff --git a/utils/src/http.cpp b/utils/src/http.cpp new file mode 100644 index 00000000..a3eda42a --- /dev/null +++ b/utils/src/http.cpp @@ -0,0 +1,58 @@ +#include + +namespace rawrbox { + void HTTP::request(const std::string& url, const rawrbox::HTTPMethod method, const std::map& headers, std::function, std::string)> callback, int timeout) { + if (callback == nullptr) throw std::runtime_error("[RawrBox-HTTP] Invalid callback"); + + cpr::Header header = {}; + + cpr::UserAgent agent = "RawrBox/1.0 (Tabby) Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36"; + cpr::Timeout time = timeout; + + // Setup headers --- + for (auto& h : headers) { + header.emplace(h); + } + // ---- + + // Setup callback --- + auto cb = [callback](cpr::Response r) { + std::map headerResp = {}; + for (auto& h : r.header) { + headerResp[h.first] = h.second; + } + + if (r.error.code != cpr::ErrorCode::OK) { + callback(r.status_code, headerResp, r.error.message); + } else { + callback(r.status_code, headerResp, r.text); + } + + return r.text; + }; + // ---- + + switch (method) { + case HTTPMethod::GET: + cpr::GetCallback(cb, + cpr::Url{url}, header, agent, time); + break; + case HTTPMethod::POST: + cpr::PostCallback(cb, + cpr::Url{url}, header, agent, time); + break; + case HTTPMethod::PUT: + cpr::PutCallback(cb, + cpr::Url{url}, header, agent, time); + break; + case HTTPMethod::ERASE: + cpr::DeleteCallback(cb, + cpr::Url{url}, header, agent, time); + break; + case HTTPMethod::OPTIONS: + cpr::OptionsCallback(cb, + cpr::Url{url}, header, agent, time); + break; + }; + } +}; // namespace rawrbox diff --git a/utils/src/string.cpp b/utils/src/string.cpp index 5298ad4a..5f32c8ae 100644 --- a/utils/src/string.cpp +++ b/utils/src/string.cpp @@ -15,6 +15,16 @@ namespace rawrbox { return str; } + std::string StrUtils::replace(std::string str, const std::string& find, const std::string& replace) { + if (str.empty()) return str; + + auto fnd = str.find(find); + if (fnd == std::string::npos) return str; + + str.replace(fnd, find.size(), replace); + return str; + } + bool StrUtils::isNumeric(const std::string& str) { std::string::const_iterator it = str.begin(); diff --git a/utils/src/timer.cpp b/utils/src/timer.cpp index 0484be49..fa935ef6 100644 --- a/utils/src/timer.cpp +++ b/utils/src/timer.cpp @@ -3,7 +3,7 @@ namespace rawrbox { uint32_t Timer::ID = 0; - std::unordered_map> Timer::timers = {}; + std::unordered_map> Timer::timers = {}; // STATIC ----- void Timer::update() { @@ -38,28 +38,57 @@ namespace rawrbox { } } + rawrbox::Timer* Timer::simple(const std::string& id, uint64_t msDelay, std::function func, std::function onComplete) { + return create(id, 1, msDelay, func, onComplete); + } + rawrbox::Timer* Timer::simple(uint64_t msDelay, std::function func, std::function onComplete) { return create(1, msDelay, func, onComplete); } + rawrbox::Timer* Timer::create(const std::string& id, int reps, uint64_t msDelay, std::function func, std::function onComplete) { + return init(id, reps, msDelay, func, onComplete); + } + rawrbox::Timer* Timer::create(int reps, uint64_t msDelay, std::function func, std::function onComplete) { - auto t = std::make_unique(); - auto id = ID++; + return init("", reps, msDelay, func, onComplete); + } + + rawrbox::Timer* Timer::init(const std::string& id, int reps, uint64_t msDelay, std::function func, std::function onComplete) { + std::string _id = id.empty() ? std::to_string(++ID) : id; + if (exists(_id)) return nullptr; + auto t = std::make_unique(); t->_msDelay = msDelay; t->_func = func; t->_onComplete = onComplete; t->_iterations = reps; t->_ticks = 0; - t->_id = id; + t->_id = _id; t->_infinite = reps <= 0; t->_nextTick = rawrbox::TimeUtils::time() + t->_msDelay; - timers[id] = std::move(t); - return timers[id].get(); + timers[_id] = std::move(t); + return timers[_id].get(); + } + + bool Timer::destroy(const std::string& id) { + auto fnd = timers.find(id); + if (fnd == timers.end()) return false; + + timers.erase(fnd); + return true; + } + + bool Timer::pause(const std::string& id, bool pause) { + auto fnd = timers.find(id); + if (fnd == timers.end()) return false; + fnd->second->pause(pause); + + return true; } - bool Timer::isRunning(uint32_t id) { + bool Timer::exists(const std::string& id) { return timers.find(id) != timers.end(); } @@ -68,24 +97,14 @@ namespace rawrbox { ID = 0; } // ----------- - - void Timer::start() { - if (isRunning(this->_id)) return; - - this->_ticks = 0; // Reset timer - this->_nextTick = rawrbox::TimeUtils::time() + this->_msDelay; - - this->setPaused(false); - } - - void Timer::stop() { + void Timer::destroy() { auto fnd = timers.find(this->_id); if (fnd == timers.end()) return; timers.erase(fnd); } - void Timer::setPaused(bool pause) { + void Timer::pause(bool pause) { this->_paused = pause; if (pause) { diff --git a/utils/tests/string.spec.cpp b/utils/tests/string.spec.cpp index 69fad859..6ccbae27 100644 --- a/utils/tests/string.spec.cpp +++ b/utils/tests/string.spec.cpp @@ -21,6 +21,11 @@ TEST_CASE("StrUtils should behave as expected", "[rawrbox::StrUtils]") { REQUIRE(rawrbox::StrUtils::extractNumbers("A3B4") == "34"); } + SECTION("rawrbox::StrUtils::replace") { + REQUIRE(rawrbox::StrUtils::replace("AVI STOP PLAYING BAD GAMES", "AVI", "BROM") == "BROM STOP PLAYING BAD GAMES"); + REQUIRE(rawrbox::StrUtils::replace("AVI STOP PLAYING BAD GAMES", "NYA", "BROM") == "AVI STOP PLAYING BAD GAMES"); + } + SECTION("rawrbox::StrUtils::split") { auto spl = rawrbox::StrUtils::split("a|bC|C", '|'); auto spl2 = rawrbox::StrUtils::split("abc", '|'); diff --git a/webm/CMakeLists.txt b/webm/CMakeLists.txt index febdb914..8956bef9 100644 --- a/webm/CMakeLists.txt +++ b/webm/CMakeLists.txt @@ -25,6 +25,7 @@ if(libwebm_ADDED) # Add codec set(VPX_VERSION v1.13.0) + set(VPX_MSC_VERSION 17) if(RAWRBOX_BUILD_MSVC_MULTITHREADED_RUNTIME) set(VPX_STATIC_MULTITHREADED ON) endif() @@ -46,14 +47,8 @@ file(GLOB_RECURSE RAWRBOX_WEBM_IMPORTS "src/*.cpp" "include/*.hpp") if(RAWRBOX_BUILD_RAWRBOX_RESOURCES) set(RAWRBOX_EXTRA_LIBS RAWRBOX.RESOURCES) else() - if(NOT RAWRBOX_BUILD_RAWRBOX_RESOURCES) - foreach(TMP_PATH ${RAWRBOX_WEBM_IMPORTS}) - string(FIND ${TMP_PATH} "/resources/" EXCLUDE_DIR_FOUND) - if(NOT ${EXCLUDE_DIR_FOUND} EQUAL -1) - list(REMOVE_ITEM RAWRBOX_WEBM_IMPORTS ${TMP_PATH}) - endif() - endforeach(TMP_PATH) - endif() + remove_folder("${RAWRBOX_WEBM_IMPORTS}" "/resources/") + set(RAWRBOX_WEBM_IMPORTS "${CLEAN_SOURCES}") endif() # ---- diff --git a/webm/include/rawrbox/webm/texture/webm.hpp b/webm/include/rawrbox/webm/texture/webm.hpp index 3a0ecef0..8c1b4544 100644 --- a/webm/include/rawrbox/webm/texture/webm.hpp +++ b/webm/include/rawrbox/webm/texture/webm.hpp @@ -12,7 +12,7 @@ namespace rawrbox { std::unique_ptr _webm = nullptr; uint32_t _trackId = 0; - int64_t _cooldown = 0; + uint64_t _cooldown = 0; void internalUpdate(); void internalLoad();