From abe2c5bdf8a06ddd0e3f98bf525149b6116efd4b Mon Sep 17 00:00:00 2001 From: cursey Date: Tue, 9 Apr 2024 21:38:03 -0700 Subject: [PATCH] Plugin: Don't cleanup global resources @ exit --- .github/workflows/cmake.yml | 9 +- .gitignore | 4 +- CMakeLists.txt | 152 +++---------- cmake.toml | 29 --- cmake/CPM.cmake | 24 ++ cmkr.cmake | 222 ------------------- deps/reframework/include/reframework/API.h | 142 ++++++++---- deps/reframework/include/reframework/API.hpp | 92 +++++++- src/D2DFont.cpp | 2 +- src/D2DPainter.cpp | 2 +- src/Plugin.cpp | 186 +++++++++------- vcpkg.json | 13 -- 12 files changed, 345 insertions(+), 532 deletions(-) delete mode 100644 cmake.toml create mode 100644 cmake/CPM.cmake delete mode 100644 cmkr.cmake delete mode 100644 vcpkg.json diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 060f8ea..efc3953 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4.1.1 - name: Configure CMake run: cmake -S ${{github.workspace}} -B ${{github.workspace}}/build -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} @@ -25,22 +25,21 @@ jobs: run: cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --prefix ${{github.workspace}}/install - name: Upload artifacts - uses: actions/upload-artifact@v2.3.1 + uses: actions/upload-artifact@v4.3.1 with: name: REFramework-D2D path: ${{github.workspace}}/install/bin/* if-no-files-found: error - name: Compress artifacts - uses: vimtor/action-zip@v1 + uses: vimtor/action-zip@v1.2 with: files: install/bin/ dest: REFramework-D2D.zip - name: Release - uses: softprops/action-gh-release@v0.1.14 + uses: softprops/action-gh-release@v2.0.4 if: ${{startsWith(github.ref, 'refs/tags/')}} with: - prerelease: ${{!startsWith(github.ref, 'refs/tags/v') || contains(github.ref, '-pre')}} files: ${{github.workspace}}/REFramework-D2D.zip diff --git a/.gitignore b/.gitignore index 17ff28b..76d76de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ build/ install/ -.vscode/ \ No newline at end of file +.vscode/ +.vs/ +out/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 4370f15..50b25ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,131 +1,39 @@ -# This file is automatically generated from cmake.toml - DO NOT EDIT -# See https://github.com/build-cpp/cmkr for more information - -cmake_minimum_required(VERSION 3.15) - -if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) - message(FATAL_ERROR "In-tree builds are not supported. Run CMake from a separate directory: cmake -B build") -endif() - -# Regenerate CMakeLists.txt automatically in the root project -set(CMKR_ROOT_PROJECT OFF) -if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - set(CMKR_ROOT_PROJECT ON) - - # Bootstrap cmkr - include(cmkr.cmake OPTIONAL RESULT_VARIABLE CMKR_INCLUDE_RESULT) - if(CMKR_INCLUDE_RESULT) - cmkr() - endif() - - # Enable folder support - set_property(GLOBAL PROPERTY USE_FOLDERS ON) -endif() - -# Create a configure-time dependency on cmake.toml to improve IDE support -if(CMKR_ROOT_PROJECT) - configure_file(cmake.toml cmake.toml COPYONLY) -endif() - +cmake_minimum_required(VERSION 3.25) project(reframework-d2d) - -set(VCPKG_TARGET_TRIPLET x64-windows-static) - -if(CMKR_ROOT_PROJECT AND NOT CMKR_DISABLE_VCPKG) - include(FetchContent) - message(STATUS "Fetching vcpkg...") - FetchContent_Declare(vcpkg URL "https://github.com/microsoft/vcpkg/archive/refs/tags/2022.06.15.tar.gz") - FetchContent_MakeAvailable(vcpkg) - include("${vcpkg_SOURCE_DIR}/scripts/buildsystems/vcpkg.cmake") -endif() - -# Packages -find_package(sol2 REQUIRED CONFIG) - -find_package(Lua REQUIRED) - -find_package(utf8cpp REQUIRED CONFIG) - -# Target reframework -set(CMKR_TARGET reframework) -set(reframework_SOURCES "") - -set(CMKR_SOURCES ${reframework_SOURCES}) -add_library(reframework INTERFACE) - -if(reframework_SOURCES) - target_sources(reframework INTERFACE ${reframework_SOURCES}) -endif() - -target_include_directories(reframework INTERFACE - "deps/reframework/include" -) - -unset(CMKR_TARGET) -unset(CMKR_SOURCES) - -# Target reframework-d2d -set(CMKR_TARGET reframework-d2d) -set(reframework-d2d_SOURCES "") - -list(APPEND reframework-d2d_SOURCES - "src/D2DFont.cpp" - "src/D2DImage.cpp" - "src/D2DPainter.cpp" - "src/D3D12Renderer.cpp" - "src/DrawList.cpp" - "src/Plugin.cpp" - "src/D2DFont.hpp" - "src/D2DImage.hpp" - "src/D2DPainter.hpp" - "src/D3D12Renderer.hpp" - "src/D3D12Shaders.hpp" - "src/DrawList.hpp" - "src/LruCache.hpp" +include (cmake/CPM.cmake) + +CPMAddPackage("gh:nemtrif/utfcpp@4.0.5") +CPMAddPackage("gh:ThePhD/sol2@3.3.0") +CPMAddPackage( + NAME lua + GITHUB_REPOSITORY lua/lua + VERSION 5.4.6 + DOWNLOAD_ONLY YES ) -list(APPEND reframework-d2d_SOURCES - cmake.toml -) - -set(CMKR_SOURCES ${reframework-d2d_SOURCES}) -add_library(reframework-d2d SHARED) +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" "${lua_SOURCE_DIR}/onelua.c") + add_library(lua STATIC ${lua_sources}) -if(reframework-d2d_SOURCES) - target_sources(reframework-d2d PRIVATE ${reframework-d2d_SOURCES}) + target_include_directories(lua + PUBLIC + $ + ) endif() -source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${reframework-d2d_SOURCES}) - -target_compile_features(reframework-d2d PUBLIC - cxx_std_20 -) - -target_include_directories(reframework-d2d PUBLIC - ${LUA_INCLUDE_DIR} -) -target_link_libraries(reframework-d2d PUBLIC - sol2::sol2 - ${LUA_LIBRARIES} - utf8cpp - reframework - d2d1 - dwrite - d3d11 - d3d12 - dxgi - d3dcompiler +add_library(reframework-d2d SHARED + src/D2DFont.cpp + src/D2DImage.cpp + src/D2DPainter.cpp + src/D3D12Renderer.cpp + src/DrawList.cpp + src/Plugin.cpp ) - -unset(CMKR_TARGET) -unset(CMKR_SOURCES) - -install( - TARGETS - reframework-d2d - DESTINATION - bin - COMPONENT - reframework-d2d +target_include_directories(reframework-d2d PRIVATE + src + deps/reframework/include ) +target_compile_features(reframework-d2d PRIVATE cxx_std_20) +target_link_libraries(reframework-d2d PRIVATE utf8cpp sol2::sol2 lua d2d1 dwrite d3d11 d3d12 dxgi d3dcompiler) diff --git a/cmake.toml b/cmake.toml deleted file mode 100644 index 7bc65d8..0000000 --- a/cmake.toml +++ /dev/null @@ -1,29 +0,0 @@ -# Reference: https://build-cpp.github.io/cmkr/cmake-toml -[project] -name = "reframework-d2d" -cmake-after = "set(VCPKG_TARGET_TRIPLET x64-windows-static)" - -[vcpkg] -version = "2022.06.15" -packages = ["sol2", "lua", "utfcpp"] - -[find-package] -sol2 = { required = true, config = true } -Lua = { required = true } -utf8cpp = { required = true, config = true } - -[target.reframework] -type = "interface" -include-directories = ["deps/reframework/include"] - -[target.reframework-d2d] -type = "shared" -sources = ["src/**.cpp"] -headers = ["src/**.hpp"] -include-directories = ["${LUA_INCLUDE_DIR}"] -link-libraries = ["sol2::sol2", "${LUA_LIBRARIES}", "utf8cpp", "reframework", "d2d1", "dwrite", "d3d11", "d3d12", "dxgi", "d3dcompiler"] -compile-features = ["cxx_std_20"] - -[[install]] -targets = ["reframework-d2d"] -destination = "bin" diff --git a/cmake/CPM.cmake b/cmake/CPM.cmake new file mode 100644 index 0000000..d0fd0e8 --- /dev/null +++ b/cmake/CPM.cmake @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: MIT +# +# SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors + +set(CPM_DOWNLOAD_VERSION 0.39.0) +set(CPM_HASH_SUM "66639bcac9dd2907b2918de466783554c1334446b9874e90d38e3778d404c2ef") + +if(CPM_SOURCE_CACHE) + set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +elseif(DEFINED ENV{CPM_SOURCE_CACHE}) + set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +else() + set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") +endif() + +# Expand relative path. This is important if the provided path contains a tilde (~) +get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) + +file(DOWNLOAD + https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake + ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM} +) + +include(${CPM_DOWNLOAD_LOCATION}) diff --git a/cmkr.cmake b/cmkr.cmake deleted file mode 100644 index 1ed1435..0000000 --- a/cmkr.cmake +++ /dev/null @@ -1,222 +0,0 @@ -include_guard() - -# Change these defaults to point to your infrastructure if desired -set(CMKR_REPO "https://github.com/build-cpp/cmkr" CACHE STRING "cmkr git repository" FORCE) -set(CMKR_TAG "v0.2.7" CACHE STRING "cmkr git tag (this needs to be available forever)" FORCE) - -# To bootstrap/generate a cmkr project: cmake -P cmkr.cmake -if(CMAKE_SCRIPT_MODE_FILE) - set(CMAKE_BINARY_DIR "${CMAKE_BINARY_DIR}/build") - set(CMAKE_CURRENT_BINARY_DIR "${CMAKE_BINARY_DIR}") - file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}") -endif() - -# Set these from the command line to customize for development/debugging purposes -set(CMKR_EXECUTABLE "" CACHE FILEPATH "cmkr executable") -set(CMKR_SKIP_GENERATION OFF CACHE BOOL "skip automatic cmkr generation") -set(CMKR_BUILD_TYPE "Debug" CACHE STRING "cmkr build configuration") - -# Disable cmkr if generation is disabled -if(DEFINED ENV{CI} OR CMKR_SKIP_GENERATION OR CMKR_BUILD_SKIP_GENERATION) - message(STATUS "[cmkr] Skipping automatic cmkr generation") - unset(CMKR_BUILD_SKIP_GENERATION CACHE) - macro(cmkr) - endmacro() - return() -endif() - -# Disable cmkr if no cmake.toml file is found -if(NOT CMAKE_SCRIPT_MODE_FILE AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") - message(AUTHOR_WARNING "[cmkr] Not found: ${CMAKE_CURRENT_SOURCE_DIR}/cmake.toml") - macro(cmkr) - endmacro() - return() -endif() - -# Convert a Windows native path to CMake path -if(CMKR_EXECUTABLE MATCHES "\\\\") - string(REPLACE "\\" "/" CMKR_EXECUTABLE_CMAKE "${CMKR_EXECUTABLE}") - set(CMKR_EXECUTABLE "${CMKR_EXECUTABLE_CMAKE}" CACHE FILEPATH "" FORCE) - unset(CMKR_EXECUTABLE_CMAKE) -endif() - -# Helper macro to execute a process (COMMAND_ERROR_IS_FATAL ANY is 3.19 and higher) -function(cmkr_exec) - execute_process(COMMAND ${ARGV} RESULT_VARIABLE CMKR_EXEC_RESULT) - if(NOT CMKR_EXEC_RESULT EQUAL 0) - message(FATAL_ERROR "cmkr_exec(${ARGV}) failed (exit code ${CMKR_EXEC_RESULT})") - endif() -endfunction() - -# Windows-specific hack (CMAKE_EXECUTABLE_PREFIX is not set at the moment) -if(WIN32) - set(CMKR_EXECUTABLE_NAME "cmkr.exe") -else() - set(CMKR_EXECUTABLE_NAME "cmkr") -endif() - -# Use cached cmkr if found -if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}") - set(CMKR_DIRECTORY_PREFIX "$ENV{CMKR_CACHE}") - string(REPLACE "\\" "/" CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}") - if(NOT CMKR_DIRECTORY_PREFIX MATCHES "\\/$") - set(CMKR_DIRECTORY_PREFIX "${CMKR_DIRECTORY_PREFIX}/") - endif() -else() - set(CMKR_DIRECTORY_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/_cmkr_") -endif() -set(CMKR_DIRECTORY "${CMKR_DIRECTORY_PREFIX}${CMKR_TAG}") -set(CMKR_CACHED_EXECUTABLE "${CMKR_DIRECTORY}/bin/${CMKR_EXECUTABLE_NAME}") - -# Handle upgrading logic -if(CMKR_EXECUTABLE AND NOT CMKR_CACHED_EXECUTABLE STREQUAL CMKR_EXECUTABLE) - if(CMKR_EXECUTABLE MATCHES "^${CMAKE_CURRENT_BINARY_DIR}/_cmkr") - if(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}") - message(AUTHOR_WARNING "[cmkr] Switching to cached cmkr: '${CMKR_CACHED_EXECUTABLE}'") - if(EXISTS "${CMKR_CACHED_EXECUTABLE}") - set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) - else() - unset(CMKR_EXECUTABLE CACHE) - endif() - else() - message(AUTHOR_WARNING "[cmkr] Upgrading '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") - unset(CMKR_EXECUTABLE CACHE) - endif() - elseif(DEFINED ENV{CMKR_CACHE} AND EXISTS "$ENV{CMKR_CACHE}" AND CMKR_EXECUTABLE MATCHES "^${CMKR_DIRECTORY_PREFIX}") - message(AUTHOR_WARNING "[cmkr] Upgrading cached '${CMKR_EXECUTABLE}' to '${CMKR_CACHED_EXECUTABLE}'") - unset(CMKR_EXECUTABLE CACHE) - endif() -endif() - -if(CMKR_EXECUTABLE AND EXISTS "${CMKR_EXECUTABLE}") - message(VERBOSE "[cmkr] Found cmkr: '${CMKR_EXECUTABLE}'") -elseif(CMKR_EXECUTABLE AND NOT CMKR_EXECUTABLE STREQUAL CMKR_CACHED_EXECUTABLE) - message(FATAL_ERROR "[cmkr] '${CMKR_EXECUTABLE}' not found") -elseif(NOT CMKR_EXECUTABLE AND EXISTS "${CMKR_CACHED_EXECUTABLE}") - set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) - message(STATUS "[cmkr] Found cached cmkr: '${CMKR_EXECUTABLE}'") -else() - set(CMKR_EXECUTABLE "${CMKR_CACHED_EXECUTABLE}" CACHE FILEPATH "Full path to cmkr executable" FORCE) - message(VERBOSE "[cmkr] Bootstrapping '${CMKR_EXECUTABLE}'") - - message(STATUS "[cmkr] Fetching cmkr...") - if(EXISTS "${CMKR_DIRECTORY}") - cmkr_exec("${CMAKE_COMMAND}" -E rm -rf "${CMKR_DIRECTORY}") - endif() - find_package(Git QUIET REQUIRED) - cmkr_exec("${GIT_EXECUTABLE}" - clone - --config advice.detachedHead=false - --branch ${CMKR_TAG} - --depth 1 - ${CMKR_REPO} - "${CMKR_DIRECTORY}" - ) - message(STATUS "[cmkr] Building cmkr (using system compiler)...") - cmkr_exec("${CMAKE_COMMAND}" - --no-warn-unused-cli - "${CMKR_DIRECTORY}" - "-B${CMKR_DIRECTORY}/build" - "-DCMAKE_BUILD_TYPE=${CMKR_BUILD_TYPE}" - "-DCMAKE_UNITY_BUILD=ON" - "-DCMAKE_INSTALL_PREFIX=${CMKR_DIRECTORY}" - "-DCMKR_GENERATE_DOCUMENTATION=OFF" - ) - cmkr_exec("${CMAKE_COMMAND}" - --build "${CMKR_DIRECTORY}/build" - --config "${CMKR_BUILD_TYPE}" - --parallel - ) - cmkr_exec("${CMAKE_COMMAND}" - --install "${CMKR_DIRECTORY}/build" - --config "${CMKR_BUILD_TYPE}" - --prefix "${CMKR_DIRECTORY}" - --component cmkr - ) - if(NOT EXISTS ${CMKR_EXECUTABLE}) - message(FATAL_ERROR "[cmkr] Failed to bootstrap '${CMKR_EXECUTABLE}'") - endif() - cmkr_exec("${CMKR_EXECUTABLE}" version) - message(STATUS "[cmkr] Bootstrapped ${CMKR_EXECUTABLE}") -endif() -execute_process(COMMAND "${CMKR_EXECUTABLE}" version - RESULT_VARIABLE CMKR_EXEC_RESULT -) -if(NOT CMKR_EXEC_RESULT EQUAL 0) - message(FATAL_ERROR "[cmkr] Failed to get version, try clearing the cache and rebuilding") -endif() - -# Use cmkr.cmake as a script -if(CMAKE_SCRIPT_MODE_FILE) - if(NOT EXISTS "${CMAKE_SOURCE_DIR}/cmake.toml") - execute_process(COMMAND "${CMKR_EXECUTABLE}" init - RESULT_VARIABLE CMKR_EXEC_RESULT - ) - if(NOT CMKR_EXEC_RESULT EQUAL 0) - message(FATAL_ERROR "[cmkr] Failed to bootstrap cmkr project. Please report an issue: https://github.com/build-cpp/cmkr/issues/new") - else() - message(STATUS "[cmkr] Modify cmake.toml and then configure using: cmake -B build") - endif() - else() - execute_process(COMMAND "${CMKR_EXECUTABLE}" gen - RESULT_VARIABLE CMKR_EXEC_RESULT - ) - if(NOT CMKR_EXEC_RESULT EQUAL 0) - message(FATAL_ERROR "[cmkr] Failed to generate project.") - else() - message(STATUS "[cmkr] Configure using: cmake -B build") - endif() - endif() -endif() - -# This is the macro that contains black magic -macro(cmkr) - # When this macro is called from the generated file, fake some internal CMake variables - get_source_file_property(CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" CMKR_CURRENT_LIST_FILE) - if(CMKR_CURRENT_LIST_FILE) - set(CMAKE_CURRENT_LIST_FILE "${CMKR_CURRENT_LIST_FILE}") - get_filename_component(CMAKE_CURRENT_LIST_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) - endif() - - # File-based include guard (include_guard is not documented to work) - get_source_file_property(CMKR_INCLUDE_GUARD "${CMAKE_CURRENT_LIST_FILE}" CMKR_INCLUDE_GUARD) - if(NOT CMKR_INCLUDE_GUARD) - set_source_files_properties("${CMAKE_CURRENT_LIST_FILE}" PROPERTIES CMKR_INCLUDE_GUARD TRUE) - - file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_PRE) - - # Generate CMakeLists.txt - cmkr_exec("${CMKR_EXECUTABLE}" gen - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - ) - - file(SHA256 "${CMAKE_CURRENT_LIST_FILE}" CMKR_LIST_FILE_SHA256_POST) - - # Delete the temporary file if it was left for some reason - set(CMKR_TEMP_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CMakerLists.txt") - if(EXISTS "${CMKR_TEMP_FILE}") - file(REMOVE "${CMKR_TEMP_FILE}") - endif() - - if(NOT CMKR_LIST_FILE_SHA256_PRE STREQUAL CMKR_LIST_FILE_SHA256_POST) - # Copy the now-generated CMakeLists.txt to CMakerLists.txt - # This is done because you cannot include() a file you are currently in - configure_file(CMakeLists.txt "${CMKR_TEMP_FILE}" COPYONLY) - - # Add the macro required for the hack at the start of the cmkr macro - set_source_files_properties("${CMKR_TEMP_FILE}" PROPERTIES - CMKR_CURRENT_LIST_FILE "${CMAKE_CURRENT_LIST_FILE}" - ) - - # 'Execute' the newly-generated CMakeLists.txt - include("${CMKR_TEMP_FILE}") - - # Delete the generated file - file(REMOVE "${CMKR_TEMP_FILE}") - - # Do not execute the rest of the original CMakeLists.txt - return() - endif() - # Resume executing the unmodified CMakeLists.txt - endif() -endmacro() diff --git a/deps/reframework/include/reframework/API.h b/deps/reframework/include/reframework/API.h index 1dca65f..afdd193 100644 --- a/deps/reframework/include/reframework/API.h +++ b/deps/reframework/include/reframework/API.h @@ -1,8 +1,13 @@ #ifndef REFRAMEWORK_API_H #define REFRAMEWORK_API_H +#ifndef __cplusplus +#include +#include +#endif + #define REFRAMEWORK_PLUGIN_VERSION_MAJOR 1 -#define REFRAMEWORK_PLUGIN_VERSION_MINOR 0 +#define REFRAMEWORK_PLUGIN_VERSION_MINOR 7 #define REFRAMEWORK_PLUGIN_VERSION_PATCH 0 #define REFRAMEWORK_RENDERER_D3D11 0 @@ -14,29 +19,37 @@ #define REFRAMEWORK_ERROR_EXCEPTION 2 #define REFRAMEWORK_ERROR_IN_ARGS_SIZE_MISMATCH 3 +#define REFRAMEWORK_HOOK_CALL_ORIGINAL 0 +#define REFRAMEWORK_HOOK_SKIP_ORIGINAL 1 + typedef int REFrameworkResult; struct lua_State; typedef void (*REFInitializedCb)(); -typedef void (*REFLuaStateCreatedCb)(lua_State*); -typedef void (*REFLuaStateDestroyedCb)(lua_State*); -typedef void (*REFOnFrameCb)(); +typedef void (*REFLuaStateCreatedCb)(struct lua_State*); +typedef void (*REFLuaStateDestroyedCb)(struct lua_State*); +typedef void (*REFOnPresentCb)(); typedef void (*REFOnPreApplicationEntryCb)(); typedef void (*REFOnPostApplicationEntryCb)(); typedef void (*REFOnDeviceResetCb)(); typedef bool (*REFOnMessageCb)(void*, unsigned int, unsigned long long, long long); +typedef struct lua_State* (*REFCreateScriptState)(); +typedef void (*REFDeleteScriptState)(struct lua_State*); + typedef bool (*REFOnInitializeFn)(REFInitializedCb); typedef bool (*REFOnLuaStateCreatedFn)(REFLuaStateCreatedCb); typedef bool (*REFOnLuaStateDestroyedFn)(REFLuaStateDestroyedCb); -typedef bool (*REFOnFrameFn)(REFOnFrameCb); +typedef bool (*REFOnPresentFn)(REFOnPresentCb); typedef bool (*REFOnPreApplicationEntryFn)(const char*, REFOnPreApplicationEntryCb); typedef bool (*REFOnPostApplicationEntryFn)(const char*, REFOnPostApplicationEntryCb); typedef void (*REFLuaLockUnlockFn)(); typedef bool (*REFOnDeviceResetFn)(REFOnDeviceResetCb); typedef bool (*REFOnMessageFn)(REFOnMessageCb); + + typedef struct { int major; int minor; @@ -49,7 +62,7 @@ typedef void (*REFPluginRequiredVersionFn)(REFrameworkPluginVersion*); typedef struct { REFOnLuaStateCreatedFn on_lua_state_created; REFOnLuaStateDestroyedFn on_lua_state_destroyed; - REFOnFrameFn on_frame; + REFOnPresentFn on_present; REFOnPreApplicationEntryFn on_pre_application_entry; REFOnPostApplicationEntryFn on_post_application_entry; REFLuaLockUnlockFn lock_lua; @@ -59,6 +72,9 @@ typedef struct { void (*log_error)(const char* format, ...); void (*log_warn)(const char* format, ...); void (*log_info)(const char* format, ...); + bool (*is_drawing_ui)(); + REFCreateScriptState create_script_state; + REFDeleteScriptState delete_script_state; } REFrameworkPluginFunctions; typedef struct { @@ -68,7 +84,7 @@ typedef struct { void* command_queue; } REFrameworkRendererData; -// strong typedefs +/* strong typedefs */ #define DECLARE_REFRAMEWORK_HANDLE(name) struct name##__ { int unused; }; \ typedef struct name##__ *name @@ -78,10 +94,13 @@ DECLARE_REFRAMEWORK_HANDLE(REFrameworkFieldHandle); DECLARE_REFRAMEWORK_HANDLE(REFrameworkPropertyHandle); DECLARE_REFRAMEWORK_HANDLE(REFrameworkManagedObjectHandle); DECLARE_REFRAMEWORK_HANDLE(REFrameworkTDBHandle); +DECLARE_REFRAMEWORK_HANDLE(REFrameworkHandle); DECLARE_REFRAMEWORK_HANDLE(REFrameworkResourceHandle); DECLARE_REFRAMEWORK_HANDLE(REFrameworkResourceManagerHandle); DECLARE_REFRAMEWORK_HANDLE(REFrameworkVMContextHandle); -DECLARE_REFRAMEWORK_HANDLE(REFrameworkTypeInfoHandle); // NOT a type definition +DECLARE_REFRAMEWORK_HANDLE(REFrameworkTypeInfoHandle); /* NOT a type definition */ +DECLARE_REFRAMEWORK_HANDLE(REFrameworkReflectionPropertyHandle); /* NOT a TDB property */ +DECLARE_REFRAMEWORK_HANDLE(REFrameworkReflectionMethodHandle); /* NOT a TDB method */ #define REFRAMEWORK_CREATE_INSTANCE_FLAGS_NONE 0 #define REFRAMEWORK_CREATE_INSTANCE_FLAGS_SIMPLIFY 1 @@ -93,7 +112,19 @@ DECLARE_REFRAMEWORK_HANDLE(REFrameworkTypeInfoHandle); // NOT a type definition #define REFRAMEWORK_VM_OBJ_TYPE_DELEGATE 4 #define REFRAMEWORK_VM_OBJ_TYPE_VALTYPE 5 +/* +struct StackFrame { + char pad_0000[8+8]; 0x0000 + const sdk::REMethodDefinition* method; + char pad_0010[24]; 0x0018 + void* in_data; 0x0030 can point to data + void* out_data; 0x0038 can be whatever, can be a dword, can point to data + void* object_ptr; 0x0040 aka "this" pointer +};*/ + typedef unsigned int REFrameworkVMObjType; +typedef void (*REFrameworkInvokeMethod)(void* stack_frame, void* context); +typedef void* (*REFrameworkReflectionPropertyMethod)(REFrameworkReflectionPropertyHandle prop, REFrameworkManagedObjectHandle thisptr, void* out_data); typedef struct { unsigned int (*get_index)(REFrameworkTypeDefinitionHandle); @@ -122,19 +153,19 @@ typedef struct { REFrameworkVMObjType (*get_vm_obj_type)(REFrameworkTypeDefinitionHandle); - // All lookups are cached on our end - // however, the pointers will always stay the same, - // so you can cache them on your end e.g. with a static var to get a minor speed increase. + /* All lookups are cached on our end */ + /* however, the pointers will always stay the same, */ + /* so you can cache them on your end e.g. with a static var to get a minor speed increase. */ REFrameworkMethodHandle (*find_method)(REFrameworkTypeDefinitionHandle, const char*); REFrameworkFieldHandle (*find_field)(REFrameworkTypeDefinitionHandle, const char*); - REFrameworkPropertyHandle (*find_property)(REFrameworkTypeDefinitionHandle, const char*); // not implemented yet. + REFrameworkPropertyHandle (*find_property)(REFrameworkTypeDefinitionHandle, const char*); /* not implemented yet. */ - // out_size is the full size, in bytes of the out buffer - // out_len is how many elements were written to the out buffer, not the size of the written data + /* out_size is the full size, in bytes of the out buffer */ + /* out_len is how many elements were written to the out buffer, not the size of the written data */ REFrameworkResult (*get_methods)(REFrameworkTypeDefinitionHandle, REFrameworkMethodHandle* out, unsigned int out_size, unsigned int* out_count); REFrameworkResult (*get_fields)(REFrameworkTypeDefinitionHandle, REFrameworkFieldHandle* out, unsigned int out_size, unsigned int* out_count); - // get_instance usually only used for native singletons + /* get_instance usually only used for native singletons */ void* (*get_instance)(REFrameworkTypeDefinitionHandle); void* (*create_instance_deprecated)(REFrameworkTypeDefinitionHandle); REFrameworkManagedObjectHandle (*create_instance)(REFrameworkTypeDefinitionHandle, unsigned int flags); @@ -144,6 +175,7 @@ typedef struct { REFrameworkTypeDefinitionHandle (*get_underlying_type)(REFrameworkTypeDefinitionHandle); REFrameworkTypeInfoHandle (*get_type_info)(REFrameworkTypeDefinitionHandle); + REFrameworkManagedObjectHandle (*get_runtime_type)(REFrameworkTypeDefinitionHandle); } REFrameworkTDBTypeDefinition; /* @@ -171,11 +203,9 @@ typedef struct { unsigned long long reserved; } REFrameworkMethodParameter; -typedef void* (*REFGenericFunction)(...); - typedef struct { - // make sure out size is at least size of InvokeRet - // each arg is always 8 bytes, even if it's something like a byte + /* make sure out size is at least size of InvokeRet */ + /* each arg is always 8 bytes, even if it's something like a byte */ REFrameworkResult (*invoke)(REFrameworkMethodHandle, void* thisptr, void** in_args, unsigned int in_args_size, void* out, unsigned int out_size); void* (*get_function)(REFrameworkMethodHandle); const char* (*get_name)(REFrameworkMethodHandle); @@ -184,8 +214,8 @@ typedef struct { unsigned int (*get_num_params)(REFrameworkMethodHandle); - // out_size is the full size, in bytes of the out buffer - // out_count is how many elements were written to the out buffer, not the size of the written data + /* out_size is the full size, in bytes of the out buffer */ + /* out_count is how many elements were written to the out buffer, not the size of the written data */ REFrameworkResult (*get_params)(REFrameworkMethodHandle, REFrameworkMethodParameter* out, unsigned int out_size, unsigned int* out_len); unsigned int (*get_index)(REFrameworkMethodHandle); @@ -214,7 +244,7 @@ typedef struct { } REFrameworkTDBField; typedef struct { - // todo + /* todo */ } REFrameworkTDBProperty; typedef struct { @@ -227,9 +257,9 @@ typedef struct { const char* (*get_string_database)(REFrameworkTDBHandle); unsigned char* (*get_raw_database)(REFrameworkTDBHandle); - // All lookups are cached on our end - // however, the pointers will always stay the same, - // so you can cache them on your end e.g. with a static var to get a minor speed increase. + /* All lookups are cached on our end */ + /* however, the pointers will always stay the same, */ + /* so you can cache them on your end e.g. with a static var to get a minor speed increase. */ REFrameworkTypeDefinitionHandle (*get_type)(REFrameworkTDBHandle, unsigned int index); REFrameworkTypeDefinitionHandle (*find_type)(REFrameworkTDBHandle, const char* name); REFrameworkTypeDefinitionHandle (*find_type_by_fqn)(REFrameworkTDBHandle, unsigned int fqn); @@ -248,17 +278,17 @@ typedef struct { unsigned int (*get_ref_count)(REFrameworkManagedObjectHandle); unsigned int (*get_size)(REFrameworkManagedObjectHandle); unsigned int (*get_vm_obj_type)(REFrameworkManagedObjectHandle); - REFrameworkTypeInfoHandle (*get_type_info)(REFrameworkManagedObjectHandle); // NOT a type definition + REFrameworkTypeInfoHandle (*get_type_info)(REFrameworkManagedObjectHandle); /* NOT a type definition */ void* (*get_reflection_properties)(REFrameworkManagedObjectHandle); - void* (*get_reflection_property_descriptor)(REFrameworkManagedObjectHandle, const char* name); - void* (*get_reflection_method_descriptor)(REFrameworkManagedObjectHandle, const char* name); + REFrameworkReflectionPropertyHandle (*get_reflection_property_descriptor)(REFrameworkManagedObjectHandle, const char* name); + REFrameworkReflectionMethodHandle (*get_reflection_method_descriptor)(REFrameworkManagedObjectHandle, const char* name); } REFrameworkManagedObject; typedef struct { void* instance; REFrameworkTypeDefinitionHandle t; REFrameworkTypeInfoHandle type_info; - const char* name; // t is not guaranteed to be non-null so we pass the name along too + const char* name; /* t is not guaranteed to be non-null so we pass the name along too */ } REFrameworkNativeSingleton; typedef struct { @@ -268,16 +298,18 @@ typedef struct { } REFrameworkManagedSingleton; typedef struct { - // resource type, and then the path to the resource in the PAK + /* resource type, and then the path to the resource in the PAK */ REFrameworkResourceHandle (*create_resource)(REFrameworkResourceManagerHandle, const char* type_name, const char* name); + REFrameworkManagedObjectHandle (*create_userdata)(REFrameworkResourceManagerHandle, const char* type_name, const char* name); } REFrameworkResourceManager; typedef struct { void (*add_ref)(REFrameworkResourceHandle); void (*release)(REFrameworkResourceHandle); + REFrameworkManagedObjectHandle (*create_holder)(REFrameworkResourceHandle, const char* type_name); } REFrameworkResource; -// NOT a type definition +/* NOT a type definition */ typedef struct { const char* (*get_name)(REFrameworkTypeInfoHandle); REFrameworkTypeDefinitionHandle (*get_type_definition)(REFrameworkTypeInfoHandle); @@ -286,8 +318,11 @@ typedef struct { void* (*get_singleton_instance)(REFrameworkTypeInfoHandle); void* (*create_instance)(REFrameworkTypeInfoHandle); void* (*get_reflection_properties)(REFrameworkTypeInfoHandle); - void* (*get_reflection_property_descriptor)(REFrameworkTypeInfoHandle, const char* name); - void* (*get_reflection_method_descriptor)(REFrameworkTypeInfoHandle, const char* name); + REFrameworkReflectionPropertyHandle (*get_reflection_property_descriptor)(REFrameworkTypeInfoHandle, const char* name); + REFrameworkReflectionMethodHandle (*get_reflection_method_descriptor)(REFrameworkTypeInfoHandle, const char* name); + void* (*get_deserializer_fn)(REFrameworkTypeInfoHandle); + REFrameworkTypeInfoHandle (*get_parent)(REFrameworkTypeInfoHandle); + unsigned int (*get_crc)(REFrameworkTypeInfoHandle); } REFrameworkTypeInfo; typedef struct { @@ -297,27 +332,48 @@ typedef struct { void (*cleanup_after_exception)(REFrameworkVMContextHandle, int old_reference_count); } REFrameworkVMContext; +/* NOT a TDB method */ +typedef struct { + REFrameworkInvokeMethod (*get_function)(REFrameworkReflectionMethodHandle); +} REFrameworkReflectionMethod; + +/* NOT a TDB property */ +typedef struct { + REFrameworkReflectionPropertyMethod (*get_getter)(REFrameworkReflectionPropertyHandle); + bool (*is_static)(REFrameworkReflectionPropertyHandle); + unsigned int (*get_size)(REFrameworkReflectionPropertyHandle); +} REFrameworkReflectionProperty; + +typedef int (*REFPreHookFn)(int argc, void** argv, REFrameworkTypeDefinitionHandle* arg_tys, unsigned long long ret_addr); +typedef void (*REFPostHookFn)(void** ret_val, REFrameworkTypeDefinitionHandle ret_ty, unsigned long long ret_addr); + typedef struct { REFrameworkTDBHandle (*get_tdb)(); REFrameworkResourceManagerHandle (*get_resource_manager)(); - REFrameworkVMContextHandle (*get_vm_context)(); // per-thread context + REFrameworkVMContextHandle (*get_vm_context)(); /* per-thread context */ - REFrameworkManagedObjectHandle (*typeof)(const char* type_name); // System.Type + REFrameworkManagedObjectHandle (*typeof_)(const char* type_name); /* System.Type */ REFrameworkManagedObjectHandle (*get_managed_singleton)(const char* type_name); void* (*get_native_singleton)(const char* type_name); - // out_size is the full size, in bytes of the out buffer - // out_count is how many elements were written to the out buffer, not the size of the written data + /* out_size is the full size, in bytes of the out buffer */ + /* out_count is how many elements were written to the out buffer, not the size of the written data */ REFrameworkResult (*get_managed_singletons)(REFrameworkManagedSingleton* out, unsigned int out_size, unsigned int* out_count); REFrameworkResult (*get_native_singletons)(REFrameworkNativeSingleton* out, unsigned int out_size, unsigned int* out_count); REFrameworkManagedObjectHandle (*create_managed_string)(const wchar_t* str); REFrameworkManagedObjectHandle (*create_managed_string_normal)(const char* str); + + unsigned int (*add_hook)(REFrameworkMethodHandle, REFPreHookFn, REFPostHookFn, bool ignore_jmp); + void (*remove_hook)(REFrameworkMethodHandle, unsigned int); + + void* (*allocate)(unsigned long long size); + void (*deallocate)(void*); } REFrameworkSDKFunctions; -// these are NOT pointers to the actual objects -// they are interfaces with functions that take handles to the objects -// the functions, however, can return the actual objects +/* these are NOT pointers to the actual objects */ +/* they are interfaces with functions that take handles to the objects */ +/* the functions, however, can return the actual objects */ typedef struct { const REFrameworkSDKFunctions* functions; const REFrameworkTDB* tdb; @@ -328,8 +384,10 @@ typedef struct { const REFrameworkManagedObject* managed_object; const REFrameworkResourceManager* resource_manager; const REFrameworkResource* resource; - const REFrameworkTypeInfo* type_info; // NOT a type definition + const REFrameworkTypeInfo* type_info; /* NOT a type definition */ const REFrameworkVMContext* vm_context; + const REFrameworkReflectionMethod* reflection_method; /* NOT a TDB method */ + const REFrameworkReflectionProperty* reflection_property; /* NOT a TDB property */ } REFrameworkSDKData; typedef struct { @@ -342,4 +400,4 @@ typedef struct { typedef bool (*REFPluginInitializeFn)(const REFrameworkPluginInitializeParam*); -#endif \ No newline at end of file +#endif diff --git a/deps/reframework/include/reframework/API.hpp b/deps/reframework/include/reframework/API.hpp index 5196f85..a7df434 100644 --- a/deps/reframework/include/reframework/API.hpp +++ b/deps/reframework/include/reframework/API.hpp @@ -46,6 +46,8 @@ class API { struct Resource; struct TypeInfo; struct VMContext; + struct ReflectionProperty; + struct ReflectionMethod; struct LuaLock { LuaLock() { @@ -96,7 +98,7 @@ class API { return m_param; } - inline const auto sdk() const { + inline const REFrameworkSDKData* sdk() const { return m_sdk; } @@ -108,6 +110,10 @@ class API { return (ResourceManager*)sdk()->functions->get_resource_manager(); } + inline const auto reframework() const { + return (REFramework*)param()->functions; + } + void lock_lua() { m_lua_mtx.lock(); m_param->functions->lock_lua(); @@ -127,7 +133,7 @@ class API { } API::ManagedObject* typeof(const char* name) const { - return (API::ManagedObject*)sdk()->functions->typeof(name); + return (API::ManagedObject*)sdk()->functions->typeof_(name); } API::ManagedObject* get_managed_singleton(std::string_view name) const { @@ -253,6 +259,16 @@ class API { } }; + struct REFramework { + operator ::REFrameworkHandle() { + return (::REFrameworkHandle)this; + } + + bool is_drawing_ui() const { + return API::s_instance->param()->functions->is_drawing_ui(); + } + }; + struct TypeDefinition { operator ::REFrameworkTypeDefinitionHandle() const { return (::REFrameworkTypeDefinitionHandle)this; @@ -421,6 +437,10 @@ class API { API::TypeInfo* get_type_info() const { return (API::TypeInfo*)API::s_instance->sdk()->type_definition->get_type_info(*this); } + + API::ManagedObject* get_runtime_type() const { + return (API::ManagedObject*)API::s_instance->sdk()->type_definition->get_runtime_type(*this); + } }; struct Method { @@ -515,6 +535,14 @@ class API { uint32_t get_invoke_id() const { return API::s_instance->sdk()->method->get_invoke_id(*this); } + + unsigned int add_hook(REFPreHookFn pre_fn, REFPostHookFn post_fn, bool ignore_jmp) const { + return API::s_instance->sdk()->functions->add_hook(*this, pre_fn, post_fn, ignore_jmp); + } + + void remove_hook(unsigned int hook_id) const { + API::s_instance->sdk()->functions->remove_hook(*this, hook_id); + } }; struct Field { @@ -610,12 +638,12 @@ class API { return API::s_instance->sdk()->managed_object->get_reflection_properties(*this); } - void* get_reflection_property_descriptor(std::string_view name) { - return API::s_instance->sdk()->managed_object->get_reflection_property_descriptor(*this, name.data()); + API::ReflectionProperty* get_reflection_property_descriptor(std::string_view name) { + return (API::ReflectionProperty*)API::s_instance->sdk()->managed_object->get_reflection_property_descriptor(*this, name.data()); } - void* get_reflection_method_descriptor(std::string_view name) { - return API::s_instance->sdk()->managed_object->get_reflection_method_descriptor(*this, name.data()); + API::ReflectionMethod* get_reflection_method_descriptor(std::string_view name) { + return (API::ReflectionMethod*)API::s_instance->sdk()->managed_object->get_reflection_method_descriptor(*this, name.data()); } template @@ -665,7 +693,7 @@ class API { return nullptr; } - return f->get_data_raw(this, is_value_type); + return (T*)f->get_data_raw((void*)this, is_value_type); } }; @@ -722,12 +750,24 @@ class API { return API::s_instance->sdk()->type_info->get_reflection_properties(*this); } - void* get_reflection_property_descriptor(std::string_view name) { - return API::s_instance->sdk()->type_info->get_reflection_property_descriptor(*this, name.data()); + API::ReflectionProperty* get_reflection_property_descriptor(std::string_view name) { + return (API::ReflectionProperty*)API::s_instance->sdk()->type_info->get_reflection_property_descriptor(*this, name.data()); + } + + API::ReflectionMethod* get_reflection_method_descriptor(std::string_view name) { + return (API::ReflectionMethod*)API::s_instance->sdk()->type_info->get_reflection_method_descriptor(*this, name.data()); + } + + void* get_deserializer_fn() const { + return API::s_instance->sdk()->type_info->get_deserializer_fn(*this); + } + + API::TypeInfo* get_parent() const { + return (API::TypeInfo*)API::s_instance->sdk()->type_info->get_parent(*this); } - void* get_reflection_method_descriptor(std::string_view name) { - return API::s_instance->sdk()->type_info->get_reflection_method_descriptor(*this, name.data()); + uint32_t get_crc() const { + return API::s_instance->sdk()->type_info->get_crc(*this); } }; @@ -753,9 +793,37 @@ class API { } }; + struct ReflectionMethod { + operator ::REFrameworkReflectionMethodHandle() const { + return (::REFrameworkReflectionMethodHandle)this; + } + + ::REFrameworkInvokeMethod get_function() const { + return API::s_instance->sdk()->reflection_method->get_function(*this); + } + }; + + struct ReflectionProperty { + operator ::REFrameworkReflectionPropertyHandle() const { + return (::REFrameworkReflectionPropertyHandle)this; + } + + ::REFrameworkReflectionPropertyMethod get_getter() const { + return API::s_instance->sdk()->reflection_property->get_getter(*this); + } + + bool is_static() const { + return API::s_instance->sdk()->reflection_property->is_static(*this); + } + + uint32_t get_size() const { + return API::s_instance->sdk()->reflection_property->get_size(*this); + } + }; + private: const REFrameworkPluginInitializeParam* m_param; const REFrameworkSDKData* m_sdk; std::recursive_mutex m_lua_mtx{}; }; -} \ No newline at end of file +} diff --git a/src/D2DFont.cpp b/src/D2DFont.cpp index c20f9c0..b1d8287 100644 --- a/src/D2DFont.cpp +++ b/src/D2DFont.cpp @@ -1,6 +1,6 @@ #include -#include +#include "utf8.h" #include "D2DFont.hpp" diff --git a/src/D2DPainter.cpp b/src/D2DPainter.cpp index 109c165..18dce8a 100644 --- a/src/D2DPainter.cpp +++ b/src/D2DPainter.cpp @@ -1,6 +1,6 @@ #include -#include +#include "utf8.h" #include "D2DPainter.hpp" diff --git a/src/Plugin.cpp b/src/Plugin.cpp index 810ef79..eda52c8 100644 --- a/src/Plugin.cpp +++ b/src/Plugin.cpp @@ -1,9 +1,9 @@ +#include #include #include -#include -#include -#include +#include "reframework/API.hpp" +#include "sol/sol.hpp" #include "D3D12Renderer.hpp" #include "DrawList.hpp" @@ -11,24 +11,40 @@ using API = reframework::API; using Clock = std::chrono::high_resolution_clock; -std::unique_ptr g_d3d12{}; -D2DPainter* g_d2d{}; -std::vector g_draw_fns{}; -std::vector g_init_fns{}; -lua_State* g_lua{}; -bool g_needs_init{}; -DrawList g_drawlist{}; -DrawList::CommandLock* g_cmds{}; -Clock::time_point g_d2d_next_frame_time{Clock::now()}; -const std::chrono::duration DEFAULT_UPDATE_INTERVAL{1.0 / 60.0}; -std::chrono::duration g_d2d_update_interval{DEFAULT_UPDATE_INTERVAL}; -bool g_update_d2d{}; - -auto get_d2d_max_updaterate() { return 1.0 / g_d2d_update_interval.count(); } -auto set_d2d_max_updaterate(double hz) { g_d2d_update_interval = std::chrono::duration{1.0 / hz}; } +struct Plugin { + std::unique_ptr d3d12{}; + D2DPainter* d2d{}; + std::vector draw_fns{}; + std::vector init_fns{}; + lua_State* lua{}; + bool needs_init{}; + DrawList drawlist{}; + DrawList::CommandLock* cmds{}; + Clock::time_point d2d_next_frame_time{Clock::now()}; + const std::chrono::duration DEFAULT_UPDATE_INTERVAL{1.0 / 60.0}; + std::chrono::duration d2d_update_interval{DEFAULT_UPDATE_INTERVAL}; + bool update_d2d{}; +}; + +Plugin* g_plugin{}; + +BOOL APIENTRY DllMain(HMODULE, DWORD reason, LPVOID) { + if (reason == DLL_PROCESS_ATTACH) { + g_plugin = new Plugin{}; + } + + return TRUE; +} + +auto get_d2d_max_updaterate() { + return 1.0 / g_plugin->d2d_update_interval.count(); +} +auto set_d2d_max_updaterate(double hz) { + g_plugin->d2d_update_interval = std::chrono::duration{1.0 / hz}; +} void on_ref_lua_state_created(lua_State* l) try { - g_lua = l; + g_plugin->lua = l; sol::state_view lua{l}; auto d2d = lua.create_table(); @@ -48,7 +64,7 @@ void on_ref_lua_state_created(lua_State* l) try { italic = italic_obj.as(); } - return std::make_shared(g_d2d->dwrite(), name, size, bold, italic); + return std::make_shared(g_plugin->d2d->dwrite(), name, size, bold, italic); }, "measure", &D2DFont::measure); @@ -65,7 +81,7 @@ void on_ref_lua_state_created(lua_State* l) try { std::filesystem::create_directories(images_path); - return std::make_shared(g_d2d->wic(), g_d2d->context(), image_path); + return std::make_shared(g_plugin->d2d->wic(), g_plugin->d2d->context(), image_path); }, "size", &D2DImage::size); @@ -73,9 +89,9 @@ void on_ref_lua_state_created(lua_State* l) try { detail["set_max_updaterate"] = [](double fps) { set_d2d_max_updaterate(fps); }; d2d["detail"] = detail; d2d["register"] = [](sol::protected_function init_fn, sol::protected_function draw_fn) { - g_init_fns.emplace_back(init_fn); - g_draw_fns.emplace_back(draw_fn); - g_needs_init = true; + g_plugin->init_fns.emplace_back(init_fn); + g_plugin->draw_fns.emplace_back(draw_fn); + g_plugin->needs_init = true; }; d2d["create_font"] = [](const char* name, int size, sol::object bold_obj, sol::object italic_obj) { auto bold = false; @@ -89,10 +105,10 @@ void on_ref_lua_state_created(lua_State* l) try { italic = italic_obj.as(); } - return std::make_shared(g_d2d->dwrite(), name, size, bold, italic); + return std::make_shared(g_plugin->d2d->dwrite(), name, size, bold, italic); }; d2d["text"] = [](std::shared_ptr& font, const char* text, float x, float y, unsigned int color) { - g_cmds->text(font, text, x, y, color); + g_plugin->cmds->text(font, text, x, y, color); }; d2d["measure_text"] = [](sol::this_state s, std::shared_ptr& font, const char* text) { auto [w, h] = font->measure(text); @@ -101,13 +117,13 @@ void on_ref_lua_state_created(lua_State* l) try { results.push_back(sol::make_object(s, h)); return results; }; - d2d["fill_rect"] = [](float x, float y, float w, float h, unsigned int color) { g_cmds->fill_rect(x, y, w, h, color); }; + d2d["fill_rect"] = [](float x, float y, float w, float h, unsigned int color) { g_plugin->cmds->fill_rect(x, y, w, h, color); }; d2d["filled_rect"] = d2d["fill_rect"]; d2d["outline_rect"] = [](float x, float y, float w, float h, float thickness, unsigned int color) { - g_cmds->outline_rect(x, y, w, h, thickness, color); + g_plugin->cmds->outline_rect(x, y, w, h, thickness, color); }; d2d["line"] = [](float x1, float y1, float x2, float y2, float thickness, unsigned int color) { - g_cmds->line(x1, y1, x2, y2, thickness, color); + g_plugin->cmds->line(x1, y1, x2, y2, thickness, color); }; d2d["image"] = [](std::shared_ptr& image, float x, float y, sol::object w_obj, sol::object h_obj) { auto [w, h] = image->size(); @@ -120,108 +136,110 @@ void on_ref_lua_state_created(lua_State* l) try { h = h_obj.as(); } - g_cmds->image(image, x, y, w, h); + g_plugin->cmds->image(image, x, y, w, h); }; d2d["surface_size"] = [](sol::this_state s) { - auto [w, h] = g_d2d->surface_size(); + auto [w, h] = g_plugin->d2d->surface_size(); sol::variadic_results results{}; results.push_back(sol::make_object(s, w)); results.push_back(sol::make_object(s, h)); return results; }; lua["d2d"] = d2d; - g_needs_init = true; + g_plugin->needs_init = true; } catch (const std::exception& e) { OutputDebugStringA(e.what()); API::get()->log_error("[reframework-d2d] [on_ref_lua_state_created] %s", e.what()); } void on_ref_lua_state_destroyed(lua_State* l) try { - g_drawlist.acquire().commands.clear(); - g_draw_fns.clear(); - g_init_fns.clear(); - g_lua = nullptr; + g_plugin->drawlist.acquire().commands.clear(); + g_plugin->draw_fns.clear(); + g_plugin->init_fns.clear(); + g_plugin->lua = nullptr; } catch (const std::exception& e) { OutputDebugStringA(e.what()); API::get()->log_error("[reframework-d2d] [on_ref_lua_state_destroyed] %s", e.what()); } void on_ref_device_reset() try { - g_drawlist.acquire().commands.clear(); - g_d2d = nullptr; - g_d3d12.reset(); + g_plugin->drawlist.acquire().commands.clear(); + g_plugin->d2d = nullptr; + g_plugin->d3d12.reset(); } catch (const std::exception& e) { OutputDebugStringA(e.what()); API::get()->log_error("[reframework-d2d] [on_ref_lua_device_reset] %s", e.what()); } void on_ref_frame() try { - if (g_draw_fns.empty()) { + if (g_plugin->draw_fns.empty()) { return; } - if (g_d3d12 == nullptr) { + if (g_plugin->d3d12 == nullptr) { auto renderer_data = API::get()->param()->renderer_data; - g_d3d12 = std::make_unique((IDXGISwapChain*)renderer_data->swapchain, (ID3D12Device*)renderer_data->device, + g_plugin->d3d12 = std::make_unique((IDXGISwapChain*)renderer_data->swapchain, (ID3D12Device*)renderer_data->device, (ID3D12CommandQueue*)renderer_data->command_queue); - g_d2d = g_d3d12->get_d2d().get(); - g_needs_init = true; + g_plugin->d2d = g_plugin->d3d12->get_d2d().get(); + g_plugin->needs_init = true; } // Just return if we need init since its not ready yet. - if (g_needs_init) { + if (g_plugin->needs_init) { return; } - g_d3d12->render([](D2DPainter& d2d) { - auto cmds_lock = g_drawlist.acquire(); + g_plugin->d3d12->render( + [](D2DPainter& d2d) { + auto cmds_lock = g_plugin->drawlist.acquire(); - for (auto&& cmd : cmds_lock.commands) { - switch (cmd.type) { - case DrawList::CommandType::TEXT: - g_d2d->text(cmd.font_resource, cmd.str, cmd.text.x, cmd.text.y, cmd.text.color); - break; + for (auto&& cmd : cmds_lock.commands) { + switch (cmd.type) { + case DrawList::CommandType::TEXT: + g_plugin->d2d->text(cmd.font_resource, cmd.str, cmd.text.x, cmd.text.y, cmd.text.color); + break; - case DrawList::CommandType::FILL_RECT: - g_d2d->fill_rect(cmd.fill_rect.x, cmd.fill_rect.y, cmd.fill_rect.w, cmd.fill_rect.h, cmd.fill_rect.color); - break; + case DrawList::CommandType::FILL_RECT: + g_plugin->d2d->fill_rect(cmd.fill_rect.x, cmd.fill_rect.y, cmd.fill_rect.w, cmd.fill_rect.h, cmd.fill_rect.color); + break; - case DrawList::CommandType::OUTLINE_RECT: - g_d2d->outline_rect(cmd.outline_rect.x, cmd.outline_rect.y, cmd.outline_rect.w, cmd.outline_rect.h, - cmd.outline_rect.thickness, cmd.outline_rect.color); - break; + case DrawList::CommandType::OUTLINE_RECT: + g_plugin->d2d->outline_rect(cmd.outline_rect.x, cmd.outline_rect.y, cmd.outline_rect.w, cmd.outline_rect.h, + cmd.outline_rect.thickness, cmd.outline_rect.color); + break; - case DrawList::CommandType::LINE: - g_d2d->line(cmd.line.x1, cmd.line.y1, cmd.line.x2, cmd.line.y2, cmd.line.thickness, cmd.line.color); - break; + case DrawList::CommandType::LINE: + g_plugin->d2d->line(cmd.line.x1, cmd.line.y1, cmd.line.x2, cmd.line.y2, cmd.line.thickness, cmd.line.color); + break; - case DrawList::CommandType::IMAGE: - g_d2d->image(cmd.image_resource, cmd.image.x, cmd.image.y, cmd.image.w, cmd.image.h); - break; + case DrawList::CommandType::IMAGE: + g_plugin->d2d->image(cmd.image_resource, cmd.image.x, cmd.image.y, cmd.image.w, cmd.image.h); + break; + } } - } - }, g_update_d2d); + }, + g_plugin->update_d2d); - g_update_d2d = false; + g_plugin->update_d2d = false; } catch (const std::exception& e) { OutputDebugStringA(e.what()); - // g_ref->functions->log_error(e.what()); + // g_plugin->ref->functions->log_plugin->error(e.what()); } void on_begin_rendering() try { - if (g_d3d12 == nullptr) { + if (g_plugin->d3d12 == nullptr) { return; } - if (g_needs_init) { + if (g_plugin->needs_init) { auto _ = API::LuaLock{}; - for (const auto& init_fn : g_init_fns) { + for (const auto& init_fn : g_plugin->init_fns) { try { auto result = init_fn(); if (!result.valid()) { - sol::script_throw_on_error(g_lua, std::move(result)); + sol::script_throw_on_error(g_plugin->lua, std::move(result)); } } catch (const std::exception& e) { MessageBox(nullptr, e.what(), "[reframework-d2d] [init_fn] error", MB_ICONERROR | MB_OK); @@ -230,33 +248,33 @@ void on_begin_rendering() try { } } - g_needs_init = false; + g_plugin->needs_init = false; } auto now = Clock::now(); - if (now >= g_d2d_next_frame_time) { + if (now >= g_plugin->d2d_next_frame_time) { auto lua_lock = API::LuaLock{}; - auto cmds_lock = g_drawlist.acquire(); - g_cmds = &cmds_lock; + auto cmds_lock = g_plugin->drawlist.acquire(); + g_plugin->cmds = &cmds_lock; cmds_lock.commands.clear(); - for (const auto& draw_fn : g_draw_fns) { + for (const auto& draw_fn : g_plugin->draw_fns) { auto result = draw_fn(); if (!result.valid()) { - sol::script_throw_on_error(g_lua, std::move(result)); + sol::script_throw_on_error(g_plugin->lua, std::move(result)); } } - g_cmds = nullptr; - g_d2d_next_frame_time = now + std::chrono::duration_cast(g_d2d_update_interval); - g_update_d2d = true; + g_plugin->cmds = nullptr; + g_plugin->d2d_next_frame_time = now + std::chrono::duration_cast(g_plugin->d2d_update_interval); + g_plugin->update_d2d = true; } } catch (const std::exception& e) { OutputDebugStringA(e.what()); - // g_ref->functions->log_error(e.what()); + // g_plugin->ref->functions->log_error(e.what()); } extern "C" __declspec(dllexport) void reframework_plugin_required_version(REFrameworkPluginVersion* version) { @@ -274,7 +292,7 @@ extern "C" __declspec(dllexport) bool reframework_plugin_initialize(const REFram param->functions->on_lua_state_created(on_ref_lua_state_created); param->functions->on_lua_state_destroyed(on_ref_lua_state_destroyed); - param->functions->on_frame(on_ref_frame); + param->functions->on_present(on_ref_frame); param->functions->on_device_reset(on_ref_device_reset); param->functions->on_pre_application_entry("BeginRendering", on_begin_rendering); diff --git a/vcpkg.json b/vcpkg.json deleted file mode 100644 index 35c3f33..0000000 --- a/vcpkg.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$cmkr": "This file is automatically generated from cmake.toml - DO NOT EDIT", - "$cmkr-url": "https://github.com/build-cpp/cmkr", - "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", - "dependencies": [ - "sol2", - "lua", - "utfcpp" - ], - "description": "", - "name": "reframework-d2d", - "version-string": "" -}