diff --git a/.github/workflows/meson.yml b/.github/workflows/meson.yml index bfdb6918d1..5fac9a0a2b 100644 --- a/.github/workflows/meson.yml +++ b/.github/workflows/meson.yml @@ -80,7 +80,7 @@ jobs: - name: Install Dependencies run: | sudo apt-get update -yq - sudo apt-get install --no-install-recommends wget liballegro4-dev libloadpng4-dev libflac++-dev luajit-5.1-dev liblua5.2-dev libminizip-dev liblz4-dev libpng++-dev libx11-dev libboost-dev libtbb-dev libsdl2-dev libsdl2-image-dev libopengl-dev libfuse2 ninja-build ccache + sudo apt-get install --no-install-recommends wget liballegro4-dev libloadpng4-dev libflac++-dev luajit-5.1-dev liblua5.2-dev libminizip-dev liblz4-dev libpng++-dev libx11-dev libtbb-dev libsdl2-dev libsdl2-image-dev libopengl-dev libfuse2 ninja-build ccache sudo pip install meson - name: ccache diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b036f1c72..f13f379edb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -249,6 +249,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Numbers saved with `Activity:SaveNumber()` are now kept as doubles instead of floats, and floating point numbers in INI and save files are written out exactly instead of being rounded to 6 digits. +- The Lua bindings now use LuaBridge3 instead of luabind, and the copy of boost that luabind needed is gone. Calls from Lua into the game are faster, especially method calls and property access on objects like `Actor`s. Scripts run around 30% to 45% faster. + Scripts don't need any changes. Everything that worked with luabind works the same, including setting values of their own on objects, overloads, inherited enums, setting things like `actor.Pos.X` in place, and passing numbers with fractions to whole number parameters. + A few things that used to raise an error now don't: functions added to a class from Lua (like `function MovableObject:Foo() end`) are also found on objects of derived classes, comparing two references to the same object with `==` gives `false`, reading something that doesn't exist from a class table gives `nil`, and functions that aren't overloaded convert their arguments the way Lua does (numbers to strings, any value to a boolean, missing arguments to `nil`) and ignore extra ones. Class tables like `Vector` are now tables instead of userdata. Error messages for calls with the wrong arguments are worded differently. +
Fixed diff --git a/Licences/LICENSE.LuaBridge3.txt b/Licences/LICENSE.LuaBridge3.txt new file mode 100644 index 0000000000..abe126dbca --- /dev/null +++ b/Licences/LICENSE.LuaBridge3.txt @@ -0,0 +1,27 @@ +LuaBridge3 is published under the terms of the MIT License + + http://www.opensource.org/licenses/mit-license.html + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +* Copyright 2020, kunitoki +* Copyright 2019, Dmitry Tarakanov +* Copyright 2012, Vinnie Falco +* Copyright 2008, Nigel Atkinson +* Copyright 2007, Nathan Reed diff --git a/Licences/LICENSE.luabind.txt b/Licences/LICENSE.luabind.txt deleted file mode 100644 index 799cd87c13..0000000000 --- a/Licences/LICENSE.luabind.txt +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2003 Daniel Wallin and Arvid Norberg - -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE -// OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/README.md b/README.md index 38128102b6..c00187ea36 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ This has been tested with WSL2 Ubuntu 22.04 but should work with other distribut # Linux and macOS Build Instructions The Linux build uses the meson build system, and builds against system libraries. -LuaJIT and luabind are the exception: they're always built from the copies in `external/sources`, including when cross compiling, because the game relies on changes made to them (such as LuaJIT's deterministic table ordering). So a system `luajit` isn't needed. +LuaJIT is the exception: it's always built from the copy in `external/sources`, including when cross compiling, because the game relies on changes made to it (such as its deterministic table ordering). So a system `luajit` isn't needed. ## Dependencies @@ -125,7 +125,7 @@ If you want to change the buildtype afterwards, you can use `meson configure --b `sudo python3 -m pip install meson` **Fedora:** -`# dnf install allegro-loadpng-devel allegro-devel libsdl2-devel SDL2_image-devel lua-devel boost-devel meson ninja-build flac-devel minizip-compat-devel tbb-devel lz4-devel libpng-devel lua-devel gcc gcc-c++` +`# dnf install allegro-loadpng-devel allegro-devel libsdl2-devel SDL2_image-devel lua-devel meson ninja-build flac-devel minizip-compat-devel tbb-devel lz4-devel libpng-devel lua-devel gcc gcc-c++` ## Troubleshooting diff --git a/RTEA.vcxproj b/RTEA.vcxproj index 731c2ad830..c8f5f0ccbf 100644 --- a/RTEA.vcxproj +++ b/RTEA.vcxproj @@ -162,7 +162,7 @@ /bigobj /Zm300 %(AdditionalOptions) /bigobj %(AdditionalOptions) Disabled - $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\boost_1_75;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\luabind-0.7.1\;$(ProjectDir)external\sources\luabind-0.7.1\luabind;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include + $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\LuaBridge3;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include _ITERATOR_DEBUG_LEVEL=0;ZLIB_COMPAT;_WINDOWS;WIN32;DEBUG_BUILD;DEBUGMODE;TARGET_MACHINE_X86;%(PreprocessorDefinitions) false EnableFastChecks @@ -185,9 +185,9 @@ false - winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic-32.lib;libminizip-32.lib;libpng16-static-32.lib;fmodL_vc.lib;allegro-debug-32.lib;loadpng-debug-32.lib;liblz4_debug_static.lib;luajit-debug-32.lib;luabind-debug-32.lib;raknet-debug-32.lib;sdl2main-debug-32.lib;sdl2-debug-32.lib;opengl32.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic-32.lib;libminizip-32.lib;libpng16-static-32.lib;fmodL_vc.lib;allegro-debug-32.lib;loadpng-debug-32.lib;liblz4_debug_static.lib;luajit-debug-32.lib;raknet-debug-32.lib;sdl2main-debug-32.lib;sdl2-debug-32.lib;opengl32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) - external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\luabind-0.7.1\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win\x86;%(AdditionalLibraryDirectories) + external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win\x86;%(AdditionalLibraryDirectories) DebugFull $(OutDir)$(TargetName).pdb Windows @@ -215,7 +215,7 @@ /bigobj /Zm300 %(AdditionalOptions) /bigobj %(AdditionalOptions) Disabled - $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\boost_1_75;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\luabind-0.7.1\;$(ProjectDir)external\sources\luabind-0.7.1\luabind;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include + $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\LuaBridge3;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include _ITERATOR_DEBUG_LEVEL=0;ZLIB_COMPAT;_WINDOWS;WIN32;DEBUG_BUILD;DEBUGMODE;%(PreprocessorDefinitions) false EnableFastChecks @@ -240,9 +240,9 @@ /bigobj %(AdditionalOptions) - winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug.lib;loadpng-debug.lib;liblz4_debug_static.lib;luajit-debug.lib;luabind-debug.lib;raknet-debug.lib;SDL3_image-static-debug.lib;SDL3-static-debug.lib;opengl32.lib;dbghelp.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug.lib;loadpng-debug.lib;liblz4_debug_static.lib;luajit-debug.lib;raknet-debug.lib;SDL3_image-static-debug.lib;SDL3-static-debug.lib;opengl32.lib;dbghelp.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) - external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\luabind-0.7.1\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win;%(AdditionalLibraryDirectories) + external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win;%(AdditionalLibraryDirectories) DebugFull $(OutDir)$(TargetName).pdb Windows @@ -269,7 +269,7 @@ /bigobj /Zm300 %(AdditionalOptions) /bigobj %(AdditionalOptions) Disabled - $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\boost_1_75;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\luabind-0.7.1\;$(ProjectDir)external\sources\luabind-0.7.1\luabind;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include + $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\LuaBridge3;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include _ITERATOR_DEBUG_LEVEL=0;ZLIB_COMPAT;_WINDOWS;WIN32;MIN_DEBUG_BUILD;DEBUGMODE;TARGET_MACHINE_X86;%(PreprocessorDefinitions) false EnableFastChecks @@ -292,9 +292,9 @@ #undef GetClassName - winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic-32.lib;libminizip-32.lib;libpng16-static-32.lib;fmodL_vc.lib;allegro-debug-32.lib;loadpng-debug-32.lib;liblz4_debug_static.lib;luajit-debug-release-32.lib;luabind-debug-32.lib;raknet-debug-32.lib;opengl32.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic-32.lib;libminizip-32.lib;libpng16-static-32.lib;fmodL_vc.lib;allegro-debug-32.lib;loadpng-debug-32.lib;liblz4_debug_static.lib;luajit-debug-release-32.lib;raknet-debug-32.lib;opengl32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) - external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\luabind-0.7.1\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win\x86;%(AdditionalLibraryDirectories) + external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win\x86;%(AdditionalLibraryDirectories) DebugFull $(OutDir)$(TargetName).pdb Windows @@ -322,7 +322,7 @@ /bigobj /Zm300 %(AdditionalOptions) /bigobj %(AdditionalOptions) Disabled - $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\boost_1_75;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\luabind-0.7.1\;$(ProjectDir)external\sources\luabind-0.7.1\luabind;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include + $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\LuaBridge3;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include _ITERATOR_DEBUG_LEVEL=0;ZLIB_COMPAT;_WINDOWS;WIN32;MIN_DEBUG_BUILD;DEBUGMODE;%(PreprocessorDefinitions) false EnableFastChecks @@ -347,9 +347,9 @@ /bigobj %(AdditionalOptions) - winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug.lib;loadpng-debug.lib;liblz4_debug_static.lib;luajit-debug-release.lib;luabind-debug.lib;raknet-debug.lib;SDL3-static-debug.lib;SDL3_image-static-debug.lib;opengl32.lib;dbghelp.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug.lib;loadpng-debug.lib;liblz4_debug_static.lib;luajit-debug-release.lib;raknet-debug.lib;SDL3-static-debug.lib;SDL3_image-static-debug.lib;opengl32.lib;dbghelp.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) - external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\luabind-0.7.1\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win;%(AdditionalLibraryDirectories) + external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win;%(AdditionalLibraryDirectories) DebugFull $(OutDir)$(TargetName).pdb Windows @@ -379,7 +379,7 @@ true Speed false - $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\boost_1_75;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\luabind-0.7.1\;$(ProjectDir)external\sources\luabind-0.7.1\luabind;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include + $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\LuaBridge3;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include _ITERATOR_DEBUG_LEVEL=0;ZLIB_COMPAT;_WINDOWS;WIN32;DEBUG_RELEASE_BUILD;NDEBUG;TRACY_ENABLE;TRACY_ON_DEMAND;TARGET_MACHINE_X86;%(PreprocessorDefinitions) Sync MultiThreadedDLL @@ -405,9 +405,9 @@ #undef GetClassName - winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic-32.lib;libminizip-32.lib;libpng16-static-32.lib;fmodL_vc.lib;allegro-debug-release-32.lib;loadpng-debug-release-32.lib;liblz4_release_static.lib;luajit-debug-release-32.lib;luabind-debug-release-32.lib;raknet-release-32.lib;opengl32.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic-32.lib;libminizip-32.lib;libpng16-static-32.lib;fmodL_vc.lib;allegro-debug-release-32.lib;loadpng-debug-release-32.lib;liblz4_release_static.lib;luajit-debug-release-32.lib;raknet-release-32.lib;opengl32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) - external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\luabind-0.7.1\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win\x86;%(AdditionalLibraryDirectories) + external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win\x86;%(AdditionalLibraryDirectories) true Windows true @@ -441,7 +441,7 @@ true Speed false - $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\boost_1_75;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\luabind-0.7.1\;$(ProjectDir)external\sources\luabind-0.7.1\luabind;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include + $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\LuaBridge3;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include _ITERATOR_DEBUG_LEVEL=0;ZLIB_COMPAT;_WINDOWS;WIN32;TRACY_ENABLE;TRACY_ON_DEMAND;PROFILING_BUILD;NDEBUG;TARGET_MACHINE_X86;%(PreprocessorDefinitions) Sync MultiThreadedDLL @@ -467,9 +467,9 @@ #undef GetClassName - winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic-32.lib;libminizip-32.lib;libpng16-static-32.lib;fmodL_vc.lib;allegro-debug-release-32.lib;loadpng-debug-release-32.lib;liblz4_release_static.lib;luajit-debug-release-32.lib;luabind-debug-release-32.lib;raknet-release-32.lib;opengl32.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic-32.lib;libminizip-32.lib;libpng16-static-32.lib;fmodL_vc.lib;allegro-debug-release-32.lib;loadpng-debug-release-32.lib;liblz4_release_static.lib;luajit-debug-release-32.lib;raknet-release-32.lib;opengl32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) - external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\luabind-0.7.1\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win\x86;%(AdditionalLibraryDirectories) + external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win\x86;%(AdditionalLibraryDirectories) true Windows true @@ -503,7 +503,7 @@ true Speed false - $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\boost_1_75;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\luabind-0.7.1\;$(ProjectDir)external\sources\luabind-0.7.1\luabind;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include + $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\LuaBridge3;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include _ITERATOR_DEBUG_LEVEL=0;ZLIB_COMPAT;_WINDOWS;WIN32;DEBUG_RELEASE_BUILD;NDEBUG;TRACY_ENABLE;TRACY_ON_DEMAND;%(PreprocessorDefinitions) Sync MultiThreadedDLL @@ -531,9 +531,9 @@ /bigobj %(AdditionalOptions) - winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug-release.lib;loadpng-debug-release.lib;liblz4_release_static.lib;luajit-debug-release.lib;luabind-debug-release.lib;raknet-release.lib;opengl32.lib;SDL3-static.lib;SDL3_image-static.lib;dbghelp.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug-release.lib;loadpng-debug-release.lib;liblz4_release_static.lib;luajit-debug-release.lib;raknet-release.lib;opengl32.lib;SDL3-static.lib;SDL3_image-static.lib;dbghelp.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) - external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\luabind-0.7.1\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win;%(AdditionalLibraryDirectories) + external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win;%(AdditionalLibraryDirectories) true Windows true @@ -566,7 +566,7 @@ true Speed true - $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\boost_1_75;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\luabind-0.7.1\;$(ProjectDir)external\sources\luabind-0.7.1\luabind;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include + $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\LuaBridge3;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include _ITERATOR_DEBUG_LEVEL=0;ZLIB_COMPAT;_WINDOWS;WIN32;TRACY_ENABLE;TRACY_ON_DEMAND;PROFILING_BUILD;NDEBUG;%(PreprocessorDefinitions) Sync MultiThreadedDLL @@ -594,9 +594,9 @@ /bigobj %(AdditionalOptions) - winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug-release.lib;loadpng-debug-release.lib;liblz4_release_static.lib;luajit-debug-release.lib;luabind-debug-release.lib;raknet-release.lib;opengl32.lib;SDL3-static.lib;SDL3_image-static.lib;dbghelp.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-debug-release.lib;loadpng-debug-release.lib;liblz4_release_static.lib;luajit-debug-release.lib;raknet-release.lib;opengl32.lib;SDL3-static.lib;SDL3_image-static.lib;dbghelp.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) - external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\luabind-0.7.1\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win;%(AdditionalLibraryDirectories) + external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win;%(AdditionalLibraryDirectories) true Windows true @@ -629,7 +629,7 @@ true Speed true - $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\boost_1_75;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\luabind-0.7.1\;$(ProjectDir)external\sources\luabind-0.7.1\luabind;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include + $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\LuaBridge3;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include _ITERATOR_DEBUG_LEVEL=0;ZLIB_COMPAT;_WINDOWS;WIN32;RELEASE_BUILD;NDEBUG;TRACY_ENABLE;TRACY_ON_DEMAND;TRACY_ONLY_LOCALHOST;TRACY_NO_BROADCAST;TARGET_MACHINE_X86;%(PreprocessorDefinitions) Sync MultiThreadedDLL @@ -653,9 +653,9 @@ #undef GetClassName - winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic-32.lib;libminizip-32.lib;libpng16-static-32.lib;fmodL_vc.lib;allegro-release-32.lib;loadpng-release-32.lib;liblz4_release_static.lib;luajit-release-32.lib;luabind-release-32.lib;raknet-release-32.lib;opengl32.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic-32.lib;libminizip-32.lib;libpng16-static-32.lib;fmodL_vc.lib;allegro-release-32.lib;loadpng-release-32.lib;liblz4_release_static.lib;luajit-release-32.lib;raknet-release-32.lib;opengl32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) - external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\luabind-0.7.1\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win\x86;%(AdditionalLibraryDirectories) + external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win\x86;%(AdditionalLibraryDirectories) DebugFull Windows true @@ -689,7 +689,7 @@ true Speed true - $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\boost_1_75;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\luabind-0.7.1\;$(ProjectDir)external\sources\luabind-0.7.1\luabind;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include + $(ProjectDir);$(ProjectDir)\Source;$(ProjectDir)Source\System;$(ProjectDir)Source\Lua;$(ProjectDir)Source\Entities;$(ProjectDir)Source\Activities;$(ProjectDir)Source\Managers;$(ProjectDir)Source\Menus;$(ProjectDir)Source\GUI;$(ProjectDir)Source\GUI\Wrappers;$(ProjectDir)Source\GUI\imgui;$(ProjectDir)Source\GUI\imgui\backends;$(ProjectDir)Source\Renderer;$(ProjectDir)external\include\LuaBridge3;$(ProjectDir)external\include\glm-0.9.9.8;$(ProjectDir)external\include\glad-2.0.0-beta;$(ProjectDir)external\include\LZ4-1.9.3\LZ4;$(ProjectDir)external\include\fmod-2.2.13;$(ProjectDir)external\include\thread-pool-3.5.0\include;$(ProjectDir)external\include\hopscotch-map-2.3.1\include;$(ProjectDir)external\sources\libpng-1.6.40\include;$(ProjectDir)external\sources\zlib-ng-2.1.3\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\include;$(ProjectDir)external\sources\allegro 4.4.3.1-custom\addons\loadpng;$(ProjectDir)external\sources\SDL3-3.2.10\include;$(ProjectDir)external\sources\SDL3_image-3.2.4\include;$(ProjectDir)external\sources\LuaJIT-2.1\src;$(ProjectDir)external\sources\RakNet\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\include;$(ProjectDir)external\sources\minizip-ng-4.0.0\src;$(ProjectDir)external\sources\tracy\public;$(ProjectDir)external\sources\fmem\include _ITERATOR_DEBUG_LEVEL=0;ZLIB_COMPAT;_WINDOWS;WIN32;RELEASE_BUILD;NDEBUG;TRACY_ENABLE;TRACY_ON_DEMAND;TRACY_ONLY_LOCALHOST;TRACY_NO_BROADCAST;%(PreprocessorDefinitions) Sync MultiThreadedDLL @@ -715,9 +715,9 @@ /bigobj %(AdditionalOptions) - winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-release.lib;loadpng-release.lib;liblz4_release_static.lib;luajit-release.lib;luabind-release.lib;raknet-release.lib;opengl32.lib;SDL3-static.lib;SDL3_image-static.lib;dbghelp.lib;%(AdditionalDependencies) + winmm.lib;ws2_32.lib;dinput8.lib;ddraw.lib;dxguid.lib;dsound.lib;imm32.lib;setupapi.lib;version.lib;zlibstatic.lib;libminizip.lib;libpng16-static.lib;fmod_vc.lib;allegro-release.lib;loadpng-release.lib;liblz4_release_static.lib;luajit-release.lib;raknet-release.lib;opengl32.lib;SDL3-static.lib;SDL3_image-static.lib;dbghelp.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) - external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\luabind-0.7.1\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win;%(AdditionalLibraryDirectories) + external\sources\zlib-ng-2.1.3\_Bin;external\sources\libpng-1.6.40\_Bin;external\sources\allegro 4.4.3.1-custom\_Bin;external\sources\SDL3-3.2.10\_Bin;external\sources\SDL3_image-3.2.4\_Bin;external\sources\LuaJIT-2.1\_Bin;external\sources\RakNet\_Bin;external\sources\minizip-ng-4.0.0\_Bin;external\lib\win;%(AdditionalLibraryDirectories) DebugFull Windows true @@ -761,8 +761,8 @@ - - + + @@ -961,7 +961,12 @@ NotUsing stdcpp17 - + + false + NotUsing + stdcpp17 + + false NotUsing stdcpp17 diff --git a/RTEA.vcxproj.filters b/RTEA.vcxproj.filters index e5f13d5197..43e3026631 100644 --- a/RTEA.vcxproj.filters +++ b/RTEA.vcxproj.filters @@ -547,7 +547,7 @@ Menus - + Lua @@ -562,7 +562,7 @@ GUI - + Lua @@ -1148,7 +1148,10 @@ GUI - + + Lua + + Lua diff --git a/Source/Activities/GAScripted.cpp b/Source/Activities/GAScripted.cpp index bcc7d2c7ee..e850a06ea8 100644 --- a/Source/Activities/GAScripted.cpp +++ b/Source/Activities/GAScripted.cpp @@ -175,11 +175,11 @@ void GAScripted::RefreshActivityFunctions() { } // We use m_LuaClassName here, because we ran the script file in the global state instead of in an environment - std::unordered_map scriptFileFunctions; + std::unordered_map scriptFileFunctions; g_LuaMan.GetMasterScriptState().RetrieveFunctions(m_LuaClassName, GetSupportedScriptFunctionNames(), scriptFileFunctions); for (const auto& [functionName, functionObject]: scriptFileFunctions) { - m_ScriptFunctions[functionName] = std::unique_ptr(functionObject); + m_ScriptFunctions[functionName] = std::unique_ptr(functionObject); } } @@ -355,7 +355,7 @@ void GAScripted::Draw(BITMAP* pTargetBitmap, const Vector& targetPos) { GameActivity::Draw(pTargetBitmap, targetPos); } -int GAScripted::RunLuaFunction(const std::string& functionName, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { +int GAScripted::RunLuaFunction(const std::string& functionName, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { // Call the defined function, but only after first checking if it exists auto funcItr = m_ScriptFunctions.find(functionName); if (funcItr == m_ScriptFunctions.end()) { @@ -367,7 +367,7 @@ int GAScripted::RunLuaFunction(const std::string& functionName, const std::vecto return error; } -int GAScripted::RunLuaConditionalTest(const std::string& functionName, bool& returnParam, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { +int GAScripted::RunLuaConditionalTest(const std::string& functionName, bool& returnParam, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { // Call the defined function, but only after first checking if it exists auto funcItr = m_ScriptFunctions.find(functionName); if (funcItr == m_ScriptFunctions.end()) { diff --git a/Source/Activities/GAScripted.h b/Source/Activities/GAScripted.h index 0f8c41faa7..d4b54e58a0 100644 --- a/Source/Activities/GAScripted.h +++ b/Source/Activities/GAScripted.h @@ -9,7 +9,7 @@ #include "GlobalScript.h" #include "Box.h" -#include "LuabindObjectWrapper.h" +#include "LuaObjectWrapper.h" namespace RTE { @@ -131,13 +131,13 @@ namespace RTE { /// @param targetPos The absolute position of the target bitmap's upper left corner in the scene. (default: Vector()) void Draw(BITMAP* pTargetBitmap, const Vector& targetPos = Vector()) override; - int RunLuaFunction(const std::string& functionName, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); - int RunLuaConditionalTest(const std::string& functionName, bool& returnParam, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); + int RunLuaFunction(const std::string& functionName, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); + int RunLuaConditionalTest(const std::string& functionName, bool& returnParam, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); /// Protected member variable and method declarations protected: /// Does nothing - we do this in script! Just overrides the base behaviour. - void InitAIs() override{}; + void InitAIs() override {}; // Member variables static Entity::ClassInfo m_sClass; @@ -152,7 +152,7 @@ namespace RTE { // The list of global scripts allowed to run during this activity std::vector m_GlobalScriptsList; - std::unordered_map> m_ScriptFunctions; //!< A map of LuabindObjectWrappers that hold Lua functions. Used to maintain script execution order and avoid extraneous Lua calls. + std::unordered_map> m_ScriptFunctions; //!< A map of LuaObjectWrappers that hold Lua functions. Used to maintain script execution order and avoid extraneous Lua calls. /// Private member variable and method declarations private: diff --git a/Source/Entities/MovableObject.cpp b/Source/Entities/MovableObject.cpp index fcc895303e..59a7a36fb8 100644 --- a/Source/Entities/MovableObject.cpp +++ b/Source/Entities/MovableObject.cpp @@ -563,7 +563,7 @@ int MovableObject::LoadScript(const std::string& scriptPath, bool loadAsEnabledS m_EnabledScripts.try_emplace(scriptPath, loadAsEnabledScript); m_AllLoadedScripts.push_back(scriptPath); - std::unordered_map scriptFileFunctions; + std::unordered_map scriptFileFunctions; if (usedState.RunScriptFileAndRetrieveFunctions(scriptPath, GetSupportedScriptFunctionNames(), scriptFileFunctions) < 0) { return -4; } @@ -571,7 +571,7 @@ int MovableObject::LoadScript(const std::string& scriptPath, bool loadAsEnabledS for (const auto& [functionName, functionObject]: scriptFileFunctions) { LuaFunction& luaFunction = m_FunctionsAndScripts.at(functionName).emplace_back(); luaFunction.m_ScriptIsEnabled = loadAsEnabledScript; - luaFunction.m_LuaFunction = std::unique_ptr(functionObject); + luaFunction.m_LuaFunction = std::unique_ptr(functionObject); if (functionName == "OnCollideWithTerrain") { m_HasOnCollideWithTerrainFunction = true; } @@ -669,7 +669,7 @@ void MovableObject::EnableOrDisableAllScripts(bool enableScripts) { } } -int MovableObject::RunScriptedFunctionInAppropriateScripts(const std::string& functionName, bool runOnDisabledScripts, bool stopOnError, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { +int MovableObject::RunScriptedFunctionInAppropriateScripts(const std::string& functionName, bool runOnDisabledScripts, bool stopOnError, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { int status = 0; auto itr = m_FunctionsAndScripts.find(functionName); @@ -685,11 +685,11 @@ int MovableObject::RunScriptedFunctionInAppropriateScripts(const std::string& fu ZoneScoped; ZoneText(functionName.c_str(), functionName.length()); for (const LuaFunction& luaFunction: itr->second) { - const LuabindObjectWrapper* luabindObjectWrapper = luaFunction.m_LuaFunction.get(); + const LuaObjectWrapper* luaObjectWrapper = luaFunction.m_LuaFunction.get(); if (runOnDisabledScripts || luaFunction.m_ScriptIsEnabled) { - LuaStateWrapper& usedState = GetAndLockStateForScript(luabindObjectWrapper->GetFilePath(), &luaFunction); + LuaStateWrapper& usedState = GetAndLockStateForScript(luaObjectWrapper->GetFilePath(), &luaFunction); std::lock_guard lock(usedState.GetMutex(), std::adopt_lock); - status = usedState.RunScriptFunctionObject(luabindObjectWrapper, "_ScriptedObjects", std::to_string(m_UniqueID), functionEntityArguments, functionLiteralArguments, functionObjectArguments); + status = usedState.RunScriptFunctionObject(luaObjectWrapper, "_ScriptedObjects", std::to_string(m_UniqueID), functionEntityArguments, functionLiteralArguments, functionObjectArguments); if (status < 0 && stopOnError) { return status; } @@ -708,8 +708,8 @@ int MovableObject::RunFunctionOfScript(const std::string& scriptPath, const std: std::lock_guard lock(usedState.GetMutex(), std::adopt_lock); for (const LuaFunction& luaFunction: m_FunctionsAndScripts.at(functionName)) { - const LuabindObjectWrapper* luabindObjectWrapper = luaFunction.m_LuaFunction.get(); - if (scriptPath == luabindObjectWrapper->GetFilePath() && usedState.RunScriptFunctionObject(luabindObjectWrapper, "_ScriptedObjects", std::to_string(m_UniqueID), functionEntityArguments, functionLiteralArguments) < 0) { + const LuaObjectWrapper* luaObjectWrapper = luaFunction.m_LuaFunction.get(); + if (scriptPath == luaObjectWrapper->GetFilePath() && usedState.RunScriptFunctionObject(luaObjectWrapper, "_ScriptedObjects", std::to_string(m_UniqueID), functionEntityArguments, functionLiteralArguments) < 0) { g_ConsoleMan.PrintString("ERROR: An error occured while trying to run the " + functionName + " function for script at path " + scriptPath); return -2; } diff --git a/Source/Entities/MovableObject.h b/Source/Entities/MovableObject.h index 0bf8db1680..6907abe58e 100644 --- a/Source/Entities/MovableObject.h +++ b/Source/Entities/MovableObject.h @@ -9,7 +9,7 @@ #include "Vector.h" #include "Matrix.h" #include "Timer.h" -#include "LuabindObjectWrapper.h" +#include "LuaObjectWrapper.h" #include "Material.h" #include "MovableMan.h" @@ -142,7 +142,7 @@ namespace RTE { /// @param functionEntityArguments Optional vector of entity pointers that should be passed into the Lua function. Their internal Lua states will not be accessible. Defaults to empty. /// @param functionLiteralArguments Optional vector of strings, that should be passed into the Lua function. Entries must be surrounded with escaped quotes (i.e.`\"`) they'll be passed in as-is, allowing them to act as booleans, etc.. Defaults to empty. /// @return An error return value signaling success or any particular failure. Anything below 0 is an error signal. - int RunScriptedFunctionInAppropriateScripts(const std::string& functionName, bool runOnDisabledScripts = false, bool stopOnError = false, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); + int RunScriptedFunctionInAppropriateScripts(const std::string& functionName, bool runOnDisabledScripts = false, bool stopOnError = false, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); /// Cleans up and destroys the script state of this object, calling the Destroy callback in lua virtual void DestroyScriptState(); @@ -871,7 +871,7 @@ namespace RTE { virtual void PostTravel(); /// Update called prior to controller update. Ugly hack. Supposed to be done every frame. - virtual void PreControllerUpdate(){}; + virtual void PreControllerUpdate() {}; /// Updates this MovableObject. Supposed to be done every frame. This also /// applies and clear the accumulated impulse forces (impulses), and the @@ -1241,7 +1241,7 @@ namespace RTE { struct LuaFunction { bool m_ScriptIsEnabled; //!< Whether this function is in an enabled script. - std::unique_ptr m_LuaFunction; //!< The lua function itself. + std::unique_ptr m_LuaFunction; //!< The lua function itself. }; std::string m_ScriptObjectName; //!< The name of this object for script usage. diff --git a/Source/Entities/PieMenu.cpp b/Source/Entities/PieMenu.cpp index 7fa69610dd..da48e33d06 100644 --- a/Source/Entities/PieMenu.cpp +++ b/Source/Entities/PieMenu.cpp @@ -862,9 +862,9 @@ void PieMenu::UpdateSliceActivation() { m_ActiveSubPieMenu->SetHoveredPieSlice(m_ActiveSubPieMenu->m_PieQuadrants.at(m_ActiveSubPieMenu->m_DirectionIfSubPieMenu).m_MiddlePieSlice.get(), true); m_ActiveSubPieMenu->m_HoverTimer.SetRealTimeLimitMS(2000); m_ActiveSubPieMenu->m_HoverTimer.Reset(); - } else if (m_ActivatedPieSlice && m_ActivatedPieSlice->GetLuabindFunctionObjectWrapper() && m_ActivatedPieSlice->GetLuabindFunctionObjectWrapper()->GetLuabindObject()) { + } else if (m_ActivatedPieSlice && m_ActivatedPieSlice->GetLuaFunctionObjectWrapper() && m_ActivatedPieSlice->GetLuaFunctionObjectWrapper()->GetLuaObject()) { if (const MovableObject* scriptTarget = m_Owner ? m_Owner : m_AffectedObject) { - g_LuaMan.GetMasterScriptState().RunScriptFunctionObject(m_ActivatedPieSlice->GetLuabindFunctionObjectWrapper(), "", "", {scriptTarget, this, m_ActivatedPieSlice}); + g_LuaMan.GetMasterScriptState().RunScriptFunctionObject(m_ActivatedPieSlice->GetLuaFunctionObjectWrapper(), "", "", {scriptTarget, this, m_ActivatedPieSlice}); } } } diff --git a/Source/Entities/PieSlice.cpp b/Source/Entities/PieSlice.cpp index 24b1593fb6..02fc09adbc 100644 --- a/Source/Entities/PieSlice.cpp +++ b/Source/Entities/PieSlice.cpp @@ -25,7 +25,7 @@ void PieSlice::Clear() { m_Enabled = true; m_Icon = nullptr; - m_LuabindFunctionObject.reset(); + m_LuaFunctionObject.reset(); m_FunctionName.clear(); m_SubPieMenu.reset(); @@ -59,8 +59,8 @@ int PieSlice::Create(const PieSlice& reference) { m_Icon = std::unique_ptr(dynamic_cast(reference.m_Icon->Clone())); m_FunctionName = reference.m_FunctionName; - if (reference.m_LuabindFunctionObject) { - m_LuabindFunctionObject = std::make_unique(nullptr, reference.m_LuabindFunctionObject->GetFilePath()); + if (reference.m_LuaFunctionObject) { + m_LuaFunctionObject = std::make_unique(nullptr, reference.m_LuaFunctionObject->GetFilePath()); ReloadScripts(); } @@ -105,14 +105,14 @@ int PieSlice::ReadProperty(const std::string_view& propName, Reader& reader) { MatchProperty("ScriptPath", { std::string scriptPath; reader >> scriptPath; - m_LuabindFunctionObject = std::make_unique(nullptr, scriptPath); + m_LuaFunctionObject = std::make_unique(nullptr, scriptPath); if (!m_FunctionName.empty()) { ReloadScripts(); } }); MatchProperty("FunctionName", { reader >> m_FunctionName; - if (m_LuabindFunctionObject) { + if (m_LuaFunctionObject) { ReloadScripts(); } }); @@ -135,8 +135,8 @@ int PieSlice::Save(Writer& writer) const { writer.NewPropertyWithValue("Enabled", m_Enabled); } writer.NewPropertyWithValue("Icon", m_Icon.get()); - if (m_LuabindFunctionObject && !m_FunctionName.empty()) { - writer.NewPropertyWithValue("ScriptPath", m_LuabindFunctionObject->GetFilePath()); + if (m_LuaFunctionObject && !m_FunctionName.empty()) { + writer.NewPropertyWithValue("ScriptPath", m_LuaFunctionObject->GetFilePath()); writer.NewPropertyWithValue("FunctionName", m_FunctionName); } if (m_SubPieMenu) { @@ -170,13 +170,13 @@ void PieSlice::SetSubPieMenu(PieMenu* newSubPieMenu) { int PieSlice::ReloadScripts() { int status = 0; - if (m_LuabindFunctionObject) { - std::string filePath = m_LuabindFunctionObject->GetFilePath(); - std::unordered_map scriptFileFunctions; + if (m_LuaFunctionObject) { + std::string filePath = m_LuaFunctionObject->GetFilePath(); + std::unordered_map scriptFileFunctions; status = g_LuaMan.GetMasterScriptState().RunScriptFileAndRetrieveFunctions(filePath, {m_FunctionName}, scriptFileFunctions, true); if (scriptFileFunctions.find(m_FunctionName) != scriptFileFunctions.end()) { - m_LuabindFunctionObject = std::unique_ptr(scriptFileFunctions.at(m_FunctionName)); + m_LuaFunctionObject = std::unique_ptr(scriptFileFunctions.at(m_FunctionName)); } } diff --git a/Source/Entities/PieSlice.h b/Source/Entities/PieSlice.h index 738074a65d..8cea8ddfba 100644 --- a/Source/Entities/PieSlice.h +++ b/Source/Entities/PieSlice.h @@ -1,7 +1,7 @@ #pragma once #include "Constants.h" -#include "LuabindObjectWrapper.h" +#include "LuaObjectWrapper.h" #include "Icon.h" namespace RTE { @@ -142,18 +142,18 @@ namespace RTE { /// @param newIcon The new Icon for this PieSlice. void SetIcon(Icon* newIcon) { m_Icon = std::unique_ptr(newIcon); } - /// Gets the LuabindObjectWrapper for the function this PieSlice should run when activated. - /// @return The LuabindObjectWrapper this PieSlice should run when activated. - const LuabindObjectWrapper* GetLuabindFunctionObjectWrapper() const { return m_LuabindFunctionObject.get(); } + /// Gets the LuaObjectWrapper for the function this PieSlice should run when activated. + /// @return The LuaObjectWrapper this PieSlice should run when activated. + const LuaObjectWrapper* GetLuaFunctionObjectWrapper() const { return m_LuaFunctionObject.get(); } /// Gets the file path of the Lua file this PieSlice should run when activated, if any. /// @return The file path to the script file this PieSlice should load when activated. - std::string GetScriptPath() const { return m_LuabindFunctionObject ? m_LuabindFunctionObject->GetFilePath() : ""; } + std::string GetScriptPath() const { return m_LuaFunctionObject ? m_LuaFunctionObject->GetFilePath() : ""; } /// Sets the file path of the scripted file this PieSlice should run when activated. /// @param newScriptPath The file path of the Lua file this PieSlice should run when activated. void SetScriptPath(const std::string& newScriptPath) { - m_LuabindFunctionObject = std::make_unique(nullptr, newScriptPath); + m_LuaFunctionObject = std::make_unique(nullptr, newScriptPath); ReloadScripts(); } @@ -238,7 +238,7 @@ namespace RTE { bool m_Enabled; //!< Whether this PieSlice is enabled or disabled and grayed out. std::unique_ptr m_Icon; //!< The icon of this PieSlice. - std::unique_ptr m_LuabindFunctionObject; //!< The LuabindObjectWrapper holding the function this PieSlice runs when activated. + std::unique_ptr m_LuaFunctionObject; //!< The LuaObjectWrapper holding the function this PieSlice runs when activated. std::string m_FunctionName; //!< Name of the function in the script this PieSlice runs. Used for safely reloading scripts. std::unique_ptr m_SubPieMenu; //!< Unique pointer to the sub-PieMenu this should open when activated. diff --git a/Source/Lua/LuaAdapterDefinitions.h b/Source/Lua/LuaAdapterDefinitions.h index 1f6616ed99..7d2eb95833 100644 --- a/Source/Lua/LuaAdapterDefinitions.h +++ b/Source/Lua/LuaAdapterDefinitions.h @@ -1,6 +1,6 @@ #pragma once -#include "LuabindDefinitions.h" +#include "LuaBridgeDefinitions.h" #include "ActivityMan.h" #include "AudioMan.h" @@ -87,7 +87,7 @@ struct lua_State; namespace RTE { - class LuabindObjectWrapper; + class LuaObjectWrapper; #pragma region Entity Lua Adapter Macros struct LuaAdaptersEntityCreate { @@ -176,10 +176,10 @@ namespace RTE { #define LuaEntityCastFunctionsDeclarationsForType(TYPE) \ static TYPE* To##TYPE(Entity* entity); \ static const TYPE* ToConst##TYPE(const Entity* entity); \ - static bool Is##TYPE(Entity* entity); \ - static LuabindObjectWrapper* ToLuabindObject##TYPE(Entity* entity, lua_State* luaState) + static bool Is##TYPE(const Entity* entity); \ + static void PushAsLuaObject##TYPE(Entity* entity, lua_State* luaState) - static std::unordered_map> s_EntityToLuabindObjectCastFunctions; //!< Map of preset names to casting methods for ensuring objects are downcast properly when passed into Lua. + static std::unordered_map s_EntityToLuaObjectPushFunctions; //!< Map of class names to functions that push objects to Lua downcast to their actual class, used for ensuring objects are downcast properly when passed into Lua. LuaEntityCastFunctionsDeclarationsForType(Entity); LuaEntityCastFunctionsDeclarationsForType(SoundContainer); @@ -306,10 +306,10 @@ namespace RTE { } static int CalculatePath(Scene* luaSelfObject, const Vector& start, const Vector& end, float jumpHeight, float digStrength, Activity::Teams team); - static void CalculatePathAsync1(Scene* luaSelfObject, const luabind::object& callback, const Vector& start, const Vector& end, float jumpHeight, float digStrength) { + static void CalculatePathAsync1(Scene* luaSelfObject, const luabridge::LuaRef& callback, const Vector& start, const Vector& end, float jumpHeight, float digStrength) { return CalculatePathAsync(luaSelfObject, callback, start, end, jumpHeight, digStrength, Activity::Teams::NoTeam); } - static void CalculatePathAsync(Scene* luaSelfObject, const luabind::object& callback, const Vector& start, const Vector& end, float jumpHeight, float digStrength, Activity::Teams team); + static void CalculatePathAsync(Scene* luaSelfObject, const luabridge::LuaRef& callback, const Vector& start, const Vector& end, float jumpHeight, float digStrength, Activity::Teams team); }; #pragma endregion @@ -342,7 +342,7 @@ namespace RTE { #pragma region Activity Lua Adapters struct LuaAdaptersActivity { static void SendMessage1(Activity* luaSelfObject, const std::string& message); - static void SendMessage2(Activity* luaSelfObject, const std::string& message, luabind::object context); + static void SendMessage2(Activity* luaSelfObject, const std::string& message, luabridge::LuaRef context); }; #pragma endregion @@ -354,7 +354,7 @@ namespace RTE { static bool DisableScript1(MovableObject* luaSelfObject); static bool DisableScript2(MovableObject* luaSelfObject, const std::string& scriptPath); static void SendMessage1(MovableObject* luaSelfObject, const std::string& message); - static void SendMessage2(MovableObject* luaSelfObject, const std::string& message, luabind::object context); + static void SendMessage2(MovableObject* luaSelfObject, const std::string& message, luabridge::LuaRef context); }; #pragma endregion @@ -425,7 +425,7 @@ namespace RTE { static void AddParticle(MovableMan& movableMan, MovableObject* particle); static void SendGlobalMessage1(MovableMan& movableMan, const std::string& message); - static void SendGlobalMessage2(MovableMan& movableMan, const std::string& message, luabind::object context); + static void SendGlobalMessage2(MovableMan& movableMan, const std::string& message, luabridge::LuaRef context); }; #pragma endregion @@ -526,7 +526,7 @@ namespace RTE { /// @param skip For every pixel checked along the line, how many to skip between them (default: 0) /// for optimization reasons. 0 = every pixel is checked. /// @return The MOID of the hit non-ignored MO, or g_NoMOID if terrain or no MO was hit. - static MOID CastMORay1(SceneMan& sceneMan, const Vector& start, const Vector& ray, const luabind::object& ignoreMOIDs, int ignoreTeam = Activity::NoTeam, unsigned char ignoreMaterial = 0, bool ignoreAllTerrain = false, int skip = 0); + static MOID CastMORay1(SceneMan& sceneMan, const Vector& start, const Vector& ray, const luabridge::LuaRef& ignoreMOIDs, int ignoreTeam = Activity::NoTeam, unsigned char ignoreMaterial = 0, bool ignoreAllTerrain = false, int skip = 0); /// Traces along a vector and returns MOID of the first non-ignored /// non-NoMOID MO encountered. If a non-air terrain pixel is encountered @@ -553,8 +553,8 @@ namespace RTE { /// @param skip For every pixel checked along the line, how many to skip between them (default: 0) /// for optimization reasons. 0 = every pixel is checked. /// @return A vector of pointers to all MovableObjects met along the ray, who aren't ignored. - static const std::vector* CastAllMOsRay(SceneMan& sceneMan, const Vector& start, const Vector& ray, const luabind::object& ignoreMOIDs, int ignoreTeam = Activity::NoTeam, unsigned char ignoreMaterial = 0, bool ignoreAllTerrain = false, int skip = 0); - + static const std::vector* CastAllMOsRay(SceneMan& sceneMan, const Vector& start, const Vector& ray, const luabridge::LuaRef& ignoreMOIDs, int ignoreTeam = Activity::NoTeam, unsigned char ignoreMaterial = 0, bool ignoreAllTerrain = false, int skip = 0); + /// Traces along a vector and returns the length of how far the trace went /// without hitting any non-ignored terrain material or MOID at all. /// @param start The starting position. @@ -574,7 +574,7 @@ namespace RTE { /// @return How far along, in pixel units, the ray the pixel of any obstacle was /// encountered. If no pixel of the right material was found, < 0 is returned. /// If an obstacle on the starting position was encountered, 0 is returned. - static float CastObstacleRay1(SceneMan& sceneMan, const Vector& start, const Vector& ray, Vector& obstaclePos, Vector& freePos, const luabind::object& ignoreMOIDs, int ignoreTeam = Activity::NoTeam, unsigned char ignoreMaterial = 0, int skip = 0); + static float CastObstacleRay1(SceneMan& sceneMan, const Vector& start, const Vector& ray, Vector& obstaclePos, Vector& freePos, const luabridge::LuaRef& ignoreMOIDs, int ignoreTeam = Activity::NoTeam, unsigned char ignoreMaterial = 0, int skip = 0); /// Traces along a vector and returns the length of how far the trace went /// without hitting any non-ignored terrain material or MOID at all. @@ -596,7 +596,7 @@ namespace RTE { /// encountered. If no pixel of the right material was found, < 0 is returned. /// If an obstacle on the starting position was encountered, 0 is returned. static float CastObstacleRay2(SceneMan& sceneMan, const Vector& start, const Vector& ray, Vector& obstaclePos, Vector& freePos, MOID ignoreMOID = g_NoMOID, int ignoreTeam = Activity::NoTeam, unsigned char ignoreMaterial = 0, int skip = 0); - + /// Takes a Box and returns a list of Boxes that describe the Box, wrapped appropriately for the current Scene. /// @param boxToWrap The Box to wrap. /// @return A list of Boxes that make up the Box to wrap, wrapped appropriately for the current Scene. @@ -611,7 +611,7 @@ namespace RTE { /// @param centerPos Position of primitive's center in Scene coordinates. /// @param color Color to draw primitive with. /// @param verticesTable A Lua table that contains the positions of the primitive's vertices, relative to the center position. - static void DrawPolygonPrimitive(PrimitiveMan& primitiveMan, const Vector& centerPos, int color, const luabind::object& verticesTable); + static void DrawPolygonPrimitive(PrimitiveMan& primitiveMan, const Vector& centerPos, int color, const luabridge::LuaRef& verticesTable); /// Schedule to draw a polygon primitive visible only to a specified player. /// @param primitiveMan A reference to PrimitiveMan, provided by Lua. @@ -619,14 +619,14 @@ namespace RTE { /// @param centerPos Position of primitive's center in Scene coordinates. /// @param color Color to draw primitive with. /// @param verticesTable A Lua table that contains the positions of the primitive's vertices, relative to the center position. - static void DrawPolygonPrimitiveForPlayer(PrimitiveMan& primitiveMan, int player, const Vector& centerPos, int color, const luabind::object& verticesTable); + static void DrawPolygonPrimitiveForPlayer(PrimitiveMan& primitiveMan, int player, const Vector& centerPos, int color, const luabridge::LuaRef& verticesTable); /// Schedule to draw a filled polygon primitive. /// @param primitiveMan A reference to PrimitiveMan, provided by Lua. /// @param startPos Start position of the primitive in Scene coordinates. /// @param color Color to draw primitive with. /// @param verticesTable A Lua table that contains the positions of the primitive's vertices, relative to the center position. - static void DrawPolygonFillPrimitive(PrimitiveMan& primitiveMan, const Vector& startPos, int color, const luabind::object& verticesTable); + static void DrawPolygonFillPrimitive(PrimitiveMan& primitiveMan, const Vector& startPos, int color, const luabridge::LuaRef& verticesTable); /// Schedule to draw a filled polygon primitive visible only to a specified player. /// @param primitiveMan A reference to PrimitiveMan, provided by Lua. @@ -634,20 +634,20 @@ namespace RTE { /// @param startPos Start position of the primitive in Scene coordinates. /// @param color Color to draw primitive with. /// @param verticesTable A Lua table that contains the positions of the primitive's vertices, relative to the center position. - static void DrawPolygonFillPrimitiveForPlayer(PrimitiveMan& primitiveMan, int player, const Vector& startPos, int color, const luabind::object& verticesTable); + static void DrawPolygonFillPrimitiveForPlayer(PrimitiveMan& primitiveMan, int player, const Vector& startPos, int color, const luabridge::LuaRef& verticesTable); /// Schedules to draw multiple primitives of varying type with transparency enabled. /// @param primitiveMan A reference to PrimitiveMan, provided by Lua. /// @param transValue The transparency value the primitives should be drawn at. From 0 (opaque) to 100 (transparent). /// @param primitivesTable A Lua table of primitives to schedule drawing for. - static void DrawPrimitivesWithTransparency(PrimitiveMan& primitiveMan, int transValue, const luabind::object& primitivesTable); + static void DrawPrimitivesWithTransparency(PrimitiveMan& primitiveMan, int transValue, const luabridge::LuaRef& primitivesTable); /// Schedule to draw multiple primitives of varying type with blending enabled. /// @param primitiveMan A reference to PrimitiveMan, provided by Lua. /// @param blendMode The blending mode the primitives should be drawn with. See DrawBlendMode enumeration. /// @param blendAmount The blending amount for all the channels. 0-100. /// @param primitivesTable A Lua table of primitives to schedule drawing for. - static void DrawPrimitivesWithBlending(PrimitiveMan& primitiveMan, int blendMode, int blendAmount, const luabind::object& primitivesTable); + static void DrawPrimitivesWithBlending(PrimitiveMan& primitiveMan, int blendMode, int blendAmount, const luabridge::LuaRef& primitivesTable); /// Schedule to draw multiple primitives of varying type with blending enabled. /// @param primitiveMan A reference to PrimitiveMan, provided by Lua. @@ -657,7 +657,7 @@ namespace RTE { /// @param blendAmountB The blending amount for the Blue channel. 0-100. /// @param blendAmountA The blending amount for the Alpha channel. 0-100. /// @param primitivesTable A Lua table of primitives to schedule drawing for. - static void DrawPrimitivesWithBlendingPerChannel(PrimitiveMan& primitiveMan, int blendMode, int blendAmountR, int blendAmountG, int blendAmountB, int blendAmountA, const luabind::object& primitivesTable); + static void DrawPrimitivesWithBlendingPerChannel(PrimitiveMan& primitiveMan, int blendMode, int blendAmountR, int blendAmountG, int blendAmountB, int blendAmountA, const luabridge::LuaRef& primitivesTable); }; #pragma endregion diff --git a/Source/Lua/LuaAdapters.cpp b/Source/Lua/LuaAdapters.cpp index df716cf88f..edca5f92d9 100644 --- a/Source/Lua/LuaAdapters.cpp +++ b/Source/Lua/LuaAdapters.cpp @@ -1,7 +1,7 @@ // Make sure this file is always set to NOT use pre-compiled headers and conformance mode (/permissive) otherwise everything will be on fire! #include "LuaAdapterDefinitions.h" -#include "LuabindObjectWrapper.h" +#include "LuaObjectWrapper.h" #include "LuaMan.h" #include "lj_obj.h" @@ -10,7 +10,7 @@ using namespace RTE; -std::unordered_map> LuaAdaptersEntityCast::s_EntityToLuabindObjectCastFunctions = {}; +std::unordered_map LuaAdaptersEntityCast::s_EntityToLuaObjectPushFunctions = {}; #define LuaEntityCreateFunctionsDefinitionsForType(TYPE) \ TYPE* LuaAdaptersEntityCreate::Create##TYPE(std::string preseName, std::string moduleName) { \ @@ -143,15 +143,17 @@ LuaEntityCloneFunctionDefinitionForType(PieMenu); } \ return targetType; \ } \ - bool LuaAdaptersEntityCast::Is##TYPE(Entity* entity) { \ - return dynamic_cast(entity) ? true : false; \ + bool LuaAdaptersEntityCast::Is##TYPE(const Entity* entity) { \ + return dynamic_cast(entity) ? true : false; \ } \ - LuabindObjectWrapper* LuaAdaptersEntityCast::ToLuabindObject##TYPE(Entity* entity, lua_State* luaState) { \ - return new LuabindObjectWrapper(new luabind::object(luaState, dynamic_cast(entity)), ""); \ + void LuaAdaptersEntityCast::PushAsLuaObject##TYPE(Entity* entity, lua_State* luaState) { \ + if (auto result = luabridge::Stack::push(luaState, dynamic_cast(entity)); !result) { \ + lua_pushnil(luaState); \ + } \ } \ - /* Bullshit semi-hack to automatically populate the Luabind Object cast function map that is used in LuaMan::RunScriptFunctionObject */ \ - static const bool EntityToLuabindObjectCastMapAutoInserterForType##TYPE = []() { \ - LuaAdaptersEntityCast::s_EntityToLuabindObjectCastFunctions.try_emplace(std::string(#TYPE), &LuaAdaptersEntityCast::ToLuabindObject##TYPE); \ + /* Bullshit semi-hack to automatically populate the Lua object push function map that is used in LuaMan::RunScriptFunctionObject */ \ + static const bool EntityToLuaObjectPushMapAutoInserterForType##TYPE = []() { \ + LuaAdaptersEntityCast::s_EntityToLuaObjectPushFunctions.try_emplace(std::string(#TYPE), &LuaAdaptersEntityCast::PushAsLuaObject##TYPE); \ return true; \ }() @@ -287,25 +289,47 @@ int LuaAdaptersScene::CalculatePath(Scene* luaSelfObject, const Vector& start, c return -1; } -void LuaAdaptersScene::CalculatePathAsync(Scene* luaSelfObject, const luabind::object& callback, const Vector& start, const Vector& end, float jumpHeight, float digStrength, Activity::Teams team) { +/// Calls a global Lua function with a callback ID and a value, raising any error it causes as a Lua error in the given calling Lua state, or printing it to the console if there's no calling state. +template +static void CallAsyncPathCallbackFunction(lua_State* luaState, const char* functionName, int callbackId, const ValueType& value, lua_State* callingState) { + lua_pushcfunction(luaState, &AddFileAndLineToError); + lua_getglobal(luaState, functionName); + lua_pushnumber(luaState, static_cast(callbackId)); + if constexpr (std::is_same_v) { + value.push(luaState); + } else if (auto result = luabridge::Stack::push(luaState, value); !result) { + lua_pushnil(luaState); + } + if (lua_pcall(luaState, 2, 0, -4) != 0) { + std::string error = lua_tostring(luaState, -1); + lua_pop(luaState, 2); + if (callingState) { + LuaBinding::RaiseError(callingState, "%s", error.c_str()); + } + g_ConsoleMan.PrintString("ERROR: " + error); + return; + } + lua_pop(luaState, 1); +} + +void LuaAdaptersScene::CalculatePathAsync(Scene* luaSelfObject, const luabridge::LuaRef& callback, const Vector& start, const Vector& end, float jumpHeight, float digStrength, Activity::Teams team) { team = std::clamp(team, Activity::Teams::NoTeam, Activity::Teams::TeamFour); - // So, luabind::object is a weak reference, holding just a stack and a position in the stack - // This means it's unsafe to store on the C++ side if we do basically anything with the lua state before using it + // We can't keep the reference to the callback around on the C++ side, since it might belong to a temporary Lua thread that's gone by the time the path is done. // As such, we need to store this function somewhere safely within our Lua state for us to access later when we need it - lua_State* luaState = mainthread(G(callback.interpreter())); // Get the main thread for the state, in case we're a temp lua thread + lua_State* luaState = mainthread(G(callback.state())); // Get the main thread for the state, in case we're a temp lua thread static std::atomic currentCallbackId{0}; int thisCallbackId = currentCallbackId.fetch_add(1, std::memory_order_relaxed); - if (luabind::type(callback) == LUA_TFUNCTION && callback.is_valid()) { - luabind::call_function(luaState, "_AddAsyncPathCallback", thisCallbackId, callback); + if (callback.isValid() && callback.isFunction()) { + CallAsyncPathCallbackFunction(luaState, "_AddAsyncPathCallback", thisCallbackId, callback, callback.state()); } auto callLuaCallback = [luaState, thisCallbackId](std::shared_ptr pathRequestVol) { // This callback is called from the async pathing thread, so we need to further delay this logic into the main thread (via AddLuaScriptCallback) g_LuaMan.AddLuaScriptCallback([luaState, thisCallbackId, pathRequestVol]() { - PathRequest pathRequest = const_cast(*pathRequestVol); // erh, to work with luabind etc - luabind::call_function(luaState, "_TriggerAsyncPathCallback", thisCallbackId, pathRequest); + PathRequest pathRequest = const_cast(*pathRequestVol); // Copy it out of the volatile shared state, so it can be pushed to Lua. + CallAsyncPathCallbackFunction(luaState, "_TriggerAsyncPathCallback", thisCallbackId, pathRequest, nullptr); }); }; @@ -329,14 +353,19 @@ int LuaAdaptersSceneObject::GetBuyableMode(const SceneObject* luaSelfObject) { } void LuaAdaptersActivity::SendMessage1(Activity* luaSelfObject, const std::string& message) { - luabind::object context; - SendMessage2(luaSelfObject, message, context); + GAScripted* scriptedActivity = dynamic_cast(luaSelfObject); + if (scriptedActivity) { + // An empty reference, which gets passed to OnMessage as nil, the same as when no context is given. + luabridge::LuaRef context(g_LuaMan.GetMasterScriptState().GetLuaState()); + LuaObjectWrapper wrapper(&context, "", false); + scriptedActivity->RunLuaFunction("OnMessage", {}, {message}, {&wrapper}); + } } -void LuaAdaptersActivity::SendMessage2(Activity* luaSelfObject, const std::string& message, luabind::object context) { +void LuaAdaptersActivity::SendMessage2(Activity* luaSelfObject, const std::string& message, luabridge::LuaRef context) { GAScripted* scriptedActivity = dynamic_cast(luaSelfObject); if (scriptedActivity) { - LuabindObjectWrapper wrapper(&context, "", false); + LuaObjectWrapper wrapper(&context, "", false); scriptedActivity->RunLuaFunction("OnMessage", {}, {message}, {&wrapper}); } } @@ -388,8 +417,8 @@ void LuaAdaptersMovableObject::SendMessage1(MovableObject* luaSelfObject, const luaSelfObject->RunScriptedFunctionInAppropriateScripts("OnMessage", false, false, {}, {message}); } -void LuaAdaptersMovableObject::SendMessage2(MovableObject* luaSelfObject, const std::string& message, luabind::object context) { - LuabindObjectWrapper wrapper(&context, "", false); +void LuaAdaptersMovableObject::SendMessage2(MovableObject* luaSelfObject, const std::string& message, luabridge::LuaRef context) { + LuaObjectWrapper wrapper(&context, "", false); luaSelfObject->RunScriptedFunctionInAppropriateScripts("OnMessage", false, false, {}, {message}, {&wrapper}); } @@ -521,8 +550,8 @@ void LuaAdaptersMovableMan::SendGlobalMessage1(MovableMan& movableMan, const std movableMan.RunLuaFunctionOnAllMOs("OnGlobalMessage", true, {}, {message}); } -void LuaAdaptersMovableMan::SendGlobalMessage2(MovableMan& movableMan, const std::string& message, luabind::object context) { - LuabindObjectWrapper wrapper(&context, "", false); +void LuaAdaptersMovableMan::SendGlobalMessage2(MovableMan& movableMan, const std::string& message, luabridge::LuaRef context) { + LuaObjectWrapper wrapper(&context, "", false); GAScripted* scriptedActivity = dynamic_cast(g_ActivityMan.GetActivity()); if (scriptedActivity) { @@ -618,7 +647,7 @@ std::list* LuaAdaptersPresetMan::GetAllEntitiesOfGroup(PresetMan& prese return entityList; } -MOID LuaAdaptersSceneMan::CastMORay1(SceneMan& sceneMan, const Vector& start, const Vector& ray, const luabind::object& ignoreMOIDs, int ignoreTeam, unsigned char ignoreMaterial, bool ignoreAllTerrain, int skip) { +MOID LuaAdaptersSceneMan::CastMORay1(SceneMan& sceneMan, const Vector& start, const Vector& ray, const luabridge::LuaRef& ignoreMOIDs, int ignoreTeam, unsigned char ignoreMaterial, bool ignoreAllTerrain, int skip) { std::vector ignoreMOIDsVec = ConvertLuaTableToVectorOfType(ignoreMOIDs); return sceneMan.CastMORay(start, ray, ignoreMOIDsVec, ignoreTeam, ignoreMaterial, ignoreAllTerrain, skip); } @@ -628,12 +657,12 @@ MOID LuaAdaptersSceneMan::CastMORay2(SceneMan& sceneMan, const Vector& start, co return sceneMan.CastMORay(start, ray, ignoreMOIDs, ignoreTeam, ignoreMaterial, ignoreAllTerrain, skip); } -const std::vector* LuaAdaptersSceneMan::CastAllMOsRay(SceneMan& sceneMan, const Vector& start, const Vector& ray, const luabind::object& ignoreMOIDs, int ignoreTeam, unsigned char ignoreMaterial, bool ignoreAllTerrain, int skip) { +const std::vector* LuaAdaptersSceneMan::CastAllMOsRay(SceneMan& sceneMan, const Vector& start, const Vector& ray, const luabridge::LuaRef& ignoreMOIDs, int ignoreTeam, unsigned char ignoreMaterial, bool ignoreAllTerrain, int skip) { std::vector ignoreMOIDsVec = ConvertLuaTableToVectorOfType(ignoreMOIDs); return sceneMan.CastAllMOsRay(start, ray, ignoreMOIDsVec, ignoreTeam, ignoreMaterial, ignoreAllTerrain, skip); } -float LuaAdaptersSceneMan::CastObstacleRay1(SceneMan& sceneMan, const Vector& start, const Vector& ray, Vector& obstaclePos, Vector& freePos, const luabind::object& ignoreMOIDs, int ignoreTeam, unsigned char ignoreMaterial, int skip) { +float LuaAdaptersSceneMan::CastObstacleRay1(SceneMan& sceneMan, const Vector& start, const Vector& ray, Vector& obstaclePos, Vector& freePos, const luabridge::LuaRef& ignoreMOIDs, int ignoreTeam, unsigned char ignoreMaterial, int skip) { std::vector ignoreMOIDsVec = ConvertLuaTableToVectorOfType(ignoreMOIDs); return sceneMan.CastObstacleRay(start, ray, obstaclePos, freePos, ignoreMOIDsVec, ignoreTeam, ignoreMaterial, skip); } @@ -649,31 +678,31 @@ const std::list* LuaAdaptersSceneMan::WrapBoxes(SceneMan& sceneMan, const B return wrappedBoxes; } -void LuaAdaptersPrimitiveMan::DrawPolygonPrimitive(PrimitiveMan& primitiveMan, const Vector& centerPos, int color, const luabind::object& verticesTable) { +void LuaAdaptersPrimitiveMan::DrawPolygonPrimitive(PrimitiveMan& primitiveMan, const Vector& centerPos, int color, const luabridge::LuaRef& verticesTable) { primitiveMan.DrawPolygonOrPolygonFillPrimitive(-1, centerPos, color, ConvertLuaTableToVectorOfType(verticesTable), false); } -void LuaAdaptersPrimitiveMan::DrawPolygonPrimitiveForPlayer(PrimitiveMan& primitiveMan, int player, const Vector& centerPos, int color, const luabind::object& verticesTable) { +void LuaAdaptersPrimitiveMan::DrawPolygonPrimitiveForPlayer(PrimitiveMan& primitiveMan, int player, const Vector& centerPos, int color, const luabridge::LuaRef& verticesTable) { primitiveMan.DrawPolygonOrPolygonFillPrimitive(player, centerPos, color, ConvertLuaTableToVectorOfType(verticesTable), false); } -void LuaAdaptersPrimitiveMan::DrawPolygonFillPrimitive(PrimitiveMan& primitiveMan, const Vector& startPos, int color, const luabind::object& verticesTable) { +void LuaAdaptersPrimitiveMan::DrawPolygonFillPrimitive(PrimitiveMan& primitiveMan, const Vector& startPos, int color, const luabridge::LuaRef& verticesTable) { primitiveMan.DrawPolygonOrPolygonFillPrimitive(-1, startPos, color, ConvertLuaTableToVectorOfType(verticesTable), true); } -void LuaAdaptersPrimitiveMan::DrawPolygonFillPrimitiveForPlayer(PrimitiveMan& primitiveMan, int player, const Vector& startPos, int color, const luabind::object& verticesTable) { +void LuaAdaptersPrimitiveMan::DrawPolygonFillPrimitiveForPlayer(PrimitiveMan& primitiveMan, int player, const Vector& startPos, int color, const luabridge::LuaRef& verticesTable) { primitiveMan.DrawPolygonOrPolygonFillPrimitive(player, startPos, color, ConvertLuaTableToVectorOfType(verticesTable), true); } -void LuaAdaptersPrimitiveMan::DrawPrimitivesWithTransparency(PrimitiveMan& primitiveMan, int transValue, const luabind::object& primitivesTable) { +void LuaAdaptersPrimitiveMan::DrawPrimitivesWithTransparency(PrimitiveMan& primitiveMan, int transValue, const luabridge::LuaRef& primitivesTable) { primitiveMan.SchedulePrimitivesForBlendedDrawing(DrawBlendMode::BlendTransparency, transValue, transValue, transValue, BlendAmountLimits::MinBlend, ConvertLuaTableToVectorOfType(primitivesTable)); } -void LuaAdaptersPrimitiveMan::DrawPrimitivesWithBlending(PrimitiveMan& primitiveMan, int blendMode, int blendAmount, const luabind::object& primitivesTable) { +void LuaAdaptersPrimitiveMan::DrawPrimitivesWithBlending(PrimitiveMan& primitiveMan, int blendMode, int blendAmount, const luabridge::LuaRef& primitivesTable) { primitiveMan.SchedulePrimitivesForBlendedDrawing(static_cast(blendMode), blendAmount, blendAmount, blendAmount, blendAmount, ConvertLuaTableToVectorOfType(primitivesTable)); } -void LuaAdaptersPrimitiveMan::DrawPrimitivesWithBlendingPerChannel(PrimitiveMan& primitiveMan, int blendMode, int blendAmountR, int blendAmountG, int blendAmountB, int blendAmountA, const luabind::object& primitivesTable) { +void LuaAdaptersPrimitiveMan::DrawPrimitivesWithBlendingPerChannel(PrimitiveMan& primitiveMan, int blendMode, int blendAmountR, int blendAmountG, int blendAmountB, int blendAmountA, const luabridge::LuaRef& primitivesTable) { primitiveMan.SchedulePrimitivesForBlendedDrawing(static_cast(blendMode), blendAmountR, blendAmountG, blendAmountB, blendAmountA, ConvertLuaTableToVectorOfType(primitivesTable)); } diff --git a/Source/Lua/LuaBindingRegisterDefinitions.h b/Source/Lua/LuaBindingRegisterDefinitions.h index 91be1b3c54..87964acba4 100644 --- a/Source/Lua/LuaBindingRegisterDefinitions.h +++ b/Source/Lua/LuaBindingRegisterDefinitions.h @@ -1,177 +1,52 @@ #pragma once -#include "LuabindDefinitions.h" +#include "LuaBridgeDefinitions.h" #include "LuaAdapterDefinitions.h" namespace RTE { -// Should be ordered with most-derived classes first -#define LIST_OF_LUABOUND_OBJECTS \ - /* SystemLuaBindings */ \ - PER_LUA_BINDING(Box) \ - PER_LUA_BINDING(Controller) \ - PER_LUA_BINDING(DataModule) \ - PER_LUA_BINDING(Timer) \ - PER_LUA_BINDING(Vector) \ - PER_LUA_BINDING(PathRequest) \ - /* ManagerLuaBindings */ \ - PER_LUA_BINDING(ActivityMan) \ - PER_LUA_BINDING(AudioMan) \ - PER_LUA_BINDING(MusicMan) \ - PER_LUA_BINDING(CameraMan) \ - PER_LUA_BINDING(ConsoleMan) \ - PER_LUA_BINDING(FrameMan) \ - PER_LUA_BINDING(MetaMan) \ - PER_LUA_BINDING(MovableMan) \ - PER_LUA_BINDING(PerformanceMan) \ - PER_LUA_BINDING(PostProcessMan) \ - PER_LUA_BINDING(PresetMan) \ - PER_LUA_BINDING(PrimitiveMan) \ - PER_LUA_BINDING(SceneMan) \ - PER_LUA_BINDING(SettingsMan) \ - PER_LUA_BINDING(TimerMan) \ - PER_LUA_BINDING(UInputMan) \ - /* EntityLuaBindings */ \ - /* ThrownDevice-Derived */ \ - PER_LUA_BINDING(TDExplosive) \ - /* HeldDevice-Derived */ \ - PER_LUA_BINDING(HDFirearm) \ - PER_LUA_BINDING(ThrownDevice) \ - /* AEmitter-Derived */ \ - PER_LUA_BINDING(AEJetpack) \ - /* ACraft-Derived */ \ - PER_LUA_BINDING(ACDropShip) \ - PER_LUA_BINDING(ACRocket) \ - /* Attachable-Derived */ \ - PER_LUA_BINDING(Arm) \ - PER_LUA_BINDING(Leg) \ - PER_LUA_BINDING(AEmitter) \ - PER_LUA_BINDING(HeldDevice) \ - PER_LUA_BINDING(Magazine) \ - PER_LUA_BINDING(Turret) \ - /* Actor-Derived */ \ - PER_LUA_BINDING(ACrab) \ - PER_LUA_BINDING(ACraft) \ - PER_LUA_BINDING(AHuman) \ - PER_LUA_BINDING(ADoor) \ - /* MOSRotating-Derived */ \ - PER_LUA_BINDING(Actor) \ - PER_LUA_BINDING(Attachable) \ - /* MOSParticle-Derived */ \ - PER_LUA_BINDING(PEmitter) \ - /* MOSprite-Derived */ \ - PER_LUA_BINDING(MOSRotating) \ - PER_LUA_BINDING(MOSParticle) \ - /* MovableObject-Derived */ \ - PER_LUA_BINDING(MOPixel) \ - PER_LUA_BINDING(MOSprite) \ - /* SceneObject-Derived */ \ - PER_LUA_BINDING(TerrainObject) \ - PER_LUA_BINDING(Deployment) \ - PER_LUA_BINDING(MovableObject) \ - /* Entity-Derived */ \ - PER_LUA_BINDING(SoundContainer) \ - PER_LUA_BINDING(PieSlice) \ - PER_LUA_BINDING(GlobalScript) \ - PER_LUA_BINDING(Emission) \ - PER_LUA_BINDING(LimbPath) \ - PER_LUA_BINDING(PieMenu) \ - PER_LUA_BINDING(Round) \ - PER_LUA_BINDING(Scene) \ - PER_LUA_BINDING(Scene::Area) \ - PER_LUA_BINDING(Material) \ - PER_LUA_BINDING(MetaPlayer) \ - PER_LUA_BINDING(SceneObject) \ - /* SceneLayer-Derived */ \ - PER_LUA_BINDING(SLBackground) \ - /* Base Classes */ \ - PER_LUA_BINDING(SoundSet) \ - PER_LUA_BINDING(Gib) \ - PER_LUA_BINDING(StaticSceneLayer) \ - PER_LUA_BINDING(Entity) \ - /* ActivityLuaBindings */ \ - PER_LUA_BINDING(GameActivity) \ - PER_LUA_BINDING(Activity) \ - /* GUILuaBindings */ \ - PER_LUA_BINDING(BuyMenuGUI) \ - PER_LUA_BINDING(SceneEditorGUI) \ - PER_LUA_BINDING(GUIBanner) \ - /* PrimitiveLuaBindings */ \ - /* GraphicalPrimitive-Derived */ \ - PER_LUA_BINDING(LinePrimitive) \ - PER_LUA_BINDING(ArcPrimitive) \ - PER_LUA_BINDING(SplinePrimitive) \ - PER_LUA_BINDING(BoxPrimitive) \ - PER_LUA_BINDING(BoxFillPrimitive) \ - PER_LUA_BINDING(RoundedBoxPrimitive) \ - PER_LUA_BINDING(RoundedBoxFillPrimitive) \ - PER_LUA_BINDING(CirclePrimitive) \ - PER_LUA_BINDING(CircleFillPrimitive) \ - PER_LUA_BINDING(EllipsePrimitive) \ - PER_LUA_BINDING(EllipseFillPrimitive) \ - PER_LUA_BINDING(TrianglePrimitive) \ - PER_LUA_BINDING(TriangleFillPrimitive) \ - PER_LUA_BINDING(TextPrimitive) \ - PER_LUA_BINDING(BitmapPrimitive) \ - /* Base Classes */ \ - PER_LUA_BINDING(GraphicalPrimitive) \ - /* InputLuaBindings */ \ - PER_LUA_BINDING(InputDevice) \ - PER_LUA_BINDING(InputElements) \ - PER_LUA_BINDING(MouseButtons) \ - PER_LUA_BINDING(JoyButtons) \ - PER_LUA_BINDING(JoyDirections) \ - PER_LUA_BINDING(SDL_Scancode) \ - PER_LUA_BINDING(SDL_Keycode) \ - PER_LUA_BINDING(SDL_GamepadButton) \ - PER_LUA_BINDING(SDL_GamepadAxis) \ - /* MiscLuaBindings */ \ - PER_LUA_BINDING(AlarmEvent) \ - PER_LUA_BINDING(Directions) \ - PER_LUA_BINDING(DrawBlendMode) - #pragma region Lua Binding Registration Macros /// Convenience macro for declaring a binding register function. #define LuaBindingRegisterFunctionDeclarationForType(TYPE) \ - static luabind::scope Register##TYPE##LuaBindings() + static void Register##TYPE##LuaBindings(LuaBinding::Registry& registry) /// Convenience macro for defining a binding register function. #define LuaBindingRegisterFunctionDefinitionForType(OWNINGSCOPE, TYPE) \ - luabind::scope OWNINGSCOPE::Register##TYPE##LuaBindings() + void OWNINGSCOPE::Register##TYPE##LuaBindings(LuaBinding::Registry& registry) -/// Convenience macro for a LuaBind scope definition of an abstract type. +/// Convenience macro for a class registration of an abstract type. #define AbstractTypeLuaClassDefinition(TYPE, PARENTTYPE) \ - luabind::class_(#TYPE) \ - .property("ClassName", &TYPE::GetClassName) + registry.Class(#TYPE) \ + .addProperty("ClassName", &TYPE::GetClassName) -/// Convenience macro for a LuaBind scope definition of a concrete type. +/// Convenience macro for a class registration of a concrete type. #define ConcreteTypeLuaClassDefinition(TYPE, PARENTTYPE) \ - luabind::class_(#TYPE) \ - .def("Clone", &LuaAdaptersEntityClone::Clone##TYPE, luabind::adopt(luabind::result)) \ - .property("ClassName", &TYPE::GetClassName) + registry.Class(#TYPE) \ + .addFunction("Clone", &LuaAdaptersEntityClone::Clone##TYPE, LuaBinding::AdoptResult) \ + .addProperty("ClassName", &TYPE::GetClassName) /// Convenience macro for calling a register function of a type. #define RegisterLuaBindingsOfType(OWNINGSCOPE, TYPE) \ - OWNINGSCOPE::Register##TYPE##LuaBindings() + OWNINGSCOPE::Register##TYPE##LuaBindings(registry) /// Convenience macro for calling a register function of an abstract type, along with registering global bindings for adapters relevant to the type. #define RegisterLuaBindingsOfAbstractType(OWNINGSCOPE, TYPE) \ - luabind::def((std::string("To") + std::string(#TYPE)).c_str(), (TYPE * (*)(Entity*)) & LuaAdaptersEntityCast::To##TYPE), \ - luabind::def((std::string("To") + std::string(#TYPE)).c_str(), (const TYPE* (*)(const Entity*)) & LuaAdaptersEntityCast::ToConst##TYPE), \ - luabind::def((std::string("Is") + std::string(#TYPE)).c_str(), (bool (*)(const Entity*)) & LuaAdaptersEntityCast::Is##TYPE), \ - OWNINGSCOPE::Register##TYPE##LuaBindings() + registry.Function("To" #TYPE, static_cast(&LuaAdaptersEntityCast::To##TYPE)); \ + registry.Function("To" #TYPE, static_cast(&LuaAdaptersEntityCast::ToConst##TYPE)); \ + registry.Function("Is" #TYPE, static_cast(&LuaAdaptersEntityCast::Is##TYPE)); \ + OWNINGSCOPE::Register##TYPE##LuaBindings(registry) /// Convenience macro for calling a register function of a concrete type, along with registering global bindings for adapters relevant to the type. #define RegisterLuaBindingsOfConcreteType(OWNINGSCOPE, TYPE) \ - luabind::def((std::string("Create") + std::string(#TYPE)).c_str(), (TYPE * (*)(std::string, std::string)) & LuaAdaptersEntityCreate::Create##TYPE, luabind::adopt(luabind::result)), \ - luabind::def((std::string("Create") + std::string(#TYPE)).c_str(), (TYPE * (*)(std::string)) & LuaAdaptersEntityCreate::Create##TYPE, luabind::adopt(luabind::result)), \ - luabind::def((std::string("Random") + std::string(#TYPE)).c_str(), (TYPE * (*)(std::string, int)) & LuaAdaptersEntityCreate::Random##TYPE, luabind::adopt(luabind::result)), \ - luabind::def((std::string("Random") + std::string(#TYPE)).c_str(), (TYPE * (*)(std::string, std::string)) & LuaAdaptersEntityCreate::Random##TYPE, luabind::adopt(luabind::result)), \ - luabind::def((std::string("Random") + std::string(#TYPE)).c_str(), (TYPE * (*)(std::string)) & LuaAdaptersEntityCreate::Random##TYPE, luabind::adopt(luabind::result)), \ - luabind::def((std::string("To") + std::string(#TYPE)).c_str(), (TYPE * (*)(Entity*)) & LuaAdaptersEntityCast::To##TYPE), \ - luabind::def((std::string("To") + std::string(#TYPE)).c_str(), (const TYPE* (*)(const Entity*)) & LuaAdaptersEntityCast::ToConst##TYPE), \ - luabind::def((std::string("Is") + std::string(#TYPE)).c_str(), (bool (*)(const Entity*)) & LuaAdaptersEntityCast::Is##TYPE), \ - OWNINGSCOPE::Register##TYPE##LuaBindings() + registry.Function("Create" #TYPE, static_cast(&LuaAdaptersEntityCreate::Create##TYPE), LuaBinding::AdoptResult); \ + registry.Function("Create" #TYPE, static_cast(&LuaAdaptersEntityCreate::Create##TYPE), LuaBinding::AdoptResult); \ + registry.Function("Random" #TYPE, static_cast(&LuaAdaptersEntityCreate::Random##TYPE), LuaBinding::AdoptResult); \ + registry.Function("Random" #TYPE, static_cast(&LuaAdaptersEntityCreate::Random##TYPE), LuaBinding::AdoptResult); \ + registry.Function("Random" #TYPE, static_cast(&LuaAdaptersEntityCreate::Random##TYPE), LuaBinding::AdoptResult); \ + registry.Function("To" #TYPE, static_cast(&LuaAdaptersEntityCast::To##TYPE)); \ + registry.Function("To" #TYPE, static_cast(&LuaAdaptersEntityCast::ToConst##TYPE)); \ + registry.Function("Is" #TYPE, static_cast(&LuaAdaptersEntityCast::Is##TYPE)); \ + OWNINGSCOPE::Register##TYPE##LuaBindings(registry) #pragma endregion /// Struct that contains Lua binding registration functions for System classes. diff --git a/Source/Lua/LuaBindingsActivities.cpp b/Source/Lua/LuaBindingsActivities.cpp index 08d1dbcc71..83cb3812d3 100644 --- a/Source/Lua/LuaBindingsActivities.cpp +++ b/Source/Lua/LuaBindingsActivities.cpp @@ -5,172 +5,172 @@ using namespace RTE; LuaBindingRegisterFunctionDefinitionForType(ActivityLuaBindings, Activity) { - return AbstractTypeLuaClassDefinition(Activity, Entity) + AbstractTypeLuaClassDefinition(Activity, Entity) - .def(luabind::constructor<>()) + .addConstructor<>() - .property("Description", &Activity::GetDescription) - .property("InCampaignStage", &Activity::GetInCampaignStage, &Activity::SetInCampaignStage) - .property("ActivityState", &Activity::GetActivityState, &Activity::SetActivityState) - .property("AllowsUserSaving", &Activity::GetAllowsUserSaving, &Activity::SetAllowsUserSaving) - .property("SceneName", &Activity::GetSceneName, &Activity::SetSceneName) - .property("PlayerCount", &Activity::GetPlayerCount) - .property("HumanCount", &Activity::GetHumanCount) - .property("TeamCount", &Activity::GetTeamCount) - .property("Difficulty", &Activity::GetDifficulty, &Activity::SetDifficulty) + .addProperty("Description", &Activity::GetDescription) + .addProperty("InCampaignStage", &Activity::GetInCampaignStage, &Activity::SetInCampaignStage) + .addProperty("ActivityState", &Activity::GetActivityState, &Activity::SetActivityState) + .addProperty("AllowsUserSaving", &Activity::GetAllowsUserSaving, &Activity::SetAllowsUserSaving) + .addProperty("SceneName", &Activity::GetSceneName, &Activity::SetSceneName) + .addProperty("PlayerCount", &Activity::GetPlayerCount) + .addProperty("HumanCount", &Activity::GetHumanCount) + .addProperty("TeamCount", &Activity::GetTeamCount) + .addProperty("Difficulty", &Activity::GetDifficulty, &Activity::SetDifficulty) - .def("DeactivatePlayer", &Activity::DeactivatePlayer) - .def("PlayerActive", &Activity::PlayerActive) - .def("PlayerHuman", &Activity::PlayerHuman) - .def("TeamActive", &Activity::TeamActive) - .def("GetTeamOfPlayer", &Activity::GetTeamOfPlayer) - .def("SetTeamOfPlayer", &Activity::SetTeamOfPlayer) - .def("PlayersInTeamCount", &Activity::PlayersInTeamCount) - .def("ScreenOfPlayer", &Activity::ScreenOfPlayer) - .def("GetViewState", &Activity::GetViewState) - .def("SetViewState", &Activity::SetViewState) - .def("GetPlayerBrain", &Activity::GetPlayerBrain) - .def("SetPlayerBrain", &Activity::SetPlayerBrain) - .def("PlayerHadBrain", &Activity::PlayerHadBrain) - .def("SetPlayerHadBrain", &Activity::SetPlayerHadBrain) - .def("SetBrainEvacuated", &Activity::SetBrainEvacuated) - .def("BrainWasEvacuated", &Activity::BrainWasEvacuated) - .def("IsAssignedBrain", &Activity::IsAssignedBrain) - .def("IsBrainOfWhichPlayer", &Activity::IsBrainOfWhichPlayer) - .def("IsOtherPlayerBrain", &Activity::IsOtherPlayerBrain) - .def("HumanBrainCount", &Activity::HumanBrainCount) - .def("AIBrainCount", &Activity::AIBrainCount) - .def("GetControlledActor", &Activity::GetControlledActor) - .def("GetPlayerController", &Activity::GetPlayerController) - .def("SetTeamFunds", &Activity::SetTeamFunds) - .def("GetTeamFunds", &Activity::GetTeamFunds) - .def("SetTeamAISkill", &Activity::SetTeamAISkill) - .def("GetTeamAISkill", &Activity::GetTeamAISkill) - .def("ChangeTeamFunds", &Activity::ChangeTeamFunds) - .def("TeamFundsChanged", &Activity::TeamFundsChanged) - .def("ReportDeath", &Activity::ReportDeath) - .def("GetTeamDeathCount", &Activity::GetTeamDeathCount) - .def("IsRunning", &Activity::IsRunning) - .def("IsPaused", &Activity::IsPaused) - .def("IsOver", &Activity::IsOver) - .def("SwitchToActor", &Activity::SwitchToActor) - .def("SwitchToNextActor", &Activity::SwitchToNextActor) - .def("SwitchToPrevActor", &Activity::SwitchToPrevActor) - .def("IsHumanTeam", &Activity::IsHumanTeam) - .def("ResetMessageTimer", &Activity::ResetMessageTimer) - .def("SaveString", &Activity::SaveString) - .def("LoadString", &Activity::LoadString) - .def("SaveNumber", &Activity::SaveNumber) - .def("LoadNumber", &Activity::LoadNumber) - .def("SendMessage", &LuaAdaptersActivity::SendMessage1) - .def("SendMessage", &LuaAdaptersActivity::SendMessage2) + .addFunction("DeactivatePlayer", &Activity::DeactivatePlayer) + .addFunction("PlayerActive", &Activity::PlayerActive) + .addFunction("PlayerHuman", &Activity::PlayerHuman) + .addFunction("TeamActive", &Activity::TeamActive) + .addFunction("GetTeamOfPlayer", &Activity::GetTeamOfPlayer) + .addFunction("SetTeamOfPlayer", &Activity::SetTeamOfPlayer) + .addFunction("PlayersInTeamCount", &Activity::PlayersInTeamCount) + .addFunction("ScreenOfPlayer", &Activity::ScreenOfPlayer) + .addFunction("GetViewState", &Activity::GetViewState) + .addFunction("SetViewState", &Activity::SetViewState) + .addFunction("GetPlayerBrain", &Activity::GetPlayerBrain) + .addFunction("SetPlayerBrain", &Activity::SetPlayerBrain) + .addFunction("PlayerHadBrain", &Activity::PlayerHadBrain) + .addFunction("SetPlayerHadBrain", &Activity::SetPlayerHadBrain) + .addFunction("SetBrainEvacuated", &Activity::SetBrainEvacuated) + .addFunction("BrainWasEvacuated", &Activity::BrainWasEvacuated) + .addFunction("IsAssignedBrain", &Activity::IsAssignedBrain) + .addFunction("IsBrainOfWhichPlayer", &Activity::IsBrainOfWhichPlayer) + .addFunction("IsOtherPlayerBrain", &Activity::IsOtherPlayerBrain) + .addFunction("HumanBrainCount", &Activity::HumanBrainCount) + .addFunction("AIBrainCount", &Activity::AIBrainCount) + .addFunction("GetControlledActor", &Activity::GetControlledActor) + .addFunction("GetPlayerController", &Activity::GetPlayerController) + .addFunction("SetTeamFunds", &Activity::SetTeamFunds) + .addFunction("GetTeamFunds", &Activity::GetTeamFunds) + .addFunction("SetTeamAISkill", &Activity::SetTeamAISkill) + .addFunction("GetTeamAISkill", &Activity::GetTeamAISkill) + .addFunction("ChangeTeamFunds", &Activity::ChangeTeamFunds) + .addFunction("TeamFundsChanged", &Activity::TeamFundsChanged) + .addFunction("ReportDeath", &Activity::ReportDeath) + .addFunction("GetTeamDeathCount", &Activity::GetTeamDeathCount) + .addFunction("IsRunning", &Activity::IsRunning) + .addFunction("IsPaused", &Activity::IsPaused) + .addFunction("IsOver", &Activity::IsOver) + .addFunction("SwitchToActor", &Activity::SwitchToActor) + .addFunction("SwitchToNextActor", &Activity::SwitchToNextActor) + .addFunction("SwitchToPrevActor", &Activity::SwitchToPrevActor) + .addFunction("IsHumanTeam", &Activity::IsHumanTeam) + .addFunction("ResetMessageTimer", &Activity::ResetMessageTimer) + .addFunction("SaveString", &Activity::SaveString) + .addFunction("LoadString", &Activity::LoadString) + .addFunction("SaveNumber", &Activity::SaveNumber) + .addFunction("LoadNumber", &Activity::LoadNumber) + .addFunction("SendMessage", &LuaAdaptersActivity::SendMessage1) + .addFunction("SendMessage", &LuaAdaptersActivity::SendMessage2) - .enum_("Players")[luabind::value("PLAYER_NONE", Players::NoPlayer), - luabind::value("PLAYER_1", Players::PlayerOne), - luabind::value("PLAYER_2", Players::PlayerTwo), - luabind::value("PLAYER_3", Players::PlayerThree), - luabind::value("PLAYER_4", Players::PlayerFour), - luabind::value("MAXPLAYERCOUNT", Players::MaxPlayerCount)] - .enum_("ActivityState")[luabind::value("NOACTIVITY", Activity::ActivityState::NoActivity), - luabind::value("NOTSTARTED", Activity::ActivityState::NotStarted), - luabind::value("STARTING", Activity::ActivityState::Starting), - luabind::value("EDITING", Activity::ActivityState::Editing), - luabind::value("PREGAME", Activity::ActivityState::PreGame), - luabind::value("RUNNING", Activity::ActivityState::Running), - luabind::value("INERROR", Activity::ActivityState::HasError), - luabind::value("OVER", Activity::ActivityState::Over)] - .enum_("Team")[luabind::value("NOTEAM", Activity::Teams::NoTeam), - luabind::value("TEAM_1", Activity::Teams::TeamOne), - luabind::value("TEAM_2", Activity::Teams::TeamTwo), - luabind::value("TEAM_3", Activity::Teams::TeamThree), - luabind::value("TEAM_4", Activity::Teams::TeamFour), - luabind::value("MAXTEAMCOUNT", Activity::Teams::MaxTeamCount)] - .enum_("ViewState")[luabind::value("NORMAL", Activity::ViewState::Normal), - luabind::value("OBSERVE", Activity::ViewState::Observe), - luabind::value("DEATHWATCH", Activity::ViewState::DeathWatch), - luabind::value("ACTORSELECT", Activity::ViewState::ActorSelect), - luabind::value("AISENTRYPOINT", Activity::ViewState::AISentryPoint), - luabind::value("AIPATROLPOINTS", Activity::ViewState::AIPatrolPoints), - luabind::value("AIGOLDDIGPOINT", Activity::ViewState::AIGoldDigPoint), - luabind::value("AIGOTOPOINT", Activity::ViewState::AIGoToPoint), - luabind::value("LZSELECT", Activity::ViewState::LandingZoneSelect)] - .enum_("DifficultySetting")[luabind::value("MINDIFFICULTY", Activity::DifficultySetting::MinDifficulty), - luabind::value("CAKEDIFFICULTY", Activity::DifficultySetting::CakeDifficulty), - luabind::value("EASYDIFFICULTY", Activity::DifficultySetting::EasyDifficulty), - luabind::value("MEDIUMDIFFICULTY", Activity::DifficultySetting::MediumDifficulty), - luabind::value("HARDDIFFICULTY", Activity::DifficultySetting::HardDifficulty), - luabind::value("NUTSDIFFICULTY", Activity::DifficultySetting::NutsDifficulty), - luabind::value("MAXDIFFICULTY", Activity::DifficultySetting::MaxDifficulty)] - .enum_("AISkillSetting")[luabind::value("MINSKILL", Activity::AISkillSetting::MinSkill), - luabind::value("INFERIORSKILL", Activity::AISkillSetting::InferiorSkill), - luabind::value("DEFAULTSKILL", Activity::AISkillSetting::DefaultSkill), - luabind::value("AVERAGESKILL", Activity::AISkillSetting::AverageSkill), - luabind::value("GOODSKILL", Activity::AISkillSetting::GoodSkill), - luabind::value("UNFAIRSKILL", Activity::AISkillSetting::UnfairSkill)]; + .addEnum({{"PLAYER_NONE", Players::NoPlayer}, + {"PLAYER_1", Players::PlayerOne}, + {"PLAYER_2", Players::PlayerTwo}, + {"PLAYER_3", Players::PlayerThree}, + {"PLAYER_4", Players::PlayerFour}, + {"MAXPLAYERCOUNT", Players::MaxPlayerCount}}) + .addEnum({{"NOACTIVITY", Activity::ActivityState::NoActivity}, + {"NOTSTARTED", Activity::ActivityState::NotStarted}, + {"STARTING", Activity::ActivityState::Starting}, + {"EDITING", Activity::ActivityState::Editing}, + {"PREGAME", Activity::ActivityState::PreGame}, + {"RUNNING", Activity::ActivityState::Running}, + {"INERROR", Activity::ActivityState::HasError}, + {"OVER", Activity::ActivityState::Over}}) + .addEnum({{"NOTEAM", Activity::Teams::NoTeam}, + {"TEAM_1", Activity::Teams::TeamOne}, + {"TEAM_2", Activity::Teams::TeamTwo}, + {"TEAM_3", Activity::Teams::TeamThree}, + {"TEAM_4", Activity::Teams::TeamFour}, + {"MAXTEAMCOUNT", Activity::Teams::MaxTeamCount}}) + .addEnum({{"NORMAL", Activity::ViewState::Normal}, + {"OBSERVE", Activity::ViewState::Observe}, + {"DEATHWATCH", Activity::ViewState::DeathWatch}, + {"ACTORSELECT", Activity::ViewState::ActorSelect}, + {"AISENTRYPOINT", Activity::ViewState::AISentryPoint}, + {"AIPATROLPOINTS", Activity::ViewState::AIPatrolPoints}, + {"AIGOLDDIGPOINT", Activity::ViewState::AIGoldDigPoint}, + {"AIGOTOPOINT", Activity::ViewState::AIGoToPoint}, + {"LZSELECT", Activity::ViewState::LandingZoneSelect}}) + .addEnum({{"MINDIFFICULTY", Activity::DifficultySetting::MinDifficulty}, + {"CAKEDIFFICULTY", Activity::DifficultySetting::CakeDifficulty}, + {"EASYDIFFICULTY", Activity::DifficultySetting::EasyDifficulty}, + {"MEDIUMDIFFICULTY", Activity::DifficultySetting::MediumDifficulty}, + {"HARDDIFFICULTY", Activity::DifficultySetting::HardDifficulty}, + {"NUTSDIFFICULTY", Activity::DifficultySetting::NutsDifficulty}, + {"MAXDIFFICULTY", Activity::DifficultySetting::MaxDifficulty}}) + .addEnum({{"MINSKILL", Activity::AISkillSetting::MinSkill}, + {"INFERIORSKILL", Activity::AISkillSetting::InferiorSkill}, + {"DEFAULTSKILL", Activity::AISkillSetting::DefaultSkill}, + {"AVERAGESKILL", Activity::AISkillSetting::AverageSkill}, + {"GOODSKILL", Activity::AISkillSetting::GoodSkill}, + {"UNFAIRSKILL", Activity::AISkillSetting::UnfairSkill}}); } LuaBindingRegisterFunctionDefinitionForType(ActivityLuaBindings, GameActivity) { - return luabind::class_("GameActivity") + registry.Class("GameActivity") - .def(luabind::constructor<>()) + .addConstructor<>() - .property("WinnerTeam", &GameActivity::GetWinnerTeam, &GameActivity::SetWinnerTeam) - .property("CPUTeam", &GameActivity::GetCPUTeam, &GameActivity::SetCPUTeam) - .property("DeliveryDelay", &GameActivity::GetDeliveryDelay, &GameActivity::SetDeliveryDelay) - .property("BuyMenuEnabled", &GameActivity::GetBuyMenuEnabled, &GameActivity::SetBuyMenuEnabled) - .property("CraftsOrbitAtTheEdge", &GameActivity::GetCraftOrbitAtTheEdge, &GameActivity::SetCraftOrbitAtTheEdge) + .addProperty("WinnerTeam", &GameActivity::GetWinnerTeam, &GameActivity::SetWinnerTeam) + .addProperty("CPUTeam", &GameActivity::GetCPUTeam, &GameActivity::SetCPUTeam) + .addProperty("DeliveryDelay", &GameActivity::GetDeliveryDelay, &GameActivity::SetDeliveryDelay) + .addProperty("BuyMenuEnabled", &GameActivity::GetBuyMenuEnabled, &GameActivity::SetBuyMenuEnabled) + .addProperty("CraftsOrbitAtTheEdge", &GameActivity::GetCraftOrbitAtTheEdge, &GameActivity::SetCraftOrbitAtTheEdge) - //.def_readwrite("ActorCursor", &GameActivity::m_ActorCursor) - .def_readwrite("CursorTimer", &GameActivity::m_CursorTimer) - .def_readwrite("GameTimer", &GameActivity::m_GameTimer) - .def_readwrite("GameOverTimer", &GameActivity::m_GameOverTimer) - .def_readwrite("GameOverPeriod", &GameActivity::m_GameOverPeriod) + //.addReadWriteMember("ActorCursor", &GameActivity::m_ActorCursor) + .addReadWriteMember("CursorTimer", &GameActivity::m_CursorTimer) + .addReadWriteMember("GameTimer", &GameActivity::m_GameTimer) + .addReadWriteMember("GameOverTimer", &GameActivity::m_GameOverTimer) + .addReadWriteMember("GameOverPeriod", &GameActivity::m_GameOverPeriod) - .def("SetObservationTarget", &GameActivity::SetObservationTarget) - .def("SetDeathViewTarget", &GameActivity::SetDeathViewTarget) - .def("SetLandingZone", &GameActivity::SetLandingZone) - .def("GetLandingZone", &GameActivity::GetLandingZone) - .def("SetActorSelectCursor", &GameActivity::SetActorSelectCursor) - .def("GetBuyGUI", &GameActivity::GetBuyGUI) - .def("IsBuyGUIVisible", &GameActivity::IsBuyGUIVisible) - .def("GetEditorGUI", &GameActivity::GetEditorGUI) - .def("LockControlledActor", &GameActivity::LockControlledActor) - .def("OtherTeam", &GameActivity::OtherTeam) - .def("OneOrNoneTeamsLeft", &GameActivity::OneOrNoneTeamsLeft) - .def("WhichTeamLeft", &GameActivity::WhichTeamLeft) - .def("NoTeamLeft", &GameActivity::NoTeamLeft) - .def("OnlyOneTeamLeft", &GameActivity::OneOrNoneTeamsLeft) // Backwards compat - .def("GetBanner", &GameActivity::GetBanner) - .def("SetLZArea", &GameActivity::SetLZArea) - .def("GetLZArea", &GameActivity::GetLZArea) - .def("SetBrainLZWidth", &GameActivity::SetBrainLZWidth) - .def("GetBrainLZWidth", &GameActivity::GetBrainLZWidth) - .def("GetActiveCPUTeamCount", &GameActivity::GetActiveCPUTeamCount) - .def("GetActiveHumanTeamCount", &GameActivity::GetActiveHumanTeamCount) - .def("AddObjectivePoint", &GameActivity::AddObjectivePoint) - .def("YSortObjectivePoints", &GameActivity::YSortObjectivePoints) - .def("ClearObjectivePoints", &GameActivity::ClearObjectivePoints) - .def("AddOverridePurchase", &GameActivity::AddOverridePurchase) - .def("SetOverridePurchaseList", (int(GameActivity::*)(const Loadout*, int)) & GameActivity::SetOverridePurchaseList) - .def("SetOverridePurchaseList", (int(GameActivity::*)(const std::string&, int)) & GameActivity::SetOverridePurchaseList) - .def("ClearOverridePurchase", &GameActivity::ClearOverridePurchase) - .def("CreateDelivery", (bool(GameActivity::*)(int)) & GameActivity::CreateDelivery) - .def("CreateDelivery", (bool(GameActivity::*)(int, int)) & GameActivity::CreateDelivery) - .def("CreateDelivery", (bool(GameActivity::*)(int, int, Vector&)) & GameActivity::CreateDelivery) - .def("CreateDelivery", (bool(GameActivity::*)(int, int, Actor*)) & GameActivity::CreateDelivery) - .def("GetDeliveryCount", &GameActivity::GetDeliveryCount) - .def("GetTeamTech", &GameActivity::GetTeamTech) - .def("SetTeamTech", &GameActivity::SetTeamTech) - .def("GetCrabToHumanSpawnRatio", &GameActivity::GetCrabToHumanSpawnRatio) - .def("TeamIsCPU", &GameActivity::TeamIsCPU) - .def("GetStartingGold", &GameActivity::GetStartingGold) - .def("GetFogOfWarEnabled", &GameActivity::GetFogOfWarEnabled) - .def("UpdateEditing", &GameActivity::UpdateEditing) - .def("DisableAIs", &GameActivity::DisableAIs) - .def("InitAIs", &GameActivity::InitAIs) + .addFunction("SetObservationTarget", &GameActivity::SetObservationTarget) + .addFunction("SetDeathViewTarget", &GameActivity::SetDeathViewTarget) + .addFunction("SetLandingZone", &GameActivity::SetLandingZone) + .addFunction("GetLandingZone", &GameActivity::GetLandingZone) + .addFunction("SetActorSelectCursor", &GameActivity::SetActorSelectCursor) + .addFunction("GetBuyGUI", &GameActivity::GetBuyGUI) + .addFunction("IsBuyGUIVisible", &GameActivity::IsBuyGUIVisible) + .addFunction("GetEditorGUI", &GameActivity::GetEditorGUI) + .addFunction("LockControlledActor", &GameActivity::LockControlledActor) + .addFunction("OtherTeam", &GameActivity::OtherTeam) + .addFunction("OneOrNoneTeamsLeft", &GameActivity::OneOrNoneTeamsLeft) + .addFunction("WhichTeamLeft", &GameActivity::WhichTeamLeft) + .addFunction("NoTeamLeft", &GameActivity::NoTeamLeft) + .addFunction("OnlyOneTeamLeft", &GameActivity::OneOrNoneTeamsLeft) // Backwards compat + .addFunction("GetBanner", &GameActivity::GetBanner) + .addFunction("SetLZArea", &GameActivity::SetLZArea) + .addFunction("GetLZArea", &GameActivity::GetLZArea) + .addFunction("SetBrainLZWidth", &GameActivity::SetBrainLZWidth) + .addFunction("GetBrainLZWidth", &GameActivity::GetBrainLZWidth) + .addFunction("GetActiveCPUTeamCount", &GameActivity::GetActiveCPUTeamCount) + .addFunction("GetActiveHumanTeamCount", &GameActivity::GetActiveHumanTeamCount) + .addFunction("AddObjectivePoint", &GameActivity::AddObjectivePoint) + .addFunction("YSortObjectivePoints", &GameActivity::YSortObjectivePoints) + .addFunction("ClearObjectivePoints", &GameActivity::ClearObjectivePoints) + .addFunction("AddOverridePurchase", &GameActivity::AddOverridePurchase) + .addFunction("SetOverridePurchaseList", (int(GameActivity::*)(const Loadout*, int)) & GameActivity::SetOverridePurchaseList) + .addFunction("SetOverridePurchaseList", (int(GameActivity::*)(const std::string&, int)) & GameActivity::SetOverridePurchaseList) + .addFunction("ClearOverridePurchase", &GameActivity::ClearOverridePurchase) + .addFunction("CreateDelivery", (bool(GameActivity::*)(int)) & GameActivity::CreateDelivery) + .addFunction("CreateDelivery", (bool(GameActivity::*)(int, int)) & GameActivity::CreateDelivery) + .addFunction("CreateDelivery", (bool(GameActivity::*)(int, int, Vector&)) & GameActivity::CreateDelivery) + .addFunction("CreateDelivery", (bool(GameActivity::*)(int, int, Actor*)) & GameActivity::CreateDelivery) + .addFunction("GetDeliveryCount", &GameActivity::GetDeliveryCount) + .addFunction("GetTeamTech", &GameActivity::GetTeamTech) + .addFunction("SetTeamTech", &GameActivity::SetTeamTech) + .addFunction("GetCrabToHumanSpawnRatio", &GameActivity::GetCrabToHumanSpawnRatio) + .addFunction("TeamIsCPU", &GameActivity::TeamIsCPU) + .addFunction("GetStartingGold", &GameActivity::GetStartingGold) + .addFunction("GetFogOfWarEnabled", &GameActivity::GetFogOfWarEnabled) + .addFunction("UpdateEditing", &GameActivity::UpdateEditing) + .addFunction("DisableAIs", &GameActivity::DisableAIs) + .addFunction("InitAIs", &GameActivity::InitAIs) - .enum_("ObjectiveArrowDir")[luabind::value("ARROWDOWN", GameActivity::ObjectiveArrowDir::ARROWDOWN), - luabind::value("ARROWLEFT", GameActivity::ObjectiveArrowDir::ARROWLEFT), - luabind::value("ARROWRIGHT", GameActivity::ObjectiveArrowDir::ARROWRIGHT), - luabind::value("ARROWUP", GameActivity::ObjectiveArrowDir::ARROWUP)]; + .addEnum({{"ARROWDOWN", GameActivity::ObjectiveArrowDir::ARROWDOWN}, + {"ARROWLEFT", GameActivity::ObjectiveArrowDir::ARROWLEFT}, + {"ARROWRIGHT", GameActivity::ObjectiveArrowDir::ARROWRIGHT}, + {"ARROWUP", GameActivity::ObjectiveArrowDir::ARROWUP}}); } diff --git a/Source/Lua/LuaBindingsEntities.cpp b/Source/Lua/LuaBindingsEntities.cpp index cb425407e2..0793d227ae 100644 --- a/Source/Lua/LuaBindingsEntities.cpp +++ b/Source/Lua/LuaBindingsEntities.cpp @@ -8,1396 +8,1395 @@ using namespace RTE; LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Entity) { - return luabind::class_("Entity") - - .def(luabind::tostring(luabind::const_self)) - - .property("ClassName", &Entity::GetClassName) - .property("PresetName", &Entity::GetPresetName, &LuaAdaptersEntity::SetPresetName) - .property("Description", &Entity::GetDescription, &Entity::SetDescription) - .property("IsOriginalPreset", &Entity::IsOriginalPreset) - .property("ModuleID", &Entity::GetModuleID) - .property("ModuleName", &Entity::GetModuleName) - .property("RandomWeight", &Entity::GetRandomWeight) - .property("Groups", &Entity::GetGroups, luabind::return_stl_iterator) - - .def("Clone", &LuaAdaptersEntityClone::CloneEntity, luabind::adopt(luabind::result)) - .def("Reset", &Entity::Reset) - .def("GetModuleAndPresetName", &Entity::GetModuleAndPresetName) - .def("AddToGroup", &Entity::AddToGroup) - .def("RemoveFromGroup", &Entity::RemoveFromGroup) - .def("IsInGroup", &Entity::IsInGroup); + registry.Class("Entity") + + .addToString() + + .addProperty("ClassName", &Entity::GetClassName) + .addProperty("PresetName", &Entity::GetPresetName, &LuaAdaptersEntity::SetPresetName) + .addProperty("Description", &Entity::GetDescription, &Entity::SetDescription) + .addProperty("IsOriginalPreset", &Entity::IsOriginalPreset) + .addProperty("ModuleID", &Entity::GetModuleID) + .addProperty("ModuleName", &Entity::GetModuleName) + .addProperty("RandomWeight", &Entity::GetRandomWeight) + .addProperty("Groups", &Entity::GetGroups, LuaBinding::ReturnStlIterator) + + .addFunction("Clone", &LuaAdaptersEntityClone::CloneEntity, LuaBinding::AdoptResult) + .addFunction("Reset", &Entity::Reset) + .addFunction("GetModuleAndPresetName", &Entity::GetModuleAndPresetName) + .addFunction("AddToGroup", &Entity::AddToGroup) + .addFunction("RemoveFromGroup", &Entity::RemoveFromGroup) + .addFunction("IsInGroup", &Entity::IsInGroup); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, ACDropShip) { - return ConcreteTypeLuaClassDefinition(ACDropShip, ACraft) - - .property("RightEngine", &ACDropShip::GetRightThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetRightThruster) - .property("LeftEngine", &ACDropShip::GetLeftThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetLeftThruster) - .property("RightThruster", &ACDropShip::GetURightThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetURightThruster) - .property("LeftThruster", &ACDropShip::GetULeftThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetULeftThruster) - .property("RightHatch", &ACDropShip::GetRightHatch, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetRightHatch) - .property("LeftHatch", &ACDropShip::GetLeftHatch, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetLeftHatch) - .property("MaxEngineAngle", &ACDropShip::GetMaxEngineAngle, &ACDropShip::SetMaxEngineAngle) - .property("LateralControlSpeed", &ACDropShip::GetLateralControlSpeed, &ACDropShip::SetLateralControlSpeed) - .property("LateralControl", &ACDropShip::GetLateralControl) - .property("HoverHeightModifier", &ACDropShip::GetHoverHeightModifier, &ACDropShip::SetHoverHeightModifier) - - .def("DetectObstacle", &ACDropShip::DetectObstacle) - .def("GetAltitude", &ACDropShip::GetAltitude); + ConcreteTypeLuaClassDefinition(ACDropShip, ACraft) + + .addProperty("RightEngine", &ACDropShip::GetRightThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetRightThruster) + .addProperty("LeftEngine", &ACDropShip::GetLeftThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetLeftThruster) + .addProperty("RightThruster", &ACDropShip::GetURightThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetURightThruster) + .addProperty("LeftThruster", &ACDropShip::GetULeftThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetULeftThruster) + .addProperty("RightHatch", &ACDropShip::GetRightHatch, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetRightHatch) + .addProperty("LeftHatch", &ACDropShip::GetLeftHatch, &LuaAdaptersPropertyOwnershipSafetyFaker::ACDropShipSetLeftHatch) + .addProperty("MaxEngineAngle", &ACDropShip::GetMaxEngineAngle, &ACDropShip::SetMaxEngineAngle) + .addProperty("LateralControlSpeed", &ACDropShip::GetLateralControlSpeed, &ACDropShip::SetLateralControlSpeed) + .addProperty("LateralControl", &ACDropShip::GetLateralControl) + .addProperty("HoverHeightModifier", &ACDropShip::GetHoverHeightModifier, &ACDropShip::SetHoverHeightModifier) + + .addFunction("DetectObstacle", &ACDropShip::DetectObstacle) + .addFunction("GetAltitude", &ACDropShip::GetAltitude); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, ACrab) { - return ConcreteTypeLuaClassDefinition(ACrab, Actor) - - .def(luabind::constructor<>()) - - .property("Turret", &ACrab::GetTurret, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetTurret) - .property("Jetpack", &ACrab::GetJetpack, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetJetpack) - .property("LeftFGLeg", &ACrab::GetLeftFGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetLeftFGLeg) - .property("LeftBGLeg", &ACrab::GetLeftBGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetLeftBGLeg) - .property("RightFGLeg", &ACrab::GetRightFGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetRightFGLeg) - .property("RightBGLeg", &ACrab::GetRightBGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetRightBGLeg) - .property("StrideSound", &ACrab::GetStrideSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetStrideSound) - .property("StrideFrame", &ACrab::StrideFrame) - .property("EquippedItem", &ACrab::GetEquippedItem) - .property("FirearmIsReady", &ACrab::FirearmIsReady) - .property("FirearmIsEmpty", &ACrab::FirearmIsEmpty) - .property("FirearmNeedsReload", &ACrab::FirearmNeedsReload) - .property("FirearmIsSemiAuto", &ACrab::FirearmIsSemiAuto) - .property("FirearmActivationDelay", &ACrab::FirearmActivationDelay) - .property("AimRangeUpperLimit", &ACrab::GetAimRangeUpperLimit, &ACrab::SetAimRangeUpperLimit) - .property("AimRangeLowerLimit", &ACrab::GetAimRangeLowerLimit, &ACrab::SetAimRangeLowerLimit) - - .def("ReloadFirearms", &ACrab::ReloadFirearms) - .def("IsWithinRange", &ACrab::IsWithinRange) - .def("Look", &ACrab::Look) - .def("LookForMOs", &ACrab::LookForMOs) - .def("GetLimbPath", &ACrab::GetLimbPath) - .def("GetLimbPathTravelSpeed", &ACrab::GetLimbPathTravelSpeed) - .def("SetLimbPathTravelSpeed", &ACrab::SetLimbPathTravelSpeed) - .def("GetLimbPathPushForce", &ACrab::GetLimbPathPushForce) - .def("SetLimbPathPushForce", &ACrab::SetLimbPathPushForce) - - .enum_("Side")[luabind::value("LEFTSIDE", ACrab::Side::LEFTSIDE), - luabind::value("RIGHTSIDE", ACrab::Side::RIGHTSIDE), - luabind::value("SIDECOUNT", ACrab::Side::SIDECOUNT)] - .enum_("Layer")[luabind::value("FGROUND", ACrab::Layer::FGROUND), - luabind::value("BGROUND", ACrab::Layer::BGROUND)] - .enum_("DeviceHandlingState")[luabind::value("STILL", ACrab::DeviceHandlingState::STILL), - luabind::value("POINTING", ACrab::DeviceHandlingState::POINTING), - luabind::value("SCANNING", ACrab::DeviceHandlingState::SCANNING), - luabind::value("AIMING", ACrab::DeviceHandlingState::AIMING), - luabind::value("FIRING", ACrab::DeviceHandlingState::FIRING), - luabind::value("THROWING", ACrab::DeviceHandlingState::THROWING), - luabind::value("DIGGING", ACrab::DeviceHandlingState::DIGGING)] - .enum_("SweepState")[luabind::value("NOSWEEP", ACrab::SweepState::NOSWEEP), - luabind::value("SWEEPINGUP", ACrab::SweepState::SWEEPINGUP), - luabind::value("SWEEPUPPAUSE", ACrab::SweepState::SWEEPUPPAUSE), - luabind::value("SWEEPINGDOWN", ACrab::SweepState::SWEEPINGDOWN), - luabind::value("SWEEPDOWNPAUSE", ACrab::SweepState::SWEEPDOWNPAUSE)] - .enum_("DigState")[luabind::value("NOTDIGGING", ACrab::DigState::NOTDIGGING), - luabind::value("PREDIG", ACrab::DigState::PREDIG), - luabind::value("STARTDIG", ACrab::DigState::STARTDIG), - luabind::value("TUNNELING", ACrab::DigState::TUNNELING), - luabind::value("FINISHINGDIG", ACrab::DigState::FINISHINGDIG), - luabind::value("PAUSEDIGGER", ACrab::DigState::PAUSEDIGGER)] - .enum_("JumpState")[luabind::value("NOTJUMPING", ACrab::JumpState::NOTJUMPING), - luabind::value("FORWARDJUMP", ACrab::JumpState::FORWARDJUMP), - luabind::value("PREJUMP", ACrab::JumpState::PREUPJUMP), - luabind::value("UPJUMP", ACrab::JumpState::UPJUMP), - luabind::value("APEXJUMP", ACrab::JumpState::APEXJUMP), - luabind::value("LANDJUMP", ACrab::JumpState::LANDJUMP)]; + ConcreteTypeLuaClassDefinition(ACrab, Actor) + + .addConstructor<>() + + .addProperty("Turret", &ACrab::GetTurret, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetTurret) + .addProperty("Jetpack", &ACrab::GetJetpack, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetJetpack) + .addProperty("LeftFGLeg", &ACrab::GetLeftFGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetLeftFGLeg) + .addProperty("LeftBGLeg", &ACrab::GetLeftBGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetLeftBGLeg) + .addProperty("RightFGLeg", &ACrab::GetRightFGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetRightFGLeg) + .addProperty("RightBGLeg", &ACrab::GetRightBGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetRightBGLeg) + .addProperty("StrideSound", &ACrab::GetStrideSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ACrabSetStrideSound) + .addProperty("StrideFrame", &ACrab::StrideFrame) + .addProperty("EquippedItem", &ACrab::GetEquippedItem) + .addProperty("FirearmIsReady", &ACrab::FirearmIsReady) + .addProperty("FirearmIsEmpty", &ACrab::FirearmIsEmpty) + .addProperty("FirearmNeedsReload", &ACrab::FirearmNeedsReload) + .addProperty("FirearmIsSemiAuto", &ACrab::FirearmIsSemiAuto) + .addProperty("FirearmActivationDelay", &ACrab::FirearmActivationDelay) + .addProperty("AimRangeUpperLimit", &ACrab::GetAimRangeUpperLimit, &ACrab::SetAimRangeUpperLimit) + .addProperty("AimRangeLowerLimit", &ACrab::GetAimRangeLowerLimit, &ACrab::SetAimRangeLowerLimit) + + .addFunction("ReloadFirearms", &ACrab::ReloadFirearms) + .addFunction("IsWithinRange", &ACrab::IsWithinRange) + .addFunction("Look", &ACrab::Look) + .addFunction("LookForMOs", &ACrab::LookForMOs) + .addFunction("GetLimbPath", &ACrab::GetLimbPath) + .addFunction("GetLimbPathTravelSpeed", &ACrab::GetLimbPathTravelSpeed) + .addFunction("SetLimbPathTravelSpeed", &ACrab::SetLimbPathTravelSpeed) + .addFunction("GetLimbPathPushForce", &ACrab::GetLimbPathPushForce) + .addFunction("SetLimbPathPushForce", &ACrab::SetLimbPathPushForce) + + .addEnum({{"LEFTSIDE", ACrab::Side::LEFTSIDE}, + {"RIGHTSIDE", ACrab::Side::RIGHTSIDE}, + {"SIDECOUNT", ACrab::Side::SIDECOUNT}}) + .addEnum({{"FGROUND", ACrab::Layer::FGROUND}, + {"BGROUND", ACrab::Layer::BGROUND}}) + .addEnum({{"STILL", ACrab::DeviceHandlingState::STILL}, + {"POINTING", ACrab::DeviceHandlingState::POINTING}, + {"SCANNING", ACrab::DeviceHandlingState::SCANNING}, + {"AIMING", ACrab::DeviceHandlingState::AIMING}, + {"FIRING", ACrab::DeviceHandlingState::FIRING}, + {"THROWING", ACrab::DeviceHandlingState::THROWING}, + {"DIGGING", ACrab::DeviceHandlingState::DIGGING}}) + .addEnum({{"NOSWEEP", ACrab::SweepState::NOSWEEP}, + {"SWEEPINGUP", ACrab::SweepState::SWEEPINGUP}, + {"SWEEPUPPAUSE", ACrab::SweepState::SWEEPUPPAUSE}, + {"SWEEPINGDOWN", ACrab::SweepState::SWEEPINGDOWN}, + {"SWEEPDOWNPAUSE", ACrab::SweepState::SWEEPDOWNPAUSE}}) + .addEnum({{"NOTDIGGING", ACrab::DigState::NOTDIGGING}, + {"PREDIG", ACrab::DigState::PREDIG}, + {"STARTDIG", ACrab::DigState::STARTDIG}, + {"TUNNELING", ACrab::DigState::TUNNELING}, + {"FINISHINGDIG", ACrab::DigState::FINISHINGDIG}, + {"PAUSEDIGGER", ACrab::DigState::PAUSEDIGGER}}) + .addEnum({{"NOTJUMPING", ACrab::JumpState::NOTJUMPING}, + {"FORWARDJUMP", ACrab::JumpState::FORWARDJUMP}, + {"PREJUMP", ACrab::JumpState::PREUPJUMP}, + {"UPJUMP", ACrab::JumpState::UPJUMP}, + {"APEXJUMP", ACrab::JumpState::APEXJUMP}, + {"LANDJUMP", ACrab::JumpState::LANDJUMP}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, ACraft) { - return AbstractTypeLuaClassDefinition(ACraft, Actor) - - .property("HatchState", &ACraft::GetHatchState) - .property("HatchOpenSound", &ACraft::GetHatchOpenSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ACraftSetHatchOpenSound) - .property("HatchCloseSound", &ACraft::GetHatchCloseSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ACraftSetHatchCloseSound) - .property("CrashSound", &ACraft::GetCrashSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ACraftSetCrashSound) - .property("CanEnterOrbit", &ACraft::GetCanEnterOrbit, &ACraft::SetCanEnterOrbit) - .property("MaxPassengers", &ACraft::GetMaxPassengers) - .property("DeliveryDelayMultiplier", &ACraft::GetDeliveryDelayMultiplier) - .property("ScuttleOnDeath", &ACraft::GetScuttleOnDeath, &ACraft::SetScuttleOnDeath) - .property("HatchDelay", &ACraft::GetHatchDelay, &ACraft::SetHatchDelay) - - .def("OpenHatch", &ACraft::OpenHatch) - .def("CloseHatch", &ACraft::CloseHatch) - - .enum_("HatchState")[luabind::value("CLOSED", ACraft::HatchState::CLOSED), - luabind::value("OPENING", ACraft::HatchState::OPENING), - luabind::value("OPEN", ACraft::HatchState::OPEN), - luabind::value("CLOSING", ACraft::HatchState::CLOSING), - luabind::value("HatchStateCount", ACraft::HatchState::HatchStateCount)] - .enum_("Side")[luabind::value("RIGHT", ACraft::Side::RIGHT), - luabind::value("LEFT", ACraft::Side::LEFT)] - - .enum_("CraftDeliverySequence")[luabind::value("FALL", ACraft::CraftDeliverySequence::FALL), - luabind::value("LAND", ACraft::CraftDeliverySequence::LAND), - luabind::value("STANDBY", ACraft::CraftDeliverySequence::STANDBY), - luabind::value("UNLOAD", ACraft::CraftDeliverySequence::UNLOAD), - luabind::value("LAUNCH", ACraft::CraftDeliverySequence::LAUNCH), - luabind::value("UNSTICK", ACraft::CraftDeliverySequence::UNSTICK)] - .enum_("AltitudeMoveState")[luabind::value("HOVER", ACraft::AltitudeMoveState::HOVER), - luabind::value("DESCEND", ACraft::AltitudeMoveState::DESCEND), - luabind::value("ASCEND", ACraft::AltitudeMoveState::ASCEND)]; + AbstractTypeLuaClassDefinition(ACraft, Actor) + + .addProperty("HatchState", &ACraft::GetHatchState) + .addProperty("HatchOpenSound", &ACraft::GetHatchOpenSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ACraftSetHatchOpenSound) + .addProperty("HatchCloseSound", &ACraft::GetHatchCloseSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ACraftSetHatchCloseSound) + .addProperty("CrashSound", &ACraft::GetCrashSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ACraftSetCrashSound) + .addProperty("CanEnterOrbit", &ACraft::GetCanEnterOrbit, &ACraft::SetCanEnterOrbit) + .addProperty("MaxPassengers", &ACraft::GetMaxPassengers) + .addProperty("DeliveryDelayMultiplier", &ACraft::GetDeliveryDelayMultiplier) + .addProperty("ScuttleOnDeath", &ACraft::GetScuttleOnDeath, &ACraft::SetScuttleOnDeath) + .addProperty("HatchDelay", &ACraft::GetHatchDelay, &ACraft::SetHatchDelay) + + .addFunction("OpenHatch", &ACraft::OpenHatch) + .addFunction("CloseHatch", &ACraft::CloseHatch) + + .addEnum({{"CLOSED", ACraft::HatchState::CLOSED}, + {"OPENING", ACraft::HatchState::OPENING}, + {"OPEN", ACraft::HatchState::OPEN}, + {"CLOSING", ACraft::HatchState::CLOSING}, + {"HatchStateCount", ACraft::HatchState::HatchStateCount}}) + .addEnum({{"RIGHT", ACraft::Side::RIGHT}, + {"LEFT", ACraft::Side::LEFT}}) + + .addEnum({{"FALL", ACraft::CraftDeliverySequence::FALL}, + {"LAND", ACraft::CraftDeliverySequence::LAND}, + {"STANDBY", ACraft::CraftDeliverySequence::STANDBY}, + {"UNLOAD", ACraft::CraftDeliverySequence::UNLOAD}, + {"LAUNCH", ACraft::CraftDeliverySequence::LAUNCH}, + {"UNSTICK", ACraft::CraftDeliverySequence::UNSTICK}}) + .addEnum({{"HOVER", ACraft::AltitudeMoveState::HOVER}, + {"DESCEND", ACraft::AltitudeMoveState::DESCEND}, + {"ASCEND", ACraft::AltitudeMoveState::ASCEND}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, ACRocket) { - return ConcreteTypeLuaClassDefinition(ACRocket, ACraft) - - .property("RightLeg", &ACRocket::GetRightLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetRightLeg) - .property("LeftLeg", &ACRocket::GetLeftLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetLeftLeg) - .property("MainEngine", &ACRocket::GetMainThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetMainThruster) - .property("LeftEngine", &ACRocket::GetLeftThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetLeftThruster) - .property("RightEngine", &ACRocket::GetRightThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetRightThruster) - .property("LeftThruster", &ACRocket::GetULeftThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetULeftThruster) - .property("RightThruster", &ACRocket::GetURightThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetURightThruster) - .property("GearState", &ACRocket::GetGearState) - - .enum_("LandingGearState")[luabind::value("RAISED", ACRocket::LandingGearState::RAISED), - luabind::value("LOWERED", ACRocket::LandingGearState::LOWERED), - luabind::value("LOWERING", ACRocket::LandingGearState::LOWERING), - luabind::value("RAISING", ACRocket::LandingGearState::RAISING), - luabind::value("GearStateCount", ACRocket::LandingGearState::GearStateCount)]; + ConcreteTypeLuaClassDefinition(ACRocket, ACraft) + + .addProperty("RightLeg", &ACRocket::GetRightLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetRightLeg) + .addProperty("LeftLeg", &ACRocket::GetLeftLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetLeftLeg) + .addProperty("MainEngine", &ACRocket::GetMainThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetMainThruster) + .addProperty("LeftEngine", &ACRocket::GetLeftThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetLeftThruster) + .addProperty("RightEngine", &ACRocket::GetRightThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetRightThruster) + .addProperty("LeftThruster", &ACRocket::GetULeftThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetULeftThruster) + .addProperty("RightThruster", &ACRocket::GetURightThruster, &LuaAdaptersPropertyOwnershipSafetyFaker::ACRocketSetURightThruster) + .addProperty("GearState", &ACRocket::GetGearState) + + .addEnum({{"RAISED", ACRocket::LandingGearState::RAISED}, + {"LOWERED", ACRocket::LandingGearState::LOWERED}, + {"LOWERING", ACRocket::LandingGearState::LOWERING}, + {"RAISING", ACRocket::LandingGearState::RAISING}, + {"GearStateCount", ACRocket::LandingGearState::GearStateCount}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Actor) { - return ConcreteTypeLuaClassDefinition(Actor, MOSRotating) - - .def(luabind::constructor<>()) - - .property("PlayerControllable", &Actor::IsPlayerControllable, &Actor::SetPlayerControllable) - .property("BodyHitSound", &Actor::GetBodyHitSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetBodyHitSound) - .property("AlarmSound", &Actor::GetAlarmSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetAlarmSound) - .property("PainSound", &Actor::GetPainSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetPainSound) - .property("DeathSound", &Actor::GetDeathSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetDeathSound) - .property("DeviceSwitchSound", &Actor::GetDeviceSwitchSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetDeviceSwitchSound) - .property("ImpulseDamageThreshold", &Actor::GetTravelImpulseDamage, &Actor::SetTravelImpulseDamage) - .property("StableRecoveryDelay", &Actor::GetStableRecoverDelay, &Actor::SetStableRecoverDelay) - .property("CanRun", &Actor::GetCanRun, &Actor::SetCanRun) - .property("CrouchWalkSpeedMultiplier", &Actor::GetCrouchWalkSpeedMultiplier, &Actor::SetCrouchWalkSpeedMultiplier) - .property("Status", &Actor::GetStatus, &Actor::SetStatus) - .property("MovementState", &Actor::GetMovementState, &Actor::SetMovementState) - .property("Health", &Actor::GetHealth, &Actor::SetHealth) - .property("PrevHealth", &Actor::GetPrevHealth) - .property("MaxHealth", &Actor::GetMaxHealth, &Actor::SetMaxHealth) - .property("InventoryMass", &Actor::GetInventoryMass) - .property("GoldCarried", &Actor::GetGoldCarried, &Actor::SetGoldCarried) - .property("AimRange", &Actor::GetAimRange, &Actor::SetAimRange) - .property("CPUPos", &Actor::GetCPUPos) - .property("EyePos", &Actor::GetEyePos) - .property("HolsterOffset", &Actor::GetHolsterOffset, &Actor::SetHolsterOffset) - .property("ReloadOffset", &Actor::GetReloadOffset, &Actor::SetReloadOffset) - .property("ViewPoint", &Actor::GetViewPoint, &Actor::SetViewPoint) - .property("ItemInReach", &Actor::GetItemInReach, &Actor::SetItemInReach) - .property("SharpAimProgress", &Actor::GetSharpAimProgress) - .property("Height", &Actor::GetHeight) - .property("AIMode", &Actor::GetAIMode, &Actor::SetAIMode) - .property("DeploymentID", &Actor::GetDeploymentID) - .property("PassengerSlots", &Actor::GetPassengerSlots, &Actor::SetPassengerSlots) - .property("Perceptiveness", &Actor::GetPerceptiveness, &Actor::SetPerceptiveness) - .property("PainThreshold", &Actor::GetPainThreshold, &Actor::SetPainThreshold) - .property("CanRevealUnseen", &Actor::GetCanRevealUnseen, &Actor::SetCanRevealUnseen) - .property("InventorySize", &Actor::GetInventorySize) - .property("MaxInventoryMass", &Actor::GetMaxInventoryMass) - .property("MovePathSize", &Actor::GetMovePathSize) - .property("MovePathEnd", &Actor::GetMovePathEnd) - .property("IsWaitingOnNewMovePath", &Actor::IsWaitingOnNewMovePath) - .property("AimDistance", &Actor::GetAimDistance, &Actor::SetAimDistance) - .property("SightDistance", &Actor::GetSightDistance, &Actor::SetSightDistance) - .property("PieMenu", &Actor::GetPieMenu, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetPieMenu) - .property("AIBaseDigStrength", &Actor::GetAIBaseDigStrength, &Actor::SetAIBaseDigStrength) - .property("DigStrength", &Actor::EstimateDigStrength) - .property("JumpHeight", &Actor::EstimateJumpHeight) - .property("SceneWaypoints", &LuaAdaptersActor::GetSceneWaypoints, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .property("LimbPushForcesAndCollisionsDisabled", &Actor::GetLimbPushForcesAndCollisionsDisabled, &Actor::SetLimbPushForcesAndCollisionsDisabled) - .property("MoveProximityLimit", &Actor::GetMoveProximityLimit, &Actor::SetMoveProximityLimit) - - .def_readwrite("MOMoveTarget", &Actor::m_pMOMoveTarget) - .def_readonly("MovePath", &Actor::m_MovePath, luabind::return_stl_iterator) - .def_readonly("Inventory", &Actor::m_Inventory, luabind::return_stl_iterator) - - .def("GetController", &Actor::GetController) - .def("IsPlayerControlled", &Actor::IsPlayerControlled) - .def("IsControllable", &Actor::IsControllable) - .def("SetControllerMode", &Actor::SetControllerMode) - .def("SwapControllerModes", &Actor::SwapControllerModes) - .def("GetStableVelocityThreshold", &Actor::GetStableVel) - .def("SetStableVelocityThreshold", (void(Actor::*)(float, float)) & Actor::SetStableVel) - .def("SetStableVelocityThreshold", (void(Actor::*)(Vector)) & Actor::SetStableVel) - .def("GetAimAngle", &Actor::GetAimAngle) - .def("SetAimAngle", &Actor::SetAimAngle) - .def("HasObject", &Actor::HasObject) - .def("HasObjectInGroup", &Actor::HasObjectInGroup) - .def("IsWithinRange", &Actor::IsWithinRange) - .def("AddGold", &Actor::AddGold) - .def("AddHealth", &Actor::AddHealth) - .def("IsStatus", &Actor::IsStatus) - .def("IsDead", &Actor::IsDead) - .def("AddAISceneWaypoint", &Actor::AddAISceneWaypoint) - .def("AddAIMOWaypoint", &Actor::AddAIMOWaypoint) - .def("ClearAIWaypoints", &Actor::ClearAIWaypoints) - .def("GetLastAIWaypoint", &Actor::GetLastAIWaypoint) - .def("GetAIMOWaypointID", &Actor::GetAIMOWaypointID) - .def("GetWaypointListSize", &Actor::GetWaypointsSize) - .def("ClearMovePath", &Actor::ClearMovePath) - .def("AddToMovePathBeginning", &Actor::AddToMovePathBeginning) - .def("AddToMovePathEnd", &Actor::AddToMovePathEnd) - .def("RemoveMovePathBeginning", &Actor::RemoveMovePathBeginning) - .def("RemoveMovePathEnd", &Actor::RemoveMovePathEnd) - .def("AddInventoryItem", &Actor::AddInventoryItem, luabind::adopt(_2)) - .def("RemoveInventoryItem", (void(Actor::*)(const std::string&)) & Actor::RemoveInventoryItem) - .def("RemoveInventoryItem", (void(Actor::*)(const std::string&, const std::string&)) & Actor::RemoveInventoryItem) - .def("RemoveInventoryItemAtIndex", &Actor::RemoveInventoryItemAtIndex, luabind::adopt(luabind::return_value)) - .def("SwapNextInventory", &Actor::SwapNextInventory, luabind::adopt(luabind::result) + luabind::adopt(_2)) - .def("SwapPrevInventory", &Actor::SwapPrevInventory, luabind::adopt(luabind::result) + luabind::adopt(_2)) - .def("DropAllInventory", &Actor::DropAllInventory) - .def("DropAllGold", &Actor::DropAllGold) - .def("IsInventoryEmpty", &Actor::IsInventoryEmpty) - .def("ActivateHotkeyAction", &Actor::ActivateHotkeyAction) - .def("DeactivateHotkeyAction", &Actor::DeactivateHotkeyAction) - .def("HotkeyActionIsActivated", &Actor::HotkeyActionIsActivated) - .def("DrawWaypoints", &Actor::DrawWaypoints) - .def("SetMovePathToUpdate", &Actor::SetMovePathToUpdate) - .def("UpdateMovePath", &Actor::UpdateMovePath) - .def("SetAlarmPoint", &Actor::AlarmPoint) - .def("GetAlarmPoint", &Actor::GetAlarmPoint) - .def("IsOrganic", &Actor::IsOrganic) - .def("IsMechanical", &Actor::IsMechanical) - - .enum_("Status")[luabind::value("STABLE", Actor::Status::STABLE), - luabind::value("UNSTABLE", Actor::Status::UNSTABLE), - luabind::value("INACTIVE", Actor::Status::INACTIVE), - luabind::value("DYING", Actor::Status::DYING), - luabind::value("DEAD", Actor::Status::DEAD)] - .enum_("MovementState")[luabind::value("NOMOVE", Actor::MovementState::NOMOVE), - luabind::value("CROUCH", Actor::MovementState::CROUCH), - luabind::value("STAND", Actor::MovementState::STAND), - luabind::value("WALK", Actor::MovementState::WALK), - luabind::value("RUN", Actor::MovementState::RUN), - luabind::value("JUMP", Actor::MovementState::JUMP), - luabind::value("DISLODGE", Actor::MovementState::DISLODGE), - luabind::value("PRONE", Actor::MovementState::PRONE), - luabind::value("CRAWL", Actor::MovementState::CRAWL), - luabind::value("ARMCRAWL", Actor::MovementState::ARMCRAWL), - luabind::value("CLIMB", Actor::MovementState::CLIMB), - luabind::value("MOVEMENTSTATECOUNT", Actor::MovementState::MOVEMENTSTATECOUNT)] - .enum_("AIMode")[luabind::value("AIMODE_NONE", Actor::AIMode::AIMODE_NONE), - luabind::value("AIMODE_SENTRY", Actor::AIMode::AIMODE_SENTRY), - luabind::value("AIMODE_PATROL", Actor::AIMode::AIMODE_PATROL), - luabind::value("AIMODE_GOTO", Actor::AIMode::AIMODE_GOTO), - luabind::value("AIMODE_BRAINHUNT", Actor::AIMode::AIMODE_BRAINHUNT), - luabind::value("AIMODE_GOLDDIG", Actor::AIMode::AIMODE_GOLDDIG), - luabind::value("AIMODE_RETURN", Actor::AIMode::AIMODE_RETURN), - luabind::value("AIMODE_STAY", Actor::AIMode::AIMODE_STAY), - luabind::value("AIMODE_SCUTTLE", Actor::AIMode::AIMODE_SCUTTLE), - luabind::value("AIMODE_DELIVER", Actor::AIMode::AIMODE_DELIVER), - luabind::value("AIMODE_BOMB", Actor::AIMode::AIMODE_BOMB), - luabind::value("AIMODE_SQUAD", Actor::AIMode::AIMODE_SQUAD), - luabind::value("AIMODE_COUNT", Actor::AIMode::AIMODE_COUNT)] - .enum_("ActionState")[luabind::value("MOVING", Actor::ActionState::MOVING), - luabind::value("MOVING_FAST", Actor::ActionState::MOVING_FAST), - luabind::value("FIRING", Actor::ActionState::FIRING), - luabind::value("ActionStateCount", Actor::ActionState::ActionStateCount)] - .enum_("AimState")[luabind::value("AIMSTILL", Actor::AimState::AIMSTILL), - luabind::value("AIMUP", Actor::AimState::AIMUP), - luabind::value("AIMDOWN", Actor::AimState::AIMDOWN), - luabind::value("AimStateCount", Actor::AimState::AimStateCount)] - .enum_("LateralMoveState")[luabind::value("LAT_STILL", Actor::LateralMoveState::LAT_STILL), - luabind::value("LAT_LEFT", Actor::LateralMoveState::LAT_LEFT), - luabind::value("LAT_RIGHT", Actor::LateralMoveState::LAT_RIGHT)] - .enum_("ObstacleState")[luabind::value("PROCEEDING", Actor::ObstacleState::PROCEEDING), - luabind::value("BACKSTEPPING", Actor::ObstacleState::BACKSTEPPING), - luabind::value("DIGPAUSING", Actor::ObstacleState::DIGPAUSING), - luabind::value("JUMPING", Actor::ObstacleState::JUMPING), - luabind::value("SOFTLANDING", Actor::ObstacleState::SOFTLANDING)] - .enum_("TeamBlockState")[luabind::value("NOTBLOCKED", Actor::TeamBlockState::NOTBLOCKED), - luabind::value("BLOCKED", Actor::TeamBlockState::BLOCKED), - luabind::value("IGNORINGBLOCK", Actor::TeamBlockState::IGNORINGBLOCK), - luabind::value("FOLLOWWAIT", Actor::TeamBlockState::FOLLOWWAIT)] - .enum_("ActorHotkeyType")[luabind::value("PRIMARYHOTKEY", Actor::ActorHotkeyType::PRIMARYHOTKEY), - luabind::value("AUXILIARYHOTKEY", Actor::ActorHotkeyType::AUXILIARYHOTKEY), - luabind::value("ACTORHOTKEYTYPECOUNT", Actor::ActorHotkeyType::ACTORHOTKEYTYPECOUNT)]; + ConcreteTypeLuaClassDefinition(Actor, MOSRotating) + + .addConstructor<>() + + .addProperty("PlayerControllable", &Actor::IsPlayerControllable, &Actor::SetPlayerControllable) + .addProperty("BodyHitSound", &Actor::GetBodyHitSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetBodyHitSound) + .addProperty("AlarmSound", &Actor::GetAlarmSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetAlarmSound) + .addProperty("PainSound", &Actor::GetPainSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetPainSound) + .addProperty("DeathSound", &Actor::GetDeathSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetDeathSound) + .addProperty("DeviceSwitchSound", &Actor::GetDeviceSwitchSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetDeviceSwitchSound) + .addProperty("ImpulseDamageThreshold", &Actor::GetTravelImpulseDamage, &Actor::SetTravelImpulseDamage) + .addProperty("StableRecoveryDelay", &Actor::GetStableRecoverDelay, &Actor::SetStableRecoverDelay) + .addProperty("CanRun", &Actor::GetCanRun, &Actor::SetCanRun) + .addProperty("CrouchWalkSpeedMultiplier", &Actor::GetCrouchWalkSpeedMultiplier, &Actor::SetCrouchWalkSpeedMultiplier) + .addProperty("Status", &Actor::GetStatus, &Actor::SetStatus) + .addProperty("MovementState", &Actor::GetMovementState, &Actor::SetMovementState) + .addProperty("Health", &Actor::GetHealth, &Actor::SetHealth) + .addProperty("PrevHealth", &Actor::GetPrevHealth) + .addProperty("MaxHealth", &Actor::GetMaxHealth, &Actor::SetMaxHealth) + .addProperty("InventoryMass", &Actor::GetInventoryMass) + .addProperty("GoldCarried", &Actor::GetGoldCarried, &Actor::SetGoldCarried) + .addProperty("AimRange", &Actor::GetAimRange, &Actor::SetAimRange) + .addProperty("CPUPos", &Actor::GetCPUPos) + .addProperty("EyePos", &Actor::GetEyePos) + .addProperty("HolsterOffset", &Actor::GetHolsterOffset, &Actor::SetHolsterOffset) + .addProperty("ReloadOffset", &Actor::GetReloadOffset, &Actor::SetReloadOffset) + .addProperty("ViewPoint", &Actor::GetViewPoint, &Actor::SetViewPoint) + .addProperty("ItemInReach", &Actor::GetItemInReach, &Actor::SetItemInReach) + .addProperty("SharpAimProgress", &Actor::GetSharpAimProgress) + .addProperty("Height", &Actor::GetHeight) + .addProperty("AIMode", &Actor::GetAIMode, &Actor::SetAIMode) + .addProperty("DeploymentID", &Actor::GetDeploymentID) + .addProperty("PassengerSlots", &Actor::GetPassengerSlots, &Actor::SetPassengerSlots) + .addProperty("Perceptiveness", &Actor::GetPerceptiveness, &Actor::SetPerceptiveness) + .addProperty("PainThreshold", &Actor::GetPainThreshold, &Actor::SetPainThreshold) + .addProperty("CanRevealUnseen", &Actor::GetCanRevealUnseen, &Actor::SetCanRevealUnseen) + .addProperty("InventorySize", &Actor::GetInventorySize) + .addProperty("MaxInventoryMass", &Actor::GetMaxInventoryMass) + .addProperty("MovePathSize", &Actor::GetMovePathSize) + .addProperty("MovePathEnd", &Actor::GetMovePathEnd) + .addProperty("IsWaitingOnNewMovePath", &Actor::IsWaitingOnNewMovePath) + .addProperty("AimDistance", &Actor::GetAimDistance, &Actor::SetAimDistance) + .addProperty("SightDistance", &Actor::GetSightDistance, &Actor::SetSightDistance) + .addProperty("PieMenu", &Actor::GetPieMenu, &LuaAdaptersPropertyOwnershipSafetyFaker::ActorSetPieMenu) + .addProperty("AIBaseDigStrength", &Actor::GetAIBaseDigStrength, &Actor::SetAIBaseDigStrength) + .addProperty("DigStrength", &Actor::EstimateDigStrength) + .addProperty("JumpHeight", &Actor::EstimateJumpHeight) + .addProperty("SceneWaypoints", &LuaAdaptersActor::GetSceneWaypoints, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addProperty("LimbPushForcesAndCollisionsDisabled", &Actor::GetLimbPushForcesAndCollisionsDisabled, &Actor::SetLimbPushForcesAndCollisionsDisabled) + .addProperty("MoveProximityLimit", &Actor::GetMoveProximityLimit, &Actor::SetMoveProximityLimit) + + .addReadWriteMember("MOMoveTarget", &Actor::m_pMOMoveTarget) + .addProperty("MovePath", &Actor::m_MovePath, LuaBinding::ReturnStlIterator) + .addProperty("Inventory", &Actor::m_Inventory, LuaBinding::ReturnStlIterator) + + .addFunction("GetController", &Actor::GetController) + .addFunction("IsPlayerControlled", &Actor::IsPlayerControlled) + .addFunction("IsControllable", &Actor::IsControllable) + .addFunction("SetControllerMode", &Actor::SetControllerMode) + .addFunction("SwapControllerModes", &Actor::SwapControllerModes) + .addFunction("GetStableVelocityThreshold", &Actor::GetStableVel) + .addFunction("SetStableVelocityThreshold", (void(Actor::*)(float, float)) & Actor::SetStableVel) + .addFunction("SetStableVelocityThreshold", (void(Actor::*)(Vector)) & Actor::SetStableVel) + .addFunction("GetAimAngle", &Actor::GetAimAngle) + .addFunction("SetAimAngle", &Actor::SetAimAngle) + .addFunction("HasObject", &Actor::HasObject) + .addFunction("HasObjectInGroup", &Actor::HasObjectInGroup) + .addFunction("IsWithinRange", &Actor::IsWithinRange) + .addFunction("AddGold", &Actor::AddGold) + .addFunction("AddHealth", &Actor::AddHealth) + .addFunction("IsStatus", &Actor::IsStatus) + .addFunction("IsDead", &Actor::IsDead) + .addFunction("AddAISceneWaypoint", &Actor::AddAISceneWaypoint) + .addFunction("AddAIMOWaypoint", &Actor::AddAIMOWaypoint) + .addFunction("ClearAIWaypoints", &Actor::ClearAIWaypoints) + .addFunction("GetLastAIWaypoint", &Actor::GetLastAIWaypoint) + .addFunction("GetAIMOWaypointID", &Actor::GetAIMOWaypointID) + .addFunction("GetWaypointListSize", &Actor::GetWaypointsSize) + .addFunction("ClearMovePath", &Actor::ClearMovePath) + .addFunction("AddToMovePathBeginning", &Actor::AddToMovePathBeginning) + .addFunction("AddToMovePathEnd", &Actor::AddToMovePathEnd) + .addFunction("RemoveMovePathBeginning", &Actor::RemoveMovePathBeginning) + .addFunction("RemoveMovePathEnd", &Actor::RemoveMovePathEnd) + .addFunction("AddInventoryItem", &Actor::AddInventoryItem, LuaBinding::AdoptArg<2>) + .addFunction("RemoveInventoryItem", (void(Actor::*)(const std::string&)) & Actor::RemoveInventoryItem) + .addFunction("RemoveInventoryItem", (void(Actor::*)(const std::string&, const std::string&)) & Actor::RemoveInventoryItem) + .addFunction("RemoveInventoryItemAtIndex", &Actor::RemoveInventoryItemAtIndex, LuaBinding::AdoptResult) + .addFunction("SwapNextInventory", &Actor::SwapNextInventory, LuaBinding::AdoptResult, LuaBinding::AdoptArg<2>) + .addFunction("SwapPrevInventory", &Actor::SwapPrevInventory, LuaBinding::AdoptResult, LuaBinding::AdoptArg<2>) + .addFunction("DropAllInventory", &Actor::DropAllInventory) + .addFunction("DropAllGold", &Actor::DropAllGold) + .addFunction("IsInventoryEmpty", &Actor::IsInventoryEmpty) + .addFunction("ActivateHotkeyAction", &Actor::ActivateHotkeyAction) + .addFunction("DeactivateHotkeyAction", &Actor::DeactivateHotkeyAction) + .addFunction("HotkeyActionIsActivated", &Actor::HotkeyActionIsActivated) + .addFunction("DrawWaypoints", &Actor::DrawWaypoints) + .addFunction("SetMovePathToUpdate", &Actor::SetMovePathToUpdate) + .addFunction("UpdateMovePath", &Actor::UpdateMovePath) + .addFunction("SetAlarmPoint", &Actor::AlarmPoint) + .addFunction("GetAlarmPoint", &Actor::GetAlarmPoint) + .addFunction("IsOrganic", &Actor::IsOrganic) + .addFunction("IsMechanical", &Actor::IsMechanical) + + .addEnum({{"STABLE", Actor::Status::STABLE}, + {"UNSTABLE", Actor::Status::UNSTABLE}, + {"INACTIVE", Actor::Status::INACTIVE}, + {"DYING", Actor::Status::DYING}, + {"DEAD", Actor::Status::DEAD}}) + .addEnum({{"NOMOVE", Actor::MovementState::NOMOVE}, + {"CROUCH", Actor::MovementState::CROUCH}, + {"STAND", Actor::MovementState::STAND}, + {"WALK", Actor::MovementState::WALK}, + {"RUN", Actor::MovementState::RUN}, + {"JUMP", Actor::MovementState::JUMP}, + {"DISLODGE", Actor::MovementState::DISLODGE}, + {"PRONE", Actor::MovementState::PRONE}, + {"CRAWL", Actor::MovementState::CRAWL}, + {"ARMCRAWL", Actor::MovementState::ARMCRAWL}, + {"CLIMB", Actor::MovementState::CLIMB}, + {"MOVEMENTSTATECOUNT", Actor::MovementState::MOVEMENTSTATECOUNT}}) + .addEnum({{"AIMODE_NONE", Actor::AIMode::AIMODE_NONE}, + {"AIMODE_SENTRY", Actor::AIMode::AIMODE_SENTRY}, + {"AIMODE_PATROL", Actor::AIMode::AIMODE_PATROL}, + {"AIMODE_GOTO", Actor::AIMode::AIMODE_GOTO}, + {"AIMODE_BRAINHUNT", Actor::AIMode::AIMODE_BRAINHUNT}, + {"AIMODE_GOLDDIG", Actor::AIMode::AIMODE_GOLDDIG}, + {"AIMODE_RETURN", Actor::AIMode::AIMODE_RETURN}, + {"AIMODE_STAY", Actor::AIMode::AIMODE_STAY}, + {"AIMODE_SCUTTLE", Actor::AIMode::AIMODE_SCUTTLE}, + {"AIMODE_DELIVER", Actor::AIMode::AIMODE_DELIVER}, + {"AIMODE_BOMB", Actor::AIMode::AIMODE_BOMB}, + {"AIMODE_SQUAD", Actor::AIMode::AIMODE_SQUAD}, + {"AIMODE_COUNT", Actor::AIMode::AIMODE_COUNT}}) + .addEnum({{"MOVING", Actor::ActionState::MOVING}, + {"MOVING_FAST", Actor::ActionState::MOVING_FAST}, + {"FIRING", Actor::ActionState::FIRING}, + {"ActionStateCount", Actor::ActionState::ActionStateCount}}) + .addEnum({{"AIMSTILL", Actor::AimState::AIMSTILL}, + {"AIMUP", Actor::AimState::AIMUP}, + {"AIMDOWN", Actor::AimState::AIMDOWN}, + {"AimStateCount", Actor::AimState::AimStateCount}}) + .addEnum({{"LAT_STILL", Actor::LateralMoveState::LAT_STILL}, + {"LAT_LEFT", Actor::LateralMoveState::LAT_LEFT}, + {"LAT_RIGHT", Actor::LateralMoveState::LAT_RIGHT}}) + .addEnum({{"PROCEEDING", Actor::ObstacleState::PROCEEDING}, + {"BACKSTEPPING", Actor::ObstacleState::BACKSTEPPING}, + {"DIGPAUSING", Actor::ObstacleState::DIGPAUSING}, + {"JUMPING", Actor::ObstacleState::JUMPING}, + {"SOFTLANDING", Actor::ObstacleState::SOFTLANDING}}) + .addEnum({{"NOTBLOCKED", Actor::TeamBlockState::NOTBLOCKED}, + {"BLOCKED", Actor::TeamBlockState::BLOCKED}, + {"IGNORINGBLOCK", Actor::TeamBlockState::IGNORINGBLOCK}, + {"FOLLOWWAIT", Actor::TeamBlockState::FOLLOWWAIT}}) + .addEnum({{"PRIMARYHOTKEY", Actor::ActorHotkeyType::PRIMARYHOTKEY}, + {"AUXILIARYHOTKEY", Actor::ActorHotkeyType::AUXILIARYHOTKEY}, + {"ACTORHOTKEYTYPECOUNT", Actor::ActorHotkeyType::ACTORHOTKEYTYPECOUNT}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, ADoor) { - return ConcreteTypeLuaClassDefinition(ADoor, Actor) - - .property("Door", &ADoor::GetDoor, &LuaAdaptersPropertyOwnershipSafetyFaker::ADoorSetDoor) - .property("DoorMoveStartSound", &ADoor::GetDoorMoveStartSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ADoorSetDoorMoveStartSound) - .property("DoorMoveSound", &ADoor::GetDoorMoveSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ADoorSetDoorMoveSound) - .property("DoorDirectionChangeSound", &ADoor::GetDoorDirectionChangeSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ADoorSetDoorDirectionChangeSound) - .property("DoorMoveEndSound", &ADoor::GetDoorMoveEndSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ADoorSetDoorMoveEndSound) - - .def("GetDoorState", &ADoor::GetDoorState) - .def("OpenDoor", &ADoor::OpenDoor) - .def("CloseDoor", &ADoor::CloseDoor) - .def("StopDoor", &ADoor::StopDoor) - .def("ResetSensorTimer", &ADoor::ResetSensorTimer) - .def("SetClosedByDefault", &ADoor::SetClosedByDefault) - - .enum_("DoorState")[luabind::value("CLOSED", ADoor::DoorState::CLOSED), - luabind::value("OPENING", ADoor::DoorState::OPENING), - luabind::value("OPEN", ADoor::DoorState::OPEN), - luabind::value("CLOSING", ADoor::DoorState::CLOSING), - luabind::value("STOPPED", ADoor::DoorState::STOPPED)]; + ConcreteTypeLuaClassDefinition(ADoor, Actor) + + .addProperty("Door", &ADoor::GetDoor, &LuaAdaptersPropertyOwnershipSafetyFaker::ADoorSetDoor) + .addProperty("DoorMoveStartSound", &ADoor::GetDoorMoveStartSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ADoorSetDoorMoveStartSound) + .addProperty("DoorMoveSound", &ADoor::GetDoorMoveSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ADoorSetDoorMoveSound) + .addProperty("DoorDirectionChangeSound", &ADoor::GetDoorDirectionChangeSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ADoorSetDoorDirectionChangeSound) + .addProperty("DoorMoveEndSound", &ADoor::GetDoorMoveEndSound, &LuaAdaptersPropertyOwnershipSafetyFaker::ADoorSetDoorMoveEndSound) + + .addFunction("GetDoorState", &ADoor::GetDoorState) + .addFunction("OpenDoor", &ADoor::OpenDoor) + .addFunction("CloseDoor", &ADoor::CloseDoor) + .addFunction("StopDoor", &ADoor::StopDoor) + .addFunction("ResetSensorTimer", &ADoor::ResetSensorTimer) + .addFunction("SetClosedByDefault", &ADoor::SetClosedByDefault) + + .addEnum({{"CLOSED", ADoor::DoorState::CLOSED}, + {"OPENING", ADoor::DoorState::OPENING}, + {"OPEN", ADoor::DoorState::OPEN}, + {"CLOSING", ADoor::DoorState::CLOSING}, + {"STOPPED", ADoor::DoorState::STOPPED}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, AEmitter) { - return ConcreteTypeLuaClassDefinition(AEmitter, Attachable) - - .property("EmissionSound", &AEmitter::GetEmissionSound, &LuaAdaptersPropertyOwnershipSafetyFaker::AEmitterSetEmissionSound) - .property("BurstSound", &AEmitter::GetBurstSound, &LuaAdaptersPropertyOwnershipSafetyFaker::AEmitterSetBurstSound) - .property("EndSound", &AEmitter::GetEndSound, &LuaAdaptersPropertyOwnershipSafetyFaker::AEmitterSetEndSound) - .property("BurstScale", &AEmitter::GetBurstScale, &AEmitter::SetBurstScale) - .property("PlayBurstSound", &AEmitter::GetPlayBurstSound, &AEmitter::SetPlayBurstSound) - .property("EmitAngle", &AEmitter::GetEmitAngle, &AEmitter::SetEmitAngle) - .property("GetThrottle", &AEmitter::GetThrottle, &AEmitter::SetThrottle) - .property("Throttle", &AEmitter::GetThrottle, &AEmitter::SetThrottle) - .property("ThrottleFactor", &AEmitter::GetThrottleFactor) - .property("NegativeThrottleMultiplier", &AEmitter::GetNegativeThrottleMultiplier, &AEmitter::SetNegativeThrottleMultiplier) - .property("PositiveThrottleMultiplier", &AEmitter::GetPositiveThrottleMultiplier, &AEmitter::SetPositiveThrottleMultiplier) - .property("BurstSpacing", &AEmitter::GetBurstSpacing, &AEmitter::SetBurstSpacing) - .property("BurstDamage", &AEmitter::GetBurstDamage, &AEmitter::SetBurstDamage) - .property("EmitterDamageMultiplier", &AEmitter::GetEmitterDamageMultiplier, &AEmitter::SetEmitterDamageMultiplier) - .property("EmitCount", &AEmitter::GetEmitCount) - .property("EmitCountLimit", &AEmitter::GetEmitCountLimit, &AEmitter::SetEmitCountLimit) - .property("EmitDamage", &AEmitter::GetEmitDamage, &AEmitter::SetEmitDamage) - .property("EmitOffset", &AEmitter::GetEmitOffset, &AEmitter::SetEmitOffset) - .property("Flash", &AEmitter::GetFlash, &LuaAdaptersPropertyOwnershipSafetyFaker::AEmitterSetFlash) - .property("FlashScale", &AEmitter::GetFlashScale, &AEmitter::SetFlashScale) - .property("TotalParticlesPerMinute", &AEmitter::GetTotalParticlesPerMinute) - .property("TotalBurstSize", &AEmitter::GetTotalBurstSize) - - .def_readonly("Emissions", &AEmitter::m_EmissionList, luabind::return_stl_iterator) - - .def("IsEmitting", &AEmitter::IsEmitting) - .def("WasEmitting", &AEmitter::WasEmitting) - .def("EnableEmission", &AEmitter::EnableEmission) - .def("GetEmitVector", &AEmitter::GetEmitVector) - .def("GetRecoilVector", &AEmitter::GetRecoilVector) - .def("EstimateImpulse", &AEmitter::EstimateImpulse) - .def("TriggerBurst", &AEmitter::TriggerBurst) - .def("IsSetToBurst", &AEmitter::IsSetToBurst) - .def("CanTriggerBurst", &AEmitter::CanTriggerBurst) - .def("GetScaledThrottle", &AEmitter::GetScaledThrottle) - .def("JustStartedEmitting", &AEmitter::JustStartedEmitting); + ConcreteTypeLuaClassDefinition(AEmitter, Attachable) + + .addProperty("EmissionSound", &AEmitter::GetEmissionSound, &LuaAdaptersPropertyOwnershipSafetyFaker::AEmitterSetEmissionSound) + .addProperty("BurstSound", &AEmitter::GetBurstSound, &LuaAdaptersPropertyOwnershipSafetyFaker::AEmitterSetBurstSound) + .addProperty("EndSound", &AEmitter::GetEndSound, &LuaAdaptersPropertyOwnershipSafetyFaker::AEmitterSetEndSound) + .addProperty("BurstScale", &AEmitter::GetBurstScale, &AEmitter::SetBurstScale) + .addProperty("PlayBurstSound", &AEmitter::GetPlayBurstSound, &AEmitter::SetPlayBurstSound) + .addProperty("EmitAngle", &AEmitter::GetEmitAngle, &AEmitter::SetEmitAngle) + .addProperty("GetThrottle", &AEmitter::GetThrottle, &AEmitter::SetThrottle) + .addProperty("Throttle", &AEmitter::GetThrottle, &AEmitter::SetThrottle) + .addProperty("ThrottleFactor", &AEmitter::GetThrottleFactor) + .addProperty("NegativeThrottleMultiplier", &AEmitter::GetNegativeThrottleMultiplier, &AEmitter::SetNegativeThrottleMultiplier) + .addProperty("PositiveThrottleMultiplier", &AEmitter::GetPositiveThrottleMultiplier, &AEmitter::SetPositiveThrottleMultiplier) + .addProperty("BurstSpacing", &AEmitter::GetBurstSpacing, &AEmitter::SetBurstSpacing) + .addProperty("BurstDamage", &AEmitter::GetBurstDamage, &AEmitter::SetBurstDamage) + .addProperty("EmitterDamageMultiplier", &AEmitter::GetEmitterDamageMultiplier, &AEmitter::SetEmitterDamageMultiplier) + .addProperty("EmitCount", &AEmitter::GetEmitCount) + .addProperty("EmitCountLimit", &AEmitter::GetEmitCountLimit, &AEmitter::SetEmitCountLimit) + .addProperty("EmitDamage", &AEmitter::GetEmitDamage, &AEmitter::SetEmitDamage) + .addProperty("EmitOffset", &AEmitter::GetEmitOffset, &AEmitter::SetEmitOffset) + .addProperty("Flash", &AEmitter::GetFlash, &LuaAdaptersPropertyOwnershipSafetyFaker::AEmitterSetFlash) + .addProperty("FlashScale", &AEmitter::GetFlashScale, &AEmitter::SetFlashScale) + .addProperty("TotalParticlesPerMinute", &AEmitter::GetTotalParticlesPerMinute) + .addProperty("TotalBurstSize", &AEmitter::GetTotalBurstSize) + + .addProperty("Emissions", &AEmitter::m_EmissionList, LuaBinding::ReturnStlIterator) + + .addFunction("IsEmitting", &AEmitter::IsEmitting) + .addFunction("WasEmitting", &AEmitter::WasEmitting) + .addFunction("EnableEmission", &AEmitter::EnableEmission) + .addFunction("GetEmitVector", &AEmitter::GetEmitVector) + .addFunction("GetRecoilVector", &AEmitter::GetRecoilVector) + .addFunction("EstimateImpulse", &AEmitter::EstimateImpulse) + .addFunction("TriggerBurst", &AEmitter::TriggerBurst) + .addFunction("IsSetToBurst", &AEmitter::IsSetToBurst) + .addFunction("CanTriggerBurst", &AEmitter::CanTriggerBurst) + .addFunction("GetScaledThrottle", &AEmitter::GetScaledThrottle) + .addFunction("JustStartedEmitting", &AEmitter::JustStartedEmitting); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, AEJetpack) { - return ConcreteTypeLuaClassDefinition(AEJetpack, AEmitter) - - .property("JetpackType", &AEJetpack::GetJetpackType, &AEJetpack::SetJetpackType) - .property("JetTimeTotal", &AEJetpack::GetJetTimeTotal, &AEJetpack::SetJetTimeTotal) - .property("JetTimeLeft", &AEJetpack::GetJetTimeLeft, &AEJetpack::SetJetTimeLeft) - .property("JetReplenishRate", &AEJetpack::GetJetReplenishRate, &AEJetpack::SetJetReplenishRate) - .property("MinimumFuelRatio", &AEJetpack::GetMinimumFuelRatio, &AEJetpack::SetMinimumFuelRatio) - .property("JetAngleRange", &AEJetpack::GetJetAngleRange, &AEJetpack::SetJetAngleRange) - .property("CanAdjustAngleWhileFiring", &AEJetpack::GetCanAdjustAngleWhileFiring, &AEJetpack::SetCanAdjustAngleWhileFiring) - .property("AdjustsThrottleForWeight", &AEJetpack::GetAdjustsThrottleForWeight, &AEJetpack::SetAdjustsThrottleForWeight) - - .enum_("JetpackType")[luabind::value("Standard", AEJetpack::Standard), - luabind::value("JumpPack", AEJetpack::JumpPack)]; + ConcreteTypeLuaClassDefinition(AEJetpack, AEmitter) + + .addProperty("JetpackType", &AEJetpack::GetJetpackType, &AEJetpack::SetJetpackType) + .addProperty("JetTimeTotal", &AEJetpack::GetJetTimeTotal, &AEJetpack::SetJetTimeTotal) + .addProperty("JetTimeLeft", &AEJetpack::GetJetTimeLeft, &AEJetpack::SetJetTimeLeft) + .addProperty("JetReplenishRate", &AEJetpack::GetJetReplenishRate, &AEJetpack::SetJetReplenishRate) + .addProperty("MinimumFuelRatio", &AEJetpack::GetMinimumFuelRatio, &AEJetpack::SetMinimumFuelRatio) + .addProperty("JetAngleRange", &AEJetpack::GetJetAngleRange, &AEJetpack::SetJetAngleRange) + .addProperty("CanAdjustAngleWhileFiring", &AEJetpack::GetCanAdjustAngleWhileFiring, &AEJetpack::SetCanAdjustAngleWhileFiring) + .addProperty("AdjustsThrottleForWeight", &AEJetpack::GetAdjustsThrottleForWeight, &AEJetpack::SetAdjustsThrottleForWeight) + + .addEnum({{"Standard", AEJetpack::Standard}, + {"JumpPack", AEJetpack::JumpPack}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, AHuman) { - return ConcreteTypeLuaClassDefinition(AHuman, Actor) - - .def(luabind::constructor<>()) - - .property("Head", &AHuman::GetHead, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetHead) - .property("Jetpack", &AHuman::GetJetpack, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetJetpack) - .property("FGArm", &AHuman::GetFGArm, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetFGArm) - .property("BGArm", &AHuman::GetBGArm, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetBGArm) - .property("FGLeg", &AHuman::GetFGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetFGLeg) - .property("BGLeg", &AHuman::GetBGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetBGLeg) - .property("FGFoot", &AHuman::GetFGFoot, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetFGFoot) - .property("BGFoot", &AHuman::GetBGFoot, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetBGFoot) - .property("MaxWalkPathCrouchShift", &AHuman::GetMaxWalkPathCrouchShift, &AHuman::SetMaxWalkPathCrouchShift) - .property("CrouchAmount", &AHuman::GetCrouchAmount) - .property("CrouchAmountOverride", &AHuman::GetCrouchAmountOverride, &AHuman::SetCrouchAmountOverride) - .property("StrideSound", &AHuman::GetStrideSound, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetStrideSound) - .property("UpperBodyState", &AHuman::GetUpperBodyState, &AHuman::SetUpperBodyState) - .property("ProneState", &AHuman::GetProneState, &AHuman::SetProneState) - .property("ThrowPrepTime", &AHuman::GetThrowPrepTime, &AHuman::SetThrowPrepTime) - .property("ThrowProgress", &AHuman::GetThrowProgress) - .property("EquippedItem", &AHuman::GetEquippedItem) - .property("EquippedBGItem", &AHuman::GetEquippedBGItem) - .property("EquippedMass", &AHuman::GetEquippedMass) - .property("FirearmIsReady", &AHuman::FirearmIsReady) - .property("ThrowableIsReady", &AHuman::ThrowableIsReady) - .property("FirearmIsEmpty", &AHuman::FirearmIsEmpty) - .property("FirearmNeedsReload", &AHuman::FirearmNeedsReload) - .property("FirearmIsSemiAuto", &AHuman::FirearmIsSemiAuto) - .property("FirearmActivationDelay", &AHuman::FirearmActivationDelay) - .property("IsClimbing", &AHuman::IsClimbing) - .property("StrideFrame", &AHuman::StrideFrame) - .property("ArmSwingRate", &AHuman::GetArmSwingRate, &AHuman::SetArmSwingRate) - .property("DeviceArmSwayRate", &AHuman::GetDeviceArmSwayRate, &AHuman::SetDeviceArmSwayRate) - - .def("EquipFirearm", &AHuman::EquipFirearm) - .def("EquipThrowable", &AHuman::EquipThrowable) - .def("EquipDiggingTool", &AHuman::EquipDiggingTool) - .def("EquipShield", &AHuman::EquipShield) - .def("EquipShieldInBGArm", &LuaAdaptersAHuman::EquipShieldInBGArm) - .def("EquipDeviceInGroup", &AHuman::EquipDeviceInGroup) - .def("EquipNamedDevice", (bool(AHuman::*)(const std::string&, bool)) & AHuman::EquipNamedDevice) - .def("EquipNamedDevice", (bool(AHuman::*)(const std::string&, const std::string&, bool)) & AHuman::EquipNamedDevice) - .def("EquipLoadedFirearmInGroup", &AHuman::EquipLoadedFirearmInGroup) - .def("UnequipFGArm", &AHuman::UnequipFGArm) - .def("UnequipBGArm", &AHuman::UnequipBGArm) - .def("UnequipArms", &AHuman::UnequipArms) - .def("ReloadFirearms", &LuaAdaptersAHuman::ReloadFirearms) - .def("ReloadFirearms", &AHuman::ReloadFirearms) - .def("FirearmsAreReloading", &AHuman::FirearmsAreReloading) - .def("IsWithinRange", &AHuman::IsWithinRange) - .def("Look", &AHuman::Look) - .def("LookForGold", &AHuman::LookForGold) - .def("LookForMOs", &AHuman::LookForMOs) - .def("GetLimbPath", &AHuman::GetLimbPath) - .def("GetLimbPathTravelSpeed", &AHuman::GetLimbPathTravelSpeed) - .def("SetLimbPathTravelSpeed", &AHuman::SetLimbPathTravelSpeed) - .def("GetLimbPathPushForce", &AHuman::GetLimbPathPushForce) - .def("SetLimbPathPushForce", &AHuman::SetLimbPathPushForce) - .def("GetRotAngleTarget", &AHuman::GetRotAngleTarget) - .def("SetRotAngleTarget", &AHuman::SetRotAngleTarget) - .def("GetWalkAngle", &AHuman::GetWalkAngle) - .def("SetWalkAngle", &AHuman::SetWalkAngle) - - .enum_("UpperBodyState")[luabind::value("WEAPON_READY", AHuman::UpperBodyState::WEAPON_READY), - luabind::value("AIMING_SHARP", AHuman::UpperBodyState::AIMING_SHARP), - luabind::value("HOLSTERING_BACK", AHuman::UpperBodyState::HOLSTERING_BACK), - luabind::value("HOLSTERING_BELT", AHuman::UpperBodyState::HOLSTERING_BELT), - luabind::value("DEHOLSTERING_BACK", AHuman::UpperBodyState::DEHOLSTERING_BACK), - luabind::value("DEHOLSTERING_BELT", AHuman::UpperBodyState::DEHOLSTERING_BELT), - luabind::value("THROWING_PREP", AHuman::UpperBodyState::THROWING_PREP), - luabind::value("THROWING_RELEASE", AHuman::UpperBodyState::THROWING_RELEASE)] - .enum_("ProneState")[luabind::value("NOTPRONE", AHuman::ProneState::NOTPRONE), - luabind::value("GOPRONE", AHuman::ProneState::GOPRONE), - luabind::value("PRONE", AHuman::ProneState::LAYINGPRONE), - luabind::value("PRONESTATECOUNT", AHuman::ProneState::PRONESTATECOUNT)] - .enum_("Layer")[luabind::value("FGROUND", AHuman::Layer::FGROUND), - luabind::value("BGROUND", AHuman::Layer::BGROUND)] - .enum_("DeviceHandlingState")[luabind::value("STILL", AHuman::DeviceHandlingState::STILL), - luabind::value("POINTING", AHuman::DeviceHandlingState::POINTING), - luabind::value("SCANNING", AHuman::DeviceHandlingState::SCANNING), - luabind::value("AIMING", AHuman::DeviceHandlingState::AIMING), - luabind::value("FIRING", AHuman::DeviceHandlingState::FIRING), - luabind::value("THROWING", AHuman::DeviceHandlingState::THROWING), - luabind::value("DIGGING", AHuman::DeviceHandlingState::DIGGING)] - .enum_("SweepState")[luabind::value("NOSWEEP", AHuman::SweepState::NOSWEEP), - luabind::value("SWEEPINGUP", AHuman::SweepState::SWEEPINGUP), - luabind::value("SWEEPUPPAUSE", AHuman::SweepState::SWEEPUPPAUSE), - luabind::value("SWEEPINGDOWN", AHuman::SweepState::SWEEPINGDOWN), - luabind::value("SWEEPDOWNPAUSE", AHuman::SweepState::SWEEPDOWNPAUSE)] - .enum_("DigState")[luabind::value("NOTDIGGING", AHuman::DigState::NOTDIGGING), - luabind::value("PREDIG", AHuman::DigState::PREDIG), - luabind::value("STARTDIG", AHuman::DigState::STARTDIG), - luabind::value("TUNNELING", AHuman::DigState::TUNNELING), - luabind::value("FINISHINGDIG", AHuman::DigState::FINISHINGDIG), - luabind::value("PAUSEDIGGER", AHuman::DigState::PAUSEDIGGER)] - .enum_("JumpState")[luabind::value("NOTJUMPING", AHuman::JumpState::NOTJUMPING), - luabind::value("FORWARDJUMP", AHuman::JumpState::FORWARDJUMP), - luabind::value("PREJUMP", AHuman::JumpState::PREUPJUMP), - luabind::value("UPJUMP", AHuman::JumpState::UPJUMP), - luabind::value("APEXJUMP", AHuman::JumpState::APEXJUMP), - luabind::value("LANDJUMP", AHuman::JumpState::LANDJUMP)]; + ConcreteTypeLuaClassDefinition(AHuman, Actor) + + .addConstructor<>() + + .addProperty("Head", &AHuman::GetHead, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetHead) + .addProperty("Jetpack", &AHuman::GetJetpack, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetJetpack) + .addProperty("FGArm", &AHuman::GetFGArm, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetFGArm) + .addProperty("BGArm", &AHuman::GetBGArm, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetBGArm) + .addProperty("FGLeg", &AHuman::GetFGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetFGLeg) + .addProperty("BGLeg", &AHuman::GetBGLeg, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetBGLeg) + .addProperty("FGFoot", &AHuman::GetFGFoot, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetFGFoot) + .addProperty("BGFoot", &AHuman::GetBGFoot, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetBGFoot) + .addProperty("MaxWalkPathCrouchShift", &AHuman::GetMaxWalkPathCrouchShift, &AHuman::SetMaxWalkPathCrouchShift) + .addProperty("CrouchAmount", &AHuman::GetCrouchAmount) + .addProperty("CrouchAmountOverride", &AHuman::GetCrouchAmountOverride, &AHuman::SetCrouchAmountOverride) + .addProperty("StrideSound", &AHuman::GetStrideSound, &LuaAdaptersPropertyOwnershipSafetyFaker::AHumanSetStrideSound) + .addProperty("UpperBodyState", &AHuman::GetUpperBodyState, &AHuman::SetUpperBodyState) + .addProperty("ProneState", &AHuman::GetProneState, &AHuman::SetProneState) + .addProperty("ThrowPrepTime", &AHuman::GetThrowPrepTime, &AHuman::SetThrowPrepTime) + .addProperty("ThrowProgress", &AHuman::GetThrowProgress) + .addProperty("EquippedItem", &AHuman::GetEquippedItem) + .addProperty("EquippedBGItem", &AHuman::GetEquippedBGItem) + .addProperty("EquippedMass", &AHuman::GetEquippedMass) + .addProperty("FirearmIsReady", &AHuman::FirearmIsReady) + .addProperty("ThrowableIsReady", &AHuman::ThrowableIsReady) + .addProperty("FirearmIsEmpty", &AHuman::FirearmIsEmpty) + .addProperty("FirearmNeedsReload", &AHuman::FirearmNeedsReload) + .addProperty("FirearmIsSemiAuto", &AHuman::FirearmIsSemiAuto) + .addProperty("FirearmActivationDelay", &AHuman::FirearmActivationDelay) + .addProperty("IsClimbing", &AHuman::IsClimbing) + .addProperty("StrideFrame", &AHuman::StrideFrame) + .addProperty("ArmSwingRate", &AHuman::GetArmSwingRate, &AHuman::SetArmSwingRate) + .addProperty("DeviceArmSwayRate", &AHuman::GetDeviceArmSwayRate, &AHuman::SetDeviceArmSwayRate) + + .addFunction("EquipFirearm", &AHuman::EquipFirearm) + .addFunction("EquipThrowable", &AHuman::EquipThrowable) + .addFunction("EquipDiggingTool", &AHuman::EquipDiggingTool) + .addFunction("EquipShield", &AHuman::EquipShield) + .addFunction("EquipShieldInBGArm", &LuaAdaptersAHuman::EquipShieldInBGArm) + .addFunction("EquipDeviceInGroup", &AHuman::EquipDeviceInGroup) + .addFunction("EquipNamedDevice", (bool(AHuman::*)(const std::string&, bool)) & AHuman::EquipNamedDevice) + .addFunction("EquipNamedDevice", (bool(AHuman::*)(const std::string&, const std::string&, bool)) & AHuman::EquipNamedDevice) + .addFunction("EquipLoadedFirearmInGroup", &AHuman::EquipLoadedFirearmInGroup) + .addFunction("UnequipFGArm", &AHuman::UnequipFGArm) + .addFunction("UnequipBGArm", &AHuman::UnequipBGArm) + .addFunction("UnequipArms", &AHuman::UnequipArms) + .addFunction("ReloadFirearms", &LuaAdaptersAHuman::ReloadFirearms) + .addFunction("ReloadFirearms", &AHuman::ReloadFirearms) + .addFunction("FirearmsAreReloading", &AHuman::FirearmsAreReloading) + .addFunction("IsWithinRange", &AHuman::IsWithinRange) + .addFunction("Look", &AHuman::Look) + .addFunction("LookForGold", &AHuman::LookForGold) + .addFunction("LookForMOs", &AHuman::LookForMOs) + .addFunction("GetLimbPath", &AHuman::GetLimbPath) + .addFunction("GetLimbPathTravelSpeed", &AHuman::GetLimbPathTravelSpeed) + .addFunction("SetLimbPathTravelSpeed", &AHuman::SetLimbPathTravelSpeed) + .addFunction("GetLimbPathPushForce", &AHuman::GetLimbPathPushForce) + .addFunction("SetLimbPathPushForce", &AHuman::SetLimbPathPushForce) + .addFunction("GetRotAngleTarget", &AHuman::GetRotAngleTarget) + .addFunction("SetRotAngleTarget", &AHuman::SetRotAngleTarget) + .addFunction("GetWalkAngle", &AHuman::GetWalkAngle) + .addFunction("SetWalkAngle", &AHuman::SetWalkAngle) + + .addEnum({{"WEAPON_READY", AHuman::UpperBodyState::WEAPON_READY}, + {"AIMING_SHARP", AHuman::UpperBodyState::AIMING_SHARP}, + {"HOLSTERING_BACK", AHuman::UpperBodyState::HOLSTERING_BACK}, + {"HOLSTERING_BELT", AHuman::UpperBodyState::HOLSTERING_BELT}, + {"DEHOLSTERING_BACK", AHuman::UpperBodyState::DEHOLSTERING_BACK}, + {"DEHOLSTERING_BELT", AHuman::UpperBodyState::DEHOLSTERING_BELT}, + {"THROWING_PREP", AHuman::UpperBodyState::THROWING_PREP}, + {"THROWING_RELEASE", AHuman::UpperBodyState::THROWING_RELEASE}}) + .addEnum({{"NOTPRONE", AHuman::ProneState::NOTPRONE}, + {"GOPRONE", AHuman::ProneState::GOPRONE}, + {"PRONE", AHuman::ProneState::LAYINGPRONE}, + {"PRONESTATECOUNT", AHuman::ProneState::PRONESTATECOUNT}}) + .addEnum({{"FGROUND", AHuman::Layer::FGROUND}, + {"BGROUND", AHuman::Layer::BGROUND}}) + .addEnum({{"STILL", AHuman::DeviceHandlingState::STILL}, + {"POINTING", AHuman::DeviceHandlingState::POINTING}, + {"SCANNING", AHuman::DeviceHandlingState::SCANNING}, + {"AIMING", AHuman::DeviceHandlingState::AIMING}, + {"FIRING", AHuman::DeviceHandlingState::FIRING}, + {"THROWING", AHuman::DeviceHandlingState::THROWING}, + {"DIGGING", AHuman::DeviceHandlingState::DIGGING}}) + .addEnum({{"NOSWEEP", AHuman::SweepState::NOSWEEP}, + {"SWEEPINGUP", AHuman::SweepState::SWEEPINGUP}, + {"SWEEPUPPAUSE", AHuman::SweepState::SWEEPUPPAUSE}, + {"SWEEPINGDOWN", AHuman::SweepState::SWEEPINGDOWN}, + {"SWEEPDOWNPAUSE", AHuman::SweepState::SWEEPDOWNPAUSE}}) + .addEnum({{"NOTDIGGING", AHuman::DigState::NOTDIGGING}, + {"PREDIG", AHuman::DigState::PREDIG}, + {"STARTDIG", AHuman::DigState::STARTDIG}, + {"TUNNELING", AHuman::DigState::TUNNELING}, + {"FINISHINGDIG", AHuman::DigState::FINISHINGDIG}, + {"PAUSEDIGGER", AHuman::DigState::PAUSEDIGGER}}) + .addEnum({{"NOTJUMPING", AHuman::JumpState::NOTJUMPING}, + {"FORWARDJUMP", AHuman::JumpState::FORWARDJUMP}, + {"PREJUMP", AHuman::JumpState::PREUPJUMP}, + {"UPJUMP", AHuman::JumpState::UPJUMP}, + {"APEXJUMP", AHuman::JumpState::APEXJUMP}, + {"LANDJUMP", AHuman::JumpState::LANDJUMP}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Arm) { - return ConcreteTypeLuaClassDefinition(Arm, Attachable) + ConcreteTypeLuaClassDefinition(Arm, Attachable) - .property("MaxLength", &Arm::GetMaxLength) - .property("MoveSpeed", &Arm::GetMoveSpeed, &Arm::SetMoveSpeed) + .addProperty("MaxLength", &Arm::GetMaxLength) + .addProperty("MoveSpeed", &Arm::GetMoveSpeed, &Arm::SetMoveSpeed) - .property("HandIdleOffset", &Arm::GetHandIdleOffset, &Arm::SetHandIdleOffset) + .addProperty("HandIdleOffset", &Arm::GetHandIdleOffset, &Arm::SetHandIdleOffset) - .property("HandPos", &Arm::GetHandPos, &Arm::SetHandPos) - .property("HasAnyHandTargets", &Arm::HasAnyHandTargets) - .property("NumberOfHandTargets", &Arm::GetNumberOfHandTargets) - .property("NextHandTargetDescription", &Arm::GetNextHandTargetDescription) - .property("NextHandTargetPosition", &Arm::GetNextHandTargetPosition) - .property("HandHasReachedCurrentTarget", &Arm::GetHandHasReachedCurrentTarget) + .addProperty("HandPos", &Arm::GetHandPos, &Arm::SetHandPos) + .addProperty("HasAnyHandTargets", &Arm::HasAnyHandTargets) + .addProperty("NumberOfHandTargets", &Arm::GetNumberOfHandTargets) + .addProperty("NextHandTargetDescription", &Arm::GetNextHandTargetDescription) + .addProperty("NextHandTargetPosition", &Arm::GetNextHandTargetPosition) + .addProperty("HandHasReachedCurrentTarget", &Arm::GetHandHasReachedCurrentTarget) - .property("GripStrength", &Arm::GetGripStrength, &Arm::SetGripStrength) - .property("ThrowStrength", &Arm::GetThrowStrength, &Arm::SetThrowStrength) + .addProperty("GripStrength", &Arm::GetGripStrength, &Arm::SetGripStrength) + .addProperty("ThrowStrength", &Arm::GetThrowStrength, &Arm::SetThrowStrength) - .property("HeldDevice", &Arm::GetHeldDevice, &LuaAdaptersPropertyOwnershipSafetyFaker::ArmSetHeldDevice) - .property("SupportedHeldDevice", &Arm::GetHeldDeviceThisArmIsTryingToSupport) + .addProperty("HeldDevice", &Arm::GetHeldDevice, &LuaAdaptersPropertyOwnershipSafetyFaker::ArmSetHeldDevice) + .addProperty("SupportedHeldDevice", &Arm::GetHeldDeviceThisArmIsTryingToSupport) - .def("AddHandTarget", (void(Arm::*)(const std::string& description, const Vector& handTargetPositionToAdd)) & Arm::AddHandTarget) - .def("AddHandTarget", (void(Arm::*)(const std::string& description, const Vector& handTargetPositionToAdd, float delayAtTarget)) & Arm::AddHandTarget) - .def("RemoveNextHandTarget", &Arm::RemoveNextHandTarget) - .def("ClearHandTargets", &Arm::ClearHandTargets); + .addFunction("AddHandTarget", (void(Arm::*)(const std::string& description, const Vector& handTargetPositionToAdd)) & Arm::AddHandTarget) + .addFunction("AddHandTarget", (void(Arm::*)(const std::string& description, const Vector& handTargetPositionToAdd, float delayAtTarget)) & Arm::AddHandTarget) + .addFunction("RemoveNextHandTarget", &Arm::RemoveNextHandTarget) + .addFunction("ClearHandTargets", &Arm::ClearHandTargets); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Attachable) { - return ConcreteTypeLuaClassDefinition(Attachable, MOSRotating) - - .property("ParentOffset", &Attachable::GetParentOffset, &Attachable::SetParentOffset) - .property("JointStrength", &Attachable::GetJointStrength, &Attachable::SetJointStrength) - .property("JointStiffness", &Attachable::GetJointStiffness, &Attachable::SetJointStiffness) - .property("JointOffset", &Attachable::GetJointOffset, &Attachable::SetJointOffset) - .property("JointPos", &Attachable::GetJointPos) - .property("DeleteWhenRemovedFromParent", &Attachable::GetDeleteWhenRemovedFromParent, &Attachable::SetDeleteWhenRemovedFromParent) - .property("GibWhenRemovedFromParent", &Attachable::GetGibWhenRemovedFromParent, &Attachable::SetGibWhenRemovedFromParent) - .property("ApplyTransferredForcesAtOffset", &Attachable::GetApplyTransferredForcesAtOffset, &Attachable::SetApplyTransferredForcesAtOffset) - .property("BreakWound", &Attachable::GetBreakWound, &LuaAdaptersPropertyOwnershipSafetyFaker::AttachableSetBreakWound) - .property("ParentBreakWound", &Attachable::GetParentBreakWound, &LuaAdaptersPropertyOwnershipSafetyFaker::AttachableSetParentBreakWound) - .property("InheritsHFlipped", &Attachable::InheritsHFlipped, &Attachable::SetInheritsHFlipped) - .property("InheritsRotAngle", &Attachable::InheritsRotAngle, &Attachable::SetInheritsRotAngle) - .property("InheritedRotAngleOffset", &Attachable::GetInheritedRotAngleOffset, &Attachable::SetInheritedRotAngleOffset) - .property("AtomSubgroupID", &Attachable::GetAtomSubgroupID) - .property("CollidesWithTerrainWhileAttached", &Attachable::GetCollidesWithTerrainWhileAttached, &Attachable::SetCollidesWithTerrainWhileAttached) - .property("IgnoresParticlesWhileAttached", &Attachable::GetIgnoresParticlesWhileAttached, &Attachable::SetIgnoresParticlesWhileAttached) - .property("CanCollideWithTerrain", &Attachable::CanCollideWithTerrain) - .property("DrawnAfterParent", &Attachable::IsDrawnAfterParent, &Attachable::SetDrawnAfterParent) - .property("InheritsFrame", &Attachable::InheritsFrame, &Attachable::SetInheritsFrame) - .property("InheritsVelWhenDetached", &Attachable::InheritsVelocityWhenDetached, &Attachable::SetInheritsVelocityWhenDetached) - .property("InheritsAngularVelWhenDetached", &Attachable::InheritsAngularVelocityWhenDetached, &Attachable::SetInheritsAngularVelocityWhenDetached) - - .def("IsAttached", &Attachable::IsAttached) - .def("IsAttachedTo", &Attachable::IsAttachedTo) - - .def("RemoveFromParent", &LuaAdaptersAttachable::RemoveFromParent1, luabind::adopt(luabind::return_value)) - .def("RemoveFromParent", &LuaAdaptersAttachable::RemoveFromParent2, luabind::adopt(luabind::return_value)); + ConcreteTypeLuaClassDefinition(Attachable, MOSRotating) + + .addProperty("ParentOffset", &Attachable::GetParentOffset, &Attachable::SetParentOffset) + .addProperty("JointStrength", &Attachable::GetJointStrength, &Attachable::SetJointStrength) + .addProperty("JointStiffness", &Attachable::GetJointStiffness, &Attachable::SetJointStiffness) + .addProperty("JointOffset", &Attachable::GetJointOffset, &Attachable::SetJointOffset) + .addProperty("JointPos", &Attachable::GetJointPos) + .addProperty("DeleteWhenRemovedFromParent", &Attachable::GetDeleteWhenRemovedFromParent, &Attachable::SetDeleteWhenRemovedFromParent) + .addProperty("GibWhenRemovedFromParent", &Attachable::GetGibWhenRemovedFromParent, &Attachable::SetGibWhenRemovedFromParent) + .addProperty("ApplyTransferredForcesAtOffset", &Attachable::GetApplyTransferredForcesAtOffset, &Attachable::SetApplyTransferredForcesAtOffset) + .addProperty("BreakWound", &Attachable::GetBreakWound, &LuaAdaptersPropertyOwnershipSafetyFaker::AttachableSetBreakWound) + .addProperty("ParentBreakWound", &Attachable::GetParentBreakWound, &LuaAdaptersPropertyOwnershipSafetyFaker::AttachableSetParentBreakWound) + .addProperty("InheritsHFlipped", &Attachable::InheritsHFlipped, &Attachable::SetInheritsHFlipped) + .addProperty("InheritsRotAngle", &Attachable::InheritsRotAngle, &Attachable::SetInheritsRotAngle) + .addProperty("InheritedRotAngleOffset", &Attachable::GetInheritedRotAngleOffset, &Attachable::SetInheritedRotAngleOffset) + .addProperty("AtomSubgroupID", &Attachable::GetAtomSubgroupID) + .addProperty("CollidesWithTerrainWhileAttached", &Attachable::GetCollidesWithTerrainWhileAttached, &Attachable::SetCollidesWithTerrainWhileAttached) + .addProperty("IgnoresParticlesWhileAttached", &Attachable::GetIgnoresParticlesWhileAttached, &Attachable::SetIgnoresParticlesWhileAttached) + .addProperty("CanCollideWithTerrain", &Attachable::CanCollideWithTerrain) + .addProperty("DrawnAfterParent", &Attachable::IsDrawnAfterParent, &Attachable::SetDrawnAfterParent) + .addProperty("InheritsFrame", &Attachable::InheritsFrame, &Attachable::SetInheritsFrame) + .addProperty("InheritsVelWhenDetached", &Attachable::InheritsVelocityWhenDetached, &Attachable::SetInheritsVelocityWhenDetached) + .addProperty("InheritsAngularVelWhenDetached", &Attachable::InheritsAngularVelocityWhenDetached, &Attachable::SetInheritsAngularVelocityWhenDetached) + + .addFunction("IsAttached", &Attachable::IsAttached) + .addFunction("IsAttachedTo", &Attachable::IsAttachedTo) + + .addFunction("RemoveFromParent", &LuaAdaptersAttachable::RemoveFromParent1, LuaBinding::AdoptResult) + .addFunction("RemoveFromParent", &LuaAdaptersAttachable::RemoveFromParent2, LuaBinding::AdoptResult); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Deployment) { - return AbstractTypeLuaClassDefinition(Deployment, SceneObject) + AbstractTypeLuaClassDefinition(Deployment, SceneObject) - .property("ID", &Deployment::GetID) - .property("HFlipped", &Deployment::IsHFlipped) - .property("SpawnRadius", &Deployment::GetSpawnRadius) + .addProperty("ID", &Deployment::GetID) + .addProperty("HFlipped", &Deployment::IsHFlipped) + .addProperty("SpawnRadius", &Deployment::GetSpawnRadius) - .def("GetLoadoutName", &Deployment::GetLoadoutName) - .def("CreateDeployedActor", (Actor * (Deployment::*)()) & Deployment::CreateDeployedActor, luabind::adopt(luabind::result)) - .def("CreateDeployedObject", (SceneObject * (Deployment::*)()) & Deployment::CreateDeployedObject, luabind::adopt(luabind::result)); + .addFunction("GetLoadoutName", &Deployment::GetLoadoutName) + .addFunction("CreateDeployedActor", (Actor * (Deployment::*)()) & Deployment::CreateDeployedActor, LuaBinding::AdoptResult) + .addFunction("CreateDeployedObject", (SceneObject * (Deployment::*)()) & Deployment::CreateDeployedObject, LuaBinding::AdoptResult); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Emission) { - return AbstractTypeLuaClassDefinition(Emission, Entity) - - .property("ParticlesPerMinute", &Emission::GetRate, &Emission::SetRate) - .property("MinVelocity", &Emission::GetMinVelocity, &Emission::SetMinVelocity) - .property("MaxVelocity", &Emission::GetMaxVelocity, &Emission::SetMaxVelocity) - .property("PushesEmitter", &Emission::PushesEmitter, &Emission::SetPushesEmitter) - .property("LifeVariation", &Emission::GetLifeVariation, &Emission::SetLifeVariation) - .property("BurstSize", &Emission::GetBurstSize, &Emission::SetBurstSize) - .property("Spread", &Emission::GetSpread, &Emission::SetSpread) - .property("Offset", &Emission::GetOffset, &Emission::SetOffset) - .property("ParticleCount", &Emission::GetParticleCount, &Emission::SetParticleCount) - .property("InheritsVel", &Emission::InheritsVelocity, &Emission::SetInheritsVelocity) - .property("InheritsAngularVel", &Emission::InheritsAngularVelocity, &Emission::SetInheritsAngularVelocity) - - .def("ResetEmissionTimers", &Emission::ResetEmissionTimers); + AbstractTypeLuaClassDefinition(Emission, Entity) + + .addProperty("ParticlesPerMinute", &Emission::GetRate, &Emission::SetRate) + .addProperty("MinVelocity", &Emission::GetMinVelocity, &Emission::SetMinVelocity) + .addProperty("MaxVelocity", &Emission::GetMaxVelocity, &Emission::SetMaxVelocity) + .addProperty("PushesEmitter", &Emission::PushesEmitter, &Emission::SetPushesEmitter) + .addProperty("LifeVariation", &Emission::GetLifeVariation, &Emission::SetLifeVariation) + .addProperty("BurstSize", &Emission::GetBurstSize, &Emission::SetBurstSize) + .addProperty("Spread", &Emission::GetSpread, &Emission::SetSpread) + .addProperty("Offset", &Emission::GetOffset, &Emission::SetOffset) + .addProperty("ParticleCount", &Emission::GetParticleCount, &Emission::SetParticleCount) + .addProperty("InheritsVel", &Emission::InheritsVelocity, &Emission::SetInheritsVelocity) + .addProperty("InheritsAngularVel", &Emission::InheritsAngularVelocity, &Emission::SetInheritsAngularVelocity) + + .addFunction("ResetEmissionTimers", &Emission::ResetEmissionTimers); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Gib) { - return luabind::class_("Gib") - - .property("ParticlePreset", &Gib::GetParticlePreset, &Gib::SetParticlePreset) - .property("MinVelocity", &Gib::GetMinVelocity, &Gib::SetMinVelocity) - .property("MaxVelocity", &Gib::GetMaxVelocity, &Gib::SetMaxVelocity) - .property("SpreadMode", &Gib::GetSpreadMode, &Gib::SetSpreadMode) - - .def_readwrite("Offset", &Gib::m_Offset) - .def_readwrite("Count", &Gib::m_Count) - .def_readwrite("Spread", &Gib::m_Spread) - .def_readwrite("LifeVariation", &Gib::m_LifeVariation) - .def_readwrite("InheritsVel", &Gib::m_InheritsVel) - .def_readwrite("InheritsAngularVel", &Gib::m_InheritsAngularVel) - .def_readwrite("IgnoresTeamHits", &Gib::m_IgnoresTeamHits) - - .enum_("SpreadMode")[luabind::value("SpreadRandom", Gib::SpreadMode::SpreadRandom), - luabind::value("SpreadEven", Gib::SpreadMode::SpreadEven), - luabind::value("SpreadSpiral", Gib::SpreadMode::SpreadSpiral)]; + registry.Class("Gib") + + .addProperty("ParticlePreset", &Gib::GetParticlePreset, &Gib::SetParticlePreset) + .addProperty("MinVelocity", &Gib::GetMinVelocity, &Gib::SetMinVelocity) + .addProperty("MaxVelocity", &Gib::GetMaxVelocity, &Gib::SetMaxVelocity) + .addProperty("SpreadMode", &Gib::GetSpreadMode, &Gib::SetSpreadMode) + + .addReadWriteMember("Offset", &Gib::m_Offset) + .addReadWriteMember("Count", &Gib::m_Count) + .addReadWriteMember("Spread", &Gib::m_Spread) + .addReadWriteMember("LifeVariation", &Gib::m_LifeVariation) + .addReadWriteMember("InheritsVel", &Gib::m_InheritsVel) + .addReadWriteMember("InheritsAngularVel", &Gib::m_InheritsAngularVel) + .addReadWriteMember("IgnoresTeamHits", &Gib::m_IgnoresTeamHits) + + .addEnum({{"SpreadRandom", Gib::SpreadMode::SpreadRandom}, + {"SpreadEven", Gib::SpreadMode::SpreadEven}, + {"SpreadSpiral", Gib::SpreadMode::SpreadSpiral}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, GlobalScript) { - return AbstractTypeLuaClassDefinition(GlobalScript, Entity) + AbstractTypeLuaClassDefinition(GlobalScript, Entity) - .def("Deactivate", &LuaAdaptersGlobalScript::Deactivate); + .addFunction("Deactivate", &LuaAdaptersGlobalScript::Deactivate); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, HDFirearm) { - return ConcreteTypeLuaClassDefinition(HDFirearm, HeldDevice) - - .property("ReloadEndOffset", &HDFirearm::GetReloadEndOffset, &HDFirearm::SetReloadEndOffset) - .property("EjectionPos", &HDFirearm::GetEjectionPos) - .property("EjectionOffset", &HDFirearm::GetEjectionOffset, &HDFirearm::SetEjectionOffset) - .property("RateOfFire", &HDFirearm::GetRateOfFire, &HDFirearm::SetRateOfFire) - .property("MSPerRound", &HDFirearm::GetMSPerRound) - .property("FullAuto", &HDFirearm::IsFullAuto, &HDFirearm::SetFullAuto) - .property("Reloadable", &HDFirearm::IsReloadable, &HDFirearm::SetReloadable) - .property("DualReloadable", &HDFirearm::IsDualReloadable, &HDFirearm::SetDualReloadable) - .property("OneHandedReloadTimeMultiplier", &HDFirearm::GetOneHandedReloadTimeMultiplier, &HDFirearm::SetOneHandedReloadTimeMultiplier) - .property("ReloadAngle", &HDFirearm::GetReloadAngle, &HDFirearm::SetReloadAngle) - .property("OneHandedReloadAngle", &HDFirearm::GetOneHandedReloadAngle, &HDFirearm::SetOneHandedReloadAngle) - .property("CurrentReloadAngle", &HDFirearm::GetCurrentReloadAngle) - .property("RoundInMagCount", &HDFirearm::GetRoundInMagCount) - .property("RoundInMagCapacity", &HDFirearm::GetRoundInMagCapacity) - .property("Magazine", &HDFirearm::GetMagazine, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetMagazine) - .property("Flash", &HDFirearm::GetFlash, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetFlash) - .property("PreFireSound", &HDFirearm::GetPreFireSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetPreFireSound) - .property("FireSound", &HDFirearm::GetFireSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetFireSound) - .property("FireEchoSound", &HDFirearm::GetFireEchoSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetFireEchoSound) - .property("ActiveSound", &HDFirearm::GetActiveSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetActiveSound) - .property("DeactivationSound", &HDFirearm::GetDeactivationSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetDeactivationSound) - .property("EmptySound", &HDFirearm::GetEmptySound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetEmptySound) - .property("ReloadStartSound", &HDFirearm::GetReloadStartSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetReloadStartSound) - .property("ReloadEndSound", &HDFirearm::GetReloadEndSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetReloadEndSound) - .property("ActivationDelay", &HDFirearm::GetActivationDelay, &HDFirearm::SetActivationDelay) - .property("DeactivationDelay", &HDFirearm::GetDeactivationDelay, &HDFirearm::SetDeactivationDelay) - .property("BaseReloadTime", &HDFirearm::GetBaseReloadTime, &HDFirearm::SetBaseReloadTime) - .property("ReloadTime", &HDFirearm::GetReloadTime) - .property("ReloadProgress", &HDFirearm::GetReloadProgress, &HDFirearm::SetReloadProgress) - .property("ShakeRange", &HDFirearm::GetShakeRange, &HDFirearm::SetShakeRange) - .property("SharpShakeRange", &HDFirearm::GetSharpShakeRange, &HDFirearm::SetSharpShakeRange) - .property("NoSupportFactor", &HDFirearm::GetNoSupportFactor, &HDFirearm::SetNoSupportFactor) - .property("ParticleSpreadRange", &HDFirearm::GetParticleSpreadRange, &HDFirearm::SetParticleSpreadRange) - .property("ShellVelVariation", &HDFirearm::GetShellVelVariation, &HDFirearm::SetShellVelVariation) - .property("FiredOnce", &HDFirearm::FiredOnce) - .property("FiredFrame", &HDFirearm::FiredFrame) - .property("CanFire", &HDFirearm::CanFire) - .property("RoundsFired", &HDFirearm::RoundsFired) - .property("IsAnimatedManually", &HDFirearm::IsAnimatedManually, &HDFirearm::SetAnimatedManually) - .property("RecoilTransmission", &HDFirearm::GetJointStiffness, &HDFirearm::SetJointStiffness) - - .def("GetReloadTimer", &HDFirearm::GetReloadTimer) - .def("GetAIFireVel", &HDFirearm::GetAIFireVel) - .def("GetAIBulletLifeTime", &HDFirearm::GetAIBulletLifeTime) - .def("GetBulletAccScalar", &HDFirearm::GetBulletAccScalar) - .def("GetAIBlastRadius", &HDFirearm::GetAIBlastRadius) - .def("GetAIPenetration", &HDFirearm::GetAIPenetration) - .def("CompareTrajectories", &HDFirearm::CompareTrajectories) - .def("GetNextMagazineName", &HDFirearm::GetNextMagazineName) - .def("SetNextMagazineName", &HDFirearm::SetNextMagazineName); + ConcreteTypeLuaClassDefinition(HDFirearm, HeldDevice) + + .addProperty("ReloadEndOffset", &HDFirearm::GetReloadEndOffset, &HDFirearm::SetReloadEndOffset) + .addProperty("EjectionPos", &HDFirearm::GetEjectionPos) + .addProperty("EjectionOffset", &HDFirearm::GetEjectionOffset, &HDFirearm::SetEjectionOffset) + .addProperty("RateOfFire", &HDFirearm::GetRateOfFire, &HDFirearm::SetRateOfFire) + .addProperty("MSPerRound", &HDFirearm::GetMSPerRound) + .addProperty("FullAuto", &HDFirearm::IsFullAuto, &HDFirearm::SetFullAuto) + .addProperty("Reloadable", &HDFirearm::IsReloadable, &HDFirearm::SetReloadable) + .addProperty("DualReloadable", &HDFirearm::IsDualReloadable, &HDFirearm::SetDualReloadable) + .addProperty("OneHandedReloadTimeMultiplier", &HDFirearm::GetOneHandedReloadTimeMultiplier, &HDFirearm::SetOneHandedReloadTimeMultiplier) + .addProperty("ReloadAngle", &HDFirearm::GetReloadAngle, &HDFirearm::SetReloadAngle) + .addProperty("OneHandedReloadAngle", &HDFirearm::GetOneHandedReloadAngle, &HDFirearm::SetOneHandedReloadAngle) + .addProperty("CurrentReloadAngle", &HDFirearm::GetCurrentReloadAngle) + .addProperty("RoundInMagCount", &HDFirearm::GetRoundInMagCount) + .addProperty("RoundInMagCapacity", &HDFirearm::GetRoundInMagCapacity) + .addProperty("Magazine", &HDFirearm::GetMagazine, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetMagazine) + .addProperty("Flash", &HDFirearm::GetFlash, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetFlash) + .addProperty("PreFireSound", &HDFirearm::GetPreFireSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetPreFireSound) + .addProperty("FireSound", &HDFirearm::GetFireSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetFireSound) + .addProperty("FireEchoSound", &HDFirearm::GetFireEchoSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetFireEchoSound) + .addProperty("ActiveSound", &HDFirearm::GetActiveSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetActiveSound) + .addProperty("DeactivationSound", &HDFirearm::GetDeactivationSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetDeactivationSound) + .addProperty("EmptySound", &HDFirearm::GetEmptySound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetEmptySound) + .addProperty("ReloadStartSound", &HDFirearm::GetReloadStartSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetReloadStartSound) + .addProperty("ReloadEndSound", &HDFirearm::GetReloadEndSound, &LuaAdaptersPropertyOwnershipSafetyFaker::HDFirearmSetReloadEndSound) + .addProperty("ActivationDelay", &HDFirearm::GetActivationDelay, &HDFirearm::SetActivationDelay) + .addProperty("DeactivationDelay", &HDFirearm::GetDeactivationDelay, &HDFirearm::SetDeactivationDelay) + .addProperty("BaseReloadTime", &HDFirearm::GetBaseReloadTime, &HDFirearm::SetBaseReloadTime) + .addProperty("ReloadTime", &HDFirearm::GetReloadTime) + .addProperty("ReloadProgress", &HDFirearm::GetReloadProgress, &HDFirearm::SetReloadProgress) + .addProperty("ShakeRange", &HDFirearm::GetShakeRange, &HDFirearm::SetShakeRange) + .addProperty("SharpShakeRange", &HDFirearm::GetSharpShakeRange, &HDFirearm::SetSharpShakeRange) + .addProperty("NoSupportFactor", &HDFirearm::GetNoSupportFactor, &HDFirearm::SetNoSupportFactor) + .addProperty("ParticleSpreadRange", &HDFirearm::GetParticleSpreadRange, &HDFirearm::SetParticleSpreadRange) + .addProperty("ShellVelVariation", &HDFirearm::GetShellVelVariation, &HDFirearm::SetShellVelVariation) + .addProperty("FiredOnce", &HDFirearm::FiredOnce) + .addProperty("FiredFrame", &HDFirearm::FiredFrame) + .addProperty("CanFire", &HDFirearm::CanFire) + .addProperty("RoundsFired", &HDFirearm::RoundsFired) + .addProperty("IsAnimatedManually", &HDFirearm::IsAnimatedManually, &HDFirearm::SetAnimatedManually) + .addProperty("RecoilTransmission", &HDFirearm::GetJointStiffness, &HDFirearm::SetJointStiffness) + + .addFunction("GetReloadTimer", &HDFirearm::GetReloadTimer) + .addFunction("GetAIFireVel", &HDFirearm::GetAIFireVel) + .addFunction("GetAIBulletLifeTime", &HDFirearm::GetAIBulletLifeTime) + .addFunction("GetBulletAccScalar", &HDFirearm::GetBulletAccScalar) + .addFunction("GetAIBlastRadius", &HDFirearm::GetAIBlastRadius) + .addFunction("GetAIPenetration", &HDFirearm::GetAIPenetration) + .addFunction("CompareTrajectories", &HDFirearm::CompareTrajectories) + .addFunction("GetNextMagazineName", &HDFirearm::GetNextMagazineName) + .addFunction("SetNextMagazineName", &HDFirearm::SetNextMagazineName); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, HeldDevice) { - return ConcreteTypeLuaClassDefinition(HeldDevice, Attachable) - - .property("SupportPos", &HeldDevice::GetSupportPos) - .property("MagazinePos", &HeldDevice::GetMagazinePos) - .property("MuzzlePos", &HeldDevice::GetMuzzlePos) - .property("MuzzleOffset", &HeldDevice::GetMuzzleOffset, &HeldDevice::SetMuzzleOffset) - .property("StanceOffset", &HeldDevice::GetStanceOffset, &HeldDevice::SetStanceOffset) - .property("SharpStanceOffset", &HeldDevice::GetSharpStanceOffset, &HeldDevice::SetSharpStanceOffset) - .property("SharpLength", &HeldDevice::GetSharpLength, &HeldDevice::SetSharpLength) - .property("SharpLength", &HeldDevice::GetSharpLength, &HeldDevice::SetSharpLength) - .property("Supportable", &HeldDevice::IsSupportable, &HeldDevice::SetSupportable) - .property("SupportOffset", &HeldDevice::GetSupportOffset, &HeldDevice::SetSupportOffset) - .property("UseSupportOffsetWhileReloading", &HeldDevice::GetUseSupportOffsetWhileReloading, &HeldDevice::SetUseSupportOffsetWhileReloading) - .property("HasPickupLimitations", &HeldDevice::HasPickupLimitations) - .property("UnPickupable", &HeldDevice::IsUnPickupable, &HeldDevice::SetUnPickupable) - .property("GripStrengthMultiplier", &HeldDevice::GetGripStrengthMultiplier, &HeldDevice::SetGripStrengthMultiplier) - .property("Supported", &HeldDevice::GetSupported, &HeldDevice::SetSupported) - .property("GetsHitByMOsWhenHeld", &HeldDevice::GetsHitByMOsWhenHeld, &HeldDevice::SetGetsHitByMOsWhenHeld) - .property("VisualRecoilMultiplier", &HeldDevice::GetVisualRecoilMultiplier, &HeldDevice::SetVisualRecoilMultiplier) - - .def("IsBeingHeld", &HeldDevice::IsBeingHeld) - .def("IsWeapon", &HeldDevice::IsWeapon) - .def("IsTool", &HeldDevice::IsTool) - .def("IsShield", &HeldDevice::IsShield) - .def("IsDualWieldable", &HeldDevice::IsDualWieldable) - .def("SetDualWieldable", &HeldDevice::SetDualWieldable) - .def("IsOneHanded", &HeldDevice::IsOneHanded) - .def("SetOneHanded", &HeldDevice::SetOneHanded) - .def("Activate", &HeldDevice::Activate) - .def("Deactivate", &HeldDevice::Deactivate) - .def("IsActivated", &HeldDevice::IsActivated) - .def("ActivateHotkeyAction", &HeldDevice::ActivateHotkeyAction) - .def("DeactivateHotkeyAction", &HeldDevice::DeactivateHotkeyAction) - .def("HotkeyActionIsActivated", &HeldDevice::HotkeyActionIsActivated) - .def("Reload", &HeldDevice::Reload) - .def("IsReloading", &HeldDevice::IsReloading) - .def("DoneReloading", &HeldDevice::DoneReloading) - .def("NeedsReloading", &HeldDevice::NeedsReloading) - .def("IsFull", &HeldDevice::IsFull) - .def("IsEmpty", &HeldDevice::IsEmpty) - .def("IsPickupableBy", &HeldDevice::IsPickupableBy) - .def("AddPickupableByPresetName", &HeldDevice::AddPickupableByPresetName) - .def("RemovePickupableByPresetName", &HeldDevice::RemovePickupableByPresetName) - - .enum_("HeldDeviceHotkeyType")[luabind::value("PRIMARYHOTKEY", HeldDeviceHotkeyType::PRIMARYHOTKEY), - luabind::value("AUXILIARYHOTKEY", HeldDeviceHotkeyType::AUXILIARYHOTKEY), - luabind::value("HELDDEVICEHOTKEYTYPECOUNT", HeldDeviceHotkeyType::HELDDEVICEHOTKEYTYPECOUNT)]; - + ConcreteTypeLuaClassDefinition(HeldDevice, Attachable) + + .addProperty("SupportPos", &HeldDevice::GetSupportPos) + .addProperty("MagazinePos", &HeldDevice::GetMagazinePos) + .addProperty("MuzzlePos", &HeldDevice::GetMuzzlePos) + .addProperty("MuzzleOffset", &HeldDevice::GetMuzzleOffset, &HeldDevice::SetMuzzleOffset) + .addProperty("StanceOffset", &HeldDevice::GetStanceOffset, &HeldDevice::SetStanceOffset) + .addProperty("SharpStanceOffset", &HeldDevice::GetSharpStanceOffset, &HeldDevice::SetSharpStanceOffset) + .addProperty("SharpLength", &HeldDevice::GetSharpLength, &HeldDevice::SetSharpLength) + .addProperty("SharpLength", &HeldDevice::GetSharpLength, &HeldDevice::SetSharpLength) + .addProperty("Supportable", &HeldDevice::IsSupportable, &HeldDevice::SetSupportable) + .addProperty("SupportOffset", &HeldDevice::GetSupportOffset, &HeldDevice::SetSupportOffset) + .addProperty("UseSupportOffsetWhileReloading", &HeldDevice::GetUseSupportOffsetWhileReloading, &HeldDevice::SetUseSupportOffsetWhileReloading) + .addProperty("HasPickupLimitations", &HeldDevice::HasPickupLimitations) + .addProperty("UnPickupable", &HeldDevice::IsUnPickupable, &HeldDevice::SetUnPickupable) + .addProperty("GripStrengthMultiplier", &HeldDevice::GetGripStrengthMultiplier, &HeldDevice::SetGripStrengthMultiplier) + .addProperty("Supported", &HeldDevice::GetSupported, &HeldDevice::SetSupported) + .addProperty("GetsHitByMOsWhenHeld", &HeldDevice::GetsHitByMOsWhenHeld, &HeldDevice::SetGetsHitByMOsWhenHeld) + .addProperty("VisualRecoilMultiplier", &HeldDevice::GetVisualRecoilMultiplier, &HeldDevice::SetVisualRecoilMultiplier) + + .addFunction("IsBeingHeld", &HeldDevice::IsBeingHeld) + .addFunction("IsWeapon", &HeldDevice::IsWeapon) + .addFunction("IsTool", &HeldDevice::IsTool) + .addFunction("IsShield", &HeldDevice::IsShield) + .addFunction("IsDualWieldable", &HeldDevice::IsDualWieldable) + .addFunction("SetDualWieldable", &HeldDevice::SetDualWieldable) + .addFunction("IsOneHanded", &HeldDevice::IsOneHanded) + .addFunction("SetOneHanded", &HeldDevice::SetOneHanded) + .addFunction("Activate", &HeldDevice::Activate) + .addFunction("Deactivate", &HeldDevice::Deactivate) + .addFunction("IsActivated", &HeldDevice::IsActivated) + .addFunction("ActivateHotkeyAction", &HeldDevice::ActivateHotkeyAction) + .addFunction("DeactivateHotkeyAction", &HeldDevice::DeactivateHotkeyAction) + .addFunction("HotkeyActionIsActivated", &HeldDevice::HotkeyActionIsActivated) + .addFunction("Reload", &HeldDevice::Reload) + .addFunction("IsReloading", &HeldDevice::IsReloading) + .addFunction("DoneReloading", &HeldDevice::DoneReloading) + .addFunction("NeedsReloading", &HeldDevice::NeedsReloading) + .addFunction("IsFull", &HeldDevice::IsFull) + .addFunction("IsEmpty", &HeldDevice::IsEmpty) + .addFunction("IsPickupableBy", &HeldDevice::IsPickupableBy) + .addFunction("AddPickupableByPresetName", &HeldDevice::AddPickupableByPresetName) + .addFunction("RemovePickupableByPresetName", &HeldDevice::RemovePickupableByPresetName) + + .addEnum({{"PRIMARYHOTKEY", HeldDeviceHotkeyType::PRIMARYHOTKEY}, + {"AUXILIARYHOTKEY", HeldDeviceHotkeyType::AUXILIARYHOTKEY}, + {"HELDDEVICEHOTKEYTYPECOUNT", HeldDeviceHotkeyType::HELDDEVICEHOTKEYTYPECOUNT}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Leg) { - return ConcreteTypeLuaClassDefinition(Leg, Attachable) + ConcreteTypeLuaClassDefinition(Leg, Attachable) - .property("Foot", &Leg::GetFoot, &LuaAdaptersPropertyOwnershipSafetyFaker::LegSetFoot) - .property("MoveSpeed", &Leg::GetMoveSpeed, &Leg::SetMoveSpeed); + .addProperty("Foot", &Leg::GetFoot, &LuaAdaptersPropertyOwnershipSafetyFaker::LegSetFoot) + .addProperty("MoveSpeed", &Leg::GetMoveSpeed, &Leg::SetMoveSpeed); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, LimbPath) { - return luabind::class_("LimbPath") + registry.Class("LimbPath") - .property("StartOffset", &LimbPath::GetStartOffset, &LimbPath::SetStartOffset) - .property("SegmentCount", &LimbPath::GetSegCount) - .property("BaseTravelSpeedMultiplier", &LimbPath::GetBaseTravelSpeedMultiplier, &LimbPath::SetBaseTravelSpeedMultiplier) - .property("TravelSpeed", &LimbPath::GetTravelSpeed, &LimbPath::SetTravelSpeed) - .property("PushForce", &LimbPath::GetPushForce, &LimbPath::SetPushForce) + .addProperty("StartOffset", &LimbPath::GetStartOffset, &LimbPath::SetStartOffset) + .addProperty("SegmentCount", &LimbPath::GetSegCount) + .addProperty("BaseTravelSpeedMultiplier", &LimbPath::GetBaseTravelSpeedMultiplier, &LimbPath::SetBaseTravelSpeedMultiplier) + .addProperty("TravelSpeed", &LimbPath::GetTravelSpeed, &LimbPath::SetTravelSpeed) + .addProperty("PushForce", &LimbPath::GetPushForce, &LimbPath::SetPushForce) - .def("GetSegment", &LimbPath::GetSegment); + .addFunction("GetSegment", &LimbPath::GetSegment); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Magazine) { - return ConcreteTypeLuaClassDefinition(Magazine, Attachable) - - .property("NextRound", &Magazine::GetNextRound) - .property("RoundCount", &Magazine::GetRoundCount, &Magazine::SetRoundCount) - .property("IsEmpty", &Magazine::IsEmpty) - .property("IsFull", &Magazine::IsFull) - .property("IsOverHalfFull", &Magazine::IsOverHalfFull) - .property("Capacity", &Magazine::GetCapacity) - .property("Discardable", &Magazine::IsDiscardable); + ConcreteTypeLuaClassDefinition(Magazine, Attachable) + + .addProperty("NextRound", &Magazine::GetNextRound) + .addProperty("RoundCount", &Magazine::GetRoundCount, &Magazine::SetRoundCount) + .addProperty("IsEmpty", &Magazine::IsEmpty) + .addProperty("IsFull", &Magazine::IsFull) + .addProperty("IsOverHalfFull", &Magazine::IsOverHalfFull) + .addProperty("Capacity", &Magazine::GetCapacity) + .addProperty("Discardable", &Magazine::IsDiscardable); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Material) { - return luabind::class_("Material") - - .property("ID", &Material::GetIndex) - .property("Restitution", &Material::GetRestitution) - .property("Bounce", &Material::GetRestitution) - .property("Friction", &Material::GetFriction) - .property("Stickiness", &Material::GetStickiness) - .property("Strength", &Material::GetIntegrity) - .property("StructuralIntegrity", &Material::GetIntegrity) - .property("DensityKGPerVolumeL", &Material::GetVolumeDensity) - .property("DensityKGPerPixel", &Material::GetPixelDensity) - .property("SettleMaterial", &Material::GetSettleMaterial) - .property("SpawnMaterial", &Material::GetSpawnMaterial) - .property("TransformsInto", &Material::GetSpawnMaterial) - .property("IsScrap", &Material::IsScrap) - - .def("GetColorIndex", &Material::GetColorIndex); + registry.Class("Material") + + .addProperty("ID", &Material::GetIndex) + .addProperty("Restitution", &Material::GetRestitution) + .addProperty("Bounce", &Material::GetRestitution) + .addProperty("Friction", &Material::GetFriction) + .addProperty("Stickiness", &Material::GetStickiness) + .addProperty("Strength", &Material::GetIntegrity) + .addProperty("StructuralIntegrity", &Material::GetIntegrity) + .addProperty("DensityKGPerVolumeL", &Material::GetVolumeDensity) + .addProperty("DensityKGPerPixel", &Material::GetPixelDensity) + .addProperty("SettleMaterial", &Material::GetSettleMaterial) + .addProperty("SpawnMaterial", &Material::GetSpawnMaterial) + .addProperty("TransformsInto", &Material::GetSpawnMaterial) + .addProperty("IsScrap", &Material::IsScrap) + + .addFunction("GetColorIndex", &Material::GetColorIndex); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, MetaPlayer) { - return luabind::class_("MetaPlayer") + registry.Class("MetaPlayer") - .def(luabind::constructor<>()) + .addConstructor<>() - .property("NativeTechModule", &MetaPlayer::GetNativeTechModule) - .property("ForeignCostMultiplier", &MetaPlayer::GetForeignCostMultiplier) - .property("NativeCostMultiplier", &MetaPlayer::GetNativeCostMultiplier) - .property("InGamePlayer", &MetaPlayer::GetInGamePlayer) - .property("BrainPoolCount", &MetaPlayer::GetBrainPoolCount, &MetaPlayer::SetBrainPoolCount) + .addProperty("NativeTechModule", &MetaPlayer::GetNativeTechModule) + .addProperty("ForeignCostMultiplier", &MetaPlayer::GetForeignCostMultiplier) + .addProperty("NativeCostMultiplier", &MetaPlayer::GetNativeCostMultiplier) + .addProperty("InGamePlayer", &MetaPlayer::GetInGamePlayer) + .addProperty("BrainPoolCount", &MetaPlayer::GetBrainPoolCount, &MetaPlayer::SetBrainPoolCount) - .def("ChangeBrainPoolCount", &MetaPlayer::ChangeBrainPoolCount); + .addFunction("ChangeBrainPoolCount", &MetaPlayer::ChangeBrainPoolCount); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, MOPixel) { - return ConcreteTypeLuaClassDefinition(MOPixel, MovableObject) + ConcreteTypeLuaClassDefinition(MOPixel, MovableObject) - .property("TrailLength", &MOPixel::GetTrailLength, &MOPixel::SetTrailLength) - .property("Staininess", &MOPixel::GetStaininess, &MOPixel::SetStaininess) + .addProperty("TrailLength", &MOPixel::GetTrailLength, &MOPixel::SetTrailLength) + .addProperty("Staininess", &MOPixel::GetStaininess, &MOPixel::SetStaininess) - .def("GetColorIndex", &MOPixel::GetColorIndex) - .def("SetColorIndex", &MOPixel::SetColorIndex); + .addFunction("GetColorIndex", &MOPixel::GetColorIndex) + .addFunction("SetColorIndex", &MOPixel::SetColorIndex); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, MOSParticle) { - return ConcreteTypeLuaClassDefinition(MOSParticle, MOSprite); + ConcreteTypeLuaClassDefinition(MOSParticle, MOSprite); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, MOSprite) { - return AbstractTypeLuaClassDefinition(MOSprite, MovableObject) - - .property("Diameter", &MOSprite::GetDiameter) - .property("BoundingBox", &MOSprite::GetBoundingBox) - .property("FrameCount", &MOSprite::GetFrameCount) - .property("SpriteOffset", &MOSprite::GetSpriteOffset, &MOSprite::SetSpriteOffset) - .property("HFlipped", &MOSprite::IsHFlipped, &MOSprite::SetHFlipped) - .property("ForcedHFlip", &MOSprite::GetForcedHFlip, &MOSprite::SetForcedHFlip) - .property("FlipFactor", &MOSprite::GetFlipFactor) - .property("RotAngle", &MOSprite::GetRotAngle, &MOSprite::SetRotAngle) - .property("PrevRotAngle", &MOSprite::GetPrevRotAngle) - .property("AngularVel", &MOSprite::GetAngularVel, &MOSprite::SetAngularVel) - .property("Frame", &MOSprite::GetFrame, &MOSprite::SetFrame) - .property("SpriteAnimMode", &MOSprite::GetSpriteAnimMode, &MOSprite::SetSpriteAnimMode) - .property("SpriteAnimDuration", &MOSprite::GetSpriteAnimDuration, &MOSprite::SetSpriteAnimDuration) - - .def("SetNextFrame", &MOSprite::SetNextFrame) - .def("IsTooFast", &MOSprite::IsTooFast) - .def("IsOnScenePoint", &MOSprite::IsOnScenePoint) - .def("RotateOffset", &MOSprite::RotateOffset) - .def("UnRotateOffset", &MOSprite::UnRotateOffset) - .def("FacingAngle", &MOSprite::FacingAngle) - .def("GetSpriteWidth", &MOSprite::GetSpriteWidth) - .def("GetSpriteHeight", &MOSprite::GetSpriteHeight) - .def("GetIconWidth", &MOSprite::GetIconWidth) - .def("GetIconHeight", &MOSprite::GetIconHeight) - .def("SetEntryWound", &MOSprite::SetEntryWound) - .def("SetExitWound", &MOSprite::SetExitWound) - .def("GetEntryWoundPresetName", &MOSprite::GetEntryWoundPresetName) - .def("GetExitWoundPresetName", &MOSprite::GetExitWoundPresetName) - .def("GetSpritePixelIndex", &MOSprite::GetSpritePixelIndex) - .def("SetSpritePixelIndex", &MOSprite::SetSpritePixelIndex) - .def("GetAllSpritePixelPositions", &MOSprite::GetAllSpritePixelPositions, luabind::return_stl_iterator) - .def("GetAllVisibleSpritePixelPositions", &MOSprite::GetAllVisibleSpritePixelPositions, luabind::return_stl_iterator) - .def("SetAllSpritePixelIndexes", &MOSprite::SetAllSpritePixelIndexes) - .def("SetAllVisibleSpritePixelIndexes", &MOSprite::SetAllVisibleSpritePixelIndexes) - - .enum_("SpriteAnimMode")[luabind::value("NOANIM", SpriteAnimMode::NOANIM), - luabind::value("ALWAYSLOOP", SpriteAnimMode::ALWAYSLOOP), - luabind::value("ALWAYSRANDOM", SpriteAnimMode::ALWAYSRANDOM), - luabind::value("ALWAYSPINGPONG", SpriteAnimMode::ALWAYSPINGPONG), - luabind::value("LOOPWHENACTIVE", SpriteAnimMode::LOOPWHENACTIVE), - luabind::value("LOOPWHENOPENCLOSE", SpriteAnimMode::LOOPWHENOPENCLOSE), - luabind::value("PINGPONGOPENCLOSE", SpriteAnimMode::PINGPONGOPENCLOSE), - luabind::value("OVERLIFETIME", SpriteAnimMode::OVERLIFETIME), - luabind::value("ONCOLLIDE", SpriteAnimMode::ONCOLLIDE)]; + AbstractTypeLuaClassDefinition(MOSprite, MovableObject) + + .addProperty("Diameter", &MOSprite::GetDiameter) + .addProperty("BoundingBox", &MOSprite::GetBoundingBox) + .addProperty("FrameCount", &MOSprite::GetFrameCount) + .addProperty("SpriteOffset", &MOSprite::GetSpriteOffset, &MOSprite::SetSpriteOffset) + .addProperty("HFlipped", &MOSprite::IsHFlipped, &MOSprite::SetHFlipped) + .addProperty("ForcedHFlip", &MOSprite::GetForcedHFlip, &MOSprite::SetForcedHFlip) + .addProperty("FlipFactor", &MOSprite::GetFlipFactor) + .addProperty("RotAngle", &MOSprite::GetRotAngle, &MOSprite::SetRotAngle) + .addProperty("PrevRotAngle", &MOSprite::GetPrevRotAngle) + .addProperty("AngularVel", &MOSprite::GetAngularVel, &MOSprite::SetAngularVel) + .addProperty("Frame", &MOSprite::GetFrame, &MOSprite::SetFrame) + .addProperty("SpriteAnimMode", &MOSprite::GetSpriteAnimMode, &MOSprite::SetSpriteAnimMode) + .addProperty("SpriteAnimDuration", &MOSprite::GetSpriteAnimDuration, &MOSprite::SetSpriteAnimDuration) + + .addFunction("SetNextFrame", &MOSprite::SetNextFrame) + .addFunction("IsTooFast", &MOSprite::IsTooFast) + .addFunction("IsOnScenePoint", &MOSprite::IsOnScenePoint) + .addFunction("RotateOffset", &MOSprite::RotateOffset) + .addFunction("UnRotateOffset", &MOSprite::UnRotateOffset) + .addFunction("FacingAngle", &MOSprite::FacingAngle) + .addFunction("GetSpriteWidth", &MOSprite::GetSpriteWidth) + .addFunction("GetSpriteHeight", &MOSprite::GetSpriteHeight) + .addFunction("GetIconWidth", &MOSprite::GetIconWidth) + .addFunction("GetIconHeight", &MOSprite::GetIconHeight) + .addFunction("SetEntryWound", &MOSprite::SetEntryWound) + .addFunction("SetExitWound", &MOSprite::SetExitWound) + .addFunction("GetEntryWoundPresetName", &MOSprite::GetEntryWoundPresetName) + .addFunction("GetExitWoundPresetName", &MOSprite::GetExitWoundPresetName) + .addFunction("GetSpritePixelIndex", &MOSprite::GetSpritePixelIndex) + .addFunction("SetSpritePixelIndex", &MOSprite::SetSpritePixelIndex) + .addFunction("GetAllSpritePixelPositions", &MOSprite::GetAllSpritePixelPositions, LuaBinding::ReturnStlIterator) + .addFunction("GetAllVisibleSpritePixelPositions", &MOSprite::GetAllVisibleSpritePixelPositions, LuaBinding::ReturnStlIterator) + .addFunction("SetAllSpritePixelIndexes", &MOSprite::SetAllSpritePixelIndexes) + .addFunction("SetAllVisibleSpritePixelIndexes", &MOSprite::SetAllVisibleSpritePixelIndexes) + + .addEnum({{"NOANIM", SpriteAnimMode::NOANIM}, + {"ALWAYSLOOP", SpriteAnimMode::ALWAYSLOOP}, + {"ALWAYSRANDOM", SpriteAnimMode::ALWAYSRANDOM}, + {"ALWAYSPINGPONG", SpriteAnimMode::ALWAYSPINGPONG}, + {"LOOPWHENACTIVE", SpriteAnimMode::LOOPWHENACTIVE}, + {"LOOPWHENOPENCLOSE", SpriteAnimMode::LOOPWHENOPENCLOSE}, + {"PINGPONGOPENCLOSE", SpriteAnimMode::PINGPONGOPENCLOSE}, + {"OVERLIFETIME", SpriteAnimMode::OVERLIFETIME}, + {"ONCOLLIDE", SpriteAnimMode::ONCOLLIDE}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, MOSRotating) { - return ConcreteTypeLuaClassDefinition(MOSRotating, MOSprite) - - //.property("Material", &MOSRotating::GetMaterial) - .property("IndividualRadius", &MOSRotating::GetIndividualRadius) - .property("IndividualDiameter", &MOSRotating::GetIndividualDiameter) - .property("IndividualMass", &MOSRotating::GetIndividualMass) - .property("RecoilForce", &MOSRotating::GetRecoilForce) - .property("RecoilOffset", &MOSRotating::GetRecoilOffset) - .property("TravelImpulse", &MOSRotating::GetTravelImpulse, &MOSRotating::SetTravelImpulse) - .property("GibWoundLimit", (int(MOSRotating::*)() const) & MOSRotating::GetGibWoundLimit, &MOSRotating::SetGibWoundLimit) - .property("GibSound", &MOSRotating::GetGibSound, &LuaAdaptersPropertyOwnershipSafetyFaker::MOSRotatingSetGibSound) - .property("GibImpulseLimit", &MOSRotating::GetGibImpulseLimit, &MOSRotating::SetGibImpulseLimit) - .property("WoundCountAffectsImpulseLimitRatio", &MOSRotating::GetWoundCountAffectsImpulseLimitRatio) - .property("GibAtEndOfLifetime", &MOSRotating::GetGibAtEndOfLifetime, &MOSRotating::SetGibAtEndOfLifetime) - .property("DamageMultiplier", &MOSRotating::GetDamageMultiplier, &MOSRotating::SetDamageMultiplier) - .property("WoundCount", (int(MOSRotating::*)() const) & MOSRotating::GetWoundCount) - .property("OrientToVel", &MOSRotating::GetOrientToVel, &MOSRotating::SetOrientToVel) - - .def_readonly("Attachables", &MOSRotating::m_Attachables, luabind::return_stl_iterator) - .def_readonly("Wounds", &MOSRotating::m_Wounds, luabind::return_stl_iterator) - .def_readonly("Gibs", &MOSRotating::m_Gibs, luabind::return_stl_iterator) - - .def("AddRecoil", &MOSRotating::AddRecoil) - .def("SetRecoil", &MOSRotating::SetRecoil) - .def("IsRecoiled", &MOSRotating::IsRecoiled) - .def("EnableDeepCheck", &MOSRotating::EnableDeepCheck) - .def("ForceDeepCheck", &MOSRotating::ForceDeepCheck) - .def("GibThis", &MOSRotating::GibThis) - .def("MoveOutOfTerrain", &MOSRotating::MoveOutOfTerrain) - .def("FlashWhite", &MOSRotating::FlashWhite) - .def("GetGibWoundLimit", (int(MOSRotating::*)() const) & MOSRotating::GetGibWoundLimit) - .def("GetGibWoundLimit", (int(MOSRotating::*)(bool positiveDamage, bool negativeDamage, bool noDamage) const) & MOSRotating::GetGibWoundLimit) - .def("GetWoundCount", (int(MOSRotating::*)() const) & MOSRotating::GetWoundCount) - .def("GetWoundCount", (int(MOSRotating::*)(bool positiveDamage, bool negativeDamage, bool noDamage) const) & MOSRotating::GetWoundCount) - .def("GetWounds", &LuaAdaptersMOSRotating::GetWounds1, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("GetWounds", &LuaAdaptersMOSRotating::GetWounds2, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("AddWound", &MOSRotating::AddWound, luabind::adopt(_2)) - .def("AddWound", &MOSRotating::AddWoundExt, luabind::adopt(_2)) - .def("RemoveWounds", (float(MOSRotating::*)(int numberOfWoundsToRemove)) & MOSRotating::RemoveWounds) - .def("RemoveWounds", (float(MOSRotating::*)(int numberOfWoundsToRemove, bool positiveDamage, bool negativeDamage, bool noDamage)) & MOSRotating::RemoveWounds) - .def("IsOnScenePoint", &MOSRotating::IsOnScenePoint) - .def("EraseFromTerrain", &MOSRotating::EraseFromTerrain) - .def("AddAttachable", (void(MOSRotating::*)(Attachable * attachableToAdd)) & MOSRotating::AddAttachable, luabind::adopt(_2)) - .def("AddAttachable", (void(MOSRotating::*)(Attachable * attachableToAdd, const Vector& parentOffset)) & MOSRotating::AddAttachable, luabind::adopt(_2)) - .def("RemoveAttachable", (Attachable * (MOSRotating::*)(int64_t uniqueIDOfAttachableToRemove)) & MOSRotating::RemoveAttachable, luabind::adopt(luabind::return_value)) - .def("RemoveAttachable", (Attachable * (MOSRotating::*)(int64_t uniqueIDOfAttachableToRemove, bool addToMovableMan, bool addBreakWounds)) & MOSRotating::RemoveAttachable, luabind::adopt(luabind::return_value)) - .def("RemoveAttachable", (Attachable * (MOSRotating::*)(Attachable * attachableToRemove)) & MOSRotating::RemoveAttachable, luabind::adopt(luabind::return_value)) - .def("RemoveAttachable", (Attachable * (MOSRotating::*)(Attachable * attachableToRemove, bool addToMovableMan, bool addBreakWounds)) & MOSRotating::RemoveAttachable) - .def("AddEmitter", (void(MOSRotating::*)(Attachable * attachableToAdd)) & MOSRotating::AddAttachable, luabind::adopt(_2)) - .def("AddEmitter", (void(MOSRotating::*)(Attachable * attachableToAdd, const Vector& parentOffset)) & MOSRotating::AddAttachable, luabind::adopt(_2)) - .def("RemoveEmitter", (Attachable * (MOSRotating::*)(int64_t uniqueIDOfAttachableToRemove)) & MOSRotating::RemoveAttachable, luabind::adopt(luabind::return_value)) - .def("RemoveEmitter", (Attachable * (MOSRotating::*)(int64_t uniqueIDOfAttachableToRemove, bool addToMovableMan, bool addBreakWounds)) & MOSRotating::RemoveAttachable, luabind::adopt(luabind::return_value)) - .def("RemoveEmitter", (Attachable * (MOSRotating::*)(Attachable * attachableToRemove)) & MOSRotating::RemoveAttachable, luabind::adopt(luabind::return_value)) - .def("RemoveEmitter", (Attachable * (MOSRotating::*)(Attachable * attachableToRemove, bool addToMovableMan, bool addBreakWounds)) & MOSRotating::RemoveAttachable, luabind::adopt(luabind::return_value)) - - .def("GibThis", &LuaAdaptersMOSRotating::GibThis); + ConcreteTypeLuaClassDefinition(MOSRotating, MOSprite) + + //.addProperty("Material", &MOSRotating::GetMaterial) + .addProperty("IndividualRadius", &MOSRotating::GetIndividualRadius) + .addProperty("IndividualDiameter", &MOSRotating::GetIndividualDiameter) + .addProperty("IndividualMass", &MOSRotating::GetIndividualMass) + .addProperty("RecoilForce", &MOSRotating::GetRecoilForce) + .addProperty("RecoilOffset", &MOSRotating::GetRecoilOffset) + .addProperty("TravelImpulse", &MOSRotating::GetTravelImpulse, &MOSRotating::SetTravelImpulse) + .addProperty("GibWoundLimit", (int(MOSRotating::*)() const) & MOSRotating::GetGibWoundLimit, &MOSRotating::SetGibWoundLimit) + .addProperty("GibSound", &MOSRotating::GetGibSound, &LuaAdaptersPropertyOwnershipSafetyFaker::MOSRotatingSetGibSound) + .addProperty("GibImpulseLimit", &MOSRotating::GetGibImpulseLimit, &MOSRotating::SetGibImpulseLimit) + .addProperty("WoundCountAffectsImpulseLimitRatio", &MOSRotating::GetWoundCountAffectsImpulseLimitRatio) + .addProperty("GibAtEndOfLifetime", &MOSRotating::GetGibAtEndOfLifetime, &MOSRotating::SetGibAtEndOfLifetime) + .addProperty("DamageMultiplier", &MOSRotating::GetDamageMultiplier, &MOSRotating::SetDamageMultiplier) + .addProperty("WoundCount", (int(MOSRotating::*)() const) & MOSRotating::GetWoundCount) + .addProperty("OrientToVel", &MOSRotating::GetOrientToVel, &MOSRotating::SetOrientToVel) + + .addProperty("Attachables", &MOSRotating::m_Attachables, LuaBinding::ReturnStlIterator) + .addProperty("Wounds", &MOSRotating::m_Wounds, LuaBinding::ReturnStlIterator) + .addProperty("Gibs", &MOSRotating::m_Gibs, LuaBinding::ReturnStlIterator) + + .addFunction("AddRecoil", &MOSRotating::AddRecoil) + .addFunction("SetRecoil", &MOSRotating::SetRecoil) + .addFunction("IsRecoiled", &MOSRotating::IsRecoiled) + .addFunction("EnableDeepCheck", &MOSRotating::EnableDeepCheck) + .addFunction("ForceDeepCheck", &MOSRotating::ForceDeepCheck) + .addFunction("GibThis", &MOSRotating::GibThis) + .addFunction("MoveOutOfTerrain", &MOSRotating::MoveOutOfTerrain) + .addFunction("FlashWhite", &MOSRotating::FlashWhite) + .addFunction("GetGibWoundLimit", (int(MOSRotating::*)() const) & MOSRotating::GetGibWoundLimit) + .addFunction("GetGibWoundLimit", (int(MOSRotating::*)(bool positiveDamage, bool negativeDamage, bool noDamage) const) & MOSRotating::GetGibWoundLimit) + .addFunction("GetWoundCount", (int(MOSRotating::*)() const) & MOSRotating::GetWoundCount) + .addFunction("GetWoundCount", (int(MOSRotating::*)(bool positiveDamage, bool negativeDamage, bool noDamage) const) & MOSRotating::GetWoundCount) + .addFunction("GetWounds", &LuaAdaptersMOSRotating::GetWounds1, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetWounds", &LuaAdaptersMOSRotating::GetWounds2, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("AddWound", &MOSRotating::AddWound, LuaBinding::AdoptArg<2>) + .addFunction("AddWound", &MOSRotating::AddWoundExt, LuaBinding::AdoptArg<2>) + .addFunction("RemoveWounds", (float(MOSRotating::*)(int numberOfWoundsToRemove)) & MOSRotating::RemoveWounds) + .addFunction("RemoveWounds", (float(MOSRotating::*)(int numberOfWoundsToRemove, bool positiveDamage, bool negativeDamage, bool noDamage)) & MOSRotating::RemoveWounds) + .addFunction("IsOnScenePoint", &MOSRotating::IsOnScenePoint) + .addFunction("EraseFromTerrain", &MOSRotating::EraseFromTerrain) + .addFunction("AddAttachable", (void(MOSRotating::*)(Attachable * attachableToAdd)) & MOSRotating::AddAttachable, LuaBinding::AdoptArg<2>) + .addFunction("AddAttachable", (void(MOSRotating::*)(Attachable * attachableToAdd, const Vector& parentOffset)) & MOSRotating::AddAttachable, LuaBinding::AdoptArg<2>) + .addFunction("RemoveAttachable", (Attachable * (MOSRotating::*)(int64_t uniqueIDOfAttachableToRemove)) & MOSRotating::RemoveAttachable, LuaBinding::AdoptResult) + .addFunction("RemoveAttachable", (Attachable * (MOSRotating::*)(int64_t uniqueIDOfAttachableToRemove, bool addToMovableMan, bool addBreakWounds)) & MOSRotating::RemoveAttachable, LuaBinding::AdoptResult) + .addFunction("RemoveAttachable", (Attachable * (MOSRotating::*)(Attachable * attachableToRemove)) & MOSRotating::RemoveAttachable, LuaBinding::AdoptResult) + .addFunction("RemoveAttachable", (Attachable * (MOSRotating::*)(Attachable * attachableToRemove, bool addToMovableMan, bool addBreakWounds)) & MOSRotating::RemoveAttachable) + .addFunction("AddEmitter", (void(MOSRotating::*)(Attachable * attachableToAdd)) & MOSRotating::AddAttachable, LuaBinding::AdoptArg<2>) + .addFunction("AddEmitter", (void(MOSRotating::*)(Attachable * attachableToAdd, const Vector& parentOffset)) & MOSRotating::AddAttachable, LuaBinding::AdoptArg<2>) + .addFunction("RemoveEmitter", (Attachable * (MOSRotating::*)(int64_t uniqueIDOfAttachableToRemove)) & MOSRotating::RemoveAttachable, LuaBinding::AdoptResult) + .addFunction("RemoveEmitter", (Attachable * (MOSRotating::*)(int64_t uniqueIDOfAttachableToRemove, bool addToMovableMan, bool addBreakWounds)) & MOSRotating::RemoveAttachable, LuaBinding::AdoptResult) + .addFunction("RemoveEmitter", (Attachable * (MOSRotating::*)(Attachable * attachableToRemove)) & MOSRotating::RemoveAttachable, LuaBinding::AdoptResult) + .addFunction("RemoveEmitter", (Attachable * (MOSRotating::*)(Attachable * attachableToRemove, bool addToMovableMan, bool addBreakWounds)) & MOSRotating::RemoveAttachable, LuaBinding::AdoptResult) + + .addFunction("GibThis", &LuaAdaptersMOSRotating::GibThis); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, MovableObject) { - return AbstractTypeLuaClassDefinition(MovableObject, SceneObject) - - .property("Material", &MovableObject::GetMaterial) - .property("Mass", &MovableObject::GetMass, &MovableObject::SetMass) - .property("Pos", &MovableObject::GetPos, &MovableObject::SetPos) - .property("Vel", &MovableObject::GetVel, &MovableObject::SetVel) - .property("PrevPos", &MovableObject::GetPrevPos) - .property("PrevVel", &MovableObject::GetPrevVel) - .property("DistanceTravelled", &MovableObject::GetDistanceTravelled) - .property("AngularVel", &MovableObject::GetAngularVel, &MovableObject::SetAngularVel) - .property("Radius", &MovableObject::GetRadius) - .property("Diameter", &MovableObject::GetDiameter) - .property("Scale", &MovableObject::GetScale, &MovableObject::SetScale) - .property("EffectRotAngle", &MovableObject::GetEffectRotAngle, &MovableObject::SetEffectRotAngle) - .property("EffectAlwaysShows", &MovableObject::GetEffectAlwaysShows, &MovableObject::SetEffectAlwaysShows) - .property("EffectStartStrength", &MovableObject::GetEffectStartStrengthFloat, &MovableObject::SetEffectStartStrengthFloat) - .property("EffectStopStrength", &MovableObject::GetEffectStopStrengthFloat, &MovableObject::SetEffectStopStrengthFloat) - .property("GlobalAccScalar", &MovableObject::GetGlobalAccScalar, &MovableObject::SetGlobalAccScalar) - .property("AirResistance", &MovableObject::GetAirResistance, &MovableObject::SetAirResistance) - .property("AirThreshold", &MovableObject::GetAirThreshold, &MovableObject::SetAirThreshold) - .property("Age", &MovableObject::GetAge, &MovableObject::SetAge) - .property("Lifetime", &MovableObject::GetLifetime, &MovableObject::SetLifetime) - .property("ID", &MovableObject::GetID) - .property("UniqueID", &MovableObject::GetUniqueID) - .property("RootID", &MovableObject::GetRootID) - .property("MOIDFootprint", &MovableObject::GetMOIDFootprint) - .property("Sharpness", &MovableObject::GetSharpness, &MovableObject::SetSharpness) - .property("HasEverBeenAddedToMovableMan", &MovableObject::HasEverBeenAddedToMovableMan) - .property("AboveHUDPos", &MovableObject::GetAboveHUDPos) - .property("HitsMOs", &MovableObject::HitsMOs, &MovableObject::SetToHitMOs) - .property("GetsHitByMOs", &MovableObject::GetsHitByMOs, &MovableObject::SetToGetHitByMOs) - .property("IgnoresTeamHits", &MovableObject::IgnoresTeamHits, &MovableObject::SetIgnoresTeamHits) - .property("IgnoresWhichTeam", &MovableObject::IgnoresWhichTeam) - .property("IgnoreTerrain", &MovableObject::IgnoreTerrain, &MovableObject::SetIgnoreTerrain) - .property("IgnoresActorHits", &MovableObject::GetIgnoresActorHits, &MovableObject::SetIgnoresActorHits) - .property("ToSettle", &MovableObject::ToSettle, &MovableObject::SetToSettle) - .property("ToDelete", &MovableObject::ToDelete, &MovableObject::SetToDelete) - .property("MissionCritical", &MovableObject::IsMissionCritical, &MovableObject::SetMissionCritical) - .property("HUDVisible", &MovableObject::GetHUDVisible, &MovableObject::SetHUDVisible) - .property("PinStrength", &MovableObject::GetPinStrength, &MovableObject::SetPinStrength) - .property("RestThreshold", &MovableObject::GetRestThreshold, &MovableObject::SetRestThreshold) - .property("DamageOnCollision", &MovableObject::DamageOnCollision, &MovableObject::SetDamageOnCollision) - .property("DamageOnPenetration", &MovableObject::DamageOnPenetration, &MovableObject::SetDamageOnPenetration) - .property("WoundDamageMultiplier", &MovableObject::WoundDamageMultiplier, &MovableObject::SetWoundDamageMultiplier) - .property("HitWhatMOID", &MovableObject::HitWhatMOID) - .property("HitWhatTerrMaterial", &MovableObject::HitWhatTerrMaterial) - .property("HitWhatParticleUniqueID", &MovableObject::HitWhatParticleUniqueID) - .property("ApplyWoundDamageOnCollision", &MovableObject::GetApplyWoundDamageOnCollision, &MovableObject::SetApplyWoundDamageOnCollision) - .property("ApplyWoundBurstDamageOnCollision", &MovableObject::GetApplyWoundBurstDamageOnCollision, &MovableObject::SetApplyWoundBurstDamageOnCollision) - .property("SimUpdatesBetweenScriptedUpdates", &MovableObject::GetSimUpdatesBetweenScriptedUpdates, &MovableObject::SetSimUpdatesBetweenScriptedUpdates) - .property("PostEffectEnabled", &MovableObject::GetPostEffectEnabled, &MovableObject::SetPostEffectEnabled) - - .def("GetParent", (MOSRotating * (MovableObject::*)()) & MovableObject::GetParent) - .def("GetParent", (const MOSRotating* (MovableObject::*)() const) & MovableObject::GetParent) - .def("GetRootParent", (MovableObject * (MovableObject::*)()) & MovableObject::GetRootParent) - .def("GetRootParent", (const MovableObject* (MovableObject::*)() const) & MovableObject::GetRootParent) - .def("ReloadScripts", &MovableObject::ReloadScripts) - .def("HasScript", &LuaAdaptersMovableObject::HasScript) - .def("AddScript", &LuaAdaptersMovableObject::AddScript) - .def("ScriptEnabled", &MovableObject::ScriptEnabled) - .def("EnableScript", &LuaAdaptersMovableObject::EnableScript) - .def("DisableScript", &LuaAdaptersMovableObject::DisableScript1) - .def("DisableScript", &LuaAdaptersMovableObject::DisableScript2) - .def("EnableOrDisableAllScripts", &MovableObject::EnableOrDisableAllScripts) - .def("GetStringValue", &MovableObject::GetStringValue) - .def("GetEncodedStringValue", &MovableObject::GetEncodedStringValue) - .def("GetNumberValue", &MovableObject::GetNumberValue) - .def("GetObjectValue", &MovableObject::GetObjectValue) - .def("SetStringValue", &MovableObject::SetStringValue) - .def("SetEncodedStringValue", &MovableObject::SetEncodedStringValue) - .def("SetNumberValue", &MovableObject::SetNumberValue) - .def("SetObjectValue", &MovableObject::SetObjectValue) - .def("RemoveStringValue", &MovableObject::RemoveStringValue) - .def("RemoveNumberValue", &MovableObject::RemoveNumberValue) - .def("RemoveObjectValue", &MovableObject::RemoveObjectValue) - .def("StringValueExists", &MovableObject::StringValueExists) - .def("NumberValueExists", &MovableObject::NumberValueExists) - .def("ObjectValueExists", &MovableObject::ObjectValueExists) - .def("GetAltitude", &MovableObject::GetAltitude) - .def("GetWhichMOToNotHit", &MovableObject::GetWhichMOToNotHit) - .def("SetWhichMOToNotHit", &MovableObject::SetWhichMOToNotHit) - .def("IsSetToDelete", &MovableObject::IsSetToDelete) - .def("IsMissionCritical", &MovableObject::IsMissionCritical) - .def("IsGeneric", &MovableObject::IsGeneric) - .def("IsActor", &MovableObject::IsActor) - .def("IsDevice", &MovableObject::IsDevice) - .def("IsHeldDevice", &MovableObject::IsHeldDevice) - .def("IsThrownDevice", &MovableObject::IsThrownDevice) - .def("IsGold", &MovableObject::IsGold) - .def("IsThrownDevice", &MovableObject::IsThrownDevice) - .def("HasObject", &MovableObject::HasObject) - .def("HasObjectInGroup", &MovableObject::HasObjectInGroup) - .def("AddForce", &MovableObject::AddForce) - .def("AddAbsForce", &MovableObject::AddAbsForce) - .def("AddImpulseForce", &MovableObject::AddImpulseForce) - .def("AddAbsImpulseForce", &MovableObject::AddAbsImpulseForce) - .def("ClearForces", &MovableObject::ClearForces) - .def("ClearImpulseForces", &MovableObject::ClearImpulseForces) - .def("GetForcesCount", &MovableObject::GetForcesCount) - .def("GetForceVector", &MovableObject::GetForceVector) - .def("GetForceOffset", &MovableObject::GetForceOffset) - .def("SetForceVector", &MovableObject::SetForceVector) - .def("SetForceOffset", &MovableObject::SetForceOffset) - .def("GetImpulsesCount", &MovableObject::GetImpulsesCount) - .def("GetImpulseVector", &MovableObject::GetImpulseVector) - .def("GetImpulseOffset", &MovableObject::GetImpulseOffset) - .def("SetImpulseVector", &MovableObject::SetImpulseVector) - .def("SetImpulseOffset", &MovableObject::SetImpulseOffset) - .def("RestDetection", &MovableObject::RestDetection) - .def("NotResting", &MovableObject::NotResting) - .def("IsAtRest", &MovableObject::IsAtRest) - .def("MoveOutOfTerrain", &MovableObject::MoveOutOfTerrain) - .def("RotateOffset", &MovableObject::RotateOffset) - .def("SendMessage", &LuaAdaptersMovableObject::SendMessage1) - .def("SendMessage", &LuaAdaptersMovableObject::SendMessage2) - .def("RequestSyncedUpdate", &MovableObject::RequestSyncedUpdate) - .def("SetEffectStrength", &MovableObject::SetEffectStrength) - .def("GetScreenEffectPath", &MovableObject::GetScreenEffectPath) - .def("SetScreenEffectPath", &MovableObject::SetScreenEffectPath); + AbstractTypeLuaClassDefinition(MovableObject, SceneObject) + + .addProperty("Material", &MovableObject::GetMaterial) + .addProperty("Mass", &MovableObject::GetMass, &MovableObject::SetMass) + .addProperty("Pos", &MovableObject::GetPos, &MovableObject::SetPos) + .addProperty("Vel", &MovableObject::GetVel, &MovableObject::SetVel) + .addProperty("PrevPos", &MovableObject::GetPrevPos) + .addProperty("PrevVel", &MovableObject::GetPrevVel) + .addProperty("DistanceTravelled", &MovableObject::GetDistanceTravelled) + .addProperty("AngularVel", &MovableObject::GetAngularVel, &MovableObject::SetAngularVel) + .addProperty("Radius", &MovableObject::GetRadius) + .addProperty("Diameter", &MovableObject::GetDiameter) + .addProperty("Scale", &MovableObject::GetScale, &MovableObject::SetScale) + .addProperty("EffectRotAngle", &MovableObject::GetEffectRotAngle, &MovableObject::SetEffectRotAngle) + .addProperty("EffectAlwaysShows", &MovableObject::GetEffectAlwaysShows, &MovableObject::SetEffectAlwaysShows) + .addProperty("EffectStartStrength", &MovableObject::GetEffectStartStrengthFloat, &MovableObject::SetEffectStartStrengthFloat) + .addProperty("EffectStopStrength", &MovableObject::GetEffectStopStrengthFloat, &MovableObject::SetEffectStopStrengthFloat) + .addProperty("GlobalAccScalar", &MovableObject::GetGlobalAccScalar, &MovableObject::SetGlobalAccScalar) + .addProperty("AirResistance", &MovableObject::GetAirResistance, &MovableObject::SetAirResistance) + .addProperty("AirThreshold", &MovableObject::GetAirThreshold, &MovableObject::SetAirThreshold) + .addProperty("Age", &MovableObject::GetAge, &MovableObject::SetAge) + .addProperty("Lifetime", &MovableObject::GetLifetime, &MovableObject::SetLifetime) + .addProperty("ID", &MovableObject::GetID) + .addProperty("UniqueID", &MovableObject::GetUniqueID) + .addProperty("RootID", &MovableObject::GetRootID) + .addProperty("MOIDFootprint", &MovableObject::GetMOIDFootprint) + .addProperty("Sharpness", &MovableObject::GetSharpness, &MovableObject::SetSharpness) + .addProperty("HasEverBeenAddedToMovableMan", &MovableObject::HasEverBeenAddedToMovableMan) + .addProperty("AboveHUDPos", &MovableObject::GetAboveHUDPos) + .addProperty("HitsMOs", &MovableObject::HitsMOs, &MovableObject::SetToHitMOs) + .addProperty("GetsHitByMOs", &MovableObject::GetsHitByMOs, &MovableObject::SetToGetHitByMOs) + .addProperty("IgnoresTeamHits", &MovableObject::IgnoresTeamHits, &MovableObject::SetIgnoresTeamHits) + .addProperty("IgnoresWhichTeam", &MovableObject::IgnoresWhichTeam) + .addProperty("IgnoreTerrain", &MovableObject::IgnoreTerrain, &MovableObject::SetIgnoreTerrain) + .addProperty("IgnoresActorHits", &MovableObject::GetIgnoresActorHits, &MovableObject::SetIgnoresActorHits) + .addProperty("ToSettle", &MovableObject::ToSettle, &MovableObject::SetToSettle) + .addProperty("ToDelete", &MovableObject::ToDelete, &MovableObject::SetToDelete) + .addProperty("MissionCritical", &MovableObject::IsMissionCritical, &MovableObject::SetMissionCritical) + .addProperty("HUDVisible", &MovableObject::GetHUDVisible, &MovableObject::SetHUDVisible) + .addProperty("PinStrength", &MovableObject::GetPinStrength, &MovableObject::SetPinStrength) + .addProperty("RestThreshold", &MovableObject::GetRestThreshold, &MovableObject::SetRestThreshold) + .addProperty("DamageOnCollision", &MovableObject::DamageOnCollision, &MovableObject::SetDamageOnCollision) + .addProperty("DamageOnPenetration", &MovableObject::DamageOnPenetration, &MovableObject::SetDamageOnPenetration) + .addProperty("WoundDamageMultiplier", &MovableObject::WoundDamageMultiplier, &MovableObject::SetWoundDamageMultiplier) + .addProperty("HitWhatMOID", &MovableObject::HitWhatMOID) + .addProperty("HitWhatTerrMaterial", &MovableObject::HitWhatTerrMaterial) + .addProperty("HitWhatParticleUniqueID", &MovableObject::HitWhatParticleUniqueID) + .addProperty("ApplyWoundDamageOnCollision", &MovableObject::GetApplyWoundDamageOnCollision, &MovableObject::SetApplyWoundDamageOnCollision) + .addProperty("ApplyWoundBurstDamageOnCollision", &MovableObject::GetApplyWoundBurstDamageOnCollision, &MovableObject::SetApplyWoundBurstDamageOnCollision) + .addProperty("SimUpdatesBetweenScriptedUpdates", &MovableObject::GetSimUpdatesBetweenScriptedUpdates, &MovableObject::SetSimUpdatesBetweenScriptedUpdates) + .addProperty("PostEffectEnabled", &MovableObject::GetPostEffectEnabled, &MovableObject::SetPostEffectEnabled) + + .addFunction("GetParent", (MOSRotating * (MovableObject::*)()) & MovableObject::GetParent) + .addFunction("GetParent", (const MOSRotating* (MovableObject::*)() const) & MovableObject::GetParent) + .addFunction("GetRootParent", (MovableObject * (MovableObject::*)()) & MovableObject::GetRootParent) + .addFunction("GetRootParent", (const MovableObject* (MovableObject::*)() const) & MovableObject::GetRootParent) + .addFunction("ReloadScripts", &MovableObject::ReloadScripts) + .addFunction("HasScript", &LuaAdaptersMovableObject::HasScript) + .addFunction("AddScript", &LuaAdaptersMovableObject::AddScript) + .addFunction("ScriptEnabled", &MovableObject::ScriptEnabled) + .addFunction("EnableScript", &LuaAdaptersMovableObject::EnableScript) + .addFunction("DisableScript", &LuaAdaptersMovableObject::DisableScript1) + .addFunction("DisableScript", &LuaAdaptersMovableObject::DisableScript2) + .addFunction("EnableOrDisableAllScripts", &MovableObject::EnableOrDisableAllScripts) + .addFunction("GetStringValue", &MovableObject::GetStringValue) + .addFunction("GetEncodedStringValue", &MovableObject::GetEncodedStringValue) + .addFunction("GetNumberValue", &MovableObject::GetNumberValue) + .addFunction("GetObjectValue", &MovableObject::GetObjectValue) + .addFunction("SetStringValue", &MovableObject::SetStringValue) + .addFunction("SetEncodedStringValue", &MovableObject::SetEncodedStringValue) + .addFunction("SetNumberValue", &MovableObject::SetNumberValue) + .addFunction("SetObjectValue", &MovableObject::SetObjectValue) + .addFunction("RemoveStringValue", &MovableObject::RemoveStringValue) + .addFunction("RemoveNumberValue", &MovableObject::RemoveNumberValue) + .addFunction("RemoveObjectValue", &MovableObject::RemoveObjectValue) + .addFunction("StringValueExists", &MovableObject::StringValueExists) + .addFunction("NumberValueExists", &MovableObject::NumberValueExists) + .addFunction("ObjectValueExists", &MovableObject::ObjectValueExists) + .addFunction("GetAltitude", &MovableObject::GetAltitude) + .addFunction("GetWhichMOToNotHit", &MovableObject::GetWhichMOToNotHit) + .addFunction("SetWhichMOToNotHit", &MovableObject::SetWhichMOToNotHit) + .addFunction("IsSetToDelete", &MovableObject::IsSetToDelete) + .addFunction("IsMissionCritical", &MovableObject::IsMissionCritical) + .addFunction("IsGeneric", &MovableObject::IsGeneric) + .addFunction("IsActor", &MovableObject::IsActor) + .addFunction("IsDevice", &MovableObject::IsDevice) + .addFunction("IsHeldDevice", &MovableObject::IsHeldDevice) + .addFunction("IsThrownDevice", &MovableObject::IsThrownDevice) + .addFunction("IsGold", &MovableObject::IsGold) + .addFunction("IsThrownDevice", &MovableObject::IsThrownDevice) + .addFunction("HasObject", &MovableObject::HasObject) + .addFunction("HasObjectInGroup", &MovableObject::HasObjectInGroup) + .addFunction("AddForce", &MovableObject::AddForce) + .addFunction("AddAbsForce", &MovableObject::AddAbsForce) + .addFunction("AddImpulseForce", &MovableObject::AddImpulseForce) + .addFunction("AddAbsImpulseForce", &MovableObject::AddAbsImpulseForce) + .addFunction("ClearForces", &MovableObject::ClearForces) + .addFunction("ClearImpulseForces", &MovableObject::ClearImpulseForces) + .addFunction("GetForcesCount", &MovableObject::GetForcesCount) + .addFunction("GetForceVector", &MovableObject::GetForceVector) + .addFunction("GetForceOffset", &MovableObject::GetForceOffset) + .addFunction("SetForceVector", &MovableObject::SetForceVector) + .addFunction("SetForceOffset", &MovableObject::SetForceOffset) + .addFunction("GetImpulsesCount", &MovableObject::GetImpulsesCount) + .addFunction("GetImpulseVector", &MovableObject::GetImpulseVector) + .addFunction("GetImpulseOffset", &MovableObject::GetImpulseOffset) + .addFunction("SetImpulseVector", &MovableObject::SetImpulseVector) + .addFunction("SetImpulseOffset", &MovableObject::SetImpulseOffset) + .addFunction("RestDetection", &MovableObject::RestDetection) + .addFunction("NotResting", &MovableObject::NotResting) + .addFunction("IsAtRest", &MovableObject::IsAtRest) + .addFunction("MoveOutOfTerrain", &MovableObject::MoveOutOfTerrain) + .addFunction("RotateOffset", &MovableObject::RotateOffset) + .addFunction("SendMessage", &LuaAdaptersMovableObject::SendMessage1) + .addFunction("SendMessage", &LuaAdaptersMovableObject::SendMessage2) + .addFunction("RequestSyncedUpdate", &MovableObject::RequestSyncedUpdate) + .addFunction("SetEffectStrength", &MovableObject::SetEffectStrength) + .addFunction("GetScreenEffectPath", &MovableObject::GetScreenEffectPath) + .addFunction("SetScreenEffectPath", &MovableObject::SetScreenEffectPath); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, PEmitter) { - return ConcreteTypeLuaClassDefinition(PEmitter, MOSParticle) - - .property("BurstScale", &PEmitter::GetBurstScale, &PEmitter::SetBurstScale) - .property("PlayBurstSound", &PEmitter::GetPlayBurstSound, &PEmitter::SetPlayBurstSound) - .property("EmitAngle", &PEmitter::GetEmitAngle, &PEmitter::SetEmitAngle) - .property("GetThrottle", &PEmitter::GetThrottle, &PEmitter::SetThrottle) - .property("Throttle", &PEmitter::GetThrottle, &PEmitter::SetThrottle) - .property("ThrottleFactor", &PEmitter::GetThrottleFactor) - .property("BurstSpacing", &PEmitter::GetBurstSpacing, &PEmitter::SetBurstSpacing) - .property("EmitCountLimit", &PEmitter::GetEmitCountLimit, &PEmitter::SetEmitCountLimit) - .property("FlashScale", &PEmitter::GetFlashScale, &PEmitter::SetFlashScale) - - .def_readonly("Emissions", &PEmitter::m_EmissionList, luabind::return_stl_iterator) - - .def("IsEmitting", &PEmitter::IsEmitting) - .def("WasEmitting", &PEmitter::WasEmitting) - .def("EnableEmission", &PEmitter::EnableEmission) - .def("GetEmitVector", &PEmitter::GetEmitVector) - .def("GetRecoilVector", &PEmitter::GetRecoilVector) - .def("EstimateImpulse", &PEmitter::EstimateImpulse) - .def("TriggerBurst", &PEmitter::TriggerBurst) - .def("IsSetToBurst", &PEmitter::IsSetToBurst) - .def("CanTriggerBurst", &PEmitter::CanTriggerBurst) - .def("JustStartedEmitting", &PEmitter::JustStartedEmitting); + ConcreteTypeLuaClassDefinition(PEmitter, MOSParticle) + + .addProperty("BurstScale", &PEmitter::GetBurstScale, &PEmitter::SetBurstScale) + .addProperty("PlayBurstSound", &PEmitter::GetPlayBurstSound, &PEmitter::SetPlayBurstSound) + .addProperty("EmitAngle", &PEmitter::GetEmitAngle, &PEmitter::SetEmitAngle) + .addProperty("GetThrottle", &PEmitter::GetThrottle, &PEmitter::SetThrottle) + .addProperty("Throttle", &PEmitter::GetThrottle, &PEmitter::SetThrottle) + .addProperty("ThrottleFactor", &PEmitter::GetThrottleFactor) + .addProperty("BurstSpacing", &PEmitter::GetBurstSpacing, &PEmitter::SetBurstSpacing) + .addProperty("EmitCountLimit", &PEmitter::GetEmitCountLimit, &PEmitter::SetEmitCountLimit) + .addProperty("FlashScale", &PEmitter::GetFlashScale, &PEmitter::SetFlashScale) + + .addProperty("Emissions", &PEmitter::m_EmissionList, LuaBinding::ReturnStlIterator) + + .addFunction("IsEmitting", &PEmitter::IsEmitting) + .addFunction("WasEmitting", &PEmitter::WasEmitting) + .addFunction("EnableEmission", &PEmitter::EnableEmission) + .addFunction("GetEmitVector", &PEmitter::GetEmitVector) + .addFunction("GetRecoilVector", &PEmitter::GetRecoilVector) + .addFunction("EstimateImpulse", &PEmitter::EstimateImpulse) + .addFunction("TriggerBurst", &PEmitter::TriggerBurst) + .addFunction("IsSetToBurst", &PEmitter::IsSetToBurst) + .addFunction("CanTriggerBurst", &PEmitter::CanTriggerBurst) + .addFunction("JustStartedEmitting", &PEmitter::JustStartedEmitting); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, PieSlice) { - return ConcreteTypeLuaClassDefinition(PieSlice, Entity) - - .property("Type", &LuaAdaptersPieSlice::GetType, &PieSlice::SetType) - .property("Direction", &PieSlice::GetDirection, &PieSlice::SetDirection) - .property("CanBeMiddleSlice", &PieSlice::GetCanBeMiddleSlice, &PieSlice::SetCanBeMiddleSlice) - .property("OriginalSource", &PieSlice::GetOriginalSource) - .property("Enabled", &PieSlice::IsEnabled, &PieSlice::SetEnabled) - - .property("ScriptPath", &PieSlice::GetScriptPath, &PieSlice::SetScriptPath) - .property("FunctionName", &PieSlice::GetFunctionName, &PieSlice::SetFunctionName) - .property("SubPieMenu", &PieSlice::GetSubPieMenu, &PieSlice::SetSubPieMenu) - - .property("DrawFlippedToMatchAbsoluteAngle", &PieSlice::GetDrawFlippedToMatchAbsoluteAngle, &PieSlice::SetDrawFlippedToMatchAbsoluteAngle) - - .def("ReloadScripts", &PieSlice::ReloadScripts) - - .enum_("SliceType")[luabind::value("NoType", static_cast(PieSliceType::NoType)), - luabind::value("Pickup", static_cast(PieSliceType::Pickup)), - luabind::value("Drop", static_cast(PieSliceType::Drop)), - luabind::value("NextItem", static_cast(PieSliceType::NextItem)), - luabind::value("PreviousItem", static_cast(PieSliceType::PreviousItem)), - luabind::value("Reload", static_cast(PieSliceType::Reload)), - luabind::value("BuyMenu", static_cast(PieSliceType::BuyMenu)), - luabind::value("Stats", static_cast(PieSliceType::Stats)), - luabind::value("Map", static_cast(PieSliceType::Map)), - luabind::value("FormSquad", static_cast(PieSliceType::FormSquad)), - luabind::value("Ceasefire", static_cast(PieSliceType::Ceasefire)), - luabind::value("Sentry", static_cast(PieSliceType::Sentry)), - luabind::value("Patrol", static_cast(PieSliceType::Patrol)), - luabind::value("BrainHunt", static_cast(PieSliceType::BrainHunt)), - luabind::value("GoldDig", static_cast(PieSliceType::GoldDig)), - luabind::value("GoTo", static_cast(PieSliceType::GoTo)), - luabind::value("Return", static_cast(PieSliceType::Return)), - luabind::value("Stay", static_cast(PieSliceType::Stay)), - luabind::value("Deliver", static_cast(PieSliceType::Deliver)), - luabind::value("Scuttle", static_cast(PieSliceType::Scuttle)), - luabind::value("Done", static_cast(PieSliceType::EditorDone)), - luabind::value("Load", static_cast(PieSliceType::EditorLoad)), - luabind::value("Save", static_cast(PieSliceType::EditorSave)), - luabind::value("New", static_cast(PieSliceType::EditorNew)), - luabind::value("Pick", static_cast(PieSliceType::EditorPick)), - luabind::value("Move", static_cast(PieSliceType::EditorMove)), - luabind::value("Remove", static_cast(PieSliceType::EditorRemove)), - luabind::value("InFront", static_cast(PieSliceType::EditorInFront)), - luabind::value("Behind", static_cast(PieSliceType::EditorBehind)), - luabind::value("ZoomIn", static_cast(PieSliceType::EditorZoomIn)), - luabind::value("ZoomOut", static_cast(PieSliceType::EditorZoomOut)), - luabind::value("Team1", static_cast(PieSliceType::EditorTeam1)), - luabind::value("Team2", static_cast(PieSliceType::EditorTeam2)), - luabind::value("Team3", static_cast(PieSliceType::EditorTeam3)), - luabind::value("Team4", static_cast(PieSliceType::EditorTeam4))]; + ConcreteTypeLuaClassDefinition(PieSlice, Entity) + + .addProperty("Type", &LuaAdaptersPieSlice::GetType, &PieSlice::SetType) + .addProperty("Direction", &PieSlice::GetDirection, &PieSlice::SetDirection) + .addProperty("CanBeMiddleSlice", &PieSlice::GetCanBeMiddleSlice, &PieSlice::SetCanBeMiddleSlice) + .addProperty("OriginalSource", &PieSlice::GetOriginalSource) + .addProperty("Enabled", &PieSlice::IsEnabled, &PieSlice::SetEnabled) + + .addProperty("ScriptPath", &PieSlice::GetScriptPath, &PieSlice::SetScriptPath) + .addProperty("FunctionName", &PieSlice::GetFunctionName, &PieSlice::SetFunctionName) + .addProperty("SubPieMenu", &PieSlice::GetSubPieMenu, &PieSlice::SetSubPieMenu) + + .addProperty("DrawFlippedToMatchAbsoluteAngle", &PieSlice::GetDrawFlippedToMatchAbsoluteAngle, &PieSlice::SetDrawFlippedToMatchAbsoluteAngle) + + .addFunction("ReloadScripts", &PieSlice::ReloadScripts) + + .addEnum({{"NoType", static_cast(PieSliceType::NoType)}, + {"Pickup", static_cast(PieSliceType::Pickup)}, + {"Drop", static_cast(PieSliceType::Drop)}, + {"NextItem", static_cast(PieSliceType::NextItem)}, + {"PreviousItem", static_cast(PieSliceType::PreviousItem)}, + {"Reload", static_cast(PieSliceType::Reload)}, + {"BuyMenu", static_cast(PieSliceType::BuyMenu)}, + {"Stats", static_cast(PieSliceType::Stats)}, + {"Map", static_cast(PieSliceType::Map)}, + {"FormSquad", static_cast(PieSliceType::FormSquad)}, + {"Ceasefire", static_cast(PieSliceType::Ceasefire)}, + {"Sentry", static_cast(PieSliceType::Sentry)}, + {"Patrol", static_cast(PieSliceType::Patrol)}, + {"BrainHunt", static_cast(PieSliceType::BrainHunt)}, + {"GoldDig", static_cast(PieSliceType::GoldDig)}, + {"GoTo", static_cast(PieSliceType::GoTo)}, + {"Return", static_cast(PieSliceType::Return)}, + {"Stay", static_cast(PieSliceType::Stay)}, + {"Deliver", static_cast(PieSliceType::Deliver)}, + {"Scuttle", static_cast(PieSliceType::Scuttle)}, + {"Done", static_cast(PieSliceType::EditorDone)}, + {"Load", static_cast(PieSliceType::EditorLoad)}, + {"Save", static_cast(PieSliceType::EditorSave)}, + {"New", static_cast(PieSliceType::EditorNew)}, + {"Pick", static_cast(PieSliceType::EditorPick)}, + {"Move", static_cast(PieSliceType::EditorMove)}, + {"Remove", static_cast(PieSliceType::EditorRemove)}, + {"InFront", static_cast(PieSliceType::EditorInFront)}, + {"Behind", static_cast(PieSliceType::EditorBehind)}, + {"ZoomIn", static_cast(PieSliceType::EditorZoomIn)}, + {"ZoomOut", static_cast(PieSliceType::EditorZoomOut)}, + {"Team1", static_cast(PieSliceType::EditorTeam1)}, + {"Team2", static_cast(PieSliceType::EditorTeam2)}, + {"Team3", static_cast(PieSliceType::EditorTeam3)}, + {"Team4", static_cast(PieSliceType::EditorTeam4)}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, PieMenu) { - return ConcreteTypeLuaClassDefinition(PieMenu, Entity) - - .property("Owner", &PieMenu::GetOwner) - .property("Controller", &PieMenu::GetController) - .property("AffectedObject", &PieMenu::GetAffectedObject) - .property("Pos", &PieMenu::GetPos) - .property("RotAngle", &PieMenu::GetRotAngle, &PieMenu::SetRotAngle) - .property("FullInnerRadius", &PieMenu::GetFullInnerRadius, &PieMenu::SetFullInnerRadius) - - .property("PieSlices", &PieMenu::GetPieSlices, luabind::return_stl_iterator) - - .def("IsSubPieMenu", &PieMenu::IsSubPieMenu) - - .def("IsEnabled", &PieMenu::IsEnabled) - .def("IsEnabling", &PieMenu::IsEnabling) - .def("IsDisabling", &PieMenu::IsDisabling) - .def("IsEnablingOrDisabling", &PieMenu::IsEnablingOrDisabling) - .def("IsVisible", &PieMenu::IsVisible) - .def("HasSubPieMenuOpen", &PieMenu::HasSubPieMenuOpen) - - .def("SetAnimationModeToNormal", &PieMenu::SetAnimationModeToNormal) - .def("DoDisableAnimation", &PieMenu::DoDisableAnimation) - .def("Wobble", &PieMenu::Wobble) - .def("FreezeAtRadius", &PieMenu::FreezeAtRadius) - - .def("GetPieCommand", &LuaAdaptersPieMenu::GetPieCommand) - .def("GetFirstPieSliceByPresetName", &PieMenu::GetFirstPieSliceByPresetName) - .def("GetFirstPieSliceByType", &PieMenu::GetFirstPieSliceByType) - .def("AddPieSlice", &PieMenu::AddPieSlice, luabind::adopt(_2)) - .def("AddPieSlice", &LuaAdaptersPieMenu::AddPieSlice, luabind::adopt(_2)) - .def("AddPieSliceIfPresetNameIsUnique", &PieMenu::AddPieSliceIfPresetNameIsUnique) - .def("AddPieSliceIfPresetNameIsUnique", &LuaAdaptersPieMenu::AddPieSliceIfPresetNameIsUnique1) - .def("AddPieSliceIfPresetNameIsUnique", &LuaAdaptersPieMenu::AddPieSliceIfPresetNameIsUnique2) - .def("RemovePieSlice", &PieMenu::RemovePieSlice, luabind::adopt(luabind::return_value)) - .def("RemovePieSlicesByPresetName", &PieMenu::RemovePieSlicesByPresetName) - .def("RemovePieSlicesByType", &PieMenu::RemovePieSlicesByType) - .def("RemovePieSlicesByOriginalSource", &PieMenu::RemovePieSlicesByOriginalSource) - .def("ReplacePieSlice", &PieMenu::ReplacePieSlice, luabind::adopt(luabind::result) + luabind::adopt(_3)); + ConcreteTypeLuaClassDefinition(PieMenu, Entity) + + .addProperty("Owner", &PieMenu::GetOwner) + .addProperty("Controller", &PieMenu::GetController) + .addProperty("AffectedObject", &PieMenu::GetAffectedObject) + .addProperty("Pos", &PieMenu::GetPos) + .addProperty("RotAngle", &PieMenu::GetRotAngle, &PieMenu::SetRotAngle) + .addProperty("FullInnerRadius", &PieMenu::GetFullInnerRadius, &PieMenu::SetFullInnerRadius) + + .addProperty("PieSlices", &PieMenu::GetPieSlices, LuaBinding::ReturnStlIterator) + + .addFunction("IsSubPieMenu", &PieMenu::IsSubPieMenu) + + .addFunction("IsEnabled", &PieMenu::IsEnabled) + .addFunction("IsEnabling", &PieMenu::IsEnabling) + .addFunction("IsDisabling", &PieMenu::IsDisabling) + .addFunction("IsEnablingOrDisabling", &PieMenu::IsEnablingOrDisabling) + .addFunction("IsVisible", &PieMenu::IsVisible) + .addFunction("HasSubPieMenuOpen", &PieMenu::HasSubPieMenuOpen) + + .addFunction("SetAnimationModeToNormal", &PieMenu::SetAnimationModeToNormal) + .addFunction("DoDisableAnimation", &PieMenu::DoDisableAnimation) + .addFunction("Wobble", &PieMenu::Wobble) + .addFunction("FreezeAtRadius", &PieMenu::FreezeAtRadius) + + .addFunction("GetPieCommand", &LuaAdaptersPieMenu::GetPieCommand) + .addFunction("GetFirstPieSliceByPresetName", &PieMenu::GetFirstPieSliceByPresetName) + .addFunction("GetFirstPieSliceByType", &PieMenu::GetFirstPieSliceByType) + .addFunction("AddPieSlice", &PieMenu::AddPieSlice, LuaBinding::AdoptArg<2>) + .addFunction("AddPieSlice", &LuaAdaptersPieMenu::AddPieSlice, LuaBinding::AdoptArg<2>) + .addFunction("AddPieSliceIfPresetNameIsUnique", &PieMenu::AddPieSliceIfPresetNameIsUnique) + .addFunction("AddPieSliceIfPresetNameIsUnique", &LuaAdaptersPieMenu::AddPieSliceIfPresetNameIsUnique1) + .addFunction("AddPieSliceIfPresetNameIsUnique", &LuaAdaptersPieMenu::AddPieSliceIfPresetNameIsUnique2) + .addFunction("RemovePieSlice", &PieMenu::RemovePieSlice, LuaBinding::AdoptResult) + .addFunction("RemovePieSlicesByPresetName", &PieMenu::RemovePieSlicesByPresetName) + .addFunction("RemovePieSlicesByType", &PieMenu::RemovePieSlicesByType) + .addFunction("RemovePieSlicesByOriginalSource", &PieMenu::RemovePieSlicesByOriginalSource) + .addFunction("ReplacePieSlice", &PieMenu::ReplacePieSlice, LuaBinding::AdoptResult, LuaBinding::AdoptArg<3>); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Round) { - return ConcreteTypeLuaClassDefinition(Round, Entity) - - .property("NextParticle", &Round::GetNextParticle) - .property("Shell", &Round::GetShell) - .property("FireVel", &Round::GetFireVel) - .property("InheritsFirerVelocity", &Round::GetInheritsFirerVelocity) - .property("ShellVel", &Round::GetShellVel) - .property("Separation", &Round::GetSeparation) - .property("ParticleCount", &Round::ParticleCount) - .property("AILifeTime", &Round::GetAILifeTime) - .property("AIFireVel", &Round::GetAIFireVel) - .property("IsEmpty", &Round::IsEmpty); + ConcreteTypeLuaClassDefinition(Round, Entity) + + .addProperty("NextParticle", &Round::GetNextParticle) + .addProperty("Shell", &Round::GetShell) + .addProperty("FireVel", &Round::GetFireVel) + .addProperty("InheritsFirerVelocity", &Round::GetInheritsFirerVelocity) + .addProperty("ShellVel", &Round::GetShellVel) + .addProperty("Separation", &Round::GetSeparation) + .addProperty("ParticleCount", &Round::ParticleCount) + .addProperty("AILifeTime", &Round::GetAILifeTime) + .addProperty("AIFireVel", &Round::GetAIFireVel) + .addProperty("IsEmpty", &Round::IsEmpty); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Scene) { - return ConcreteTypeLuaClassDefinition(Scene, Entity) - - .property("Location", &Scene::GetLocation, &Scene::SetLocation) - //.property("Terrain", &Scene::GetTerrain) - .property("Dimensions", &Scene::GetDimensions) - .property("Width", &Scene::GetWidth) - .property("Height", &Scene::GetHeight) - .property("WrapsX", &Scene::WrapsX) - .property("WrapsY", &Scene::WrapsY) - .property("TeamOwnership", &Scene::GetTeamOwnership, &Scene::SetTeamOwnership) - .property("GlobalAcc", &Scene::GetGlobalAcc, &Scene::SetGlobalAcc) - .property("ScenePathSize", &Scene::GetScenePathSize) - - .def_readonly("Deployments", &Scene::m_Deployments, luabind::return_stl_iterator) - .def_readonly("Areas", &Scene::m_AreaList, luabind::return_stl_iterator) - .def_readonly("BackgroundLayers", &Scene::m_BackLayerList, luabind::return_stl_iterator) - - .def("GetScenePath", &Scene::GetScenePath, luabind::return_stl_iterator) - .def("GetBuildBudget", &Scene::GetBuildBudget) - .def("SetBuildBudget", &Scene::SetBuildBudget) - .def("IsScanScheduled", &Scene::IsScanScheduled) - .def("SetScheduledScan", &Scene::SetScheduledScan) - .def("ClearPlacedObjectSet", &Scene::ClearPlacedObjectSet) - .def("PlaceResidentBrain", &Scene::PlaceResidentBrain) - .def("PlaceResidentBrains", &Scene::PlaceResidentBrains) - .def("RetrieveResidentBrains", &Scene::RetrieveResidentBrains) - .def("GetResidentBrain", &Scene::GetResidentBrain) - .def("SetResidentBrain", &Scene::SetResidentBrain) - .def("SetArea", &Scene::SetArea) - .def("HasArea", &Scene::HasArea) - .def("GetArea", &Scene::GetArea) - .def("WithinArea", &Scene::WithinArea) - .def("AddNavigableArea", &Scene::AddNavigableArea) - .def("ClearNavigableAreas", &Scene::ClearNavigableAreas) - .def("ResetPathFinding", &Scene::ResetPathFinding) - .def("UpdatePathFinding", &Scene::UpdatePathFinding) - .def("PathFindingUpdated", &Scene::PathFindingUpdated) - .def("CalculatePath", &LuaAdaptersScene::CalculatePath) - .def("CalculatePath", &LuaAdaptersScene::CalculatePath1) - .def("CalculatePathAsync", &LuaAdaptersScene::CalculatePathAsync) - .def("CalculatePathAsync", &LuaAdaptersScene::CalculatePathAsync1) - - .enum_("PlacedObjectSets")[luabind::value("PLACEONLOAD", Scene::PlacedObjectSets::PLACEONLOAD), - luabind::value("BLUEPRINT", Scene::PlacedObjectSets::BLUEPRINT), - luabind::value("AIPLAN", Scene::PlacedObjectSets::AIPLAN), - luabind::value("PLACEDSETSCOUNT", Scene::PlacedObjectSets::PLACEDSETSCOUNT)]; + ConcreteTypeLuaClassDefinition(Scene, Entity) + + .addProperty("Location", &Scene::GetLocation, &Scene::SetLocation) + //.addProperty("Terrain", &Scene::GetTerrain) + .addProperty("Dimensions", &Scene::GetDimensions) + .addProperty("Width", &Scene::GetWidth) + .addProperty("Height", &Scene::GetHeight) + .addProperty("WrapsX", &Scene::WrapsX) + .addProperty("WrapsY", &Scene::WrapsY) + .addProperty("TeamOwnership", &Scene::GetTeamOwnership, &Scene::SetTeamOwnership) + .addProperty("GlobalAcc", &Scene::GetGlobalAcc, &Scene::SetGlobalAcc) + .addProperty("ScenePathSize", &Scene::GetScenePathSize) + + .addProperty("Deployments", &Scene::m_Deployments, LuaBinding::ReturnStlIterator) + .addProperty("Areas", &Scene::m_AreaList, LuaBinding::ReturnStlIterator) + .addProperty("BackgroundLayers", &Scene::m_BackLayerList, LuaBinding::ReturnStlIterator) + + .addFunction("GetScenePath", &Scene::GetScenePath, LuaBinding::ReturnStlIterator) + .addFunction("GetBuildBudget", &Scene::GetBuildBudget) + .addFunction("SetBuildBudget", &Scene::SetBuildBudget) + .addFunction("IsScanScheduled", &Scene::IsScanScheduled) + .addFunction("SetScheduledScan", &Scene::SetScheduledScan) + .addFunction("ClearPlacedObjectSet", &Scene::ClearPlacedObjectSet) + .addFunction("PlaceResidentBrain", &Scene::PlaceResidentBrain) + .addFunction("PlaceResidentBrains", &Scene::PlaceResidentBrains) + .addFunction("RetrieveResidentBrains", &Scene::RetrieveResidentBrains) + .addFunction("GetResidentBrain", &Scene::GetResidentBrain) + .addFunction("SetResidentBrain", &Scene::SetResidentBrain) + .addFunction("SetArea", &Scene::SetArea) + .addFunction("HasArea", &Scene::HasArea) + .addFunction("GetArea", &Scene::GetArea) + .addFunction("WithinArea", &Scene::WithinArea) + .addFunction("AddNavigableArea", &Scene::AddNavigableArea) + .addFunction("ClearNavigableAreas", &Scene::ClearNavigableAreas) + .addFunction("ResetPathFinding", &Scene::ResetPathFinding) + .addFunction("UpdatePathFinding", &Scene::UpdatePathFinding) + .addFunction("PathFindingUpdated", &Scene::PathFindingUpdated) + .addFunction("CalculatePath", &LuaAdaptersScene::CalculatePath) + .addFunction("CalculatePath", &LuaAdaptersScene::CalculatePath1) + .addFunction("CalculatePathAsync", &LuaAdaptersScene::CalculatePathAsync) + .addFunction("CalculatePathAsync", &LuaAdaptersScene::CalculatePathAsync1) + + .addEnum({{"PLACEONLOAD", Scene::PlacedObjectSets::PLACEONLOAD}, + {"BLUEPRINT", Scene::PlacedObjectSets::BLUEPRINT}, + {"AIPLAN", Scene::PlacedObjectSets::AIPLAN}, + {"PLACEDSETSCOUNT", Scene::PlacedObjectSets::PLACEDSETSCOUNT}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, SceneArea) { - return luabind::class_("Area") - - .def(luabind::constructor<>()) - .def(luabind::constructor()) - .def(luabind::constructor()) - - .property("ClassName", &Scene::Area::GetClassName) - .property("Name", &Scene::Area::GetName) - .property("FirstBox", &Scene::Area::GetFirstBox) - .property("Center", &Scene::Area::GetCenterPoint) - .property("RandomPoint", &Scene::Area::GetRandomPoint) - - .def_readonly("Boxes", &Scene::Area::m_BoxList, luabind::return_stl_iterator) - - .def("Reset", &Scene::Area::Reset) - .def("AddBox", &Scene::Area::AddBox) - .def("RemoveBox", &Scene::Area::RemoveBox) - .def("HasNoArea", &Scene::Area::HasNoArea) - .def("IsInside", &Scene::Area::IsInside) - .def("IsInsideX", &Scene::Area::IsInsideX) - .def("IsInsideY", &Scene::Area::IsInsideY) - .def("GetBoxInside", &Scene::Area::GetBoxInside) - .def("RemoveBoxInside", &Scene::Area::RemoveBoxInside) - .def("GetCenterPoint", &Scene::Area::GetCenterPoint) - .def("GetRandomPoint", &Scene::Area::GetRandomPoint); + registry.Class("Area") + + .addConstructor<>() + .addConstructor() + .addConstructor() + + .addProperty("ClassName", &Scene::Area::GetClassName) + .addProperty("Name", &Scene::Area::GetName) + .addProperty("FirstBox", &Scene::Area::GetFirstBox) + .addProperty("Center", &Scene::Area::GetCenterPoint) + .addProperty("RandomPoint", &Scene::Area::GetRandomPoint) + + .addProperty("Boxes", &Scene::Area::m_BoxList, LuaBinding::ReturnStlIterator) + + .addFunction("Reset", &Scene::Area::Reset) + .addFunction("AddBox", &Scene::Area::AddBox) + .addFunction("RemoveBox", &Scene::Area::RemoveBox) + .addFunction("HasNoArea", &Scene::Area::HasNoArea) + .addFunction("IsInside", &Scene::Area::IsInside) + .addFunction("IsInsideX", &Scene::Area::IsInsideX) + .addFunction("IsInsideY", &Scene::Area::IsInsideY) + .addFunction("GetBoxInside", &Scene::Area::GetBoxInside) + .addFunction("RemoveBoxInside", &Scene::Area::RemoveBoxInside) + .addFunction("GetCenterPoint", &Scene::Area::GetCenterPoint) + .addFunction("GetRandomPoint", &Scene::Area::GetRandomPoint); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, StaticSceneLayer) { - return luabind::class_("StaticSceneLayer"); + registry.Class("StaticSceneLayer"); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, SceneObject) { - return AbstractTypeLuaClassDefinition(SceneObject, Entity) - - .property("Pos", &SceneObject::GetPos, &SceneObject::SetPos) - .property("HFlipped", &SceneObject::IsHFlipped, &SceneObject::SetHFlipped) - .property("RotAngle", &SceneObject::GetRotAngle, &SceneObject::SetRotAngle) - .property("Team", &SceneObject::GetTeam, &SceneObject::SetTeam) - .property("PlacedByPlayer", &SceneObject::GetPlacedByPlayer, &SceneObject::SetPlacedByPlayer) - .property("Buyable", &SceneObject::IsBuyable) - - .property("BuyableMode", &LuaAdaptersSceneObject::GetBuyableMode) - - .def("IsOnScenePoint", &SceneObject::IsOnScenePoint) - .def("GetGoldValue", &SceneObject::GetGoldValueOld) - .def("GetGoldValue", &SceneObject::GetGoldValue) - .def("SetGoldValue", &SceneObject::SetGoldValue) - .def("GetGoldValueString", &SceneObject::GetGoldValueString) - - .def("GetTotalValue", &SceneObject::GetTotalValue) - .def("GetTotalValue", &LuaAdaptersSceneObject::GetTotalValue) - - .enum_("BuyableMode")[luabind::value("NORESTRICTIONS", static_cast(SceneObject::BuyableMode::NoRestrictions)), - luabind::value("BUYMENUONLY", static_cast(SceneObject::BuyableMode::BuyMenuOnly)), - luabind::value("OBJECTPICKERONLY", static_cast(SceneObject::BuyableMode::ObjectPickerOnly)), - luabind::value("SCRIPTONLY", static_cast(SceneObject::BuyableMode::ScriptOnly))]; + AbstractTypeLuaClassDefinition(SceneObject, Entity) + + .addProperty("Pos", &SceneObject::GetPos, &SceneObject::SetPos) + .addProperty("HFlipped", &SceneObject::IsHFlipped, &SceneObject::SetHFlipped) + .addProperty("RotAngle", &SceneObject::GetRotAngle, &SceneObject::SetRotAngle) + .addProperty("Team", &SceneObject::GetTeam, &SceneObject::SetTeam) + .addProperty("PlacedByPlayer", &SceneObject::GetPlacedByPlayer, &SceneObject::SetPlacedByPlayer) + .addProperty("Buyable", &SceneObject::IsBuyable) + + .addProperty("BuyableMode", &LuaAdaptersSceneObject::GetBuyableMode) + + .addFunction("IsOnScenePoint", &SceneObject::IsOnScenePoint) + .addFunction("GetGoldValue", &SceneObject::GetGoldValueOld) + .addFunction("GetGoldValue", &SceneObject::GetGoldValue) + .addFunction("SetGoldValue", &SceneObject::SetGoldValue) + .addFunction("GetGoldValueString", &SceneObject::GetGoldValueString) + + .addFunction("GetTotalValue", &SceneObject::GetTotalValue) + .addFunction("GetTotalValue", &LuaAdaptersSceneObject::GetTotalValue) + + .addEnum({{"NORESTRICTIONS", static_cast(SceneObject::BuyableMode::NoRestrictions)}, + {"BUYMENUONLY", static_cast(SceneObject::BuyableMode::BuyMenuOnly)}, + {"OBJECTPICKERONLY", static_cast(SceneObject::BuyableMode::ObjectPickerOnly)}, + {"SCRIPTONLY", static_cast(SceneObject::BuyableMode::ScriptOnly)}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, SLBackground) { - return luabind::class_("SLBackground") - - .property("Frame", &SLBackground::GetFrame, &SLBackground::SetFrame) - .property("SpriteAnimMode", &SLBackground::GetSpriteAnimMode, &SLBackground::SetSpriteAnimMode) - .property("SpriteAnimDuration", &SLBackground::GetSpriteAnimDuration, &SLBackground::SetSpriteAnimDuration) - .property("IsAnimatedManually", &SLBackground::IsAnimatedManually, &SLBackground::SetAnimatedManually) - .property("AutoScrollX", &SLBackground::GetAutoScrollX, &SLBackground::SetAutoScrollX) - .property("AutoScrollY", &SLBackground::GetAutoScrollY, &SLBackground::SetAutoScrollY) - .property("AutoScrollInterval", &SLBackground::GetAutoScrollStepInterval, &SLBackground::SetAutoScrollStepInterval) - .property("AutoScrollStep", &SLBackground::GetAutoScrollStep, &SLBackground::SetAutoScrollStep) - .property("AutoScrollStepX", &SLBackground::GetAutoScrollStepX, &SLBackground::SetAutoScrollStepX) - .property("AutoScrollStepY", &SLBackground::GetAutoScrollStepY, &SLBackground::SetAutoScrollStepY) - - .def("IsAutoScrolling", &SLBackground::IsAutoScrolling); + registry.Class("SLBackground") + + .addProperty("Frame", &SLBackground::GetFrame, &SLBackground::SetFrame) + .addProperty("SpriteAnimMode", &SLBackground::GetSpriteAnimMode, &SLBackground::SetSpriteAnimMode) + .addProperty("SpriteAnimDuration", &SLBackground::GetSpriteAnimDuration, &SLBackground::SetSpriteAnimDuration) + .addProperty("IsAnimatedManually", &SLBackground::IsAnimatedManually, &SLBackground::SetAnimatedManually) + .addProperty("AutoScrollX", &SLBackground::GetAutoScrollX, &SLBackground::SetAutoScrollX) + .addProperty("AutoScrollY", &SLBackground::GetAutoScrollY, &SLBackground::SetAutoScrollY) + .addProperty("AutoScrollInterval", &SLBackground::GetAutoScrollStepInterval, &SLBackground::SetAutoScrollStepInterval) + .addProperty("AutoScrollStep", &SLBackground::GetAutoScrollStep, &SLBackground::SetAutoScrollStep) + .addProperty("AutoScrollStepX", &SLBackground::GetAutoScrollStepX, &SLBackground::SetAutoScrollStepX) + .addProperty("AutoScrollStepY", &SLBackground::GetAutoScrollStepY, &SLBackground::SetAutoScrollStepY) + + .addFunction("IsAutoScrolling", &SLBackground::IsAutoScrolling); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, SoundContainer) { - return ConcreteTypeLuaClassDefinition(SoundContainer, Entity) - - .def(luabind::constructor<>()) - - .property("SoundOverlapMode", &SoundContainer::GetSoundOverlapMode, &SoundContainer::SetSoundOverlapMode) - .property("BusRouting", &SoundContainer::GetBusRouting, &SoundContainer::SetBusRouting) - .property("Immobile", &SoundContainer::IsImmobile, &SoundContainer::SetImmobile) - .property("AttenuationStartDistance", &SoundContainer::GetAttenuationStartDistance, &SoundContainer::SetAttenuationStartDistance) - .property("CustomPanValue", &SoundContainer::GetCustomPanValue, &SoundContainer::SetCustomPanValue) - .property("PanningStrengthMultiplier", &SoundContainer::GetPanningStrengthMultiplier, &SoundContainer::SetPanningStrengthMultiplier) - .property("Loops", &SoundContainer::GetLoopSetting, &SoundContainer::SetLoopSetting) - .property("Priority", &SoundContainer::GetPriority, &SoundContainer::SetPriority) - .property("AffectedByGlobalPitch", &SoundContainer::IsAffectedByGlobalPitch, &SoundContainer::SetAffectedByGlobalPitch) - .property("Pos", &SoundContainer::GetPosition, &SoundContainer::SetPosition) - .property("Volume", &SoundContainer::GetVolume, &SoundContainer::SetVolume) - .property("Pitch", &SoundContainer::GetPitch, &SoundContainer::SetPitch) - .property("Paused", &SoundContainer::IsPaused, &SoundContainer::SetPaused) - .property("PitchVariation", &SoundContainer::GetPitchVariation, &SoundContainer::SetPitchVariation) - - .def("HasAnySounds", &SoundContainer::HasAnySounds) - .def("GetTopLevelSoundSet", &SoundContainer::GetTopLevelSoundSet) - .def("SetTopLevelSoundSet", &SoundContainer::SetTopLevelSoundSet) - .def("GetAudibleVolume", &SoundContainer::GetAudibleVolume) - .def("IsBeingPlayed", &SoundContainer::IsBeingPlayed) - .def("Play", (bool(SoundContainer::*)()) & SoundContainer::Play) - .def("Play", (bool(SoundContainer::*)(const int player)) & SoundContainer::Play) - .def("Play", (bool(SoundContainer::*)(const Vector& position)) & SoundContainer::Play) - .def("Play", (bool(SoundContainer::*)(const Vector& position, int player)) & SoundContainer::Play) - .def("Stop", (bool(SoundContainer::*)()) & SoundContainer::Stop) - .def("Stop", (bool(SoundContainer::*)(int player)) & SoundContainer::Stop) - .def("Restart", (bool(SoundContainer::*)()) & SoundContainer::Restart) - .def("Restart", (bool(SoundContainer::*)(int player)) & SoundContainer::Restart) - .def("FadeOut", &SoundContainer::FadeOut) - - .enum_("BusRouting")[luabind::value("SFX", SoundContainer::BusRouting::SFX), - luabind::value("UI", SoundContainer::BusRouting::UI), - luabind::value("MUSIC", SoundContainer::BusRouting::MUSIC)] - - .enum_("SoundOverlapMode")[luabind::value("OVERLAP", SoundContainer::SoundOverlapMode::OVERLAP), - luabind::value("RESTART", SoundContainer::SoundOverlapMode::RESTART), - luabind::value("IGNORE_PLAY", SoundContainer::SoundOverlapMode::IGNORE_PLAY)]; + ConcreteTypeLuaClassDefinition(SoundContainer, Entity) + + .addConstructor<>() + + .addProperty("SoundOverlapMode", &SoundContainer::GetSoundOverlapMode, &SoundContainer::SetSoundOverlapMode) + .addProperty("BusRouting", &SoundContainer::GetBusRouting, &SoundContainer::SetBusRouting) + .addProperty("Immobile", &SoundContainer::IsImmobile, &SoundContainer::SetImmobile) + .addProperty("AttenuationStartDistance", &SoundContainer::GetAttenuationStartDistance, &SoundContainer::SetAttenuationStartDistance) + .addProperty("CustomPanValue", &SoundContainer::GetCustomPanValue, &SoundContainer::SetCustomPanValue) + .addProperty("PanningStrengthMultiplier", &SoundContainer::GetPanningStrengthMultiplier, &SoundContainer::SetPanningStrengthMultiplier) + .addProperty("Loops", &SoundContainer::GetLoopSetting, &SoundContainer::SetLoopSetting) + .addProperty("Priority", &SoundContainer::GetPriority, &SoundContainer::SetPriority) + .addProperty("AffectedByGlobalPitch", &SoundContainer::IsAffectedByGlobalPitch, &SoundContainer::SetAffectedByGlobalPitch) + .addProperty("Pos", &SoundContainer::GetPosition, &SoundContainer::SetPosition) + .addProperty("Volume", &SoundContainer::GetVolume, &SoundContainer::SetVolume) + .addProperty("Pitch", &SoundContainer::GetPitch, &SoundContainer::SetPitch) + .addProperty("Paused", &SoundContainer::IsPaused, &SoundContainer::SetPaused) + .addProperty("PitchVariation", &SoundContainer::GetPitchVariation, &SoundContainer::SetPitchVariation) + + .addFunction("HasAnySounds", &SoundContainer::HasAnySounds) + .addFunction("GetTopLevelSoundSet", &SoundContainer::GetTopLevelSoundSet) + .addFunction("SetTopLevelSoundSet", &SoundContainer::SetTopLevelSoundSet) + .addFunction("GetAudibleVolume", &SoundContainer::GetAudibleVolume) + .addFunction("IsBeingPlayed", &SoundContainer::IsBeingPlayed) + .addFunction("Play", (bool(SoundContainer::*)()) & SoundContainer::Play) + .addFunction("Play", (bool(SoundContainer::*)(const int player)) & SoundContainer::Play) + .addFunction("Play", (bool(SoundContainer::*)(const Vector& position)) & SoundContainer::Play) + .addFunction("Play", (bool(SoundContainer::*)(const Vector& position, int player)) & SoundContainer::Play) + .addFunction("Stop", (bool(SoundContainer::*)()) & SoundContainer::Stop) + .addFunction("Stop", (bool(SoundContainer::*)(int player)) & SoundContainer::Stop) + .addFunction("Restart", (bool(SoundContainer::*)()) & SoundContainer::Restart) + .addFunction("Restart", (bool(SoundContainer::*)(int player)) & SoundContainer::Restart) + .addFunction("FadeOut", &SoundContainer::FadeOut) + + .addEnum({{"SFX", SoundContainer::BusRouting::SFX}, + {"UI", SoundContainer::BusRouting::UI}, + {"MUSIC", SoundContainer::BusRouting::MUSIC}}) + + .addEnum({{"OVERLAP", SoundContainer::SoundOverlapMode::OVERLAP}, + {"RESTART", SoundContainer::SoundOverlapMode::RESTART}, + {"IGNORE_PLAY", SoundContainer::SoundOverlapMode::IGNORE_PLAY}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, SoundSet) { - return luabind::class_("SoundSet") + registry.Class("SoundSet") - .def(luabind::constructor<>()) + .addConstructor<>() - .property("SoundSelectionCycleMode", &SoundSet::GetSoundSelectionCycleMode, &SoundSet::SetSoundSelectionCycleMode) + .addProperty("SoundSelectionCycleMode", &SoundSet::GetSoundSelectionCycleMode, &SoundSet::SetSoundSelectionCycleMode) - .def_readonly("SubSoundSets", &SoundSet::m_SubSoundSets, luabind::return_stl_iterator) + .addProperty("SubSoundSets", &SoundSet::m_SubSoundSets, LuaBinding::ReturnStlIterator) - .def("HasAnySounds", &SoundSet::HasAnySounds) - .def("SelectNextSounds", &SoundSet::SelectNextSounds) - .def("AddSound", (void(SoundSet::*)(const std::string& soundFilePath)) & SoundSet::AddSound) - .def("AddSound", (void(SoundSet::*)(const std::string& soundFilePath, const Vector& offset, float minimumAudibleDistance, float attenuationStartDistance)) & SoundSet::AddSound) - .def("RemoveSound", (bool(SoundSet::*)(const std::string& soundFilePath)) & SoundSet::RemoveSound) - .def("RemoveSound", (bool(SoundSet::*)(const std::string& soundFilePath, bool removeFromSubSoundSets)) & SoundSet::RemoveSound) - .def("AddSoundSet", &SoundSet::AddSoundSet) + .addFunction("HasAnySounds", &SoundSet::HasAnySounds) + .addFunction("SelectNextSounds", &SoundSet::SelectNextSounds) + .addFunction("AddSound", (void(SoundSet::*)(const std::string& soundFilePath)) & SoundSet::AddSound) + .addFunction("AddSound", (void(SoundSet::*)(const std::string& soundFilePath, const Vector& offset, float minimumAudibleDistance, float attenuationStartDistance)) & SoundSet::AddSound) + .addFunction("RemoveSound", (bool(SoundSet::*)(const std::string& soundFilePath)) & SoundSet::RemoveSound) + .addFunction("RemoveSound", (bool(SoundSet::*)(const std::string& soundFilePath, bool removeFromSubSoundSets)) & SoundSet::RemoveSound) + .addFunction("AddSoundSet", &SoundSet::AddSoundSet) - .enum_("SoundSelectionCycleMode")[luabind::value("RANDOM", SoundSet::SoundSelectionCycleMode::RANDOM), - luabind::value("FORWARDS", SoundSet::SoundSelectionCycleMode::FORWARDS), - luabind::value("ALL", SoundSet::SoundSelectionCycleMode::ALL)]; + .addEnum({{"RANDOM", SoundSet::SoundSelectionCycleMode::RANDOM}, + {"FORWARDS", SoundSet::SoundSelectionCycleMode::FORWARDS}, + {"ALL", SoundSet::SoundSelectionCycleMode::ALL}}); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, TDExplosive) { - return ConcreteTypeLuaClassDefinition(TDExplosive, ThrownDevice) + ConcreteTypeLuaClassDefinition(TDExplosive, ThrownDevice) - .property("IsAnimatedManually", &TDExplosive::IsAnimatedManually, &TDExplosive::SetAnimatedManually); + .addProperty("IsAnimatedManually", &TDExplosive::IsAnimatedManually, &TDExplosive::SetAnimatedManually); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, TerrainObject) { - return ConcreteTypeLuaClassDefinition(TerrainObject, SceneObject) + ConcreteTypeLuaClassDefinition(TerrainObject, SceneObject) - .def("GetBitmapOffset", &TerrainObject::GetBitmapOffset) - .def("GetBitmapWidth", &TerrainObject::GetBitmapWidth) - .def("GetBitmapHeight", &TerrainObject::GetBitmapHeight); + .addFunction("GetBitmapOffset", &TerrainObject::GetBitmapOffset) + .addFunction("GetBitmapWidth", &TerrainObject::GetBitmapWidth) + .addFunction("GetBitmapHeight", &TerrainObject::GetBitmapHeight); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, ThrownDevice) { - return ConcreteTypeLuaClassDefinition(ThrownDevice, HeldDevice) + ConcreteTypeLuaClassDefinition(ThrownDevice, HeldDevice) - .property("MinThrowVel", &ThrownDevice::GetMinThrowVel, &ThrownDevice::SetMinThrowVel) - .property("MaxThrowVel", &ThrownDevice::GetMaxThrowVel, &ThrownDevice::SetMaxThrowVel) - .property("StartThrowOffset", &ThrownDevice::GetStartThrowOffset, &ThrownDevice::SetStartThrowOffset) - .property("EndThrowOffset", &ThrownDevice::GetEndThrowOffset, &ThrownDevice::SetEndThrowOffset) + .addProperty("MinThrowVel", &ThrownDevice::GetMinThrowVel, &ThrownDevice::SetMinThrowVel) + .addProperty("MaxThrowVel", &ThrownDevice::GetMaxThrowVel, &ThrownDevice::SetMaxThrowVel) + .addProperty("StartThrowOffset", &ThrownDevice::GetStartThrowOffset, &ThrownDevice::SetStartThrowOffset) + .addProperty("EndThrowOffset", &ThrownDevice::GetEndThrowOffset, &ThrownDevice::SetEndThrowOffset) - .def("GetCalculatedMaxThrowVelIncludingArmThrowStrength", &ThrownDevice::GetCalculatedMaxThrowVelIncludingArmThrowStrength); + .addFunction("GetCalculatedMaxThrowVelIncludingArmThrowStrength", &ThrownDevice::GetCalculatedMaxThrowVelIncludingArmThrowStrength); } LuaBindingRegisterFunctionDefinitionForType(EntityLuaBindings, Turret) { - return ConcreteTypeLuaClassDefinition(Turret, Attachable) + ConcreteTypeLuaClassDefinition(Turret, Attachable) - .property("MountedDevice", &Turret::GetFirstMountedDevice, &LuaAdaptersPropertyOwnershipSafetyFaker::TurretSetFirstMountedDevice) - .property("MountedDeviceRotationOffset", &Turret::GetMountedDeviceRotationOffset, &Turret::SetMountedDeviceRotationOffset) + .addProperty("MountedDevice", &Turret::GetFirstMountedDevice, &LuaAdaptersPropertyOwnershipSafetyFaker::TurretSetFirstMountedDevice) + .addProperty("MountedDeviceRotationOffset", &Turret::GetMountedDeviceRotationOffset, &Turret::SetMountedDeviceRotationOffset) - .def("GetMountedDevices", &Turret::GetMountedDevices, luabind::return_stl_iterator) - .def("AddMountedDevice", &Turret::AddMountedDevice, luabind::adopt(_2)) - .def("AddMountedDevice", &LuaAdaptersTurret::AddMountedFirearm, luabind::adopt(_2)); + .addFunction("GetMountedDevices", &Turret::GetMountedDevices, LuaBinding::ReturnStlIterator) + .addFunction("AddMountedDevice", &Turret::AddMountedDevice, LuaBinding::AdoptArg<2>) + .addFunction("AddMountedDevice", &LuaAdaptersTurret::AddMountedFirearm, LuaBinding::AdoptArg<2>); } diff --git a/Source/Lua/LuaBindingsGUI.cpp b/Source/Lua/LuaBindingsGUI.cpp index 706b93ee84..238586e5ed 100644 --- a/Source/Lua/LuaBindingsGUI.cpp +++ b/Source/Lua/LuaBindingsGUI.cpp @@ -5,89 +5,89 @@ using namespace RTE; LuaBindingRegisterFunctionDefinitionForType(GUILuaBindings, GUIBanner) { - return luabind::class_("GUIBanner") + registry.Class("GUIBanner") - .property("BannerText", &GUIBanner::GetBannerText) - .property("AnimState", &GUIBanner::GetAnimState) - .property("Kerning", &GUIBanner::GetKerning, &GUIBanner::SetKerning) + .addProperty("BannerText", &GUIBanner::GetBannerText) + .addProperty("AnimState", &GUIBanner::GetAnimState) + .addProperty("Kerning", &GUIBanner::GetKerning, &GUIBanner::SetKerning) - .def("IsVisible", &GUIBanner::IsVisible) - .def("ShowText", &GUIBanner::ShowText) - .def("HideText", &GUIBanner::HideText) - .def("ClearText", &GUIBanner::ClearText) + .addFunction("IsVisible", &GUIBanner::IsVisible) + .addFunction("ShowText", &GUIBanner::ShowText) + .addFunction("HideText", &GUIBanner::HideText) + .addFunction("ClearText", &GUIBanner::ClearText) - .enum_("AnimMode")[luabind::value("BLINKING", GUIBanner::AnimMode::BLINKING), - luabind::value("FLYBYLEFTWARD", GUIBanner::AnimMode::FLYBYLEFTWARD), - luabind::value("FLYBYRIGHTWARD", GUIBanner::AnimMode::FLYBYRIGHTWARD), - luabind::value("ANIMMODECOUNT", GUIBanner::AnimMode::ANIMMODECOUNT)] - .enum_("AnimState")[luabind::value("NOTSTARTED", GUIBanner::AnimState::NOTSTARTED), - luabind::value("SHOWING", GUIBanner::AnimState::SHOWING), - luabind::value("SHOW", GUIBanner::AnimState::SHOW), - luabind::value("HIDING", GUIBanner::AnimState::HIDING), - luabind::value("OVER", GUIBanner::AnimState::OVER), - luabind::value("ANIMSTATECOUNT", GUIBanner::AnimState::ANIMSTATECOUNT)] - .enum_("BannerColor")[luabind::value("RED", GameActivity::BannerColor::RED), - luabind::value("YELLOW", GameActivity::BannerColor::YELLOW)]; + .addEnum({{"BLINKING", GUIBanner::AnimMode::BLINKING}, + {"FLYBYLEFTWARD", GUIBanner::AnimMode::FLYBYLEFTWARD}, + {"FLYBYRIGHTWARD", GUIBanner::AnimMode::FLYBYRIGHTWARD}, + {"ANIMMODECOUNT", GUIBanner::AnimMode::ANIMMODECOUNT}}) + .addEnum({{"NOTSTARTED", GUIBanner::AnimState::NOTSTARTED}, + {"SHOWING", GUIBanner::AnimState::SHOWING}, + {"SHOW", GUIBanner::AnimState::SHOW}, + {"HIDING", GUIBanner::AnimState::HIDING}, + {"OVER", GUIBanner::AnimState::OVER}, + {"ANIMSTATECOUNT", GUIBanner::AnimState::ANIMSTATECOUNT}}) + .addEnum({{"RED", GameActivity::BannerColor::RED}, + {"YELLOW", GameActivity::BannerColor::YELLOW}}); } LuaBindingRegisterFunctionDefinitionForType(GUILuaBindings, BuyMenuGUI) { - return luabind::class_("BuyMenuGUI") + registry.Class("BuyMenuGUI") - .property("ShowOnlyOwnedItems", &BuyMenuGUI::GetOnlyShowOwnedItems, &BuyMenuGUI::SetOnlyShowOwnedItems) - .property("EnforceMaxPassengersConstraint", &BuyMenuGUI::EnforceMaxPassengersConstraint, &BuyMenuGUI::SetEnforceMaxPassengersConstraint) - .property("EnforceMaxMassConstraint", &BuyMenuGUI::EnforceMaxMassConstraint, &BuyMenuGUI::SetEnforceMaxMassConstraint) + .addProperty("ShowOnlyOwnedItems", &BuyMenuGUI::GetOnlyShowOwnedItems, &BuyMenuGUI::SetOnlyShowOwnedItems) + .addProperty("EnforceMaxPassengersConstraint", &BuyMenuGUI::EnforceMaxPassengersConstraint, &BuyMenuGUI::SetEnforceMaxPassengersConstraint) + .addProperty("EnforceMaxMassConstraint", &BuyMenuGUI::EnforceMaxMassConstraint, &BuyMenuGUI::SetEnforceMaxMassConstraint) - .def("SetMetaPlayer", &BuyMenuGUI::SetMetaPlayer) - .def("SetNativeTechModule", &BuyMenuGUI::SetNativeTechModule) - .def("SetForeignCostMultiplier", &BuyMenuGUI::SetForeignCostMultiplier) - .def("SetModuleExpanded", &BuyMenuGUI::SetModuleExpanded) - .def("LoadAllLoadoutsFromFile", &BuyMenuGUI::LoadAllLoadoutsFromFile) - .def("AddAllowedItem", &BuyMenuGUI::AddAllowedItem) - .def("RemoveAllowedItem", &BuyMenuGUI::RemoveAllowedItem) - .def("ClearAllowedItems", &BuyMenuGUI::ClearAllowedItems) - .def("AddAlwaysAllowedItem", &BuyMenuGUI::AddAlwaysAllowedItem) - .def("RemoveAlwaysAllowedItem", &BuyMenuGUI::RemoveAlwaysAllowedItem) - .def("ClearAlwaysAllowedItems", &BuyMenuGUI::ClearAlwaysAllowedItems) - .def("AddProhibitedItem", &BuyMenuGUI::AddProhibitedItem) - .def("RemoveProhibitedItem", &BuyMenuGUI::RemoveProhibitedItem) - .def("ClearProhibitedItems", &BuyMenuGUI::ClearProhibitedItems) - .def("ForceRefresh", &BuyMenuGUI::ForceRefresh) - .def("SetOwnedItemsAmount", &BuyMenuGUI::SetOwnedItemsAmount) - .def("GetOwnedItemsAmount", &BuyMenuGUI::GetOwnedItemsAmount) - .def("SetBannerImage", &BuyMenuGUI::SetBannerImage) - .def("SetLogoImage", &BuyMenuGUI::SetLogoImage) - .def("ClearCartList", &BuyMenuGUI::ClearCartList) - .def("LoadDefaultLoadoutToCart", &BuyMenuGUI::LoadDefaultLoadoutToCart) - .def("GetOrderList", &LuaAdaptersBuyMenuGUI::GetOrderList, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("GetTotalCartCost", &BuyMenuGUI::GetTotalCartCost) - .def("GetTotalOrderCost", &BuyMenuGUI::GetTotalOrderCost) - .def("GetTotalOrderMass", &BuyMenuGUI::GetTotalOrderMass) - .def("GetTotalOrderPassengers", &BuyMenuGUI::GetTotalOrderPassengers); + .addFunction("SetMetaPlayer", &BuyMenuGUI::SetMetaPlayer) + .addFunction("SetNativeTechModule", &BuyMenuGUI::SetNativeTechModule) + .addFunction("SetForeignCostMultiplier", &BuyMenuGUI::SetForeignCostMultiplier) + .addFunction("SetModuleExpanded", &BuyMenuGUI::SetModuleExpanded) + .addFunction("LoadAllLoadoutsFromFile", &BuyMenuGUI::LoadAllLoadoutsFromFile) + .addFunction("AddAllowedItem", &BuyMenuGUI::AddAllowedItem) + .addFunction("RemoveAllowedItem", &BuyMenuGUI::RemoveAllowedItem) + .addFunction("ClearAllowedItems", &BuyMenuGUI::ClearAllowedItems) + .addFunction("AddAlwaysAllowedItem", &BuyMenuGUI::AddAlwaysAllowedItem) + .addFunction("RemoveAlwaysAllowedItem", &BuyMenuGUI::RemoveAlwaysAllowedItem) + .addFunction("ClearAlwaysAllowedItems", &BuyMenuGUI::ClearAlwaysAllowedItems) + .addFunction("AddProhibitedItem", &BuyMenuGUI::AddProhibitedItem) + .addFunction("RemoveProhibitedItem", &BuyMenuGUI::RemoveProhibitedItem) + .addFunction("ClearProhibitedItems", &BuyMenuGUI::ClearProhibitedItems) + .addFunction("ForceRefresh", &BuyMenuGUI::ForceRefresh) + .addFunction("SetOwnedItemsAmount", &BuyMenuGUI::SetOwnedItemsAmount) + .addFunction("GetOwnedItemsAmount", &BuyMenuGUI::GetOwnedItemsAmount) + .addFunction("SetBannerImage", &BuyMenuGUI::SetBannerImage) + .addFunction("SetLogoImage", &BuyMenuGUI::SetLogoImage) + .addFunction("ClearCartList", &BuyMenuGUI::ClearCartList) + .addFunction("LoadDefaultLoadoutToCart", &BuyMenuGUI::LoadDefaultLoadoutToCart) + .addFunction("GetOrderList", &LuaAdaptersBuyMenuGUI::GetOrderList, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetTotalCartCost", &BuyMenuGUI::GetTotalCartCost) + .addFunction("GetTotalOrderCost", &BuyMenuGUI::GetTotalOrderCost) + .addFunction("GetTotalOrderMass", &BuyMenuGUI::GetTotalOrderMass) + .addFunction("GetTotalOrderPassengers", &BuyMenuGUI::GetTotalOrderPassengers); } LuaBindingRegisterFunctionDefinitionForType(GUILuaBindings, SceneEditorGUI) { - return luabind::class_("SceneEditorGUI") + registry.Class("SceneEditorGUI") - .property("EditorMode", &SceneEditorGUI::GetEditorGUIMode, &SceneEditorGUI::SetEditorGUIMode) + .addProperty("EditorMode", &SceneEditorGUI::GetEditorGUIMode, &SceneEditorGUI::SetEditorGUIMode) - .def("SetCursorPos", &SceneEditorGUI::SetCursorPos) - .def("GetCurrentObject", &SceneEditorGUI::GetCurrentObject) - .def("SetCurrentObject", &SceneEditorGUI::SetCurrentObject, luabind::adopt(_2)) - .def("SetModuleSpace", &SceneEditorGUI::SetModuleSpace) - .def("SetNativeTechModule", &SceneEditorGUI::SetNativeTechModule) - .def("SetForeignCostMultiplier", &SceneEditorGUI::SetForeignCostMultiplier) - .def("TestBrainResidence", &SceneEditorGUI::TestBrainResidence) - .def("Update", &SceneEditorGUI::Update) // Gacyr Note: I hate this being here but it's necessary for some metagame bullshit. + .addFunction("SetCursorPos", &SceneEditorGUI::SetCursorPos) + .addFunction("GetCurrentObject", &SceneEditorGUI::GetCurrentObject) + .addFunction("SetCurrentObject", &SceneEditorGUI::SetCurrentObject, LuaBinding::AdoptArg<2>) + .addFunction("SetModuleSpace", &SceneEditorGUI::SetModuleSpace) + .addFunction("SetNativeTechModule", &SceneEditorGUI::SetNativeTechModule) + .addFunction("SetForeignCostMultiplier", &SceneEditorGUI::SetForeignCostMultiplier) + .addFunction("TestBrainResidence", &SceneEditorGUI::TestBrainResidence) + .addFunction("Update", &SceneEditorGUI::Update) // Gacyr Note: I hate this being here but it's necessary for some metagame bullshit. - .enum_("EditorGUIMode")[luabind::value("INACTIVE", SceneEditorGUI::EditorGUIMode::INACTIVE), - luabind::value("PICKINGOBJECT", SceneEditorGUI::EditorGUIMode::PICKINGOBJECT), - luabind::value("ADDINGOBJECT", SceneEditorGUI::EditorGUIMode::ADDINGOBJECT), - luabind::value("INSTALLINGBRAIN", SceneEditorGUI::EditorGUIMode::INSTALLINGBRAIN), - luabind::value("PLACINGOBJECT", SceneEditorGUI::EditorGUIMode::PLACINGOBJECT), - luabind::value("MOVINGOBJECT", SceneEditorGUI::EditorGUIMode::MOVINGOBJECT), - luabind::value("DELETINGOBJECT", SceneEditorGUI::EditorGUIMode::DELETINGOBJECT), - luabind::value("PLACEINFRONT", SceneEditorGUI::EditorGUIMode::PLACEINFRONT), - luabind::value("PLACEBEHIND", SceneEditorGUI::EditorGUIMode::PLACEBEHIND), - luabind::value("DONEEDITING", SceneEditorGUI::EditorGUIMode::DONEEDITING), - luabind::value("EDITORGUIMODECOUNT", SceneEditorGUI::EditorGUIMode::EDITORGUIMODECOUNT)]; + .addEnum({{"INACTIVE", SceneEditorGUI::EditorGUIMode::INACTIVE}, + {"PICKINGOBJECT", SceneEditorGUI::EditorGUIMode::PICKINGOBJECT}, + {"ADDINGOBJECT", SceneEditorGUI::EditorGUIMode::ADDINGOBJECT}, + {"INSTALLINGBRAIN", SceneEditorGUI::EditorGUIMode::INSTALLINGBRAIN}, + {"PLACINGOBJECT", SceneEditorGUI::EditorGUIMode::PLACINGOBJECT}, + {"MOVINGOBJECT", SceneEditorGUI::EditorGUIMode::MOVINGOBJECT}, + {"DELETINGOBJECT", SceneEditorGUI::EditorGUIMode::DELETINGOBJECT}, + {"PLACEINFRONT", SceneEditorGUI::EditorGUIMode::PLACEINFRONT}, + {"PLACEBEHIND", SceneEditorGUI::EditorGUIMode::PLACEBEHIND}, + {"DONEEDITING", SceneEditorGUI::EditorGUIMode::DONEEDITING}, + {"EDITORGUIMODECOUNT", SceneEditorGUI::EditorGUIMode::EDITORGUIMODECOUNT}}); } diff --git a/Source/Lua/LuaBindingsInput.cpp b/Source/Lua/LuaBindingsInput.cpp index b09c41d1ef..ad91f6d394 100644 --- a/Source/Lua/LuaBindingsInput.cpp +++ b/Source/Lua/LuaBindingsInput.cpp @@ -9,586 +9,586 @@ using namespace RTE; LuaBindingRegisterFunctionDefinitionForType(InputLuaBindings, InputDevice) { - return luabind::class_("InputDevice") + registry.Class("InputDevice") - .enum_("InputDevice")[luabind::value("DEVICE_KEYB_ONLY", InputDevice::DEVICE_KEYB_ONLY), - luabind::value("DEVICE_MOUSE_KEYB", InputDevice::DEVICE_MOUSE_KEYB), - luabind::value("DEVICE_GAMEPAD_1", InputDevice::DEVICE_GAMEPAD_1), - luabind::value("DEVICE_GAMEPAD_2", InputDevice::DEVICE_GAMEPAD_2), - luabind::value("DEVICE_GAMEPAD_3", InputDevice::DEVICE_GAMEPAD_3), - luabind::value("DEVICE_GAMEPAD_4", InputDevice::DEVICE_GAMEPAD_4), - luabind::value("DEVICE_COUNT", InputDevice::DEVICE_COUNT)]; + .addEnum({{"DEVICE_KEYB_ONLY", InputDevice::DEVICE_KEYB_ONLY}, + {"DEVICE_MOUSE_KEYB", InputDevice::DEVICE_MOUSE_KEYB}, + {"DEVICE_GAMEPAD_1", InputDevice::DEVICE_GAMEPAD_1}, + {"DEVICE_GAMEPAD_2", InputDevice::DEVICE_GAMEPAD_2}, + {"DEVICE_GAMEPAD_3", InputDevice::DEVICE_GAMEPAD_3}, + {"DEVICE_GAMEPAD_4", InputDevice::DEVICE_GAMEPAD_4}, + {"DEVICE_COUNT", InputDevice::DEVICE_COUNT}}); } LuaBindingRegisterFunctionDefinitionForType(InputLuaBindings, InputElements) { - return luabind::class_("InputElements") + registry.Class("InputElements") - .enum_("InputElements")[luabind::value("INPUT_L_UP", InputElements::INPUT_L_UP), - luabind::value("INPUT_L_DOWN", InputElements::INPUT_L_DOWN), - luabind::value("INPUT_L_LEFT", InputElements::INPUT_L_LEFT), - luabind::value("INPUT_L_RIGHT", InputElements::INPUT_L_RIGHT), - luabind::value("INPUT_MOVE_FAST", InputElements::INPUT_MOVE_FAST), - luabind::value("INPUT_MOVE_FAST_TOGGLE", InputElements::INPUT_MOVE_FAST_TOGGLE), - luabind::value("INPUT_R_UP", InputElements::INPUT_R_UP), - luabind::value("INPUT_R_DOWN", InputElements::INPUT_R_DOWN), - luabind::value("INPUT_R_LEFT", InputElements::INPUT_R_LEFT), - luabind::value("INPUT_R_RIGHT", InputElements::INPUT_R_RIGHT), - luabind::value("INPUT_FIRE", InputElements::INPUT_FIRE), - luabind::value("INPUT_AIM", InputElements::INPUT_AIM), - luabind::value("INPUT_AIM_UP", InputElements::INPUT_AIM_UP), - luabind::value("INPUT_AIM_DOWN", InputElements::INPUT_AIM_DOWN), - luabind::value("INPUT_AIM_LEFT", InputElements::INPUT_AIM_LEFT), - luabind::value("INPUT_AIM_RIGHT", InputElements::INPUT_AIM_RIGHT), - luabind::value("INPUT_PIEMENU_ANALOG", InputElements::INPUT_PIEMENU_ANALOG), - luabind::value("INPUT_PIEMENU_DIGITAL", InputElements::INPUT_PIEMENU_DIGITAL), - luabind::value("INPUT_JUMP", InputElements::INPUT_JUMP), - luabind::value("INPUT_CROUCH", InputElements::INPUT_PRONE), // awful, but script compat - luabind::value("INPUT_PRONE", InputElements::INPUT_PRONE), - luabind::value("INPUT_WALKCROUCH", InputElements::INPUT_CROUCH), - luabind::value("INPUT_NEXT", InputElements::INPUT_NEXT), - luabind::value("INPUT_PREV", InputElements::INPUT_PREV), - luabind::value("INPUT_START", InputElements::INPUT_START), - luabind::value("INPUT_BACK", InputElements::INPUT_BACK), - luabind::value("INPUT_COUNT", InputElements::INPUT_COUNT)]; + .addEnum({{"INPUT_L_UP", InputElements::INPUT_L_UP}, + {"INPUT_L_DOWN", InputElements::INPUT_L_DOWN}, + {"INPUT_L_LEFT", InputElements::INPUT_L_LEFT}, + {"INPUT_L_RIGHT", InputElements::INPUT_L_RIGHT}, + {"INPUT_MOVE_FAST", InputElements::INPUT_MOVE_FAST}, + {"INPUT_MOVE_FAST_TOGGLE", InputElements::INPUT_MOVE_FAST_TOGGLE}, + {"INPUT_R_UP", InputElements::INPUT_R_UP}, + {"INPUT_R_DOWN", InputElements::INPUT_R_DOWN}, + {"INPUT_R_LEFT", InputElements::INPUT_R_LEFT}, + {"INPUT_R_RIGHT", InputElements::INPUT_R_RIGHT}, + {"INPUT_FIRE", InputElements::INPUT_FIRE}, + {"INPUT_AIM", InputElements::INPUT_AIM}, + {"INPUT_AIM_UP", InputElements::INPUT_AIM_UP}, + {"INPUT_AIM_DOWN", InputElements::INPUT_AIM_DOWN}, + {"INPUT_AIM_LEFT", InputElements::INPUT_AIM_LEFT}, + {"INPUT_AIM_RIGHT", InputElements::INPUT_AIM_RIGHT}, + {"INPUT_PIEMENU_ANALOG", InputElements::INPUT_PIEMENU_ANALOG}, + {"INPUT_PIEMENU_DIGITAL", InputElements::INPUT_PIEMENU_DIGITAL}, + {"INPUT_JUMP", InputElements::INPUT_JUMP}, + {"INPUT_CROUCH", InputElements::INPUT_PRONE}, // awful, but script compat + {"INPUT_PRONE", InputElements::INPUT_PRONE}, + {"INPUT_WALKCROUCH", InputElements::INPUT_CROUCH}, + {"INPUT_NEXT", InputElements::INPUT_NEXT}, + {"INPUT_PREV", InputElements::INPUT_PREV}, + {"INPUT_START", InputElements::INPUT_START}, + {"INPUT_BACK", InputElements::INPUT_BACK}, + {"INPUT_COUNT", InputElements::INPUT_COUNT}}); } LuaBindingRegisterFunctionDefinitionForType(InputLuaBindings, MouseButtons) { - return luabind::class_("MouseButtons") + registry.Class("MouseButtons") - .enum_("MouseButtons")[luabind::value("MOUSE_NONE", MouseButtons::MOUSE_NONE), - luabind::value("MOUSE_LEFT", MouseButtons::MOUSE_LEFT), - luabind::value("MOUSE_RIGHT", MouseButtons::MOUSE_RIGHT), - luabind::value("MOUSE_MIDDLE", MouseButtons::MOUSE_MIDDLE), - luabind::value("MAX_MOUSE_BUTTONS", MouseButtons::MAX_MOUSE_BUTTONS)]; + .addEnum({{"MOUSE_NONE", MouseButtons::MOUSE_NONE}, + {"MOUSE_LEFT", MouseButtons::MOUSE_LEFT}, + {"MOUSE_RIGHT", MouseButtons::MOUSE_RIGHT}, + {"MOUSE_MIDDLE", MouseButtons::MOUSE_MIDDLE}, + {"MAX_MOUSE_BUTTONS", MouseButtons::MAX_MOUSE_BUTTONS}}); } LuaBindingRegisterFunctionDefinitionForType(InputLuaBindings, JoyButtons) { - return luabind::class_("JoyButtons") + registry.Class("JoyButtons") - .enum_("JoyButtons")[luabind::value("JOY_NONE", JoyButtons::JOY_NONE), - luabind::value("JOY_1", JoyButtons::JOY_1), - luabind::value("JOY_2", JoyButtons::JOY_2), - luabind::value("JOY_3", JoyButtons::JOY_3), - luabind::value("JOY_4", JoyButtons::JOY_4), - luabind::value("JOY_5", JoyButtons::JOY_5), - luabind::value("JOY_6", JoyButtons::JOY_6), - luabind::value("JOY_7", JoyButtons::JOY_7), - luabind::value("JOY_8", JoyButtons::JOY_8), - luabind::value("JOY_9", JoyButtons::JOY_9), - luabind::value("JOY_10", JoyButtons::JOY_10), - luabind::value("JOY_11", JoyButtons::JOY_11), - luabind::value("JOY_12", JoyButtons::JOY_12), - luabind::value("MAX_JOY_BUTTONS", JoyButtons::MAX_JOY_BUTTONS)]; + .addEnum({{"JOY_NONE", JoyButtons::JOY_NONE}, + {"JOY_1", JoyButtons::JOY_1}, + {"JOY_2", JoyButtons::JOY_2}, + {"JOY_3", JoyButtons::JOY_3}, + {"JOY_4", JoyButtons::JOY_4}, + {"JOY_5", JoyButtons::JOY_5}, + {"JOY_6", JoyButtons::JOY_6}, + {"JOY_7", JoyButtons::JOY_7}, + {"JOY_8", JoyButtons::JOY_8}, + {"JOY_9", JoyButtons::JOY_9}, + {"JOY_10", JoyButtons::JOY_10}, + {"JOY_11", JoyButtons::JOY_11}, + {"JOY_12", JoyButtons::JOY_12}, + {"MAX_JOY_BUTTONS", JoyButtons::MAX_JOY_BUTTONS}}); } LuaBindingRegisterFunctionDefinitionForType(InputLuaBindings, JoyDirections) { - return luabind::class_("JoyDirections") + registry.Class("JoyDirections") - .enum_("JoyDirections")[luabind::value("JOYDIR_ONE", JoyDirections::JOYDIR_ONE), - luabind::value("JOYDIR_TWO", JoyDirections::JOYDIR_TWO)]; + .addEnum({{"JOYDIR_ONE", JoyDirections::JOYDIR_ONE}, + {"JOYDIR_TWO", JoyDirections::JOYDIR_TWO}}); } LuaBindingRegisterFunctionDefinitionForType(InputLuaBindings, SDL_Keycode) { - return luabind::class_("Key") + registry.Class("Key") // Make sure to update https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/wiki/SDL-Keycode-and-Scancode-enum-values-in-Lua#key-codes if any changes are made. - .enum_("Key")[luabind::value("UNKNOWN", SDLK_UNKNOWN), - luabind::value("RETURN", SDLK_RETURN), - luabind::value("ESCAPE", SDLK_ESCAPE), - luabind::value("BACKSPACE", SDLK_BACKSPACE), - luabind::value("TAB", SDLK_TAB), - luabind::value("SPACE", SDLK_SPACE), - luabind::value("EXCLAIM", SDLK_EXCLAIM), - luabind::value("QUOTEDBL", SDLK_DBLAPOSTROPHE), - luabind::value("HASH", SDLK_HASH), - luabind::value("PERCENT", SDLK_PERCENT), - luabind::value("DOLLAR", SDLK_DOLLAR), - luabind::value("AMPERSAND", SDLK_AMPERSAND), - luabind::value("QUOTE", SDLK_APOSTROPHE), - luabind::value("LEFTPAREN", SDLK_LEFTPAREN), - luabind::value("RIGHTPAREN", SDLK_RIGHTPAREN), - luabind::value("ASTERISK", SDLK_ASTERISK), - luabind::value("PLUS", SDLK_PLUS), - luabind::value("COMMA", SDLK_COMMA), - luabind::value("MINUS", SDLK_MINUS), - luabind::value("PERIOD", SDLK_PERIOD), - luabind::value("SLASH", SDLK_SLASH), - luabind::value("K_0", SDLK_0), - luabind::value("K_1", SDLK_1), - luabind::value("K_2", SDLK_2), - luabind::value("K_3", SDLK_3), - luabind::value("K_4", SDLK_4), - luabind::value("K_5", SDLK_5), - luabind::value("K_6", SDLK_6), - luabind::value("K_7", SDLK_7), - luabind::value("K_8", SDLK_8), - luabind::value("K_9", SDLK_9), - luabind::value("COLON", SDLK_COLON), - luabind::value("SEMICOLON", SDLK_SEMICOLON), - luabind::value("LESS", SDLK_LESS), - luabind::value("EQUALS", SDLK_EQUALS), - luabind::value("GREATER", SDLK_GREATER), - luabind::value("QUESTION", SDLK_QUESTION), - luabind::value("AT", SDLK_AT), - luabind::value("LEFTBRACKET", SDLK_LEFTBRACKET), - luabind::value("BACKSLASH", SDLK_BACKSLASH), - luabind::value("RIGHTBRACKET", SDLK_RIGHTBRACKET), - luabind::value("CARET", SDLK_CARET), - luabind::value("UNDERSCORE", SDLK_UNDERSCORE), - luabind::value("BACKQUOTE", SDLK_GRAVE), - luabind::value("A", SDLK_A), - luabind::value("B", SDLK_B), - luabind::value("C", SDLK_C), - luabind::value("D", SDLK_D), - luabind::value("E", SDLK_E), - luabind::value("F", SDLK_F), - luabind::value("G", SDLK_G), - luabind::value("H", SDLK_H), - luabind::value("I", SDLK_I), - luabind::value("J", SDLK_J), - luabind::value("K", SDLK_K), - luabind::value("L", SDLK_L), - luabind::value("M", SDLK_M), - luabind::value("N", SDLK_N), - luabind::value("O", SDLK_O), - luabind::value("P", SDLK_P), - luabind::value("Q", SDLK_Q), - luabind::value("R", SDLK_R), - luabind::value("S", SDLK_S), - luabind::value("T", SDLK_T), - luabind::value("U", SDLK_U), - luabind::value("V", SDLK_V), - luabind::value("W", SDLK_W), - luabind::value("X", SDLK_X), - luabind::value("Y", SDLK_Y), - luabind::value("Z", SDLK_Z), - luabind::value("CAPSLOCK", SDLK_CAPSLOCK), - luabind::value("F1", SDLK_F1), - luabind::value("F2", SDLK_F2), - luabind::value("F3", SDLK_F3), - luabind::value("F4", SDLK_F4), - luabind::value("F5", SDLK_F5), - luabind::value("F6", SDLK_F6), - luabind::value("F7", SDLK_F7), - luabind::value("F8", SDLK_F8), - luabind::value("F9", SDLK_F9), - luabind::value("F10", SDLK_F10), - luabind::value("F11", SDLK_F11), - luabind::value("F12", SDLK_F12), - luabind::value("PRINTSCREEN", SDLK_PRINTSCREEN), - luabind::value("SCROLLLOCK", SDLK_SCROLLLOCK), - luabind::value("PAUSE", SDLK_PAUSE), - luabind::value("INSERT", SDLK_INSERT), - luabind::value("HOME", SDLK_HOME), - luabind::value("PAGEUP", SDLK_PAGEUP), - luabind::value("DELETE", SDLK_DELETE), - luabind::value("END", SDLK_END), - luabind::value("PAGEDOWN", SDLK_PAGEDOWN), - luabind::value("RIGHT", SDLK_RIGHT), - luabind::value("LEFT", SDLK_LEFT), - luabind::value("DOWN", SDLK_DOWN), - luabind::value("UP", SDLK_UP), - luabind::value("NUMLOCKCLEAR", SDLK_NUMLOCKCLEAR), - luabind::value("KP_DIVIDE", SDLK_KP_DIVIDE), - luabind::value("KP_MULTIPLY", SDLK_KP_MULTIPLY), - luabind::value("KP_MINUS", SDLK_KP_MINUS), - luabind::value("KP_PLUS", SDLK_KP_PLUS), - luabind::value("KP_ENTER", SDLK_KP_ENTER), - luabind::value("KP_1", SDLK_KP_1), - luabind::value("KP_2", SDLK_KP_2), - luabind::value("KP_3", SDLK_KP_3), - luabind::value("KP_4", SDLK_KP_4), - luabind::value("KP_5", SDLK_KP_5), - luabind::value("KP_6", SDLK_KP_6), - luabind::value("KP_7", SDLK_KP_7), - luabind::value("KP_8", SDLK_KP_8), - luabind::value("KP_9", SDLK_KP_9), - luabind::value("KP_0", SDLK_KP_0), - luabind::value("KP_PERIOD", SDLK_KP_PERIOD), - luabind::value("APPLICATION", SDLK_APPLICATION), - luabind::value("POWER", SDLK_POWER), - luabind::value("KP_EQUALS", SDLK_KP_EQUALS), - luabind::value("F13", SDLK_F13), - luabind::value("F14", SDLK_F14), - luabind::value("F15", SDLK_F15), - luabind::value("F16", SDLK_F16), - luabind::value("F17", SDLK_F17), - luabind::value("F18", SDLK_F18), - luabind::value("F19", SDLK_F19), - luabind::value("F20", SDLK_F20), - luabind::value("F21", SDLK_F21), - luabind::value("F22", SDLK_F22), - luabind::value("F23", SDLK_F23), - luabind::value("F24", SDLK_F24), - luabind::value("EXECUTE", SDLK_EXECUTE), - luabind::value("HELP", SDLK_HELP), - luabind::value("MENU", SDLK_MENU), - luabind::value("SELECT", SDLK_SELECT), - luabind::value("STOP", SDLK_STOP), - luabind::value("AGAIN", SDLK_AGAIN), - luabind::value("UNDO", SDLK_UNDO), - luabind::value("CUT", SDLK_CUT), - luabind::value("COPY", SDLK_COPY), - luabind::value("PASTE", SDLK_PASTE), - luabind::value("FIND", SDLK_FIND), - luabind::value("MUTE", SDLK_MUTE), - luabind::value("VOLUMEUP", SDLK_VOLUMEUP), - luabind::value("VOLUMEDOWN", SDLK_VOLUMEDOWN), - luabind::value("KP_COMMA", SDLK_KP_COMMA), - luabind::value("KP_EQUALSAS400", SDLK_KP_EQUALSAS400), - luabind::value("ALTERASE", SDLK_ALTERASE), - luabind::value("SYSREQ", SDLK_SYSREQ), - luabind::value("CANCEL", SDLK_CANCEL), - luabind::value("CLEAR", SDLK_CLEAR), - luabind::value("PRIOR", SDLK_PRIOR), - luabind::value("RETURN2", SDLK_RETURN2), - luabind::value("SEPARATOR", SDLK_SEPARATOR), - luabind::value("OUT", SDLK_OUT), - luabind::value("OPER", SDLK_OPER), - luabind::value("CLEARAGAIN", SDLK_CLEARAGAIN), - luabind::value("CRSEL", SDLK_CRSEL), - luabind::value("EXSEL", SDLK_EXSEL), - luabind::value("KP_00", SDLK_KP_00), - luabind::value("KP_000", SDLK_KP_000), - luabind::value("THOUSANDSSEPARATOR", SDLK_THOUSANDSSEPARATOR), - luabind::value("DECIMALSEPARATOR", SDLK_DECIMALSEPARATOR), - luabind::value("CURRENCYUNIT", SDLK_CURRENCYUNIT), - luabind::value("CURRENCYSUBUNIT", SDLK_CURRENCYSUBUNIT), - luabind::value("KP_LEFTPAREN", SDLK_KP_LEFTPAREN), - luabind::value("KP_RIGHTPAREN", SDLK_KP_RIGHTPAREN), - luabind::value("KP_LEFTBRACE", SDLK_KP_LEFTBRACE), - luabind::value("KP_RIGHTBRACE", SDLK_KP_RIGHTBRACE), - luabind::value("KP_TAB", SDLK_KP_TAB), - luabind::value("KP_BACKSPACE", SDLK_KP_BACKSPACE), - luabind::value("KP_A", SDLK_KP_A), - luabind::value("KP_B", SDLK_KP_B), - luabind::value("KP_C", SDLK_KP_C), - luabind::value("KP_D", SDLK_KP_D), - luabind::value("KP_E", SDLK_KP_E), - luabind::value("KP_F", SDLK_KP_F), - luabind::value("KP_XOR", SDLK_KP_XOR), - luabind::value("KP_POWER", SDLK_KP_POWER), - luabind::value("KP_PERCENT", SDLK_KP_PERCENT), - luabind::value("KP_LESS", SDLK_KP_LESS), - luabind::value("KP_GREATER", SDLK_KP_GREATER), - luabind::value("KP_AMPERSAND", SDLK_KP_AMPERSAND), - luabind::value("KP_DBLAMPERSAND", SDLK_KP_DBLAMPERSAND), - luabind::value("KP_VERTICALBAR", SDLK_KP_VERTICALBAR), - luabind::value("KP_DBLVERTICALBAR", SDLK_KP_DBLVERTICALBAR), - luabind::value("KP_COLON", SDLK_KP_COLON), - luabind::value("KP_HASH", SDLK_KP_HASH), - luabind::value("KP_SPACE", SDLK_KP_SPACE), - luabind::value("KP_AT", SDLK_KP_AT), - luabind::value("KP_EXCLAM", SDLK_KP_EXCLAM), - luabind::value("KP_MEMSTORE", SDLK_KP_MEMSTORE), - luabind::value("KP_MEMRECALL", SDLK_KP_MEMRECALL), - luabind::value("KP_MEMCLEAR", SDLK_KP_MEMCLEAR), - luabind::value("KP_MEMADD", SDLK_KP_MEMADD), - luabind::value("KP_MEMSUBTRACT", SDLK_KP_MEMSUBTRACT), - luabind::value("KP_MEMMULTIPLY", SDLK_KP_MEMMULTIPLY), - luabind::value("KP_MEMDIVIDE", SDLK_KP_MEMDIVIDE), - luabind::value("KP_PLUSMINUS", SDLK_KP_PLUSMINUS), - luabind::value("KP_CLEAR", SDLK_KP_CLEAR), - luabind::value("KP_CLEARENTRY", SDLK_KP_CLEARENTRY), - luabind::value("KP_BINARY", SDLK_KP_BINARY), - luabind::value("KP_OCTAL", SDLK_KP_OCTAL), - luabind::value("KP_DECIMAL", SDLK_KP_DECIMAL), - luabind::value("KP_HEXADECIMAL", SDLK_KP_HEXADECIMAL), - luabind::value("LCTRL", SDLK_LCTRL), - luabind::value("LSHIFT", SDLK_LSHIFT), - luabind::value("LALT", SDLK_LALT), - luabind::value("LGUI", SDLK_LGUI), - luabind::value("RCTRL", SDLK_RCTRL), - luabind::value("RSHIFT", SDLK_RSHIFT), - luabind::value("RALT", SDLK_RALT), - luabind::value("RGUI", SDLK_RGUI), - luabind::value("MODE", SDLK_MODE), - luabind::value("AUDIONEXT", SDLK_MEDIA_NEXT_TRACK), - luabind::value("AUDIOPREV", SDLK_MEDIA_PREVIOUS_TRACK), - luabind::value("AUDIOSTOP", SDLK_MEDIA_STOP), - luabind::value("AUDIOPLAY", SDLK_MEDIA_PLAY), - luabind::value("AUDIOMUTE", SDLK_MUTE), - luabind::value("MEDIASELECT", SDLK_MEDIA_SELECT), - luabind::value("AC_SEARCH", SDLK_AC_SEARCH), - luabind::value("AC_HOME", SDLK_AC_HOME), - luabind::value("AC_BACK", SDLK_AC_BACK), - luabind::value("AC_FORWARD", SDLK_AC_FORWARD), - luabind::value("AC_STOP", SDLK_AC_STOP), - luabind::value("AC_REFRESH", SDLK_AC_REFRESH), - luabind::value("AC_BOOKMARKS", SDLK_AC_BOOKMARKS), - luabind::value("EJECT", SDLK_MEDIA_EJECT), - luabind::value("SLEEP", SDLK_SLEEP)]; + .addEnum({{"UNKNOWN", SDLK_UNKNOWN}, + {"RETURN", SDLK_RETURN}, + {"ESCAPE", SDLK_ESCAPE}, + {"BACKSPACE", SDLK_BACKSPACE}, + {"TAB", SDLK_TAB}, + {"SPACE", SDLK_SPACE}, + {"EXCLAIM", SDLK_EXCLAIM}, + {"QUOTEDBL", SDLK_DBLAPOSTROPHE}, + {"HASH", SDLK_HASH}, + {"PERCENT", SDLK_PERCENT}, + {"DOLLAR", SDLK_DOLLAR}, + {"AMPERSAND", SDLK_AMPERSAND}, + {"QUOTE", SDLK_APOSTROPHE}, + {"LEFTPAREN", SDLK_LEFTPAREN}, + {"RIGHTPAREN", SDLK_RIGHTPAREN}, + {"ASTERISK", SDLK_ASTERISK}, + {"PLUS", SDLK_PLUS}, + {"COMMA", SDLK_COMMA}, + {"MINUS", SDLK_MINUS}, + {"PERIOD", SDLK_PERIOD}, + {"SLASH", SDLK_SLASH}, + {"K_0", SDLK_0}, + {"K_1", SDLK_1}, + {"K_2", SDLK_2}, + {"K_3", SDLK_3}, + {"K_4", SDLK_4}, + {"K_5", SDLK_5}, + {"K_6", SDLK_6}, + {"K_7", SDLK_7}, + {"K_8", SDLK_8}, + {"K_9", SDLK_9}, + {"COLON", SDLK_COLON}, + {"SEMICOLON", SDLK_SEMICOLON}, + {"LESS", SDLK_LESS}, + {"EQUALS", SDLK_EQUALS}, + {"GREATER", SDLK_GREATER}, + {"QUESTION", SDLK_QUESTION}, + {"AT", SDLK_AT}, + {"LEFTBRACKET", SDLK_LEFTBRACKET}, + {"BACKSLASH", SDLK_BACKSLASH}, + {"RIGHTBRACKET", SDLK_RIGHTBRACKET}, + {"CARET", SDLK_CARET}, + {"UNDERSCORE", SDLK_UNDERSCORE}, + {"BACKQUOTE", SDLK_GRAVE}, + {"A", SDLK_A}, + {"B", SDLK_B}, + {"C", SDLK_C}, + {"D", SDLK_D}, + {"E", SDLK_E}, + {"F", SDLK_F}, + {"G", SDLK_G}, + {"H", SDLK_H}, + {"I", SDLK_I}, + {"J", SDLK_J}, + {"K", SDLK_K}, + {"L", SDLK_L}, + {"M", SDLK_M}, + {"N", SDLK_N}, + {"O", SDLK_O}, + {"P", SDLK_P}, + {"Q", SDLK_Q}, + {"R", SDLK_R}, + {"S", SDLK_S}, + {"T", SDLK_T}, + {"U", SDLK_U}, + {"V", SDLK_V}, + {"W", SDLK_W}, + {"X", SDLK_X}, + {"Y", SDLK_Y}, + {"Z", SDLK_Z}, + {"CAPSLOCK", SDLK_CAPSLOCK}, + {"F1", SDLK_F1}, + {"F2", SDLK_F2}, + {"F3", SDLK_F3}, + {"F4", SDLK_F4}, + {"F5", SDLK_F5}, + {"F6", SDLK_F6}, + {"F7", SDLK_F7}, + {"F8", SDLK_F8}, + {"F9", SDLK_F9}, + {"F10", SDLK_F10}, + {"F11", SDLK_F11}, + {"F12", SDLK_F12}, + {"PRINTSCREEN", SDLK_PRINTSCREEN}, + {"SCROLLLOCK", SDLK_SCROLLLOCK}, + {"PAUSE", SDLK_PAUSE}, + {"INSERT", SDLK_INSERT}, + {"HOME", SDLK_HOME}, + {"PAGEUP", SDLK_PAGEUP}, + {"DELETE", SDLK_DELETE}, + {"END", SDLK_END}, + {"PAGEDOWN", SDLK_PAGEDOWN}, + {"RIGHT", SDLK_RIGHT}, + {"LEFT", SDLK_LEFT}, + {"DOWN", SDLK_DOWN}, + {"UP", SDLK_UP}, + {"NUMLOCKCLEAR", SDLK_NUMLOCKCLEAR}, + {"KP_DIVIDE", SDLK_KP_DIVIDE}, + {"KP_MULTIPLY", SDLK_KP_MULTIPLY}, + {"KP_MINUS", SDLK_KP_MINUS}, + {"KP_PLUS", SDLK_KP_PLUS}, + {"KP_ENTER", SDLK_KP_ENTER}, + {"KP_1", SDLK_KP_1}, + {"KP_2", SDLK_KP_2}, + {"KP_3", SDLK_KP_3}, + {"KP_4", SDLK_KP_4}, + {"KP_5", SDLK_KP_5}, + {"KP_6", SDLK_KP_6}, + {"KP_7", SDLK_KP_7}, + {"KP_8", SDLK_KP_8}, + {"KP_9", SDLK_KP_9}, + {"KP_0", SDLK_KP_0}, + {"KP_PERIOD", SDLK_KP_PERIOD}, + {"APPLICATION", SDLK_APPLICATION}, + {"POWER", SDLK_POWER}, + {"KP_EQUALS", SDLK_KP_EQUALS}, + {"F13", SDLK_F13}, + {"F14", SDLK_F14}, + {"F15", SDLK_F15}, + {"F16", SDLK_F16}, + {"F17", SDLK_F17}, + {"F18", SDLK_F18}, + {"F19", SDLK_F19}, + {"F20", SDLK_F20}, + {"F21", SDLK_F21}, + {"F22", SDLK_F22}, + {"F23", SDLK_F23}, + {"F24", SDLK_F24}, + {"EXECUTE", SDLK_EXECUTE}, + {"HELP", SDLK_HELP}, + {"MENU", SDLK_MENU}, + {"SELECT", SDLK_SELECT}, + {"STOP", SDLK_STOP}, + {"AGAIN", SDLK_AGAIN}, + {"UNDO", SDLK_UNDO}, + {"CUT", SDLK_CUT}, + {"COPY", SDLK_COPY}, + {"PASTE", SDLK_PASTE}, + {"FIND", SDLK_FIND}, + {"MUTE", SDLK_MUTE}, + {"VOLUMEUP", SDLK_VOLUMEUP}, + {"VOLUMEDOWN", SDLK_VOLUMEDOWN}, + {"KP_COMMA", SDLK_KP_COMMA}, + {"KP_EQUALSAS400", SDLK_KP_EQUALSAS400}, + {"ALTERASE", SDLK_ALTERASE}, + {"SYSREQ", SDLK_SYSREQ}, + {"CANCEL", SDLK_CANCEL}, + {"CLEAR", SDLK_CLEAR}, + {"PRIOR", SDLK_PRIOR}, + {"RETURN2", SDLK_RETURN2}, + {"SEPARATOR", SDLK_SEPARATOR}, + {"OUT", SDLK_OUT}, + {"OPER", SDLK_OPER}, + {"CLEARAGAIN", SDLK_CLEARAGAIN}, + {"CRSEL", SDLK_CRSEL}, + {"EXSEL", SDLK_EXSEL}, + {"KP_00", SDLK_KP_00}, + {"KP_000", SDLK_KP_000}, + {"THOUSANDSSEPARATOR", SDLK_THOUSANDSSEPARATOR}, + {"DECIMALSEPARATOR", SDLK_DECIMALSEPARATOR}, + {"CURRENCYUNIT", SDLK_CURRENCYUNIT}, + {"CURRENCYSUBUNIT", SDLK_CURRENCYSUBUNIT}, + {"KP_LEFTPAREN", SDLK_KP_LEFTPAREN}, + {"KP_RIGHTPAREN", SDLK_KP_RIGHTPAREN}, + {"KP_LEFTBRACE", SDLK_KP_LEFTBRACE}, + {"KP_RIGHTBRACE", SDLK_KP_RIGHTBRACE}, + {"KP_TAB", SDLK_KP_TAB}, + {"KP_BACKSPACE", SDLK_KP_BACKSPACE}, + {"KP_A", SDLK_KP_A}, + {"KP_B", SDLK_KP_B}, + {"KP_C", SDLK_KP_C}, + {"KP_D", SDLK_KP_D}, + {"KP_E", SDLK_KP_E}, + {"KP_F", SDLK_KP_F}, + {"KP_XOR", SDLK_KP_XOR}, + {"KP_POWER", SDLK_KP_POWER}, + {"KP_PERCENT", SDLK_KP_PERCENT}, + {"KP_LESS", SDLK_KP_LESS}, + {"KP_GREATER", SDLK_KP_GREATER}, + {"KP_AMPERSAND", SDLK_KP_AMPERSAND}, + {"KP_DBLAMPERSAND", SDLK_KP_DBLAMPERSAND}, + {"KP_VERTICALBAR", SDLK_KP_VERTICALBAR}, + {"KP_DBLVERTICALBAR", SDLK_KP_DBLVERTICALBAR}, + {"KP_COLON", SDLK_KP_COLON}, + {"KP_HASH", SDLK_KP_HASH}, + {"KP_SPACE", SDLK_KP_SPACE}, + {"KP_AT", SDLK_KP_AT}, + {"KP_EXCLAM", SDLK_KP_EXCLAM}, + {"KP_MEMSTORE", SDLK_KP_MEMSTORE}, + {"KP_MEMRECALL", SDLK_KP_MEMRECALL}, + {"KP_MEMCLEAR", SDLK_KP_MEMCLEAR}, + {"KP_MEMADD", SDLK_KP_MEMADD}, + {"KP_MEMSUBTRACT", SDLK_KP_MEMSUBTRACT}, + {"KP_MEMMULTIPLY", SDLK_KP_MEMMULTIPLY}, + {"KP_MEMDIVIDE", SDLK_KP_MEMDIVIDE}, + {"KP_PLUSMINUS", SDLK_KP_PLUSMINUS}, + {"KP_CLEAR", SDLK_KP_CLEAR}, + {"KP_CLEARENTRY", SDLK_KP_CLEARENTRY}, + {"KP_BINARY", SDLK_KP_BINARY}, + {"KP_OCTAL", SDLK_KP_OCTAL}, + {"KP_DECIMAL", SDLK_KP_DECIMAL}, + {"KP_HEXADECIMAL", SDLK_KP_HEXADECIMAL}, + {"LCTRL", SDLK_LCTRL}, + {"LSHIFT", SDLK_LSHIFT}, + {"LALT", SDLK_LALT}, + {"LGUI", SDLK_LGUI}, + {"RCTRL", SDLK_RCTRL}, + {"RSHIFT", SDLK_RSHIFT}, + {"RALT", SDLK_RALT}, + {"RGUI", SDLK_RGUI}, + {"MODE", SDLK_MODE}, + {"AUDIONEXT", SDLK_MEDIA_NEXT_TRACK}, + {"AUDIOPREV", SDLK_MEDIA_PREVIOUS_TRACK}, + {"AUDIOSTOP", SDLK_MEDIA_STOP}, + {"AUDIOPLAY", SDLK_MEDIA_PLAY}, + {"AUDIOMUTE", SDLK_MUTE}, + {"MEDIASELECT", SDLK_MEDIA_SELECT}, + {"AC_SEARCH", SDLK_AC_SEARCH}, + {"AC_HOME", SDLK_AC_HOME}, + {"AC_BACK", SDLK_AC_BACK}, + {"AC_FORWARD", SDLK_AC_FORWARD}, + {"AC_STOP", SDLK_AC_STOP}, + {"AC_REFRESH", SDLK_AC_REFRESH}, + {"AC_BOOKMARKS", SDLK_AC_BOOKMARKS}, + {"EJECT", SDLK_MEDIA_EJECT}, + {"SLEEP", SDLK_SLEEP}}); } LuaBindingRegisterFunctionDefinitionForType(InputLuaBindings, SDL_Scancode) { - return luabind::class_("Scancode") + registry.Class("Scancode") // Make sure to update https://github.com/cortex-command-community/Cortex-Command-Community-Project-Source/wiki/SDL-Keycode-and-Scancode-enum-values-in-Lua#scan-codes if any changes are made. - .enum_("Scancode")[luabind::value("UNKNOWN", SDL_SCANCODE_UNKNOWN), - luabind::value("A", SDL_SCANCODE_A), - luabind::value("B", SDL_SCANCODE_B), - luabind::value("C", SDL_SCANCODE_C), - luabind::value("D", SDL_SCANCODE_D), - luabind::value("E", SDL_SCANCODE_E), - luabind::value("F", SDL_SCANCODE_F), - luabind::value("G", SDL_SCANCODE_G), - luabind::value("H", SDL_SCANCODE_H), - luabind::value("I", SDL_SCANCODE_I), - luabind::value("J", SDL_SCANCODE_J), - luabind::value("K", SDL_SCANCODE_K), - luabind::value("L", SDL_SCANCODE_L), - luabind::value("M", SDL_SCANCODE_M), - luabind::value("N", SDL_SCANCODE_N), - luabind::value("O", SDL_SCANCODE_O), - luabind::value("P", SDL_SCANCODE_P), - luabind::value("Q", SDL_SCANCODE_Q), - luabind::value("R", SDL_SCANCODE_R), - luabind::value("S", SDL_SCANCODE_S), - luabind::value("T", SDL_SCANCODE_T), - luabind::value("U", SDL_SCANCODE_U), - luabind::value("V", SDL_SCANCODE_V), - luabind::value("W", SDL_SCANCODE_W), - luabind::value("X", SDL_SCANCODE_X), - luabind::value("Y", SDL_SCANCODE_Y), - luabind::value("Z", SDL_SCANCODE_Z), - luabind::value("K_1", SDL_SCANCODE_1), - luabind::value("K_2", SDL_SCANCODE_2), - luabind::value("K_3", SDL_SCANCODE_3), - luabind::value("K_4", SDL_SCANCODE_4), - luabind::value("K_5", SDL_SCANCODE_5), - luabind::value("K_6", SDL_SCANCODE_6), - luabind::value("K_7", SDL_SCANCODE_7), - luabind::value("K_8", SDL_SCANCODE_8), - luabind::value("K_9", SDL_SCANCODE_9), - luabind::value("K_0", SDL_SCANCODE_0), - luabind::value("RETURN", SDL_SCANCODE_RETURN), - luabind::value("ESCAPE", SDL_SCANCODE_ESCAPE), - luabind::value("BACKSPACE", SDL_SCANCODE_BACKSPACE), - luabind::value("TAB", SDL_SCANCODE_TAB), - luabind::value("SPACE", SDL_SCANCODE_SPACE), - luabind::value("MINUS", SDL_SCANCODE_MINUS), - luabind::value("EQUALS", SDL_SCANCODE_EQUALS), - luabind::value("LEFTBRACKET", SDL_SCANCODE_LEFTBRACKET), - luabind::value("RIGHTBRACKET", SDL_SCANCODE_RIGHTBRACKET), - luabind::value("BACKSLASH", SDL_SCANCODE_BACKSLASH), - luabind::value("NONUSHASH", SDL_SCANCODE_NONUSHASH), - luabind::value("SEMICOLON", SDL_SCANCODE_SEMICOLON), - luabind::value("APOSTROPHE", SDL_SCANCODE_APOSTROPHE), - luabind::value("GRAVE", SDL_SCANCODE_GRAVE), - luabind::value("COMMA", SDL_SCANCODE_COMMA), - luabind::value("PERIOD", SDL_SCANCODE_PERIOD), - luabind::value("SLASH", SDL_SCANCODE_SLASH), - luabind::value("CAPSLOCK", SDL_SCANCODE_CAPSLOCK), - luabind::value("F1", SDL_SCANCODE_F1), - luabind::value("F2", SDL_SCANCODE_F2), - luabind::value("F3", SDL_SCANCODE_F3), - luabind::value("F4", SDL_SCANCODE_F4), - luabind::value("F5", SDL_SCANCODE_F5), - luabind::value("F6", SDL_SCANCODE_F6), - luabind::value("F7", SDL_SCANCODE_F7), - luabind::value("F8", SDL_SCANCODE_F8), - luabind::value("F9", SDL_SCANCODE_F9), - luabind::value("F10", SDL_SCANCODE_F10), - luabind::value("F11", SDL_SCANCODE_F11), - luabind::value("F12", SDL_SCANCODE_F12), - luabind::value("PRINTSCREEN", SDL_SCANCODE_PRINTSCREEN), - luabind::value("SCROLLLOCK", SDL_SCANCODE_SCROLLLOCK), - luabind::value("PAUSE", SDL_SCANCODE_PAUSE), - luabind::value("INSERT", SDL_SCANCODE_INSERT), - luabind::value("HOME", SDL_SCANCODE_HOME), - luabind::value("PAGEUP", SDL_SCANCODE_PAGEUP), - luabind::value("DELETE", SDL_SCANCODE_DELETE), - luabind::value("END", SDL_SCANCODE_END), - luabind::value("PAGEDOWN", SDL_SCANCODE_PAGEDOWN), - luabind::value("RIGHT", SDL_SCANCODE_RIGHT), - luabind::value("LEFT", SDL_SCANCODE_LEFT), - luabind::value("DOWN", SDL_SCANCODE_DOWN), - luabind::value("UP", SDL_SCANCODE_UP), - luabind::value("NUMLOCKCLEAR", SDL_SCANCODE_NUMLOCKCLEAR), - luabind::value("KP_DIVIDE", SDL_SCANCODE_KP_DIVIDE), - luabind::value("KP_MULTIPLY", SDL_SCANCODE_KP_MULTIPLY), - luabind::value("KP_MINUS", SDL_SCANCODE_KP_MINUS), - luabind::value("KP_PLUS", SDL_SCANCODE_KP_PLUS), - luabind::value("KP_ENTER", SDL_SCANCODE_KP_ENTER), - luabind::value("KP_1", SDL_SCANCODE_KP_1), - luabind::value("KP_2", SDL_SCANCODE_KP_2), - luabind::value("KP_3", SDL_SCANCODE_KP_3), - luabind::value("KP_4", SDL_SCANCODE_KP_4), - luabind::value("KP_5", SDL_SCANCODE_KP_5), - luabind::value("KP_6", SDL_SCANCODE_KP_6), - luabind::value("KP_7", SDL_SCANCODE_KP_7), - luabind::value("KP_8", SDL_SCANCODE_KP_8), - luabind::value("KP_9", SDL_SCANCODE_KP_9), - luabind::value("KP_0", SDL_SCANCODE_KP_0), - luabind::value("KP_PERIOD", SDL_SCANCODE_KP_PERIOD), - luabind::value("NONUSBACKSLASH", SDL_SCANCODE_NONUSBACKSLASH), - luabind::value("APPLICATION", SDL_SCANCODE_APPLICATION), - luabind::value("POWER", SDL_SCANCODE_POWER), - luabind::value("KP_EQUALS", SDL_SCANCODE_KP_EQUALS), - luabind::value("F13", SDL_SCANCODE_F13), - luabind::value("F14", SDL_SCANCODE_F14), - luabind::value("F15", SDL_SCANCODE_F15), - luabind::value("F16", SDL_SCANCODE_F16), - luabind::value("F17", SDL_SCANCODE_F17), - luabind::value("F18", SDL_SCANCODE_F18), - luabind::value("F19", SDL_SCANCODE_F19), - luabind::value("F20", SDL_SCANCODE_F20), - luabind::value("F21", SDL_SCANCODE_F21), - luabind::value("F22", SDL_SCANCODE_F22), - luabind::value("F23", SDL_SCANCODE_F23), - luabind::value("F24", SDL_SCANCODE_F24), - luabind::value("EXECUTE", SDL_SCANCODE_EXECUTE), - luabind::value("HELP", SDL_SCANCODE_HELP), - luabind::value("MENU", SDL_SCANCODE_MENU), - luabind::value("SELECT", SDL_SCANCODE_SELECT), - luabind::value("STOP", SDL_SCANCODE_STOP), - luabind::value("AGAIN", SDL_SCANCODE_AGAIN), - luabind::value("UNDO", SDL_SCANCODE_UNDO), - luabind::value("CUT", SDL_SCANCODE_CUT), - luabind::value("COPY", SDL_SCANCODE_COPY), - luabind::value("PASTE", SDL_SCANCODE_PASTE), - luabind::value("FIND", SDL_SCANCODE_FIND), - luabind::value("MUTE", SDL_SCANCODE_MUTE), - luabind::value("VOLUMEUP", SDL_SCANCODE_VOLUMEUP), - luabind::value("VOLUMEDOWN", SDL_SCANCODE_VOLUMEDOWN), - luabind::value("KP_COMMA", SDL_SCANCODE_KP_COMMA), - luabind::value("KP_EQUALSAS400", SDL_SCANCODE_KP_EQUALSAS400), - luabind::value("INTERNATIONAL1", SDL_SCANCODE_INTERNATIONAL1), - luabind::value("INTERNATIONAL2", SDL_SCANCODE_INTERNATIONAL2), - luabind::value("INTERNATIONAL3", SDL_SCANCODE_INTERNATIONAL3), - luabind::value("INTERNATIONAL4", SDL_SCANCODE_INTERNATIONAL4), - luabind::value("INTERNATIONAL5", SDL_SCANCODE_INTERNATIONAL5), - luabind::value("INTERNATIONAL6", SDL_SCANCODE_INTERNATIONAL6), - luabind::value("INTERNATIONAL7", SDL_SCANCODE_INTERNATIONAL7), - luabind::value("INTERNATIONAL8", SDL_SCANCODE_INTERNATIONAL8), - luabind::value("INTERNATIONAL9", SDL_SCANCODE_INTERNATIONAL9), - luabind::value("LANG1", SDL_SCANCODE_LANG1), - luabind::value("LANG2", SDL_SCANCODE_LANG2), - luabind::value("LANG3", SDL_SCANCODE_LANG3), - luabind::value("LANG4", SDL_SCANCODE_LANG4), - luabind::value("LANG5", SDL_SCANCODE_LANG5), - luabind::value("LANG6", SDL_SCANCODE_LANG6), - luabind::value("LANG7", SDL_SCANCODE_LANG7), - luabind::value("LANG8", SDL_SCANCODE_LANG8), - luabind::value("LANG9", SDL_SCANCODE_LANG9), - luabind::value("ALTERASE", SDL_SCANCODE_ALTERASE), - luabind::value("SYSREQ", SDL_SCANCODE_SYSREQ), - luabind::value("CANCEL", SDL_SCANCODE_CANCEL), - luabind::value("CLEAR", SDL_SCANCODE_CLEAR), - luabind::value("PRIOR", SDL_SCANCODE_PRIOR), - luabind::value("RETURN2", SDL_SCANCODE_RETURN2), - luabind::value("SEPARATOR", SDL_SCANCODE_SEPARATOR), - luabind::value("OUT", SDL_SCANCODE_OUT), - luabind::value("OPER", SDL_SCANCODE_OPER), - luabind::value("CLEARAGAIN", SDL_SCANCODE_CLEARAGAIN), - luabind::value("CRSEL", SDL_SCANCODE_CRSEL), - luabind::value("EXSEL", SDL_SCANCODE_EXSEL), - luabind::value("KP_00", SDL_SCANCODE_KP_00), - luabind::value("KP_000", SDL_SCANCODE_KP_000), - luabind::value("THOUSANDSSEPARATOR", SDL_SCANCODE_THOUSANDSSEPARATOR), - luabind::value("DECIMALSEPARATOR", SDL_SCANCODE_DECIMALSEPARATOR), - luabind::value("CURRENCYUNIT", SDL_SCANCODE_CURRENCYUNIT), - luabind::value("CURRENCYSUBUNIT", SDL_SCANCODE_CURRENCYSUBUNIT), - luabind::value("KP_LEFTPAREN", SDL_SCANCODE_KP_LEFTPAREN), - luabind::value("KP_RIGHTPAREN", SDL_SCANCODE_KP_RIGHTPAREN), - luabind::value("KP_LEFTBRACE", SDL_SCANCODE_KP_LEFTBRACE), - luabind::value("KP_RIGHTBRACE", SDL_SCANCODE_KP_RIGHTBRACE), - luabind::value("KP_TAB", SDL_SCANCODE_KP_TAB), - luabind::value("KP_BACKSPACE", SDL_SCANCODE_KP_BACKSPACE), - luabind::value("KP_A", SDL_SCANCODE_KP_A), - luabind::value("KP_B", SDL_SCANCODE_KP_B), - luabind::value("KP_C", SDL_SCANCODE_KP_C), - luabind::value("KP_D", SDL_SCANCODE_KP_D), - luabind::value("KP_E", SDL_SCANCODE_KP_E), - luabind::value("KP_F", SDL_SCANCODE_KP_F), - luabind::value("KP_XOR", SDL_SCANCODE_KP_XOR), - luabind::value("KP_POWER", SDL_SCANCODE_KP_POWER), - luabind::value("KP_PERCENT", SDL_SCANCODE_KP_PERCENT), - luabind::value("KP_LESS", SDL_SCANCODE_KP_LESS), - luabind::value("KP_GREATER", SDL_SCANCODE_KP_GREATER), - luabind::value("KP_AMPERSAND", SDL_SCANCODE_KP_AMPERSAND), - luabind::value("KP_DBLAMPERSAND", SDL_SCANCODE_KP_DBLAMPERSAND), - luabind::value("KP_VERTICALBAR", SDL_SCANCODE_KP_VERTICALBAR), - luabind::value("KP_DBLVERTICALBAR", SDL_SCANCODE_KP_DBLVERTICALBAR), - luabind::value("KP_COLON", SDL_SCANCODE_KP_COLON), - luabind::value("KP_HASH", SDL_SCANCODE_KP_HASH), - luabind::value("KP_SPACE", SDL_SCANCODE_KP_SPACE), - luabind::value("KP_AT", SDL_SCANCODE_KP_AT), - luabind::value("KP_EXCLAM", SDL_SCANCODE_KP_EXCLAM), - luabind::value("KP_MEMSTORE", SDL_SCANCODE_KP_MEMSTORE), - luabind::value("KP_MEMRECALL", SDL_SCANCODE_KP_MEMRECALL), - luabind::value("KP_MEMCLEAR", SDL_SCANCODE_KP_MEMCLEAR), - luabind::value("KP_MEMADD", SDL_SCANCODE_KP_MEMADD), - luabind::value("KP_MEMSUBTRACT", SDL_SCANCODE_KP_MEMSUBTRACT), - luabind::value("KP_MEMMULTIPLY", SDL_SCANCODE_KP_MEMMULTIPLY), - luabind::value("KP_MEMDIVIDE", SDL_SCANCODE_KP_MEMDIVIDE), - luabind::value("KP_PLUSMINUS", SDL_SCANCODE_KP_PLUSMINUS), - luabind::value("KP_CLEAR", SDL_SCANCODE_KP_CLEAR), - luabind::value("KP_CLEARENTRY", SDL_SCANCODE_KP_CLEARENTRY), - luabind::value("KP_BINARY", SDL_SCANCODE_KP_BINARY), - luabind::value("KP_OCTAL", SDL_SCANCODE_KP_OCTAL), - luabind::value("KP_DECIMAL", SDL_SCANCODE_KP_DECIMAL), - luabind::value("KP_HEXADECIMAL", SDL_SCANCODE_KP_HEXADECIMAL), - luabind::value("LCTRL", SDL_SCANCODE_LCTRL), - luabind::value("LSHIFT", SDL_SCANCODE_LSHIFT), - luabind::value("LALT", SDL_SCANCODE_LALT), - luabind::value("LGUI", SDL_SCANCODE_LGUI), - luabind::value("RCTRL", SDL_SCANCODE_RCTRL), - luabind::value("RSHIFT", SDL_SCANCODE_RSHIFT), - luabind::value("RALT", SDL_SCANCODE_RALT), - luabind::value("RGUI", SDL_SCANCODE_RGUI), - luabind::value("MODE", SDL_SCANCODE_MODE), - luabind::value("AUDIONEXT", SDL_SCANCODE_MEDIA_NEXT_TRACK), - luabind::value("AUDIOPREV", SDL_SCANCODE_MEDIA_PREVIOUS_TRACK), - luabind::value("AUDIOSTOP", SDL_SCANCODE_MEDIA_STOP), - luabind::value("AUDIOPLAY", SDL_SCANCODE_MEDIA_PLAY), - luabind::value("AUDIOMUTE", SDL_SCANCODE_MUTE), - luabind::value("MEDIASELECT", SDL_SCANCODE_MEDIA_SELECT), - luabind::value("AC_SEARCH", SDL_SCANCODE_AC_SEARCH), - luabind::value("AC_HOME", SDL_SCANCODE_AC_HOME), - luabind::value("AC_BACK", SDL_SCANCODE_AC_BACK), - luabind::value("AC_FORWARD", SDL_SCANCODE_AC_FORWARD), - luabind::value("AC_STOP", SDL_SCANCODE_AC_STOP), - luabind::value("AC_REFRESH", SDL_SCANCODE_AC_REFRESH), - luabind::value("AC_BOOKMARKS", SDL_SCANCODE_AC_BOOKMARKS), - luabind::value("EJECT", SDL_SCANCODE_MEDIA_EJECT), - luabind::value("SLEEP", SDL_SCANCODE_SLEEP), - luabind::value("AUDIOREWIND", SDL_SCANCODE_MEDIA_REWIND), - luabind::value("AUDIOFASTFORWARD", SDL_SCANCODE_MEDIA_FAST_FORWARD), - luabind::value("NUM_SCANCODES", SDL_SCANCODE_COUNT)]; + .addEnum({{"UNKNOWN", SDL_SCANCODE_UNKNOWN}, + {"A", SDL_SCANCODE_A}, + {"B", SDL_SCANCODE_B}, + {"C", SDL_SCANCODE_C}, + {"D", SDL_SCANCODE_D}, + {"E", SDL_SCANCODE_E}, + {"F", SDL_SCANCODE_F}, + {"G", SDL_SCANCODE_G}, + {"H", SDL_SCANCODE_H}, + {"I", SDL_SCANCODE_I}, + {"J", SDL_SCANCODE_J}, + {"K", SDL_SCANCODE_K}, + {"L", SDL_SCANCODE_L}, + {"M", SDL_SCANCODE_M}, + {"N", SDL_SCANCODE_N}, + {"O", SDL_SCANCODE_O}, + {"P", SDL_SCANCODE_P}, + {"Q", SDL_SCANCODE_Q}, + {"R", SDL_SCANCODE_R}, + {"S", SDL_SCANCODE_S}, + {"T", SDL_SCANCODE_T}, + {"U", SDL_SCANCODE_U}, + {"V", SDL_SCANCODE_V}, + {"W", SDL_SCANCODE_W}, + {"X", SDL_SCANCODE_X}, + {"Y", SDL_SCANCODE_Y}, + {"Z", SDL_SCANCODE_Z}, + {"K_1", SDL_SCANCODE_1}, + {"K_2", SDL_SCANCODE_2}, + {"K_3", SDL_SCANCODE_3}, + {"K_4", SDL_SCANCODE_4}, + {"K_5", SDL_SCANCODE_5}, + {"K_6", SDL_SCANCODE_6}, + {"K_7", SDL_SCANCODE_7}, + {"K_8", SDL_SCANCODE_8}, + {"K_9", SDL_SCANCODE_9}, + {"K_0", SDL_SCANCODE_0}, + {"RETURN", SDL_SCANCODE_RETURN}, + {"ESCAPE", SDL_SCANCODE_ESCAPE}, + {"BACKSPACE", SDL_SCANCODE_BACKSPACE}, + {"TAB", SDL_SCANCODE_TAB}, + {"SPACE", SDL_SCANCODE_SPACE}, + {"MINUS", SDL_SCANCODE_MINUS}, + {"EQUALS", SDL_SCANCODE_EQUALS}, + {"LEFTBRACKET", SDL_SCANCODE_LEFTBRACKET}, + {"RIGHTBRACKET", SDL_SCANCODE_RIGHTBRACKET}, + {"BACKSLASH", SDL_SCANCODE_BACKSLASH}, + {"NONUSHASH", SDL_SCANCODE_NONUSHASH}, + {"SEMICOLON", SDL_SCANCODE_SEMICOLON}, + {"APOSTROPHE", SDL_SCANCODE_APOSTROPHE}, + {"GRAVE", SDL_SCANCODE_GRAVE}, + {"COMMA", SDL_SCANCODE_COMMA}, + {"PERIOD", SDL_SCANCODE_PERIOD}, + {"SLASH", SDL_SCANCODE_SLASH}, + {"CAPSLOCK", SDL_SCANCODE_CAPSLOCK}, + {"F1", SDL_SCANCODE_F1}, + {"F2", SDL_SCANCODE_F2}, + {"F3", SDL_SCANCODE_F3}, + {"F4", SDL_SCANCODE_F4}, + {"F5", SDL_SCANCODE_F5}, + {"F6", SDL_SCANCODE_F6}, + {"F7", SDL_SCANCODE_F7}, + {"F8", SDL_SCANCODE_F8}, + {"F9", SDL_SCANCODE_F9}, + {"F10", SDL_SCANCODE_F10}, + {"F11", SDL_SCANCODE_F11}, + {"F12", SDL_SCANCODE_F12}, + {"PRINTSCREEN", SDL_SCANCODE_PRINTSCREEN}, + {"SCROLLLOCK", SDL_SCANCODE_SCROLLLOCK}, + {"PAUSE", SDL_SCANCODE_PAUSE}, + {"INSERT", SDL_SCANCODE_INSERT}, + {"HOME", SDL_SCANCODE_HOME}, + {"PAGEUP", SDL_SCANCODE_PAGEUP}, + {"DELETE", SDL_SCANCODE_DELETE}, + {"END", SDL_SCANCODE_END}, + {"PAGEDOWN", SDL_SCANCODE_PAGEDOWN}, + {"RIGHT", SDL_SCANCODE_RIGHT}, + {"LEFT", SDL_SCANCODE_LEFT}, + {"DOWN", SDL_SCANCODE_DOWN}, + {"UP", SDL_SCANCODE_UP}, + {"NUMLOCKCLEAR", SDL_SCANCODE_NUMLOCKCLEAR}, + {"KP_DIVIDE", SDL_SCANCODE_KP_DIVIDE}, + {"KP_MULTIPLY", SDL_SCANCODE_KP_MULTIPLY}, + {"KP_MINUS", SDL_SCANCODE_KP_MINUS}, + {"KP_PLUS", SDL_SCANCODE_KP_PLUS}, + {"KP_ENTER", SDL_SCANCODE_KP_ENTER}, + {"KP_1", SDL_SCANCODE_KP_1}, + {"KP_2", SDL_SCANCODE_KP_2}, + {"KP_3", SDL_SCANCODE_KP_3}, + {"KP_4", SDL_SCANCODE_KP_4}, + {"KP_5", SDL_SCANCODE_KP_5}, + {"KP_6", SDL_SCANCODE_KP_6}, + {"KP_7", SDL_SCANCODE_KP_7}, + {"KP_8", SDL_SCANCODE_KP_8}, + {"KP_9", SDL_SCANCODE_KP_9}, + {"KP_0", SDL_SCANCODE_KP_0}, + {"KP_PERIOD", SDL_SCANCODE_KP_PERIOD}, + {"NONUSBACKSLASH", SDL_SCANCODE_NONUSBACKSLASH}, + {"APPLICATION", SDL_SCANCODE_APPLICATION}, + {"POWER", SDL_SCANCODE_POWER}, + {"KP_EQUALS", SDL_SCANCODE_KP_EQUALS}, + {"F13", SDL_SCANCODE_F13}, + {"F14", SDL_SCANCODE_F14}, + {"F15", SDL_SCANCODE_F15}, + {"F16", SDL_SCANCODE_F16}, + {"F17", SDL_SCANCODE_F17}, + {"F18", SDL_SCANCODE_F18}, + {"F19", SDL_SCANCODE_F19}, + {"F20", SDL_SCANCODE_F20}, + {"F21", SDL_SCANCODE_F21}, + {"F22", SDL_SCANCODE_F22}, + {"F23", SDL_SCANCODE_F23}, + {"F24", SDL_SCANCODE_F24}, + {"EXECUTE", SDL_SCANCODE_EXECUTE}, + {"HELP", SDL_SCANCODE_HELP}, + {"MENU", SDL_SCANCODE_MENU}, + {"SELECT", SDL_SCANCODE_SELECT}, + {"STOP", SDL_SCANCODE_STOP}, + {"AGAIN", SDL_SCANCODE_AGAIN}, + {"UNDO", SDL_SCANCODE_UNDO}, + {"CUT", SDL_SCANCODE_CUT}, + {"COPY", SDL_SCANCODE_COPY}, + {"PASTE", SDL_SCANCODE_PASTE}, + {"FIND", SDL_SCANCODE_FIND}, + {"MUTE", SDL_SCANCODE_MUTE}, + {"VOLUMEUP", SDL_SCANCODE_VOLUMEUP}, + {"VOLUMEDOWN", SDL_SCANCODE_VOLUMEDOWN}, + {"KP_COMMA", SDL_SCANCODE_KP_COMMA}, + {"KP_EQUALSAS400", SDL_SCANCODE_KP_EQUALSAS400}, + {"INTERNATIONAL1", SDL_SCANCODE_INTERNATIONAL1}, + {"INTERNATIONAL2", SDL_SCANCODE_INTERNATIONAL2}, + {"INTERNATIONAL3", SDL_SCANCODE_INTERNATIONAL3}, + {"INTERNATIONAL4", SDL_SCANCODE_INTERNATIONAL4}, + {"INTERNATIONAL5", SDL_SCANCODE_INTERNATIONAL5}, + {"INTERNATIONAL6", SDL_SCANCODE_INTERNATIONAL6}, + {"INTERNATIONAL7", SDL_SCANCODE_INTERNATIONAL7}, + {"INTERNATIONAL8", SDL_SCANCODE_INTERNATIONAL8}, + {"INTERNATIONAL9", SDL_SCANCODE_INTERNATIONAL9}, + {"LANG1", SDL_SCANCODE_LANG1}, + {"LANG2", SDL_SCANCODE_LANG2}, + {"LANG3", SDL_SCANCODE_LANG3}, + {"LANG4", SDL_SCANCODE_LANG4}, + {"LANG5", SDL_SCANCODE_LANG5}, + {"LANG6", SDL_SCANCODE_LANG6}, + {"LANG7", SDL_SCANCODE_LANG7}, + {"LANG8", SDL_SCANCODE_LANG8}, + {"LANG9", SDL_SCANCODE_LANG9}, + {"ALTERASE", SDL_SCANCODE_ALTERASE}, + {"SYSREQ", SDL_SCANCODE_SYSREQ}, + {"CANCEL", SDL_SCANCODE_CANCEL}, + {"CLEAR", SDL_SCANCODE_CLEAR}, + {"PRIOR", SDL_SCANCODE_PRIOR}, + {"RETURN2", SDL_SCANCODE_RETURN2}, + {"SEPARATOR", SDL_SCANCODE_SEPARATOR}, + {"OUT", SDL_SCANCODE_OUT}, + {"OPER", SDL_SCANCODE_OPER}, + {"CLEARAGAIN", SDL_SCANCODE_CLEARAGAIN}, + {"CRSEL", SDL_SCANCODE_CRSEL}, + {"EXSEL", SDL_SCANCODE_EXSEL}, + {"KP_00", SDL_SCANCODE_KP_00}, + {"KP_000", SDL_SCANCODE_KP_000}, + {"THOUSANDSSEPARATOR", SDL_SCANCODE_THOUSANDSSEPARATOR}, + {"DECIMALSEPARATOR", SDL_SCANCODE_DECIMALSEPARATOR}, + {"CURRENCYUNIT", SDL_SCANCODE_CURRENCYUNIT}, + {"CURRENCYSUBUNIT", SDL_SCANCODE_CURRENCYSUBUNIT}, + {"KP_LEFTPAREN", SDL_SCANCODE_KP_LEFTPAREN}, + {"KP_RIGHTPAREN", SDL_SCANCODE_KP_RIGHTPAREN}, + {"KP_LEFTBRACE", SDL_SCANCODE_KP_LEFTBRACE}, + {"KP_RIGHTBRACE", SDL_SCANCODE_KP_RIGHTBRACE}, + {"KP_TAB", SDL_SCANCODE_KP_TAB}, + {"KP_BACKSPACE", SDL_SCANCODE_KP_BACKSPACE}, + {"KP_A", SDL_SCANCODE_KP_A}, + {"KP_B", SDL_SCANCODE_KP_B}, + {"KP_C", SDL_SCANCODE_KP_C}, + {"KP_D", SDL_SCANCODE_KP_D}, + {"KP_E", SDL_SCANCODE_KP_E}, + {"KP_F", SDL_SCANCODE_KP_F}, + {"KP_XOR", SDL_SCANCODE_KP_XOR}, + {"KP_POWER", SDL_SCANCODE_KP_POWER}, + {"KP_PERCENT", SDL_SCANCODE_KP_PERCENT}, + {"KP_LESS", SDL_SCANCODE_KP_LESS}, + {"KP_GREATER", SDL_SCANCODE_KP_GREATER}, + {"KP_AMPERSAND", SDL_SCANCODE_KP_AMPERSAND}, + {"KP_DBLAMPERSAND", SDL_SCANCODE_KP_DBLAMPERSAND}, + {"KP_VERTICALBAR", SDL_SCANCODE_KP_VERTICALBAR}, + {"KP_DBLVERTICALBAR", SDL_SCANCODE_KP_DBLVERTICALBAR}, + {"KP_COLON", SDL_SCANCODE_KP_COLON}, + {"KP_HASH", SDL_SCANCODE_KP_HASH}, + {"KP_SPACE", SDL_SCANCODE_KP_SPACE}, + {"KP_AT", SDL_SCANCODE_KP_AT}, + {"KP_EXCLAM", SDL_SCANCODE_KP_EXCLAM}, + {"KP_MEMSTORE", SDL_SCANCODE_KP_MEMSTORE}, + {"KP_MEMRECALL", SDL_SCANCODE_KP_MEMRECALL}, + {"KP_MEMCLEAR", SDL_SCANCODE_KP_MEMCLEAR}, + {"KP_MEMADD", SDL_SCANCODE_KP_MEMADD}, + {"KP_MEMSUBTRACT", SDL_SCANCODE_KP_MEMSUBTRACT}, + {"KP_MEMMULTIPLY", SDL_SCANCODE_KP_MEMMULTIPLY}, + {"KP_MEMDIVIDE", SDL_SCANCODE_KP_MEMDIVIDE}, + {"KP_PLUSMINUS", SDL_SCANCODE_KP_PLUSMINUS}, + {"KP_CLEAR", SDL_SCANCODE_KP_CLEAR}, + {"KP_CLEARENTRY", SDL_SCANCODE_KP_CLEARENTRY}, + {"KP_BINARY", SDL_SCANCODE_KP_BINARY}, + {"KP_OCTAL", SDL_SCANCODE_KP_OCTAL}, + {"KP_DECIMAL", SDL_SCANCODE_KP_DECIMAL}, + {"KP_HEXADECIMAL", SDL_SCANCODE_KP_HEXADECIMAL}, + {"LCTRL", SDL_SCANCODE_LCTRL}, + {"LSHIFT", SDL_SCANCODE_LSHIFT}, + {"LALT", SDL_SCANCODE_LALT}, + {"LGUI", SDL_SCANCODE_LGUI}, + {"RCTRL", SDL_SCANCODE_RCTRL}, + {"RSHIFT", SDL_SCANCODE_RSHIFT}, + {"RALT", SDL_SCANCODE_RALT}, + {"RGUI", SDL_SCANCODE_RGUI}, + {"MODE", SDL_SCANCODE_MODE}, + {"AUDIONEXT", SDL_SCANCODE_MEDIA_NEXT_TRACK}, + {"AUDIOPREV", SDL_SCANCODE_MEDIA_PREVIOUS_TRACK}, + {"AUDIOSTOP", SDL_SCANCODE_MEDIA_STOP}, + {"AUDIOPLAY", SDL_SCANCODE_MEDIA_PLAY}, + {"AUDIOMUTE", SDL_SCANCODE_MUTE}, + {"MEDIASELECT", SDL_SCANCODE_MEDIA_SELECT}, + {"AC_SEARCH", SDL_SCANCODE_AC_SEARCH}, + {"AC_HOME", SDL_SCANCODE_AC_HOME}, + {"AC_BACK", SDL_SCANCODE_AC_BACK}, + {"AC_FORWARD", SDL_SCANCODE_AC_FORWARD}, + {"AC_STOP", SDL_SCANCODE_AC_STOP}, + {"AC_REFRESH", SDL_SCANCODE_AC_REFRESH}, + {"AC_BOOKMARKS", SDL_SCANCODE_AC_BOOKMARKS}, + {"EJECT", SDL_SCANCODE_MEDIA_EJECT}, + {"SLEEP", SDL_SCANCODE_SLEEP}, + {"AUDIOREWIND", SDL_SCANCODE_MEDIA_REWIND}, + {"AUDIOFASTFORWARD", SDL_SCANCODE_MEDIA_FAST_FORWARD}, + {"NUM_SCANCODES", SDL_SCANCODE_COUNT}}); } LuaBindingRegisterFunctionDefinitionForType(InputLuaBindings, SDL_GamepadButton) { - return luabind::class_("GamepadButton") + registry.Class("GamepadButton") - .enum_("GamepadButton")[luabind::value("INVALID", SDL_GAMEPAD_BUTTON_INVALID), - luabind::value("A", SDL_GAMEPAD_BUTTON_SOUTH), - luabind::value("B", SDL_GAMEPAD_BUTTON_EAST), - luabind::value("X", SDL_GAMEPAD_BUTTON_WEST), - luabind::value("Y", SDL_GAMEPAD_BUTTON_NORTH), - luabind::value("BACK", SDL_GAMEPAD_BUTTON_BACK), - luabind::value("GUIDE", SDL_GAMEPAD_BUTTON_GUIDE), - luabind::value("START", SDL_GAMEPAD_BUTTON_START), - luabind::value("LEFTSTICK", SDL_GAMEPAD_BUTTON_LEFT_STICK), - luabind::value("RIGHTSTICK", SDL_GAMEPAD_BUTTON_RIGHT_STICK), - luabind::value("LEFTSHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER), - luabind::value("RIGHTSHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER), - luabind::value("DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP), - luabind::value("DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN), - luabind::value("DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT), - luabind::value("DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT), - luabind::value("MAX", SDL_GAMEPAD_BUTTON_COUNT)]; + .addEnum({{"INVALID", SDL_GAMEPAD_BUTTON_INVALID}, + {"A", SDL_GAMEPAD_BUTTON_SOUTH}, + {"B", SDL_GAMEPAD_BUTTON_EAST}, + {"X", SDL_GAMEPAD_BUTTON_WEST}, + {"Y", SDL_GAMEPAD_BUTTON_NORTH}, + {"BACK", SDL_GAMEPAD_BUTTON_BACK}, + {"GUIDE", SDL_GAMEPAD_BUTTON_GUIDE}, + {"START", SDL_GAMEPAD_BUTTON_START}, + {"LEFTSTICK", SDL_GAMEPAD_BUTTON_LEFT_STICK}, + {"RIGHTSTICK", SDL_GAMEPAD_BUTTON_RIGHT_STICK}, + {"LEFTSHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER}, + {"RIGHTSHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER}, + {"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP}, + {"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN}, + {"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT}, + {"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT}, + {"MAX", SDL_GAMEPAD_BUTTON_COUNT}}); } LuaBindingRegisterFunctionDefinitionForType(InputLuaBindings, SDL_GamepadAxis) { - return luabind::class_("GamepadAxis") + registry.Class("GamepadAxis") - .enum_("GamepadAxis")[luabind::value("INVALID", SDL_GAMEPAD_AXIS_INVALID), - luabind::value("LEFTX", SDL_GAMEPAD_AXIS_LEFTX), - luabind::value("LEFTY", SDL_GAMEPAD_AXIS_LEFTY), - luabind::value("RIGHTX", SDL_GAMEPAD_AXIS_RIGHTX), - luabind::value("RIGHTY", SDL_GAMEPAD_AXIS_RIGHTY), - luabind::value("TRIGGERLEFT", SDL_GAMEPAD_AXIS_LEFT_TRIGGER), - luabind::value("TRIGGERRIGHT", SDL_GAMEPAD_AXIS_RIGHT_TRIGGER), - luabind::value("MAX", SDL_GAMEPAD_AXIS_COUNT)]; + .addEnum({{"INVALID", SDL_GAMEPAD_AXIS_INVALID}, + {"LEFTX", SDL_GAMEPAD_AXIS_LEFTX}, + {"LEFTY", SDL_GAMEPAD_AXIS_LEFTY}, + {"RIGHTX", SDL_GAMEPAD_AXIS_RIGHTX}, + {"RIGHTY", SDL_GAMEPAD_AXIS_RIGHTY}, + {"TRIGGERLEFT", SDL_GAMEPAD_AXIS_LEFT_TRIGGER}, + {"TRIGGERRIGHT", SDL_GAMEPAD_AXIS_RIGHT_TRIGGER}, + {"MAX", SDL_GAMEPAD_AXIS_COUNT}}); } diff --git a/Source/Lua/LuaBindingsManagers.cpp b/Source/Lua/LuaBindingsManagers.cpp index 55d60d8bfc..f9f8b62919 100644 --- a/Source/Lua/LuaBindingsManagers.cpp +++ b/Source/Lua/LuaBindingsManagers.cpp @@ -5,477 +5,477 @@ using namespace RTE; LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, ActivityMan) { - return luabind::class_("ActivityManager") - - .property("DefaultActivityType", &ActivityMan::GetDefaultActivityType, &ActivityMan::SetDefaultActivityType) - .property("DefaultActivityName", &ActivityMan::GetDefaultActivityName, &ActivityMan::SetDefaultActivityName) - - .def("SetStartActivity", &ActivityMan::SetStartActivity, luabind::adopt(_2)) // Transfers ownership of the Activity to start into the ActivityMan, adopts ownership (_1 is the this ptr) - .def("GetStartActivity", &ActivityMan::GetStartActivity) - .def("GetActivity", &ActivityMan::GetActivity) - .def("StartActivity", (int(ActivityMan::*)(Activity*)) & ActivityMan::StartActivity, luabind::adopt(_2)) // Transfers ownership of the Activity to start into the ActivityMan, adopts ownership (_1 is the this ptr) - .def("StartActivity", (int(ActivityMan::*)(const std::string&, const std::string&)) & ActivityMan::StartActivity) - .def("RestartActivity", &ActivityMan::RestartActivity) - .def("PauseActivity", &ActivityMan::PauseActivity) - .def("EndActivity", &ActivityMan::EndActivity) - .def("ActivityRunning", &ActivityMan::ActivityRunning) - .def("ActivityPaused", &ActivityMan::ActivityPaused) - .def("SaveGame", &ActivityMan::SaveCurrentGame) - .def("LoadGame", &ActivityMan::LoadAndLaunchGame); + registry.Class("ActivityManager") + + .addProperty("DefaultActivityType", &ActivityMan::GetDefaultActivityType, &ActivityMan::SetDefaultActivityType) + .addProperty("DefaultActivityName", &ActivityMan::GetDefaultActivityName, &ActivityMan::SetDefaultActivityName) + + .addFunction("SetStartActivity", &ActivityMan::SetStartActivity, LuaBinding::AdoptArg<2>) // Transfers ownership of the Activity to start into the ActivityMan, adopts ownership (_1 is the this ptr) + .addFunction("GetStartActivity", &ActivityMan::GetStartActivity) + .addFunction("GetActivity", &ActivityMan::GetActivity) + .addFunction("StartActivity", (int(ActivityMan::*)(Activity*)) & ActivityMan::StartActivity, LuaBinding::AdoptArg<2>) // Transfers ownership of the Activity to start into the ActivityMan, adopts ownership (_1 is the this ptr) + .addFunction("StartActivity", (int(ActivityMan::*)(const std::string&, const std::string&)) & ActivityMan::StartActivity) + .addFunction("RestartActivity", &ActivityMan::RestartActivity) + .addFunction("PauseActivity", &ActivityMan::PauseActivity) + .addFunction("EndActivity", &ActivityMan::EndActivity) + .addFunction("ActivityRunning", &ActivityMan::ActivityRunning) + .addFunction("ActivityPaused", &ActivityMan::ActivityPaused) + .addFunction("SaveGame", &ActivityMan::SaveCurrentGame) + .addFunction("LoadGame", &ActivityMan::LoadAndLaunchGame); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, AudioMan) { - return luabind::class_("AudioManager") - - .property("MusicVolume", &AudioMan::GetMusicVolume, &AudioMan::SetMusicVolume) - .property("SoundsVolume", &AudioMan::GetSoundsVolume, &AudioMan::SetSoundsVolume) - - .def("StopAll", &AudioMan::StopAll) - .def("GetGlobalPitch", &AudioMan::GetGlobalPitch) - .def("IsMusicPlaying", &AudioMan::IsMusicPlaying) - .def("SetMusicPitch", &AudioMan::SetMusicPitch) - .def("SetMusicMuffledState", &AudioMan::SetMusicMuffledState) - .def("PlaySound", (SoundContainer * (AudioMan::*)(const std::string& filePath)) & AudioMan::PlaySound, luabind::adopt(luabind::result)) - .def("PlaySound", (SoundContainer * (AudioMan::*)(const std::string& filePath, const Vector& position)) & AudioMan::PlaySound, luabind::adopt(luabind::result)) - .def("PlaySound", (SoundContainer * (AudioMan::*)(const std::string& filePath, const Vector& position, int player)) & AudioMan::PlaySound, luabind::adopt(luabind::result)); + registry.Class("AudioManager") + + .addProperty("MusicVolume", &AudioMan::GetMusicVolume, &AudioMan::SetMusicVolume) + .addProperty("SoundsVolume", &AudioMan::GetSoundsVolume, &AudioMan::SetSoundsVolume) + + .addFunction("StopAll", &AudioMan::StopAll) + .addFunction("GetGlobalPitch", &AudioMan::GetGlobalPitch) + .addFunction("IsMusicPlaying", &AudioMan::IsMusicPlaying) + .addFunction("SetMusicPitch", &AudioMan::SetMusicPitch) + .addFunction("SetMusicMuffledState", &AudioMan::SetMusicMuffledState) + .addFunction("PlaySound", (SoundContainer * (AudioMan::*)(const std::string& filePath)) & AudioMan::PlaySound, LuaBinding::AdoptResult) + .addFunction("PlaySound", (SoundContainer * (AudioMan::*)(const std::string& filePath, const Vector& position)) & AudioMan::PlaySound, LuaBinding::AdoptResult) + .addFunction("PlaySound", (SoundContainer * (AudioMan::*)(const std::string& filePath, const Vector& position, int player)) & AudioMan::PlaySound, LuaBinding::AdoptResult); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, MusicMan) { - return luabind::class_("MusicManager") - - .def("ResetMusicState", &MusicMan::ResetMusicState) - .def("IsMusicPlaying", &MusicMan::IsMusicPlaying) - .def("PlayDynamicSong", &LuaAdaptersMusicMan::PlayDynamicSong1) - .def("PlayDynamicSong", &LuaAdaptersMusicMan::PlayDynamicSong2) - .def("PlayDynamicSong", &LuaAdaptersMusicMan::PlayDynamicSong3) - .def("PlayDynamicSong", &LuaAdaptersMusicMan::PlayDynamicSong4) - .def("PlayDynamicSong", &LuaAdaptersMusicMan::PlayDynamicSong5) - .def("SetNextDynamicSongSection", &LuaAdaptersMusicMan::SetNextDynamicSongSection1) - .def("SetNextDynamicSongSection", &LuaAdaptersMusicMan::SetNextDynamicSongSection2) - .def("SetNextDynamicSongSection", &LuaAdaptersMusicMan::SetNextDynamicSongSection3) - .def("SetNextDynamicSongSection", &LuaAdaptersMusicMan::SetNextDynamicSongSection4) - .def("CyclePlayingSoundContainers", &LuaAdaptersMusicMan::CyclePlayingSoundContainers1) - .def("CyclePlayingSoundContainers", &LuaAdaptersMusicMan::CyclePlayingSoundContainers2) - .def("GetCurrentDynamicSongSectionType", &MusicMan::GetCurrentSongSectionType) - .def("EndDynamicMusic", &LuaAdaptersMusicMan::EndDynamicMusic1) - .def("EndDynamicMusic", &LuaAdaptersMusicMan::EndDynamicMusic2) - .def("PlayInterruptingMusic", &MusicMan::PlayInterruptingMusic) - .def("EndInterruptingMusic", &MusicMan::EndInterruptingMusic); + registry.Class("MusicManager") + + .addFunction("ResetMusicState", &MusicMan::ResetMusicState) + .addFunction("IsMusicPlaying", &MusicMan::IsMusicPlaying) + .addFunction("PlayDynamicSong", &LuaAdaptersMusicMan::PlayDynamicSong1) + .addFunction("PlayDynamicSong", &LuaAdaptersMusicMan::PlayDynamicSong2) + .addFunction("PlayDynamicSong", &LuaAdaptersMusicMan::PlayDynamicSong3) + .addFunction("PlayDynamicSong", &LuaAdaptersMusicMan::PlayDynamicSong4) + .addFunction("PlayDynamicSong", &LuaAdaptersMusicMan::PlayDynamicSong5) + .addFunction("SetNextDynamicSongSection", &LuaAdaptersMusicMan::SetNextDynamicSongSection1) + .addFunction("SetNextDynamicSongSection", &LuaAdaptersMusicMan::SetNextDynamicSongSection2) + .addFunction("SetNextDynamicSongSection", &LuaAdaptersMusicMan::SetNextDynamicSongSection3) + .addFunction("SetNextDynamicSongSection", &LuaAdaptersMusicMan::SetNextDynamicSongSection4) + .addFunction("CyclePlayingSoundContainers", &LuaAdaptersMusicMan::CyclePlayingSoundContainers1) + .addFunction("CyclePlayingSoundContainers", &LuaAdaptersMusicMan::CyclePlayingSoundContainers2) + .addFunction("GetCurrentDynamicSongSectionType", &MusicMan::GetCurrentSongSectionType) + .addFunction("EndDynamicMusic", &LuaAdaptersMusicMan::EndDynamicMusic1) + .addFunction("EndDynamicMusic", &LuaAdaptersMusicMan::EndDynamicMusic2) + .addFunction("PlayInterruptingMusic", &MusicMan::PlayInterruptingMusic) + .addFunction("EndInterruptingMusic", &MusicMan::EndInterruptingMusic); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, ConsoleMan) { - return luabind::class_("ConsoleManager") + registry.Class("ConsoleManager") - .def("PrintString", &ConsoleMan::PrintString) - .def("SaveInputLog", &ConsoleMan::SaveInputLog) - .def("SaveAllText", &ConsoleMan::SaveAllText) - .def("Clear", &ConsoleMan::ClearLog); + .addFunction("PrintString", &ConsoleMan::PrintString) + .addFunction("SaveInputLog", &ConsoleMan::SaveInputLog) + .addFunction("SaveAllText", &ConsoleMan::SaveAllText) + .addFunction("Clear", &ConsoleMan::ClearLog); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, FrameMan) { - return luabind::class_("FrameManager") - - .property("PlayerScreenWidth", &FrameMan::GetPlayerScreenWidth) - .property("PlayerScreenHeight", &FrameMan::GetPlayerScreenHeight) - .property("ScreenCount", &FrameMan::GetScreenCount) - .property("ResolutionMultiplier", &FrameMan::GetResolutionMultiplier) - - .def("IsHudDisabled", &FrameMan::IsHudDisabled) - .def("SetHudDisabled", &FrameMan::SetHudDisabled) - .def("LoadPalette", &FrameMan::LoadPalette) - .def("SetScreenText", &FrameMan::SetScreenText) - .def("ClearScreenText", &FrameMan::ClearScreenText) - .def("FadeInPalette", &FrameMan::FadeInPalette) - .def("FadeOutPalette", &FrameMan::FadeOutPalette) - .def("SaveScreenToPNG", &FrameMan::SaveScreenToPNG) - .def("SaveBitmapToPNG", &FrameMan::SaveBitmapToPNG) - .def("FlashScreen", &FrameMan::FlashScreen) - .def("CalculateTextHeight", &FrameMan::CalculateTextHeight) - .def("CalculateTextWidth", &FrameMan::CalculateTextWidth) - .def("SplitStringToFitWidth", &FrameMan::SplitStringToFitWidth); + registry.Class("FrameManager") + + .addProperty("PlayerScreenWidth", &FrameMan::GetPlayerScreenWidth) + .addProperty("PlayerScreenHeight", &FrameMan::GetPlayerScreenHeight) + .addProperty("ScreenCount", &FrameMan::GetScreenCount) + .addProperty("ResolutionMultiplier", &FrameMan::GetResolutionMultiplier) + + .addFunction("IsHudDisabled", &FrameMan::IsHudDisabled) + .addFunction("SetHudDisabled", &FrameMan::SetHudDisabled) + .addFunction("LoadPalette", &FrameMan::LoadPalette) + .addFunction("SetScreenText", &FrameMan::SetScreenText) + .addFunction("ClearScreenText", &FrameMan::ClearScreenText) + .addFunction("FadeInPalette", &FrameMan::FadeInPalette) + .addFunction("FadeOutPalette", &FrameMan::FadeOutPalette) + .addFunction("SaveScreenToPNG", &FrameMan::SaveScreenToPNG) + .addFunction("SaveBitmapToPNG", &FrameMan::SaveBitmapToPNG) + .addFunction("FlashScreen", &FrameMan::FlashScreen) + .addFunction("CalculateTextHeight", &FrameMan::CalculateTextHeight) + .addFunction("CalculateTextWidth", &FrameMan::CalculateTextWidth) + .addFunction("SplitStringToFitWidth", &FrameMan::SplitStringToFitWidth); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, MetaMan) { - return luabind::class_("MetaManager") + registry.Class("MetaManager") - .property("GameName", &MetaMan::GetGameName, &MetaMan::SetGameName) - .property("PlayerTurn", &MetaMan::GetPlayerTurn) - .property("PlayerCount", &MetaMan::GetPlayerCount) + .addProperty("GameName", &MetaMan::GetGameName, &MetaMan::SetGameName) + .addProperty("PlayerTurn", &MetaMan::GetPlayerTurn) + .addProperty("PlayerCount", &MetaMan::GetPlayerCount) - .def_readonly("Players", &MetaMan::m_Players, luabind::return_stl_iterator) + .addProperty("Players", &MetaMan::m_Players, LuaBinding::ReturnStlIterator) - .def("GetTeamOfPlayer", &MetaMan::GetTeamOfPlayer) - .def("GetPlayer", &MetaMan::GetPlayer) - .def("GetMetaPlayerOfInGamePlayer", &MetaMan::GetMetaPlayerOfInGamePlayer); + .addFunction("GetTeamOfPlayer", &MetaMan::GetTeamOfPlayer) + .addFunction("GetPlayer", &MetaMan::GetPlayer) + .addFunction("GetMetaPlayerOfInGamePlayer", &MetaMan::GetMetaPlayerOfInGamePlayer); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, MovableMan) { - return luabind::class_("MovableManager") - - .property("MaxDroppedItems", &MovableMan::GetMaxDroppedItems, &MovableMan::SetMaxDroppedItems) - - .def_readonly("Actors", &MovableMan::m_Actors, luabind::return_stl_iterator) - .def_readonly("Items", &MovableMan::m_Items, luabind::return_stl_iterator) - .def_readonly("Particles", &MovableMan::m_Particles, luabind::return_stl_iterator) - .def_readonly("AddedActors", &MovableMan::m_AddedActors, luabind::return_stl_iterator) - .def_readonly("AddedItems", &MovableMan::m_AddedItems, luabind::return_stl_iterator) - .def_readonly("AddedParticles", &MovableMan::m_AddedParticles, luabind::return_stl_iterator) - .def_readonly("AlarmEvents", &MovableMan::m_AlarmEvents, luabind::return_stl_iterator) - .def_readonly("AddedAlarmEvents", &MovableMan::m_AddedAlarmEvents, luabind::return_stl_iterator) - - .def("GetMOFromID", &MovableMan::GetMOFromID) - .def("FindObjectByUniqueID", &MovableMan::FindObjectByUniqueID) - .def("GetMOIDCount", &MovableMan::GetMOIDCount) - .def("GetTeamMOIDCount", &MovableMan::GetTeamMOIDCount) - .def("PurgeAllMOs", &MovableMan::PurgeAllMOs) - .def("GetNextActorInGroup", &MovableMan::GetNextActorInGroup) - .def("GetPrevActorInGroup", &MovableMan::GetPrevActorInGroup) - .def("GetNextTeamActor", &MovableMan::GetNextTeamActor) - .def("GetPrevTeamActor", &MovableMan::GetPrevTeamActor) - .def("GetClosestTeamActor", (Actor * (MovableMan::*)(int team, int player, const Vector& scenePoint, int maxRadius, Vector& getDistance, const Actor* excludeThis)) & MovableMan::GetClosestTeamActor) - .def("GetClosestTeamActor", (Actor * (MovableMan::*)(int team, int player, const Vector& scenePoint, int maxRadius, Vector& getDistance, bool onlyPlayerControllableActors, const Actor* excludeThis)) & MovableMan::GetClosestTeamActor) - .def("GetClosestEnemyActor", &MovableMan::GetClosestEnemyActor) - .def("GetFirstTeamActor", &MovableMan::GetFirstTeamActor) - .def("GetClosestActor", &MovableMan::GetClosestActor) - .def("GetClosestBrainActor", &MovableMan::GetClosestBrainActor) - .def("GetFirstBrainActor", &MovableMan::GetFirstBrainActor) - .def("GetClosestOtherBrainActor", &MovableMan::GetClosestOtherBrainActor) - .def("GetFirstOtherBrainActor", &MovableMan::GetFirstOtherBrainActor) - .def("GetUnassignedBrain", &MovableMan::GetUnassignedBrain) - .def("GetParticleCount", &MovableMan::GetParticleCount) - .def("GetSplashRatio", &MovableMan::GetSplashRatio) - .def("SortTeamRoster", &MovableMan::SortTeamRoster) - .def("ChangeActorTeam", &MovableMan::ChangeActorTeam) - .def("RemoveActor", &MovableMan::RemoveActor, luabind::adopt(luabind::return_value)) - .def("RemoveItem", &MovableMan::RemoveItem, luabind::adopt(luabind::return_value)) - .def("RemoveParticle", &MovableMan::RemoveParticle, luabind::adopt(luabind::return_value)) - .def("ValidMO", &MovableMan::ValidMO) - .def("IsActor", &MovableMan::IsActor) - .def("IsDevice", &MovableMan::IsDevice) - .def("IsParticle", &MovableMan::IsParticle) - .def("IsOfActor", &MovableMan::IsOfActor) - .def("GetRootMOID", &MovableMan::GetRootMOID) - .def("RemoveMO", &MovableMan::RemoveMO) - .def("KillAllTeamActors", &MovableMan::KillAllTeamActors) - .def("KillAllEnemyActors", &MovableMan::KillAllEnemyActors) - .def("OpenAllDoors", &MovableMan::OpenAllDoors) - .def("IsParticleSettlingEnabled", &MovableMan::IsParticleSettlingEnabled) - .def("EnableParticleSettling", &MovableMan::EnableParticleSettling) - .def("IsMOSubtractionEnabled", &MovableMan::IsMOSubtractionEnabled) - .def("GetMOsInBox", (const std::vector* (MovableMan::*)(const Box& box) const) & MovableMan::GetMOsInBox, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("GetMOsInBox", (const std::vector* (MovableMan::*)(const Box& box, int ignoreTeam) const) & MovableMan::GetMOsInBox, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("GetMOsInBox", (const std::vector* (MovableMan::*)(const Box& box, int ignoreTeam, bool getsHitByMOsOnly) const) & MovableMan::GetMOsInBox, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("GetMOsInRadius", (const std::vector* (MovableMan::*)(const Vector& centre, float radius) const) & MovableMan::GetMOsInRadius, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("GetMOsInRadius", (const std::vector* (MovableMan::*)(const Vector& centre, float radius, int ignoreTeam) const) & MovableMan::GetMOsInRadius, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("GetMOsInRadius", (const std::vector* (MovableMan::*)(const Vector& centre, float radius, int ignoreTeam, bool getsHitByMOsOnly) const) & MovableMan::GetMOsInRadius, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("GetMOsAtPosition", (const std::vector* (MovableMan::*)(int pixelX, int pixelY) const) & MovableMan::GetMOsAtPosition, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("GetMOsAtPosition", (const std::vector* (MovableMan::*)(int pixelX, int pixelY, int ignoreTeam) const) & MovableMan::GetMOsAtPosition, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("GetMOsAtPosition", (const std::vector* (MovableMan::*)(int pixelX, int pixelY, int ignoreTeam, bool getsHitByMOsOnly) const) & MovableMan::GetMOsAtPosition, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - - .def("SendGlobalMessage", &LuaAdaptersMovableMan::SendGlobalMessage1) - .def("SendGlobalMessage", &LuaAdaptersMovableMan::SendGlobalMessage2) - .def("AddMO", &LuaAdaptersMovableMan::AddMO, luabind::adopt(_2)) - .def("AddActor", &LuaAdaptersMovableMan::AddActor, luabind::adopt(_2)) - .def("AddItem", &LuaAdaptersMovableMan::AddItem, luabind::adopt(_2)) - .def("AddParticle", &LuaAdaptersMovableMan::AddParticle, luabind::adopt(_2)); + registry.Class("MovableManager") + + .addProperty("MaxDroppedItems", &MovableMan::GetMaxDroppedItems, &MovableMan::SetMaxDroppedItems) + + .addProperty("Actors", &MovableMan::m_Actors, LuaBinding::ReturnStlIterator) + .addProperty("Items", &MovableMan::m_Items, LuaBinding::ReturnStlIterator) + .addProperty("Particles", &MovableMan::m_Particles, LuaBinding::ReturnStlIterator) + .addProperty("AddedActors", &MovableMan::m_AddedActors, LuaBinding::ReturnStlIterator) + .addProperty("AddedItems", &MovableMan::m_AddedItems, LuaBinding::ReturnStlIterator) + .addProperty("AddedParticles", &MovableMan::m_AddedParticles, LuaBinding::ReturnStlIterator) + .addProperty("AlarmEvents", &MovableMan::m_AlarmEvents, LuaBinding::ReturnStlIterator) + .addProperty("AddedAlarmEvents", &MovableMan::m_AddedAlarmEvents, LuaBinding::ReturnStlIterator) + + .addFunction("GetMOFromID", &MovableMan::GetMOFromID) + .addFunction("FindObjectByUniqueID", &MovableMan::FindObjectByUniqueID) + .addFunction("GetMOIDCount", &MovableMan::GetMOIDCount) + .addFunction("GetTeamMOIDCount", &MovableMan::GetTeamMOIDCount) + .addFunction("PurgeAllMOs", &MovableMan::PurgeAllMOs) + .addFunction("GetNextActorInGroup", &MovableMan::GetNextActorInGroup) + .addFunction("GetPrevActorInGroup", &MovableMan::GetPrevActorInGroup) + .addFunction("GetNextTeamActor", &MovableMan::GetNextTeamActor) + .addFunction("GetPrevTeamActor", &MovableMan::GetPrevTeamActor) + .addFunction("GetClosestTeamActor", (Actor * (MovableMan::*)(int team, int player, const Vector& scenePoint, int maxRadius, Vector& getDistance, const Actor* excludeThis)) & MovableMan::GetClosestTeamActor) + .addFunction("GetClosestTeamActor", (Actor * (MovableMan::*)(int team, int player, const Vector& scenePoint, int maxRadius, Vector& getDistance, bool onlyPlayerControllableActors, const Actor* excludeThis)) & MovableMan::GetClosestTeamActor) + .addFunction("GetClosestEnemyActor", &MovableMan::GetClosestEnemyActor) + .addFunction("GetFirstTeamActor", &MovableMan::GetFirstTeamActor) + .addFunction("GetClosestActor", &MovableMan::GetClosestActor) + .addFunction("GetClosestBrainActor", &MovableMan::GetClosestBrainActor) + .addFunction("GetFirstBrainActor", &MovableMan::GetFirstBrainActor) + .addFunction("GetClosestOtherBrainActor", &MovableMan::GetClosestOtherBrainActor) + .addFunction("GetFirstOtherBrainActor", &MovableMan::GetFirstOtherBrainActor) + .addFunction("GetUnassignedBrain", &MovableMan::GetUnassignedBrain) + .addFunction("GetParticleCount", &MovableMan::GetParticleCount) + .addFunction("GetSplashRatio", &MovableMan::GetSplashRatio) + .addFunction("SortTeamRoster", &MovableMan::SortTeamRoster) + .addFunction("ChangeActorTeam", &MovableMan::ChangeActorTeam) + .addFunction("RemoveActor", &MovableMan::RemoveActor, LuaBinding::AdoptResult) + .addFunction("RemoveItem", &MovableMan::RemoveItem, LuaBinding::AdoptResult) + .addFunction("RemoveParticle", &MovableMan::RemoveParticle, LuaBinding::AdoptResult) + .addFunction("ValidMO", &MovableMan::ValidMO) + .addFunction("IsActor", &MovableMan::IsActor) + .addFunction("IsDevice", &MovableMan::IsDevice) + .addFunction("IsParticle", &MovableMan::IsParticle) + .addFunction("IsOfActor", &MovableMan::IsOfActor) + .addFunction("GetRootMOID", &MovableMan::GetRootMOID) + .addFunction("RemoveMO", &MovableMan::RemoveMO) + .addFunction("KillAllTeamActors", &MovableMan::KillAllTeamActors) + .addFunction("KillAllEnemyActors", &MovableMan::KillAllEnemyActors) + .addFunction("OpenAllDoors", &MovableMan::OpenAllDoors) + .addFunction("IsParticleSettlingEnabled", &MovableMan::IsParticleSettlingEnabled) + .addFunction("EnableParticleSettling", &MovableMan::EnableParticleSettling) + .addFunction("IsMOSubtractionEnabled", &MovableMan::IsMOSubtractionEnabled) + .addFunction("GetMOsInBox", (const std::vector* (MovableMan::*)(const Box& box) const) & MovableMan::GetMOsInBox, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetMOsInBox", (const std::vector* (MovableMan::*)(const Box& box, int ignoreTeam) const) & MovableMan::GetMOsInBox, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetMOsInBox", (const std::vector* (MovableMan::*)(const Box& box, int ignoreTeam, bool getsHitByMOsOnly) const) & MovableMan::GetMOsInBox, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetMOsInRadius", (const std::vector* (MovableMan::*)(const Vector& centre, float radius) const) & MovableMan::GetMOsInRadius, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetMOsInRadius", (const std::vector* (MovableMan::*)(const Vector& centre, float radius, int ignoreTeam) const) & MovableMan::GetMOsInRadius, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetMOsInRadius", (const std::vector* (MovableMan::*)(const Vector& centre, float radius, int ignoreTeam, bool getsHitByMOsOnly) const) & MovableMan::GetMOsInRadius, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetMOsAtPosition", (const std::vector* (MovableMan::*)(int pixelX, int pixelY) const) & MovableMan::GetMOsAtPosition, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetMOsAtPosition", (const std::vector* (MovableMan::*)(int pixelX, int pixelY, int ignoreTeam) const) & MovableMan::GetMOsAtPosition, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetMOsAtPosition", (const std::vector* (MovableMan::*)(int pixelX, int pixelY, int ignoreTeam, bool getsHitByMOsOnly) const) & MovableMan::GetMOsAtPosition, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + + .addFunction("SendGlobalMessage", &LuaAdaptersMovableMan::SendGlobalMessage1) + .addFunction("SendGlobalMessage", &LuaAdaptersMovableMan::SendGlobalMessage2) + .addFunction("AddMO", &LuaAdaptersMovableMan::AddMO, LuaBinding::AdoptArg<2>) + .addFunction("AddActor", &LuaAdaptersMovableMan::AddActor, LuaBinding::AdoptArg<2>) + .addFunction("AddItem", &LuaAdaptersMovableMan::AddItem, LuaBinding::AdoptArg<2>) + .addFunction("AddParticle", &LuaAdaptersMovableMan::AddParticle, LuaBinding::AdoptArg<2>); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, PerformanceMan) { - return luabind::class_("PerformanceManager") + registry.Class("PerformanceManager") - .property("ShowPerformanceStats", &PerformanceMan::IsShowingPerformanceStats, &PerformanceMan::ShowPerformanceStats); + .addProperty("ShowPerformanceStats", &PerformanceMan::IsShowingPerformanceStats, &PerformanceMan::ShowPerformanceStats); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, PostProcessMan) { - return luabind::class_("PostProcessManager") + registry.Class("PostProcessManager") - .def("RegisterPostEffect", &PostProcessMan::RegisterPostEffect); + .addFunction("RegisterPostEffect", &PostProcessMan::RegisterPostEffect); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, PresetMan) { - return luabind::class_("PresetManager") - - .def_readonly("Modules", &PresetMan::m_pDataModules, luabind::return_stl_iterator) - - .def("LoadDataModule", (bool(PresetMan::*)(const std::string&)) & PresetMan::LoadDataModule) - .def("GetDataModule", &PresetMan::GetDataModule) - .def("GetModuleID", &PresetMan::GetModuleID) - .def("GetModuleIDFromPath", &PresetMan::GetModuleIDFromPath) - .def("GetTotalModuleCount", &PresetMan::GetTotalModuleCount) - .def("GetOfficialModuleCount", &PresetMan::GetOfficialModuleCount) - .def("AddPreset", &PresetMan::AddEntityPreset) - .def("GetPreset", (const Entity* (PresetMan::*)(const std::string&, std::string, int)) & PresetMan::GetEntityPreset) - .def("GetPreset", (const Entity* (PresetMan::*)(const std::string&, std::string, std::string)) & PresetMan::GetEntityPreset) - .def("GetLoadout", (Actor * (PresetMan::*)(std::string, std::string, bool)) & PresetMan::GetLoadout, luabind::adopt(luabind::result)) - .def("GetLoadout", (Actor * (PresetMan::*)(std::string, int, bool)) & PresetMan::GetLoadout, luabind::adopt(luabind::result)) - .def("GetRandomOfGroup", &PresetMan::GetRandomOfGroup) - .def("GetRandomOfGroupInModuleSpace", &PresetMan::GetRandomOfGroupInModuleSpace) - .def("GetEntityDataLocation", &PresetMan::GetEntityDataLocation) - .def("ReadReflectedPreset", &PresetMan::ReadReflectedPreset) - .def("ReloadEntityPreset", &LuaAdaptersPresetMan::ReloadEntityPreset1) - .def("ReloadEntityPreset", &LuaAdaptersPresetMan::ReloadEntityPreset2) - .def("GetAllEntities", &LuaAdaptersPresetMan::GetAllEntities, luabind::adopt(luabind::result) + luabind::return_stl_iterator) - .def("GetAllEntitiesOfGroup", &LuaAdaptersPresetMan::GetAllEntitiesOfGroup, luabind::adopt(luabind::result) + luabind::return_stl_iterator) - .def("GetAllEntitiesOfGroup", &LuaAdaptersPresetMan::GetAllEntitiesOfGroup2, luabind::adopt(luabind::result) + luabind::return_stl_iterator) - .def("GetAllEntitiesOfGroup", &LuaAdaptersPresetMan::GetAllEntitiesOfGroup3, luabind::adopt(luabind::result) + luabind::return_stl_iterator) - .def("ReloadAllScripts", &PresetMan::ReloadAllScripts) - .def("IsModuleOfficial", &PresetMan::IsModuleOfficial) - .def("IsModuleUserdata", &PresetMan::IsModuleUserdata) - .def("GetFullModulePath", &PresetMan::GetFullModulePath); + registry.Class("PresetManager") + + .addProperty("Modules", &PresetMan::m_pDataModules, LuaBinding::ReturnStlIterator) + + .addFunction("LoadDataModule", (bool(PresetMan::*)(const std::string&)) & PresetMan::LoadDataModule) + .addFunction("GetDataModule", &PresetMan::GetDataModule) + .addFunction("GetModuleID", &PresetMan::GetModuleID) + .addFunction("GetModuleIDFromPath", &PresetMan::GetModuleIDFromPath) + .addFunction("GetTotalModuleCount", &PresetMan::GetTotalModuleCount) + .addFunction("GetOfficialModuleCount", &PresetMan::GetOfficialModuleCount) + .addFunction("AddPreset", &PresetMan::AddEntityPreset) + .addFunction("GetPreset", (const Entity* (PresetMan::*)(const std::string&, std::string, int)) & PresetMan::GetEntityPreset) + .addFunction("GetPreset", (const Entity* (PresetMan::*)(const std::string&, std::string, std::string)) & PresetMan::GetEntityPreset) + .addFunction("GetLoadout", (Actor * (PresetMan::*)(std::string, std::string, bool)) & PresetMan::GetLoadout, LuaBinding::AdoptResult) + .addFunction("GetLoadout", (Actor * (PresetMan::*)(std::string, int, bool)) & PresetMan::GetLoadout, LuaBinding::AdoptResult) + .addFunction("GetRandomOfGroup", &PresetMan::GetRandomOfGroup) + .addFunction("GetRandomOfGroupInModuleSpace", &PresetMan::GetRandomOfGroupInModuleSpace) + .addFunction("GetEntityDataLocation", &PresetMan::GetEntityDataLocation) + .addFunction("ReadReflectedPreset", &PresetMan::ReadReflectedPreset) + .addFunction("ReloadEntityPreset", &LuaAdaptersPresetMan::ReloadEntityPreset1) + .addFunction("ReloadEntityPreset", &LuaAdaptersPresetMan::ReloadEntityPreset2) + .addFunction("GetAllEntities", &LuaAdaptersPresetMan::GetAllEntities, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetAllEntitiesOfGroup", &LuaAdaptersPresetMan::GetAllEntitiesOfGroup, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetAllEntitiesOfGroup", &LuaAdaptersPresetMan::GetAllEntitiesOfGroup2, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetAllEntitiesOfGroup", &LuaAdaptersPresetMan::GetAllEntitiesOfGroup3, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("ReloadAllScripts", &PresetMan::ReloadAllScripts) + .addFunction("IsModuleOfficial", &PresetMan::IsModuleOfficial) + .addFunction("IsModuleUserdata", &PresetMan::IsModuleUserdata) + .addFunction("GetFullModulePath", &PresetMan::GetFullModulePath); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, PrimitiveMan) { - return luabind::class_("PrimitiveManager") - - .def("DrawLinePrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawLinePrimitive) - .def("DrawLinePrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, unsigned char color, int thickness)) & PrimitiveMan::DrawLinePrimitive) - .def("DrawLinePrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawLinePrimitive) - .def("DrawLinePrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, unsigned char color, int thickness)) & PrimitiveMan::DrawLinePrimitive) - .def("DrawArcPrimitive", (void(PrimitiveMan::*)(const Vector& pos, float startAngle, float endAngle, int radius, unsigned char color)) & PrimitiveMan::DrawArcPrimitive) - .def("DrawArcPrimitive", (void(PrimitiveMan::*)(const Vector& pos, float startAngle, float endAngle, int radius, unsigned char color, int thickness)) & PrimitiveMan::DrawArcPrimitive) - .def("DrawArcPrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, float startAngle, float endAngle, int radius, unsigned char color)) & PrimitiveMan::DrawArcPrimitive) - .def("DrawArcPrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, float startAngle, float endAngle, int radius, unsigned char color, int thickness)) & PrimitiveMan::DrawArcPrimitive) - .def("DrawSplinePrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& guideA, const Vector& guideB, const Vector& end, unsigned char color)) & PrimitiveMan::DrawSplinePrimitive) - .def("DrawSplinePrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& guideA, const Vector& guideB, const Vector& end, unsigned char color)) & PrimitiveMan::DrawSplinePrimitive) - .def("DrawBoxPrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawBoxPrimitive) - .def("DrawBoxPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawBoxPrimitive) - .def("DrawBoxFillPrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawBoxFillPrimitive) - .def("DrawBoxFillPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawBoxFillPrimitive) - .def("DrawRoundedBoxPrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, int cornerRadius, unsigned char color)) & PrimitiveMan::DrawRoundedBoxPrimitive) - .def("DrawRoundedBoxPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, int cornerRadius, unsigned char color)) & PrimitiveMan::DrawRoundedBoxPrimitive) - .def("DrawRoundedBoxFillPrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, int cornerRadius, unsigned char color)) & PrimitiveMan::DrawRoundedBoxFillPrimitive) - .def("DrawRoundedBoxFillPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, int cornerRadius, unsigned char color)) & PrimitiveMan::DrawRoundedBoxFillPrimitive) - .def("DrawCirclePrimitive", (void(PrimitiveMan::*)(const Vector& pos, int radius, unsigned char color)) & PrimitiveMan::DrawCirclePrimitive) - .def("DrawCirclePrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, int radius, unsigned char color)) & PrimitiveMan::DrawCirclePrimitive) - .def("DrawCircleFillPrimitive", (void(PrimitiveMan::*)(const Vector& pos, int radius, unsigned char color)) & PrimitiveMan::DrawCircleFillPrimitive) - .def("DrawCircleFillPrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, int radius, unsigned char color)) & PrimitiveMan::DrawCircleFillPrimitive) - .def("DrawEllipsePrimitive", (void(PrimitiveMan::*)(const Vector& pos, int horizRadius, int vertRadius, unsigned char color)) & PrimitiveMan::DrawEllipsePrimitive) - .def("DrawEllipsePrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, int horizRadius, int vertRadius, unsigned char color)) & PrimitiveMan::DrawEllipsePrimitive) - .def("DrawEllipseFillPrimitive", (void(PrimitiveMan::*)(const Vector& pos, int horizRadius, int vertRadius, unsigned char color)) & PrimitiveMan::DrawEllipseFillPrimitive) - .def("DrawEllipseFillPrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, int horizRadius, int vertRadius, unsigned char color)) & PrimitiveMan::DrawEllipseFillPrimitive) - .def("DrawTrianglePrimitive", (void(PrimitiveMan::*)(const Vector& pointA, const Vector& pointB, const Vector& pointC, unsigned char color)) & PrimitiveMan::DrawTrianglePrimitive) - .def("DrawTrianglePrimitive", (void(PrimitiveMan::*)(int player, const Vector& pointA, const Vector& pointB, const Vector& pointC, unsigned char color)) & PrimitiveMan::DrawTrianglePrimitive) - .def("DrawTriangleFillPrimitive", (void(PrimitiveMan::*)(const Vector& pointA, const Vector& pointB, const Vector& pointC, unsigned char color)) & PrimitiveMan::DrawTriangleFillPrimitive) - .def("DrawTriangleFillPrimitive", (void(PrimitiveMan::*)(int player, const Vector& pointA, const Vector& pointB, const Vector& pointC, unsigned char color)) & PrimitiveMan::DrawTriangleFillPrimitive) - .def("DrawTextPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& text, bool isSmall, int alignment)) & PrimitiveMan::DrawTextPrimitive) - .def("DrawTextPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& text, bool isSmall, int alignment, float rotAngle)) & PrimitiveMan::DrawTextPrimitive) - .def("DrawTextPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& text, bool isSmall, int alignment)) & PrimitiveMan::DrawTextPrimitive) - .def("DrawTextPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& text, bool isSmall, int alignment, float rotAngle)) & PrimitiveMan::DrawTextPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, float scale)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, float scale, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, float scale)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, float scale, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& filePath, float rotAngle)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& filePath, float rotAngle, float scale)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& filePath, float rotAngle, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& filePath, float rotAngle, float scale, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& filePath, float rotAngle)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& filePath, float rotAngle, float scale)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& filePath, float rotAngle, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& filePath, float rotAngle, float scale, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) - .def("DrawIconPrimitive", (void(PrimitiveMan::*)(const Vector& start, Entity* entity)) & PrimitiveMan::DrawIconPrimitive) - .def("DrawIconPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, Entity* entity)) & PrimitiveMan::DrawIconPrimitive) - - .def("DrawPolygonPrimitive", &LuaAdaptersPrimitiveMan::DrawPolygonPrimitive) - .def("DrawPolygonPrimitive", &LuaAdaptersPrimitiveMan::DrawPolygonPrimitiveForPlayer) - .def("DrawPolygonFillPrimitive", &LuaAdaptersPrimitiveMan::DrawPolygonFillPrimitive) - .def("DrawPolygonFillPrimitive", &LuaAdaptersPrimitiveMan::DrawPolygonFillPrimitiveForPlayer) - .def("DrawPrimitives", &LuaAdaptersPrimitiveMan::DrawPrimitivesWithTransparency) - .def("DrawPrimitives", &LuaAdaptersPrimitiveMan::DrawPrimitivesWithBlending) - .def("DrawPrimitives", &LuaAdaptersPrimitiveMan::DrawPrimitivesWithBlendingPerChannel); + registry.Class("PrimitiveManager") + + .addFunction("DrawLinePrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawLinePrimitive) + .addFunction("DrawLinePrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, unsigned char color, int thickness)) & PrimitiveMan::DrawLinePrimitive) + .addFunction("DrawLinePrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawLinePrimitive) + .addFunction("DrawLinePrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, unsigned char color, int thickness)) & PrimitiveMan::DrawLinePrimitive) + .addFunction("DrawArcPrimitive", (void(PrimitiveMan::*)(const Vector& pos, float startAngle, float endAngle, int radius, unsigned char color)) & PrimitiveMan::DrawArcPrimitive) + .addFunction("DrawArcPrimitive", (void(PrimitiveMan::*)(const Vector& pos, float startAngle, float endAngle, int radius, unsigned char color, int thickness)) & PrimitiveMan::DrawArcPrimitive) + .addFunction("DrawArcPrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, float startAngle, float endAngle, int radius, unsigned char color)) & PrimitiveMan::DrawArcPrimitive) + .addFunction("DrawArcPrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, float startAngle, float endAngle, int radius, unsigned char color, int thickness)) & PrimitiveMan::DrawArcPrimitive) + .addFunction("DrawSplinePrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& guideA, const Vector& guideB, const Vector& end, unsigned char color)) & PrimitiveMan::DrawSplinePrimitive) + .addFunction("DrawSplinePrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& guideA, const Vector& guideB, const Vector& end, unsigned char color)) & PrimitiveMan::DrawSplinePrimitive) + .addFunction("DrawBoxPrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawBoxPrimitive) + .addFunction("DrawBoxPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawBoxPrimitive) + .addFunction("DrawBoxFillPrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawBoxFillPrimitive) + .addFunction("DrawBoxFillPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, unsigned char color)) & PrimitiveMan::DrawBoxFillPrimitive) + .addFunction("DrawRoundedBoxPrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, int cornerRadius, unsigned char color)) & PrimitiveMan::DrawRoundedBoxPrimitive) + .addFunction("DrawRoundedBoxPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, int cornerRadius, unsigned char color)) & PrimitiveMan::DrawRoundedBoxPrimitive) + .addFunction("DrawRoundedBoxFillPrimitive", (void(PrimitiveMan::*)(const Vector& start, const Vector& end, int cornerRadius, unsigned char color)) & PrimitiveMan::DrawRoundedBoxFillPrimitive) + .addFunction("DrawRoundedBoxFillPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const Vector& end, int cornerRadius, unsigned char color)) & PrimitiveMan::DrawRoundedBoxFillPrimitive) + .addFunction("DrawCirclePrimitive", (void(PrimitiveMan::*)(const Vector& pos, int radius, unsigned char color)) & PrimitiveMan::DrawCirclePrimitive) + .addFunction("DrawCirclePrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, int radius, unsigned char color)) & PrimitiveMan::DrawCirclePrimitive) + .addFunction("DrawCircleFillPrimitive", (void(PrimitiveMan::*)(const Vector& pos, int radius, unsigned char color)) & PrimitiveMan::DrawCircleFillPrimitive) + .addFunction("DrawCircleFillPrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, int radius, unsigned char color)) & PrimitiveMan::DrawCircleFillPrimitive) + .addFunction("DrawEllipsePrimitive", (void(PrimitiveMan::*)(const Vector& pos, int horizRadius, int vertRadius, unsigned char color)) & PrimitiveMan::DrawEllipsePrimitive) + .addFunction("DrawEllipsePrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, int horizRadius, int vertRadius, unsigned char color)) & PrimitiveMan::DrawEllipsePrimitive) + .addFunction("DrawEllipseFillPrimitive", (void(PrimitiveMan::*)(const Vector& pos, int horizRadius, int vertRadius, unsigned char color)) & PrimitiveMan::DrawEllipseFillPrimitive) + .addFunction("DrawEllipseFillPrimitive", (void(PrimitiveMan::*)(int player, const Vector& pos, int horizRadius, int vertRadius, unsigned char color)) & PrimitiveMan::DrawEllipseFillPrimitive) + .addFunction("DrawTrianglePrimitive", (void(PrimitiveMan::*)(const Vector& pointA, const Vector& pointB, const Vector& pointC, unsigned char color)) & PrimitiveMan::DrawTrianglePrimitive) + .addFunction("DrawTrianglePrimitive", (void(PrimitiveMan::*)(int player, const Vector& pointA, const Vector& pointB, const Vector& pointC, unsigned char color)) & PrimitiveMan::DrawTrianglePrimitive) + .addFunction("DrawTriangleFillPrimitive", (void(PrimitiveMan::*)(const Vector& pointA, const Vector& pointB, const Vector& pointC, unsigned char color)) & PrimitiveMan::DrawTriangleFillPrimitive) + .addFunction("DrawTriangleFillPrimitive", (void(PrimitiveMan::*)(int player, const Vector& pointA, const Vector& pointB, const Vector& pointC, unsigned char color)) & PrimitiveMan::DrawTriangleFillPrimitive) + .addFunction("DrawTextPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& text, bool isSmall, int alignment)) & PrimitiveMan::DrawTextPrimitive) + .addFunction("DrawTextPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& text, bool isSmall, int alignment, float rotAngle)) & PrimitiveMan::DrawTextPrimitive) + .addFunction("DrawTextPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& text, bool isSmall, int alignment)) & PrimitiveMan::DrawTextPrimitive) + .addFunction("DrawTextPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& text, bool isSmall, int alignment, float rotAngle)) & PrimitiveMan::DrawTextPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, float scale)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, float scale, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, float scale)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const MOSprite* moSprite, float rotAngle, unsigned int frame, float scale, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& filePath, float rotAngle)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& filePath, float rotAngle, float scale)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& filePath, float rotAngle, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(const Vector& start, const std::string& filePath, float rotAngle, float scale, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& filePath, float rotAngle)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& filePath, float rotAngle, float scale)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& filePath, float rotAngle, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawBitmapPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, const std::string& filePath, float rotAngle, float scale, bool hFlipped, bool vFlipped)) & PrimitiveMan::DrawBitmapPrimitive) + .addFunction("DrawIconPrimitive", (void(PrimitiveMan::*)(const Vector& start, Entity* entity)) & PrimitiveMan::DrawIconPrimitive) + .addFunction("DrawIconPrimitive", (void(PrimitiveMan::*)(int player, const Vector& start, Entity* entity)) & PrimitiveMan::DrawIconPrimitive) + + .addFunction("DrawPolygonPrimitive", &LuaAdaptersPrimitiveMan::DrawPolygonPrimitive) + .addFunction("DrawPolygonPrimitive", &LuaAdaptersPrimitiveMan::DrawPolygonPrimitiveForPlayer) + .addFunction("DrawPolygonFillPrimitive", &LuaAdaptersPrimitiveMan::DrawPolygonFillPrimitive) + .addFunction("DrawPolygonFillPrimitive", &LuaAdaptersPrimitiveMan::DrawPolygonFillPrimitiveForPlayer) + .addFunction("DrawPrimitives", &LuaAdaptersPrimitiveMan::DrawPrimitivesWithTransparency) + .addFunction("DrawPrimitives", &LuaAdaptersPrimitiveMan::DrawPrimitivesWithBlending) + .addFunction("DrawPrimitives", &LuaAdaptersPrimitiveMan::DrawPrimitivesWithBlendingPerChannel); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, SceneMan) { - return luabind::class_("SceneManager") - - .property("Scene", &SceneMan::GetScene) - .property("SceneDim", &SceneMan::GetSceneDim) - .property("SceneWidth", &SceneMan::GetSceneWidth) - .property("SceneHeight", &SceneMan::GetSceneHeight) - .property("SceneWrapsX", &SceneMan::SceneWrapsX) - .property("SceneWrapsY", &SceneMan::SceneWrapsY) - .property("SceneOrbitDirection", &SceneMan::GetSceneOrbitDirection) - .property("LayerDrawMode", &SceneMan::GetLayerDrawMode, &SceneMan::SetLayerDrawMode) - .property("GlobalAcc", &SceneMan::GetGlobalAcc) - .property("OzPerKg", &SceneMan::GetOzPerKg) - .property("KgPerOz", &SceneMan::GetKgPerOz) - .property("ScrapCompactingHeight", &SceneMan::GetScrapCompactingHeight, &SceneMan::SetScrapCompactingHeight) - - .def("LoadScene", (int(SceneMan::*)(const std::string&, bool, bool)) & SceneMan::LoadScene) - .def("LoadScene", (int(SceneMan::*)(const std::string&, bool)) & SceneMan::LoadScene) - - .def("GetTerrain", &SceneMan::GetTerrain) - .def("GetMaterial", &SceneMan::GetMaterial) - .def("GetMaterialFromID", &SceneMan::GetMaterialFromID) - .def("GetTerrMatter", &SceneMan::GetTerrMatter) - .def("GetMOIDPixel", (MOID(SceneMan::*)(int, int)) & SceneMan::GetMOIDPixel) - .def("GetMOIDPixel", (MOID(SceneMan::*)(int, int, int)) & SceneMan::GetMOIDPixel) - .def("SetLayerDrawMode", &SceneMan::SetLayerDrawMode) - .def("LoadUnseenLayer", &SceneMan::LoadUnseenLayer) - .def("MakeAllUnseen", &SceneMan::MakeAllUnseen) - .def("AnythingUnseen", &SceneMan::AnythingUnseen) - .def("GetUnseenResolution", &SceneMan::GetUnseenResolution) - .def("IsUnseen", &SceneMan::IsUnseen) - .def("RevealUnseen", &SceneMan::RevealUnseen) - .def("RevealUnseenBox", &SceneMan::RevealUnseenBox) - .def("RestoreUnseen", &SceneMan::RestoreUnseen) - .def("RestoreUnseenBox", &SceneMan::RestoreUnseenBox) - .def("CastSeeRay", &SceneMan::CastSeeRay) - .def("CastUnseeRay", &SceneMan::CastUnseeRay) - .def("CastUnseenRay", &SceneMan::CastUnseenRay) - .def("CastMaterialRay", (bool(SceneMan::*)(const Vector&, const Vector&, unsigned char, Vector&, int, bool)) & SceneMan::CastMaterialRay) - .def("CastMaterialRay", (float(SceneMan::*)(const Vector&, const Vector&, unsigned char, int)) & SceneMan::CastMaterialRay) - .def("CastNotMaterialRay", (bool(SceneMan::*)(const Vector&, const Vector&, unsigned char, Vector&, int, bool)) & SceneMan::CastNotMaterialRay) - .def("CastNotMaterialRay", (float(SceneMan::*)(const Vector&, const Vector&, unsigned char, int, bool)) & SceneMan::CastNotMaterialRay) - .def("CastStrengthSumRay", &SceneMan::CastStrengthSumRay) - .def("CastMaxStrengthRay", (float(SceneMan::*)(const Vector&, const Vector&, int, unsigned char)) & SceneMan::CastMaxStrengthRay) - .def("CastMaxStrengthRay", (float(SceneMan::*)(const Vector&, const Vector&, int)) & SceneMan::CastMaxStrengthRay) - .def("CastStrengthRay", &SceneMan::CastStrengthRay) - .def("CastWeaknessRay", &SceneMan::CastWeaknessRay) - .def("CastMORay", &LuaAdaptersSceneMan::CastMORay1) - .def("CastMORay", &LuaAdaptersSceneMan::CastMORay2) - .def("CastAllMOsRay", &LuaAdaptersSceneMan::CastAllMOsRay, luabind::return_stl_iterator) - .def("CastFindMORay", (bool(SceneMan::*)(const Vector&, const Vector&, MOID, const Vector&, unsigned char, bool, int)) & SceneMan::CastFindMORay) - .def("CastFindMORay", &SceneMan::CastFindMORay) - .def("CastObstacleRay", &LuaAdaptersSceneMan::CastObstacleRay1) - .def("CastObstacleRay", &LuaAdaptersSceneMan::CastObstacleRay2) - .def("CastTerrainPenetrationRay", &SceneMan::CastTerrainPenetrationRay) - .def("GetLastRayHitPos", &SceneMan::GetLastRayHitPos) - .def("FindAltitude", (float(SceneMan::*)(const Vector&, int, int)) &SceneMan::FindAltitude) - .def("FindAltitude", (float(SceneMan::*)(const Vector&, int, int, bool)) &SceneMan::FindAltitude) - .def("MovePointToGround", (Vector(SceneMan::*)(const Vector&, int, int)) &SceneMan::MovePointToGround) - .def("MovePointToGround", (Vector(SceneMan::*)(const Vector&, int, int, int)) &SceneMan::MovePointToGround) - .def("IsWithinBounds", &SceneMan::IsWithinBounds) - .def("ForceBounds", (bool(SceneMan::*)(Vector&) const) & SceneMan::ForceBounds) //, out_value(_2)) - .def("WrapPosition", (bool(SceneMan::*)(Vector&) const) & SceneMan::WrapPosition) //, out_value(_2)) - .def("SnapPosition", &SceneMan::SnapPosition) - .def("ShortestDistance", &SceneMan::ShortestDistance) - .def("WrapBox", &LuaAdaptersSceneMan::WrapBoxes, luabind::return_stl_iterator) - .def("ObscuredPoint", (bool(SceneMan::*)(Vector&, int)) & SceneMan::ObscuredPoint) //, out_value(_2)) - .def("ObscuredPoint", (bool(SceneMan::*)(int, int, int)) & SceneMan::ObscuredPoint) - .def("AddSceneObject", &SceneMan::AddSceneObject, luabind::adopt(_2)) - .def("CheckAndRemoveOrphans", (int(SceneMan::*)(int, int, int, int, bool)) & SceneMan::RemoveOrphans) - .def("DislodgePixel", &SceneMan::DislodgePixel) - .def("DislodgePixel", &SceneMan::DislodgePixelBool) - .def("DislodgePixelLine", (const std::vector* (SceneMan::*)(const Vector& start, const Vector& ray, int skip, bool deletePixels) const) & SceneMan::DislodgePixelLine, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("DislodgePixelLine", (const std::vector* (SceneMan::*)(const Vector& start, const Vector& ray, int skip) const) & SceneMan::DislodgePixelLineNoBool, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("DislodgePixelCircle", (const std::vector* (SceneMan::*)(const Vector& centre, float radius, bool deletePixels) const) & SceneMan::DislodgePixelCircle, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("DislodgePixelCircle", (const std::vector* (SceneMan::*)(const Vector& centre, float radius) const) & SceneMan::DislodgePixelCircleNoBool, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("DislodgePixelBox", (const std::vector* (SceneMan::*)(const Vector& upperLeftCorner, const Vector& lowerRightCorner, bool deletePixels) const) & SceneMan::DislodgePixelBox, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("DislodgePixelBox", (const std::vector* (SceneMan::*)(const Vector& upperLeftCorner, const Vector& lowerRightCorner) const) & SceneMan::DislodgePixelBoxNoBool, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("DislodgePixelRing", (const std::vector* (SceneMan::*)(const Vector& centre, float innerRadius, float outerRadius, bool deletePixels) const) & SceneMan::DislodgePixelRing, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("DislodgePixelRing", (const std::vector* (SceneMan::*)(const Vector& centre, float innerRadius, float outerRadius) const) & SceneMan::DislodgePixelRingNoBool, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator); + registry.Class("SceneManager") + + .addProperty("Scene", &SceneMan::GetScene) + .addProperty("SceneDim", &SceneMan::GetSceneDim) + .addProperty("SceneWidth", &SceneMan::GetSceneWidth) + .addProperty("SceneHeight", &SceneMan::GetSceneHeight) + .addProperty("SceneWrapsX", &SceneMan::SceneWrapsX) + .addProperty("SceneWrapsY", &SceneMan::SceneWrapsY) + .addProperty("SceneOrbitDirection", &SceneMan::GetSceneOrbitDirection) + .addProperty("LayerDrawMode", &SceneMan::GetLayerDrawMode, &SceneMan::SetLayerDrawMode) + .addProperty("GlobalAcc", &SceneMan::GetGlobalAcc) + .addProperty("OzPerKg", &SceneMan::GetOzPerKg) + .addProperty("KgPerOz", &SceneMan::GetKgPerOz) + .addProperty("ScrapCompactingHeight", &SceneMan::GetScrapCompactingHeight, &SceneMan::SetScrapCompactingHeight) + + .addFunction("LoadScene", (int(SceneMan::*)(const std::string&, bool, bool)) & SceneMan::LoadScene) + .addFunction("LoadScene", (int(SceneMan::*)(const std::string&, bool)) & SceneMan::LoadScene) + + .addFunction("GetTerrain", &SceneMan::GetTerrain) + .addFunction("GetMaterial", &SceneMan::GetMaterial) + .addFunction("GetMaterialFromID", &SceneMan::GetMaterialFromID) + .addFunction("GetTerrMatter", &SceneMan::GetTerrMatter) + .addFunction("GetMOIDPixel", (MOID(SceneMan::*)(int, int)) & SceneMan::GetMOIDPixel) + .addFunction("GetMOIDPixel", (MOID(SceneMan::*)(int, int, int)) & SceneMan::GetMOIDPixel) + .addFunction("SetLayerDrawMode", &SceneMan::SetLayerDrawMode) + .addFunction("LoadUnseenLayer", &SceneMan::LoadUnseenLayer) + .addFunction("MakeAllUnseen", &SceneMan::MakeAllUnseen) + .addFunction("AnythingUnseen", &SceneMan::AnythingUnseen) + .addFunction("GetUnseenResolution", &SceneMan::GetUnseenResolution) + .addFunction("IsUnseen", &SceneMan::IsUnseen) + .addFunction("RevealUnseen", &SceneMan::RevealUnseen) + .addFunction("RevealUnseenBox", &SceneMan::RevealUnseenBox) + .addFunction("RestoreUnseen", &SceneMan::RestoreUnseen) + .addFunction("RestoreUnseenBox", &SceneMan::RestoreUnseenBox) + .addFunction("CastSeeRay", &SceneMan::CastSeeRay) + .addFunction("CastUnseeRay", &SceneMan::CastUnseeRay) + .addFunction("CastUnseenRay", &SceneMan::CastUnseenRay) + .addFunction("CastMaterialRay", (bool(SceneMan::*)(const Vector&, const Vector&, unsigned char, Vector&, int, bool)) & SceneMan::CastMaterialRay) + .addFunction("CastMaterialRay", (float(SceneMan::*)(const Vector&, const Vector&, unsigned char, int)) & SceneMan::CastMaterialRay) + .addFunction("CastNotMaterialRay", (bool(SceneMan::*)(const Vector&, const Vector&, unsigned char, Vector&, int, bool)) & SceneMan::CastNotMaterialRay) + .addFunction("CastNotMaterialRay", (float(SceneMan::*)(const Vector&, const Vector&, unsigned char, int, bool)) & SceneMan::CastNotMaterialRay) + .addFunction("CastStrengthSumRay", &SceneMan::CastStrengthSumRay) + .addFunction("CastMaxStrengthRay", (float(SceneMan::*)(const Vector&, const Vector&, int, unsigned char)) & SceneMan::CastMaxStrengthRay) + .addFunction("CastMaxStrengthRay", (float(SceneMan::*)(const Vector&, const Vector&, int)) & SceneMan::CastMaxStrengthRay) + .addFunction("CastStrengthRay", &SceneMan::CastStrengthRay) + .addFunction("CastWeaknessRay", &SceneMan::CastWeaknessRay) + .addFunction("CastMORay", &LuaAdaptersSceneMan::CastMORay1) + .addFunction("CastMORay", &LuaAdaptersSceneMan::CastMORay2) + .addFunction("CastAllMOsRay", &LuaAdaptersSceneMan::CastAllMOsRay, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) // The result is allocated for Lua, so the iterator owns it rather than leaking it like luabind did. + .addFunction("CastFindMORay", (bool(SceneMan::*)(const Vector&, const Vector&, MOID, const Vector&, unsigned char, bool, int)) & SceneMan::CastFindMORay) + .addFunction("CastFindMORay", &SceneMan::CastFindMORay) + .addFunction("CastObstacleRay", &LuaAdaptersSceneMan::CastObstacleRay1) + .addFunction("CastObstacleRay", &LuaAdaptersSceneMan::CastObstacleRay2) + .addFunction("CastTerrainPenetrationRay", &SceneMan::CastTerrainPenetrationRay) + .addFunction("GetLastRayHitPos", &SceneMan::GetLastRayHitPos) + .addFunction("FindAltitude", (float(SceneMan::*)(const Vector&, int, int)) & SceneMan::FindAltitude) + .addFunction("FindAltitude", (float(SceneMan::*)(const Vector&, int, int, bool)) & SceneMan::FindAltitude) + .addFunction("MovePointToGround", (Vector(SceneMan::*)(const Vector&, int, int)) & SceneMan::MovePointToGround) + .addFunction("MovePointToGround", (Vector(SceneMan::*)(const Vector&, int, int, int)) & SceneMan::MovePointToGround) + .addFunction("IsWithinBounds", &SceneMan::IsWithinBounds) + .addFunction("ForceBounds", (bool(SceneMan::*)(Vector&) const) & SceneMan::ForceBounds) //, out_value(_2)) + .addFunction("WrapPosition", (bool(SceneMan::*)(Vector&) const) & SceneMan::WrapPosition) //, out_value(_2)) + .addFunction("SnapPosition", &SceneMan::SnapPosition) + .addFunction("ShortestDistance", &SceneMan::ShortestDistance) + .addFunction("WrapBox", &LuaAdaptersSceneMan::WrapBoxes, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) // The result is allocated for Lua, so the iterator owns it rather than leaking it like luabind did. + .addFunction("ObscuredPoint", (bool(SceneMan::*)(Vector&, int)) & SceneMan::ObscuredPoint) //, out_value(_2)) + .addFunction("ObscuredPoint", (bool(SceneMan::*)(int, int, int)) & SceneMan::ObscuredPoint) + .addFunction("AddSceneObject", &SceneMan::AddSceneObject, LuaBinding::AdoptArg<2>) + .addFunction("CheckAndRemoveOrphans", (int(SceneMan::*)(int, int, int, int, bool)) & SceneMan::RemoveOrphans) + .addFunction("DislodgePixel", &SceneMan::DislodgePixel) + .addFunction("DislodgePixel", &SceneMan::DislodgePixelBool) + .addFunction("DislodgePixelLine", (const std::vector* (SceneMan::*)(const Vector& start, const Vector& ray, int skip, bool deletePixels) const) & SceneMan::DislodgePixelLine, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("DislodgePixelLine", (const std::vector* (SceneMan::*)(const Vector& start, const Vector& ray, int skip) const) & SceneMan::DislodgePixelLineNoBool, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("DislodgePixelCircle", (const std::vector* (SceneMan::*)(const Vector& centre, float radius, bool deletePixels) const) & SceneMan::DislodgePixelCircle, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("DislodgePixelCircle", (const std::vector* (SceneMan::*)(const Vector& centre, float radius) const) & SceneMan::DislodgePixelCircleNoBool, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("DislodgePixelBox", (const std::vector* (SceneMan::*)(const Vector& upperLeftCorner, const Vector& lowerRightCorner, bool deletePixels) const) & SceneMan::DislodgePixelBox, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("DislodgePixelBox", (const std::vector* (SceneMan::*)(const Vector& upperLeftCorner, const Vector& lowerRightCorner) const) & SceneMan::DislodgePixelBoxNoBool, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("DislodgePixelRing", (const std::vector* (SceneMan::*)(const Vector& centre, float innerRadius, float outerRadius, bool deletePixels) const) & SceneMan::DislodgePixelRing, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("DislodgePixelRing", (const std::vector* (SceneMan::*)(const Vector& centre, float innerRadius, float outerRadius) const) & SceneMan::DislodgePixelRingNoBool, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, CameraMan) { - return luabind::class_("CameraManager") - - .def("GetOffset", &CameraMan::GetOffset) - .def("SetOffset", &CameraMan::SetOffset) - .def("GetScreenOcclusion", &CameraMan::GetScreenOcclusion) - .def("SetScreenOcclusion", &CameraMan::SetScreenOcclusion) - .def("GetScrollTarget", &CameraMan::GetScrollTarget) - .def("SetScrollTarget", &CameraMan::SetScrollTarget) - .def("TargetDistanceScalar", &CameraMan::TargetDistanceScalar) - .def("CheckOffset", &CameraMan::CheckOffset) - .def("SetScroll", &CameraMan::SetScroll) - .def("AddScreenShake", (void(CameraMan::*)(float, int)) & CameraMan::AddScreenShake) - .def("AddScreenShake", (void(CameraMan::*)(float, const Vector&)) & CameraMan::AddScreenShake); + registry.Class("CameraManager") + + .addFunction("GetOffset", &CameraMan::GetOffset) + .addFunction("SetOffset", &CameraMan::SetOffset) + .addFunction("GetScreenOcclusion", &CameraMan::GetScreenOcclusion) + .addFunction("SetScreenOcclusion", &CameraMan::SetScreenOcclusion) + .addFunction("GetScrollTarget", &CameraMan::GetScrollTarget) + .addFunction("SetScrollTarget", &CameraMan::SetScrollTarget) + .addFunction("TargetDistanceScalar", &CameraMan::TargetDistanceScalar) + .addFunction("CheckOffset", &CameraMan::CheckOffset) + .addFunction("SetScroll", &CameraMan::SetScroll) + .addFunction("AddScreenShake", (void(CameraMan::*)(float, int)) & CameraMan::AddScreenShake) + .addFunction("AddScreenShake", (void(CameraMan::*)(float, const Vector&)) & CameraMan::AddScreenShake); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, SettingsMan) { - return luabind::class_("SettingsManager") + registry.Class("SettingsManager") - .property("PrintDebugInfo", &SettingsMan::PrintDebugInfo, &SettingsMan::SetPrintDebugInfo) - .property("RecommendedMOIDCount", &SettingsMan::RecommendedMOIDCount) - .property("AIUpdateInterval", &SettingsMan::GetAIUpdateInterval, &SettingsMan::SetAIUpdateInterval) - .property("ShowEnemyHUD", &SettingsMan::ShowEnemyHUD) - .property("AutomaticGoldDeposit", &SettingsMan::GetAutomaticGoldDeposit); + .addProperty("PrintDebugInfo", &SettingsMan::PrintDebugInfo, &SettingsMan::SetPrintDebugInfo) + .addProperty("RecommendedMOIDCount", &SettingsMan::RecommendedMOIDCount) + .addProperty("AIUpdateInterval", &SettingsMan::GetAIUpdateInterval, &SettingsMan::SetAIUpdateInterval) + .addProperty("ShowEnemyHUD", &SettingsMan::ShowEnemyHUD) + .addProperty("AutomaticGoldDeposit", &SettingsMan::GetAutomaticGoldDeposit); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, TimerMan) { - return luabind::class_("TimerManager") + registry.Class("TimerManager") - .property("TimeScale", &TimerMan::GetTimeScale, &TimerMan::SetTimeScale) - .property("RealToSimCap", &TimerMan::GetRealToSimCap) - .property("DeltaTimeTicks", &LuaAdaptersTimerMan::GetDeltaTimeTicks, &TimerMan::SetDeltaTimeTicks) - .property("DeltaTimeSecs", &TimerMan::GetDeltaTimeSecs, &TimerMan::SetDeltaTimeSecs) - .property("DeltaTimeMS", &TimerMan::GetDeltaTimeMS) - .property("AIDeltaTimeSecs", &TimerMan::GetAIDeltaTimeSecs) - .property("AIDeltaTimeMS", &TimerMan::GetAIDeltaTimeMS) + .addProperty("TimeScale", &TimerMan::GetTimeScale, &TimerMan::SetTimeScale) + .addProperty("RealToSimCap", &TimerMan::GetRealToSimCap) + .addProperty("DeltaTimeTicks", &LuaAdaptersTimerMan::GetDeltaTimeTicks, &TimerMan::SetDeltaTimeTicks) + .addProperty("DeltaTimeSecs", &TimerMan::GetDeltaTimeSecs, &TimerMan::SetDeltaTimeSecs) + .addProperty("DeltaTimeMS", &TimerMan::GetDeltaTimeMS) + .addProperty("AIDeltaTimeSecs", &TimerMan::GetAIDeltaTimeSecs) + .addProperty("AIDeltaTimeMS", &TimerMan::GetAIDeltaTimeMS) - .property("TicksPerSecond", &LuaAdaptersTimerMan::GetTicksPerSecond) + .addProperty("TicksPerSecond", &LuaAdaptersTimerMan::GetTicksPerSecond) - .def("TimeForSimUpdate", &TimerMan::TimeForSimUpdate) - .def("DrawnSimUpdate", &TimerMan::DrawnSimUpdate); + .addFunction("TimeForSimUpdate", &TimerMan::TimeForSimUpdate) + .addFunction("DrawnSimUpdate", &TimerMan::DrawnSimUpdate); } LuaBindingRegisterFunctionDefinitionForType(ManagerLuaBindings, UInputMan) { - return luabind::class_("UInputManager") - - .property("FlagLAltState", &UInputMan::FlagLAltState) - .property("FlagRAltState", &UInputMan::FlagRAltState) - .property("FlagAltState", &UInputMan::FlagAltState) - .property("FlagLCtrlState", &UInputMan::FlagLCtrlState) - .property("FlagRCtrlState", &UInputMan::FlagRCtrlState) - .property("FlagCtrlState", &UInputMan::FlagCtrlState) - .property("FlagLShiftState", &UInputMan::FlagLShiftState) - .property("FlagRShiftState", &UInputMan::FlagRShiftState) - .property("FlagShiftState", &UInputMan::FlagShiftState) - - .def("GetInputDevice", &UInputMan::GetInputDevice) - .def("ElementPressed", &UInputMan::ElementPressed) - .def("ElementReleased", &UInputMan::ElementReleased) - .def("ElementHeld", &UInputMan::ElementHeld) - .def("KeyPressed", (bool(UInputMan::*)(SDL_Keycode, int) const) & UInputMan::KeyPressed) - .def("KeyPressed", (bool(UInputMan::*)(SDL_Keycode) const) & UInputMan::KeyPressedKeycode) - .def("KeyReleased", (bool(UInputMan::*)(SDL_Keycode, int) const) & UInputMan::KeyReleased) - .def("KeyReleased", (bool(UInputMan::*)(SDL_Keycode) const) & UInputMan::KeyReleasedKeycode) - .def("KeyHeld", (bool(UInputMan::*)(SDL_Keycode, int) const) & UInputMan::KeyHeld) - .def("KeyHeld", (bool(UInputMan::*)(SDL_Keycode) const) & UInputMan::KeyHeldKeycode) - .def("ScancodePressed", (bool(UInputMan::*)(SDL_Scancode, int) const) & UInputMan::KeyPressed) - .def("ScancodePressed", (bool(UInputMan::*)(SDL_Scancode) const) & UInputMan::KeyPressedScancode) - .def("ScancodeReleased", (bool(UInputMan::*)(SDL_Scancode, int) const) & UInputMan::KeyReleased) - .def("ScancodeReleased", (bool(UInputMan::*)(SDL_Scancode) const) & UInputMan::KeyReleasedScancode) - .def("ScancodeHeld", (bool(UInputMan::*)(SDL_Scancode, int) const) & UInputMan::KeyHeld) - .def("ScancodeHeld", (bool(UInputMan::*)(SDL_Scancode) const) & UInputMan::KeyHeldScancode) - .def("MouseButtonPressed", &UInputMan::MouseButtonPressed) - .def("MouseButtonReleased", &UInputMan::MouseButtonReleased) - .def("MouseButtonHeld", &UInputMan::MouseButtonHeld) - .def("GetMousePos", &UInputMan::GetAbsoluteMousePosition) - .def("MouseWheelMoved", &UInputMan::MouseWheelMoved) - .def("JoyButtonPressed", &UInputMan::JoyButtonPressed) - .def("JoyButtonReleased", &UInputMan::JoyButtonReleased) - .def("JoyButtonHeld", &UInputMan::JoyButtonHeld) - .def("WhichJoyButtonPressed", &UInputMan::WhichJoyButtonPressed) - .def("JoyDirectionPressed", &UInputMan::JoyDirectionPressed) - .def("JoyDirectionReleased", &UInputMan::JoyDirectionReleased) - .def("JoyDirectionHeld", &UInputMan::JoyDirectionHeld) - .def("AnalogMoveValues", &UInputMan::AnalogMoveValues) - .def("AnalogAimValues", &UInputMan::AnalogAimValues) - .def("SetMouseValueMagnitude", &UInputMan::SetMouseValueMagnitude) - .def("AnalogAxisValue", &UInputMan::AnalogAxisValue) - .def("MouseUsedByPlayer", &UInputMan::MouseUsedByPlayer) - .def("AnyMouseButtonPress", &UInputMan::AnyMouseButtonPress) - .def("GetMouseMovement", &UInputMan::GetMouseMovement) - .def("DisableMouseMoving", &UInputMan::DisableMouseMoving) - .def("SetMousePos", &UInputMan::SetMousePos) - .def("ForceMouseWithinBox", &UInputMan::ForceMouseWithinBox) - .def("AnyKeyPress", &UInputMan::AnyKeyPress) - .def("AnyJoyInput", &UInputMan::AnyJoyInput) - .def("AnyJoyPress", &UInputMan::AnyJoyPress) - .def("AnyJoyButtonPress", &UInputMan::AnyJoyButtonPress) - .def("AnyInput", &UInputMan::AnyKeyOrJoyInput) - .def("AnyPress", &UInputMan::AnyPress) - .def("AnyStartPress", &UInputMan::AnyStartPress) - .def("HasTextInput", &UInputMan::HasTextInput) - .def("GetTextInput", (const std::string& (UInputMan::*)() const) & UInputMan::GetTextInput) - - .def("MouseButtonPressed", &LuaAdaptersUInputMan::MouseButtonPressed) - .def("MouseButtonReleased", &LuaAdaptersUInputMan::MouseButtonReleased) - .def("MouseButtonHeld", &LuaAdaptersUInputMan::MouseButtonHeld); + registry.Class("UInputManager") + + .addProperty("FlagLAltState", &UInputMan::FlagLAltState) + .addProperty("FlagRAltState", &UInputMan::FlagRAltState) + .addProperty("FlagAltState", &UInputMan::FlagAltState) + .addProperty("FlagLCtrlState", &UInputMan::FlagLCtrlState) + .addProperty("FlagRCtrlState", &UInputMan::FlagRCtrlState) + .addProperty("FlagCtrlState", &UInputMan::FlagCtrlState) + .addProperty("FlagLShiftState", &UInputMan::FlagLShiftState) + .addProperty("FlagRShiftState", &UInputMan::FlagRShiftState) + .addProperty("FlagShiftState", &UInputMan::FlagShiftState) + + .addFunction("GetInputDevice", &UInputMan::GetInputDevice) + .addFunction("ElementPressed", &UInputMan::ElementPressed) + .addFunction("ElementReleased", &UInputMan::ElementReleased) + .addFunction("ElementHeld", &UInputMan::ElementHeld) + .addFunction("KeyPressed", (bool(UInputMan::*)(SDL_Keycode, int) const) & UInputMan::KeyPressed) + .addFunction("KeyPressed", (bool(UInputMan::*)(SDL_Keycode) const) & UInputMan::KeyPressedKeycode) + .addFunction("KeyReleased", (bool(UInputMan::*)(SDL_Keycode, int) const) & UInputMan::KeyReleased) + .addFunction("KeyReleased", (bool(UInputMan::*)(SDL_Keycode) const) & UInputMan::KeyReleasedKeycode) + .addFunction("KeyHeld", (bool(UInputMan::*)(SDL_Keycode, int) const) & UInputMan::KeyHeld) + .addFunction("KeyHeld", (bool(UInputMan::*)(SDL_Keycode) const) & UInputMan::KeyHeldKeycode) + .addFunction("ScancodePressed", (bool(UInputMan::*)(SDL_Scancode, int) const) & UInputMan::KeyPressed) + .addFunction("ScancodePressed", (bool(UInputMan::*)(SDL_Scancode) const) & UInputMan::KeyPressedScancode) + .addFunction("ScancodeReleased", (bool(UInputMan::*)(SDL_Scancode, int) const) & UInputMan::KeyReleased) + .addFunction("ScancodeReleased", (bool(UInputMan::*)(SDL_Scancode) const) & UInputMan::KeyReleasedScancode) + .addFunction("ScancodeHeld", (bool(UInputMan::*)(SDL_Scancode, int) const) & UInputMan::KeyHeld) + .addFunction("ScancodeHeld", (bool(UInputMan::*)(SDL_Scancode) const) & UInputMan::KeyHeldScancode) + .addFunction("MouseButtonPressed", &UInputMan::MouseButtonPressed) + .addFunction("MouseButtonReleased", &UInputMan::MouseButtonReleased) + .addFunction("MouseButtonHeld", &UInputMan::MouseButtonHeld) + .addFunction("GetMousePos", &UInputMan::GetAbsoluteMousePosition) + .addFunction("MouseWheelMoved", &UInputMan::MouseWheelMoved) + .addFunction("JoyButtonPressed", &UInputMan::JoyButtonPressed) + .addFunction("JoyButtonReleased", &UInputMan::JoyButtonReleased) + .addFunction("JoyButtonHeld", &UInputMan::JoyButtonHeld) + .addFunction("WhichJoyButtonPressed", &UInputMan::WhichJoyButtonPressed) + .addFunction("JoyDirectionPressed", &UInputMan::JoyDirectionPressed) + .addFunction("JoyDirectionReleased", &UInputMan::JoyDirectionReleased) + .addFunction("JoyDirectionHeld", &UInputMan::JoyDirectionHeld) + .addFunction("AnalogMoveValues", &UInputMan::AnalogMoveValues) + .addFunction("AnalogAimValues", &UInputMan::AnalogAimValues) + .addFunction("SetMouseValueMagnitude", &UInputMan::SetMouseValueMagnitude) + .addFunction("AnalogAxisValue", &UInputMan::AnalogAxisValue) + .addFunction("MouseUsedByPlayer", &UInputMan::MouseUsedByPlayer) + .addFunction("AnyMouseButtonPress", &UInputMan::AnyMouseButtonPress) + .addFunction("GetMouseMovement", &UInputMan::GetMouseMovement) + .addFunction("DisableMouseMoving", &UInputMan::DisableMouseMoving) + .addFunction("SetMousePos", &UInputMan::SetMousePos) + .addFunction("ForceMouseWithinBox", &UInputMan::ForceMouseWithinBox) + .addFunction("AnyKeyPress", &UInputMan::AnyKeyPress) + .addFunction("AnyJoyInput", &UInputMan::AnyJoyInput) + .addFunction("AnyJoyPress", &UInputMan::AnyJoyPress) + .addFunction("AnyJoyButtonPress", &UInputMan::AnyJoyButtonPress) + .addFunction("AnyInput", &UInputMan::AnyKeyOrJoyInput) + .addFunction("AnyPress", &UInputMan::AnyPress) + .addFunction("AnyStartPress", &UInputMan::AnyStartPress) + .addFunction("HasTextInput", &UInputMan::HasTextInput) + .addFunction("GetTextInput", (const std::string& (UInputMan::*)() const) & UInputMan::GetTextInput) + + .addFunction("MouseButtonPressed", &LuaAdaptersUInputMan::MouseButtonPressed) + .addFunction("MouseButtonReleased", &LuaAdaptersUInputMan::MouseButtonReleased) + .addFunction("MouseButtonHeld", &LuaAdaptersUInputMan::MouseButtonHeld); } diff --git a/Source/Lua/LuaBindingsMisc.cpp b/Source/Lua/LuaBindingsMisc.cpp index a57e9e369e..83b00df620 100644 --- a/Source/Lua/LuaBindingsMisc.cpp +++ b/Source/Lua/LuaBindingsMisc.cpp @@ -5,52 +5,50 @@ using namespace RTE; LuaBindingRegisterFunctionDefinitionForType(MiscLuaBindings, AlarmEvent) { - return luabind::class_("AlarmEvent") + registry.Class("AlarmEvent") - .def(luabind::constructor<>()) - .def(luabind::constructor()) + .addConstructor<>() + .addConstructor() - .def_readwrite("ScenePos", &AlarmEvent::m_ScenePos) - .def_readwrite("Team", &AlarmEvent::m_Team) - .def_readwrite("Range", &AlarmEvent::m_Range); + .addReadWriteMember("ScenePos", &AlarmEvent::m_ScenePos) + .addReadWriteMember("Team", &AlarmEvent::m_Team) + .addReadWriteMember("Range", &AlarmEvent::m_Range); } LuaBindingRegisterFunctionDefinitionForType(MiscLuaBindings, Directions) { - return luabind::class_("Directions") - - .enum_("Directions")[luabind::value("None", Directions::None), - luabind::value("Up", Directions::Up), - luabind::value("Down", Directions::Down), - luabind::value("Left", Directions::Left), - luabind::value("Right", Directions::Right), - luabind::value("Any", Directions::Any)]; + registry.Class("Directions") + + .addEnum({{"None", Directions::None}, + {"Up", Directions::Up}, + {"Down", Directions::Down}, + {"Left", Directions::Left}, + {"Right", Directions::Right}, + {"Any", Directions::Any}}); } LuaBindingRegisterFunctionDefinitionForType(MiscLuaBindings, DrawBlendMode) { - return luabind::class_("DrawBlendMode") - - .enum_("DrawBlendMode")[luabind::value("NoBlend", DrawBlendMode::NoBlend), - luabind::value("Burn", DrawBlendMode::BlendBurn), - luabind::value("Color", DrawBlendMode::BlendColor), - luabind::value("Difference", DrawBlendMode::BlendDifference), - luabind::value("Dissolve", DrawBlendMode::BlendDissolve), - luabind::value("Dodge", DrawBlendMode::BlendDodge), - luabind::value("Invert", DrawBlendMode::BlendInvert), - luabind::value("Luminance", DrawBlendMode::BlendLuminance), - luabind::value("Multiply", DrawBlendMode::BlendMultiply), - luabind::value("Saturation", DrawBlendMode::BlendSaturation), - luabind::value("Screen", DrawBlendMode::BlendScreen), - luabind::value("Transparency", DrawBlendMode::BlendTransparency), - luabind::value("BlendModeCount", DrawBlendMode::BlendModeCount)]; + registry.Class("DrawBlendMode") + + .addEnum({{"NoBlend", DrawBlendMode::NoBlend}, + {"Burn", DrawBlendMode::BlendBurn}, + {"Color", DrawBlendMode::BlendColor}, + {"Difference", DrawBlendMode::BlendDifference}, + {"Dissolve", DrawBlendMode::BlendDissolve}, + {"Dodge", DrawBlendMode::BlendDodge}, + {"Invert", DrawBlendMode::BlendInvert}, + {"Luminance", DrawBlendMode::BlendLuminance}, + {"Multiply", DrawBlendMode::BlendMultiply}, + {"Saturation", DrawBlendMode::BlendSaturation}, + {"Screen", DrawBlendMode::BlendScreen}, + {"Transparency", DrawBlendMode::BlendTransparency}, + {"BlendModeCount", DrawBlendMode::BlendModeCount}}); } LuaBindingRegisterFunctionDefinitionForType(MiscLuaBindings, DrawDepth) { - return luabind::class_("DrawDepth") - .enum_("DrawDepth")[ - luabind::value("Default", c_DefaultDrawDepth), - luabind::value("GUI", c_GuiDepth), - luabind::value("Primitive", c_PrimitiveDepth), - luabind::value("TerrainBackground", c_TerrainBGDepth), - luabind::value("Background", c_BackgroundDepth) - ]; + registry.Class("DrawDepth") + .addEnum({{"Default", c_DefaultDrawDepth}, + {"GUI", c_GuiDepth}, + {"Primitive", c_PrimitiveDepth}, + {"TerrainBackground", c_TerrainBGDepth}, + {"Background", c_BackgroundDepth}}); } diff --git a/Source/Lua/LuaBindingsPrimitives.cpp b/Source/Lua/LuaBindingsPrimitives.cpp index 6c08f707f4..0e1928a795 100644 --- a/Source/Lua/LuaBindingsPrimitives.cpp +++ b/Source/Lua/LuaBindingsPrimitives.cpp @@ -5,115 +5,115 @@ using namespace RTE; LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, GraphicalPrimitive) { - return luabind::class_("GraphicalPrimitive"); + registry.Class("GraphicalPrimitive"); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, LinePrimitive) { - return luabind::class_("LinePrimitive") + registry.Class("LinePrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, ArcPrimitive) { - return luabind::class_("ArcPrimitive") + registry.Class("ArcPrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, SplinePrimitive) { - return luabind::class_("SplinePrimitive") + registry.Class("SplinePrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, BoxPrimitive) { - return luabind::class_("BoxPrimitive") + registry.Class("BoxPrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, BoxFillPrimitive) { - return luabind::class_("BoxFillPrimitive") + registry.Class("BoxFillPrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, RoundedBoxPrimitive) { - return luabind::class_("RoundedBoxPrimitive") + registry.Class("RoundedBoxPrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, RoundedBoxFillPrimitive) { - return luabind::class_("RoundedBoxFillPrimitive") + registry.Class("RoundedBoxFillPrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, CirclePrimitive) { - return luabind::class_("CirclePrimitive") + registry.Class("CirclePrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, CircleFillPrimitive) { - return luabind::class_("CircleFillPrimitive") + registry.Class("CircleFillPrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, EllipsePrimitive) { - return luabind::class_("EllipsePrimitive") + registry.Class("EllipsePrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, EllipseFillPrimitive) { - return luabind::class_("EllipseFillPrimitive") + registry.Class("EllipseFillPrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, TrianglePrimitive) { - return luabind::class_("TrianglePrimitive") + registry.Class("TrianglePrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, TriangleFillPrimitive) { - return luabind::class_("TriangleFillPrimitive") + registry.Class("TriangleFillPrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, TextPrimitive) { - return luabind::class_("TextPrimitive") + registry.Class("TextPrimitive") - .def(luabind::constructor()) - .def(luabind::constructor()); + .addConstructor() + .addConstructor(); } LuaBindingRegisterFunctionDefinitionForType(PrimitiveLuaBindings, BitmapPrimitive) { - return luabind::class_("BitmapPrimitive") - - .def(luabind::constructor()) - .def(luabind::constructor()) - .def(luabind::constructor()) - .def(luabind::constructor()) - .def(luabind::constructor()) - .def(luabind::constructor()); + registry.Class("BitmapPrimitive") + + .addConstructor() + .addConstructor() + .addConstructor() + .addConstructor() + .addConstructor() + .addConstructor(); } diff --git a/Source/Lua/LuaBindingsSystem.cpp b/Source/Lua/LuaBindingsSystem.cpp index 19aa29ac4d..30bf55e719 100644 --- a/Source/Lua/LuaBindingsSystem.cpp +++ b/Source/Lua/LuaBindingsSystem.cpp @@ -1,248 +1,247 @@ // Make sure that binding definition files are always set to NOT use pre-compiled headers and conformance mode (/permissive) otherwise everything will be on fire! #include "LuaBindingRegisterDefinitions.h" -#include "return_reference_to_policy.hpp" using namespace RTE; LuaBindingRegisterFunctionDefinitionForType(SystemLuaBindings, Box) { - return luabind::class_("Box") - - .def(luabind::constructor<>()) - .def(luabind::constructor()) - .def(luabind::constructor()) - .def(luabind::constructor()) - .def(luabind::constructor()) - .def(luabind::self == luabind::other()) - - .property("ClassName", &Box::GetClassName) - .property("Corner", &Box::GetCorner, &Box::SetCorner) - .property("Width", &Box::GetWidth, &Box::SetWidth) - .property("Height", &Box::GetHeight, &Box::SetHeight) - .property("Center", &Box::GetCenter, &Box::SetCenter) - .property("Area", &Box::GetArea) - - .def("GetRandomPoint", &Box::GetRandomPoint) - .def("Unflip", &Box::Unflip) - .def("IsWithinBox", &Box::IsWithinBox) - .def("IsWithinBoxX", &Box::IsWithinBoxX) - .def("IsWithinBoxY", &Box::IsWithinBoxY) - .def("GetWithinBoxX", &Box::GetWithinBoxX) - .def("GetWithinBoxY", &Box::GetWithinBoxY) - .def("GetWithinBox", &Box::GetWithinBox) - .def("IntersectsBox", &Box::IntersectsBox); + registry.Class("Box") + + .addConstructor<>() + .addConstructor() + .addConstructor() + .addConstructor() + .addConstructor() + .addEqualityOperator() + + .addProperty("ClassName", &Box::GetClassName) + .addProperty("Corner", &Box::GetCorner, &Box::SetCorner) + .addProperty("Width", &Box::GetWidth, &Box::SetWidth) + .addProperty("Height", &Box::GetHeight, &Box::SetHeight) + .addProperty("Center", &Box::GetCenter, &Box::SetCenter) + .addProperty("Area", &Box::GetArea) + + .addFunction("GetRandomPoint", &Box::GetRandomPoint) + .addFunction("Unflip", &Box::Unflip) + .addFunction("IsWithinBox", &Box::IsWithinBox) + .addFunction("IsWithinBoxX", &Box::IsWithinBoxX) + .addFunction("IsWithinBoxY", &Box::IsWithinBoxY) + .addFunction("GetWithinBoxX", &Box::GetWithinBoxX) + .addFunction("GetWithinBoxY", &Box::GetWithinBoxY) + .addFunction("GetWithinBox", &Box::GetWithinBox) + .addFunction("IntersectsBox", &Box::IntersectsBox); } LuaBindingRegisterFunctionDefinitionForType(SystemLuaBindings, Controller) { - return luabind::class_("Controller") - - .def(luabind::constructor<>()) - - .property("InputMode", &Controller::GetInputMode, &Controller::SetInputMode) - .property("ControlledActor", &Controller::GetControlledActor, &Controller::SetControlledActor) - .property("Team", &Controller::GetTeam, &Controller::SetTeam) - .property("AnalogMove", &Controller::GetAnalogMove, &Controller::SetAnalogMove) - .property("AnalogAim", &Controller::GetAnalogAim, &Controller::SetAnalogAim) - .property("AnalogCursor", &Controller::GetAnalogCursor, &Controller::SetAnalogCursor) - .property("Player", &Controller::GetPlayer, &Controller::SetPlayer) - .property("MouseMovement", &Controller::GetMouseMovement) - .property("Disabled", &Controller::IsDisabled, &Controller::SetDisabled) - - .def("IsPlayerControlled", &Controller::IsPlayerControlled) - .def("RelativeCursorMovement", &Controller::RelativeCursorMovement) - .def("IsMouseControlled", &Controller::IsMouseControlled) - .def("IsKeyboardOnlyControlled", &Controller::IsKeyboardOnlyControlled) - .def("IsGamepadControlled", &Controller::IsGamepadControlled) - .def("SetState", &Controller::SetState) - .def("IsState", &Controller::IsState) - .def("Override", &Controller::Override) - - .enum_("ControlState")[luabind::value("PRIMARY_ACTION", ControlState::PRIMARY_ACTION), - luabind::value("SECONDARY_ACTION", ControlState::SECONDARY_ACTION), - luabind::value("MOVE_IDLE", ControlState::MOVE_IDLE), - luabind::value("MOVE_RIGHT", ControlState::MOVE_RIGHT), - luabind::value("MOVE_LEFT", ControlState::MOVE_LEFT), - luabind::value("MOVE_UP", ControlState::MOVE_UP), - luabind::value("MOVE_DOWN", ControlState::MOVE_DOWN), - luabind::value("MOVE_FAST", ControlState::MOVE_FAST), - luabind::value("BODY_JUMPSTART", ControlState::BODY_JUMPSTART), - luabind::value("BODY_JUMP", ControlState::BODY_JUMP), - luabind::value("BODY_CROUCH", ControlState::BODY_PRONE), // awful, but script compat - luabind::value("BODY_PRONE", ControlState::BODY_PRONE), - luabind::value("BODY_WALKCROUCH", ControlState::BODY_CROUCH), - luabind::value("AIM_UP", ControlState::AIM_UP), - luabind::value("AIM_DOWN", ControlState::AIM_DOWN), - luabind::value("AIM_SHARP", ControlState::AIM_SHARP), - luabind::value("WEAPON_FIRE", ControlState::WEAPON_FIRE), - luabind::value("WEAPON_RELOAD", ControlState::WEAPON_RELOAD), - luabind::value("WEAPON_RELOADHELD", ControlState::WEAPON_RELOADHELD), - luabind::value("PIE_MENU_OPENED", ControlState::PIE_MENU_OPENED), - luabind::value("PIE_MENU_ACTIVE", ControlState::PIE_MENU_ACTIVE), - luabind::value("WEAPON_CHANGE_NEXT", ControlState::WEAPON_CHANGE_NEXT), - luabind::value("WEAPON_CHANGE_PREV", ControlState::WEAPON_CHANGE_PREV), - luabind::value("WEAPON_PICKUP", ControlState::WEAPON_PICKUP), - luabind::value("WEAPON_DROP", ControlState::WEAPON_DROP), - luabind::value("WEAPON_PRIMARY_HOTKEY", ControlState::WEAPON_PRIMARY_HOTKEY), - luabind::value("WEAPON_AUXILIARY_HOTKEY", ControlState::WEAPON_AUXILIARY_HOTKEY), - luabind::value("ACTOR_PRIMARY_HOTKEY", ControlState::ACTOR_PRIMARY_HOTKEY), - luabind::value("ACTOR_AUXILIARY_HOTKEY", ControlState::ACTOR_AUXILIARY_HOTKEY), - luabind::value("WEAPON_PRIMARY_HOTKEYSTART", ControlState::WEAPON_PRIMARY_HOTKEYSTART), - luabind::value("WEAPON_AUXILIARY_HOTKEYSTART", ControlState::WEAPON_AUXILIARY_HOTKEYSTART), - luabind::value("ACTOR_PRIMARY_HOTKEYSTART", ControlState::ACTOR_PRIMARY_HOTKEYSTART), - luabind::value("ACTOR_AUXILIARY_HOTKEYSTART", ControlState::ACTOR_AUXILIARY_HOTKEYSTART), - luabind::value("ACTOR_NEXT", ControlState::ACTOR_NEXT), - luabind::value("ACTOR_PREV", ControlState::ACTOR_PREV), - luabind::value("ACTOR_BRAIN", ControlState::ACTOR_BRAIN), - luabind::value("ACTOR_NEXT_PREP", ControlState::ACTOR_NEXT_PREP), - luabind::value("ACTOR_PREV_PREP", ControlState::ACTOR_PREV_PREP), - luabind::value("HOLD_RIGHT", ControlState::HOLD_RIGHT), - luabind::value("HOLD_LEFT", ControlState::HOLD_LEFT), - luabind::value("HOLD_UP", ControlState::HOLD_UP), - luabind::value("HOLD_DOWN", ControlState::HOLD_DOWN), - luabind::value("PRESS_PRIMARY", ControlState::PRESS_PRIMARY), - luabind::value("PRESS_SECONDARY", ControlState::PRESS_SECONDARY), - luabind::value("PRESS_RIGHT", ControlState::PRESS_RIGHT), - luabind::value("PRESS_LEFT", ControlState::PRESS_LEFT), - luabind::value("PRESS_UP", ControlState::PRESS_UP), - luabind::value("PRESS_DOWN", ControlState::PRESS_DOWN), - luabind::value("RELEASE_PRIMARY", ControlState::RELEASE_PRIMARY), - luabind::value("RELEASE_SECONDARY", ControlState::RELEASE_SECONDARY), - luabind::value("PRESS_FACEBUTTON", ControlState::PRESS_FACEBUTTON), - luabind::value("RELEASE_FACEBUTTON", ControlState::RELEASE_FACEBUTTON), - luabind::value("SCROLL_UP", ControlState::SCROLL_UP), - luabind::value("SCROLL_DOWN", ControlState::SCROLL_DOWN), - luabind::value("DEBUG_ONE", ControlState::DEBUG_ONE), - luabind::value("CONTROLSTATECOUNT", ControlState::CONTROLSTATECOUNT)] - .enum_("InputMode")[luabind::value("CIM_DISABLED", Controller::InputMode::CIM_DISABLED), - luabind::value("CIM_PLAYER", Controller::InputMode::CIM_PLAYER), - luabind::value("CIM_AI", Controller::InputMode::CIM_AI), - luabind::value("CIM_NETWORK", Controller::InputMode::CIM_NETWORK), - luabind::value("CIM_INPUTMODECOUNT", Controller::InputMode::CIM_INPUTMODECOUNT)]; + registry.Class("Controller") + + .addConstructor<>() + + .addProperty("InputMode", &Controller::GetInputMode, &Controller::SetInputMode) + .addProperty("ControlledActor", &Controller::GetControlledActor, &Controller::SetControlledActor) + .addProperty("Team", &Controller::GetTeam, &Controller::SetTeam) + .addProperty("AnalogMove", &Controller::GetAnalogMove, &Controller::SetAnalogMove) + .addProperty("AnalogAim", &Controller::GetAnalogAim, &Controller::SetAnalogAim) + .addProperty("AnalogCursor", &Controller::GetAnalogCursor, &Controller::SetAnalogCursor) + .addProperty("Player", &Controller::GetPlayer, &Controller::SetPlayer) + .addProperty("MouseMovement", &Controller::GetMouseMovement) + .addProperty("Disabled", &Controller::IsDisabled, &Controller::SetDisabled) + + .addFunction("IsPlayerControlled", &Controller::IsPlayerControlled) + .addFunction("RelativeCursorMovement", &Controller::RelativeCursorMovement) + .addFunction("IsMouseControlled", &Controller::IsMouseControlled) + .addFunction("IsKeyboardOnlyControlled", &Controller::IsKeyboardOnlyControlled) + .addFunction("IsGamepadControlled", &Controller::IsGamepadControlled) + .addFunction("SetState", &Controller::SetState) + .addFunction("IsState", &Controller::IsState) + .addFunction("Override", &Controller::Override) + + .addEnum({{"PRIMARY_ACTION", ControlState::PRIMARY_ACTION}, + {"SECONDARY_ACTION", ControlState::SECONDARY_ACTION}, + {"MOVE_IDLE", ControlState::MOVE_IDLE}, + {"MOVE_RIGHT", ControlState::MOVE_RIGHT}, + {"MOVE_LEFT", ControlState::MOVE_LEFT}, + {"MOVE_UP", ControlState::MOVE_UP}, + {"MOVE_DOWN", ControlState::MOVE_DOWN}, + {"MOVE_FAST", ControlState::MOVE_FAST}, + {"BODY_JUMPSTART", ControlState::BODY_JUMPSTART}, + {"BODY_JUMP", ControlState::BODY_JUMP}, + {"BODY_CROUCH", ControlState::BODY_PRONE}, // awful, but script compat + {"BODY_PRONE", ControlState::BODY_PRONE}, + {"BODY_WALKCROUCH", ControlState::BODY_CROUCH}, + {"AIM_UP", ControlState::AIM_UP}, + {"AIM_DOWN", ControlState::AIM_DOWN}, + {"AIM_SHARP", ControlState::AIM_SHARP}, + {"WEAPON_FIRE", ControlState::WEAPON_FIRE}, + {"WEAPON_RELOAD", ControlState::WEAPON_RELOAD}, + {"WEAPON_RELOADHELD", ControlState::WEAPON_RELOADHELD}, + {"PIE_MENU_OPENED", ControlState::PIE_MENU_OPENED}, + {"PIE_MENU_ACTIVE", ControlState::PIE_MENU_ACTIVE}, + {"WEAPON_CHANGE_NEXT", ControlState::WEAPON_CHANGE_NEXT}, + {"WEAPON_CHANGE_PREV", ControlState::WEAPON_CHANGE_PREV}, + {"WEAPON_PICKUP", ControlState::WEAPON_PICKUP}, + {"WEAPON_DROP", ControlState::WEAPON_DROP}, + {"WEAPON_PRIMARY_HOTKEY", ControlState::WEAPON_PRIMARY_HOTKEY}, + {"WEAPON_AUXILIARY_HOTKEY", ControlState::WEAPON_AUXILIARY_HOTKEY}, + {"ACTOR_PRIMARY_HOTKEY", ControlState::ACTOR_PRIMARY_HOTKEY}, + {"ACTOR_AUXILIARY_HOTKEY", ControlState::ACTOR_AUXILIARY_HOTKEY}, + {"WEAPON_PRIMARY_HOTKEYSTART", ControlState::WEAPON_PRIMARY_HOTKEYSTART}, + {"WEAPON_AUXILIARY_HOTKEYSTART", ControlState::WEAPON_AUXILIARY_HOTKEYSTART}, + {"ACTOR_PRIMARY_HOTKEYSTART", ControlState::ACTOR_PRIMARY_HOTKEYSTART}, + {"ACTOR_AUXILIARY_HOTKEYSTART", ControlState::ACTOR_AUXILIARY_HOTKEYSTART}, + {"ACTOR_NEXT", ControlState::ACTOR_NEXT}, + {"ACTOR_PREV", ControlState::ACTOR_PREV}, + {"ACTOR_BRAIN", ControlState::ACTOR_BRAIN}, + {"ACTOR_NEXT_PREP", ControlState::ACTOR_NEXT_PREP}, + {"ACTOR_PREV_PREP", ControlState::ACTOR_PREV_PREP}, + {"HOLD_RIGHT", ControlState::HOLD_RIGHT}, + {"HOLD_LEFT", ControlState::HOLD_LEFT}, + {"HOLD_UP", ControlState::HOLD_UP}, + {"HOLD_DOWN", ControlState::HOLD_DOWN}, + {"PRESS_PRIMARY", ControlState::PRESS_PRIMARY}, + {"PRESS_SECONDARY", ControlState::PRESS_SECONDARY}, + {"PRESS_RIGHT", ControlState::PRESS_RIGHT}, + {"PRESS_LEFT", ControlState::PRESS_LEFT}, + {"PRESS_UP", ControlState::PRESS_UP}, + {"PRESS_DOWN", ControlState::PRESS_DOWN}, + {"RELEASE_PRIMARY", ControlState::RELEASE_PRIMARY}, + {"RELEASE_SECONDARY", ControlState::RELEASE_SECONDARY}, + {"PRESS_FACEBUTTON", ControlState::PRESS_FACEBUTTON}, + {"RELEASE_FACEBUTTON", ControlState::RELEASE_FACEBUTTON}, + {"SCROLL_UP", ControlState::SCROLL_UP}, + {"SCROLL_DOWN", ControlState::SCROLL_DOWN}, + {"DEBUG_ONE", ControlState::DEBUG_ONE}, + {"CONTROLSTATECOUNT", ControlState::CONTROLSTATECOUNT}}) + .addEnum({{"CIM_DISABLED", Controller::InputMode::CIM_DISABLED}, + {"CIM_PLAYER", Controller::InputMode::CIM_PLAYER}, + {"CIM_AI", Controller::InputMode::CIM_AI}, + {"CIM_NETWORK", Controller::InputMode::CIM_NETWORK}, + {"CIM_INPUTMODECOUNT", Controller::InputMode::CIM_INPUTMODECOUNT}}); } LuaBindingRegisterFunctionDefinitionForType(SystemLuaBindings, DataModule) { - return luabind::class_("DataModule") + registry.Class("DataModule") - .property("FileName", &DataModule::GetFileName) - .property("FriendlyName", &DataModule::GetFriendlyName) - .property("Author", &DataModule::GetAuthor) - .property("Description", &DataModule::GetDescription) - .property("Version", &DataModule::GetVersionNumber) - .property("IsFaction", &DataModule::IsFaction) - .property("IsMerchant", &DataModule::IsMerchant) + .addProperty("FileName", &DataModule::GetFileName) + .addProperty("FriendlyName", &DataModule::GetFriendlyName) + .addProperty("Author", &DataModule::GetAuthor) + .addProperty("Description", &DataModule::GetDescription) + .addProperty("Version", &DataModule::GetVersionNumber) + .addProperty("IsFaction", &DataModule::IsFaction) + .addProperty("IsMerchant", &DataModule::IsMerchant) - .def_readwrite("Presets", &DataModule::m_EntityList, luabind::return_stl_iterator); + .addProperty("Presets", &DataModule::m_EntityList, LuaBinding::ReturnStlIterator); } LuaBindingRegisterFunctionDefinitionForType(SystemLuaBindings, Timer) { - return luabind::class_("Timer") - - .def(luabind::constructor<>()) - .def(luabind::constructor()) - .def(luabind::constructor()) - - .property("StartRealTimeMS", &Timer::GetStartRealTimeMS, &Timer::SetStartRealTimeMS) - .property("ElapsedRealTimeS", &Timer::GetElapsedRealTimeS, &Timer::SetElapsedRealTimeS) - .property("ElapsedRealTimeMS", &Timer::GetElapsedRealTimeMS, &Timer::SetElapsedRealTimeMS) - .property("StartSimTimeMS", &Timer::GetStartSimTimeMS, &Timer::SetStartSimTimeMS) - .property("ElapsedSimTimeS", &Timer::GetElapsedSimTimeS, &Timer::SetElapsedSimTimeS) - .property("ElapsedSimTimeMS", &Timer::GetElapsedSimTimeMS, &Timer::SetElapsedSimTimeMS) - .property("RealTimeLimitProgress", &Timer::GetRealTimeLimitProgress, &Timer::SetRealTimeLimitProgress) - .property("SimTimeLimitProgress", &Timer::GetSimTimeLimitProgress, &Timer::SetSimTimeLimitProgress) - - .def("Reset", &Timer::Reset) - .def("SetRealTimeLimitMS", &Timer::SetRealTimeLimitMS) - .def("SetRealTimeLimitS", &Timer::SetRealTimeLimitS) - .def("IsPastRealTimeLimit", &Timer::IsPastRealTimeLimit) - .def("LeftTillRealTimeLimitMS", &Timer::LeftTillRealTimeLimitMS) - .def("LeftTillRealTimeLimitS", &Timer::LeftTillRealTimeLimitS) - .def("LeftTillRealMS", &Timer::LeftTillRealMS) - .def("IsPastRealMS", &Timer::IsPastRealMS) - .def("AlternateReal", &Timer::AlternateReal) - .def("GetSimTimeLimitMS", &Timer::GetSimTimeLimitMS) - .def("SetSimTimeLimitMS", &Timer::SetSimTimeLimitMS) - .def("GetSimTimeLimitS", &Timer::GetSimTimeLimitS) - .def("SetSimTimeLimitS", &Timer::SetSimTimeLimitS) - .def("IsPastSimTimeLimit", &Timer::IsPastSimTimeLimit) - .def("LeftTillSimTimeLimitMS", &Timer::LeftTillSimTimeLimitMS) - .def("LeftTillSimTimeLimitS", &Timer::LeftTillSimTimeLimitS) - .def("LeftTillSimMS", &Timer::LeftTillSimMS) - .def("IsPastSimMS", &Timer::IsPastSimMS) - .def("AlternateSim", &Timer::AlternateSim); + registry.Class("Timer") + + .addConstructor<>() + .addConstructor() + .addConstructor() + + .addProperty("StartRealTimeMS", &Timer::GetStartRealTimeMS, &Timer::SetStartRealTimeMS) + .addProperty("ElapsedRealTimeS", &Timer::GetElapsedRealTimeS, &Timer::SetElapsedRealTimeS) + .addProperty("ElapsedRealTimeMS", &Timer::GetElapsedRealTimeMS, &Timer::SetElapsedRealTimeMS) + .addProperty("StartSimTimeMS", &Timer::GetStartSimTimeMS, &Timer::SetStartSimTimeMS) + .addProperty("ElapsedSimTimeS", &Timer::GetElapsedSimTimeS, &Timer::SetElapsedSimTimeS) + .addProperty("ElapsedSimTimeMS", &Timer::GetElapsedSimTimeMS, &Timer::SetElapsedSimTimeMS) + .addProperty("RealTimeLimitProgress", &Timer::GetRealTimeLimitProgress, &Timer::SetRealTimeLimitProgress) + .addProperty("SimTimeLimitProgress", &Timer::GetSimTimeLimitProgress, &Timer::SetSimTimeLimitProgress) + + .addFunction("Reset", &Timer::Reset) + .addFunction("SetRealTimeLimitMS", &Timer::SetRealTimeLimitMS) + .addFunction("SetRealTimeLimitS", &Timer::SetRealTimeLimitS) + .addFunction("IsPastRealTimeLimit", &Timer::IsPastRealTimeLimit) + .addFunction("LeftTillRealTimeLimitMS", &Timer::LeftTillRealTimeLimitMS) + .addFunction("LeftTillRealTimeLimitS", &Timer::LeftTillRealTimeLimitS) + .addFunction("LeftTillRealMS", &Timer::LeftTillRealMS) + .addFunction("IsPastRealMS", &Timer::IsPastRealMS) + .addFunction("AlternateReal", &Timer::AlternateReal) + .addFunction("GetSimTimeLimitMS", &Timer::GetSimTimeLimitMS) + .addFunction("SetSimTimeLimitMS", &Timer::SetSimTimeLimitMS) + .addFunction("GetSimTimeLimitS", &Timer::GetSimTimeLimitS) + .addFunction("SetSimTimeLimitS", &Timer::SetSimTimeLimitS) + .addFunction("IsPastSimTimeLimit", &Timer::IsPastSimTimeLimit) + .addFunction("LeftTillSimTimeLimitMS", &Timer::LeftTillSimTimeLimitMS) + .addFunction("LeftTillSimTimeLimitS", &Timer::LeftTillSimTimeLimitS) + .addFunction("LeftTillSimMS", &Timer::LeftTillSimMS) + .addFunction("IsPastSimMS", &Timer::IsPastSimMS) + .addFunction("AlternateSim", &Timer::AlternateSim); } LuaBindingRegisterFunctionDefinitionForType(SystemLuaBindings, Vector) { - return luabind::class_("Vector") - - .def(luabind::constructor<>()) - .def(luabind::constructor()) - .def(luabind::self == luabind::other()) - .def(luabind::const_self + luabind::other()) - .def(luabind::const_self - luabind::other()) - .def(luabind::const_self * float()) - .def(luabind::const_self / float()) - .def(luabind::tostring(luabind::const_self)) - - .property("ClassName", &Vector::GetClassName) - .property("RoundedX", &Vector::GetRoundIntX) - .property("RoundedY", &Vector::GetRoundIntY) - .property("Rounded", &Vector::GetRounded) - .property("FlooredX", &Vector::GetFloorIntX) - .property("FlooredY", &Vector::GetFloorIntY) - .property("Floored", &Vector::GetFloored) - .property("CeilingedX", &Vector::GetCeilingIntX) - .property("CeilingedY", &Vector::GetCeilingIntY) - .property("Ceilinged", &Vector::GetCeilinged) - .property("Magnitude", &Vector::GetMagnitude) - .property("SqrMagnitude", &Vector::GetSqrMagnitude) - .property("Largest", &Vector::GetLargest) - .property("Smallest", &Vector::GetSmallest) - .property("Normalized", &Vector::GetNormalized) - .property("Perpendicular", &Vector::GetPerpendicular) - .property("AbsRadAngle", &Vector::GetAbsRadAngle, &Vector::SetAbsRadAngle) - .property("AbsDegAngle", &Vector::GetAbsDegAngle, &Vector::SetAbsDegAngle) - - .def_readwrite("X", &Vector::m_X) - .def_readwrite("Y", &Vector::m_Y) - - .def("MagnitudeIsGreaterThan", &Vector::MagnitudeIsGreaterThan) - .def("MagnitudeIsLessThan", &Vector::MagnitudeIsLessThan) - .def("SetMagnitude", &Vector::SetMagnitude, luabind::return_reference_to(_1)) - .def("GetXFlipped", &Vector::GetXFlipped) - .def("GetYFlipped", &Vector::GetYFlipped) - .def("CapMagnitude", &Vector::CapMagnitude, luabind::return_reference_to(_1)) - .def("ClampMagnitude", &Vector::ClampMagnitude, luabind::return_reference_to(_1)) - .def("FlipX", &Vector::FlipX, luabind::return_reference_to(_1)) - .def("FlipY", &Vector::FlipY, luabind::return_reference_to(_1)) - .def("IsZero", &Vector::IsZero) - .def("IsOpposedTo", &Vector::IsOpposedTo) - .def("Dot", &Vector::Dot) - .def("Cross", &Vector::Cross) - .def("Round", &Vector::Round, luabind::return_reference_to(_1)) - .def("ToHalf", &Vector::ToHalf, luabind::return_reference_to(_1)) - .def("Floor", &Vector::Floor, luabind::return_reference_to(_1)) - .def("Ceiling", &Vector::Ceiling, luabind::return_reference_to(_1)) - .def("Normalize", &Vector::Normalize, luabind::return_reference_to(_1)) - .def("Perpendicularize", &Vector::Perpendicularize, luabind::return_reference_to(_1)) - .def("Reset", &Vector::Reset) - .def("RadRotate", &Vector::RadRotate, luabind::return_reference_to(_1)) - .def("DegRotate", &Vector::DegRotate, luabind::return_reference_to(_1)) - .def("GetRadRotatedCopy", &Vector::GetRadRotatedCopy) - .def("GetDegRotatedCopy", &Vector::GetDegRotatedCopy) - .def("AbsRotateTo", &Vector::AbsRotateTo, luabind::return_reference_to(_1)) - .def("SetXY", &Vector::SetXY, luabind::return_reference_to(_1)); + registry.Class("Vector") + + .addConstructor<>() + .addConstructor() + .addEqualityOperator() + .addFunction("__add", +[](const Vector& self, const Vector& other) { return self + other; }) + .addFunction("__sub", +[](const Vector& self, const Vector& other) { return self - other; }) + .addFunction("__mul", +[](const Vector& self, float scalar) { return self * scalar; }) + .addFunction("__div", +[](const Vector& self, float scalar) { return self / scalar; }) + .addToString() + + .addProperty("ClassName", &Vector::GetClassName) + .addProperty("RoundedX", &Vector::GetRoundIntX) + .addProperty("RoundedY", &Vector::GetRoundIntY) + .addProperty("Rounded", &Vector::GetRounded) + .addProperty("FlooredX", &Vector::GetFloorIntX) + .addProperty("FlooredY", &Vector::GetFloorIntY) + .addProperty("Floored", &Vector::GetFloored) + .addProperty("CeilingedX", &Vector::GetCeilingIntX) + .addProperty("CeilingedY", &Vector::GetCeilingIntY) + .addProperty("Ceilinged", &Vector::GetCeilinged) + .addProperty("Magnitude", &Vector::GetMagnitude) + .addProperty("SqrMagnitude", &Vector::GetSqrMagnitude) + .addProperty("Largest", &Vector::GetLargest) + .addProperty("Smallest", &Vector::GetSmallest) + .addProperty("Normalized", &Vector::GetNormalized) + .addProperty("Perpendicular", &Vector::GetPerpendicular) + .addProperty("AbsRadAngle", &Vector::GetAbsRadAngle, &Vector::SetAbsRadAngle) + .addProperty("AbsDegAngle", &Vector::GetAbsDegAngle, &Vector::SetAbsDegAngle) + + .addReadWriteMember("X", &Vector::m_X) + .addReadWriteMember("Y", &Vector::m_Y) + + .addFunction("MagnitudeIsGreaterThan", &Vector::MagnitudeIsGreaterThan) + .addFunction("MagnitudeIsLessThan", &Vector::MagnitudeIsLessThan) + .addFunction("SetMagnitude", &Vector::SetMagnitude, LuaBinding::ReturnSelf) + .addFunction("GetXFlipped", &Vector::GetXFlipped) + .addFunction("GetYFlipped", &Vector::GetYFlipped) + .addFunction("CapMagnitude", &Vector::CapMagnitude, LuaBinding::ReturnSelf) + .addFunction("ClampMagnitude", &Vector::ClampMagnitude, LuaBinding::ReturnSelf) + .addFunction("FlipX", &Vector::FlipX, LuaBinding::ReturnSelf) + .addFunction("FlipY", &Vector::FlipY, LuaBinding::ReturnSelf) + .addFunction("IsZero", &Vector::IsZero) + .addFunction("IsOpposedTo", &Vector::IsOpposedTo) + .addFunction("Dot", &Vector::Dot) + .addFunction("Cross", &Vector::Cross) + .addFunction("Round", &Vector::Round, LuaBinding::ReturnSelf) + .addFunction("ToHalf", &Vector::ToHalf, LuaBinding::ReturnSelf) + .addFunction("Floor", &Vector::Floor, LuaBinding::ReturnSelf) + .addFunction("Ceiling", &Vector::Ceiling, LuaBinding::ReturnSelf) + .addFunction("Normalize", &Vector::Normalize, LuaBinding::ReturnSelf) + .addFunction("Perpendicularize", &Vector::Perpendicularize, LuaBinding::ReturnSelf) + .addFunction("Reset", &Vector::Reset) + .addFunction("RadRotate", &Vector::RadRotate, LuaBinding::ReturnSelf) + .addFunction("DegRotate", &Vector::DegRotate, LuaBinding::ReturnSelf) + .addFunction("GetRadRotatedCopy", &Vector::GetRadRotatedCopy) + .addFunction("GetDegRotatedCopy", &Vector::GetDegRotatedCopy) + .addFunction("AbsRotateTo", &Vector::AbsRotateTo, LuaBinding::ReturnSelf) + .addFunction("SetXY", &Vector::SetXY, LuaBinding::ReturnSelf); } LuaBindingRegisterFunctionDefinitionForType(SystemLuaBindings, PathRequest) { using namespace micropather; - return luabind::class_("PathRequest") + registry.Class("PathRequest") - .def_readonly("Path", &PathRequest::path, luabind::return_stl_iterator) - .def_readonly("PathLength", &PathRequest::pathLength) - .def_readonly("Status", &PathRequest::status) - .def_readonly("TotalCost", &PathRequest::totalCost) + .addProperty("Path", &PathRequest::path, LuaBinding::ReturnStlIterator) + .addProperty("PathLength", &PathRequest::pathLength) + .addProperty("Status", &PathRequest::status) + .addProperty("TotalCost", &PathRequest::totalCost) - .enum_("Status")[luabind::value("Solved", micropather::MicroPather::SOLVED), - luabind::value("NoSolution", micropather::MicroPather::NO_SOLUTION), - luabind::value("StartEndSame", micropather::MicroPather::START_END_SAME)]; + .addEnum({{"Solved", micropather::MicroPather::SOLVED}, + {"NoSolution", micropather::MicroPather::NO_SOLUTION}, + {"StartEndSame", micropather::MicroPather::START_END_SAME}}); } diff --git a/Source/Lua/LuaBridgeDefinitions.h b/Source/Lua/LuaBridgeDefinitions.h new file mode 100644 index 0000000000..5a4ca30895 --- /dev/null +++ b/Source/Lua/LuaBridgeDefinitions.h @@ -0,0 +1,1229 @@ +#pragma once + +// LuaBridge must only ever be included through this header, so that every translation unit sees LuaBridge with the same configuration. +// Stack checks are turned off because Lua always guarantees LUA_MINSTACK free slots to C functions, which is all our bindings ever use. +#define LUABRIDGE_SAFE_STACK_CHECKS 0 +// Lua numbers are truncated when passed to integer parameters, the same way luabind did it, rather than rejected when they have a fractional part. +#define LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS 1 + +#include "lua.hpp" +#include "LuaBridge/LuaBridge.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace RTE { + class Entity; + class GraphicalPrimitive; +} // namespace RTE + +#pragma region Enum Stack Specialization +namespace luabridge { + /// Enums go to and from Lua as plain numbers, like they did with luabind. Any Lua number (or numeric string) is accepted and truncated, without any range checks. + template + struct Stack>> { + [[nodiscard]] static Result push(lua_State* luaState, T value) { + lua_pushnumber(luaState, static_cast(static_cast>(value))); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* luaState, int index) { + if (!lua_isnumber(luaState, index)) { + return makeErrorCode(ErrorCode::InvalidTypeCast); + } + return static_cast(static_cast(lua_tonumber(luaState, index))); + } + + [[nodiscard]] static bool isInstance(lua_State* luaState, int index) { return lua_isnumber(luaState, index) != 0; } + }; +} // namespace luabridge +#pragma endregion + +namespace RTE::LuaBinding { + +#pragma region Raw Lua Helpers + /// Pushes the value stored under a light userdata key in the table at the given index. Lua 5.1 has no lua_rawgetp, and LuaBridge's version checks the stack on every call. + /// Keys must be fixed values, like LuaBridge's own keys are, and never the address of something. + /// Light userdata are hashed by their value, so with addresses for keys, when a table has to grow would differ from run to run. That changes how memory gets used, and with it when the garbage collector runs, + /// which changes which strings get collected and made again with new IDs, and so the order pairs() goes through tables with string keys in, which breaks the simulation's determinism. + inline void RawGetP(lua_State* luaState, int tableIndex, const void* key) { + tableIndex = tableIndex < 0 && tableIndex > LUA_REGISTRYINDEX ? lua_gettop(luaState) + tableIndex + 1 : tableIndex; + lua_pushlightuserdata(luaState, const_cast(key)); + lua_rawget(luaState, tableIndex); + } + + /// Sets the value at the top of the stack under a light userdata key in the table at the given index, popping the value. + inline void RawSetP(lua_State* luaState, int tableIndex, const void* key) { + tableIndex = tableIndex < 0 && tableIndex > LUA_REGISTRYINDEX ? lua_gettop(luaState) + tableIndex + 1 : tableIndex; + lua_pushlightuserdata(luaState, const_cast(key)); + lua_insert(luaState, -2); + lua_rawset(luaState, tableIndex); + } + + /// Raises a Lua error with a printf style message. Never returns. + [[noreturn]] void RaiseError(lua_State* luaState, const char* format, ...); +#pragma endregion + +#pragma region Storage + /// Keeps the parts of a Lua state's bindings that never change once they're registered, like the functions that methods call and the property accessors, for as long as the Lua state is open. + /// Lua refers to them with light userdata pointing in here, rather than having full userdata of their own. There are thousands of them in every Lua state, and Lua's garbage collector visits every full userdata on every cycle, + /// which made garbage collection take much longer than it did with luabind. Light userdata aren't garbage collected at all. + class Storage { + public: + /// Stores a value. It's never destroyed, only freed along with the storage, which has to outlive the Lua state that uses it. + /// @return Pointer to the stored value, which never moves. + template + T* Emplace(Args&&... args) { + static_assert(std::is_trivially_destructible_v, "Stored values are never destroyed, so they can't need destructing!"); + static_assert(alignof(T) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__, "Stored values can't need more alignment than new gives!"); + return new (Allocate(sizeof(T), alignof(T))) T(std::forward(args)...); + } + + /// Allocates memory that's freed along with the storage. + /// @param size How many bytes to allocate. + /// @param alignment What the memory has to be aligned to, which can't be more than what new aligns to. + /// @return Pointer to the memory, which never moves. + void* Allocate(std::size_t size, std::size_t alignment); + + private: + static constexpr std::size_t c_BlockSize = 16384; //!< How many bytes each block of memory that values are stored in has, unless a value needs more. + + std::vector> m_Blocks; //!< The blocks of memory values are stored in. + std::size_t m_LastBlockSize = 0; //!< How many bytes the last block has. + std::size_t m_LastBlockUsed = 0; //!< How many bytes of the last block are used. + }; +#pragma endregion + +#pragma region Class Type Info + /// Function that pushes a raw, non-owned pointer to an object of a registered class, given as a void pointer to the exact registered type, into a Lua state. + using PushPointerFunction = void (*)(lua_State* luaState, void* object); + + /// Information about a registered class that's stored in each of its metatables, used for working out overload scores, casting objects to their base classes quickly, and copying objects between Lua states. + /// It's kept in the bindings' Storage, and the metatables have light userdata pointing to it. + /// It starts with LuaBridge's AncestryInfo, which LuaBridge reads to cast objects to their base classes, so it has to stay standard layout. + struct ClassTypeInfo { + luabridge::detail::AncestryInfo Ancestry; //!< The class registry keys of the class and its bases, nearest first, so the index in there is the luabind cast distance, with the pointer offsets to them. Also says whether the objects are const. + const char* Name; //!< The class name, as registered in Lua. + PushPointerFunction PushPointer; //!< Pushes a non-owned pointer to an object of this class into another Lua state, or null if it's not a pointer-pushable type. + + /// Gets whether objects with this metatable are const. + bool IsConst() const { return Ancestry.IsConst; } + }; + static_assert(std::is_standard_layout_v, "LuaBridge reads ClassTypeInfo as the AncestryInfo it starts with!"); + + /// Gets the key ClassTypeInfo are stored under in metatables. + inline const void* GetClassTypeInfoKey() { + return luabridge::detail::getAncestryInfoKey(); + } + + /// Gets the ClassTypeInfo of the userdata at the given stack index, or null if it isn't an object of a registered class. + inline const ClassTypeInfo* GetClassTypeInfo(lua_State* luaState, int index) { + if (lua_type(luaState, index) != LUA_TUSERDATA || !lua_getmetatable(luaState, index)) { + return nullptr; + } + RawGetP(luaState, -1, GetClassTypeInfoKey()); + const ClassTypeInfo* info = static_cast(lua_touserdata(luaState, -1)); + lua_pop(luaState, 2); + return info; + } + + /// Works out how many inheritance steps away the registered class identified by its class registry key is from the class of the object at the given stack index. + /// @return The number of steps, or -1 if the object isn't of that class or a class derived from it. + inline int GetClassDistance(const ClassTypeInfo* info, const void* classKey) { + if (info) { + for (int i = 0; i < info->Ancestry.Count; ++i) { + if (info->Ancestry.ClassKeys[i] == classKey) { + return i; + } + } + } + return -1; + } + + /// Gets how many bytes have to be added to a pointer to an object of class T to get a pointer to its Base, which is only ever not 0 with multiple inheritance. + template + std::ptrdiff_t GetBaseOffset() { + static_assert(std::is_base_of_v, "Base has to be a base class of T!"); + // Any non-null, suitably aligned address works for this, since casting to a non-virtual base only adds a fixed offset without reading anything. + constexpr std::uintptr_t probeAddress = 0x10000; + return static_cast(reinterpret_cast(static_cast(reinterpret_cast(probeAddress))) - probeAddress); + } +#pragma endregion + +#pragma region Owned Objects + /// Userdata for objects that Lua owns, and deletes when they're garbage collected, unless C++ takes the ownership over first. + /// These are what luabind called adopted objects. Unlike LuaBridge's own value userdata, the object lives on the heap, so C++ can take it over and keep using the same object. + class OwnedUserdataBase : public luabridge::detail::Userdata { + public: + /// Gets whether Lua still owns the object. + bool IsOwned() const { return m_Owned; } + + /// Gives up Lua's ownership of the object, so it won't be deleted when this userdata is garbage collected. + void ReleaseOwnership() { m_Owned = false; } + + protected: + bool m_Owned = true; //!< Whether Lua owns the object. + }; + + /// Owned userdata for a specific class. + template + class OwnedUserdata final : public OwnedUserdataBase { + static_assert(!std::is_const_v, "Lua can only own non-const objects."); + + public: + ~OwnedUserdata() override { + if (m_Owned && m_p) { + delete static_cast(m_p); + } + } + + /// Pushes an object onto the Lua stack, giving Lua the ownership of it. Pushes nil if the object is null. + static void Push(lua_State* luaState, T* object) { + if (!object) { + lua_pushnil(luaState); + return; + } + OwnedUserdata* userdata = new (lua_newuserdata(luaState, sizeof(OwnedUserdata))) OwnedUserdata(object); + RawGetP(luaState, LUA_REGISTRYINDEX, luabridge::detail::getClassRegistryKey()); + if (!lua_istable(luaState, -1)) { + lua_pop(luaState, 1); + userdata->m_Owned = false; + userdata->~OwnedUserdata(); + RaiseError(luaState, "Tried to push an object of an unregistered class to Lua!"); + } + lua_setmetatable(luaState, -2); + } + + private: + explicit OwnedUserdata(T* object) { m_p = object; } + }; + + /// Gets the owned userdata at the given stack index, or null if the value there isn't an owned object. + inline OwnedUserdataBase* GetOwnedUserdata(lua_State* luaState, int index) { + if (lua_type(luaState, index) != LUA_TUSERDATA || !GetClassTypeInfo(luaState, index)) { + return nullptr; + } + return dynamic_cast(static_cast(lua_touserdata(luaState, index))); + } + + /// Whether objects of a class constructed from Lua are put on the heap as owned objects, so C++ can take them over later, rather than being stored inside their userdata. + /// Everything that C++ can take ownership of, i.e. Entities and the primitives that PrimitiveMan schedules, has to be. + template + inline constexpr bool c_ConstructOnHeap = std::is_base_of_v || std::is_base_of_v; +#pragma endregion + +#pragma region Policy Types + /// Return type wrapper for pointers whose ownership is handed to Lua (luabind's adopt(result)). + template + struct Owned { + T* Object; + }; + + /// Parameter type wrapper for pointers whose ownership is taken away from Lua (luabind's adopt(_N)). Only objects that Lua owns can be passed. + template + struct Adopted { + T* Object; + }; + + /// Return type for functions that return the object they were called on, i.e. the very same userdata (luabind's return_reference_to(_1)). + struct SelfReference {}; + + /// Return type for an iterator over a container that's owned by C++ (luabind's return_stl_iterator). The iterator function is what's returned to Lua. + template + struct StlIterator { + const Container* TheContainer; + }; + + /// Return type for an iterator over a heap allocated container that the iterator takes ownership of, and deletes once it's garbage collected. + template + struct OwnedStlIterator { + Container* TheContainer; + }; + + /// Policy tags, given after the function or property getter when registering it. They work like the luabind policies of the same names did. + struct AdoptResultPolicy {}; + struct ReturnStlIteratorPolicy {}; + struct ReturnSelfPolicy {}; + template struct AdoptArgPolicy {}; + + inline constexpr AdoptResultPolicy AdoptResult{}; //!< Lua takes ownership of the returned pointer. luabind's adopt(result)/adopt(return_value). + inline constexpr ReturnStlIteratorPolicy ReturnStlIterator{}; //!< The returned container is returned as an iterator function. luabind's return_stl_iterator. + inline constexpr ReturnSelfPolicy ReturnSelf{}; //!< The function returns the object it was called on. luabind's return_reference_to(_1). + /// Lua gives up ownership of the Nth argument. Arguments are counted the way luabind did, so the object a member function is called on is 1 and the first actual argument is 2. luabind's adopt(_N). + template inline constexpr AdoptArgPolicy AdoptArg{}; +#pragma endregion + +#pragma region Iterator Implementation + /// Pushes an element of a container the way luabind's iterators did: pointers as pointers, and everything else as a copy. + template + void PushIteratorElement(lua_State* luaState, const Element& element) { + if (auto result = luabridge::Stack::push(luaState, element); !result) { + RaiseError(luaState, "%s", result.error_cstr()); + } + } + + /// The state of an iterator over a container, stored in a userdata that's the upvalue of the iterator function. + template + struct StlIteratorState { + using Iterator = typename Container::const_iterator; + + Container* OwnedContainer; //!< The container, if the iterator owns it, otherwise null. + Iterator Current; //!< The next element to return. + Iterator End; //!< The end of the container. + + static int Next(lua_State* luaState) { + StlIteratorState* state = static_cast(lua_touserdata(luaState, lua_upvalueindex(1))); + if (state->Current == state->End) { + lua_pushnil(luaState); + } else { + PushIteratorElement(luaState, *state->Current); + ++state->Current; + } + return 1; + } + + static int GarbageCollect(lua_State* luaState) { + static_cast(lua_touserdata(luaState, 1))->~StlIteratorState(); + return 0; + } + + ~StlIteratorState() { delete OwnedContainer; } + + /// Pushes an iterator function over the container. + static void Push(lua_State* luaState, const Container* container, Container* ownedContainer) { + if (!container) { + lua_pushnil(luaState); + return; + } + new (lua_newuserdata(luaState, sizeof(StlIteratorState))) StlIteratorState{ownedContainer, container->begin(), container->end()}; + + // A fixed value for each kind of container, rather than an address, see RawGetP. + const void* metatableKey = reinterpret_cast(luabridge::detail::typeHash()); + RawGetP(luaState, LUA_REGISTRYINDEX, metatableKey); + if (lua_isnil(luaState, -1)) { + lua_pop(luaState, 1); + lua_createtable(luaState, 0, 1); + lua_pushcfunction(luaState, &StlIteratorState::GarbageCollect); + lua_setfield(luaState, -2, "__gc"); + lua_pushvalue(luaState, -1); + RawSetP(luaState, LUA_REGISTRYINDEX, metatableKey); + } + lua_setmetatable(luaState, -2); + lua_pushcclosure(luaState, &StlIteratorState::Next, 1); + } + }; +#pragma endregion + +} // namespace RTE::LuaBinding + +#pragma region Policy Type Stack Specializations +namespace luabridge { + template + struct Stack> { + [[nodiscard]] static Result push(lua_State* luaState, const RTE::LuaBinding::Owned& value) { + RTE::LuaBinding::OwnedUserdata::Push(luaState, value.Object); + return {}; + } + }; + + template + struct Stack> { + [[nodiscard]] static TypeResult> get(lua_State* luaState, int index) { + RTE::LuaBinding::OwnedUserdataBase* owned = RTE::LuaBinding::GetOwnedUserdata(luaState, index); + if (!owned || !owned->IsOwned()) { + RTE::LuaBinding::RaiseError(luaState, "Argument %d has to be an object that Lua owns, since its ownership is being handed over!", index); + } + auto object = detail::Userdata::get(luaState, index, false); + if (!object) { + return object.error(); + } + owned->ReleaseOwnership(); + return RTE::LuaBinding::Adopted{*object}; + } + + [[nodiscard]] static bool isInstance(lua_State* luaState, int index) { return detail::Userdata::isInstance(luaState, index); } + }; + + template <> + struct Stack { + [[nodiscard]] static Result push(lua_State* luaState, const RTE::LuaBinding::SelfReference&) { + lua_pushvalue(luaState, 1); + return {}; + } + }; + + template + struct Stack> { + [[nodiscard]] static Result push(lua_State* luaState, const RTE::LuaBinding::StlIterator& value) { + RTE::LuaBinding::StlIteratorState::Push(luaState, value.TheContainer, nullptr); + return {}; + } + }; + + template + struct Stack> { + [[nodiscard]] static Result push(lua_State* luaState, const RTE::LuaBinding::OwnedStlIterator& value) { + RTE::LuaBinding::StlIteratorState::Push(luaState, value.TheContainer, value.TheContainer); + return {}; + } + }; +} // namespace luabridge +#pragma endregion + +namespace RTE::LuaBinding { + +#pragma region Function Signatures + /// Breaks a function or member function pointer type down into its parts. + template + struct FunctionSignature; + + template + struct FunctionSignature { + using Return = R; + using Class = C; + using Args = std::tuple; + static constexpr bool c_IsMember = true; + static constexpr bool c_IsConst = false; + }; + template + struct FunctionSignature : FunctionSignature { + static constexpr bool c_IsConst = true; + }; + template + struct FunctionSignature : FunctionSignature {}; + template + struct FunctionSignature : FunctionSignature {}; + + template + struct FunctionSignature { + using Return = R; + using Class = void; + using Args = std::tuple; + static constexpr bool c_IsMember = false; + static constexpr bool c_IsConst = false; + }; + template + struct FunctionSignature : FunctionSignature {}; + + /// Gets the parameter types of a callable as LuaBridge sees them, i.e. including the object for proxy functions and lambdas, and as T* or const T* for member functions of class T. + template + struct LuaParameters { + using Type = typename luabridge::detail::function_traits::argument_types; + }; + template + struct LuaParameters>> { + using Signature = FunctionSignature; + using Type = decltype(std::tuple_cat(std::declval>>(), std::declval())); + }; +#pragma endregion + +#pragma region Overload Matching + /// Score luabind gave to luabind::object parameters, which accept anything but are the least preferred. + inline constexpr int c_AnyValueMatchScore = 100000; + + /// Scores how well the Lua value at the given stack index matches a C++ parameter type, the way luabind did it, so that overloads get picked the same way. + /// @return The score, lower being a better match, or -1 if the value can't be passed as that type. + template + struct ArgumentMatcher { + using Decayed = std::remove_cv_t>; + + static int Match(lua_State* luaState, int index) { + if constexpr (std::is_same_v) { + return lua_type(luaState, index) == LUA_TBOOLEAN ? 0 : -1; + } else if constexpr (std::is_enum_v) { + return lua_isnumber(luaState, index) ? 0 : -1; + } else if constexpr (std::is_arithmetic_v) { + return lua_type(luaState, index) == LUA_TNUMBER ? 0 : -1; + } else if constexpr (std::is_same_v || std::is_same_v) { + return lua_type(luaState, index) == LUA_TSTRING ? 0 : -1; + } else if constexpr (std::is_same_v || std::is_same_v) { + return (lua_type(luaState, index) == LUA_TSTRING || lua_isnil(luaState, index)) ? 0 : -1; + } else if constexpr (std::is_same_v) { + return c_AnyValueMatchScore; + } else if constexpr (std::is_pointer_v) { + using Pointee = std::remove_pointer_t; + if (lua_isnil(luaState, index)) { + return 0; + } + const ClassTypeInfo* info = GetClassTypeInfo(luaState, index); + int distance = GetClassDistance(info, luabridge::detail::getClassRegistryKey>()); + if (distance < 0) { + return -1; + } + if constexpr (std::is_const_v) { + return distance + (info->IsConst() ? 0 : 1); + } else { + return info->IsConst() ? -1 : distance; + } + } else if constexpr (std::is_class_v) { + // Registered class passed by value or reference. + if (lua_isnil(luaState, index)) { + return -1; + } + const ClassTypeInfo* info = GetClassTypeInfo(luaState, index); + int distance = GetClassDistance(info, luabridge::detail::getClassRegistryKey()); + if (distance < 0) { + return -1; + } + if constexpr (std::is_lvalue_reference_v

&& !std::is_const_v>) { + return info->IsConst() ? -1 : distance; + } else if constexpr (std::is_lvalue_reference_v

) { + return distance + (info->IsConst() ? 0 : 1); + } else { + return distance; + } + } else { + static_assert(sizeof(P) == 0, "Unsupported parameter type for overload matching!"); + return -1; + } + } + }; + + template + struct ArgumentMatcher> { + static int Match(lua_State* luaState, int index) { + OwnedUserdataBase* owned = GetOwnedUserdata(luaState, index); + if (!owned || !owned->IsOwned()) { + return -1; + } + const ClassTypeInfo* info = GetClassTypeInfo(luaState, index); + return info->IsConst() ? -1 : GetClassDistance(info, luabridge::detail::getClassRegistryKey()); + } + }; + + /// Function that scores how well the arguments on the stack, starting at the given index, match an overload. Returns -1 if they don't. + using MatchFunction = int (*)(lua_State* luaState, int firstArgumentIndex); + + template + struct TupleMatcher; + + template + struct TupleMatcher> { + static constexpr int c_Arity = static_cast(sizeof...(P)); + + static int Match(lua_State* luaState, int firstArgumentIndex) { + return MatchImpl(luaState, firstArgumentIndex, std::index_sequence_for{}); + } + + private: + template + static int MatchImpl(lua_State* luaState, int firstArgumentIndex, std::index_sequence) { + int total = 0; + bool matched = true; + ((matched = matched && Accumulate(ArgumentMatcher

::Match(luaState, firstArgumentIndex + static_cast(I)), total)), ...); + return matched ? total : -1; + } + + static bool Accumulate(int score, int& total) { + if (score < 0) { + return false; + } + total += score; + return true; + } + }; + /// Scores the arguments of a method, where the first parameter is the object it's called on, which can't be nil. + template + struct MethodMatcher { + static int Match(lua_State* luaState, int firstArgumentIndex) { + return lua_isnil(luaState, firstArgumentIndex) ? -1 : TupleMatcher::Match(luaState, firstArgumentIndex); + } + }; +#pragma endregion + +#pragma region Policy Application + template + inline constexpr bool c_HasPolicy = (std::is_same_v || ...); + + template + inline constexpr bool c_AdoptsArgument = (std::is_same_v, Policies> || ...); + + /// Gets whether a parameter is a non-const reference to something that isn't an object of a registered class, like std::string&. + /// LuaBridge can't pass those, so they're taken by value in a wrapper and passed on as a reference to that. + template + inline constexpr bool c_IsNonConstReferenceToValue = std::is_lvalue_reference_v

&& !std::is_const_v> && !luabridge::detail::IsUserdata>::value; + + /// The type a parameter is declared as in a policy wrapper, given its luabind argument index. + template + struct WrappedParameter { + using Type = std::conditional_t, std::remove_reference_t

, P>; + }; + template + struct WrappedParameter { + using Type = std::conditional_t, Adopted, T*>; + }; + + /// Passes a wrapper's argument on to the wrapped function, which takes it as the parameter type P. + template + decltype(auto) UnwrapArgument(A& argument) { + if constexpr (std::is_lvalue_reference_v

) { + return static_cast

(argument); + } else { + return static_cast&&>(argument); + } + } + template + T* UnwrapArgument(Adopted& argument) { + return argument.Object; + } + + /// Gets whether a function has to be wrapped for LuaBridge to be able to call it, because it returns a const value, or takes a non-const reference to something that isn't an object. + template + struct NeedsWrappingImpl; + template + struct NeedsWrappingImpl> { + static constexpr bool c_Value = (std::is_const_v && !std::is_reference_v) || (c_IsNonConstReferenceToValue || ...); + }; + template + inline constexpr bool c_NeedsWrapping = NeedsWrappingImpl::Return, typename FunctionSignature::Args>::c_Value; + + /// Gets whether a parameter type is a pointer or reference to const. + template + inline constexpr bool c_IsConstIndirection = std::is_const_v>>; + + /// Converts the object a wrapped method is called on to the type the wrapped free function takes it as, which may be a base class, a pointer or a reference. + template + decltype(auto) AdaptSelf(Self self) { + if constexpr (std::is_pointer_v

) { + return static_cast

(self); + } else { + static_assert(std::is_reference_v

, "Free functions registered as methods have to take the object as a pointer or reference!"); + return static_cast

(*self); + } + } + + /// Works out the return type of a policy wrapper, and converts the wrapped function's return value to it. + template + struct WrappedReturn { + static constexpr bool c_ReturnsSelf = c_HasPolicy; + static constexpr bool c_Adopts = c_HasPolicy; + static constexpr bool c_Iterates = c_HasPolicy; + + using Bare = std::remove_cv_t>; + using Container = std::remove_cv_t>; + + /// The function's return type, minus any top level const on a value, which LuaBridge can't push. + using Plain = std::conditional_t, R, std::remove_const_t>; + + using Type = std::conditional_t && !std::is_reference_v), OwnedStlIterator, StlIterator>, + std::conditional_t>, Plain>>>; + + template + static Type Invoke(Call&& call) { + if constexpr (c_ReturnsSelf) { + call(); + return SelfReference{}; + } else if constexpr (c_Iterates) { + if constexpr (c_Adopts) { + static_assert(std::is_pointer_v, "An adopted iterator container has to be returned as a pointer!"); + return Type{const_cast(call())}; + } else if constexpr (std::is_pointer_v) { + return Type{call()}; + } else if constexpr (std::is_reference_v) { + return Type{&call()}; + } else { + // Returned by value, so the iterator has to keep its own copy, rather than iterating over a destroyed temporary like luabind did. + return Type{new Container(call())}; + } + } else if constexpr (c_Adopts) { + static_assert(std::is_pointer_v, "Only pointers can be adopted!"); + return Type{call()}; + } else { + return call(); + } + } + }; + + /// Makes sure the object a wrapped method is called on isn't nil, which LuaBridge passes on as a null pointer. + /// Throwing makes LuaBridge raise it as a Lua error, like luabind's failed overload match was. + inline void CheckSelf(const void* self) { + if (!self) { + throw std::invalid_argument("Tried to call a method on nil instead of an object, use : rather than . to call methods!"); + } + } + + template + auto WrapMemberFunction(F function, std::index_sequence) { + using Signature = FunctionSignature; + using Args = typename Signature::Args; + using Return = WrappedReturn; + using Self = std::conditional_t; + + return [function](Self self, typename WrappedParameter, static_cast(I) + 2, Policies...>::Type... arguments) -> typename Return::Type { + CheckSelf(self); + return Return::Invoke([&]() -> decltype(auto) { return std::invoke(function, self, UnwrapArgument>(arguments)...); }); + }; + } + + template + auto WrapFreeFunctionAsMember(F function, std::index_sequence) { + using Signature = FunctionSignature; + using Args = typename Signature::Args; + using Return = WrappedReturn; + using SelfParameter = std::tuple_element_t<0, Args>; + using Self = std::conditional_t, const T*, T*>; + + return [function](Self self, typename WrappedParameter, static_cast(I) + 2, Policies...>::Type... arguments) -> typename Return::Type { + CheckSelf(self); + return Return::Invoke([&]() -> decltype(auto) { return std::invoke(function, AdaptSelf(self), UnwrapArgument>(arguments)...); }); + }; + } + + template + auto WrapFreeFunction(F function, std::index_sequence) { + using Signature = FunctionSignature; + using Args = typename Signature::Args; + using Return = WrappedReturn; + + return [function](typename WrappedParameter, static_cast(I) + 1, Policies...>::Type... arguments) -> typename Return::Type { + return Return::Invoke([&]() -> decltype(auto) { return std::invoke(function, UnwrapArgument>(arguments)...); }); + }; + } + + /// Makes a method of class T out of a member function or a free function that takes the object as its first parameter, applying the given policies. + /// Member functions without policies are returned as they are, since LuaBridge can call them directly, and everything else is wrapped in a lambda that takes the object as T* or const T*. + template + auto MakeMethod(F function, Policies...) { + using Signature = FunctionSignature; + constexpr std::size_t argumentCount = std::tuple_size_v; + if constexpr (Signature::c_IsMember) { + if constexpr (sizeof...(Policies) == 0 && !AlwaysWrap && !c_NeedsWrapping) { + return function; + } else { + return WrapMemberFunction(function, std::make_index_sequence{}); + } + } else { + static_assert(argumentCount > 0, "Free functions registered as methods have to take the object as their first parameter!"); + return WrapFreeFunctionAsMember(function, std::make_index_sequence{}); + } + } + + /// Makes a global function out of a free function, applying the given policies. + template + auto MakeFunction(F function, Policies...) { + if constexpr (sizeof...(Policies) == 0 && !c_NeedsWrapping) { + return function; + } else { + return WrapFreeFunction(function, std::make_index_sequence::Args>>{}); + } + } +#pragma endregion + +#pragma region Property Accessors + /// A property getter or setter, kept in the bindings' Storage, with light userdata pointing to it in a class's property tables, which the class's __index and __newindex call directly. + /// Calling them this way, rather than through Lua closures like LuaBridge's own properties, saves a Lua call and a type check on every property access, which scripts do more of than anything else. + struct PropertyAccessor { + /// Pushes the property's value for getters, or sets the property to the value at stack index 3 for setters. + /// @param object Pointer to the object, already adjusted to point to the class the property is registered on. + /// @param callable The getter or setter function, member pointer or lambda. + /// @return How many values were pushed. + using Function = int (*)(lua_State* luaState, void* object, const void* callable); + + Function Call; //!< Calls the getter or setter. + const void* Callable; //!< The getter or setter that Call calls, also kept in the bindings' Storage. + std::ptrdiff_t Offset; //!< What to add to a pointer to an object of the class whose property tables this is in, to get a pointer to the class the property is registered on. + }; + + /// Calls a property getter of class T and pushes what it returns. + template + int CallPropertyGetter(lua_State* luaState, void* object, const void* callable) { + const Getter& getter = *static_cast(callable); + luabridge::Result result; + try { + // luabind let properties be read from const objects whatever the getter took the object as. + if constexpr (std::is_invocable_v) { + using Value = decltype(std::invoke(getter, static_cast(object))); + result = luabridge::Stack::push(luaState, std::invoke(getter, static_cast(object))); + } else { + using Value = decltype(std::invoke(getter, static_cast(object))); + result = luabridge::Stack::push(luaState, std::invoke(getter, static_cast(object))); + } + } catch (const std::exception& exception) { + RaiseError(luaState, "%s", exception.what()); + } + if (!result) { + RaiseError(luaState, "%s", result.error_cstr()); + } + return 1; + } + + /// Calls a property setter of class T with the value at stack index 3. Setters take the object as const, see ClassBuilder::MakeSetter. + template + int CallPropertySetter(lua_State* luaState, void* object, const void* callable) { + const Setter& setter = *static_cast(callable); + using Value = std::tuple_element_t<1, typename luabridge::detail::function_traits::argument_types>; + try { + luabridge::detail::invoke_callable_from_stack, 3>(luaState, [&setter, object](Value value) { std::invoke(setter, static_cast(object), std::forward(value)); }); + } catch (const std::exception& exception) { + RaiseError(luaState, "%s", exception.what()); + } + return 0; + } + + /// A property registered on a class, recorded during registration and put into the property tables of the class and its derived classes once every class is registered. + struct PropertyRecord { + std::string Name; //!< The property name. + PropertyAccessor Getter; //!< The getter. + PropertyAccessor Setter; //!< The setter, or one with a null Call if the property is read only. + }; +#pragma endregion + +#pragma region Registration + /// An overload of a function, method, operator or constructor, recorded during registration and resolved once every class is registered. + struct OverloadRecord { + std::string Name; //!< The name it's registered under. + int ClosureReference; //!< Lua registry reference to the function closure that calls it. + int Arity; //!< How many arguments it takes, including the object for methods. + MatchFunction Matcher; //!< Scores how well arguments match it. + const std::type_info* Signature; //!< The type of the tuple of its parameters excluding the object, used to find methods hidden by identical ones in derived classes. + bool ConstCallable; //!< Whether it can be called on const objects. + }; + + /// Everything recorded about a registered class. + struct ClassRecord { + std::string Name; //!< The class name. + const void* ClassKey; //!< LuaBridge registry key of the class metatable. + const void* ConstKey; //!< LuaBridge registry key of the const metatable. + const void* StaticKey; //!< LuaBridge registry key of the static (class) table. + int ParentIndex; //!< Index of the base class's record, or -1 if there isn't one. + std::ptrdiff_t ParentOffset; //!< What has to be added to a pointer to an object of the class to get a pointer to its base class part. + PushPointerFunction PushPointer; //!< Pushes a non-owned pointer to an object of the class. + std::vector Methods; //!< The methods and operator metamethods registered on this class itself. + std::vector Constructors; //!< The constructors of this class. + std::vector> Constants; //!< The enum values registered on this class itself. + std::vector Properties; //!< The properties registered on this class itself. + }; + + /// Pushes a closure that calls a functor, which is kept in the storage. + template + void PushFunctor(lua_State* luaState, Storage& storage, F functor) { + lua_pushlightuserdata(luaState, storage.Emplace(std::move(functor))); + lua_pushcclosure(luaState, &luabridge::detail::invoke_proxy_functor, 1); + } + + /// Pushes a closure that calls a method of class T, which is either a member function pointer or a functor that takes the object as its first parameter. + /// It's the closure LuaBridge's push_member_function makes, except that the member function pointer or functor is kept in the storage rather than in a full userdata of its own. + template + void PushMethod(lua_State* luaState, Storage& storage, F method) { + if constexpr (std::is_member_function_pointer_v) { + lua_pushlightuserdata(luaState, storage.Emplace(method)); + // The class's metatables, which LuaBridge compares the object's metatable with first, to skip casting objects that are exactly a T. + RawGetP(luaState, LUA_REGISTRYINDEX, luabridge::detail::getClassRegistryKey()); + if constexpr (FunctionSignature::c_IsConst) { + RawGetP(luaState, LUA_REGISTRYINDEX, luabridge::detail::getConstRegistryKey()); + lua_pushcclosure(luaState, &luabridge::detail::invoke_const_member_function, 3); + } else { + lua_pushcclosure(luaState, &luabridge::detail::invoke_member_function, 2); + } + } else { + PushFunctor(luaState, storage, std::move(method)); + } + } + + /// Pushes a closure that calls a global function, which is either a function pointer or a functor. + template + void PushFunction(lua_State* luaState, Storage& storage, F function) { + if constexpr (std::is_pointer_v) { + // LuaBridge already keeps function pointers in light userdata. + luabridge::detail::push_function(luaState, function, ""); + } else { + PushFunctor(luaState, storage, std::move(function)); + } + } + + template + class ClassBuilder; + + /// Collects everything registered into a Lua state, and sets up the luabind compatible lookups for it once it's all registered. + class Registry { + template + friend class ClassBuilder; + + public: + /// Constructor method used to instantiate a Registry object for a Lua state. + /// @param luaState The Lua state to register into. + /// @param storage Where to keep what the bindings call, which has to outlive the Lua state. + Registry(lua_State* luaState, Storage& storage) : + m_LuaState(luaState), m_Storage(storage) {} + + /// Gets the Lua state being registered into. + lua_State* GetLuaState() const { return m_LuaState; } + + /// Starts registering a class. + /// @tparam Base The registered base class of the class, if it has one. + template + ClassBuilder Class(const char* name); + + /// Registers a global function. Registering more under the same name adds overloads to it. + template + Registry& Function(const char* name, F function, Policies... policies) { + auto wrapped = MakeFunction(function, policies...); + using Parameters = typename luabridge::detail::function_traits::argument_types; + PushFunction(m_LuaState, m_Storage, std::move(wrapped)); + m_Functions.push_back({name, luaL_ref(m_LuaState, LUA_REGISTRYINDEX), TupleMatcher::c_Arity, &TupleMatcher::Match, &typeid(Parameters), true}); + return *this; + } + + /// Sets up the metatables of every registered class, and the global functions, so they behave the way they did with luabind. Has to be called once everything is registered. + void Finalize(); + + /// Stores a copy of a property getter or setter for as long as the Lua state is open. + /// @return Pointer to the stored copy, which never moves. + template + const void* StoreCallable(Callable callable) { + return m_Storage.Emplace(std::move(callable)); + } + + private: + lua_State* m_LuaState; //!< The Lua state being registered into. + Storage& m_Storage; //!< Where what the bindings call is kept. + std::vector m_Classes; //!< Every registered class, bases before their derived classes. + std::unordered_map m_ClassIndices; //!< Index of each class's record, by class registry key. + std::vector m_Functions; //!< The global functions. + }; + + /// Gets a function that pushes a non-owned pointer to an object of class T. + template + PushPointerFunction GetPushPointerFunction() { + return [](lua_State* luaState, void* object) { + if (auto result = luabridge::Stack::push(luaState, static_cast(object)); !result) { + lua_pushnil(luaState); + } + }; + } + + /// Registers the members of a class, mirroring luabind's class_. Methods registered more than once under the same name become overloads, including across base and derived classes. + template + class ClassBuilder { + public: + ClassBuilder(Registry& registry, const char* name) : + m_Registry(®istry), m_Class(Begin(registry.GetLuaState(), name)), m_RecordIndex(static_cast(registry.m_Classes.size())) { + ClassRecord record; + record.Name = name; + record.ClassKey = luabridge::detail::getClassRegistryKey(); + record.ConstKey = luabridge::detail::getConstRegistryKey(); + record.StaticKey = luabridge::detail::getStaticRegistryKey(); + record.ParentIndex = -1; + record.ParentOffset = 0; + if constexpr (!std::is_void_v) { + record.ParentOffset = GetBaseOffset(); + auto parent = registry.m_ClassIndices.find(luabridge::detail::getClassRegistryKey()); + if (parent == registry.m_ClassIndices.end()) { + RaiseError(registry.GetLuaState(), "Class %s was registered before its base class!", name); + } + record.ParentIndex = parent->second; + } + record.PushPointer = GetPushPointerFunction(); + registry.m_ClassIndices.emplace(record.ClassKey, m_RecordIndex); + registry.m_Classes.push_back(std::move(record)); + } + + ClassBuilder(ClassBuilder&&) = default; + + /// Registers a method, or an overload of one. Free functions are registered as methods by taking the object as their first parameter, like they were with luabind. + template + ClassBuilder&& addFunction(const char* name, F function, Policies... policies) && { + AddMethod(name, MakeMethod(function, policies...)); + return std::move(*this); + } + + /// Registers a read only property. Policies can be given for the getter. + template + ClassBuilder&& addProperty(const char* name, Getter getter, Policies... policies) && { + if constexpr (sizeof...(Policies) > 0 && !(IsPolicy() && ...)) { + AddReadWriteProperty(name, getter, policies...); + } else if constexpr (std::is_member_object_pointer_v) { + AddDataMember(name, getter, policies...); + } else { + AddAccessors(name, MakeGetter(getter, policies...)); + } + return std::move(*this); + } + + /// Registers a data member that can be read and written to, luabind's def_readwrite. + /// Members that are objects of registered classes are returned as references to them, so they can be changed in place, like `box.Corner.X = 5`. + template + ClassBuilder&& addReadWriteMember(const char* name, M T::*member) && { + if constexpr (luabridge::detail::IsUserdata>::value) { + AddAccessors(name, [member](const T* self) -> M& { return const_cast(self)->*member; }, MakeMemberSetter(member)); + } else { + AddAccessors(name, [member](const T* self) -> M { return self->*member; }, MakeMemberSetter(member)); + } + return std::move(*this); + } + + /// Registers a constructor, or an overload of one. + template + ClassBuilder&& addConstructor() && { + lua_State* luaState = m_Registry->GetLuaState(); + lua_pushcfunction(luaState, &Construct); + using Parameters = std::tuple; + Record().Constructors.push_back({"__init", luaL_ref(luaState, LUA_REGISTRYINDEX), TupleMatcher::c_Arity, &TupleMatcher::Match, &typeid(Parameters), true}); + return std::move(*this); + } + + /// Registers enum values as constants on the class, the way luabind's enum_ did. They're stored as integers, like luabind did it. + ClassBuilder&& addEnum(std::initializer_list> values) && { + for (const auto& [valueName, value]: values) { + Record().Constants.emplace_back(valueName, value); + } + return std::move(*this); + } + + /// Registers the == operator against another type, luabind's self == other(). + template + ClassBuilder&& addEqualityOperator() && { + AddMethod("__eq", [](const T* self, Other other) { return *self == other; }); + return std::move(*this); + } + + /// Registers tostring support using the class's << operator, luabind's tostring(const_self). + ClassBuilder&& addToString() && { + AddMethod("__tostring", [](const T* self) { + std::stringstream stream; + stream << *self; + return stream.str(); + }); + return std::move(*this); + } + + private: + Registry* m_Registry; //!< The registry this class is registered in. + using LuaBridgeClass = decltype(std::declval().template beginClass("")); //!< LuaBridge's class registration type, which is private, but can be named this way. + + LuaBridgeClass m_Class; //!< The LuaBridge class registration. Ends the registration when it's destroyed. + int m_RecordIndex; //!< Index of this class's record in the registry. + + static LuaBridgeClass Begin(lua_State* luaState, const char* name) { + if constexpr (std::is_void_v) { + return luabridge::getGlobalNamespace(luaState).beginClass(name, luabridge::extensibleClass); + } else { + return luabridge::getGlobalNamespace(luaState).deriveClass(name, luabridge::extensibleClass); + } + } + + ClassRecord& Record() { return m_Registry->m_Classes[m_RecordIndex]; } + + template + static constexpr bool IsPolicy() { + return std::is_same_v || std::is_same_v || std::is_same_v; + } + + /// Makes a property getter. Const member functions are used as they are, everything else is wrapped. + template + static auto MakeGetter(Getter getter, Policies... policies) { + if constexpr (sizeof...(Policies) == 0 && std::is_member_function_pointer_v && FunctionSignature::c_IsConst && !c_NeedsWrapping) { + return getter; + } else { + return MakeMethod(getter, policies...); + } + } + + /// Records a property with the given getter, and setter if there is one, which ends up in the property tables of the class and its derived classes when the registry is finalized. + template + void AddAccessors(const char* name, Getter getter) { + PropertyRecord record{name, {&CallPropertyGetter, m_Registry->StoreCallable(std::move(getter)), 0}, {nullptr, nullptr, 0}}; + Record().Properties.push_back(std::move(record)); + } + template + void AddAccessors(const char* name, Getter getter, Setter setter) { + PropertyRecord record{name, {&CallPropertyGetter, m_Registry->StoreCallable(std::move(getter)), 0}, {&CallPropertySetter, m_Registry->StoreCallable(std::move(setter)), 0}}; + Record().Properties.push_back(std::move(record)); + } + + /// Makes a property setter. + /// luabind let properties be set on const objects too, and scripts rely on that to change things like `actor.Pos.X` in place, so setters take the object as const and cast that away. + template + static auto MakeSetter(Setter setter) { + using Signature = FunctionSignature; + using Args = typename Signature::Args; + if constexpr (Signature::c_IsMember) { + using Value = std::tuple_element_t<0, Args>; + return [setter](const T* self, typename WrappedParameter::Type value) { + std::invoke(setter, const_cast(self), UnwrapArgument(value)); + }; + } else { + using SelfParameter = std::tuple_element_t<0, Args>; + using Value = std::tuple_element_t<1, Args>; + return [setter](const T* self, typename WrappedParameter::Type value) { + std::invoke(setter, AdaptSelf(const_cast(self)), UnwrapArgument(value)); + }; + } + } + + /// Makes a setter for a data member that can be set on const objects too, see MakeSetter. + template + static auto MakeMemberSetter(M T::*member) { + using Value = std::conditional_t || std::is_enum_v || std::is_pointer_v, M, const M&>; + return [member](const T* self, Value value) { const_cast(self)->*member = value; }; + } + + template + void AddReadWriteProperty(const char* name, Getter getter, Setter setter, Policies... policies) { + static_assert((IsPolicy() && ...), "Only getters can take policies!"); + AddAccessors(name, MakeGetter(getter, policies...), MakeSetter(setter)); + } + + template + void AddDataMember(const char* name, M T::*member, Policies...) { + if constexpr (sizeof...(Policies) > 0) { + static_assert((std::is_same_v && ...), "Data members can only take the iterator policy!"); + AddAccessors(name, [member](const T* self) { return StlIterator>{&(self->*member)}; }); + } else if constexpr (luabridge::detail::IsUserdata>::value) { + // Read only data members of registered classes are returned as const references, the way luabind did it. + AddAccessors(name, [member](const T* self) -> const M& { return self->*member; }); + } else { + AddAccessors(name, [member](const T* self) -> M { return self->*member; }); + } + } + + template + void AddMethod(const char* name, F function) { + lua_State* luaState = m_Registry->GetLuaState(); + using Parameters = typename LuaParameters::Type; + using Self = std::tuple_element_t<0, Parameters>; + using SelfPointee = std::remove_reference_t>; + PushMethod(luaState, m_Registry->m_Storage, std::move(function)); + Record().Methods.push_back({name, luaL_ref(luaState, LUA_REGISTRYINDEX), TupleMatcher::c_Arity, &MethodMatcher::Match, &typeid(TailOf), std::is_const_v}); + } + + template + struct Tail; + template + struct Tail> { + using Type = std::tuple; + }; + template + using TailOf = typename Tail::Type; + + /// Constructs an object from the arguments after the class table, which is the first argument of __call. + template + static int Construct(lua_State* luaState) { + if constexpr (c_ConstructOnHeap) { + T* object = luabridge::detail::invoke_callable_from_stack, 2>(luaState, [](Args... arguments) { return new T(arguments...); }); + OwnedUserdata::Push(luaState, object); + } else { + std::error_code error; + auto* userdata = luabridge::detail::UserdataValue::place(luaState, error); + if (!userdata) { + RaiseError(luaState, "%s", error.message().c_str()); + } + luabridge::detail::invoke_callable_from_stack, 2>(luaState, [userdata](Args... arguments) { new (userdata->getObject()) T(arguments...); }); + userdata->commit(); + } + return 1; + } + }; + + template + ClassBuilder Registry::Class(const char* name) { + return ClassBuilder(*this, name); + } +#pragma endregion + +} // namespace RTE::LuaBinding + +namespace RTE { + /// Can't have global enums in the master state so we use this dummy struct as a class and register the enums under it. + struct enum_wrapper {}; + + /// Derived structs for each of the input enums because we can't register enum_wrapper multiple times under a different name. + /// We're doing this so we can access each enum separately by name rather than having all of them accessed from a shared name. + /// If this proves to be a hassle then we can easily revert to the shared name access by registering everything under enum_wrapper. + struct input_device : public enum_wrapper {}; + struct input_elements : public enum_wrapper {}; + struct mouse_buttons : public enum_wrapper {}; + struct joy_buttons : public enum_wrapper {}; + struct joy_directions : public enum_wrapper {}; + struct key_codes : public enum_wrapper {}; + struct scan_codes : public enum_wrapper {}; + struct gamepad_buttons : public enum_wrapper {}; + struct gamepad_axis : public enum_wrapper {}; + struct directions : public enum_wrapper {}; + struct blend_modes : public enum_wrapper {}; + struct draw_depths : public enum_wrapper {}; + + /// Special callback function for adding file name and line number to error messages when calling functions incorrectly. + /// @param luaState The Lua master state. + /// @return An error signal, 1, so Lua correctly reports that there's been an error. + static int AddFileAndLineToError(lua_State* luaState) { + lua_Debug luaDebug; + if (lua_getstack(luaState, 2, &luaDebug) > 0) { + lua_getinfo(luaState, "Sln", &luaDebug); + std::string errorString = lua_tostring(luaState, -1); + + if (errorString.find(".lua") != std::string::npos) { + lua_pushstring(luaState, errorString.c_str()); + } else { + std::stringstream messageStream; + messageStream << ((luaDebug.name == nullptr || strstr(luaDebug.name, ".rte") == nullptr) ? luaDebug.short_src : luaDebug.name); + messageStream << ":" << luaDebug.currentline << ": " << errorString; + lua_pushstring(luaState, messageStream.str().c_str()); + } + } + return 1; + } + + /// Converts a Lua table to a C++ vector of the specified type. Ownership of the objects in the Lua table is transferred! + /// @param luaTable The Lua table object to convert to vector. + /// @return A C++ vector containing all the objects from the Lua table. Ownership is transferred! + /// @remark In case of type mismatch (by specifying wrong type or a mix of types in the Lua table) a Lua error is raised, like luabind's object_cast did. + template + static std::vector ConvertLuaTableToVectorOfType(const luabridge::LuaRef& luaTable) { + std::vector outVector = {}; + if (!luaTable.isValid() || !luaTable.isTable()) { + return outVector; + } + lua_State* luaState = luaTable.state(); + luaTable.push(luaState); + const int tableIndex = lua_gettop(luaState); + lua_pushnil(luaState); + while (lua_next(luaState, tableIndex) != 0) { + if constexpr (std::is_pointer_v) { + using Pointee = std::remove_pointer_t; + auto object = luabridge::detail::Userdata::get(luaState, -1, true); + if (!object || !*object) { + LuaBinding::RaiseError(luaState, "Wrong type of object in table, expected %s!", typeid(Pointee).name()); + } + if constexpr (LuaBinding::c_ConstructOnHeap) { + // The object is handed over to C++, so Lua mustn't delete it anymore. + LuaBinding::OwnedUserdataBase* owned = LuaBinding::GetOwnedUserdata(luaState, -1); + if (!owned || !owned->IsOwned()) { + LuaBinding::RaiseError(luaState, "Objects in the table have to be owned by Lua, since their ownership is being handed over!"); + } + owned->ReleaseOwnership(); + outVector.emplace_back(*object); + } else { + // Values are stored inside their userdata, so hand over a copy that C++ owns instead. + outVector.emplace_back(new Pointee(**object)); + } + } else { + auto value = luabridge::Stack::get(luaState, -1); + if (!value) { + LuaBinding::RaiseError(luaState, "Wrong type of value in table: %s", value.error_cstr()); + } + outVector.emplace_back(*value); + } + lua_pop(luaState, 1); + } + lua_pop(luaState, 1); + return outVector; + } +} // namespace RTE diff --git a/Source/Lua/LuaBridgeRegistry.cpp b/Source/Lua/LuaBridgeRegistry.cpp new file mode 100644 index 0000000000..f13fd04cd9 --- /dev/null +++ b/Source/Lua/LuaBridgeRegistry.cpp @@ -0,0 +1,579 @@ +// Sets up the metatables of the classes registered with LuaBridge so that they behave the way they did with luabind. +// +// LuaBridge's own lookups are replaced, because Cortex Command's scripts rely on a few luabind behaviours that LuaBridge does differently: +// - Every object can have values of its own set on it from Lua, like `self.Timer = Timer()`, that are separate for each object (or rather, each userdata), the way luabind's object tables were. +// LuaBridge's extensible classes store such values on the class instead, which would share them between every object of the class. +// - Methods registered more than once under the same name are overloads, including across base and derived classes, and calls pick the best matching overload the way luabind did. +// - When a base and derived class both have a property of the same name, the base class's getter and setter win, like they did with luabind. +// - Enum values are constants on the class table, and are inherited by derived classes. +// - Lookups go to the object's own values first, then methods, then properties, and each is a single table lookup since everything is flattened into the class. +// +// Properties don't use LuaBridge's property support at all. Their getters and setters are PropertyAccessors, which __index and __newindex call directly with the object's pointer already +// adjusted for the class the property is on, so a property access costs no more than a table lookup and the call itself. Objects of registered classes also carry the list of classes +// they can be used as (ClassTypeInfo, which starts with LuaBridge's AncestryInfo), so passing them to a function that takes one of their base classes is quick too. + +#include "LuaBridgeDefinitions.h" + +#include +#include +#include +#include +#include +#include + +using namespace RTE; +using namespace RTE::LuaBinding; + +namespace { + // Light userdata keys are fixed values like LuaBridge's own, rather than the addresses of something, see RawGetP. + const void* const c_InstanceTableMarkerKey = reinterpret_cast(0x1257ab); //!< Registry key of the metatable that marks a userdata environment as the object's own value table. + const void* const c_ClassNameKey = reinterpret_cast(0xc1a55a); //!< Key the class name string is stored under in metatables, so the name in ClassTypeInfo stays valid. + + /// One entry in an overload dispatcher. + struct DispatchEntry { + int Arity; //!< How many arguments the overload takes. + MatchFunction Matcher; //!< Scores how well arguments match the overload. + }; + + /// The overloads a dispatcher picks between. The closures that call them are in a table upvalue, in the same order. + struct DispatchInfo { + int Count; //!< How many overloads there are. + int FirstArgumentIndex; //!< Stack index of the first argument that's matched, which is 2 for constructors called through the class table. + DispatchEntry Entries[1]; //!< The overloads, actually Count long. + }; + + /// Calls the overload that best matches the arguments, like luabind did: the arity has to match exactly, the overload with the lowest total score wins, and a tie between the best is an error. + /// Upvalues: 1 light userdata pointing to the DispatchInfo, 2 the table of overload closures, 3 the name for error messages. + int DispatchOverload(lua_State* luaState) { + const DispatchInfo* info = static_cast(lua_touserdata(luaState, lua_upvalueindex(1))); + const int top = lua_gettop(luaState); + const int argumentCount = top - info->FirstArgumentIndex + 1; + + int bestOverload = -1; + int bestScore = INT_MAX; + bool ambiguous = false; + for (int i = 0; i < info->Count; ++i) { + const DispatchEntry& entry = info->Entries[i]; + if (entry.Arity != argumentCount) { + continue; + } + int score = entry.Matcher(luaState, info->FirstArgumentIndex); + if (score < 0) { + continue; + } + if (score < bestScore) { + bestScore = score; + bestOverload = i; + ambiguous = false; + } else if (score == bestScore) { + ambiguous = true; + } + } + if (bestOverload < 0) { + RaiseError(luaState, "No matching overload of %s found for the given %d argument(s)!", lua_tostring(luaState, lua_upvalueindex(3)), argumentCount); + } + if (ambiguous) { + RaiseError(luaState, "Ambiguous call to %s, more than one overload matches the given arguments equally well!", lua_tostring(luaState, lua_upvalueindex(3))); + } + lua_rawgeti(luaState, lua_upvalueindex(2), bestOverload + 1); + lua_insert(luaState, 1); + lua_call(luaState, top, LUA_MULTRET); + return lua_gettop(luaState); + } + + /// Converts a numeric key to a string in place, like luabind's lookups did with lua_tostring. + /// @return Whether the key is (now) a string that can be looked up. + inline bool NormalizeKey(lua_State* luaState) { + switch (lua_type(luaState, 2)) { + case LUA_TSTRING: + return true; + case LUA_TNUMBER: + lua_tostring(luaState, 2); + return true; + default: + return false; + } + } + + /// Pushes the object's own value table if it has one, and returns whether it does. Pushes nothing if it doesn't. + /// The table is the userdata's environment, which is marked as the object's own by its metatable. Upvalue 3 is that marker. + inline bool PushInstanceTable(lua_State* luaState) { + lua_getfenv(luaState, 1); + // Objects that were never given values of their own still have the globals they were made with as their environment, which is the common case, so check for that first. + if (lua_rawequal(luaState, -1, LUA_GLOBALSINDEX)) { + lua_pop(luaState, 1); + return false; + } + if (lua_getmetatable(luaState, -1)) { + bool isInstanceTable = lua_rawequal(luaState, -1, lua_upvalueindex(3)); + lua_pop(luaState, 1); + if (isInstanceTable) { + return true; + } + } + lua_pop(luaState, 1); + return false; + } + + /// Gets the pointer to the object at stack index 1 with the given offset added, raising an error if it's not an object. + inline void* GetObjectPointer(lua_State* luaState, std::ptrdiff_t offset) { + void* object = lua_type(luaState, 1) == LUA_TUSERDATA ? static_cast(lua_touserdata(luaState, 1))->getPointer() : nullptr; + if (!object) { + RaiseError(luaState, "Tried to access a property of something that isn't an object!"); + } + return static_cast(object) + offset; + } + + /// __index of objects. Looks in the object's own values, then the class's methods, then its property getters, like luabind did. + /// Upvalues: 1 methods table, 2 property getters table (of light userdata pointing to PropertyAccessors), 3 instance table marker, 4 the string "__ok". + int InstanceIndex(lua_State* luaState) { + if (!NormalizeKey(luaState)) { + lua_pushnil(luaState); + return 1; + } + if (lua_rawequal(luaState, 2, lua_upvalueindex(4))) { + // luabind's special member for checking whether the object's pointer is valid. + lua_pushboolean(luaState, static_cast(lua_touserdata(luaState, 1))->getPointer() != nullptr); + return 1; + } + if (PushInstanceTable(luaState)) { + lua_pushvalue(luaState, 2); + lua_rawget(luaState, -2); + if (!lua_isnil(luaState, -1)) { + return 1; + } + lua_pop(luaState, 2); + } + lua_pushvalue(luaState, 2); + lua_rawget(luaState, lua_upvalueindex(1)); + if (!lua_isnil(luaState, -1)) { + return 1; + } + lua_pop(luaState, 1); + lua_pushvalue(luaState, 2); + lua_rawget(luaState, lua_upvalueindex(2)); + if (!lua_isnil(luaState, -1)) { + const PropertyAccessor* getter = static_cast(lua_touserdata(luaState, -1)); + return getter->Call(luaState, GetObjectPointer(luaState, getter->Offset), getter->Callable); + } + return 1; + } + + /// __newindex of objects. Calls the property setter if there is one, raises an error for read only properties, and otherwise stores the value in the object's own value table. + /// Upvalues: 1 property setters table, 2 property getters table (both of light userdata pointing to PropertyAccessors), 3 instance table marker, 4 class name. + int InstanceNewIndex(lua_State* luaState) { + if (!NormalizeKey(luaState)) { + RaiseError(luaState, "Can't set a value with a %s key on a %s!", luaL_typename(luaState, 2), lua_tostring(luaState, lua_upvalueindex(4))); + } + lua_pushvalue(luaState, 2); + lua_rawget(luaState, lua_upvalueindex(1)); + if (!lua_isnil(luaState, -1)) { + const PropertyAccessor* setter = static_cast(lua_touserdata(luaState, -1)); + setter->Call(luaState, GetObjectPointer(luaState, setter->Offset), setter->Callable); + return 0; + } + lua_pop(luaState, 1); + lua_pushvalue(luaState, 2); + lua_rawget(luaState, lua_upvalueindex(2)); + if (!lua_isnil(luaState, -1)) { + RaiseError(luaState, "the attribute '%s.%s' is read only", lua_tostring(luaState, lua_upvalueindex(4)), lua_tostring(luaState, 2)); + } + lua_pop(luaState, 1); + if (!PushInstanceTable(luaState)) { + lua_createtable(luaState, 0, 4); + lua_pushvalue(luaState, lua_upvalueindex(3)); + lua_setmetatable(luaState, -2); + lua_pushvalue(luaState, -1); + lua_setfenv(luaState, 1); + } + lua_pushvalue(luaState, 2); + lua_pushvalue(luaState, 3); + lua_rawset(luaState, -3); + return 0; + } + + /// __index of class tables, for getting methods through the class, like Vector.Normalize. Constants are stored in the class table itself, so they never get here. + /// Upvalues: 1 methods table. + int StaticIndex(lua_State* luaState) { + lua_pushvalue(luaState, 2); + lua_rawget(luaState, lua_upvalueindex(1)); + return 1; + } + + /// __newindex of class tables. Lets classes be extended from Lua: the value is stored in the class table, and functions also become methods of the class's objects, and of the objects of derived classes that don't have a method of that name already. + /// Upvalues: 1 array of methods tables, with the class's own (non-const and const) ones first, followed by those of every derived class. + int StaticNewIndex(lua_State* luaState) { + lua_pushvalue(luaState, 2); + lua_pushvalue(luaState, 3); + lua_rawset(luaState, 1); + + if (lua_isfunction(luaState, 3)) { + const int tableCount = static_cast(lua_objlen(luaState, lua_upvalueindex(1))); + for (int i = 1; i <= tableCount; ++i) { + lua_rawgeti(luaState, lua_upvalueindex(1), i); + bool isOwnTable = i <= 2; + bool shouldSet = isOwnTable; + if (!isOwnTable) { + lua_pushvalue(luaState, 2); + lua_rawget(luaState, -2); + shouldSet = lua_isnil(luaState, -1); + lua_pop(luaState, 1); + } + if (shouldSet) { + lua_pushvalue(luaState, 2); + lua_pushvalue(luaState, 3); + lua_rawset(luaState, -3); + } + lua_pop(luaState, 1); + } + } + return 0; + } + + /// An overload being considered for a class's flattened method table, with how far up the class hierarchy it was registered. + struct Candidate { + const OverloadRecord* Record; + int Depth; + }; + + /// Removes overloads that are hidden by an overload with exactly the same parameters registered on a class nearer to the object's class. Those could never be picked, since the object would always be a closer match for the nearer one. + std::vector RemoveHiddenOverloads(const std::vector& candidates) { + std::vector result; + for (const Candidate& candidate: candidates) { + bool hidden = false; + for (const Candidate& other: candidates) { + if (other.Depth < candidate.Depth && *other.Record->Signature == *candidate.Record->Signature && other.Record->ConstCallable == candidate.Record->ConstCallable && other.Record->Arity == candidate.Record->Arity) { + hidden = true; + break; + } + } + if (!hidden) { + result.push_back(candidate.Record); + } + } + return result; + } + + /// The dispatchers made so far, so that classes with the same set of overloads for a method, like every class that inherits it unchanged, share one dispatcher. + struct DispatcherCache { + int TableIndex; //!< Stack index of the Lua array the dispatchers are in. + std::map, int>, int> Slots; //!< Where in the array the dispatcher for each set of overloads and first argument index is. + }; + + /// Pushes the function that calls a set of overloads: the overload's own closure if there's only one, otherwise a dispatcher that picks between them. + /// A dispatcher is named after the first class it was made for in error messages, which is the class the overloads come from when the others inherited them. + void PushOverloadSet(lua_State* luaState, Storage& storage, DispatcherCache& cache, const std::vector& overloads, const std::string& name, int firstArgumentIndex) { + if (overloads.size() == 1 && firstArgumentIndex == 1) { + lua_rawgeti(luaState, LUA_REGISTRYINDEX, overloads.front()->ClosureReference); + return; + } + auto [slot, isNew] = cache.Slots.try_emplace({overloads, firstArgumentIndex}, static_cast(cache.Slots.size()) + 1); + if (!isNew) { + lua_rawgeti(luaState, cache.TableIndex, slot->second); + return; + } + const int count = static_cast(overloads.size()); + DispatchInfo* info = new (storage.Allocate(sizeof(DispatchInfo) + sizeof(DispatchEntry) * (count - 1), alignof(DispatchInfo))) DispatchInfo; + info->Count = count; + info->FirstArgumentIndex = firstArgumentIndex; + lua_pushlightuserdata(luaState, info); + lua_createtable(luaState, count, 0); + for (int i = 0; i < count; ++i) { + info->Entries[i] = {overloads[i]->Arity, overloads[i]->Matcher}; + lua_rawgeti(luaState, LUA_REGISTRYINDEX, overloads[i]->ClosureReference); + lua_rawseti(luaState, -2, i + 1); + } + lua_pushstring(luaState, name.c_str()); + lua_pushcclosure(luaState, &DispatchOverload, 3); + lua_pushvalue(luaState, -1); + lua_rawseti(luaState, cache.TableIndex, slot->second); + } + + /// Sets the value at the top of the stack as a field of the table at the given index without invoking metamethods, popping the value. + /// This is needed for LuaBridge's metatables, which are their own metatables, so lua_setfield on them would call their __newindex. + void RawSetField(lua_State* luaState, int tableIndex, const char* name) { + tableIndex = tableIndex < 0 ? lua_gettop(luaState) + tableIndex + 1 : tableIndex; + lua_pushstring(luaState, name); + lua_insert(luaState, -2); + lua_rawset(luaState, tableIndex); + } + + /// The stored copies of the property accessors that don't need a pointer offset, by the accessor in the registry's records they're copies of. Classes that inherit a property share these. + using SharedAccessors = std::unordered_map; + + /// Pushes a light userdata pointing to a stored property accessor, for a class whose objects need the given offset added to point to the class the property is registered on. + /// Accessors without an offset are shared between all the classes that inherit them. + void PushPropertyAccessor(lua_State* luaState, Storage& storage, SharedAccessors& sharedAccessors, const PropertyAccessor& accessor, std::ptrdiff_t offset) { + const PropertyAccessor* stored; + if (offset == 0) { + const PropertyAccessor*& shared = sharedAccessors[&accessor]; + if (!shared) { + shared = storage.Emplace(accessor); + } + stored = shared; + } else { + PropertyAccessor* copy = storage.Emplace(accessor); + copy->Offset = offset; + stored = copy; + } + lua_pushlightuserdata(luaState, const_cast(stored)); + } +} // namespace + +namespace RTE::LuaBinding { + void* Storage::Allocate(std::size_t size, std::size_t alignment) { + std::size_t offset = (m_LastBlockUsed + alignment - 1) / alignment * alignment; + if (m_Blocks.empty() || offset + size > m_LastBlockSize) { + m_LastBlockSize = std::max(size, c_BlockSize); + m_Blocks.push_back(std::make_unique(m_LastBlockSize)); + offset = 0; + } + m_LastBlockUsed = offset + size; + return m_Blocks.back().get() + offset; + } + + void RaiseError(lua_State* luaState, const char* format, ...) { + char message[1024]; + va_list arguments; + va_start(arguments, format); + std::vsnprintf(message, sizeof(message), format, arguments); + va_end(arguments); + lua_pushstring(luaState, message); + lua_error(luaState); + std::abort(); // lua_error never returns. + } + + void Registry::Finalize() { + lua_State* luaState = m_LuaState; + const int stackTop = lua_gettop(luaState); + // Stack checks are off for LuaBridge, so make sure there's room for everything below, which isn't called from inside a Lua C function that would guarantee some. + if (!lua_checkstack(luaState, 64)) { + RaiseError(luaState, "Not enough Lua stack space to finish registering the bindings!"); + } + + lua_newtable(luaState); + const int instanceTableMarkerIndex = lua_gettop(luaState); + lua_pushvalue(luaState, instanceTableMarkerIndex); + RawSetP(luaState, LUA_REGISTRYINDEX, c_InstanceTableMarkerKey); + lua_pushstring(luaState, "__ok"); + const int okKeyIndex = lua_gettop(luaState); + + const int classCount = static_cast(m_Classes.size()); + + // The flattened methods tables of every class, non-const then const, so class tables can be extended from Lua. + lua_createtable(luaState, classCount * 2, 0); + const int allMethodsTablesIndex = lua_gettop(luaState); + + lua_newtable(luaState); + DispatcherCache dispatchers{lua_gettop(luaState), {}}; + SharedAccessors sharedAccessors; + std::vector> descendants(classCount); + + for (int classIndex = 0; classIndex < classCount; ++classIndex) { + const ClassRecord& record = m_Classes[classIndex]; + + std::vector chain; + for (int i = classIndex; i >= 0; i = m_Classes[i].ParentIndex) { + chain.push_back(i); + if (i != classIndex) { + descendants[i].push_back(classIndex); + } + } + if (static_cast(chain.size()) > luabridge::detail::AncestryInfo::MaxAncestors) { + RaiseError(luaState, "Class %s has a deeper hierarchy than is supported!", record.Name.c_str()); + } + + RawGetP(luaState, LUA_REGISTRYINDEX, record.ClassKey); + const int classMetatableIndex = lua_gettop(luaState); + RawGetP(luaState, LUA_REGISTRYINDEX, record.ConstKey); + const int constMetatableIndex = lua_gettop(luaState); + // LuaBridge's static registry key is for the metatable of the class table, rather than the class table that's visible from Lua, which only the global namespace refers to. + RawGetP(luaState, LUA_REGISTRYINDEX, record.StaticKey); + const int staticMetatableIndex = lua_gettop(luaState); + lua_getglobal(luaState, record.Name.c_str()); + const int staticTableIndex = lua_gettop(luaState); + if (!lua_istable(luaState, staticTableIndex) || !lua_getmetatable(luaState, staticTableIndex)) { + RaiseError(luaState, "Class %s isn't registered as a global!", record.Name.c_str()); + } + if (!lua_rawequal(luaState, -1, staticMetatableIndex)) { + RaiseError(luaState, "Global %s isn't the class table of the class registered under that name!", record.Name.c_str()); + } + lua_pop(luaState, 1); + + // Type info, for overload matching and copying objects between Lua states. + for (int metatableIndex: {classMetatableIndex, constMetatableIndex}) { + lua_pushstring(luaState, record.Name.c_str()); + const char* persistentName = lua_tostring(luaState, -1); + RawSetP(luaState, metatableIndex, c_ClassNameKey); + + ClassTypeInfo* info = m_Storage.Emplace(); + info->Ancestry.Count = static_cast(chain.size()); + std::ptrdiff_t offset = 0; + for (int i = 0; i < info->Ancestry.Count; ++i) { + info->Ancestry.ClassKeys[i] = m_Classes[chain[i]].ClassKey; + info->Ancestry.Offsets[i] = offset; + offset += m_Classes[chain[i]].ParentOffset; + } + info->Ancestry.IsConst = metatableIndex == constMetatableIndex; + info->Name = persistentName; + info->PushPointer = record.PushPointer; + lua_pushlightuserdata(luaState, info); + RawSetP(luaState, metatableIndex, GetClassTypeInfoKey()); + } + + // Methods and operators, with overloads merged across the whole hierarchy like luabind did. + std::map> methodCandidates; + std::map> constMethodCandidates; + for (int depth = 0; depth < static_cast(chain.size()); ++depth) { + for (const OverloadRecord& method: m_Classes[chain[depth]].Methods) { + methodCandidates[method.Name].push_back({&method, depth}); + if (method.ConstCallable) { + constMethodCandidates[method.Name].push_back({&method, depth}); + } + } + } + + lua_newtable(luaState); + const int methodsIndex = lua_gettop(luaState); + lua_newtable(luaState); + const int constMethodsIndex = lua_gettop(luaState); + + for (const auto& [name, candidates]: methodCandidates) { + PushOverloadSet(luaState, m_Storage, dispatchers, RemoveHiddenOverloads(candidates), record.Name + "." + name, 1); + if (name.rfind("__", 0) == 0) { + // Operators have to be in the metatables themselves, and the same function in both, or Lua won't compare const and non-const objects with each other. + lua_pushvalue(luaState, -1); + RawSetField(luaState, classMetatableIndex, name.c_str()); + RawSetField(luaState, constMetatableIndex, name.c_str()); + } else { + lua_setfield(luaState, methodsIndex, name.c_str()); + } + } + for (const auto& [name, candidates]: constMethodCandidates) { + if (name.rfind("__", 0) != 0) { + PushOverloadSet(luaState, m_Storage, dispatchers, RemoveHiddenOverloads(candidates), record.Name + "." + name, 1); + lua_setfield(luaState, constMethodsIndex, name.c_str()); + } + } + lua_pushvalue(luaState, methodsIndex); + lua_rawseti(luaState, allMethodsTablesIndex, classIndex * 2 + 1); + lua_pushvalue(luaState, constMethodsIndex); + lua_rawseti(luaState, allMethodsTablesIndex, classIndex * 2 + 2); + + // Property getters and setters, where the base class wins when there are ones of the same name, like luabind did. + lua_newtable(luaState); + const int gettersIndex = lua_gettop(luaState); + lua_newtable(luaState); + const int settersIndex = lua_gettop(luaState); + std::ptrdiff_t ancestorOffset = 0; + for (int chainIndex: chain) { + for (const PropertyRecord& property: m_Classes[chainIndex].Properties) { + PushPropertyAccessor(luaState, m_Storage, sharedAccessors, property.Getter, ancestorOffset); + RawSetField(luaState, gettersIndex, property.Name.c_str()); + if (property.Setter.Call) { + PushPropertyAccessor(luaState, m_Storage, sharedAccessors, property.Setter, ancestorOffset); + RawSetField(luaState, settersIndex, property.Name.c_str()); + } + } + ancestorOffset += m_Classes[chainIndex].ParentOffset; + } + + // The lookups for objects. + for (bool isConst: {false, true}) { + const int metatableIndex = isConst ? constMetatableIndex : classMetatableIndex; + + lua_pushvalue(luaState, isConst ? constMethodsIndex : methodsIndex); + lua_pushvalue(luaState, gettersIndex); + lua_pushvalue(luaState, instanceTableMarkerIndex); + lua_pushvalue(luaState, okKeyIndex); + lua_pushcclosure(luaState, &InstanceIndex, 4); + RawSetField(luaState, metatableIndex, "__index"); + + lua_pushvalue(luaState, settersIndex); + lua_pushvalue(luaState, gettersIndex); + lua_pushvalue(luaState, instanceTableMarkerIndex); + lua_pushstring(luaState, record.Name.c_str()); + lua_pushcclosure(luaState, &InstanceNewIndex, 4); + RawSetField(luaState, metatableIndex, "__newindex"); + } + + // Enum constants, stored in the class table itself, where the base class wins when there are ones of the same name, like luabind did. + std::map constants; + for (int chainIndex: chain) { + for (const auto& [name, value]: m_Classes[chainIndex].Constants) { + constants[name] = value; + } + } + for (const auto& [name, value]: constants) { + lua_pushstring(luaState, name.c_str()); + lua_pushnumber(luaState, static_cast(value)); + lua_rawset(luaState, staticTableIndex); + } + + // The class table's lookups, and its constructors. + lua_pushvalue(luaState, methodsIndex); + lua_pushcclosure(luaState, &StaticIndex, 1); + RawSetField(luaState, staticMetatableIndex, "__index"); + if (!record.Constructors.empty()) { + std::vector constructors; + for (const OverloadRecord& constructor: record.Constructors) { + constructors.push_back(&constructor); + } + PushOverloadSet(luaState, m_Storage, dispatchers, constructors, record.Name, 2); + RawSetField(luaState, staticMetatableIndex, "__call"); + } + + lua_settop(luaState, dispatchers.TableIndex); + } + + // Class tables can only be extended once all the derived classes' method tables exist. + for (int classIndex = 0; classIndex < classCount; ++classIndex) { + RawGetP(luaState, LUA_REGISTRYINDEX, m_Classes[classIndex].StaticKey); + lua_createtable(luaState, 2 + static_cast(descendants[classIndex].size()) * 2, 0); + int tableCount = 0; + for (int tableClassIndex: {classIndex}) { + lua_rawgeti(luaState, allMethodsTablesIndex, tableClassIndex * 2 + 1); + lua_rawseti(luaState, -2, ++tableCount); + lua_rawgeti(luaState, allMethodsTablesIndex, tableClassIndex * 2 + 2); + lua_rawseti(luaState, -2, ++tableCount); + } + for (int descendantIndex: descendants[classIndex]) { + lua_rawgeti(luaState, allMethodsTablesIndex, descendantIndex * 2 + 1); + lua_rawseti(luaState, -2, ++tableCount); + lua_rawgeti(luaState, allMethodsTablesIndex, descendantIndex * 2 + 2); + lua_rawseti(luaState, -2, ++tableCount); + } + lua_pushcclosure(luaState, &StaticNewIndex, 1); + RawSetField(luaState, -2, "__newindex"); + lua_pop(luaState, 1); + } + + // Global functions. + std::map> functions; + for (const OverloadRecord& function: m_Functions) { + functions[function.Name].push_back(&function); + } + for (const auto& [name, overloads]: functions) { + PushOverloadSet(luaState, m_Storage, dispatchers, overloads, name, 1); + lua_setglobal(luaState, name.c_str()); + } + + lua_settop(luaState, stackTop); + + // Everything that needs the overload closures holds onto them by now, so the registry doesn't need to anymore. + for (ClassRecord& record: m_Classes) { + for (OverloadRecord& method: record.Methods) { + luaL_unref(luaState, LUA_REGISTRYINDEX, method.ClosureReference); + } + for (OverloadRecord& constructor: record.Constructors) { + luaL_unref(luaState, LUA_REGISTRYINDEX, constructor.ClosureReference); + } + } + for (OverloadRecord& function: m_Functions) { + luaL_unref(luaState, LUA_REGISTRYINDEX, function.ClosureReference); + } + m_Classes.clear(); + m_ClassIndices.clear(); + m_Functions.clear(); + } +} // namespace RTE::LuaBinding diff --git a/Source/Lua/LuaObjectWrapper.cpp b/Source/Lua/LuaObjectWrapper.cpp new file mode 100644 index 0000000000..170e057033 --- /dev/null +++ b/Source/Lua/LuaObjectWrapper.cpp @@ -0,0 +1,94 @@ +#include "LuaObjectWrapper.h" + +#include "LuaBridgeDefinitions.h" + +#include + +using namespace RTE; + +// With multithreaded Lua, objects can be destructed from multiple threads at once. +// Releasing a Lua reference pokes at the Lua state it belongs to, and the object being deleted by one thread might belong to a Lua state that another thread is running. +// As such, we don't actually delete the object until we're in a safe environment outside the multithreaded parts. +// Note - this is required even though we force objects in multithreaded environments to be within our Lua state. +// This is because we may assign an object to another state in a singlethreaded context, before the GC runs in the multithreaded context. +static std::vector s_QueuedDeletions; +static std::mutex s_QueuedDeletionsMutex; + +void LuaObjectWrapper::ApplyQueuedDeletions() { + std::vector queuedDeletions; + { + std::lock_guard guard(s_QueuedDeletionsMutex); + queuedDeletions.swap(s_QueuedDeletions); + } + for (luabridge::LuaRef* luaObject: queuedDeletions) { + delete luaObject; + } +} + +LuaObjectWrapper::~LuaObjectWrapper() { + if (m_OwnsObject) { + std::lock_guard guard(s_QueuedDeletionsMutex); + s_QueuedDeletions.push_back(m_LuaObject); + } +} + +/// Pushes a copy of the value at the given index of one Lua state onto another Lua state. +/// Numbers, booleans and strings are copied, tables are copied deeply, objects of registered classes are pushed as pointers to the same object, and anything else becomes nil. +static void PushCopyForState(lua_State* sourceState, int sourceIndex, lua_State* targetState) { + sourceIndex = sourceIndex < 0 ? lua_gettop(sourceState) + sourceIndex + 1 : sourceIndex; + switch (lua_type(sourceState, sourceIndex)) { + case LUA_TNUMBER: + lua_pushnumber(targetState, lua_tonumber(sourceState, sourceIndex)); + return; + case LUA_TBOOLEAN: + lua_pushboolean(targetState, lua_toboolean(sourceState, sourceIndex)); + return; + case LUA_TSTRING: { + size_t length = 0; + const char* string = lua_tolstring(sourceState, sourceIndex, &length); + lua_pushlstring(targetState, string, length); + return; + } + case LUA_TTABLE: { + lua_newtable(targetState); + const int targetTableIndex = lua_gettop(targetState); + lua_pushnil(sourceState); + while (lua_next(sourceState, sourceIndex) != 0) { + PushCopyForState(sourceState, -2, targetState); + PushCopyForState(sourceState, -1, targetState); + lua_settable(targetState, targetTableIndex); + lua_pop(sourceState, 1); + } + return; + } + case LUA_TUSERDATA: { + // Like luabind's copy did, objects become non-owned pointers to the same object, and const objects can't be copied. + const LuaBinding::ClassTypeInfo* info = LuaBinding::GetClassTypeInfo(sourceState, sourceIndex); + if (info && !info->IsConst() && info->PushPointer) { + void* object = static_cast(lua_touserdata(sourceState, sourceIndex))->getPointer(); + if (object) { + info->PushPointer(targetState, object); + return; + } + } + break; + } + default: + break; + } + lua_pushnil(targetState); +} + +LuaObjectWrapper LuaObjectWrapper::GetCopyForState(lua_State& targetState) const { + luabridge::LuaRef* copy = nullptr; + if (m_LuaObject && m_LuaObject->isValid()) { + lua_State* sourceState = m_LuaObject->state(); + m_LuaObject->push(sourceState); + PushCopyForState(sourceState, -1, &targetState); + lua_pop(sourceState, 1); + copy = new luabridge::LuaRef(luabridge::LuaRef::fromStack(&targetState)); + } else { + copy = new luabridge::LuaRef(&targetState); + } + return LuaObjectWrapper(copy, m_FilePath, true); +} diff --git a/Source/Lua/LuaObjectWrapper.h b/Source/Lua/LuaObjectWrapper.h new file mode 100644 index 0000000000..a9dd29186e --- /dev/null +++ b/Source/Lua/LuaObjectWrapper.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include + +struct lua_State; + +namespace luabridge { + class LuaRef; +} + +namespace RTE { + +#pragma region Global Macro Definitions +#define ScriptFunctionNames(...) \ + virtual std::vector GetSupportedScriptFunctionNames() const { return {__VA_ARGS__}; } + +#define AddScriptFunctionNames(PARENT, ...) \ + std::vector GetSupportedScriptFunctionNames() const override { \ + std::vector functionNames = PARENT::GetSupportedScriptFunctionNames(); \ + functionNames.insert(functionNames.end(), {__VA_ARGS__}); \ + return functionNames; \ + } +#pragma endregion + + /// A wrapper for references to Lua objects, so that LuaBridge doesn't have to be included everywhere they're stored. + class LuaObjectWrapper { + + public: +#pragma region Creation + /// Constructor method used for LuaObjectWrapper. + LuaObjectWrapper() = default; + + /// Constructor method used to instantiate a LuaObjectWrapper object in system memory. + explicit LuaObjectWrapper(luabridge::LuaRef* luaObject, const std::string_view& filePath, bool ownsObject = true) : + m_OwnsObject(ownsObject), m_LuaObject(luaObject), m_FilePath(filePath) {} +#pragma endregion + +#pragma region Destruction + /// Deletes the Lua object references whose deletion was put off until it was safe, see the destructor. + static void ApplyQueuedDeletions(); + + /// Destructor method used to clean up a LuaObjectWrapper object before deletion from system memory. + ~LuaObjectWrapper(); +#pragma endregion + + /// Attempts to copy a Lua object into another state. + LuaObjectWrapper GetCopyForState(lua_State& newState) const; + +#pragma region Getters + /// Gets the LuaObjectWrapper's Lua object reference. Ownership is NOT transferred! + /// @return The LuaObjectWrapper's Lua object reference. + luabridge::LuaRef* GetLuaObject() const { return m_LuaObject; } + + /// Gets the LuaObjectWrapper's file path. + /// @return The LuaObjectWrapper's file path. + const std::string& GetFilePath() const { return m_FilePath; } +#pragma endregion + + private: + bool m_OwnsObject = false; //!< Whether or not we own the Lua object reference this is wrapping. + luabridge::LuaRef* m_LuaObject = nullptr; //!< The Lua object reference this is wrapping. + std::string m_FilePath; //!< The filepath the wrapped Lua object represents, if it's a function. + + // Disallow the use of some implicit methods. + LuaObjectWrapper(const LuaObjectWrapper& reference) = delete; + LuaObjectWrapper& operator=(const LuaObjectWrapper& rhs) = delete; + }; +} // namespace RTE diff --git a/Source/Lua/LuabindDefinitions.h b/Source/Lua/LuabindDefinitions.h deleted file mode 100644 index eb3ef34c10..0000000000 --- a/Source/Lua/LuabindDefinitions.h +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once - -#define BOOST_BIND_GLOBAL_PLACEHOLDERS 1 - -// Todo - figure out luabind error callbacks and blah-de-blah -// #define LUABIND_NO_EXCEPTIONS - -#include "lua.hpp" -#include "luabind.hpp" -#include "luabind/object.hpp" -#include "luabind/operator.hpp" -#include "luabind/copy_policy.hpp" -#include "luabind/adopt_policy.hpp" -#include "luabind/out_value_policy.hpp" -#include "luabind/iterator_policy.hpp" -#include "luabind/return_reference_to_policy.hpp" - -namespace luabind { - /// Function that extracts the raw pointer from the smart pointer. This is needed when Lua calls member functions on held types, the 'this' pointer must be a raw pointer, it is also needed to allow the smart_pointer to raw_pointer conversion from Lua to C++. - /// @param ptr The smart pointer to get raw pointer for. - /// @return Raw pointer of the passed in smart pointer. - template Type* get_pointer(boost::shared_ptr& ptr) { - return ptr.get(); - } - - /// Can't have global enums in the master state so we use this dummy struct as a class and register the enums under it. - struct enum_wrapper {}; -} // namespace luabind - -namespace RTE { - /// Derived structs for each of the input enums because we can't register enum_wrapper multiple times under a different name. - /// We're doing this so we can access each enum separately by name rather than having all of them accessed from a shared name. - /// If this proves to be a hassle then we can easily revert to the shared name access by registering everything under enum_wrapper. - struct input_device : public luabind::enum_wrapper {}; - struct input_elements : public luabind::enum_wrapper {}; - struct mouse_buttons : public luabind::enum_wrapper {}; - struct joy_buttons : public luabind::enum_wrapper {}; - struct joy_directions : public luabind::enum_wrapper {}; - struct key_codes : public luabind::enum_wrapper {}; - struct scan_codes : public luabind::enum_wrapper {}; - struct gamepad_buttons : public luabind::enum_wrapper {}; - struct gamepad_axis : public luabind::enum_wrapper {}; - struct directions : public luabind::enum_wrapper {}; - struct blend_modes : public luabind::enum_wrapper {}; - struct draw_depths : public luabind::enum_wrapper {}; - - /// Special callback function for adding file name and line number to error messages when calling functions incorrectly. - /// @param luaState The Lua master state. - /// @return An error signal, 1, so Lua correctly reports that there's been an error. - static int AddFileAndLineToError(lua_State* luaState) { - lua_Debug luaDebug; - if (lua_getstack(luaState, 2, &luaDebug) > 0) { - lua_getinfo(luaState, "Sln", &luaDebug); - std::string errorString = lua_tostring(luaState, -1); - - if (errorString.find(".lua") != std::string::npos) { - lua_pushstring(luaState, errorString.c_str()); - } else { - std::stringstream messageStream; - messageStream << ((luaDebug.name == nullptr || strstr(luaDebug.name, ".rte") == nullptr) ? luaDebug.short_src : luaDebug.name); - messageStream << ":" << luaDebug.currentline << ": " << errorString; - lua_pushstring(luaState, messageStream.str().c_str()); - } - } - return 1; - } - - /// Converts a Lua table to a C++ vector of the specified type. Ownership of the objects in the Lua table is transferred! - /// @param luaTable The Lua table object to convert to vector. - /// @return A C++ vector containing all the objects from the Lua table. Ownership is transferred! - /// @remark In case of type mismatch (by specifying wrong type or a mix of types in the Lua table) object_cast will print an error to the console and throw, so no need to check what it returns before emplacing. - template static std::vector ConvertLuaTableToVectorOfType(const luabind::object& luaObject) { - std::vector outVector = {}; - if (luaObject.is_valid() && luabind::type(luaObject) == LUA_TTABLE) { - for (luabind::iterator tableItr(luaObject), tableEnd; tableItr != tableEnd; ++tableItr) { - if constexpr (std::is_pointer_v) { - outVector.emplace_back(luabind::object_cast(*tableItr, luabind::adopt(luabind::result))); - } else { - outVector.emplace_back(luabind::object_cast(*tableItr)); - } - } - } - return outVector; - } -} // namespace RTE diff --git a/Source/Lua/LuabindObjectWrapper.cpp b/Source/Lua/LuabindObjectWrapper.cpp deleted file mode 100644 index fc8174b03b..0000000000 --- a/Source/Lua/LuabindObjectWrapper.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Make sure that this wrapper file is always set to NOT use pre-compiled headers and conformance mode (/permissive) otherwise everything will be on fire cause luabind is a nightmare! - -#include "LuabindObjectWrapper.h" -#include "luabind/object.hpp" - -#include "LuaBindingRegisterDefinitions.h" - -#include "SoundSet.h" - -using namespace RTE; - -// With multithreaded Lua, objects can be destructed from multiple threads at once -// This is okay, but LuaBind wants to do some management on the lua state when one of it's objects is deleted -// This means that potentially an object being deleted by one lua state actually exists in another lua state -// And upon deletion, it's unsafe for LuaBind to poke at the state until we're out the multithreaded context -// As such, we don't actually delete the object until we're in a safe environment outside the multithreaded parts -// Note - this is required even though we force objects in multithreaded environments to be within our Lua state -// This is because we may assign an object to another state in a singlethreaded context, before the GC runs in the multithreaded context -static std::vector s_QueuedDeletions; - -void LuabindObjectWrapper::ApplyQueuedDeletions() { - for (luabind::adl::object* obj: s_QueuedDeletions) { - delete obj; - } - - s_QueuedDeletions.clear(); -} - -LuabindObjectWrapper::~LuabindObjectWrapper() { - if (m_OwnsObject) { - static std::mutex mut; - std::lock_guard guard(mut); - s_QueuedDeletions.push_back(m_LuabindObject); - } -} - -luabind::adl::object GetCopyForStateInternal(const luabind::adl::object& obj, lua_State& targetState) { - if (obj.is_valid()) { - int type = luabind::type(obj); - if (type == LUA_TNUMBER) { - return luabind::adl::object(&targetState, luabind::object_cast(obj)); - } else if (type == LUA_TBOOLEAN) { - return luabind::adl::object(&targetState, luabind::object_cast(obj)); - } else if (type == LUA_TSTRING) { - return luabind::adl::object(&targetState, luabind::object_cast(obj)); - } else if (type == LUA_TTABLE) { - luabind::object table = luabind::newtable(&targetState); - for (luabind::iterator itr(obj), itrEnd; itr != itrEnd; ++itr) { - table[GetCopyForStateInternal(itr.key(), targetState)] = GetCopyForStateInternal(*itr, targetState); - } - return table; - } else if (type == LUA_TUSERDATA) { -#define PER_LUA_BINDING(Type) \ - if (boost::optional boundObject = luabind::object_cast_nothrow(obj)) { \ - return luabind::adl::object(&targetState, boundObject.get()); \ - } - - LIST_OF_LUABOUND_OBJECTS -#undef PER_LUA_BINDING - } - } - - // Dear god, I hope this is safe and equivalent to nil, because I can't find another way of doing it. - return luabind::adl::object(); -} - -LuabindObjectWrapper LuabindObjectWrapper::GetCopyForState(lua_State& targetState) const { - luabind::adl::object* copy = new luabind::adl::object(GetCopyForStateInternal(*m_LuabindObject, targetState)); - return LuabindObjectWrapper(copy, m_FilePath, true); -} diff --git a/Source/Lua/LuabindObjectWrapper.h b/Source/Lua/LuabindObjectWrapper.h deleted file mode 100644 index 8056028bc1..0000000000 --- a/Source/Lua/LuabindObjectWrapper.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include -#include - -struct lua_State; - -namespace luabind::adl { - class object; -} - -namespace RTE { - -#pragma region Global Macro Definitions -#define ScriptFunctionNames(...) \ - virtual std::vector GetSupportedScriptFunctionNames() const { return {__VA_ARGS__}; } - -#define AddScriptFunctionNames(PARENT, ...) \ - std::vector GetSupportedScriptFunctionNames() const override { \ - std::vector functionNames = PARENT::GetSupportedScriptFunctionNames(); \ - functionNames.insert(functionNames.end(), {__VA_ARGS__}); \ - return functionNames; \ - } -#pragma endregion - - /// A wrapper for luabind objects, to avoid include problems with luabind. - class LuabindObjectWrapper { - - public: -#pragma region Creation - /// Constructor method used for LuabindObjectWrapper. - LuabindObjectWrapper() = default; - - /// Constructor method used to instantiate a LuabindObjectWrapper object in system memory. - explicit LuabindObjectWrapper(luabind::adl::object* luabindObject, const std::string_view& filePath, bool ownsObject = true) : - m_OwnsObject(ownsObject), m_LuabindObject(luabindObject), m_FilePath(filePath) {} -#pragma endregion - -#pragma region Destruction - static void ApplyQueuedDeletions(); - - /// Destructor method used to clean up a LuabindObjectWrapper object before deletion from system memory. - ~LuabindObjectWrapper(); -#pragma endregion - - /// Attempts to copy a luabind object into another state. - LuabindObjectWrapper GetCopyForState(lua_State& newState) const; - -#pragma region Getters - /// Gets the LuabindObjectWrapper's luabind object. Ownership is NOT transferred! - /// @return The LuabindObjectWrapper's luabind object. - luabind::adl::object* GetLuabindObject() const { return m_LuabindObject; } - - /// Gets the LuabindObjectWrapper's file path. - /// @return The LuabindObjectWrapper's file path. - const std::string& GetFilePath() const { return m_FilePath; } -#pragma endregion - - private: - bool m_OwnsObject; //!< Whether or not we own the luabind object this is wrapping. - luabind::adl::object* m_LuabindObject; //!< The luabind object this is wrapping. - std::string m_FilePath; //!< The filepath the wrapped luabind object represents, if it's a function. - - // Disallow the use of some implicit methods. - LuabindObjectWrapper(const LuabindObjectWrapper& reference) = delete; - LuabindObjectWrapper& operator=(const LuabindObjectWrapper& rhs) = delete; - }; -} // namespace RTE diff --git a/Source/Lua/meson.build b/Source/Lua/meson.build index f52ed9f644..8d25a01a72 100644 --- a/Source/Lua/meson.build +++ b/Source/Lua/meson.build @@ -1,5 +1,4 @@ lua_sources = files( -'LuabindObjectWrapper.cpp', 'LuaAdapters.cpp', 'LuaBindingsActivities.cpp', 'LuaBindingsEntities.cpp', @@ -8,19 +7,19 @@ lua_sources = files( 'LuaBindingsManagers.cpp', 'LuaBindingsMisc.cpp', 'LuaBindingsSystem.cpp', -'LuaBindingsPrimitives.cpp' +'LuaBindingsPrimitives.cpp', +'LuaBridgeRegistry.cpp', +'LuaObjectWrapper.cpp' ) luabindings_cpp_args = [] defaults_override = [] if compiler.get_argument_syntax() == 'gcc' elif compiler.get_argument_syntax() == 'msvc' - luabindings_cpp_args += ['-D_HAS_ITERATOR_DEBUGGING=0', '-D_HAS_AUTO_PTR_ETC=1', '-permissive', '-bigobj'] - defaults_override = ['cpp_std=v'+get_option('cpp_std')] # override standard to use vc++, removing permissive- flag - message(defaults_override) + luabindings_cpp_args += ['-bigobj'] else error('Unsupported compiler') endif -lua_bindings = static_library('lua_bindings', lua_sources, dependencies:deps + luabind_dep, include_directories: [source_inc_dirs, external_inc_dirs], cpp_args: luabindings_cpp_args, cpp_pch:pch, override_options: defaults_override) +lua_bindings = static_library('lua_bindings', lua_sources, dependencies:deps, include_directories: [source_inc_dirs, external_inc_dirs], cpp_args: luabindings_cpp_args, cpp_pch:pch, override_options: defaults_override) source_libs += lua_bindings diff --git a/Source/Managers/LuaMan.cpp b/Source/Managers/LuaMan.cpp index 88bab187f0..64e712143b 100644 --- a/Source/Managers/LuaMan.cpp +++ b/Source/Managers/LuaMan.cpp @@ -1,6 +1,6 @@ #include "LuaMan.h" -#include "LuabindObjectWrapper.h" +#include "LuaObjectWrapper.h" #include "LuaBindingRegisterDefinitions.h" #include "ThreadMan.h" #include "System.h" @@ -35,11 +35,10 @@ void LuaStateWrapper::Clear() { void LuaStateWrapper::Initialize() { m_State = luaL_newstate(); - luabind::open(m_State); tracy::LuaRegister(m_State); // We do async GC, but we still keep the normal GC on so it can catch any big spikes or runaway allocs - //lua_gc(m_State, LUA_GCSTOP, 0); + // lua_gc(m_State, LUA_GCSTOP, 0); const luaL_Reg libsToLoad[] = { // Basic Lua libraries @@ -50,11 +49,11 @@ void LuaStateWrapper::Initialize() { {LUA_MATHLIBNAME, luaopen_math}, {LUA_DBLIBNAME, luaopen_debug}, - // These were removed for "security reasons" but we need them for debugger integration + // These were removed for "security reasons" but we need them for debugger integration {LUA_IOLIBNAME, luaopen_io}, {LUA_OSLIBNAME, luaopen_os}, - // LuaJIT libraries + // LuaJIT libraries {LUA_BITLIBNAME, luaopen_bit}, {LUA_FFILIBNAME, luaopen_ffi}, {LUA_JITLIBNAME, luaopen_jit}, @@ -76,176 +75,176 @@ void LuaStateWrapper::Initialize() { RTEAbort("Failed to initialize LuaJIT!\nIf this error persists, please disable LuaJIT with \"Settings.ini\" property \"DisableLuaJIT\"."); } - // From LuaBind documentation: - // As mentioned in the Lua documentation, it is possible to pass an error handler function to lua_pcall(). LuaBind makes use of lua_pcall() internally when calling member functions and free functions. - // It is possible to set the error handler function that LuaBind will use globally: - // set_pcall_callback(&AddFileAndLineToError); // NOTE: this seems to do nothing because retrieving the error from the lua stack wasn't done correctly. The current error handling works just fine but might look into doing this properly sometime later. - // Register all relevant bindings to the state. Note that the order of registration is important, as bindings can't derive from an unregistered type (inheritance and all that). - luabind::module(m_State)[luabind::class_("LuaManager") - .property("TempEntity", &LuaStateWrapper::GetTempEntity) - .property("TempEntities", &LuaStateWrapper::GetTempEntityVector, luabind::return_stl_iterator) - .def("SelectRand", &LuaStateWrapper::SelectRand) - .def("RangeRand", &LuaStateWrapper::RangeRand) - .def("PosRand", &LuaStateWrapper::PosRand) - .def("NormalRand", &LuaStateWrapper::NormalRand) - .def("GetDirectoryList", &LuaStateWrapper::DirectoryList, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("GetFileList", &LuaStateWrapper::FileList, luabind::adopt(luabind::return_value) + luabind::return_stl_iterator) - .def("FileExists", &LuaStateWrapper::FileExists) - .def("DirectoryExists", &LuaStateWrapper::DirectoryExists) - .def("FileOpen", &LuaStateWrapper::FileOpen) - .def("FileClose", &LuaStateWrapper::FileClose) - .def("FileRemove", &LuaStateWrapper::FileRemove) - .def("DirectoryCreate", &LuaStateWrapper::DirectoryCreate1) - .def("DirectoryCreate", &LuaStateWrapper::DirectoryCreate2) - .def("DirectoryRemove", &LuaStateWrapper::DirectoryRemove1) - .def("DirectoryRemove", &LuaStateWrapper::DirectoryRemove2) - .def("FileRename", &LuaStateWrapper::FileRename) - .def("DirectoryRename", &LuaStateWrapper::DirectoryRename) - .def("FileReadLine", &LuaStateWrapper::FileReadLine) - .def("FileWriteLine", &LuaStateWrapper::FileWriteLine) - .def("FileEOF", &LuaStateWrapper::FileEOF), - - luabind::def("DeleteEntity", &LuaAdaptersUtility::DeleteEntity, luabind::adopt(_1)), // NOT a member function, so adopting _1 instead of the _2 for the first param, since there's no "this" pointer!! - luabind::def("LERP", (float (*)(float, float, float, float, float))&Lerp), - luabind::def("Lerp", (float (*)(float, float, float, float, float))&Lerp), - luabind::def("Lerp", (Vector(*)(float, float, Vector, Vector, float))&Lerp), - luabind::def("Lerp", (Matrix(*)(float, float, const Matrix&, const Matrix&, float))&Lerp), - luabind::def("EaseIn", &EaseIn), - luabind::def("EaseOut", &EaseOut), - luabind::def("EaseInOut", &EaseInOut), - luabind::def("Clamp", &Limit), - luabind::def("NormalizeAngleBetween0And2PI", &NormalizeAngleBetween0And2PI), - luabind::def("NormalizeAngleBetweenNegativePIAndPI", &NormalizeAngleBetweenNegativePIAndPI), - luabind::def("AngleWithinRange", &AngleWithinRange), - luabind::def("ClampAngle", &ClampAngle), - luabind::def("GetPPM", &LuaAdaptersUtility::GetPPM), - luabind::def("GetMPP", &LuaAdaptersUtility::GetMPP), - luabind::def("GetPPL", &LuaAdaptersUtility::GetPPL), - luabind::def("GetLPP", &LuaAdaptersUtility::GetLPP), - luabind::def("GetPathFindingFlyingJumpHeight", &LuaAdaptersUtility::GetPathFindingFlyingJumpHeight), - luabind::def("GetPathFindingDefaultDigStrength", &LuaAdaptersUtility::GetPathFindingDefaultDigStrength), - luabind::def("RoundFloatToPrecision", &RoundFloatToPrecision), - luabind::def("RoundToNearestMultiple", &RoundToNearestMultiple), - - RegisterLuaBindingsOfType(SystemLuaBindings, Vector), - RegisterLuaBindingsOfType(SystemLuaBindings, Box), - RegisterLuaBindingsOfType(EntityLuaBindings, Entity), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, SoundContainer), - RegisterLuaBindingsOfType(EntityLuaBindings, SoundSet), - RegisterLuaBindingsOfType(EntityLuaBindings, LimbPath), - RegisterLuaBindingsOfAbstractType(EntityLuaBindings, SceneObject), - RegisterLuaBindingsOfAbstractType(EntityLuaBindings, MovableObject), - RegisterLuaBindingsOfType(EntityLuaBindings, Material), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, MOPixel), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, TerrainObject), - RegisterLuaBindingsOfAbstractType(EntityLuaBindings, MOSprite), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, MOSParticle), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, MOSRotating), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Attachable), - RegisterLuaBindingsOfAbstractType(EntityLuaBindings, Emission), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, AEmitter), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, AEJetpack), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, PEmitter), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Actor), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, ADoor), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Arm), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Leg), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, AHuman), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, ACrab), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Turret), - RegisterLuaBindingsOfAbstractType(EntityLuaBindings, ACraft), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, ACDropShip), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, ACRocket), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, HeldDevice), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Magazine), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Round), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, HDFirearm), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, ThrownDevice), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, TDExplosive), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, PieSlice), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, PieMenu), - RegisterLuaBindingsOfType(EntityLuaBindings, Gib), - RegisterLuaBindingsOfType(SystemLuaBindings, Controller), - RegisterLuaBindingsOfType(SystemLuaBindings, Timer), - RegisterLuaBindingsOfType(SystemLuaBindings, PathRequest), - RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Scene), - RegisterLuaBindingsOfType(EntityLuaBindings, SceneArea), - RegisterLuaBindingsOfType(EntityLuaBindings, StaticSceneLayer), - RegisterLuaBindingsOfType(EntityLuaBindings, SLBackground), - RegisterLuaBindingsOfAbstractType(EntityLuaBindings, Deployment), - RegisterLuaBindingsOfType(SystemLuaBindings, DataModule), - RegisterLuaBindingsOfType(ActivityLuaBindings, Activity), - RegisterLuaBindingsOfAbstractType(ActivityLuaBindings, GameActivity), - RegisterLuaBindingsOfAbstractType(EntityLuaBindings, GlobalScript), - RegisterLuaBindingsOfType(EntityLuaBindings, MetaPlayer), - RegisterLuaBindingsOfType(GUILuaBindings, GUIBanner), - RegisterLuaBindingsOfType(GUILuaBindings, BuyMenuGUI), - RegisterLuaBindingsOfType(GUILuaBindings, SceneEditorGUI), - RegisterLuaBindingsOfType(ManagerLuaBindings, ActivityMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, AudioMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, MusicMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, CameraMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, ConsoleMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, FrameMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, MetaMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, MovableMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, PerformanceMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, PostProcessMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, PresetMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, PrimitiveMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, SceneMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, SettingsMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, TimerMan), - RegisterLuaBindingsOfType(ManagerLuaBindings, UInputMan), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, GraphicalPrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, LinePrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, ArcPrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, SplinePrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, BoxPrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, BoxFillPrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, RoundedBoxPrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, RoundedBoxFillPrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, CirclePrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, CircleFillPrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, EllipsePrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, EllipseFillPrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, TrianglePrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, TriangleFillPrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, TextPrimitive), - RegisterLuaBindingsOfType(PrimitiveLuaBindings, BitmapPrimitive), - RegisterLuaBindingsOfType(InputLuaBindings, InputDevice), - RegisterLuaBindingsOfType(InputLuaBindings, InputElements), - RegisterLuaBindingsOfType(InputLuaBindings, JoyButtons), - RegisterLuaBindingsOfType(InputLuaBindings, JoyDirections), - RegisterLuaBindingsOfType(InputLuaBindings, MouseButtons), - RegisterLuaBindingsOfType(InputLuaBindings, SDL_Keycode), - RegisterLuaBindingsOfType(InputLuaBindings, SDL_Scancode), - RegisterLuaBindingsOfType(InputLuaBindings, SDL_GamepadButton), - RegisterLuaBindingsOfType(InputLuaBindings, SDL_GamepadAxis), - RegisterLuaBindingsOfType(MiscLuaBindings, AlarmEvent), - RegisterLuaBindingsOfType(MiscLuaBindings, Directions), - RegisterLuaBindingsOfType(MiscLuaBindings, DrawBlendMode), - RegisterLuaBindingsOfType(MiscLuaBindings, DrawDepth)]; + m_BindingStorage = std::make_unique(); + LuaBinding::Registry registry(m_State, *m_BindingStorage); + + registry.Class("LuaManager") + .addProperty("TempEntity", &LuaStateWrapper::GetTempEntity) + .addProperty("TempEntities", &LuaStateWrapper::GetTempEntityVector, LuaBinding::ReturnStlIterator) + .addFunction("SelectRand", &LuaStateWrapper::SelectRand) + .addFunction("RangeRand", &LuaStateWrapper::RangeRand) + .addFunction("PosRand", &LuaStateWrapper::PosRand) + .addFunction("NormalRand", &LuaStateWrapper::NormalRand) + .addFunction("GetDirectoryList", &LuaStateWrapper::DirectoryList, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("GetFileList", &LuaStateWrapper::FileList, LuaBinding::AdoptResult, LuaBinding::ReturnStlIterator) + .addFunction("FileExists", &LuaStateWrapper::FileExists) + .addFunction("DirectoryExists", &LuaStateWrapper::DirectoryExists) + .addFunction("FileOpen", &LuaStateWrapper::FileOpen) + .addFunction("FileClose", &LuaStateWrapper::FileClose) + .addFunction("FileRemove", &LuaStateWrapper::FileRemove) + .addFunction("DirectoryCreate", &LuaStateWrapper::DirectoryCreate1) + .addFunction("DirectoryCreate", &LuaStateWrapper::DirectoryCreate2) + .addFunction("DirectoryRemove", &LuaStateWrapper::DirectoryRemove1) + .addFunction("DirectoryRemove", &LuaStateWrapper::DirectoryRemove2) + .addFunction("FileRename", &LuaStateWrapper::FileRename) + .addFunction("DirectoryRename", &LuaStateWrapper::DirectoryRename) + .addFunction("FileReadLine", &LuaStateWrapper::FileReadLine) + .addFunction("FileWriteLine", &LuaStateWrapper::FileWriteLine) + .addFunction("FileEOF", &LuaStateWrapper::FileEOF); + + registry.Function("DeleteEntity", &LuaAdaptersUtility::DeleteEntity, LuaBinding::AdoptArg<1>); // NOT a member function, so adopting argument 1 instead of 2 for the first param, since there's no "this" pointer!! + registry.Function("LERP", (float (*)(float, float, float, float, float)) & Lerp); + registry.Function("Lerp", (float (*)(float, float, float, float, float)) & Lerp); + registry.Function("Lerp", (Vector(*)(float, float, Vector, Vector, float)) & Lerp); + registry.Function("Lerp", (Matrix(*)(float, float, const Matrix&, const Matrix&, float)) & Lerp); + registry.Function("EaseIn", &EaseIn); + registry.Function("EaseOut", &EaseOut); + registry.Function("EaseInOut", &EaseInOut); + registry.Function("Clamp", &Limit); + registry.Function("NormalizeAngleBetween0And2PI", &NormalizeAngleBetween0And2PI); + registry.Function("NormalizeAngleBetweenNegativePIAndPI", &NormalizeAngleBetweenNegativePIAndPI); + registry.Function("AngleWithinRange", &AngleWithinRange); + registry.Function("ClampAngle", &ClampAngle); + registry.Function("GetPPM", &LuaAdaptersUtility::GetPPM); + registry.Function("GetMPP", &LuaAdaptersUtility::GetMPP); + registry.Function("GetPPL", &LuaAdaptersUtility::GetPPL); + registry.Function("GetLPP", &LuaAdaptersUtility::GetLPP); + registry.Function("GetPathFindingFlyingJumpHeight", &LuaAdaptersUtility::GetPathFindingFlyingJumpHeight); + registry.Function("GetPathFindingDefaultDigStrength", &LuaAdaptersUtility::GetPathFindingDefaultDigStrength); + registry.Function("RoundFloatToPrecision", &RoundFloatToPrecision); + registry.Function("RoundToNearestMultiple", &RoundToNearestMultiple); + + RegisterLuaBindingsOfType(SystemLuaBindings, Vector); + RegisterLuaBindingsOfType(SystemLuaBindings, Box); + RegisterLuaBindingsOfType(EntityLuaBindings, Entity); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, SoundContainer); + RegisterLuaBindingsOfType(EntityLuaBindings, SoundSet); + RegisterLuaBindingsOfType(EntityLuaBindings, LimbPath); + RegisterLuaBindingsOfAbstractType(EntityLuaBindings, SceneObject); + RegisterLuaBindingsOfAbstractType(EntityLuaBindings, MovableObject); + RegisterLuaBindingsOfType(EntityLuaBindings, Material); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, MOPixel); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, TerrainObject); + RegisterLuaBindingsOfAbstractType(EntityLuaBindings, MOSprite); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, MOSParticle); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, MOSRotating); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Attachable); + RegisterLuaBindingsOfAbstractType(EntityLuaBindings, Emission); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, AEmitter); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, AEJetpack); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, PEmitter); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Actor); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, ADoor); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Arm); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Leg); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, AHuman); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, ACrab); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Turret); + RegisterLuaBindingsOfAbstractType(EntityLuaBindings, ACraft); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, ACDropShip); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, ACRocket); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, HeldDevice); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Magazine); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Round); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, HDFirearm); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, ThrownDevice); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, TDExplosive); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, PieSlice); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, PieMenu); + RegisterLuaBindingsOfType(EntityLuaBindings, Gib); + RegisterLuaBindingsOfType(SystemLuaBindings, Controller); + RegisterLuaBindingsOfType(SystemLuaBindings, Timer); + RegisterLuaBindingsOfType(SystemLuaBindings, PathRequest); + RegisterLuaBindingsOfConcreteType(EntityLuaBindings, Scene); + RegisterLuaBindingsOfType(EntityLuaBindings, SceneArea); + RegisterLuaBindingsOfType(EntityLuaBindings, StaticSceneLayer); + RegisterLuaBindingsOfType(EntityLuaBindings, SLBackground); + RegisterLuaBindingsOfAbstractType(EntityLuaBindings, Deployment); + RegisterLuaBindingsOfType(SystemLuaBindings, DataModule); + RegisterLuaBindingsOfType(ActivityLuaBindings, Activity); + RegisterLuaBindingsOfAbstractType(ActivityLuaBindings, GameActivity); + RegisterLuaBindingsOfAbstractType(EntityLuaBindings, GlobalScript); + RegisterLuaBindingsOfType(EntityLuaBindings, MetaPlayer); + RegisterLuaBindingsOfType(GUILuaBindings, GUIBanner); + RegisterLuaBindingsOfType(GUILuaBindings, BuyMenuGUI); + RegisterLuaBindingsOfType(GUILuaBindings, SceneEditorGUI); + RegisterLuaBindingsOfType(ManagerLuaBindings, ActivityMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, AudioMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, MusicMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, CameraMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, ConsoleMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, FrameMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, MetaMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, MovableMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, PerformanceMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, PostProcessMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, PresetMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, PrimitiveMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, SceneMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, SettingsMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, TimerMan); + RegisterLuaBindingsOfType(ManagerLuaBindings, UInputMan); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, GraphicalPrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, LinePrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, ArcPrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, SplinePrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, BoxPrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, BoxFillPrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, RoundedBoxPrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, RoundedBoxFillPrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, CirclePrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, CircleFillPrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, EllipsePrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, EllipseFillPrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, TrianglePrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, TriangleFillPrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, TextPrimitive); + RegisterLuaBindingsOfType(PrimitiveLuaBindings, BitmapPrimitive); + RegisterLuaBindingsOfType(InputLuaBindings, InputDevice); + RegisterLuaBindingsOfType(InputLuaBindings, InputElements); + RegisterLuaBindingsOfType(InputLuaBindings, JoyButtons); + RegisterLuaBindingsOfType(InputLuaBindings, JoyDirections); + RegisterLuaBindingsOfType(InputLuaBindings, MouseButtons); + RegisterLuaBindingsOfType(InputLuaBindings, SDL_Keycode); + RegisterLuaBindingsOfType(InputLuaBindings, SDL_Scancode); + RegisterLuaBindingsOfType(InputLuaBindings, SDL_GamepadButton); + RegisterLuaBindingsOfType(InputLuaBindings, SDL_GamepadAxis); + RegisterLuaBindingsOfType(MiscLuaBindings, AlarmEvent); + RegisterLuaBindingsOfType(MiscLuaBindings, Directions); + RegisterLuaBindingsOfType(MiscLuaBindings, DrawBlendMode); + RegisterLuaBindingsOfType(MiscLuaBindings, DrawDepth); + + registry.Finalize(); // Assign the manager instances to globals in the lua master state - luabind::globals(m_State)["TimerMan"] = &g_TimerMan; - luabind::globals(m_State)["FrameMan"] = &g_FrameMan; - luabind::globals(m_State)["PerformanceMan"] = &g_PerformanceMan; - luabind::globals(m_State)["PostProcessMan"] = &g_PostProcessMan; - luabind::globals(m_State)["PrimitiveMan"] = &g_PrimitiveMan; - luabind::globals(m_State)["PresetMan"] = &g_PresetMan; - luabind::globals(m_State)["AudioMan"] = &g_AudioMan; - luabind::globals(m_State)["MusicMan"] = &g_MusicMan; - luabind::globals(m_State)["UInputMan"] = &g_UInputMan; - luabind::globals(m_State)["SceneMan"] = &g_SceneMan; - luabind::globals(m_State)["ActivityMan"] = &g_ActivityMan; - luabind::globals(m_State)["MetaMan"] = &g_MetaMan; - luabind::globals(m_State)["MovableMan"] = &g_MovableMan; - luabind::globals(m_State)["CameraMan"] = &g_CameraMan; - luabind::globals(m_State)["ConsoleMan"] = &g_ConsoleMan; - luabind::globals(m_State)["LuaMan"] = this; - luabind::globals(m_State)["SettingsMan"] = &g_SettingsMan; + luabridge::setGlobal(m_State, &g_TimerMan, "TimerMan"); + luabridge::setGlobal(m_State, &g_FrameMan, "FrameMan"); + luabridge::setGlobal(m_State, &g_PerformanceMan, "PerformanceMan"); + luabridge::setGlobal(m_State, &g_PostProcessMan, "PostProcessMan"); + luabridge::setGlobal(m_State, &g_PrimitiveMan, "PrimitiveMan"); + luabridge::setGlobal(m_State, &g_PresetMan, "PresetMan"); + luabridge::setGlobal(m_State, &g_AudioMan, "AudioMan"); + luabridge::setGlobal(m_State, &g_MusicMan, "MusicMan"); + luabridge::setGlobal(m_State, &g_UInputMan, "UInputMan"); + luabridge::setGlobal(m_State, &g_SceneMan, "SceneMan"); + luabridge::setGlobal(m_State, &g_ActivityMan, "ActivityMan"); + luabridge::setGlobal(m_State, &g_MetaMan, "MetaMan"); + luabridge::setGlobal(m_State, &g_MovableMan, "MovableMan"); + luabridge::setGlobal(m_State, &g_CameraMan, "CameraMan"); + luabridge::setGlobal(m_State, &g_ConsoleMan, "ConsoleMan"); + luabridge::setGlobal(m_State, this, "LuaMan"); + luabridge::setGlobal(m_State, &g_SettingsMan, "SettingsMan"); const uint64_t seed = RandomNum(0, std::numeric_limits::max()); m_RandomGenerator.Seed(seed); @@ -285,6 +284,7 @@ void LuaStateWrapper::Initialize() { void LuaStateWrapper::Destroy() { lua_close(m_State); + m_BindingStorage.reset(); } void LuaStateWrapper::SetRunningAI(bool runningAI) { @@ -588,7 +588,7 @@ int LuaStateWrapper::RunScriptString(const std::string& scriptString, bool conso return error; } -int LuaStateWrapper::RunScriptFunctionObject(const LuabindObjectWrapper* functionObject, const std::string& selfGlobalTableName, const std::string& selfGlobalTableKey, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { +int LuaStateWrapper::RunScriptFunctionObject(const LuaObjectWrapper* functionObject, const std::string& selfGlobalTableName, const std::string& selfGlobalTableKey, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { int status = 0; std::lock_guard lock(m_Mutex); @@ -596,7 +596,7 @@ int LuaStateWrapper::RunScriptFunctionObject(const LuabindObjectWrapper* functio m_CurrentlyRunningScriptPath = functionObject->GetFilePath(); lua_pushcfunction(m_State, &AddFileAndLineToError); - functionObject->GetLuabindObject()->push(m_State); + functionObject->GetLuaObject()->push(m_State); int argumentCount = functionEntityArguments.size() + functionLiteralArguments.size() + functionObjectArguments.size(); if (!selfGlobalTableName.empty() && TableEntryIsDefined(selfGlobalTableName, selfGlobalTableKey)) { @@ -607,8 +607,7 @@ int LuaStateWrapper::RunScriptFunctionObject(const LuabindObjectWrapper* functio } for (const Entity* functionEntityArgument: functionEntityArguments) { - std::unique_ptr downCastEntityAsLuabindObjectWrapper(LuaAdaptersEntityCast::s_EntityToLuabindObjectCastFunctions.at(functionEntityArgument->GetClassName())(const_cast(functionEntityArgument), m_State)); - downCastEntityAsLuabindObjectWrapper->GetLuabindObject()->push(m_State); + LuaAdaptersEntityCast::s_EntityToLuaObjectPushFunctions.at(functionEntityArgument->GetClassName())(const_cast(functionEntityArgument), m_State); } for (const std::string_view& functionLiteralArgument: functionLiteralArguments) { @@ -624,12 +623,12 @@ int LuaStateWrapper::RunScriptFunctionObject(const LuabindObjectWrapper* functio } } - for (const LuabindObjectWrapper* functionObjectArgument: functionObjectArguments) { - if (functionObjectArgument->GetLuabindObject()->interpreter() != m_State) { - LuabindObjectWrapper copy = functionObjectArgument->GetCopyForState(*m_State); - copy.GetLuabindObject()->push(m_State); + for (const LuaObjectWrapper* functionObjectArgument: functionObjectArguments) { + if (functionObjectArgument->GetLuaObject()->state() != m_State) { + LuaObjectWrapper copy = functionObjectArgument->GetCopyForState(*m_State); + copy.GetLuaObject()->push(m_State); } else { - functionObjectArgument->GetLuabindObject()->push(m_State); + functionObjectArgument->GetLuaObject()->push(m_State); } } const std::string& path = functionObject->GetFilePath(); @@ -669,7 +668,7 @@ int LuaStateWrapper::RunScriptFunctionObject(const LuabindObjectWrapper* functio return status; } -int LuaStateWrapper::RunScriptConditionalTestFunctionObject(const LuabindObjectWrapper* functionObject, const std::string& selfGlobalTableName, const std::string& selfGlobalTableKey, bool& returnParam, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { +int LuaStateWrapper::RunScriptConditionalTestFunctionObject(const LuaObjectWrapper* functionObject, const std::string& selfGlobalTableName, const std::string& selfGlobalTableKey, bool& returnParam, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { int status = 0; std::lock_guard lock(m_Mutex); @@ -677,7 +676,7 @@ int LuaStateWrapper::RunScriptConditionalTestFunctionObject(const LuabindObjectW m_CurrentlyRunningScriptPath = functionObject->GetFilePath(); lua_pushcfunction(m_State, &AddFileAndLineToError); - functionObject->GetLuabindObject()->push(m_State); + functionObject->GetLuaObject()->push(m_State); int argumentCount = functionEntityArguments.size() + functionLiteralArguments.size() + functionObjectArguments.size(); if (!selfGlobalTableName.empty() && TableEntryIsDefined(selfGlobalTableName, selfGlobalTableKey)) { @@ -688,8 +687,7 @@ int LuaStateWrapper::RunScriptConditionalTestFunctionObject(const LuabindObjectW } for (const Entity* functionEntityArgument: functionEntityArguments) { - std::unique_ptr downCastEntityAsLuabindObjectWrapper(LuaAdaptersEntityCast::s_EntityToLuabindObjectCastFunctions.at(functionEntityArgument->GetClassName())(const_cast(functionEntityArgument), m_State)); - downCastEntityAsLuabindObjectWrapper->GetLuabindObject()->push(m_State); + LuaAdaptersEntityCast::s_EntityToLuaObjectPushFunctions.at(functionEntityArgument->GetClassName())(const_cast(functionEntityArgument), m_State); } for (const std::string_view& functionLiteralArgument: functionLiteralArguments) { @@ -705,12 +703,12 @@ int LuaStateWrapper::RunScriptConditionalTestFunctionObject(const LuabindObjectW } } - for (const LuabindObjectWrapper* functionObjectArgument: functionObjectArguments) { - if (functionObjectArgument->GetLuabindObject()->interpreter() != m_State) { - LuabindObjectWrapper copy = functionObjectArgument->GetCopyForState(*m_State); - copy.GetLuabindObject()->push(m_State); + for (const LuaObjectWrapper* functionObjectArgument: functionObjectArguments) { + if (functionObjectArgument->GetLuaObject()->state() != m_State) { + LuaObjectWrapper copy = functionObjectArgument->GetCopyForState(*m_State); + copy.GetLuaObject()->push(m_State); } else { - functionObjectArgument->GetLuabindObject()->push(m_State); + functionObjectArgument->GetLuaObject()->push(m_State); } } @@ -821,14 +819,17 @@ int LuaStateWrapper::RunScriptFile(const std::string& filePath, bool consoleErro return error; } -bool LuaStateWrapper::RetrieveFunctions(const std::string& funcObjectName, const std::vector& functionNamesToLookFor, std::unordered_map& outFunctionNamesAndObjects) { +bool LuaStateWrapper::RetrieveFunctions(const std::string& funcObjectName, const std::vector& functionNamesToLookFor, std::unordered_map& outFunctionNamesAndObjects) { std::lock_guard lock(m_Mutex); s_currentLuaState = this; - luabind::object funcHoldingObject = luabind::globals(m_State)[funcObjectName.c_str()]; - if (luabind::type(funcHoldingObject) == LUA_TNIL) { + const int stackTop = lua_gettop(m_State); + lua_getglobal(m_State, funcObjectName.c_str()); + if (lua_isnil(m_State, -1)) { + lua_settop(m_State, stackTop); return false; } + const int funcHoldingObjectIndex = lua_gettop(m_State); auto& newScript = m_ScriptCache[funcObjectName.c_str()]; for (auto& pair: newScript.functionNamesAndObjects) { @@ -836,22 +837,25 @@ bool LuaStateWrapper::RetrieveFunctions(const std::string& funcObjectName, const } newScript.functionNamesAndObjects.clear(); for (const std::string& functionName: functionNamesToLookFor) { - luabind::object functionObject = funcHoldingObject[functionName]; - if (luabind::type(functionObject) == LUA_TFUNCTION) { - luabind::object* functionObjectCopyForStoring = new luabind::object(functionObject); - newScript.functionNamesAndObjects.try_emplace(functionName, new LuabindObjectWrapper(functionObjectCopyForStoring, funcObjectName)); + lua_getfield(m_State, funcHoldingObjectIndex, functionName.c_str()); + if (lua_isfunction(m_State, -1)) { + luabridge::LuaRef* functionObjectCopyForStoring = new luabridge::LuaRef(luabridge::LuaRef::fromStack(m_State)); + newScript.functionNamesAndObjects.try_emplace(functionName, new LuaObjectWrapper(functionObjectCopyForStoring, funcObjectName)); + } else { + lua_pop(m_State, 1); } } + lua_settop(m_State, stackTop); for (auto& pair: newScript.functionNamesAndObjects) { - luabind::object* functionObjectCopyForStoring = new luabind::object(*pair.second->GetLuabindObject()); - outFunctionNamesAndObjects.try_emplace(pair.first, new LuabindObjectWrapper(functionObjectCopyForStoring, funcObjectName)); + luabridge::LuaRef* functionObjectCopyForStoring = new luabridge::LuaRef(*pair.second->GetLuaObject()); + outFunctionNamesAndObjects.try_emplace(pair.first, new LuaObjectWrapper(functionObjectCopyForStoring, funcObjectName)); } return true; } -int LuaStateWrapper::RunScriptFileAndRetrieveFunctions(const std::string& filePath, const std::vector& functionNamesToLookFor, std::unordered_map& outFunctionNamesAndObjects, bool forceReload) { +int LuaStateWrapper::RunScriptFileAndRetrieveFunctions(const std::string& filePath, const std::vector& functionNamesToLookFor, std::unordered_map& outFunctionNamesAndObjects, bool forceReload) { static bool disableCaching = false; forceReload = forceReload || disableCaching; @@ -861,8 +865,8 @@ int LuaStateWrapper::RunScriptFileAndRetrieveFunctions(const std::string& filePa if (!forceReload && cachedScript != m_ScriptCache.end()) { for (auto& pair: cachedScript->second.functionNamesAndObjects) { if (std::find(functionNamesToLookFor.begin(), functionNamesToLookFor.end(), pair.first) != functionNamesToLookFor.end()) { - luabind::object* functionObjectCopyForStoring = new luabind::object(*pair.second->GetLuabindObject()); - outFunctionNamesAndObjects.try_emplace(pair.first, new LuabindObjectWrapper(functionObjectCopyForStoring, filePath)); + luabridge::LuaRef* functionObjectCopyForStoring = new luabridge::LuaRef(*pair.second->GetLuaObject()); + outFunctionNamesAndObjects.try_emplace(pair.first, new LuaObjectWrapper(functionObjectCopyForStoring, filePath)); } } @@ -1298,7 +1302,7 @@ void LuaMan::Update() { m_GarbageCollectionTask.wait(); // Apply all deletions queued from lua - LuabindObjectWrapper::ApplyQueuedDeletions(); + LuaObjectWrapper::ApplyQueuedDeletions(); } void LuaMan::StartAsyncGarbageCollection() { diff --git a/Source/Managers/LuaMan.h b/Source/Managers/LuaMan.h index f7ee1fe8d6..6275eb6dee 100644 --- a/Source/Managers/LuaMan.h +++ b/Source/Managers/LuaMan.h @@ -8,6 +8,7 @@ #include "BS_thread_pool.hpp" #include +#include #include #define g_LuaMan LuaMan::Instance() @@ -16,8 +17,11 @@ struct lua_State; namespace RTE { - class LuabindObjectWrapper; + class LuaObjectWrapper; class MovableObject; + namespace LuaBinding { + class Storage; + } /// A single lua state. Multiple of these can exist at once for multithreaded scripting. class LuaStateWrapper { @@ -127,23 +131,23 @@ namespace RTE { /// Runs the given Lua function object. The first argument to the function will always be the self object. /// If either argument list has entries, they will be passed into the function in order, with entity arguments first. - /// @param functionObjectWrapper The LuabindObjectWrapper containing the Lua function to be run. + /// @param functionObjectWrapper The LuaObjectWrapper containing the Lua function to be run. /// @param selfGlobalTableName The name of the global Lua table that gives access to the self object. /// @param selfGlobalTableKey The key for this object in the respective global Lua table. /// @param functionEntityArguments Optional vector of entity pointers that should be passed into the Lua function. Their internal Lua states will not be accessible. Defaults to empty. /// @param functionLiteralArguments Optional vector of strings that should be passed into the Lua function. Entries must be surrounded with escaped quotes (i.e.`\"`) they'll be passed in as-is, allowing them to act as booleans, etc.. Defaults to empty. /// @return An error return value signaling success or any particular failure. Anything below 0 is an error signal. - int RunScriptFunctionObject(const LuabindObjectWrapper* functionObjectWrapper, const std::string& selfGlobalTableName, const std::string& selfGlobalTableKey, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); - + int RunScriptFunctionObject(const LuaObjectWrapper* functionObjectWrapper, const std::string& selfGlobalTableName, const std::string& selfGlobalTableKey, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); + /// Runs the given Lua function object. The first argument to the function will always be the self object. /// If either argument list has entries, they will be passed into the function in order, with entity arguments first. - /// @param functionObjectWrapper The LuabindObjectWrapper containing the Lua function to be run. + /// @param functionObjectWrapper The LuaObjectWrapper containing the Lua function to be run. /// @param selfGlobalTableName The name of the global Lua table that gives access to the self object. /// @param selfGlobalTableKey The key for this object in the respective global Lua table. /// @param functionEntityArguments Optional vector of entity pointers that should be passed into the Lua function. Their internal Lua states will not be accessible. Defaults to empty. /// @param functionLiteralArguments Optional vector of strings that should be passed into the Lua function. Entries must be surrounded with escaped quotes (i.e.`\"`) they'll be passed in as-is, allowing them to act as booleans, etc.. Defaults to empty. /// @return An error return value signaling success or any particular failure. Anything below 0 is an error signal. - int RunScriptConditionalTestFunctionObject(const LuabindObjectWrapper* functionObjectWrapper, const std::string& selfGlobalTableName, const std::string& selfGlobalTableKey, bool& returnParam, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); + int RunScriptConditionalTestFunctionObject(const LuaObjectWrapper* functionObjectWrapper, const std::string& selfGlobalTableName, const std::string& selfGlobalTableKey, bool& returnParam, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); /// Opens and loads a file containing a script and runs it on the state. /// @param filePath The path to the file to load and run. @@ -155,17 +159,17 @@ namespace RTE { /// Retrieves all of the specified functions that exist into the output map, and refreshes the cache. /// @param filePath The path to the file to load and run. /// @param functionNamesToLookFor The vector of strings defining the function names to be retrieved. - /// @param outFunctionNamesAndObjects The map of function names to LuabindObjectWrappers to be retrieved from the script that was run. + /// @param outFunctionNamesAndObjects The map of function names to LuaObjectWrappers to be retrieved from the script that was run. /// @return Returns whether functions were successfully retrieved. - bool RetrieveFunctions(const std::string& functionObjectName, const std::vector& functionNamesToLookFor, std::unordered_map& outFunctionNamesAndObjects); + bool RetrieveFunctions(const std::string& functionObjectName, const std::vector& functionNamesToLookFor, std::unordered_map& outFunctionNamesAndObjects); /// Opens and loads a file containing a script and runs it on the state, then retrieves all of the specified functions that exist into the output map. /// @param filePath The path to the file to load and run. /// @param functionNamesToLookFor The vector of strings defining the function names to be retrieved. - /// @param outFunctionNamesAndObjects The map of function names to LuabindObjectWrappers to be retrieved from the script that was run. + /// @param outFunctionNamesAndObjects The map of function names to LuaObjectWrappers to be retrieved from the script that was run. /// @param noCaching Whether caching shouldn't be used. /// @return Returns less than zero if any errors encountered when running this script. To get the actual error string, call GetLastError. - int RunScriptFileAndRetrieveFunctions(const std::string& filePath, const std::vector& functionNamesToLookFor, std::unordered_map& outFunctionNamesAndObjects, bool forceReload = false); + int RunScriptFileAndRetrieveFunctions(const std::string& filePath, const std::vector& functionNamesToLookFor, std::unordered_map& outFunctionNamesAndObjects, bool forceReload = false); #pragma endregion #pragma region Concrete Methods @@ -272,6 +276,7 @@ namespace RTE { std::unordered_set m_AddedRegisteredMOs; //!< The objects using our lua state that were recently added. lua_State* m_State; + std::unique_ptr m_BindingStorage; //!< What the Lua bindings of this state call, kept outside the Lua heap. Has to outlive the Lua state. Entity* m_TempEntity; //!< Temporary holder for an Entity object that we want to pass into the Lua state without fuss. Lets you export objects to lua easily. std::vector m_TempEntityVector; //!< Temporary holder for a vector of Entities that we want to pass into the Lua state without a fuss. Usually used to pass arguments to special Lua functions. std::string m_LastError; //!< Description of the last error that occurred in the script execution. @@ -281,7 +286,7 @@ namespace RTE { std::recursive_mutex m_Mutex; //!< Mutex to ensure multiple threads aren't running something in this lua state simultaneously. struct LuaScriptFunctionObjects { - std::unordered_map functionNamesAndObjects; + std::unordered_map functionNamesAndObjects; }; std::unordered_map m_ScriptCache; diff --git a/Source/Managers/MovableMan.cpp b/Source/Managers/MovableMan.cpp index ced2cc53e5..000a7e9ba6 100644 --- a/Source/Managers/MovableMan.cpp +++ b/Source/Managers/MovableMan.cpp @@ -30,9 +30,9 @@ using namespace RTE; AlarmEvent::AlarmEvent(const Vector& pos, int team, float range) : - m_ScenePos(pos), - m_Team((Activity::Teams)team), - m_Range(range * g_FrameMan.GetPlayerScreenWidth() * 0.51F) {} + m_ScenePos(pos), + m_Team((Activity::Teams)team), + m_Range(range * g_FrameMan.GetPlayerScreenWidth() * 0.51F) {} const std::string MovableMan::c_ClassName = "MovableMan"; @@ -1197,7 +1197,7 @@ void MovableMan::RegisterAlarmEvent(const AlarmEvent& newEvent) { m_AddedAlarmEvents.push_back(new AlarmEvent(newEvent)); } -void callLuaFunctionOnMORecursive(MovableObject* mo, const std::string& functionName, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { +void callLuaFunctionOnMORecursive(MovableObject* mo, const std::string& functionName, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { if (MOSRotating* mosr = dynamic_cast(mo)) { for (auto attachablrItr = mosr->GetAttachableList().begin(); attachablrItr != mosr->GetAttachableList().end();) { Attachable* attachable = *attachablrItr; @@ -1219,7 +1219,7 @@ void callLuaFunctionOnMORecursive(MovableObject* mo, const std::string& function mo->RunScriptedFunctionInAppropriateScripts(functionName, false, false, functionEntityArguments, functionLiteralArguments, functionObjectArguments); }; -void MovableMan::RunLuaFunctionOnAllMOs(const std::string& functionName, bool includeAdded, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { +void MovableMan::RunLuaFunctionOnAllMOs(const std::string& functionName, bool includeAdded, const std::vector& functionEntityArguments, const std::vector& functionLiteralArguments, const std::vector& functionObjectArguments) { if (includeAdded) { for (Actor* actor: m_AddedActors) { callLuaFunctionOnMORecursive(actor, functionName, functionEntityArguments, functionLiteralArguments, functionObjectArguments); diff --git a/Source/Managers/MovableMan.h b/Source/Managers/MovableMan.h index 3e672be257..57ee374f23 100644 --- a/Source/Managers/MovableMan.h +++ b/Source/Managers/MovableMan.h @@ -29,7 +29,7 @@ namespace RTE { class SceneLayer; class SceneObject; class Box; - class LuabindObjectWrapper; + class LuaObjectWrapper; class StateHasher; /// A struct to keep all data about a an alarming event for the AI Actors. @@ -553,9 +553,9 @@ namespace RTE { /// @param getsHitByMOsOnly Whether to only include MOs that have GetsHitByMOs enabled, or all MOs. /// @return Pointers to the MOs that are within the specified radius of the given centre position. const std::vector* GetMOsAtPosition(int pixelX, int pixelY, int ignoreTeam, bool getsHitByMOsOnly) const; - + /// Runs a lua function on all MOs in the simulation, including owned child MOs. - void RunLuaFunctionOnAllMOs(const std::string& functionName, bool includeAdded, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); + void RunLuaFunctionOnAllMOs(const std::string& functionName, bool includeAdded, const std::vector& functionEntityArguments = std::vector(), const std::vector& functionLiteralArguments = std::vector(), const std::vector& functionObjectArguments = std::vector()); /// Clears all cached lua functions on all MOs, including owned child MOs. void ReloadLuaScripts(); diff --git a/Source/Managers/meson.build b/Source/Managers/meson.build index 7d6b7ff6e2..2c44e12ad8 100644 --- a/Source/Managers/meson.build +++ b/Source/Managers/meson.build @@ -27,14 +27,11 @@ sources += files( luaman_cpp_args = preprocessor_flags defaults_override = [] if compiler.get_argument_syntax() == 'gcc' - luaman_cpp_args += ['-fpermissive'] elif compiler.get_argument_syntax() == 'msvc' - luaman_cpp_args += ['-D_HAS_ITERATOR_DEBUGGING=0', '-D_HAS_AUTO_PTR_ETC=1', '-permissive', '-bigobj'] - defaults_override = ['cpp_std=v'+get_option('cpp_std')] # override standard to use vc++, removing permissive- flag - message(defaults_override) + luaman_cpp_args += ['-bigobj'] else error('Unsupported compiler') endif -luaman = static_library('LuaMan', 'LuaMan.cpp', dependencies:deps + luabind_dep, include_directories: [source_inc_dirs, external_inc_dirs], cpp_args: luaman_cpp_args, cpp_pch:pch, override_options: defaults_override) +luaman = static_library('LuaMan', 'LuaMan.cpp', dependencies:deps, include_directories: [source_inc_dirs, external_inc_dirs], cpp_args: luaman_cpp_args, cpp_pch:pch, override_options: defaults_override) source_libs += luaman diff --git a/external/include/LuaBridge3/.gitattributes b/external/include/LuaBridge3/.gitattributes new file mode 100644 index 0000000000..f9bc644b9c --- /dev/null +++ b/external/include/LuaBridge3/.gitattributes @@ -0,0 +1,2 @@ +# The patch has to keep the line endings of the files it applies to, which are stored as LF. +*.patch text eol=lf diff --git a/external/include/LuaBridge3/CortexCommandChanges.md b/external/include/LuaBridge3/CortexCommandChanges.md new file mode 100644 index 0000000000..1f124e1b5a --- /dev/null +++ b/external/include/LuaBridge3/CortexCommandChanges.md @@ -0,0 +1,19 @@ +# LuaBridge3 in Cortex Command + +This is [LuaBridge3](https://github.com/kunitoki/LuaBridge3) at commit `64b3ec3d265578c742abd5d3939b133353952718` (version 3.1 development, October 2026), with only the `Source/LuaBridge` folder kept. + +It replaced luabind 0.7.1. Most of what makes the bindings behave the way scripts written for luabind expect lives in `Source/Lua/LuaBridgeDefinitions.h` and `Source/Lua/LuaBridgeRegistry.cpp` rather than in here, and LuaBridge itself is changed as little as possible, so it can be updated without much trouble. + +## Changes made to LuaBridge + +Every change is marked with a `Cortex Command` comment, and `CortexCommandChanges.patch` has all of them in one place. Any other change made to LuaBridge needs adding to it too. + +- `detail/Config.h`: added the `LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS` option, off by default. The game turns it on in `LuaBridgeDefinitions.h`. +- `detail/Stack.h`: with `LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS` on, the integer `Stack` specializations truncate any Lua number towards zero like luabind did, instead of rejecting numbers that have a fractional part or don't fit, and the floating point ones don't range check. Scripts pass things like `self.Team + 0.5` and `math.floor` results that ended up as floats all over the place. +- `detail/CFunctions.h`: calling a method on `nil` (most often by using `.` instead of `:`) raises a Lua error, like it did with luabind, instead of calling the member function through a null pointer and crashing the game. +- `detail/CFunctions.h`: `invoke_member_function`, `invoke_const_member_function` and `invoke_proxy_functor` accept the function they call in a light userdata as well as in a full userdata. The game keeps what its bindings call outside the Lua heap and hands Lua light userdata pointing to it, since the garbage collector visits every full userdata on every cycle, and there would be thousands of them. +- `detail/Userdata.h`: added `AncestryInfo`, a list of every class an object's class can be cast to with the pointer offsets to them, which `Userdata::get` uses when an object's metatable has one. LuaBridge otherwise goes up the class hierarchy one parent list and cast table at a time, which made using an object as one of its base classes, like calling an `Entity` method on an `AHuman`, several times slower than with luabind. The game puts these in the metatables of every class it registers. Like LuaBridge's own keys, the key it's stored under is a fixed value rather than an address, which the simulation's determinism depends on (see `RawGetP` in `Source/Lua/LuaBridgeDefinitions.h`). + +## Updating + +Copy over `Source/LuaBridge` from the new version and commit it on its own, then apply the changes again by running `git apply --3way external/include/LuaBridge3/CortexCommandChanges.patch` from the root of the repository. Afterwards, make the patch again with `git diff` against that commit, keeping the header at its top, and update the upstream commit given here and in the patch. diff --git a/external/include/LuaBridge3/CortexCommandChanges.patch b/external/include/LuaBridge3/CortexCommandChanges.patch new file mode 100644 index 0000000000..7f46ea39a8 --- /dev/null +++ b/external/include/LuaBridge3/CortexCommandChanges.patch @@ -0,0 +1,380 @@ +Cortex Command's changes to LuaBridge3, against upstream commit 64b3ec3d265578c742abd5d3939b133353952718. +They're described in CortexCommandChanges.md. To apply them to a fresh copy of upstream, run this from the root of the repository: + git apply external/include/LuaBridge3/CortexCommandChanges.patch + +diff --git a/external/include/LuaBridge3/LuaBridge/detail/CFunctions.h b/external/include/LuaBridge3/LuaBridge/detail/CFunctions.h +index f0d534486..83618e52a 100644 +--- a/external/include/LuaBridge3/LuaBridge/detail/CFunctions.h ++++ b/external/include/LuaBridge3/LuaBridge/detail/CFunctions.h +@@ -2030,6 +2030,10 @@ TypeResult get_member_object(lua_State* L, bool canBeConst) + lua_pop(L, 1); + } + ++ // Cortex Command: calling a method on nil (e.g. with . instead of :) is a Lua error like it was with luabind, rather than a call through a null pointer. ++ if (lua_isnil(L, selfIndex)) ++ raise_lua_error(L, "Tried to call a method on nil instead of an object, use : rather than . to call methods!"); ++ + return Userdata::get(L, selfIndex, canBeConst); + } + +@@ -2044,7 +2048,8 @@ int invoke_member_function(lua_State* L) + { + using FnTraits = function_traits; + +- LUABRIDGE_ASSERT(isfulluserdata(L, lua_upvalueindex(1))); ++ // Cortex Command: the member function pointer can also be in a light userdata, pointing to memory that's kept outside the Lua heap. ++ LUABRIDGE_ASSERT(lua_isuserdata(L, lua_upvalueindex(1))); + + auto ptr = get_member_object(L, false); + if (! ptr) +@@ -2061,7 +2066,8 @@ int invoke_const_member_function(lua_State* L) + { + using FnTraits = function_traits; + +- LUABRIDGE_ASSERT(isfulluserdata(L, lua_upvalueindex(1))); ++ // Cortex Command: the member function pointer can also be in a light userdata, pointing to memory that's kept outside the Lua heap. ++ LUABRIDGE_ASSERT(lua_isuserdata(L, lua_upvalueindex(1))); + + auto ptr = get_member_object(L, true); + if (! ptr) +@@ -2171,7 +2177,8 @@ int invoke_proxy_functor(lua_State* L) + { + using FnTraits = function_traits>; + +- LUABRIDGE_ASSERT(isfulluserdata(L, lua_upvalueindex(1))); ++ // Cortex Command: the functor can also be in a light userdata, pointing to memory that's kept outside the Lua heap. ++ LUABRIDGE_ASSERT(lua_isuserdata(L, lua_upvalueindex(1))); + + auto& func = *align>(lua_touserdata(L, lua_upvalueindex(1))); + +diff --git a/external/include/LuaBridge3/LuaBridge/detail/Config.h b/external/include/LuaBridge3/LuaBridge/detail/Config.h +index e5e759207..5918c53a3 100644 +--- a/external/include/LuaBridge3/LuaBridge/detail/Config.h ++++ b/external/include/LuaBridge3/LuaBridge/detail/Config.h +@@ -102,6 +102,18 @@ + #define LUABRIDGE_STRICT_STACK_CONVERSIONS 0 + #endif + ++/** ++ * @brief Convert Lua numbers to C++ numbers the way luabind did. (Cortex Command addition.) ++ * ++ * When enabled, integer `Stack` specializations truncate any `LUA_TNUMBER` towards zero (as `static_cast` from `lua_Number` does) instead of ++ * rejecting numbers with a fractional part or out of the target type's range, and floating point specializations don't range-check. ++ * ++ * @note Default is disabled. ++ */ ++#if !defined(LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS) ++#define LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS 0 ++#endif ++ + /** + * @brief Enable safe exception handling when lua is compiled as `C` and exceptions raise during execution of registered `lua_CFunction`. + * +diff --git a/external/include/LuaBridge3/LuaBridge/detail/Stack.h b/external/include/LuaBridge3/LuaBridge/detail/Stack.h +index 94517c9e5..512124baf 100644 +--- a/external/include/LuaBridge3/LuaBridge/detail/Stack.h ++++ b/external/include/LuaBridge3/LuaBridge/detail/Stack.h +@@ -306,10 +306,15 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -347,10 +352,15 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -387,10 +397,15 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -427,10 +442,15 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -468,10 +488,15 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -509,10 +534,15 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -550,10 +580,15 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -591,10 +626,15 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -632,10 +672,15 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -673,10 +718,15 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -715,10 +765,15 @@ struct Stack<__int128_t> + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast<__int128_t>(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by<__int128_t>(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast<__int128_t>(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -756,10 +811,15 @@ struct Stack<__uint128_t> + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS ++ // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. ++ return static_cast<__uint128_t>(static_cast(lua_tonumber(L, index))); ++#else + if (! is_integral_representable_by<__uint128_t>(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast<__uint128_t>(lua_tointeger(L, index)); ++#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) +@@ -798,8 +858,10 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if !LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + if (! is_floating_point_representable_by(L, index)) + return makeErrorCode(ErrorCode::FloatingPointDoesntFitIntoLuaNumber); ++#endif + + return static_cast(lua_tonumber(L, index)); + } +@@ -839,8 +901,10 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if !LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + if (! is_floating_point_representable_by(L, index)) + return makeErrorCode(ErrorCode::FloatingPointDoesntFitIntoLuaNumber); ++#endif + + return static_cast(lua_tonumber(L, index)); + } +@@ -880,8 +944,10 @@ struct Stack + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + ++#if !LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + if (! is_floating_point_representable_by(L, index)) + return makeErrorCode(ErrorCode::FloatingPointDoesntFitIntoLuaNumber); ++#endif + + return static_cast(lua_tonumber(L, index)); + } +diff --git a/external/include/LuaBridge3/LuaBridge/detail/Userdata.h b/external/include/LuaBridge3/LuaBridge/detail/Userdata.h +index 431f3823b..d2aa04625 100644 +--- a/external/include/LuaBridge3/LuaBridge/detail/Userdata.h ++++ b/external/include/LuaBridge3/LuaBridge/detail/Userdata.h +@@ -14,6 +14,7 @@ + #include "Result.h" + #include "Stack.h" + ++#include + #include + #include + +@@ -40,6 +41,35 @@ std::error_code getNilBadArgError(lua_State* L, int index) + return makeErrorCode(ErrorCode::InvalidTypeCast); + } + ++//================================================================================================= ++/** ++ * @brief Every class an object's class can be cast to, stored in its class and const metatables. (Cortex Command addition.) ++ * ++ * When a metatable has one of these under getAncestryInfoKey(), Userdata::get finds out whether the object can be used as a T, and ++ * where the T is within it, with a single lookup and a short loop, instead of going up the parent lists and the cast tables one class ++ * at a time. That matters for deep class hierarchies, where it used to make every access to a member of a base class slow. ++ * LuaBridge never puts these in metatables itself, so it works the same as before without them. ++ */ ++struct AncestryInfo ++{ ++ static constexpr int MaxAncestors = 24; ++ ++ const void* ClassKeys[MaxAncestors]; ///< Class registry keys of the class itself, followed by its bases, nearest first. ++ std::ptrdiff_t Offsets[MaxAncestors]; ///< What to add to a pointer to the class to get a pointer to each of those, in bytes. ++ int Count; ///< How many entries of the arrays are used. ++ bool IsConst; ///< Whether the metatable this is in is a const one. ++}; ++ ++/** ++ * @brief The key AncestryInfo is stored under in metatables. (Cortex Command addition.) ++ */ ++[[nodiscard]] inline const void* getAncestryInfoKey() noexcept ++{ ++ // A fixed value like the rest of LuaBridge's keys, rather than the address of something. Tables with keys that are addresses grow at ++ // different times from run to run, which changes when Lua's garbage collector runs, and Cortex Command's simulation has to be deterministic. ++ return reinterpret_cast(0xa9ce); ++} ++ + //================================================================================================= + /** + * @brief Return the identity pointer for our lightuserdata tokens. +@@ -300,6 +330,30 @@ public: + // Common-case fast path: compare the object's metatable directly against the registry class/const tables. + if (lua_getmetatable(L, absIndex)) // Stack: ..., mt + { ++ // Cortex Command: when the metatable says what classes its objects can be cast to, that's all that's needed. ++ lua_rawgetp_x(L, -1, getAncestryInfoKey()); // Stack: ..., mt, ancestry | nil ++ if (const auto* ancestry = static_cast(lua_touserdata(L, -1))) ++ { ++ lua_pop(L, 2); // Stack: ... ++ if (! ancestry->IsConst || canBeConst) ++ { ++ for (int i = 0; i < ancestry->Count; ++i) ++ { ++ if (ancestry->ClassKeys[i] == classId) ++ { ++ void* rawPtr = static_cast(lua_touserdata(L, absIndex))->getPointer(); ++ return rawPtr ? reinterpret_cast(static_cast(rawPtr) + ancestry->Offsets[i]) : nullptr; ++ } ++ } ++ } ++ // It can't be used as a T, so leave it to the rest to report why. ++ lua_getmetatable(L, absIndex); // Stack: ..., mt ++ } ++ else ++ { ++ lua_pop(L, 1); // Stack: ..., mt ++ } ++ + lua_rawgetp_x(L, LUA_REGISTRYINDEX, classId); // Stack: ..., mt, class_mt + if (lua_rawequal(L, -2, -1)) + { diff --git a/external/include/LuaBridge3/LuaBridge/Any.h b/external/include/LuaBridge3/LuaBridge/Any.h new file mode 100644 index 0000000000..3b753f40fa --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/Any.h @@ -0,0 +1,82 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2026, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" +#include "detail/Config.h" + +#if LUABRIDGE_HAS_CXX17_ANY + +#include +#include +#include +#include + +namespace luabridge { + +namespace detail { + +using AnyPushFn = std::function; + +inline std::unordered_map& anyPushRegistry() +{ + static std::unordered_map registry; + return registry; +} + +} // namespace detail + +//================================================================================================= +/** + * @brief Register a push handler for std::any holding type T. + */ +template +void registerAnyPush(lua_State*) +{ + detail::anyPushRegistry()[std::type_index(typeid(T))] = + [](lua_State* L, const std::any& value) -> Result + { + return Stack::push(L, std::any_cast(value)); + }; +} + +//================================================================================================= +/** + * @brief Stack specialization for `std::any` (push-only). + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, const std::any& value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! value.has_value()) + { + lua_pushnil(L); + return {}; + } + + auto& registry = detail::anyPushRegistry(); + + auto it = registry.find(std::type_index(value.type())); + if (it == registry.end()) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + return it->second(L, value); + } + + [[nodiscard]] static bool isInstance(lua_State*, int) + { + return false; // std::any cannot be detected from Lua side + } +}; + +} // namespace luabridge + +#endif // LUABRIDGE_HAS_CXX17_ANY diff --git a/external/include/LuaBridge3/LuaBridge/Array.h b/external/include/LuaBridge3/LuaBridge/Array.h new file mode 100644 index 0000000000..51e289d176 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/Array.h @@ -0,0 +1,83 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2020, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::array`. + */ +template +struct Stack> +{ + using Type = std::array; + + [[nodiscard]] static Result push(lua_State* L, const Type& array) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, static_cast(Size), 0); + const int tableIndex = lua_gettop(L); + + for (std::size_t i = 0; i < Size; ++i) + { + auto result = Stack::push(L, array[i]); + if (! result) + return result; + + lua_rawseti(L, tableIndex, static_cast(i + 1)); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + if (get_length(L, index) != Size) + return makeErrorCode(ErrorCode::InvalidTableSizeInCast); + + const StackRestore stackRestore(L); + + Type array; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + int arrayIndex = 0; + while (lua_next(L, absIndex) != 0) + { + auto item = Stack::get(L, -1); + if (!item) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + array[arrayIndex++] = *item; + lua_pop(L, 1); + } + + return array; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index) && get_length(L, index) == Size; + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/Deque.h b/external/include/LuaBridge3/LuaBridge/Deque.h new file mode 100644 index 0000000000..20c4421837 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/Deque.h @@ -0,0 +1,80 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2026, kunitoki +// Copyright 2020, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::deque`. + */ +template +struct Stack> +{ + using Type = std::deque; + + [[nodiscard]] static Result push(lua_State* L, const Type& deque) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, static_cast(deque.size()), 0); + const int tableIndex = lua_gettop(L); + + auto it = deque.cbegin(); + for (std::size_t i = 1; it != deque.cend(); ++i, ++it) + { + auto result = Stack::push(L, *it); + if (! result) + return result; + + lua_rawseti(L, tableIndex, static_cast(i)); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type deque; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto item = Stack::get(L, -1); + if (! item) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + deque.emplace_back(*item); + lua_pop(L, 1); + } + + return deque; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/Dump.h b/external/include/LuaBridge3/LuaBridge/Dump.h new file mode 100644 index 0000000000..a9899f7c09 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/Dump.h @@ -0,0 +1,156 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2019, Dmitry Tarakanov +// Copyright 2012, Vinnie Falco +// Copyright 2007, Nathan Reed +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/ClassInfo.h" + +#include +#include + +namespace luabridge { +namespace detail { +inline void putIndent(std::ostream& stream, unsigned level) +{ + for (unsigned i = 0; i < level; ++i) + stream << " "; +} +} // namespace detail + +//================================================================================================= +/** + * @brief Forward for dumpTable. + */ +inline void dumpTable(lua_State* L, int index, unsigned maxDepth = 1, unsigned level = 0, bool newLine = true, std::ostream& stream = std::cerr); + +//================================================================================================= +/** + * @brief Dump a lua value on the stack. + */ +inline void dumpValue(lua_State* L, int index, unsigned maxDepth = 1, unsigned level = 0, bool newLine = true, std::ostream& stream = std::cerr) +{ + const int stackTop = lua_gettop(L); + const int absIndex = (index > 0) ? index : (index < 0 ? stackTop + index + 1 : 0); + const int type = (absIndex < 1 || absIndex > stackTop) ? LUA_TNONE : lua_type(L, index); + switch (type) + { + case LUA_TNIL: + stream << "nil"; + break; + + case LUA_TBOOLEAN: + stream << (lua_toboolean(L, index) ? "true" : "false"); + break; + + case LUA_TNUMBER: + stream << lua_tonumber(L, index); + break; + + case LUA_TSTRING: + stream << '"' << lua_tostring(L, index) << '"'; + break; + + case LUA_TFUNCTION: + if (lua_iscfunction(L, index)) + stream << "cfunction@" << lua_topointer(L, index); + else + stream << "function@" << lua_topointer(L, index); + break; + + case LUA_TTHREAD: + stream << "thread@" << lua_tothread(L, index); + break; + + case LUA_TLIGHTUSERDATA: + stream << "lightuserdata@" << lua_touserdata(L, index); + break; + + case LUA_TTABLE: + dumpTable(L, index, maxDepth, level, false, stream); + break; + + case LUA_TUSERDATA: + stream << "userdata@" << lua_touserdata(L, index); + break; + + default: + stream << lua_typename(L, type); + break; + } + + if (newLine) + stream << '\n'; +} + +//================================================================================================= +/** + * @brief Dump a lua table on the stack. + */ +inline void dumpTable(lua_State* L, int index, unsigned maxDepth, unsigned level, bool newLine, std::ostream& stream) +{ + stream << "table@" << lua_topointer(L, index); + + if (level > maxDepth) + { + if (newLine) + stream << '\n'; + + return; + } + + index = lua_absindex(L, index); + + stream << " {"; + + int valuesCount = 0; + + lua_pushnil(L); // Initial key + while (lua_next(L, index)) + { + stream << '\n'; + detail::putIndent(stream, level + 1); + + dumpValue(L, -2, maxDepth, level + 1, false, stream); // Key + stream << ": "; + dumpValue(L, -1, maxDepth, level + 1, false, stream); // Value + stream << ","; + + lua_pop(L, 1); // Value + + ++valuesCount; + } + + if (valuesCount > 0) + { + stream << '\n'; + detail::putIndent(stream, level); + } + + stream << "}"; + + if (newLine) + stream << '\n'; +} + +//================================================================================================= +/** + * @brief Dump the current stack, optionally recursively. + */ +inline void dumpState(lua_State* L, unsigned maxDepth = 1, std::ostream& stream = std::cerr) +{ + stream << "----------------------------------------------" << '\n'; + + int top = lua_gettop(L); + for (int i = 1; i <= top; ++i) + { + stream << "stack #" << i << " (" << -(top - i + 1) << "): "; + + dumpValue(L, i, maxDepth, 0, true, stream); + } +} + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/FlatMap.h b/external/include/LuaBridge3/LuaBridge/FlatMap.h new file mode 100644 index 0000000000..6c8d507a5c --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/FlatMap.h @@ -0,0 +1,89 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#if LUABRIDGE_HAS_CXX23_FLAT_MAP + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::flat_map`. + */ +template +struct Stack> +{ + using Type = std::flat_map; + + [[nodiscard]] static Result push(lua_State* L, const Type& map) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, 0, static_cast(map.size())); + + for (auto it = map.begin(); it != map.end(); ++it) + { + auto result = Stack::push(L, it->first); + if (! result) + return result; + + result = Stack::push(L, it->second); + if (! result) + return result; + + lua_settable(L, -3); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type map; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto value = Stack::get(L, -1); + if (! value) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + auto key = Stack::get(L, -2); + if (! key) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + map.emplace(*key, *value); + lua_pop(L, 1); + } + + return map; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge + +#endif // LUABRIDGE_HAS_CXX23_FLAT_MAP diff --git a/external/include/LuaBridge3/LuaBridge/FlatSet.h b/external/include/LuaBridge3/LuaBridge/FlatSet.h new file mode 100644 index 0000000000..44db824e40 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/FlatSet.h @@ -0,0 +1,84 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#if LUABRIDGE_HAS_CXX23_FLAT_SET + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::flat_set`. + */ +template +struct Stack> +{ + using Type = std::flat_set; + + [[nodiscard]] static Result push(lua_State* L, const Type& set) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, 0, static_cast(set.size())); + + auto it = set.cbegin(); + for (lua_Integer tableIndex = 1; it != set.cend(); ++tableIndex, ++it) + { + lua_pushinteger(L, tableIndex); + + auto result = Stack::push(L, *it); + if (! result) + return result; + + lua_settable(L, -3); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type set; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto item = Stack::get(L, -1); + if (! item) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + set.emplace(*item); + lua_pop(L, 1); + } + + return set; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge + +#endif // LUABRIDGE_HAS_CXX23_FLAT_SET diff --git a/external/include/LuaBridge3/LuaBridge/ForwardList.h b/external/include/LuaBridge3/LuaBridge/ForwardList.h new file mode 100644 index 0000000000..e14019da44 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/ForwardList.h @@ -0,0 +1,82 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2026, kunitoki +// Copyright 2020, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::forward_list`. + */ +template +struct Stack> +{ + using Type = std::forward_list; + + [[nodiscard]] static Result push(lua_State* L, const Type& list) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, 0, 0); + + auto it = list.cbegin(); + for (std::size_t tableIndex = 1; it != list.cend(); ++tableIndex, ++it) + { + lua_pushinteger(L, static_cast(tableIndex)); + + auto result = Stack::push(L, *it); + if (! result) + return result; + + lua_settable(L, -3); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type list; + auto insertPos = list.before_begin(); + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto item = Stack::get(L, -1); + if (! item) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + insertPos = list.insert_after(insertPos, *item); + lua_pop(L, 1); + } + + return list; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/List.h b/external/include/LuaBridge3/LuaBridge/List.h new file mode 100644 index 0000000000..649783e277 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/List.h @@ -0,0 +1,80 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2020, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::array`. + */ +template +struct Stack> +{ + using Type = std::list; + + [[nodiscard]] static Result push(lua_State* L, const Type& list) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, static_cast(list.size()), 0); + const int tableIndex = lua_gettop(L); + + auto it = list.cbegin(); + for (std::size_t i = 1; it != list.cend(); ++i, ++it) + { + auto result = Stack::push(L, *it); + if (! result) + return result; + + lua_rawseti(L, tableIndex, static_cast(i)); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type list; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto item = Stack::get(L, -1); + if (! item) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + list.emplace_back(*item); + lua_pop(L, 1); + } + + return list; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/LuaBridge.h b/external/include/LuaBridge3/LuaBridge/LuaBridge.h new file mode 100644 index 0000000000..ede78604ca --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/LuaBridge.h @@ -0,0 +1,40 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2020, Dmitry Tarakanov +// Copyright 2012, Vinnie Falco +// Copyright 2007, Nathan Reed +// SPDX-License-Identifier: MIT + +#pragma once + +// All #include dependencies are listed here +// instead of in the individual header files. + +#define LUABRIDGE_MAJOR_VERSION 3 +#define LUABRIDGE_MINOR_VERSION 1 +#define LUABRIDGE_VERSION 301 + +#include "detail/Config.h" + +#include "detail/CFunctions.h" +#include "detail/ClassInfo.h" +#include "detail/Coroutine.h" +#include "detail/Enum.h" +#include "detail/Errors.h" +#include "detail/Expected.h" +#include "detail/FlagSet.h" +#include "detail/FuncTraits.h" +#include "detail/Globals.h" +#include "detail/Invoke.h" +#include "detail/Iterator.h" +#include "detail/LuaException.h" +#include "detail/LuaHelpers.h" +#include "detail/LuaRef.h" +#include "detail/Namespace.h" +#include "detail/Options.h" +#include "detail/Overload.h" +#include "detail/Result.h" +#include "detail/ScopeGuard.h" +#include "detail/Stack.h" +#include "detail/TypeTraits.h" +#include "detail/Userdata.h" diff --git a/external/include/LuaBridge3/LuaBridge/Map.h b/external/include/LuaBridge3/LuaBridge/Map.h new file mode 100644 index 0000000000..e4ac42dec5 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/Map.h @@ -0,0 +1,86 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2018, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::map`. + */ +template +struct Stack> +{ + using Type = std::map; + + [[nodiscard]] static Result push(lua_State* L, const Type& map) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, 0, static_cast(map.size())); + + for (auto it = map.begin(); it != map.end(); ++it) + { + auto result = Stack::push(L, it->first); + if (! result) + return result; + + result = Stack::push(L, it->second); + if (! result) + return result; + + lua_settable(L, -3); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type map; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto value = Stack::get(L, -1); + if (! value) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + auto key = Stack::get(L, -2); + if (! key) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + map.emplace(*key, *value); + lua_pop(L, 1); + } + + return map; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/MultiMap.h b/external/include/LuaBridge3/LuaBridge/MultiMap.h new file mode 100644 index 0000000000..0c6b37a828 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/MultiMap.h @@ -0,0 +1,107 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2026, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::multimap`. + */ +template +struct Stack> +{ + using Type = std::multimap; + + [[nodiscard]] static Result push(lua_State* L, const Type& map) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, 0, 0); + + auto it = map.begin(); + while (it != map.end()) + { + auto result = Stack::push(L, it->first); + if (! result) + return result; + + auto range = map.equal_range(it->first); + lua_createtable(L, static_cast(std::distance(range.first, range.second)), 0); + + int innerIndex = 1; + for (auto innerIt = range.first; innerIt != range.second; ++innerIt, ++innerIndex) + { + result = Stack::push(L, innerIt->second); + if (! result) + return result; + + lua_rawseti(L, -2, innerIndex); + } + + lua_settable(L, -3); + it = range.second; + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (! lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type map; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto key = Stack::get(L, -2); + if (! key) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + if (! lua_istable(L, -1)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + int innerAbsIndex = lua_absindex(L, -1); + lua_pushnil(L); + + while (lua_next(L, innerAbsIndex) != 0) + { + auto value = Stack::get(L, -1); + if (! value) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + map.emplace(*key, *value); + lua_pop(L, 1); + } + + lua_pop(L, 1); + } + + return map; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/Set.h b/external/include/LuaBridge3/LuaBridge/Set.h new file mode 100644 index 0000000000..ccb92d7ba7 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/Set.h @@ -0,0 +1,80 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::set`. + */ +template +struct Stack> +{ + using Type = std::set; + + [[nodiscard]] static Result push(lua_State* L, const Type& set) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, 0, static_cast(set.size())); + + auto it = set.cbegin(); + for (lua_Integer tableIndex = 1; it != set.cend(); ++tableIndex, ++it) + { + lua_pushinteger(L, tableIndex); + + auto result = Stack::push(L, *it); + if (! result) + return result; + + lua_settable(L, -3); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type set; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto item = Stack::get(L, -1); + if (! item) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + set.emplace(*item); + lua_pop(L, 1); + } + + return set; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/Span.h b/external/include/LuaBridge3/LuaBridge/Span.h new file mode 100644 index 0000000000..5db44cf35e --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/Span.h @@ -0,0 +1,66 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2026, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#if LUABRIDGE_HAS_CXX20_SPAN + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::span` (push-only). + */ +template +struct Stack> +{ + using Type = std::span; + + [[nodiscard]] static Result push(lua_State* L, Type span) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, static_cast(span.size()), 0); + const int tableIndex = lua_gettop(L); + + int i = 1; + for (const auto& element : span) + { + auto result = Stack>::push(L, element); + if (! result) + return result; + + lua_rawseti(L, tableIndex, i++); + } + + stackRestore.reset(); + return {}; + } + + template + [[nodiscard]] static TypeResult get(lua_State*, int) + { + static_assert(sizeof(U) == 0, + "std::span cannot be retrieved from Lua — use std::vector to retrieve sequences from Lua"); + return makeErrorCode(ErrorCode::InvalidTypeCast); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge + +#endif // LUABRIDGE_HAS_CXX20_SPAN diff --git a/external/include/LuaBridge3/LuaBridge/StdExpected.h b/external/include/LuaBridge3/LuaBridge/StdExpected.h new file mode 100644 index 0000000000..2eb1f9ece6 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/StdExpected.h @@ -0,0 +1,69 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#if LUABRIDGE_HAS_CXX23_EXPECTED + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::expected` (C++23). + */ +template +struct Stack> +{ + using Type = std::expected; + + [[nodiscard]] static Result push(lua_State* L, const Type& value) + { + if (value.has_value()) + { + StackRestore stackRestore(L); + + auto result = Stack::push(L, *value); + if (! result) + return result; + + stackRestore.reset(); + return {}; + } + +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushnil(L); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + const auto type = lua_type(L, index); + if (type == LUA_TNIL || type == LUA_TNONE) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + auto result = Stack::get(L, index); + if (! result) + return result.error(); + + return Type(*result); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + const auto type = lua_type(L, index); + return (type != LUA_TNIL && type != LUA_TNONE) && Stack::isInstance(L, index); + } +}; + +} // namespace luabridge + +#endif // LUABRIDGE_HAS_CXX23_EXPECTED diff --git a/external/include/LuaBridge3/LuaBridge/UnorderedMap.h b/external/include/LuaBridge3/LuaBridge/UnorderedMap.h new file mode 100644 index 0000000000..cef355ca58 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/UnorderedMap.h @@ -0,0 +1,86 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2019, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::unordered_map`. + */ +template +struct Stack> +{ + using Type = std::unordered_map; + + [[nodiscard]] static Result push(lua_State* L, const Type& map) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, 0, static_cast(map.size())); + + for (auto it = map.begin(); it != map.end(); ++it) + { + auto result = Stack::push(L, it->first); + if (! result) + return result; + + result = Stack::push(L, it->second); + if (! result) + return result; + + lua_settable(L, -3); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type map; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto value = Stack::get(L, -1); + if (! value) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + auto key = Stack::get(L, -2); + if (! key) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + map.emplace(*key, *value); + lua_pop(L, 1); + } + + return map; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/UnorderedMultiMap.h b/external/include/LuaBridge3/LuaBridge/UnorderedMultiMap.h new file mode 100644 index 0000000000..cabcc8b272 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/UnorderedMultiMap.h @@ -0,0 +1,107 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2026, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::unordered_multimap`. + */ +template +struct Stack> +{ + using Type = std::unordered_multimap; + + [[nodiscard]] static Result push(lua_State* L, const Type& map) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, 0, 0); + + auto it = map.begin(); + while (it != map.end()) + { + auto result = Stack::push(L, it->first); + if (! result) + return result; + + auto range = map.equal_range(it->first); + lua_createtable(L, static_cast(std::distance(range.first, range.second)), 0); + + int innerIndex = 1; + for (auto innerIt = range.first; innerIt != range.second; ++innerIt, ++innerIndex) + { + result = Stack::push(L, innerIt->second); + if (! result) + return result; + + lua_rawseti(L, -2, innerIndex); + } + + lua_settable(L, -3); + it = range.second; + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (! lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type map; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto key = Stack::get(L, -2); + if (! key) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + if (! lua_istable(L, -1)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + int innerAbsIndex = lua_absindex(L, -1); + lua_pushnil(L); + + while (lua_next(L, innerAbsIndex) != 0) + { + auto value = Stack::get(L, -1); + if (! value) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + map.emplace(*key, *value); + lua_pop(L, 1); + } + + lua_pop(L, 1); + } + + return map; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/UnorderedSet.h b/external/include/LuaBridge3/LuaBridge/UnorderedSet.h new file mode 100644 index 0000000000..c7cadd4624 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/UnorderedSet.h @@ -0,0 +1,80 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2026, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::unordered_set`. + */ +template +struct Stack> +{ + using Type = std::unordered_set; + + [[nodiscard]] static Result push(lua_State* L, const Type& set) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, 0, static_cast(set.size())); + + auto it = set.cbegin(); + for (lua_Integer tableIndex = 1; it != set.cend(); ++tableIndex, ++it) + { + lua_pushinteger(L, tableIndex); + + auto result = Stack::push(L, *it); + if (! result) + return result; + + lua_settable(L, -3); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type set; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto item = Stack::get(L, -1); + if (! item) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + set.emplace(*item); + lua_pop(L, 1); + } + + return set; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/Variant.h b/external/include/LuaBridge3/LuaBridge/Variant.h new file mode 100644 index 0000000000..dbc279e9b1 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/Variant.h @@ -0,0 +1,94 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2026, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::variant`. + */ +template +struct Stack> +{ + using Type = std::variant; + + [[nodiscard]] static Result push(lua_State* L, const Type& variant) + { + return std::visit([L](const auto& value) { return Stack>::push(L, value); }, variant); + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + return tryGet(L, index); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return (Stack::isInstance(L, index) || ...); + } + +private: + template + [[nodiscard]] static TypeResult tryGet(lua_State* L, int index) + { + if (auto value = Stack::get(L, index)) + { +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + return Type{ std::in_place_type, std::move(*value) }; +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic pop +#endif + } + + if constexpr (sizeof...(Rest) > 0) + return tryGet(L, index); + + return makeErrorCode(ErrorCode::InvalidTypeCast); + } +}; + +/** + * @brief Stack specialization for `std::monostate`. + */ +template <> +struct Stack +{ + using Type = std::monostate; + + [[nodiscard]] static Result push(lua_State* L, const Type&) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushnil(L); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_isnoneornil(L, index)) + return Type{}; + + return makeErrorCode(ErrorCode::InvalidTypeCast); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_isnoneornil(L, index); + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/Vector.h b/external/include/LuaBridge3/LuaBridge/Vector.h new file mode 100644 index 0000000000..c5d94d68b7 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/Vector.h @@ -0,0 +1,80 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2018, Dmitry Tarakanov +// SPDX-License-Identifier: MIT + +#pragma once + +#include "detail/Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack specialization for `std::vector`. + */ +template +struct Stack> +{ + using Type = std::vector; + + [[nodiscard]] static Result push(lua_State* L, const Type& vector) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, static_cast(vector.size()), 0); + const int tableIndex = lua_gettop(L); + + for (std::size_t i = 0; i < vector.size(); ++i) + { + auto result = Stack::push(L, vector[i]); + if (! result) + return result; + + lua_rawseti(L, tableIndex, static_cast(i + 1)); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + const StackRestore stackRestore(L); + + Type vector; + vector.reserve(static_cast(get_length(L, index))); + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + while (lua_next(L, absIndex) != 0) + { + auto item = Stack::get(L, -1); + if (! item) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + vector.emplace_back(*item); + lua_pop(L, 1); + } + + return vector; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_istable(L, index); + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/CFunctions.h b/external/include/LuaBridge3/LuaBridge/detail/CFunctions.h new file mode 100644 index 0000000000..83618e52ab --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/CFunctions.h @@ -0,0 +1,3328 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2019, Dmitry Tarakanov +// Copyright 2012, Vinnie Falco +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" +#include "ClassInfo.h" +#include "Errors.h" +#include "FuncTraits.h" +#include "LuaHelpers.h" +#include "Options.h" +#include "Stack.h" +#include "TypeTraits.h" +#include "Userdata.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace luabridge { + +class LuaRef; + +namespace detail { + +//================================================================================================= +/** + * @brief Extract exactly what Stack::get() produces. + * + * Allows that implicit conversions (e.g. std::reference_wrapper → T&) happen correctly at the call site. + */ +template +using stack_value_t = remove_cvref_t< + decltype(*std::declval::get(std::declval(), 0))>())>; + +//================================================================================================= +/** + * @brief Trivially-destructible storage for one decoded function argument. + * + * Longjmp-safe: the raw byte array and the construction flag are trivially + * destructible, so raise_lua_error (longjmp) while ArgStorage objects sit on + * the C++ stack does not skip any live C++ destructor. The contained T must + * be managed explicitly via construct/destroy. + */ +template +struct ArgStorage +{ + using StoredType = stack_value_t; + + alignas(StoredType) std::byte data[sizeof(StoredType)]; + bool constructed = false; + + StoredType* ptr() noexcept { return std::launder(reinterpret_cast(data)); } + + void destroy() noexcept + { + if (constructed) + { + std::destroy_at(ptr()); + constructed = false; + } + } +}; + +//================================================================================================= +/** + * @brief Decode one argument from the Lua stack into storage element I. + * + * Sets error_arg/error_msg on the first failure; subsequent calls are no-ops. + */ +template +void decode_arg(lua_State* L, StorageTuple& storage, int& error_arg, const char*& error_msg) +{ + using T = std::tuple_element_t; + using StoredType = typename std::tuple_element_t::StoredType; + + if (error_arg) + return; + + auto result = Stack::get(L, static_cast(I + Start)); + if (! result) + { + error_arg = static_cast(I + 1); + error_msg = result.error_cstr(); + return; + } + + ::new (std::get(storage).data) StoredType(std::move(*result)); + std::get(storage).constructed = true; +} + +//================================================================================================= +/** + * @brief Make argument lists extracting them from the lua state, starting at a stack index. + * + * Arguments are decoded sequentially left to right. On failure every already- + * constructed argument is explicitly destroyed before raise_lua_error is called, + * so longjmp never skips a live C++ destructor. + * + * @tparam ArgsPack Arguments pack to extract from the lua stack. + * @tparam Start Start index where stack variables are located in the lua stack. + */ +template +auto make_arguments_list_impl([[maybe_unused]] lua_State* L, std::index_sequence) +{ + std::tuple>...> storage; + + int error_arg = 0; + const char* error_msg = nullptr; + + (decode_arg(L, storage, error_arg, error_msg), ...); + + if (error_arg) + { + (std::get(storage).destroy(), ...); + raise_lua_error(L, "Error decoding argument #%d: %s", error_arg, error_msg); + } + + auto result = tupleize(std::move(*std::get(storage).ptr())...); + (std::get(storage).destroy(), ...); + return result; +} + +template +auto make_arguments_list(lua_State* L) +{ + return make_arguments_list_impl(L, std::make_index_sequence>()); +} + +//================================================================================================= +/** + * @brief Helpers for iterating through tuple arguments, pushing each argument to the lua stack. + */ +template +auto push_arguments(lua_State*, std::tuple) + -> std::enable_if_t> +{ + return std::make_tuple(Result(), Index + 1); +} + +template +auto push_arguments(lua_State* L, std::tuple t) + -> std::enable_if_t> +{ + using T = std::tuple_element_t>; + + auto result = Stack::push(L, std::get(t)); + if (! result) + return std::make_tuple(result, Index + 1); + + return push_arguments(L, std::move(t)); +} + +//================================================================================================= +/** + * @brief Helpers for iterating through tuple arguments, popping each argument from the lua stack. + */ +template +auto pop_arguments(lua_State*, std::tuple&) + -> std::enable_if_t +{ + return sizeof...(Types); +} + +template +auto pop_arguments(lua_State* L, std::tuple& t) + -> std::enable_if_t +{ + using T = std::tuple_element_t>; + + std::get(t) = Stack::get(L, Start - Index); + + return pop_arguments(L, t); +} + +//================================================================================================= +/** + * @brief Push a tuple on the stack. + */ +template +Result push_tuple_impl(lua_State* L, const Tuple& value, std::index_sequence) +{ + Result result; + (void)((result = Stack>>::push(L, std::get(value)), bool(result)) && ...); + return result; +} + +template +Result push_tuple(lua_State* L, const std::tuple& value) +{ + return push_tuple_impl(L, value, std::index_sequence_for{}); +} + +//================================================================================================= +/** + * @brief Check if a method name is a metamethod. + */ +template +constexpr auto make_array(Args&&... args) +{ + if constexpr (std::is_same_v) + return std::array...>, sizeof...(Args)>{{ std::forward(args)... }}; + else + return std::array{{ std::forward(args)... }}; +} + +inline bool is_metamethod(std::string_view method_name) +{ + static constexpr auto metamethods = make_array( + "__add", + "__band", + "__bnot", + "__bor", + "__bxor", + "__call", + "__close", + "__concat", + "__div", + "__eq", + "__gc", + "__idiv", + "__index", + "__ipairs", + "__le", + "__len", + "__lt", + "__metatable", + "__mod", + "__mode", + "__mul", + "__name", + "__newindex", + "__pairs", + "__pow", + "__shl", + "__shr", + "__sub", + "__tostring", + "__unm" + ); + + if (method_name.size() <= 2 || method_name[0] != '_' || method_name[1] != '_') + return false; + + auto result = std::lower_bound(metamethods.begin(), metamethods.end(), method_name); + return result != metamethods.end() && *result == method_name; +} + +/** + * @brief Check if a method name is a binary operator metamethod. + */ +inline bool is_binary_operator_metamethod(std::string_view method_name) +{ + static constexpr auto metamethods = make_array( + "__add", + "__band", + "__bor", + "__bxor", + "__concat", + "__div", + "__eq", + "__idiv", + "__le", + "__lt", + "__mod", + "__mul", + "__pow", + "__shl", + "__shr", + "__sub" + ); + + if (method_name.size() <= 2 || method_name[0] != '_' || method_name[1] != '_') + return false; + + auto result = std::lower_bound(metamethods.begin(), metamethods.end(), method_name); + return result != metamethods.end() && *result == method_name; +} + +/** + * @brief Get the key at the given stack index as a string, only if it is a string. + * + * Unlike lua_tostring, a number key is not converted in place, so the original key type is preserved for metamethods. + */ +inline const char* get_string_key(lua_State* L, int index) +{ + return lua_type(L, index) == LUA_TSTRING ? lua_tostring(L, index) : nullptr; +} + +/** + * @brief Get a printable name for the key at the given stack index, for error reporting only. + * + * May push a value onto the stack. + */ +inline const char* get_key_name_for_error(lua_State* L, int index) +{ + index = lua_absindex(L, index); + + switch (lua_type(L, index)) + { + case LUA_TSTRING: + return lua_tostring(L, index); + + case LUA_TNUMBER: + lua_pushvalue(L, index); + return lua_tostring(L, -1); + + default: + return lua_typename(L, lua_type(L, index)); + } +} + +inline void rawset_super_method(lua_State* L, int tableIndex, const char* key) +{ + LUABRIDGE_ASSERT(key != nullptr); + + tableIndex = lua_absindex(L, tableIndex); + + // Stack before: ..., value + if (key[0] == '_') + lua_pushliteral(L, "super"); // Stack: ..., value, "super" + else + lua_pushliteral(L, "super_"); // Stack: ..., value, "super_" + + lua_pushstring(L, key); // Stack: ..., value, prefix, key + lua_concat(L, 2); // Stack: ..., value, super_key + lua_insert(L, -2); // Stack: ..., super_key, value + lua_rawset(L, tableIndex); // Pops key/value. Stack: ... +} + +//================================================================================================= +/** + * @brief Make super method name. + */ +inline Options get_class_options(lua_State* L, int index) +{ + LUABRIDGE_ASSERT(lua_istable(L, index)); // Stack: mt + + Options options = defaultOptions; + + lua_rawgetp_x(L, index, getClassOptionsKey()); // Stack: mt, ifb (may be nil) + if (lua_isnumber(L, -1)) + options = Options::fromUnderlying(lua_tointeger(L, -1)); + + lua_pop(L, 1); + + return options; +} + +//================================================================================================= +/** + * @brief Push class or const table onto stack. + */ +inline void push_class_or_const_table(lua_State* L, int index) +{ + LUABRIDGE_ASSERT(lua_istable(L, index)); // Stack: mt + + lua_rawgetp_x(L, index, getClassKey()); // Stack: mt, class table (ct) | nil + if (! lua_istable(L, -1)) // Stack: mt, nil + { + lua_pop(L, 1); // Stack: mt + + lua_rawgetp_x(L, index, getConstKey()); // Stack: mt, const table (co) | nil + if (! lua_istable(L, -1)) // Stack: mt, nil + return; + } +} + +//================================================================================================= +/** + * @brief Look up a static function or property through an object's class metatable. + */ +inline std::optional try_call_instance_static_index(lua_State* L, int classMetatableIndex) +{ + lua_rawgetp_x(L, classMetatableIndex, getStaticKey()); // Stack: ..., static table (st) | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); + return std::nullopt; + } + + lua_pushvalue(L, 2); // Stack: ..., st, field name + lua_rawget(L, -2); // Stack: ..., st, value | nil + if (! lua_isnil(L, -1)) + { + lua_remove(L, -2); // Stack: ..., value + return 1; + } + + lua_pop(L, 1); // Stack: ..., st + lua_rawgetp_x(L, -1, getPropgetKey()); // Stack: ..., st, propget table (pg) | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 2); + return std::nullopt; + } + + lua_pushvalue(L, 2); // Stack: ..., st, pg, field name + lua_rawget(L, -2); // Stack: ..., st, pg, getter | nil + if (! lua_iscfunction(L, -1)) + { + lua_pop(L, 3); + return std::nullopt; + } + + lua_remove(L, -2); // Stack: ..., st, getter + lua_remove(L, -2); // Stack: ..., getter + lua_call(L, 0, 1); // Stack: ..., value + return 1; +} + +/** + * @brief Call a static property setter through an object's class metatable. + */ +inline std::optional try_call_instance_static_newindex(lua_State* L, int classMetatableIndex) +{ + lua_rawgetp_x(L, classMetatableIndex, getStaticKey()); // Stack: ..., static table (st) | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); + return std::nullopt; + } + + lua_rawgetp_x(L, -1, getPropsetKey()); // Stack: ..., st, propset table (ps) | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 2); + return std::nullopt; + } + + lua_pushvalue(L, 2); // Stack: ..., st, ps, field name + lua_rawget(L, -2); // Stack: ..., st, ps, setter | nil + if (! lua_iscfunction(L, -1)) + { + lua_pop(L, 3); + return std::nullopt; + } + + lua_remove(L, -2); // Stack: ..., st, setter + lua_remove(L, -2); // Stack: ..., setter + lua_pushvalue(L, 3); // Stack: ..., setter, new value + lua_call(L, 1, 0); + return 0; +} + +//================================================================================================= +/** + * @brief __index metamethod for a namespace or class static and non-static members. + * + * Retrieves functions from metatables and properties from propget tables. Looks through the class hierarchy if inheritance is present. + */ + +inline std::optional try_call_index_fallback(lua_State* L) +{ + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: mt + + lua_rawgetp_x(L, -1, getIndexFallbackKey()); // Stack: mt, ifb (may be nil) + if (! lua_iscfunction(L, -1)) + { + lua_pop(L, 1); // Stack: mt + return std::nullopt; + } + + lua_pushvalue(L, 1); // Stack: mt, ifb, arg1 + lua_pushvalue(L, 2); // Stack: mt, ifb, arg1, arg2 + lua_call(L, 2, 1); // Stack: mt, ifbresult + + if (! lua_isnoneornil(L, -1)) + { + lua_remove(L, -2); // Stack: ifbresult + return 1; + } + + lua_pop(L, 1); // Stack: mt + return std::nullopt; +} + +inline std::optional try_call_static_index_fallback(lua_State* L) +{ + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: mt + + lua_rawgetp_x(L, -1, getStaticIndexFallbackKey()); // Stack: mt, ifb (may be nil) + if (! lua_iscfunction(L, -1)) + { + lua_pop(L, 1); // Stack: mt + return std::nullopt; + } + + lua_pushvalue(L, 2); // Stack: mt, ifb, arg1 (key only, no self for static) + lua_call(L, 1, 1); // Stack: mt, ifbresult + + if (! lua_isnoneornil(L, -1)) + { + lua_remove(L, -2); // Stack: ifbresult + return 1; + } + + lua_pop(L, 1); // Stack: mt + return std::nullopt; +} + +template +inline std::optional try_call_index_extensible(lua_State* L) +{ + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: mt + + if constexpr (IsObject) + push_class_or_const_table(L, -1); // Stack: mt, cl | co + else + lua_rawgetp_x(L, -1, getStaticKey()); // Stack: mt, st + + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: mt, cl | co | st + lua_pushvalue(L, 2); // Stack: mt, cl | co | st, field name + lua_rawget(L, -2); // Stack: mt, cl | co | st, ifbresult | nil + + if (! lua_isnoneornil(L, -1)) // Stack: mt, cl | co | st, ifbresult + { + lua_remove(L, -2); // Stack: mt, ifbresult + lua_remove(L, -2); // Stack: ifbresult + return 1; + } + + lua_pop(L, 2); // Stack: mt + return std::nullopt; +} + +/** + * @brief Scan the flattened parent list for an extensible class getter. + * + * Only extensible checks are performed; __index fallbacks are intentionally ignored so that a + * registered getter anywhere in the hierarchy always takes priority over any fallback. + */ +template +inline std::optional try_call_parent_index_extensibles(lua_State* L) +{ + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: mt + + lua_rawgetp_x(L, -1, getParentKey()); // Stack: mt, parent list | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); // Stack: mt + return std::nullopt; + } + + const int parentListIndex = lua_absindex(L, -1); + const int parentCount = get_length(L, parentListIndex); + + for (int i = 1; i <= parentCount; ++i) + { + lua_rawgeti(L, parentListIndex, i); // Stack: mt, parent list, parent mt + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); + continue; + } + + const Options parentOptions = get_class_options(L, -1); // Stack: mt, parent list, parent mt + if (parentOptions.test(extensibleClass | ~allowOverridingMethods)) + { + if (auto result = try_call_index_extensible(L)) + { + lua_remove(L, -2); // Stack: mt, result + lua_remove(L, -2); // Stack: result + return *result; + } + } + + lua_pop(L, 1); // Stack: mt, parent list + } + + lua_pop(L, 1); // Stack: mt + return std::nullopt; +} + +/** + * @brief Scan the flattened parent list for a __index fallback. + * + * Only fallbacks are checked; extensible getters are intentionally ignored because they + * have already been searched by try_call_parent_index_extensibles. + */ +template +inline std::optional try_call_parent_index_fallbacks(lua_State* L) +{ + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: mt + + lua_rawgetp_x(L, -1, getParentKey()); // Stack: mt, parent list | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); // Stack: mt + return std::nullopt; + } + + const int parentListIndex = lua_absindex(L, -1); + const int parentCount = get_length(L, parentListIndex); + + for (int i = 1; i <= parentCount; ++i) + { + lua_rawgeti(L, parentListIndex, i); // Stack: mt, parent list, parent mt + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); + continue; + } + + lua_rawgetp_x(L, -1, getIndexFallbackKey()); // Stack: mt, parent list, parent mt, ifb | nil + if (lua_iscfunction(L, -1)) + { + lua_pushvalue(L, 1); // Stack: mt, parent list, parent mt, ifb, arg1 + lua_pushvalue(L, 2); // Stack: mt, parent list, parent mt, ifb, arg1, arg2 + lua_call(L, 2, 1); // Stack: mt, parent list, parent mt, result + + if (! lua_isnoneornil(L, -1)) + { + lua_remove(L, -2); // Stack: mt, parent list, result + lua_remove(L, -2); // Stack: mt, result + lua_remove(L, -2); // Stack: result + return 1; + } + + lua_pop(L, 1); // Stack: mt, parent list, parent mt + } + else + { + lua_pop(L, 1); // Stack: mt, parent list, parent mt + } + + lua_pop(L, 1); // Stack: mt, parent list + } + + lua_pop(L, 1); // Stack: mt + return std::nullopt; +} + +template +inline int index_metamethod(lua_State* L) +{ +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(L, 6, detail::error_lua_stack_overflow); +#endif + + LUABRIDGE_ASSERT(lua_istable(L, 1) || lua_isuserdata(L, 1)); // Stack (further not shown): table | userdata, name + + lua_getmetatable(L, 1); // Stack: class/const table (mt) + LUABRIDGE_ASSERT(lua_istable(L, -1)); + + // Protect internal meta methods + const char* key = get_string_key(L, 2); + if (key != nullptr && is_metamethod(key)) + { + lua_pushnil(L); + return 1; + } + + for (;;) + { + const Options options = get_class_options(L, -1); // Stack: mt + + // For static __index: the static fallback takes priority over registered static + // property getters so that a user-defined static __index fallback can shadow + // static properties. + // For instance __index with allowOverridingMethods: the instance fallback takes + // priority over class-table Lua methods, enabling Lua-side method overrides via + // __newindex. + if constexpr (IsObject) + { + if (options.test(extensibleClass | allowOverridingMethods)) + { + if (auto result = try_call_index_fallback(L)) + return *result; + } + } + else + { + if (auto result = try_call_static_index_fallback(L)) + return *result; + } + + // Search into self or metatable + if (lua_istable(L, 1)) + { + if constexpr (IsObject) + lua_pushvalue(L, 1); // Stack: mt, self + else + push_class_or_const_table(L, -1); // Stack: mt, cl | co + + if (lua_istable(L, -1)) + { + lua_pushvalue(L, 2); // Stack: mt, self | cl | co, field name + lua_rawget(L, -2); // Stack: mt, self | cl | co, field | nil + lua_remove(L, -2); // Stack: mt, field | nil + if (! lua_isnil(L, -1)) // Stack: mt, field + { + lua_remove(L, -2); // Stack: field + return 1; + } + } + + lua_pop(L, 1); // Stack: mt + } + + lua_pushvalue(L, 2); // Stack: mt, field name + lua_rawget(L, -2); // Stack: mt, field | nil + if (! lua_isnil(L, -1)) // Stack: mt, field + { + lua_remove(L, -2); // Stack: field + return 1; + } + + LUABRIDGE_ASSERT(lua_isnil(L, -1)); // Stack: mt, nil + lua_pop(L, 1); // Stack: mt + + // Repeat the lookup in the index extensible, for method overrides + if (options.test(extensibleClass | allowOverridingMethods)) + { + if (auto result = try_call_index_extensible(L)) + return *result; + } + + // Try in the propget key + lua_rawgetp_x(L, -1, getPropgetKey()); // Stack: mt, propget table (pg) + LUABRIDGE_ASSERT(lua_istable(L, -1)); + + lua_pushvalue(L, 2); // Stack: mt, pg, field name + lua_rawget(L, -2); // Stack: mt, pg, getter | nil + lua_remove(L, -2); // Stack: mt, getter | nil + + if (lua_iscfunction(L, -1)) // Stack: mt, getter + { + lua_remove(L, -2); // Stack: getter + lua_pushvalue(L, 1); // Stack: getter, table | userdata + lua_call(L, 1, 1); // Stack: value + return 1; + } + + LUABRIDGE_ASSERT(lua_isnil(L, -1)); // Stack: mt, nil + lua_pop(L, 1); // Stack: mt + + if constexpr (IsObject) + { + if (auto result = try_call_instance_static_index(L, -1)) + return *result; + } + + // It may mean that the field may be in const table and it's constness violation. + + // Search flattened parent list in declaration-order DFS. + lua_rawgetp_x(L, -1, getParentKey()); // Stack: mt, parent list | nil + + if (lua_istable(L, -1)) + { + const int parentListIndex = lua_absindex(L, -1); + const int parentCount = get_length(L, parentListIndex); + + for (int i = 1; i <= parentCount; ++i) + { + lua_rawgeti(L, parentListIndex, i); // Stack: mt, parent list, parent mt + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); + continue; + } + + lua_pushvalue(L, 2); // Stack: mt, parent list, parent mt, field name + lua_rawget(L, -2); // Stack: mt, parent list, parent mt, field | nil + if (! lua_isnil(L, -1)) + { + lua_remove(L, -2); // Stack: mt, parent list, field + lua_remove(L, -2); // Stack: mt, field + lua_remove(L, -2); // Stack: field + return 1; + } + lua_pop(L, 1); // Stack: mt, parent list, parent mt + + lua_rawgetp_x(L, -1, getPropgetKey()); // Stack: mt, parent list, parent mt, pg | nil + if (lua_istable(L, -1)) + { + lua_pushvalue(L, 2); // Stack: mt, parent list, parent mt, pg, field name + lua_rawget(L, -2); // Stack: mt, parent list, parent mt, pg, getter | nil + lua_remove(L, -2); // Stack: mt, parent list, parent mt, getter | nil + if (lua_iscfunction(L, -1)) + { + lua_remove(L, -2); // Stack: mt, parent list, getter + lua_remove(L, -2); // Stack: mt, getter + lua_remove(L, -2); // Stack: getter + lua_pushvalue(L, 1); // Stack: getter, table | userdata + lua_call(L, 1, 1); // Stack: value + return 1; + } + + lua_pop(L, 1); // Stack: mt, parent list, parent mt + } + else + { + lua_pop(L, 1); // Stack: mt, parent list, parent mt + } + + lua_pop(L, 1); // Stack: mt, parent list + } + } + + lua_pop(L, 2); // Stack: - + break; + } + + lua_getmetatable(L, 1); // Stack: class/const table (mt) + LUABRIDGE_ASSERT(lua_istable(L, -1)); + + const Options options = get_class_options(L, -1); // Stack: mt + if (options.test(extensibleClass | ~allowOverridingMethods)) + { + if (auto result = try_call_index_extensible(L)) + return *result; + } + + // Before consulting any __index fallback, scan the entire parent hierarchy for a + // matching extensible getter. This ensures that a registered getter anywhere in the + // inheritance chain always takes priority over a __index fallback defined at a + // narrower scope (e.g. an intermediate or leaf class). + if (auto result = try_call_parent_index_extensibles(L)) + return *result; + + if constexpr (IsObject) + { + if (auto result = try_call_index_fallback(L)) + return *result; + } + else + { + if (auto result = try_call_static_index_fallback(L)) + return *result; + } + + if (auto result = try_call_parent_index_fallbacks(L)) + return *result; + + lua_pop(L, 1); // Stack: - + lua_pushnil(L); + return 1; + + // no return +} + +template +inline int index_metamethod_simple(lua_State* L) +{ +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(L, 3, detail::error_lua_stack_overflow); +#endif + + LUABRIDGE_ASSERT(lua_istable(L, 1) || lua_isuserdata(L, 1)); + + // Fast path for simple userdata objects: when registration provides propget and + // method tables as closure upvalues, avoid metatable/pointer-key lookups. + if constexpr (IsObject) + { + if (lua_isuserdata(L, 1)) + { + const char* key = get_string_key(L, 2); + + const auto rawlookup = [L](int tableIndex) + { + lua_pushvalue(L, 2); + lua_rawget(L, tableIndex); + }; + + rawlookup(lua_upvalueindex(1)); // Stack: getter | nil + if (lua_iscfunction(L, -1)) + { + lua_pushvalue(L, 1); // Stack: getter, self + lua_call(L, 1, 1); // Stack: value + return 1; + } + + lua_pop(L, 1); + + if (key != nullptr && is_metamethod(key)) + { + lua_pushnil(L); + return 1; + } + + rawlookup(lua_upvalueindex(2)); // Stack: value | nil + if (! lua_isnil(L, -1)) + return 1; + + lua_pop(L, 1); + + if (auto result = try_call_instance_static_index(L, lua_upvalueindex(2))) + return *result; + + lua_pushnil(L); + return 1; + } + } + else + { + // Fast path for simple static tables: capture propget/class/metatable as upvalues. + if (lua_istable(L, 1)) + { + const char* key = get_string_key(L, 2); + + const auto rawlookup = [L](int tableIndex) + { + lua_pushvalue(L, 2); + lua_rawget(L, tableIndex); + }; + + if (key != nullptr && is_metamethod(key)) + { + lua_pushnil(L); + return 1; + } + + if (lua_istable(L, lua_upvalueindex(2))) + { + rawlookup(lua_upvalueindex(2)); // Stack: value | nil + if (! lua_isnil(L, -1)) + return 1; + + lua_pop(L, 1); + } + + rawlookup(lua_upvalueindex(3)); // Stack: value | nil + if (! lua_isnil(L, -1)) + return 1; + + lua_pop(L, 1); + + rawlookup(lua_upvalueindex(1)); // Stack: getter | nil + if (lua_iscfunction(L, -1)) + { + lua_pushvalue(L, 1); // Stack: getter, self + lua_call(L, 1, 1); // Stack: value + return 1; + } + + lua_pop(L, 1); + lua_pushnil(L); + return 1; + } + } + + lua_getmetatable(L, 1); // Stack: mt + LUABRIDGE_ASSERT(lua_istable(L, -1)); + + const char* key = get_string_key(L, 2); + + const auto rawlookup = [L]() + { + lua_pushvalue(L, 2); + lua_rawget(L, -2); + }; + + // For userdata instance property access, checking propget first avoids an always-miss lookup + // in the class table for common property keys. + if (lua_isuserdata(L, 1)) + { + lua_rawgetp_x(L, -1, getPropgetKey()); // Stack: mt, pg + LUABRIDGE_ASSERT(lua_istable(L, -1)); + + rawlookup(); // Stack: mt, pg, getter | nil + lua_remove(L, -2); // Stack: mt, getter | nil + + if (lua_iscfunction(L, -1)) + { + lua_remove(L, -2); // Stack: getter + lua_pushvalue(L, 1); // Stack: getter, self + lua_call(L, 1, 1); // Stack: value + return 1; + } + + lua_pop(L, 1); // Stack: mt + } + if (key != nullptr && is_metamethod(key)) + { + lua_pushnil(L); + return 1; + } + + if (lua_istable(L, 1)) + { + if constexpr (IsObject) + lua_pushvalue(L, 1); // Stack: mt, self + else + push_class_or_const_table(L, -1); // Stack: mt, cl | co + + if (lua_istable(L, -1)) + { + rawlookup(); // Stack: mt, self | cl | co, value | nil + lua_remove(L, -2); // Stack: mt, value | nil + if (! lua_isnil(L, -1)) + { + lua_remove(L, -2); // Stack: value + return 1; + } + } + + lua_pop(L, 1); // Stack: mt + } + + rawlookup(); // Stack: mt, value | nil + if (! lua_isnil(L, -1)) + { + lua_remove(L, -2); // Stack: value + return 1; + } + + lua_pop(L, 1); // Stack: mt + + lua_rawgetp_x(L, -1, getPropgetKey()); // Stack: mt, pg + LUABRIDGE_ASSERT(lua_istable(L, -1)); + + rawlookup(); // Stack: mt, pg, getter | nil + lua_remove(L, -2); // Stack: mt, getter | nil + + if (lua_iscfunction(L, -1)) + { + lua_remove(L, -2); // Stack: getter + lua_pushvalue(L, 1); // Stack: getter, self + lua_call(L, 1, 1); // Stack: value + return 1; + } + + lua_pop(L, 2); // Stack: - + lua_pushnil(L); + return 1; +} + +//================================================================================================= +/** + * @brief __newindex metamethod for non-static members. + * + * Retrieves properties from propset tables. + */ + +inline std::optional try_call_newindex_fallback(lua_State* L) +{ + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: mt + + lua_rawgetp_x(L, -1, getNewIndexFallbackKey()); // Stack: mt, nifb (may be nil) + if (! lua_iscfunction(L, -1)) + { + lua_pop(L, 1); // Stack: mt + return std::nullopt; + } + + lua_pushvalue(L, 1); // stack: mt, nifb, arg1 + lua_pushvalue(L, 2); // stack: mt, nifb, arg1, arg2 + lua_pushvalue(L, 3); // stack: mt, nifb, arg1, arg2, arg3 + lua_call(L, 3, 0); // stack: mt + + return 0; +} + +inline std::optional try_call_static_newindex_fallback(lua_State* L) +{ + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: mt + + lua_rawgetp_x(L, -1, getStaticNewIndexFallbackKey()); // Stack: mt, nifb (may be nil) + if (! lua_iscfunction(L, -1)) + { + lua_pop(L, 1); // Stack: mt + return std::nullopt; + } + + lua_pushvalue(L, 2); // stack: mt, nifb, arg1 (key only, no self for static) + lua_pushvalue(L, 3); // stack: mt, nifb, arg1, arg2 (value) + lua_call(L, 2, 0); // stack: mt + + return 0; +} + +inline std::optional try_call_newindex_extensible(lua_State* L, const char* key) +{ + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: mt + + // For Lua function values (instance methods added from Lua), capture the originating class + // table so the method is stored there rather than in a traversed-to parent class table. + // This prevents e.g. `function Derived:init()` from polluting `Base`'s method table. + // + // For non-function values (static properties like `Class.prop = val`), the original + // traversal-end behaviour is preserved: storing them in the nearest class table that + // already has a matching key (or the topmost base if none exists). This keeps static + // properties out of the derived class table, which is also used for instance extensible + // method lookup, avoiding unintended shadowing of per-instance properties accessed via an + // index-fallback metamethod registered on a non-extensible base class. + const bool value_is_function = lua_isfunction(L, 3); + + if (value_is_function) + { + // Capture the original (most-derived) class table — always write here. + push_class_or_const_table(L, -1); // Stack: mt, orig_ct | nil + if (! lua_istable(L, -1)) // Stack: mt, nil + { + lua_pop(L, 1); // Stack: mt + return std::nullopt; + } + // Stack: mt, orig_ct + + const int mtIndex = lua_absindex(L, -2); + const int origClassTableIndex = lua_absindex(L, -1); + const auto process_metatable = [=](int candidateMtIndex) + { + push_class_or_const_table(L, candidateMtIndex); // Stack: ..., candidate_ct | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); + return false; + } + + lua_pushvalue(L, 2); // Stack: ..., candidate_ct, field name + lua_rawget(L, -2); // Stack: ..., candidate_ct, field | nil + + if (lua_isnil(L, -1)) + { + lua_pop(L, 2); // Stack: ... + return false; + } + + if (! lua_iscfunction(L, -1)) + { + lua_pop(L, 2); // Stack: ... + return true; + } + + const Options options = get_class_options(L, -2); + if (! options.test(allowOverridingMethods)) + raise_lua_error(L, "immutable member '%s'", get_key_name_for_error(L, 2)); + + if (key != nullptr) + rawset_super_method(L, origClassTableIndex, key); // Stack: ..., candidate_ct + lua_pop(L, 1); // Stack: ... + return true; + }; + + (void) process_metatable(mtIndex); + + lua_rawgetp_x(L, mtIndex, getParentKey()); // Stack: mt, orig_ct, parent list | nil + if (lua_istable(L, -1)) + { + const int parentListIndex = lua_absindex(L, -1); + const int parentCount = get_length(L, parentListIndex); + + for (int i = 1; i <= parentCount; ++i) + { + lua_rawgeti(L, parentListIndex, i); // Stack: mt, orig_ct, parent list, parent mt + if (lua_istable(L, -1)) + { + if (process_metatable(lua_absindex(L, -1))) + { + lua_pop(L, 1); // Stack: mt, orig_ct, parent list + break; + } + } + + lua_pop(L, 1); // Stack: mt, orig_ct, parent list + } + } + + lua_pop(L, 1); // Stack: mt, orig_ct + + // Stack: mt, orig_ct — write to the original (most-derived) class table. + lua_getmetatable(L, -1); // Stack: mt, orig_ct, orig_ct_mt + lua_pushvalue(L, 3); // Stack: mt, orig_ct, orig_ct_mt, arg3 + lua_pushvalue(L, 2); // Stack: mt, orig_ct, orig_ct_mt, arg3, field name + lua_insert(L, -2); // Stack: mt, orig_ct, orig_ct_mt, field name, arg3 + lua_rawset(L, -3); // Stack: mt, orig_ct, orig_ct_mt + lua_pop(L, 2); // Stack: mt + return 0; + } + + // Non-function value (static property): use original traversal-end write location. + const int rootMetatableIndex = lua_absindex(L, -1); + lua_pushvalue(L, rootMetatableIndex); // Stack: mt, target mt + const int targetMetatableIndex = lua_absindex(L, -1); + + const auto process_metatable = [=](int candidateMtIndex) + { + push_class_or_const_table(L, candidateMtIndex); // Stack: ..., candidate_ct | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); + return false; + } + + lua_pushvalue(L, 2); // Stack: ..., candidate_ct, field name + lua_rawget(L, -2); // Stack: ..., candidate_ct, field | nil + + if (lua_isnil(L, -1)) + { + lua_pop(L, 2); // Stack: ... + return false; + } + + lua_pushvalue(L, candidateMtIndex); + lua_replace(L, targetMetatableIndex); + + if (! lua_iscfunction(L, -1)) + { + lua_pop(L, 2); // Stack: ... + return true; + } + + const Options options = get_class_options(L, -2); + if (! options.test(allowOverridingMethods)) + raise_lua_error(L, "immutable member '%s'", get_key_name_for_error(L, 2)); + + if (key != nullptr) + rawset_super_method(L, -2, key); // Stack: ..., candidate_ct + lua_pop(L, 1); // Stack: ... + return true; + }; + + (void) process_metatable(rootMetatableIndex); + + lua_rawgetp_x(L, rootMetatableIndex, getParentKey()); // Stack: mt, target mt, parent list | nil + if (lua_istable(L, -1)) + { + const int parentListIndex = lua_absindex(L, -1); + const int parentCount = get_length(L, parentListIndex); + + for (int i = 1; i <= parentCount; ++i) + { + lua_rawgeti(L, parentListIndex, i); // Stack: mt, target mt, parent list, parent mt + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); + continue; + } + + // Preserve old traversal-end behavior when no member exists in the chain. + lua_pushvalue(L, -1); + lua_replace(L, targetMetatableIndex); + + if (process_metatable(lua_absindex(L, -1))) + { + lua_pop(L, 1); // Stack: mt, target mt, parent list + break; + } + + lua_pop(L, 1); // Stack: mt, target mt, parent list + } + } + + lua_pop(L, 1); // Stack: mt, target mt + + push_class_or_const_table(L, targetMetatableIndex); // Stack: mt, target mt, ct | nil + if (! lua_istable(L, -1)) // Stack: mt, target mt, nil + { + lua_pop(L, 2); // Stack: mt + return std::nullopt; + } + + lua_getmetatable(L, -1); // Stack: mt, target mt, ct, ct_mt + lua_pushvalue(L, 3); // Stack: mt, target mt, ct, ct_mt, arg3 + lua_pushvalue(L, 2); // Stack: mt, target mt, ct, ct_mt, arg3, field name + lua_insert(L, -2); // Stack: mt, target mt, ct, ct_mt, field name, arg3 + lua_rawset(L, -3); // Stack: mt, target mt, ct, ct_mt + lua_pop(L, 3); // Stack: mt + return 0; +} + +/** + * @brief Scan the flattened parent list for a property setter matching the key (stack[2]). + * + * Only setters are checked; __newindex fallbacks are intentionally ignored so that a + * registered property anywhere in the hierarchy always takes priority over any fallback. + */ +template +inline std::optional try_call_parent_newindex_setters(lua_State* L) +{ + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: mt + + lua_rawgetp_x(L, -1, getParentKey()); // Stack: mt, parent list | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); // Stack: mt + return std::nullopt; + } + + const int parentListIndex = lua_absindex(L, -1); + const int parentCount = get_length(L, parentListIndex); + + for (int i = 1; i <= parentCount; ++i) + { + lua_rawgeti(L, parentListIndex, i); // Stack: mt, parent list, parent mt + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); + continue; + } + + lua_rawgetp_x(L, -1, getPropsetKey()); // Stack: mt, parent list, parent mt, ps | nil + if (lua_istable(L, -1)) + { + lua_pushvalue(L, 2); // Stack: mt, parent list, parent mt, ps, field name + lua_rawget(L, -2); // Stack: mt, parent list, parent mt, ps, setter | nil + lua_remove(L, -2); // Stack: mt, parent list, parent mt, setter | nil + + if (lua_iscfunction(L, -1)) + { + lua_remove(L, -2); // Stack: mt, parent list, setter + lua_remove(L, -2); // Stack: mt, setter + lua_remove(L, -2); // Stack: setter + + if constexpr (IsObject) + lua_pushvalue(L, 1); // Stack: setter, table | userdata + lua_pushvalue(L, 3); // Stack: setter, table | userdata, new value + lua_call(L, IsObject ? 2 : 1, 0); // Stack: - + return 0; + } + + lua_pop(L, 1); // Stack: mt, parent list, parent mt + } + else + { + lua_pop(L, 1); // Stack: mt, parent list, parent mt + } + + lua_pop(L, 1); // Stack: mt, parent list + } + + lua_pop(L, 1); // Stack: mt + return std::nullopt; +} + +/** + * @brief Scan the flattened parent list for a __newindex fallback. + * + * Only fallbacks are checked; property setters are intentionally ignored because they + * have already been searched by try_call_parent_newindex_setters. + */ +template +inline std::optional try_call_parent_newindex_fallbacks(lua_State* L) +{ + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: mt + + lua_rawgetp_x(L, -1, getParentKey()); // Stack: mt, parent list | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); // Stack: mt + return std::nullopt; + } + + const int parentListIndex = lua_absindex(L, -1); + const int parentCount = get_length(L, parentListIndex); + + for (int i = 1; i <= parentCount; ++i) + { + lua_rawgeti(L, parentListIndex, i); // Stack: mt, parent list, parent mt + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); + continue; + } + + lua_rawgetp_x(L, -1, getNewIndexFallbackKey()); // Stack: mt, parent list, parent mt, nifb | nil + if (lua_iscfunction(L, -1)) + { + lua_pushvalue(L, 1); // Stack: mt, parent list, parent mt, nifb, arg1 + lua_pushvalue(L, 2); // Stack: mt, parent list, parent mt, nifb, arg1, arg2 + lua_pushvalue(L, 3); // Stack: mt, parent list, parent mt, nifb, arg1, arg2, arg3 + lua_call(L, 3, 0); // Stack: mt, parent list, parent mt + + lua_pop(L, 3); // Stack: - + return 0; + } + + lua_pop(L, 2); // Stack: mt, parent list + } + + lua_pop(L, 1); // Stack: mt + return std::nullopt; +} + +template +inline int newindex_metamethod(lua_State* L) +{ +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(L, 6, detail::error_lua_stack_overflow); +#endif + + LUABRIDGE_ASSERT(lua_istable(L, 1) || lua_isuserdata(L, 1)); // Stack (further not shown): table | userdata, name, new value + + lua_getmetatable(L, 1); // Stack: metatable (mt) + LUABRIDGE_ASSERT(lua_istable(L, -1)); + + const char* key = get_string_key(L, 2); + + const Options options = get_class_options(L, -1); + + // Try in the property set table on the current class first. + lua_rawgetp_x(L, -1, getPropsetKey()); // Stack: mt, propset table (ps) | nil + if (! lua_istable(L, -1)) + raise_lua_error(L, "no member named '%s'", get_key_name_for_error(L, 2)); + + lua_pushvalue(L, 2); // Stack: mt, ps, field name + lua_rawget(L, -2); // Stack: mt, ps, setter | nil + lua_remove(L, -2); // Stack: mt, setter | nil + + if (lua_iscfunction(L, -1)) // Stack: mt, setter + { + lua_remove(L, -2); // Stack: setter + if constexpr (IsObject) + lua_pushvalue(L, 1); // Stack: setter, table | userdata + lua_pushvalue(L, 3); // Stack: setter, table | userdata, new value + lua_call(L, IsObject ? 2 : 1, 0); // Stack: - + return 0; + } + + lua_pop(L, 1); // Stack: mt + + // Before consulting any __newindex fallback, scan the entire parent hierarchy for a + // matching property setter. This ensures that a registered property anywhere in the + // inheritance chain always takes priority over a __newindex fallback defined at a + // narrower scope (e.g. an intermediate or leaf class). + if (auto result = try_call_parent_newindex_setters(L)) + return *result; + + if constexpr (IsObject) + { + if (auto result = try_call_instance_static_newindex(L, -1)) + return *result; + } + + // Before consulting any __newindex fallback, scan the entire parent hierarchy for a + // matching property setter. This ensures that a registered property anywhere in the + // inheritance chain always takes priority over a __newindex fallback defined at a + // narrower scope (e.g. an intermediate or leaf class). + if (auto result = try_call_parent_newindex_setters(L)) + return *result; + + if constexpr (IsObject) + { + if (auto result = try_call_instance_static_newindex(L, -1)) + return *result; + } + + // Before consulting any __newindex fallback, scan the entire parent hierarchy for a + // matching property setter. This ensures that a registered property anywhere in the + // inheritance chain always takes priority over a __newindex fallback defined at a + // narrower scope (e.g. an intermediate or leaf class). + if (auto result = try_call_parent_newindex_setters(L)) + return *result; + + if constexpr (IsObject) + { + if (auto result = try_call_newindex_fallback(L)) + return *result; + } + else + { + if (auto result = try_call_static_newindex_fallback(L)) + return *result; + + if (options.test(extensibleClass)) + { + // For static extensible writes of plain values, store directly on the class table. + // Function values still go through try_call_newindex_extensible to preserve super_* wiring. + if (! lua_isfunction(L, 3)) + { + lua_pushvalue(L, 2); + lua_pushvalue(L, 3); + lua_rawset(L, 1); + return 0; + } + + if (auto result = try_call_newindex_extensible(L, key)) + return *result; + } + } + + if (auto result = try_call_parent_newindex_fallbacks(L)) + return *result; + + if constexpr (IsObject) + { + // Parent metamethods should win; extensible storage is the final fallback. + if (options.test(extensibleClass)) + { + if (auto result = try_call_newindex_extensible(L, key)) + return *result; + } + } + + lua_pop(L, 1); // Stack: - + raise_lua_error(L, "no writable member '%s'", get_key_name_for_error(L, 2)); +} + +template +inline int newindex_metamethod_simple(lua_State* L) +{ +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(L, 3, detail::error_lua_stack_overflow); +#endif + + LUABRIDGE_ASSERT(lua_istable(L, 1) || lua_isuserdata(L, 1)); + + // Fast path for simple userdata objects: propset table is captured as upvalue. + if constexpr (IsObject) + { + if (lua_isuserdata(L, 1)) + { + if (! lua_istable(L, lua_upvalueindex(1))) + raise_lua_error(L, "no writable member '%s'", get_key_name_for_error(L, 2)); + + lua_pushvalue(L, 2); // Stack: key + lua_rawget(L, lua_upvalueindex(1)); // Stack: setter | nil + + if (lua_iscfunction(L, -1)) + { + lua_pushvalue(L, 1); // Stack: setter, self + lua_pushvalue(L, 3); // Stack: setter, self, value + lua_call(L, 2, 0); + return 0; + } + + lua_pop(L, 1); + lua_getmetatable(L, 1); // Stack: mt + LUABRIDGE_ASSERT(lua_istable(L, -1)); + if (auto result = try_call_instance_static_newindex(L, -1)) + return *result; + lua_pop(L, 1); + + luaL_error(L, "no writable member '%s'", get_key_name_for_error(L, 2)); + } + } + else + { + // Fast path for simple static tables: propset table is captured as upvalue. + if (lua_istable(L, 1)) + { + if (! lua_istable(L, lua_upvalueindex(1))) + raise_lua_error(L, "no writable member '%s'", get_key_name_for_error(L, 2)); + + lua_pushvalue(L, 2); // Stack: key + lua_rawget(L, lua_upvalueindex(1)); // Stack: setter | nil + + if (lua_iscfunction(L, -1)) + { + lua_pushvalue(L, 3); // Stack: setter, value + lua_call(L, 1, 0); + return 0; + } + + raise_lua_error(L, "no writable member '%s'", get_key_name_for_error(L, 2)); + } + } + + lua_getmetatable(L, 1); // Stack: mt + LUABRIDGE_ASSERT(lua_istable(L, -1)); + + lua_rawgetp_x(L, -1, getPropsetKey()); // Stack: mt, ps | nil + if (! lua_istable(L, -1)) + raise_lua_error(L, "no member named '%s'", get_key_name_for_error(L, 2)); + + lua_pushvalue(L, 2); // Stack: mt, ps, key + lua_rawget(L, -2); // Stack: mt, ps, setter | nil + lua_remove(L, -2); // Stack: mt, setter | nil + + if (lua_iscfunction(L, -1)) + { + lua_remove(L, -2); // Stack: setter + if constexpr (IsObject) + lua_pushvalue(L, 1); // Stack: setter, self + lua_pushvalue(L, 3); // Stack: setter, self, value + lua_call(L, IsObject ? 2 : 1, 0); + return 0; + } + + raise_lua_error(L, "no writable member '%s'", get_key_name_for_error(L, 2)); +} + +//================================================================================================= +/** + * @brief lua_CFunction to report an error writing to a read-only value. + * + * The name of the variable is in the first upvalue. + */ +[[noreturn]] inline int read_only_error(lua_State* L) +{ + raise_lua_error(L, "'%s' is read-only", lua_tostring(L, lua_upvalueindex(1))); +} + +//================================================================================================= +/** + * @brief __tostring metamethod for a class. + */ +template +int tostring_metamethod(lua_State* L) +{ + const void* ptr = lua_topointer(L, 1); + + lua_getmetatable(L, -1); // Stack: metatable (mt) + lua_rawgetp_x(L, -1, getTypeKey()); // Stack: mt, classname (cn) + lua_remove(L, -2); // Stack: cn + + std::stringstream ss; + ss << ": 0x" << std::hex << reinterpret_cast(const_cast(ptr)); + lua_pushstring(L, ss.str().c_str()); // Stack: cn, address string (astr) + lua_concat(L, 2); // Stack: astr + + return 1; +} + +//================================================================================================= +/** + * @brief __destruct metamethod for a class. + */ +template +int destruct_metamethod(lua_State* L) +{ + LUABRIDGE_ASSERT(lua_isuserdata(L, 1)); // Stack: userdata (ud) + const auto top = lua_gettop(L); + + const int result = lua_getmetatable(L, 1); // Stack: ud, object metatable (ot) | nothing + if (result == 0) + return 0; + + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: ud, ot + + lua_rawgetp_x(L, LUA_REGISTRYINDEX, detail::getClassRegistryKey()); // Stack: ud, ot, registry metatable (rt) | nil + if (lua_istable(L, -1)) // Stack: ud, ot, rt + { + rawgetfield(L, -1, "__destruct"); // Stack: ud, ot, rt, ud, function | nil + if (lua_isfunction(L, -1)) + { + lua_pushvalue(L, 1); // Stack: ud, ot, rt, function, ud + lua_pcall(L, 1, 0, 0); // Stack: ud, ot, rt + } + } + + lua_settop(L, top); // Stack: ud + return 0; +} + +//================================================================================================= +/** + * @brief __gc metamethod for a class. + */ +template +int gc_metamethod(lua_State* L) +{ + destruct_metamethod(L); + + Userdata* ud = Userdata::getExact(L, 1); + LUABRIDGE_ASSERT(ud); + + ud->~Userdata(); + + return 0; +} + +//================================================================================================= + +template +struct property_getter; + +/** + * @brief lua_CFunction to get a variable. + * + * This is used for global variables or class static data members. The pointer to the data is in the first upvalue. + */ +template +struct property_getter +{ + static int call(lua_State* L) + { + LUABRIDGE_ASSERT(lua_islightuserdata(L, lua_upvalueindex(1))); + + T* ptr = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + LUABRIDGE_ASSERT(ptr != nullptr); + + auto result = Stack::push(L, *ptr); + if (! result) + raise_lua_error(L, "%s", result.error_cstr()); + + return 1; + } +}; + +/** + * @brief lua_CFunction to get a class data member. + * + * The pointer-to-member is in the first upvalue. The class userdata object is at the top of the Lua stack. + */ +template +struct property_getter +{ + static int call(lua_State* L) + { + auto c = Userdata::get(L, 1, true); + if (! c) + raise_lua_error(L, "%s", c.error_cstr()); + + T C::** mp = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + + Result result; + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + result = Stack::push(L, (*c)->**mp); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + if (! result) + raise_lua_error(L, "%s", result.error_cstr()); + + return 1; + } +}; + +/** + * @brief Helper function to push a property getter on a table at a specific index. + */ +inline void add_property_getter(lua_State* L, const char* name, int tableIndex) +{ +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(L, 2, detail::error_lua_stack_overflow); +#endif + + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, tableIndex)); + LUABRIDGE_ASSERT(lua_iscfunction(L, -1)); // Stack: getter + + lua_rawgetp_x(L, tableIndex, getPropgetKey()); // Stack: getter, propget table (pg) + lua_pushvalue(L, -2); // Stack: getter, pg, getter + rawsetfield(L, -2, name); // Stack: getter, pg + lua_pop(L, 2); // Stack: - +} + +//================================================================================================= + +template +struct property_setter; + +/** + * @brief lua_CFunction to set a variable. + * + * This is used for global variables or class static data members. The pointer to the data is in the first upvalue. + */ +template +struct property_setter +{ + static int call(lua_State* L) + { + LUABRIDGE_ASSERT(lua_islightuserdata(L, lua_upvalueindex(1))); + + T* ptr = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + LUABRIDGE_ASSERT(ptr != nullptr); + + auto result = Stack::get(L, 1); + if (! result) + raise_lua_error(L, "%s", result.error_cstr()); + + *ptr = std::move(*result); + + return 0; + } +}; + +/** + * @brief lua_CFunction to set a class data member. + * + * The pointer-to-member is in the first upvalue. The class userdata object is at the top of the Lua stack. + */ +template +struct property_setter +{ + static int call(lua_State* L) + { + auto c = Userdata::get(L, 1, false); + if (! c) + raise_lua_error(L, "%s", c.error_cstr()); + + T C::** mp = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + auto result = Stack::get(L, 2); + if (! result) + raise_lua_error(L, "%s", result.error_cstr()); + + (*c)->** mp = std::move(*result); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + return 0; + } +}; + +/** + * @brief Helper function to push a property setter on a table at a specific index. + */ +inline void add_property_setter(lua_State* L, const char* name, int tableIndex) +{ +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(L, 2, detail::error_lua_stack_overflow); +#endif + + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, tableIndex)); + LUABRIDGE_ASSERT(lua_iscfunction(L, -1)); // Stack: setter + + lua_rawgetp_x(L, tableIndex, getPropsetKey()); // Stack: setter, propset table (ps) + lua_pushvalue(L, -2); // Stack: setter, ps, setter + rawsetfield(L, -2, name); // Stack: setter, ps + lua_pop(L, 2); // Stack: - +} + +//================================================================================================= +/** + * @brief Function generator. + */ +template +decltype(auto) invoke_callable_from_stack(lua_State* L, F&& func) +{ + return std::apply(std::forward(func), make_arguments_list(L)); +} + +template +decltype(auto) invoke_member_callable_from_stack(lua_State* L, T* ptr, F&& func) +{ + return std::apply( + std::forward(func), + std::tuple_cat(std::tuple(ptr), make_arguments_list(L))); +} + +template +struct function +{ + template + static int call(lua_State* L, F&& func) + { + Result result; + int numResults = 1; + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + if constexpr (detail::is_tuple_v) + { + numResults = static_cast(std::tuple_size_v); + result = detail::push_tuple(L, invoke_callable_from_stack(L, std::forward(func))); + } + else + { + result = Stack::push(L, invoke_callable_from_stack(L, std::forward(func))); + } +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + if (! result) + raise_lua_error(L, "%s", result.error_cstr()); + + return numResults; + } + + template + static int call(lua_State* L, T* ptr, F&& func) + { + Result result; + int numResults = 1; + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + if constexpr (detail::is_tuple_v) + { + numResults = static_cast(std::tuple_size_v); + result = detail::push_tuple(L, invoke_member_callable_from_stack(L, ptr, std::forward(func))); + } + else + { + result = Stack::push(L, invoke_member_callable_from_stack(L, ptr, std::forward(func))); + } +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + if (! result) + raise_lua_error(L, "%s", result.error_cstr()); + + return numResults; + } +}; + +template +struct function, ArgsPack, Start> : function +{ + template + static int call(lua_State* L, F&& func) + { +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + invoke_callable_from_stack(L, std::forward(func)); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + return 0; + } + + template + static int call(lua_State* L, T* ptr, F&& func) + { +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + invoke_member_callable_from_stack(L, ptr, std::forward(func)); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + return 0; + } +}; + +template +struct function +{ + template + static int call(lua_State* L, F&& func) + { +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + invoke_callable_from_stack(L, std::forward(func)); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + return 0; + } + + template + static int call(lua_State* L, T* ptr, F&& func) + { +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + invoke_member_callable_from_stack(L, ptr, std::forward(func)); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + return 0; + } +}; + +template +TypeResult get_member_object(lua_State* L, bool canBeConst) +{ + const int selfIndex = lua_absindex(L, 1); + + if (lua_getmetatable(L, selfIndex)) + { + if (lua_type(L, lua_upvalueindex(2)) == LUA_TTABLE && lua_rawequal(L, -1, lua_upvalueindex(2))) + { + lua_pop(L, 1); + return Userdata::getExactPointer(L, selfIndex); + } + + if (canBeConst && lua_type(L, lua_upvalueindex(3)) == LUA_TTABLE && lua_rawequal(L, -1, lua_upvalueindex(3))) + { + lua_pop(L, 1); + return Userdata::getExactPointer(L, selfIndex); + } + + lua_pop(L, 1); + } + + // Cortex Command: calling a method on nil (e.g. with . instead of :) is a Lua error like it was with luabind, rather than a call through a null pointer. + if (lua_isnil(L, selfIndex)) + raise_lua_error(L, "Tried to call a method on nil instead of an object, use : rather than . to call methods!"); + + return Userdata::get(L, selfIndex, canBeConst); +} + +//================================================================================================= +/** + * @brief lua_CFunction to call a class member function with a return value. + * + * The member function pointer is in the first upvalue. The class userdata object is at the top of the Lua stack. + */ +template +int invoke_member_function(lua_State* L) +{ + using FnTraits = function_traits; + + // Cortex Command: the member function pointer can also be in a light userdata, pointing to memory that's kept outside the Lua heap. + LUABRIDGE_ASSERT(lua_isuserdata(L, lua_upvalueindex(1))); + + auto ptr = get_member_object(L, false); + if (! ptr) + raise_lua_error(L, "%s", ptr.error_cstr()); + + const F& func = *static_cast(lua_touserdata(L, lua_upvalueindex(1))); + LUABRIDGE_ASSERT(func != nullptr); + + return function::call(L, *ptr, func); +} + +template +int invoke_const_member_function(lua_State* L) +{ + using FnTraits = function_traits; + + // Cortex Command: the member function pointer can also be in a light userdata, pointing to memory that's kept outside the Lua heap. + LUABRIDGE_ASSERT(lua_isuserdata(L, lua_upvalueindex(1))); + + auto ptr = get_member_object(L, true); + if (! ptr) + raise_lua_error(L, "%s", ptr.error_cstr()); + + const F& func = *static_cast(lua_touserdata(L, lua_upvalueindex(1))); + LUABRIDGE_ASSERT(func != nullptr); + + return function::call(L, *ptr, func); +} + +//================================================================================================= +/** + * @brief lua_CFunction to call a class member lua_CFunction. + * + * The member function pointer is in the first upvalue. The object userdata ('this') value is at top ot the Lua stack. + */ +template +int invoke_member_cfunction(lua_State* L) +{ + using F = int (T::*)(lua_State* L); + + LUABRIDGE_ASSERT(isfulluserdata(L, lua_upvalueindex(1))); + + auto t = Userdata::get(L, 1, false); + if (! t) + raise_lua_error(L, "%s", t.error_cstr()); + + const F& func = *static_cast(lua_touserdata(L, lua_upvalueindex(1))); + LUABRIDGE_ASSERT(func != nullptr); + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + return ((*t)->*func)(L); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } + + return 0; +#endif +} + +template +int invoke_const_member_cfunction(lua_State* L) +{ + using F = int (T::*)(lua_State * L) const; + + LUABRIDGE_ASSERT(isfulluserdata(L, lua_upvalueindex(1))); + + auto t = Userdata::get(L, 1, true); + if (! t) + raise_lua_error(L, "%s", t.error_cstr()); + + const F& func = *static_cast(lua_touserdata(L, lua_upvalueindex(1))); + LUABRIDGE_ASSERT(func != nullptr); + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + return ((*t)->*func)(L); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } + + return 0; +#endif +} + +//================================================================================================= +/** + * @brief lua_CFunction to call on a object via function pointer. + * + * The proxy function pointer (lightuserdata) is in the first upvalue. The class userdata object is at the top of the Lua stack. + */ +template +int invoke_proxy_function(lua_State* L) +{ + using FnTraits = function_traits; + + LUABRIDGE_ASSERT(lua_islightuserdata(L, lua_upvalueindex(1))); + + auto func = reinterpret_cast(lua_touserdata(L, lua_upvalueindex(1))); + LUABRIDGE_ASSERT(func != nullptr); + + return function::call(L, func); +} + +//================================================================================================= +/** + * @brief lua_CFunction to call on a object via functor (lambda wrapped in a std::function). + * + * The proxy std::function (lightuserdata) is in the first upvalue. The class userdata object is at the top of the Lua stack. + */ +template +int invoke_proxy_functor(lua_State* L) +{ + using FnTraits = function_traits>; + + // Cortex Command: the functor can also be in a light userdata, pointing to memory that's kept outside the Lua heap. + LUABRIDGE_ASSERT(lua_isuserdata(L, lua_upvalueindex(1))); + + auto& func = *align>(lua_touserdata(L, lua_upvalueindex(1))); + + return function::call(L, func); +} + +//================================================================================================= +/** + * @brief lua_CFunction to call safely by trapping exceptions + */ +#if LUABRIDGE_SAFE_LUA_C_EXCEPTION_HANDLING && LUABRIDGE_HAS_EXCEPTIONS +inline int invoke_safe_cfunction(lua_State* L) +{ + LUABRIDGE_ASSERT(lua_iscfunction(L, lua_upvalueindex(1))); + + auto func = lua_tocfunction(L, lua_upvalueindex(1)); + + try + { + return func(L); + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } + + return 0; +} +#endif + +//================================================================================================= +/** + * @brief lua_CFunction to call on a object constructor via functor (lambda wrapped in a std::function). + * + * The proxy std::function (lightuserdata) is in the first upvalue. The class userdata object will be pushed at the top of the Lua stack. + */ +template +int invoke_proxy_constructor(lua_State* L) +{ + using FnTraits = function_traits; + + LUABRIDGE_ASSERT(isfulluserdata(L, lua_upvalueindex(1))); + + auto& func = *align(lua_touserdata(L, lua_upvalueindex(1))); + + function::call(L, func); + + return 1; +} + +//================================================================================================= +/** + * @brief lua_CFunction to call on a object constructor via functor (lambda wrapped in a std::function). + * + * The proxy std::function (lightuserdata) is in the first upvalue. The class userdata object will be pushed at the top of the Lua stack. + */ +template +int invoke_proxy_destructor(lua_State* L) +{ + using FnTraits = function_traits; + + LUABRIDGE_ASSERT(isfulluserdata(L, lua_upvalueindex(1))); + + auto& func = *align(lua_touserdata(L, lua_upvalueindex(1))); + + function::call(L, func); + + return 1; +} + +//================================================================================================= +/** + * @brief C++ storage for a single overload entry: arity and optional type checker. + * + * Stored inside an OverloadSet which is kept as a Lua full userdata (auto-GC'd). + */ +struct OverloadEntry +{ + using TypeChecker = bool (*)(lua_State*, int start); + + int arity; // -1 for variadic (lua_CFunction): always attempt + TypeChecker checker; // nullptr for variadic: skip type pre-checking +}; + +/** + * @brief C++ storage for all overloads of a function. + * + * Stored as a Lua full userdata so it is GC'd automatically when the closure is collected. + * The actual function closures are stored separately in a flat Lua table (upvalue 2). + */ +struct OverloadSet +{ + std::vector entries; +}; + +/** + * @brief Check a single argument type, skipping lua_State* (auto-injected, not on the Lua stack). + */ +template +bool overload_check_one_arg(lua_State* L, int& idx) +{ + if constexpr (std::is_pointer_v && + std::is_same_v>, lua_State>) + { + return true; // lua_State* is auto-injected by LuaBridge, not a Lua-visible argument + } + else + { + return Stack::isInstance(L, idx++); + } +} + +template +bool overload_check_args_impl(lua_State* L, int start, std::index_sequence) +{ + [[maybe_unused]] int idx = start; + return (overload_check_one_arg>(L, idx) && ...); +} + +template +bool overload_check_args(lua_State* L, int start) +{ + return overload_check_args_impl(L, start, + std::make_index_sequence>{}); +} + +/** + * @brief Type checker instantiable as an OverloadEntry::TypeChecker function pointer. + * + * Checks that the Lua stack arguments starting at @p start match the types in @tparam ArgsPack, + * using Stack::isInstance without raising errors. lua_State* arguments are skipped. + */ +template +bool overload_type_checker(lua_State* L, int start) +{ + return overload_check_args(L, start); +} + +/** + * @brief Type checker for reversed proxy functions (binary operators with swapped operands). + * + * Checks all arguments from absolute stack index 1, ignoring @p start, because the class object + * is not the first operand on the stack (eg. `3 * vec`). + */ +template +bool reversed_overload_type_checker(lua_State* L, int) +{ + return overload_check_args(L, 1); +} + +//================================================================================================= +/** + * @brief lua_CFunction to resolve an invocation between several overloads. + * + * upvalue[1] = OverloadSet full userdata — C++ vector of {arity, type_checker} per overload. + * upvalue[2] = flat Lua table {[1]=func1, [2]=func2, ...} — the actual function closures. + * + * Dispatch: + * 1. Arity check in C++ (no Lua call). + * 2. Type check via Stack::isInstance in C++ (no pcall) — skips clearly mismatched overloads. + * 3. Only calls lua_pcall for type-matched candidates, eliminating failed pcalls for type mismatches. + */ +template +inline int try_overload_functions(lua_State* L) +{ + const int nargs = lua_gettop(L); + const int effective_args = nargs - (Member ? 1 : 0); + const int start_arg = Member ? 2 : 1; + + LUABRIDGE_ASSERT(isfulluserdata(L, lua_upvalueindex(1))); + auto* overload_set = align(lua_touserdata(L, lua_upvalueindex(1))); + + // push flat functions table (upvalue 2) + lua_pushvalue(L, lua_upvalueindex(2)); + LUABRIDGE_ASSERT(lua_istable(L, -1)); + const int idx_funcs = nargs + 1; + + // create table to hold error messages + lua_createtable(L, static_cast(overload_set->entries.size()), 0); + const int idx_errors = nargs + 2; + int nerrors = 0; + + for (int i = 0; i < static_cast(overload_set->entries.size()); ++i) + { + const auto& entry = overload_set->entries[i]; + + // fast arity check (C++, no Lua calls) + if (entry.arity >= 0 && entry.arity != effective_args) + { + lua_pushfstring(L, "Skipped overload #%d with unmatched arity of %d instead of %d", i, entry.arity, effective_args); + lua_rawseti(L, idx_errors, ++nerrors); + continue; + } + + // fast type check (C++, no pcall) — avoids expensive pcall for clearly mismatched types + if (entry.checker != nullptr && !entry.checker(L, start_arg)) + { + lua_pushfstring(L, "Skipped overload #%d with unmatched argument types", i); + lua_rawseti(L, idx_errors, ++nerrors); + continue; + } + + // O(1) function lookup from flat table + lua_rawgeti(L, idx_funcs, i + 1); + LUABRIDGE_ASSERT(lua_isfunction(L, -1)); + + // push arguments + for (int j = 1; j <= nargs; ++j) + lua_pushvalue(L, j); + + // call f, this pops the function and its args, pushes result(s) + const int err = lua_pcall(L, nargs, LUA_MULTRET, 0); + if (err == LUABRIDGE_LUA_OK) + { + // 2 extra items on stack below results: idx_funcs, idx_errors + return lua_gettop(L) - nargs - 2; + } + else if (err == LUA_ERRRUN) + { + // store error message and try next overload + lua_rawseti(L, idx_errors, ++nerrors); + } + else + { + lua_error_x(L); // critical error: rethrow + } + } + + lua_Debug debug; + lua_getstack_info_x(L, 0, "n", &debug); + lua_pushfstring(L, "All %d overloads of %s returned an error:", nerrors, debug.name); + + // Concatenate error messages of each overload + for (int i = 1; i <= nerrors; ++i) + { + lua_pushfstring(L, "\n%d: ", i); + lua_rawgeti(L, idx_errors, i); + } + lua_concat(L, nerrors * 2 + 1); + + const char* message = lua_tostring(L, -1); + raise_lua_error(L, "%s", message ? message : ""); +} + +//================================================================================================= + +// Lua CFunction +inline void push_function(lua_State* L, lua_CFunction fp, const char* debugname) +{ +#if LUABRIDGE_SAFE_LUA_C_EXCEPTION_HANDLING && LUABRIDGE_HAS_EXCEPTIONS + lua_pushcfunction_x(L, fp, debugname); + lua_pushcclosure_x(L, invoke_safe_cfunction, debugname, 1); +#else + lua_pushcfunction_x(L, fp, debugname); +#endif +} + +// Generic function pointer +template +inline void push_function(lua_State* L, ReturnType (*fp)(Params...), const char* debugname) +{ + using FnType = decltype(fp); + + lua_pushlightuserdata(L, reinterpret_cast(fp)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +inline void push_function(lua_State* L, ReturnType (*fp)(Params...) noexcept, const char* debugname) +{ + using FnType = decltype(fp); + + lua_pushlightuserdata(L, reinterpret_cast(fp)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +// Callable object (lambdas) +template && !std::is_pointer_v && !std::is_member_function_pointer_v>> +inline void push_function(lua_State* L, F&& f, const char* debugname) +{ + lua_newuserdata_aligned(L, std::forward(f)); + lua_pushcclosure_x(L, &invoke_proxy_functor, debugname, 1); +} + +//================================================================================================= +// Lua CFunction +template +void push_member_function(lua_State* L, lua_CFunction fp, const char* debugname) +{ +#if LUABRIDGE_SAFE_LUA_C_EXCEPTION_HANDLING && LUABRIDGE_HAS_EXCEPTIONS + lua_pushcfunction_x(L, fp, debugname); + lua_pushcclosure_x(L, invoke_safe_cfunction, debugname, 1); +#else + lua_pushcfunction_x(L, fp, debugname); +#endif +} + +// Generic function pointer +template +void push_member_function(lua_State* L, ReturnType (*fp)(T*, Params...), const char* debugname) +{ + using FnType = decltype(fp); + + lua_pushlightuserdata(L, reinterpret_cast(fp)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_member_function(lua_State* L, ReturnType (*fp)(T&, Params...), const char* debugname) +{ + using FnType = decltype(fp); + + lua_pushlightuserdata(L, reinterpret_cast(fp)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_member_function(lua_State* L, ReturnType (*fp)(T*, Params...) noexcept, const char* debugname) +{ + using FnType = decltype(fp); + + lua_pushlightuserdata(L, reinterpret_cast(fp)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_member_function(lua_State* L, ReturnType (*fp)(T&, Params...) noexcept, const char* debugname) +{ + using FnType = decltype(fp); + + lua_pushlightuserdata(L, reinterpret_cast(fp)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_member_function(lua_State* L, ReturnType (*fp)(const T*, Params...), const char* debugname) +{ + using FnType = decltype(fp); + + lua_pushlightuserdata(L, reinterpret_cast(fp)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_member_function(lua_State* L, ReturnType (*fp)(const T&, Params...), const char* debugname) +{ + using FnType = decltype(fp); + + lua_pushlightuserdata(L, reinterpret_cast(fp)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_member_function(lua_State* L, ReturnType (*fp)(const T*, Params...) noexcept, const char* debugname) +{ + using FnType = decltype(fp); + + lua_pushlightuserdata(L, reinterpret_cast(fp)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_member_function(lua_State* L, ReturnType (*fp)(const T&, Params...) noexcept, const char* debugname) +{ + using FnType = decltype(fp); + + lua_pushlightuserdata(L, reinterpret_cast(fp)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +// Callable object (lambdas) +template && + std::is_object_v && + !std::is_pointer_v && + !std::is_member_function_pointer_v>> +void push_member_function(lua_State* L, F&& f, const char* debugname) +{ + static_assert(std::is_same_v>>> || + is_reversed_proxy_function_v); + + lua_newuserdata_aligned(L, std::forward(f)); + lua_pushcclosure_x(L, &invoke_proxy_functor, debugname, 1); +} + +// Non const member function pointer +template +void push_member_function(lua_State* L, ReturnType (U::*mfp)(Params...), const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using F = decltype(mfp); + + new (lua_newuserdata_x(L, sizeof(F))) F(mfp); + lua_rawgetp_x(L, LUA_REGISTRYINDEX, detail::getClassRegistryKey()); + lua_pushcclosure_x(L, &invoke_member_function, debugname, 2); +} + +template +void push_member_function(lua_State* L, ReturnType (U::*mfp)(Params...) noexcept, const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using F = decltype(mfp); + + new (lua_newuserdata_x(L, sizeof(F))) F(mfp); + lua_rawgetp_x(L, LUA_REGISTRYINDEX, detail::getClassRegistryKey()); + lua_pushcclosure_x(L, &invoke_member_function, debugname, 2); +} + +// Const member function pointer +template +void push_member_function(lua_State* L, ReturnType (U::*mfp)(Params...) const, const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using F = decltype(mfp); + + new (lua_newuserdata_x(L, sizeof(F))) F(mfp); + lua_rawgetp_x(L, LUA_REGISTRYINDEX, detail::getClassRegistryKey()); + lua_rawgetp_x(L, LUA_REGISTRYINDEX, detail::getConstRegistryKey()); + lua_pushcclosure_x(L, &detail::invoke_const_member_function, debugname, 3); +} + +template +void push_member_function(lua_State* L, ReturnType (U::*mfp)(Params...) const noexcept, const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using F = decltype(mfp); + + new (lua_newuserdata_x(L, sizeof(F))) F(mfp); + lua_rawgetp_x(L, LUA_REGISTRYINDEX, detail::getClassRegistryKey()); + lua_rawgetp_x(L, LUA_REGISTRYINDEX, detail::getConstRegistryKey()); + lua_pushcclosure_x(L, &detail::invoke_const_member_function, debugname, 3); +} + +// Non const member Lua CFunction pointer +template +void push_member_function(lua_State* L, int (U::*mfp)(lua_State*), const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using F = decltype(mfp); + + new (lua_newuserdata_x(L, sizeof(F))) F(mfp); + lua_pushcclosure_x(L, &invoke_member_cfunction, debugname, 1); +} + +// Const member Lua CFunction pointer +template +void push_member_function(lua_State* L, int (U::*mfp)(lua_State*) const, const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using F = decltype(mfp); + + new (lua_newuserdata_x(L, sizeof(F))) F(mfp); + lua_pushcclosure_x(L, &invoke_const_member_cfunction, debugname, 1); +} + +//================================================================================================= +/** + * @brief + */ +template || !detail::is_callable_v)>> +void push_property_getter(lua_State* L, const T* value, const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(const_cast(value))); + lua_pushcclosure_x(L, &property_getter::call, debugname, 1); +} + +template +void push_property_getter(lua_State* L, T (*getter)(), const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(getter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_property_getter(lua_State* L, T (*getter)() noexcept, const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(getter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template >> +void push_property_getter(lua_State* L, T getter, const char* debugname) +{ + if constexpr (std::is_same_v) + { + lua_pushcfunction_x(L, getter, debugname); + } + else + { + lua_newuserdata_aligned(L, std::move(getter)); + lua_pushcclosure_x(L, &invoke_proxy_functor, debugname, 1); + } +} + +//================================================================================================= +/** + * @brief + */ +template +void push_class_property_getter(lua_State* L, T (U::*value), const char* debugname) +{ + using MemberValue = decltype(value); + + new (lua_newuserdata_x(L, sizeof(MemberValue))) MemberValue(value); + lua_pushcclosure_x(L, &property_getter::call, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (B::*getter)() const, const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using GetType = decltype(getter); + + new (lua_newuserdata_x(L, sizeof(GetType))) GetType(getter); + lua_pushcclosure_x(L, &invoke_const_member_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (B::*getter)() const noexcept, const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using GetType = decltype(getter); + + new (lua_newuserdata_x(L, sizeof(GetType))) GetType(getter); + lua_pushcclosure_x(L, &invoke_const_member_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (B::*getter)(lua_State*) const, const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using GetType = decltype(getter); + + new (lua_newuserdata_x(L, sizeof(GetType))) GetType(getter); + lua_pushcclosure_x(L, &invoke_const_member_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (B::*getter)(lua_State*) const noexcept, const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using GetType = decltype(getter); + + new (lua_newuserdata_x(L, sizeof(GetType))) GetType(getter); + lua_pushcclosure_x(L, &invoke_const_member_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (*getter)(const C*), const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(getter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (*getter)(const C&), const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(getter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (*getter)(const C*, lua_State*), const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(getter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (*getter)(const C&, lua_State*), const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(getter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (*getter)(const C*) noexcept, const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(getter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (*getter)(const C&) noexcept, const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(getter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (*getter)(const C*, lua_State*) noexcept, const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(getter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, T (*getter)(const C&, lua_State*) noexcept, const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(getter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_getter(lua_State* L, lua_CFunction getter, const char* debugname) +{ + lua_pushcfunction_x(L, getter, debugname); +} + +template && detail::is_callable_v>> +void push_class_property_getter(lua_State* L, T getter, const char* debugname) +{ + using FirstArg = detail::function_argument_t<0, T>; + static_assert(std::is_same_v>>, C>); + + lua_newuserdata_aligned(L, std::move(getter)); + lua_pushcclosure_x(L, &invoke_proxy_functor, debugname, 1); +} + +//================================================================================================= +/** + * @brief + */ +template || !detail::is_callable_v)>> +void push_property_setter(lua_State* L, T* value, const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(value)); + lua_pushcclosure_x(L, &property_setter::call, debugname, 1); +} + +template +void push_property_setter(lua_State* L, void (*setter)(T), const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(setter)); + lua_pushcclosure_x(L, &detail::invoke_proxy_function, debugname, 1); +} + +template +void push_property_setter(lua_State* L, void (*setter)(T) noexcept, const char* debugname) +{ + lua_pushlightuserdata(L, reinterpret_cast(setter)); + lua_pushcclosure_x(L, &detail::invoke_proxy_function, debugname, 1); +} + +template >> +void push_property_setter(lua_State* L, T setter, const char* debugname) +{ + if constexpr (std::is_same_v) + { + lua_pushcfunction_x(L, setter, debugname); + } + else + { + lua_newuserdata_aligned(L, std::move(setter)); + lua_pushcclosure_x(L, &invoke_proxy_functor, debugname, 1); + } +} + +//================================================================================================= +/** + * @brief + */ +template +void push_class_property_setter(lua_State* L, T U::*value, const char* debugname) +{ + using MemberValue = decltype(value); + + new (lua_newuserdata_x(L, sizeof(MemberValue))) MemberValue(value); + lua_pushcclosure_x(L, &property_setter::call, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (B::*setter)(T), const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using SetType = decltype(setter); + + new (lua_newuserdata_x(L, sizeof(SetType))) SetType(setter); + lua_pushcclosure_x(L, &invoke_member_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (B::*setter)(T) noexcept, const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using SetType = decltype(setter); + + new (lua_newuserdata_x(L, sizeof(SetType))) SetType(setter); + lua_pushcclosure_x(L, &invoke_member_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (B::*setter)(T, lua_State*), const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using SetType = decltype(setter); + + new (lua_newuserdata_x(L, sizeof(SetType))) SetType(setter); + lua_pushcclosure_x(L, &invoke_member_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (B::*setter)(T, lua_State*) noexcept, const char* debugname) +{ + static_assert(std::is_same_v || std::is_base_of_v); + + using SetType = decltype(setter); + + new (lua_newuserdata_x(L, sizeof(SetType))) SetType(setter); + lua_pushcclosure_x(L, &invoke_member_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (*setter)(C*, T), const char* debugname) +{ + lua_pushlightuserdata( L, reinterpret_cast(setter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (*setter)(C&, T), const char* debugname) +{ + lua_pushlightuserdata( L, reinterpret_cast(setter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (*setter)(C*, T, lua_State*), const char* debugname) +{ + lua_pushlightuserdata( L, reinterpret_cast(setter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (*setter)(C&, T, lua_State*), const char* debugname) +{ + lua_pushlightuserdata( L, reinterpret_cast(setter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (*setter)(C*, T) noexcept, const char* debugname) +{ + lua_pushlightuserdata( L, reinterpret_cast(setter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (*setter)(C&, T) noexcept, const char* debugname) +{ + lua_pushlightuserdata( L, reinterpret_cast(setter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (*setter)(C*, T, lua_State*) noexcept, const char* debugname) +{ + lua_pushlightuserdata( L, reinterpret_cast(setter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, void (*setter)(C&, T, lua_State*) noexcept, const char* debugname) +{ + lua_pushlightuserdata( L, reinterpret_cast(setter)); + lua_pushcclosure_x(L, &invoke_proxy_function, debugname, 1); +} + +template +void push_class_property_setter(lua_State* L, lua_CFunction setter, const char* debugname) +{ + lua_pushcfunction_x(L, setter, debugname); +} + +template && detail::is_callable_v>> +void push_class_property_setter(lua_State* L, T setter, const char* debugname) +{ + using FirstArg = detail::function_argument_t<0, T>; + static_assert(std::is_same_v>, C>); + + lua_newuserdata_aligned(L, std::move(setter)); + lua_pushcclosure_x(L, &invoke_proxy_functor, debugname, 1); +} + +//================================================================================================= +/** + * @brief + */ +inline void push_property_readonly(lua_State* L, const char* debugname) +{ + lua_pushstring(L, debugname); + lua_pushcclosure_x(L, &detail::read_only_error, debugname, 1); +} + +//================================================================================================= +/** + * @brief Constructor generators. + * + * These templates call operator new with the contents of a type/value list passed to the constructor. Two versions of call() are provided. + * One performs a regular new, the other performs a placement new. + */ +template +struct constructor +{ + static T* construct(const Args& args) + { + auto alloc = [](auto&&... args) { return new T(std::forward(args)...); }; + + return std::apply(alloc, args); + } + + static T* construct(void* ptr, const Args& args) + { + auto alloc = [ptr](auto&&... args) { return new (ptr) T(std::forward(args)...); }; + + return std::apply(alloc, args); + } +}; + +//================================================================================================= +/** + * @brief Placement constructor generators. + */ +template +struct placement_constructor +{ + template + static T* construct(void* ptr, F&& func, const Args& args) + { + auto alloc = [ptr, func = std::forward(func)](auto&&... args) { return func(ptr, std::forward(args)...); }; + + return std::apply(alloc, args); + } +}; + +//================================================================================================= +/** + * @brief Container allocator generators. + */ +template +struct container_constructor +{ + template + static C construct(F&& func, const Args& args) + { + auto alloc = [func = std::forward(func)](auto&&... args) { return func(std::forward(args)...); }; + + return std::apply(alloc, args); + } +}; + +//================================================================================================= +/** + * @brief External allocator generators. + */ +template +struct external_constructor +{ + template + static T* construct(F&& func, const Args& args) + { + auto alloc = [func = std::forward(func)](auto&&... args) { return func(std::forward(args)...); }; + + return std::apply(alloc, args); + } +}; + +//================================================================================================= +/** + * @brief lua_CFunction to construct a class object wrapped in a container. + */ +template +int constructor_container_proxy(lua_State* L) +{ + using T = typename ContainerTraits::Type; + + T* object = nullptr; + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + object = constructor::construct(make_arguments_list(L)); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + auto result = UserdataSharedHelper::push(L, object); + if (! result) + raise_lua_error(L, "%s", result.error_cstr()); + + return 1; +} + +/** + * @brief lua_CFunction to construct a class object in-place in the userdata. + */ +template +int constructor_placement_proxy(lua_State* L) +{ + auto args = make_arguments_list(L); + + std::error_code ec; + auto* value = UserdataValue::place(L, ec); + if (! value) + raise_lua_error(L, "%s", detail::ErrorCategory::errorString(ec.value())); + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + + constructor::construct(value->getObject(), std::move(args)); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + value->commit(); + + return 1; +} + +//================================================================================================= +/** + * @brief Constructor forwarder. + */ +template +struct constructor_forwarder +{ + explicit constructor_forwarder(F f) + : m_func(std::move(f)) + { + } + + T* operator()(lua_State* L) + { + using FnTraits = function_traits; + using FnArgs = remove_first_type_t; + + auto args = make_arguments_list(L); + + std::error_code ec; + auto* value = UserdataValue::place(L, ec); + if (! value) + raise_lua_error(L, "%s", detail::ErrorCategory::errorString(ec.value())); + + T* object = nullptr; + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + object = placement_constructor::construct(value->getObject(), m_func, std::move(args)); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + value->commit(); + + return object; + } + +private: + F m_func; +}; + +//================================================================================================= +/** + * @brief Constructor forwarder. + */ +template +struct destructor_forwarder +{ + explicit destructor_forwarder(F f) + : m_func(std::move(f)) + { + } + + void operator()(lua_State* L) + { + auto value = Userdata::get(L, -1, false); + if (! value) + raise_lua_error(L, "%s", value.error_cstr()); + + std::invoke(m_func, *value); + } + +private: + F m_func; +}; + +//================================================================================================= +/** + * @brief Constructor forwarder. + */ +template +struct factory_forwarder +{ + explicit factory_forwarder(Alloc alloc, Dealloc dealloc) + : m_alloc(std::move(alloc)) + , m_dealloc(std::move(dealloc)) + { + } + + T* operator()(lua_State* L) + { + using FnTraits = function_traits; + using FnArgs = typename FnTraits::argument_types; + + T* object = nullptr; + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + object = external_constructor::construct(m_alloc, make_arguments_list(L)); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } +#endif + + std::error_code ec; + auto* value = UserdataValueExternal::place(L, object, m_dealloc, ec); + if (! value) + raise_lua_error(L, "%s", detail::ErrorCategory::errorString(ec.value())); + + return object; + } + +private: + Alloc m_alloc; + Dealloc m_dealloc; +}; + +//================================================================================================= +/** + * @brief Container forwarder. + */ +template +struct container_forwarder +{ + explicit container_forwarder(F f) + : m_func(std::move(f)) + { + } + + C operator()(lua_State* L) + { + using FnTraits = function_traits; + using FnArgs = typename FnTraits::argument_types; + + alignas(C) std::byte object_storage[sizeof(C)]; + C* object = nullptr; + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + object = ::new (object_storage) C( + container_constructor::construct(m_func, make_arguments_list(L))); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + if (object != nullptr) + std::destroy_at(object); + + raise_lua_error(L, "%s", e.what()); + } +#endif + + LUABRIDGE_ASSERT(object != nullptr); + + Result result; + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { +#endif + result = UserdataSharedHelper::push(L, *object); + +#if LUABRIDGE_HAS_EXCEPTIONS + } + catch (const std::exception& e) + { + std::destroy_at(object); + + raise_lua_error(L, "%s", e.what()); + } +#endif + + if (! result) + { + std::destroy_at(object); + raise_lua_error(L, "%s", result.error_cstr()); + } + + C ret = std::move(*object); + std::destroy_at(object); + return ret; + } + +private: + F m_func; +}; + +} // namespace detail +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/ClassInfo.h b/external/include/LuaBridge3/LuaBridge/detail/ClassInfo.h new file mode 100644 index 0000000000..82e4899928 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/ClassInfo.h @@ -0,0 +1,259 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2020, Dmitry Tarakanov +// Copyright 2012, Vinnie Falco +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" + +#include +#include +#include + +#if defined __clang__ || defined __GNUC__ +#define LUABRIDGE_PRETTY_FUNCTION __PRETTY_FUNCTION__ +#define LUABRIDGE_PRETTY_FUNCTION_PREFIX '=' +#define LUABRIDGE_PRETTY_FUNCTION_SUFFIX ']' +#elif defined _MSC_VER +#define LUABRIDGE_PRETTY_FUNCTION __FUNCSIG__ +#define LUABRIDGE_PRETTY_FUNCTION_PREFIX '<' +#define LUABRIDGE_PRETTY_FUNCTION_SUFFIX '>' +#endif + +namespace luabridge { +namespace detail { + +[[nodiscard]] constexpr auto fnv1a(const char* s, std::size_t count) noexcept +{ + uint32_t seed = 2166136261u; + + for (std::size_t i = 0; i < count; ++i) + seed = static_cast(static_cast(seed ^ static_cast(*s++)) * 16777619u); + + if constexpr (sizeof(void*) == 8) + return static_cast(seed); + else + return seed; +} + +template +[[nodiscard]] static constexpr auto typeName(T* = nullptr) noexcept +{ + constexpr std::string_view prettyName{ LUABRIDGE_PRETTY_FUNCTION }; + + constexpr auto first = prettyName.find_first_not_of(' ', prettyName.find_first_of(LUABRIDGE_PRETTY_FUNCTION_PREFIX) + 1); + + return prettyName.substr(first, prettyName.find_last_of(LUABRIDGE_PRETTY_FUNCTION_SUFFIX) - first); +} + +template ().find_first_of('.')> +[[nodiscard]] static constexpr auto typeHash(T* = nullptr) noexcept +{ + constexpr auto stripped = typeName(); + + return fnv1a(stripped.data(), stripped.size()); +} + +//================================================================================================= +/** + * @brief A unique key for the exceptions in the registry. + */ +[[nodiscard]] inline void* getExceptionsKey() noexcept +{ + return reinterpret_cast(0xc7); +} + +//================================================================================================= +/** + * @brief A unique key for a type name in a metatable. + */ +[[nodiscard]] inline const void* getTypeKey() noexcept +{ + return reinterpret_cast(0x71); +} + +//================================================================================================= +/** + * @brief The key of a const table in another metatable. + */ +[[nodiscard]] inline const void* getConstKey() noexcept +{ + return reinterpret_cast(0xc07); +} + +//================================================================================================= +/** + * @brief The key of a class table in another metatable. + */ +[[nodiscard]] inline const void* getClassKey() noexcept +{ + return reinterpret_cast(0xc1a); +} + +//================================================================================================= +/** + * @brief The key of a class options table in another metatable. + */ +[[nodiscard]] inline const void* getClassOptionsKey() noexcept +{ + return reinterpret_cast(0xc2b); +} + +//================================================================================================= +/** + * @brief The key of a type identity tag in class/const metatables. + */ +[[nodiscard]] inline const void* getTypeIdentityKey() noexcept +{ + return reinterpret_cast(0xc2c); +} + +//================================================================================================= +/** + * @brief The key of a propget table in another metatable. + */ +[[nodiscard]] inline const void* getPropgetKey() noexcept +{ + return reinterpret_cast(0x6e7); +} + +//================================================================================================= +/** + * @brief The key of a propset table in another metatable. + */ +[[nodiscard]] inline const void* getPropsetKey() noexcept +{ + return reinterpret_cast(0x5e7); +} + +//================================================================================================= +/** + * @brief The key of a static table in another metatable. + */ +[[nodiscard]] inline const void* getStaticKey() noexcept +{ + return reinterpret_cast(0x57a); +} + +//================================================================================================= +/** + * @brief The key of a parent table in another metatable. + */ +[[nodiscard]] inline const void* getParentKey() noexcept +{ + return reinterpret_cast(0xdad); +} + +//================================================================================================= +/** + * @brief The key of a cast offset table in a derived class metatable. + * + * Maps base class registry keys to byte offsets for pointer adjustment when converting + * a derived class pointer to a base class pointer in multiple inheritance scenarios. + */ +[[nodiscard]] inline const void* getCastTableKey() noexcept +{ + return reinterpret_cast(0xca57); +} + +//================================================================================================= +/** + * The key of the index fall back in another metatable. + */ +[[nodiscard]] inline const void* getIndexFallbackKey() +{ + return reinterpret_cast(0x81ca); +} + +[[nodiscard]] inline const void* getIndexExtensibleKey() +{ + return reinterpret_cast(0x81cb); +} + +//================================================================================================= +/** + * The key of the new index fall back in another metatable. + */ +[[nodiscard]] inline const void* getNewIndexFallbackKey() +{ + return reinterpret_cast(0x8107); +} + +[[nodiscard]] inline const void* getNewIndexExtensibleKey() +{ + return reinterpret_cast(0x8108); +} + +//================================================================================================= +/** + * @brief The key of a ConverterRegistry userdata in a class metatable. + */ +[[nodiscard]] inline const void* getConvertersKey() noexcept +{ + return reinterpret_cast(0xc0de); +} + +//================================================================================================= +/** + * The key of the static index fall back in another metatable. + */ +[[nodiscard]] inline const void* getStaticIndexFallbackKey() +{ + return reinterpret_cast(0x81cc); +} + +//================================================================================================= +/** + * The key of the static new index fall back in another metatable. + */ +[[nodiscard]] inline const void* getStaticNewIndexFallbackKey() +{ + return reinterpret_cast(0x8109); +} + +//================================================================================================= +/** + * @brief Get the key for the static table in the Lua registry. + * + * The static table holds the static data members, static properties, and static member functions for a class. + */ +template +[[nodiscard]] const void* getStaticRegistryKey() noexcept +{ + static auto value = typeHash(); + + return reinterpret_cast(value); +} + +//================================================================================================= +/** + * @brief Get the key for the class table in the Lua registry. + * + * The class table holds the data members, properties, and member functions of a class. Read-only data and properties, and const + * member functions are also placed here (to save a lookup in the const table). + */ +template +[[nodiscard]] const void* getClassRegistryKey() noexcept +{ + static auto value = typeHash() ^ 1; + + return reinterpret_cast(value); +} + +//================================================================================================= +/** + * @brief Get the key for the const table in the Lua registry. + * + * The const table holds read-only data members and properties, and const member functions of a class. + */ +template +[[nodiscard]] const void* getConstRegistryKey() noexcept +{ + static auto value = typeHash() ^ 2; + + return reinterpret_cast(value); +} +} // namespace detail +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/Config.h b/external/include/LuaBridge3/LuaBridge/detail/Config.h new file mode 100644 index 0000000000..5918c53a3d --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Config.h @@ -0,0 +1,284 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2020, Dmitry Tarakanov +// Copyright 2019, George Tokmaji +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#if __has_include() +#include +#endif + +#if !(__cplusplus >= 201703L || (defined(_MSC_VER) && _HAS_CXX17)) +#error LuaBridge 3 requires a compliant C++17 compiler, or C++17 has not been enabled ! +#endif + +#if __cplusplus >= 202302L || (defined(_MSC_VER) && _HAS_CXX23) +#define LUABRIDGE_CXX23_OR_GREATER 1 +#elif __cplusplus >= 202002L || (defined(_MSC_VER) && _HAS_CXX20) +#define LUABRIDGE_CXX20_OR_GREATER 1 +#endif + +#if defined(LUAU_FASTMATH_BEGIN) +#define LUABRIDGE_ON_LUAU 1 +#elif defined(LUAJIT_VERSION) +#define LUABRIDGE_ON_LUAJIT 1 +#elif defined(RAVI_OPTION_STRING2) +#define LUABRIDGE_ON_RAVI 1 +#elif defined(LUA_VERSION_NUM) +#define LUABRIDGE_ON_LUA 1 +#else +#error "Lua headers must be included prior to LuaBridge ones" +#endif + +#if !defined(LUABRIDGE_HAS_EXCEPTIONS) +#if defined(_MSC_VER) +#if _CPPUNWIND || _HAS_EXCEPTIONS +#define LUABRIDGE_HAS_EXCEPTIONS 1 +#else +#define LUABRIDGE_HAS_EXCEPTIONS 0 +#endif +#elif defined(__clang__) +#if __EXCEPTIONS && __has_feature(cxx_exceptions) +#define LUABRIDGE_HAS_EXCEPTIONS 1 +#else +#define LUABRIDGE_HAS_EXCEPTIONS 0 +#endif +#elif defined(__GNUC__) +#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) +#define LUABRIDGE_HAS_EXCEPTIONS 1 +#else +#define LUABRIDGE_HAS_EXCEPTIONS 0 +#endif +#endif +#endif + +#if LUABRIDGE_HAS_EXCEPTIONS +#define LUABRIDGE_IF_EXCEPTIONS(...) __VA_ARGS__ +#define LUABRIDGE_IF_NO_EXCEPTIONS(...) +#else +#define LUABRIDGE_IF_EXCEPTIONS(...) +#define LUABRIDGE_IF_NO_EXCEPTIONS(...) __VA_ARGS__ +#endif + +#if defined(__clang__) || defined(__GNUC__) +#define LUABRIDGE_NO_SANITIZE(x) __attribute__((no_sanitize(x))) +#else +#define LUABRIDGE_NO_SANITIZE(x) +#endif + +#if defined(__OBJC__) +#define LUABRIDGE_ON_OBJECTIVE_C 1 +#endif + +/** + * @brief Enable safe stack checks to avoid lua stack overflow when pushing values on the stack. + * + * @note Default is enabled. + */ +#if !defined(LUABRIDGE_SAFE_STACK_CHECKS) +#define LUABRIDGE_SAFE_STACK_CHECKS 1 +#endif + +/** + * @brief Enable strict stack conversions to enforce exact type matching when getting values from the stack. + * + * When enabled: + * - `Stack::get` only accepts `LUA_TBOOLEAN` (nil is not convertible to bool). + * - Integer `Stack` specializations only accept Lua integer values (not floats with integer representation, on Lua 5.3+). + * - `Stack::get` only accepts `LUA_TSTRING` (numbers are not coerced to strings). + * + * When disabled (default), a more permissive conversion is used: + * - `Stack::get` accepts `LUA_TBOOLEAN` and `LUA_TNIL` (nil converts to false). + * - Integer `Stack` specializations accept any `LUA_TNUMBER` that can be represented as the target integer type. + * - `Stack::get` accepts `LUA_TSTRING` and `LUA_TNUMBER` (numbers are coerced to strings). + * + * @note Default is disabled. + */ +#if !defined(LUABRIDGE_STRICT_STACK_CONVERSIONS) +#define LUABRIDGE_STRICT_STACK_CONVERSIONS 0 +#endif + +/** + * @brief Convert Lua numbers to C++ numbers the way luabind did. (Cortex Command addition.) + * + * When enabled, integer `Stack` specializations truncate any `LUA_TNUMBER` towards zero (as `static_cast` from `lua_Number` does) instead of + * rejecting numbers with a fractional part or out of the target type's range, and floating point specializations don't range-check. + * + * @note Default is disabled. + */ +#if !defined(LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS) +#define LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS 0 +#endif + +/** + * @brief Enable safe exception handling when lua is compiled as `C` and exceptions raise during execution of registered `lua_CFunction`. + * + * This is a problem that manifests when exceptions are leaking a CFunction when lua is compiled as `C` because the library will then longjmp + * instead of correctly unwinding the exception into C++ land. If you have exceptions enabled and are compiling lua as `C` and you are getting random + * crashes when invoking CFunctions that throw, you have two options: or you catch exceptions in your CFunction and raise a `lua_error` instead + * or you enable this macro, which will add a safe indirection doing exceptions catching and raising when invoking your registered CFunction. + * + * @warning When enabled, some performance degradation is to be expected when invoking registered `lua_CFunction` through the library. + * + * @note Default is disabled, can only be enabled when `LUABRIDGE_HAS_EXCEPTIONS` is 1. + */ +#if !defined(LUABRIDGE_SAFE_LUA_C_EXCEPTION_HANDLING) +#define LUABRIDGE_SAFE_LUA_C_EXCEPTION_HANDLING 0 +#endif + +/** + * @brief Control raising when an unregistered class is used. + * + * @note Default is enabled when exceptions are enabled, disabled otherwise. + */ +#if !defined(LUABRIDGE_RAISE_UNREGISTERED_CLASS_USAGE) +#if LUABRIDGE_HAS_EXCEPTIONS +#define LUABRIDGE_RAISE_UNREGISTERED_CLASS_USAGE 1 +#else +#define LUABRIDGE_RAISE_UNREGISTERED_CLASS_USAGE 0 +#endif +#endif + + +/** + * @brief Control the assertion mechanism used by the library. + * + * @note By default, assertions are enabled in debug builds and disabled in release builds. Define LUABRIDGE_FORCE_ASSERT_RELEASE to enable assertions even in release builds. + */ +#if !defined(LUABRIDGE_ASSERT) +#if defined(NDEBUG) && !defined(LUABRIDGE_FORCE_ASSERT_RELEASE) +#define LUABRIDGE_ASSERT(expr) ((void)(expr)) +#else +#define LUABRIDGE_ASSERT(expr) assert(expr) +#endif +#endif + +/** + * @brief Enable C++17 filesystem library support. + * + * Requires C++17 and the filesystem header to be available. + * Define LUABRIDGE_DISABLE_CXX17_FILESYSTEM to force-disable even when available. + */ +#if !defined(LUABRIDGE_HAS_CXX17_FILESYSTEM) +#if !defined(LUABRIDGE_DISABLE_CXX17_FILESYSTEM) && __has_include() && defined(__cpp_lib_filesystem) +#define LUABRIDGE_HAS_CXX17_FILESYSTEM 1 +#else +#define LUABRIDGE_HAS_CXX17_FILESYSTEM 0 +#endif +#endif + +/** + * @brief Enable C++17 any library support. + * + * Requires C++17 and the any header to be available. + * Define LUABRIDGE_DISABLE_CXX17_ANY to force-disable even when available. + */ +#if !defined(LUABRIDGE_HAS_CXX17_ANY) +#if !defined(LUABRIDGE_DISABLE_CXX17_ANY) && __has_include() && defined(__cpp_lib_any) +#define LUABRIDGE_HAS_CXX17_ANY 1 +#else +#define LUABRIDGE_HAS_CXX17_ANY 0 +#endif +#endif + +/** + * @brief Enable C++20 span library support. + * + * Requires C++20 and the span header to be available. + * Define LUABRIDGE_DISABLE_CXX20_SPAN to force-disable even when available. + */ +#if !defined(LUABRIDGE_HAS_CXX20_SPAN) +#if !defined(LUABRIDGE_DISABLE_CXX20_SPAN) && LUABRIDGE_CXX20_OR_GREATER && __has_include() && defined(__cpp_lib_span) +#define LUABRIDGE_HAS_CXX20_SPAN 1 +#else +#define LUABRIDGE_HAS_CXX20_SPAN 0 +#endif +#endif + +/** + * @brief Enable C++20 ranges library support. + * + * Requires C++20 and the ranges header to be available. + * Define LUABRIDGE_DISABLE_CXX20_RANGES to force-disable even when available. + */ +#if !defined(LUABRIDGE_HAS_CXX20_RANGES) +#if !defined(LUABRIDGE_DISABLE_CXX20_RANGES) && LUABRIDGE_CXX20_OR_GREATER && defined(__cpp_lib_ranges) +#define LUABRIDGE_HAS_CXX20_RANGES 1 +#else +#define LUABRIDGE_HAS_CXX20_RANGES 0 +#endif +#endif + +/** + * @brief Enable C++20 coroutine integration with Lua coroutines. + * + * Requires C++20 and Lua 5.2+ (lua_yieldk). Not supported on Lua 5.1, LuaJIT, or Luau. + * Define LUABRIDGE_DISABLE_CXX20_COROUTINES to force-disable even when C++20 is available. + */ +#if !defined(LUABRIDGE_HAS_CXX20_COROUTINES) +#if !defined(LUABRIDGE_DISABLE_CXX20_COROUTINES) && LUABRIDGE_CXX20_OR_GREATER && !(LUABRIDGE_ON_LUAU || LUABRIDGE_ON_LUAJIT || LUABRIDGE_ON_RAVI || LUA_VERSION_NUM < 502) +#define LUABRIDGE_HAS_CXX20_COROUTINES 1 +#else +#define LUABRIDGE_HAS_CXX20_COROUTINES 0 +#endif +#endif + +/** + * @brief Enable C++23 expected library support. + * + * Requires C++23 and the expected header to be available. + * Define LUABRIDGE_DISABLE_CXX23_EXPECTED to force-disable even when available. + */ +#if !defined(LUABRIDGE_HAS_CXX23_EXPECTED) +#if !defined(LUABRIDGE_DISABLE_CXX23_EXPECTED) && LUABRIDGE_CXX23_OR_GREATER && __has_include() && defined(__cpp_lib_expected) +#define LUABRIDGE_HAS_CXX23_EXPECTED 1 +#else +#define LUABRIDGE_HAS_CXX23_EXPECTED 0 +#endif +#endif + +/** + * @brief Enable C++23 flat map library support. + * + * Requires C++23 and the flat_map header to be available. + * Define LUABRIDGE_DISABLE_CXX23_FLAT_MAP to force-disable even when available. + */ +#if !defined(LUABRIDGE_HAS_CXX23_FLAT_MAP) +#if !defined(LUABRIDGE_DISABLE_CXX23_FLAT_MAP) && LUABRIDGE_CXX23_OR_GREATER && __has_include() && defined(__cpp_lib_flat_map) +#define LUABRIDGE_HAS_CXX23_FLAT_MAP 1 +#else +#define LUABRIDGE_HAS_CXX23_FLAT_MAP 0 +#endif +#endif + +/** + * @brief Enable C++23 flat set library support. + * + * Requires C++23 and the flat_set header to be available. + * Define LUABRIDGE_DISABLE_CXX23_FLAT_SET to force-disable even when available. + */ +#if !defined(LUABRIDGE_HAS_CXX23_FLAT_SET) +#if !defined(LUABRIDGE_DISABLE_CXX23_FLAT_SET) && LUABRIDGE_CXX23_OR_GREATER && __has_include() && defined(__cpp_lib_flat_set) +#define LUABRIDGE_HAS_CXX23_FLAT_SET 1 +#else +#define LUABRIDGE_HAS_CXX23_FLAT_SET 0 +#endif +#endif + +/** + * @brief Enable C++23 move_only_function library support. + * + * Requires C++23 and move_only_function to be available. + * Define LUABRIDGE_DISABLE_CXX23_MOVE_ONLY_FUNCTION to force-disable even when available. + */ +#if !defined(LUABRIDGE_HAS_CXX23_MOVE_ONLY_FUNCTION) +#if !defined(LUABRIDGE_DISABLE_CXX23_MOVE_ONLY_FUNCTION) && LUABRIDGE_CXX23_OR_GREATER && defined(__cpp_lib_move_only_function) +#define LUABRIDGE_HAS_CXX23_MOVE_ONLY_FUNCTION 1 +#else +#define LUABRIDGE_HAS_CXX23_MOVE_ONLY_FUNCTION 0 +#endif +#endif diff --git a/external/include/LuaBridge3/LuaBridge/detail/Converter.h b/external/include/LuaBridge3/LuaBridge/detail/Converter.h new file mode 100644 index 0000000000..f2bafcf4cc --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Converter.h @@ -0,0 +1,183 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2026, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "ClassInfo.h" +#include "Errors.h" +#include "LuaHelpers.h" +#include "Result.h" + +#include +#include +#include +#include +#include + +namespace luabridge { + +// Forward declaration. +template +struct Stack; + +//================================================================================================= +/** + * @brief Opt-in trait for enabling custom type converters for type T. + * + * Specialize with enabled = true so that Stack::get consults the metatable + * converter registry as a Phase 3 fallback after Phase 1 (exact match) and + * Phase 2 (inheritance) both fail. + * + * Example: + * template <> struct luabridge::StackConversion { static constexpr bool enabled = true; }; + */ +template +struct StackConversion +{ + static constexpr bool enabled = false; +}; + +//================================================================================================= +/** + * @brief User-defined conversion hook from source type From to target type To. + * + * Specialize this template for each (To, From) pair and provide: + * static To convert(const From& from); + * + * Example: + * template <> + * struct luabridge::StackConverter { + * static Vec3 convert(const glm::vec3& v) { return {v.x, v.y, v.z}; } + * }; + */ +template +struct StackConverter; + +//================================================================================================= + +namespace detail { + +struct ConverterRegistry +{ + std::unordered_map converters; +}; + +inline ConverterRegistry* getOrCreateConverterRegistry(lua_State* L, int metatableIdx) +{ + const int absIdx = lua_absindex(L, metatableIdx); + + lua_rawgetp_x(L, absIdx, getConvertersKey()); + if (lua_isuserdata(L, -1) && !lua_islightuserdata(L, -1)) + { + auto* reg = align(lua_touserdata(L, -1)); + lua_pop(L, 1); + return reg; + } + lua_pop(L, 1); // pop nil or unexpected value + + // Create ConverterRegistry as an aligned Lua full userdata with automatic __gc + lua_newuserdata_aligned(L); + auto* reg = align(lua_touserdata(L, -1)); + + // Store the userdata in the class metatable + lua_pushvalue(L, -1); // dup userdata + lua_rawsetp_x(L, absIdx, getConvertersKey()); // store, pops dup + lua_pop(L, 1); // pop the original userdata + + return reg; +} + +template +class ConverterConstRef +{ +public: + explicit ConverterConstRef(const T& value) noexcept + : m_ref(std::addressof(value)) + { + } + + explicit ConverterConstRef(T&& value) noexcept(std::is_nothrow_move_constructible_v) + : m_value(std::move(value)) + , m_ref(std::addressof(*m_value)) + { + } + + ConverterConstRef(ConverterConstRef&& other) noexcept(std::is_nothrow_move_constructible_v) + : m_value(std::move(other.m_value)) + , m_ref(m_value.has_value() ? std::addressof(*m_value) : other.m_ref) + { + } + + ConverterConstRef(const ConverterConstRef& other) + : m_value(other.m_value) + , m_ref(m_value.has_value() ? std::addressof(*m_value) : other.m_ref) + { + } + + ConverterConstRef& operator=(ConverterConstRef&& other) noexcept(std::is_nothrow_move_assignable_v) + { + m_value = std::move(other.m_value); + m_ref = m_value.has_value() ? std::addressof(*m_value) : other.m_ref; + return *this; + } + + ConverterConstRef& operator=(const ConverterConstRef& other) + { + m_value = other.m_value; + m_ref = m_value.has_value() ? std::addressof(*m_value) : other.m_ref; + return *this; + } + + operator const T&() const noexcept + { + return *m_ref; + } + +private: + std::optional m_value; + const T* m_ref = nullptr; +}; + +template +TypeResult tryConvertFromRegisteredConverter(lua_State* L, int index) +{ + using FnType = TypeResult(*)(lua_State*, int); + + if (! lua_getmetatable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + lua_rawgetp_x(L, -1, detail::getConvertersKey()); + if (lua_isuserdata(L, -1) && !lua_islightuserdata(L, -1)) + { + auto* reg = align(lua_touserdata(L, -1)); + lua_pop(L, 2); // registry userdata + metatable + + auto it = reg->converters.find(detail::getClassRegistryKey()); + if (it != reg->converters.end() && it->second) + { + const auto* fn = static_cast(it->second); + return (*fn)(L, index); + } + } + else + { + lua_pop(L, 2); // nil/other + metatable + } + + return makeErrorCode(ErrorCode::InvalidTypeCast); +} + +template +TypeResult convertFromStack(lua_State* L, int index) +{ + auto result = detail::Userdata::get(L, index, true); + + if (!result || !*result) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + return StackConverter::convert(**result); +} + +} // namespace detail +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/Coroutine.h b/external/include/LuaBridge3/LuaBridge/detail/Coroutine.h new file mode 100644 index 0000000000..2afb92909d --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Coroutine.h @@ -0,0 +1,492 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2026, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" +#include "CFunctions.h" +#include "Errors.h" +#include "LuaHelpers.h" +#include "Stack.h" + +#if LUABRIDGE_HAS_CXX20_COROUTINES + +#if LUABRIDGE_ON_LUAJIT || LUA_VERSION_NUM == 501 || LUABRIDGE_ON_LUAU +#ifndef LUABRIDGE_DISABLE_COROUTINE_INTEGRATION +#error "C++20 coroutine integration requires Lua 5.2+ with lua_yieldk support. Define LUABRIDGE_DISABLE_COROUTINE_INTEGRATION to suppress this error." +#endif +#else + +#include +#include +#include +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief A C++20 coroutine type callable from Lua. + * + * Register instances via Namespace::addCoroutine(). When called from Lua, the coroutine body + * runs until the first co_yield (which yields a value back to Lua) or co_return (which + * returns a final value). Subsequent Lua resumes continue the body from the last suspension point. + * + * @tparam R The type yielded/returned by the coroutine. May be void. + * + * Example: + * @code + * luabridge::getGlobalNamespace(L) + * .addCoroutine("range", [](int start, int stop) -> luabridge::CppCoroutine { + * for (int i = start; i < stop; ++i) + * co_yield i; + * co_return -1; + * }); + * @endcode + * + * @note Requires Lua 5.2+ (lua_yieldk). Not supported on Lua 5.1, LuaJIT, or Luau. + * @note Not thread-safe. Must be driven from a single OS thread. + */ +template +struct CppCoroutine +{ + struct promise_type + { + lua_State* L = nullptr; + int nresults = 0; + bool is_done = false; + std::exception_ptr exception; + + std::suspend_always initial_suspend() noexcept { return {}; } + std::suspend_always final_suspend() noexcept { return {}; } + + void unhandled_exception() noexcept + { + exception = std::current_exception(); + } + + std::suspend_always yield_value(const R& value) + { + nresults = 0; + if (L) + { + auto result = Stack::push(L, value); + if (result) + nresults = 1; + else + exception = std::make_exception_ptr(std::system_error(result.error())); + } + return {}; + } + + std::suspend_always yield_value(R&& value) + { + nresults = 0; + if (L) + { + auto result = Stack::push(L, std::move(value)); + if (result) + nresults = 1; + else + exception = std::make_exception_ptr(std::system_error(result.error())); + } + return {}; + } + + void return_value(const R& value) + { + nresults = 0; + if (L) + { + auto result = Stack::push(L, value); + if (result) + nresults = 1; + else + exception = std::make_exception_ptr(std::system_error(result.error())); + } + is_done = true; + } + + void return_value(R&& value) + { + nresults = 0; + if (L) + { + auto result = Stack::push(L, std::move(value)); + if (result) + nresults = 1; + else + exception = std::make_exception_ptr(std::system_error(result.error())); + } + is_done = true; + } + + CppCoroutine get_return_object() + { + return CppCoroutine{ std::coroutine_handle::from_promise(*this) }; + } + }; + + std::coroutine_handle handle; + + explicit CppCoroutine(std::coroutine_handle h) noexcept + : handle(h) + { + } + + CppCoroutine(CppCoroutine&& other) noexcept + : handle(std::exchange(other.handle, {})) + { + } + + CppCoroutine(const CppCoroutine&) = delete; + CppCoroutine& operator=(const CppCoroutine&) = delete; + ~CppCoroutine() = default; +}; + +//================================================================================================= +/** + * @brief Specialisation for void-returning coroutines. + */ +template <> +struct CppCoroutine +{ + struct promise_type + { + lua_State* L = nullptr; + int nresults = 0; + bool is_done = false; + std::exception_ptr exception; + + std::suspend_always initial_suspend() noexcept { return {}; } + std::suspend_always final_suspend() noexcept { return {}; } + + void unhandled_exception() noexcept + { + exception = std::current_exception(); + } + + void return_void() + { + nresults = 0; + is_done = true; + } + + CppCoroutine get_return_object() + { + return CppCoroutine{ std::coroutine_handle::from_promise(*this) }; + } + }; + + std::coroutine_handle handle; + + explicit CppCoroutine(std::coroutine_handle h) noexcept + : handle(h) + { + } + + CppCoroutine(CppCoroutine&& other) noexcept + : handle(std::exchange(other.handle, {})) + { + } + + CppCoroutine(const CppCoroutine&) = delete; + CppCoroutine& operator=(const CppCoroutine&) = delete; + ~CppCoroutine() = default; +}; + +//================================================================================================= +/** + * @brief An awaitable wrapper around a Lua coroutine thread. + * + * Use inside a CppCoroutine body to synchronously resume a child Lua thread and obtain + * the number of values it left on its stack (either from yield or return). + * + * @note Runs the Lua thread synchronously (no external event loop required). + */ +class LuaCoroutine +{ +public: + LuaCoroutine(lua_State* thread, lua_State* from = nullptr) noexcept + : m_thread(thread) + , m_from(from) + { + } + + bool await_ready() noexcept + { + m_status = lua_resume_x(m_thread, m_from, 0, &m_nresults); + return true; // Always ready: runs synchronously + } + + void await_suspend(std::coroutine_handle<>) noexcept + { + // Never called because await_ready always returns true + } + + /** + * @returns {status, nresults} where status is LUA_OK or LUA_YIELD, + * and nresults is the number of values on the thread's stack. + */ + std::pair await_resume() noexcept + { + return { m_status, m_nresults }; + } + +private: + lua_State* m_thread; + lua_State* m_from; + int m_status = LUABRIDGE_LUA_OK; + int m_nresults = 0; +}; + +//================================================================================================= +namespace detail { + +/** + * @brief Trait: is T a CppCoroutine specialisation? + */ +template +struct is_cpp_coroutine : std::false_type +{ +}; + +template +struct is_cpp_coroutine> : std::true_type +{ +}; + +/** + * @brief Trait: does callable F return a CppCoroutine? + */ +template +struct is_cpp_coroutine_factory : std::false_type +{ +}; + +template +struct is_cpp_coroutine_factory>::result_type>> + : is_cpp_coroutine>::result_type> +{ +}; + +template +inline constexpr bool is_cpp_coroutine_factory_v = is_cpp_coroutine_factory::value; + +//================================================================================================= +/** + * @brief RAII frame for a suspended CppCoroutine, stored as a Lua full userdata. + * + * Kept alive on the Lua thread's own stack (not in the registry) so that abandoning the + * coroutine — i.e. letting the Lua thread be collected by the GC — automatically triggers + * the __gc metamethod, which calls the destructor and destroys the coroutine handle. + */ +template +struct CppCoroutineFrame +{ + using HandleType = std::coroutine_handle; + + HandleType handle; + + explicit CppCoroutineFrame(HandleType h) noexcept + : handle(h) + { + } + + CppCoroutineFrame(const CppCoroutineFrame&) = delete; + CppCoroutineFrame& operator=(const CppCoroutineFrame&) = delete; + + ~CppCoroutineFrame() + { + if (handle && !handle.done()) + handle.destroy(); + } +}; + +//================================================================================================= +// Version-portable yield helpers. +// +// Lua 5.2: lua_yieldk ctx is int; continuation signature is (lua_State*, int) — ctx +// retrieved inside via lua_getctx(). +// Lua 5.3+: lua_yieldk ctx is lua_KContext; continuation signature is +// (lua_State*, int, lua_KContext) — ctx passed directly. + +// Forward declarations +template int coroutine_continuation_body(lua_State* L, int frame_abs_idx); + +#if LUA_VERSION_NUM < 503 +// Lua 5.2: lua_yieldk takes lua_CFunction (int(*)(lua_State*)) as continuation. +// The context is recovered inside via lua_getctx(). +template +int coroutine_continuation(lua_State* L) +{ + int frame_abs_idx = 0; + lua_getctx(L, &frame_abs_idx); + return coroutine_continuation_body(L, frame_abs_idx); +} + +template +int do_yield(lua_State* L, int nresults, int frame_abs_idx) +{ + return lua_yieldk(L, nresults, frame_abs_idx, &coroutine_continuation); +} +#else +// Lua 5.3+: continuation receives lua_KContext directly. +template +int coroutine_continuation(lua_State* L, int /*status*/, lua_KContext ctx) +{ + return coroutine_continuation_body(L, static_cast(ctx)); +} + +template +int do_yield(lua_State* L, int nresults, int frame_abs_idx) +{ + return lua_yieldk(L, nresults, static_cast(frame_abs_idx), &coroutine_continuation); +} +#endif + +//================================================================================================= +/** + * @brief Raises a Lua error from a stored C++ exception (or a generic message). + * Removes the frame userdata from the stack before raising so GC can collect it. + */ +[[noreturn]] inline void raise_from_exception(lua_State* L, int frame_abs_idx, [[maybe_unused]] std::exception_ptr ex) +{ + lua_settop(L, frame_abs_idx - 1); // pop frame (and any value above it) — GC will collect it + +#if LUABRIDGE_HAS_EXCEPTIONS + try + { + std::rethrow_exception(ex); + } + catch (const std::exception& e) + { + raise_lua_error(L, "%s", e.what()); + } + catch (...) + { +#endif + + raise_lua_error(L, "unknown exception in C++ coroutine"); + +#if LUABRIDGE_HAS_EXCEPTIONS + } +#endif +} + +//================================================================================================= +/** + * @brief Common body for the coroutine continuation: resumes the C++ coroutine handle + * and either yields again or returns the final result. + * + * @param frame_abs_idx Absolute stack index where the CppCoroutineFrame userdata lives. + * Any resume arguments pushed above it are discarded first. + */ +template +int coroutine_continuation_body(lua_State* L, int frame_abs_idx) +{ + using CoroType = typename function_traits>::result_type; + using FrameType = CppCoroutineFrame; + + // Discard resume arguments pushed above the frame (we don't expose them to C++ yet) + lua_settop(L, frame_abs_idx); + + // Recover the frame from its stable stack position + auto* frame = align(lua_touserdata(L, frame_abs_idx)); + + // Resume the C++ coroutine body; yield_value/return_value will push at frame_abs_idx+1 + frame->handle.resume(); + + auto& promise = frame->handle.promise(); + + if (promise.exception) + raise_from_exception(L, frame_abs_idx, promise.exception); + + if (promise.is_done) + { + if (promise.nresults == 1) + lua_replace(L, frame_abs_idx); // swap return value into frame slot; pops frame userdata + else + lua_settop(L, frame_abs_idx - 1); // void: remove frame entirely + return promise.nresults; + } + + // yield_value pushed one value above the frame; yield it, keeping frame below + return do_yield(L, promise.nresults, frame_abs_idx); +} + +//================================================================================================= +/** + * @brief lua_CFunction entry point for a registered CppCoroutine factory. + * + * Upvalue 1: the factory functor F (as aligned full userdata). + * + * The CppCoroutineFrame userdata is left on the Lua thread's own stack (not in the registry). + * This means an abandoned coroutine is naturally cleaned up when the Lua thread is GC'd. + */ +template +int invoke_coroutine_entry(lua_State* L) +{ + using FnTraits = function_traits>; + using ArgsPack = typename FnTraits::argument_types; + using CoroType = typename FnTraits::result_type; + using FrameType = CppCoroutineFrame; + + LUABRIDGE_ASSERT(isfulluserdata(L, lua_upvalueindex(1))); + auto& factory = *align(lua_touserdata(L, lua_upvalueindex(1))); + + // Invoke the factory to create the coroutine object. + // The coroutine body does not run yet (initial_suspend returns suspend_always). + auto coro = invoke_callable_from_stack(L, factory); + + // Push the frame as a Lua full userdata and remember its absolute stack position. + // It is NOT pinned in the registry; keeping it on the thread's stack means GC will + // collect it (via __gc) when the Lua thread is abandoned. + lua_newuserdata_aligned(L, std::move(coro.handle)); + coro.handle = {}; // ownership transferred to frame + + int frame_abs_idx = lua_gettop(L); + auto* frame = align(lua_touserdata(L, frame_abs_idx)); + + // Give the promise access to the Lua state so yield_value/return_value can push values + frame->handle.promise().L = L; + + // First resume: runs the body to the first co_yield or co_return + frame->handle.resume(); + + auto& promise = frame->handle.promise(); + + if (promise.exception) + raise_from_exception(L, frame_abs_idx, promise.exception); + + if (promise.is_done) + { + if (promise.nresults == 1) + lua_replace(L, frame_abs_idx); // swap return value into frame slot + else + lua_settop(L, frame_abs_idx - 1); // void: remove frame + return promise.nresults; + } + + // yield_value pushed one value above the frame; yield it, keeping frame below + return do_yield(L, promise.nresults, frame_abs_idx); +} + +//================================================================================================= +/** + * @brief Pushes a CppCoroutine factory as a Lua closure onto the stack. + */ +template >> +inline void push_coroutine_function(lua_State* L, F&& f, const char* debugname) +{ + using FDecay = std::decay_t; + lua_newuserdata_aligned(L, std::forward(f)); + lua_pushcclosure_x(L, &invoke_coroutine_entry, debugname, 1); +} + +} // namespace detail +} // namespace luabridge + +#endif // !Lua 5.1 / LuaJIT / Luau +#endif // LUABRIDGE_HAS_CXX20_COROUTINES diff --git a/external/include/LuaBridge3/LuaBridge/detail/Enum.h b/external/include/LuaBridge3/LuaBridge/detail/Enum.h new file mode 100644 index 0000000000..b782712cfc --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Enum.h @@ -0,0 +1,67 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2023, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" +#include "Errors.h" +#include "LuaHelpers.h" +#include "Stack.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief LuaBridge enum wrapper for enums as integers. + * + * An enum exposed with this class will just be decayed to lua as integer. It's responsibility of + * the developer to make sure that a lua integer could be converted back to C++. Failing to validate a lua + * integer before converting to the corresponding C++ enum value could lead to a C++ enum that has no defined value. + * + * For improved security, specify which values the enum will have, so runtime validation could be performed. + */ +template +struct Enum +{ + static_assert(std::is_enum_v); + + using Type = std::underlying_type_t; + + [[nodiscard]] static Result push(lua_State* L, T value) + { + return Stack::push(L, static_cast(value)); + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + const auto result = Stack::get(L, index); + if (! result) + return result.error(); + + if constexpr (sizeof...(Values) > 0) + { + constexpr Type values[] = { static_cast(Values)... }; + for (std::size_t i = 0; i < sizeof...(Values); ++i) + { + if (values[i] == *result) + return static_cast(*result); + } + + return makeErrorCode(ErrorCode::InvalidTypeCast); + } + else + { + return static_cast(*result); + } + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_type(L, index) == LUA_TNUMBER; + } +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/Errors.h b/external/include/LuaBridge3/LuaBridge/detail/Errors.h new file mode 100644 index 0000000000..a9f091a01a --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Errors.h @@ -0,0 +1,123 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2021, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" + +#include + +namespace luabridge { + +//================================================================================================= +namespace detail { + +static inline constexpr char error_lua_stack_overflow[] = "stack overflow"; + +} // namespace detail + +//================================================================================================= +/** + * @brief LuaBridge error codes. + */ +enum class ErrorCode +{ + ClassNotRegistered = 1, + + LuaStackOverflow, + + LuaFunctionCallFailed, + + IntegerDoesntFitIntoLuaInteger, + + FloatingPointDoesntFitIntoLuaNumber, + + InvalidTypeCast, + + InvalidTableSizeInCast, + + CoroutineYieldFromNonCoroutine, + + CoroutineAlreadyDone +}; + +//================================================================================================= +namespace detail { +struct ErrorCategory : std::error_category +{ + const char* name() const noexcept override + { + return "luabridge"; + } + + std::string message(int ev) const override + { + return errorString(ev); + } + + static const char* errorString(int ev) noexcept + { + switch (static_cast(ev)) + { + case ErrorCode::ClassNotRegistered: + return "The class is not registered in LuaBridge"; + + case ErrorCode::LuaStackOverflow: + return "The lua stack has overflow"; + + case ErrorCode::LuaFunctionCallFailed: + return "The lua function invocation raised an error"; + + case ErrorCode::IntegerDoesntFitIntoLuaInteger: + return "The native integer can't fit inside a lua integer"; + + case ErrorCode::FloatingPointDoesntFitIntoLuaNumber: + return "The native floating point can't fit inside a lua number"; + + case ErrorCode::InvalidTypeCast: + return "The lua object can't be cast to desired type"; + + case ErrorCode::InvalidTableSizeInCast: + return "The lua table has different size than expected"; + + case ErrorCode::CoroutineYieldFromNonCoroutine: + return "Cannot yield from a non-coroutine Lua state"; + + case ErrorCode::CoroutineAlreadyDone: + return "The Lua coroutine has already finished execution"; + + default: + return "Unknown error"; + } + } + + static const ErrorCategory& getInstance() noexcept + { + static ErrorCategory category; + return category; + } +}; +} // namespace detail + +//================================================================================================= +/** + * @brief Construct an error code from the error enum. + */ +inline std::error_code makeErrorCode(ErrorCode e) +{ + return { static_cast(e), detail::ErrorCategory::getInstance() }; +} + +/** + * @brief Supports std::error_code construction. + */ +inline std::error_code make_error_code(ErrorCode e) +{ + return { static_cast(e), detail::ErrorCategory::getInstance() }; +} +} // namespace luabridge + +namespace std { +template <> struct is_error_code_enum : true_type {}; +} // namespace std diff --git a/external/include/LuaBridge3/LuaBridge/detail/Expected.h b/external/include/LuaBridge3/LuaBridge/detail/Expected.h new file mode 100644 index 0000000000..6eb7544070 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Expected.h @@ -0,0 +1,1632 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2022, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" + +#include +#include +#include +#include + +#if LUABRIDGE_HAS_EXCEPTIONS +#include +#endif + +namespace luabridge { +namespace detail { +using std::swap; + +template +T* construct_at(T* ptr, Args&&... args) noexcept(std::is_nothrow_constructible::value) +{ + return static_cast(::new (const_cast(static_cast(ptr))) T(std::forward(args)...)); +} + +template +struct is_swappable_with_impl : std::false_type +{ +}; + +template +struct is_swappable_with_impl(), std::declval()))>> + : std::true_type +{ +}; + +template +struct is_nothrow_swappable_with_impl +{ + static constexpr bool value = noexcept(swap(std::declval(), std::declval())) && noexcept(swap(std::declval(), std::declval())); + + using type = std::bool_constant; +}; + +template +struct is_swappable_with + : std::conjunction< + is_swappable_with_impl, std::add_lvalue_reference_t>, + is_swappable_with_impl, std::add_lvalue_reference_t>>::type +{ +}; + +template +struct is_nothrow_swappable_with + : std::conjunction, is_nothrow_swappable_with_impl>::type +{ +}; + +template +struct is_nothrow_swappable + : std::is_nothrow_swappable_with, std::add_lvalue_reference_t> +{ +}; + +template +struct has_member_message : std::false_type +{ +}; + +template +struct has_member_message().message())>> : std::true_type +{ +}; + +template +inline static constexpr bool has_member_message_v = has_member_message::value; +} // namespace detail + +template +class Expected; + +struct UnexpectType +{ + constexpr UnexpectType() = default; +}; + +static constexpr auto unexpect = UnexpectType(); + +namespace detail { +template , bool = (std::is_void_v || std::is_trivial_v) && std::is_trivial_v> +union expected_storage +{ +public: + template >> + constexpr expected_storage() noexcept + : value_() + { + } + + template + constexpr explicit expected_storage(std::in_place_t, Args&&... args) noexcept + : value_(std::forward(args)...) + { + } + + template + constexpr explicit expected_storage(UnexpectType, Args&&... args) noexcept + : error_(std::forward(args)...) + { + } + + ~expected_storage() = default; + + constexpr const T& value() const noexcept + { + return value_; + } + + constexpr T& value() noexcept + { + return value_; + } + + constexpr const E& error() const noexcept + { + return error_; + } + + constexpr E& error() noexcept + { + return error_; + } + +private: + T value_; + E error_; +}; + +template +union expected_storage +{ +public: + constexpr expected_storage() noexcept + : dummy_(0) + { + } + + template + constexpr explicit expected_storage(UnexpectType, Args&&... args) noexcept + : error_(std::forward(args)...) + { + } + + ~expected_storage() = default; + + constexpr const E& error() const noexcept + { + return error_; + } + + constexpr E& error() noexcept + { + return error_; + } + +private: + char dummy_; + E error_; +}; + +template +union expected_storage +{ +public: + constexpr expected_storage() noexcept(std::is_nothrow_default_constructible_v) + : value_() + { + } + + template + constexpr explicit expected_storage(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : value_(std::forward(args)...) + { + } + + template + constexpr explicit expected_storage(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : error_(std::forward(args)...) + { + } + + ~expected_storage() + { + } + + constexpr const T& value() const noexcept + { + return value_; + } + + constexpr T& value() noexcept + { + return value_; + } + + constexpr const E& error() const noexcept + { + return error_; + } + + constexpr E& error() noexcept + { + return error_; + } + +private: + T value_; + E error_; +}; + +template +union expected_storage +{ +public: + constexpr explicit expected_storage() noexcept + : dummy_(0) + { + } + + template + constexpr explicit expected_storage(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : value_(std::forward(args)...) + { + } + + template + constexpr explicit expected_storage(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : error_(std::forward(args)...) + { + } + + ~expected_storage() + { + } + + constexpr const T& value() const noexcept + { + return value_; + } + + constexpr T& value() noexcept + { + return value_; + } + + constexpr const E& error() const noexcept + { + return error_; + } + + constexpr E& error() noexcept + { + return error_; + } + +private: + char dummy_; + T value_; + E error_; +}; + +template +union expected_storage +{ +public: + constexpr expected_storage() noexcept + : dummy_(0) + { + } + + template + constexpr explicit expected_storage(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : error_(std::forward(args)...) + { + } + + ~expected_storage() = default; + + constexpr const E& error() const noexcept + { + return error_; + } + + constexpr E& error() noexcept + { + return error_; + } + +private: + char dummy_; + E error_; +}; + +template +class expected_base_trivial +{ + using this_type = expected_base_trivial; + +protected: + using storage_type = expected_storage; + + constexpr expected_base_trivial() noexcept + : valid_(true) + { + } + + template + constexpr expected_base_trivial(std::in_place_t, Args&&... args) noexcept + : storage_(std::in_place, std::forward(args)...) + , valid_(true) + { + } + + template + constexpr expected_base_trivial(UnexpectType, Args&&... args) noexcept + : storage_(unexpect, std::forward(args)...) + , valid_(false) + { + } + + expected_base_trivial(const expected_base_trivial& other) noexcept + { + if (other.valid_) + { + construct(std::in_place, other.value()); + } + else + { + construct(unexpect, other.error()); + } + } + + expected_base_trivial(expected_base_trivial&& other) noexcept + { + if (other.valid_) + { + construct(std::in_place, std::move(other.value())); + } + else + { + construct(unexpect, std::move(other.error())); + } + } + + ~expected_base_trivial() noexcept = default; + + constexpr const T& value() const noexcept + { + return storage_.value(); + } + + constexpr T& value() noexcept + { + return storage_.value(); + } + + constexpr const E& error() const noexcept + { + return storage_.error(); + } + + constexpr E& error() noexcept + { + return storage_.error(); + } + + constexpr const T* valuePtr() const noexcept + { + return std::addressof(value()); + } + + constexpr T* valuePtr() noexcept + { + return std::addressof(value()); + } + + constexpr const E* errorPtr() const noexcept + { + return std::addressof(error()); + } + + constexpr E* errorPtr() noexcept + { + return std::addressof(error()); + } + + constexpr bool valid() const noexcept + { + return valid_; + } + + template + inline T& construct(std::in_place_t, Args&&... args) noexcept + { + valid_ = true; + return *detail::construct_at(valuePtr(), std::forward(args)...); + } + + template + inline E& construct(UnexpectType, Args&&... args) noexcept + { + valid_ = false; + return *detail::construct_at(errorPtr(), std::forward(args)...); + } + + inline void destroy() noexcept + { + } + +private: + storage_type storage_; + bool valid_; +}; + +template +class expected_base_non_trivial +{ + using this_type = expected_base_non_trivial; + +protected: + using storage_type = expected_storage; + + constexpr expected_base_non_trivial() noexcept(std::is_nothrow_default_constructible_v) + : valid_(true) + { + } + + template + constexpr expected_base_non_trivial(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : storage_(std::in_place, std::forward(args)...) + , valid_(true) + { + } + + template + constexpr expected_base_non_trivial(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : storage_(unexpect, std::forward(args)...) + , valid_(false) + { + } + + expected_base_non_trivial(const expected_base_non_trivial& other) + { + if (other.valid_) + { + construct(std::in_place, other.value()); + } + else + { + construct(unexpect, other.error()); + } + } + + expected_base_non_trivial(expected_base_non_trivial&& other) noexcept + { + if (other.valid_) + { + construct(std::in_place, std::move(other.value())); + } + else + { + construct(unexpect, std::move(other.error())); + } + } + + ~expected_base_non_trivial() + { + destroy(); + } + + constexpr const T& value() const noexcept + { + return storage_.value(); + } + + constexpr T& value() noexcept + { + return storage_.value(); + } + + constexpr const E& error() const noexcept + { + return storage_.error(); + } + + constexpr E& error() noexcept + { + return storage_.error(); + } + + constexpr const T* valuePtr() const noexcept + { + return std::addressof(value()); + } + + constexpr T* valuePtr() noexcept + { + return std::addressof(value()); + } + + constexpr const E* errorPtr() const noexcept + { + return std::addressof(error()); + } + + constexpr E* errorPtr() noexcept + { + return std::addressof(error()); + } + + constexpr bool valid() const noexcept + { + return valid_; + } + + template + inline T& construct(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) + { + valid_ = true; + return *detail::construct_at(valuePtr(), std::forward(args)...); + } + + template + inline E& construct(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + { + valid_ = false; + return *detail::construct_at(errorPtr(), std::forward(args)...); + } + + inline void destroy() noexcept(std::is_nothrow_destructible_v&& std::is_nothrow_destructible_v) + { + if (valid_) + { + std::destroy_at(valuePtr()); + } + else + { + std::destroy_at(errorPtr()); + } + } + +private: + storage_type storage_; + bool valid_; +}; + +template +class expected_base_non_trivial +{ + using this_type = expected_base_non_trivial; + +protected: + using storage_type = expected_storage; + + constexpr expected_base_non_trivial() noexcept(std::is_nothrow_default_constructible_v) + : valid_(true) + { + } + + template + constexpr expected_base_non_trivial(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : storage_(std::in_place, std::forward(args)...) + , valid_(true) + { + } + + template + constexpr expected_base_non_trivial(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : storage_(unexpect, std::forward(args)...) + , valid_(false) + { + } + + expected_base_non_trivial(const expected_base_non_trivial& other) = delete; + + expected_base_non_trivial(expected_base_non_trivial&& other) noexcept + { + if (other.valid_) + { + construct(std::in_place, std::move(other.value())); + } + else + { + construct(unexpect, std::move(other.error())); + } + } + + ~expected_base_non_trivial() + { + destroy(); + } + + constexpr const T& value() const noexcept + { + return storage_.value(); + } + + constexpr T& value() noexcept + { + return storage_.value(); + } + + constexpr const E& error() const noexcept + { + return storage_.error(); + } + + constexpr E& error() noexcept + { + return storage_.error(); + } + + constexpr const T* valuePtr() const noexcept + { + return std::addressof(value()); + } + + constexpr T* valuePtr() noexcept + { + return std::addressof(value()); + } + + constexpr const E* errorPtr() const noexcept + { + return std::addressof(error()); + } + + constexpr E* errorPtr() noexcept + { + return std::addressof(error()); + } + + constexpr bool valid() const noexcept + { + return valid_; + } + + template + inline T& construct(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) + { + valid_ = true; + return *detail::construct_at(valuePtr(), std::forward(args)...); + } + + template + inline E& construct(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + { + valid_ = false; + return *detail::construct_at(errorPtr(), std::forward(args)...); + } + + inline void destroy() noexcept(std::is_nothrow_destructible_v&& std::is_nothrow_destructible_v) + { + if (valid_) + { + std::destroy_at(valuePtr()); + } + else + { + std::destroy_at(errorPtr()); + } + } + +private: + storage_type storage_; + bool valid_; +}; + +template +class expected_base_non_trivial +{ + using this_type = expected_base_non_trivial; + +protected: + using storage_type = expected_storage; + + template >> + constexpr expected_base_non_trivial() noexcept(std::is_nothrow_default_constructible_v) + : valid_(true) + { + } + + template + constexpr expected_base_non_trivial(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : storage_(std::in_place, std::forward(args)...) + , valid_(true) + { + } + + template + constexpr expected_base_non_trivial(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : storage_(unexpect, std::forward(args)...) + , valid_(false) + { + } + + expected_base_non_trivial(const expected_base_non_trivial& other) + { + if (other.valid_) + { + construct(std::in_place, other.value()); + } + else + { + construct(unexpect, other.error()); + } + } + + expected_base_non_trivial(expected_base_non_trivial&& other) = delete; + + ~expected_base_non_trivial() + { + destroy(); + } + + constexpr const T& value() const noexcept + { + return storage_.value(); + } + + constexpr T& value() noexcept + { + return storage_.value(); + } + + constexpr const E& error() const noexcept + { + return storage_.error(); + } + + constexpr E& error() noexcept + { + return storage_.error(); + } + + constexpr const T* valuePtr() const noexcept + { + return std::addressof(value()); + } + + constexpr T* valuePtr() noexcept + { + return std::addressof(value()); + } + + constexpr const E* errorPtr() const noexcept + { + return std::addressof(error()); + } + + constexpr E* errorPtr() noexcept + { + return std::addressof(error()); + } + + constexpr bool valid() const noexcept + { + return valid_; + } + + template + inline T& construct(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) + { + valid_ = true; + return *detail::construct_at(valuePtr(), std::forward(args)...); + } + + template + inline E& construct(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + { + valid_ = false; + return *detail::construct_at(errorPtr(), std::forward(args)...); + } + + inline void destroy() noexcept(std::is_nothrow_destructible_v&& std::is_nothrow_destructible_v) + { + if (valid_) + { + std::destroy_at(valuePtr()); + } + else + { + std::destroy_at(errorPtr()); + } + } + +private: + storage_type storage_; + bool valid_; +}; + +template +class expected_base_non_trivial +{ + using this_type = expected_base_non_trivial; + +protected: + using storage_type = expected_storage; + + template >> + constexpr expected_base_non_trivial() noexcept(std::is_nothrow_default_constructible_v) + : valid_(true) + { + } + + template + constexpr expected_base_non_trivial(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : storage_(std::in_place, std::forward(args)...) + , valid_(true) + { + } + + template + constexpr expected_base_non_trivial(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : storage_(unexpect, std::forward(args)...) + , valid_(false) + { + } + + expected_base_non_trivial(const expected_base_non_trivial& other) = delete; + + expected_base_non_trivial(expected_base_non_trivial&& other) = delete; + + ~expected_base_non_trivial() + { + destroy(); + } + + constexpr const T& value() const noexcept + { + return storage_.value(); + } + + constexpr T& value() noexcept + { + return storage_.value(); + } + + constexpr const E& error() const noexcept + { + return storage_.error(); + } + + constexpr E& error() noexcept + { + return storage_.error(); + } + + constexpr const T* valuePtr() const noexcept + { + return std::addressof(value()); + } + + constexpr T* valuePtr() noexcept + { + return std::addressof(value()); + } + + constexpr const E* errorPtr() const noexcept + { + return std::addressof(error()); + } + + constexpr E* errorPtr() noexcept + { + return std::addressof(error()); + } + + constexpr bool valid() const noexcept + { + return valid_; + } + + template + inline T& construct(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) + { + valid_ = true; + return *detail::construct_at(valuePtr(), std::forward(args)...); + } + + template + inline E& construct(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + { + valid_ = false; + return *detail::construct_at(errorPtr(), std::forward(args)...); + } + + inline void destroy() noexcept(std::is_nothrow_destructible_v&& std::is_nothrow_destructible_v) + { + if (valid_) + { + std::destroy_at(valuePtr()); + } + else + { + std::destroy_at(errorPtr()); + } + } + +private: + storage_type storage_; + bool valid_; +}; + +template +using expected_base = std::conditional_t< + (std::is_void_v || std::is_trivially_destructible_v) && std::is_trivially_destructible_v, + expected_base_trivial, + expected_base_non_trivial>; + +} // namespace detail + +template +class Unexpected +{ + static_assert(!std::is_reference_v && !std::is_void_v, "Unexpected type can't be a reference or void"); + +public: + Unexpected() = delete; + + constexpr explicit Unexpected(E&& e) noexcept(std::is_nothrow_move_constructible_v) + : error_(std::move(e)) + { + } + + constexpr explicit Unexpected(const E& e) noexcept(std::is_nothrow_copy_constructible_v) + : error_(e) + { + } + + constexpr const E& value() const& noexcept + { + return error_; + } + + constexpr E& value() & noexcept + { + return error_; + } + + constexpr const E&& value() const&& noexcept + { + return std::move(error_); + } + + constexpr E&& value() && noexcept + { + return std::move(error_); + } + +private: + E error_; +}; + +template +constexpr bool operator==(const Unexpected& lhs, const Unexpected& rhs) noexcept +{ + return lhs.value() == rhs.value(); +} + +template +constexpr bool operator!=(const Unexpected& lhs, const Unexpected& rhs) noexcept +{ + return lhs.value() != rhs.value(); +} + +template +constexpr inline Unexpected> makeUnexpected(E&& error) noexcept(std::is_nothrow_constructible_v>, E>) +{ + return Unexpected>{ std::forward(error) }; +} + +#if LUABRIDGE_HAS_EXCEPTIONS +template +class BadExpectedAccess; + +template <> +class BadExpectedAccess : public std::runtime_error +{ + template + friend class BadExpectedAccess; + + BadExpectedAccess(std::in_place_t) noexcept + : std::runtime_error("Bad access to expected value") + { + } + +public: + BadExpectedAccess() noexcept + : BadExpectedAccess(std::in_place) + { + } + + explicit BadExpectedAccess(const std::string& message) noexcept + : std::runtime_error(message) + { + } +}; + +template +class BadExpectedAccess : public std::runtime_error +{ +public: + explicit BadExpectedAccess(E error) noexcept(std::is_nothrow_constructible_v) + : std::runtime_error([](const E& error) + { + if constexpr (detail::has_member_message_v) + return error.message(); + else + return "Bad access to expected value"; + }(error)) + , error_(std::move(error)) + { + } + + const E& error() const& noexcept + { + return error_; + } + + E& error() & noexcept + { + return error_; + } + + E&& error() && noexcept + { + return std::move(error_); + } + +private: + E error_; +}; +#endif + +namespace detail { +template +inline void throw_bad_expected_access_or_abort([[maybe_unused]] E e) +{ +#if LUABRIDGE_HAS_EXCEPTIONS + throw BadExpectedAccess(std::move(e)); +#else + std::abort(); +#endif +} +} // namespace detail + +template +struct is_expected : std::false_type +{ +}; + +template +struct is_expected> : std::true_type +{ +}; +template +struct is_unexpected : std::false_type +{ +}; + +template +struct is_unexpected> : std::true_type +{ +}; + +template +class Expected : public detail::expected_base, std::is_move_constructible_v> +{ + static_assert(!std::is_reference_v && !std::is_void_v, "Unexpected type can't be a reference or void"); + + using base_type = detail::expected_base, std::is_move_constructible_v>; + using this_type = Expected; + +public: + using value_type = T; + + using error_type = E; + + using unexpected_type = Unexpected; + + template + struct rebind + { + using type = Expected; + }; + + template >> + constexpr Expected() noexcept(std::is_nothrow_default_constructible_v) + : base_type() + { + } + + constexpr Expected(const Expected& other) noexcept(std::is_nothrow_copy_constructible_v) = default; + + constexpr Expected(Expected&& other) noexcept(std::is_nothrow_move_constructible_v) = default; + + template + Expected(const Expected& other) + { + if (other.hasValue()) + { + this->construct(std::in_place, other.value()); + } + else + { + this->construct(unexpect, other.error()); + } + } + + template + Expected(Expected&& other) + { + if (other.hasValue()) + { + this->construct(std::in_place, std::move(other.value())); + } + else + { + this->construct(unexpect, std::move(other.error())); + } + } + + template && std::is_constructible_v && !std::is_same_v, std::in_place_t> && !is_expected>::value && !is_unexpected>::value, int> = 0> + constexpr Expected(U&& value) noexcept(std::is_nothrow_constructible_v) + : base_type(std::in_place, std::forward(value)) + { + } + + template + constexpr explicit Expected(std::in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : base_type(std::in_place, std::forward(args)...) + { + } + + template + constexpr explicit Expected(std::in_place_t, std::initializer_list ilist, Args&&... args) noexcept(std::is_nothrow_constructible_v, Args...>) + : base_type(std::in_place, ilist, std::forward(args)...) + { + } + + template + constexpr Expected(const Unexpected& u) noexcept(std::is_nothrow_constructible_v) + : base_type(unexpect, u.value()) + { + } + + template + constexpr Expected(Unexpected&& u) noexcept(std::is_nothrow_constructible_v) + : base_type(unexpect, std::move(u.value())) + { + } + + template + constexpr explicit Expected(UnexpectType, Args&&... args) noexcept(std::is_nothrow_constructible_v) + : base_type(unexpect, std::forward(args)...) + { + } + + template + constexpr explicit Expected(UnexpectType, std::initializer_list ilist, Args&&... args) noexcept(std::is_nothrow_constructible_v, Args...>) + : base_type(unexpect, ilist, std::forward(args)...) + { + } + + Expected& operator=(const Expected& other) + { + if (other.hasValue()) + { + assign(std::in_place, other.value()); + } + else + { + assign(unexpect, other.error()); + } + + return *this; + } + + Expected& operator=(Expected&& other) noexcept + { + if (other.hasValue()) + { + assign(std::in_place, std::move(other.value())); + } + else + { + assign(unexpect, std::move(other.error())); + } + + return *this; + } + + template >::value && !is_unexpected>::value, int> = 0> + Expected& operator=(U&& value) + { + assign(std::in_place, std::forward(value)); + return *this; + } + + template + Expected& operator=(const Unexpected& u) + { + assign(unexpect, u.value()); + return *this; + } + + template + Expected& operator=(Unexpected&& u) + { + assign(unexpect, std::move(u.value())); + return *this; + } + + template + T& emplace(Args&&... args) noexcept(noexcept(std::declval().assign(std::in_place, std::forward(args)...))) + { + return assign(std::in_place, std::forward(args)...); + } + + template + T& emplace(std::initializer_list ilist, Args&&... args) noexcept(noexcept(std::declval().assign(std::in_place, ilist, std::forward(args)...))) + { + return assign(std::in_place, ilist, std::forward(args)...); + } + + void swap(Expected& other) noexcept(detail::is_nothrow_swappable::value && detail::is_nothrow_swappable::value) + { + using std::swap; + + if (hasValue()) + { + if (other.hasValue()) + { + swap(value(), other.value()); + } + else + { + E error = std::move(other.error()); + other.assign(std::in_place, std::move(value())); + assign(unexpect, std::move(error)); + } + } + else + { + if (other.hasValue()) + { + other.swap(*this); + } + else + { + swap(error(), other.error()); + } + } + } + + constexpr const T* operator->() const + { + return base_type::valuePtr(); + } + + constexpr T* operator->() + { + return base_type::valuePtr(); + } + + constexpr const T& operator*() const& + { + return value(); + } + + constexpr T& operator*() & + { + return value(); + } + + constexpr const T&& operator*() const&& + { + return std::move(value()); + } + + constexpr T&& operator*() && + { + return std::move(value()); + } + + constexpr explicit operator bool() const noexcept + { + return hasValue(); + } + + constexpr bool hasValue() const noexcept + { + return base_type::valid(); + } + + constexpr const T& value() const& LUABRIDGE_IF_NO_EXCEPTIONS(noexcept) + { + if (!hasValue()) + detail::throw_bad_expected_access_or_abort(std::move(error())); + + return base_type::value(); + } + + constexpr T& value() & LUABRIDGE_IF_NO_EXCEPTIONS(noexcept) + { + if (!hasValue()) + detail::throw_bad_expected_access_or_abort(std::move(error())); + + return base_type::value(); + } + + constexpr const T&& value() const&& LUABRIDGE_IF_NO_EXCEPTIONS(noexcept) + { + if (!hasValue()) + detail::throw_bad_expected_access_or_abort(std::move(error())); + + return std::move(base_type::value()); + } + + constexpr T&& value() && LUABRIDGE_IF_NO_EXCEPTIONS(noexcept) + { + if (!hasValue()) + detail::throw_bad_expected_access_or_abort(std::move(error())); + + return std::move(base_type::value()); + } + + constexpr const E& error() const& noexcept + { + return base_type::error(); + } + + constexpr E& error() & noexcept + { + return base_type::error(); + } + + constexpr const E&& error() const&& noexcept + { + return std::move(base_type::error()); + } + + constexpr E&& error() && noexcept + { + return std::move(base_type::error()); + } + + template + constexpr T valueOr(U&& defaultValue) const& + { + return hasValue() ? value() : static_cast(std::forward(defaultValue)); + } + + template + T valueOr(U&& defaultValue) && + { + return hasValue() ? std::move(value()) : static_cast(std::forward(defaultValue)); + } + +private: + template + auto assign(Tag tag, Args&&... args) noexcept(noexcept(std::declval().destroy()) && noexcept(std::declval().construct(tag, std::forward(args)...))) + -> decltype(std::declval().construct(tag, std::forward(args)...)) + { + this->destroy(); + + return this->construct(tag, std::forward(args)...); + } +}; + +template +class Expected : public detail::expected_base, std::is_move_constructible_v> +{ + static_assert(!std::is_reference_v && !std::is_void_v, "Unexpected type can't be a reference or void"); + + using base_type = detail::expected_base, std::is_move_constructible_v>; + using this_type = Expected; + +public: + using value_type = void; + + using error_type = E; + + using unexpected_type = Unexpected; + + template + struct rebind + { + using type = Expected; + }; + + constexpr Expected() = default; + + constexpr Expected(const Expected& other) = default; + + constexpr Expected(Expected&& other) = default; + + template + Expected(const Expected& other) + { + if (other.hasValue()) + { + this->valid_ = true; + } + else + { + this->construct(unexpect, other.error()); + } + } + + template + Expected(Expected&& other) + { + if (other.hasValue()) + { + this->valid_ = true; + } + else + { + this->construct(unexpect, std::move(other.error())); + } + } + + template + constexpr Expected(const Unexpected& u) + : base_type(unexpect, u.value()) + { + } + + template + constexpr Expected(Unexpected&& u) + : base_type(unexpect, std::move(u.value())) + { + } + + template + constexpr explicit Expected(UnexpectType, Args&&... args) + : base_type(unexpect, std::forward(args)...) + { + } + + template + constexpr explicit Expected(UnexpectType, std::initializer_list ilist, Args&&... args) + : base_type(unexpect, ilist, std::forward(args)...) + { + } + + Expected& operator=(const Expected& other) + { + if (other.hasValue()) + { + assign(std::in_place); + } + else + { + assign(unexpect, other.error()); + } + + return *this; + } + + Expected& operator=(Expected&& other) + { + if (other.hasValue()) + { + assign(std::in_place); + } + else + { + assign(unexpect, std::move(other.error())); + } + + return *this; + } + + template + Expected& operator=(const Unexpected& u) + { + assign(unexpect, u.value()); + return *this; + } + + template + Expected& operator=(Unexpected&& u) + { + assign(unexpect, std::move(u.value())); + return *this; + } + + void swap(Expected& other) noexcept(detail::is_nothrow_swappable::value) + { + using std::swap; + + if (hasValue()) + { + if (!other.hasValue()) + { + assign(unexpect, std::move(other.error())); + other.assign(std::in_place); + } + } + else + { + if (other.hasValue()) + { + other.swap(*this); + } + else + { + swap(error(), other.error()); + } + } + } + + constexpr explicit operator bool() const noexcept + { + return hasValue(); + } + + constexpr bool hasValue() const noexcept + { + return base_type::valid(); + } + + constexpr const E& error() const& noexcept + { + return base_type::error(); + } + + constexpr E& error() & noexcept + { + return base_type::error(); + } + + constexpr const E&& error() const&& noexcept + { + return std::move(base_type::error()); + } + + constexpr E&& error() && noexcept + { + return std::move(base_type::error()); + } + +private: + template + void assign(Tag tag, Args&&... args) noexcept(noexcept(std::declval().destroy()) && noexcept(std::declval().construct(tag, std::forward(args)...))) + { + this->destroy(); + this->construct(tag, std::forward(args)...); + } +}; + +template +constexpr bool operator==(const Expected& lhs, const Expected& rhs) +{ + return (lhs && rhs) ? *lhs == *rhs : ((!lhs && !rhs) ? lhs.error() == rhs.error() : false); +} + +template +constexpr bool operator==(const Expected& lhs, const Expected& rhs) +{ + return (lhs && rhs) ? true : ((!lhs && !rhs) ? lhs.error() == rhs.error() : false); +} + +template +constexpr bool operator!=(const Expected& lhs, const Expected& rhs) +{ + return !(lhs == rhs); +} + +template +constexpr bool operator==(const Expected& lhs, const T& rhs) +{ + return lhs ? *lhs == rhs : false; +} + +template +constexpr bool operator==(const T& lhs, const Expected& rhs) +{ + return rhs == lhs; +} + +template +constexpr bool operator!=(const Expected& lhs, const T& rhs) +{ + return !(lhs == rhs); +} + +template +constexpr bool operator!=(const T& lhs, const Expected& rhs) +{ + return rhs != lhs; +} + +template +constexpr bool operator==(const Expected& lhs, const Unexpected& rhs) +{ + return lhs ? false : lhs.error() == rhs.value(); +} + +template +constexpr bool operator==(const Unexpected& lhs, const Expected& rhs) +{ + return rhs == lhs; +} + +template +constexpr bool operator!=(const Expected& lhs, const Unexpected& rhs) +{ + return !(lhs == rhs); +} + +template +constexpr bool operator!=(const Unexpected& lhs, const Expected& rhs) +{ + return rhs != lhs; +} +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/FlagSet.h b/external/include/LuaBridge3/LuaBridge/detail/FlagSet.h new file mode 100644 index 0000000000..91b4667697 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/FlagSet.h @@ -0,0 +1,124 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2023, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" + +#include +#include +#include + +namespace luabridge { + +template +class FlagSet +{ + static_assert(std::is_integral_v); + +public: + constexpr FlagSet() noexcept = default; + + constexpr void set(FlagSet other) noexcept + { + flags |= other.flags; + } + + constexpr FlagSet withSet(FlagSet other) const noexcept + { + FlagSet result { flags }; + result.flags |= other.flags; + return result; + } + + constexpr void unset(FlagSet other) noexcept + { + flags &= ~other.flags; + } + + constexpr FlagSet withUnset(FlagSet other) const noexcept + { + FlagSet result { flags }; + result.flags &= ~other.flags; + return result; + } + + constexpr bool test(FlagSet other) const noexcept + { + return (flags & other.flags) != 0; + } + + constexpr FlagSet operator|(FlagSet other) const noexcept + { + return FlagSet(flags | other.flags); + } + + constexpr FlagSet operator&(FlagSet other) const noexcept + { + return FlagSet(flags & other.flags); + } + + constexpr FlagSet operator~() const noexcept + { + return FlagSet(~flags); + } + + constexpr T toUnderlying() const noexcept + { + return flags; + } + + std::string toString() const + { + std::string result; + result.reserve(sizeof(T) * std::numeric_limits::digits); + + (result.append((mask() & flags) ? "1" : "0"), ...); + + for (std::size_t i = sizeof...(Ts); i < sizeof(T) * std::numeric_limits::digits; ++i) + result.append("0"); + + std::reverse(result.begin(), result.end()); + + return result; + } + + template + static constexpr FlagSet Value() noexcept + { + return FlagSet{ mask() }; + } + + template + static constexpr auto fromUnderlying(U newFlags) noexcept + -> std::enable_if_t && std::is_convertible_v, FlagSet> + { + return { static_cast(newFlags) }; + } + +private: + template + static constexpr T indexOf() noexcept + { + if constexpr (std::is_same_v) + return static_cast(0); + else + return static_cast(1) + indexOf(); + } + + template + static constexpr T mask() noexcept + { + return ((static_cast(1) << indexOf()) | ...); + } + + constexpr FlagSet(T flags) noexcept + : flags(flags) + { + } + + T flags = 0; +}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/FuncTraits.h b/external/include/LuaBridge3/LuaBridge/detail/FuncTraits.h new file mode 100644 index 0000000000..8eb6d10407 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/FuncTraits.h @@ -0,0 +1,895 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2020, Dmitry Tarakanov +// Copyright 2019, George Tokmaji +// Copyright 2012, Vinnie Falco +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" + +#include +#include + +namespace luabridge { +namespace detail { + +//================================================================================================= +/** + * @brief Invokes undefined behavior when an unreachable part of the code is reached. + * + * An implementation may use this to optimize impossible code branches away (typically, in optimized builds) or to trap them to prevent + * further execution (typically, in debug builds). + */ +[[noreturn]] inline void unreachable() +{ +#if defined(__GNUC__) // GCC, Clang, ICC + __builtin_unreachable(); +#elif defined(_MSC_VER) // MSVC + __assume(false); +#endif +} + +//================================================================================================= +/** + * @brief Provides the member typedef type which is the type referred to by T with its topmost cv-qualifiers removed. + */ +template< class T > +struct remove_cvref +{ + typedef std::remove_cv_t> type; +}; + +template +using remove_cvref_t = typename remove_cvref::type; + +//================================================================================================= +/** + * @brief Generic function traits. + * + * @tparam IsMember True if the function is a member function pointer. + * @tparam IsConst True if the function is const. + * @tparam R Return type of the function. + * @tparam Args Arguments types as variadic parameter pack. + */ +template +struct function_traits_base +{ + using result_type = R; + + using argument_types = std::tuple; + + static constexpr auto arity = sizeof...(Args); + + static constexpr auto is_member = IsMember; + + static constexpr auto is_const = IsConst; +}; + +template +struct function_traits_impl; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +#if defined(_MSC_VER) && defined(_M_IX86) // Windows: WINAPI (a.k.a. __stdcall) function pointers (32bit only). +inline static constexpr bool is_stdcall_default_calling_convention = std::is_same_v; +inline static constexpr bool is_fastcall_default_calling_convention = std::is_same_v; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; + +template +struct function_traits_impl : function_traits_base +{ +}; +#endif + +template +struct has_call_operator : std::false_type +{ +}; + +template +struct has_call_operator> : std::true_type +{ +}; + +template +inline static constexpr bool has_call_operator_v = has_call_operator::value; + +template +struct is_move_only_function : std::false_type {}; + +#if LUABRIDGE_HAS_CXX23_MOVE_ONLY_FUNCTION +template struct is_move_only_function> : std::true_type {}; +template struct is_move_only_function> : std::true_type {}; +template struct is_move_only_function> : std::true_type {}; +template struct is_move_only_function> : std::true_type {}; +#endif + +template +inline static constexpr bool is_move_only_function_v = is_move_only_function::value; + +template +struct functor_traits_impl +{ +}; + +template +struct functor_traits_impl && !is_move_only_function_v>> : function_traits_impl +{ +}; + +template +struct functor_traits_impl && std::is_invocable_v && !is_move_only_function_v>> + : function_traits_base> +{ +}; + +#if LUABRIDGE_HAS_CXX23_MOVE_ONLY_FUNCTION + +template +struct functor_traits_impl> + : function_traits_base +{ +}; + +template +struct functor_traits_impl> + : function_traits_base +{ +}; + +template +struct functor_traits_impl> + : function_traits_base +{ +}; + +template +struct functor_traits_impl> + : function_traits_base +{ +}; + +#endif // LUABRIDGE_HAS_CXX23_MOVE_ONLY_FUNCTION + +//================================================================================================= +/** + * @brief Traits class for callable objects (e.g. function pointers, lambdas) + * + * @tparam F Callable object. + */ +template +struct function_traits : std::conditional_t, + detail::functor_traits_impl, + detail::function_traits_impl> +{ +}; + +template , class = void> +struct has_function_traits : std::false_type +{ +}; + +template +struct has_function_traits::result_type, typename function_traits::argument_types>> : std::true_type +{ +}; + +template +inline static constexpr bool has_function_traits_v = has_function_traits::value; + +//================================================================================================= +/** + * @brief Deduces the argument type of a callble object or void in case it has no argument. + * + * @tparam I Argument index. + * @tparam F Callable object. + */ +template +struct function_argument_or_void +{ + using type = void; +}; + +template +struct function_argument_or_void::argument_types>>> +{ + using type = std::tuple_element_t::argument_types>; +}; + +template +using function_argument_or_void_t = typename function_argument_or_void::type; + +//================================================================================================= +/** + * @brief Deduces the return type of a callble object. + * + * @tparam F Callable object. + */ +template +using function_result_t = typename function_traits::result_type; + +/** + * @brief Deduces the argument type of a callble object. + * + * @tparam I Argument index. + * @tparam F Callable object. + */ +template +using function_argument_t = std::tuple_element_t::argument_types>; + +/** + * @brief Deduces the arguments type of a callble object. + * + * @tparam F Callable object. + */ +template +using function_arguments_t = typename function_traits::argument_types; + +/** + * @brief An integral constant expression that gives the number of arguments accepted by the callable object. + * + * @tparam F Callable object. + */ +template +static constexpr std::size_t function_arity_v = function_traits::arity; + +/** + * @brief An boolean constant expression that checks if the callable object is a member function. + * + * @tparam F Callable object. + */ +template +static constexpr bool function_is_member_v = function_traits::is_member; + +/** + * @brief An boolean constant expression that checks if the callable object is const. + * + * @tparam F Callable object. + */ +template +static constexpr bool function_is_const_v = function_traits::is_const; + +//================================================================================================= +/** + * @brief Detect if we T is a callable object. + * + * @tparam T Potentially callable object. + */ +template +struct is_callable +{ + static constexpr bool value = false; +}; + +template +struct is_callable> +{ + static constexpr bool value = true; +}; + +template +struct is_callable && !has_call_operator_v && has_function_traits_v>> +{ + static constexpr bool value = true; +}; + +template +struct is_callable && std::is_function_v>>> +{ + static constexpr bool value = true; +}; + +template +struct is_callable>> +{ + static constexpr bool value = true; +}; + +template +inline static constexpr bool is_callable_v = is_callable::value; + +//================================================================================================= +/** + * @brief Detect if we T is a const member function pointer. + * + * @tparam T Potentially const member function pointer. + */ +template +struct is_const_member_function_pointer +{ + static constexpr bool value = false; +}; + +template +struct is_const_member_function_pointer +{ + static constexpr bool value = false; +}; + +template +struct is_const_member_function_pointer +{ + static constexpr bool value = true; +}; + +template +struct is_const_member_function_pointer +{ + static constexpr bool value = false; +}; + +template +struct is_const_member_function_pointer +{ + static constexpr bool value = true; +}; + +template +inline static constexpr bool is_const_member_function_pointer_v = is_const_member_function_pointer::value; + +//================================================================================================= +/** + * @brief Detect if T is a lua cfunction pointer. + * + * @tparam T Potentially lua cfunction pointer. + */ +template +struct is_cfunction_pointer +{ + static constexpr bool value = false; +}; + +template <> +struct is_cfunction_pointer +{ + static constexpr bool value = true; +}; + +template +inline static constexpr bool is_cfunction_pointer_v = is_cfunction_pointer::value; + +//================================================================================================= +/** + * @brief Detect if T is a member lua cfunction pointer. + * + * @tparam T Potentially member lua cfunction pointer. + */ +template +struct is_member_cfunction_pointer +{ + static constexpr bool value = false; +}; + +template +struct is_member_cfunction_pointer +{ + static constexpr bool value = true; +}; + +template +struct is_member_cfunction_pointer +{ + static constexpr bool value = true; +}; + +template +inline static constexpr bool is_member_cfunction_pointer_v = is_member_cfunction_pointer::value; + +/** + * @brief Detect if T is a const member lua cfunction pointer. + * + * @tparam T Potentially const member lua cfunction pointer. + */ +template +struct is_const_member_cfunction_pointer +{ + static constexpr bool value = false; +}; + +template +struct is_const_member_cfunction_pointer +{ + static constexpr bool value = false; +}; + +template +struct is_const_member_cfunction_pointer +{ + static constexpr bool value = true; +}; + +template +inline static constexpr bool is_const_member_cfunction_pointer_v = is_const_member_cfunction_pointer::value; + +//================================================================================================= +/** + * @brief Detect if T is a member or non member lua cfunction pointer. + * + * @tparam T Potentially member or non member lua cfunction pointer. + */ +template +inline static constexpr bool is_any_cfunction_pointer_v = is_cfunction_pointer_v || is_member_cfunction_pointer_v; + +//================================================================================================= +/** + * @brief A constexpr check for proxy_member functions. + * + * @tparam T Type where the callable should be able to operate. + * @tparam F Callable object. + */ +template +inline static constexpr bool is_proxy_member_function_v = + !std::is_member_function_pointer_v && + std::is_same_v>>>; + +template +inline static constexpr bool is_const_proxy_function_v = + is_proxy_member_function_v && + std::is_const_v>>>; + +//================================================================================================= +/** + * @brief A constexpr check for reversed proxy member functions (binary operators). + * + * A reversed proxy function is a binary callable where T is the second argument instead of the + * first, as needed by binary operator metamethods invoked with swapped operands (eg. `3 * vec`). + * + * @tparam T Type where the callable should be able to operate. + * @tparam F Callable object. + */ +template +inline static constexpr bool is_reversed_proxy_function_v = + !std::is_member_function_pointer_v && + !is_proxy_member_function_v && + function_arity_v == 2 && + std::is_same_v>>>; + +template +inline static constexpr bool is_const_reversed_proxy_function_v = + is_reversed_proxy_function_v && + std::is_const_v>>>; + +//================================================================================================= +/** + * @brief An integral constant expression that gives the number of arguments excluding one type (usually used with lua_State*) accepted by the callable object. + * + * @tparam F Callable object. + */ +template +struct function_arity_excluding +{ +}; + +template < class... Ts, class ExclusionType> +struct function_arity_excluding, ExclusionType> + : std::integral_constant, ExclusionType> ? 0 : 1))> +{ +}; + +template +inline static constexpr std::size_t function_arity_excluding_v = function_arity_excluding, ExclusionType>::value; + +/** + * @brief An integral constant expression that gives the number of arguments excluding one type (usually used with lua_State*) accepted by the callable object. + * + * @tparam F Callable object. + */ +template +struct member_function_arity_excluding +{ +}; + +template +struct member_function_arity_excluding, ExclusionType, std::enable_if_t>> + : std::integral_constant, ExclusionType> ? 0 : 1))> +{ +}; + +template +struct member_function_arity_excluding, ExclusionType, std::enable_if_t>> + : std::integral_constant, ExclusionType> ? 0 : 1)) - 1> +{ +}; + +template +inline static constexpr std::size_t member_function_arity_excluding_v = member_function_arity_excluding, ExclusionType>::value; + +//================================================================================================= +/** + * @brief Detectors for const and non const functions in packs and counting them. + */ +template +static constexpr bool is_const_function = + detail::is_const_member_function_pointer_v || + (detail::function_arity_v > 0 && detail::is_const_proxy_function_v) || + detail::is_const_reversed_proxy_function_v; + +template +inline static constexpr std::size_t const_functions_count = (0 + ... + (is_const_function ? 1 : 0)); + +template +inline static constexpr std::size_t non_const_functions_count = (0 + ... + (is_const_function ? 0 : 1)); + +//================================================================================================= +/** + * @brief Simple make_tuple alternative that doesn't decay the types. + * + * @tparam Types Argument types that will compose the tuple. + */ +template +constexpr auto tupleize(Types&&... types) +{ + return std::tuple(std::forward(types)...); +} + +//================================================================================================= +/** + * @brief Remove first type from tuple. + */ +template +struct remove_first_type +{ +}; + +template +struct remove_first_type> +{ + using type = std::tuple; +}; + +template +using remove_first_type_t = typename remove_first_type::type; + +//================================================================================================= +/** + * @brief Drop the first N types from a tuple. + */ +template +struct tuple_drop_first +{ + using type = typename tuple_drop_first>::type; +}; + +template +struct tuple_drop_first<0, Tuple> +{ + using type = Tuple; +}; + +template +using tuple_drop_first_t = typename tuple_drop_first::type; + +//================================================================================================= +/** + * @brief Prepend a type to a tuple. + */ +template +struct tuple_prepend; + +template +struct tuple_prepend> +{ + using type = std::tuple; +}; + +template +using tuple_prepend_t = typename tuple_prepend::type; + +//================================================================================================= +/** + * @brief Take only the first N types from a tuple (uses an accumulator to avoid ambiguity). + */ +template > +struct tuple_take_first_impl +{ + using type = Accum; +}; + +template +struct tuple_take_first_impl, std::tuple> +{ + using type = typename tuple_take_first_impl, std::tuple>::type; +}; + +template +struct tuple_take_first_impl<0, std::tuple, std::tuple> +{ + using type = std::tuple; +}; + +template +using tuple_take_first_t = typename tuple_take_first_impl::type; + +//================================================================================================= +/** + * @brief Extracts the class type from a member function pointer. + */ +template +struct member_function_class; + +template +struct member_function_class { using type = C; }; + +template +struct member_function_class { using type = const C; }; + +template +struct member_function_class { using type = C; }; + +template +struct member_function_class { using type = const C; }; + +template +using member_function_class_t = typename member_function_class::type; + +//================================================================================================= +/** + * @brief Computes the leading argument tuple for bind_back: for member function pointers, + * prepends ClassType* to the explicit remaining args; for all other callables, returns + * the explicit remaining args unchanged. + */ +template +struct bind_back_leading_impl +{ + using type = ExplicitRemaining; +}; + +template +struct bind_back_leading_impl +{ + using type = tuple_prepend_t*, ExplicitRemaining>; +}; + +template +using bind_back_leading_t = + typename bind_back_leading_impl>::type; + +//================================================================================================= +/** + * @brief Internal storage for luabridge::bind_front — exposes a non-template operator() so that + * function_traits can statically resolve result_type and argument_types. + */ +template +struct bind_front_wrapper; + +template +struct bind_front_wrapper, Fn, BoundArgs...> +{ + Fn fn_; + std::tuple bound_; + + template + bind_front_wrapper(F&& f, BA&&... ba) + : fn_(std::forward(f)), bound_(std::forward(ba)...) + { + } + + R operator()(Remaining... args) const + { + return std::apply([&](const auto&... ba) { return std::invoke(fn_, ba..., args...); }, bound_); + } +}; + +} // namespace detail + +//================================================================================================= +/** + * @brief Drop-in replacement for std::bind_front with statically introspectable argument types. + * + * std::bind_front returns an object whose operator() is a template, so its argument and result + * types cannot be resolved at compile time without an explicit std::function cast. This + * wrapper stores the callable and its leading bound arguments, then exposes a concrete + * non-template operator() whose parameter types are derived directly from the underlying + * callable's signature. + * + * For member function pointers the implicit object argument consumed by std::invoke is not + * counted as part of the remaining (Lua-visible) parameter list, matching std::bind_front + * semantics. + * + * @tparam F Callable type (function pointer, member function pointer, functor). + * @tparam BoundArgs Leading argument types to bind. + * @param f The callable to wrap. + * @param args Leading arguments forwarded into the wrapper by value. + * @return A callable object whose operator() accepts the remaining (unbound) arguments. + */ +template +auto bind_front(F&& f, BoundArgs&&... args) +{ + using Fn = std::decay_t; + using FnTraits = detail::function_traits; + + static constexpr std::size_t skip = std::is_member_function_pointer_v ? 1u : 0u; + static constexpr std::size_t num_effective_bound = sizeof...(BoundArgs) - skip; + + using remaining = detail::tuple_drop_first_t; + using R = typename FnTraits::result_type; + + return detail::bind_front_wrapper...>( + std::forward(f), std::forward(args)...); +} + +//================================================================================================= +namespace detail { + +/** + * @brief Internal storage for luabridge::bind_back — exposes a non-template operator() so that + * function_traits can statically resolve result_type and argument_types. + * + * LeadingArgsTuple is the tuple of arguments that the caller must provide; BoundArgs are + * the trailing arguments captured at bind time. For member function pointers, the class + * pointer is included as the first element of LeadingArgsTuple. + */ +template +struct bind_back_wrapper; + +template +struct bind_back_wrapper, Fn, BoundArgs...> +{ + Fn fn_; + std::tuple bound_; + + template + bind_back_wrapper(F&& f, BA&&... ba) + : fn_(std::forward(f)), bound_(std::forward(ba)...) + { + } + + R operator()(Leading... args) const + { + return std::apply([&](const auto&... ba) { return std::invoke(fn_, args..., ba...); }, bound_); + } +}; + +} // namespace detail + +//================================================================================================= +/** + * @brief Drop-in replacement for std::bind_back with statically introspectable argument types. + * + * Stores the callable and its trailing bound arguments, then exposes a concrete non-template + * operator() whose parameter types are derived directly from the underlying callable's signature. + * This lets LuaBridge register the result with addFunction / addStaticFunction without any extra + * annotation. + * + * For member function pointers the class pointer is automatically prepended to the remaining + * (Lua-visible) parameter list so that LuaBridge can dispatch it as a proxy member function. + * + * @tparam F Callable type (function pointer, member function pointer, functor). + * @tparam BoundArgs Trailing argument types to bind. + * @param f The callable to wrap. + * @param args Trailing arguments forwarded into the wrapper by value. + * @return A callable object whose operator() accepts the remaining (leading) arguments. + */ +template +auto bind_back(F&& f, BoundArgs&&... args) +{ + using Fn = std::decay_t; + using FnTraits = detail::function_traits; + + static constexpr std::size_t num_explicit = FnTraits::arity; + static constexpr std::size_t num_bound = sizeof...(BoundArgs); + static constexpr std::size_t num_remaining = num_explicit - num_bound; + + using explicit_remaining = detail::tuple_take_first_t; + using leading = detail::bind_back_leading_t; + using R = typename FnTraits::result_type; + + return detail::bind_back_wrapper...>( + std::forward(f), std::forward(args)...); +} + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/Globals.h b/external/include/LuaBridge3/LuaBridge/detail/Globals.h new file mode 100644 index 0000000000..d1fc0db6a1 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Globals.h @@ -0,0 +1,77 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2023, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" +#include "Stack.h" + +#include +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Get a global value from the lua_State. + * + * @note This works on any type specialized by `Stack`, including `LuaRef` and its table proxies. +*/ +template +TypeResult getGlobal(lua_State* L, const char* name) +{ + lua_getglobal(L, name); + + auto result = luabridge::Stack::get(L, -1); + + lua_pop(L, 1); + + return result; +} + +//================================================================================================= +/** + * @brief Try to get a field from a global table without creating a LuaRef. + * + * This is a fast-path helper for optional lookup patterns. It invokes normal Lua field access + * on the table, including metamethods, and returns std::nullopt when the global is not a table + * or the field cannot be converted to the requested type. + */ +template +std::optional tryGetGlobalField(lua_State* L, const char* globalName, const char* fieldName) +{ + const StackRestore stackRestore(L); + + lua_getglobal(L, globalName); + if (! lua_istable(L, -1)) + return std::nullopt; + + lua_getfield(L, -1, fieldName); + + auto result = Stack>::get(L, -1); + if (! result) + return std::nullopt; + + return *result; +} + +//================================================================================================= +/** + * @brief Set a global value in the lua_State. + * + * @note This works on any type specialized by `Stack`, including `LuaRef` and its table proxies. + */ +template +bool setGlobal(lua_State* L, T&& t, const char* name) +{ + if (auto result = push(L, std::forward(t))) + { + lua_setglobal(L, name); + return true; + } + + return false; +} + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/Invoke.h b/external/include/LuaBridge3/LuaBridge/detail/Invoke.h new file mode 100644 index 0000000000..8638f343fe --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Invoke.h @@ -0,0 +1,263 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2021, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" +#include "Errors.h" +#include "Stack.h" +#include "LuaRef.h" +#include "LuaException.h" + +#include +#include +#include +#include + +namespace luabridge { + +//================================================================================================= +namespace detail { + +template +bool is_handler_valid(const F& f) noexcept +{ + if constexpr (std::is_pointer_v>) + return f != nullptr; + else if constexpr (std::is_constructible_v>) + return static_cast(f); + else + return true; +} + +template +TypeResult decode_tuple_result(lua_State* L, int first_result_index, std::index_sequence) +{ + auto results = std::make_tuple( + Stack>::get(L, first_result_index + static_cast(Indices))...); + + std::error_code ec; + + const bool ok = + (([&]() + { + const auto& element = std::get(results); + if (! element) + { + ec = element.error(); + return false; + } + return true; + }()) + && ...); + + if (! ok) + return ec; + + return Tuple{ std::move(*std::get(results))... }; +} + +template +TypeResult decode_call_result(lua_State* L, int first_result_index, int num_returned_values) +{ + if constexpr (std::is_same_v || std::is_same_v>) + { + if (num_returned_values != 0) + return makeErrorCode(ErrorCode::InvalidTableSizeInCast); + + return {}; + } + else if constexpr (is_tuple_v) + { + constexpr auto expected_size = static_cast(std::tuple_size_v); + if (num_returned_values != expected_size) + return makeErrorCode(ErrorCode::InvalidTableSizeInCast); + + return decode_tuple_result(L, first_result_index, std::make_index_sequence{}); + } + else + { + if (num_returned_values < 1) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + return Stack::get(L, first_result_index); + } +} + +} // namespace detail + +//================================================================================================= +/** + * @brief Safely call Lua code and decode the return values to R. + */ +template +TypeResult callWithHandler(const Ref& object, F&& errorHandler, Args&&... args) +{ + static_assert(std::is_same_v, detail::remove_cvref_t> || std::is_invocable_r_v); + + static constexpr bool isValidHandler = + !std::is_same_v, detail::remove_cvref_t>; + + lua_State* L = object.state(); + const StackRestore stackRestore(L); + const int initialTop = lua_gettop(L); + + bool hasHandler = false; + if constexpr (isValidHandler) + { + hasHandler = detail::is_handler_valid(errorHandler); + if (hasHandler) + detail::push_function(L, std::forward(errorHandler), ""); + } + + object.push(); + + { + const auto [result, index] = detail::push_arguments(L, std::forward_as_tuple(args...)); + if (! result) + return result.error(); + } + + const int messageHandlerIndex = hasHandler ? (initialTop + 1) : 0; + const int code = lua_pcall(L, sizeof...(Args), LUA_MULTRET, messageHandlerIndex); + if (code != LUABRIDGE_LUA_OK) + { + auto ec = makeErrorCode(ErrorCode::LuaFunctionCallFailed); + +#if LUABRIDGE_HAS_EXCEPTIONS + if constexpr (! isValidHandler) + { + if (LuaException::areExceptionsEnabled(L)) + LuaException::raise(L, ec); + } +#endif + + lua_pop(L, 1); + return ec; + } + + if (hasHandler) + lua_remove(L, initialTop + 1); + + const int firstResultIndex = initialTop + 1; + const int numReturnedValues = lua_gettop(L) - initialTop; + return detail::decode_call_result(L, firstResultIndex, numReturnedValues); +} + +template +TypeResult callWithHandler(const Ref& object, F&& errorHandler, Args&&... args) +{ + return callWithHandler(object, std::forward(errorHandler), std::forward(args)...); +} + +template +TypeResult call(const Ref& object, Args&&... args) +{ + return callWithHandler(object, std::ignore, std::forward(args)...); +} + +template +class LuaFunction; + +template +class LuaFunction +{ +public: + LuaFunction() = default; + + explicit LuaFunction(const LuaRef& function) + : m_function(function) + { + } + + explicit LuaFunction(LuaRef&& function) + : m_function(std::move(function)) + { + } + + [[nodiscard]] TypeResult operator()(Args... args) const + { + return call(std::forward(args)...); + } + + [[nodiscard]] TypeResult call(Args... args) const + { + return luabridge::call(m_function, std::forward(args)...); + } + + template + [[nodiscard]] TypeResult callWithHandler(F&& errorHandler, Args... args) const + { + return luabridge::callWithHandler(m_function, std::forward(errorHandler), std::forward(args)...); + } + + [[nodiscard]] bool isValid() const + { + return m_function.isCallable(); + } + + [[nodiscard]] const LuaRef& ref() const + { + return m_function; + } + +private: + LuaRef m_function; +}; + +//============================================================================================= +/** + * @brief Wrapper for `lua_pcall` that throws if exceptions are enabled. + */ +inline int pcall(lua_State* L, int nargs = 0, int nresults = 0, int msgh = 0) +{ + const int code = lua_pcall(L, nargs, nresults, msgh); + +#if LUABRIDGE_HAS_EXCEPTIONS + if (code != LUABRIDGE_LUA_OK && LuaException::areExceptionsEnabled(L)) + LuaException::raise(L, makeErrorCode(ErrorCode::LuaFunctionCallFailed)); +#endif + + return code; +} + +//============================================================================================= +template +template +TypeResult LuaRefBase::call(Args&&... args) const +{ + return luabridge::call(impl(), std::forward(args)...); +} + +template +template +TypeResult LuaRefBase::operator()(Args&&... args) const +{ + return call(std::forward(args)...); +} + +template +template +TypeResult LuaRefBase::callWithHandler(F&& errorHandler, Args&&... args) const +{ + return luabridge::callWithHandler(impl(), std::forward(errorHandler), std::forward(args)...); +} + +template +template +TypeResult LuaRefBase::callWithHandler(F&& errorHandler, Args&&... args) const +{ + return callWithHandler(std::forward(errorHandler), std::forward(args)...); +} + +template +template +LuaFunction LuaRefBase::callable() const +{ + const StackRestore stackRestore(m_L); + impl().push(m_L); + return LuaFunction(LuaRef::fromStack(m_L)); +} + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/Iterator.h b/external/include/LuaBridge3/LuaBridge/detail/Iterator.h new file mode 100644 index 0000000000..698510929f --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Iterator.h @@ -0,0 +1,256 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2018, Dmitry Tarakanov +// Copyright 2012, Vinnie Falco +// SPDX-License-Identifier: MIT + +#pragma once + +#include "LuaRef.h" + +#include + +#if LUABRIDGE_HAS_CXX20_RANGES +#include +#include +#endif + +namespace luabridge { + +//================================================================================================= +/** + * @brief Iterator class to allow table iteration. + * + * @see Range class. + */ +class Iterator +{ +public: + explicit Iterator(const LuaRef& table, bool isEnd = false) + : m_L(table.state()) + , m_table(table) + , m_key(table.state()) // m_key is nil + , m_value(table.state()) // m_value is nil + { + if (! isEnd) + { + next(); // get the first (key, value) pair from table + } + } + +#if LUABRIDGE_HAS_CXX20_RANGES + using value_type = std::pair; + using difference_type = std::ptrdiff_t; + using iterator_concept = std::input_iterator_tag; +#endif + + /** + * @brief Return an associated Lua state. + * + * @return A Lua state. + */ + lua_State* state() const noexcept + { + return m_L; + } + + /** + * @brief Dereference the iterator. + * + * @return A key-value pair for a current table entry. + */ + std::pair operator*() const + { + return std::make_pair(m_key, m_value); + } + + /** + * @brief Return the value referred by the iterator. + * + * @return A value for the current table entry. + */ + LuaRef operator->() const + { + return m_value; + } + + /** + * @brief Compare two iterators. + * + * @param rhs Another iterator. + * + * @return True if iterators point to the same entry of the same table, false otherwise. + */ + bool operator!=(const Iterator& rhs) const + { + LUABRIDGE_ASSERT(m_L == rhs.m_L); + + return ! m_table.rawequal(rhs.m_table) || ! m_key.rawequal(rhs.m_key); + } + + /** + * @brief Move the iterator to the next table entry. + * + * @return This iterator. + */ + Iterator& operator++() + { + if (isNil()) + { + // if the iterator reaches the end, do nothing + return *this; + } + else + { + next(); + return *this; + } + } + + /** + * @brief Check if the iterator points after the last table entry. + * + * @return True if there are no more table entries to iterate, false otherwise. + */ + bool isNil() const noexcept + { + return m_key.isNil(); + } + + /** + * @brief Return the key for the current table entry. + * + * @return A reference to the entry key. + */ + LuaRef key() const + { + return m_key; + } + + /** + * @brief Return the key for the current table entry. + * + * @return A reference to the entry value. + */ + LuaRef value() const + { + return m_value; + } + +private: + // Don't use postfix increment, it is less efficient + Iterator operator++(int); + + void next() + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(m_L, 2)) + { + m_key = LuaNil(); + m_value = LuaNil(); + return; + } +#endif + + m_table.push(); + m_key.push(); + + if (lua_next(m_L, -2)) + { + m_value.pop(); + m_key.pop(); + } + else + { + m_key = LuaNil(); + m_value = LuaNil(); + } + + lua_pop(m_L, 1); + } + + lua_State* m_L = nullptr; + LuaRef m_table; + LuaRef m_key; + LuaRef m_value; +}; + +//================================================================================================= +/** + * @brief Range class taking two table iterators. + */ +class Range +{ +public: + Range(const Iterator& begin, const Iterator& end) + : m_begin(begin) + , m_end(end) + { + } + + const Iterator& begin() const noexcept + { + return m_begin; + } + + const Iterator& end() const noexcept + { + return m_end; + } + +private: + Iterator m_begin; + Iterator m_end; +}; + +//================================================================================================= +/** + * @brief Return a range for the Lua table reference. + * + * @return A range suitable for range-based for statement. + */ +inline Range pairs(const LuaRef& table) +{ + return Range{ Iterator(table, false), Iterator(table, true) }; +} + +#if LUABRIDGE_HAS_CXX20_RANGES + +/** + * @brief Equality comparison for Iterator. + */ +inline bool operator==(const Iterator& lhs, const Iterator& rhs) +{ + if (lhs.isNil() && rhs.isNil()) + return true; + if (lhs.isNil() != rhs.isNil()) + return false; + return lhs.key().rawequal(rhs.key()) && lhs.value().rawequal(rhs.value()); +} + +/** + * @brief Sentinel type for Iterator end detection. + */ +struct IteratorSentinel {}; + +/** + * @brief Sentinel equality: Iterator is at end when isNil(). + */ +inline bool operator==(const Iterator& it, IteratorSentinel) +{ + return it.isNil(); +} + +inline bool operator==(IteratorSentinel, const Iterator& it) +{ + return it.isNil(); +} + +#endif // LUABRIDGE_HAS_CXX20_RANGES + +} // namespace luabridge + +#if LUABRIDGE_HAS_CXX20_RANGES +template <> +inline constexpr bool std::ranges::enable_borrowed_range = false; +#endif diff --git a/external/include/LuaBridge3/LuaBridge/detail/LuaException.h b/external/include/LuaBridge3/LuaBridge/detail/LuaException.h new file mode 100644 index 0000000000..f70d5c3484 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/LuaException.h @@ -0,0 +1,188 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2021, kunitoki +// Copyright 2012, Vinnie Falco +// Copyright 2008, Nigel Atkinson +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" + +#include "ClassInfo.h" +#include "LuaHelpers.h" + +#include +#include +#include + +namespace luabridge { + +//================================================================================================ +class LuaException : public std::exception +{ +public: + //============================================================================================= + /** + * @brief Construct a LuaException from a LuaBridge error code. + */ + LuaException(lua_State* L, std::error_code code) + : m_L(L) + , m_code(code) + , m_what(code.message()) + { + } + + ~LuaException() noexcept override + { + } + + //============================================================================================= + /** + * @brief Return the error message. + */ + const char* what() const noexcept override + { + return m_what.c_str(); + } + + //============================================================================================= + /** + * @brief Throw an exception or raises a luaerror when exceptions are disabled. + */ + [[noreturn]] static void raise(lua_State* L, std::error_code code) + { + LUABRIDGE_ASSERT(areExceptionsEnabled(L)); + +#if LUABRIDGE_HAS_EXCEPTIONS + throw LuaException(L, code, FromLua{}); +#else + unused(L, code); + + std::abort(); +#endif + } + + //============================================================================================= + /** + * @brief Check if exceptions are enabled. + */ + static bool areExceptionsEnabled(lua_State* L) noexcept + { + lua_pushlightuserdata(L, detail::getExceptionsKey()); + lua_gettable(L, LUA_REGISTRYINDEX); + + const bool enabled = lua_isboolean(L, -1) ? static_cast(lua_toboolean(L, -1)) : false; + lua_pop(L, 1); + + return enabled; + } + + /** + * @brief Initializes error handling. + * + * Subsequent Lua errors are translated to C++ exceptions, or logging and abort if exceptions are disabled. + */ + static void enableExceptions(lua_State* L) noexcept + { + lua_pushlightuserdata(L, detail::getExceptionsKey()); + lua_pushboolean(L, true); + lua_settable(L, LUA_REGISTRYINDEX); + +#if LUABRIDGE_HAS_EXCEPTIONS && LUABRIDGE_ON_LUAJIT + lua_pushlightuserdata(L, (void*)luajitWrapperCallback); + luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON); + lua_pop(L, 1); +#endif + +#if LUABRIDGE_ON_LUAU + auto callbacks = lua_callbacks(L); + callbacks->panic = +[](lua_State* L, int) { panicHandlerCallback(L); }; +#else + lua_atpanic(L, panicHandlerCallback); +#endif + } + + //============================================================================================= + /** + * @brief Retrieve the lua_State associated with the exception. + * + * @return A Lua state. + */ + lua_State* state() const { return m_L; } + +private: + struct FromLua {}; + + LuaException(lua_State* L, std::error_code code, FromLua) + : m_L(L) + , m_code(code) + { + whatFromStack(); + } + + void whatFromStack() + { + std::stringstream ss; + + const char* errorText = nullptr; + + if (lua_gettop(m_L) > 0) + { + errorText = lua_tostring(m_L, -1); + lua_pop(m_L, 1); + } + + ss << (errorText ? errorText : "Unknown error") << " (code=" << m_code.message() << ")"; + + m_what = std::move(ss).str(); + } + + static int panicHandlerCallback(lua_State* L) + { +#if LUABRIDGE_HAS_EXCEPTIONS + throw LuaException(L, makeErrorCode(ErrorCode::LuaFunctionCallFailed), FromLua{}); +#else + unused(L); + + std::abort(); +#endif + } + +#if LUABRIDGE_HAS_EXCEPTIONS && LUABRIDGE_ON_LUAJIT + static int luajitWrapperCallback(lua_State* L, lua_CFunction f) + { + try + { + return f(L); + } + catch (const std::exception& e) + { + lua_pushstring(L, e.what()); + lua_error_x(L); + } + } +#endif + + lua_State* m_L = nullptr; + std::error_code m_code; + std::string m_what; +}; + +//================================================================================================= +/** + * @brief Initializes error handling using C++ exceptions. + * + * Subsequent Lua errors are translated to C++ exceptions. It aborts the application if called when no exceptions. + */ +inline void enableExceptions(lua_State* L) noexcept +{ +#if LUABRIDGE_HAS_EXCEPTIONS + LuaException::enableExceptions(L); +#else + unused(L); + + LUABRIDGE_ASSERT(false); // Never call this function when exceptions are not enabled. +#endif +} + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/LuaHelpers.h b/external/include/LuaBridge3/LuaBridge/detail/LuaHelpers.h new file mode 100644 index 0000000000..98d6f7a442 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/LuaHelpers.h @@ -0,0 +1,793 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2012, Vinnie Falco +// Copyright 2007, Nathan Reed +// SPDX-License-Identifier: MIT + +#pragma once + +#include "FuncTraits.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace luabridge { + +/** + * @brief Helper for unused vars. + */ +template +constexpr void unused(Args&&...) +{ +} + +// These are for Lua versions prior to 5.2.0. +#if LUA_VERSION_NUM < 502 +using lua_Unsigned = std::make_unsigned_t; + +#if ! LUABRIDGE_ON_LUAU +inline int lua_absindex(lua_State* L, int idx) +{ + if (idx > LUA_REGISTRYINDEX && idx < 0) + return lua_gettop(L) + idx + 1; + else + return idx; +} +#endif + +#define LUA_OPEQ 1 +#define LUA_OPLT 2 +#define LUA_OPLE 3 + +inline int lua_compare(lua_State* L, int idx1, int idx2, int op) +{ + switch (op) + { + case LUA_OPEQ: + return lua_equal(L, idx1, idx2); + + case LUA_OPLT: + return lua_lessthan(L, idx1, idx2); + + case LUA_OPLE: + return lua_equal(L, idx1, idx2) || lua_lessthan(L, idx1, idx2); + + default: + return 0; + } +} + +#if ! LUABRIDGE_ON_LUAJIT +inline void* luaL_testudata(lua_State* L, int ud, const char* tname) +{ + void* p = lua_touserdata(L, ud); + if (p == nullptr) + return nullptr; + + if (! lua_getmetatable(L, ud)) + return nullptr; + + luaL_getmetatable(L, tname); + if (! lua_rawequal(L, -1, -2)) + p = nullptr; + + lua_pop(L, 2); + return p; +} +#endif + +inline int get_length(lua_State* L, int idx) +{ + return static_cast(lua_objlen(L, idx)); +} +#else // LUA_VERSION_NUM >= 502 +inline int get_length(lua_State* L, int idx) +{ + return static_cast(lua_rawlen(L, idx)); +} +#endif // LUA_VERSION_NUM < 502 + +// These functions and defines are for Luau. +#if LUABRIDGE_ON_LUAU +inline int luaL_ref(lua_State* L, int idx) +{ + LUABRIDGE_ASSERT(idx == LUA_REGISTRYINDEX); + + const int ref = lua_ref(L, -1); + + lua_pop(L, 1); + + return ref; +} + +inline void luaL_unref(lua_State* L, int idx, int ref) +{ + unused(idx); + + lua_unref(L, ref); +} + +/** + * @brief Trampolines adapting a `void(void*)` destructor to the signature expected by `lua_newuserdatadtor`. + * + * Older Luau versions take `void (*)(void*)`, newer ones take `lua_Destructor` (`void (*)(lua_State*, void*)`). + * Overload resolution against the parameter type of `lua_newuserdatadtor` picks the right one. + */ +template +inline void luau_userdata_dtor(void* x) +{ + Dtor(x); +} + +template +inline void luau_userdata_dtor(lua_State*, void* x) +{ + Dtor(x); +} + +template +inline void* lua_newuserdatadtor_x(lua_State* L, size_t sz) +{ + return lua_newuserdatadtor(L, sz, &luau_userdata_dtor); +} + +template +inline void luau_destroy_userdata(void* x) +{ + T* object = static_cast(x); + object->~T(); +} + +template +inline void* lua_newuserdata_x(lua_State* L, size_t sz) +{ + return lua_newuserdatadtor_x<&luau_destroy_userdata>(L, sz); +} + +inline void lua_pushcfunction_x(lua_State *L, lua_CFunction fn, const char* debugname) +{ + lua_pushcfunction(L, fn, debugname); +} + +inline void lua_pushcclosure_x(lua_State* L, lua_CFunction fn, const char* debugname, int n) +{ + lua_pushcclosure(L, fn, debugname, n); +} + +[[noreturn]] inline void lua_error_x(lua_State* L) +{ + lua_error(L); + + detail::unreachable(); +} + +inline int lua_getstack_x(lua_State* L, int level, lua_Debug* ar) +{ + return lua_getinfo(L, level, "nlS", ar); +} + +inline int lua_getstack_info_x(lua_State* L, int level, const char* what, lua_Debug* ar) +{ + return lua_getinfo(L, level, what, ar); +} + +inline int lua_rawgetp_x(lua_State* L, int idx, void* p) +{ + return lua_rawgetp(L, idx, p); +} + +inline void lua_rawsetp_x(lua_State* L, int idx, void* p) +{ + lua_rawsetp(L, idx, p); +} + +#else +using ::luaL_ref; +using ::luaL_unref; + +template +inline void* lua_newuserdata_x(lua_State* L, size_t sz) +{ + return lua_newuserdata(L, sz); +} + +inline void lua_pushcfunction_x(lua_State *L, lua_CFunction fn, const char* debugname) +{ + unused(debugname); + + lua_pushcfunction(L, fn); +} + +inline void lua_pushcclosure_x(lua_State* L, lua_CFunction fn, const char* debugname, int n) +{ + unused(debugname); + + lua_pushcclosure(L, fn, n); +} + +[[noreturn]] inline void lua_error_x(lua_State* L) +{ + lua_error(L); + + detail::unreachable(); +} + +inline int lua_getstack_x(lua_State* L, int level, lua_Debug* ar) +{ + return lua_getstack(L, level, ar); +} + +inline int lua_getstack_info_x(lua_State* L, int level, const char* what, lua_Debug* ar) +{ + lua_getstack(L, level, ar); + return lua_getinfo(L, what, ar); +} + +inline int lua_rawgetp_x(lua_State* L, int idx, void* p) +{ +#if LUA_VERSION_NUM < 503 + idx = lua_absindex(L, idx); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushlightuserdata(L, p); + lua_rawget(L, idx); + return lua_type(L, -1); +#else + return lua_rawgetp(L, idx, p); +#endif +} + +inline void lua_rawsetp_x(lua_State* L, int idx, void* p) +{ +#if LUA_VERSION_NUM < 503 + idx = lua_absindex(L, idx); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushlightuserdata(L, p); + lua_insert(L, -2); + lua_rawset(L, idx); +#else + lua_rawsetp(L, idx, p); +#endif +} + +#endif // LUABRIDGE_ON_LUAU + +// These are for Lua versions prior to 5.5.0. +#if LUA_VERSION_NUM < 505 +inline lua_State* lua_newstate_x(lua_Alloc f, void* ud, [[maybe_unused]] unsigned seed) +{ + return lua_newstate(f, ud); +} +#else +inline lua_State* lua_newstate_x(lua_Alloc f, void* ud, unsigned seed) +{ + return lua_newstate(f, ud, seed); +} +#endif + +// These are for Lua versions prior to 5.3.0. +#if LUA_VERSION_NUM < 503 +inline lua_Number to_numberx(lua_State* L, int idx, int* isnum) +{ + lua_Number n = lua_tonumber(L, idx); + + if (isnum) + *isnum = (n != 0 || lua_isnumber(L, idx)); + + return n; +} + +inline lua_Integer to_integerx(lua_State* L, int idx, int* isnum) +{ + int ok = 0; + lua_Number n = to_numberx(L, idx, &ok); + + if (ok) + { + if (n < static_cast(std::numeric_limits::min()) || + n >= -static_cast(std::numeric_limits::min())) + { + if (isnum) + *isnum = 0; + return 0; + } + + const auto int_n = static_cast(n); + if (n == static_cast(int_n)) + { + if (isnum) + *isnum = 1; + + return int_n; + } + } + + if (isnum) + *isnum = 0; + + return 0; +} +#endif // LUA_VERSION_NUM < 503 + +inline int lua_rawgetp_x(lua_State* L, int idx, const void* p) +{ + return lua_rawgetp_x(L, idx, const_cast(p)); +} + +inline void lua_rawsetp_x(lua_State* L, int idx, const void* p) +{ + lua_rawsetp_x(L, idx, const_cast(p)); +} + +#ifndef LUA_OK +#define LUABRIDGE_LUA_OK 0 +#else +#define LUABRIDGE_LUA_OK LUA_OK +#endif + +/** + * @brief Helper to throw or return an error code. + */ +template +std::error_code throw_or_error_code(ErrorType error) +{ +#if LUABRIDGE_HAS_EXCEPTIONS + throw T(makeErrorCode(error).message().c_str()); +#else + return makeErrorCode(error); +#endif +} + +template +std::error_code throw_or_error_code(lua_State* L, ErrorType error) +{ +#if LUABRIDGE_HAS_EXCEPTIONS + throw T(L, makeErrorCode(error)); +#else + return unused(L), makeErrorCode(error); +#endif +} + +/** + * @brief Helper to throw or LUABRIDGE_ASSERT. + */ +template +void throw_or_assert(Args&&... args) +{ +#if LUABRIDGE_HAS_EXCEPTIONS + throw T(std::forward(args)...); +#else + unused(std::forward(args)...); + LUABRIDGE_ASSERT(false); +#endif +} + +/** + * @brief Helper to set unsigned. + */ +template +void pushunsigned(lua_State* L, T value) +{ + static_assert(std::is_unsigned_v); + + lua_pushinteger(L, static_cast(value)); +} + +/** + * @brief Helper to convert to integer. + */ +inline lua_Number tonumber(lua_State* L, int idx, int* isnum) +{ +#if ! LUABRIDGE_ON_LUAU && LUA_VERSION_NUM > 502 + return lua_tonumberx(L, idx, isnum); +#else + return to_numberx(L, idx, isnum); +#endif +} + +/** + * @brief Helper to convert to integer. + */ +inline lua_Integer tointeger(lua_State* L, int idx, int* isnum) +{ +#if ! LUABRIDGE_ON_LUAU && LUA_VERSION_NUM > 502 + return lua_tointegerx(L, idx, isnum); +#else + return to_integerx(L, idx, isnum); +#endif +} + +/** + * @brief Register main thread, only supported on 5.1. + */ +inline constexpr char main_thread_name[] = "__luabridge_main_thread"; + +inline void register_main_thread(lua_State* threadL) +{ +#if LUA_VERSION_NUM < 502 + if (threadL == nullptr) + lua_pushnil(threadL); + else + lua_pushthread(threadL); + + lua_setglobal(threadL, main_thread_name); +#else + unused(threadL); +#endif +} + +/** + * @brief Get main thread, not supported on 5.1. + */ +inline lua_State* main_thread(lua_State* threadL) +{ +#if LUA_VERSION_NUM < 502 + lua_getglobal(threadL, main_thread_name); + if (lua_isthread(threadL, -1)) + { + auto L = lua_tothread(threadL, -1); + lua_pop(threadL, 1); + return L; + } + LUABRIDGE_ASSERT(false); // Have you forgot to call luabridge::registerMainThread ? + lua_pop(threadL, 1); + return threadL; +#else + lua_rawgeti(threadL, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); + lua_State* L = lua_tothread(threadL, -1); + lua_pop(threadL, 1); + return L; +#endif +} + +/** + * @brief Get a table value, bypassing metamethods. + */ +inline int rawgetfield(lua_State* L, int index, const char* key) +{ + LUABRIDGE_ASSERT(lua_istable(L, index)); + index = lua_absindex(L, index); + lua_pushstring(L, key); +#if LUA_VERSION_NUM <= 502 + lua_rawget(L, index); + return lua_type(L, -1); +#else + return lua_rawget(L, index); +#endif +} + +/** + * @brief Set a table value, bypassing metamethods. + */ +inline void rawsetfield(lua_State* L, int index, const char* key) +{ + LUABRIDGE_ASSERT(lua_istable(L, index)); + index = lua_absindex(L, index); + lua_pushstring(L, key); + lua_insert(L, -2); + lua_rawset(L, index); +} + +/** + * @brief Returns true if the value is a full userdata (not light). + */ +[[nodiscard]] inline bool isfulluserdata(lua_State* L, int index) +{ + return lua_isuserdata(L, index) && !lua_islightuserdata(L, index); +} + +/** + * @brief Test lua_State objects for global equality. + * + * This can determine if two different lua_State objects really point + * to the same global state, such as when using coroutines. + * + * @note This is used for assertions. + */ +[[nodiscard]] inline bool equalstates(lua_State* L1, lua_State* L2) +{ + return lua_topointer(L1, LUA_REGISTRYINDEX) == lua_topointer(L2, LUA_REGISTRYINDEX); +} + +/** + * @brief Return the size of lua table, even if not a sequence { 1=x, 2=y, 3=... }. + */ +[[nodiscard]] inline int table_length(lua_State* L, int index) +{ + LUABRIDGE_ASSERT(lua_istable(L, index)); + + int items_count = 0; + + lua_pushnil(L); + while (lua_next(L, index) != 0) + { + ++items_count; + + lua_pop(L, 1); + } + + return items_count; +} + +/** + * @brief Return an aligned pointer of type T. + */ +template +[[nodiscard]] T* align(void* ptr) noexcept +{ + const auto address = reinterpret_cast(ptr); + + const auto offset = address % alignof(T); + const auto aligned_address = (offset == 0) ? address : (address + alignof(T) - offset); + + return reinterpret_cast(aligned_address); +} + +/** + * @brief Return if a pointer of type T is aligned. + */ +template , int> = 0> +[[nodiscard]] bool is_aligned(T address) noexcept +{ + static_assert(Alignment > 0u); + + return (reinterpret_cast(address) & (Alignment - 1u)) == 0u; +} + +/** + * @brief Return the space needed to align the type T on an unaligned address. + */ +template +[[nodiscard]] constexpr size_t maximum_space_needed_to_align() noexcept +{ + return sizeof(T) + alignof(T) - 1; +} + +/** + * @brief Deallocate lua userdata taking into account alignment. + */ +template +int lua_deleteuserdata_aligned(lua_State* L) +{ + LUABRIDGE_ASSERT(isfulluserdata(L, 1)); + + T* aligned = align(lua_touserdata(L, 1)); + aligned->~T(); + + return 0; +} + +#if LUABRIDGE_ON_LUAU +/** + * @brief Destroy luau userdata taking into account alignment. + */ +template +void luau_destroy_userdata_aligned(void* x) +{ + T* aligned = align(x); + aligned->~T(); +} +#endif + +/** + * @brief Allocate lua userdata taking into account alignment. + * + * Using this instead of lua_newuserdata directly prevents alignment warnings on 64bits platforms. + */ +template +void* lua_newuserdata_aligned(lua_State* L, Args&&... args) +{ + using U = std::remove_reference_t; + +#if LUABRIDGE_ON_LUAU + void* pointer = lua_newuserdatadtor_x<&luau_destroy_userdata_aligned>(L, maximum_space_needed_to_align()); +#else + void* pointer = lua_newuserdata_x(L, maximum_space_needed_to_align()); + + lua_newtable(L); + lua_pushcfunction_x(L, &lua_deleteuserdata_aligned, ""); + rawsetfield(L, -2, "__gc"); + lua_setmetatable(L, -2); +#endif + + U* aligned = align(pointer); + + new (aligned) U(std::forward(args)...); + + return pointer; +} + +/** + * @brief Safe error able to walk backwards for error reporting correctly. + */ +[[noreturn]] inline void raise_lua_error(lua_State* L, const char* fmt, ...) +{ + va_list argp; + va_start(argp, fmt); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + + const char* message = lua_tostring(L, -1); + if (message != nullptr) + { + if (auto str = std::string_view(message); !str.empty() && str[0] == '[') + lua_error_x(L); + } + + bool pushed_error = false; + for (int level = 1; level <= 2; ++level) + { + lua_Debug ar; + +#if LUABRIDGE_ON_LUAU + if (lua_getinfo(L, level, "sl", &ar) == 0) + continue; +#else + if (lua_getstack(L, level, &ar) == 0 || lua_getinfo(L, "Sl", &ar) == 0) + continue; +#endif + + if (ar.currentline <= 0) + continue; + + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); + pushed_error = true; + + break; + } + + if (! pushed_error) + lua_pushliteral(L, ""); + + lua_pushvalue(L, -2); + lua_remove(L, -3); + lua_concat(L, 2); + + lua_error_x(L); +} + +/** + * @brief Checks if the value on the stack is a number type and can fit into the corresponding c++ integral type.. + */ +template +constexpr bool is_integral_representable_by(T value) +{ + constexpr bool same_signedness = (std::is_unsigned_v && std::is_unsigned_v) + || (!std::is_unsigned_v && !std::is_unsigned_v); + + if constexpr (sizeof(T) == sizeof(U)) + { + if constexpr (same_signedness) + { + return true; + } + else if constexpr (std::is_unsigned_v) + { + return value <= static_cast((std::numeric_limits::max)()); + } + else + { + return value >= static_cast((std::numeric_limits::min)()) + && static_cast(value) <= (std::numeric_limits::max)(); + } + } + else if constexpr (sizeof(T) < sizeof(U)) + { + return static_cast(value) >= (std::numeric_limits::min)() + && static_cast(value) <= (std::numeric_limits::max)(); + } + else if constexpr (std::is_unsigned_v) + { + return value <= static_cast((std::numeric_limits::max)()); + } + else + { + return value >= static_cast((std::numeric_limits::min)()) + && value <= static_cast((std::numeric_limits::max)()); + } +} + +template +bool is_integral_representable_by(lua_State* L, int index) +{ + int isValid = 0; + + const auto value = tointeger(L, index, &isValid); + + return isValid ? is_integral_representable_by(value) : false; +} + +/** + * @brief Checks if the value on the stack is a number type and can fit into the corresponding c++ numerical type.. + */ +template +bool is_floating_point_representable_by(T value) +{ + if constexpr (sizeof(T) == sizeof(U)) + { + return true; + } + else if constexpr (sizeof(T) < sizeof(U)) + { + if (std::isnan(value) || std::isinf(value)) + return true; + + return static_cast(value) >= -(std::numeric_limits::max)() + && static_cast(value) <= (std::numeric_limits::max)(); + } + else + { + if (std::isnan(value) || std::isinf(value)) + return true; + + return value >= static_cast(-(std::numeric_limits::max)()) + && value <= static_cast((std::numeric_limits::max)()); + } +} + +template +bool is_floating_point_representable_by(lua_State* L, int index) +{ + int isValid = 0; + + const auto value = tonumber(L, index, &isValid); + + return isValid ? is_floating_point_representable_by(value) : false; +} + +/** + * @brief Portable wrapper for lua_resume that normalises calling convention differences + * across Lua 5.1/LuaJIT (no from, no nresults), 5.2-5.3 (from but no nresults), and 5.4+ (from + nresults). + * + * @param L The coroutine thread to resume. + * @param from The thread doing the resuming (may be nullptr on older Lua). + * @param nargs Number of arguments on L's stack to pass to the resumed function. + * @param nresults Output: number of values on L's stack after resume (yielded or returned). + * For Lua 5.4+, filled directly by lua_resume. For older versions, computed via lua_gettop. + * @returns LUA_OK, LUA_YIELD, or an error code. + */ +inline int lua_resume_x(lua_State* L, lua_State* from, int nargs, int* nresults = nullptr) +{ +#if LUABRIDGE_ON_LUAJIT || LUA_VERSION_NUM == 501 + unused(from); + int status = lua_resume(L, nargs); + if (nresults) + *nresults = lua_gettop(L); + return status; +#elif LUABRIDGE_ON_LUAU || LUABRIDGE_ON_RAVI || LUA_VERSION_NUM < 504 + int status = lua_resume(L, from, nargs); + if (nresults) + *nresults = lua_gettop(L); + return status; +#else + int nr = 0; + int status = lua_resume(L, from, nargs, &nr); + if (nresults) + *nresults = nr; + return status; +#endif +} + +/** + * @brief Returns true if the currently running C function can yield via lua_yieldk. + * + * Returns false on Lua 5.1, LuaJIT, and Luau where lua_yieldk is unavailable. + */ +inline bool lua_isyieldable_x(lua_State* L) +{ +#if LUABRIDGE_ON_LUAJIT || LUA_VERSION_NUM == 501 || LUABRIDGE_ON_LUAU + unused(L); + return false; +#elif LUA_VERSION_NUM < 503 + unused(L); + return true; // lua_yieldk exists in 5.2; assume yieldable when reached +#else + return lua_isyieldable(L) != 0; +#endif +} + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/LuaRef.h b/external/include/LuaBridge3/LuaBridge/detail/LuaRef.h new file mode 100644 index 0000000000..2c2f59ce8e --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/LuaRef.h @@ -0,0 +1,2099 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2019, George Tokmaji +// Copyright 2018, Dmitry Tarakanov +// Copyright 2012, Vinnie Falco +// Copyright 2008, Nigel Atkinson +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" +#include "Errors.h" +#include "Expected.h" +#include "Stack.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace luabridge { + +template +class LuaFunction; + +//================================================================================================= +/** + * @brief Type tag for representing LUA_TNIL. + * + * Construct one of these using `LuaNil ()` to represent a Lua nil. This is faster than creating a reference in the registry to nil. + * Example: + * + * @code + * LuaRef t (LuaRef::createTable (L)); + * ... + * t ["k"] = LuaNil (); // assign nil + * @endcode + */ +struct LuaNil +{ +}; + +/** + * @brief Stack specialization for LuaNil. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, const LuaNil&) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushnil(L); + return {}; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_type(L, index) == LUA_TNIL; + } +}; + +//================================================================================================= +/** + * @brief Base class for Lua variables and table item reference classes. + */ +template +class LuaRefBase +{ +protected: + friend struct Stack; + + //============================================================================================= + /** + * @brief Type tag for stack construction. + */ + struct FromStack + { + }; + + LuaRefBase(lua_State* L) noexcept + : m_L(L) + { + LUABRIDGE_ASSERT(L != nullptr); + } + + //============================================================================================= + /** + * @brief Create a reference to this reference. + * + * @returns An index in the Lua registry. + */ + int createRef() const + { + impl().push(m_L); + + return luaL_ref(m_L, LUA_REGISTRYINDEX); + } + +public: + //============================================================================================= + /** + * @brief Convert to a string using lua_tostring function. + * + * @returns A string representation of the referred Lua value. + */ + std::string tostring() const + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(m_L, 2)) + return {}; +#endif + + const StackRestore stackRestore(m_L); + + lua_getglobal(m_L, "tostring"); + + impl().push(m_L); + + lua_call(m_L, 1, 1); + + const char* str = lua_tostring(m_L, -1); + return str != nullptr ? str : ""; + } + + //============================================================================================= + /** + * @brief Print a text description of the value to a stream. + * + * This is used for diagnostics. + * + * @param os An output stream. + */ + void print(std::ostream& os) const + { + switch (type()) + { + case LUA_TNONE: + case LUA_TNIL: + os << "nil"; + break; + + case LUA_TNUMBER: + os << unsafe_cast(); + break; + + case LUA_TBOOLEAN: + os << (unsafe_cast() ? "true" : "false"); + break; + + case LUA_TSTRING: + os << '"' << unsafe_cast() << '"'; + break; + + case LUA_TTABLE: + case LUA_TFUNCTION: + case LUA_TTHREAD: + case LUA_TUSERDATA: + case LUA_TLIGHTUSERDATA: + os << tostring(); + break; + + default: + os << "unknown"; + break; + } + } + + //============================================================================================= + /** + * @brief Insert a Lua value or table item reference to a stream. + * + * @param os An output stream. + * @param ref A Lua reference. + * + * @returns The output stream. + */ + friend std::ostream& operator<<(std::ostream& os, const LuaRefBase& ref) + { + ref.print(os); + return os; + } + + //============================================================================================= + /** + * @brief Retrieve the lua_State associated with the reference. + * + * @returns A Lua state. + */ + lua_State* state() const + { + return m_L; + } + + //============================================================================================= + /** + * @brief Return the Lua type of the referred value. + * + * This invokes lua_type(). + * + * @returns The type of the referred value. + * + * @see lua_type() + */ + int type() const + { + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + return lua_type(m_L, -1); + } + + /** + * @brief Indicate whether it is a nil reference. + * + * @returns True if this is a nil reference, false otherwise. + */ + bool isNil() const { return type() == LUA_TNIL; } + + /** + * @brief Indicate whether it is a reference to a boolean. + * + * @returns True if it is a reference to a boolean, false otherwise. + */ + bool isBool() const { return type() == LUA_TBOOLEAN; } + + /** + * @brief Indicate whether it is a reference to a number. + * + * @returns True if it is a reference to a number, false otherwise. + */ + bool isNumber() const { return type() == LUA_TNUMBER; } + + /** + * @brief Indicate whether it is a reference to a string. + * + * @returns True if it is a reference to a string, false otherwise. + */ + bool isString() const { return type() == LUA_TSTRING; } + + /** + * @brief Indicate whether it is a reference to a table. + * + * @returns True if it is a reference to a table, false otherwise. + */ + bool isTable() const { return type() == LUA_TTABLE; } + + /** + * @brief Indicate whether it is a reference to a function. + * + * @returns True if it is a reference to a function, false otherwise. + */ + bool isFunction() const { return type() == LUA_TFUNCTION; } + + /** + * @brief Indicate whether it is a reference to a full userdata. + * + * @returns True if it is a reference to a full userdata, false otherwise. + */ + bool isUserdata() const { return type() == LUA_TUSERDATA; } + + /** + * @brief Indicate whether it is a reference to a lua thread (coroutine). + * + * @returns True if it is a reference to a lua thread, false otherwise. + */ + bool isThread() const { return type() == LUA_TTHREAD; } + + /** + * @brief Indicate whether it is a reference to a light userdata. + * + * @returns True if it is a reference to a light userdata, false otherwise. + */ + bool isLightUserdata() const { return type() == LUA_TLIGHTUSERDATA; } + + /** + * @brief Indicate whether it is a callable. + * + * @returns True if it is a callable, false otherwise. + */ + bool isCallable() const + { + if (isFunction()) + return true; + + auto metatable = getMetatable(); + return metatable.isTable() && metatable["__call"].isFunction(); + } + + /** + * @brief Get the name of the class, only if it is a C++ registered class via the library. + * + * @returns An optional string containing the name used to register the class with `beginClass`, nullopt in case it's not a registered class. + */ + std::optional getClassName() const + { + if (! isUserdata()) + return std::nullopt; + + const StackRestore stackRestore(m_L); + + impl().push(m_L); + if (! lua_getmetatable(m_L, -1)) + return std::nullopt; + + lua_rawgetp_x(m_L, -1, detail::getTypeKey()); + if (lua_isstring(m_L, -1)) + return lua_tostring(m_L, -1); + + return std::nullopt; + } + + //============================================================================================= + /** + * @brief Perform a safe explicit conversion to the type T. + * + * @returns An expected holding a value of the type T converted from this reference or an error code. + */ + template + TypeResult cast() const + { + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + return Stack::get(m_L, -1); + } + + /** + * @brief Perform an unsafe explicit conversion to the type T. + * + * @returns A value of the type T converted from this reference. + */ + template + T unsafe_cast() const + { + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + return *Stack::get(m_L, -1); + } + + //============================================================================================= + /** + * @brief Indicate if this reference is convertible to the type T. + * + * @returns True if the referred value is convertible to the type T, false otherwise. + */ + template + bool isInstance() const + { + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + return Stack::isInstance(m_L, -1); + } + + //============================================================================================= + /** + * @brief Type cast operator. + * + * This operator calls cast and always dereference the returned expected instance, resulting in exceptions being thrown if the + * exceptions are enabled, or otherwise we'll enter the UB land (and a likely crash down the line). + * + * @returns A value of the type T converted from this reference. + */ + template + operator T() const + { + return cast().value(); + } + + //============================================================================================= + /** + * @brief Get the metatable for the LuaRef. + * + * @returns A LuaRef holding the metatable of the lua object. + */ + LuaRef getMetatable() const + { + if (isNil()) + return LuaRef(m_L); + + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + if (! lua_getmetatable(m_L, -1)) + return LuaRef(m_L); + + return LuaRef::fromStack(m_L); + } + + //============================================================================================= + /** + * @brief Compare this reference with a specified value using lua_compare(). + * + * This invokes metamethods. + * + * @param rhs A value to compare with. + * + * @returns True if the referred value is equal to the specified one. + */ + template + bool operator==(const T& rhs) const + { + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + if (! Stack::push(m_L, rhs)) + return false; + + return lua_compare(m_L, -2, -1, LUA_OPEQ) == 1; + } + + /** + * @brief Compare this reference with a specified value using lua_compare(). + * + * This invokes metamethods. + * + * @param rhs A value to compare with. + * + * @returns True if the referred value is not equal to the specified one. + */ + template + bool operator!=(const T& rhs) const + { + return !(*this == rhs); + } + + /** + * @brief Compare this reference with a specified value using lua_compare(). + * + * This invokes metamethods. + * + * @param rhs A value to compare with. + * + * @returns True if the referred value is less than the specified one. + */ + template + bool operator<(const T& rhs) const + { + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + if (! Stack::push(m_L, rhs)) + return false; + + const int lhsType = lua_type(m_L, -2); + const int rhsType = lua_type(m_L, -1); + if (lhsType != rhsType) + return lhsType < rhsType; + + return lua_compare(m_L, -2, -1, LUA_OPLT) == 1; + } + + /** + * @brief Compare this reference with a specified value using lua_compare(). + * + * This invokes metamethods. + * + * @param rhs A value to compare with. + * + * @returns True if the referred value is less than or equal to the specified one. + */ + template + bool operator<=(const T& rhs) const + { + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + if (! Stack::push(m_L, rhs)) + return false; + + const int lhsType = lua_type(m_L, -2); + const int rhsType = lua_type(m_L, -1); + if (lhsType != rhsType) + return lhsType <= rhsType; + + return lua_compare(m_L, -2, -1, LUA_OPLE) == 1; + } + + /** + * @brief Compare this reference with a specified value using lua_compare(). + * + * This invokes metamethods. + * + * @param rhs A value to compare with. + * + * @returns True if the referred value is greater than the specified one. + */ + template + bool operator>(const T& rhs) const + { + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + if (! Stack::push(m_L, rhs)) + return false; + + const int lhsType = lua_type(m_L, -2); + const int rhsType = lua_type(m_L, -1); + if (lhsType != rhsType) + return lhsType > rhsType; + + return lua_compare(m_L, -1, -2, LUA_OPLT) == 1; + } + + /** + * @brief Compare this reference with a specified value using lua_compare(). + * + * This invokes metamethods. + * + * @param rhs A value to compare with. + * + * @returns True if the referred value is greater than or equal to the specified one. + */ + template + bool operator>=(const T& rhs) const + { + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + if (! Stack::push(m_L, rhs)) + return false; + + const int lhsType = lua_type(m_L, -2); + const int rhsType = lua_type(m_L, -1); + if (lhsType != rhsType) + return lhsType >= rhsType; + + return lua_compare(m_L, -1, -2, LUA_OPLE) == 1; + } + + /** + * @brief Compare this reference with a specified value using lua_compare(). + * + * This does not invoke metamethods. + * + * @param rhs A value to compare with. + * + * @returns True if the referred value is equal to the specified one. + */ + template + [[nodiscard]] bool rawequal(const T& v) const + { + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + if (! Stack::push(m_L, v)) + return false; + + return lua_rawequal(m_L, -1, -2) == 1; + } + + //============================================================================================= + /** + * @brief Return the length of a referred array. + * + * This is identical to applying the Lua # operator. + * + * @returns The length of the referred array. + */ + [[nodiscard]] int length() const + { + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + return get_length(m_L, -1); + } + + //============================================================================================= + /** + * @brief Append one or more values to a referred table. + * + * If the table is a sequence this will add more elements to it. + * + * @param vs Values to append. + * + * @returns True if all values were successfully appended. + */ + template + [[nodiscard]] bool append(const Ts&... vs) const + { + static_assert(sizeof...(vs) > 0); + + const StackRestore stackRestore(m_L); + + impl().push(m_L); + + int index = get_length(m_L, -1) + 1; + + auto appendOne = [&](const auto& v) -> bool + { + if (! Stack>::push(m_L, v)) + return false; + + lua_rawseti(m_L, -2, index++); + return true; + }; + + return (appendOne(vs) && ...); + } + + //============================================================================================= + /** + * @brief Call Lua code and decode the first return value to R. + * + * For tuple types, each tuple element is decoded from a distinct Lua return value. + */ + template + TypeResult call(Args&&... args) const; + + /** + * @brief Call Lua code assuming no return values. + */ + template + TypeResult operator()(Args&&... args) const; + + /** + * @brief Call Lua code with an explicit error handler and decode the return type. + */ + template + TypeResult callWithHandler(F&& errorHandler, Args&&... args) const; + + /** + * @brief Call Lua code with an explicit error handler and no return values. + */ + template + TypeResult callWithHandler(F&& errorHandler, Args&&... args) const; + + /** + * @brief Build a typed callable wrapper from this Lua object. + */ + template + LuaFunction callable() const; + +protected: + lua_State* m_L = nullptr; + +private: + const Impl& impl() const { return static_cast(*this); } + + Impl& impl() { return static_cast(*this); } +}; + +//================================================================================================= +/** + * @brief Lightweight reference to a Lua object. + * + * The reference is maintained for the lifetime of the C++ object. + */ +class LuaRef : public LuaRefBase +{ + //============================================================================================= + /** + * @brief A proxy for representing table values. + */ + class TableItem : public LuaRefBase + { + friend class LuaRef; + + struct AdoptTableRef + { + }; + + struct ChainTableRef + { + }; + + public: + // Table items own the table they reference so stored proxies remain valid after the parent LuaRef changes. + // Rvalue indexing can adopt the parent table ref and defer one chained lookup to avoid extra registry churn. + //========================================================================================= + /** + * @brief Construct a TableItem from a table value. + * + * The table is in the registry, and the key is at the top of the stack. + * The key is popped off the stack. + * + * @param L A lua state. + * @param tableRef The index of a table in the Lua registry. + */ + TableItem(lua_State* L, int tableRef) + : LuaRefBase(L) + , m_keyRef(luaL_ref(L, LUA_REGISTRYINDEX)) + , m_ownsTableRef(true) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(m_L, 1, detail::error_lua_stack_overflow); +#endif + + lua_rawgeti(m_L, LUA_REGISTRYINDEX, tableRef); + m_tableRef = luaL_ref(L, LUA_REGISTRYINDEX); + } + + template + TableItem(lua_State* L, int tableRef, const char (&key)[N]) + : LuaRefBase(L) + , m_keyLiteral(key) + , m_ownsTableRef(true) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(m_L, 1, detail::error_lua_stack_overflow); +#endif + + lua_rawgeti(m_L, LUA_REGISTRYINDEX, tableRef); + m_tableRef = luaL_ref(L, LUA_REGISTRYINDEX); + } + + TableItem(lua_State* L, int tableRef, AdoptTableRef) + : LuaRefBase(L) + , m_tableRef(tableRef) + , m_keyRef(luaL_ref(L, LUA_REGISTRYINDEX)) + , m_ownsTableRef(true) + { + } + + template + TableItem(lua_State* L, int tableRef, AdoptTableRef, const char (&key)[N]) + : LuaRefBase(L) + , m_tableRef(tableRef) + , m_keyLiteral(key) + , m_ownsTableRef(true) + { + } + + TableItem(TableItem&& table, ChainTableRef) + : LuaRefBase(table.m_L) + , m_tableRef(std::exchange(table.m_tableRef, LUA_NOREF)) + , m_keyRef(luaL_ref(m_L, LUA_REGISTRYINDEX)) + , m_parentKeyRef(std::exchange(table.m_keyRef, LUA_NOREF)) + , m_parentKeyLiteral(std::exchange(table.m_keyLiteral, nullptr)) + , m_ownsTableRef(std::exchange(table.m_ownsTableRef, false)) + { + } + + template + TableItem(TableItem&& table, ChainTableRef, const char (&key)[N]) + : LuaRefBase(table.m_L) + , m_tableRef(std::exchange(table.m_tableRef, LUA_NOREF)) + , m_parentKeyRef(std::exchange(table.m_keyRef, LUA_NOREF)) + , m_keyLiteral(key) + , m_parentKeyLiteral(std::exchange(table.m_keyLiteral, nullptr)) + , m_ownsTableRef(std::exchange(table.m_ownsTableRef, false)) + { + } + + //========================================================================================= + /** + * @brief Create a TableItem via copy constructor. + * + * It is best to avoid code paths that invoke this, because it creates an extra temporary Lua reference. Typically this is done by + * passing the TableItem parameter as a `const` reference. + * + * @param other Another Lua table item reference. + */ + TableItem(const TableItem& other) + : LuaRefBase(other.m_L) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(m_L, 1)) + return; +#endif + + other.pushTable(m_L); + m_tableRef = luaL_ref(m_L, LUA_REGISTRYINDEX); + m_ownsTableRef = true; + + m_keyLiteral = other.m_keyLiteral; + if (other.m_keyRef != LUA_NOREF) + { + other.pushKey(m_L); + m_keyRef = luaL_ref(m_L, LUA_REGISTRYINDEX); + } + } + + //========================================================================================= + /** + * @brief Destroy the proxy. + * + * This does not destroy the table value. + */ + ~TableItem() + { + if (m_keyRef != LUA_NOREF) + luaL_unref(m_L, LUA_REGISTRYINDEX, m_keyRef); + + if (m_parentKeyRef != LUA_NOREF) + luaL_unref(m_L, LUA_REGISTRYINDEX, m_parentKeyRef); + + if (m_ownsTableRef && m_tableRef != LUA_NOREF) + luaL_unref(m_L, LUA_REGISTRYINDEX, m_tableRef); + } + + //========================================================================================= + /** + * @brief Indicate whether this TableItem proxy is in a valid state. + * + * @returns True if the table reference is valid, false otherwise. + */ + bool isValid() const { return m_tableRef != LUA_NOREF; } + + //========================================================================================= + /** + * @brief Copy assignment operator (copy-and-swap idiom). + * + * Makes this TableItem refer to the same table slot as `other`. + * + * @param other Another Lua table item reference. + * + * @returns This reference. + */ + TableItem& operator=(const TableItem& other) + { + if (this == &other) + return *this; + TableItem tmp(other); + swap(tmp); + return *this; + } + + //========================================================================================= + /** + * @brief Move constructor. + * + * Transfers ownership of the table and key refs from `other` to this. + * + * @param other Another Lua table item reference (moved-from). + */ + TableItem(TableItem&& other) noexcept + : LuaRefBase(other.m_L) + , m_tableRef(std::exchange(other.m_tableRef, LUA_NOREF)) + , m_keyRef(std::exchange(other.m_keyRef, LUA_NOREF)) + , m_parentKeyRef(std::exchange(other.m_parentKeyRef, LUA_NOREF)) + , m_keyLiteral(std::exchange(other.m_keyLiteral, nullptr)) + , m_parentKeyLiteral(std::exchange(other.m_parentKeyLiteral, nullptr)) + , m_ownsTableRef(std::exchange(other.m_ownsTableRef, false)) + { + } + + //========================================================================================= + /** + * @brief Move assignment operator. + * + * Releases this TableItem's refs and takes ownership of `other`'s refs. + * + * @param other Another Lua table item reference (moved-from). + * + * @returns This reference. + */ + TableItem& operator=(TableItem&& other) noexcept + { + if (this == &other) + return *this; + + if (m_keyRef != LUA_NOREF) + luaL_unref(m_L, LUA_REGISTRYINDEX, m_keyRef); + if (m_parentKeyRef != LUA_NOREF) + luaL_unref(m_L, LUA_REGISTRYINDEX, m_parentKeyRef); + if (m_ownsTableRef && m_tableRef != LUA_NOREF) + luaL_unref(m_L, LUA_REGISTRYINDEX, m_tableRef); + + m_L = other.m_L; + m_tableRef = std::exchange(other.m_tableRef, LUA_NOREF); + m_keyRef = std::exchange(other.m_keyRef, LUA_NOREF); + m_parentKeyRef = std::exchange(other.m_parentKeyRef, LUA_NOREF); + m_keyLiteral = std::exchange(other.m_keyLiteral, nullptr); + m_parentKeyLiteral = std::exchange(other.m_parentKeyLiteral, nullptr); + m_ownsTableRef = std::exchange(other.m_ownsTableRef, false); + + return *this; + } + + //========================================================================================= + /** + * @brief Assign a new value to this table key. + * + * This may invoke metamethods. + * + * @tparam T The type of a value to assign. + * + * @param v A value to assign. + * + * @returns This reference. + */ + template + TableItem& operator=(const T& v) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(m_L, 3)) + return *this; +#endif + + const StackRestore stackRestore(m_L); + + pushTable(m_L); + if (m_keyLiteral != nullptr) + { + if (! Stack::push(m_L, v)) + return *this; + + lua_setfield(m_L, -2, m_keyLiteral); + } + else + { + pushKey(m_L); + + if (! Stack::push(m_L, v)) + return *this; + + lua_settable(m_L, -3); + } + + return *this; + } + + //========================================================================================= + /** + * @brief Assign a new value to this table key. + * + * The assignment is raw, no metamethods are invoked. + * + * @tparam T The type of a value to assign. + * + * @param v A value to assign. + * + * @returns This reference. + */ + template + TableItem& rawset(const T& v) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(m_L, 3)) + return *this; +#endif + + const StackRestore stackRestore(m_L); + + pushTable(m_L); + if (m_keyLiteral != nullptr) + { + lua_pushstring(m_L, m_keyLiteral); + + if (! Stack::push(m_L, v)) + return *this; + + lua_rawset(m_L, -3); + } + else + { + pushKey(m_L); + + if (! Stack::push(m_L, v)) + return *this; + + lua_rawset(m_L, -3); + } + + return *this; + } + + //========================================================================================= + /** + * @brief Push the value onto the Lua stack. + */ + void push() const + { + push(m_L); + } + + void push(lua_State* L) const + { + LUABRIDGE_ASSERT(equalstates(L, m_L)); + +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return; +#endif + + pushTable(L); + + if (m_keyLiteral != nullptr) + { + lua_getfield(L, -1, m_keyLiteral); + } + else + { + pushKey(L); + lua_gettable(L, -2); + } + + lua_remove(L, -2); // remove the table + } + + //========================================================================================= + /** + * @brief Access a table value using a key. + * + * This invokes metamethods. + * + * @tparam T The type of a key. + * + * @param key A key value. + * + * @returns A Lua table item reference. + */ + template + TableItem operator[](const T& key) const& + { + const StackRestore stackRestore(m_L); + + if (! Stack::push(m_L, key)) + lua_pushnil(m_L); + + return materializedChildFromStackKey(); + } + + template + TableItem operator[](const T& key) && + { + if (canChain()) + { + if (! Stack::push(m_L, key)) + lua_pushnil(m_L); + + return TableItem(std::move(*this), ChainTableRef{}); + } + + const StackRestore stackRestore(m_L); + + if (! Stack::push(m_L, key)) + lua_pushnil(m_L); + + return materializedChildFromStackKey(); + } + + template + TableItem operator[](const char (&key)[N]) const& + { + const StackRestore stackRestore(m_L); + + push(m_L); + + const auto tableRef = luaL_ref(m_L, LUA_REGISTRYINDEX); + + return TableItem(m_L, tableRef, AdoptTableRef{}, key); + } + + template + TableItem operator[](const char (&key)[N]) && + { + if (canChain()) + return TableItem(std::move(*this), ChainTableRef{}, key); + + const StackRestore stackRestore(m_L); + + push(m_L); + + const auto tableRef = luaL_ref(m_L, LUA_REGISTRYINDEX); + + return TableItem(m_L, tableRef, AdoptTableRef{}, key); + } + + //========================================================================================= + /** + * @brief Access a table value using a key. + * + * The operation is raw, metamethods are not invoked. The result is passed by value and may not be modified. + * + * @tparam T The type of a key. + * + * @param key A key value. + * + * @returns A Lua value reference. + */ + template + LuaRef rawget(const T& key) const + { + return LuaRef(*this).rawget(key); + } + + //========================================================================================= + /** + * @brief Get a field from the table item value without metamethods in an unsafe fast path. + * + * @param key A field key. + * + * @returns The converted value. + */ + template + T unsafeRawgetField(const char* key) const + { +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(m_L, 3, detail::error_lua_stack_overflow); +#endif + + push(m_L); + lua_pushstring(m_L, key); + lua_rawget(m_L, -2); + + auto result = Stack::get(m_L, -1); + lua_pop(m_L, 2); + + return result.value(); + } + + //========================================================================================= + /** + * @brief Set a field on the table item value without metamethods in an unsafe fast path. + * + * @param key A field key. + * @param value A value to assign. + */ + template + void unsafeRawsetField(const char* key, T&& value) const + { +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(m_L, 3, detail::error_lua_stack_overflow); +#endif + + push(m_L); + lua_pushstring(m_L, key); + [[maybe_unused]] const auto pushed = Stack>::push(m_L, std::forward(value)); + LUABRIDGE_ASSERT(static_cast(pushed)); + + lua_rawset(m_L, -3); + lua_pop(m_L, 1); + } + + private: + void swap(TableItem& other) noexcept + { + using std::swap; + swap(m_L, other.m_L); + swap(m_tableRef, other.m_tableRef); + swap(m_keyRef, other.m_keyRef); + swap(m_parentKeyRef, other.m_parentKeyRef); + swap(m_keyLiteral, other.m_keyLiteral); + swap(m_parentKeyLiteral, other.m_parentKeyLiteral); + swap(m_ownsTableRef, other.m_ownsTableRef); + } + + bool hasParentKey() const + { + return m_parentKeyLiteral != nullptr || m_parentKeyRef != LUA_NOREF; + } + + bool canChain() const + { + return m_ownsTableRef && ! hasParentKey(); + } + + TableItem materializedChildFromStackKey() const + { + push(m_L); + lua_insert(m_L, -2); + + lua_pushvalue(m_L, -2); + const auto tableRef = luaL_ref(m_L, LUA_REGISTRYINDEX); + lua_remove(m_L, -2); + + return TableItem(m_L, tableRef, AdoptTableRef{}); + } + + void pushTable(lua_State* L) const + { + if (m_tableRef == LUA_REFNIL) + lua_pushnil(L); + else + lua_rawgeti(L, LUA_REGISTRYINDEX, m_tableRef); + + if (m_parentKeyLiteral != nullptr) + { + lua_getfield(L, -1, m_parentKeyLiteral); + lua_remove(L, -2); + } + else if (m_parentKeyRef != LUA_NOREF) + { + pushRef(L, m_parentKeyRef); + lua_gettable(L, -2); + lua_remove(L, -2); + } + } + + void pushKey(lua_State* L) const + { + pushRef(L, m_keyRef); + } + + void pushRef(lua_State* L, int ref) const + { + if (ref == LUA_REFNIL) + lua_pushnil(L); + else + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); + } + + int m_tableRef = LUA_NOREF; + int m_keyRef = LUA_NOREF; + int m_parentKeyRef = LUA_NOREF; + const char* m_keyLiteral = nullptr; + const char* m_parentKeyLiteral = nullptr; + bool m_ownsTableRef = false; + }; + + friend struct Stack; + friend struct Stack; + + //========================================================================================= + /** + * @brief Create a reference to an object at the top of the Lua stack and pop it. + * + * This constructor is private and not invoked directly. Instead, use the `fromStack` function. + * + * @param L A Lua state. + * + * @note The object is popped. + */ + LuaRef(lua_State* L, FromStack) noexcept + : LuaRefBase(L) + , m_ref(luaL_ref(m_L, LUA_REGISTRYINDEX)) + { + } + + //========================================================================================= + /** + * @brief Create a reference to an object on the Lua stack. + * + * This constructor is private and not invoked directly. Instead, use the `fromStack` function. + * + * @param L A Lua state. + * + * @param index The index of the value on the Lua stack. + * + * @note The object is not popped. + */ + LuaRef(lua_State* L, int index, FromStack) + : LuaRefBase(L) + , m_ref(LUA_NOREF) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(m_L, 1)) + return; +#endif + + lua_pushvalue(m_L, index); + m_ref = luaL_ref(m_L, LUA_REGISTRYINDEX); + } + + LuaRef(std::nullptr_t) noexcept = delete; + +public: + //============================================================================================= + /** + * @brief Create an invalid reference that will be treated as nil. + * + * The Lua reference may be assigned later. + * + * @param L A Lua state. + */ + LuaRef(lua_State* L) noexcept + : LuaRefBase(L) + , m_ref(LUA_NOREF) + { + } + + //============================================================================================= + /** + * @brief Push a value onto a Lua stack and return a reference to it. + * + * @param L A Lua state. + * @param v A value to push. + */ + template + LuaRef(lua_State* L, const T& v) + : LuaRefBase(L) + , m_ref(LUA_NOREF) + { + if (! Stack::push(m_L, v)) + return; + + m_ref = luaL_ref(m_L, LUA_REGISTRYINDEX); + } + + //============================================================================================= + /** + * @brief Create a reference to a table item. + * + * @param v A table item reference. + */ + LuaRef(const TableItem& v) + : LuaRefBase(v.state()) + , m_ref(v.createRef()) + { + } + + //============================================================================================= + /** + * @brief Create a new reference to an existing Lua value. + * + * @param other An existing reference. + */ + LuaRef(const LuaRef& other) + : LuaRefBase(other.m_L) + , m_ref(other.createRef()) + { + } + + //============================================================================================= + /** + * @brief Move a reference to an existing Lua value. + * + * @param other An existing reference. + */ + LuaRef(LuaRef&& other) noexcept + : LuaRefBase(other.m_L) + , m_ref(std::exchange(other.m_ref, LUA_NOREF)) + { + } + + //============================================================================================= + /** + * @brief Destroy a reference. + * + * The corresponding Lua registry reference will be released. + * + * @note If the state refers to a thread, it is the responsibility of the caller to ensure that the thread still exists when the LuaRef is destroyed. + */ + ~LuaRef() + { + if (m_ref != LUA_NOREF) + luaL_unref(m_L, LUA_REGISTRYINDEX, m_ref); + } + + //============================================================================================= + /** + * @brief Return a reference to the top Lua stack item and pop it. + * + * The stack item is popped. + * + * @param L A Lua state. + * + * @returns A reference to a value that was on the top of the Lua stack. + */ + static LuaRef fromStack(lua_State* L) + { + return LuaRef(L, FromStack()); + } + + //============================================================================================= + /** + * @brief Return a reference to a Lua stack item with a specified index. + * + * The stack item is not removed. + * + * @param L A Lua state. + * @param index An index in the Lua stack. + * + * @returns A reference to a value in a Lua stack. + */ + static LuaRef fromStack(lua_State* L, int index) + { + return LuaRef(L, index, FromStack()); + } + + //============================================================================================= + /** + * @brief Create a new empty table on the top of a Lua stack and return a reference to it. + * + * @param L A Lua state. + * + * @returns A reference to the newly created table. + * + * @see luabridge::newTable() + */ + static LuaRef newTable(lua_State* L) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return { L }; +#endif + + lua_newtable(L); + return LuaRef(L, FromStack()); + } + + //============================================================================================= + /** + * @brief Create a new function on the top of a Lua stack and return a reference to it. + * + * @param L A Lua state. + * @param func The c++ function to map to lua. + * @param debugname Optional debug name (used only by Luau). + * + * @returns A reference to the newly created function. + * + * @see luabridge::newFunction() + */ + template + static LuaRef newFunction(lua_State* L, F&& func, const char* debugname = "") + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return { L }; +#endif + + detail::push_function(L, std::forward(func), debugname); + return LuaRef(L, FromStack()); + } + + //============================================================================================= + /** + * @brief Return a reference to a named global Lua variable. + * + * @param L A Lua state. + * @param name The name of a global variable. + * + * @returns A reference to the Lua variable. + * + * @see luabridge::getGlobal() + */ + static LuaRef getGlobal(lua_State* L, const char* name) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return { L }; +#endif + + lua_getglobal(L, name); + return LuaRef(L, FromStack()); + } + + //============================================================================================= + /** + * @brief Indicate whether it is an invalid reference. + * + * @returns True if this is an invalid reference, false otherwise. + */ + bool isValid() const { return m_ref != LUA_NOREF; } + + //============================================================================================= + /** + * @brief Assign another LuaRef to this LuaRef. + * + * @param rhs A reference to assign from. + * + * @returns This reference. + */ + LuaRef& operator=(const LuaRef& rhs) + { + LuaRef ref(rhs); + swap(ref); + return *this; + } + + //============================================================================================= + /** + * @brief Move assign another LuaRef to this LuaRef. + * + * @param rhs A reference to assign from. + * + * @returns This reference. + */ + LuaRef& operator=(LuaRef&& rhs) noexcept + { + if (m_ref != LUA_NOREF) + luaL_unref(m_L, LUA_REGISTRYINDEX, m_ref); + + m_L = rhs.m_L; + m_ref = std::exchange(rhs.m_ref, LUA_NOREF); + + return *this; + } + + //============================================================================================= + /** + * @brief Assign a table item reference. + * + * @param rhs A table item reference. + * + * @returns This reference. + */ + LuaRef& operator=(const LuaRef::TableItem& rhs) + { + LuaRef ref(rhs); + swap(ref); + return *this; + } + + //============================================================================================= + /** + * @brief Assign nil to this reference. + * + * @returns This reference. + */ + LuaRef& operator=(const LuaNil&) + { + LuaRef ref(m_L); + swap(ref); + return *this; + } + + //============================================================================================= + /** + * @brief Assign a different value to this reference. + * + * @param rhs A value to assign. + * + * @returns This reference. + */ + template + LuaRef& operator=(const T& rhs) + { + LuaRef ref(m_L, rhs); + swap(ref); + return *this; + } + + //============================================================================================= + /** + * @brief Place the object onto the Lua stack. + */ + void push() const + { + push(m_L); + } + + void push(lua_State* L) const + { + LUABRIDGE_ASSERT(equalstates(L, m_L)); + +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return; +#endif + + lua_rawgeti(L, LUA_REGISTRYINDEX, m_ref); + } + + //============================================================================================= + /** + * @brief Pop the top of Lua stack and assign the ref to m_ref + */ + void pop() + { + pop(m_L); + } + + void pop(lua_State* L) + { + LUABRIDGE_ASSERT(equalstates(L, m_L)); + + if (m_ref != LUA_NOREF) + luaL_unref(L, LUA_REGISTRYINDEX, m_ref); + + m_ref = luaL_ref(L, LUA_REGISTRYINDEX); + } + + //============================================================================================= + /** + * @brief Move the reference to a separate coroutine (lua_State). + */ + void moveTo(lua_State* newL) + { + push(); // push value onto m_L + + lua_xmove(m_L, newL, 1); // move value from m_L to newL (pops m_L, pushes newL) + + const int oldRef = m_ref; + lua_State* const oldL = m_L; + + m_L = newL; + m_ref = luaL_ref(newL, LUA_REGISTRYINDEX); // register on newL (pops from newL's stack) + + luaL_unref(oldL, LUA_REGISTRYINDEX, oldRef); // release old registry entry + } + + //============================================================================================= + /** + * @brief Access a table value using a key. + * + * This invokes metamethods. + * + * @param key A key in the table. + * + * @returns A reference to the table item. + */ + template + TableItem operator[](const T& key) const& + { + if (! Stack::push(m_L, key)) + { + lua_pushnil(m_L); + return TableItem(m_L, m_ref); + } + + return TableItem(m_L, m_ref); + } + + template + TableItem operator[](const T& key) && + { + if (! Stack::push(m_L, key)) + { + lua_pushnil(m_L); + return TableItem(m_L, m_ref); + } + + return TableItem(m_L, std::exchange(m_ref, LUA_NOREF), typename TableItem::AdoptTableRef{}); + } + + template + TableItem operator[](const char (&key)[N]) const& + { + return TableItem(m_L, m_ref, key); + } + + template + TableItem operator[](const char (&key)[N]) && + { + return TableItem(m_L, std::exchange(m_ref, LUA_NOREF), typename TableItem::AdoptTableRef{}, key); + } + + //============================================================================================= + /** + * @brief Access a table value using a key. + * + * The operation is raw, metamethods are not invoked. The result is passed by value and may not be modified. + * + * @param key A key in the table. + * + * @returns A reference to the table item. + */ + template + [[nodiscard]] LuaRef rawget(const T& key) const + { + const StackRestore stackRestore(m_L); + + push(m_L); + + if (! Stack::push(m_L, key)) + return LuaRef(m_L); + + lua_rawget(m_L, -2); + return LuaRef(m_L, FromStack()); + } + + + //============================================================================================= + /** + * @brief Get a table field by C-string key and convert to T. + * + * This invokes metamethods. + * + * @param key A field key. + * + * @returns A converted value or an error. + */ + template + [[nodiscard]] TypeResult getField(const char* key) const + { + const StackRestore stackRestore(m_L); + + push(m_L); + lua_getfield(m_L, -1, key); + + return Stack::get(m_L, -1); + } + + //============================================================================================= + /** + * @brief Try to get a table field by C-string key and convert to T. + * + * This invokes metamethods and returns std::nullopt when the referred value is not a table + * or the field cannot be converted to the requested type. + */ + template + [[nodiscard]] std::optional tryGetField(const char* key) const + { + const StackRestore stackRestore(m_L); + + push(m_L); + if (! lua_istable(m_L, -1)) + return std::nullopt; + + lua_getfield(m_L, -1, key); + + auto result = Stack>::get(m_L, -1); + if (! result) + return std::nullopt; + + return *result; + } + + //============================================================================================= + /** + * @brief Set a table field by C-string key. + * + * This invokes metamethods. + * + * @param key A field key. + * @param value A value to assign. + * + * @returns True if value push succeeded, false otherwise. + */ + template + [[nodiscard]] bool setField(const char* key, T&& value) const + { + const StackRestore stackRestore(m_L); + + push(m_L); + + if (! Stack>::push(m_L, std::forward(value))) + return false; + + lua_setfield(m_L, -2, key); + return true; + } + + //============================================================================================= + /** + * @brief Get a table field by C-string key without metamethods. + * + * @param key A field key. + * + * @returns A converted value or an error. + */ + template + [[nodiscard]] TypeResult rawgetField(const char* key) const + { + const StackRestore stackRestore(m_L); + + push(m_L); + lua_pushstring(m_L, key); + lua_rawget(m_L, -2); + + return Stack::get(m_L, -1); + } + + //============================================================================================= + /** + * @brief Set a table field by C-string key without metamethods. + * + * @param key A field key. + * @param value A value to assign. + * + * @returns True if key/value push succeeded, false otherwise. + */ + template + [[nodiscard]] bool rawsetField(const char* key, T&& value) const + { + const StackRestore stackRestore(m_L); + + push(m_L); + lua_pushstring(m_L, key); + + if (! Stack>::push(m_L, std::forward(value))) + return false; + + lua_rawset(m_L, -3); + return true; + } + + //============================================================================================= + /** + * @brief Get a table field by C-string key without metamethods in an unsafe fast path. + * + * This helper is intended for hot loops where stack conversion is known to succeed. + * + * @param key A field key. + * + * @returns The converted value. + */ + template + T unsafeRawgetField(const char* key) const + { +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(m_L, 3, detail::error_lua_stack_overflow); +#endif + + push(m_L); + lua_pushstring(m_L, key); + lua_rawget(m_L, -2); + + auto result = Stack::get(m_L, -1); + lua_pop(m_L, 2); + + return result.value(); + } + + //============================================================================================= + /** + * @brief Set a table field by C-string key without metamethods in an unsafe fast path. + * + * @param key A field key. + * @param value A value to assign. + */ + template + void unsafeRawsetField(const char* key, T&& value) const + { +#if LUABRIDGE_SAFE_STACK_CHECKS + luaL_checkstack(m_L, 3, detail::error_lua_stack_overflow); +#endif + + push(m_L); + lua_pushstring(m_L, key); + [[maybe_unused]] const auto pushed = Stack>::push(m_L, std::forward(value)); + LUABRIDGE_ASSERT(static_cast(pushed)); + + lua_rawset(m_L, -3); + lua_pop(m_L, 1); + } + + //============================================================================================= + /** + * @brief Get the Lua pointer of the referenced value. + */ + const void* getPointer() const + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(m_L, 3)) + return nullptr; +#endif + + lua_rawgeti(m_L, LUA_REGISTRYINDEX, m_ref); + + if (lua_isuserdata(m_L, -1) && lua_getmetatable(m_L, -1)) + { + const void* key = static_cast(detail::getTypeKey()); + lua_pushlightuserdata(m_L, const_cast(key)); + lua_rawget(m_L, -2); + const bool isLuaBridgeType = lua_isstring(m_L, -1); + lua_pop(m_L, 2); + + if (isLuaBridgeType) + { + const auto* ud = static_cast(lua_touserdata(m_L, -1)); + const void* ptr = ud->getPointer(); + lua_pop(m_L, 1); + return ptr; + } + } + + const void* ptr = lua_topointer(m_L, -1); + lua_pop(m_L, 1); + + return ptr; + } + + //============================================================================================= + /** + * @brief Get the unique hash of a LuaRef. + */ + [[nodiscard]] std::size_t hash() const + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(m_L, 1)) + return 0; +#endif + + lua_rawgeti(m_L, LUA_REGISTRYINDEX, m_ref); + + const int t = lua_type(m_L, -1); + + std::size_t value; + switch (t) + { + case LUA_TNONE: + case LUA_TNIL: + value = std::hash{}(nullptr); + break; + + case LUA_TBOOLEAN: + value = std::hash{}(lua_toboolean(m_L, -1) != 0); + break; + + case LUA_TNUMBER: + value = std::hash{}(lua_tonumber(m_L, -1)); + break; + + case LUA_TSTRING: + { + std::size_t len = 0; + const char* s = lua_tolstring(m_L, -1, &len); + value = std::hash{}(std::string_view(s, len)); + break; + } + + case LUA_TTABLE: + case LUA_TFUNCTION: + case LUA_TTHREAD: + case LUA_TUSERDATA: + case LUA_TLIGHTUSERDATA: + default: + value = reinterpret_cast(lua_topointer(m_L, -1)); + break; + } + + lua_pop(m_L, 1); + + const std::size_t seed = std::hash{}(t == LUA_TNONE ? LUA_TNIL : t); + return value + 0x9e3779b9u + (seed << 6) + (seed >> 2); + } + +private: + void swap(LuaRef& other) noexcept + { + using std::swap; + + swap(m_L, other.m_L); + swap(m_ref, other.m_ref); + } + + int m_ref = LUA_NOREF; +}; + +//================================================================================================= +/** + * @brief Equality between type T and LuaRef. + */ +template +auto operator==(const T& lhs, const LuaRef& rhs) + -> std::enable_if_t && !std::is_same_v>, bool> +{ + return rhs == lhs; +} + +/** + * @brief Inequality between type T and LuaRef. + */ +template +auto operator!=(const T& lhs, const LuaRef& rhs) + -> std::enable_if_t && !std::is_same_v>, bool> +{ + return !(rhs == lhs); +} + +/** + * @brief Less than between type T and LuaRef. + */ +template +auto operator<(const T& lhs, const LuaRef& rhs) + -> std::enable_if_t && !std::is_same_v>, bool> +{ + return rhs > lhs; +} + +/** + * @brief Less than equal between type T and LuaRef. + */ +template +auto operator<=(const T& lhs, const LuaRef& rhs) + -> std::enable_if_t && !std::is_same_v>, bool> +{ + return rhs >= lhs; +} + +/** + * @brief Greater than between type T and LuaRef. + */ +template +auto operator>(const T& lhs, const LuaRef& rhs) + -> std::enable_if_t && !std::is_same_v>, bool> +{ + return rhs < lhs; +} + +/** + * @brief Greater than equal between type T and LuaRef. + */ +template +auto operator>=(const T& lhs, const LuaRef& rhs) + -> std::enable_if_t && !std::is_same_v>, bool> +{ + return rhs <= lhs; +} + +//================================================================================================= +/** + * @brief Stack specialization for `LuaRef`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, const LuaRef& v) + { + v.push(L); + + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + return LuaRef::fromStack(L, index); + } + + [[nodiscard]] static bool isInstance(lua_State*, int) + { + return true; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `TableItem`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, const LuaRef::TableItem& v) + { + v.push(L); + + return {}; + } +}; + +//================================================================================================= +/** + * @brief Create a reference to a new, empty table. + * + * This is a syntactic abbreviation for LuaRef::newTable (). + */ +[[nodiscard]] inline LuaRef newTable(lua_State* L) +{ + return LuaRef::newTable(L); +} + +//================================================================================================= +/** + * @brief Create a reference to a new function. + * + * This is a syntactic abbreviation for LuaRef::newFunction (). + */ +template +[[nodiscard]] inline LuaRef newFunction(lua_State* L, F&& func) +{ + return LuaRef::newFunction(L, std::forward(func)); +} + +//================================================================================================= +/** + * @brief Create a reference to a value in the global table. + * + * This is a syntactic abbreviation for LuaRef::getGlobal (). + */ +[[nodiscard]] inline LuaRef getGlobal(lua_State* L, const char* name) +{ + return LuaRef::getGlobal(L, name); +} + +//================================================================================================= +/** + * @brief C++ like cast syntax, safe. + */ +template +[[nodiscard]] TypeResult cast(const LuaRef& ref) +{ + return ref.cast(); +} + +/** + * @brief C++ like cast syntax, unsafe. + */ +template +[[nodiscard]] T unsafe_cast(const LuaRef& ref) +{ + return ref.unsafe_cast(); +} +} // namespace luabridge + +namespace std { +template <> +struct hash +{ + std::size_t operator()(const luabridge::LuaRef& x) const + { + return x.hash(); + } +}; +} // namespace std diff --git a/external/include/LuaBridge3/LuaBridge/detail/Namespace.h b/external/include/LuaBridge3/LuaBridge/detail/Namespace.h new file mode 100644 index 0000000000..6d59cde01f --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Namespace.h @@ -0,0 +1,2206 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2019, Dmitry Tarakanov +// Copyright 2012, Vinnie Falco +// Copyright 2007, Nathan Reed +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" +#include "ClassInfo.h" +#include "FlagSet.h" +#include "LuaHelpers.h" +#include "LuaException.h" +#include "Options.h" +#include "TypeTraits.h" + +#include +#include +#include +#include +#include +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Base for class and namespace registration. + * + * Maintains Lua stack in the proper state. Once beginNamespace, beginClass or deriveClass is called the parent object upon its destruction + * may no longer clear the Lua stack. + * + * Then endNamespace or endClass is called, a new parent is created and the child transfers the responsibility for clearing stack to it. + * + * So there can be maximum one "active" registrar object. + */ +namespace detail { + +struct BaseClassInfo +{ + const void* staticKey; + const void* classKey; + lua_Integer castOffset; +}; + +template +lua_Integer computeCastOffset() noexcept +{ + static_assert(std::is_base_of_v); + + alignas(Derived) std::byte buf[sizeof(Derived)] = {}; + + auto* derived = reinterpret_cast(buf); + auto* base = static_cast(derived); // implicit upcast, purely pointer arithmetic + + return static_cast(reinterpret_cast(base) - reinterpret_cast(derived)); +} + +class Registrar +{ +protected: + Registrar(lua_State* L) + : L(L) + , m_stackSize(0) + { + } + + Registrar(lua_State* L, int skipStackPops) + : L(L) + , m_stackSize(0) + , m_skipStackPops(skipStackPops) + { + } + + Registrar(const Registrar& rhs) = delete; + + Registrar(Registrar&& rhs) + : L(rhs.L) + , m_stackSize(std::exchange(rhs.m_stackSize, 0)) + , m_skipStackPops(std::exchange(rhs.m_skipStackPops, 0)) + { + } + + Registrar& operator=(const Registrar& rhs) = delete; + + Registrar& operator=(Registrar&& rhs) + { + m_stackSize = std::exchange(rhs.m_stackSize, 0); + m_skipStackPops = std::exchange(rhs.m_skipStackPops, 0); + + return *this; + } + + ~Registrar() + { + const int popsCount = m_stackSize - m_skipStackPops; + if (popsCount > 0) + { + LUABRIDGE_ASSERT(popsCount <= lua_gettop(L)); + + lua_pop(L, popsCount); + } + } + + void assertIsActive() const + { + if (m_stackSize == 0) + { + throw_or_assert("Unable to continue registration"); + } + } + + lua_State* const L = nullptr; + int m_stackSize = 0; + int m_skipStackPops = 0; +}; + +} // namespace detail + +//================================================================================================= +/** + * @brief Provides C++ to Lua registration capabilities. + * + * This class is not instantiated directly, call `getGlobalNamespace` to start the registration process. + */ +class Namespace : public detail::Registrar +{ + //============================================================================================= +#if 0 + /** + * @brief Error reporting. + * + * This function looks handy, why aren't we using it? + */ + static int luaError(lua_State* L, std::string message) + { + LUABRIDGE_ASSERT(lua_isstring(L, lua_upvalueindex(1))); + std::string s; + + // Get information on the caller's caller to format the message, + // so the error appears to originate from the Lua source. + lua_Debug ar; + + int result = lua_getstack(L, 2, &ar); + if (result != 0) + { + lua_getinfo(L, "Sl", &ar); + s = ar.short_src; + if (ar.currentline != -1) + { + // poor mans int to string to avoid . + lua_pushnumber(L, ar.currentline); + s = s + ":" + lua_tostring(L, -1) + ": "; + lua_pop(L, 1); + } + } + + s = s + message; + + luaL_error(L, "%s", s.c_str()); + } +#endif + + //============================================================================================= + /** + * @brief Factored base to reduce template instantiations. + */ + class ClassBase : public detail::Registrar + { + public: + explicit ClassBase(const char* name, Namespace parent) + : Registrar(std::move(parent)) + , className(name == nullptr ? "" : name) + { + } + + using Registrar::operator=; + + protected: + static void appendParentList(lua_State* L, int parentsIndex, int visitedIndex, int baseMetatableIndex) + { + parentsIndex = lua_absindex(L, parentsIndex); + visitedIndex = lua_absindex(L, visitedIndex); + baseMetatableIndex = lua_absindex(L, baseMetatableIndex); + + LUABRIDGE_ASSERT(lua_istable(L, parentsIndex)); + LUABRIDGE_ASSERT(lua_istable(L, visitedIndex)); + LUABRIDGE_ASSERT(lua_istable(L, baseMetatableIndex)); + + const auto appendUnique = [=](int metatableIndex) + { + metatableIndex = lua_absindex(L, metatableIndex); + + if (! lua_istable(L, metatableIndex)) + return; + + auto* metatablePtr = const_cast(lua_topointer(L, metatableIndex)); + LUABRIDGE_ASSERT(metatablePtr != nullptr); + + lua_pushlightuserdata(L, metatablePtr); + lua_rawget(L, visitedIndex); + const bool alreadyVisited = ! lua_isnil(L, -1); + lua_pop(L, 1); + + if (alreadyVisited) + return; + + lua_pushlightuserdata(L, metatablePtr); + lua_pushboolean(L, 1); + lua_rawset(L, visitedIndex); + + lua_pushvalue(L, metatableIndex); + lua_rawseti(L, parentsIndex, static_cast(static_cast(get_length(L, parentsIndex)) + 1)); + }; + + appendUnique(baseMetatableIndex); + + lua_rawgetp_x(L, baseMetatableIndex, detail::getParentKey()); // Stack: ..., parent list | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 1); + return; + } + + const int parentListIndex = lua_absindex(L, -1); + const int count = get_length(L, parentListIndex); + + for (int i = 1; i <= count; ++i) + { + lua_rawgeti(L, parentListIndex, i); + appendUnique(-1); + lua_pop(L, 1); + } + + lua_pop(L, 1); + } + + void setObjectMetaMethods(int tableIndex, bool simple) + { + tableIndex = lua_absindex(L, tableIndex); + + if (simple) + { + lua_rawgetp_x(L, tableIndex, detail::getPropgetKey()); // Stack: ..., pg | nil + lua_pushvalue(L, tableIndex); // Stack: ..., pg | nil, mt + lua_pushcclosure_x(L, &detail::index_metamethod_simple, "__index", 2); + rawsetfield(L, tableIndex, "__index"); + + lua_rawgetp_x(L, tableIndex, detail::getPropsetKey()); // Stack: ..., ps | nil + lua_pushcclosure_x(L, &detail::newindex_metamethod_simple, "__newindex", 1); + rawsetfield(L, tableIndex, "__newindex"); + } + else + { + lua_pushcfunction_x(L, &detail::index_metamethod, "__index"); + rawsetfield(L, tableIndex, "__index"); + + lua_pushcfunction_x(L, &detail::newindex_metamethod, "__newindex"); + rawsetfield(L, tableIndex, "__newindex"); + } + } + + void setStaticMetaMethods(int tableIndex, bool simple) + { + tableIndex = lua_absindex(L, tableIndex); + + if (simple) + { + lua_rawgetp_x(L, tableIndex, detail::getPropgetKey()); // Stack: ..., pg | nil + lua_rawgetp_x(L, tableIndex, detail::getClassKey()); // Stack: ..., pg | nil, cl | nil + lua_pushvalue(L, tableIndex); // Stack: ..., pg | nil, cl | nil, mt + lua_pushcclosure_x(L, &detail::index_metamethod_simple, "__index", 3); + rawsetfield(L, tableIndex, "__index"); + + lua_rawgetp_x(L, tableIndex, detail::getPropsetKey()); // Stack: ..., ps | nil + lua_pushcclosure_x(L, &detail::newindex_metamethod_simple, "__newindex", 1); + rawsetfield(L, tableIndex, "__newindex"); + } + else + { + lua_pushcfunction_x(L, &detail::index_metamethod, "__index"); + rawsetfield(L, tableIndex, "__index"); + + lua_pushcfunction_x(L, &detail::newindex_metamethod, "__newindex"); + rawsetfield(L, tableIndex, "__newindex"); + } + } + + //========================================================================================= + /** + * @brief Create the const table. + */ + void createConstTable(const char* name, bool trueConst, Options options) + { + LUABRIDGE_ASSERT(name != nullptr); + + std::string type_name = std::string(trueConst ? "const " : "") + name; + + // Stack: namespace table (ns) + + lua_newtable(L); // Stack: ns, const table (co) + lua_pushvalue(L, -1); // Stack: ns, co, co + lua_setmetatable(L, -2); // co.__metatable = co. Stack: ns, co + + pushunsigned(L, options.toUnderlying()); // Stack: ns, co, options + lua_rawsetp_x(L, -2, detail::getClassOptionsKey()); // co [classOptionsKey] = options. Stack: ns, co + + lua_pushstring(L, type_name.c_str()); // Stack: ns, co, name + lua_rawsetp_x(L, -2, detail::getTypeKey()); // co [typeKey] = name. Stack: ns, co + + lua_newtable(L); // Stack: ns, co, propget table (pg) + lua_rawsetp_x(L, -2, detail::getPropgetKey()); // Stack: ns, co + + setObjectMetaMethods(-1, ! options.test(extensibleClass)); // Stack: ns, co + + if (! options.test(visibleMetatables)) + { + lua_pushboolean(L, 0); + rawsetfield(L, -2, "__metatable"); + } + } + + //========================================================================================= + /** + * @brief Create the class table. + * + * The Lua stack should have the const table on top. + */ + void createClassTable(const char* name, Options options) + { + LUABRIDGE_ASSERT(name != nullptr); + + // Stack: namespace table (ns), const table (co) + + // Class table is the same as const table except the propset table + createConstTable(name, false, options); // Stack: ns, co, cl + + lua_newtable(L); // Stack: ns, co, cl, propset table (ps) + lua_rawsetp_x(L, -2, detail::getPropsetKey()); // cl [propsetKey] = ps. Stack: ns, co, cl + + lua_pushvalue(L, -2); // Stack: ns, co, cl, co + lua_rawsetp_x(L, -2, detail::getConstKey()); // cl [constKey] = co. Stack: ns, co, cl + + lua_pushvalue(L, -1); // Stack: ns, co, cl, cl + lua_rawsetp_x(L, -3, detail::getClassKey()); // co [classKey] = cl. Stack: ns, co, cl + + if (! options.test(extensibleClass)) + setObjectMetaMethods(-1, true); + } + + //========================================================================================= + /** + * @brief Create the static table. + */ + void createStaticTable(const char* name, Options options) + { + LUABRIDGE_ASSERT(name != nullptr); + + // Stack: namespace table (ns), const table (co), class table (cl) + + lua_newtable(L); // Stack: ns, co, cl, static table (st) + lua_newtable(L); // Stack: ns, co, cl, st, static metatable (mt) + lua_pushvalue(L, -1); // Stack: ns, co, cl, st, mt, mt + lua_setmetatable(L, -3); // st.__metatable = mt. Stack: ns, co, cl, st, mt + lua_insert(L, -2); // Stack: ns, co, cl, st, mt, st + rawsetfield(L, -5, name); // ns [name] = st. Stack: ns, co, cl, st, mt + + pushunsigned(L, options.toUnderlying()); // Stack: ns, co, cl, st, mt, options + lua_rawsetp_x(L, -2, detail::getClassOptionsKey()); // st [classOptionsKey] = options. Stack: ns, co, cl, st, mt + + lua_newtable(L); // Stack: ns, co, cl, st, proget table (pg) + lua_rawsetp_x(L, -2, detail::getPropgetKey()); // st [propgetKey] = pg. Stack: ns, co, cl, st + + lua_newtable(L); // Stack: ns, co, cl, st, propset table (ps) + lua_rawsetp_x(L, -2, detail::getPropsetKey()); // st [propsetKey] = pg. Stack: ns, co, cl, st + + lua_pushvalue(L, -2); // Stack: ns, co, cl, st, cl + lua_rawsetp_x(L, -2, detail::getClassKey()); // st [classKey] = cl. Stack: ns, co, cl, st + + setStaticMetaMethods(-1, ! options.test(extensibleClass)); + + if (! options.test(visibleMetatables)) + { + lua_pushboolean(L, 0); + rawsetfield(L, -2, "__metatable"); + } + } + + //========================================================================================= + /** + * @brief Asserts on stack state. + */ + void assertStackState() const + { + // Stack: const table (co), class table (cl), static table (st) + LUABRIDGE_ASSERT(lua_istable(L, -3)); + LUABRIDGE_ASSERT(lua_istable(L, -2)); + LUABRIDGE_ASSERT(lua_istable(L, -1)); + } + + //========================================================================================= + const char* className = ""; + }; + + //============================================================================================= + /** + * @brief Provides a class registration in a lua_State. + * + * After construction the Lua stack holds these objects: + * -1 static table + * -2 class table + * -3 const table + * -4 enclosing namespace table + */ + template + class Class : public ClassBase + { + public: + //========================================================================================= + + /** + * @brief Register a new class or add to an existing class registration. + * + * @param name The new class name. + * @param parent A parent namespace object. + * @param options Class options. + */ + Class(const char* name, Namespace parent, Options options) + : ClassBase(name, std::move(parent)) + { + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns) + + rawgetfield(L, -1, name); // Stack: ns, static table (st) | nil + + if (lua_isnil(L, -1)) // Stack: ns, nil + { + lua_pop(L, 1); // Stack: ns + + createConstTable(name, true, options); // Stack: ns, const table (co) + ++m_stackSize; +#if !defined(LUABRIDGE_ON_LUAU) + lua_pushcfunction_x(L, &detail::gc_metamethod, "__gc"); // Stack: ns, co, function + rawsetfield(L, -2, "__gc"); // co ["__gc"] = function. Stack: ns, co +#endif + lua_pushcfunction_x(L, &detail::tostring_metamethod, "__tostring"); + rawsetfield(L, -2, "__tostring"); + + createClassTable(name, options); // Stack: ns, co, class table (cl) + ++m_stackSize; + + lua_pushlightuserdata(L, const_cast(detail::getConstRegistryKey())); // Stack: ns, co, cl, id + lua_rawsetp_x(L, -3, detail::getTypeIdentityKey()); // co[typeIdentityKey] = const id. Stack: ns, co, cl + lua_pushlightuserdata(L, const_cast(detail::getClassRegistryKey())); // Stack: ns, co, cl, id + lua_rawsetp_x(L, -2, detail::getTypeIdentityKey()); // cl[typeIdentityKey] = class id. Stack: ns, co, cl + +#if !defined(LUABRIDGE_ON_LUAU) + lua_pushcfunction_x(L, &detail::gc_metamethod, "__gc"); // Stack: ns, co, cl, function + rawsetfield(L, -2, "__gc"); // cl ["__gc"] = function. Stack: ns, co, cl +#endif + + lua_pushcfunction_x(L, &detail::tostring_metamethod, "__tostring"); + rawsetfield(L, -2, "__tostring"); + + createStaticTable(name, options); // Stack: ns, co, cl, st + ++m_stackSize; + + lua_pushvalue(L, -1); // Stack: ns, co, cl, st, st + lua_rawsetp_x(L, -2, detail::getStaticKey()); // cl [staticKey] = st. Stack: ns, co, cl, st + lua_pushvalue(L, -1); // Stack: ns, co, cl, st, st + lua_rawsetp_x(L, -3, detail::getStaticKey()); // co [staticKey] = st. Stack: ns, co, cl, st + + // Map T back to its tables. + lua_pushvalue(L, -1); // Stack: ns, co, cl, st, st + lua_rawsetp_x(L, LUA_REGISTRYINDEX, detail::getStaticRegistryKey()); // Stack: ns, co, cl, st + lua_pushvalue(L, -2); // Stack: ns, co, cl, st, cl + lua_rawsetp_x(L, LUA_REGISTRYINDEX, detail::getClassRegistryKey()); // Stack: ns, co, cl, st + lua_pushvalue(L, -3); // Stack: ns, co, cl, st, co + lua_rawsetp_x(L, LUA_REGISTRYINDEX, detail::getConstRegistryKey()); // Stack: ns, co, cl, st + } + else + { + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: ns, vst + ++m_stackSize; + + lua_getmetatable(L, -1); // Stack: ns, vst, st + lua_insert(L, -2); // Stack: ns, st, vst + lua_pop(L, 1); // Stack: ns, st + + // Map T back from its stored tables + lua_rawgetp_x(L, LUA_REGISTRYINDEX, detail::getConstRegistryKey()); // Stack: ns, st, co + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Class was previously registered as table or namespace ? + lua_insert(L, -2); // Stack: ns, co, st + ++m_stackSize; + + lua_rawgetp_x(L, LUA_REGISTRYINDEX, detail::getClassRegistryKey()); // Stack: ns, co, st, cl + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Class was previously registered as table or namespace ? + lua_insert(L, -2); // Stack: ns, co, cl, st + ++m_stackSize; + } + } + + //========================================================================================= + /** + * @brief Derive a new class. + * + * @param name The class name. + * @param parent A parent namespace object. + * @param staticKey Key where the class is stored. + */ + Class(const char* name, Namespace parent, std::initializer_list bases, Options options) + : ClassBase(name, std::move(parent)) + { + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns) + + createConstTable(name, true, options); // Stack: ns, const table (co) + ++m_stackSize; +#if !defined(LUABRIDGE_ON_LUAU) + lua_pushcfunction_x(L, &detail::gc_metamethod, "__gc"); // Stack: ns, co, function + rawsetfield(L, -2, "__gc"); // co ["__gc"] = function. Stack: ns, co +#endif + lua_pushcfunction_x(L, &detail::tostring_metamethod, "__tostring"); + rawsetfield(L, -2, "__tostring"); + + createClassTable(name, options); // Stack: ns, co, class table (cl) + ++m_stackSize; + + lua_pushlightuserdata(L, const_cast(detail::getConstRegistryKey())); // Stack: ns, co, cl, id + lua_rawsetp_x(L, -3, detail::getTypeIdentityKey()); // co[typeIdentityKey] = const id. Stack: ns, co, cl + lua_pushlightuserdata(L, const_cast(detail::getClassRegistryKey())); // Stack: ns, co, cl, id + lua_rawsetp_x(L, -2, detail::getTypeIdentityKey()); // cl[typeIdentityKey] = class id. Stack: ns, co, cl + +#if !defined(LUABRIDGE_ON_LUAU) + lua_pushcfunction_x(L, &detail::gc_metamethod, "__gc"); // Stack: ns, co, cl, function + rawsetfield(L, -2, "__gc"); // cl ["__gc"] = function. Stack: ns, co, cl +#endif + lua_pushcfunction_x(L, &detail::tostring_metamethod, "__tostring"); + rawsetfield(L, -2, "__tostring"); + + createStaticTable(name, options); // Stack: ns, co, cl, st + ++m_stackSize; + + lua_pushvalue(L, -1); // Stack: ns, co, cl, st, st + lua_rawsetp_x(L, -2, detail::getStaticKey()); // cl [staticKey] = st. Stack: ns, co, cl, st + lua_pushvalue(L, -1); // Stack: ns, co, cl, st, st + lua_rawsetp_x(L, -3, detail::getStaticKey()); // co [staticKey] = st. Stack: ns, co, cl, st + + const int coIndex = lua_absindex(L, -3); + const int clIndex = lua_absindex(L, -2); + const int stIndex = lua_absindex(L, -1); + + lua_newtable(L); // Stack: ns, co, cl, st, cl parents + const int clParentsIndex = lua_absindex(L, -1); + lua_newtable(L); // Stack: ns, co, cl, st, cl parents, cast table + const int castTableIndex = lua_absindex(L, -1); + lua_newtable(L); // Stack: ns, co, cl, st, cl parents, cast table, visited + const int visitedIndex = lua_absindex(L, -1); + + for (const detail::BaseClassInfo& base : bases) + { + lua_rawgetp_x(L, LUA_REGISTRYINDEX, base.staticKey); // Stack: ..., visited, base st | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 4); // pop (nil), visited, cast table, cl parents. Stack: ns, co, cl, st + + throw_or_assert("Base class is not registered"); +#if !LUABRIDGE_HAS_EXCEPTIONS + return; +#endif + } + + lua_rawgetp_x(L, -1, detail::getClassKey()); // Stack: ..., visited, base st, base cl | nil + if (! lua_istable(L, -1)) + { + lua_pop(L, 5); // pop (nil), base st, visited, cast table, cl parents. Stack: ns, co, cl, st + + throw_or_assert("Base class is not registered"); +#if !LUABRIDGE_HAS_EXCEPTIONS + return; +#endif + } + + appendParentList(L, clParentsIndex, visitedIndex, -1); + + // Store the direct pointer adjustment offset for this base class + lua_pushlightuserdata(L, const_cast(base.classKey)); + lua_pushinteger(L, base.castOffset); + lua_rawset(L, castTableIndex); + + // Compose and propagate ancestor offsets from the base's own cast table. + // offset(T → ancestor) = offset(T → base) + offset(base → ancestor) + lua_rawgetp_x(L, -1, detail::getCastTableKey()); // Stack: ..., base st, base cl, base cast table | nil + if (lua_istable(L, -1)) + { + lua_pushnil(L); + while (lua_next(L, -2) != 0) + { + // Stack: ..., base cast table, ancestor key, ancestor offset + const lua_Integer ancestorOffset = lua_tointeger(L, -1); + + lua_pushvalue(L, -2); // duplicate ancestor key to check presence + lua_rawget(L, castTableIndex); + const bool alreadyPresent = ! lua_isnil(L, -1); + lua_pop(L, 1); + + if (! alreadyPresent) + { + lua_pushvalue(L, -2); // push ancestor key + lua_pushinteger(L, base.castOffset + ancestorOffset); + lua_rawset(L, castTableIndex); + } + + lua_pop(L, 1); // pop ancestor offset; ancestor key stays for next() + } + lua_pop(L, 1); // pop base cast table + } + else + { + lua_pop(L, 1); // pop nil + } + + lua_pop(L, 2); // pop base cl and base st. Stack: ..., cast table, visited + } + + lua_pop(L, 1); // pop visited. Stack: ns, co, cl, st, cl parents, cast table + + // Store the cast table in both class and const metatables + lua_pushvalue(L, castTableIndex); + lua_rawsetp_x(L, clIndex, detail::getCastTableKey()); // cl[castTableKey] = cast table + lua_pushvalue(L, castTableIndex); + lua_rawsetp_x(L, coIndex, detail::getCastTableKey()); // co[castTableKey] = cast table + lua_pop(L, 1); // pop cast table. Stack: ns, co, cl, st, cl parents + + lua_createtable(L, get_length(L, clParentsIndex), 0); // Stack: ns, co, cl, st, cl parents, co parents + const int coParentsIndex = lua_absindex(L, -1); + lua_createtable(L, get_length(L, clParentsIndex), 0); // Stack: ns, co, cl, st, cl parents, co parents, st parents + const int stParentsIndex = lua_absindex(L, -1); + + const int parentCount = get_length(L, clParentsIndex); + for (int i = 1; i <= parentCount; ++i) + { + lua_rawgeti(L, clParentsIndex, i); // Stack: ..., st parents, parent cl + LUABRIDGE_ASSERT(lua_istable(L, -1)); + + lua_rawgetp_x(L, -1, detail::getConstKey()); // Stack: ..., parent cl, parent co + LUABRIDGE_ASSERT(lua_istable(L, -1)); + lua_rawseti(L, coParentsIndex, i); // Stack: ..., parent cl + + lua_rawgetp_x(L, -1, detail::getStaticKey()); // Stack: ..., parent cl, parent st + LUABRIDGE_ASSERT(lua_istable(L, -1)); + lua_rawseti(L, stParentsIndex, i); // Stack: ..., parent cl + + lua_pop(L, 1); // Stack: ..., st parents + } + + lua_pushvalue(L, coParentsIndex); + lua_rawsetp_x(L, coIndex, detail::getParentKey()); + + lua_pushvalue(L, clParentsIndex); + lua_rawsetp_x(L, clIndex, detail::getParentKey()); + + lua_pushvalue(L, stParentsIndex); + lua_rawsetp_x(L, stIndex, detail::getParentKey()); + + lua_pop(L, 3); // Stack: ns, co, cl, st + + setObjectMetaMethods(-3, false); // co + setObjectMetaMethods(-2, false); // cl + setStaticMetaMethods(-1, false); // st + + lua_pushvalue(L, -1); // Stack: ns, co, cl, st, st + lua_rawsetp_x(L, LUA_REGISTRYINDEX, detail::getStaticRegistryKey()); // Stack: ns, co, cl, st + lua_pushvalue(L, -2); // Stack: ns, co, cl, st, cl + lua_rawsetp_x(L, LUA_REGISTRYINDEX, detail::getClassRegistryKey()); // Stack: ns, co, cl, st + lua_pushvalue(L, -3); // Stack: ns, co, cl, st, co + lua_rawsetp_x(L, LUA_REGISTRYINDEX, detail::getConstRegistryKey()); // Stack: ns, co, cl, st + } + + //========================================================================================= + /** + * @brief Continue registration in the enclosing namespace. + * + * @returns A parent registration object. + */ + Namespace endClass() + { + LUABRIDGE_ASSERT(m_stackSize > 3); + + m_stackSize -= 3; + lua_pop(L, 3); + + return Namespace(std::move(*this)); + } + + //========================================================================================= + /** + * @brief Add or replace a static property. + */ + template + Class& addStaticProperty(const char* name, Getter get, bool) = delete; + + template + Class& addStaticProperty(const char* name, Getter get) + { + LUABRIDGE_ASSERT(name != nullptr); + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + detail::push_property_getter(L, std::move(get), name); // Stack: co, cl, st, function + detail::add_property_getter(L, name, -2); // Stack: co, cl, st + + detail::push_property_readonly(L, name); // Stack: co, cl, st, function + detail::add_property_setter(L, name, -2); // Stack: co, cl, st + + return *this; + } + + template + Class& addStaticProperty(const char* name, Getter get, Setter set) + { + LUABRIDGE_ASSERT(name != nullptr); + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + detail::push_property_getter(L, std::move(get), name); // Stack: co, cl, st, function + detail::add_property_getter(L, name, -2); // Stack: co, cl, st + + detail::push_property_setter(L, std::move(set), name); // Stack: co, cl, st, function + detail::add_property_setter(L, name, -2); // Stack: co, cl, st + + return *this; + } + + template + Class& addStaticPropertyReadWrite(const char* name, Field member) + { + return addStaticProperty(name, member, member); + } + + //========================================================================================= + /** + * @brief Add or replace a single static function or multiple overloaded functions. + * + * @param name The overload name. + * @param functions A single or set of static functions that will be invoked. + * + * @returns This class registration object. + */ + template + auto addStaticFunction(const char* name, Functions... functions) + -> std::enable_if_t<(detail::is_callable_v && ...) && (sizeof...(Functions) > 0), Class&> + { + LUABRIDGE_ASSERT(name != nullptr); + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + if constexpr (sizeof...(Functions) == 1) + { + ([&] + { + detail::push_function(L, std::move(functions), name); + + } (), ...); + } + else + { + // upvalue 1: OverloadSet (C++ struct with arity + type checker per overload) + auto* overload_set_unaligned = lua_newuserdata_aligned(L); + auto* overload_set = align(overload_set_unaligned); + + ([&] + { + detail::OverloadEntry entry; + if constexpr (detail::is_any_cfunction_pointer_v) + { + entry.arity = -1; + entry.checker = nullptr; + } + else + { + using ArgsPack = detail::function_arguments_t; + entry.arity = static_cast(detail::function_arity_excluding_v); + entry.checker = &detail::overload_type_checker; + } + overload_set->entries.push_back(entry); + + } (), ...); + + // upvalue 2: flat table of function closures indexed 1..N + lua_createtable(L, static_cast(sizeof...(Functions)), 0); + + int idx = 1; + + ([&] + { + detail::push_function(L, std::move(functions), name); + lua_rawseti(L, -2, idx++); + + } (), ...); + + lua_pushcclosure_x(L, &detail::try_overload_functions, name, 2); + } + + rawsetfield(L, -2, name); + + return *this; + } + + //========================================================================================= + /** + * @brief Add a static index metamethod function fallback that is triggered when no result is found in static functions, properties or any other static members. + * + * Let the user define a fallback index (__index) metamethod for the static class table. + */ + template + auto addStaticIndexMetaMethod(Function function) + -> std::enable_if_t + && std::is_invocable_v, Class&> + { + using FnType = decltype(function); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + lua_newuserdata_aligned(L, std::move(function)); // Stack: co, cl, st, function userdata (ud) + lua_pushcclosure_x(L, &detail::invoke_proxy_functor, "__index", 1); // Stack: co, cl, st, function + lua_rawsetp_x(L, -2, detail::getStaticIndexFallbackKey()); + setStaticMetaMethods(-1, false); + + return *this; + } + + Class& addStaticIndexMetaMethod(LuaRef (*idxf)(const LuaRef&, lua_State*)) + { + using FnType = decltype(idxf); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + lua_pushlightuserdata(L, reinterpret_cast(idxf)); // Stack: co, cl, st, function ptr + lua_pushcclosure_x(L, &detail::invoke_proxy_function, "__index", 1); // Stack: co, cl, st, function + lua_rawsetp_x(L, -2, detail::getStaticIndexFallbackKey()); + setStaticMetaMethods(-1, false); + + return *this; + } + + //========================================================================================= + /** + * @brief Add a static new index metamethod function fallback that is triggered when no result is found in static functions, properties or any other static members. + * + * Let the user define a fallback new index (__newindex) metamethod for the static class table. + */ + template + auto addStaticNewIndexMetaMethod(Function function) + -> std::enable_if_t + && std::is_invocable_v, Class&> + { + using FnType = decltype(function); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + lua_newuserdata_aligned(L, std::move(function)); // Stack: co, cl, st, function userdata (ud) + lua_pushcclosure_x(L, &detail::invoke_proxy_functor, "__newindex", 1); // Stack: co, cl, st, function + lua_rawsetp_x(L, -2, detail::getStaticNewIndexFallbackKey()); + setStaticMetaMethods(-1, false); + + return *this; + } + + Class& addStaticNewIndexMetaMethod(LuaRef (*idxf)(const LuaRef&, const LuaRef&, lua_State*)) + { + using FnType = decltype(idxf); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + lua_pushlightuserdata(L, reinterpret_cast(idxf)); // Stack: co, cl, st, function ptr + lua_pushcclosure_x(L, &detail::invoke_proxy_function, "__newindex", 1); // Stack: co, cl, st, function + lua_rawsetp_x(L, -2, detail::getStaticNewIndexFallbackKey()); + setStaticMetaMethods(-1, false); + + return *this; + } + + //========================================================================================= + /** + * @brief Add or replace a property member, by constructible by std::function. + */ + template + Class& addProperty(const char* name, Getter getter, bool) = delete; + + template + Class& addProperty(const char* name, Getter getter) + { + LUABRIDGE_ASSERT(name != nullptr); + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + detail::push_class_property_getter(L, std::move(getter), name); // Stack: co, cl, st, getter + lua_pushvalue(L, -1); // Stack: co, cl, st, getter, getter + detail::add_property_getter(L, name, -4); // Stack: co, cl, st, getter + detail::add_property_getter(L, name, -4); // Stack: co, cl, st + + detail::push_property_readonly(L, name); // Stack: co, cl, st, function + detail::add_property_setter(L, name, -3); // Stack: co, cl, st + + return *this; + } + + template + Class& addProperty(const char* name, Getter getter, Setter setter) + { + LUABRIDGE_ASSERT(name != nullptr); + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + detail::push_class_property_getter(L, std::move(getter), name); // Stack: co, cl, st, getter + lua_pushvalue(L, -1); // Stack: co, cl, st, getter, getter + detail::add_property_getter(L, name, -4); // Stack: co, cl, st, getter + detail::add_property_getter(L, name, -4); // Stack: co, cl, st + + detail::push_class_property_setter(L, std::move(setter), name); // Stack: co, cl, st, setter + detail::add_property_setter(L, name, -3); // Stack: co, cl, st + + return *this; + } + + template + Class& addPropertyReadWrite(const char* name, Field T::*member) + { + return addProperty(name, member, member); + } + + //========================================================================================= + /** + * @brief Add or replace a function that can operate on the class. + * + * @param name The function or overloaded functions name. + * @param functions A single or set of functions that will be invoked. + * + * @returns This class registration object. + */ + template + auto addFunction(const char* name, Functions... functions) + -> std::enable_if_t<(detail::is_callable_v && ...) && (sizeof...(Functions) > 0), Class&> + { + LUABRIDGE_ASSERT(name != nullptr); + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + if (name == std::string_view("__gc")) + { + throw_or_assert("__gc metamethod registration is forbidden"); +#if !LUABRIDGE_HAS_EXCEPTIONS + return *this; +#endif + } + + if constexpr ((detail::is_reversed_proxy_function_v || ...)) + { + if (!detail::is_binary_operator_metamethod(name)) + { + throw_or_assert("reversed functions are only allowed on binary operator metamethods"); + return *this; + } + } + + if constexpr (sizeof...(Functions) == 1) + { + ([&] + { + detail::push_member_function(L, std::move(functions), name); + + } (), ...); + + if constexpr (detail::const_functions_count == 1) + { + lua_pushvalue(L, -1); // Stack: co, cl, st, function, function + rawsetfield(L, -4, name); // Stack: co, cl, st, function + rawsetfield(L, -4, name); // Stack: co, cl, st + } + else + { + rawsetfield(L, -3, name); // Stack: co, cl, st + } + } + else + { + // create new closure of const try_overload_functions with new table + if constexpr (detail::const_functions_count > 0) + { + // upvalue 1: OverloadSet + auto* overload_set_const_unaligned = lua_newuserdata_aligned(L); + auto* overload_set_const = align(overload_set_const_unaligned); + + ([&] + { + if (!detail::is_const_function) + return; + + detail::OverloadEntry entry; + if constexpr (detail::is_any_cfunction_pointer_v) + { + entry.arity = -1; + entry.checker = nullptr; + } + else if constexpr (detail::is_proxy_member_function_v) + { + using ArgsPack = detail::remove_first_type_t>; + entry.arity = static_cast(detail::member_function_arity_excluding_v); + entry.checker = &detail::overload_type_checker; + } + else if constexpr (detail::is_reversed_proxy_function_v) + { + using ArgsPack = detail::function_arguments_t; + entry.arity = static_cast(detail::member_function_arity_excluding_v) - 1; + entry.checker = &detail::reversed_overload_type_checker; + } + else + { + using ArgsPack = detail::function_arguments_t; + entry.arity = static_cast(detail::member_function_arity_excluding_v); + entry.checker = &detail::overload_type_checker; + } + overload_set_const->entries.push_back(entry); + + } (), ...); + + LUABRIDGE_ASSERT(!overload_set_const->entries.empty()); + + // upvalue 2: flat table of function closures + lua_createtable(L, static_cast(detail::const_functions_count), 0); + + int idx = 1; + + ([&] + { + if (!detail::is_const_function) + return; + + detail::push_member_function(L, std::move(functions), name); + lua_rawseti(L, -2, idx++); + + } (), ...); + + lua_pushcclosure_x(L, &detail::try_overload_functions, name, 2); + lua_pushvalue(L, -1); // Stack: co, cl, st, function, function + rawsetfield(L, -4, name); // Stack: co, cl, st, function + rawsetfield(L, -4, name); // Stack: co, cl, st + } + + // create new closure of non const try_overload_functions with new table + if constexpr (detail::non_const_functions_count > 0) + { + // upvalue 1: OverloadSet + auto* overload_set_nonconst_unaligned = lua_newuserdata_aligned(L); + auto* overload_set_nonconst = align(overload_set_nonconst_unaligned); + + ([&] + { + if (detail::is_const_function) + return; + + detail::OverloadEntry entry; + if constexpr (detail::is_any_cfunction_pointer_v) + { + entry.arity = -1; + entry.checker = nullptr; + } + else if constexpr (detail::is_proxy_member_function_v) + { + using ArgsPack = detail::remove_first_type_t>; + entry.arity = static_cast(detail::member_function_arity_excluding_v); + entry.checker = &detail::overload_type_checker; + } + else if constexpr (detail::is_reversed_proxy_function_v) + { + using ArgsPack = detail::function_arguments_t; + entry.arity = static_cast(detail::member_function_arity_excluding_v) - 1; + entry.checker = &detail::reversed_overload_type_checker; + } + else + { + using ArgsPack = detail::function_arguments_t; + entry.arity = static_cast(detail::member_function_arity_excluding_v); + entry.checker = &detail::overload_type_checker; + } + overload_set_nonconst->entries.push_back(entry); + + } (), ...); + + LUABRIDGE_ASSERT(!overload_set_nonconst->entries.empty()); + + // upvalue 2: flat table of function closures + lua_createtable(L, static_cast(detail::non_const_functions_count), 0); + + int idx = 1; + + ([&] + { + if (detail::is_const_function) + return; + + detail::push_member_function(L, std::move(functions), name); + lua_rawseti(L, -2, idx++); + + } (), ...); + + lua_pushcclosure_x(L, &detail::try_overload_functions, name, 2); + rawsetfield(L, -3, name); // Stack: co, cl, st + } + } + + return *this; + } + +#if LUABRIDGE_HAS_CXX20_COROUTINES + //========================================================================================= + /** + * @brief Add a C++20 coroutine as a static function to this class. + * + * The factory must be a callable returning CppCoroutine. When Lua calls the registered + * function, a new C++ coroutine is created and run; co_yield sends values to the Lua caller + * and co_return sends the final return value. + * + * @param name The function name to register. + * @param factory A callable returning CppCoroutine. + * + * @returns This class registration object. + */ + template + auto addStaticCoroutine(const char* name, F factory) + -> std::enable_if_t, Class&> + { + LUABRIDGE_ASSERT(name != nullptr); + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + detail::push_coroutine_function(L, std::move(factory), name); + rawsetfield(L, -2, name); // Stack: co, cl, st (into st) + + return *this; + } + + //========================================================================================= + /** + * @brief Add a C++20 coroutine as a member function to this class. + * + * The factory must be a callable whose first argument is T* or const T*, followed by any + * additional arguments, and returning CppCoroutine. When Lua calls the method on an + * object, a new C++ coroutine is created with the object as the first argument; co_yield + * sends values to the Lua caller and co_return sends the final return value. + * + * If the factory takes const T* as the first argument it is registered as a const method + * (accessible on both const and non-const objects); otherwise it is registered as a + * non-const method (accessible on non-const objects only). + * + * @param name The method name to register. + * @param factory A callable taking T* or const T* as the first argument (the object + * pointer), plus optional further arguments, returning CppCoroutine. + * + * @returns This class registration object. + */ + template + auto addCoroutine(const char* name, F factory) + -> std::enable_if_t< + detail::is_cpp_coroutine_factory_v && detail::is_proxy_member_function_v, + Class&> + { + LUABRIDGE_ASSERT(name != nullptr); + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + detail::push_coroutine_function(L, std::move(factory), name); + + if constexpr (detail::is_const_function) + { + lua_pushvalue(L, -1); // Stack: co, cl, st, func, func + rawsetfield(L, -4, name); // Stack: co, cl, st, func (sets in cl) + rawsetfield(L, -4, name); // Stack: co, cl, st (sets in co) + } + else + { + rawsetfield(L, -3, name); // Stack: co, cl, st (sets in cl) + } + + return *this; + } +#endif // LUABRIDGE_HAS_CXX20_COROUTINES + + //========================================================================================= + /** + * @brief Add or replace a primary Constructor. + * + * The primary Constructor is invoked when calling the class type table like a function. + * + * The template parameter should be a function pointer type that matches the desired Constructor (since you can't take the + * address of a Constructor and pass it as an argument). + */ + template + auto addConstructor() + -> std::enable_if_t<(sizeof...(Functions) > 0), Class&> + { + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + if constexpr (sizeof...(Functions) == 1) + { + ([&] + { + lua_pushcclosure_x(L, &detail::constructor_placement_proxy>, className, 0); + + } (), ...); + } + else + { + // upvalue 1: OverloadSet + auto* overload_set_unaligned = lua_newuserdata_aligned(L); + auto* overload_set = align(overload_set_unaligned); + + ([&] + { + using ArgsPack = detail::function_arguments_t; + detail::OverloadEntry entry; + entry.arity = static_cast(detail::function_arity_excluding_v); + entry.checker = &detail::overload_type_checker; + overload_set->entries.push_back(entry); + + } (), ...); + + // upvalue 2: flat table of function closures + lua_createtable(L, static_cast(sizeof...(Functions)), 0); + + int idx = 1; + + ([&] + { + lua_pushcclosure_x(L, &detail::constructor_placement_proxy>, className, 0); + lua_rawseti(L, -2, idx++); + + } (), ...); + + lua_pushcclosure_x(L, &detail::try_overload_functions, className, 2); + } + + rawsetfield(L, -2, "__call"); + + return *this; + } + + //========================================================================================= + /** + * @brief Add or replace a placement constructor. + * + * The primary placement constructor is invoked when calling the class type table like a function. + * + * The provider of the Function argument is responsible of doing placement new of the type T over the void* pointer provided to + * the method as first argument. + */ + template + auto addConstructor(Functions... functions) + -> std::enable_if_t<(detail::is_callable_v && ...) && (sizeof...(Functions) > 0), Class&> + { + static_assert(((detail::function_arity_excluding_v >= 1) && ...)); + static_assert(((std::is_same_v, void*>) && ...)); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + if constexpr (sizeof...(Functions) == 1) + { + ([&] + { + using F = detail::constructor_forwarder; + + lua_newuserdata_aligned(L, F(std::move(functions))); // Stack: co, cl, st, upvalue + lua_pushcclosure_x(L, &detail::invoke_proxy_constructor, className, 1); // Stack: co, cl, st, function + + } (), ...); + } + else + { + // upvalue 1: OverloadSet + auto* overload_set_unaligned = lua_newuserdata_aligned(L); + auto* overload_set = align(overload_set_unaligned); + + ([&] + { + detail::OverloadEntry entry; + if constexpr (detail::is_any_cfunction_pointer_v) + { + entry.arity = -1; + entry.checker = nullptr; + } + else + { + // skip void* first arg (placement new destination, not a Lua argument) + using ArgsPack = detail::remove_first_type_t>; + entry.arity = static_cast(detail::function_arity_excluding_v) - 1; + entry.checker = &detail::overload_type_checker; + } + overload_set->entries.push_back(entry); + + } (), ...); + + // upvalue 2: flat table of function closures + lua_createtable(L, static_cast(sizeof...(Functions)), 0); + + int idx = 1; + + ([&] + { + using F = detail::constructor_forwarder; + + lua_newuserdata_aligned(L, F(std::move(functions))); + lua_pushcclosure_x(L, &detail::invoke_proxy_constructor, className, 1); + lua_rawseti(L, -2, idx++); + + } (), ...); + + lua_pushcclosure_x(L, &detail::try_overload_functions, className, 2); + } + + rawsetfield(L, -2, "__call"); // Stack: co, cl, st + + return *this; + } + + //========================================================================================= + /** + * @brief Add or replace a primary Constructor when the type is used from an intrusive container C. + */ + template + auto addConstructorFrom() + -> std::enable_if_t<(sizeof...(Functions) > 0), Class&> + { + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + if constexpr (sizeof...(Functions) == 1) + { + ([&] + { + lua_pushcclosure_x(L, &detail::constructor_container_proxy>, className, 0); + + } (), ...); + } + else + { + // upvalue 1: OverloadSet + auto* overload_set_unaligned = lua_newuserdata_aligned(L); + auto* overload_set = align(overload_set_unaligned); + + ([&] + { + using ArgsPack = detail::function_arguments_t; + detail::OverloadEntry entry; + entry.arity = static_cast(detail::function_arity_excluding_v); + entry.checker = &detail::overload_type_checker; + overload_set->entries.push_back(entry); + + } (), ...); + + // upvalue 2: flat table of function closures + lua_createtable(L, static_cast(sizeof...(Functions)), 0); + + int idx = 1; + + ([&] + { + lua_pushcclosure_x(L, &detail::constructor_container_proxy>, className, 0); + lua_rawseti(L, -2, idx++); + + } (), ...); + + lua_pushcclosure_x(L, &detail::try_overload_functions, className, 2); + } + + rawsetfield(L, -2, "__call"); + + return *this; + } + + //========================================================================================= + /** + * @brief Add or replace a primary Constructor when the type is used from an intrusive container C. + * + * The provider of the Function argument is responsible of constructing the container C forwarding arguments in the callable Functions passed in. + */ + template + auto addConstructorFrom(Functions... functions) + -> std::enable_if_t<(detail::is_callable_v && ...) && (sizeof...(Functions) > 0), Class&> + { + static_assert(((std::is_same_v, C>) && ...)); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + if constexpr (sizeof...(Functions) == 1) + { + ([&] + { + using F = detail::container_forwarder; + + lua_newuserdata_aligned(L, F(std::move(functions))); // Stack: co, cl, st, upvalue + lua_pushcclosure_x(L, &detail::invoke_proxy_constructor, className, 1); // Stack: co, cl, st, function + + } (), ...); + } + else + { + // upvalue 1: OverloadSet + auto* overload_set_unaligned = lua_newuserdata_aligned(L); + auto* overload_set = align(overload_set_unaligned); + + ([&] + { + detail::OverloadEntry entry; + if constexpr (detail::is_any_cfunction_pointer_v) + { + entry.arity = -1; + entry.checker = nullptr; + } + else + { + using ArgsPack = detail::function_arguments_t; + entry.arity = static_cast(detail::function_arity_excluding_v); + entry.checker = &detail::overload_type_checker; + } + overload_set->entries.push_back(entry); + + } (), ...); + + // upvalue 2: flat table of function closures + lua_createtable(L, static_cast(sizeof...(Functions)), 0); + + int idx = 1; + + ([&] + { + using F = detail::container_forwarder; + + lua_newuserdata_aligned(L, F(std::move(functions))); + lua_pushcclosure_x(L, &detail::invoke_proxy_constructor, className, 1); + lua_rawseti(L, -2, idx++); + + } (), ...); + + lua_pushcclosure_x(L, &detail::try_overload_functions, className, 2); + } + + rawsetfield(L, -2, "__call"); // Stack: co, cl, st + + return *this; + } + + //========================================================================================= + template + auto addDestructor(Function function) + -> std::enable_if_t, Class&> + { + static_assert(detail::function_arity_excluding_v == 1); + static_assert(std::is_same_v, T*>); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + using F = detail::destructor_forwarder; + + lua_newuserdata_aligned(L, F(std::move(function))); // Stack: co, cl, st, upvalue + lua_pushcclosure_x(L, &detail::invoke_proxy_destructor, className, 1); // Stack: co, cl, st, function + + rawsetfield(L, -3, "__destruct"); // Stack: co, cl, st + + return *this; + } + + //========================================================================================= + /** + * @brief Add or replace a factory. + * + * The primary Constructor is invoked when calling the class type table like a function. + * + * The template parameter should be a function pointer type that matches the desired Constructor (since you can't take the + * address of a Constructor and pass it as an argument). + */ + template + Class& addFactory(Allocator allocator, Deallocator deallocator) + { + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + using F = detail::factory_forwarder; + + lua_newuserdata_aligned(L, F(std::move(allocator), std::move(deallocator))); // Stack: co, cl, st, upvalue + lua_pushcclosure_x(L, &detail::invoke_proxy_constructor, className, 1); // Stack: co, cl, st, function + rawsetfield(L, -2, "__call"); // Stack: co, cl, st + + return *this; + } + + //========================================================================================= + /** + * @brief Add an index metamethod function fallback that is triggered when no result is found in functions, properties or any other members. + * + * Let the user define a fallback index (__index) metamethod at its level. + */ + template + auto addIndexMetaMethod(Function function) + -> std::enable_if_t + && std::is_invocable_v, Class&> + { + using FnType = decltype(function); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + lua_newuserdata_aligned(L, std::move(function)); // Stack: co, cl, st, function userdata (ud) + lua_pushcclosure_x(L, &detail::invoke_proxy_functor, "__index", 1); // Stack: co, cl, st, function + lua_rawsetp_x(L, -3, detail::getIndexFallbackKey()); + setObjectMetaMethods(-2, false); + + return *this; + } + + Class& addIndexMetaMethod(LuaRef (*idxf)(T&, const LuaRef&, lua_State*)) + { + using FnType = decltype(idxf); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + lua_pushlightuserdata(L, reinterpret_cast(idxf)); // Stack: co, cl, st, function ptr + lua_pushcclosure_x(L, &detail::invoke_proxy_function, "__index", 1); // Stack: co, cl, st, function + lua_rawsetp_x(L, -3, detail::getIndexFallbackKey()); + setObjectMetaMethods(-2, false); + + return *this; + } + + Class& addIndexMetaMethod(LuaRef (T::* idxf)(const LuaRef&, lua_State*)) + { + using MemFnPtr = decltype(idxf); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + new (lua_newuserdata_x(L, sizeof(MemFnPtr))) MemFnPtr(idxf); + lua_pushcclosure_x(L, &detail::invoke_member_function, "__index", 1); + lua_rawsetp_x(L, -3, detail::getIndexFallbackKey()); + setObjectMetaMethods(-2, false); + + return *this; + } + + //========================================================================================= + /** + * @brief Add an insert index metamethod function fallback that is triggered when no result is found in functions, properties or any other members. + * + * Let the user define a fallback insert index (___newindex) metamethod at its level. + */ + template + auto addNewIndexMetaMethod(Function function) + -> std::enable_if_t + && std::is_invocable_v, Class&> + { + using FnType = decltype(function); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + lua_newuserdata_aligned(L, std::move(function)); // Stack: co, cl, st, function userdata (ud) + lua_pushcclosure_x(L, &detail::invoke_proxy_functor, "__newindex", 1); // Stack: co, cl, st, function + lua_rawsetp_x(L, -3, detail::getNewIndexFallbackKey()); + setObjectMetaMethods(-2, false); + + return *this; + } + + Class& addNewIndexMetaMethod(LuaRef (*idxf)(T&, const LuaRef&, const LuaRef&, lua_State*)) + { + using FnType = decltype(idxf); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + lua_pushlightuserdata(L, reinterpret_cast(idxf)); // Stack: co, cl, st, function ptr + lua_pushcclosure_x(L, &detail::invoke_proxy_function, "__newindex", 1); // Stack: co, cl, st, function + lua_rawsetp_x(L, -3, detail::getNewIndexFallbackKey()); + setObjectMetaMethods(-2, false); + + return *this; + } + + Class& addNewIndexMetaMethod(LuaRef (T::* idxf)(const LuaRef&, const LuaRef&, lua_State*)) + { + using MemFnPtr = decltype(idxf); + + assertStackState(); // Stack: const table (co), class table (cl), static table (st) + + new (lua_newuserdata_x(L, sizeof(MemFnPtr))) MemFnPtr(idxf); + lua_pushcclosure_x(L, &detail::invoke_member_function, "__newindex", 1); + lua_rawsetp_x(L, -3, detail::getNewIndexFallbackKey()); + setObjectMetaMethods(-2, false); + + return *this; + } + + //========================================================================================= + /** + * @brief Register a custom type converter from this class (T) to a target type (To). + * + * Stores a function pointer in the FROM class's (T's) Lua metatable under + * getConvertersKey() → getClassRegistryKey(), for both the class table and + * the const table. Phase 3 in Stack::get reads it back during extraction. + * + * Requirements: + * - StackConversion::enabled must be true (user specializes to opt in). + * - StackConverter must provide: static To convert(const T&). + * + * @tparam To Target type. Stack and Stack gain Phase 3 fallback. + */ + template + Class& addConverter() + { + static_assert(StackConversion::enabled, + "Specialize StackConversion with enabled=true before calling addConverter()"); + + using FnType = TypeResult(*)(lua_State*, int); + static const FnType fn = &detail::convertFromStack; + + // Stack during Class methods: ns, co, cl, st + // Store into both cl (-2) and co (-3) so both mutable and const userdatas work. + detail::getOrCreateConverterRegistry(L, lua_absindex(L, -2))->converters[detail::getClassRegistryKey()] = &fn; // cl + detail::getOrCreateConverterRegistry(L, lua_absindex(L, -3))->converters[detail::getClassRegistryKey()] = &fn; // co + + return *this; + } + }; + + class Table : public detail::Registrar + { + public: + explicit Table(const char* name, Namespace parent) + : Registrar(std::move(parent)) + { + lua_newtable(L); // Stack: ns, table (tb) + lua_pushvalue(L, -1); // Stack: ns, tb, tb + rawsetfield(L, -3, name); + ++m_stackSize; + + lua_newtable(L); // Stack: ns, table (tb) + lua_pushvalue(L, -1); // Stack: ns, tb, tb + lua_setmetatable(L, -3); // tb.__metatable = tb. Stack: ns, tb + ++m_stackSize; + } + + using Registrar::operator=; + + template + Table& addFunction(const char* name, Function function) + { + using FnType = decltype(function); + + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns) + + lua_newuserdata_aligned(L, std::move(function)); // Stack: ns, function userdata (ud) + lua_pushcclosure_x(L, &detail::invoke_proxy_functor, name, 1); // Stack: ns, function + rawsetfield(L, -3, name); // Stack: ns + + return *this; + } + + template + Table& addMetaFunction(const char* name, Function function) + { + using FnType = decltype(function); + + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns) + + lua_newuserdata_aligned(L, std::move(function)); // Stack: ns, function userdata (ud) + lua_pushcclosure_x(L, &detail::invoke_proxy_functor, name, 1); // Stack: ns, function + rawsetfield(L, -2, name); // Stack: ns + + return *this; + } + + Namespace endTable() + { + LUABRIDGE_ASSERT(m_stackSize > 2); + + m_stackSize -= 2; + lua_pop(L, 2); + + return Namespace(std::move(*this)); + } + }; + +private: + struct FromStack {}; + + //============================================================================================= + /** + * @brief Open the global namespace for registrations. + * + * @param L A Lua state. + */ + explicit Namespace(lua_State* L) + : Registrar(L) + { + lua_getglobal(L, "_G"); + + ++m_stackSize; + } + + //============================================================================================= + /** + * @brief Open the a namespace for registrations from a table on top of the stack. + * + * @param L A Lua state. + */ + Namespace(lua_State* L, Options options, FromStack) + : Registrar(L, 1) + { + LUABRIDGE_ASSERT(lua_istable(L, -1)); + + lua_pushvalue(L, -1); // Stack: ns, ns + + // ns.__metatable = ns + lua_setmetatable(L, -2); // Stack: ns + + // ns.__index = index_static_metamethod + lua_pushcfunction_x(L, &detail::index_metamethod, "__index"); + rawsetfield(L, -2, "__index"); // Stack: ns + + // ns.__newindex = newindex_static_metamethod + //lua_pushcfunction_x(L, &detail::newindex_metamethod, "__newindex"); + //rawsetfield(L, -2, "__newindex"); // Stack: pns, ns + + lua_newtable(L); // Stack: ns, mt, propget table (pg) + lua_rawsetp_x(L, -2, detail::getPropgetKey()); // ns [propgetKey] = pg. Stack: ns + + lua_newtable(L); // Stack: ns, mt, propset table (ps) + lua_rawsetp_x(L, -2, detail::getPropsetKey()); // ns [propsetKey] = ps. Stack: ns + + if (! options.test(visibleMetatables)) + { + lua_pushboolean(L, 0); + rawsetfield(L, -2, "__metatable"); + } + + ++m_stackSize; + } + + //============================================================================================= + /** + * @brief Open a namespace for registrations. + * + * The namespace is created if it doesn't already exist. + * + * @param name The namespace name. + * @param parent The parent namespace object. + * + * @pre The parent namespace is at the top of the Lua stack. + */ + Namespace(const char* name, Namespace parent, Options options) + : Registrar(std::move(parent)) + { + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: parent namespace (pns) + + rawgetfield(L, -1, name); // Stack: pns, namespace (ns) | nil + + if (lua_isnil(L, -1)) // Stack: pns, nil + { + lua_pop(L, 1); // Stack: pns + + lua_newtable(L); // Stack: pns, ns + lua_pushvalue(L, -1); // Stack: pns, ns, mt + + // ns.__metatable = ns + lua_setmetatable(L, -2); // Stack: pns, ns + + // ns.__index = index_static_metamethod + lua_pushcfunction_x(L, &detail::index_metamethod, "__index"); + rawsetfield(L, -2, "__index"); // Stack: pns, ns + + // ns.__newindex = newindex_static_metamethod + lua_pushcfunction_x(L, &detail::newindex_metamethod, "__newindex"); + rawsetfield(L, -2, "__newindex"); // Stack: pns, ns + + lua_newtable(L); // Stack: pns, ns, propget table (pg) + lua_rawsetp_x(L, -2, detail::getPropgetKey()); // ns [propgetKey] = pg. Stack: pns, ns + + lua_newtable(L); // Stack: pns, ns, propset table (ps) + lua_rawsetp_x(L, -2, detail::getPropsetKey()); // ns [propsetKey] = ps. Stack: pns, ns + + if (! options.test(visibleMetatables)) + { + lua_pushboolean(L, 0); + rawsetfield(L, -2, "__metatable"); + } + + // pns [name] = ns + lua_pushvalue(L, -1); // Stack: pns, ns, ns + rawsetfield(L, -3, name); // Stack: pns, ns + } + + ++m_stackSize; + } + + //============================================================================================= + /** + * @brief Close the class and continue the namespace registrations. + * + * @param child A child class registration object. + */ + explicit Namespace(ClassBase child) + : Registrar(std::move(child)) + { + } + + explicit Namespace(Table child) + : Registrar(std::move(child)) + { + } + + using Registrar::operator=; + +public: + //============================================================================================= + /** + * @brief Retrieve the global namespace. + * + * It is recommended to put your namespace inside the global namespace, and then add your classes and functions to it, rather than + * adding many classes and functions directly to the global namespace. + * + * @param L A Lua state. + * + * @returns A namespace registration object. + */ + static Namespace getGlobalNamespace(lua_State* L) + { + return Namespace(L); + } + + /** + * @brief Retrieve the namespace on top of the stack. + * + * You should have a table on top of the stack before calling this function. It will then use the table there as destination for registrations. + * + * @param L A Lua state. + * + * @returns A namespace registration object. + */ + static Namespace getNamespaceFromStack(lua_State* L, Options options = defaultOptions) + { + return Namespace(L, options, FromStack{}); + } + + //============================================================================================= + /** + * @brief Open a new or existing namespace for registrations. + * + * @param name The namespace name. + * + * @returns A namespace registration object. + */ + Namespace beginNamespace(const char* name, Options options = defaultOptions) + { + assertIsActive(); + return Namespace(name, std::move(*this), options); + } + + //============================================================================================= + /** + * @brief Continue namespace registration in the parent. + * + * Do not use this on the global namespace. + * + * @returns A parent namespace registration object. + */ + Namespace endNamespace() + { + if (m_stackSize == 1) + { + throw_or_assert("endNamespace() called on global namespace"); + +#if !LUABRIDGE_HAS_EXCEPTIONS + return Namespace(std::move(*this)); +#endif + } + + LUABRIDGE_ASSERT(m_stackSize > 1); + --m_stackSize; + lua_pop(L, 1); + + return Namespace(std::move(*this)); + } + + //============================================================================================= + /** + * @brief Add or replace a variable that will be added in the namespace by copy of the passed value. + * + * @param name The variable name. + * @param value A value object. + * + * @returns This namespace registration object. + */ + template + Namespace& addVariable(const char* name, const T& value) + { + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns) + + if constexpr (std::is_enum_v) + { + using U = std::underlying_type_t; + + if (auto result = Stack::push(L, static_cast(value)); ! result) + throw_or_assert(result.message().c_str()); + } + else + { + if (auto result = Stack::push(L, value); ! result) + throw_or_assert(result.message().c_str()); + } + + rawsetfield(L, -2, name); // Stack: ns + + return *this; + } + + //============================================================================================= + /** + * @brief Add or replace a readonly property. + * + * @param name The property name. + * @param get A pointer to a property getter function. + * + * @returns This namespace registration object. + */ + template + Namespace& addProperty(const char* name, Getter getter) + { + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns) + + if (! checkTableHasPropertyGetter()) + { + throw_or_assert("addProperty() called on global namespace"); + +#if !LUABRIDGE_HAS_EXCEPTIONS + return *this; +#endif + } + + detail::push_property_getter(L, std::move(getter), name); // Stack: ns, getter + detail::add_property_getter(L, name, -2); // Stack: ns, getter + + detail::push_property_readonly(L, name); // Stack: ns, function + detail::add_property_setter(L, name, -2); // Stack: ns + + return *this; + } + + /** + * @brief Add or replace a mutable property. + * + * @param name The property name. + * @param get A pointer to a property getter function. + * @param set A pointer to a property setter function. + * + * @returns This namespace registration object. + */ + template + Namespace& addProperty(const char* name, Getter getter, Setter setter) + { + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns) + + if (! checkTableHasPropertyGetter()) + { + throw_or_assert("addProperty() called on global namespace"); + +#if !LUABRIDGE_HAS_EXCEPTIONS + return *this; +#endif + } + + detail::push_property_getter(L, std::move(getter), name); // Stack: ns, getter + detail::add_property_getter(L, name, -2); // Stack: ns + + detail::push_property_setter(L, std::move(setter), name); // Stack: ns, setter + detail::add_property_setter(L, name, -2); // Stack: ns + + return *this; + } + + //============================================================================================= + /** + * @brief Add or replace a single function or multiple overloaded functions. + * + * @param name The overload name. + * @param functions A single or set of functions that will be invoked. + * + * @returns This namespace registration object. + */ + template + auto addFunction(const char* name, Functions... functions) + -> std::enable_if_t<(detail::is_callable_v && ...) && (sizeof...(Functions) > 0), Namespace&> + { + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns) + + if constexpr (sizeof...(Functions) == 1) + { + ([&] + { + detail::push_function(L, std::move(functions), name); + + } (), ...); + } + else + { + // upvalue 1: OverloadSet (C++ struct with arity + type checker per overload) + auto* overload_set_unaligned = lua_newuserdata_aligned(L); + auto* overload_set = align(overload_set_unaligned); + + ([&] + { + detail::OverloadEntry entry; + if constexpr (detail::is_any_cfunction_pointer_v) + { + entry.arity = -1; + entry.checker = nullptr; + } + else + { + using ArgsPack = detail::function_arguments_t; + entry.arity = static_cast(detail::function_arity_excluding_v); + entry.checker = &detail::overload_type_checker; + } + overload_set->entries.push_back(entry); + + } (), ...); + + // upvalue 2: flat table of function closures indexed 1..N + lua_createtable(L, static_cast(sizeof...(Functions)), 0); + + int idx = 1; + + ([&] + { + detail::push_function(L, std::move(functions), name); + lua_rawseti(L, -2, idx++); + + } (), ...); + + lua_pushcclosure_x(L, &detail::try_overload_functions, name, 2); + } + + rawsetfield(L, -2, name); + + return *this; + } + +#if LUABRIDGE_HAS_CXX20_COROUTINES + //============================================================================================= + /** + * @brief Add a C++20 coroutine function to this namespace. + * + * The factory must be a callable returning CppCoroutine. When Lua calls the registered + * function, a new C++ coroutine is created and run; co_yield sends values to the Lua caller + * and co_return sends the final return value. + * + * @param name The function name to register. + * @param factory A callable returning CppCoroutine. + * + * @returns This namespace registration object. + */ + template + auto addCoroutine(const char* name, F factory) + -> std::enable_if_t, Namespace&> + { + LUABRIDGE_ASSERT(name != nullptr); + LUABRIDGE_ASSERT(lua_istable(L, -1)); // Stack: namespace table (ns) + + detail::push_coroutine_function(L, std::move(factory), name); + rawsetfield(L, -2, name); + + return *this; + } +#endif // LUABRIDGE_HAS_CXX20_COROUTINES + + //============================================================================================= + /** + * @brief Open a new or existing table as namespace for registrations. + * + * @param name The table name. + * + * @returns A table registration object. + */ + Table beginTable(const char* name) + { + assertIsActive(); + return Table(name, std::move(*this)); + } + + //============================================================================================= + /** + * @brief Open a new or existing class for registrations. + * + * @param name The class name. + * @param options The class options. + * + * @returns A class registration object. + */ + template + Class beginClass(const char* name, Options options = defaultOptions) + { + assertIsActive(); + return Class(name, std::move(*this), options); + } + + //============================================================================================= + /** + * @brief Derive a new class for registrations. + * + * Call deriveClass() only once. To continue registrations for the class later, use beginClass(). + * + * @param name The class name. + * @param options The class options. + * + * @returns A class registration object. + */ + template + Class deriveClass(const char* name, Options options = defaultOptions) + { + static_assert(std::is_base_of_v, "Derived must inherit from Base1"); + static_assert((std::is_base_of_v && ...), "Derived must inherit from all specified base classes"); + + assertIsActive(); + return Class(name, std::move(*this), { + detail::BaseClassInfo{ + detail::getStaticRegistryKey(), + detail::getClassRegistryKey(), + detail::computeCastOffset() + }, + detail::BaseClassInfo{ + detail::getStaticRegistryKey(), + detail::getClassRegistryKey(), + detail::computeCastOffset() + }... + }, options); + } + +private: + /** + * @brief Checks if the table has a property getter metatable. + */ + bool checkTableHasPropertyGetter() const + { + if (m_stackSize == 1 && lua_istable(L, -1)) + { + lua_rawgetp_x(L, -1, detail::getPropgetKey()); + const bool propertyGetterTableIsValid = lua_istable(L, -1); + lua_pop(L, 1); + + return propertyGetterTableIsValid; + } + + return true; + } +}; + +//================================================================================================= +/** + * @brief Retrieve the global namespace. + * + * It is recommended to put your namespace inside the global namespace, and then add your classes and functions to it, rather than adding + * many classes and functions directly to the global namespace. + * + * @param L A Lua state. + * + * @returns A namespace registration object. + */ +inline Namespace getGlobalNamespace(lua_State* L) +{ + return Namespace::getGlobalNamespace(L); +} + +//================================================================================================= +/** + * @brief Retrieve the namespace on top of the stack. + * + * You should have a table on top of the stack before calling this function. It will then use the table there as destination for registrations. + * + * @param L A Lua state. + * + * @returns A namespace registration object. + */ +inline Namespace getNamespaceFromStack(lua_State* L) +{ + return Namespace::getNamespaceFromStack(L); +} + +//================================================================================================= +/** + * @brief Registers main thread. + * + * This is a backward compatibility mitigation for lua 5.1 not supporting LUA_RIDX_MAINTHREAD. + * + * @param L The main Lua state that will be registered as main thread. + * + * @returns A namespace registration object. + */ +inline void registerMainThread(lua_State* L) +{ + register_main_thread(L); +} + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/Options.h b/external/include/LuaBridge3/LuaBridge/detail/Options.h new file mode 100644 index 0000000000..63a8267bf8 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Options.h @@ -0,0 +1,50 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2023, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "FlagSet.h" + +#include + +namespace luabridge { + +//================================================================================================= +namespace detail { +struct OptionExtensibleClass; +struct OptionAllowOverridingMethods; +struct OptionVisibleMetatables; +} // namespace Detail + +/** + * @brief Options for the library. + */ +using Options = FlagSet; + +/** + * @brief Set of default options. + * + * This setting means all options are not enabled. + */ +static inline constexpr Options defaultOptions = Options(); + +/** + * @brief Enable extensible C++ classes when registering them. + */ +static inline constexpr Options extensibleClass = Options::Value(); + +/** + * @brief Allow to be able to override methods from lua in extensible C++ classes. + */ +static inline constexpr Options allowOverridingMethods = Options::Value(); + +/** + * @brief Specify if metatables are visible for namespaces and classes. + */ +static inline constexpr Options visibleMetatables = Options::Value(); + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/Overload.h b/external/include/LuaBridge3/LuaBridge/detail/Overload.h new file mode 100644 index 0000000000..54bff00064 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Overload.h @@ -0,0 +1,84 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2020, Dmitry Tarakanov +// Copyright 2019, George Tokmaji +// Copyright 2012, Vinnie Falco +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" +#include "Errors.h" +#include "Stack.h" +#include "TypeTraits.h" +#include "Userdata.h" + +#include +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Overloaded objects. + */ +template +struct NonConstOverload +{ + template + constexpr auto operator()(R (T::*ptr)(Args...)) const noexcept -> decltype(ptr) + { + return ptr; + } + + template + static constexpr auto with(R (T::*ptr)(Args...)) noexcept -> decltype(ptr) + { + return ptr; + } +}; + +template +struct ConstOverload +{ + template + constexpr auto operator()(R (T::*ptr)(Args...) const) const noexcept -> decltype(ptr) + { + return ptr; + } + + template + static constexpr auto with(R (T::*ptr)(Args...) const) noexcept -> decltype(ptr) + { + return ptr; + } +}; + +template +struct Overload : ConstOverload, NonConstOverload +{ + using ConstOverload::operator(); + using NonConstOverload::operator(); + + template + constexpr auto operator()(R (*ptr)(Args...)) const noexcept -> decltype(ptr) + { + return ptr; + } + + template + static constexpr auto with(R (T::*ptr)(Args...)) noexcept -> decltype(ptr) + { + return ptr; + } +}; + +//================================================================================================= +/** + * @brief Overload resolution. + */ +template [[maybe_unused]] constexpr Overload overload = {}; +template [[maybe_unused]] constexpr ConstOverload constOverload = {}; +template [[maybe_unused]] constexpr NonConstOverload nonConstOverload = {}; + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/Result.h b/external/include/LuaBridge3/LuaBridge/detail/Result.h new file mode 100644 index 0000000000..6f59c331e8 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Result.h @@ -0,0 +1,257 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2022, kunitoki +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Errors.h" + +#include + +namespace luabridge { + +//================================================================================================= +/** + * @brief Simple result class containing a result. + */ +struct Result +{ + Result() noexcept = default; + + Result(std::error_code ec) noexcept + : m_ec(ec) + { + } + + Result(const Result&) noexcept = default; + Result(Result&&) noexcept = default; + Result& operator=(const Result&) noexcept = default; + Result& operator=(Result&&) noexcept = default; + + explicit operator bool() const noexcept + { + return !m_ec; + } + + std::error_code error() const noexcept + { + return m_ec; + } + + const char* error_cstr() const noexcept + { + return detail::ErrorCategory::errorString(m_ec.value()); + } + + operator std::error_code() const noexcept + { + return m_ec; + } + + std::string message() const + { + return m_ec.message(); + } + +#if LUABRIDGE_HAS_EXCEPTIONS + void throw_on_error() const + { + if (m_ec) + throw std::system_error(m_ec); + } +#endif + +private: + std::error_code m_ec; +}; + +//================================================================================================= +/** + * @brief Simple result class containing or a type T or an error code. + */ +template +struct TypeResult +{ + TypeResult() noexcept = default; + + template && !std::is_same_v, std::error_code>>> + TypeResult(U&& value) noexcept + : m_value(std::in_place, std::forward(value)) + { + } + + TypeResult(std::error_code ec) noexcept + : m_value(makeUnexpected(ec)) + { + } + + TypeResult(const TypeResult&) = default; + TypeResult(TypeResult&&) = default; + TypeResult& operator=(const TypeResult&) = default; + TypeResult& operator=(TypeResult&&) = default; + + explicit operator bool() const noexcept + { + return m_value.hasValue(); + } + + const T& value() const + { + return m_value.value(); + } + + T& operator*() & + { + return m_value.value(); + } + + T operator*() && + { + return std::move(m_value.value()); + } + + const T& operator*() const& + { + return m_value.value(); + } + + T operator*() const&& + { + return std::move(m_value.value()); + } + + T* operator->() + { + return &m_value.value(); + } + + const T* operator->() const + { + return &m_value.value(); + } + + template + T valueOr(U&& defaultValue) const& + { + return m_value.valueOr(std::forward(defaultValue)); + } + + template + T valueOr(U&& defaultValue) && + { + return m_value.valueOr(std::forward(defaultValue)); + } + + std::error_code error() const + { + return m_value.error(); + } + + const char* error_cstr() const noexcept + { + return detail::ErrorCategory::errorString(m_value.error().value()); + } + + operator std::error_code() const + { + return m_value.error(); + } + + std::string message() const + { + return m_value.error().message(); + } + +#if LUABRIDGE_HAS_EXCEPTIONS + void throw_on_error() const + { + if (! m_value.hasValue()) + throw std::system_error(m_value.error()); + } +#endif + +private: + Expected m_value; +}; + +template <> +struct TypeResult +{ + TypeResult() noexcept = default; + + TypeResult(std::error_code ec) noexcept + : m_ec(ec) + { + } + + TypeResult(const TypeResult&) noexcept = default; + TypeResult(TypeResult&&) noexcept = default; + TypeResult& operator=(const TypeResult&) noexcept = default; + TypeResult& operator=(TypeResult&&) noexcept = default; + + explicit operator bool() const noexcept + { + return ! m_ec; + } + + void value() const noexcept + { + } + + std::error_code error() const noexcept + { + return m_ec; + } + + const char* error_cstr() const noexcept + { + return detail::ErrorCategory::errorString(m_ec.value()); + } + + operator std::error_code() const noexcept + { + return m_ec; + } + + std::string message() const + { + return m_ec.message(); + } + +#if LUABRIDGE_HAS_EXCEPTIONS + void throw_on_error() const + { + if (m_ec) + throw std::system_error(m_ec); + } +#endif + +private: + std::error_code m_ec; +}; + +template +inline bool operator==(const TypeResult& lhs, const U& rhs) noexcept +{ + return lhs ? *lhs == rhs : false; +} + +template +inline bool operator==(const U& lhs, const TypeResult& rhs) noexcept +{ + return rhs == lhs; +} + +template +inline bool operator!=(const TypeResult& lhs, const U& rhs) noexcept +{ + return !(lhs == rhs); +} + +template +inline bool operator!=(const U& lhs, const TypeResult& rhs) noexcept +{ + return !(rhs == lhs); +} + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/ScopeGuard.h b/external/include/LuaBridge3/LuaBridge/detail/ScopeGuard.h new file mode 100644 index 0000000000..057fb79fb0 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/ScopeGuard.h @@ -0,0 +1,47 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2021, kunitoki +// Copyright 2012, Vinnie Falco +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" +#include "Stack.h" + +namespace luabridge::detail { + +//================================================================================================= +/** + * @brief Scope guard. + */ +template +class ScopeGuard +{ +public: + template + explicit ScopeGuard(V&& v) + : m_func(std::forward(v)) + , m_shouldRun(true) + { + } + + ~ScopeGuard() + { + if (m_shouldRun) + m_func(); + } + + void reset() noexcept + { + m_shouldRun = false; + } + +private: + F m_func; + bool m_shouldRun; +}; + +template +ScopeGuard(F&&) -> ScopeGuard; + +} // namespace luabridge::detail diff --git a/external/include/LuaBridge3/LuaBridge/detail/Stack.h b/external/include/LuaBridge3/LuaBridge/detail/Stack.h new file mode 100644 index 0000000000..512124bafe --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/Stack.h @@ -0,0 +1,1792 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2019, Dmitry Tarakanov +// Copyright 2012, Vinnie Falco +// Copyright 2007, Nathan Reed +// SPDX-License-Identifier: MIT + +#pragma once + +#include "LuaHelpers.h" +#include "Errors.h" +#include "Expected.h" +#include "Result.h" +#include "Userdata.h" +#include "Converter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if LUABRIDGE_HAS_CXX17_FILESYSTEM +#include +#endif + +namespace luabridge { + +//================================================================================================= +/** + * @brief Stack restorer. + */ +class StackRestore final +{ +public: + StackRestore(lua_State* L) + : m_L(L) + , m_stackTop(lua_gettop(L)) + { + } + + ~StackRestore() + { + if (m_doRestoreStack) + lua_settop(m_L, m_stackTop); + } + + void reset() + { + m_doRestoreStack = false; + } + +private: + lua_State* const m_L = nullptr; + int m_stackTop = 0; + bool m_doRestoreStack = true; +}; + +//================================================================================================= +/** + * @brief Lua stack traits for C++ types. + * + * @tparam T A C++ type. + */ +template +struct Stack; + +//================================================================================================= +/** + * @brief Specialization for void type. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State*) + { + return {}; + } +}; + +//================================================================================================= +/** + * @brief Specialization for nullptr_t. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, std::nullptr_t) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushnil(L); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (! lua_isnil(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + return nullptr; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_isnil(L, index); + } +}; + +//================================================================================================= +/** + * @brief Receive the lua_State* as an argument. + */ +template <> +struct Stack +{ + [[nodiscard]] static TypeResult get(lua_State* L, int) + { + return L; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for a lua_CFunction. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, lua_CFunction f) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushcfunction_x(L, f, ""); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (! lua_iscfunction(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + return lua_tocfunction(L, index); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_iscfunction(L, index) != 0; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `bool`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, bool value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushboolean(L, value ? 1 : 0); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { +#if LUABRIDGE_STRICT_STACK_CONVERSIONS + if (lua_type(L, index) != LUA_TBOOLEAN) + return makeErrorCode(ErrorCode::InvalidTypeCast); +#endif + + return lua_toboolean(L, index) ? true : false; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_isboolean(L, index); + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `std::byte`. + */ +template <> +struct Stack +{ + static_assert(sizeof(std::byte) < sizeof(lua_Integer)); + + [[nodiscard]] static Result push(lua_State* L, std::byte value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + pushunsigned(L, std::to_integer>(value)); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `char`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, char value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushlstring(L, &value, 1); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TSTRING) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + std::size_t length = 0; + const char* str = lua_tolstring(L, index, &length); + + if (str == nullptr || length != 1) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + return str[0]; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TSTRING) + { + std::size_t len = 0; + lua_tolstring(L, index, &len); + return len == 1; + } + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `int8_t`. + */ +#if !defined(__BORLANDC__) +template <> +struct Stack +{ + static_assert(sizeof(int8_t) < sizeof(lua_Integer)); + + [[nodiscard]] static Result push(lua_State* L, int8_t value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushinteger(L, static_cast(value)); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by(L, index); + + return false; + } +}; +#endif + +//================================================================================================= +/** + * @brief Stack specialization for `unsigned char`. + */ +template <> +struct Stack +{ + static_assert(sizeof(unsigned char) < sizeof(lua_Integer)); + + [[nodiscard]] static Result push(lua_State* L, unsigned char value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + pushunsigned(L, value); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `short`. + */ +template <> +struct Stack +{ + static_assert(sizeof(short) < sizeof(lua_Integer)); + + [[nodiscard]] static Result push(lua_State* L, short value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushinteger(L, static_cast(value)); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `unsigned short`. + */ +template <> +struct Stack +{ + static_assert(sizeof(unsigned short) < sizeof(lua_Integer)); + + [[nodiscard]] static Result push(lua_State* L, unsigned short value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + pushunsigned(L, value); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `int`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, int value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! is_integral_representable_by(value)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + lua_pushinteger(L, static_cast(value)); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `unsigned int`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, unsigned int value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! is_integral_representable_by(value)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + pushunsigned(L, value); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `long`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, long value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! is_integral_representable_by(value)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + lua_pushinteger(L, static_cast(value)); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `unsigned long`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, unsigned long value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! is_integral_representable_by(value)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + pushunsigned(L, value); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `long long`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, long long value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! is_integral_representable_by(value)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + lua_pushinteger(L, static_cast(value)); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `unsigned long long`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, unsigned long long value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! is_integral_representable_by(value)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + pushunsigned(L, value); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by(L, index); + + return false; + } +}; + +#if 0 // defined(__SIZEOF_INT128__) +//================================================================================================= +/** + * @brief Stack specialization for `__int128_t`. + */ +template <> +struct Stack<__int128_t> +{ + [[nodiscard]] static Result push(lua_State* L, __int128_t value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! is_integral_representable_by(value)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + lua_pushinteger(L, static_cast(value)); + return {}; + } + + [[nodiscard]] static TypeResult<__int128_t> get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast<__int128_t>(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by<__int128_t>(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast<__int128_t>(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by<__int128_t>(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `__uint128_t`. + */ +template <> +struct Stack<__uint128_t> +{ + [[nodiscard]] static Result push(lua_State* L, __uint128_t value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! is_integral_representable_by(value)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + lua_pushinteger(L, static_cast(value)); + return {}; + } + + [[nodiscard]] static TypeResult<__uint128_t> get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + // Cortex Command: truncate like luabind did (static_cast from lua_Number) instead of rejecting non-integral numbers. + return static_cast<__uint128_t>(static_cast(lua_tonumber(L, index))); +#else + if (! is_integral_representable_by<__uint128_t>(L, index)) + return makeErrorCode(ErrorCode::IntegerDoesntFitIntoLuaInteger); + + return static_cast<__uint128_t>(lua_tointeger(L, index)); +#endif + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_integral_representable_by<__uint128_t>(L, index); + + return false; + } +}; +#endif + +//================================================================================================= +/** + * @brief Stack specialization for `float`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, float value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! is_floating_point_representable_by(value)) + return makeErrorCode(ErrorCode::FloatingPointDoesntFitIntoLuaNumber); + + lua_pushnumber(L, static_cast(value)); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if !LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + if (! is_floating_point_representable_by(L, index)) + return makeErrorCode(ErrorCode::FloatingPointDoesntFitIntoLuaNumber); +#endif + + return static_cast(lua_tonumber(L, index)); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_floating_point_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `double`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, double value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! is_floating_point_representable_by(value)) + return makeErrorCode(ErrorCode::FloatingPointDoesntFitIntoLuaNumber); + + lua_pushnumber(L, static_cast(value)); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if !LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + if (! is_floating_point_representable_by(L, index)) + return makeErrorCode(ErrorCode::FloatingPointDoesntFitIntoLuaNumber); +#endif + + return static_cast(lua_tonumber(L, index)); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_floating_point_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `long double`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, long double value) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (! is_floating_point_representable_by(value)) + return makeErrorCode(ErrorCode::FloatingPointDoesntFitIntoLuaNumber); + + lua_pushnumber(L, static_cast(value)); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TNUMBER) + return makeErrorCode(ErrorCode::InvalidTypeCast); + +#if !LUABRIDGE_LUABIND_COMPATIBLE_NUMBERS + if (! is_floating_point_representable_by(L, index)) + return makeErrorCode(ErrorCode::FloatingPointDoesntFitIntoLuaNumber); +#endif + + return static_cast(lua_tonumber(L, index)); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + if (lua_type(L, index) == LUA_TNUMBER) + return is_floating_point_representable_by(L, index); + + return false; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `const char*`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, const char* str) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + if (str != nullptr) + lua_pushstring(L, str); + else + lua_pushnil(L); + + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + const bool isNil = lua_isnil(L, index); + + if (!isNil && lua_type(L, index) != LUA_TSTRING) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + if (isNil) + return nullptr; + + std::size_t length = 0; + const char* str = lua_tolstring(L, index, &length); + if (str == nullptr) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + return str; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_isnil(L, index) || lua_type(L, index) == LUA_TSTRING; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `std::string_view`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, std::string_view str) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushlstring(L, str.data(), str.size()); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TSTRING) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + std::size_t length = 0; + const char* str = lua_tolstring(L, index, &length); + if (str == nullptr) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + return std::string_view{ str, length }; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_type(L, index) == LUA_TSTRING; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `std::string`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, const std::string& str) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushlstring(L, str.data(), str.size()); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + std::size_t length = 0; + const char* str = nullptr; + + if (lua_type(L, index) == LUA_TSTRING) + { + str = lua_tolstring(L, index, &length); + } +#if !LUABRIDGE_STRICT_STACK_CONVERSIONS + else + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + // Lua reference manual: + // If the value is a number, then lua_tolstring also changes the actual value in the stack + // to a string. (This change confuses lua_next when lua_tolstring is applied to keys during + // a table traversal) + lua_pushvalue(L, index); + str = lua_tolstring(L, -1, &length); + lua_pop(L, 1); + } +#endif + + if (str == nullptr) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + return std::string{ str, length }; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_type(L, index) == LUA_TSTRING; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `std::optional`. + */ +template +struct Stack> +{ + using Type = std::optional; + + [[nodiscard]] static Result push(lua_State* L, const Type& value) + { + if (value) + { + StackRestore stackRestore(L); + + auto result = Stack::push(L, *value); + if (! result) + return result; + + stackRestore.reset(); + return {}; + } + +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushnil(L); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + const auto type = lua_type(L, index); + if (type == LUA_TNIL || type == LUA_TNONE) + return std::nullopt; + + auto result = Stack::get(L, index); + if (! result) + return result.error(); + + return std::make_optional(std::move(*result)); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + const auto type = lua_type(L, index); + return (type == LUA_TNIL || type == LUA_TNONE) || Stack::isInstance(L, index); + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `luabridge::Expected`. + */ +template +struct Stack> +{ + using Type = Expected; + + [[nodiscard]] static Result push(lua_State* L, const Type& value) + { + if (value.hasValue()) + { + StackRestore stackRestore(L); + + auto result = Stack::push(L, *value); + if (! result) + return result; + + stackRestore.reset(); + return {}; + } + +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushnil(L); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + const auto type = lua_type(L, index); + if (type == LUA_TNIL || type == LUA_TNONE) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + auto result = Stack::get(L, index); + if (! result) + return result.error(); + + return Type(*result); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + const auto type = lua_type(L, index); + return (type != LUA_TNIL && type != LUA_TNONE) && Stack::isInstance(L, index); + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `std::pair`. + */ +template +struct Stack> +{ + [[nodiscard]] static Result push(lua_State* L, const std::pair& t) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, 2, 0); + + auto result1 = push_element<0>(L, t); + if (! result1) + return result1; + + auto result2 = push_element<1>(L, t); + if (! result2) + return result2; + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult> get(lua_State* L, int index) + { + const StackRestore stackRestore(L); + + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + if (get_length(L, index) != 2) + return makeErrorCode(ErrorCode::InvalidTableSizeInCast); + + std::pair value; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + auto result1 = pop_element<0>(L, absIndex, value); + if (! result1) + return result1.error(); + + auto result2 = pop_element<1>(L, absIndex, value); + if (! result2) + return result2.error(); + + return value; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_type(L, index) == LUA_TTABLE && get_length(L, index) == 2; + } + +private: + template + static Result push_element(lua_State* L, const std::pair& p) + { + static_assert(Index < 2); + + using T = std::tuple_element_t>; + + lua_pushinteger(L, static_cast(Index + 1)); + + auto result = Stack::push(L, std::get(p)); + if (! result) + return result; + + lua_settable(L, -3); + + return {}; + } + + template + static Result pop_element(lua_State* L, int absIndex, std::pair& p) + { + static_assert(Index < 2); + + using T = std::tuple_element_t>; + + if (lua_next(L, absIndex) == 0) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + auto result = Stack::get(L, -1); + if (! result) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + std::get(p) = std::move(*result); + lua_pop(L, 1); + + return {}; + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `std::tuple`. + */ +template +struct Stack> +{ + [[nodiscard]] static Result push(lua_State* L, const std::tuple& t) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 3)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, static_cast(Size), 0); + + auto result = push_element(L, t); + if (! result) + return result; + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static TypeResult> get(lua_State* L, int index) + { + const StackRestore stackRestore(L); + + if (!lua_istable(L, index)) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + if (get_length(L, index) != static_cast(Size)) + return makeErrorCode(ErrorCode::InvalidTableSizeInCast); + + std::tuple value; + + int absIndex = lua_absindex(L, index); + lua_pushnil(L); + + auto result = pop_element(L, absIndex, value); + if (! result) + return result.error(); + + return value; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_type(L, index) == LUA_TTABLE && get_length(L, index) == static_cast(Size); + } + +private: + static constexpr std::size_t Size = std::tuple_size_v>; + + template + static auto push_element(lua_State*, const std::tuple&) + -> std::enable_if_t + { + return {}; + } + + template + static auto push_element(lua_State* L, const std::tuple& t) + -> std::enable_if_t + { + using T = std::tuple_element_t>; + + lua_pushinteger(L, static_cast(Index + 1)); + + auto result = Stack::push(L, std::get(t)); + if (! result) + return result; + + lua_settable(L, -3); + + return push_element(L, t); + } + + template + static auto pop_element(lua_State*, int, std::tuple&) + -> std::enable_if_t + { + return {}; + } + + template + static auto pop_element(lua_State* L, int absIndex, std::tuple& t) + -> std::enable_if_t + { + using T = std::tuple_element_t>; + + if (lua_next(L, absIndex) == 0) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + auto result = Stack::get(L, -1); + if (! result) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + std::get(t) = std::move(*result); + lua_pop(L, 1); + + return pop_element(L, absIndex, t); + } +}; + +//================================================================================================= +/** + * @brief Stack specialization for `T[N]`. + */ +template +struct Stack +{ + static_assert(N > 0, "Unsupported zero sized array"); + + [[nodiscard]] static Result push(lua_State* L, const T (&value)[N]) + { + if constexpr (std::is_same_v) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushlstring(L, value, N - 1); + return {}; + } + +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 2)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + StackRestore stackRestore(L); + + lua_createtable(L, static_cast(N), 0); + + for (std::size_t i = 0; i < N; ++i) + { + lua_pushinteger(L, static_cast(i + 1)); + + auto result = Stack::push(L, value[i]); + if (! result) + return result; + + lua_settable(L, -3); + } + + stackRestore.reset(); + return {}; + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_type(L, index) == LUA_TTABLE && get_length(L, index) == static_cast(N); + } +}; + +//================================================================================================= +/** + * @brief Specialization for `void*` and `const void*` type. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, void* ptr) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushlightuserdata(L, ptr); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_isnil(L, index)) + return nullptr; + + if (lua_islightuserdata(L, index)) + return lua_touserdata(L, index); + + return makeErrorCode(ErrorCode::InvalidTypeCast); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_islightuserdata(L, index) || lua_isnil(L, index); + } +}; + +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, const void* ptr) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushlightuserdata(L, const_cast(ptr)); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_isnil(L, index)) + return nullptr; + + if (lua_islightuserdata(L, index)) + return lua_touserdata(L, index); + + return makeErrorCode(ErrorCode::InvalidTypeCast); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_islightuserdata(L, index) || lua_isnil(L, index); + } +}; + +#if LUABRIDGE_HAS_CXX17_FILESYSTEM + +//================================================================================================= +/** + * @brief Stack specialization for `std::filesystem::path`. + */ +template <> +struct Stack +{ + [[nodiscard]] static Result push(lua_State* L, const std::filesystem::path& path) + { +#if LUABRIDGE_SAFE_STACK_CHECKS + if (! lua_checkstack(L, 1)) + return makeErrorCode(ErrorCode::LuaStackOverflow); +#endif + + lua_pushlstring(L, path.string().c_str(), path.string().size()); + return {}; + } + + [[nodiscard]] static TypeResult get(lua_State* L, int index) + { + if (lua_type(L, index) != LUA_TSTRING) + return makeErrorCode(ErrorCode::InvalidTypeCast); + + std::size_t len = 0; + const char* str = lua_tolstring(L, index, &len); + return std::filesystem::path(std::string(str, len)); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return lua_type(L, index) == LUA_TSTRING; + } +}; +#endif // LUABRIDGE_HAS_CXX17_FILESYSTEM + +//================================================================================================= + +namespace detail { + +template +struct StackOpSelector +{ + using ReturnType = TypeResult; + + static Result push(lua_State* L, T* value) + { + return value ? Stack::push(L, *value) : Stack::push(L, nullptr); + } + + static ReturnType get(lua_State* L, int index) { return Stack::get(L, index); } + + template + static bool isInstance(lua_State* L, int index) { return Stack::isInstance(L, index); } +}; + +template +struct StackOpSelector +{ + using ReturnType = TypeResult; + + static Result push(lua_State* L, const T* value) + { + return value ? Stack::push(L, *value) : Stack::push(L, nullptr); + } + + static ReturnType get(lua_State* L, int index) { return Stack::get(L, index); } + + template + static bool isInstance(lua_State* L, int index) { return Stack::isInstance(L, index); } +}; + +template +struct StackOpSelector +{ + using ReturnType = TypeResult; + + static Result push(lua_State* L, T& value) { return Stack::push(L, value); } + + static ReturnType get(lua_State* L, int index) { return Stack::get(L, index); } + + template + static bool isInstance(lua_State* L, int index) { return Stack::isInstance(L, index); } +}; + +template +struct StackOpSelector +{ + using ReturnType = TypeResult; + + static Result push(lua_State* L, const T& value) { return Stack::push(L, value); } + + static ReturnType get(lua_State* L, int index) { return Stack::get(L, index); } + + template + static bool isInstance(lua_State* L, int index) { return Stack::isInstance(L, index); } +}; + +} // namespace detail + +template +struct Stack +{ + using Helper = detail::StackOpSelector::value>; + using ReturnType = typename Helper::ReturnType; + + [[nodiscard]] static Result push(lua_State* L, T* value) { return Helper::push(L, value); } + + [[nodiscard]] static ReturnType get(lua_State* L, int index) { return Helper::get(L, index); } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) { return Helper::isInstance(L, index); } +}; + +template +struct Stack +{ + using Helper = detail::StackOpSelector::value>; + using ReturnType = typename Helper::ReturnType; + + [[nodiscard]] static Result push(lua_State* L, const T* value) { return Helper::push(L, value); } + + [[nodiscard]] static ReturnType get(lua_State* L, int index) { return Helper::get(L, index); } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) { return Helper::isInstance(L, index); } +}; + +template +struct Stack && !std::is_const_v>> +{ + using Helper = detail::StackOpSelector::value>; + using ReturnType = typename Helper::ReturnType; + + [[nodiscard]] static Result push(lua_State* L, T& value) { return Helper::push(L, value); } + + [[nodiscard]] static ReturnType get(lua_State* L, int index) { return Helper::get(L, index); } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) { return Helper::isInstance(L, index); } +}; + +template +struct Stack && !StackConversion::enabled>> +{ + using Helper = detail::StackOpSelector::value>; + using ReturnType = typename Helper::ReturnType; + + [[nodiscard]] static Result push(lua_State* L, const T& value) { return Helper::push(L, value); } + + [[nodiscard]] static ReturnType get(lua_State* L, int index) { return Helper::get(L, index); } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) { return Helper::isInstance(L, index); } +}; + +template +struct Stack::enabled && !std::is_array_v>> +{ + using ReturnType = TypeResult>; + + [[nodiscard]] static Result push(lua_State* L, const T& value) + { + return Stack::push(L, value); + } + + [[nodiscard]] static ReturnType get(lua_State* L, int index) + { + if (detail::Userdata::isInstance(L, index)) + { + auto result = detail::Userdata::get(L, index, true); + if (!result) + return result.error(); + + if (T* ptr = *result) + return detail::ConverterConstRef(*ptr); + + return detail::getNilBadArgError(L, index); + } + + auto converted = detail::tryConvertFromRegisteredConverter(L, index); + if (!converted) + return converted.error(); + + return detail::ConverterConstRef(std::move(*converted)); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return Stack::isInstance(L, index); + } +}; + +template +struct Stack::enabled>> +{ + using IsUserdata = void; + using ReturnType = TypeResult; + + [[nodiscard]] static Result push(lua_State* L, const T& value) + { + return detail::StackHelper::value>::push(L, value); + } + + [[nodiscard]] static Result push(lua_State* L, T&& value) + { + return detail::StackHelper::value>::push(L, std::move(value)); + } + + [[nodiscard]] static ReturnType get(lua_State* L, int index) + { + if (detail::Userdata::isInstance(L, index)) + { + auto result = detail::Userdata::get(L, index, true); + if (result) + { + if (T* ptr = *result) + return *ptr; + } + return result.error(); + } + + return detail::tryConvertFromRegisteredConverter(L, index); + } + + [[nodiscard]] static bool isInstance(lua_State* L, int index) + { + return detail::Userdata::isInstance(L, index); + } +}; + +//================================================================================================= +/** + * @brief Push an object onto the Lua stack. + */ +template +[[nodiscard]] Result push(lua_State* L, const T& t) +{ + return Stack::push(L, t); +} + +//================================================================================================= +/** + * @brief Get an object from the Lua stack. + */ +template +[[nodiscard]] TypeResult get(lua_State* L, int index) +{ + return Stack::get(L, index); +} + +//================================================================================================= +/** + * @brief Check whether an object on the Lua stack is of type T. + */ +template +[[nodiscard]] bool isInstance(lua_State* L, int index) +{ + return Stack::isInstance(L, index); +} + +} // namespace luabridge diff --git a/external/include/LuaBridge3/LuaBridge/detail/TypeTraits.h b/external/include/LuaBridge3/LuaBridge/detail/TypeTraits.h new file mode 100644 index 0000000000..58f895af31 --- /dev/null +++ b/external/include/LuaBridge3/LuaBridge/detail/TypeTraits.h @@ -0,0 +1,159 @@ +// https://github.com/kunitoki/LuaBridge3 +// Copyright 2020, kunitoki +// Copyright 2019, Dmitry Tarakanov +// Copyright 2012, Vinnie Falco +// SPDX-License-Identifier: MIT + +#pragma once + +#include "Config.h" + +#include +#include + +namespace luabridge { +namespace detail { +template