diff --git a/.gitmodules b/.gitmodules index 1713c4b9..90e8840f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -40,3 +40,6 @@ [submodule "3rdparty/JoltPhysics"] path = 3rdparty/JoltPhysics url = https://github.com/jrouwe/JoltPhysics.git +[submodule "3rdparty/godot-cpp"] + path = 3rdparty/godot-cpp + url = https://github.com/godotengine/godot-cpp diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index cd711720..4ea3ba10 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -122,16 +122,16 @@ if(NOT OSP_USE_SYSTEM_SDL) SET(SDL_VIRTUAL_JOYSTICK ON CACHE BOOL "" FORCE) SET(LIBSAMPLERATE ON CACHE BOOL "" FORCE) - SET(LIBSAMPLERATE_SHARED ON CACHE BOOL "" FORCE) + SET(LIBSAMPLERATE_SHARED OFF CACHE BOOL "" FORCE) SET(SDL_EVENTS ON CACHE BOOL "" FORCE) SET(SDL_THREADS ON CACHE BOOL "" FORCE) # This assumes you want to have SDL as a static library. If not, set SDL_STATIC # to OFF instead. - SET(SDL_DLOPEN ON CACHE BOOL "" FORCE) - SET(SDL_SHARED ON CACHE BOOL "" FORCE) - SET(SDL_STATIC OFF CACHE BOOL "" FORCE) + SET(SDL_DLOPEN OFF CACHE BOOL "" FORCE) + SET(SDL_SHARED OFF CACHE BOOL "" FORCE) + SET(SDL_STATIC ON CACHE BOOL "" FORCE) SET(SDL2_DISABLE_SDL2MAIN ON CACHE BOOL "" FORCE) SET(SDL2_DISABLE_INSTALL ON CACHE BOOL "" FORCE) @@ -191,26 +191,22 @@ SET(MAGNUM_WITH_SHADERS ON CACHE BOOL "" FORCE) SET(MAGNUM_WITH_SHADERTOOLS OFF CACHE BOOL "" FORCE) SET(MAGNUM_WITH_TESTSUITE OFF CACHE BOOL "" FORCE) SET(MAGNUM_WITH_TEXT OFF CACHE BOOL "" FORCE) +SET(MAGNUM_WITH_GL ON CACHE BOOL "" FORCE) +SET(MAGNUM_TARGET_GL ON CACHE BOOL "" FORCE) + +IF (OSP_BUILD_GDEXTENSION) +SET(MAGNUM_WITH_SDL2APPLICATION OFF CACHE BOOL "" FORCE) +SET(MAGNUM_WITH_SHADERS OFF CACHE BOOL "" FORCE) +SET(MAGNUM_WITH_GL OFF CACHE BOOL "" FORCE) +SET(MAGNUM_TARGET_GL OFF CACHE BOOL "" FORCE) +ENDIF() + ADD_SUBDIRECTORY(magnum EXCLUDE_FROM_ALL) SET(MAGNUM_WITH_TINYGLTFIMPORTER ON CACHE BOOL "" FORCE) SET(MAGNUM_WITH_STBIMAGEIMPORTER ON CACHE BOOL "" FORCE) ADD_SUBDIRECTORY(magnum-plugins EXCLUDE_FROM_ALL) -SET(NEWTON_BUILD_SANDBOX_DEMOS OFF CACHE BOOL "" FORCE) -SET(NEWTON_BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE) -SET(NEWTON_USE_PLUGIN_DLL OFF CACHE BOOL "" FORCE) -SET(NEWTON_WITH_AVX_PLUGIN OFF CACHE BOOL "" FORCE) -SET(NEWTON_WITH_REFERENCE_GPU_PLUGIN OFF CACHE BOOL "" FORCE) -ADD_SUBDIRECTORY(newton-dynamics/newton-3.14/ EXCLUDE_FROM_ALL) - -# Newton sets CMAKE_ARCHIVE_OUTPUT_DIRECTORY and CMAKE_LIBRARY_OUTPUT_DIRECTORY -# for UNIX, so manually set each target to our desired location -SET_TARGET_PROPERTIES(dAnimation dContainers dCustomJoints dMath dModel dNewton dScene dVehicle dgCore dgPhysics newton PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" -) - ADD_SUBDIRECTORY(entt EXCLUDE_FROM_ALL) # toml11 3.8.0 added a check for this global variable, which they should not have. @@ -222,6 +218,7 @@ ADD_SUBDIRECTORY(toml11 EXCLUDE_FROM_ALL) SET(SPDLOG_ENABLE_PCH ON CACHE BOOL "" FORCE) # Not yet supported by github runners # SET(SPDLOG_USE_STD_FORMAT ON CACHE BOOL "" FORCE) +SET(SPDLOG_BUILD_PIC ON CACHE BOOL "" FORCE) ADD_SUBDIRECTORY(spdlog EXCLUDE_FROM_ALL) ADD_SUBDIRECTORY(longeronpp EXCLUDE_FROM_ALL) @@ -229,25 +226,36 @@ ADD_SUBDIRECTORY(longeronpp EXCLUDE_FROM_ALL) SET(gtest_force_shared_crt ON CACHE BOOL "" FORCE) ADD_SUBDIRECTORY(googletest EXCLUDE_FROM_ALL) -SET(FT_DISABLE_ZLIB ON CACHE BOOL "" FORCE) -SET(FT_DISABLE_BZIP2 ON CACHE BOOL "" FORCE) -SET(FT_DISABLE_PNG ON CACHE BOOL "" FORCE) -SET(FT_DISABLE_HARFBUZZ ON CACHE BOOL "" FORCE) -SET(FT_DISABLE_BROTLI ON CACHE BOOL "" FORCE) -SET(SKIP_INSTALL_ALL ON CACHE BOOL "" FORCE) -SET(SKIP_INSTALL_LIBRARIES ON CACHE BOOL "" FORCE) -SET(BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE) -ADD_SUBDIRECTORY(freetype EXCLUDE_FROM_ALL) - -INSTALL(TARGETS freetype - EXPORT RmlUiTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - ) +# SET(FT_DISABLE_ZLIB ON CACHE BOOL "" FORCE) +# SET(FT_DISABLE_BZIP2 ON CACHE BOOL "" FORCE) +# SET(FT_DISABLE_PNG ON CACHE BOOL "" FORCE) +# SET(FT_DISABLE_HARFBUZZ ON CACHE BOOL "" FORCE) +# SET(FT_DISABLE_BROTLI ON CACHE BOOL "" FORCE) +# SET(SKIP_INSTALL_ALL ON CACHE BOOL "" FORCE) +# SET(SKIP_INSTALL_LIBRARIES ON CACHE BOOL "" FORCE) +# SET(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) +# ADD_SUBDIRECTORY(freetype EXCLUDE_FROM_ALL) + +# INSTALL(TARGETS freetype +# EXPORT RmlUiTargets +# LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +# ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} +# RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +# ) SET(RML_SKIP_INSTALL ON CACHE BOOL "" FORCE) SET(CUSTOM_CONFIGURATION ON CACHE BOOL "" FORCE) #ADD_SUBDIRECTORY(RmlUi EXCLUDE_FROM_ALL) SET(ENABLE_ALL_WARNINGS OFF CACHE BOOL "" FORCE) +SET(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) ADD_SUBDIRECTORY(JoltPhysics/Build EXCLUDE_FROM_ALL) +target_compile_options(Jolt PRIVATE "-fPIC") + +SET( GODOT_CPP_SYSTEM_HEADERS ON CACHE BOOL "" FORCE ) + +ADD_SUBDIRECTORY( godot-cpp EXCLUDE_FROM_ALL) + +SET_TARGET_PROPERTIES( godot-cpp + PROPERTIES + CXX_VISIBILITY_PRESET hidden # visibility needs to be the same as the main library +) diff --git a/3rdparty/RmlUi b/3rdparty/RmlUi deleted file mode 160000 index 40edf1ac..00000000 --- a/3rdparty/RmlUi +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 40edf1acfa7f13f0c9b2af91d6f09ed47aa2c2c9 diff --git a/3rdparty/godot-cpp b/3rdparty/godot-cpp new file mode 160000 index 00000000..98c143a4 --- /dev/null +++ b/3rdparty/godot-cpp @@ -0,0 +1 @@ +Subproject commit 98c143a48365f3f3bf5f99d6289a2cb25e6472d1 diff --git a/3rdparty/newton-dynamics b/3rdparty/newton-dynamics deleted file mode 160000 index d8fb1d92..00000000 --- a/3rdparty/newton-dynamics +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d8fb1d9213a15e914236ceaab39cb187b406f77c diff --git a/CMakeLists.txt b/CMakeLists.txt index 06f4dc94..5986ef7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,9 +43,35 @@ IF(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows" AND NOT CMAKE_SYSTEM_VERSION) SET(CMAKE_SYSTEM_VERSION "10.0.18362.0" CACHE INTERNAL "" FORCE) ENDIF() +#build universally on macOS +if ( APPLE ) + set( CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "" ) +endif() + # Set project name PROJECT(OSP-MAGNUM CXX) +# From: https://crascit.com/2016/04/09/using-ccache-with-cmake/ +find_program( CCACHE_PROGRAM ccache ) + +if ( CCACHE_PROGRAM ) + # get version information + execute_process( + COMMAND "${CCACHE_PROGRAM}" --version + OUTPUT_VARIABLE CCACHE_VERSION + ) + + string( REGEX MATCH "[^\r\n]*" CCACHE_VERSION ${CCACHE_VERSION} ) + + message( STATUS "Using ccache: ${CCACHE_PROGRAM} (${CCACHE_VERSION})" ) + + # Turn on ccache for all targets + set( CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" ) + set( CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" ) + + unset( CCACHE_VERSION ) +endif() + # Setup things for the test subdir below # Has to be in toplevel CMakeLists.txt or ctest gets mad. enable_testing() @@ -56,7 +82,7 @@ OPTION(OSP_ENABLE_COMPILER_WARNINGS "Build with the majority of compiler warning OPTION(OSP_ENABLE_IWYU "Build with warnings from IWYU turned on" OFF) OPTION(OSP_ENABLE_CLANG_TIDY "Build with warnings from clang-tidy turned on" OFF) OPTION(OSP_USE_SYSTEM_SDL "Build with SDL that you provide if turned on, compiles SDL if turned off. Off by default" OFF) - +OPTION(OSP_BUILD_GDEXTENSION "Build the GDExtension for osp instead of the standalone binary" OFF) # If the environment has these set, pull them into proper variables. SET(CLANG_COMPILE_FLAGS ${CLANG_COMPILE_FLAGS}) SET(GCC_COMPILE_FLAGS ${GCC_COMPILE_FLAGS}) @@ -158,9 +184,11 @@ ADD_SUBDIRECTORY(3rdparty) ADD_SUBDIRECTORY(src) # Unit Tests -ADD_SUBDIRECTORY(test) +#ADD_SUBDIRECTORY(test) # Set OSP as default startup project in Visual Studio set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT osp-magnum) # Set execution directory of osp-magnum so that we don't have to copy the files -set_property(TARGET osp-magnum PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin") +if (OSP_BUILD_GDEXTENSION EQUAL OFF) + set_property(TARGET osp-magnum PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin") +endif() \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 71da1fd2..078abedf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ ## # Open Space Program -# Copyright © 2019-2020 Open Space Program Project +# Copyright © 2019-2024 Open Space Program Project # # MIT License # @@ -23,137 +23,18 @@ # SOFTWARE. ## -find_package(Magnum REQUIRED - GL - Shaders - MeshTools - Primitives - #SceneGraph - Trade - Sdl2Application - AnyImageImporter - ) +# TODO put that in the right place. -find_package(MagnumPlugins REQUIRED - TinyGltfImporter - StbImageImporter) -set(THREADS_PREFER_PTHREAD_FLAG TRUE) -find_package(Threads) -if(NOT Threads_FOUND) - message(FATAL_ERROR "Can't find a thread library to use!") -endif() +add_subdirectory(common) -add_library(osp-magnum-deps INTERFACE) -add_custom_target(compile-osp-magnum-deps) +if(OSP_BUILD_GDEXTENSION) -# Include Newton Dynamics to the project +add_subdirectory(gdextension) -# TODO: find a better way to do this. -# Somehow Newton needs some defines for headers to work properly. -# This section was based on Newton Dynamic's CMakeLists.txt -if(UNIX) - if (BUILD_64) - target_compile_definitions(osp-magnum-deps INTERFACE -D_POSIX_VER_64) - else (BUILD_64) - target_compile_definitions(osp-magnum-deps INTERFACE -D_POSIX_VER) - endif (BUILD_64) +else() -elseif(MSVC) - if(WIN32) - if(CMAKE_CL_64) - target_compile_definitions(osp-magnum-deps INTERFACE -D_WIN_64_VER) - else() - target_compile_definitions(osp-magnum-deps INTERFACE -D_WIN_32_VER) - endif() - else() - target_compile_definitions(osp-magnum-deps INTERFACE -D_ARM_VER) - endif() +add_subdirectory(standalone) -elseif(MINGW) - if(CMAKE_CL_64) - target_compile_definitions(osp-magnum-deps INTERFACE -D_MINGW_64_VER) - target_compile_definitions(osp-magnum-deps INTERFACE -D_WIN_64_VER) - else() - target_compile_definitions(osp-magnum-deps INTERFACE -D_MINGW_32_VER) - target_compile_definitions(osp-magnum-deps INTERFACE -D_WIN_32_VER) - endif() endif() -# TODO: This list shouldn't be required, but there appears to be a bug in cmake where -# the add_custom_target() command, pointing to an INTERFACE dependency, doesn't -# result in the dependencies of the interface building. -# See: https://gitlab.kitware.com/cmake/cmake/-/issues/23569 -SET(OSP_MAGNUM_DEPS_LIBS - Threads::Threads - EnTT::EnTT - Corrade::Main - Magnum::Application - Magnum::GL - Magnum::Magnum - Magnum::MeshTools - Magnum::Primitives - #Magnum::SceneGraph - Magnum::Shaders - Magnum::Trade - Magnum::AnyImageImporter - MagnumPlugins::TinyGltfImporter - MagnumPlugins::StbImageImporter - dNewton dScene dModel dVehicle - toml11 - spdlog - longeron - Jolt) -target_link_libraries(osp-magnum-deps INTERFACE ${OSP_MAGNUM_DEPS_LIBS}) -add_dependencies(compile-osp-magnum-deps ${OSP_MAGNUM_DEPS_LIBS}) - -add_executable(osp-magnum) - -target_compile_features(osp-magnum PUBLIC cxx_std_20) - -target_include_directories(osp-magnum PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) - -# Link it to the interface library that describes the dependencies -target_link_libraries(osp-magnum PRIVATE osp-magnum-deps) - -# Gather paths to OSP headers and sources -file(GLOB_RECURSE CPP_FILES CONFIGURE_DEPENDS *.cpp) -file(GLOB_RECURSE H_FILES CONFIGURE_DEPENDS *.h) -target_sources(osp-magnum PRIVATE "${CPP_FILES}" "${H_FILES}") - -# Add shaders to IDE project -set(SHADERS_DIR "../bin/OSPData/adera/Shaders") -file (GLOB_RECURSE SHADER_FILES CONFIGURE_DEPENDS - "${SHADERS_DIR}/*.vert" - "${SHADERS_DIR}/*.frag" - "${SHADERS_DIR}/*.comp" -) -# For some reason, source_group() requires all files to be added to the executable -target_sources(osp-magnum PRIVATE "${SHADER_FILES}") - -# Segregate headers, shaders into filters -source_group("Shader Files" FILES ${SHADER_FILES}) -source_group("Header Files" FILES ${H_FILES}) - -# Enforce conformance mode for osp-magnum -target_compile_options(osp-magnum PRIVATE $<$:/permissive->) - -set_target_properties(osp-magnum PROPERTIES - EXPORT_COMPILE_COMMANDS TRUE - INSTALL_RPATH "$ORIGIN/lib" - C_EXTENSIONS OFF - C_STANDARD_REQUIRED ON - CXX_EXTENSIONS OFF - CXX_STANDARD_REQUIRED ON -) - -# Copy root/bin to build/bin after building -add_custom_command(TARGET osp-magnum - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/../bin" "${CMAKE_BINARY_DIR}/$" - VERBATIM -) - -add_custom_target(run-osp-magnum - COMMAND $ - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/$) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt new file mode 100644 index 00000000..516baeaa --- /dev/null +++ b/src/common/CMakeLists.txt @@ -0,0 +1,92 @@ +## +# Open Space Program +# Copyright © 2019-2024 Open Space Program Project +# +# MIT License +# +# 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. +## +set(THREADS_PREFER_PTHREAD_FLAG TRUE) +find_package(Threads) +if(NOT Threads_FOUND) + message(FATAL_ERROR "Can't find a thread library to use!") +endif() + +find_package(Magnum REQUIRED + MeshTools + Trade + AnyImageImporter + ) + +find_package(MagnumPlugins REQUIRED + TinyGltfImporter + StbImageImporter) + +add_library(osp-common-deps INTERFACE) +add_custom_target(compile-osp-common-deps) + +# TODO: This list shouldn't be required, but there appears to be a bug in cmake where +# the add_custom_target() command, pointing to an INTERFACE dependency, doesn't +# result in the dependencies of the interface building. +# See: https://gitlab.kitware.com/cmake/cmake/-/issues/23569 +SET(OSP_COMMON_DEPS_LIBS + Threads::Threads + EnTT::EnTT + Corrade::Main + Magnum::Magnum + Magnum::Trade + Magnum::AnyImageImporter + MagnumPlugins::TinyGltfImporter + MagnumPlugins::StbImageImporter + toml11 + spdlog + longeron + Jolt) +target_link_libraries(osp-common-deps INTERFACE ${OSP_COMMON_DEPS_LIBS}) +add_dependencies(compile-osp-common-deps ${OSP_COMMON_DEPS_LIBS}) + +add_library(osp-common STATIC) + +target_compile_options(osp-common PRIVATE "-fPIC") +target_compile_features(osp-common PUBLIC cxx_std_20) + +target_include_directories(osp-common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +# Link it to the interface library that describes the dependencies +target_link_libraries(osp-common PUBLIC osp-common-deps) + +# Gather paths to OSP headers and sources +file(GLOB_RECURSE CPP_FILES CONFIGURE_DEPENDS *.cpp) +file(GLOB_RECURSE H_FILES CONFIGURE_DEPENDS *.h) +target_sources(osp-common PRIVATE "${CPP_FILES}" "${H_FILES}") + +# Segregate headers into filters +source_group("Header Files" FILES ${H_FILES}) + +# Enforce conformance mode for osp-common +target_compile_options(osp-common PRIVATE $<$:/permissive->) + +set_target_properties(osp-common PROPERTIES + EXPORT_COMPILE_COMMANDS TRUE + INSTALL_RPATH "$ORIGIN/lib" + C_EXTENSIONS OFF + C_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF + CXX_STANDARD_REQUIRED ON +) diff --git a/src/adera/Plume.h b/src/common/adera/Plume.h similarity index 100% rename from src/adera/Plume.h rename to src/common/adera/Plume.h diff --git a/src/adera/ShipResources.h b/src/common/adera/ShipResources.h similarity index 100% rename from src/adera/ShipResources.h rename to src/common/adera/ShipResources.h diff --git a/src/adera/SysExhaustPlume.cpp b/src/common/adera/SysExhaustPlume.cpp similarity index 100% rename from src/adera/SysExhaustPlume.cpp rename to src/common/adera/SysExhaustPlume.cpp diff --git a/src/adera/SysExhaustPlume.h b/src/common/adera/SysExhaustPlume.h similarity index 100% rename from src/adera/SysExhaustPlume.h rename to src/common/adera/SysExhaustPlume.h diff --git a/src/adera/activescene/VehicleBuilder.cpp b/src/common/adera/activescene/VehicleBuilder.cpp similarity index 100% rename from src/adera/activescene/VehicleBuilder.cpp rename to src/common/adera/activescene/VehicleBuilder.cpp diff --git a/src/adera/activescene/VehicleBuilder.h b/src/common/adera/activescene/VehicleBuilder.h similarity index 100% rename from src/adera/activescene/VehicleBuilder.h rename to src/common/adera/activescene/VehicleBuilder.h diff --git a/src/adera/activescene/vehicles_vb_fn.cpp b/src/common/adera/activescene/vehicles_vb_fn.cpp similarity index 100% rename from src/adera/activescene/vehicles_vb_fn.cpp rename to src/common/adera/activescene/vehicles_vb_fn.cpp diff --git a/src/adera/activescene/vehicles_vb_fn.h b/src/common/adera/activescene/vehicles_vb_fn.h similarity index 100% rename from src/adera/activescene/vehicles_vb_fn.h rename to src/common/adera/activescene/vehicles_vb_fn.h diff --git a/src/adera/drawing/CameraController.cpp b/src/common/adera/drawing/CameraController.cpp similarity index 100% rename from src/adera/drawing/CameraController.cpp rename to src/common/adera/drawing/CameraController.cpp diff --git a/src/adera/drawing/CameraController.h b/src/common/adera/drawing/CameraController.h similarity index 100% rename from src/adera/drawing/CameraController.h rename to src/common/adera/drawing/CameraController.h diff --git a/src/adera/machines/links.cpp b/src/common/adera/machines/links.cpp similarity index 100% rename from src/adera/machines/links.cpp rename to src/common/adera/machines/links.cpp diff --git a/src/adera/machines/links.h b/src/common/adera/machines/links.h similarity index 100% rename from src/adera/machines/links.h rename to src/common/adera/machines/links.h diff --git a/src/osp/activescene/active_ent.h b/src/common/osp/activescene/active_ent.h similarity index 100% rename from src/osp/activescene/active_ent.h rename to src/common/osp/activescene/active_ent.h diff --git a/src/osp/activescene/basic.h b/src/common/osp/activescene/basic.h similarity index 100% rename from src/osp/activescene/basic.h rename to src/common/osp/activescene/basic.h diff --git a/src/osp/activescene/basic_fn.cpp b/src/common/osp/activescene/basic_fn.cpp similarity index 100% rename from src/osp/activescene/basic_fn.cpp rename to src/common/osp/activescene/basic_fn.cpp diff --git a/src/osp/activescene/basic_fn.h b/src/common/osp/activescene/basic_fn.h similarity index 100% rename from src/osp/activescene/basic_fn.h rename to src/common/osp/activescene/basic_fn.h diff --git a/src/osp/activescene/physics.h b/src/common/osp/activescene/physics.h similarity index 100% rename from src/osp/activescene/physics.h rename to src/common/osp/activescene/physics.h diff --git a/src/osp/activescene/physics_fn.cpp b/src/common/osp/activescene/physics_fn.cpp similarity index 100% rename from src/osp/activescene/physics_fn.cpp rename to src/common/osp/activescene/physics_fn.cpp diff --git a/src/osp/activescene/physics_fn.h b/src/common/osp/activescene/physics_fn.h similarity index 100% rename from src/osp/activescene/physics_fn.h rename to src/common/osp/activescene/physics_fn.h diff --git a/src/osp/activescene/prefab_fn.cpp b/src/common/osp/activescene/prefab_fn.cpp similarity index 100% rename from src/osp/activescene/prefab_fn.cpp rename to src/common/osp/activescene/prefab_fn.cpp diff --git a/src/osp/activescene/prefab_fn.h b/src/common/osp/activescene/prefab_fn.h similarity index 100% rename from src/osp/activescene/prefab_fn.h rename to src/common/osp/activescene/prefab_fn.h diff --git a/src/osp/activescene/vehicles.h b/src/common/osp/activescene/vehicles.h similarity index 100% rename from src/osp/activescene/vehicles.h rename to src/common/osp/activescene/vehicles.h diff --git a/src/osp/core/Resources.cpp b/src/common/osp/core/Resources.cpp similarity index 100% rename from src/osp/core/Resources.cpp rename to src/common/osp/core/Resources.cpp diff --git a/src/osp/core/Resources.h b/src/common/osp/core/Resources.h similarity index 100% rename from src/osp/core/Resources.h rename to src/common/osp/core/Resources.h diff --git a/src/osp/core/array_view.h b/src/common/osp/core/array_view.h similarity index 100% rename from src/osp/core/array_view.h rename to src/common/osp/core/array_view.h diff --git a/src/osp/core/bitvector.h b/src/common/osp/core/bitvector.h similarity index 100% rename from src/osp/core/bitvector.h rename to src/common/osp/core/bitvector.h diff --git a/src/osp/core/copymove_macros.h b/src/common/osp/core/copymove_macros.h similarity index 100% rename from src/osp/core/copymove_macros.h rename to src/common/osp/core/copymove_macros.h diff --git a/src/osp/core/global_id.h b/src/common/osp/core/global_id.h similarity index 100% rename from src/osp/core/global_id.h rename to src/common/osp/core/global_id.h diff --git a/src/osp/core/id_map.h b/src/common/osp/core/id_map.h similarity index 100% rename from src/osp/core/id_map.h rename to src/common/osp/core/id_map.h diff --git a/src/osp/core/id_utils.h b/src/common/osp/core/id_utils.h similarity index 100% rename from src/osp/core/id_utils.h rename to src/common/osp/core/id_utils.h diff --git a/src/osp/core/keyed_vector.h b/src/common/osp/core/keyed_vector.h similarity index 100% rename from src/osp/core/keyed_vector.h rename to src/common/osp/core/keyed_vector.h diff --git a/src/osp/core/math_2pow.h b/src/common/osp/core/math_2pow.h similarity index 100% rename from src/osp/core/math_2pow.h rename to src/common/osp/core/math_2pow.h diff --git a/src/osp/core/math_int64.h b/src/common/osp/core/math_int64.h similarity index 100% rename from src/osp/core/math_int64.h rename to src/common/osp/core/math_int64.h diff --git a/src/osp/core/math_types.h b/src/common/osp/core/math_types.h similarity index 100% rename from src/osp/core/math_types.h rename to src/common/osp/core/math_types.h diff --git a/src/osp/core/resourcetypes.h b/src/common/osp/core/resourcetypes.h similarity index 100% rename from src/osp/core/resourcetypes.h rename to src/common/osp/core/resourcetypes.h diff --git a/src/osp/core/shared_string.h b/src/common/osp/core/shared_string.h similarity index 100% rename from src/osp/core/shared_string.h rename to src/common/osp/core/shared_string.h diff --git a/src/osp/core/storage.h b/src/common/osp/core/storage.h similarity index 100% rename from src/osp/core/storage.h rename to src/common/osp/core/storage.h diff --git a/src/osp/core/string_concat.h b/src/common/osp/core/string_concat.h similarity index 100% rename from src/osp/core/string_concat.h rename to src/common/osp/core/string_concat.h diff --git a/src/osp/core/strong_id.h b/src/common/osp/core/strong_id.h similarity index 100% rename from src/osp/core/strong_id.h rename to src/common/osp/core/strong_id.h diff --git a/src/osp/core/unpack.h b/src/common/osp/core/unpack.h similarity index 100% rename from src/osp/core/unpack.h rename to src/common/osp/core/unpack.h diff --git a/src/osp/drawing/draw_ent.h b/src/common/osp/drawing/draw_ent.h similarity index 100% rename from src/osp/drawing/draw_ent.h rename to src/common/osp/drawing/draw_ent.h diff --git a/src/osp/drawing/drawing.h b/src/common/osp/drawing/drawing.h similarity index 100% rename from src/osp/drawing/drawing.h rename to src/common/osp/drawing/drawing.h diff --git a/src/osp/drawing/drawing_fn.cpp b/src/common/osp/drawing/drawing_fn.cpp similarity index 100% rename from src/osp/drawing/drawing_fn.cpp rename to src/common/osp/drawing/drawing_fn.cpp diff --git a/src/osp/drawing/drawing_fn.h b/src/common/osp/drawing/drawing_fn.h similarity index 100% rename from src/osp/drawing/drawing_fn.h rename to src/common/osp/drawing/drawing_fn.h diff --git a/src/osp/drawing/own_restypes.h b/src/common/osp/drawing/own_restypes.h similarity index 100% rename from src/osp/drawing/own_restypes.h rename to src/common/osp/drawing/own_restypes.h diff --git a/src/osp/drawing/prefab_draw.cpp b/src/common/osp/drawing/prefab_draw.cpp similarity index 100% rename from src/osp/drawing/prefab_draw.cpp rename to src/common/osp/drawing/prefab_draw.cpp diff --git a/src/osp/drawing/prefab_draw.h b/src/common/osp/drawing/prefab_draw.h similarity index 100% rename from src/osp/drawing/prefab_draw.h rename to src/common/osp/drawing/prefab_draw.h diff --git a/src/osp/link/machines.cpp b/src/common/osp/link/machines.cpp similarity index 100% rename from src/osp/link/machines.cpp rename to src/common/osp/link/machines.cpp diff --git a/src/osp/link/machines.h b/src/common/osp/link/machines.h similarity index 100% rename from src/osp/link/machines.h rename to src/common/osp/link/machines.h diff --git a/src/osp/link/signal.h b/src/common/osp/link/signal.h similarity index 100% rename from src/osp/link/signal.h rename to src/common/osp/link/signal.h diff --git a/src/osp/scientific/constants.h b/src/common/osp/scientific/constants.h similarity index 100% rename from src/osp/scientific/constants.h rename to src/common/osp/scientific/constants.h diff --git a/src/osp/scientific/shapes.cpp b/src/common/osp/scientific/shapes.cpp similarity index 100% rename from src/osp/scientific/shapes.cpp rename to src/common/osp/scientific/shapes.cpp diff --git a/src/osp/scientific/shapes.h b/src/common/osp/scientific/shapes.h similarity index 100% rename from src/osp/scientific/shapes.h rename to src/common/osp/scientific/shapes.h diff --git a/src/osp/tasks/builder.h b/src/common/osp/tasks/builder.h similarity index 100% rename from src/osp/tasks/builder.h rename to src/common/osp/tasks/builder.h diff --git a/src/osp/tasks/execute.cpp b/src/common/osp/tasks/execute.cpp similarity index 100% rename from src/osp/tasks/execute.cpp rename to src/common/osp/tasks/execute.cpp diff --git a/src/osp/tasks/execute.h b/src/common/osp/tasks/execute.h similarity index 100% rename from src/osp/tasks/execute.h rename to src/common/osp/tasks/execute.h diff --git a/src/osp/tasks/tasks.cpp b/src/common/osp/tasks/tasks.cpp similarity index 100% rename from src/osp/tasks/tasks.cpp rename to src/common/osp/tasks/tasks.cpp diff --git a/src/osp/tasks/tasks.h b/src/common/osp/tasks/tasks.h similarity index 100% rename from src/osp/tasks/tasks.h rename to src/common/osp/tasks/tasks.h diff --git a/src/osp/tasks/top_execute.cpp b/src/common/osp/tasks/top_execute.cpp similarity index 100% rename from src/osp/tasks/top_execute.cpp rename to src/common/osp/tasks/top_execute.cpp diff --git a/src/osp/tasks/top_execute.h b/src/common/osp/tasks/top_execute.h similarity index 100% rename from src/osp/tasks/top_execute.h rename to src/common/osp/tasks/top_execute.h diff --git a/src/osp/tasks/top_session.h b/src/common/osp/tasks/top_session.h similarity index 100% rename from src/osp/tasks/top_session.h rename to src/common/osp/tasks/top_session.h diff --git a/src/osp/tasks/top_tasks.h b/src/common/osp/tasks/top_tasks.h similarity index 100% rename from src/osp/tasks/top_tasks.h rename to src/common/osp/tasks/top_tasks.h diff --git a/src/osp/tasks/top_utils.h b/src/common/osp/tasks/top_utils.h similarity index 100% rename from src/osp/tasks/top_utils.h rename to src/common/osp/tasks/top_utils.h diff --git a/src/osp/tasks/top_worker.h b/src/common/osp/tasks/top_worker.h similarity index 100% rename from src/osp/tasks/top_worker.h rename to src/common/osp/tasks/top_worker.h diff --git a/src/osp/tasks/worker.h b/src/common/osp/tasks/worker.h similarity index 100% rename from src/osp/tasks/worker.h rename to src/common/osp/tasks/worker.h diff --git a/src/osp/universe/coordinates.h b/src/common/osp/universe/coordinates.h similarity index 100% rename from src/osp/universe/coordinates.h rename to src/common/osp/universe/coordinates.h diff --git a/src/osp/universe/universe.h b/src/common/osp/universe/universe.h similarity index 100% rename from src/osp/universe/universe.h rename to src/common/osp/universe/universe.h diff --git a/src/osp/universe/universetypes.h b/src/common/osp/universe/universetypes.h similarity index 100% rename from src/osp/universe/universetypes.h rename to src/common/osp/universe/universetypes.h diff --git a/src/osp/util/UserInputHandler.cpp b/src/common/osp/util/UserInputHandler.cpp similarity index 100% rename from src/osp/util/UserInputHandler.cpp rename to src/common/osp/util/UserInputHandler.cpp diff --git a/src/osp/util/UserInputHandler.h b/src/common/osp/util/UserInputHandler.h similarity index 100% rename from src/osp/util/UserInputHandler.h rename to src/common/osp/util/UserInputHandler.h diff --git a/src/osp/util/logging.h b/src/common/osp/util/logging.h similarity index 100% rename from src/osp/util/logging.h rename to src/common/osp/util/logging.h diff --git a/src/osp/vehicles/ImporterData.h b/src/common/osp/vehicles/ImporterData.h similarity index 100% rename from src/osp/vehicles/ImporterData.h rename to src/common/osp/vehicles/ImporterData.h diff --git a/src/osp/vehicles/blueprints.h b/src/common/osp/vehicles/blueprints.h similarity index 100% rename from src/osp/vehicles/blueprints.h rename to src/common/osp/vehicles/blueprints.h diff --git a/src/osp/vehicles/load_tinygltf.cpp b/src/common/osp/vehicles/load_tinygltf.cpp similarity index 100% rename from src/osp/vehicles/load_tinygltf.cpp rename to src/common/osp/vehicles/load_tinygltf.cpp diff --git a/src/osp/vehicles/load_tinygltf.h b/src/common/osp/vehicles/load_tinygltf.h similarity index 100% rename from src/osp/vehicles/load_tinygltf.h rename to src/common/osp/vehicles/load_tinygltf.h diff --git a/src/osp/vehicles/prefabs.h b/src/common/osp/vehicles/prefabs.h similarity index 100% rename from src/osp/vehicles/prefabs.h rename to src/common/osp/vehicles/prefabs.h diff --git a/src/ospjolt/activescene/forcefactors.h b/src/common/ospjolt/activescene/forcefactors.h similarity index 100% rename from src/ospjolt/activescene/forcefactors.h rename to src/common/ospjolt/activescene/forcefactors.h diff --git a/src/ospjolt/activescene/joltinteg.h b/src/common/ospjolt/activescene/joltinteg.h similarity index 99% rename from src/ospjolt/activescene/joltinteg.h rename to src/common/ospjolt/activescene/joltinteg.h index 54be7724..a4540077 100644 --- a/src/ospjolt/activescene/joltinteg.h +++ b/src/common/ospjolt/activescene/joltinteg.h @@ -283,7 +283,7 @@ struct ACtxJoltWorld //Should this be called on world creation ? not ideal in case of multiple worlds. static void initJoltGlobal() { - std::call_once(ACtxJoltWorld::initFlag, ACtxJoltWorld::initJoltGlobalInternal); + ACtxJoltWorld::initJoltGlobalInternal(); } @@ -314,7 +314,6 @@ struct ACtxJoltWorld static void initJoltGlobalInternal() { - RegisterDefaultAllocator(); // Install trace and assert callbacks diff --git a/src/ospjolt/activescene/joltinteg_fn.cpp b/src/common/ospjolt/activescene/joltinteg_fn.cpp similarity index 100% rename from src/ospjolt/activescene/joltinteg_fn.cpp rename to src/common/ospjolt/activescene/joltinteg_fn.cpp diff --git a/src/ospjolt/activescene/joltinteg_fn.h b/src/common/ospjolt/activescene/joltinteg_fn.h similarity index 100% rename from src/ospjolt/activescene/joltinteg_fn.h rename to src/common/ospjolt/activescene/joltinteg_fn.h diff --git a/src/planet-a/chunk_generate.cpp b/src/common/planet-a/chunk_generate.cpp similarity index 100% rename from src/planet-a/chunk_generate.cpp rename to src/common/planet-a/chunk_generate.cpp diff --git a/src/planet-a/chunk_generate.h b/src/common/planet-a/chunk_generate.h similarity index 100% rename from src/planet-a/chunk_generate.h rename to src/common/planet-a/chunk_generate.h diff --git a/src/planet-a/chunk_utils.cpp b/src/common/planet-a/chunk_utils.cpp similarity index 100% rename from src/planet-a/chunk_utils.cpp rename to src/common/planet-a/chunk_utils.cpp diff --git a/src/planet-a/chunk_utils.h b/src/common/planet-a/chunk_utils.h similarity index 100% rename from src/planet-a/chunk_utils.h rename to src/common/planet-a/chunk_utils.h diff --git a/src/planet-a/geometry.cpp b/src/common/planet-a/geometry.cpp similarity index 100% rename from src/planet-a/geometry.cpp rename to src/common/planet-a/geometry.cpp diff --git a/src/planet-a/geometry.h b/src/common/planet-a/geometry.h similarity index 100% rename from src/planet-a/geometry.h rename to src/common/planet-a/geometry.h diff --git a/src/planet-a/icosahedron.cpp b/src/common/planet-a/icosahedron.cpp similarity index 100% rename from src/planet-a/icosahedron.cpp rename to src/common/planet-a/icosahedron.cpp diff --git a/src/planet-a/icosahedron.h b/src/common/planet-a/icosahedron.h similarity index 100% rename from src/planet-a/icosahedron.h rename to src/common/planet-a/icosahedron.h diff --git a/src/planet-a/planeta_types.h b/src/common/planet-a/planeta_types.h similarity index 100% rename from src/planet-a/planeta_types.h rename to src/common/planet-a/planeta_types.h diff --git a/src/planet-a/skeleton.cpp b/src/common/planet-a/skeleton.cpp similarity index 100% rename from src/planet-a/skeleton.cpp rename to src/common/planet-a/skeleton.cpp diff --git a/src/planet-a/skeleton.h b/src/common/planet-a/skeleton.h similarity index 100% rename from src/planet-a/skeleton.h rename to src/common/planet-a/skeleton.h diff --git a/src/planet-a/skeleton_subdiv.cpp b/src/common/planet-a/skeleton_subdiv.cpp similarity index 100% rename from src/planet-a/skeleton_subdiv.cpp rename to src/common/planet-a/skeleton_subdiv.cpp diff --git a/src/planet-a/skeleton_subdiv.h b/src/common/planet-a/skeleton_subdiv.h similarity index 100% rename from src/planet-a/skeleton_subdiv.h rename to src/common/planet-a/skeleton_subdiv.h diff --git a/src/planet-a/subdiv_id_registry.h b/src/common/planet-a/subdiv_id_registry.h similarity index 100% rename from src/planet-a/subdiv_id_registry.h rename to src/common/planet-a/subdiv_id_registry.h diff --git a/src/gdextension/CMakeLists.txt b/src/gdextension/CMakeLists.txt new file mode 100644 index 00000000..fc223a7b --- /dev/null +++ b/src/gdextension/CMakeLists.txt @@ -0,0 +1,80 @@ +## +# Open Space Program +# Copyright © 2024-2025 Open Space Program Project +# +# MIT License +# +# 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. +## + +ADD_LIBRARY( osp-gdextension SHARED) + +set( LIB_ARCH ${CMAKE_SYSTEM_PROCESSOR} ) +if ( APPLE ) + set( LIB_ARCH "universal" ) +endif() + +set( LIB_DIR "lib/${CMAKE_SYSTEM_NAME}-${LIB_ARCH}" ) +set( BUILD_OUTPUT_DIR "${CMAKE_BINARY_DIR}/$/" ) + +set_target_properties( osp-gdextension + PROPERTIES + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN true + RUNTIME_OUTPUT_DIRECTORY "${BUILD_OUTPUT_DIR}/${LIB_DIR}" + LIBRARY_OUTPUT_DIRECTORY "${BUILD_OUTPUT_DIR}/${LIB_DIR}" +) + + +# Copy over additional files from the support_files directory +add_custom_command( + TARGET osp-gdextension POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_CURRENT_SOURCE_DIR}/support_files" + ${BUILD_OUTPUT_DIR} +) + +file(GLOB_RECURSE CPP_FILES CONFIGURE_DEPENDS *.cpp) +file(GLOB_RECURSE H_FILES CONFIGURE_DEPENDS *.h) +target_sources(osp-gdextension PRIVATE "${CPP_FILES}" "${H_FILES}") + +target_include_directories(osp-gdextension PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries(osp-gdextension PRIVATE godot-cpp osp-common) + +target_compile_options(osp-gdextension PRIVATE "-static") + + +# Install library, extension file, and support files in ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME} +set( INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/osp-gdextension/" ) + +add_subdirectory( templates ) + +install( TARGETS osp-gdextension +LIBRARY +DESTINATION ${INSTALL_DIR}/${LIB_DIR} +RUNTIME +DESTINATION ${INSTALL_DIR}/${LIB_DIR} +) + +# Copy over support files +install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/support_files/" +DESTINATION ${INSTALL_DIR} +PATTERN ".*" EXCLUDE +) \ No newline at end of file diff --git a/src/gdextension/Example.cpp b/src/gdextension/Example.cpp new file mode 100644 index 00000000..fb302100 --- /dev/null +++ b/src/gdextension/Example.cpp @@ -0,0 +1,848 @@ +// Copied from godot-cpp/test/src and modified. + +#include "godot_cpp/classes/global_constants.hpp" +#include "godot_cpp/classes/label.hpp" +#include "godot_cpp/core/class_db.hpp" +#include "godot_cpp/variant/utility_functions.hpp" +#include "ospjolt/activescene/joltinteg.h" + +#include "Example.h" + +// Used to mark unused parameters to indicate intent and suppress warnings. +#define UNUSED( expr ) (void)( expr ) + +namespace +{ + constexpr int MAGIC_NUMBER = 42; + + class MyCallableCustom : public godot::CallableCustom + { + public: + virtual uint32_t hash() const + { + return 27; + } + + virtual godot::String get_as_text() const + { + return ""; + } + + static bool compare_equal_func( const CallableCustom *inA, const CallableCustom *inB ) + { + return inA == inB; + } + + virtual CompareEqualFunc get_compare_equal_func() const + { + return &MyCallableCustom::compare_equal_func; + } + + static bool compare_less_func( const CallableCustom *inA, const CallableCustom *inB ) + { + return reinterpret_cast( inA ) < reinterpret_cast( inB ); + } + + virtual CompareLessFunc get_compare_less_func() const + { + return &MyCallableCustom::compare_less_func; + } + + bool is_valid() const + { + return true; + } + + virtual godot::ObjectID get_object() const + { + return godot::ObjectID(); + } + + virtual void call( const godot::Variant **inArguments, int inArgcount, + godot::Variant &outReturnValue, + GDExtensionCallError &outCallError ) const + { + UNUSED( inArguments ); + UNUSED( inArgcount ); + + outReturnValue = "Hi"; + outCallError.error = GDEXTENSION_CALL_OK; + } + }; +} + +//// ExampleRef + +int ExampleRef::sInstanceCount = 0; +int ExampleRef::sLastID = 0; + +ExampleRef::ExampleRef() +{ + mID = ++sLastID; + sInstanceCount++; + + godot::UtilityFunctions::print( + "ExampleRef ", godot::itos( mID ), + " created, current instance count: ", godot::itos( sInstanceCount ) ); +} + +ExampleRef::~ExampleRef() +{ + sInstanceCount--; + godot::UtilityFunctions::print( + "ExampleRef ", godot::itos( mID ), + " destroyed, current instance count: ", godot::itos( sInstanceCount ) ); +} + +void ExampleRef::setId( int inID ) +{ + mID = inID; +} + +int ExampleRef::getID() const +{ + return mID; +} + +void ExampleRef::_bind_methods() +{ + godot::ClassDB::bind_method( godot::D_METHOD( "set_id", "id" ), &ExampleRef::setId ); + godot::ClassDB::bind_method( godot::D_METHOD( "get_id" ), &ExampleRef::getID ); + + godot::ClassDB::bind_method( godot::D_METHOD( "was_post_initialized" ), + &ExampleRef::wasPostInitialized ); +} + +void ExampleRef::_notification( int inWhat ) +{ + if ( inWhat == NOTIFICATION_POSTINITIALIZE ) + { + mPostInitialized = true; + } +} + +//// ExampleMin + +void ExampleMin::_bind_methods() +{ +} + +//// Example + +Example::Example() +{ + godot::UtilityFunctions::print( "Constructor." ); + ospjolt::ACtxJoltWorld::initJoltGlobal(); + auto world = ospjolt::ACtxJoltWorld(); +} + +Example::~Example() +{ + godot::UtilityFunctions::print( "Destructor." ); +} + +// Methods. +void Example::simpleFunc() +{ + godot::UtilityFunctions::print( " Simple func called." ); +} + +void Example::simpleConstFunc() const +{ + godot::UtilityFunctions::print( " Simple const func called." ); +} + +godot::String Example::returnSomething( const godot::String &inBase ) +{ + godot::UtilityFunctions::print( " Return something called." ); + + return inBase; +} + +godot::Viewport *Example::returnSomethingConst() const +{ + godot::UtilityFunctions::print( " Return something const called." ); + + if ( is_inside_tree() ) + { + godot::Viewport *result = get_viewport(); + + return result; + } + + return nullptr; +} + +godot::Ref Example::returnEmptyRef() const +{ + godot::Ref ref; + return ref; +} + +ExampleRef *Example::returnExtendedRef() const +{ + // You can instance and return a refcounted object like this, but keep in mind that refcounting + // starts with the returned object and it will be destroyed when all references are destroyed. + // If you store this pointer you run the risk of having a pointer to a destroyed object. + return memnew( ExampleRef() ); +} + +godot::Ref Example::extendedRefChecks( godot::Ref inRef ) const +{ + // This is the preferred way of instancing and returning a refcounted object: + godot::Ref ref; + ref.instantiate(); + + godot::UtilityFunctions::print( + " Example ref checks called with value: ", inRef->get_instance_id(), + ", returning value: ", ref->get_instance_id() ); + + return ref; +} + +godot::Variant Example::varargsFunc( const godot::Variant **inArgs, GDExtensionInt inArgCount, + GDExtensionCallError &outError ) +{ + UNUSED( inArgs ); + UNUSED( outError ); + + godot::UtilityFunctions::print( " Varargs (Variant return) called with ", + godot::String::num_int64( inArgCount ), " arguments" ); + + return inArgCount; +} + +int Example::varargsFuncNonVoidReturn( const godot::Variant **inArgs, GDExtensionInt inArgCount, + GDExtensionCallError &outError ) +{ + UNUSED( inArgs ); + UNUSED( outError ); + + godot::UtilityFunctions::print( " Varargs (int return) called with ", + godot::String::num_int64( inArgCount ), " arguments" ); + + return MAGIC_NUMBER; +} + +void Example::varargsFuncVoidReturn( const godot::Variant **inArgs, GDExtensionInt inArgCount, + GDExtensionCallError &outError ) +{ + UNUSED( inArgs ); + UNUSED( outError ); + + godot::UtilityFunctions::print( " Varargs (no return) called with ", + godot::String::num_int64( inArgCount ), " arguments" ); +} + +void Example::emitCustomSignal( const godot::String &inName, int inValue ) +{ + emit_signal( "custom_signal", inName, inValue ); +} + +int Example::defArgs( int inA, int inB ) const +{ + return inA + inB; +} + +godot::Array Example::testArray() const +{ + godot::Array arr; + + arr.resize( 2 ); + arr[0] = godot::Variant( 1 ); + arr[1] = godot::Variant( 2 ); + + return arr; +} + +void Example::testTypedArrayArg( const godot::TypedArray &inArray ) +{ + for ( int i = 0; i < inArray.size(); ++i ) + { + godot::UtilityFunctions::print( inArray[i] ); + } +} + +godot::TypedArray Example::testTypedArray() const +{ + godot::TypedArray arr; + + arr.resize( 2 ); + arr[0] = godot::Vector2( 1, 2 ); + arr[1] = godot::Vector2( 2, 3 ); + + return arr; +} + +godot::Dictionary Example::testDictionary() const +{ + godot::Dictionary dict; + + dict["hello"] = "world"; + dict["foo"] = "bar"; + + return dict; +} + +Example *Example::testNodeArgument( Example *inNode ) const +{ + // This should use godot::String::num_uint64(), but it is currently broken: + // https://github.com/godotengine/godot-cpp/issues/1014 + godot::UtilityFunctions::print( + " Test node argument called with ", + ( inNode != nullptr ) + ? godot::String::num_int64( static_cast( inNode->get_instance_id() ) ) + : "null" ); + return inNode; +} + +godot::String Example::testStringOps() const +{ + godot::String s = godot::String( "A" ); + s += "B"; + s += "C"; + s += char32_t( 0x010E ); + s = s + "E"; + + return s; +} + +godot::String Example::testStrUtility() const +{ + return godot::UtilityFunctions::str( "Hello, ", "World", "! The answer is ", 42 ); +} + +bool Example::testStringIsFortyTwo( const godot::String &inString ) const +{ + return strcmp( inString.utf8().ptr(), "forty two" ) == 0; +} + +godot::String Example::testStringResize( godot::String ioString ) const +{ + int64_t orig_len = ioString.length(); + + // This cast is to fix an issue with the API. + // See: https://github.com/godotengine/godot-cpp/issues/1338 + ioString.resize( static_cast( orig_len ) + 3 ); + + char32_t *data = ioString.ptrw(); + data[orig_len + 0] = '!'; + data[orig_len + 1] = '?'; + data[orig_len + 2] = '\0'; + + return ioString; +} + +int Example::testVectorOps() const +{ + godot::PackedInt32Array arr; + arr.push_back( 10 ); + arr.push_back( 20 ); + arr.push_back( 30 ); + arr.push_back( 45 ); + + int ret = 0; + for ( const int32_t &E : arr ) + { + ret += E; + } + + return ret; +} + +bool Example::testObjectCastToNode( godot::Object *inObject ) const +{ + return godot::Object::cast_to( inObject ) != nullptr; +} + +bool Example::testObjectCastToControl( godot::Object *inObject ) const +{ + return godot::Object::cast_to( inObject ) != nullptr; +} + +bool Example::testObjectCastToExample( godot::Object *inObject ) const +{ + return godot::Object::cast_to( inObject ) != nullptr; +} + +godot::Vector2i Example::testVariantVector2iConversion( const godot::Variant &inVariant ) const +{ + return inVariant; +} + +int Example::testVariantIntConversion( const godot::Variant &inVariant ) const +{ + return inVariant; +} + +float Example::testVariantFloatConversion( const godot::Variant &inVariant ) const +{ + return inVariant; +} + +godot::Variant Example::testVariantCall( godot::Variant inVariant ) +{ + return inVariant.call( "test", "hello" ); +} + +godot::Variant Example::testVariantIterator( const godot::Variant &inVariant ) +{ + godot::Array output; + godot::Variant iter; + + bool is_init_valid = true; + + if ( !inVariant.iter_init( iter, is_init_valid ) ) + { + if ( !is_init_valid ) + { + return "iter_init: not valid"; + } + + return output; + } + + bool is_iter_next_valid = true; + bool is_iter_get_valid = true; + + do + { + if ( !is_iter_next_valid ) + { + return "iter_next: not valid"; + } + + godot::Variant value = inVariant.iter_get( iter, is_iter_get_valid ); + + if ( !is_iter_get_valid ) + { + return "iter_get: not valid"; + } + + output.push_back( ( static_cast( value ) ) + 5 ); + + } while ( inVariant.iter_next( iter, is_iter_next_valid ) ); + + if ( !is_iter_next_valid ) + { + return "iter_next: not valid"; + } + + return output; +} + +void Example::testAddChild( godot::Node *inNode ) +{ + add_child( inNode ); +} + +void Example::testSetTileset( godot::TileMap *inTilemap, + const godot::Ref &inTileset ) const +{ + inTilemap->set_tileset( inTileset ); +} + +godot::Callable Example::testCallableMP() +{ + return callable_mp( this, &Example::unboundMethod1 ); +} + +godot::Callable Example::testCallableMPRet() +{ + return callable_mp( this, &Example::unboundMethod2 ); +} + +godot::Callable Example::testCallableMPRetC() const +{ + return callable_mp( this, &Example::unboundMethod3 ); +} + +godot::Callable Example::testCallableMPStatic() const +{ + return callable_mp_static( &Example::unboundStaticMethod1 ); +} + +godot::Callable Example::testCallableMPStaticRet() const +{ + return callable_mp_static( &Example::unboundStaticMethod2 ); +} + +godot::Callable Example::testCustomCallable() const +{ + return godot::Callable( memnew( MyCallableCustom ) ); +} + +void Example::callableBind() +{ + godot::Callable c = godot::Callable( this, "emit_custom_signal" ).bind( "bound", 11 ); + c.call(); +} + +void Example::unboundMethod1( godot::Object *inObject, godot::String inString, int inInt ) +{ + godot::String test = "unbound_method1: "; + test += inObject->get_class(); + test += " - " + inString; + emitCustomSignal( test, inInt ); +} + +godot::String Example::unboundMethod2( godot::Object *inObject, godot::String inString, int inInt ) +{ + godot::String test = "unbound_method2: "; + test += inObject->get_class(); + test += " - " + inString; + test += " - " + godot::itos( inInt ); + return test; +} + +godot::String Example::unboundMethod3( godot::Object *inObject, godot::String inString, + int inInt ) const +{ + godot::String test = "unbound_method3: "; + test += inObject->get_class(); + test += " - " + inString; + test += " - " + godot::itos( inInt ); + return test; +} + +void Example::unboundStaticMethod1( Example *inObject, godot::String inString, int inInt ) +{ + godot::String test = "unbound_static_method1: "; + test += inObject->get_class(); + test += " - " + inString; + inObject->emitCustomSignal( test, inInt ); +} + +godot::String Example::unboundStaticMethod2( godot::Object *inObject, godot::String inString, + int inInt ) +{ + godot::String test = "unbound_static_method2: "; + test += inObject->get_class(); + test += " - " + inString; + test += " - " + godot::itos( inInt ); + return test; +} + +godot::BitField Example::testBitfield( godot::BitField inFlags ) +{ + godot::UtilityFunctions::print( " Got BitField: ", godot::String::num_int64( inFlags ) ); + return inFlags; +} + +// RPC +void Example::testRPC( int inValue ) +{ + mLastRPCArg = inValue; +} + +void Example::testSendRPC( int inValue ) +{ + rpc( "test_rpc", inValue ); +} + +int Example::returnLastRPCArg() +{ + return mLastRPCArg; +} + +// Properties +void Example::setCustomPosition( const godot::Vector2 &inPos ) +{ + mCustomPosition = inPos; +} + +godot::Vector2 Example::getCustomPosition() const +{ + return mCustomPosition; +} + +godot::Vector4 Example::getV4() const +{ + return { 1.2f, 3.4f, 5.6f, 7.8f }; +} + +bool Example::testPostInitialize() const +{ + godot::Ref new_example_ref; + + new_example_ref.instantiate(); + + return new_example_ref->wasPostInitialized(); +} + +// Static methods +int Example::testStatic( int inA, int inB ) +{ + return inA + inB; +} + +void Example::testStatic2() +{ + godot::UtilityFunctions::print( " void static" ); +} + +// Virtual function override. +bool Example::_has_point( const godot::Vector2 &inPoint ) const +{ + auto *label = godot::Control::get_node( "Label" ); + + label->set_text( "Got point: " + godot::Variant( inPoint ).stringify() ); + + return false; +} + +void Example::_bind_methods() +{ + // Methods. + godot::ClassDB::bind_method( godot::D_METHOD( "simple_func" ), &Example::simpleFunc ); + godot::ClassDB::bind_method( godot::D_METHOD( "simple_const_func" ), + &Example::simpleConstFunc ); + godot::ClassDB::bind_method( godot::D_METHOD( "return_something" ), &Example::returnSomething ); + godot::ClassDB::bind_method( godot::D_METHOD( "return_something_const" ), + &Example::returnSomethingConst ); + godot::ClassDB::bind_method( godot::D_METHOD( "return_empty_ref" ), &Example::returnEmptyRef ); + godot::ClassDB::bind_method( godot::D_METHOD( "return_extended_ref" ), + &Example::returnExtendedRef ); + godot::ClassDB::bind_method( godot::D_METHOD( "extended_ref_checks", "ref" ), + &Example::extendedRefChecks ); + + godot::ClassDB::bind_method( godot::D_METHOD( "test_array" ), &Example::testArray ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_tarray_arg", "array" ), + &Example::testTypedArrayArg ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_tarray" ), &Example::testTypedArray ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_dictionary" ), &Example::testDictionary ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_node_argument" ), + &Example::testNodeArgument ); + + godot::ClassDB::bind_method( godot::D_METHOD( "test_string_ops" ), &Example::testStringOps ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_str_utility" ), &Example::testStrUtility ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_string_is_forty_two" ), + &Example::testStringIsFortyTwo ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_string_resize" ), + &Example::testStringResize ); + + godot::ClassDB::bind_method( godot::D_METHOD( "test_vector_ops" ), &Example::testVectorOps ); + + godot::ClassDB::bind_method( godot::D_METHOD( "test_object_cast_to_node", "object" ), + &Example::testObjectCastToNode ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_object_cast_to_control", "object" ), + &Example::testObjectCastToControl ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_object_cast_to_example", "object" ), + &Example::testObjectCastToExample ); + + godot::ClassDB::bind_method( godot::D_METHOD( "test_variant_vector2i_conversion", "variant" ), + &Example::testVariantVector2iConversion ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_variant_int_conversion", "variant" ), + &Example::testVariantIntConversion ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_variant_float_conversion", "variant" ), + &Example::testVariantFloatConversion ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_variant_call", "variant" ), + &Example::testVariantCall ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_variant_iterator", "input" ), + &Example::testVariantIterator ); + + godot::ClassDB::bind_method( godot::D_METHOD( "test_add_child", "node" ), + &Example::testAddChild ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_set_tileset", "tilemap", "tileset" ), + &Example::testSetTileset ); + + godot::ClassDB::bind_method( godot::D_METHOD( "test_callable_mp" ), &Example::testCallableMP ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_callable_mp_ret" ), + &Example::testCallableMPRet ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_callable_mp_retc" ), + &Example::testCallableMPRetC ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_callable_mp_static" ), + &Example::testCallableMPStatic ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_callable_mp_static_ret" ), + &Example::testCallableMPStaticRet ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_custom_callable" ), + &Example::testCustomCallable ); + + godot::ClassDB::bind_method( godot::D_METHOD( "test_bitfield", "flags" ), + &Example::testBitfield ); + + godot::ClassDB::bind_method( godot::D_METHOD( "test_rpc", "value" ), &Example::testRPC ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_send_rpc", "value" ), + &Example::testSendRPC ); + godot::ClassDB::bind_method( godot::D_METHOD( "return_last_rpc_arg" ), + &Example::returnLastRPCArg ); + + godot::ClassDB::bind_method( godot::D_METHOD( "def_args", "a", "b" ), &Example::defArgs, + DEFVAL( 100 ), DEFVAL( 200 ) ); + godot::ClassDB::bind_method( godot::D_METHOD( "callable_bind" ), &Example::callableBind ); + godot::ClassDB::bind_method( godot::D_METHOD( "test_post_initialize" ), + &Example::testPostInitialize ); + + godot::ClassDB::bind_static_method( "Example", godot::D_METHOD( "test_static", "a", "b" ), + &Example::testStatic ); + godot::ClassDB::bind_static_method( "Example", godot::D_METHOD( "test_static2" ), + &Example::testStatic2 ); + + { + godot::MethodInfo mi; + mi.arguments.emplace_back( godot::Variant::STRING, "some_argument" ); + mi.name = "varargs_func"; + + godot::ClassDB::bind_vararg_method( godot::METHOD_FLAGS_DEFAULT, "varargs_func", + &Example::varargsFunc, mi ); + } + + { + godot::MethodInfo mi; + mi.arguments.emplace_back( godot::Variant::STRING, "some_argument" ); + mi.name = "varargs_func_nv"; + + godot::ClassDB::bind_vararg_method( godot::METHOD_FLAGS_DEFAULT, "varargs_func_nv", + &Example::varargsFuncNonVoidReturn, mi ); + } + + { + godot::MethodInfo mi; + mi.arguments.emplace_back( godot::Variant::STRING, "some_argument" ); + mi.name = "varargs_func_void"; + + godot::ClassDB::bind_vararg_method( godot::METHOD_FLAGS_DEFAULT, "varargs_func_void", + &Example::varargsFuncVoidReturn, mi ); + } + + // Properties. + ADD_GROUP( "Test group", "group_" ); + ADD_SUBGROUP( "Test subgroup", "group_subgroup_" ); + + godot::ClassDB::bind_method( godot::D_METHOD( "get_custom_position" ), + &Example::getCustomPosition ); + godot::ClassDB::bind_method( godot::D_METHOD( "get_v4" ), &Example::getV4 ); + godot::ClassDB::bind_method( godot::D_METHOD( "set_custom_position", "position" ), + &Example::setCustomPosition ); + ADD_PROPERTY( godot::PropertyInfo( godot::Variant::VECTOR2, "group_subgroup_custom_position" ), + "set_custom_position", "get_custom_position" ); + + // Signals. + ADD_SIGNAL( godot::MethodInfo( "custom_signal", + godot::PropertyInfo( godot::Variant::STRING, "name" ), + godot::PropertyInfo( godot::Variant::INT, "value" ) ) ); + godot::ClassDB::bind_method( godot::D_METHOD( "emit_custom_signal", "name", "value" ), + &Example::emitCustomSignal ); + + // Constants. + BIND_ENUM_CONSTANT( FIRST ) + BIND_ENUM_CONSTANT( ANSWER_TO_EVERYTHING ) + + BIND_BITFIELD_FLAG( FLAG_ONE ); + BIND_BITFIELD_FLAG( FLAG_TWO ); + + BIND_CONSTANT( CONSTANT_WITHOUT_ENUM ); + BIND_ENUM_CONSTANT( OUTSIDE_OF_CLASS ); +} + +void Example::_notification( int inWhat ) +{ + godot::UtilityFunctions::print( "Notification: ", godot::String::num( inWhat ) ); +} + +bool Example::_set( const godot::StringName &inName, const godot::Variant &inValue ) +{ + godot::String name = inName; + + if ( name.begins_with( "dproperty" ) ) + { + int64_t index = name.get_slicec( '_', 1 ).to_int(); + mDProp[index] = inValue; + + return true; + } + + if ( name == "property_from_list" ) + { + mPropertyFromList = inValue; + + return true; + } + + return false; +} + +bool Example::_get( const godot::StringName &inName, godot::Variant &outReturn ) const +{ + godot::String name = inName; + + if ( name.begins_with( "dproperty" ) ) + { + int64_t index = name.get_slicec( '_', 1 ).to_int(); + outReturn = mDProp[index]; + + return true; + } + + if ( name == "property_from_list" ) + { + outReturn = mPropertyFromList; + + return true; + } + + return false; +} + +void Example::_get_property_list( godot::List *outList ) const +{ + outList->push_back( godot::PropertyInfo( godot::Variant::VECTOR3, "property_from_list" ) ); + + for ( int i = 0; i < 3; ++i ) + { + outList->push_back( + godot::PropertyInfo( godot::Variant::VECTOR2, "dproperty_" + godot::itos( i ) ) ); + } +} + +bool Example::_property_can_revert( const godot::StringName &inName ) const +{ + if ( inName == godot::StringName( "property_from_list" ) && + mPropertyFromList != godot::Vector3( MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER ) ) + { + return true; + } + + return false; +}; + +bool Example::_property_get_revert( const godot::StringName &inName, + godot::Variant &outProperty ) const +{ + if ( inName == godot::StringName( "property_from_list" ) ) + { + outProperty = godot::Vector3( MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER ); + + return true; + } + + return false; +}; + +void Example::_validate_property( godot::PropertyInfo &inProperty ) const +{ + godot::String name = inProperty.name; + + // Test hiding the "mouse_filter" property from the editor. + if ( name == "mouse_filter" ) + { + inProperty.usage = godot::PROPERTY_USAGE_NO_EDITOR; + } +} + +godot::String Example::_to_string() const +{ + return "[ GDExtension::Example <--> Instance ID:" + godot::uitos( get_instance_id() ) + " ]"; +} + +//// ExampleVirtual + +void ExampleVirtual::_bind_methods() +{ +} + +//// ExampleAbstract + +void ExampleAbstract::_bind_methods() +{ +} diff --git a/src/gdextension/Example.h b/src/gdextension/Example.h new file mode 100644 index 00000000..dc876a8c --- /dev/null +++ b/src/gdextension/Example.h @@ -0,0 +1,200 @@ +#pragma once +// Copied from godot-cpp/test/src and modified. + +#include "godot_cpp/classes/control.hpp" +#include "godot_cpp/classes/global_constants.hpp" +#include "godot_cpp/classes/tile_map.hpp" +#include "godot_cpp/classes/tile_set.hpp" +#include "godot_cpp/classes/viewport.hpp" +#include "godot_cpp/core/binder_common.hpp" +#include "godot_cpp/variant/variant.hpp" + +class ExampleRef : public godot::RefCounted +{ + GDCLASS( ExampleRef, RefCounted ) + +public: + ExampleRef(); + ~ExampleRef() override; + + void setId( int inID ); + int getID() const; + + bool wasPostInitialized() const + { + return mPostInitialized; + } + +protected: + static void _bind_methods(); + + void _notification( int inWhat ); + +private: + static int sInstanceCount; + static int sLastID; + + int mID; + bool mPostInitialized = false; +}; + +class ExampleMin : public godot::Control +{ + GDCLASS( ExampleMin, Control ) + +protected: + static void _bind_methods(); +}; + +class Example : public godot::Control +{ + GDCLASS( Example, godot::Control ) + +public: + // Constants. + enum Constants + { + FIRST, + ANSWER_TO_EVERYTHING = 42, + }; + + enum + { + CONSTANT_WITHOUT_ENUM = 314, + }; + + enum Flags + { + FLAG_ONE = 1, + FLAG_TWO = 2, + }; + + Example(); + ~Example() override; + + // Functions. + void simpleFunc(); + void simpleConstFunc() const; + godot::String returnSomething( const godot::String &inBase ); + godot::Viewport *returnSomethingConst() const; + godot::Ref returnEmptyRef() const; + ExampleRef *returnExtendedRef() const; + godot::Ref extendedRefChecks( godot::Ref inRef ) const; + godot::Variant varargsFunc( const godot::Variant **inArgs, GDExtensionInt inArgCount, + GDExtensionCallError &outError ); + int varargsFuncNonVoidReturn( const godot::Variant **inArgs, GDExtensionInt inArgCount, + GDExtensionCallError &outError ); + void varargsFuncVoidReturn( const godot::Variant **inArgs, GDExtensionInt inArgCount, + GDExtensionCallError &outError ); + + void emitCustomSignal( const godot::String &inName, int inValue ); + int defArgs( int inA = 100, int inB = 200 ) const; + + godot::Array testArray() const; + void testTypedArrayArg( const godot::TypedArray &inArray ); + godot::TypedArray testTypedArray() const; + godot::Dictionary testDictionary() const; + Example *testNodeArgument( Example *inNode ) const; + godot::String testStringOps() const; + godot::String testStrUtility() const; + bool testStringIsFortyTwo( const godot::String &inString ) const; + godot::String testStringResize( godot::String ioString ) const; + int testVectorOps() const; + + bool testObjectCastToNode( godot::Object *inObject ) const; + bool testObjectCastToControl( godot::Object *inObject ) const; + bool testObjectCastToExample( godot::Object *inObject ) const; + + godot::Vector2i testVariantVector2iConversion( const godot::Variant &inVariant ) const; + int testVariantIntConversion( const godot::Variant &inVariant ) const; + float testVariantFloatConversion( const godot::Variant &inVariant ) const; + godot::Variant testVariantCall( godot::Variant inVariant ); + godot::Variant testVariantIterator( const godot::Variant &inVariant ); + + void testAddChild( godot::Node *inNode ); + void testSetTileset( godot::TileMap *inTilemap, + const godot::Ref &inTileset ) const; + + godot::Callable testCallableMP(); + godot::Callable testCallableMPRet(); + godot::Callable testCallableMPRetC() const; + godot::Callable testCallableMPStatic() const; + godot::Callable testCallableMPStaticRet() const; + godot::Callable testCustomCallable() const; + + void callableBind(); + + void unboundMethod1( godot::Object *inObject, godot::String inString, int inInt ); + godot::String unboundMethod2( godot::Object *inObject, godot::String inString, int inInt ); + godot::String unboundMethod3( godot::Object *inObject, godot::String inString, + int inInt ) const; + static void unboundStaticMethod1( Example *inObject, godot::String inString, int inInt ); + static godot::String unboundStaticMethod2( godot::Object *inObject, godot::String inString, + int inInt ); + + godot::BitField testBitfield( godot::BitField inFlags ); + + // RPC + void testRPC( int inValue ); + void testSendRPC( int inValue ); + int returnLastRPCArg(); + + // Property + void setCustomPosition( const godot::Vector2 &inPos ); + godot::Vector2 getCustomPosition() const; + godot::Vector4 getV4() const; + + bool testPostInitialize() const; + + // Static method. + static int testStatic( int inA, int inB ); + static void testStatic2(); + + // Virtual function override (no need to bind manually). + virtual bool _has_point( const godot::Vector2 &inPoint ) const override; + +protected: + static void _bind_methods(); + + void _notification( int inWhat ); + bool _set( const godot::StringName &inName, const godot::Variant &inValue ); + bool _get( const godot::StringName &inName, godot::Variant &outReturn ) const; + void _get_property_list( godot::List *outList ) const; + bool _property_can_revert( const godot::StringName &inName ) const; + bool _property_get_revert( const godot::StringName &inName, godot::Variant &outProperty ) const; + void _validate_property( godot::PropertyInfo &inProperty ) const; + + godot::String _to_string() const; + +private: + godot::Vector2 mCustomPosition; + godot::Vector3 mPropertyFromList; + godot::Vector2 mDProp[3]; + + int mLastRPCArg = 0; +}; + +VARIANT_ENUM_CAST( Example::Constants ); +VARIANT_BITFIELD_CAST( Example::Flags ); + +enum EnumWithoutClass +{ + OUTSIDE_OF_CLASS = 512 +}; +VARIANT_ENUM_CAST( EnumWithoutClass ); + +class ExampleVirtual : public godot::Object +{ + GDCLASS( ExampleVirtual, godot::Object ) + +protected: + static void _bind_methods(); +}; + +class ExampleAbstract : public godot::Object +{ + GDCLASS( ExampleAbstract, godot::Object ) + +protected: + static void _bind_methods(); +}; diff --git a/src/gdextension/GDExtensionTemplate.cpp b/src/gdextension/GDExtensionTemplate.cpp new file mode 100644 index 00000000..dd2f373c --- /dev/null +++ b/src/gdextension/GDExtensionTemplate.cpp @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: Unlicense + +#include "godot_cpp/core/class_db.hpp" +#include "godot_cpp/core/version.hpp" + +#include "GDExtensionTemplate.h" + +/// @file +/// GDExtensionTemplate example implementation. + +/*! +@brief Get the version string for this extension. + +@details +The version string is generated by cmake using src/Version.h.in. + +It uses the form " -<# commits since last tag>-". +If there are no commits since the last tag, only the tag is shown. + +@return The version string (e.g. "Foo v1.2.3-gdedbd01"). +*/ +godot::String GDExtensionTemplate::version() +{ + return "osp-gdextension v0.0.1"; +} + +/*! +@brief Get the godot-cpp version string for this extension. + +@details +The version string is generated using godot-cpp's core/version.hpp. + +@return The version string (e.g. "godot-cpp v4.2.0-stable"). +*/ +godot::String GDExtensionTemplate::godotCPPVersion() +{ + return "godot-cpp v" + godot::uitos( GODOT_VERSION_MAJOR ) + "." + + godot::uitos( GODOT_VERSION_MINOR ) + "." + godot::uitos( GODOT_VERSION_PATCH ) + "-" + + GODOT_VERSION_STATUS; +} + +/// Bind our methods so GDScript can access them. +void GDExtensionTemplate::_bind_methods() +{ + godot::ClassDB::bind_static_method( "GDExtensionTemplate", godot::D_METHOD( "version" ), + &GDExtensionTemplate::version ); + godot::ClassDB::bind_static_method( "GDExtensionTemplate", + godot::D_METHOD( "godot_cpp_version" ), + &GDExtensionTemplate::godotCPPVersion ); +} diff --git a/src/gdextension/GDExtensionTemplate.h b/src/gdextension/GDExtensionTemplate.h new file mode 100644 index 00000000..5eb40d01 --- /dev/null +++ b/src/gdextension/GDExtensionTemplate.h @@ -0,0 +1,21 @@ +#pragma once +// SPDX-License-Identifier: Unlicense + +#include "godot_cpp/classes/object.hpp" + +namespace godot +{ + class ClassDB; +}; + +class GDExtensionTemplate : public godot::Object +{ + GDCLASS( GDExtensionTemplate, godot::Object ) + +public: + static godot::String version(); + static godot::String godotCPPVersion(); + +private: + static void _bind_methods(); +}; diff --git a/src/gdextension/RegisterExtension.cpp b/src/gdextension/RegisterExtension.cpp new file mode 100644 index 00000000..699c4ee2 --- /dev/null +++ b/src/gdextension/RegisterExtension.cpp @@ -0,0 +1,78 @@ +// Copied from godot-cpp/test/src and modified. + +#include "gdextension_interface.h" + +#include "godot_cpp/core/class_db.hpp" +#include "godot_cpp/core/defs.hpp" +#include "godot_cpp/godot.hpp" + +#include "Example.h" +#include "GDExtensionTemplate.h" + +/// @file +/// Register our classes with Godot. + +namespace +{ + /// @brief Called by Godot to let us register our classes with Godot. + /// + /// @param p_level the level being initialized by Godot + /// + /// @see GDExtensionInit + void initializeExtension( godot::ModuleInitializationLevel p_level ) + { + if ( p_level != godot::MODULE_INITIALIZATION_LEVEL_SCENE ) + { + return; + } + + godot::ClassDB::register_class(); + godot::ClassDB::register_class(); + godot::ClassDB::register_class(); + godot::ClassDB::register_class( true ); + godot::ClassDB::register_abstract_class(); + + godot::ClassDB::register_class(); + } + + /// @brief Called by Godot to let us do any cleanup. + /// + /// @see GDExtensionInit + void uninitializeExtension( godot::ModuleInitializationLevel p_level ) + { + if ( p_level != godot::MODULE_INITIALIZATION_LEVEL_SCENE ) + { + return; + } + } +} + +extern "C" +{ + /// @brief This is the entry point for the shared library. + /// + /// @note The name of this function must match the "entry_symbol" in + /// templates/template.*.gdextension.in + /// + /// @param p_get_proc_address the interface (need more info) + /// @param p_library the library (need more info) + /// @param r_initialization the intialization (need more info) + /// + /// @returns GDExtensionBool + GDExtensionBool GDE_EXPORT GDExtensionInit( + GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, + GDExtensionInitialization *r_initialization ) + { + { + godot::GDExtensionBinding::InitObject init_obj( p_get_proc_address, p_library, + r_initialization ); + + init_obj.register_initializer( initializeExtension ); + init_obj.register_terminator( uninitializeExtension ); + init_obj.set_minimum_library_initialization_level( + godot::MODULE_INITIALIZATION_LEVEL_SCENE ); + + return init_obj.init(); + } + } +} diff --git a/src/gdextension/templates/CMakeLists.txt b/src/gdextension/templates/CMakeLists.txt new file mode 100644 index 00000000..da0190cd --- /dev/null +++ b/src/gdextension/templates/CMakeLists.txt @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: Unlicense + +add_custom_target( templates + SOURCES + template.debug.gdextension.in + template.release.gdextension.in +) + +add_dependencies( osp-gdextension templates ) + +# TODO make this a bit generic with some kind of template. Currently hardcoded. + +set( GD_EXTENSION_FILE_INPUT osp.gdextension ) + +# Install the gdextension file +install( + FILES ${GD_EXTENSION_FILE_INPUT} + DESTINATION ${INSTALL_DIR} +) + +unset( ALLOWED_BUILDS ) +unset( BUILD_TYPE ) +unset( GD_EXTENSION_FILE ) +unset( GD_EXTENSION_FILE_INPUT ) +unset( LIB_PREFIX ) diff --git a/src/gdextension/templates/osp.gdextension b/src/gdextension/templates/osp.gdextension new file mode 100644 index 00000000..7111f874 --- /dev/null +++ b/src/gdextension/templates/osp.gdextension @@ -0,0 +1,11 @@ +[configuration] +entry_symbol = "GDExtensionInit" +compatibility_minimum = 4.1 + +[icons] +Example = "icons/Example.svg" + +[libraries] +linux.debug.x86_64 = "lib/Linux-x86_64/libosp-gdextension.so" +macos.debug = "lib/Darwin-Universal/libosp-gdextension.dylib" +windows.debug.x86_64 = "lib/Windows-AMD64/osp-gdextension.dll" diff --git a/src/gdextension/templates/template.debug.gdextension.in b/src/gdextension/templates/template.debug.gdextension.in new file mode 100644 index 00000000..42c08114 --- /dev/null +++ b/src/gdextension/templates/template.debug.gdextension.in @@ -0,0 +1,11 @@ +[configuration] +entry_symbol = "GDExtensionInit" +compatibility_minimum = 4.1 + +[icons] +Example = "icons/Example.svg" + +[libraries] +linux.debug.x86_64 = "lib/Linux-x86_64/lib${PROJECT_NAME}-d.so" +macos.debug = "lib/Darwin-Universal/lib${PROJECT_NAME}-d.dylib" +windows.debug.x86_64 = "lib/Windows-AMD64/${LIB_PREFIX}${PROJECT_NAME}-d.dll" diff --git a/src/gdextension/templates/template.release.gdextension.in b/src/gdextension/templates/template.release.gdextension.in new file mode 100644 index 00000000..4d5ba9bd --- /dev/null +++ b/src/gdextension/templates/template.release.gdextension.in @@ -0,0 +1,11 @@ +[configuration] +entry_symbol = "GDExtensionInit" +compatibility_minimum = 4.1 + +[icons] +Example = "icons/Example.svg" + +[libraries] +linux.release.x86_64 = "lib/Linux-x86_64/lib${PROJECT_NAME}.so" +macos.release = "lib/Darwin-universal/lib${PROJECT_NAME}.dylib" +windows.release.x86_64 = "lib/Windows-AMD64/${LIB_PREFIX}${PROJECT_NAME}.dll" diff --git a/src/ospnewton/activescene/forcefactors.h b/src/ospnewton/activescene/forcefactors.h deleted file mode 100644 index dc1c5259..00000000 --- a/src/ospnewton/activescene/forcefactors.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Open Space Program - * Copyright © 2019-2022 Open Space Program Project - * - * MIT License - * - * 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. - */ -#pragma once - -#include -#include - -namespace ospnewton -{ - -// Each rigid body is given 64 bits to enable/disable forces -// These determine which physics calculations are required for a certain -// rigid body, such as gravity, thurst, or aerodynamics. -// Forces are assignable at runtime in ACtxNwtWorld::m_factors -using ForceFactors_t = std::array; - -} diff --git a/src/ospnewton/activescene/newtoninteg.h b/src/ospnewton/activescene/newtoninteg.h deleted file mode 100644 index 208f6ef1..00000000 --- a/src/ospnewton/activescene/newtoninteg.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Open Space Program - * Copyright © 2019-2021 Open Space Program Project - * - * MIT License - * - * 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. - */ -#pragma once - -#include "forcefactors.h" - -#include -#include - -#include - -#include -#include - -#include - - -namespace ospnewton -{ - -template -struct NwtDeleter -{ - void operator() (auto const* pNwtType) - { - FUNC_T(pNwtType); - } -}; - -using NwtBodyPtr_t = std::unique_ptr< NewtonBody, NwtDeleter >; - -using NwtColliderPtr_t = std::unique_ptr >; - -//using ForceFactor_t = void (*)( -// ActiveEnt, ViewProjMatrix const&, UserData_t) noexcept; - -using BodyId = uint32_t; - -using ColliderStorage_t = osp::Storage_t; - -/** - * @brief Represents an instance of a Newton physics world in the scane - */ -struct ACtxNwtWorld -{ - - struct ForceFactorFunc - { - using UserData_t = std::array; - using Func_t = void (*)(NewtonBody const* pBody, BodyId BodyId, ACtxNwtWorld const&, UserData_t, osp::Vector3&, osp::Vector3&) noexcept; - - Func_t m_func; - UserData_t m_userData; - }; - - struct Deleter - { - void operator() (NewtonWorld* pNwtWorld) { NewtonDestroy(pNwtWorld); } - }; - - ACtxNwtWorld(int threadCount) - : m_world(NewtonCreate()) - { - NewtonWorldSetUserData(m_world.get(), this); - } - - // note: important that m_nwtBodies and m_nwtColliders are destructed - // before m_nwtWorld - std::unique_ptr m_world; - - lgrn::IdRegistryStl m_bodyIds; - std::vector m_bodyPtrs; - std::vector m_bodyFactors; - lgrn::IdSetStl m_bodyDirty; - - std::vector m_bodyToEnt; - osp::IdMap_t m_entToBody; - - std::vector m_factors; - - ColliderStorage_t m_colliders; - - osp::active::ACompTransformStorage_t *m_pTransform; -}; - - -} diff --git a/src/ospnewton/activescene/newtoninteg_fn.cpp b/src/ospnewton/activescene/newtoninteg_fn.cpp deleted file mode 100644 index d909a5f4..00000000 --- a/src/ospnewton/activescene/newtoninteg_fn.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/** - * Open Space Program - * Copyright © 2019-2020 Open Space Program Project - * - * MIT License - * - * 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. - */ - -#include "newtoninteg_fn.h" // IWYU pragma: associated - -#include - -#include // for NewtonBodySetCollision - -#include // for std::exchange -#include // for assert - -// IWYU pragma: no_include -// IWYU pragma: no_include - -using namespace ospnewton; - -// for the 0xrrggbb_rgbf and angle literals -using namespace Magnum::Math::Literals; - -using osp::EShape; - -using osp::active::ActiveEnt; -using osp::active::ACtxPhysics; -using osp::active::SysSceneGraph; - -using osp::Matrix3; -using osp::Matrix4; -using osp::Vector3; - - -// Callback called for dynamic rigid bodies for applying force and torque -void SysNewton::cb_force_torque( - NewtonBody const* pBody, dFloat const timestep, NwtThreadIndex_t const thread) -{ - ACtxNwtWorld &rWorldCtx = SysNewton::context_from_nwtbody(pBody); - BodyId const bodyId = SysNewton::get_userdata_bodyid(pBody); - - Vector3 force{0.0f}; - Vector3 torque{0.0f}; - - auto factorBits = lgrn::bit_view(rWorldCtx.m_bodyFactors[bodyId]); - for (std::size_t const factorIdx : factorBits.ones()) - { - ACtxNwtWorld::ForceFactorFunc const& factor = rWorldCtx.m_factors[factorIdx]; - - factor.m_func(pBody, bodyId, rWorldCtx, factor.m_userData, force, torque); - } - - NewtonBodySetForce(pBody, force.data()); - NewtonBodySetTorque(pBody, torque.data()); -} // cb_force_torque() - -void SysNewton::cb_set_transform( - NewtonBody const* pBody, dFloat const* const pMatrix, NwtThreadIndex_t const thread) -{ - ACtxNwtWorld &rWorldCtx = SysNewton::context_from_nwtbody(pBody); - BodyId const bodyId = SysNewton::get_userdata_bodyid(pBody); - - ActiveEnt const ent = rWorldCtx.m_bodyToEnt[bodyId]; - - NewtonBodyGetMatrix(pBody, rWorldCtx.m_pTransform->get(ent).m_transform.data()); -} // cb_set_transform() - - -void SysNewton::resize_body_data(ACtxNwtWorld& rCtxWorld) -{ - std::size_t const capacity = rCtxWorld.m_bodyIds.capacity(); - rCtxWorld.m_bodyPtrs .resize(capacity); - rCtxWorld.m_bodyToEnt .resize(capacity); - rCtxWorld.m_bodyFactors .resize(capacity); -} - -NwtColliderPtr_t SysNewton::create_primative( - ACtxNwtWorld& rCtxWorld, - EShape shape) -{ - NewtonWorld* pNwtWorld = rCtxWorld.m_world.get(); - NewtonCollision* pCollision; - switch (shape) - { - case EShape::Sphere: - pCollision = NewtonCreateSphere(pNwtWorld, 1.0f, 0, nullptr); - break; - case EShape::Box: - pCollision = NewtonCreateBox(pNwtWorld, 2, 2, 2, 0, nullptr); - break; - case EShape::Cylinder: - pCollision = NewtonCreateCylinder(pNwtWorld, 1, 1, 2, 0, nullptr); - break; - default: - // TODO: support other shapes, sphere is used for now - pCollision = NewtonCreateSphere(pNwtWorld, 1.0f, 0, nullptr); - break; - } - - return NwtColliderPtr_t{pCollision}; -} - -void SysNewton::orient_collision( - NewtonCollision const* pCollision, - osp::EShape shape, - osp::Vector3 const& translation, - osp::Matrix3 const& rotation, - osp::Vector3 const& scale) -{ - if (shape != EShape::Cylinder) - { - Matrix4 const matrix = Matrix4::from(rotation, translation); - NewtonCollisionSetMatrix(pCollision, matrix.data()); - NewtonCollisionSetScale(pCollision, scale.x(), scale.y(), scale.z()); - } - else - { - static constexpr Matrix3 const rotX90deg - { - { 0.0f, 0.0f, -1.0f}, - { 0.0f, 1.0f, 0.0f}, - { 1.0f, 0.0f, 0.0f} - }; - Matrix4 const matrix = Matrix4::from(rotation * rotX90deg, translation); - NewtonCollisionSetMatrix(pCollision, matrix.data()); - NewtonCollisionSetScale(pCollision, scale.z(), scale.y(), scale.x()); - } -} - -void SysNewton::update_translate(ACtxPhysics& rCtxPhys, ACtxNwtWorld& rCtxWorld) noexcept -{ - NewtonWorld const* pNwtWorld = rCtxWorld.m_world.get(); - - // Origin translation - if (Vector3 const translate = std::exchange(rCtxPhys.m_originTranslate, {}); - ! translate.isZero()) - { - // Translate every newton body - for (NewtonBody const* pBody = NewtonWorldGetFirstBody(pNwtWorld); - pBody != nullptr; pBody = NewtonWorldGetNextBody(pNwtWorld, pBody)) - { - Matrix4 matrix; - NewtonBodyGetMatrix(pBody, matrix.data()); - matrix.translation() += translate; - NewtonBodySetMatrix(pBody, matrix.data()); - } - } -} - -using Corrade::Containers::ArrayView; - -void SysNewton::update_world( - ACtxPhysics& rCtxPhys, - ACtxNwtWorld& rCtxWorld, - float timestep, - ACtxSceneGraph const& rScnGraph, - ACompTransformStorage_t& rTf) noexcept -{ - NewtonWorld const* pNwtWorld = rCtxWorld.m_world.get(); - - // Apply changed velocities - for (auto const& [ent, vel] : std::exchange(rCtxPhys.m_setVelocity, {})) - { - BodyId const bodyId = rCtxWorld.m_entToBody.at(ent); - NewtonBody const *pBody = rCtxWorld.m_bodyPtrs[bodyId].get(); - - NewtonBodySetVelocity(pBody, vel.data()); - } - - rCtxWorld.m_pTransform = std::addressof(rTf); - - // Update the world - NewtonUpdate(pNwtWorld, timestep); -} - -void SysNewton::remove_components(ACtxNwtWorld& rCtxWorld, ActiveEnt ent) noexcept -{ - auto itBodyId = rCtxWorld.m_entToBody.find(ent); - - if (itBodyId != rCtxWorld.m_entToBody.end()) - { - BodyId const bodyId = itBodyId->second; - rCtxWorld.m_bodyPtrs[bodyId].reset(); - rCtxWorld.m_bodyToEnt[bodyId] = lgrn::id_null(); - rCtxWorld.m_entToBody.erase(itBodyId); - } - - rCtxWorld.m_colliders.remove(ent); -} - - -void SysNewton::find_colliders_recurse( - ACtxPhysics const& rCtxPhys, - ACtxNwtWorld& rCtxWorld, - ACtxSceneGraph const& rScnGraph, - ACompTransformStorage_t const& rTf, - ActiveEnt ent, - Matrix4 const& transform, - NewtonCollision* pCompound) noexcept -{ - // Add newton collider if exists - if (rCtxWorld.m_colliders.contains(ent)) - { - NewtonCollision const *pCollision - = rCtxWorld.m_colliders.get(ent).get(); - - // Set transform relative to root body - - // cylinder needs to be rotated 90 degrees Z to aligned with Y axis - // TODO: replace this with something more sophisticated some time - Matrix4 const &colliderTf - = (rCtxPhys.m_shape[ent] != EShape::Cylinder) - ? transform : transform * Matrix4::rotationZ(90.0_degf); - - Matrix4 const normScale = Matrix4::from(colliderTf.rotation(), colliderTf.translation()); - - NewtonCollisionSetMatrix(pCollision, normScale.data()); - - Vector3 const scale = colliderTf.scaling(); - NewtonCollisionSetScale(pCollision, scale.x(), scale.y(), scale.z()); - - // Add body to compound collision - NewtonCompoundCollisionAddSubCollision(pCompound, pCollision); - } - - if ( ! rCtxPhys.m_hasColliders.contains(ent) ) - { - return; - } - - // Recurse into children if there are more colliders - for (ActiveEnt child : SysSceneGraph::children(rScnGraph, ent)) - { - if (rTf.contains(child)) - { - ACompTransform const &rChildTransform = rTf.get(child); - - Matrix4 const childMatrix = transform * rChildTransform.m_transform; - - find_colliders_recurse( - rCtxPhys, rCtxWorld, rScnGraph, rTf, child, childMatrix, pCompound); - } - - } - -} - - diff --git a/src/ospnewton/activescene/newtoninteg_fn.h b/src/ospnewton/activescene/newtoninteg_fn.h deleted file mode 100644 index 641d6a47..00000000 --- a/src/ospnewton/activescene/newtoninteg_fn.h +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Open Space Program - * Copyright © 2019-2020 Open Space Program Project - * - * MIT License - * - * 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. - */ -#pragma once - -#include "newtoninteg.h" - -#include -#include - -#include - -#include - -// IWYU pragma: no_include -// IWYU pragma: no_include -// IWYU pragma: no_include - -namespace ospnewton -{ - -class SysNewton -{ - using ActiveEnt = osp::active::ActiveEnt; - using ACtxPhysics = osp::active::ACtxPhysics; - using ACtxSceneGraph = osp::active::ACtxSceneGraph; - using ACompTransform = osp::active::ACompTransform; - using ACompTransformStorage_t = osp::active::ACompTransformStorage_t; -public: - - using NwtThreadIndex_t = int; - - static void cb_force_torque(const NewtonBody* pBody, dFloat timestep, NwtThreadIndex_t thread); - - static void cb_set_transform(NewtonBody const* pBody, dFloat const* pMatrix, NwtThreadIndex_t thread); - - static void resize_body_data(ACtxNwtWorld& rCtxWorld); - - [[nodiscard]] static NwtColliderPtr_t create_primative( - ACtxNwtWorld& rCtxWorld, - osp::EShape shape); - - - static void orient_collision( - NewtonCollision const* pCollision, - osp::EShape shape, - osp::Vector3 const& translation, - osp::Matrix3 const& rotation, - osp::Vector3 const& scale); - - /** - * @brief Respond to scene origin shifts by translating all rigid bodies - * - * @param rCtxPhys [ref] Generic physics context with m_originTranslate - * @param rCtxWorld [ref] Newton World - */ - static void update_translate( - ACtxPhysics& rCtxPhys, - ACtxNwtWorld& rCtxWorld) noexcept; - - /** - * @brief Synchronize generic physics colliders with Newton colliders - * - * @param rCtxPhys [ref] Generic physics context - * @param rCtxWorld [ref] Newton World - * @param rCollidersDirty [in] Colliders to update - */ - static void update_colliders( - ACtxPhysics& rCtxPhys, - ACtxNwtWorld& rCtxWorld, - std::vector const& collidersDirty) noexcept; - - /** - * @brief Step the entire Newton World forward in time - * - * @param rCtxPhys [ref] Generic Physics context. Updates linear and angular velocity. - * @param rCtxWorld [ref] Newton world to update - * @param timestep [in] Time to step world, passed to Newton update - * @param inputs [ref] Physics inputs (from different threads) - * @param rHier [in] Storage for Hierarchy components - * @param rTf [ref] Relative transforms used by rigid bodies - * @param rTfControlled [ref] Flags for controlled transforms - * @param rTfMutable [ref] Flags for mutable transforms - */ - static void update_world( - ACtxPhysics& rCtxPhys, - ACtxNwtWorld& rCtxWorld, - float timestep, - ACtxSceneGraph const& rScnGraph, - osp::active::ACompTransformStorage_t& rTf) noexcept; - - static void remove_components( - ACtxNwtWorld& rCtxWorld, ActiveEnt ent) noexcept; - - template - static void update_delete( - ACtxNwtWorld &rCtxWorld, IT_T first, IT_T const& last) noexcept - { - while (first != last) - { - remove_components(rCtxWorld, *first); - std::advance(first, 1); - } - } - - static ACtxNwtWorld& context_from_nwtbody(NewtonBody const* const pBody) - { - return *static_cast(NewtonWorldGetUserData(NewtonBodyGetWorld(pBody))); - } - - static BodyId get_userdata_bodyid(NewtonBody const* const pBody) - { - return reinterpret_cast(NewtonBodyGetUserData(pBody)); - } - - static void set_userdata_bodyid(NewtonBody const* const pBody, BodyId const body) - { - return NewtonBodySetUserData(pBody, reinterpret_cast(std::uintptr_t(body))); - } - -private: - - /** - * @brief Find colliders in an entity and its hierarchy, and add them to - * a Newton Compound Collision - * - * @param rCtxPhys [in] Generic Physics context. - * @param rCtxWorld [ref] Newton world - * @param rHier [in] Storage for hierarchy components - * @param rTf [in] Storage for relative hierarchy transforms - * @param ent [in] Entity to search - * @param transform [in] Transform relative to root (part of recursion) - * @param pCompound [out] NewtonCompoundCollision to add colliders to - */ - static void find_colliders_recurse( - ACtxPhysics const& rCtxPhys, - ACtxNwtWorld& rCtxWorld, - ACtxSceneGraph const& rScnGraph, - ACompTransformStorage_t const& rTf, - ActiveEnt ent, - osp::Matrix4 const& transform, - NewtonCollision* pCompound) noexcept; - -}; - -} - diff --git a/src/standalone/CMakeLists.txt b/src/standalone/CMakeLists.txt new file mode 100644 index 00000000..11843725 --- /dev/null +++ b/src/standalone/CMakeLists.txt @@ -0,0 +1,125 @@ +## +# Open Space Program +# Copyright © 2019-2024 Open Space Program Project +# +# MIT License +# +# 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. +## + +find_package(Magnum REQUIRED + GL + Shaders + MeshTools + Primitives + Trade + Sdl2Application + AnyImageImporter + ) + +find_package(MagnumPlugins REQUIRED + TinyGltfImporter + StbImageImporter) + +set(THREADS_PREFER_PTHREAD_FLAG TRUE) +find_package(Threads) +if(NOT Threads_FOUND) + message(FATAL_ERROR "Can't find a thread library to use!") +endif() + + +add_library(osp-magnum-deps INTERFACE) +add_custom_target(compile-osp-magnum-deps) + +# TODO: This list shouldn't be required, but there appears to be a bug in cmake where +# the add_custom_target() command, pointing to an INTERFACE dependency, doesn't +# result in the dependencies of the interface building. +# See: https://gitlab.kitware.com/cmake/cmake/-/issues/23569 +SET(OSP_MAGNUM_DEPS_LIBS + osp-common + Threads::Threads + EnTT::EnTT + Corrade::Main + Magnum::Application + Magnum::GL + Magnum::Magnum + Magnum::MeshTools + Magnum::Primitives + Magnum::Shaders + Magnum::Trade + Magnum::AnyImageImporter + MagnumPlugins::TinyGltfImporter + MagnumPlugins::StbImageImporter + toml11 + spdlog + longeron + Jolt) +target_link_libraries(osp-magnum-deps INTERFACE ${OSP_MAGNUM_DEPS_LIBS}) +add_dependencies(compile-osp-magnum-deps ${OSP_MAGNUM_DEPS_LIBS}) + +add_executable(osp-magnum) + +target_compile_features(osp-magnum PUBLIC cxx_std_20) + +target_include_directories(osp-magnum PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +# Link it to the interface library that describes the dependencies +target_link_libraries(osp-magnum PRIVATE osp-magnum-deps) + +# Gather paths to OSP headers and sources +file(GLOB_RECURSE CPP_FILES CONFIGURE_DEPENDS *.cpp) +file(GLOB_RECURSE H_FILES CONFIGURE_DEPENDS *.h) +target_sources(osp-magnum PRIVATE "${CPP_FILES}" "${H_FILES}") + +# Add shaders to IDE project +set(SHADERS_DIR "../../bin/OSPData/adera/Shaders") +file (GLOB_RECURSE SHADER_FILES CONFIGURE_DEPENDS + "${SHADERS_DIR}/*.vert" + "${SHADERS_DIR}/*.frag" + "${SHADERS_DIR}/*.comp" +) +# For some reason, source_group() requires all files to be added to the executable +target_sources(osp-magnum PRIVATE "${SHADER_FILES}") + +# Segregate headers, shaders into filters +source_group("Shader Files" FILES ${SHADER_FILES}) +source_group("Header Files" FILES ${H_FILES}) + +# Enforce conformance mode for osp-magnum +target_compile_options(osp-magnum PRIVATE $<$:/permissive->) + +set_target_properties(osp-magnum PROPERTIES + EXPORT_COMPILE_COMMANDS TRUE + INSTALL_RPATH "$ORIGIN/lib" + C_EXTENSIONS OFF + C_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF + CXX_STANDARD_REQUIRED ON +) + +# Copy root/bin to build/bin after building +add_custom_command(TARGET osp-magnum + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_SOURCE_DIR}/../../bin" "${CMAKE_BINARY_DIR}/$" + VERBATIM +) + +add_custom_target(run-osp-magnum + COMMAND $ + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/$) diff --git a/src/osp/drawing_gl/FullscreenTriShader.cpp b/src/standalone/drawing_gl/FullscreenTriShader.cpp similarity index 100% rename from src/osp/drawing_gl/FullscreenTriShader.cpp rename to src/standalone/drawing_gl/FullscreenTriShader.cpp diff --git a/src/osp/drawing_gl/FullscreenTriShader.h b/src/standalone/drawing_gl/FullscreenTriShader.h similarity index 100% rename from src/osp/drawing_gl/FullscreenTriShader.h rename to src/standalone/drawing_gl/FullscreenTriShader.h diff --git a/src/osp/drawing_gl/rendergl.cpp b/src/standalone/drawing_gl/rendergl.cpp similarity index 99% rename from src/osp/drawing_gl/rendergl.cpp rename to src/standalone/drawing_gl/rendergl.cpp index b283d572..fbd7dcfd 100644 --- a/src/osp/drawing_gl/rendergl.cpp +++ b/src/standalone/drawing_gl/rendergl.cpp @@ -26,9 +26,9 @@ #include "rendergl.h" #include "FullscreenTriShader.h" -#include "../core/Resources.h" -#include "../drawing/own_restypes.h" -#include "../util/logging.h" +#include +#include +#include #include diff --git a/src/osp/drawing_gl/rendergl.h b/src/standalone/drawing_gl/rendergl.h similarity index 99% rename from src/osp/drawing_gl/rendergl.h rename to src/standalone/drawing_gl/rendergl.h index b6f4f3d6..4877fad5 100644 --- a/src/osp/drawing_gl/rendergl.h +++ b/src/standalone/drawing_gl/rendergl.h @@ -26,7 +26,7 @@ #include "FullscreenTriShader.h" -#include "../drawing/drawing_fn.h" +#include #include #include diff --git a/src/adera/drawing_gl/flat_shader.cpp b/src/standalone/shader/flat_shader.cpp similarity index 100% rename from src/adera/drawing_gl/flat_shader.cpp rename to src/standalone/shader/flat_shader.cpp diff --git a/src/adera/drawing_gl/flat_shader.h b/src/standalone/shader/flat_shader.h similarity index 99% rename from src/adera/drawing_gl/flat_shader.h rename to src/standalone/shader/flat_shader.h index 78dcd4a0..122f4017 100644 --- a/src/adera/drawing_gl/flat_shader.h +++ b/src/standalone/shader/flat_shader.h @@ -24,7 +24,7 @@ */ #pragma once -#include +#include #include diff --git a/src/adera/drawing_gl/phong_shader.cpp b/src/standalone/shader/phong_shader.cpp similarity index 100% rename from src/adera/drawing_gl/phong_shader.cpp rename to src/standalone/shader/phong_shader.cpp diff --git a/src/adera/drawing_gl/phong_shader.h b/src/standalone/shader/phong_shader.h similarity index 99% rename from src/adera/drawing_gl/phong_shader.h rename to src/standalone/shader/phong_shader.h index ef09161c..540aa125 100644 --- a/src/adera/drawing_gl/phong_shader.h +++ b/src/standalone/shader/phong_shader.h @@ -24,7 +24,7 @@ */ #pragma once -#include +#include #include diff --git a/src/adera/drawing_gl/plume_shader.cpp b/src/standalone/shader/plume_shader.cpp similarity index 100% rename from src/adera/drawing_gl/plume_shader.cpp rename to src/standalone/shader/plume_shader.cpp diff --git a/src/adera/drawing_gl/plume_shader.h b/src/standalone/shader/plume_shader.h similarity index 100% rename from src/adera/drawing_gl/plume_shader.h rename to src/standalone/shader/plume_shader.h diff --git a/src/adera/drawing_gl/visualizer_shader.cpp b/src/standalone/shader/visualizer_shader.cpp similarity index 100% rename from src/adera/drawing_gl/visualizer_shader.cpp rename to src/standalone/shader/visualizer_shader.cpp diff --git a/src/adera/drawing_gl/visualizer_shader.h b/src/standalone/shader/visualizer_shader.h similarity index 98% rename from src/adera/drawing_gl/visualizer_shader.h rename to src/standalone/shader/visualizer_shader.h index c134d234..fcc2c9b1 100644 --- a/src/adera/drawing_gl/visualizer_shader.h +++ b/src/standalone/shader/visualizer_shader.h @@ -24,7 +24,7 @@ */ #pragma once -#include +#include #include diff --git a/src/testapp/MagnumApplication.cpp b/src/standalone/testapp/MagnumApplication.cpp similarity index 100% rename from src/testapp/MagnumApplication.cpp rename to src/standalone/testapp/MagnumApplication.cpp diff --git a/src/testapp/MagnumApplication.h b/src/standalone/testapp/MagnumApplication.h similarity index 100% rename from src/testapp/MagnumApplication.h rename to src/standalone/testapp/MagnumApplication.h diff --git a/src/testapp/README.md b/src/standalone/testapp/README.md similarity index 100% rename from src/testapp/README.md rename to src/standalone/testapp/README.md diff --git a/src/testapp/enginetest.cpp b/src/standalone/testapp/enginetest.cpp similarity index 99% rename from src/testapp/enginetest.cpp rename to src/standalone/testapp/enginetest.cpp index 86ca9a5b..aa2d21b2 100644 --- a/src/testapp/enginetest.cpp +++ b/src/standalone/testapp/enginetest.cpp @@ -29,10 +29,10 @@ #include #include #include -#include +#include #include -#include +#include #include #include diff --git a/src/testapp/enginetest.h b/src/standalone/testapp/enginetest.h similarity index 98% rename from src/testapp/enginetest.h rename to src/standalone/testapp/enginetest.h index 38438315..d0c0ed23 100644 --- a/src/testapp/enginetest.h +++ b/src/standalone/testapp/enginetest.h @@ -26,7 +26,7 @@ #include "MagnumApplication.h" -#include +#include namespace testapp::enginetest { diff --git a/src/testapp/identifiers.h b/src/standalone/testapp/identifiers.h similarity index 100% rename from src/testapp/identifiers.h rename to src/standalone/testapp/identifiers.h diff --git a/src/testapp/main.cpp b/src/standalone/testapp/main.cpp similarity index 100% rename from src/testapp/main.cpp rename to src/standalone/testapp/main.cpp diff --git a/src/testapp/scenarios.cpp b/src/standalone/testapp/scenarios.cpp similarity index 100% rename from src/testapp/scenarios.cpp rename to src/standalone/testapp/scenarios.cpp diff --git a/src/testapp/scenarios.h b/src/standalone/testapp/scenarios.h similarity index 100% rename from src/testapp/scenarios.h rename to src/standalone/testapp/scenarios.h diff --git a/src/testapp/sessions/common.cpp b/src/standalone/testapp/sessions/common.cpp similarity index 100% rename from src/testapp/sessions/common.cpp rename to src/standalone/testapp/sessions/common.cpp diff --git a/src/testapp/sessions/common.h b/src/standalone/testapp/sessions/common.h similarity index 100% rename from src/testapp/sessions/common.h rename to src/standalone/testapp/sessions/common.h diff --git a/src/testapp/sessions/jolt.cpp b/src/standalone/testapp/sessions/jolt.cpp similarity index 100% rename from src/testapp/sessions/jolt.cpp rename to src/standalone/testapp/sessions/jolt.cpp diff --git a/src/testapp/sessions/jolt.h b/src/standalone/testapp/sessions/jolt.h similarity index 100% rename from src/testapp/sessions/jolt.h rename to src/standalone/testapp/sessions/jolt.h diff --git a/src/testapp/sessions/magnum.cpp b/src/standalone/testapp/sessions/magnum.cpp similarity index 99% rename from src/testapp/sessions/magnum.cpp rename to src/standalone/testapp/sessions/magnum.cpp index 01d1722f..b9200d3e 100644 --- a/src/testapp/sessions/magnum.cpp +++ b/src/standalone/testapp/sessions/magnum.cpp @@ -31,12 +31,12 @@ #include #include -#include -#include -#include +#include +#include +#include #include #include -#include +#include #include #include diff --git a/src/testapp/sessions/magnum.h b/src/standalone/testapp/sessions/magnum.h similarity index 100% rename from src/testapp/sessions/magnum.h rename to src/standalone/testapp/sessions/magnum.h diff --git a/src/testapp/sessions/misc.cpp b/src/standalone/testapp/sessions/misc.cpp similarity index 100% rename from src/testapp/sessions/misc.cpp rename to src/standalone/testapp/sessions/misc.cpp diff --git a/src/testapp/sessions/misc.h b/src/standalone/testapp/sessions/misc.h similarity index 100% rename from src/testapp/sessions/misc.h rename to src/standalone/testapp/sessions/misc.h diff --git a/src/testapp/sessions/physics.cpp b/src/standalone/testapp/sessions/physics.cpp similarity index 100% rename from src/testapp/sessions/physics.cpp rename to src/standalone/testapp/sessions/physics.cpp diff --git a/src/testapp/sessions/physics.h b/src/standalone/testapp/sessions/physics.h similarity index 100% rename from src/testapp/sessions/physics.h rename to src/standalone/testapp/sessions/physics.h diff --git a/src/testapp/sessions/shapes.cpp b/src/standalone/testapp/sessions/shapes.cpp similarity index 100% rename from src/testapp/sessions/shapes.cpp rename to src/standalone/testapp/sessions/shapes.cpp diff --git a/src/testapp/sessions/shapes.h b/src/standalone/testapp/sessions/shapes.h similarity index 100% rename from src/testapp/sessions/shapes.h rename to src/standalone/testapp/sessions/shapes.h diff --git a/src/testapp/sessions/terrain.cpp b/src/standalone/testapp/sessions/terrain.cpp similarity index 100% rename from src/testapp/sessions/terrain.cpp rename to src/standalone/testapp/sessions/terrain.cpp diff --git a/src/testapp/sessions/terrain.h b/src/standalone/testapp/sessions/terrain.h similarity index 100% rename from src/testapp/sessions/terrain.h rename to src/standalone/testapp/sessions/terrain.h diff --git a/src/testapp/sessions/universe.cpp b/src/standalone/testapp/sessions/universe.cpp similarity index 100% rename from src/testapp/sessions/universe.cpp rename to src/standalone/testapp/sessions/universe.cpp diff --git a/src/testapp/sessions/universe.h b/src/standalone/testapp/sessions/universe.h similarity index 100% rename from src/testapp/sessions/universe.h rename to src/standalone/testapp/sessions/universe.h diff --git a/src/testapp/sessions/vehicles.cpp b/src/standalone/testapp/sessions/vehicles.cpp similarity index 100% rename from src/testapp/sessions/vehicles.cpp rename to src/standalone/testapp/sessions/vehicles.cpp diff --git a/src/testapp/sessions/vehicles.h b/src/standalone/testapp/sessions/vehicles.h similarity index 100% rename from src/testapp/sessions/vehicles.h rename to src/standalone/testapp/sessions/vehicles.h diff --git a/src/testapp/sessions/vehicles_machines.cpp b/src/standalone/testapp/sessions/vehicles_machines.cpp similarity index 100% rename from src/testapp/sessions/vehicles_machines.cpp rename to src/standalone/testapp/sessions/vehicles_machines.cpp diff --git a/src/testapp/sessions/vehicles_machines.h b/src/standalone/testapp/sessions/vehicles_machines.h similarity index 100% rename from src/testapp/sessions/vehicles_machines.h rename to src/standalone/testapp/sessions/vehicles_machines.h diff --git a/src/testapp/sessions/vehicles_prebuilt.cpp b/src/standalone/testapp/sessions/vehicles_prebuilt.cpp similarity index 100% rename from src/testapp/sessions/vehicles_prebuilt.cpp rename to src/standalone/testapp/sessions/vehicles_prebuilt.cpp diff --git a/src/testapp/sessions/vehicles_prebuilt.h b/src/standalone/testapp/sessions/vehicles_prebuilt.h similarity index 100% rename from src/testapp/sessions/vehicles_prebuilt.h rename to src/standalone/testapp/sessions/vehicles_prebuilt.h diff --git a/src/testapp/testapp.cpp b/src/standalone/testapp/testapp.cpp similarity index 100% rename from src/testapp/testapp.cpp rename to src/standalone/testapp/testapp.cpp diff --git a/src/testapp/testapp.h b/src/standalone/testapp/testapp.h similarity index 100% rename from src/testapp/testapp.h rename to src/standalone/testapp/testapp.h diff --git a/src/testapp/sessions/newton.cpp b/src/testapp/sessions/newton.cpp deleted file mode 100644 index 3cc0ba9a..00000000 --- a/src/testapp/sessions/newton.cpp +++ /dev/null @@ -1,715 +0,0 @@ -/** - * Open Space Program - * Copyright © 2019-2022 Open Space Program Project - * - * MIT License - * - * 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. - */ -#include "newton.h" -#include "physics.h" -#include "shapes.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -using namespace osp; -using namespace osp::active; -using namespace osp::link; -using namespace ospnewton; - -using osp::restypes::gc_importer; -using Corrade::Containers::arrayView; - -namespace testapp::scenes -{ - - -Session setup_newton( - TopTaskBuilder& rBuilder, - ArrayView const topData, - osp::Session const& scene, - Session const& commonScene, - Session const& physics) -{ - OSP_DECLARE_GET_DATA_IDS(scene, TESTAPP_DATA_SCENE); - OSP_DECLARE_GET_DATA_IDS(commonScene, TESTAPP_DATA_COMMON_SCENE); - OSP_DECLARE_GET_DATA_IDS(physics, TESTAPP_DATA_PHYSICS); - - auto const tgScn = scene .get_pipelines(); - auto const tgCS = commonScene .get_pipelines(); - auto const tgPhy = physics .get_pipelines(); - - Session out; - OSP_DECLARE_CREATE_DATA_IDS(out, topData, TESTAPP_DATA_NEWTON); - auto const tgNwt = out.create_pipelines(rBuilder); - - rBuilder.pipeline(tgNwt.nwtBody).parent(tgScn.update); - - top_emplace< ACtxNwtWorld >(topData, idNwt, 2); - - using ospnewton::SysNewton; - - rBuilder.task() - .name ("Delete Newton components") - .run_on ({tgCS.activeEntDelete(UseOrRun)}) - .sync_with ({tgNwt.nwtBody(Delete)}) - .push_to (out.m_tasks) - .args({ idNwt, idActiveEntDel }) - .func([] (ACtxNwtWorld& rNwt, ActiveEntVec_t const& rActiveEntDel) noexcept - { - SysNewton::update_delete (rNwt, rActiveEntDel.cbegin(), rActiveEntDel.cend()); - }); - - rBuilder.task() - .name ("Update Newton world") - .run_on ({tgScn.update(Run)}) - .sync_with ({tgNwt.nwtBody(Prev), tgCS.hierarchy(Prev), tgPhy.physBody(Prev), tgPhy.physUpdate(Run), tgCS.transform(Prev)}) - .push_to (out.m_tasks) - .args({ idBasic, idPhys, idNwt, idDeltaTimeIn }) - .func([] (ACtxBasic& rBasic, ACtxPhysics& rPhys, ACtxNwtWorld& rNwt, float const deltaTimeIn, WorkerContext ctx) noexcept - { - SysNewton::update_world(rPhys, rNwt, deltaTimeIn, rBasic.m_scnGraph, rBasic.m_transform); - }); - - top_emplace< ACtxNwtWorld >(topData, idNwt, 2); - - return out; -} // setup_newton - - - - -osp::Session setup_newton_factors( - TopTaskBuilder& rBuilder, - ArrayView topData) -{ - Session out; - OSP_DECLARE_CREATE_DATA_IDS(out, topData, TESTAPP_DATA_NEWTON_FORCES); - - auto &rFactors = top_emplace(topData, idNwtFactors); - - std::fill(rFactors.begin(), rFactors.end(), 0); - - return out; -} // setup_newton_factors - - - - -osp::Session setup_newton_force_accel( - TopTaskBuilder& rBuilder, - ArrayView topData, - Session const& newton, - Session const& nwtFactors, - Vector3 accel) -{ - using UserData_t = ACtxNwtWorld::ForceFactorFunc::UserData_t; - OSP_DECLARE_GET_DATA_IDS(newton, TESTAPP_DATA_NEWTON); - OSP_DECLARE_GET_DATA_IDS(nwtFactors, TESTAPP_DATA_NEWTON_FORCES); - - auto &rNwt = top_get(topData, idNwt); - - Session nwtAccel; - OSP_DECLARE_CREATE_DATA_IDS(nwtAccel, topData, TESTAPP_DATA_NEWTON_ACCEL); - - auto &rAccel = top_emplace(topData, idAcceleration, accel); - - ACtxNwtWorld::ForceFactorFunc const factor - { - .m_func = [] (NewtonBody const* pBody, BodyId const bodyID, ACtxNwtWorld const& rNwt, UserData_t data, Vector3& rForce, Vector3& rTorque) noexcept - { - float mass = 0.0f; - float dummy = 0.0f; - NewtonBodyGetMass(pBody, &mass, &dummy, &dummy, &dummy); - - auto const& force = *reinterpret_cast(data[0]); - rForce += force * mass; - }, - .m_userData = {&rAccel} - }; - - // Register force - - std::size_t const index = rNwt.m_factors.size(); - rNwt.m_factors.emplace_back(factor); - - auto factorBits = lgrn::bit_view(top_get(topData, idNwtFactors)); - factorBits.set(index); - - return nwtAccel; -} // setup_newton_force_accel - - - - -Session setup_phys_shapes_newton( - TopTaskBuilder& rBuilder, - ArrayView const topData, - Session const& commonScene, - Session const& physics, - Session const& physShapes, - Session const& newton, - Session const& nwtFactors) -{ - - OSP_DECLARE_GET_DATA_IDS(commonScene, TESTAPP_DATA_COMMON_SCENE); - OSP_DECLARE_GET_DATA_IDS(physics, TESTAPP_DATA_PHYSICS); - OSP_DECLARE_GET_DATA_IDS(physShapes, TESTAPP_DATA_PHYS_SHAPES); - OSP_DECLARE_GET_DATA_IDS(newton, TESTAPP_DATA_NEWTON); - OSP_DECLARE_GET_DATA_IDS(nwtFactors, TESTAPP_DATA_NEWTON_FORCES); - - auto const tgPhy = physics .get_pipelines(); - auto const tgShSp = physShapes .get_pipelines(); - auto const tgNwt = newton .get_pipelines(); - - Session out; - - rBuilder.task() - .name ("Add Newton physics to spawned shapes") - .run_on ({tgShSp.spawnRequest(UseOrRun)}) - .sync_with ({tgShSp.spawnedEnts(UseOrRun), tgNwt.nwtBody(New), tgPhy.physUpdate(Done)}) - .push_to (out.m_tasks) - .args({ idBasic, idPhysShapes, idPhys, idNwt, idNwtFactors }) - .func([] (ACtxBasic const &rBasic, ACtxPhysShapes& rPhysShapes, ACtxPhysics& rPhys, ACtxNwtWorld& rNwt, ForceFactors_t nwtFactors) noexcept - { - for (std::size_t i = 0; i < rPhysShapes.m_spawnRequest.size(); ++i) - { - SpawnShape const &spawn = rPhysShapes.m_spawnRequest[i]; - ActiveEnt const root = rPhysShapes.m_ents[i * 2]; - ActiveEnt const child = rPhysShapes.m_ents[i * 2 + 1]; - - NwtColliderPtr_t pCollision{ SysNewton::create_primative(rNwt, spawn.m_shape) }; - SysNewton::orient_collision(pCollision.get(), spawn.m_shape, {0.0f, 0.0f, 0.0f}, Matrix3{}, spawn.m_size); - NewtonBody *pBody = NewtonCreateDynamicBody(rNwt.m_world.get(), pCollision.get(), Matrix4{}.data()); - - BodyId const bodyId = rNwt.m_bodyIds.create(); - SysNewton::resize_body_data(rNwt); - - rNwt.m_bodyPtrs[bodyId].reset(pBody); - - rNwt.m_bodyToEnt[bodyId] = root; - rNwt.m_bodyFactors[bodyId] = nwtFactors; - rNwt.m_entToBody.emplace(root, bodyId); - - Vector3 const inertia = collider_inertia_tensor(spawn.m_shape, spawn.m_size, spawn.m_mass); - - NewtonBodySetMassMatrix(pBody, spawn.m_mass, inertia.x(), inertia.y(), inertia.z()); - NewtonBodySetMatrix(pBody, Matrix4::translation(spawn.m_position).data()); - NewtonBodySetLinearDamping(pBody, 0.0f); - NewtonBodySetForceAndTorqueCallback(pBody, &SysNewton::cb_force_torque); - NewtonBodySetTransformCallback(pBody, &SysNewton::cb_set_transform); - SysNewton::set_userdata_bodyid(pBody, bodyId); - } - }); - - return out; -} // setup_phys_shapes_newton - - - - - -void compound_collect_recurse( - ACtxPhysics const& rCtxPhys, - ACtxNwtWorld& rCtxWorld, - ACtxBasic const& rBasic, - ActiveEnt ent, - Matrix4 const& transform, - NewtonCollision* pCompound) -{ - EShape const shape = rCtxPhys.m_shape[ent]; - - if (shape != EShape::None) - { - NwtColliderPtr_t &rPtr = rCtxWorld.m_colliders.contains(ent) - ? rCtxWorld.m_colliders.get(ent) - : rCtxWorld.m_colliders.emplace(ent); - - if (rPtr.get() == nullptr) - { - rPtr = SysNewton::create_primative(rCtxWorld, shape); - } - - SysNewton::orient_collision(rPtr.get(), shape, transform.translation(), transform.rotation(), transform.scaling()); - NewtonCompoundCollisionAddSubCollision(pCompound, rPtr.get()); - } - - if ( ! rCtxPhys.m_hasColliders.contains(ent) ) - { - return; - } - - // Recurse into children if there are more colliders - for (ActiveEnt child : SysSceneGraph::children(rBasic.m_scnGraph, ent)) - { - if (rBasic.m_transform.contains(child)) - { - ACompTransform const &rChildTransform = rBasic.m_transform.get(child); - - Matrix4 const childMatrix = transform * rChildTransform.m_transform; - - compound_collect_recurse( - rCtxPhys, rCtxWorld, rBasic, child, childMatrix, pCompound); - } - } -} - - - -Session setup_vehicle_spawn_newton( - TopTaskBuilder& rBuilder, - ArrayView const topData, - Session const& application, - Session const& commonScene, - Session const& physics, - Session const& prefabs, - Session const& parts, - Session const& vehicleSpawn, - Session const& newton) -{ - OSP_DECLARE_GET_DATA_IDS(application, TESTAPP_DATA_APPLICATION); - OSP_DECLARE_GET_DATA_IDS(commonScene, TESTAPP_DATA_COMMON_SCENE); - OSP_DECLARE_GET_DATA_IDS(physics, TESTAPP_DATA_PHYSICS); - OSP_DECLARE_GET_DATA_IDS(prefabs, TESTAPP_DATA_PREFABS); - OSP_DECLARE_GET_DATA_IDS(vehicleSpawn, TESTAPP_DATA_VEHICLE_SPAWN); - OSP_DECLARE_GET_DATA_IDS(newton, TESTAPP_DATA_NEWTON); - OSP_DECLARE_GET_DATA_IDS(parts, TESTAPP_DATA_PARTS); - auto const tgCS = commonScene .get_pipelines(); - auto const tgPhy = physics .get_pipelines(); - auto const tgPf = prefabs .get_pipelines(); - auto const tgParts = parts .get_pipelines(); - auto const tgVhSp = vehicleSpawn .get_pipelines(); - auto const tgNwt = newton .get_pipelines(); - - Session out; - - rBuilder.task() - .name ("Create root ActiveEnts for each Weld") - .run_on ({tgVhSp.spawnRequest(UseOrRun)}) - .sync_with ({tgCS.activeEnt(New), tgCS.activeEntResized(Schedule), tgParts.mapWeldActive(Modify), tgVhSp.rootEnts(Resize)}) - .push_to (out.m_tasks) - .args ({ idBasic, idVehicleSpawn, idScnParts}) - .func([] (ACtxBasic& rBasic, ACtxVehicleSpawn& rVehicleSpawn, ACtxParts& rScnParts) noexcept - { - LGRN_ASSERT(rVehicleSpawn.new_vehicle_count() != 0); - - rVehicleSpawn.rootEnts.resize(rVehicleSpawn.spawnedWelds.size()); - rBasic.m_activeIds.create(rVehicleSpawn.rootEnts.begin(), rVehicleSpawn.rootEnts.end()); - - // update WeldId->ActiveEnt mapping - auto itWeldEnt = rVehicleSpawn.rootEnts.begin(); - for (WeldId const weld : rVehicleSpawn.spawnedWelds) - { - rScnParts.weldToActive[weld] = *itWeldEnt; - ++itWeldEnt; - } - }); - - rBuilder.task() - .name ("Add vehicle entities to Scene Graph") - .run_on ({tgVhSp.spawnRequest(UseOrRun)}) - .sync_with ({tgVhSp.rootEnts(UseOrRun), tgParts.mapWeldActive(Ready), tgPf.spawnedEnts(UseOrRun), tgPf.spawnRequest(UseOrRun), tgPf.inSubtree(Run), tgCS.transform(Ready), tgCS.hierarchy(Modify)}) - .push_to (out.m_tasks) - .args ({ idBasic, idVehicleSpawn, idScnParts, idPrefabs, idResources}) - .func([] (ACtxBasic& rBasic, ACtxVehicleSpawn const& rVehicleSpawn, ACtxParts& rScnParts, ACtxPrefabs& rPrefabs, Resources& rResources) noexcept - { - LGRN_ASSERT(rVehicleSpawn.new_vehicle_count() != 0); - - // ActiveEnts created for welds + ActiveEnts created for vehicle prefabs - std::size_t const totalEnts = rVehicleSpawn.rootEnts.size() + rPrefabs.newEnts.size(); - - auto const& itWeldsFirst = rVehicleSpawn.spawnedWelds.begin(); - auto const& itWeldOffsetsLast = rVehicleSpawn.spawnedWeldOffsets.end(); - auto itWeldOffsets = rVehicleSpawn.spawnedWeldOffsets.begin(); - - rBasic.m_scnGraph.resize(rBasic.m_activeIds.capacity()); - - for (ACtxVehicleSpawn::TmpToInit const& toInit : rVehicleSpawn.spawnRequest) - { - auto const itWeldOffsetsNext = std::next(itWeldOffsets); - SpWeldId const weldOffsetNext = (itWeldOffsetsNext != itWeldOffsetsLast) - ? (*itWeldOffsetsNext) - : SpWeldId(uint32_t(rVehicleSpawn.spawnedWelds.size())); - - std::for_each(itWeldsFirst + std::ptrdiff_t{*itWeldOffsets}, - itWeldsFirst + std::ptrdiff_t{weldOffsetNext}, - [&rBasic, &rScnParts, &rVehicleSpawn, &rPrefabs, &rResources, &toInit] (WeldId const weld) - { - // Count parts in this weld first - std::size_t entCount = 0; - for (PartId const part : rScnParts.weldToParts[weld]) - { - SpPartId const newPart = rVehicleSpawn.partToSpawned[part]; - uint32_t const prefabInit = rVehicleSpawn.spawnedPrefabs[newPart]; - entCount += rPrefabs.spawnedEntsOffset[prefabInit].size(); - } - - ActiveEnt const weldEnt = rScnParts.weldToActive[weld]; - - rBasic.m_transform.emplace(weldEnt, Matrix4::from(toInit.rotation.toMatrix(), toInit.position)); - - SubtreeBuilder bldRoot = SysSceneGraph::add_descendants(rBasic.m_scnGraph, entCount + 1); - SubtreeBuilder bldWeld = bldRoot.add_child(weldEnt, entCount); - - for (PartId const part : rScnParts.weldToParts[weld]) - { - SpPartId const newPart = rVehicleSpawn.partToSpawned[part]; - uint32_t const prefabInit = rVehicleSpawn.spawnedPrefabs[newPart]; - auto const& basic = rPrefabs.spawnRequest[prefabInit]; - auto const& ents = rPrefabs.spawnedEntsOffset[prefabInit]; - - SysPrefabInit::add_to_subtree(basic, ents, rResources, bldWeld); - } - }); - - itWeldOffsets = itWeldOffsetsNext; - } - }); - - rBuilder.task() - .name ("Add Newton physics to Weld entities") - .run_on ({tgVhSp.spawnRequest(UseOrRun)}) - .sync_with ({tgVhSp.rootEnts(UseOrRun), tgPf.spawnedEnts(UseOrRun), tgCS.transform(Ready), tgPhy.physBody(Ready), tgNwt.nwtBody(New), tgPhy.physUpdate(Done), tgCS.hierarchy(Ready)}) - .push_to (out.m_tasks) - .args ({ idBasic, idPhys, idNwt, idVehicleSpawn, idScnParts}) - .func([] (ACtxBasic& rBasic, ACtxPhysics& rPhys, ACtxNwtWorld& rNwt, ACtxVehicleSpawn const& rVehicleSpawn, ACtxParts const& rScnParts) noexcept - { - LGRN_ASSERT(rVehicleSpawn.new_vehicle_count() != 0); - - rPhys.m_hasColliders.resize(rBasic.m_activeIds.capacity()); - - auto const& itWeldsFirst = std::begin(rVehicleSpawn.spawnedWelds); - auto const& itWeldOffsetsLast = std::end(rVehicleSpawn.spawnedWeldOffsets); - auto itWeldOffsets = std::begin(rVehicleSpawn.spawnedWeldOffsets); - - for (ACtxVehicleSpawn::TmpToInit const& toInit : rVehicleSpawn.spawnRequest) - { - auto const itWeldOffsetsNext = std::next(itWeldOffsets); - SpWeldId const weldOffsetNext = (itWeldOffsetsNext != itWeldOffsetsLast) - ? (*itWeldOffsetsNext) - : SpWeldId(uint32_t(rVehicleSpawn.spawnedWelds.size())); - - std::for_each(itWeldsFirst + std::ptrdiff_t{*itWeldOffsets}, - itWeldsFirst + std::ptrdiff_t{weldOffsetNext}, - [&rBasic, &rScnParts, &rVehicleSpawn, &toInit, &rPhys, &rNwt] (WeldId const weld) - { - ActiveEnt const weldEnt = rScnParts.weldToActive[weld]; - - auto const transform = Matrix4::from(toInit.rotation.toMatrix(), toInit.position); - NwtColliderPtr_t pCompound{ NewtonCreateCompoundCollision(rNwt.m_world.get(), 0) }; - - rPhys.m_hasColliders.insert(weldEnt); - - // Collect all colliders from hierarchy. - NewtonCompoundCollisionBeginAddRemove(pCompound.get()); - compound_collect_recurse( rPhys, rNwt, rBasic, weldEnt, Matrix4{}, pCompound.get() ); - NewtonCompoundCollisionEndAddRemove(pCompound.get()); - - NewtonBody *pBody = NewtonCreateDynamicBody(rNwt.m_world.get(), pCompound.get(), Matrix4{}.data()); - - BodyId const bodyId = rNwt.m_bodyIds.create(); - SysNewton::resize_body_data(rNwt); - - - rNwt.m_bodyPtrs[bodyId].reset(pBody); - rNwt.m_bodyToEnt[bodyId] = weldEnt; - rNwt.m_bodyFactors[bodyId] = {1}; // TODO: temporary - rNwt.m_entToBody.emplace(weldEnt, bodyId); - - float totalMass = 0.0f; - Vector3 massPos{0.0f}; - SysPhysics::calculate_subtree_mass_center(rBasic.m_transform, rPhys, rBasic.m_scnGraph, weldEnt, massPos, totalMass); - - Vector3 const com = massPos / totalMass; - auto const comToOrigin = Matrix4::translation( - com ); - - Matrix3 inertiaTensor{0.0f}; - SysPhysics::calculate_subtree_mass_inertia(rBasic.m_transform, rPhys, rBasic.m_scnGraph, weldEnt, inertiaTensor, comToOrigin); - - Matrix4 const inertiaTensorMat4{inertiaTensor}; - //NewtonBodySetMassMatrix(pBody, 0.0f, 1.0f, 1.0f, 1.0f); - NewtonBodySetFullMassMatrix (pBody, totalMass, inertiaTensorMat4.data()); - NewtonBodySetCentreOfMass (pBody, com.data()); - NewtonBodySetGyroscopicTorque (pBody, 1); - NewtonBodySetMatrix (pBody, transform.data()); - NewtonBodySetLinearDamping (pBody, 0.0f); - NewtonBodySetAngularDamping (pBody, Vector3{0.0f}.data()); - NewtonBodySetForceAndTorqueCallback (pBody, &SysNewton::cb_force_torque); - NewtonBodySetTransformCallback (pBody, &SysNewton::cb_set_transform); - SysNewton::set_userdata_bodyid (pBody, bodyId); - - rPhys.m_setVelocity.emplace_back(weldEnt, toInit.velocity); - }); - - itWeldOffsets = itWeldOffsetsNext; - } - }); - - return out; -} // setup_vehicle_spawn_newton - - -struct BodyRocket -{ - Quaternion m_rotation; - Vector3 m_offset; - - MachLocalId m_local {lgrn::id_null()}; - NodeId m_throttleIn {lgrn::id_null()}; - NodeId m_multiplierIn {lgrn::id_null()}; -}; - -struct ACtxRocketsNwt -{ - // map each bodyId to a {machine, offset} - lgrn::IntArrayMultiMap m_bodyRockets; - -}; - -static void assign_rockets( - ACtxBasic const& rBasic, - ACtxParts const& rScnParts, - ACtxNwtWorld& rNwt, - ACtxRocketsNwt& rRocketsNwt, - Nodes const& rFloatNodes, - PerMachType const& machtypeRocket, - ForceFactors_t const& rNwtFactors, - WeldId const weld, - std::vector& rTemp) -{ - using adera::gc_mtMagicRocket; - using adera::ports_magicrocket::gc_throttleIn; - using adera::ports_magicrocket::gc_multiplierIn; - - ActiveEnt const weldEnt = rScnParts.weldToActive[weld]; - BodyId const body = rNwt.m_entToBody.at(weldEnt); - - if (rRocketsNwt.m_bodyRockets.contains(body)) - { - rRocketsNwt.m_bodyRockets.erase(body); - } - - for (PartId const part : rScnParts.weldToParts[weld]) - { - auto const sizeBefore = rTemp.size(); - - for (MachinePair const pair : rScnParts.partToMachines[part]) - { - if (pair.type != gc_mtMagicRocket) - { - continue; // This machine is not a rocket - } - - MachAnyId const mach = machtypeRocket.localToAny[pair.local]; - auto const& portSpan = rFloatNodes.machToNode[mach]; - NodeId const throttleIn = connected_node(portSpan, gc_throttleIn.port); - NodeId const multiplierIn = connected_node(portSpan, gc_multiplierIn.port); - - if ( (throttleIn == lgrn::id_null()) - || (multiplierIn == lgrn::id_null()) ) - { - continue; // Throttle and/or multiplier is not connected - } - - BodyRocket &rBodyRocket = rTemp.emplace_back(); - rBodyRocket.m_local = pair.local; - rBodyRocket.m_throttleIn = throttleIn; - rBodyRocket.m_multiplierIn = multiplierIn; - } - - if (sizeBefore == rTemp.size()) - { - continue; // No rockets found - } - - // calculate transform relative to body root - // start from part, then walk parents up - ActiveEnt const partEnt = rScnParts.partToActive[part]; - - Matrix4 transform = rBasic.m_transform.get(partEnt).m_transform; - ActiveEnt parent = rBasic.m_scnGraph.m_entParent[partEnt]; - - while (parent != weldEnt) - { - Matrix4 const& parentTransform = rBasic.m_transform.get(parent).m_transform; - transform = parentTransform * transform; - parent = rBasic.m_scnGraph.m_entParent[parent]; - } - - auto const rotation = Quaternion::fromMatrix(transform.rotation()); - Vector3 const offset = transform.translation(); - - for (BodyRocket &rBodyRocket : arrayView(rTemp).exceptPrefix(sizeBefore)) - { - rBodyRocket.m_rotation = rotation; - rBodyRocket.m_offset = offset; - } - } - - ForceFactors_t &rBodyFactors = rNwt.m_bodyFactors[body]; - - // TODO: Got lazy, eventually iterate ForceFactors_t instead of - // just using [0]. This breaks if more factor bits are added - static_assert(ForceFactors_t{}.size() == 1u); - - if ( rTemp.empty() ) - { - rBodyFactors[0] &= ~rNwtFactors[0]; - return; - } - - rBodyFactors[0] |= rNwtFactors[0]; - - rRocketsNwt.m_bodyRockets.emplace(body, rTemp.begin(), rTemp.end()); - rTemp.clear(); -} - -// ACtxNwtWorld::ForceFactorFunc::Func_t -static void rocket_thrust_force(NewtonBody const* pBody, BodyId const body, ACtxNwtWorld const& rNwt, ACtxNwtWorld::ForceFactorFunc::UserData_t data, Vector3& rForce, Vector3& rTorque) noexcept -{ - auto const& rRocketsNwt = *reinterpret_cast (data[0]); - auto const& rMachines = *reinterpret_cast (data[1]); - auto const& rSigValFloat = *reinterpret_cast const*> (data[2]); - - auto &rBodyRockets = rRocketsNwt.m_bodyRockets[body]; - - if (rBodyRockets.empty()) - { - return; - } - - std::array nwtRot; // quaternion xyzw - NewtonBodyGetRotation(pBody, nwtRot.data()); - Quaternion const rot{{nwtRot[0], nwtRot[1], nwtRot[2]}, nwtRot[3]}; - - Vector3 com; - NewtonBodyGetCentreOfMass(pBody, com.data()); - - for (BodyRocket const& bodyRocket : rBodyRockets) - { - float const throttle = std::clamp(rSigValFloat[bodyRocket.m_throttleIn], 0.0f, 1.0f); - float const multiplier = rSigValFloat[bodyRocket.m_multiplierIn]; - - float const thrustMag = throttle * multiplier; - - if (thrustMag == 0.0f) - { - continue; - } - - Vector3 const offsetRel = rot.transformVector(bodyRocket.m_offset - com); - - Vector3 const direction = (rot * bodyRocket.m_rotation).transformVector(adera::gc_rocketForward); - - Vector3 const thrustForce = direction * thrustMag; - Vector3 const thrustTorque = Magnum::Math::cross(offsetRel, thrustForce); - - rForce += thrustForce; - rTorque += thrustTorque; - } -} - -Session setup_rocket_thrust_newton( - TopTaskBuilder& rBuilder, - ArrayView const topData, - Session const& scene, - Session const& commonScene, - Session const& physics, - Session const& prefabs, - Session const& parts, - Session const& signalsFloat, - Session const& newton, - Session const& nwtFactors) -{ - OSP_DECLARE_GET_DATA_IDS(scene, TESTAPP_DATA_SCENE); - OSP_DECLARE_GET_DATA_IDS(commonScene, TESTAPP_DATA_COMMON_SCENE); - OSP_DECLARE_GET_DATA_IDS(physics, TESTAPP_DATA_PHYSICS); - OSP_DECLARE_GET_DATA_IDS(parts, TESTAPP_DATA_PARTS); - OSP_DECLARE_GET_DATA_IDS(signalsFloat, TESTAPP_DATA_SIGNALS_FLOAT) - OSP_DECLARE_GET_DATA_IDS(newton, TESTAPP_DATA_NEWTON); - OSP_DECLARE_GET_DATA_IDS(nwtFactors, TESTAPP_DATA_NEWTON_FORCES); - auto const tgScn = scene .get_pipelines(); - auto const tgParts = parts .get_pipelines(); - auto const tgNwt = newton .get_pipelines(); - - Session out; - OSP_DECLARE_CREATE_DATA_IDS(out, topData, TESTAPP_DATA_ROCKETS_NWT); - - auto &rRocketsNwt = top_emplace< ACtxRocketsNwt >(topData, idRocketsNwt); - - rBuilder.task() - .name ("Assign rockets to Newton bodies") - .run_on ({tgScn.update(Run)}) - .sync_with ({tgParts.weldIds(Ready), tgNwt.nwtBody(Ready), tgParts.connect(Ready)}) - .push_to (out.m_tasks) - .args ({ idBasic, idPhys, idNwt, idScnParts, idRocketsNwt, idNwtFactors}) - .func([] (ACtxBasic& rBasic, ACtxPhysics& rPhys, ACtxNwtWorld& rNwt, ACtxParts const& rScnParts, ACtxRocketsNwt& rRocketsNwt, ForceFactors_t const& rNwtFactors) noexcept - { - using adera::gc_mtMagicRocket; - - Nodes const &rFloatNodes = rScnParts.nodePerType[gc_ntSigFloat]; - PerMachType const& machtypeRocket = rScnParts.machines.perType[gc_mtMagicRocket]; - - rRocketsNwt.m_bodyRockets.ids_reserve(rNwt.m_bodyIds.size()); - rRocketsNwt.m_bodyRockets.data_reserve(rScnParts.machines.perType[gc_mtMagicRocket].localIds.capacity()); - - std::vector temp; - - for (WeldId const weld : rScnParts.weldDirty) - { - assign_rockets(rBasic, rScnParts, rNwt, rRocketsNwt, rFloatNodes, machtypeRocket, rNwtFactors, weld, temp); - } - }); - - auto &rScnParts = top_get< ACtxParts > (topData, idScnParts); - auto &rSigValFloat = top_get< SignalValues_t > (topData, idSigValFloat); - Machines &rMachines = rScnParts.machines; - - - ACtxNwtWorld::ForceFactorFunc const factor - { - .m_func = &rocket_thrust_force, - .m_userData = { &rRocketsNwt, &rMachines, &rSigValFloat } - }; - - auto &rNwt = top_get(topData, idNwt); - - std::size_t const index = rNwt.m_factors.size(); - rNwt.m_factors.emplace_back(factor); - - auto factorBits = lgrn::bit_view(top_get(topData, idNwtFactors)); - factorBits.set(index); - - return out; -} // setup_rocket_thrust_newton - - -} // namespace testapp::scenes - - diff --git a/src/testapp/sessions/newton.h b/src/testapp/sessions/newton.h deleted file mode 100644 index 18a659ee..00000000 --- a/src/testapp/sessions/newton.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Open Space Program - * Copyright © 2019-2022 Open Space Program Project - * - * MIT License - * - * 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. - */ -#pragma once - -#include "../scenarios.h" - -#include -#include -#include -#include -#include - -#include - -#include - -namespace testapp::scenes -{ - -/** - * @brief Newton Dynamics physics integration - */ -osp::Session setup_newton( - osp::TopTaskBuilder& rBuilder, - osp::ArrayView topData, - osp::Session const& scene, - osp::Session const& commonScene, - osp::Session const& physics); - -/** - * @brief Create a single empty force factor bitset - * - * This is a simple bitset that can be assigned to a rigid body to set which - * functions contribute to its force and torque - */ -osp::Session setup_newton_factors( - osp::TopTaskBuilder& rBuilder, - osp::ArrayView topData); - -/** - * @brief Setup constant acceleration force, add to a force factor bitset - */ -osp::Session setup_newton_force_accel( - osp::TopTaskBuilder& rBuilder, - osp::ArrayView topData, - osp::Session const& newton, - osp::Session const& nwtFactors, - osp::Vector3 accel); - -/** - * @brief Support for Shape Spawner physics using Newton Dynamics - */ -osp::Session setup_phys_shapes_newton( - osp::TopTaskBuilder& rBuilder, - osp::ArrayView topData, - osp::Session const& commonScene, - osp::Session const& physics, - osp::Session const& physShapes, - osp::Session const& newton, - osp::Session const& nwtFactors); - -/** - * @brief Support for Vehicle physics using Newton Dynamics - */ -osp::Session setup_vehicle_spawn_newton( - osp::TopTaskBuilder& rBuilder, - osp::ArrayView topData, - osp::Session const& application, - osp::Session const& commonScene, - osp::Session const& physics, - osp::Session const& prefabs, - osp::Session const& parts, - osp::Session const& vehicleSpawn, - osp::Session const& newton); - -/** - * @brief Add thrust forces to Magic Rockets from setup_mach_rocket - */ -osp::Session setup_rocket_thrust_newton( - osp::TopTaskBuilder& rBuilder, - osp::ArrayView topData, - osp::Session const& scene, - osp::Session const& commonScene, - osp::Session const& physics, - osp::Session const& prefabs, - osp::Session const& parts, - osp::Session const& signalsFloat, - osp::Session const& newton, - osp::Session const& nwtFactors); - -} // namespace testapp::scenes