From 51af9aed7b65c6e4e5a1b2a3a6c31a7376c58cf5 Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sun, 9 Mar 2025 21:55:28 +0800 Subject: [PATCH 01/21] add clrhost --- CSharp/LuaSTG/.gitignore | 400 ++++++++++++++++++ CSharp/LuaSTG/LuaSTG.sln | 25 ++ CSharp/LuaSTG/LuaSTG/Class1.cs | 7 + CSharp/LuaSTG/LuaSTG/LuaSTG.csproj | 11 + .../LuaSTG/LuaSTG/runtimeconfig.template.json | 3 + LuaSTG/CMakeLists.txt | 11 + LuaSTG/LuaSTG/AppFrame.cpp | 7 + LuaSTG/LuaSTG/AppFrame.h | 3 + LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp | 0 LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp | 0 LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp | 155 +++++++ LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp | 45 ++ 12 files changed, 667 insertions(+) create mode 100644 CSharp/LuaSTG/.gitignore create mode 100644 CSharp/LuaSTG/LuaSTG.sln create mode 100644 CSharp/LuaSTG/LuaSTG/Class1.cs create mode 100644 CSharp/LuaSTG/LuaSTG/LuaSTG.csproj create mode 100644 CSharp/LuaSTG/LuaSTG/runtimeconfig.template.json create mode 100644 LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp create mode 100644 LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp create mode 100644 LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp create mode 100644 LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp diff --git a/CSharp/LuaSTG/.gitignore b/CSharp/LuaSTG/.gitignore new file mode 100644 index 00000000..60b2ea06 --- /dev/null +++ b/CSharp/LuaSTG/.gitignore @@ -0,0 +1,400 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +# but not Directory.Build.rsp, as it configures directory-level build defaults +!Directory.Build.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml \ No newline at end of file diff --git a/CSharp/LuaSTG/LuaSTG.sln b/CSharp/LuaSTG/LuaSTG.sln new file mode 100644 index 00000000..cee08410 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.13.35825.156 d17.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuaSTG", "LuaSTG\LuaSTG.csproj", "{13D615BA-2A83-4640-9A2A-14E2DE7039AA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {13D615BA-2A83-4640-9A2A-14E2DE7039AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {13D615BA-2A83-4640-9A2A-14E2DE7039AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {13D615BA-2A83-4640-9A2A-14E2DE7039AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {13D615BA-2A83-4640-9A2A-14E2DE7039AA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7AE1B659-BD97-4D55-87F7-183145C0C2A4} + EndGlobalSection +EndGlobal diff --git a/CSharp/LuaSTG/LuaSTG/Class1.cs b/CSharp/LuaSTG/LuaSTG/Class1.cs new file mode 100644 index 00000000..142076d1 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG/Class1.cs @@ -0,0 +1,7 @@ +namespace LuaSTG +{ + public class Class1 + { + + } +} diff --git a/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj b/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj new file mode 100644 index 00000000..32079d47 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj @@ -0,0 +1,11 @@ + + + + net8.0 + enable + enable + $(MSBuildProjectDirectory)..\..\..\..\build\amd64\bin\Managed + true + Library + + diff --git a/CSharp/LuaSTG/LuaSTG/runtimeconfig.template.json b/CSharp/LuaSTG/LuaSTG/runtimeconfig.template.json new file mode 100644 index 00000000..f022b7ff --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG/runtimeconfig.template.json @@ -0,0 +1,3 @@ +{ + "rollForwardOnNoCandidateFx": 2 +} \ No newline at end of file diff --git a/LuaSTG/CMakeLists.txt b/LuaSTG/CMakeLists.txt index 7d333e93..0bdec356 100644 --- a/LuaSTG/CMakeLists.txt +++ b/LuaSTG/CMakeLists.txt @@ -140,6 +140,11 @@ set(LUASTG_ENGINE_SOURCES LuaSTG/LuaBinding/generated/ColorMember.hpp LuaSTG/LuaBinding/generated/GameObjectMember.cpp LuaSTG/LuaBinding/generated/GameObjectMember.hpp + + LuaSTG/CLRBinding/CLRHost.cpp + LuaSTG/CLRBinding/CLRHost.hpp + LuaSTG/CLRBinding/CLRBinding.cpp + LuaSTG/CLRBinding/CLRBinding.hpp LuaSTG/SteamAPI/SteamAPI.cpp LuaSTG/SteamAPI/SteamAPI.hpp @@ -220,10 +225,16 @@ if (LUASTG_LINK_LUASOCKET) message(STATUS "[LuaSTG] Link: luasocket") endif () +set (CLR_HOST_PATH "C:/Program Files/dotnet/packs/Microsoft.NETCore.App.Host.win-x64/8.0.13/runtimes/win-x64/native") +include_directories (${CLR_HOST_PATH}) +find_library (HOSTFXR NAMES nethost PATHS ${CLR_HOST_PATH}) +target_link_libraries (LuaSTG PRIVATE ${HOSTFXR}) + add_custom_command(TARGET LuaSTG POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/bin COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${CMAKE_BINARY_DIR}/bin/$ COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${CMAKE_BINARY_DIR}/bin/$ COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${CMAKE_BINARY_DIR}/bin/$ + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CLR_HOST_PATH}/nethost.dll ${CMAKE_BINARY_DIR}/bin/nethost.dll VERBATIM ) diff --git a/LuaSTG/LuaSTG/AppFrame.cpp b/LuaSTG/LuaSTG/AppFrame.cpp index 64739841..45f429eb 100644 --- a/LuaSTG/LuaSTG/AppFrame.cpp +++ b/LuaSTG/LuaSTG/AppFrame.cpp @@ -169,6 +169,13 @@ bool AppFrame::Init()noexcept return false; } + CLR = new CLRHost(L".\\Managed\\net8.0\\LuaSTG.runtimeconfig.json"); + if (!CLR->init()) + { + spdlog::info("[luastg] 初始化coreclr失败"); + return false; + } + // 加载初始化脚本(可选) if (!OnLoadLaunchScriptAndFiles()) { diff --git a/LuaSTG/LuaSTG/AppFrame.h b/LuaSTG/LuaSTG/AppFrame.h index 6da1bdfa..58ce25dc 100644 --- a/LuaSTG/LuaSTG/AppFrame.h +++ b/LuaSTG/LuaSTG/AppFrame.h @@ -4,6 +4,7 @@ #include "GameResource/ResourceManager.h" #include "GameObject/GameObjectPool.h" #include "Platform/DirectInput.hpp" +#include "CLRBinding/CLRHost.hpp" namespace LuaSTGPlus { @@ -72,6 +73,8 @@ namespace LuaSTGPlus // 输入设备 std::unique_ptr m_DirectInput; + CLRHost* CLR = nullptr; + public: /// @brief 保护模式执行脚本 /// @note 该函数仅限框架调用,为主逻辑最外层调用。若脚本运行时发生错误,该函数负责截获错误发出错误消息。 diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp new file mode 100644 index 00000000..e69de29b diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp new file mode 100644 index 00000000..e69de29b diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp new file mode 100644 index 00000000..b193dcfc --- /dev/null +++ b/LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp @@ -0,0 +1,155 @@ +#include +#include +#include +#include "windows.h" + +#include "CLRHost.hpp" + +void* LuaSTGPlus::CLRHost::load_library(const char_t* path) +{ + HMODULE h = ::LoadLibraryW(path); + assert(h != nullptr); + return (void*)h; +} + +void* LuaSTGPlus::CLRHost::get_export(void* h, const char* name) +{ + void* f = ::GetProcAddress((HMODULE)h, name); + assert(f != nullptr); + return f; +} + +bool LuaSTGPlus::CLRHost::init_hostfxr() +{ + // Pre-allocate a large buffer for the path to hostfxr + char_t buffer[MAX_PATH]; + size_t buffer_size = sizeof(buffer) / sizeof(char_t); + int rc = get_hostfxr_path(buffer, &buffer_size, nullptr); + if (rc != 0) + return false; + + // Load hostfxr and get desired exports + void* lib = load_library(buffer); + _init_runtime = (hostfxr_initialize_for_runtime_config_fn)get_export(lib, "hostfxr_initialize_for_runtime_config"); + _get_delegate = (hostfxr_get_runtime_delegate_fn)get_export(lib, "hostfxr_get_runtime_delegate"); + _close_context = (hostfxr_close_fn)get_export(lib, "hostfxr_close"); + + return (_init_runtime && _get_delegate && _close_context); +} + +bool LuaSTGPlus::CLRHost::get_dotnet_load_assembly_config(const char_t* config_path) +{ + hostfxr_handle cxt = nullptr; + int rc = _init_runtime(config_path, nullptr, &cxt); + if (rc != 0 || cxt == nullptr) + { + //std::cerr << "Init failed: " << std::hex << std::showbase << rc << std::endl; + _close_context(cxt); + return false; + } + + void* load_assembly_and_get_function_pointer = nullptr; + void* load_assembly = nullptr; + void* get_function_pointer = nullptr; + + rc = _get_delegate( + cxt, + hdt_load_assembly_and_get_function_pointer, + &load_assembly_and_get_function_pointer); + if (rc != 0 || load_assembly_and_get_function_pointer == nullptr) + { + //std::cerr << "Get delegate failed: " << std::hex << std::showbase << rc << std::endl; + return false; + } + + rc = _get_delegate( + cxt, + hdt_load_assembly, + &load_assembly); + if (rc != 0 || load_assembly == nullptr) + { + //std::cerr << "Get delegate failed: " << std::hex << std::showbase << rc << std::endl; + return false; + } + + rc = _get_delegate( + cxt, + hdt_get_function_pointer, + &get_function_pointer); + if (rc != 0 || get_function_pointer == nullptr) + { + //std::cerr << "Get delegate failed: " << std::hex << std::showbase << rc << std::endl; + return false; + } + + _close_context(cxt); + + _load_assembly_and_get_function_pointer = (load_assembly_and_get_function_pointer_fn)load_assembly_and_get_function_pointer; + _load_assembly = (load_assembly_fn)load_assembly; + _get_function_pointer = (get_function_pointer_fn)get_function_pointer; + return true; +} + +LuaSTGPlus::CLRHost::CLRHost(const char_t* config_path) +{ + _init_runtime = nullptr; + _get_delegate = nullptr; + _close_context = nullptr; + + _load_assembly_and_get_function_pointer = nullptr; + _load_assembly = nullptr; + _get_function_pointer = nullptr; + + _config_path = config_path; +} + +bool LuaSTGPlus::CLRHost::init() +{ + return init_hostfxr() && get_dotnet_load_assembly_config(_config_path); +} + +inline int LuaSTGPlus::CLRHost::load_assembly_and_get_function_pointer( + const char_t* assembly_path, + const char_t* type_name, + const char_t* method_name, + const char_t* delegate_type_name, + /*out*/ void** delegate) const +{ + return _load_assembly_and_get_function_pointer( + assembly_path, + type_name, + method_name, + delegate_type_name, + nullptr, + delegate + ); +} + +inline int LuaSTGPlus::CLRHost::load_assembly(const char_t* assembly_path) const +{ + return _load_assembly( + assembly_path, + nullptr, + nullptr + ); +} + +inline int LuaSTGPlus::CLRHost::get_function_pointer( + const char_t* type_name, + const char_t* method_name, + const char_t* delegate_type_name, + /*out*/ void** delegate) +{ + return _get_function_pointer( + type_name, + method_name, + delegate_type_name, + nullptr, + nullptr, + delegate + ); +} + +LuaSTGPlus::CLRHost::~CLRHost() +{ +} \ No newline at end of file diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp b/LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp new file mode 100644 index 00000000..50a958c0 --- /dev/null +++ b/LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include + +namespace LuaSTGPlus +{ + class CLRHost + { + private: + hostfxr_initialize_for_runtime_config_fn _init_runtime = nullptr; + hostfxr_get_runtime_delegate_fn _get_delegate = nullptr; + hostfxr_close_fn _close_context = nullptr; + + load_assembly_and_get_function_pointer_fn _load_assembly_and_get_function_pointer = nullptr; + load_assembly_fn _load_assembly = nullptr; + get_function_pointer_fn _get_function_pointer = nullptr; + + const char_t* _config_path; + + void* load_library(const char_t* path); + void* get_export(void* h, const char* name); + + bool init_hostfxr(); + bool get_dotnet_load_assembly_config(const char_t* config_path); + public: + CLRHost(const char_t* config_path); + bool init(); + + inline int load_assembly_and_get_function_pointer( + const char_t* assembly_path, + const char_t* type_name, + const char_t* method_name, + const char_t* delegate_type_name, + /*out*/ void** delegate) const; + inline int load_assembly(const char_t* assembly_path) const; + inline int get_function_pointer(const char_t* type_name, + const char_t* method_name, + const char_t* delegate_type_name, + /*out*/ void** delegate); + + ~CLRHost(); + }; +} \ No newline at end of file From 167ced37b7e85b1c3b2dc1192d718ade5ef2c344 Mon Sep 17 00:00:00 2001 From: czh098tom Date: Tue, 11 Mar 2025 21:36:04 +0800 Subject: [PATCH 02/21] add binding --- CSharp/LuaSTG/LuaSTG/Class1.cs | 7 ---- CSharp/LuaSTG/LuaSTG/InitPayload.cs | 15 ++++++++ CSharp/LuaSTG/LuaSTG/LuaSTG.csproj | 1 + CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs | 33 ++++++++++++++++++ LuaSTG/LuaSTG/AppFrame.cpp | 7 ++++ LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp | 46 +++++++++++++++++++++++++ LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp | 31 +++++++++++++++++ LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp | 8 ++--- LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp | 8 ++--- 9 files changed, 141 insertions(+), 15 deletions(-) delete mode 100644 CSharp/LuaSTG/LuaSTG/Class1.cs create mode 100644 CSharp/LuaSTG/LuaSTG/InitPayload.cs create mode 100644 CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs diff --git a/CSharp/LuaSTG/LuaSTG/Class1.cs b/CSharp/LuaSTG/LuaSTG/Class1.cs deleted file mode 100644 index 142076d1..00000000 --- a/CSharp/LuaSTG/LuaSTG/Class1.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace LuaSTG -{ - public class Class1 - { - - } -} diff --git a/CSharp/LuaSTG/LuaSTG/InitPayload.cs b/CSharp/LuaSTG/LuaSTG/InitPayload.cs new file mode 100644 index 00000000..16330f85 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG/InitPayload.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG +{ + [StructLayout(LayoutKind.Sequential)] + public unsafe struct InitPayload + { + public delegate* unmanaged log; + } +} diff --git a/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj b/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj index 32079d47..73ca515f 100644 --- a/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj +++ b/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj @@ -7,5 +7,6 @@ $(MSBuildProjectDirectory)..\..\..\..\build\amd64\bin\Managed true Library + true diff --git a/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs b/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs new file mode 100644 index 00000000..506c90ae --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG +{ + public static unsafe class LuaSTGAPI + { + public static delegate* unmanaged log; + + public delegate void GameCallback(); + + [UnmanagedCallersOnly] + public static void StartUp(InitPayload initPayload) + { + log = initPayload.log; + + Console.WriteLine("From CLR"); + + Log(); + } + + public static void GameInit() + { + + } + + public static void Log() => log(); + } +} diff --git a/LuaSTG/LuaSTG/AppFrame.cpp b/LuaSTG/LuaSTG/AppFrame.cpp index 45f429eb..cd537efe 100644 --- a/LuaSTG/LuaSTG/AppFrame.cpp +++ b/LuaSTG/LuaSTG/AppFrame.cpp @@ -7,6 +7,7 @@ #include "utf8.hpp" #include "resource.h" #include "core/Configuration.hpp" +#include "CLRBinding/CLRBinding.hpp" using namespace LuaSTGPlus; @@ -176,6 +177,12 @@ bool AppFrame::Init()noexcept return false; } + CLRFunctions clr_fn{}; + if (!InitCLRBinding(CLR, &clr_fn)) + { + spdlog::info("[luastg] 托管程序集LuaSTG.dll加载失败"); + } + // 加载初始化脚本(可选) if (!OnLoadLaunchScriptAndFiles()) { diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp index e69de29b..a83bbbaf 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp @@ -0,0 +1,46 @@ +#include "CLRBinding.hpp" + +void Log() +{ + spdlog::level::level_enum const level = spdlog::level::level_enum::debug; + std::string_view message = "FromCLR"; + spdlog::log(level, "[lua] {}", message); +} + +void LuaSTGPlus::CallCLRStartUp(const entry_point_fn& entry_point) +{ + CLRInitPayload payload{}; + payload.log = Log; + entry_point(payload); +} + +bool LuaSTGPlus::InitCLRBinding(const CLRHost* host, CLRFunctions* functions) +{ + void* fn = nullptr; + if (host->load_assembly_and_get_function_pointer( + L".\\Managed\\net8.0\\LuaSTG.dll", + L"LuaSTG.LuaSTGAPI, LuaSTG", + L"StartUp", + UNMANAGEDCALLERSONLY_METHOD, + &fn) || !fn) + { + return false; + } + + CLRInitPayload payload{}; + payload.log = Log; + ((entry_point_fn)fn)(payload); + + fn = nullptr; + if (host->get_function_pointer( + L"LuaSTG.LuaSTGAPI, LuaSTG", + L"GameInit", + L"LuaSTG.LuaSTGAPI+GameInit, LuaSTG", + &fn) || !fn) + { + return false; + } + functions->GameInit = (game_callback_fn)fn; + + return true; +} diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp index e69de29b..3beb4436 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "CLRBinding/CLRHost.hpp" + +namespace LuaSTGPlus +{ + typedef void (CORECLR_DELEGATE_CALLTYPE* Log_fn)(); + typedef void (CORECLR_DELEGATE_CALLTYPE* game_callback_fn)(); + typedef bool (CORECLR_DELEGATE_CALLTYPE* game_loop_fn)(); + + struct CLRInitPayload + { + Log_fn log; + }; + + struct CLRFunctions + { + game_callback_fn GameInit; + game_loop_fn FrameFunc; + game_callback_fn RenderFunc; + game_callback_fn GameExit; + game_callback_fn FocusLoseFunc; + game_callback_fn FocusGainFunc; + }; + + typedef void (CORECLR_DELEGATE_CALLTYPE* entry_point_fn)(CLRInitPayload); + + void CallCLRStartUp(const entry_point_fn& entry_point); + + bool InitCLRBinding(const CLRHost* host, CLRFunctions* functions); +} \ No newline at end of file diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp index b193dcfc..bfacf3e0 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp @@ -108,7 +108,7 @@ bool LuaSTGPlus::CLRHost::init() return init_hostfxr() && get_dotnet_load_assembly_config(_config_path); } -inline int LuaSTGPlus::CLRHost::load_assembly_and_get_function_pointer( +int LuaSTGPlus::CLRHost::load_assembly_and_get_function_pointer( const char_t* assembly_path, const char_t* type_name, const char_t* method_name, @@ -125,7 +125,7 @@ inline int LuaSTGPlus::CLRHost::load_assembly_and_get_function_pointer( ); } -inline int LuaSTGPlus::CLRHost::load_assembly(const char_t* assembly_path) const +int LuaSTGPlus::CLRHost::load_assembly(const char_t* assembly_path) const { return _load_assembly( assembly_path, @@ -134,11 +134,11 @@ inline int LuaSTGPlus::CLRHost::load_assembly(const char_t* assembly_path) const ); } -inline int LuaSTGPlus::CLRHost::get_function_pointer( +int LuaSTGPlus::CLRHost::get_function_pointer( const char_t* type_name, const char_t* method_name, const char_t* delegate_type_name, - /*out*/ void** delegate) + /*out*/ void** delegate) const { return _get_function_pointer( type_name, diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp b/LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp index 50a958c0..df91182e 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp @@ -28,17 +28,17 @@ namespace LuaSTGPlus CLRHost(const char_t* config_path); bool init(); - inline int load_assembly_and_get_function_pointer( + int load_assembly_and_get_function_pointer( const char_t* assembly_path, const char_t* type_name, const char_t* method_name, const char_t* delegate_type_name, /*out*/ void** delegate) const; - inline int load_assembly(const char_t* assembly_path) const; - inline int get_function_pointer(const char_t* type_name, + int load_assembly(const char_t* assembly_path) const; + int get_function_pointer(const char_t* type_name, const char_t* method_name, const char_t* delegate_type_name, - /*out*/ void** delegate); + /*out*/ void** delegate) const; ~CLRHost(); }; From d800ddc3b5dd5110d1a8b708d1ec8e1d88eee975 Mon Sep 17 00:00:00 2001 From: czh098tom Date: Wed, 12 Mar 2025 23:41:32 +0800 Subject: [PATCH 03/21] C# call beginscene endscene renderclear test --- CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs | 70 ++++++++++++++++--- CSharp/LuaSTG/LuaSTG/ManagedAPI.cs | 20 ++++++ .../{InitPayload.cs => UnmanagedAPI.cs} | 6 +- LuaSTG/LuaSTG/AppFrame.cpp | 7 +- LuaSTG/LuaSTG/AppFrame.h | 3 + LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp | 36 +++++----- LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp | 27 ++++--- 7 files changed, 126 insertions(+), 43 deletions(-) create mode 100644 CSharp/LuaSTG/LuaSTG/ManagedAPI.cs rename CSharp/LuaSTG/LuaSTG/{InitPayload.cs => UnmanagedAPI.cs} (51%) diff --git a/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs b/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs index 506c90ae..8082bed1 100644 --- a/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs +++ b/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs @@ -9,25 +9,79 @@ namespace LuaSTG { public static unsafe class LuaSTGAPI { - public static delegate* unmanaged log; + private static UnmanagedAPI api; - public delegate void GameCallback(); + [UnmanagedCallersOnly] + public static int StartUp(UnmanagedAPI* unmanagedAPI, ManagedAPI* managedAPI) + { + try + { + api = *unmanagedAPI; + + managedAPI->GameInit = &GameInit; + managedAPI->FrameFunc = &FrameFunc; + managedAPI->RenderFunc = &RenderFunc; + managedAPI->GameExit = &GameExit; + managedAPI->FocusGainFunc = &FocusGainFunc; + managedAPI->FocusLoseFunc = &FocusLoseFunc; + + return 0; + } + catch (Exception) + { + return 1; + } + } + + [UnmanagedCallersOnly] + public unsafe static void GameInit() + { + + } + + static long time = 0; + private const double PI_3_2 = Math.PI / 3 * 2; + private const double DEG2RAD = Math.PI / 180; + + [UnmanagedCallersOnly] + public unsafe static byte FrameFunc() + { + time++; + return 0; + } + + [UnmanagedCallersOnly] + public unsafe static void RenderFunc() + { + var rad = time * DEG2RAD; + BeginScene(); + RenderClear(255, + Convert.ToByte(127.0f + 127.0f * Math.Cos(rad)), + Convert.ToByte(127.0f + 127.0f * Math.Cos(rad + PI_3_2)), + Convert.ToByte(127.0f + 127.0f * Math.Cos(rad + PI_3_2 * 2))); + EndScene(); + } [UnmanagedCallersOnly] - public static void StartUp(InitPayload initPayload) + public unsafe static void GameExit() { - log = initPayload.log; - Console.WriteLine("From CLR"); + } + + [UnmanagedCallersOnly] + public unsafe static void FocusGainFunc() + { - Log(); } - public static void GameInit() + [UnmanagedCallersOnly] + public unsafe static void FocusLoseFunc() { } - public static void Log() => log(); + public static void BeginScene() => api.beginScene(); + public static void EndScene() => api.endScene(); + public static void RenderClear(byte a, byte r, byte g, byte b) => api.renderClear(a, r, g, b); } } diff --git a/CSharp/LuaSTG/LuaSTG/ManagedAPI.cs b/CSharp/LuaSTG/LuaSTG/ManagedAPI.cs new file mode 100644 index 00000000..3f144282 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG/ManagedAPI.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG +{ + [StructLayout(LayoutKind.Sequential)] + public unsafe struct ManagedAPI + { + public delegate* unmanaged GameInit; + public delegate* unmanaged FrameFunc; + public delegate* unmanaged RenderFunc; + public delegate* unmanaged GameExit; + public delegate* unmanaged FocusLoseFunc; + public delegate* unmanaged FocusGainFunc; + } +} diff --git a/CSharp/LuaSTG/LuaSTG/InitPayload.cs b/CSharp/LuaSTG/LuaSTG/UnmanagedAPI.cs similarity index 51% rename from CSharp/LuaSTG/LuaSTG/InitPayload.cs rename to CSharp/LuaSTG/LuaSTG/UnmanagedAPI.cs index 16330f85..f2c28abb 100644 --- a/CSharp/LuaSTG/LuaSTG/InitPayload.cs +++ b/CSharp/LuaSTG/LuaSTG/UnmanagedAPI.cs @@ -8,8 +8,10 @@ namespace LuaSTG { [StructLayout(LayoutKind.Sequential)] - public unsafe struct InitPayload + public unsafe struct UnmanagedAPI { - public delegate* unmanaged log; + public delegate* unmanaged beginScene; + public delegate* unmanaged endScene; + public delegate* unmanaged renderClear; } } diff --git a/LuaSTG/LuaSTG/AppFrame.cpp b/LuaSTG/LuaSTG/AppFrame.cpp index cd537efe..8c3960aa 100644 --- a/LuaSTG/LuaSTG/AppFrame.cpp +++ b/LuaSTG/LuaSTG/AppFrame.cpp @@ -177,7 +177,6 @@ bool AppFrame::Init()noexcept return false; } - CLRFunctions clr_fn{}; if (!InitCLRBinding(CLR, &clr_fn)) { spdlog::info("[luastg] 托管程序集LuaSTG.dll加载失败"); @@ -262,6 +261,7 @@ bool AppFrame::Init()noexcept if (!SafeCallGlobalFunction(LuaSTG::LuaEngine::G_CALLBACK_EngineInit)) { return false; } + clr_fn.GameInit(); return true; } @@ -270,6 +270,7 @@ void AppFrame::Shutdown()noexcept if (L) { SafeCallGlobalFunction(LuaSTG::LuaEngine::G_CALLBACK_EngineStop); } + clr_fn.GameExit(); m_GameObjectPool = nullptr; spdlog::info("[luastg] 清空对象池"); @@ -391,6 +392,7 @@ bool AppFrame::onUpdate() result = false; m_pAppModel->requestExit(); } + clr_fn.FocusLoseFunc(); } if (window_active_changed & 0x1) { @@ -406,6 +408,7 @@ bool AppFrame::onUpdate() result = false; m_pAppModel->requestExit(); } + clr_fn.FocusGainFunc(); } if (window_active_changed & 0x4) { @@ -435,6 +438,7 @@ bool AppFrame::onUpdate() } bool tAbort = lua_toboolean(L, -1) != 0; lua_pop(L, 1); + tAbort |= clr_fn.FrameFunc(); if (tAbort) m_pAppModel->requestExit(); m_ResourceMgr.UpdateSound(); @@ -452,6 +456,7 @@ bool AppFrame::onRender() bool result = SafeCallGlobalFunction(LuaSTG::LuaEngine::G_CALLBACK_EngineDraw); if (!result) m_pAppModel->requestExit(); + clr_fn.RenderFunc(); GetRenderTargetManager()->EndRenderTargetStack(); diff --git a/LuaSTG/LuaSTG/AppFrame.h b/LuaSTG/LuaSTG/AppFrame.h index 58ce25dc..d0290647 100644 --- a/LuaSTG/LuaSTG/AppFrame.h +++ b/LuaSTG/LuaSTG/AppFrame.h @@ -5,6 +5,7 @@ #include "GameObject/GameObjectPool.h" #include "Platform/DirectInput.hpp" #include "CLRBinding/CLRHost.hpp" +#include "CLRBinding/CLRBinding.hpp" namespace LuaSTGPlus { @@ -61,6 +62,8 @@ namespace LuaSTGPlus // Lua虚拟机 lua_State* L = nullptr; + CLRFunctions clr_fn; + // 目标帧率 uint32_t m_target_fps{ 60 }; // 测量值 diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp index a83bbbaf..6653e3e5 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp @@ -1,17 +1,23 @@ #include "CLRBinding.hpp" +#include "LuaWrapper.hpp" +#include "AppFrame.h" -void Log() +inline Core::Graphics::IRenderer* LR2D() { return LAPP.GetAppModel()->getRenderer(); } + +void BeginScene() { - spdlog::level::level_enum const level = spdlog::level::level_enum::debug; - std::string_view message = "FromCLR"; - spdlog::log(level, "[lua] {}", message); + LR2D()->beginBatch(); } -void LuaSTGPlus::CallCLRStartUp(const entry_point_fn& entry_point) +void EndScene() { - CLRInitPayload payload{}; - payload.log = Log; - entry_point(payload); + LR2D()->endBatch(); +} + +void RenderClear(unsigned char a, unsigned char r, unsigned char g, unsigned char b) +{ + Core::Color4B color(r, g, b, a); + LR2D()->clearRenderTarget(color); } bool LuaSTGPlus::InitCLRBinding(const CLRHost* host, CLRFunctions* functions) @@ -28,19 +34,13 @@ bool LuaSTGPlus::InitCLRBinding(const CLRHost* host, CLRFunctions* functions) } CLRInitPayload payload{}; - payload.log = Log; - ((entry_point_fn)fn)(payload); - - fn = nullptr; - if (host->get_function_pointer( - L"LuaSTG.LuaSTGAPI, LuaSTG", - L"GameInit", - L"LuaSTG.LuaSTGAPI+GameInit, LuaSTG", - &fn) || !fn) + payload.BeginScene = BeginScene; + payload.EndScene = EndScene; + payload.RenderClear = RenderClear; + if (((entry_point_fn)fn)(&payload, functions)) { return false; } - functions->GameInit = (game_callback_fn)fn; return true; } diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp index 3beb4436..a75ccb82 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp @@ -2,30 +2,29 @@ #include "CLRBinding/CLRHost.hpp" +#define CORECLR_BINDING(ret, name, parameter) typedef ret (CORECLR_DELEGATE_CALLTYPE* t_##name)(parameter);\ +t_##name name; + namespace LuaSTGPlus { - typedef void (CORECLR_DELEGATE_CALLTYPE* Log_fn)(); - typedef void (CORECLR_DELEGATE_CALLTYPE* game_callback_fn)(); - typedef bool (CORECLR_DELEGATE_CALLTYPE* game_loop_fn)(); - struct CLRInitPayload { - Log_fn log; + void (CORECLR_DELEGATE_CALLTYPE* BeginScene)(); + void (CORECLR_DELEGATE_CALLTYPE* EndScene)(); + void (CORECLR_DELEGATE_CALLTYPE* RenderClear)(unsigned char, unsigned char, unsigned char, unsigned char); }; struct CLRFunctions { - game_callback_fn GameInit; - game_loop_fn FrameFunc; - game_callback_fn RenderFunc; - game_callback_fn GameExit; - game_callback_fn FocusLoseFunc; - game_callback_fn FocusGainFunc; + void (CORECLR_DELEGATE_CALLTYPE* GameInit)(); + bool (CORECLR_DELEGATE_CALLTYPE* FrameFunc)(); + void (CORECLR_DELEGATE_CALLTYPE* RenderFunc)(); + void (CORECLR_DELEGATE_CALLTYPE* GameExit)(); + void (CORECLR_DELEGATE_CALLTYPE* FocusLoseFunc)(); + void (CORECLR_DELEGATE_CALLTYPE* FocusGainFunc)(); }; - typedef void (CORECLR_DELEGATE_CALLTYPE* entry_point_fn)(CLRInitPayload); - - void CallCLRStartUp(const entry_point_fn& entry_point); + typedef int (CORECLR_DELEGATE_CALLTYPE* entry_point_fn)(CLRInitPayload*, CLRFunctions*); bool InitCLRBinding(const CLRHost* host, CLRFunctions* functions); } \ No newline at end of file From 8208035b49e0947c4eddc3effaa8033ced22d81e Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sun, 16 Mar 2025 14:48:58 +0800 Subject: [PATCH 04/21] remove test code --- CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs b/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs index 8082bed1..c4da90cf 100644 --- a/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs +++ b/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs @@ -53,13 +53,13 @@ public unsafe static byte FrameFunc() [UnmanagedCallersOnly] public unsafe static void RenderFunc() { - var rad = time * DEG2RAD; - BeginScene(); - RenderClear(255, - Convert.ToByte(127.0f + 127.0f * Math.Cos(rad)), - Convert.ToByte(127.0f + 127.0f * Math.Cos(rad + PI_3_2)), - Convert.ToByte(127.0f + 127.0f * Math.Cos(rad + PI_3_2 * 2))); - EndScene(); + //var rad = time * DEG2RAD; + //BeginScene(); + //RenderClear(255, + // Convert.ToByte(127.0f + 127.0f * Math.Cos(rad)), + // Convert.ToByte(127.0f + 127.0f * Math.Cos(rad + PI_3_2)), + // Convert.ToByte(127.0f + 127.0f * Math.Cos(rad + PI_3_2 * 2))); + //EndScene(); } [UnmanagedCallersOnly] From f54ae7e27be29e5c28175b78ebb31ab3bcb1623e Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sat, 22 Mar 2025 23:46:10 +0800 Subject: [PATCH 05/21] rearrange C# side program structure --- CSharp/LuaSTG/LuaSTG.Core/ILuaSTGApp.cs | 18 ++++ CSharp/LuaSTG/LuaSTG.Core/LuaSTG.Core.csproj | 10 +++ CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs | 76 ++++++++++++++++ CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs | 69 +++++++++++++++ CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs | 31 +++++++ CSharp/LuaSTG/LuaSTG.sln | 8 +- CSharp/LuaSTG/LuaSTG/LuaSTG.csproj | 5 +- CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs | 87 ------------------- CSharp/LuaSTG/LuaSTG/LuaSTGApp.cs | 40 +++++++++ CSharp/LuaSTG/LuaSTG/ManagedAPI.cs | 20 ----- .../LuaSTG/Properties/launchSettings.json | 9 ++ CSharp/LuaSTG/LuaSTG/UnmanagedAPI.cs | 17 ---- LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp | 2 +- 13 files changed, 265 insertions(+), 127 deletions(-) create mode 100644 CSharp/LuaSTG/LuaSTG.Core/ILuaSTGApp.cs create mode 100644 CSharp/LuaSTG/LuaSTG.Core/LuaSTG.Core.csproj create mode 100644 CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs create mode 100644 CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs create mode 100644 CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs delete mode 100644 CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs create mode 100644 CSharp/LuaSTG/LuaSTG/LuaSTGApp.cs delete mode 100644 CSharp/LuaSTG/LuaSTG/ManagedAPI.cs create mode 100644 CSharp/LuaSTG/LuaSTG/Properties/launchSettings.json delete mode 100644 CSharp/LuaSTG/LuaSTG/UnmanagedAPI.cs diff --git a/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGApp.cs b/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGApp.cs new file mode 100644 index 00000000..a7e3ad32 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGApp.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + public interface ILuaSTGApp + { + void GameInit(); + bool FrameFunc(); + void RenderFunc(); + void GameExit(); + void FocusGainFunc(); + void FocusLoseFunc(); + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/LuaSTG.Core.csproj b/CSharp/LuaSTG/LuaSTG.Core/LuaSTG.Core.csproj new file mode 100644 index 00000000..bd44ee5a --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/LuaSTG.Core.csproj @@ -0,0 +1,10 @@ + + + + net8.0 + enable + enable + true + + + diff --git a/CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs new file mode 100644 index 00000000..b2676ca6 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Loader; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + public static unsafe partial class LuaSTGAPI + { + private static ILuaSTGApp? app; + + [UnmanagedCallersOnly] + private static int StartUp(UnmanagedAPI* unmanagedAPI, ManagedAPI* managedAPI) + { + try + { + SaveUnmanagedAPI(unmanagedAPI); + AssignManagedAPI(managedAPI); + LoadAppAssembly(); + + return 0; + } + catch (Exception) + { + return 1; + } + } + + private static void LoadAppAssembly() + { + var currAssembly = typeof(LuaSTGAPI).Assembly; + var dir = Path.GetDirectoryName(currAssembly.Location); + if (dir == null) return; + Assembly mainAssembly = AssemblyLoadContext.GetLoadContext(currAssembly) + ?.LoadFromAssemblyPath(Path.Combine(dir, "LuaSTG.dll")) ?? currAssembly; + + LoadDependencyRecursively(mainAssembly); + + foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) + { + var type = asm.GetType("LuaSTG.LuaSTGApp"); + if (type != null) + { + app = Activator.CreateInstance(type) as ILuaSTGApp; + break; + } + } + } + + private static void LoadDependencyRecursively(Assembly assembly) + { + var resolver = new AssemblyDependencyResolver(assembly.Location); + foreach (var an in assembly.GetReferencedAssemblies()) + { + if (an.Name?.StartsWith("LuaSTG") ?? false) + { + Assembly loaded; + var path = resolver.ResolveAssemblyToPath(an); + if (path != null) + { + loaded = Assembly.LoadFrom(path); + } + else + { + loaded = Assembly.Load(an); + } + LoadDependencyRecursively(loaded); + } + } + } + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs new file mode 100644 index 00000000..f72fb82d --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct ManagedAPI + { + public delegate* unmanaged GameInit; + public delegate* unmanaged FrameFunc; + public delegate* unmanaged RenderFunc; + public delegate* unmanaged GameExit; + public delegate* unmanaged FocusLoseFunc; + public delegate* unmanaged FocusGainFunc; + } + + public static unsafe partial class LuaSTGAPI + { + [UnmanagedCallersOnly] + internal unsafe static void GameInit() + { + app?.GameInit(); + } + + [UnmanagedCallersOnly] + internal unsafe static byte FrameFunc() + { + return (byte)((app?.FrameFunc() ?? false) ? 1 : 0); + } + + [UnmanagedCallersOnly] + internal unsafe static void RenderFunc() + { + app?.RenderFunc(); + } + + [UnmanagedCallersOnly] + internal unsafe static void GameExit() + { + app?.GameExit(); + } + + [UnmanagedCallersOnly] + internal unsafe static void FocusGainFunc() + { + app?.FocusGainFunc(); + } + + [UnmanagedCallersOnly] + internal unsafe static void FocusLoseFunc() + { + app?.FocusLoseFunc(); + } + + private static void AssignManagedAPI(ManagedAPI* managedAPI) + { + managedAPI->GameInit = &GameInit; + managedAPI->FrameFunc = &FrameFunc; + managedAPI->RenderFunc = &RenderFunc; + managedAPI->GameExit = &GameExit; + managedAPI->FocusGainFunc = &FocusGainFunc; + managedAPI->FocusLoseFunc = &FocusLoseFunc; + } + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs new file mode 100644 index 00000000..a81357c9 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct UnmanagedAPI + { + public delegate* unmanaged beginScene; + public delegate* unmanaged endScene; + public delegate* unmanaged renderClear; + } + + public static unsafe partial class LuaSTGAPI + { + public static void BeginScene() => api.beginScene(); + public static void EndScene() => api.endScene(); + public static void RenderClear(byte a, byte r, byte g, byte b) => api.renderClear(a, r, g, b); + + private static UnmanagedAPI api; + + private static void SaveUnmanagedAPI(UnmanagedAPI* unmanagedAPI) + { + api = *unmanagedAPI; + } + } +} diff --git a/CSharp/LuaSTG/LuaSTG.sln b/CSharp/LuaSTG/LuaSTG.sln index cee08410..5a44e912 100644 --- a/CSharp/LuaSTG/LuaSTG.sln +++ b/CSharp/LuaSTG/LuaSTG.sln @@ -1,10 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.13.35825.156 d17.13 +VisualStudioVersion = 17.13.35825.156 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuaSTG", "LuaSTG\LuaSTG.csproj", "{13D615BA-2A83-4640-9A2A-14E2DE7039AA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuaSTG.Core", "LuaSTG.Core\LuaSTG.Core.csproj", "{877B4324-2F7A-4B22-BC28-5B75BA854BFD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {13D615BA-2A83-4640-9A2A-14E2DE7039AA}.Debug|Any CPU.Build.0 = Debug|Any CPU {13D615BA-2A83-4640-9A2A-14E2DE7039AA}.Release|Any CPU.ActiveCfg = Release|Any CPU {13D615BA-2A83-4640-9A2A-14E2DE7039AA}.Release|Any CPU.Build.0 = Release|Any CPU + {877B4324-2F7A-4B22-BC28-5B75BA854BFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {877B4324-2F7A-4B22-BC28-5B75BA854BFD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {877B4324-2F7A-4B22-BC28-5B75BA854BFD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {877B4324-2F7A-4B22-BC28-5B75BA854BFD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj b/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj index 73ca515f..386a2f98 100644 --- a/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj +++ b/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj @@ -7,6 +7,9 @@ $(MSBuildProjectDirectory)..\..\..\..\build\amd64\bin\Managed true Library - true + + + + diff --git a/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs b/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs deleted file mode 100644 index c4da90cf..00000000 --- a/CSharp/LuaSTG/LuaSTG/LuaSTGAPI.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace LuaSTG -{ - public static unsafe class LuaSTGAPI - { - private static UnmanagedAPI api; - - [UnmanagedCallersOnly] - public static int StartUp(UnmanagedAPI* unmanagedAPI, ManagedAPI* managedAPI) - { - try - { - api = *unmanagedAPI; - - managedAPI->GameInit = &GameInit; - managedAPI->FrameFunc = &FrameFunc; - managedAPI->RenderFunc = &RenderFunc; - managedAPI->GameExit = &GameExit; - managedAPI->FocusGainFunc = &FocusGainFunc; - managedAPI->FocusLoseFunc = &FocusLoseFunc; - - return 0; - } - catch (Exception) - { - return 1; - } - } - - [UnmanagedCallersOnly] - public unsafe static void GameInit() - { - - } - - static long time = 0; - private const double PI_3_2 = Math.PI / 3 * 2; - private const double DEG2RAD = Math.PI / 180; - - [UnmanagedCallersOnly] - public unsafe static byte FrameFunc() - { - time++; - return 0; - } - - [UnmanagedCallersOnly] - public unsafe static void RenderFunc() - { - //var rad = time * DEG2RAD; - //BeginScene(); - //RenderClear(255, - // Convert.ToByte(127.0f + 127.0f * Math.Cos(rad)), - // Convert.ToByte(127.0f + 127.0f * Math.Cos(rad + PI_3_2)), - // Convert.ToByte(127.0f + 127.0f * Math.Cos(rad + PI_3_2 * 2))); - //EndScene(); - } - - [UnmanagedCallersOnly] - public unsafe static void GameExit() - { - - } - - [UnmanagedCallersOnly] - public unsafe static void FocusGainFunc() - { - - } - - [UnmanagedCallersOnly] - public unsafe static void FocusLoseFunc() - { - - } - - public static void BeginScene() => api.beginScene(); - public static void EndScene() => api.endScene(); - public static void RenderClear(byte a, byte r, byte g, byte b) => api.renderClear(a, r, g, b); - } -} diff --git a/CSharp/LuaSTG/LuaSTG/LuaSTGApp.cs b/CSharp/LuaSTG/LuaSTG/LuaSTGApp.cs new file mode 100644 index 00000000..b0a4bfef --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG/LuaSTGApp.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using LuaSTG.Core; + +using static LuaSTG.Core.LuaSTGAPI; + +namespace LuaSTG +{ + public class LuaSTGApp : ILuaSTGApp + { + public void GameInit() + { + } + + public bool FrameFunc() + { + return false; + } + + public void RenderFunc() + { + } + + public void GameExit() + { + } + + public void FocusGainFunc() + { + } + + public void FocusLoseFunc() + { + } + } +} diff --git a/CSharp/LuaSTG/LuaSTG/ManagedAPI.cs b/CSharp/LuaSTG/LuaSTG/ManagedAPI.cs deleted file mode 100644 index 3f144282..00000000 --- a/CSharp/LuaSTG/LuaSTG/ManagedAPI.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace LuaSTG -{ - [StructLayout(LayoutKind.Sequential)] - public unsafe struct ManagedAPI - { - public delegate* unmanaged GameInit; - public delegate* unmanaged FrameFunc; - public delegate* unmanaged RenderFunc; - public delegate* unmanaged GameExit; - public delegate* unmanaged FocusLoseFunc; - public delegate* unmanaged FocusGainFunc; - } -} diff --git a/CSharp/LuaSTG/LuaSTG/Properties/launchSettings.json b/CSharp/LuaSTG/LuaSTG/Properties/launchSettings.json new file mode 100644 index 00000000..b9899be7 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "LuaSTGSub": { + "commandName": "Executable", + "executablePath": "../../../build/amd64/bin/LuaSTG.exe", + "workingDirectory": "../../../build/amd64/bin/" + } + } +} \ No newline at end of file diff --git a/CSharp/LuaSTG/LuaSTG/UnmanagedAPI.cs b/CSharp/LuaSTG/LuaSTG/UnmanagedAPI.cs deleted file mode 100644 index f2c28abb..00000000 --- a/CSharp/LuaSTG/LuaSTG/UnmanagedAPI.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace LuaSTG -{ - [StructLayout(LayoutKind.Sequential)] - public unsafe struct UnmanagedAPI - { - public delegate* unmanaged beginScene; - public delegate* unmanaged endScene; - public delegate* unmanaged renderClear; - } -} diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp index 6653e3e5..cb38c485 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp @@ -25,7 +25,7 @@ bool LuaSTGPlus::InitCLRBinding(const CLRHost* host, CLRFunctions* functions) void* fn = nullptr; if (host->load_assembly_and_get_function_pointer( L".\\Managed\\net8.0\\LuaSTG.dll", - L"LuaSTG.LuaSTGAPI, LuaSTG", + L"LuaSTG.Core.LuaSTGAPI, LuaSTG.Core", L"StartUp", UNMANAGEDCALLERSONLY_METHOD, &fn) || !fn) From 74dfa16a498a0e83797cfb116433aa77d23dd6aa Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sun, 30 Mar 2025 13:30:58 +0800 Subject: [PATCH 06/21] add clr_fn reference --- LuaSTG/LuaSTG/AppFrame.cpp | 2 +- LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp | 3 ++- LuaSTG/LuaSTG/GameObject/GameObjectPool.h | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/LuaSTG/LuaSTG/AppFrame.cpp b/LuaSTG/LuaSTG/AppFrame.cpp index 8c3960aa..8a839177 100644 --- a/LuaSTG/LuaSTG/AppFrame.cpp +++ b/LuaSTG/LuaSTG/AppFrame.cpp @@ -202,7 +202,7 @@ bool AppFrame::Init()noexcept spdlog::info("[luastg] 初始化对象池,容量{}", LOBJPOOL_SIZE); try { - m_GameObjectPool = std::make_unique(L); + m_GameObjectPool = std::make_unique(L, &clr_fn); } catch (const std::bad_alloc&) { diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp index 22e38f9e..778fe584 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp @@ -13,12 +13,13 @@ namespace LuaSTGPlus static GameObjectPool* g_GameObjectPool = nullptr; - GameObjectPool::GameObjectPool(lua_State* pL) + GameObjectPool::GameObjectPool(lua_State* pL, CLRFunctions* clr_fn) { assert(g_GameObjectPool == nullptr); g_GameObjectPool = this; // Lua_State G_L = pL; + CLR_fn = clr_fn; // 初始化对象链表 _ClearLinkList(); m_RenderList.clear(); diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h index 8007496e..5ff1e4ba 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h @@ -3,6 +3,7 @@ #include "Utility/fixed_object_pool.hpp" #include #include +#include "CLRBinding/CLRBinding.hpp" // 对象池信息 #define LOBJPOOL_SIZE 32768 // 最大对象数 //32768(full) //16384(half) @@ -32,6 +33,7 @@ namespace LuaSTGPlus cpp::fixed_object_pool m_ObjectPool; uint64_t m_iUid = 0; lua_State* G_L = nullptr; + CLRFunctions* CLR_fn; // GameObject List struct _less_render { @@ -313,7 +315,7 @@ namespace LuaSTGPlus static int api_ParticleSetEmission(lua_State* L) noexcept; public: - GameObjectPool(lua_State* pL); + GameObjectPool(lua_State* pL, CLRFunctions* clr_fn); GameObjectPool& operator=(const GameObjectPool&) = delete; GameObjectPool(const GameObjectPool&) = delete; ~GameObjectPool(); From a653c36aaa18a128c5bfec572caf58de1183e899 Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sun, 30 Mar 2025 14:24:49 +0800 Subject: [PATCH 07/21] create app by factory --- CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs | 13 +++++++++++++ CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs | 4 ++-- CSharp/LuaSTG/LuaSTG/LuaSTGAppFactory.cs | 18 ++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs create mode 100644 CSharp/LuaSTG/LuaSTG/LuaSTGAppFactory.cs diff --git a/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs b/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs new file mode 100644 index 00000000..c3c95d5a --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + public interface ILuaSTGAppFactory + { + ILuaSTGApp Create(); + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs index b2676ca6..0009893e 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs @@ -42,10 +42,10 @@ private static void LoadAppAssembly() foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) { - var type = asm.GetType("LuaSTG.LuaSTGApp"); + var type = asm.GetType("LuaSTG.LuaSTGAppFactory"); if (type != null) { - app = Activator.CreateInstance(type) as ILuaSTGApp; + app = (Activator.CreateInstance(type) as ILuaSTGAppFactory)?.Create(); break; } } diff --git a/CSharp/LuaSTG/LuaSTG/LuaSTGAppFactory.cs b/CSharp/LuaSTG/LuaSTG/LuaSTGAppFactory.cs new file mode 100644 index 00000000..388f79c5 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG/LuaSTGAppFactory.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using LuaSTG.Core; + +namespace LuaSTG +{ + public class LuaSTGAppFactory : ILuaSTGAppFactory + { + public ILuaSTGApp Create() + { + return new LuaSTGApp(); + } + } +} From 71ae860d967d1180bc58e0f70d82151d56cd9938 Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sun, 30 Mar 2025 14:51:02 +0800 Subject: [PATCH 08/21] try marshal string --- CSharp/LuaSTG/LuaSTG.Core/LogLevel.cs | 18 ++++++++++++++++++ CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs | 11 +++++++++++ LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp | 11 ++++++++++- LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp | 9 +++++---- 4 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 CSharp/LuaSTG/LuaSTG.Core/LogLevel.cs diff --git a/CSharp/LuaSTG/LuaSTG.Core/LogLevel.cs b/CSharp/LuaSTG/LuaSTG.Core/LogLevel.cs new file mode 100644 index 00000000..7dfc92fa --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/LogLevel.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + public enum LogLevel + { + Trace = 0, + Debug = 1, + Info = 2, + Warning = 3, + Error = 4, + Critical = 5, + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs index a81357c9..9e632b99 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; @@ -10,6 +11,7 @@ namespace LuaSTG.Core [StructLayout(LayoutKind.Sequential)] internal unsafe struct UnmanagedAPI { + public delegate* unmanaged log; public delegate* unmanaged beginScene; public delegate* unmanaged endScene; public delegate* unmanaged renderClear; @@ -17,8 +19,17 @@ internal unsafe struct UnmanagedAPI public static unsafe partial class LuaSTGAPI { + public static void Log(LogLevel level, string message) + { + IntPtr unmanagedString = Marshal.StringToHGlobalAnsi(message); + api.log((int) level, unmanagedString); + Marshal.FreeHGlobal(unmanagedString); + } + public static void BeginScene() => api.beginScene(); + public static void EndScene() => api.endScene(); + public static void RenderClear(byte a, byte r, byte g, byte b) => api.renderClear(a, r, g, b); private static UnmanagedAPI api; diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp index cb38c485..382715ab 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp @@ -14,12 +14,17 @@ void EndScene() LR2D()->endBatch(); } -void RenderClear(unsigned char a, unsigned char r, unsigned char g, unsigned char b) +void RenderClear(uint8_t a, uint8_t r, uint8_t g, uint8_t b) { Core::Color4B color(r, g, b, a); LR2D()->clearRenderTarget(color); } +void Log(int32_t level, intptr_t str) +{ + spdlog::log(static_cast(level), "[CSharp] {}", std::string_view((char*)str)); +} + bool LuaSTGPlus::InitCLRBinding(const CLRHost* host, CLRFunctions* functions) { void* fn = nullptr; @@ -34,9 +39,13 @@ bool LuaSTGPlus::InitCLRBinding(const CLRHost* host, CLRFunctions* functions) } CLRInitPayload payload{}; + + payload.Log = Log; + payload.BeginScene = BeginScene; payload.EndScene = EndScene; payload.RenderClear = RenderClear; + if (((entry_point_fn)fn)(&payload, functions)) { return false; diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp index a75ccb82..6fe1e71d 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp @@ -2,26 +2,27 @@ #include "CLRBinding/CLRHost.hpp" -#define CORECLR_BINDING(ret, name, parameter) typedef ret (CORECLR_DELEGATE_CALLTYPE* t_##name)(parameter);\ -t_##name name; - namespace LuaSTGPlus { struct CLRInitPayload { + void (CORECLR_DELEGATE_CALLTYPE* Log)(int32_t, intptr_t); + void (CORECLR_DELEGATE_CALLTYPE* BeginScene)(); void (CORECLR_DELEGATE_CALLTYPE* EndScene)(); - void (CORECLR_DELEGATE_CALLTYPE* RenderClear)(unsigned char, unsigned char, unsigned char, unsigned char); + void (CORECLR_DELEGATE_CALLTYPE* RenderClear)(uint8_t, uint8_t, uint8_t, uint8_t); }; struct CLRFunctions { +#pragma region GameLoop void (CORECLR_DELEGATE_CALLTYPE* GameInit)(); bool (CORECLR_DELEGATE_CALLTYPE* FrameFunc)(); void (CORECLR_DELEGATE_CALLTYPE* RenderFunc)(); void (CORECLR_DELEGATE_CALLTYPE* GameExit)(); void (CORECLR_DELEGATE_CALLTYPE* FocusLoseFunc)(); void (CORECLR_DELEGATE_CALLTYPE* FocusGainFunc)(); +#pragma endregion }; typedef int (CORECLR_DELEGATE_CALLTYPE* entry_point_fn)(CLRInitPayload*, CLRFunctions*); From 3f30dbe307390d4172d46fa79f9eaca2946eb4ed Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sun, 30 Mar 2025 15:51:53 +0800 Subject: [PATCH 09/21] rename method --- CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs | 2 +- CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs | 2 +- CSharp/LuaSTG/LuaSTG/LuaSTGAppFactory.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs b/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs index c3c95d5a..7fb7d872 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs @@ -8,6 +8,6 @@ namespace LuaSTG.Core { public interface ILuaSTGAppFactory { - ILuaSTGApp Create(); + ILuaSTGApp? GetApplication(); } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs index 0009893e..d0ed23d5 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/LuaSTGAPI.cs @@ -45,7 +45,7 @@ private static void LoadAppAssembly() var type = asm.GetType("LuaSTG.LuaSTGAppFactory"); if (type != null) { - app = (Activator.CreateInstance(type) as ILuaSTGAppFactory)?.Create(); + app = (Activator.CreateInstance(type) as ILuaSTGAppFactory)?.GetApplication(); break; } } diff --git a/CSharp/LuaSTG/LuaSTG/LuaSTGAppFactory.cs b/CSharp/LuaSTG/LuaSTG/LuaSTGAppFactory.cs index 388f79c5..a4648d44 100644 --- a/CSharp/LuaSTG/LuaSTG/LuaSTGAppFactory.cs +++ b/CSharp/LuaSTG/LuaSTG/LuaSTGAppFactory.cs @@ -10,7 +10,7 @@ namespace LuaSTG { public class LuaSTGAppFactory : ILuaSTGAppFactory { - public ILuaSTGApp Create() + public ILuaSTGApp? GetApplication() { return new LuaSTGApp(); } From 60521341892d8855f807e8324e54ceefda6e9f50 Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sun, 30 Mar 2025 15:52:02 +0800 Subject: [PATCH 10/21] add comments --- CSharp/LuaSTG/LuaSTG.Core/ILuaSTGApp.cs | 24 +++++++++++++++++++ .../LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs | 14 +++++++++++ CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs | 18 ++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGApp.cs b/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGApp.cs index a7e3ad32..ce620981 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGApp.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGApp.cs @@ -6,13 +6,37 @@ namespace LuaSTG.Core { + /// + /// Represents a LuaSTG application. + /// public interface ILuaSTGApp { + /// + /// Method called at the startup of the application. + /// void GameInit(); + /// + /// Method called each frame. + /// + /// + /// if app has finished its execution. + /// bool FrameFunc(); + /// + /// Method called after frame for rendering. + /// void RenderFunc(); + /// + /// Method called when exiting application. + /// void GameExit(); + /// + /// Method called when application gain focus. + /// void FocusGainFunc(); + /// + /// Method called when application lose focus. + /// void FocusLoseFunc(); } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs b/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs index 7fb7d872..4f1add59 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/ILuaSTGAppFactory.cs @@ -6,8 +6,22 @@ namespace LuaSTG.Core { + /// + /// Represents a factory creating a LuaSTG application. + /// + /// + /// After finished loading assemblies, launching procedure will try to find + /// a type with full name "LuaSTG.LuaSTGAppFactory". + /// if the type is found, it will try to create an object with the parameterless constructor + /// and invoke once to obtain an application. + /// The application object obtained will be a singleton. + /// public interface ILuaSTGAppFactory { + /// + /// Get an application instance. + /// + /// An application instance if success, otherwise null. ILuaSTGApp? GetApplication(); } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs index 9e632b99..7e6720c6 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs @@ -19,6 +19,11 @@ internal unsafe struct UnmanagedAPI public static unsafe partial class LuaSTGAPI { + /// + /// Print a log to LuaSTG Engine. + /// + /// Logging level. + /// Logging message. public static void Log(LogLevel level, string message) { IntPtr unmanagedString = Marshal.StringToHGlobalAnsi(message); @@ -26,10 +31,23 @@ public static void Log(LogLevel level, string message) Marshal.FreeHGlobal(unmanagedString); } + /// + /// Notify engine to start rendering. + /// public static void BeginScene() => api.beginScene(); + /// + /// Notify engine to finish rendering. + /// public static void EndScene() => api.endScene(); + /// + /// Clear the current render target by the color provided. + /// + /// Alpha value. + /// Red value. + /// Green value. + /// Blue value. public static void RenderClear(byte a, byte r, byte g, byte b) => api.renderClear(a, r, g, b); private static UnmanagedAPI api; From cbe492146190c84d9344a54981e82b47c47dc3cc Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sun, 30 Mar 2025 16:48:39 +0800 Subject: [PATCH 11/21] force msbuild copy package ref --- CSharp/LuaSTG/LuaSTG/LuaSTG.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj b/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj index 386a2f98..79d81b85 100644 --- a/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj +++ b/CSharp/LuaSTG/LuaSTG/LuaSTG.csproj @@ -7,6 +7,7 @@ $(MSBuildProjectDirectory)..\..\..\..\build\amd64\bin\Managed true Library + true From ee55db3bb751b00c1607715dc4018229effca1e7 Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sun, 30 Mar 2025 16:51:02 +0800 Subject: [PATCH 12/21] format code --- CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs index 7e6720c6..009a6e09 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs @@ -27,7 +27,7 @@ public static unsafe partial class LuaSTGAPI public static void Log(LogLevel level, string message) { IntPtr unmanagedString = Marshal.StringToHGlobalAnsi(message); - api.log((int) level, unmanagedString); + api.log((int)level, unmanagedString); Marshal.FreeHGlobal(unmanagedString); } From 3e0ca8be0323efcc6ba658fb243e8915dc8a47ee Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sat, 5 Apr 2025 01:44:47 +0800 Subject: [PATCH 13/21] CLR sync lifecycle of Lua GameObjects --- CSharp/LuaSTG/LuaSTG.Core/GameObject.cs | 66 +++++++++++++++++++++ CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs | 4 ++ CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs | 4 ++ LuaSTG/LuaSTG/AppFrame.h | 2 +- LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp | 7 ++- LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp | 13 ++-- LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp | 37 +++++++++++- LuaSTG/LuaSTG/GameObject/GameObjectPool.h | 15 ++++- 8 files changed, 138 insertions(+), 10 deletions(-) create mode 100644 CSharp/LuaSTG/LuaSTG.Core/GameObject.cs diff --git a/CSharp/LuaSTG/LuaSTG.Core/GameObject.cs b/CSharp/LuaSTG/LuaSTG.Core/GameObject.cs new file mode 100644 index 00000000..6e34ac80 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/GameObject.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + using static LuaSTGAPI; + + public class GameObject + { + internal static Dictionary _id2Obj = new(65536); + + private IntPtr _nativePtr; + + public GameObject() + { + _nativePtr = GameObject_New(); + _id2Obj.Add(GameObject_GetID(_nativePtr), this); + } + + internal GameObject(IntPtr nativePtr) + { + _nativePtr = nativePtr; + _id2Obj.Add(GameObject_GetID(_nativePtr), this); + } + + public bool IsValid() + { + return _nativePtr != 0; + } + + internal void Detach() + { + _nativePtr = 0; + } + } + + public static unsafe partial class LuaSTGAPI + { + internal static IntPtr GameObject_New() + { + return api.gameObject_New(); + } + + internal static ulong GameObject_GetID(IntPtr p) + { + return api.gameObject_GetID(p); + } + + [UnmanagedCallersOnly] + private static void CreateLuaGameObject(IntPtr p) + { + _ = new GameObject(p); + } + + [UnmanagedCallersOnly] + private static void DetachGameObject(ulong id) + { + GameObject._id2Obj[id].Detach(); + GameObject._id2Obj.Remove(id); + } + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs index f72fb82d..3ff59051 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs @@ -16,6 +16,8 @@ internal unsafe struct ManagedAPI public delegate* unmanaged GameExit; public delegate* unmanaged FocusLoseFunc; public delegate* unmanaged FocusGainFunc; + public delegate* unmanaged DetachGameObject; + public delegate* unmanaged CreateLuaGameObject; } public static unsafe partial class LuaSTGAPI @@ -64,6 +66,8 @@ private static void AssignManagedAPI(ManagedAPI* managedAPI) managedAPI->GameExit = &GameExit; managedAPI->FocusGainFunc = &FocusGainFunc; managedAPI->FocusLoseFunc = &FocusLoseFunc; + managedAPI->CreateLuaGameObject = &CreateLuaGameObject; + managedAPI->DetachGameObject = &DetachGameObject; } } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs index 009a6e09..c61e1fed 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs @@ -12,6 +12,10 @@ namespace LuaSTG.Core internal unsafe struct UnmanagedAPI { public delegate* unmanaged log; + + public delegate* unmanaged gameObject_New; + public delegate* unmanaged gameObject_GetID; + public delegate* unmanaged beginScene; public delegate* unmanaged endScene; public delegate* unmanaged renderClear; diff --git a/LuaSTG/LuaSTG/AppFrame.h b/LuaSTG/LuaSTG/AppFrame.h index d0290647..0ab73c16 100644 --- a/LuaSTG/LuaSTG/AppFrame.h +++ b/LuaSTG/LuaSTG/AppFrame.h @@ -62,7 +62,7 @@ namespace LuaSTGPlus // Lua虚拟机 lua_State* L = nullptr; - CLRFunctions clr_fn; + ManagedAPI clr_fn; // 目标帧率 uint32_t m_target_fps{ 60 }; diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp index 382715ab..4d016347 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp @@ -25,7 +25,7 @@ void Log(int32_t level, intptr_t str) spdlog::log(static_cast(level), "[CSharp] {}", std::string_view((char*)str)); } -bool LuaSTGPlus::InitCLRBinding(const CLRHost* host, CLRFunctions* functions) +bool LuaSTGPlus::InitCLRBinding(const CLRHost* host, ManagedAPI* functions) { void* fn = nullptr; if (host->load_assembly_and_get_function_pointer( @@ -38,10 +38,13 @@ bool LuaSTGPlus::InitCLRBinding(const CLRHost* host, CLRFunctions* functions) return false; } - CLRInitPayload payload{}; + UnmanagedAPI payload{}; payload.Log = Log; + payload.GameObject_New = GameObjectPool::CLR_API_New; + payload.GameObject_GetID = GameObjectPool::CLR_API_GetID; + payload.BeginScene = BeginScene; payload.EndScene = EndScene; payload.RenderClear = RenderClear; diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp index 6fe1e71d..a8160054 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp @@ -4,16 +4,19 @@ namespace LuaSTGPlus { - struct CLRInitPayload + struct UnmanagedAPI { void (CORECLR_DELEGATE_CALLTYPE* Log)(int32_t, intptr_t); + intptr_t (CORECLR_DELEGATE_CALLTYPE* GameObject_New)(); + uint64_t (CORECLR_DELEGATE_CALLTYPE* GameObject_GetID)(intptr_t); + void (CORECLR_DELEGATE_CALLTYPE* BeginScene)(); void (CORECLR_DELEGATE_CALLTYPE* EndScene)(); void (CORECLR_DELEGATE_CALLTYPE* RenderClear)(uint8_t, uint8_t, uint8_t, uint8_t); }; - struct CLRFunctions + struct ManagedAPI { #pragma region GameLoop void (CORECLR_DELEGATE_CALLTYPE* GameInit)(); @@ -23,9 +26,11 @@ namespace LuaSTGPlus void (CORECLR_DELEGATE_CALLTYPE* FocusLoseFunc)(); void (CORECLR_DELEGATE_CALLTYPE* FocusGainFunc)(); #pragma endregion + void (CORECLR_DELEGATE_CALLTYPE* DetachGameObject)(uint64_t); + void (CORECLR_DELEGATE_CALLTYPE* CreateLuaGameObject)(intptr_t); }; - typedef int (CORECLR_DELEGATE_CALLTYPE* entry_point_fn)(CLRInitPayload*, CLRFunctions*); + typedef int (CORECLR_DELEGATE_CALLTYPE* entry_point_fn)(UnmanagedAPI*, ManagedAPI*); - bool InitCLRBinding(const CLRHost* host, CLRFunctions* functions); + bool InitCLRBinding(const CLRHost* host, ManagedAPI* functions); } \ No newline at end of file diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp index 778fe584..245f6eac 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp @@ -13,7 +13,7 @@ namespace LuaSTGPlus static GameObjectPool* g_GameObjectPool = nullptr; - GameObjectPool::GameObjectPool(lua_State* pL, CLRFunctions* clr_fn) + GameObjectPool::GameObjectPool(lua_State* pL, ManagedAPI* clr_fn) { assert(g_GameObjectPool == nullptr); g_GameObjectPool = this; @@ -212,6 +212,8 @@ namespace LuaSTGPlus // 释放引用的资源 p->ReleaseResource(); + CLR_fn->DetachGameObject(p->id); + GameObject* pRet = _ReleaseObject(p); return pRet; @@ -829,6 +831,7 @@ namespace LuaSTGPlus static std::string _name(""); spdlog::debug("[object] new {}-{} (img = {})", p->id, p->uid, p->res ? p->res->GetResName() : _name); #endif + CLR_fn->CreateLuaGameObject((intptr_t)p); return 1; } @@ -1396,4 +1399,36 @@ namespace LuaSTGPlus p->ps->SetEmission((int)std::max(0, luaL_checkinteger(L, 2))); return 0; } + + GameObject* GameObjectPool::CLR_New() noexcept + { + // 分配一个对象 + GameObject* p = _AllocObject(); + if (p == nullptr) + { + return nullptr; + } + +#if (defined(_DEBUG) && defined(LuaSTG_enable_GameObjectManager_Debug)) + static std::string _name(""); + spdlog::debug("[object] new {}-{} (img = {})", p->id, p->uid, p->res ? p->res->GetResName() : _name); +#endif + + return p; + } + + size_t GameObjectPool::CLR_GetID(GameObject* p) noexcept + { + return p->id; + } + + intptr_t GameObjectPool::CLR_API_New() noexcept + { + return (intptr_t)(g_GameObjectPool->CLR_New()); + } + + uint64_t GameObjectPool::CLR_API_GetID(intptr_t p) noexcept + { + return g_GameObjectPool->CLR_GetID((GameObject*)p); + } } diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h index 5ff1e4ba..cb83812c 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h @@ -33,7 +33,7 @@ namespace LuaSTGPlus cpp::fixed_object_pool m_ObjectPool; uint64_t m_iUid = 0; lua_State* G_L = nullptr; - CLRFunctions* CLR_fn; + ManagedAPI* CLR_fn; // GameObject List struct _less_render { @@ -315,7 +315,18 @@ namespace LuaSTGPlus static int api_ParticleSetEmission(lua_State* L) noexcept; public: - GameObjectPool(lua_State* pL, CLRFunctions* clr_fn); + // CORECLR + + /// @brief 创建新对象 + GameObject* CLR_New() noexcept; + size_t CLR_GetID(GameObject*) noexcept; + public: + // CORECLR API + static intptr_t CLR_API_New() noexcept; + static uint64_t CLR_API_GetID(intptr_t) noexcept; + + public: + GameObjectPool(lua_State* pL, ManagedAPI* clr_fn); GameObjectPool& operator=(const GameObjectPool&) = delete; GameObjectPool(const GameObjectPool&) = delete; ~GameObjectPool(); From 0d2ecd88c9930a7ead808a8856cafb4b5b9b26c0 Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sat, 5 Apr 2025 23:09:40 +0800 Subject: [PATCH 14/21] add new gameobject support for clr --- CSharp/LuaSTG/LuaSTG.Core/Collision.cs | 12 ++ CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs | 15 +++ CSharp/LuaSTG/LuaSTG.Core/DeleteEventArgs.cs | 13 ++ CSharp/LuaSTG/LuaSTG.Core/GameObject.cs | 48 +------ CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs | 118 ++++++++++++++++++ CSharp/LuaSTG/LuaSTG.Core/LuaGameObject.cs | 32 +++++ CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs | 10 ++ CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs | 7 +- LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp | 1 + LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp | 11 +- LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp | 54 ++++++-- LuaSTG/LuaSTG/GameObject/GameObjectPool.h | 10 +- .../LuaSTG/LuaBinding/LuaInternalSource.cpp | 13 ++ 13 files changed, 289 insertions(+), 55 deletions(-) create mode 100644 CSharp/LuaSTG/LuaSTG.Core/Collision.cs create mode 100644 CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs create mode 100644 CSharp/LuaSTG/LuaSTG.Core/DeleteEventArgs.cs create mode 100644 CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs create mode 100644 CSharp/LuaSTG/LuaSTG.Core/LuaGameObject.cs diff --git a/CSharp/LuaSTG/LuaSTG.Core/Collision.cs b/CSharp/LuaSTG/LuaSTG.Core/Collision.cs new file mode 100644 index 00000000..717d9cb8 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/Collision.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + public record struct Collision(GameObjectBase other) + { + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs b/CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs new file mode 100644 index 00000000..1c49ca5f --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + public enum DeleteEventType : int + { + Bound = 0, + Del = 1, + Kill = 2, + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/DeleteEventArgs.cs b/CSharp/LuaSTG/LuaSTG.Core/DeleteEventArgs.cs new file mode 100644 index 00000000..b6a83b90 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/DeleteEventArgs.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + public record struct DeleteEventArgs(DeleteEventType DeleteEventType) + { + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/GameObject.cs b/CSharp/LuaSTG/LuaSTG.Core/GameObject.cs index 6e34ac80..8d350673 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/GameObject.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/GameObject.cs @@ -1,66 +1,28 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace LuaSTG.Core { - using static LuaSTGAPI; - - public class GameObject + public class GameObject : GameObjectBase { - internal static Dictionary _id2Obj = new(65536); - - private IntPtr _nativePtr; - - public GameObject() - { - _nativePtr = GameObject_New(); - _id2Obj.Add(GameObject_GetID(_nativePtr), this); - } - - internal GameObject(IntPtr nativePtr) - { - _nativePtr = nativePtr; - _id2Obj.Add(GameObject_GetID(_nativePtr), this); - } - - public bool IsValid() - { - return _nativePtr != 0; - } - - internal void Detach() + public GameObject() : base() { - _nativePtr = 0; - } - } - public static unsafe partial class LuaSTGAPI - { - internal static IntPtr GameObject_New() - { - return api.gameObject_New(); } - internal static ulong GameObject_GetID(IntPtr p) + public override void OnFrame() { - return api.gameObject_GetID(p); } - [UnmanagedCallersOnly] - private static void CreateLuaGameObject(IntPtr p) + public override void OnColli(Collision collision) { - _ = new GameObject(p); } - [UnmanagedCallersOnly] - private static void DetachGameObject(ulong id) + public override void OnDestroy(DeleteEventArgs args) { - GameObject._id2Obj[id].Detach(); - GameObject._id2Obj.Remove(id); } } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs b/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs new file mode 100644 index 00000000..c46dd964 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + using static LuaSTGAPI; + + public abstract class GameObjectBase + { + internal static Dictionary _id2Obj = new(65536); + + private IntPtr _nativePtr; + private ulong _id; + + internal GameObjectBase() + { + _nativePtr = GameObject_New(); + _id = GameObject_GetID(_nativePtr); + _id2Obj.Add(_id, this); + } + + internal GameObjectBase(IntPtr nativePtr) + { + _nativePtr = nativePtr; + _id = GameObject_GetID(_nativePtr); + _id2Obj.Add(_id, this); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool IsValid() + { + return _nativePtr != 0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal void Detach() + { + _nativePtr = 0; + } + + public abstract void OnFrame(); + public abstract void OnDestroy(DeleteEventArgs args); + public abstract void OnColli(Collision other); + public virtual void OnRender() + { + DefaultRenderFunc(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected void DefaultRenderFunc() + { + ThrowIfInvalid(); + GameObject_DefaultRenderFunc(_nativePtr); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ThrowIfInvalid() + { + if (!IsValid()) throw new InvalidOperationException("gameobject has been disposed."); + } + } + + public static unsafe partial class LuaSTGAPI + { + // TODO: pass non-zero arg for callback optimization + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static IntPtr GameObject_New() => api.gameObject_New(0); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static ulong GameObject_GetID(IntPtr p) => api.gameObject_GetID(p); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void GameObject_DefaultRenderFunc(IntPtr nativePtr) => api.gameObject_DefaultRenderFunc(nativePtr); + + [UnmanagedCallersOnly] + private static void CreateLuaGameObject(IntPtr p) + { + _ = new LuaGameObject(p); + } + + [UnmanagedCallersOnly] + private static void DetachGameObject(ulong id) + { + GameObjectBase._id2Obj[id].Detach(); + GameObjectBase._id2Obj.Remove(id); + } + + [UnmanagedCallersOnly] + private static void CallOnFrame(ulong id) + { + GameObjectBase._id2Obj[id].OnFrame(); + } + + [UnmanagedCallersOnly] + private static void CallOnRender(ulong id) + { + GameObjectBase._id2Obj[id].OnRender(); + } + + [UnmanagedCallersOnly] + private static void CallOnDestroy(ulong id, int reason) + { + GameObjectBase._id2Obj[id].OnDestroy(new((DeleteEventType)reason)); + } + + [UnmanagedCallersOnly] + private static void CallOnColli(ulong id, ulong otherID) + { + GameObjectBase._id2Obj[id].OnColli(new(GameObjectBase._id2Obj[otherID])); + } + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/LuaGameObject.cs b/CSharp/LuaSTG/LuaSTG.Core/LuaGameObject.cs new file mode 100644 index 00000000..d9de1e9c --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/LuaGameObject.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + public sealed class LuaGameObject : GameObjectBase + { + internal LuaGameObject(IntPtr nativePtr) : base(nativePtr) + { + + } + + public override sealed void OnFrame() + { + } + + public override void OnRender() + { + } + + public override sealed void OnDestroy(DeleteEventArgs args) + { + } + + public override sealed void OnColli(Collision collision) + { + } + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs index 3ff59051..d52fbd34 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/ManagedAPI.cs @@ -16,8 +16,13 @@ internal unsafe struct ManagedAPI public delegate* unmanaged GameExit; public delegate* unmanaged FocusLoseFunc; public delegate* unmanaged FocusGainFunc; + public delegate* unmanaged DetachGameObject; public delegate* unmanaged CreateLuaGameObject; + public delegate* unmanaged CallOnFrame; + public delegate* unmanaged CallOnRender; + public delegate* unmanaged CallOnDestroy; + public delegate* unmanaged CallOnColli; } public static unsafe partial class LuaSTGAPI @@ -66,8 +71,13 @@ private static void AssignManagedAPI(ManagedAPI* managedAPI) managedAPI->GameExit = &GameExit; managedAPI->FocusGainFunc = &FocusGainFunc; managedAPI->FocusLoseFunc = &FocusLoseFunc; + managedAPI->CreateLuaGameObject = &CreateLuaGameObject; managedAPI->DetachGameObject = &DetachGameObject; + managedAPI->CallOnFrame = &CallOnFrame; + managedAPI->CallOnRender = &CallOnRender; + managedAPI->CallOnDestroy = &CallOnDestroy; + managedAPI->CallOnColli = &CallOnColli; } } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs index c61e1fed..d96d8667 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs @@ -13,8 +13,9 @@ internal unsafe struct UnmanagedAPI { public delegate* unmanaged log; - public delegate* unmanaged gameObject_New; + public delegate* unmanaged gameObject_New; public delegate* unmanaged gameObject_GetID; + public delegate* unmanaged gameObject_DefaultRenderFunc; public delegate* unmanaged beginScene; public delegate* unmanaged endScene; @@ -28,6 +29,7 @@ public static unsafe partial class LuaSTGAPI /// /// Logging level. /// Logging message. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Log(LogLevel level, string message) { IntPtr unmanagedString = Marshal.StringToHGlobalAnsi(message); @@ -38,11 +40,13 @@ public static void Log(LogLevel level, string message) /// /// Notify engine to start rendering. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void BeginScene() => api.beginScene(); /// /// Notify engine to finish rendering. /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void EndScene() => api.endScene(); /// @@ -52,6 +56,7 @@ public static void Log(LogLevel level, string message) /// Red value. /// Green value. /// Blue value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void RenderClear(byte a, byte r, byte g, byte b) => api.renderClear(a, r, g, b); private static UnmanagedAPI api; diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp index 4d016347..5cadcb49 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp @@ -44,6 +44,7 @@ bool LuaSTGPlus::InitCLRBinding(const CLRHost* host, ManagedAPI* functions) payload.GameObject_New = GameObjectPool::CLR_API_New; payload.GameObject_GetID = GameObjectPool::CLR_API_GetID; + payload.GameObject_DefaultRenderFunc = GameObjectPool::CLR_API_DefaultRenderFunc; payload.BeginScene = BeginScene; payload.EndScene = EndScene; diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp index a8160054..cc67bb99 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp @@ -8,8 +8,9 @@ namespace LuaSTGPlus { void (CORECLR_DELEGATE_CALLTYPE* Log)(int32_t, intptr_t); - intptr_t (CORECLR_DELEGATE_CALLTYPE* GameObject_New)(); + intptr_t (CORECLR_DELEGATE_CALLTYPE* GameObject_New)(uint32_t); uint64_t (CORECLR_DELEGATE_CALLTYPE* GameObject_GetID)(intptr_t); + void (CORECLR_DELEGATE_CALLTYPE* GameObject_DefaultRenderFunc)(intptr_t); void (CORECLR_DELEGATE_CALLTYPE* BeginScene)(); void (CORECLR_DELEGATE_CALLTYPE* EndScene)(); @@ -28,8 +29,16 @@ namespace LuaSTGPlus #pragma endregion void (CORECLR_DELEGATE_CALLTYPE* DetachGameObject)(uint64_t); void (CORECLR_DELEGATE_CALLTYPE* CreateLuaGameObject)(intptr_t); + void (CORECLR_DELEGATE_CALLTYPE* CallOnFrame)(uint64_t); + void (CORECLR_DELEGATE_CALLTYPE* CallOnRender)(uint64_t); + void (CORECLR_DELEGATE_CALLTYPE* CallOnDestroy)(uint64_t, int32_t); + void (CORECLR_DELEGATE_CALLTYPE* CallOnColli)(uint64_t, uint64_t); }; + const int CLR_DESTROY_BOUNDS = 0; + const int CLR_DESTROY_DEL = 1; + const int CLR_DESTROY_KILL = 2; + typedef int (CORECLR_DELEGATE_CALLTYPE* entry_point_fn)(UnmanagedAPI*, ManagedAPI*); bool InitCLRBinding(const CLRHost* host, ManagedAPI* functions); diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp index 245f6eac..2a76a94f 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp @@ -343,6 +343,7 @@ namespace LuaSTGPlus #endif // USING_ADVANCE_GAMEOBJECT_CLASS m_pCurrentObject = p; _GameObjectCallback(L, objects_index, p, LGOBJ_CC_FRAME); + CLR_fn->CallOnFrame(p->id); m_pCurrentObject = nullptr; p->Update(); } @@ -361,6 +362,7 @@ namespace LuaSTGPlus #endif // USING_ADVANCE_GAMEOBJECT_CLASS m_pCurrentObject = p; _GameObjectCallback(L, objects_index, p, LGOBJ_CC_FRAME); + CLR_fn->CallOnFrame(p->id); m_pCurrentObject = nullptr; } } @@ -395,6 +397,7 @@ namespace LuaSTGPlus { #endif // USING_ADVANCE_GAMEOBJECT_CLASS _GameObjectCallback(G_L, ot_idx, p, LGOBJ_CC_RENDER); + CLR_fn->CallOnRender(p->id); #ifdef USING_ADVANCE_GAMEOBJECT_CLASS } else @@ -496,6 +499,7 @@ namespace LuaSTGPlus #endif // USING_ADVANCE_GAMEOBJECT_CLASS m_pCurrentObject = p; _GameObjectCallback(L, objects_index, p, LGOBJ_CC_DEL); + CLR_fn->CallOnDestroy(p->id, CLR_DESTROY_BOUNDS); m_pCurrentObject = nullptr; } } @@ -550,6 +554,7 @@ namespace LuaSTGPlus lua_pushstring(L, "luastg:leave_world_border"); // ... object class colli object "luastg:leave_world_border" lua_call(L, 2, 0); // ... object class lua_pop(L, 2); // ... + CLR_fn->CallOnDestroy(object->id, CLR_DESTROY_BOUNDS); m_pCurrentObject = nullptr; } } @@ -590,6 +595,7 @@ namespace LuaSTGPlus lua_rawgeti(L, objects_index, pB->id + 1); // ... object1 class1 colli1 object1 object2 lua_call(L, 2, 0); // ... object1 class1 lua_pop(L, 2); // ... + CLR_fn->CallOnColli(pA->id, pB->id); m_pCurrentObject = nullptr; m_LockObjectA = nullptr; m_LockObjectB = nullptr; @@ -649,6 +655,7 @@ namespace LuaSTGPlus lua_rawgeti(L, objects_index, object2->id + 1); // ... object1 class1 colli1 object1 object2 lua_call(L, 2, 0); // ... object1 class1 lua_pop(L, 2); // ... + CLR_fn->CallOnColli(object1->id, object2->id); m_pCurrentObject = nullptr; m_LockObjectA = nullptr; m_LockObjectB = nullptr; @@ -864,6 +871,7 @@ namespace LuaSTGPlus lua_insert(L, 1); // callback object ... lua_pop(L, 1); // callback object ... lua_call(L, lua_gettop(L) - 1, 0); // + CLR_fn->CallOnDestroy(p->id, (!kill_mode) ? CLR_DESTROY_DEL : CLR_DESTROY_KILL); #ifdef USING_ADVANCE_GAMEOBJECT_CLASS } #endif // USING_ADVANCE_GAMEOBJECT_CLASS @@ -1400,7 +1408,7 @@ namespace LuaSTGPlus return 0; } - GameObject* GameObjectPool::CLR_New() noexcept + GameObject* GameObjectPool::CLR_New(uint32_t callbackMask) noexcept { // 分配一个对象 GameObject* p = _AllocObject(); @@ -1409,6 +1417,38 @@ namespace LuaSTGPlus return nullptr; } +#if (defined(_DEBUG) && defined(LuaSTG_enable_GameObjectManager_Debug)) + static std::string _name(""); + spdlog::debug("[object] new {}-{} (img = {})", p->id, p->uid, p->res ? p->res->GetResName() : _name); +#endif + +#ifdef USING_ADVANCE_GAMEOBJECT_CLASS + //TODO: create by arg + //p->luaclass.CheckClassClass(G_L, 1); +#endif // USING_ADVANCE_GAMEOBJECT_CLASS + + lua_getglobal(G_L, "___clr_class"); // class ... + + // 创建对象 table + GetObjectTable(G_L); // class ... ot + lua_createtable(G_L, 3, 0); // class ... ot object + lua_pushvalue(G_L, 1); // class ... ot object class + lua_rawseti(G_L, -2, 1); // class ... ot object + lua_pushinteger(G_L, (lua_Integer)p->id); // class ... ot object id + lua_rawseti(G_L, -2, 2); // class ... ot object + lua_pushlightuserdata(G_L, p); // class ... ot object pGameObject + lua_rawseti(G_L, -2, 3); // class ... ot object + + // 设置对象 metatable + lua_rawgeti(G_L, -2, LOBJPOOL_METATABLE_IDX); // class ... ot object mt + lua_setmetatable(G_L, -2); // class ... ot object + + // 设置到全局表 ot[n] + lua_pushvalue(G_L, -1); // class ... ot object object + lua_rawseti(G_L, -3, (int)p->id + 1); // class ... ot object + + lua_settop(G_L, 0); + #if (defined(_DEBUG) && defined(LuaSTG_enable_GameObjectManager_Debug)) static std::string _name(""); spdlog::debug("[object] new {}-{} (img = {})", p->id, p->uid, p->res ? p->res->GetResName() : _name); @@ -1417,18 +1457,18 @@ namespace LuaSTGPlus return p; } - size_t GameObjectPool::CLR_GetID(GameObject* p) noexcept + intptr_t GameObjectPool::CLR_API_New(uint32_t callbackMask) noexcept { - return p->id; + return (intptr_t)(g_GameObjectPool->CLR_New(callbackMask)); } - intptr_t GameObjectPool::CLR_API_New() noexcept + uint64_t GameObjectPool::CLR_API_GetID(intptr_t p) noexcept { - return (intptr_t)(g_GameObjectPool->CLR_New()); + return ((GameObject*)p)->id; } - uint64_t GameObjectPool::CLR_API_GetID(intptr_t p) noexcept + void GameObjectPool::CLR_API_DefaultRenderFunc(intptr_t p) noexcept { - return g_GameObjectPool->CLR_GetID((GameObject*)p); + return ((GameObject*)p)->Render(); } } diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h index cb83812c..9d57b149 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h @@ -318,12 +318,16 @@ namespace LuaSTGPlus // CORECLR /// @brief 创建新对象 - GameObject* CLR_New() noexcept; - size_t CLR_GetID(GameObject*) noexcept; + GameObject* CLR_New(uint32_t) noexcept; + static void CLR_CallOnFrame(uint64_t) noexcept; + static void CLR_CallOnRender(uint64_t) noexcept; + static void CLR_CallOnDestroy(uint64_t, int32_t) noexcept; + static void CLR_CallOnColli(uint64_t, uint64_t) noexcept; public: // CORECLR API - static intptr_t CLR_API_New() noexcept; + static intptr_t CLR_API_New(uint32_t) noexcept; static uint64_t CLR_API_GetID(intptr_t) noexcept; + static void CLR_API_DefaultRenderFunc(intptr_t) noexcept; public: GameObjectPool(lua_State* pL, ManagedAPI* clr_fn); diff --git a/LuaSTG/LuaSTG/LuaBinding/LuaInternalSource.cpp b/LuaSTG/LuaSTG/LuaBinding/LuaInternalSource.cpp index b9683751..2efa1979 100644 --- a/LuaSTG/LuaSTG/LuaBinding/LuaInternalSource.cpp +++ b/LuaSTG/LuaSTG/LuaBinding/LuaInternalSource.cpp @@ -48,6 +48,19 @@ end function EventFunc(event, ...) end +local function ___clr_no_callback() end +___clr_class = +{ + [1] = ___clr_no_callback, + [2] = ___clr_no_callback, + [3] = ___clr_no_callback, + [4] = ___clr_no_callback, + [5] = ___clr_no_callback, + [6] = ___clr_no_callback, + ["is_class"] = true, + ["default_function"] = 110 +} + )"; #pragma endregion From 859cc02950a299d598971654c1711c4cb86b91ca Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sun, 13 Apr 2025 16:32:24 +0800 Subject: [PATCH 15/21] rename and add comments --- CSharp/LuaSTG/LuaSTG.Core/Collision.cs | 7 ++- CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs | 14 +++++- CSharp/LuaSTG/LuaSTG.Core/DeleteEventArgs.cs | 13 ----- CSharp/LuaSTG/LuaSTG.Core/DestroyEventArgs.cs | 17 +++++++ CSharp/LuaSTG/LuaSTG.Core/GameObject.cs | 5 +- CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs | 49 +++++++++++++++---- CSharp/LuaSTG/LuaSTG.Core/LuaGameObject.cs | 5 +- 7 files changed, 83 insertions(+), 27 deletions(-) delete mode 100644 CSharp/LuaSTG/LuaSTG.Core/DeleteEventArgs.cs create mode 100644 CSharp/LuaSTG/LuaSTG.Core/DestroyEventArgs.cs diff --git a/CSharp/LuaSTG/LuaSTG.Core/Collision.cs b/CSharp/LuaSTG/LuaSTG.Core/Collision.cs index 717d9cb8..fa2743eb 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/Collision.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/Collision.cs @@ -6,7 +6,12 @@ namespace LuaSTG.Core { - public record struct Collision(GameObjectBase other) + /// + /// Stores a collision info. + /// + /// The object which has group of first argument in CheckCollision. + /// The object which has group of second argument in CheckCollision. + public record struct Collision(GameObjectBase Self, GameObjectBase Other) { } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs b/CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs index 1c49ca5f..eb97a833 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs @@ -6,10 +6,22 @@ namespace LuaSTG.Core { - public enum DeleteEventType : int + /// + /// Type of the destroy event. + /// + public enum DestroyEventType : int { + /// + /// Destroy by out-of-bounds. + /// Bound = 0, + /// + /// Destroy by Del method. + /// Del = 1, + /// + /// Destroy by Kill method. + /// Kill = 2, } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/DeleteEventArgs.cs b/CSharp/LuaSTG/LuaSTG.Core/DeleteEventArgs.cs deleted file mode 100644 index b6a83b90..00000000 --- a/CSharp/LuaSTG/LuaSTG.Core/DeleteEventArgs.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace LuaSTG.Core -{ - public record struct DeleteEventArgs(DeleteEventType DeleteEventType) - { - } -} diff --git a/CSharp/LuaSTG/LuaSTG.Core/DestroyEventArgs.cs b/CSharp/LuaSTG/LuaSTG.Core/DestroyEventArgs.cs new file mode 100644 index 00000000..eae87a28 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/DestroyEventArgs.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + /// + /// Stores a destroy event info. + /// + /// Type of the destroy event. + public record struct DestroyEventArgs(DestroyEventType DestroyEventType) + { + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/GameObject.cs b/CSharp/LuaSTG/LuaSTG.Core/GameObject.cs index 8d350673..332ba821 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/GameObject.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/GameObject.cs @@ -6,6 +6,9 @@ namespace LuaSTG.Core { + /// + /// Base class for any objects created in CLR. + /// public class GameObject : GameObjectBase { public GameObject() : base() @@ -21,7 +24,7 @@ public override void OnColli(Collision collision) { } - public override void OnDestroy(DeleteEventArgs args) + public override void OnDestroy(DestroyEventArgs args) { } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs b/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs index c46dd964..c92a4584 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs @@ -11,27 +11,31 @@ namespace LuaSTG.Core { using static LuaSTGAPI; + /// + /// Base class for any objects created by game engine. + /// public abstract class GameObjectBase { internal static Dictionary _id2Obj = new(65536); private IntPtr _nativePtr; - private ulong _id; internal GameObjectBase() { _nativePtr = GameObject_New(); - _id = GameObject_GetID(_nativePtr); - _id2Obj.Add(_id, this); + _id2Obj.Add(GameObject_GetID(_nativePtr), this); } internal GameObjectBase(IntPtr nativePtr) { _nativePtr = nativePtr; - _id = GameObject_GetID(_nativePtr); - _id2Obj.Add(_id, this); + _id2Obj.Add(GameObject_GetID(_nativePtr), this); } + /// + /// Check whether the current gameobject is active in object pool. + /// + /// for active, otherwise . [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsValid() { @@ -44,14 +48,34 @@ internal void Detach() _nativePtr = 0; } + /// + /// When override in child class, called each frame when this gameobject is active. + /// public abstract void OnFrame(); - public abstract void OnDestroy(DeleteEventArgs args); - public abstract void OnColli(Collision other); + + /// + /// When override in child class, called when this gameobject is set to be deactivated. + /// + /// Args depends on the call site. + public abstract void OnDestroy(DestroyEventArgs args); + + /// + /// When override in child class, called when a collision detected. + /// + /// Info of the collision. + public abstract void OnColli(Collision collision); + + /// + /// When override in child class, called when this gameobject is being rendered. + /// public virtual void OnRender() { DefaultRenderFunc(); } + /// + /// Call default render func for current game object. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] protected void DefaultRenderFunc() { @@ -59,8 +83,12 @@ protected void DefaultRenderFunc() GameObject_DefaultRenderFunc(_nativePtr); } + /// + /// Throw an exception if the current gameobject is active in object pool. + /// + /// Exception thrown if not in valid state. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ThrowIfInvalid() + protected void ThrowIfInvalid() { if (!IsValid()) throw new InvalidOperationException("gameobject has been disposed."); } @@ -106,13 +134,14 @@ private static void CallOnRender(ulong id) [UnmanagedCallersOnly] private static void CallOnDestroy(ulong id, int reason) { - GameObjectBase._id2Obj[id].OnDestroy(new((DeleteEventType)reason)); + GameObjectBase._id2Obj[id].OnDestroy(new((DestroyEventType)reason)); } [UnmanagedCallersOnly] private static void CallOnColli(ulong id, ulong otherID) { - GameObjectBase._id2Obj[id].OnColli(new(GameObjectBase._id2Obj[otherID])); + var self = GameObjectBase._id2Obj[id]; + self.OnColli(new(self, GameObjectBase._id2Obj[otherID])); } } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/LuaGameObject.cs b/CSharp/LuaSTG/LuaSTG.Core/LuaGameObject.cs index d9de1e9c..b9052442 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/LuaGameObject.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/LuaGameObject.cs @@ -6,6 +6,9 @@ namespace LuaSTG.Core { + /// + /// Gameobject instances created by lua script. This object should not be instantiated by user. + /// public sealed class LuaGameObject : GameObjectBase { internal LuaGameObject(IntPtr nativePtr) : base(nativePtr) @@ -21,7 +24,7 @@ public override void OnRender() { } - public override sealed void OnDestroy(DeleteEventArgs args) + public override sealed void OnDestroy(DestroyEventArgs args) { } From 83ad8c9f43c4f81a92b99f301907f5b6ef55185b Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sun, 13 Apr 2025 16:48:39 +0800 Subject: [PATCH 16/21] remove redundant declaration --- LuaSTG/LuaSTG/GameObject/GameObjectPool.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h index 9d57b149..667c2b3a 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h @@ -319,10 +319,6 @@ namespace LuaSTGPlus /// @brief 创建新对象 GameObject* CLR_New(uint32_t) noexcept; - static void CLR_CallOnFrame(uint64_t) noexcept; - static void CLR_CallOnRender(uint64_t) noexcept; - static void CLR_CallOnDestroy(uint64_t, int32_t) noexcept; - static void CLR_CallOnColli(uint64_t, uint64_t) noexcept; public: // CORECLR API static intptr_t CLR_API_New(uint32_t) noexcept; From 62dd93c37a4646d567184e9052badf0367499d06 Mon Sep 17 00:00:00 2001 From: czh098tom Date: Thu, 17 Apr 2025 22:58:50 +0800 Subject: [PATCH 17/21] add del and objlist --- .../{DelEventArgs.cs => DestroyEventType.cs} | 0 CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs | 37 +++++-- CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs | 6 +- LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp | 97 ++++++++++++------- LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp | 40 ++++++-- LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp | 58 +++++------ LuaSTG/LuaSTG/GameObject/GameObjectPool.h | 10 +- 7 files changed, 153 insertions(+), 95 deletions(-) rename CSharp/LuaSTG/LuaSTG.Core/{DelEventArgs.cs => DestroyEventType.cs} (100%) diff --git a/CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs b/CSharp/LuaSTG/LuaSTG.Core/DestroyEventType.cs similarity index 100% rename from CSharp/LuaSTG/LuaSTG.Core/DelEventArgs.cs rename to CSharp/LuaSTG/LuaSTG.Core/DestroyEventType.cs diff --git a/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs b/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs index c92a4584..5de2da54 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs @@ -16,9 +16,9 @@ namespace LuaSTG.Core /// public abstract class GameObjectBase { - internal static Dictionary _id2Obj = new(65536); + internal static GameObjectBase?[] _id2Obj = new GameObjectBase[65536]; - private IntPtr _nativePtr; + internal IntPtr _nativePtr; internal GameObjectBase() { @@ -101,11 +101,28 @@ public static unsafe partial class LuaSTGAPI internal static IntPtr GameObject_New() => api.gameObject_New(0); [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static ulong GameObject_GetID(IntPtr p) => api.gameObject_GetID(p); + internal static int GameObject_GetID(IntPtr p) => api.gameObject_GetID(p); [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void GameObject_DefaultRenderFunc(IntPtr nativePtr) => api.gameObject_DefaultRenderFunc(nativePtr); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Del(GameObjectBase gameObject, bool killMode = false) + { + api.Del(gameObject._nativePtr, (byte)(killMode ? 1 : 0)); + } + + public static IEnumerable ObjList(long groupID) + { + for (var id = FirstObject(groupID); id >= 0; id = NextObject(groupID, id)) + { + yield return GameObjectBase._id2Obj[id]!; + } + } + + private static int FirstObject(long groupID) => api.FirstObject(groupID); + private static int NextObject(long groupID, int id) => api.NextObject(groupID, id); + [UnmanagedCallersOnly] private static void CreateLuaGameObject(IntPtr p) { @@ -115,33 +132,33 @@ private static void CreateLuaGameObject(IntPtr p) [UnmanagedCallersOnly] private static void DetachGameObject(ulong id) { - GameObjectBase._id2Obj[id].Detach(); - GameObjectBase._id2Obj.Remove(id); + GameObjectBase._id2Obj[id]!.Detach(); + GameObjectBase._id2Obj[id] = null; } [UnmanagedCallersOnly] private static void CallOnFrame(ulong id) { - GameObjectBase._id2Obj[id].OnFrame(); + GameObjectBase._id2Obj[id]!.OnFrame(); } [UnmanagedCallersOnly] private static void CallOnRender(ulong id) { - GameObjectBase._id2Obj[id].OnRender(); + GameObjectBase._id2Obj[id]!.OnRender(); } [UnmanagedCallersOnly] private static void CallOnDestroy(ulong id, int reason) { - GameObjectBase._id2Obj[id].OnDestroy(new((DestroyEventType)reason)); + GameObjectBase._id2Obj[id]!.OnDestroy(new((DestroyEventType)reason)); } [UnmanagedCallersOnly] private static void CallOnColli(ulong id, ulong otherID) { - var self = GameObjectBase._id2Obj[id]; - self.OnColli(new(self, GameObjectBase._id2Obj[otherID])); + var self = GameObjectBase._id2Obj[id]!; + self.OnColli(new(self, GameObjectBase._id2Obj[otherID]!)); } } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs index d96d8667..42317046 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/UnmanagedAPI.cs @@ -14,9 +14,13 @@ internal unsafe struct UnmanagedAPI public delegate* unmanaged log; public delegate* unmanaged gameObject_New; - public delegate* unmanaged gameObject_GetID; + public delegate* unmanaged gameObject_GetID; public delegate* unmanaged gameObject_DefaultRenderFunc; + public delegate* unmanaged Del; + public delegate* unmanaged FirstObject; + public delegate* unmanaged NextObject; + public delegate* unmanaged beginScene; public delegate* unmanaged endScene; public delegate* unmanaged renderClear; diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp index 5cadcb49..3cc16ee8 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp @@ -4,56 +4,79 @@ inline Core::Graphics::IRenderer* LR2D() { return LAPP.GetAppModel()->getRenderer(); } -void BeginScene() +namespace LuaSTGPlus { - LR2D()->beginBatch(); -} + void CLRBinding::Log(int32_t level, intptr_t str) + { + spdlog::log(static_cast(level), "[CSharp] {}", std::string_view((char*)str)); + } -void EndScene() -{ - LR2D()->endBatch(); -} + intptr_t CLRBinding::GameObject_New(uint32_t callbackMask) + { + return (intptr_t)(GameObjectPool::GetInstance()->CLR_New(callbackMask)); + } -void RenderClear(uint8_t a, uint8_t r, uint8_t g, uint8_t b) -{ - Core::Color4B color(r, g, b, a); - LR2D()->clearRenderTarget(color); -} + int32_t CLRBinding::GameObject_GetID(intptr_t p) + { + return ((GameObject*)p)->id; + } -void Log(int32_t level, intptr_t str) -{ - spdlog::log(static_cast(level), "[CSharp] {}", std::string_view((char*)str)); -} + void CLRBinding::GameObject_DefaultRenderFunc(intptr_t p) + { + ((GameObject*)p)->Render(); + } -bool LuaSTGPlus::InitCLRBinding(const CLRHost* host, ManagedAPI* functions) -{ - void* fn = nullptr; - if (host->load_assembly_and_get_function_pointer( - L".\\Managed\\net8.0\\LuaSTG.dll", - L"LuaSTG.Core.LuaSTGAPI, LuaSTG.Core", - L"StartUp", - UNMANAGEDCALLERSONLY_METHOD, - &fn) || !fn) + void CLRBinding::Del(intptr_t p, bool kill_mode) { - return false; + GameObjectPool::GetInstance()->Del((GameObject*)p, kill_mode); } - UnmanagedAPI payload{}; + int32_t CLRBinding::FirstObject(int64_t group_id) + { + return GameObjectPool::GetInstance()->FirstObject(static_cast(group_id)); + } - payload.Log = Log; + int32_t CLRBinding::NextObject(int64_t group_id, int32_t id) + { + return GameObjectPool::GetInstance()->NextObject(static_cast(group_id), id); + } - payload.GameObject_New = GameObjectPool::CLR_API_New; - payload.GameObject_GetID = GameObjectPool::CLR_API_GetID; - payload.GameObject_DefaultRenderFunc = GameObjectPool::CLR_API_DefaultRenderFunc; + void CLRBinding::BeginScene() + { + LR2D()->beginBatch(); + } - payload.BeginScene = BeginScene; - payload.EndScene = EndScene; - payload.RenderClear = RenderClear; + void CLRBinding::EndScene() + { + LR2D()->endBatch(); + } - if (((entry_point_fn)fn)(&payload, functions)) + void CLRBinding::RenderClear(uint8_t a, uint8_t r, uint8_t g, uint8_t b) { - return false; + Core::Color4B color(r, g, b, a); + LR2D()->clearRenderTarget(color); } - return true; + bool InitCLRBinding(const CLRHost* host, ManagedAPI* functions) + { + void* fn = nullptr; + if (host->load_assembly_and_get_function_pointer( + L".\\Managed\\net8.0\\LuaSTG.dll", + L"LuaSTG.Core.LuaSTGAPI, LuaSTG.Core", + L"StartUp", + UNMANAGEDCALLERSONLY_METHOD, + &fn) || !fn) + { + return false; + } + + UnmanagedAPI payload{}; + + if (((entry_point_fn)fn)(&payload, functions)) + { + return false; + } + + return true; + } } diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp index cc67bb99..8f82e616 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp @@ -4,17 +4,39 @@ namespace LuaSTGPlus { - struct UnmanagedAPI - { - void (CORECLR_DELEGATE_CALLTYPE* Log)(int32_t, intptr_t); +#define BINDING_METHODS \ + DECLARE_CLR_API(void, Log, (int32_t, intptr_t)) \ + \ + DECLARE_CLR_API(intptr_t, GameObject_New, (uint32_t)) \ + DECLARE_CLR_API(int32_t, GameObject_GetID, (intptr_t)) \ + DECLARE_CLR_API(void, GameObject_DefaultRenderFunc, (intptr_t)) \ + \ + DECLARE_CLR_API(void, Del, (intptr_t, bool)) \ + \ + DECLARE_CLR_API(int32_t, FirstObject, (int64_t)) \ + DECLARE_CLR_API(int32_t, NextObject, (int64_t, int32_t)) \ + \ + DECLARE_CLR_API(void, BeginScene, ()) \ + DECLARE_CLR_API(void, EndScene, ()) \ + DECLARE_CLR_API(void, RenderClear, (uint8_t, uint8_t, uint8_t, uint8_t)) + + class CLRBinding { + public: +#define DECLARE_CLR_API(ReturnType, Name, Params) static ReturnType Name Params; + BINDING_METHODS +#undef DECLARE_CLR_API + }; - intptr_t (CORECLR_DELEGATE_CALLTYPE* GameObject_New)(uint32_t); - uint64_t (CORECLR_DELEGATE_CALLTYPE* GameObject_GetID)(intptr_t); - void (CORECLR_DELEGATE_CALLTYPE* GameObject_DefaultRenderFunc)(intptr_t); + struct UnmanagedAPI { +#define DECLARE_CLR_API(ReturnType, Name, Params) ReturnType (CORECLR_DELEGATE_CALLTYPE* Name) Params; + BINDING_METHODS +#undef DECLARE_CLR_API - void (CORECLR_DELEGATE_CALLTYPE* BeginScene)(); - void (CORECLR_DELEGATE_CALLTYPE* EndScene)(); - void (CORECLR_DELEGATE_CALLTYPE* RenderClear)(uint8_t, uint8_t, uint8_t, uint8_t); + UnmanagedAPI() { +#define DECLARE_CLR_API(ReturnType, Name, Params) Name = CLRBinding::Name; + BINDING_METHODS +#undef DECLARE_CLR_API + } }; struct ManagedAPI diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp index 2a76a94f..5e4f363e 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp @@ -254,6 +254,29 @@ namespace LuaSTGPlus lua_pop(L, 2); // ??? ot } + void LuaSTGPlus::GameObjectPool::Del(GameObject* p, bool kill_mode) noexcept + { + if (p->status == GameObjectStatus::Active) + { + // 标记为即将回收的状态 + p->status = (!kill_mode) ? GameObjectStatus::Dead : GameObjectStatus::Killed; + // 回调 +#ifdef USING_ADVANCE_GAMEOBJECT_CLASS + if (!(!kill_mode && p->luaclass.IsDefaultDestroy) && !(kill_mode && p->luaclass.IsDefaultLegacyKill)) + { +#endif // USING_ADVANCE_GAMEOBJECT_CLASS + lua_rawgeti(G_L, 1, 1); // object ... class + lua_rawgeti(G_L, -1, (!kill_mode) ? LGOBJ_CC_DEL : LGOBJ_CC_KILL); // object ... class callback + lua_insert(G_L, 1); // callback object ... + lua_pop(G_L, 1); // callback object ... + lua_call(G_L, lua_gettop(G_L) - 1, 0); // + CLR_fn->CallOnDestroy(p->id, (!kill_mode) ? CLR_DESTROY_DEL : CLR_DESTROY_KILL); +#ifdef USING_ADVANCE_GAMEOBJECT_CLASS + } +#endif // USING_ADVANCE_GAMEOBJECT_CLASS + } + } + // -------------------------------------------------------------------------------- void GameObjectPool::DebugNextFrame() @@ -857,25 +880,7 @@ namespace LuaSTGPlus int GameObjectPool::Del(lua_State* L, bool kill_mode) noexcept { GameObject* p = _ToGameObject(L, 1); - if (p->status == GameObjectStatus::Active) - { - // 标记为即将回收的状态 - p->status = (!kill_mode) ? GameObjectStatus::Dead : GameObjectStatus::Killed; - // 回调 -#ifdef USING_ADVANCE_GAMEOBJECT_CLASS - if (!(!kill_mode && p->luaclass.IsDefaultDestroy) && !(kill_mode && p->luaclass.IsDefaultLegacyKill)) - { -#endif // USING_ADVANCE_GAMEOBJECT_CLASS - lua_rawgeti(L, 1, 1); // object ... class - lua_rawgeti(L, -1, (!kill_mode) ? LGOBJ_CC_DEL : LGOBJ_CC_KILL); // object ... class callback - lua_insert(L, 1); // callback object ... - lua_pop(L, 1); // callback object ... - lua_call(L, lua_gettop(L) - 1, 0); // - CLR_fn->CallOnDestroy(p->id, (!kill_mode) ? CLR_DESTROY_DEL : CLR_DESTROY_KILL); -#ifdef USING_ADVANCE_GAMEOBJECT_CLASS - } -#endif // USING_ADVANCE_GAMEOBJECT_CLASS - } + Del(p, kill_mode); return 0; } int GameObjectPool::IsValid(lua_State* L) noexcept @@ -1456,19 +1461,8 @@ namespace LuaSTGPlus return p; } - - intptr_t GameObjectPool::CLR_API_New(uint32_t callbackMask) noexcept - { - return (intptr_t)(g_GameObjectPool->CLR_New(callbackMask)); - } - - uint64_t GameObjectPool::CLR_API_GetID(intptr_t p) noexcept - { - return ((GameObject*)p)->id; - } - - void GameObjectPool::CLR_API_DefaultRenderFunc(intptr_t p) noexcept + GameObjectPool* GameObjectPool::GetInstance() { - return ((GameObject*)p)->Render(); + return g_GameObjectPool; } } diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h index 667c2b3a..ad6559b1 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h @@ -110,12 +110,13 @@ namespace LuaSTGPlus GameObject* _TableToGameObject(lua_State* L, int idx); void _GameObjectCallback(lua_State* L, int otidx, GameObject* p, int cbidx); - public: void DebugNextFrame(); FrameStatistics DebugGetFrameStatistics(); public: + void Del(GameObject* p, bool kill_mode = false) noexcept; + int PushCurrentObject(lua_State* L) noexcept; GameObject* CastGameObject(lua_State* L, int idx); @@ -319,11 +320,8 @@ namespace LuaSTGPlus /// @brief 创建新对象 GameObject* CLR_New(uint32_t) noexcept; - public: - // CORECLR API - static intptr_t CLR_API_New(uint32_t) noexcept; - static uint64_t CLR_API_GetID(intptr_t) noexcept; - static void CLR_API_DefaultRenderFunc(intptr_t) noexcept; + + static GameObjectPool* GetInstance(); public: GameObjectPool(lua_State* pL, ManagedAPI* clr_fn); From 1e1645017f8b8bfe20d7a1768b4eb06872e162fe Mon Sep 17 00:00:00 2001 From: czh098tom Date: Fri, 9 May 2025 22:01:20 +0800 Subject: [PATCH 18/21] add obj properties --- CSharp/LuaSTG/LuaSTG.Core/BlendMode.cs | 12 + CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs | 253 +++++++++++++++++++- 2 files changed, 262 insertions(+), 3 deletions(-) create mode 100644 CSharp/LuaSTG/LuaSTG.Core/BlendMode.cs diff --git a/CSharp/LuaSTG/LuaSTG.Core/BlendMode.cs b/CSharp/LuaSTG/LuaSTG.Core/BlendMode.cs new file mode 100644 index 00000000..eea85079 --- /dev/null +++ b/CSharp/LuaSTG/LuaSTG.Core/BlendMode.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LuaSTG.Core +{ + public enum BlendMode : int + { + } +} diff --git a/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs b/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs index 5de2da54..2fbfaebd 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs @@ -14,22 +14,48 @@ namespace LuaSTG.Core /// /// Base class for any objects created by game engine. /// - public abstract class GameObjectBase + public unsafe abstract class GameObjectBase { + public enum GameObjectStatus : int + { + /// + /// Available state + /// + Free = 0, + + /// + /// Normal state, active in object pool. + /// + Active = 1, + + /// + /// End of life cycle. + /// + Dead = 2, + + /// + /// End of life cycle. + /// + Killed = 4, + } + internal static GameObjectBase?[] _id2Obj = new GameObjectBase[65536]; internal IntPtr _nativePtr; + private GameObject* _nativePtrConverted; internal GameObjectBase() { _nativePtr = GameObject_New(); - _id2Obj.Add(GameObject_GetID(_nativePtr), this); + _nativePtrConverted = (GameObject*)_nativePtr.ToPointer(); + _id2Obj[GameObject_GetID(_nativePtr)] = this; } internal GameObjectBase(IntPtr nativePtr) { _nativePtr = nativePtr; - _id2Obj.Add(GameObject_GetID(_nativePtr), this); + _nativePtrConverted = (GameObject*)_nativePtr.ToPointer(); + _id2Obj[GameObject_GetID(_nativePtr)] = this; } /// @@ -46,6 +72,7 @@ public bool IsValid() internal void Detach() { _nativePtr = 0; + _nativePtrConverted = null; } /// @@ -92,6 +119,226 @@ protected void ThrowIfInvalid() { if (!IsValid()) throw new InvalidOperationException("gameobject has been disposed."); } + + #region properties + + public GameObjectStatus Status + { + get => _nativePtrConverted->status; + } + + public double X + { + get => _nativePtrConverted->x; + set => _nativePtrConverted->x = value; + } + + public double Y + { + get => _nativePtrConverted->y; + set => _nativePtrConverted->y = value; + } + + public double LastX + { + get => _nativePtrConverted->lastx; + } + + public double LastY + { + get => _nativePtrConverted->lasty; + } + + public double DX + { + get => _nativePtrConverted->dx; + } + + public double DY + { + get => _nativePtrConverted->dy; + } + + public double VX + { + get => _nativePtrConverted->vx; + set => _nativePtrConverted->vx = value; + } + + public double VY + { + get => _nativePtrConverted->vy; + set => _nativePtrConverted->vy = value; + } + + public double AX + { + get => _nativePtrConverted->ax; + set => _nativePtrConverted->ax = value; + } + + public double AY + { + get => _nativePtrConverted->ay; + set => _nativePtrConverted->ay = value; + } + + public double MaxVX + { + get => _nativePtrConverted->maxvx; + set => _nativePtrConverted->maxvx = value; + } + + public double MaxVY + { + get => _nativePtrConverted->maxvy; + set => _nativePtrConverted->maxvy = value; + } + + public double MaxV + { + get => _nativePtrConverted->maxv; + set => _nativePtrConverted->maxv = value; + } + + public long Group + { + get => _nativePtrConverted->group; + // TODO: API + //set => ((GameObject*)_nativePtr.ToPointer())->group = value; + } + + public bool Bound + { + get => _nativePtrConverted->bound != 0; + set => _nativePtrConverted->bound = value ? (byte)0 : (byte)1; + } + + public bool Colli + { + get => _nativePtrConverted->colli != 0; + set => _nativePtrConverted->colli = value ? (byte)0 : (byte)1; + } + + public bool Rect + { + get => _nativePtrConverted->rect != 0; + set => _nativePtrConverted->rect = value ? (byte)0 : (byte)1; + } + + public double A + { + get => _nativePtrConverted->a; + set => _nativePtrConverted->a = value; + } + + public double B + { + get => _nativePtrConverted->b; + set => _nativePtrConverted->b = value; + } + + public double Layer + { + get => _nativePtrConverted->layer; + // TODO: API + //set => _nativePtrConverted->layer = value; + } + + public double HScale + { + get => _nativePtrConverted->hscale; + set => _nativePtrConverted->hscale = value; + } + + public double VScale + { + get => _nativePtrConverted->vscale; + set => _nativePtrConverted->vscale = value; + } + + public double Rot + { + get => _nativePtrConverted->rot; + set => _nativePtrConverted->rot = value; + } + + public double Omega + { + get => _nativePtrConverted->omega; + set => _nativePtrConverted->omega = value; + } + + public bool Hide + { + get => _nativePtrConverted->hide != 0; + set => _nativePtrConverted->hide = value ? (byte)0 : (byte)1; + } + + public bool Navi + { + get => _nativePtrConverted->navi != 0; + set => _nativePtrConverted->navi = value ? (byte)0 : (byte)1; + } + + + public long Timer + { + get => _nativePtrConverted->timer; + set => _nativePtrConverted->timer = value; + } + + [StructLayout(LayoutKind.Explicit, Size = 320)] + private struct GameObject + { + [FieldOffset(0)] public IntPtr pUpdatePrev; + [FieldOffset(8)] public IntPtr pUpdateNext; + [FieldOffset(16)] public IntPtr pColliPrev; + [FieldOffset(24)] public IntPtr pColliNext; + [FieldOffset(32)] public GameObjectStatus status; + [FieldOffset(36)] public int luaclass; + [FieldOffset(40)] public long uid; + [FieldOffset(48)] public long id; + [FieldOffset(56)] public long world; + [FieldOffset(64)] public double lastx; + [FieldOffset(72)] public double lasty; + [FieldOffset(80)] public double x; + [FieldOffset(88)] public double y; + [FieldOffset(96)] public double dx; + [FieldOffset(104)] public double dy; + [FieldOffset(112)] public double vx; + [FieldOffset(120)] public double vy; + [FieldOffset(128)] public double ax; + [FieldOffset(136)] public double ay; + [FieldOffset(144)] public double maxvx; + [FieldOffset(152)] public double maxvy; + [FieldOffset(160)] public double maxv; + [FieldOffset(168)] public double ag; + [FieldOffset(176)] public long group; + [FieldOffset(184)] public byte bound; + [FieldOffset(185)] public byte colli; + [FieldOffset(186)] public byte rect; + [FieldOffset(192)] public double a; + [FieldOffset(200)] public double b; + [FieldOffset(208)] public double col_r; + [FieldOffset(216)] public double layer; + [FieldOffset(224)] public double nextlayer; + [FieldOffset(232)] public double hscale; + [FieldOffset(240)] public double vscale; + [FieldOffset(248)] public double rot; + [FieldOffset(256)] public double omega; + [FieldOffset(264)] public BlendMode blendmode; + [FieldOffset(268)] public uint vertexcolor; + [FieldOffset(272)] public long ani_timer; + [FieldOffset(280)] public byte hide; + [FieldOffset(281)] public byte navi; + [FieldOffset(288)] public IntPtr res; + [FieldOffset(296)] public IntPtr ps; + [FieldOffset(304)] public long timer; + [FieldOffset(312)] public byte ignore_superpause; + [FieldOffset(313)] public byte touch_lastx_lasty; + } + #endregion } public static unsafe partial class LuaSTGAPI From 8d78411ba7d27d9c806ea5c9dd325b5183ace858 Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sat, 10 May 2025 00:49:01 +0800 Subject: [PATCH 19/21] fix compile error --- LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp | 6 +++--- LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp | 2 +- LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp | 20 ++++++++++---------- LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp | 2 +- LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp | 12 ++++++------ 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp index 3cc16ee8..60c6aeee 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.cpp @@ -2,9 +2,9 @@ #include "LuaWrapper.hpp" #include "AppFrame.h" -inline Core::Graphics::IRenderer* LR2D() { return LAPP.GetAppModel()->getRenderer(); } +inline core::Graphics::IRenderer* LR2D() { return LAPP.GetAppModel()->getRenderer(); } -namespace LuaSTGPlus +namespace luastg { void CLRBinding::Log(int32_t level, intptr_t str) { @@ -53,7 +53,7 @@ namespace LuaSTGPlus void CLRBinding::RenderClear(uint8_t a, uint8_t r, uint8_t g, uint8_t b) { - Core::Color4B color(r, g, b, a); + core::Color4B color(r, g, b, a); LR2D()->clearRenderTarget(color); } diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp index 8f82e616..3fd2215d 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRBinding.hpp @@ -2,7 +2,7 @@ #include "CLRBinding/CLRHost.hpp" -namespace LuaSTGPlus +namespace luastg { #define BINDING_METHODS \ DECLARE_CLR_API(void, Log, (int32_t, intptr_t)) \ diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp b/LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp index bfacf3e0..9eef7ac9 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRHost.cpp @@ -5,21 +5,21 @@ #include "CLRHost.hpp" -void* LuaSTGPlus::CLRHost::load_library(const char_t* path) +void* luastg::CLRHost::load_library(const char_t* path) { HMODULE h = ::LoadLibraryW(path); assert(h != nullptr); return (void*)h; } -void* LuaSTGPlus::CLRHost::get_export(void* h, const char* name) +void* luastg::CLRHost::get_export(void* h, const char* name) { void* f = ::GetProcAddress((HMODULE)h, name); assert(f != nullptr); return f; } -bool LuaSTGPlus::CLRHost::init_hostfxr() +bool luastg::CLRHost::init_hostfxr() { // Pre-allocate a large buffer for the path to hostfxr char_t buffer[MAX_PATH]; @@ -37,7 +37,7 @@ bool LuaSTGPlus::CLRHost::init_hostfxr() return (_init_runtime && _get_delegate && _close_context); } -bool LuaSTGPlus::CLRHost::get_dotnet_load_assembly_config(const char_t* config_path) +bool luastg::CLRHost::get_dotnet_load_assembly_config(const char_t* config_path) { hostfxr_handle cxt = nullptr; int rc = _init_runtime(config_path, nullptr, &cxt); @@ -90,7 +90,7 @@ bool LuaSTGPlus::CLRHost::get_dotnet_load_assembly_config(const char_t* config_p return true; } -LuaSTGPlus::CLRHost::CLRHost(const char_t* config_path) +luastg::CLRHost::CLRHost(const char_t* config_path) { _init_runtime = nullptr; _get_delegate = nullptr; @@ -103,12 +103,12 @@ LuaSTGPlus::CLRHost::CLRHost(const char_t* config_path) _config_path = config_path; } -bool LuaSTGPlus::CLRHost::init() +bool luastg::CLRHost::init() { return init_hostfxr() && get_dotnet_load_assembly_config(_config_path); } -int LuaSTGPlus::CLRHost::load_assembly_and_get_function_pointer( +int luastg::CLRHost::load_assembly_and_get_function_pointer( const char_t* assembly_path, const char_t* type_name, const char_t* method_name, @@ -125,7 +125,7 @@ int LuaSTGPlus::CLRHost::load_assembly_and_get_function_pointer( ); } -int LuaSTGPlus::CLRHost::load_assembly(const char_t* assembly_path) const +int luastg::CLRHost::load_assembly(const char_t* assembly_path) const { return _load_assembly( assembly_path, @@ -134,7 +134,7 @@ int LuaSTGPlus::CLRHost::load_assembly(const char_t* assembly_path) const ); } -int LuaSTGPlus::CLRHost::get_function_pointer( +int luastg::CLRHost::get_function_pointer( const char_t* type_name, const char_t* method_name, const char_t* delegate_type_name, @@ -150,6 +150,6 @@ int LuaSTGPlus::CLRHost::get_function_pointer( ); } -LuaSTGPlus::CLRHost::~CLRHost() +luastg::CLRHost::~CLRHost() { } \ No newline at end of file diff --git a/LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp b/LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp index df91182e..a714cd4e 100644 --- a/LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp +++ b/LuaSTG/LuaSTG/CLRBinding/CLRHost.hpp @@ -4,7 +4,7 @@ #include #include -namespace LuaSTGPlus +namespace luastg { class CLRHost { diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp index 406321ab..82b11322 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp @@ -868,7 +868,7 @@ namespace luastg _InsertToRenderList(p); _InsertToColliLinkList(p, (size_t)p->group); } - void LuaSTGPlus::GameObjectPool::Del(GameObject* p, bool kill_mode) noexcept + void GameObjectPool::Del(GameObject* p, bool kill_mode) noexcept { if (p->status == GameObjectStatus::Active) { @@ -877,11 +877,11 @@ namespace luastg // 回调 if ((!kill_mode && p->features.has_callback_destroy) || (kill_mode && p->features.has_callback_legacy_kill)) { - lua_rawgeti(L, 1, 1); // object ... class - lua_rawgeti(L, -1, (!kill_mode) ? LGOBJ_CC_DEL : LGOBJ_CC_KILL); // object ... class callback - lua_insert(L, 1); // callback object ... - lua_pop(L, 1); // callback object ... - lua_call(L, lua_gettop(L) - 1, 0); // + lua_rawgeti(G_L, 1, 1); // object ... class + lua_rawgeti(G_L, -1, (!kill_mode) ? LGOBJ_CC_DEL : LGOBJ_CC_KILL); // object ... class callback + lua_insert(G_L, 1); // callback object ... + lua_pop(G_L, 1); // callback object ... + lua_call(G_L, lua_gettop(G_L) - 1, 0); // } } } From 6b46f0da9e52769a2ccf827ca23d69b5cc94147f Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sat, 10 May 2025 01:47:00 +0800 Subject: [PATCH 20/21] sync gameobject struct layout change --- CSharp/LuaSTG/LuaSTG.Core/BlendMode.cs | 2 +- CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs | 194 ++++++++++++++------ 2 files changed, 142 insertions(+), 54 deletions(-) diff --git a/CSharp/LuaSTG/LuaSTG.Core/BlendMode.cs b/CSharp/LuaSTG/LuaSTG.Core/BlendMode.cs index eea85079..46f1b61b 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/BlendMode.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/BlendMode.cs @@ -6,7 +6,7 @@ namespace LuaSTG.Core { - public enum BlendMode : int + public enum BlendMode : byte { } } diff --git a/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs b/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs index 2fbfaebd..54fc32ba 100644 --- a/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs +++ b/CSharp/LuaSTG/LuaSTG.Core/GameObjectBase.cs @@ -16,7 +16,7 @@ namespace LuaSTG.Core /// public unsafe abstract class GameObjectBase { - public enum GameObjectStatus : int + public enum GameObjectStatus : byte { /// /// Available state @@ -210,20 +210,20 @@ public long Group public bool Bound { - get => _nativePtrConverted->bound != 0; - set => _nativePtrConverted->bound = value ? (byte)0 : (byte)1; + get => _nativePtrConverted->Bound; + set => _nativePtrConverted->Bound = value; } public bool Colli { - get => _nativePtrConverted->colli != 0; - set => _nativePtrConverted->colli = value ? (byte)0 : (byte)1; + get => _nativePtrConverted->Colli; + set => _nativePtrConverted->Colli = value; } public bool Rect { - get => _nativePtrConverted->rect != 0; - set => _nativePtrConverted->rect = value ? (byte)0 : (byte)1; + get => _nativePtrConverted->Rect; + set => _nativePtrConverted->Rect = value; } public double A @@ -271,14 +271,14 @@ public double Omega public bool Hide { - get => _nativePtrConverted->hide != 0; - set => _nativePtrConverted->hide = value ? (byte)0 : (byte)1; + get => _nativePtrConverted->Hide; + set => _nativePtrConverted->Hide = value; } public bool Navi { - get => _nativePtrConverted->navi != 0; - set => _nativePtrConverted->navi = value ? (byte)0 : (byte)1; + get => _nativePtrConverted->Navi; + set => _nativePtrConverted->Navi = value; } @@ -295,48 +295,136 @@ private struct GameObject [FieldOffset(8)] public IntPtr pUpdateNext; [FieldOffset(16)] public IntPtr pColliPrev; [FieldOffset(24)] public IntPtr pColliNext; - [FieldOffset(32)] public GameObjectStatus status; - [FieldOffset(36)] public int luaclass; - [FieldOffset(40)] public long uid; - [FieldOffset(48)] public long id; - [FieldOffset(56)] public long world; - [FieldOffset(64)] public double lastx; - [FieldOffset(72)] public double lasty; - [FieldOffset(80)] public double x; - [FieldOffset(88)] public double y; - [FieldOffset(96)] public double dx; - [FieldOffset(104)] public double dy; - [FieldOffset(112)] public double vx; - [FieldOffset(120)] public double vy; - [FieldOffset(128)] public double ax; - [FieldOffset(136)] public double ay; - [FieldOffset(144)] public double maxvx; - [FieldOffset(152)] public double maxvy; - [FieldOffset(160)] public double maxv; - [FieldOffset(168)] public double ag; - [FieldOffset(176)] public long group; - [FieldOffset(184)] public byte bound; - [FieldOffset(185)] public byte colli; - [FieldOffset(186)] public byte rect; - [FieldOffset(192)] public double a; - [FieldOffset(200)] public double b; - [FieldOffset(208)] public double col_r; - [FieldOffset(216)] public double layer; - [FieldOffset(224)] public double nextlayer; - [FieldOffset(232)] public double hscale; - [FieldOffset(240)] public double vscale; - [FieldOffset(248)] public double rot; - [FieldOffset(256)] public double omega; - [FieldOffset(264)] public BlendMode blendmode; - [FieldOffset(268)] public uint vertexcolor; - [FieldOffset(272)] public long ani_timer; - [FieldOffset(280)] public byte hide; - [FieldOffset(281)] public byte navi; - [FieldOffset(288)] public IntPtr res; - [FieldOffset(296)] public IntPtr ps; - [FieldOffset(304)] public long timer; - [FieldOffset(312)] public byte ignore_superpause; - [FieldOffset(313)] public byte touch_lastx_lasty; + + [FieldOffset(32)] public ulong uid; + [FieldOffset(40)] public ulong id; + + [FieldOffset(48)] public double lastx; + [FieldOffset(56)] public double lasty; + [FieldOffset(64)] public double x; + [FieldOffset(72)] public double y; + [FieldOffset(80)] public double dx; + [FieldOffset(88)] public double dy; + [FieldOffset(96)] public double vx; + [FieldOffset(104)] public double vy; + [FieldOffset(112)] public double ax; + [FieldOffset(120)] public double ay; + [FieldOffset(128)] public double maxvx; + [FieldOffset(136)] public double maxvy; + [FieldOffset(144)] public double maxv; + [FieldOffset(152)] public double ag; + + [FieldOffset(160)] public long group; + + [FieldOffset(168)] public double a; + [FieldOffset(176)] public double b; + [FieldOffset(184)] public double col_r; + [FieldOffset(192)] public double layer; + [FieldOffset(200)] public double nextlayer; + [FieldOffset(208)] public double hscale; + [FieldOffset(216)] public double vscale; + [FieldOffset(224)] public double rot; + [FieldOffset(232)] public double omega; + [FieldOffset(240)] public double ani_timer; + + [FieldOffset(248)] public IntPtr res; + [FieldOffset(256)] public IntPtr ps; + + [FieldOffset(264)] public long timer; + + [FieldOffset(272)] public uint vertexcolor; + + [FieldOffset(276)] public BlendMode blendmode; + //[FieldOffset(277)] public GameObjectFeatures features; + [FieldOffset(278)] public GameObjectStatus status; + + // 位域标志位集合 + [FieldOffset(279)] public byte flags; + + // 位域访问属性 + public bool Bound + { + readonly get => (flags & (1 << 0)) != 0; + set + { + if (value) + flags |= (1 << 0); + else + flags &= unchecked((byte)~(1 << 0)); + } + } + + public bool Colli + { + readonly get => (flags & (1 << 1)) != 0; + set + { + if (value) + flags |= (1 << 1); + else + flags &= unchecked((byte)~(1 << 1)); + } + } + + public bool Rect + { + readonly get => (flags & (1 << 2)) != 0; + set + { + if (value) + flags |= (1 << 2); + else + flags &= unchecked((byte)~(1 << 2)); + } + } + + public bool Hide + { + readonly get => (flags & (1 << 3)) != 0; + set + { + if (value) + flags |= (1 << 3); + else + flags &= unchecked((byte)~(1 << 3)); + } + } + + public bool Navi + { + readonly get => (flags & (1 << 4)) != 0; + set + { + if (value) + flags |= (1 << 4); + else + flags &= unchecked((byte)~(1 << 4)); + } + } + + public bool IgnoreSuperpause + { + readonly get => (flags & (1 << 5)) != 0; + set + { + if (value) + flags |= (1 << 5); + else + flags &= unchecked((byte)~(1 << 5)); + } + } + + public bool TouchLastXY + { + readonly get => (flags & (1 << 6)) != 0; + set + { + if (value) + flags |= (1 << 6); + else + flags &= unchecked((byte)~(1 << 6)); + } + } } #endregion } From c93628319d068ca2304da151f05d4c3528550cc7 Mon Sep 17 00:00:00 2001 From: czh098tom Date: Sat, 10 May 2025 02:03:53 +0800 Subject: [PATCH 21/21] fix crash --- LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp | 16 ++++++++++------ LuaSTG/LuaSTG/GameObject/GameObjectPool.h | 2 ++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp index 82b11322..a9cf77ea 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.cpp @@ -262,7 +262,7 @@ namespace luastg int GameObjectPool::Del(lua_State* L, bool kill_mode) noexcept { GameObject* p = _ToGameObject(L, 1); - Del(p, kill_mode); + Del(L, p, kill_mode); return 0; } @@ -869,6 +869,10 @@ namespace luastg _InsertToColliLinkList(p, (size_t)p->group); } void GameObjectPool::Del(GameObject* p, bool kill_mode) noexcept + { + Del(G_L, p, kill_mode); + } + void GameObjectPool::Del(lua_State* L, GameObject* p, bool kill_mode) noexcept { if (p->status == GameObjectStatus::Active) { @@ -877,11 +881,11 @@ namespace luastg // 回调 if ((!kill_mode && p->features.has_callback_destroy) || (kill_mode && p->features.has_callback_legacy_kill)) { - lua_rawgeti(G_L, 1, 1); // object ... class - lua_rawgeti(G_L, -1, (!kill_mode) ? LGOBJ_CC_DEL : LGOBJ_CC_KILL); // object ... class callback - lua_insert(G_L, 1); // callback object ... - lua_pop(G_L, 1); // callback object ... - lua_call(G_L, lua_gettop(G_L) - 1, 0); // + lua_rawgeti(L, 1, 1); // object ... class + lua_rawgeti(L, -1, (!kill_mode) ? LGOBJ_CC_DEL : LGOBJ_CC_KILL); // object ... class callback + lua_insert(L, 1); // callback object ... + lua_pop(L, 1); // callback object ... + lua_call(L, lua_gettop(L) - 1, 0); // } } } diff --git a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h index 9612a016..36e615e8 100644 --- a/LuaSTG/LuaSTG/GameObject/GameObjectPool.h +++ b/LuaSTG/LuaSTG/GameObject/GameObjectPool.h @@ -112,6 +112,8 @@ namespace luastg GameObject* _TableToGameObject(lua_State* L, int idx); void _GameObjectCallback(lua_State* L, int otidx, GameObject* p, int cbidx); + + void Del(lua_State* L, GameObject* p, bool kill_mode = false) noexcept; public: void DebugNextFrame(); FrameStatistics DebugGetFrameStatistics();