diff options
308 files changed, 10210 insertions, 7654 deletions
diff --git a/.github/workflows/linux_builds.yml b/.github/workflows/linux_builds.yml index 8a49959a30..f6d11e2efe 100644 --- a/.github/workflows/linux_builds.yml +++ b/.github/workflows/linux_builds.yml @@ -34,6 +34,7 @@ jobs: tests: true sconsflags: use_asan=yes use_ubsan=yes proj-test: true + godot-cpp-test: true bin: "./bin/godot.linuxbsd.tools.64s" # Skip 2GiB artifact speeding up action. artifact: false @@ -85,6 +86,15 @@ jobs: run: | ${{ matrix.bin }} --test + # Check class reference + - name: Check for class reference updates + if: ${{ matrix.doc-test }} + run: | + echo "Running --doctool to see if this changes the public API without updating the documentation." + echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n" + ${{ matrix.bin }} --doctool --headless 2>&1 > /dev/null || true + git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$' + # Download, unzip and setup SwiftShader library [4466040] - name: Download SwiftShader if: ${{ matrix.tests }} @@ -95,15 +105,6 @@ jobs: curr="$(pwd)/libvk_swiftshader.so" sed -i "s|PATH_TO_CHANGE|$curr|" vk_swiftshader_icd.json - # Check class reference - - name: Check for class reference updates - if: ${{ matrix.doc-test }} - run: | - echo "Running --doctool to see if this changes the public API without updating the documentation." - echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n" - VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --doctool . 2>&1 > /dev/null || true - git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$' - # Download and extract zip archive with project, folder is renamed to be able to easy change used project - name: Download test project if: ${{ matrix.proj-test }} @@ -126,6 +127,46 @@ jobs: VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} 40 --audio-driver Dummy --path test_project 2>&1 | tee sanitizers_log.txt || true misc/scripts/check_ci_log.py sanitizers_log.txt + # Checkout godot-cpp + - name: Checkout godot-cpp + if: ${{ matrix.godot-cpp-test }} + uses: actions/checkout@v2 + with: + repository: godotengine/godot-cpp + submodules: 'recursive' + path: 'godot-cpp' + + # Check extension API + - name: Check for extension api updates + if: ${{ matrix.godot-cpp-test }} + run: | + echo "Running --dump-extension-api to create extensions api." + VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run ${{ matrix.bin }} --audio-driver Dummy --dump-extension-api 2>&1 > /dev/null || true + misc/scripts/compare_extension_api.py godot-cpp/godot-headers/extension_api.json extension_api.json + + # Copy new extension API files into place + - name: Copy new extension API files into place + if: ${{ matrix.godot-cpp-test }} + run: | + cp -f extension_api.json godot-cpp/godot-headers/ + cp -f core/extension/gdnative_interface.h godot-cpp/godot-headers/godot/ + + # Build godot-cpp library + - name: Build godot-cpp library + if: ${{ matrix.godot-cpp-test }} + run: | + cd godot-cpp + scons target=${{ matrix.target }} generate_bindings=yes -j2 + cd .. + + # Build godot-cpp test extension + - name: Build godot-cpp test extension + if: ${{ matrix.godot-cpp-test }} + run: | + cd godot-cpp/test + scons target=${{ matrix.target }} -j2 + cd ../.. + - name: Prepare artifact if: ${{ matrix.artifact }} run: | diff --git a/.gitignore b/.gitignore index 5b3414fe7e..5a8f6aec40 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ # Documentation generated by doxygen or from classes.xml doc/_build/ +# Extension API dump +extension_api.json + # Javascript specific *.bc diff --git a/core/debugger/engine_debugger.h b/core/debugger/engine_debugger.h index 22c6ef943e..41142bf305 100644 --- a/core/debugger/engine_debugger.h +++ b/core/debugger/engine_debugger.h @@ -128,7 +128,7 @@ public: virtual void poll_events(bool p_is_idle) {} virtual void send_message(const String &p_msg, const Array &p_data) = 0; - virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) = 0; + virtual void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) = 0; virtual void debug(bool p_can_continue = true, bool p_is_error_breakpoint = false) = 0; virtual ~EngineDebugger(); diff --git a/core/debugger/local_debugger.cpp b/core/debugger/local_debugger.cpp index f7e56351b0..60aa3e6be7 100644 --- a/core/debugger/local_debugger.cpp +++ b/core/debugger/local_debugger.cpp @@ -358,7 +358,7 @@ void LocalDebugger::send_message(const String &p_message, const Array &p_args) { // print_line("MESSAGE: '" + p_message + "' - " + String(Variant(p_args))); } -void LocalDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) { +void LocalDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) { print_line("ERROR: '" + (p_descr.is_empty() ? p_err : p_descr) + "'"); } diff --git a/core/debugger/local_debugger.h b/core/debugger/local_debugger.h index e793b2a859..cb59eb82e9 100644 --- a/core/debugger/local_debugger.h +++ b/core/debugger/local_debugger.h @@ -50,7 +50,7 @@ private: public: void debug(bool p_can_continue, bool p_is_error_breakpoint); void send_message(const String &p_message, const Array &p_args); - void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type); + void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type); LocalDebugger(); ~LocalDebugger(); diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index 032c7d55c0..9967d1e361 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -455,7 +455,7 @@ Error RemoteDebugger::_put_msg(String p_message, Array p_data) { return err; } -void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, ErrorHandlerType p_type) { +void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, bool p_editor_notify, ErrorHandlerType p_type) { if (p_type == ERR_HANDLER_SCRIPT) { return; //ignore script errors, those go through debugger } @@ -475,7 +475,7 @@ void RemoteDebugger::_err_handler(void *p_this, const char *p_func, const char * } // send_error will lock internally. - rd->script_debugger->send_error(p_func, p_file, p_line, p_err, p_descr, p_type, si); + rd->script_debugger->send_error(p_func, p_file, p_line, p_err, p_descr, p_editor_notify, p_type, si); } void RemoteDebugger::_print_handler(void *p_this, const String &p_string, bool p_error) { @@ -605,7 +605,7 @@ void RemoteDebugger::send_message(const String &p_message, const Array &p_args) } } -void RemoteDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type) { +void RemoteDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type) { ErrorMessage oe; oe.error = p_err; oe.error_descr = p_descr; diff --git a/core/debugger/remote_debugger.h b/core/debugger/remote_debugger.h index 28e670747e..73799e3f81 100644 --- a/core/debugger/remote_debugger.h +++ b/core/debugger/remote_debugger.h @@ -89,7 +89,7 @@ private: PrintHandlerList phl; static void _print_handler(void *p_this, const String &p_string, bool p_error); ErrorHandlerList eh; - static void _err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, ErrorHandlerType p_type); + static void _err_handler(void *p_this, const char *p_func, const char *p_file, int p_line, const char *p_err, const char *p_descr, bool p_editor_notify, ErrorHandlerType p_type); ErrorMessage _create_overflow_error(const String &p_what, const String &p_descr); Error _put_msg(String p_message, Array p_data); @@ -111,7 +111,7 @@ public: // Overrides void poll_events(bool p_is_idle); void send_message(const String &p_message, const Array &p_args); - void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type); + void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type); void debug(bool p_can_continue = true, bool p_is_error_breakpoint = false); RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer); diff --git a/core/debugger/script_debugger.cpp b/core/debugger/script_debugger.cpp index 6d1e4ed101..70ec101a03 100644 --- a/core/debugger/script_debugger.cpp +++ b/core/debugger/script_debugger.cpp @@ -100,10 +100,10 @@ void ScriptDebugger::debug(ScriptLanguage *p_lang, bool p_can_continue, bool p_i break_lang = prev; } -void ScriptDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info) { +void ScriptDebugger::send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info) { // Store stack info, this is ugly, but allows us to separate EngineDebugger and ScriptDebugger. There might be a better way. error_stack_info.append_array(p_stack_info); - EngineDebugger::get_singleton()->send_error(p_func, p_file, p_line, p_err, p_descr, p_type); + EngineDebugger::get_singleton()->send_error(p_func, p_file, p_line, p_err, p_descr, p_editor_notify, p_type); error_stack_info.resize(0); } diff --git a/core/debugger/script_debugger.h b/core/debugger/script_debugger.h index 9f034a5e5d..c1d0170334 100644 --- a/core/debugger/script_debugger.h +++ b/core/debugger/script_debugger.h @@ -71,7 +71,7 @@ public: void debug(ScriptLanguage *p_lang, bool p_can_continue = true, bool p_is_error_breakpoint = false); ScriptLanguage *get_break_language() const; - void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info); + void send_error(const String &p_func, const String &p_file, int p_line, const String &p_err, const String &p_descr, bool p_editor_notify, ErrorHandlerType p_type, const Vector<StackInfo> &p_stack_info); Vector<StackInfo> get_error_stack_info() const; ScriptDebugger() {} }; diff --git a/core/error/error_macros.cpp b/core/error/error_macros.cpp index 272dda97d8..719ea8afb5 100644 --- a/core/error/error_macros.cpp +++ b/core/error/error_macros.cpp @@ -65,45 +65,49 @@ void remove_error_handler(ErrorHandlerList *p_handler) { _global_unlock(); } -void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type) { - _err_print_error(p_function, p_file, p_line, p_error, "", p_type); +// Errors without messages. +void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify, ErrorHandlerType p_type) { + _err_print_error(p_function, p_file, p_line, p_error, "", p_editor_notify, p_type); } -void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, ErrorHandlerType p_type) { - _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), "", p_type); +void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify, ErrorHandlerType p_type) { + _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), "", p_editor_notify, p_type); } -void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, ErrorHandlerType p_type) { +// Main error printing function. +void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) { OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, p_message, (Logger::ErrorType)p_type); _global_lock(); ErrorHandlerList *l = error_handler_list; while (l) { - l->errfunc(l->userdata, p_function, p_file, p_line, p_error, p_message, p_type); + l->errfunc(l->userdata, p_function, p_file, p_line, p_error, p_message, p_editor_notify, p_type); l = l->next; } _global_unlock(); } -void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, ErrorHandlerType p_type) { - _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_type); +// Errors with message. (All combinations of p_error and p_message as String or char*.) +void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify, ErrorHandlerType p_type) { + _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message, p_editor_notify, p_type); } -void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, ErrorHandlerType p_type) { - _err_print_error(p_function, p_file, p_line, p_error, p_message.utf8().get_data(), p_type); +void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify, ErrorHandlerType p_type) { + _err_print_error(p_function, p_file, p_line, p_error, p_message.utf8().get_data(), p_editor_notify, p_type); } -void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, ErrorHandlerType p_type) { - _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message.utf8().get_data(), p_type); +void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify, ErrorHandlerType p_type) { + _err_print_error(p_function, p_file, p_line, p_error.utf8().get_data(), p_message.utf8().get_data(), p_editor_notify, p_type); } -void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool fatal) { - String fstr(fatal ? "FATAL: " : ""); +// Index errors. (All combinations of p_message as String or char*.) +void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message, bool p_editor_notify, bool p_fatal) { + String fstr(p_fatal ? "FATAL: " : ""); String err(fstr + "Index " + p_index_str + " = " + itos(p_index) + " is out of bounds (" + p_size_str + " = " + itos(p_size) + ")."); _err_print_error(p_function, p_file, p_line, err.utf8().get_data(), p_message); } -void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool fatal) { - _err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), fatal); +void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify, bool p_fatal) { + _err_print_index_error(p_function, p_file, p_line, p_index, p_size, p_index_str, p_size_str, p_message.utf8().get_data(), p_fatal); } diff --git a/core/error/error_macros.h b/core/error/error_macros.h index 1bed8d366b..4eb862dce2 100644 --- a/core/error/error_macros.h +++ b/core/error/error_macros.h @@ -46,7 +46,7 @@ enum ErrorHandlerType { // Pointer to the error handler printing function. Reassign to any function to have errors printed. // Parameters: userdata, function, file, line, error, explanation, type. -typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, ErrorHandlerType p_type); +typedef void (*ErrorHandlerFunc)(void *, const char *, const char *, int p_line, const char *, const char *, bool p_editor_notify, ErrorHandlerType p_type); struct ErrorHandlerList { ErrorHandlerFunc errfunc = nullptr; @@ -61,14 +61,14 @@ void add_error_handler(ErrorHandlerList *p_handler); void remove_error_handler(ErrorHandlerList *p_handler); // Functions used by the error macros. -void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR); -void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, ErrorHandlerType p_type = ERR_HANDLER_ERROR); -void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR); -void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR); -void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR); -void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, ErrorHandlerType p_type = ERR_HANDLER_ERROR); -void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool fatal = false); -void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool fatal = false); +void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR); +void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR); +void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR); +void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const char *p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR); +void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR); +void _err_print_error(const char *p_function, const char *p_file, int p_line, const String &p_error, const String &p_message, bool p_editor_notify = false, ErrorHandlerType p_type = ERR_HANDLER_ERROR); +void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const char *p_message = "", bool p_editor_notify = false, bool fatal = false); +void _err_print_index_error(const char *p_function, const char *p_file, int p_line, int64_t p_index, int64_t p_size, const char *p_index_str, const char *p_size_str, const String &p_message, bool p_editor_notify = false, bool fatal = false); #ifdef __GNUC__ //#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying @@ -136,6 +136,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li ((void)0) /** + * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. + * If not, prints `m_msg`, notifies in the editor, and the current function returns. + */ +#define ERR_FAIL_INDEX_EDMSG(m_index, m_size, m_msg) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \ + return; \ + } else \ + ((void)0) + +/** * Try using `ERR_FAIL_INDEX_V_MSG`. * Only use this macro if there is no sensible error message. * @@ -161,6 +172,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li ((void)0) /** + * Ensures an integer index `m_index` is less than `m_size` and greater than or equal to 0. + * If not, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`. + */ +#define ERR_FAIL_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \ + if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \ + return m_retval; \ + } else \ + ((void)0) + +/** * Try using `ERR_FAIL_INDEX_MSG` or `ERR_FAIL_INDEX_V_MSG`. * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and * there is no sensible error message. @@ -215,6 +237,16 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li return; \ } else \ ((void)0) +/** + * Ensures an unsigned integer index `m_index` is less than `m_size`. + * If not, prints `m_msg`, notifies in the editor, and the current function returns. + */ +#define ERR_FAIL_UNSIGNED_INDEX_EDMSG(m_index, m_size, m_msg) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \ + return; \ + } else \ + ((void)0) /** * Try using `ERR_FAIL_UNSIGNED_INDEX_V_MSG`. @@ -242,6 +274,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li ((void)0) /** + * Ensures an unsigned integer index `m_index` is less than `m_size`. + * If not, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`. + */ +#define ERR_FAIL_UNSIGNED_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \ + if (unlikely((m_index) >= (m_size))) { \ + _err_print_index_error(FUNCTION_STR, __FILE__, __LINE__, m_index, m_size, _STR(m_index), _STR(m_size), m_msg, true); \ + return m_retval; \ + } else \ + ((void)0) + +/** * Try using `ERR_FAIL_UNSIGNED_INDEX_MSG` or `ERR_FAIL_UNSIGNED_INDEX_V_MSG`. * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and * there is no sensible error message. @@ -298,6 +341,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li ((void)0) /** + * Ensures a pointer `m_param` is not null. + * If it is null, prints `m_msg`, notifies in the editor, and the current function returns. + */ +#define ERR_FAIL_NULL_EDMSG(m_param, m_msg) \ + if (unlikely(m_param == nullptr)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \ + return; \ + } else \ + ((void)0) + +/** * Try using `ERR_FAIL_NULL_V_MSG`. * Only use this macro if there is no sensible error message. * @@ -323,6 +377,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li ((void)0) /** + * Ensures a pointer `m_param` is not null. + * If it is null, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`. + */ +#define ERR_FAIL_NULL_V_EDMSG(m_param, m_retval, m_msg) \ + if (unlikely(m_param == nullptr)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter \"" _STR(m_param) "\" is null.", m_msg, true); \ + return m_retval; \ + } else \ + ((void)0) + +/** * Try using `ERR_FAIL_COND_MSG`. * Only use this macro if there is no sensible error message. * If checking for null use ERR_FAIL_NULL_MSG instead. @@ -353,6 +418,20 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li ((void)0) /** + * Ensures `m_cond` is false. + * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current function returns. + * + * If checking for null use ERR_FAIL_NULL_MSG instead. + * If checking index bounds use ERR_FAIL_INDEX_MSG instead. + */ +#define ERR_FAIL_COND_EDMSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true.", m_msg, true); \ + return; \ + } else \ + ((void)0) + +/** * Try using `ERR_FAIL_COND_V_MSG`. * Only use this macro if there is no sensible error message. * If checking for null use ERR_FAIL_NULL_V_MSG instead. @@ -383,6 +462,20 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li ((void)0) /** + * Ensures `m_cond` is false. + * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current function returns `m_retval`. + * + * If checking for null use ERR_FAIL_NULL_V_MSG instead. + * If checking index bounds use ERR_FAIL_INDEX_V_MSG instead. + */ +#define ERR_FAIL_COND_V_EDMSG(m_cond, m_retval, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Returning: " _STR(m_retval), m_msg, true); \ + return m_retval; \ + } else \ + ((void)0) + +/** * Try using `ERR_CONTINUE_MSG`. * Only use this macro if there is no sensible error message. * @@ -408,6 +501,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li ((void)0) /** + * Ensures `m_cond` is false. + * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current loop continues. + */ +#define ERR_CONTINUE_EDMSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Continuing.", m_msg, true); \ + continue; \ + } else \ + ((void)0) + +/** * Try using `ERR_BREAK_MSG`. * Only use this macro if there is no sensible error message. * @@ -433,6 +537,17 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li ((void)0) /** + * Ensures `m_cond` is false. + * If `m_cond` is true, prints `m_msg`, notifies in the editor, and the current loop breaks. + */ +#define ERR_BREAK_EDMSG(m_cond, m_msg) \ + if (unlikely(m_cond)) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition \"" _STR(m_cond) "\" is true. Breaking.", m_msg, true); \ + break; \ + } else \ + ((void)0) + +/** * Try using `ERR_FAIL_COND_MSG` or `ERR_FAIL_COND_V_MSG`. * Only use this macro if there is no sensible fallback i.e. the error is unrecoverable, and * there is no sensible error message. @@ -491,6 +606,19 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li ((void)0) /** + * Try using `ERR_FAIL_COND_MSG`. + * Only use this macro if more complex error detection or recovery is required. + * + * Prints `m_msg`, notifies in the editor, and the current function returns. + */ +#define ERR_FAIL_EDMSG(m_msg) \ + if (true) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed.", m_msg, true); \ + return; \ + } else \ + ((void)0) + +/** * Try using `ERR_FAIL_COND_V_MSG` or `ERR_FAIL_V_MSG`. * Only use this macro if more complex error detection or recovery is required, and * there is no sensible error message. @@ -518,6 +646,19 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li ((void)0) /** + * Try using `ERR_FAIL_COND_V_MSG`. + * Only use this macro if more complex error detection or recovery is required. + * + * Prints `m_msg`, notifies in the editor, and the current function returns `m_retval`. + */ +#define ERR_FAIL_V_EDMSG(m_retval, m_msg) \ + if (true) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Method/function failed. Returning: " _STR(m_retval), m_msg, true); \ + return m_retval; \ + } else \ + ((void)0) + +/** * Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or ERR_BREAK_MSG. * Only use this macro at the start of a function that has not been implemented yet, or * if more complex error detection or recovery is required. @@ -528,6 +669,16 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg) /** + * Try using `ERR_FAIL_COND_MSG`, `ERR_FAIL_COND_V_MSG`, `ERR_CONTINUE_MSG` or ERR_BREAK_MSG. + * Only use this macro at the start of a function that has not been implemented yet, or + * if more complex error detection or recovery is required. + * + * Prints `m_msg` and notifies the editor. + */ +#define ERR_PRINT_ED(m_msg) \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ) + +/** * Prints `m_msg` once during the application lifetime. */ #define ERR_PRINT_ONCE(m_msg) \ @@ -540,6 +691,19 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li } else \ ((void)0) +/** + * Prints `m_msg` and notifies the editor once during the application lifetime. + */ +#define ERR_PRINT_ONCE_ED(m_msg) \ + if (true) { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true); \ + first_print = false; \ + } \ + } else \ + ((void)0) + // Print warning message macros. /** @@ -548,52 +712,75 @@ void _err_print_index_error(const char *p_function, const char *p_file, int p_li * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ #define WARN_PRINT(m_msg) \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING) + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING) + +/** + * Prints `m_msg` and notifies the editor. + * + * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. + */ +#define WARN_PRINT_ED(m_msg) \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING) /** * Prints `m_msg` once during the application lifetime. * * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ -#define WARN_PRINT_ONCE(m_msg) \ - if (true) { \ - static bool first_print = true; \ - if (first_print) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, ERR_HANDLER_WARNING); \ - first_print = false; \ - } \ - } else \ +#define WARN_PRINT_ONCE(m_msg) \ + if (true) { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, false, ERR_HANDLER_WARNING); \ + first_print = false; \ + } \ + } else \ ((void)0) -// Print deprecated warning message macros. - /** - * Warns that the current function is deprecated. + * Prints `m_msg` and notifies the editor once during the application lifetime. + * + * If warning about deprecated usage, use `WARN_DEPRECATED` or `WARN_DEPRECATED_MSG` instead. */ -#define WARN_DEPRECATED \ - if (true) { \ - static SafeFlag warning_shown; \ - if (!warning_shown.is_set()) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", ERR_HANDLER_WARNING); \ - warning_shown.set(); \ - } \ - } else \ +#define WARN_PRINT_ONCE_ED(m_msg) \ + if (true) { \ + static bool first_print = true; \ + if (first_print) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_msg, true, ERR_HANDLER_WARNING); \ + first_print = false; \ + } \ + } else \ ((void)0) +// Print deprecated warning message macros. + /** - * Warns that the current function is deprecated and prints `m_msg`. + * Warns that the current function is deprecated. */ -#define WARN_DEPRECATED_MSG(m_msg) \ +#define WARN_DEPRECATED \ if (true) { \ static SafeFlag warning_shown; \ if (!warning_shown.is_set()) { \ - _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, ERR_HANDLER_WARNING); \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", false, ERR_HANDLER_WARNING); \ warning_shown.set(); \ } \ } else \ ((void)0) /** + * Warns that the current function is deprecated and prints `m_msg`. + */ +#define WARN_DEPRECATED_MSG(m_msg) \ + if (true) { \ + static SafeFlag warning_shown; \ + if (!warning_shown.is_set()) { \ + _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, false, ERR_HANDLER_WARNING); \ + warning_shown.set(); \ + } \ + } else \ + ((void)0) + +/** * Do not use. * If the application should never reach this point use CRASH_NOW_MSG(m_msg) to explain why. * diff --git a/core/extension/gdnative_interface.cpp b/core/extension/gdnative_interface.cpp index ff09b0b86c..4770c9c65f 100644 --- a/core/extension/gdnative_interface.cpp +++ b/core/extension/gdnative_interface.cpp @@ -51,13 +51,13 @@ static void gdnative_free(void *p_mem) { // Helper print functions. static void gdnative_print_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { - _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_ERROR); + _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_ERROR); } static void gdnative_print_warning(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { - _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_WARNING); + _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_WARNING); } static void gdnative_print_script_error(const char *p_description, const char *p_function, const char *p_file, int32_t p_line) { - _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_SCRIPT); + _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT); } // Variant functions diff --git a/core/input/input.cpp b/core/input/input.cpp index 296aa1f071..c3b43a4274 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -133,6 +133,7 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2())); ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event); ClassDB::bind_method(D_METHOD("set_use_accumulated_input", "enable"), &Input::set_use_accumulated_input); + ClassDB::bind_method(D_METHOD("flush_buffered_events"), &Input::flush_buffered_events); BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); diff --git a/core/input/input.h b/core/input/input.h index 6819fc8eb0..f63138a875 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -265,7 +265,6 @@ public: float get_joy_vibration_duration(int p_device); uint64_t get_joy_vibration_timestamp(int p_device); void joy_connection_changed(int p_idx, bool p_connected, String p_name, String p_guid = ""); - void parse_joypad_mapping(String p_mapping, bool p_update_existing); Vector3 get_gravity() const; Vector3 get_accelerometer() const; diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 1d2b5f19ee..c6448b1e44 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -452,8 +452,13 @@ bool InputEventKey::is_match(const Ref<InputEvent> &p_event, bool p_exact_match) return false; } - return keycode == key->keycode && - (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask()); + if (keycode == 0) { + return physical_keycode == key->physical_keycode && + (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask()); + } else { + return keycode == key->keycode && + (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask()); + } } void InputEventKey::_bind_methods() { diff --git a/core/io/compression.h b/core/io/compression.h index cbfed74124..06f26876e5 100644 --- a/core/io/compression.h +++ b/core/io/compression.h @@ -54,8 +54,6 @@ public: static int get_max_compressed_buffer_size(int p_src_size, Mode p_mode = MODE_ZSTD); static int decompress(uint8_t *p_dst, int p_dst_max_size, const uint8_t *p_src, int p_src_size, Mode p_mode = MODE_ZSTD); static int decompress_dynamic(Vector<uint8_t> *p_dst_vect, int p_max_dst_size, const uint8_t *p_src, int p_src_size, Mode p_mode); - - Compression() {} }; #endif // COMPRESSION_H diff --git a/core/io/logger.cpp b/core/io/logger.cpp index 09539f716c..b68a8b20a5 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -50,7 +50,7 @@ void Logger::set_flush_stdout_on_print(bool value) { _flush_stdout_on_print = value; } -void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) { +void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) { if (!should_log(true)) { return; } @@ -81,7 +81,11 @@ void Logger::log_error(const char *p_function, const char *p_file, int p_line, c err_details = p_code; } - logf_error("%s: %s\n", err_type, err_details); + if (p_editor_notify) { + logf_error("%s: %s\n", err_type, err_details); + } else { + logf_error("USER %s: %s\n", err_type, err_details); + } logf_error(" at: %s (%s:%i) - %s\n", p_function, p_file, p_line, p_code); } @@ -256,7 +260,7 @@ void CompositeLogger::logv(const char *p_format, va_list p_list, bool p_err) { } } -void CompositeLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) { +void CompositeLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) { if (!should_log(true)) { return; } diff --git a/core/io/logger.h b/core/io/logger.h index ccf68562d6..48b073aa45 100644 --- a/core/io/logger.h +++ b/core/io/logger.h @@ -54,7 +54,7 @@ public: static void set_flush_stdout_on_print(bool value); virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0 = 0; - virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR); + virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR); void logf(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; void logf_error(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; @@ -83,7 +83,6 @@ class RotatedFileLogger : public Logger { FileAccess *file = nullptr; - void rotate_file_without_closing(); void close_file(); void clear_old_backups(); void rotate_file(); @@ -103,7 +102,7 @@ public: CompositeLogger(Vector<Logger *> p_loggers); virtual void logv(const char *p_format, va_list p_list, bool p_err) _PRINTF_FORMAT_ATTRIBUTE_2_0; - virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR); + virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type = ERR_ERROR); void add_logger(Logger *p_logger); diff --git a/core/io/resource.cpp b/core/io/resource.cpp index 1cefa52d69..972076e397 100644 --- a/core/io/resource.cpp +++ b/core/io/resource.cpp @@ -136,6 +136,7 @@ String Resource::get_scene_unique_id() const { void Resource::set_name(const String &p_name) { name = p_name; + emit_changed(); } String Resource::get_name() const { diff --git a/core/math/convex_hull.cpp b/core/math/convex_hull.cpp index f67035c803..684814b1ae 100644 --- a/core/math/convex_hull.cpp +++ b/core/math/convex_hull.cpp @@ -594,8 +594,6 @@ private: IntermediateHull() { } - - void print(); }; enum Orientation { NONE, diff --git a/core/math/geometry_2d.h b/core/math/geometry_2d.h index 8e5830f9b3..6010159597 100644 --- a/core/math/geometry_2d.h +++ b/core/math/geometry_2d.h @@ -37,8 +37,6 @@ #include "core/templates/vector.h" class Geometry2D { - Geometry2D(); - public: static real_t get_closest_points_between_segments(const Vector2 &p1, const Vector2 &q1, const Vector2 &p2, const Vector2 &q2, Vector2 &c1, Vector2 &c2) { Vector2 d1 = q1 - p1; // Direction vector of segment S1. diff --git a/core/math/geometry_3d.h b/core/math/geometry_3d.h index 766689e222..6a59b34585 100644 --- a/core/math/geometry_3d.h +++ b/core/math/geometry_3d.h @@ -36,8 +36,6 @@ #include "core/templates/vector.h" class Geometry3D { - Geometry3D(); - public: static void get_closest_points_between_segments(const Vector3 &p1, const Vector3 &p2, const Vector3 &q1, const Vector3 &q2, Vector3 &c1, Vector3 &c2) { // Do the function 'd' as defined by pb. I think it's a dot product of some sort. diff --git a/core/os/memory.h b/core/os/memory.h index f67384a17e..ac56a12330 100644 --- a/core/os/memory.h +++ b/core/os/memory.h @@ -42,7 +42,6 @@ #endif class Memory { - Memory(); #ifdef DEBUG_ENABLED static SafeNumeric<uint64_t> mem_usage; static SafeNumeric<uint64_t> max_usage; diff --git a/core/os/os.cpp b/core/os/os.cpp index 12f85858c3..7404ffdcd5 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -75,12 +75,12 @@ void OS::add_logger(Logger *p_logger) { } } -void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type) { +void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, Logger::ErrorType p_type) { if (!_stderr_enabled) { return; } - _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type); + _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, p_type); } void OS::print(const char *p_format, ...) { diff --git a/core/os/os.h b/core/os/os.h index 29d33ce4f0..6d7bc47407 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -110,7 +110,7 @@ public: static OS *get_singleton(); - void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type = Logger::ERR_ERROR); + void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, Logger::ErrorType p_type = Logger::ERR_ERROR); void print(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; void printerr(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3; diff --git a/core/string/ustring.cpp b/core/string/ustring.cpp index daeb7fbd17..b1e685651e 100644 --- a/core/string/ustring.cpp +++ b/core/string/ustring.cpp @@ -2137,7 +2137,7 @@ int64_t String::hex_to_int() const { s++; } - if (len > 2 && s[0] == '0' && s[1] == 'x') { + if (len > 2 && s[0] == '0' && lower_case(s[1]) == 'x') { s += 2; } @@ -2151,7 +2151,7 @@ int64_t String::hex_to_int() const { } else if (c >= 'a' && c <= 'f') { n = (c - 'a') + 10; } else { - return 0; + ERR_FAIL_COND_V_MSG(true, 0, "Invalid hexadecimal notation character \"" + chr(*s) + "\" in string \"" + *this + "\"."); } // Check for overflow/underflow, with special case to ensure INT64_MIN does not result in error bool overflow = ((hex > INT64_MAX / 16) && (sign == 1 || (sign == -1 && hex != (INT64_MAX >> 4) + 1))) || (sign == -1 && hex == (INT64_MAX >> 4) + 1 && c > '0'); diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 7c8239977f..332d171457 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -763,10 +763,10 @@ </method> <method name="set_drag_forwarding"> <return type="void" /> - <argument index="0" name="target" type="Node" /> + <argument index="0" name="target" type="Object" /> <description> - Forwards the handling of this control's drag and drop to [code]target[/code] node. - Forwarding can be implemented in the target node similar to the methods [method _get_drag_data], [method _can_drop_data], and [method _drop_data] but with two differences: + Forwards the handling of this control's drag and drop to [code]target[/code] object. + Forwarding can be implemented in the target object similar to the methods [method _get_drag_data], [method _can_drop_data], and [method _drop_data] but with two differences: 1. The function name must be suffixed with [b]_fw[/b] 2. The function must take an extra argument that is the control doing the forwarding [codeblocks] diff --git a/doc/classes/DirectionalLight3D.xml b/doc/classes/DirectionalLight3D.xml index 7c006ad3a6..f2a6e5b6f8 100644 --- a/doc/classes/DirectionalLight3D.xml +++ b/doc/classes/DirectionalLight3D.xml @@ -11,7 +11,7 @@ </tutorials> <members> <member name="directional_shadow_blend_splits" type="bool" setter="set_blend_splits" getter="is_blend_splits_enabled" default="false"> - If [code]true[/code], shadow detail is sacrificed in exchange for smoother transitions between splits. + If [code]true[/code], shadow detail is sacrificed in exchange for smoother transitions between splits. This is ignored when [member directional_shadow_mode] is [code]SHADOW_ORTHOGONAL[/code]. </member> <member name="directional_shadow_fade_start" type="float" setter="set_param" getter="get_param" default="0.8"> Proportion of [member directional_shadow_max_distance] at which point the shadow starts to fade. At [member directional_shadow_max_distance] the shadow will disappear. @@ -29,7 +29,7 @@ The distance from camera to shadow split 1. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [code]SHADOW_PARALLEL_2_SPLITS[/code] or [code]SHADOW_PARALLEL_4_SPLITS[/code]. </member> <member name="directional_shadow_split_2" type="float" setter="set_param" getter="get_param" default="0.2"> - The distance from shadow split 1 to split 2. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [code]SHADOW_PARALLEL_2_SPLITS[/code] or [code]SHADOW_PARALLEL_4_SPLITS[/code]. + The distance from shadow split 1 to split 2. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [code]SHADOW_PARALLEL_4_SPLITS[/code]. </member> <member name="directional_shadow_split_3" type="float" setter="set_param" getter="get_param" default="0.5"> The distance from shadow split 2 to split 3. Relative to [member directional_shadow_max_distance]. Only used when [member directional_shadow_mode] is [code]SHADOW_PARALLEL_4_SPLITS[/code]. diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 7a467c03c1..4b43286594 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -13,6 +13,13 @@ Returns the user's clipboard as a string if possible. </description> </method> + <method name="clipboard_get_primary" qualifiers="const"> + <return type="String" /> + <description> + Returns the user's primary clipboard as a string if possible. + [b]Note:[/b] This method is only implemented on Linux. + </description> + </method> <method name="clipboard_set"> <return type="void" /> <argument index="0" name="clipboard" type="String" /> @@ -20,6 +27,14 @@ Sets the user's clipboard content to the given string. </description> </method> + <method name="clipboard_set_primary"> + <return type="void" /> + <argument index="0" name="clipboard_primary" type="String" /> + <description> + Sets the user's primary clipboard content to the given string. + [b]Note:[/b] This method is only implemented on Linux. + </description> + </method> <method name="console_set_visible"> <return type="void" /> <argument index="0" name="console_visible" type="bool" /> diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml index 6af6507606..5f342e6dc2 100644 --- a/doc/classes/EditorProperty.xml +++ b/doc/classes/EditorProperty.xml @@ -73,8 +73,8 @@ <member name="deletable" type="bool" setter="set_deletable" getter="is_deletable" default="false"> Used by the inspector, set to [code]true[/code] when the property can be deleted by the user. </member> - <member name="draw_red" type="bool" setter="set_draw_red" getter="is_draw_red" default="false"> - Used by the inspector, set to [code]true[/code] when the property must draw with error color. This is used for editable children's properties. + <member name="draw_warning" type="bool" setter="set_draw_warning" getter="is_draw_warning" default="false"> + Used by the inspector, set to [code]true[/code] when the property is drawn with the editor theme's warning color. This is used for editable children's properties. </member> <member name="keying" type="bool" setter="set_keying" getter="is_keying" default="false"> Used by the inspector, set to [code]true[/code] when the property can add keys for animation. diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 88e4a67615..1fded42db2 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -37,6 +37,13 @@ Adds a new mapping entry (in SDL2 format) to the mapping database. Optionally update already connected devices. </description> </method> + <method name="flush_buffered_events"> + <return type="void" /> + <description> + Sends all input events which are in the current buffer to the game loop. These events may have been buffered as a result of accumulated input ([method set_use_accumulated_input]) or agile input flushing ([member ProjectSettings.input_devices/buffering/agile_event_flushing]). + The engine will already do this itself at key execution points (at least once per frame). However, this can be useful in advanced cases where you want precise control over the timing of event handling. + </description> + </method> <method name="get_accelerometer" qualifiers="const"> <return type="Vector3" /> <description> diff --git a/doc/classes/Light3D.xml b/doc/classes/Light3D.xml index 52359b0ede..dbda22d618 100644 --- a/doc/classes/Light3D.xml +++ b/doc/classes/Light3D.xml @@ -32,7 +32,7 @@ If [code]true[/code], the light only appears in the editor and will not be visible at runtime. </member> <member name="light_angular_distance" type="float" setter="set_param" getter="get_param" default="0.0"> - The light's angular size in degrees. Only available for [DirectionalLight3D]s. For reference, the Sun from the Earth is approximately [code]0.5[/code]. + The light's angular size in degrees. Increasing this will make shadows softer at greater distances. Only available for [DirectionalLight3D]s. For reference, the Sun from the Earth is approximately [code]0.5[/code]. </member> <member name="light_bake_mode" type="int" setter="set_bake_mode" getter="get_bake_mode" enum="Light3D.BakeMode" default="1"> The light's bake mode. See [enum BakeMode]. diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index 75f2d72396..a37bab9b11 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -222,6 +222,10 @@ [/csharp] [/codeblocks] </member> + <member name="middle_mouse_paste_enabled" type="bool" setter="set_middle_mouse_paste_enabled" getter="is_middle_mouse_paste_enabled" default="true"> + If [code]false[/code], using middle mouse button to paste clipboard will be disabled. + [b]Note:[/b] This method is only implemented on Linux. + </member> <member name="mouse_default_cursor_shape" type="int" setter="set_default_cursor_shape" getter="get_default_cursor_shape" override="true" enum="Control.CursorShape" default="1" /> <member name="placeholder_alpha" type="float" setter="set_placeholder_alpha" getter="get_placeholder_alpha" default="0.6"> Opacity of the [member placeholder_text]. From [code]0[/code] to [code]1[/code]. diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml index e476949360..b100a20963 100644 --- a/doc/classes/NavigationMesh.xml +++ b/doc/classes/NavigationMesh.xml @@ -84,7 +84,7 @@ <member name="agent/max_slope" type="float" setter="set_agent_max_slope" getter="get_agent_max_slope" default="45.0"> The maximum slope that is considered walkable, in degrees. </member> - <member name="agent/radius" type="float" setter="set_agent_radius" getter="get_agent_radius" default="0.6"> + <member name="agent/radius" type="float" setter="set_agent_radius" getter="get_agent_radius" default="1.0"> The distance to erode/shrink the walkable area of the heightfield away from obstructions. [b]Note:[/b] While baking, this value will be rounded up to the nearest multiple of [member cell/size]. </member> diff --git a/doc/classes/SceneTreeTimer.xml b/doc/classes/SceneTreeTimer.xml index f97c5e42b5..b0509a322e 100644 --- a/doc/classes/SceneTreeTimer.xml +++ b/doc/classes/SceneTreeTimer.xml @@ -10,7 +10,7 @@ [gdscript] func some_function(): print("Timer started.") - yield(get_tree().create_timer(1.0), "timeout") + await get_tree().create_timer(1.0).timeout print("Timer ended.") [/gdscript] [csharp] diff --git a/doc/classes/String.xml b/doc/classes/String.xml index 10ce03c4b2..abb68e0d05 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -56,11 +56,11 @@ Converts a string containing a binary number into an integer. Binary strings can either be prefixed with [code]0b[/code] or not, and they can also start with a [code]-[/code] before the optional prefix. [codeblocks] [gdscript] - print("0x101".bin_to_int()) # Prints "5". + print("0b101".bin_to_int()) # Prints "5". print("101".bin_to_int()) # Prints "5". [/gdscript] [csharp] - GD.Print("0x101".BinToInt()); // Prints "5". + GD.Print("0b101".BinToInt()); // Prints "5". GD.Print("101".BinToInt()); // Prints "5". [/csharp] [/codeblocks] diff --git a/doc/classes/Tabs.xml b/doc/classes/TabBar.xml index ded4f0b32f..3ca124bb58 100644 --- a/doc/classes/Tabs.xml +++ b/doc/classes/TabBar.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="Tabs" inherits="Control" version="4.0"> +<class name="TabBar" inherits="Control" version="4.0"> <brief_description> - Tabs control. + Tab bar control. </brief_description> <description> Simple tabs control, similar to [TabContainer] but is only in charge of drawing tabs, not interacting with children. @@ -114,7 +114,7 @@ <method name="get_tabs_rearrange_group" qualifiers="const"> <return type="int" /> <description> - Returns the [Tabs]' rearrange group ID. + Returns the [TabBar]'s rearrange group ID. </description> </method> <method name="move_tab"> @@ -192,7 +192,7 @@ <return type="void" /> <argument index="0" name="group_id" type="int" /> <description> - Defines the rearrange group ID. Choose for each [Tabs] the same value to dragging tabs between [Tabs]. Enable drag with [member drag_to_rearrange_enabled]. + Defines the rearrange group ID. Choose for each [TabBar] the same value to dragging tabs between [TabBar]. Enable drag with [member drag_to_rearrange_enabled]. </description> </method> </methods> @@ -209,10 +209,10 @@ <member name="scrolling_enabled" type="bool" setter="set_scrolling_enabled" getter="get_scrolling_enabled" default="true"> if [code]true[/code], the mouse's scroll wheel can be used to navigate the scroll view. </member> - <member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="Tabs.TabAlign" default="1"> + <member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="TabBar.TabAlign" default="1"> The alignment of all tabs. See [enum TabAlign] for details. </member> - <member name="tab_close_display_policy" type="int" setter="set_tab_close_display_policy" getter="get_tab_close_display_policy" enum="Tabs.CloseButtonDisplayPolicy" default="0"> + <member name="tab_close_display_policy" type="int" setter="set_tab_close_display_policy" getter="get_tab_close_display_policy" enum="TabBar.CloseButtonDisplayPolicy" default="0"> Sets when the close button will appear on the tabs. See [enum CloseButtonDisplayPolicy] for details. </member> </members> diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index a3914b58df..ba3394b54a 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -41,6 +41,13 @@ Override this method to define what happens when the user performs a paste operation. </description> </method> + <method name="_paste_primary_clipboard" qualifiers="virtual"> + <return type="void" /> + <description> + Override this method to define what happens when the user performs a paste operation with middle mouse button. + [b]Note:[/b] This method is only implemented on Linux. + </description> + </method> <method name="add_gutter"> <return type="void" /> <argument index="0" name="at" type="int" default="-1" /> @@ -937,6 +944,10 @@ <member name="language" type="String" setter="set_language" getter="get_language" default=""""> Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead. </member> + <member name="middle_mouse_paste_enabled" type="bool" setter="set_middle_mouse_paste_enabled" getter="is_middle_mouse_paste_enabled" default="true"> + If [code]false[/code], using middle mouse button to paste clipboard will be disabled. + [b]Note:[/b] This method is only implemented on Linux. + </member> <member name="minimap_draw" type="bool" setter="set_draw_minimap" getter="is_drawing_minimap" default="false"> If [code]true[/code], a minimap is shown, providing an outline of your source code. </member> diff --git a/doc/classes/TextParagraph.xml b/doc/classes/TextParagraph.xml index e06dfee698..5bd6b0572c 100644 --- a/doc/classes/TextParagraph.xml +++ b/doc/classes/TextParagraph.xml @@ -199,7 +199,7 @@ Returns width (for horizontal layout) or height (for vertical) of the line of text. </description> </method> - <method name="get_non_wraped_size" qualifiers="const"> + <method name="get_non_wrapped_size" qualifiers="const"> <return type="Vector2" /> <description> Returns the size of the bounding box of the paragraph, without line breaks. diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index d7108c3a2a..e65d5b4533 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -117,6 +117,14 @@ Returns the neighboring cell to the one at coordinates [code]coords[/code], indentified by the [code]neighbor[/code] direction. This method takes into account the different layouts a TileMap can take. </description> </method> + <method name="get_pattern"> + <return type="TileMapPattern" /> + <argument index="0" name="layer" type="int" /> + <argument index="1" name="coords_array" type="Vector2i[]" /> + <description> + Creates a new [TileMapPattern] from the given layer and set of cells. + </description> + </method> <method name="get_surrounding_tiles"> <return type="Vector2i[]" /> <argument index="0" name="coords" type="Vector2i" /> @@ -151,6 +159,15 @@ Returns if a layer Y-sorts its tiles. </description> </method> + <method name="map_pattern"> + <return type="Vector2i" /> + <argument index="0" name="position_in_tilemap" type="Vector2i" /> + <argument index="1" name="coords_in_pattern" type="Vector2i" /> + <argument index="2" name="pattern" type="TileMapPattern" /> + <description> + Returns for the given coodinate [code]coords_in_pattern[/code] in a [TileMapPattern] the corresponding cell coordinates if the pattern was pasted at the [code]position_in_tilemap[/code] coordinates (see [method set_pattern]). This mapping is required as in half-offset tile shapes, the mapping might not work by calculating [code]position_in_tile_map + coords_in_pattern[/code] + </description> + </method> <method name="map_to_world" qualifiers="const"> <return type="Vector2" /> <argument index="0" name="map_position" type="Vector2i" /> @@ -237,6 +254,15 @@ Sets a layers Z-index value. This Z-index is added to each tile's Z-index value. </description> </method> + <method name="set_pattern"> + <return type="void" /> + <argument index="0" name="layer" type="int" /> + <argument index="1" name="position" type="Vector2i" /> + <argument index="2" name="pattern" type="TileMapPattern" /> + <description> + Paste the given [TileMapPattern] at the given [code]position[/code] and [code]layer[/code] in the tile map. + </description> + </method> <method name="world_to_map" qualifiers="const"> <return type="Vector2i" /> <argument index="0" name="world_position" type="Vector2" /> diff --git a/doc/classes/TileMapPattern.xml b/doc/classes/TileMapPattern.xml new file mode 100644 index 0000000000..4c46625423 --- /dev/null +++ b/doc/classes/TileMapPattern.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="TileMapPattern" inherits="Resource" version="4.0"> + <brief_description> + Holds a pattern to be copied from or pasted into [TileMap]s. + </brief_description> + <description> + This resource holds a set of cells to help bulk manipulations of [TileMap]. + A pattern always start at the [code](0,0)[/code] coordinates and cannot have cells with negative coordinates. + </description> + <tutorials> + </tutorials> + <methods> + <method name="get_cell_alternative_tile" qualifiers="const"> + <return type="int" /> + <argument index="0" name="coords" type="Vector2i" /> + <description> + Returns the tile alternative ID of the cell at [code]coords[/code]. + </description> + </method> + <method name="get_cell_atlas_coords" qualifiers="const"> + <return type="Vector2i" /> + <argument index="0" name="coords" type="Vector2i" /> + <description> + Returns the tile atlas coordinates ID of the cell at [code]coords[/code]. + </description> + </method> + <method name="get_cell_source_id" qualifiers="const"> + <return type="int" /> + <argument index="0" name="coords" type="Vector2i" /> + <description> + Returns the tile source ID of the cell at [code]coords[/code]. + </description> + </method> + <method name="get_size" qualifiers="const"> + <return type="Vector2i" /> + <description> + Returns the size, in cells, of the pattern. + </description> + </method> + <method name="get_used_cells" qualifiers="const"> + <return type="Vector2i[]" /> + <description> + Returns the list of used cell coordinates in the pattern. + </description> + </method> + <method name="has_cell" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="coords" type="Vector2i" /> + <description> + Returns whether the pattern has a tile at the given coordinates. + </description> + </method> + <method name="is_empty" qualifiers="const"> + <return type="bool" /> + <description> + Returns whether the pattern is empty or not. + </description> + </method> + <method name="remove_cell"> + <return type="void" /> + <argument index="0" name="coords" type="Vector2i" /> + <argument index="1" name="arg1" type="bool" /> + <description> + Remove the cell at the given coordinates. + </description> + </method> + <method name="set_cell"> + <return type="void" /> + <argument index="0" name="coords" type="Vector2i" /> + <argument index="1" name="source_id" type="int" default="-1" /> + <argument index="2" name="atlas_coords" type="Vector2i" default="Vector2i(-1, -1)" /> + <argument index="3" name="alternative_tile" type="int" default="-1" /> + <description> + Sets the tile indentifiers for the cell at coordinates [code]coords[/code]. See [method TileMap.set_cell]. + </description> + </method> + <method name="set_size"> + <return type="void" /> + <argument index="0" name="size" type="Vector2i" /> + <description> + Sets the size of the pattern. + </description> + </method> + </methods> +</class> diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml index 02baded019..45d6f9ca6c 100644 --- a/doc/classes/TileSet.xml +++ b/doc/classes/TileSet.xml @@ -46,6 +46,14 @@ Occlusion layers allow assigning occlusion polygons to atlas tiles. </description> </method> + <method name="add_pattern"> + <return type="int" /> + <argument index="0" name="pattern" type="TileMapPattern" /> + <argument index="1" name="index" type="int" default="-1" /> + <description> + Adds a [TileMapPattern] to be stored in the TileSet resouce. If provided, insert it at the given [code]index[/code]. + </description> + </method> <method name="add_physics_layer"> <return type="void" /> <argument index="0" name="to_position" type="int" default="-1" /> @@ -154,6 +162,19 @@ Returns the occlusion layers count. </description> </method> + <method name="get_pattern"> + <return type="TileMapPattern" /> + <argument index="0" name="index" type="int" default="-1" /> + <description> + Returns the [TileMapPattern] at the given [code]index[/code]. + </description> + </method> + <method name="get_patterns_count"> + <return type="int" /> + <description> + Returns the number of [TileMapPattern] this tile set handles. + </description> + </method> <method name="get_physics_layer_collision_layer" qualifiers="const"> <return type="int" /> <argument index="0" name="layer_index" type="int" /> @@ -374,6 +395,13 @@ Removes the occlusion layer at index [code]layer_index[/code]. Also updates the atlas tiles accordingly. </description> </method> + <method name="remove_pattern"> + <return type="void" /> + <argument index="0" name="index" type="int" /> + <description> + Remove the [TileMapPattern] at the given index. + </description> + </method> <method name="remove_physics_layer"> <return type="void" /> <argument index="0" name="layer_index" type="int" /> diff --git a/doc/classes/XRAnchor3D.xml b/doc/classes/XRAnchor3D.xml index 94fc8fc13d..2c54c728ed 100644 --- a/doc/classes/XRAnchor3D.xml +++ b/doc/classes/XRAnchor3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="XRAnchor3D" inherits="Node3D" version="4.0"> +<class name="XRAnchor3D" inherits="XRNode3D" version="4.0"> <brief_description> An anchor point in AR space. </brief_description> @@ -11,24 +11,6 @@ <tutorials> </tutorials> <methods> - <method name="get_anchor_name" qualifiers="const"> - <return type="String" /> - <description> - Returns the name given to this anchor. - </description> - </method> - <method name="get_is_active" qualifiers="const"> - <return type="bool" /> - <description> - Returns [code]true[/code] if the anchor is being tracked and [code]false[/code] if no anchor with this ID is currently known. - </description> - </method> - <method name="get_mesh" qualifiers="const"> - <return type="Mesh" /> - <description> - If provided by the [XRInterface], this returns a mesh object for the anchor. For an anchor, this can be a shape related to the object being tracked or it can be a mesh that provides topology related to the anchor and can be used to create shadows/reflections on surfaces or for generating collision shapes. - </description> - </method> <method name="get_plane" qualifiers="const"> <return type="Plane" /> <description> @@ -42,17 +24,4 @@ </description> </method> </methods> - <members> - <member name="anchor_id" type="int" setter="set_anchor_id" getter="get_anchor_id" default="1"> - The anchor's ID. You can set this before the anchor itself exists. The first anchor gets an ID of [code]1[/code], the second an ID of [code]2[/code], etc. When anchors get removed, the engine can then assign the corresponding ID to new anchors. The most common situation where anchors "disappear" is when the AR server identifies that two anchors represent different parts of the same plane and merges them. - </member> - </members> - <signals> - <signal name="mesh_updated"> - <argument index="0" name="mesh" type="Mesh" /> - <description> - Emitted when the mesh associated with the anchor changes or when one becomes available. This is especially important for topology that is constantly being [code]mesh_updated[/code]. - </description> - </signal> - </signals> </class> diff --git a/doc/classes/XRController3D.xml b/doc/classes/XRController3D.xml index 35edf5c2b2..eb91196e00 100644 --- a/doc/classes/XRController3D.xml +++ b/doc/classes/XRController3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="XRController3D" inherits="Node3D" version="4.0"> +<class name="XRController3D" inherits="XRNode3D" version="4.0"> <brief_description> A spatial node representing a spatially-tracked controller. </brief_description> @@ -7,63 +7,41 @@ This is a helper spatial node that is linked to the tracking of controllers. It also offers several handy passthroughs to the state of buttons and such on the controllers. Controllers are linked by their ID. You can create controller nodes before the controllers are available. If your game always uses two controllers (one for each hand), you can predefine the controllers with ID 1 and 2; they will become active as soon as the controllers are identified. If you expect additional controllers to be used, you should react to the signals and add XRController3D nodes to your scene. The position of the controller node is automatically updated by the [XRServer]. This makes this node ideal to add child nodes to visualize the controller. + As many XR runtimes now use a configurable action map all inputs are named. </description> <tutorials> <link title="VR documentation index">https://docs.godotengine.org/en/latest/tutorials/vr/index.html</link> </tutorials> <methods> - <method name="get_controller_name" qualifiers="const"> - <return type="String" /> + <method name="get_axis" qualifiers="const"> + <return type="Vector2" /> + <argument index="0" name="name" type="StringName" /> <description> - If active, returns the name of the associated controller if provided by the AR/VR SDK used. + Returns a [Vector2] for the input with the given [code]name[/code]. This is used for thumbsticks and thumbpads found on many controllers. </description> </method> - <method name="get_is_active" qualifiers="const"> - <return type="bool" /> + <method name="get_tracker_hand" qualifiers="const"> + <return type="int" enum="XRPositionalTracker.TrackerHand" /> <description> - Returns [code]true[/code] if the bound controller is active. XR systems attempt to track active controllers. + Returns the hand holding this controller, if known. See [enum XRPositionalTracker.TrackerHand]. </description> </method> - <method name="get_joystick_axis" qualifiers="const"> + <method name="get_value" qualifiers="const"> <return type="float" /> - <argument index="0" name="axis" type="int" /> - <description> - Returns the value of the given axis for things like triggers, touchpads, etc. that are embedded into the controller. - </description> - </method> - <method name="get_joystick_id" qualifiers="const"> - <return type="int" /> - <description> - Returns the ID of the joystick object bound to this. Every controller tracked by the [XRServer] that has buttons and axis will also be registered as a joystick within Godot. This means that all the normal joystick tracking and input mapping will work for buttons and axis found on the AR/VR controllers. This ID is purely offered as information so you can link up the controller with its joystick entry. - </description> - </method> - <method name="get_mesh" qualifiers="const"> - <return type="Mesh" /> + <argument index="0" name="name" type="StringName" /> <description> - If provided by the [XRInterface], this returns a mesh associated with the controller. This can be used to visualize the controller. - </description> - </method> - <method name="get_tracker_hand" qualifiers="const"> - <return type="int" enum="XRPositionalTracker.TrackerHand" /> - <description> - Returns the hand holding this controller, if known. See [enum XRPositionalTracker.TrackerHand]. + Returns a numeric value for the input with the given [code]name[/code]. This is used for triggers and grip sensors. </description> </method> <method name="is_button_pressed" qualifiers="const"> <return type="bool" /> - <argument index="0" name="button" type="int" /> + <argument index="0" name="name" type="StringName" /> <description> - Returns [code]true[/code] if the button at index [code]button[/code] is pressed. See [enum JoyButton]. + Returns [code]true[/code] if the button with the given [code]name[/code] is pressed. </description> </method> </methods> <members> - <member name="controller_id" type="int" setter="set_controller_id" getter="get_controller_id" default="1"> - The controller's ID. - A controller ID of 0 is unbound and will always result in an inactive node. Controller ID 1 is reserved for the first controller that identifies itself as the left-hand controller and ID 2 is reserved for the first controller that identifies itself as the right-hand controller. - For any other controller that the [XRServer] detects, we continue with controller ID 3. - When a controller is turned off, its slot is freed. This ensures controllers will keep the same ID even when controllers with lower IDs are turned off. - </member> <member name="rumble" type="float" setter="set_rumble" getter="get_rumble" default="0.0"> The degree to which the controller vibrates. Ranges from [code]0.0[/code] to [code]1.0[/code] with precision [code].01[/code]. If changed, updates [member XRPositionalTracker.rumble] accordingly. This is a useful property to animate if you want the controller to vibrate for a limited duration. @@ -71,21 +49,29 @@ </members> <signals> <signal name="button_pressed"> - <argument index="0" name="button" type="int" /> + <argument index="0" name="name" type="String" /> <description> Emitted when a button on this controller is pressed. </description> </signal> <signal name="button_released"> - <argument index="0" name="button" type="int" /> + <argument index="0" name="name" type="String" /> <description> Emitted when a button on this controller is released. </description> </signal> - <signal name="mesh_updated"> - <argument index="0" name="mesh" type="Mesh" /> + <signal name="input_axis_changed"> + <argument index="0" name="name" type="String" /> + <argument index="1" name="value" type="Vector2" /> + <description> + Emitted when a thumbstick or thumbpad on this controller is moved. + </description> + </signal> + <signal name="input_value_changed"> + <argument index="0" name="name" type="String" /> + <argument index="1" name="value" type="float" /> <description> - Emitted when the mesh associated with the controller changes or when one becomes available. Generally speaking this will be a static mesh after becoming available. + Emitted when a trigger or similar input on this controller changes value. </description> </signal> </signals> diff --git a/doc/classes/XRInterface.xml b/doc/classes/XRInterface.xml index ffc2bc138d..7ae70f97a2 100644 --- a/doc/classes/XRInterface.xml +++ b/doc/classes/XRInterface.xml @@ -29,6 +29,12 @@ Returns the name of this interface (OpenXR, OpenVR, OpenHMD, ARKit, etc). </description> </method> + <method name="get_play_area" qualifiers="const"> + <return type="PackedVector3Array" /> + <description> + Returns an array of vectors that denotes the physical play area mapped to the virtual space around the [XROrigin3D] point. The points form a convex polygon that can be used to react to or visualise the play area. This returns an empty array if this feature is not supported or if the information is not yet available. + </description> + </method> <method name="get_render_target_size"> <return type="Vector2" /> <description> @@ -63,6 +69,34 @@ Is [code]true[/code] if this interface has been initialised. </description> </method> + <method name="set_play_area_mode"> + <return type="bool" /> + <argument index="0" name="mode" type="int" enum="XRInterface.PlayAreaMode" /> + <description> + Sets the active play area mode, will return [code]false[/code] if the mode can't be used with this interface. + </description> + </method> + <method name="supports_play_area_mode"> + <return type="bool" /> + <argument index="0" name="mode" type="int" enum="XRInterface.PlayAreaMode" /> + <description> + Call this to find out if a given play area mode is supported by this interface. + </description> + </method> + <method name="trigger_haptic_pulse"> + <return type="void" /> + <argument index="0" name="action_name" type="String" /> + <argument index="1" name="tracker_name" type="StringName" /> + <argument index="2" name="frequency" type="float" /> + <argument index="3" name="amplitude" type="float" /> + <argument index="4" name="duration_sec" type="float" /> + <argument index="5" name="delay_sec" type="float" /> + <description> + Triggers a haptic pulse on a device associated with this interface. + [code]action_name[/code] is the name of the action for this pulse. + [code]tracker_name[/code] is optional and can be used to direct the pulse to a specific device provided that device is bound to this haptic. + </description> + </method> <method name="uninitialize"> <return type="void" /> <description> @@ -77,7 +111,18 @@ <member name="interface_is_primary" type="bool" setter="set_primary" getter="is_primary" default="false"> [code]true[/code] if this is the primary interface. </member> + <member name="xr_play_area_mode" type="int" setter="set_play_area_mode" getter="get_play_area_mode" enum="XRInterface.PlayAreaMode" default="0"> + The play area mode for this interface. + </member> </members> + <signals> + <signal name="play_area_changed"> + <argument index="0" name="mode" type="int" /> + <description> + Emitted when the play area is changed. This can be a result of the player resetting the boundary or entering a new play area, the player changing the play area mode, the world scale changing or the player resetting their headset orientation. + </description> + </signal> + </signals> <constants> <constant name="XR_NONE" value="0" enum="Capabilities"> No XR capabilities. @@ -88,20 +133,17 @@ <constant name="XR_STEREO" value="2" enum="Capabilities"> This interface supports stereoscopic rendering. </constant> - <constant name="XR_AR" value="4" enum="Capabilities"> - This interface supports AR (video background and real world tracking). - </constant> - <constant name="XR_EXTERNAL" value="8" enum="Capabilities"> - This interface outputs to an external device. If the main viewport is used, the on screen output is an unmodified buffer of either the left or right eye (stretched if the viewport size is not changed to the same aspect ratio of [method get_render_target_size]). Using a separate viewport node frees up the main viewport for other purposes. + <constant name="XR_QUAD" value="4" enum="Capabilities"> + This interface supports quad rendering (not yet supported by Godot). </constant> - <constant name="EYE_MONO" value="0" enum="Eyes"> - Mono output, this is mostly used internally when retrieving positioning information for our camera node or when stereo scopic rendering is not supported. + <constant name="XR_VR" value="8" enum="Capabilities"> + this interface supports VR. </constant> - <constant name="EYE_LEFT" value="1" enum="Eyes"> - Left eye output, this is mostly used internally when rendering the image for the left eye and obtaining positioning and projection information. + <constant name="XR_AR" value="16" enum="Capabilities"> + This interface supports AR (video background and real world tracking). </constant> - <constant name="EYE_RIGHT" value="2" enum="Eyes"> - Right eye output, this is mostly used internally when rendering the image for the right eye and obtaining positioning and projection information. + <constant name="XR_EXTERNAL" value="32" enum="Capabilities"> + This interface outputs to an external device. If the main viewport is used, the on screen output is an unmodified buffer of either the left or right eye (stretched if the viewport size is not changed to the same aspect ratio of [method get_render_target_size]). Using a separate viewport node frees up the main viewport for other purposes. </constant> <constant name="XR_NORMAL_TRACKING" value="0" enum="TrackingStatus"> Tracking is behaving as expected. @@ -118,5 +160,20 @@ <constant name="XR_NOT_TRACKING" value="4" enum="TrackingStatus"> Tracking is not functional (camera not plugged in or obscured, lighthouses turned off, etc.). </constant> + <constant name="XR_PLAY_AREA_UNKNOWN" value="0" enum="PlayAreaMode"> + Play area mode not set or not available. + </constant> + <constant name="XR_PLAY_AREA_3DOF" value="1" enum="PlayAreaMode"> + Play area only supports orientation tracking, no positional tracking, area will center around player. + </constant> + <constant name="XR_PLAY_AREA_SITTING" value="2" enum="PlayAreaMode"> + Player is in seated position, limited positional tracking, fixed guardian around player. + </constant> + <constant name="XR_PLAY_AREA_ROOMSCALE" value="3" enum="PlayAreaMode"> + Player is free to move around, full positional tracking. + </constant> + <constant name="XR_PLAY_AREA_STAGE" value="4" enum="PlayAreaMode"> + Same as roomscale but origin point is fixed to the center of the physical space, XRServer.center_on_hmd disabled. + </constant> </constants> </class> diff --git a/doc/classes/XRInterfaceExtension.xml b/doc/classes/XRInterfaceExtension.xml index 84b46e0ddd..d2bb6aa59a 100644 --- a/doc/classes/XRInterfaceExtension.xml +++ b/doc/classes/XRInterfaceExtension.xml @@ -41,6 +41,16 @@ <description> </description> </method> + <method name="_get_play_area" qualifiers="virtual const"> + <return type="PackedVector3Array" /> + <description> + </description> + </method> + <method name="_get_play_area_mode" qualifiers="virtual const"> + <return type="int" /> + <description> + </description> + </method> <method name="_get_projection_for_view" qualifiers="virtual"> <return type="PackedFloat64Array" /> <argument index="0" name="view" type="int" /> @@ -55,6 +65,17 @@ <description> </description> </method> + <method name="_get_suggested_pose_names" qualifiers="virtual const"> + <return type="PackedStringArray" /> + <argument index="0" name="tracker_name" type="StringName" /> + <description> + </description> + </method> + <method name="_get_suggested_tracker_names" qualifiers="virtual const"> + <return type="PackedStringArray" /> + <description> + </description> + </method> <method name="_get_tracking_status" qualifiers="virtual const"> <return type="int" /> <description> @@ -99,6 +120,29 @@ <description> </description> </method> + <method name="_set_play_area_mode" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="mode" type="int" /> + <description> + </description> + </method> + <method name="_supports_play_area_mode" qualifiers="virtual const"> + <return type="bool" /> + <argument index="0" name="mode" type="int" enum="XRInterface.PlayAreaMode" /> + <description> + </description> + </method> + <method name="_trigger_haptic_pulse" qualifiers="virtual"> + <return type="void" /> + <argument index="0" name="action_name" type="String" /> + <argument index="1" name="tracker_name" type="StringName" /> + <argument index="2" name="frequency" type="float" /> + <argument index="3" name="amplitude" type="float" /> + <argument index="4" name="duration_sec" type="float" /> + <argument index="5" name="delay_sec" type="float" /> + <description> + </description> + </method> <method name="_uninitialize" qualifiers="virtual"> <return type="void" /> <description> diff --git a/doc/classes/XRNode3D.xml b/doc/classes/XRNode3D.xml new file mode 100644 index 0000000000..2e6d11d729 --- /dev/null +++ b/doc/classes/XRNode3D.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="XRNode3D" inherits="Node3D" version="4.0"> + <brief_description> + A spatial node that has its position automatically updated by the [XRServer]. + </brief_description> + <description> + This node can be bound to a specific pose of a [XRPositionalTracker] and will automatically have its [member Node3D.transform] updated by the [XRServer]. Nodes of this type must be added as children of the [XROrigin3D] node. + </description> + <tutorials> + </tutorials> + <methods> + <method name="get_has_tracking_data" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if the [member tracker] has current tracking data for the [member pose] being tracked. + </description> + </method> + <method name="get_is_active" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code] if the [member tracker] has been registered and the [member pose] is being tracked. + </description> + </method> + <method name="get_pose"> + <return type="XRPose" /> + <description> + Returns the [XRPose] containing the current state of the pose being tracked. This gives access to additional properties of this pose. + </description> + </method> + <method name="trigger_haptic_pulse"> + <return type="void" /> + <argument index="0" name="action_name" type="String" /> + <argument index="1" name="frequency" type="float" /> + <argument index="2" name="amplitude" type="float" /> + <argument index="3" name="duration_sec" type="float" /> + <argument index="4" name="delay_sec" type="float" /> + <description> + Triggers a haptic pulse on a device associated with this interface. + [code]action_name[/code] is the name of the action for this pulse. + </description> + </method> + </methods> + <members> + <member name="pose" type="StringName" setter="set_pose_name" getter="get_pose_name" default="&"default""> + The name of the pose we're bound to. Which poses a tracker supports is not known during design time. + Godot defines number of standard pose names such as [code]aim[/code] and [code]grip[/code] but other may be configured within a given [XRInterface]. + </member> + <member name="tracker" type="StringName" setter="set_tracker" getter="get_tracker" default="&"""> + The name of the tracker we're bound to. Which trackers are available is not known during design time. + Godot defines a number of standard trackers such as [code]left_hand[/code] and [code]right_hand[/code] but others may be configured within a given [XRInterface]. + </member> + </members> +</class> diff --git a/doc/classes/XRPose.xml b/doc/classes/XRPose.xml new file mode 100644 index 0000000000..0de2bc9e48 --- /dev/null +++ b/doc/classes/XRPose.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="XRPose" inherits="RefCounted" version="4.0"> + <brief_description> + This object contains all data related to a pose on a tracked object. + </brief_description> + <description> + XR runtimes often identify multiple locations on devices such as controllers that are spatially tracked. + Orientation, location, linear velocity and angular velocity are all provided for each pose by the XR runtime. This object contains this state of a pose. + </description> + <tutorials> + </tutorials> + <methods> + <method name="get_adjusted_transform" qualifiers="const"> + <return type="Transform3D" /> + <description> + Returns the [member transform] with world scale and our reference frame applied. This is the transform used to position [XRNode3D] objects. + </description> + </method> + </methods> + <members> + <member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity" default="Vector3(0, 0, 0)"> + The angular velocity for this pose. + </member> + <member name="has_tracking_data" type="bool" setter="set_has_tracking_data" getter="get_has_tracking_data" default="false"> + If [code]true[/code] our tracking data is up to date. If [code]false[/code] we're no longer receiving new tracking data and our state is whatever that last valid state was. + </member> + <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector3(0, 0, 0)"> + The linear velocity of this pose. + </member> + <member name="name" type="StringName" setter="set_name" getter="get_name" default="&"""> + The name of this pose. Pose names are often driven by an action map setup by the user. Godot does suggest a number of pose names that it expects [XRInterface]s to implement: + - [code]root[/code] defines a root location, often used for tracked objects that do not have further nodes. + - [code]aim[/code] defines the tip of a controller with the orientation pointing outwards, for instance: add your raycasts to this. + - [code]grip[/code] defines the location where the user grips the controller + - [code]skeleton[/code] defines the root location a hand mesh should be placed when using hand tracking and the animated skeleton supplied by the XR runtime. + </member> + <member name="transform" type="Transform3D" setter="set_transform" getter="get_transform" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)"> + The transform containing the original and transform as reported by the XR runtime. + </member> + </members> +</class> diff --git a/doc/classes/XRPositionalTracker.xml b/doc/classes/XRPositionalTracker.xml index d231bfde74..bd6a518835 100644 --- a/doc/classes/XRPositionalTracker.xml +++ b/doc/classes/XRPositionalTracker.xml @@ -5,86 +5,113 @@ </brief_description> <description> An instance of this object represents a device that is tracked, such as a controller or anchor point. HMDs aren't represented here as they are handled internally. - As controllers are turned on and the AR/VR interface detects them, instances of this object are automatically added to this list of active tracking objects accessible through the [XRServer]. - The [XRController3D] and [XRAnchor3D] both consume objects of this type and should be used in your project. The positional trackers are just under-the-hood objects that make this all work. These are mostly exposed so that GDNative-based interfaces can interact with them. + As controllers are turned on and the [XRInterface] detects them, instances of this object are automatically added to this list of active tracking objects accessible through the [XRServer]. + The [XRController3D] and [XRAnchor3D] both consume objects of this type and should be used in your project. The positional trackers are just under-the-hood objects that make this all work. These are mostly exposed so that GDExtension-based interfaces can interact with them. </description> <tutorials> <link title="VR documentation index">https://docs.godotengine.org/en/latest/tutorials/vr/index.html</link> </tutorials> <methods> - <method name="get_joy_id" qualifiers="const"> - <return type="int" /> + <method name="get_input" qualifiers="const"> + <return type="Variant" /> + <argument index="0" name="name" type="StringName" /> <description> - If this is a controller that is being tracked, the controller will also be represented by a joystick entry with this ID. + Returns an input for this tracker. It can return a boolean, float or [Vector2] value depending on whether the input is a button, trigger or thumbstick/thumbpad. </description> </method> - <method name="get_mesh" qualifiers="const"> - <return type="Mesh" /> + <method name="get_pose" qualifiers="const"> + <return type="XRPose" /> + <argument index="0" name="name" type="StringName" /> <description> - Returns the mesh related to a controller or anchor point if one is available. + Returns the current [XRPose] state object for the bound [code]pose[/code]. </description> </method> - <method name="get_orientation" qualifiers="const"> - <return type="Basis" /> + <method name="has_pose" qualifiers="const"> + <return type="bool" /> + <argument index="0" name="name" type="StringName" /> <description> - Returns the controller's orientation matrix. + Returns [code]true[/code] if the bound [code]tracker[/code] is available and is currently tracking the bound [code]pose[/code]. </description> </method> - <method name="get_position" qualifiers="const"> - <return type="Vector3" /> + <method name="invalidate_pose"> + <return type="void" /> + <argument index="0" name="name" type="StringName" /> <description> - Returns the world-space controller position. + Marks this pose as invalid, we don't clear the last reported state but it allows users to decide if trackers need to be hidden if we loose tracking or just remain at their last known position. </description> </method> - <method name="get_tracker_hand" qualifiers="const"> - <return type="int" enum="XRPositionalTracker.TrackerHand" /> + <method name="set_input"> + <return type="void" /> + <argument index="0" name="name" type="StringName" /> + <argument index="1" name="value" type="Variant" /> <description> - Returns the hand holding this tracker, if known. See [enum TrackerHand] constants. + Changes the value for the given input. This method is called by a [XRInterface] implementation and should not be used directly. </description> </method> - <method name="get_tracker_id" qualifiers="const"> - <return type="int" /> + <method name="set_pose"> + <return type="void" /> + <argument index="0" name="name" type="StringName" /> + <argument index="1" name="transform" type="Transform3D" /> + <argument index="2" name="linear_velocity" type="Vector3" /> + <argument index="3" name="angular_velocity" type="Vector3" /> <description> - Returns the internal tracker ID. This uniquely identifies the tracker per tracker type and matches the ID you need to specify for nodes such as the [XRController3D] and [XRAnchor3D] nodes. + Sets the transform, linear velocity and angular velocity for the given pose. This method is called by a [XRInterface] implementation and should not be used directly. </description> </method> - <method name="get_tracker_name" qualifiers="const"> - <return type="StringName" /> + </methods> + <members> + <member name="description" type="String" setter="set_tracker_desc" getter="get_tracker_desc" default=""""> + The description of this tracker. + </member> + <member name="hand" type="int" setter="set_tracker_hand" getter="get_tracker_hand" enum="XRPositionalTracker.TrackerHand" default="0"> + Defines which hand this tracker relates to. + </member> + <member name="name" type="StringName" setter="set_tracker_name" getter="get_tracker_name" default="&"Unknown""> + The unique name of this tracker. The trackers that are available differ between various XR runtimes and can often be configured by the user. Godot maintains a number of reserved names that it expects the [XRInterface] to implement if applicable: + - [code]left_hand[/code] identifies the controller held in the players left hand + - [code]right_hand[/code] identifies the controller held in the players right hand + </member> + <member name="rumble" type="float" setter="set_rumble" getter="get_rumble" default="0.0"> + The degree to which the tracker rumbles. Ranges from [code]0.0[/code] to [code]1.0[/code] with precision [code].01[/code]. + </member> + <member name="type" type="int" setter="set_tracker_type" getter="get_tracker_type" enum="XRServer.TrackerType" default="128"> + The type of tracker. + </member> + </members> + <signals> + <signal name="button_pressed"> + <argument index="0" name="name" type="String" /> <description> - Returns the controller or anchor point's name, if applicable. + Emitted when a button on this tracker is pressed. Note that many XR runtimes allow other inputs to be mapped to buttons. </description> - </method> - <method name="get_tracker_type" qualifiers="const"> - <return type="int" enum="XRServer.TrackerType" /> + </signal> + <signal name="button_released"> + <argument index="0" name="name" type="String" /> <description> - Returns the tracker's type, which will be one of the values from the [enum XRServer.TrackerType] enum. + Emitted when a button on this tracker is released. </description> - </method> - <method name="get_transform" qualifiers="const"> - <return type="Transform3D" /> - <argument index="0" name="adjust_by_reference_frame" type="bool" /> + </signal> + <signal name="input_axis_changed"> + <argument index="0" name="name" type="String" /> + <argument index="1" name="vector" type="Vector2" /> <description> - Returns the transform combining this device's orientation and position. + Emitted when a thumbstick or thumbpad on this tracker moves. </description> - </method> - <method name="is_tracking_orientation" qualifiers="const"> - <return type="bool" /> + </signal> + <signal name="input_value_changed"> + <argument index="0" name="name" type="String" /> + <argument index="1" name="value" type="float" /> <description> - Returns [code]true[/code] if this device is tracking orientation. + Emitted when a trigger or similar input on this tracker changes value. </description> - </method> - <method name="is_tracking_position" qualifiers="const"> - <return type="bool" /> + </signal> + <signal name="pose_changed"> + <argument index="0" name="pose" type="XRPose" /> <description> - Returns [code]true[/code] if this device is tracking position. + Emitted when the state of a pose tracked by this tracker changes. </description> - </method> - </methods> - <members> - <member name="rumble" type="float" setter="set_rumble" getter="get_rumble" default="0.0"> - The degree to which the tracker rumbles. Ranges from [code]0.0[/code] to [code]1.0[/code] with precision [code].01[/code]. - </member> - </members> + </signal> + </signals> <constants> <constant name="TRACKER_HAND_UNKNOWN" value="0" enum="TrackerHand"> The hand this tracker is held in is unknown or not applicable. diff --git a/doc/classes/XRServer.xml b/doc/classes/XRServer.xml index 0929094fd1..87164ebb52 100644 --- a/doc/classes/XRServer.xml +++ b/doc/classes/XRServer.xml @@ -90,20 +90,21 @@ <method name="get_reference_frame" qualifiers="const"> <return type="Transform3D" /> <description> - Returns the reference frame transform. Mostly used internally and exposed for GDNative build interfaces. + Returns the reference frame transform. Mostly used internally and exposed for GDExtension build interfaces. </description> </method> <method name="get_tracker" qualifiers="const"> <return type="XRPositionalTracker" /> - <argument index="0" name="idx" type="int" /> + <argument index="0" name="tracker_name" type="StringName" /> <description> - Returns the positional tracker at the given ID. + Returns the positional tracker with this name. </description> </method> - <method name="get_tracker_count" qualifiers="const"> - <return type="int" /> + <method name="get_trackers"> + <return type="Dictionary" /> + <argument index="0" name="tracker_types" type="int" /> <description> - Returns the number of trackers currently registered. + Returns a dictionary of trackers for this type. </description> </method> <method name="remove_interface"> @@ -145,7 +146,6 @@ <signal name="tracker_added"> <argument index="0" name="tracker_name" type="StringName" /> <argument index="1" name="type" type="int" /> - <argument index="2" name="id" type="int" /> <description> Emitted when a new tracker has been added. If you don't use a fixed number of controllers or if you're using [XRAnchor3D]s for an AR solution, it is important to react to this signal to add the appropriate [XRController3D] or [XRAnchor3D] nodes related to this new tracker. </description> @@ -153,20 +153,29 @@ <signal name="tracker_removed"> <argument index="0" name="tracker_name" type="StringName" /> <argument index="1" name="type" type="int" /> - <argument index="2" name="id" type="int" /> <description> Emitted when a tracker is removed. You should remove any [XRController3D] or [XRAnchor3D] points if applicable. This is not mandatory, the nodes simply become inactive and will be made active again when a new tracker becomes available (i.e. a new controller is switched on that takes the place of the previous one). </description> </signal> + <signal name="tracker_updated"> + <argument index="0" name="tracker_name" type="StringName" /> + <argument index="1" name="type" type="int" /> + <description> + Emitted when an existing tracker has been updated. This can happen if the user switches controllers. + </description> + </signal> </signals> <constants> - <constant name="TRACKER_CONTROLLER" value="1" enum="TrackerType"> + <constant name="TRACKER_HEAD" value="1" enum="TrackerType"> + The tracker tracks the location of the players head. This is usually a location centered between the players eyes. Note that for handheld AR devices this can be the current location of the device. + </constant> + <constant name="TRACKER_CONTROLLER" value="2" enum="TrackerType"> The tracker tracks the location of a controller. </constant> - <constant name="TRACKER_BASESTATION" value="2" enum="TrackerType"> + <constant name="TRACKER_BASESTATION" value="4" enum="TrackerType"> The tracker tracks the location of a base station. </constant> - <constant name="TRACKER_ANCHOR" value="4" enum="TrackerType"> + <constant name="TRACKER_ANCHOR" value="8" enum="TrackerType"> The tracker tracks the location and size of an AR anchor. </constant> <constant name="TRACKER_ANY_KNOWN" value="127" enum="TrackerType"> diff --git a/doc/translations/Makefile b/doc/translations/Makefile index ceee79ec95..ab08e107d0 100644 --- a/doc/translations/Makefile +++ b/doc/translations/Makefile @@ -21,3 +21,24 @@ merge: check: @for po in $(POFILES); do msgfmt -c $$po -o /dev/null; done + +# Generate completion ratio from statistics string such as: +# 2775 translated messages, 272 fuzzy translations, 151 untranslated messages. +# First number can be 0, second and third numbers are only present if non-zero. +include-list: + @list=""; \ + threshold=0.10; \ + for po in $(POFILES); do \ + res=`msgfmt --statistics $$po -o /dev/null 2>&1 | sed 's/[^0-9,]*//g'`; \ + complete=`cut -d',' -f1 <<< $$res`; \ + fuzzy_or_untranslated=`cut -d',' -f2 <<< $$res`; \ + untranslated_maybe=`cut -d',' -f3 <<< $$res`; \ + if [ -z "$$fuzzy_or_untranslated" ]; then fuzzy_or_untranslated=0; fi; \ + if [ -z "$$untranslated_maybe" ]; then untranslated_maybe=0; fi; \ + incomplete=`expr $$fuzzy_or_untranslated + $$untranslated_maybe`; \ + if `awk "BEGIN {exit !($$complete / ($$complete + $$incomplete) > $$threshold)}"`; then \ + lang=`basename $$po .po`; \ + list+="$$lang,"; \ + fi; \ + done; \ + echo $$list; diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 3032c31629..193825a73f 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -528,7 +528,7 @@ String OS_Unix::get_executable_path() const { #endif } -void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) { +void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type) { if (!should_log(true)) { return; } diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index bf82019d38..eb36bf4255 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -102,7 +102,7 @@ public: class UnixTerminalLogger : public StdLogger { public: - virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR); + virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type = ERR_ERROR); virtual ~UnixTerminalLogger(); }; diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 8743135f89..e7ac447426 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -8913,6 +8913,8 @@ void RenderingDeviceVulkan::initialize(VulkanContext *p_context, bool p_local_de } } + // Note: If adding new project settings here, also duplicate their definition in + // rendering_server.cpp for headless doctool. staging_buffer_block_size = GLOBAL_DEF("rendering/vulkan/staging_buffer/block_size_kb", 256); staging_buffer_block_size = MAX(4, staging_buffer_block_size); staging_buffer_block_size *= 1024; //kb -> bytes diff --git a/editor/SCsub b/editor/SCsub index e8d417319a..6b18eeae93 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -5,7 +5,6 @@ Import("env") env.editor_sources = [] import os -import os.path import glob import editor_builders @@ -59,7 +58,7 @@ if env["tools"]: else: docs += Glob(d + "/*.xml") # Custom. - _make_doc_data_class_path(os.path.join(env.Dir("#").abspath, "editor")) + _make_doc_data_class_path(env.Dir("#editor").abspath) docs = sorted(docs) env.Depends("#editor/doc_data_compressed.gen.h", docs) @@ -69,10 +68,17 @@ if env["tools"]: env.Run(editor_builders.make_doc_header, "Generating documentation header."), ) - path = env.Dir(".").abspath + # Editor interface and class reference translations incur a significant size + # cost for the editor binary (see godot-proposals#3421). + # To limit it, we only include translations with a high enough completion + # ratio (30% for the editor UI, 10% for the class reference). + # Generated with `make include-list` for each resource. # Editor translations - tlist = glob.glob(path + "/translations/*.po") + to_include = ( + "ar,bg,bn,ca,cs,de,el,eo,es_AR,es,fi,fr,gl,he,hu,id,it,ja,ko,ms,nb,nl,pl,pt_BR,pt,ro,ru,sk,sv,th,tr,uk,vi,zh_CN,zh_TW" + ).split(",") + tlist = [env.Dir("#editor/translations").abspath + "/" + f + ".po" for f in to_include] env.Depends("#editor/editor_translations.gen.h", tlist) env.CommandNoCache( "#editor/editor_translations.gen.h", @@ -81,7 +87,8 @@ if env["tools"]: ) # Documentation translations - tlist = glob.glob(env.Dir("#doc").abspath + "/translations/*.po") + to_include = "es,fr,ja,zh_CN".split(",") + tlist = [env.Dir("#doc/translations").abspath + "/" + f + ".po" for f in to_include] env.Depends("#editor/doc_translations.gen.h", tlist) env.CommandNoCache( "#editor/doc_translations.gen.h", @@ -90,8 +97,8 @@ if env["tools"]: ) # Fonts - flist = glob.glob(path + "/../thirdparty/fonts/*.ttf") - flist.extend(glob.glob(path + "/../thirdparty/fonts/*.otf")) + flist = glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.ttf") + flist.extend(glob.glob(env.Dir("#thirdparty").abspath + "/fonts/*.otf")) flist.sort() env.Depends("#editor/builtin_fonts.gen.h", flist) env.CommandNoCache( diff --git a/editor/code_editor.h b/editor/code_editor.h index 3c52a0c6e8..6e3bd88112 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -53,7 +53,6 @@ public: void popup_find_line(CodeEdit *p_edit); int get_line() const; - void set_text_editor(CodeEdit *p_text_editor); GotoLineDialog(); }; @@ -101,7 +100,6 @@ class FindReplaceBar : public HBoxContainer { void _search_text_changed(const String &p_text); void _search_text_submitted(const String &p_text); void _replace_text_submitted(const String &p_text); - void _update_size(); protected: void _notification(int p_what); diff --git a/editor/editor_command_palette.cpp b/editor/editor_command_palette.cpp index e69ced8522..71e9fac219 100644 --- a/editor/editor_command_palette.cpp +++ b/editor/editor_command_palette.cpp @@ -212,6 +212,12 @@ void EditorCommandPalette::_add_command(String p_command_name, String p_key_name command.callable = p_binded_action; command.shortcut = p_shortcut_text; + // Commands added from plugins don't exist yet when the history is loaded, so we assign the last use time here if it was recorded. + Dictionary command_history = EditorSettings::get_singleton()->get_project_metadata("command_palette", "command_history", Dictionary()); + if (command_history.has(p_key_name)) { + command.last_used = command_history[p_key_name]; + } + commands[p_key_name] = command; } @@ -242,7 +248,9 @@ void EditorCommandPalette::register_shortcuts_as_command() { Array history_entries = command_history.keys(); for (int i = 0; i < history_entries.size(); i++) { const String &history_key = history_entries[i]; - commands[history_key].last_used = command_history[history_key]; + if (commands.has(history_key)) { + commands[history_key].last_used = command_history[history_key]; + } } } diff --git a/editor/editor_data.h b/editor/editor_data.h index 9184ddcf39..976d718b8e 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -135,8 +135,6 @@ private: Vector<Callable> undo_redo_callbacks; Map<StringName, Callable> move_element_functions; - void _cleanup_history(); - Vector<EditedScene> edited_scene; int current_edited_scene; diff --git a/editor/editor_help.h b/editor/editor_help.h index 7a45b1abc1..46605b6763 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -57,7 +57,6 @@ class FindBar : public HBoxContainer { int results_count; - void _show_search(); void _hide_bar(); void _search_text_changed(const String &p_text); @@ -66,8 +65,6 @@ class FindBar : public HBoxContainer { void _update_results_count(); void _update_matches_label(); - void _update_size(); - protected: void _notification(int p_what); virtual void unhandled_input(const Ref<InputEvent> &p_event) override; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 4d0f27c5d4..9f049a0e58 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -245,13 +245,15 @@ void EditorProperty::_notification(int p_what) { } Color color; - if (draw_red) { - color = get_theme_color(is_read_only() ? SNAME("readonly_error_color") : SNAME("error_color")); + if (draw_warning) { + color = get_theme_color(is_read_only() ? SNAME("readonly_warning_color") : SNAME("warning_color")); } else { color = get_theme_color(is_read_only() ? SNAME("readonly_color") : SNAME("property_color")); } if (label.find(".") != -1) { - color.a = 0.5; //this should be un-hacked honestly, as it's used for editor overrides + // FIXME: Move this to the project settings editor, as this is only used + // for project settings feature tag overrides. + color.a = 0.5; } int ofs = get_theme_constant(SNAME("font_offset")); @@ -625,8 +627,8 @@ bool EditorProperty::is_checked() const { return checked; } -void EditorProperty::set_draw_red(bool p_draw_red) { - draw_red = p_draw_red; +void EditorProperty::set_draw_warning(bool p_draw_warning) { + draw_warning = p_draw_warning; update(); } @@ -650,8 +652,8 @@ bool EditorProperty::is_keying() const { return keying; } -bool EditorProperty::is_draw_red() const { - return draw_red; +bool EditorProperty::is_draw_warning() const { + return draw_warning; } void EditorProperty::_focusable_focused(int p_index) { @@ -969,8 +971,8 @@ void EditorProperty::_bind_methods() { ClassDB::bind_method(D_METHOD("set_checked", "checked"), &EditorProperty::set_checked); ClassDB::bind_method(D_METHOD("is_checked"), &EditorProperty::is_checked); - ClassDB::bind_method(D_METHOD("set_draw_red", "draw_red"), &EditorProperty::set_draw_red); - ClassDB::bind_method(D_METHOD("is_draw_red"), &EditorProperty::is_draw_red); + ClassDB::bind_method(D_METHOD("set_draw_warning", "draw_warning"), &EditorProperty::set_draw_warning); + ClassDB::bind_method(D_METHOD("is_draw_warning"), &EditorProperty::is_draw_warning); ClassDB::bind_method(D_METHOD("set_keying", "keying"), &EditorProperty::set_keying); ClassDB::bind_method(D_METHOD("is_keying"), &EditorProperty::is_keying); @@ -993,7 +995,7 @@ void EditorProperty::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "read_only"), "set_read_only", "is_read_only"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "checkable"), "set_checkable", "is_checkable"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "checked"), "set_checked", "is_checked"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_red"), "set_draw_red", "is_draw_red"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_warning"), "set_draw_warning", "is_draw_warning"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keying"), "set_keying", "is_keying"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deletable"), "set_deletable", "is_deletable"); ADD_SIGNAL(MethodInfo("property_changed", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT))); @@ -1018,7 +1020,7 @@ EditorProperty::EditorProperty() { read_only = false; checkable = false; checked = false; - draw_red = false; + draw_warning = false; keying = false; deletable = false; keying_hover = false; @@ -2393,14 +2395,15 @@ void EditorInspector::update_tree() { valid_plugins.push_back(inspector_plugins[i]); } - // Decide if properties should be drawn in red. - bool draw_red = false; + // Decide if properties should be drawn with the warning color (yellow). + bool draw_warning = false; if (is_inside_tree()) { Node *nod = Object::cast_to<Node>(object); Node *es = EditorNode::get_singleton()->get_edited_scene(); if (nod && es != nod && nod->get_owner() != es) { - // Draw in red edited nodes that are not in the currently edited scene. - draw_red = true; + // Draw in warning color edited nodes that are not in the currently edited scene, + // as changes may be lost in the future. + draw_warning = true; } } @@ -2855,7 +2858,7 @@ void EditorInspector::update_tree() { editor_property_map[prop].push_back(ep); } } - ep->set_draw_red(draw_red); + ep->set_draw_warning(draw_warning); ep->set_use_folding(use_folding); ep->set_checkable(checkable); ep->set_checked(checked); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index b71efe8f19..124ea31302 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -74,7 +74,7 @@ private: bool read_only; bool checkable; bool checked; - bool draw_red; + bool draw_warning; bool keying; bool deletable; @@ -96,8 +96,6 @@ private: bool draw_top_bg; void _ensure_popup(); - bool _is_property_different(const Variant &p_current, const Variant &p_orig); - bool _get_instantiated_node_original_property(const StringName &p_prop, Variant &value); void _focusable_focused(int p_index); bool selectable; @@ -150,8 +148,8 @@ public: void set_checked(bool p_checked); bool is_checked() const; - void set_draw_red(bool p_draw_red); - bool is_draw_red() const; + void set_draw_warning(bool p_draw_warning); + bool is_draw_warning() const; void set_keying(bool p_keying); bool is_keying() const; @@ -281,8 +279,6 @@ public: void unfold(); void fold(); - Object *get_edited_object(); - EditorInspectorSection(); ~EditorInspectorSection(); }; diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 346b93a87c..251e1c2385 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -37,7 +37,7 @@ #include "scene/gui/center_container.h" #include "scene/resources/font.h" -void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type) { +void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type) { EditorLog *self = (EditorLog *)p_self; if (self->current != Thread::get_caller_id()) { return; @@ -50,6 +50,10 @@ void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_f err_str = String(p_file) + ":" + itos(p_line) + " - " + String(p_error); } + if (p_editor_notify) { + err_str += " (User)"; + } + if (p_type == ERR_HANDLER_WARNING) { self->add_message(err_str, MSG_TYPE_WARNING); } else { diff --git a/editor/editor_log.h b/editor/editor_log.h index 6cbf4bedee..43cc5680bd 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -136,7 +136,7 @@ private: bool is_loading_state = false; // Used to disable saving requests while loading (some signals from buttons will try trigger a save, which happens during loading). Timer *save_state_timer; - static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type); + static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type); ErrorHandlerList eh; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 2f92f60d5e..891705da98 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -59,8 +59,8 @@ #include "scene/gui/panel.h" #include "scene/gui/panel_container.h" #include "scene/gui/split_container.h" +#include "scene/gui/tab_bar.h" #include "scene/gui/tab_container.h" -#include "scene/gui/tabs.h" #include "scene/gui/texture_progress_bar.h" #include "scene/main/window.h" #include "scene/resources/packed_scene.h" @@ -95,6 +95,7 @@ #include "editor/editor_settings.h" #include "editor/editor_spin_slider.h" #include "editor/editor_themes.h" +#include "editor/editor_toaster.h" #include "editor/editor_translation_parser.h" #include "editor/export_template_manager.h" #include "editor/filesystem_dock.h" @@ -657,7 +658,7 @@ void EditorNode::_notification(int p_what) { } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); + scene_tabs->set_tab_close_display_policy((bool(EDITOR_GET("interface/scene_tabs/always_show_close_button")) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); theme = create_custom_theme(theme_base->get_theme()); theme_base->set_theme(theme); @@ -837,7 +838,7 @@ void EditorNode::_resources_changed(const Vector<String> &p_resources) { } if (res->get_import_path() != String()) { - //this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback + // this is an imported resource, will be reloaded if reimported via the _resources_reimported() callback continue; } @@ -941,21 +942,21 @@ void EditorNode::_fs_changed() { } void EditorNode::_resources_reimported(const Vector<String> &p_resources) { - List<String> scenes; //will load later + List<String> scenes; // will load later int current_tab = scene_tabs->get_current_tab(); for (int i = 0; i < p_resources.size(); i++) { String file_type = ResourceLoader::get_resource_type(p_resources[i]); if (file_type == "PackedScene") { scenes.push_back(p_resources[i]); - //reload later if needed, first go with normal resources + // reload later if needed, first go with normal resources continue; } if (!ResourceCache::has(p_resources[i])) { - continue; //not loaded, no need to reload + continue; // not loaded, no need to reload } - //reload normally + // reload normally Resource *resource = ResourceCache::get(p_resources[i]); if (resource) { resource->reload_from_file(); @@ -1139,7 +1140,7 @@ Error EditorNode::load_resource(const String &p_resource, bool p_ignore_broken_d ERR_FAIL_COND_V(!res.is_valid(), ERR_CANT_OPEN); if (!p_ignore_broken_deps && dependency_errors.has(p_resource)) { - //current_option = -1; + // current_option = -1; Vector<String> errors; for (Set<String>::Element *E = dependency_errors[p_resource].front(); E; E = E->next()) { errors.push_back(E->get()); @@ -1215,7 +1216,7 @@ void EditorNode::save_resource_as(const Ref<Resource> &p_resource, const String List<String> preferred; for (const String &E : extensions) { if (p_resource->is_class("Script") && (E == "tres" || E == "res")) { - //this serves no purpose and confused people + // this serves no purpose and confused people continue; } file->add_filter("*." + E + " ; " + E.to_upper()); @@ -1324,7 +1325,7 @@ void EditorNode::_get_scene_metadata(const String &p_file) { Error err = cf->load(path); if (err != OK || !cf->has_section("editor_states")) { - return; //must not exist + return; // must not exist } List<String> esl; @@ -1348,7 +1349,7 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) { return; } - scene->set_meta("__editor_run_settings__", Variant()); //clear it (no point in keeping it) + scene->set_meta("__editor_run_settings__", Variant()); // clear it (no point in keeping it) scene->set_meta("__editor_plugin_states__", Variant()); String path = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg"); @@ -1391,10 +1392,10 @@ bool EditorNode::_find_and_save_resource(RES p_res, Map<RES, bool> &processed, i if (p_res->get_path().is_resource_file()) { if (changed || subchanged) { - //save + // save ResourceSaver::save(p_res->get_path(), p_res, flags); } - processed[p_res] = false; //because it's a file + processed[p_res] = false; // because it's a file return false; } else { processed[p_res] = changed; @@ -1492,7 +1493,7 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { _find_node_types(editor_data.get_edited_scene_root(), c2d, c3d); save.step(TTR("Creating Thumbnail"), 1); - //current view? + // current view? Ref<Image> img; // If neither 3D or 2D nodes are present, make a 1x1 black texture. @@ -1545,12 +1546,12 @@ void EditorNode::_save_scene_with_preview(String p_file, int p_idx) { } img->convert(Image::FORMAT_RGB8); - //save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5 + // save thumbnail directly, as thumbnailer may not update due to actual scene not changing md5 String temp_path = EditorPaths::get_singleton()->get_cache_dir(); String cache_base = ProjectSettings::get_singleton()->globalize_path(p_file).md5_text(); cache_base = temp_path.plus_file("resthumb-" + cache_base); - //does not have it, try to load a cached thumbnail + // does not have it, try to load a cached thumbnail String file = cache_base + ".png"; @@ -1598,7 +1599,7 @@ static bool _find_edited_resources(const Ref<Resource> &p_resource, Set<Ref<Reso if (res.is_null()) { continue; } - if (res->get_path().is_resource_file()) { //not a subresource, continue + if (res->get_path().is_resource_file()) { // not a subresource, continue continue; } if (_find_edited_resources(res, edited_resources)) { @@ -1611,7 +1612,7 @@ static bool _find_edited_resources(const Ref<Resource> &p_resource, Set<Ref<Reso } int EditorNode::_save_external_resources() { - //save external resources and its subresources if any was modified + // save external resources and its subresources if any was modified int flg = 0; if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources")) { @@ -1627,7 +1628,7 @@ int EditorNode::_save_external_resources() { if (!res->get_path().is_resource_file()) { continue; } - //not only check if this resource is edited, check contained subresources too + // not only check if this resource is edited, check contained subresources too if (_find_edited_resources(res, edited_subresources)) { ResourceSaver::save(res->get_path(), res, flg); saved++; @@ -1836,7 +1837,7 @@ void EditorNode::_dialog_action(String p_file) { case SETTINGS_PICK_MAIN_SCENE: { ProjectSettings::get_singleton()->set("application/run/main_scene", p_file); ProjectSettings::get_singleton()->save(); - //would be nice to show the project manager opened with the highlighted field.. + // would be nice to show the project manager opened with the highlighted field.. if (pick_main_scene->has_meta("from_native") && (bool)pick_main_scene->get_meta("from_native")) { run_native->resume_run_native(); @@ -1979,7 +1980,7 @@ void EditorNode::_dialog_action(String p_file) { } } break; - default: { //save scene? + default: { // save scene? if (file->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { _save_scene_with_preview(p_file); @@ -2140,7 +2141,7 @@ void EditorNode::_edit_current() { bool is_resource = current_obj->is_class("Resource"); bool is_node = current_obj->is_class("Node"); - String editable_warning; //none by default + String editable_warning; // none by default if (is_resource) { Resource *current_res = Object::cast_to<Resource>(current_obj); @@ -2242,7 +2243,7 @@ void EditorNode::_edit_current() { for (; plugin_index < editor_table.size(); plugin_index++) { if (editor_table[plugin_index] == main_plugin) { if (!main_editor_buttons[plugin_index]->is_visible()) { - main_plugin = nullptr; //if button is not visible, then no plugin active + main_plugin = nullptr; // if button is not visible, then no plugin active } break; @@ -2328,7 +2329,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { } if (run_filename == "") { - //evidently, run the scene + // evidently, run the scene if (!ensure_main_scene(false)) { return; } @@ -2411,7 +2412,7 @@ void EditorNode::_android_build_source_selected(const String &p_file) { export_template_manager->install_android_template_from_file(p_file); } void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { - if (!p_confirmed) { //this may be a hack.. + if (!p_confirmed) { // this may be a hack.. current_option = (MenuOptions)p_option; } @@ -2980,7 +2981,7 @@ int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) { void EditorNode::_exit_editor() { exiting = true; - resource_preview->stop(); //stop early to avoid crashes + resource_preview->stop(); // stop early to avoid crashes _save_docks(); // Dim the editor window while it's quitting to make it clearer that it's busy @@ -3086,7 +3087,7 @@ void EditorNode::_editor_select(int p_which) { ERR_FAIL_INDEX(p_which, editor_table.size()); - if (!main_editor_buttons[p_which]->is_visible()) { //button hidden, no editor + if (!main_editor_buttons[p_which]->is_visible()) { // button hidden, no editor return; } @@ -3228,7 +3229,7 @@ void EditorNode::set_addon_plugin_enabled(const String &p_addon, bool p_enabled, if (!p_enabled) { EditorPlugin *addon = plugin_addons[p_addon]; remove_editor_plugin(addon, p_config_changed); - memdelete(addon); //bye + memdelete(addon); // bye plugin_addons.erase(p_addon); _update_addon_config(); return; @@ -3320,10 +3321,10 @@ void EditorNode::_remove_edited_scene(bool p_change_tab) { void EditorNode::_remove_scene(int index, bool p_change_tab) { if (editor_data.get_edited_scene() == index) { - //Scene to remove is current scene + // Scene to remove is current scene _remove_edited_scene(p_change_tab); } else { - //Scene to remove is not active scene + // Scene to remove is not active scene editor_data.remove_scene(index); } } @@ -3337,7 +3338,7 @@ void EditorNode::set_edited_scene(Node *p_scene) { get_editor_data().set_edited_scene_root(p_scene); if (Object::cast_to<Popup>(p_scene)) { - Object::cast_to<Popup>(p_scene)->show(); //show popups + Object::cast_to<Popup>(p_scene)->show(); // show popups } scene_tree_dock->set_edited_scene(p_scene); if (get_tree()) { @@ -3373,7 +3374,7 @@ Dictionary EditorNode::_get_main_scene_state() { void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { if (get_edited_scene() != p_for_scene && p_for_scene != nullptr) { - return; //not for this scene + return; // not for this scene } changing_scene = false; @@ -3388,7 +3389,7 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { if (p_state.has("editor_index")) { int index = p_state["editor_index"]; - if (current < 2) { //if currently in spatial/2d, only switch to spatial/2d. if currently in script, stay there + if (current < 2) { // if currently in spatial/2d, only switch to spatial/2d. if currently in script, stay there if (index < 2 || !get_edited_scene()) { _editor_select(index); } @@ -3397,7 +3398,7 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { if (get_edited_scene()) { if (current < 2) { - //use heuristic instead + // use heuristic instead int n2d = 0, n3d = 0; _find_node_types(get_edited_scene(), n2d, n3d); if (n2d > n3d) { @@ -3419,7 +3420,7 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) { scene_tree_dock->set_filter(p_state["node_filter"]); } - //this should only happen at the very end + // this should only happen at the very end EditorDebuggerNode::get_singleton()->update_live_edit_root(); ScriptEditor::get_singleton()->set_scene_root_script(editor_data.get_scene_root_script(editor_data.get_edited_scene())); @@ -3440,7 +3441,7 @@ void EditorNode::_clear_undo_history() { } void EditorNode::set_current_scene(int p_idx) { - //Save the folding in case the scene gets reloaded. + // Save the folding in case the scene gets reloaded. if (editor_data.get_scene_path(p_idx) != "" && editor_data.get_edited_scene_root(p_idx)) { editor_folding.save_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx)); } @@ -3468,7 +3469,7 @@ void EditorNode::set_current_scene(int p_idx) { Node *new_scene = editor_data.get_edited_scene_root(); if (Object::cast_to<Popup>(new_scene)) { - Object::cast_to<Popup>(new_scene)->show(); //show popups + Object::cast_to<Popup>(new_scene)->show(); // show popups } scene_tree_dock->set_edited_scene(new_scene); @@ -3487,7 +3488,7 @@ void EditorNode::set_current_scene(int p_idx) { _update_title(); - call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); //do after everything else is done setting up + call_deferred(SNAME("_set_main_scene_state"), state, get_edited_scene()); // do after everything else is done setting up } bool EditorNode::is_scene_open(const String &p_path) { @@ -3589,7 +3590,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b return ERR_FILE_MISSING_DEPENDENCIES; } - dependency_errors.erase(lpath); //at least not self path + dependency_errors.erase(lpath); // at least not self path for (KeyValue<String, Set<String>> &E : dependency_errors) { String txt = vformat(TTR("Scene '%s' has broken dependencies:"), E.key) + "\n"; @@ -3600,7 +3601,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b } if (ResourceCache::has(lpath)) { - //used from somewhere else? no problem! update state and replace sdata + // used from somewhere else? no problem! update state and replace sdata Ref<PackedScene> ps = Ref<PackedScene>(Object::cast_to<PackedScene>(ResourceCache::get(lpath))); if (ps.is_valid()) { ps->replace_state(sdata->get_state()); @@ -3609,7 +3610,7 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b } } else { - sdata->set_path(lpath, true); //take over path + sdata->set_path(lpath, true); // take over path } Node *new_scene = sdata->instantiate(PackedScene::GEN_EDIT_STATE_MAIN); @@ -4223,7 +4224,7 @@ void EditorNode::_dock_make_float() { ERR_FAIL_COND(!dock); const Size2i borders = Size2i(4, 4) * EDSCALE; - Size2 dock_size = dock->get_size() + borders * 2; //remember size + Size2 dock_size = dock->get_size() + borders * 2; // remember size Point2 dock_screen_pos = dock->get_global_position() + get_tree()->get_root()->get_position() - borders; print_line("dock pos: " + dock->get_global_position() + " window pos: " + get_tree()->get_root()->get_position()); @@ -4463,7 +4464,7 @@ void EditorNode::_dock_select_draw() { void EditorNode::_save_docks() { if (waiting_for_first_scan) { - return; //scanning, do not touch docks + return; // scanning, do not touch docks } Ref<ConfigFile> config; config.instantiate(); @@ -4534,7 +4535,7 @@ void EditorNode::_load_docks() { config.instantiate(); Error err = config->load(EditorSettings::get_singleton()->get_project_settings_dir().plus_file("editor_layout.cfg")); if (err != OK) { - //no config + // no config if (overridden_default_layout >= 0) { _layout_menu_option(overridden_default_layout); } @@ -4647,7 +4648,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String for (int j = 0; j < names.size(); j++) { String name = names[j]; - //find it, in a horribly inefficient way + // find it, in a horribly inefficient way int atidx = -1; Control *node = nullptr; for (int k = 0; k < DOCK_SLOT_MAX; k++) { @@ -4661,7 +4662,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String atidx = k; break; } - if (atidx == -1) { //well, it's not anywhere + if (atidx == -1) { // well, it's not anywhere continue; } @@ -4777,7 +4778,7 @@ bool EditorNode::has_scenes_in_session() { } bool EditorNode::ensure_main_scene(bool p_from_native) { - pick_main_scene->set_meta("from_native", p_from_native); //whether from play button or native run + pick_main_scene->set_meta("from_native", p_from_native); // whether from play button or native run String main_scene = GLOBAL_DEF("application/run/main_scene", ""); if (main_scene == "") { @@ -4898,7 +4899,7 @@ void EditorNode::_update_layouts_menu() { config.instantiate(); Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config()); if (err != OK) { - return; //no config + return; // no config } List<String> layouts; @@ -4939,7 +4940,7 @@ void EditorNode::_layout_menu_option(int p_id) { config.instantiate(); Error err = config->load(EditorSettings::get_singleton()->get_editor_layouts_config()); if (err != OK) { - return; //no config + return; // no config } _load_docks_from_config(config, editor_layouts->get_item_text(p_id)); @@ -5080,7 +5081,7 @@ void EditorNode::_scene_tab_changed(int p_tab) { bool unsaved = (saved_version != editor_data.get_undo_redo().get_version()); if (p_tab == editor_data.get_edited_scene()) { - return; //pointless + return; // pointless } uint64_t next_scene_version = editor_data.get_scene_version(p_tab); @@ -5283,11 +5284,11 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) { Ref<Texture2D> preview; { - //todo make proper previews + // todo make proper previews Ref<ImageTexture> texture = gui_base->get_theme_icon(SNAME("FileBigThumb"), SNAME("EditorIcons")); Ref<Image> img = texture->get_image(); img = img->duplicate(); - img->resize(48, 48); //meh + img->resize(48, 48); // meh Ref<ImageTexture> resized_pic = Ref<ImageTexture>(memnew(ImageTexture)); resized_pic->create_from_image(img); preview = resized_pic; @@ -5305,7 +5306,7 @@ Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) { drag_control->add_child(label); - p_from->set_drag_preview(drag_control); //wait until it enters scene + p_from->set_drag_preview(drag_control); // wait until it enters scene label->set_position(Point2((preview->get_width() - label->get_minimum_size().width) / 2, preview->get_height())); @@ -5359,7 +5360,7 @@ Variant EditorNode::drag_files_and_dirs(const Vector<String> &p_paths, Control * } vbox->add_child(label); } - p_from->set_drag_preview(vbox); //wait until it enters scene + p_from->set_drag_preview(vbox); // wait until it enters scene Dictionary drag_data; drag_data["type"] = has_folder ? "files_and_dirs" : "files"; @@ -5476,7 +5477,7 @@ void EditorNode::reload_scene(const String &p_path) { if (scene_idx == -1) { if (get_edited_scene()) { - //scene is not open, so at it might be instantiated. We'll refresh the whole scene later. + // scene is not open, so at it might be instantiated. We'll refresh the whole scene later. editor_data.get_undo_redo().clear_history(); } return; @@ -5487,17 +5488,17 @@ void EditorNode::reload_scene(const String &p_path) { _set_scene_metadata(p_path); } - //remove scene + // remove scene _remove_scene(scene_idx, false); - //reload scene + // reload scene load_scene(p_path, true, false, true, true); - //adjust index so tab is back a the previous position + // adjust index so tab is back a the previous position editor_data.move_edited_scene_to_index(scene_idx); get_undo_redo()->clear_history(); - //recover the tab + // recover the tab scene_tabs->set_current_tab(current_tab); } @@ -5597,7 +5598,7 @@ void EditorNode::_update_video_driver_color() { void EditorNode::_video_driver_selected(int p_which) { String driver = video_driver->get_item_metadata(p_which); - String current = ""; //OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver()); + String current = ""; // OS::get_singleton()->get_video_driver_name(OS::get_singleton()->get_current_video_driver()); if (driver == current) { return; @@ -5786,9 +5787,9 @@ EditorNode::EditorNode() { PhysicsServer2D::get_singleton()->set_active(false); // no physics by default if editor ScriptServer::set_scripting_enabled(false); // no scripting by default if editor - EditorHelp::generate_doc(); //before any editor classes are created + EditorHelp::generate_doc(); // before any editor classes are created SceneState::set_disable_placeholders(true); - ResourceLoader::clear_translation_remaps(); //no remaps using during editor + ResourceLoader::clear_translation_remaps(); // no remaps using during editor ResourceLoader::clear_path_remaps(); Input *id = Input::get_singleton(); @@ -5802,8 +5803,8 @@ EditorNode::EditorNode() { } if (!found_touchscreen && Input::get_singleton()) { - //only if no touchscreen ui hint, set emulation - id->set_emulate_touch_from_mouse(false); //just disable just in case + // only if no touchscreen ui hint, set emulation + id->set_emulate_touch_from_mouse(false); // just disable just in case } DisplayServer::get_singleton()->cursor_set_custom_image(RES()); } @@ -5870,7 +5871,7 @@ EditorNode::EditorNode() { ResourceLoader::set_error_notify_func(this, _load_error_notify); ResourceLoader::set_dependency_error_notify_func(this, _dependency_error_report); - { //register importers at the beginning, so dialogs are created with the right extensions + { // register importers at the beginning, so dialogs are created with the right extensions Ref<ResourceImporterTexture> import_texture; import_texture.instantiate(); ResourceFormatImporter::get_singleton()->add_importer(import_texture); @@ -5973,7 +5974,7 @@ EditorNode::EditorNode() { EditorFileSystem *efs = memnew(EditorFileSystem); add_child(efs); - //used for previews + // used for previews FileDialog::get_icon_func = _file_dialog_get_icon; FileDialog::register_func = _file_dialog_register; FileDialog::unregister_func = _file_dialog_unregister; @@ -5992,7 +5993,7 @@ EditorNode::EditorNode() { ClassDB::set_class_enabled("RootMotionView", true); - //defs here, use EDITOR_GET in logic + // defs here, use EDITOR_GET in logic EDITOR_DEF_RST("interface/scene_tabs/always_show_close_button", false); EDITOR_DEF_RST("interface/scene_tabs/resize_if_many_tabs", true); EDITOR_DEF_RST("interface/scene_tabs/minimum_width", 50); @@ -6216,13 +6217,13 @@ EditorNode::EditorNode() { tab_preview->set_position(Point2(2, 2) * EDSCALE); tab_preview_panel->add_child(tab_preview); - scene_tabs = memnew(Tabs); + scene_tabs = memnew(TabBar); scene_tabs->add_theme_style_override("tab_selected", gui_base->get_theme_stylebox(SNAME("SceneTabFG"), SNAME("EditorStyles"))); scene_tabs->add_theme_style_override("tab_unselected", gui_base->get_theme_stylebox(SNAME("SceneTabBG"), SNAME("EditorStyles"))); scene_tabs->set_select_with_rmb(true); scene_tabs->add_tab("unsaved"); - scene_tabs->set_tab_align(Tabs::ALIGN_LEFT); - scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); + scene_tabs->set_tab_align(TabBar::ALIGN_LEFT); + scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/scene_tabs/always_show_close_button", false)) ? TabBar::CLOSE_BUTTON_SHOW_ALWAYS : TabBar::CLOSE_BUTTON_SHOW_ACTIVE_ONLY)); scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE); scene_tabs->set_drag_to_rearrange_enabled(true); scene_tabs->connect("tab_changed", callable_mp(this, &EditorNode::_scene_tab_changed)); @@ -6748,6 +6749,9 @@ EditorNode::EditorNode() { bottom_panel_hb_editors->set_h_size_flags(Control::SIZE_EXPAND_FILL); bottom_panel_hb->add_child(bottom_panel_hb_editors); + editor_toaster = memnew(EditorToaster); + bottom_panel_hb->add_child(editor_toaster); + VBoxContainer *version_info_vbc = memnew(VBoxContainer); bottom_panel_hb->add_child(version_info_vbc); @@ -6920,7 +6924,7 @@ EditorNode::EditorNode() { EditorAudioBuses *audio_bus_editor = EditorAudioBuses::register_editor(); - ScriptTextEditor::register_editor(); //register one for text scripts + ScriptTextEditor::register_editor(); // register one for text scripts TextEditor::register_editor(); if (StreamPeerSSL::is_available()) { @@ -6929,12 +6933,12 @@ EditorNode::EditorNode() { WARN_PRINT("Asset Library not available, as it requires SSL to work."); } - //add interface before adding plugins + // add interface before adding plugins editor_interface = memnew(EditorInterface); add_child(editor_interface); - //more visually meaningful to have this later + // more visually meaningful to have this later raise_bottom_panel_item(AnimationPlayerEditor::get_singleton()); add_editor_plugin(VersionControlEditorPlugin::get_singleton()); diff --git a/editor/editor_node.h b/editor/editor_node.h index 73feeecfee..c64bcc0460 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -37,6 +37,7 @@ #include "editor/editor_folding.h" #include "editor/editor_native_shader_source_visualizer.h" #include "editor/editor_run.h" +#include "editor/editor_toaster.h" #include "editor/inspector_dock.h" #include "editor/property_editor.h" #include "editor/scene_tree_dock.h" @@ -84,7 +85,7 @@ class ProjectSettingsEditor; class RunSettingsDialog; class ScriptCreateDialog; class TabContainer; -class Tabs; +class TabBar; class TextureProgressBar; class Button; class VSplitContainer; @@ -215,7 +216,7 @@ private: TOOL_MENU_BASE = 1000 }; - SubViewport *scene_root; //root of the scene being edited + SubViewport *scene_root; // root of the scene being edited PanelContainer *scene_root_parent; Control *theme_base; @@ -249,7 +250,7 @@ private: // Main tabs - Tabs *scene_tabs; + TabBar *scene_tabs; PopupMenu *scene_tabs_context_menu; Panel *tab_preview_panel; TextureRect *tab_preview; @@ -323,7 +324,7 @@ private: EditorSettingsDialog *settings_config_dialog; ProjectSettingsEditor *project_settings; - bool settings_changed = true; //make it update settings on first frame + bool settings_changed = true; // make it update settings on first frame void _update_from_settings(); PopupMenu *vcs_actions_menu; @@ -438,6 +439,7 @@ private: HBoxContainer *bottom_panel_hb; HBoxContainer *bottom_panel_hb_editors; VBoxContainer *bottom_panel_vb; + EditorToaster *editor_toaster; LinkButton *version_btn; Button *bottom_panel_raise; @@ -518,9 +520,6 @@ private: void _run(bool p_current = false, const String &p_custom = ""); void _run_native(const Ref<EditorExportPreset> &p_preset); - void _save_optimized(); - void _import_action(const String &p_action); - void _import(const String &p_file); void _add_to_recent_scenes(const String &p_scene); void _update_recent_scenes(); void _open_recent_scene(int p_idx); @@ -558,7 +557,6 @@ private: static void _editor_file_dialog_register(EditorFileDialog *p_dialog); static void _editor_file_dialog_unregister(EditorFileDialog *p_dialog); - void _cleanup_scene(); void _remove_edited_scene(bool p_change_tab = true); void _remove_scene(int index, bool p_change_tab = true); bool _find_and_save_resource(RES p_res, Map<RES, bool> &processed, int32_t flags); @@ -656,8 +654,6 @@ private: static int build_callback_count; static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS]; - void _license_tree_selected(); - void _update_update_spinner(); Vector<Ref<EditorResourceConversionPlugin>> resource_conversion_plugins; @@ -773,10 +769,9 @@ public: Node *get_edited_scene() { return editor_data.get_edited_scene_root(); } - SubViewport *get_scene_root() { return scene_root; } //root of the scene being edited + SubViewport *get_scene_root() { return scene_root; } // root of the scene being edited void fix_dependencies(const String &p_for_file); - void clear_scene() { _cleanup_scene(); } int new_scene(); Error load_scene(const String &p_scene, bool p_ignore_broken_deps = false, bool p_set_inherited = false, bool p_clear_errors = true, bool p_force_open_imported = false, bool p_silent_change_tab = false); Error load_resource(const String &p_resource, bool p_ignore_broken_deps = false); @@ -849,8 +844,6 @@ public: bool is_scene_in_use(const String &p_path); - void scan_import_changes(); - void save_layout(); void open_export_template_manager(); @@ -892,7 +885,6 @@ public: EditorNode(); ~EditorNode(); - void get_singleton(const char *arg1, bool arg2); void add_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin); void remove_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin); diff --git a/editor/editor_path.h b/editor/editor_path.h index cabfa931d6..07f8b7244e 100644 --- a/editor/editor_path.h +++ b/editor/editor_path.h @@ -47,7 +47,6 @@ class EditorPath : public Button { PopupMenu *sub_objects_menu; Vector<ObjectID> objects; - EditorPath(); void _show_popup(); void _id_pressed(int p_idx); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 223cc6650c..1da9213b89 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -442,6 +442,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("interface/editor/hide_console_window", false); _initial_set("interface/editor/mouse_extra_buttons_navigate_history", true); _initial_set("interface/editor/save_each_scene_on_quit", true); // Regression + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/show_internal_errors_in_toast_notifications", 0, "Auto,Enabled,Disabled") // Inspector EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/inspector/max_array_dictionary_items_per_page", 20, "10,100,1") diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 2d4db48f2a..fdcc0438ae 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -403,7 +403,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { float prev_icon_saturation = theme->has_color("icon_saturation", "Editor") ? theme->get_color("icon_saturation", "Editor").r : 1.0; - theme->set_color("icon_saturation", "Editor", Color(icon_saturation, icon_saturation, icon_saturation)); //can't save single float in theme, so using color + theme->set_color("icon_saturation", "Editor", Color(icon_saturation, icon_saturation, icon_saturation)); // can't save single float in theme, so using color theme->set_color("accent_color", "Editor", accent_color); theme->set_color("highlight_color", "Editor", highlight_color); theme->set_color("disabled_highlight_color", "Editor", disabled_highlight_color); @@ -431,7 +431,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { Color error_color = Color(1, 0.47, 0.42); Color property_color = font_color.lerp(Color(0.5, 0.5, 0.5), 0.5); Color readonly_color = property_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.5); - Color readonly_error_color = error_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.5); + Color readonly_warning_color = error_color.lerp(dark_theme ? Color(0, 0, 0) : Color(1, 1, 1), 0.5); if (!dark_theme) { // Darken some colors to be readable on a light background @@ -445,7 +445,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("error_color", "Editor", error_color); theme->set_color("property_color", "Editor", property_color); theme->set_color("readonly_color", "Editor", readonly_color); - theme->set_color("readonly_error_color", "EditorProperty", readonly_error_color); if (!dark_theme) { theme->set_color("vulkan_color", "Editor", Color::hex(0xad1128ff)); @@ -549,7 +548,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { Ref<StyleBoxEmpty> style_empty = make_empty_stylebox(default_margin_size, default_margin_size, default_margin_size, default_margin_size); - // Tabs + // TabBar Ref<StyleBoxFlat> style_tab_selected = style_widget->duplicate(); @@ -819,10 +818,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_stylebox("bg_selected", "EditorProperty", style_property_bg); theme->set_stylebox("bg", "EditorProperty", Ref<StyleBoxEmpty>(memnew(StyleBoxEmpty))); theme->set_constant("vseparation", "EditorProperty", (extra_spacing + default_margin_size) * EDSCALE); - theme->set_color("error_color", "EditorProperty", error_color); + theme->set_color("warning_color", "EditorProperty", warning_color); theme->set_color("property_color", "EditorProperty", property_color); theme->set_color("readonly_color", "EditorProperty", readonly_color); - theme->set_color("readonly_error_color", "EditorProperty", readonly_error_color); + theme->set_color("readonly_warning_color", "EditorProperty", readonly_warning_color); Color inspector_section_color = font_color.lerp(Color(0.5, 0.5, 0.5), 0.35); theme->set_color("font_color", "EditorInspectorSection", inspector_section_color); @@ -950,33 +949,33 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_constant("icon_margin", "ItemList", 6 * EDSCALE); theme->set_constant("line_separation", "ItemList", 3 * EDSCALE); - // Tabs & TabContainer + // TabBar & TabContainer theme->set_stylebox("tab_selected", "TabContainer", style_tab_selected); theme->set_stylebox("tab_unselected", "TabContainer", style_tab_unselected); theme->set_stylebox("tab_disabled", "TabContainer", style_tab_disabled); - theme->set_stylebox("tab_selected", "Tabs", style_tab_selected); - theme->set_stylebox("tab_unselected", "Tabs", style_tab_unselected); - theme->set_stylebox("tab_disabled", "Tabs", style_tab_disabled); + theme->set_stylebox("tab_selected", "TabBar", style_tab_selected); + theme->set_stylebox("tab_unselected", "TabBar", style_tab_unselected); + theme->set_stylebox("tab_disabled", "TabBar", style_tab_disabled); theme->set_color("font_selected_color", "TabContainer", font_color); theme->set_color("font_unselected_color", "TabContainer", font_disabled_color); - theme->set_color("font_selected_color", "Tabs", font_color); - theme->set_color("font_unselected_color", "Tabs", font_disabled_color); + theme->set_color("font_selected_color", "TabBar", font_color); + theme->set_color("font_unselected_color", "TabBar", font_disabled_color); theme->set_icon("menu", "TabContainer", theme->get_icon("GuiTabMenu", "EditorIcons")); theme->set_icon("menu_highlight", "TabContainer", theme->get_icon("GuiTabMenuHl", "EditorIcons")); theme->set_stylebox("SceneTabFG", "EditorStyles", style_tab_selected); theme->set_stylebox("SceneTabBG", "EditorStyles", style_tab_unselected); - theme->set_icon("close", "Tabs", theme->get_icon("GuiClose", "EditorIcons")); - theme->set_stylebox("close_bg_pressed", "Tabs", style_menu); - theme->set_stylebox("close_bg_highlight", "Tabs", style_menu); + theme->set_icon("close", "TabBar", theme->get_icon("GuiClose", "EditorIcons")); + theme->set_stylebox("close_bg_pressed", "TabBar", style_menu); + theme->set_stylebox("close_bg_highlight", "TabBar", style_menu); theme->set_icon("increment", "TabContainer", theme->get_icon("GuiScrollArrowRight", "EditorIcons")); theme->set_icon("decrement", "TabContainer", theme->get_icon("GuiScrollArrowLeft", "EditorIcons")); - theme->set_icon("increment", "Tabs", theme->get_icon("GuiScrollArrowRight", "EditorIcons")); - theme->set_icon("decrement", "Tabs", theme->get_icon("GuiScrollArrowLeft", "EditorIcons")); - theme->set_icon("increment_highlight", "Tabs", theme->get_icon("GuiScrollArrowRightHl", "EditorIcons")); - theme->set_icon("decrement_highlight", "Tabs", theme->get_icon("GuiScrollArrowLeftHl", "EditorIcons")); + theme->set_icon("increment", "TabBar", theme->get_icon("GuiScrollArrowRight", "EditorIcons")); + theme->set_icon("decrement", "TabBar", theme->get_icon("GuiScrollArrowLeft", "EditorIcons")); + theme->set_icon("increment_highlight", "TabBar", theme->get_icon("GuiScrollArrowRightHl", "EditorIcons")); + theme->set_icon("decrement_highlight", "TabBar", theme->get_icon("GuiScrollArrowLeftHl", "EditorIcons")); theme->set_icon("increment_highlight", "TabContainer", theme->get_icon("GuiScrollArrowRightHl", "EditorIcons")); theme->set_icon("decrement_highlight", "TabContainer", theme->get_icon("GuiScrollArrowLeftHl", "EditorIcons")); - theme->set_constant("hseparation", "Tabs", 4 * EDSCALE); + theme->set_constant("hseparation", "TabBar", 4 * EDSCALE); // Content of each tab Ref<StyleBoxFlat> style_content_panel = style_default->duplicate(); diff --git a/editor/editor_toaster.cpp b/editor/editor_toaster.cpp new file mode 100644 index 0000000000..9de0ea40fe --- /dev/null +++ b/editor/editor_toaster.cpp @@ -0,0 +1,513 @@ +/*************************************************************************/ +/* editor_toaster.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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 "editor/editor_node.h" +#include "editor/editor_scale.h" +#include "scene/gui/label.h" +#include "scene/gui/panel_container.h" + +#include "editor_toaster.h" + +EditorToaster *EditorToaster::singleton = nullptr; + +void EditorToaster::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_INTERNAL_PROCESS: { + double delta = get_process_delta_time(); + + // Check if one element is hovered, if so, don't elapse time. + bool hovered = false; + for (const KeyValue<Control *, Toast> &element : toasts) { + if (Rect2(Vector2(), element.key->get_size()).has_point(element.key->get_local_mouse_position())) { + hovered = true; + break; + } + } + + // Elapses the time and remove toasts if needed. + if (!hovered) { + for (const KeyValue<Control *, Toast> &element : toasts) { + if (!element.value.popped || element.value.duration <= 0) { + continue; + } + toasts[element.key].remaining_time -= delta; + if (toasts[element.key].remaining_time < 0) { + close(element.key); + } + element.key->update(); + } + } else { + // Reset the timers when hovered. + for (const KeyValue<Control *, Toast> &element : toasts) { + if (!element.value.popped || element.value.duration <= 0) { + continue; + } + toasts[element.key].remaining_time = element.value.duration; + element.key->update(); + } + } + + // Change alpha over time. + bool needs_update = false; + for (const KeyValue<Control *, Toast> &element : toasts) { + Color modulate = element.key->get_modulate(); + + // Change alpha over time. + if (element.value.popped && modulate.a < 1.0) { + modulate.a += delta * 3; + element.key->set_modulate(modulate); + } else if (!element.value.popped && modulate.a > 0.0) { + modulate.a -= delta * 2; + element.key->set_modulate(modulate); + } + + // Hide element if it is not visible anymore. + if (modulate.a <= 0) { + if (element.key->is_visible()) { + element.key->hide(); + needs_update = true; + } + } + } + + if (needs_update) { + _update_vbox_position(); + _update_disable_notifications_button(); + main_button->update(); + } + } break; + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + if (vbox_container->is_visible()) { + main_button->set_icon(get_theme_icon(SNAME("Notification"), SNAME("EditorIcons"))); + } else { + main_button->set_icon(get_theme_icon(SNAME("NotificationDisabled"), SNAME("EditorIcons"))); + } + disable_notifications_button->set_icon(get_theme_icon(SNAME("NotificationDisabled"), SNAME("EditorIcons"))); + + // Styleboxes background. + info_panel_style_background->set_bg_color(get_theme_color("base_color", "Editor")); + + warning_panel_style_background->set_bg_color(get_theme_color("base_color", "Editor")); + warning_panel_style_background->set_border_color(get_theme_color("warning_color", "Editor")); + + error_panel_style_background->set_bg_color(get_theme_color("base_color", "Editor")); + error_panel_style_background->set_border_color(get_theme_color("error_color", "Editor")); + + // Styleboxes progress. + info_panel_style_progress->set_bg_color(get_theme_color("base_color", "Editor").lightened(0.03)); + + warning_panel_style_progress->set_bg_color(get_theme_color("base_color", "Editor").lightened(0.03)); + warning_panel_style_progress->set_border_color(get_theme_color("warning_color", "Editor")); + + error_panel_style_progress->set_bg_color(get_theme_color("base_color", "Editor").lightened(0.03)); + error_panel_style_progress->set_border_color(get_theme_color("error_color", "Editor")); + + main_button->update(); + disable_notifications_button->update(); + } break; + case NOTIFICATION_TRANSFORM_CHANGED: { + _update_vbox_position(); + _update_disable_notifications_button(); + } break; + default: + break; + } +} + +void EditorToaster::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type) { + if (!EditorToaster::get_singleton() || !EditorToaster::get_singleton()->is_inside_tree()) { + return; + } + +#ifdef DEV_ENABLED + bool in_dev = true; +#else + bool in_dev = false; +#endif + + int show_all_setting = EDITOR_GET("interface/editor/show_internal_errors_in_toast_notifications"); + + if (p_editor_notify || (show_all_setting == 0 && in_dev) || show_all_setting == 1) { + String err_str; + if (p_errorexp && p_errorexp[0]) { + err_str = p_errorexp; + } else { + err_str = String(p_error); + } + String tooltip_str = String(p_file) + ":" + itos(p_line); + + if (!p_editor_notify) { + if (p_type == ERR_HANDLER_WARNING) { + err_str = "INTERNAL WARNING: " + err_str; + } else { + err_str = "INTERNAL ERROR: " + err_str; + } + } + + if (p_type == ERR_HANDLER_WARNING) { + EditorToaster::get_singleton()->popup_str(err_str, SEVERITY_WARNING, tooltip_str); + } else { + EditorToaster::get_singleton()->popup_str(err_str, SEVERITY_ERROR, tooltip_str); + } + } +} + +void EditorToaster::_update_vbox_position() { + // This is kind of a workaround because it's hard to keep the VBox anchroed to the bottom. + vbox_container->set_size(Vector2()); + vbox_container->set_position(get_global_position() - vbox_container->get_size() + Vector2(get_size().x, -5 * EDSCALE)); +} + +void EditorToaster::_update_disable_notifications_button() { + bool any_visible = false; + for (KeyValue<Control *, Toast> element : toasts) { + if (element.key->is_visible()) { + any_visible = true; + break; + } + } + + if (!any_visible || !vbox_container->is_visible()) { + disable_notifications_panel->hide(); + } else { + disable_notifications_panel->show(); + disable_notifications_panel->set_position(get_global_position() + Vector2(5 * EDSCALE, -disable_notifications_panel->get_minimum_size().y) + Vector2(get_size().x, -5 * EDSCALE)); + } +} + +void EditorToaster::_auto_hide_or_free_toasts() { + // Hide or free old temporary items. + int visible_temporary = 0; + int temporary = 0; + LocalVector<Control *> to_delete; + for (int i = vbox_container->get_child_count() - 1; i >= 0; i--) { + Control *control = Object::cast_to<Control>(vbox_container->get_child(i)); + if (toasts[control].duration <= 0) { + continue; // Ignore non-temporary toasts. + } + + temporary++; + if (control->is_visible()) { + visible_temporary++; + } + + // Hide + if (visible_temporary > max_temporary_count) { + close(control); + } + + // Free + if (temporary > max_temporary_count * 2) { + to_delete.push_back(control); + } + } + + // Delete the control right away (removed as child) as it might cause issues otherwise when iterative over the vbox_container children. + for (unsigned int i = 0; i < to_delete.size(); i++) { + vbox_container->remove_child(to_delete[i]); + to_delete[i]->queue_delete(); + toasts.erase(to_delete[i]); + } +} + +void EditorToaster::_draw_button() { + bool has_one = false; + Severity highest_severity = SEVERITY_INFO; + for (const KeyValue<Control *, Toast> &element : toasts) { + if (!element.key->is_visible()) { + continue; + } + has_one = true; + if (element.value.severity > highest_severity) { + highest_severity = element.value.severity; + } + } + + if (!has_one) { + return; + } + + Color color; + real_t button_radius = main_button->get_size().x / 8; + switch (highest_severity) { + case SEVERITY_INFO: + color = get_theme_color("accent_color", "Editor"); + break; + case SEVERITY_WARNING: + color = get_theme_color("warning_color", "Editor"); + break; + case SEVERITY_ERROR: + color = get_theme_color("error_color", "Editor"); + break; + default: + break; + } + main_button->draw_circle(Vector2(button_radius * 2, button_radius * 2), button_radius, color); +} + +void EditorToaster::_draw_progress(Control *panel) { + if (toasts.has(panel) && toasts[panel].remaining_time > 0 && toasts[panel].duration > 0) { + Size2 size = panel->get_size(); + size.x *= MIN(1, Math::range_lerp(toasts[panel].remaining_time, 0, toasts[panel].duration, 0, 2)); + + Ref<StyleBoxFlat> stylebox; + switch (toasts[panel].severity) { + case SEVERITY_INFO: + stylebox = info_panel_style_progress; + break; + case SEVERITY_WARNING: + stylebox = warning_panel_style_progress; + break; + case SEVERITY_ERROR: + stylebox = error_panel_style_progress; + break; + default: + break; + } + panel->draw_style_box(stylebox, Rect2(Vector2(), size)); + } +} + +void EditorToaster::_set_notifications_enabled(bool p_enabled) { + vbox_container->set_visible(p_enabled); + if (p_enabled) { + main_button->set_icon(get_theme_icon(SNAME("Notification"), SNAME("EditorIcons"))); + } else { + main_button->set_icon(get_theme_icon(SNAME("NotificationDisabled"), SNAME("EditorIcons"))); + } + _update_disable_notifications_button(); +} + +void EditorToaster::_repop_old() { + // Repop olds, up to max_temporary_count + bool needs_update = false; + int visible = 0; + for (int i = vbox_container->get_child_count() - 1; i >= 0; i--) { + Control *control = Object::cast_to<Control>(vbox_container->get_child(i)); + if (!control->is_visible()) { + control->show(); + toasts[control].remaining_time = toasts[control].duration; + toasts[control].popped = true; + needs_update = true; + } + visible++; + if (visible >= max_temporary_count) { + break; + } + } + if (needs_update) { + _update_vbox_position(); + _update_disable_notifications_button(); + main_button->update(); + } +} + +Control *EditorToaster::popup(Control *p_control, Severity p_severity, double p_time, String p_tooltip) { + // Create the panel according to the severity. + PanelContainer *panel = memnew(PanelContainer); + panel->set_tooltip(p_tooltip); + switch (p_severity) { + case SEVERITY_INFO: + panel->add_theme_style_override("panel", info_panel_style_background); + break; + case SEVERITY_WARNING: + panel->add_theme_style_override("panel", warning_panel_style_background); + break; + case SEVERITY_ERROR: + panel->add_theme_style_override("panel", error_panel_style_background); + break; + default: + break; + } + panel->set_modulate(Color(1, 1, 1, 0)); + panel->connect("draw", callable_bind(callable_mp(this, &EditorToaster::_draw_progress), panel)); + + // Horizontal container. + HBoxContainer *hbox_container = memnew(HBoxContainer); + hbox_container->set_h_size_flags(SIZE_EXPAND_FILL); + panel->add_child(hbox_container); + + // Content control. + p_control->set_h_size_flags(SIZE_EXPAND_FILL); + hbox_container->add_child(p_control); + + // Close button. + if (p_time > 0.0) { + Button *close_button = memnew(Button); + close_button->set_flat(true); + close_button->set_icon(get_theme_icon("Close", "EditorIcons")); + close_button->connect("pressed", callable_bind(callable_mp(this, &EditorToaster::close), panel)); + hbox_container->add_child(close_button); + } + + toasts[panel].severity = p_severity; + if (p_time > 0.0) { + toasts[panel].duration = p_time; + toasts[panel].remaining_time = p_time; + } else { + toasts[panel].duration = -1.0; + } + toasts[panel].popped = true; + vbox_container->add_child(panel); + _auto_hide_or_free_toasts(); + _update_vbox_position(); + _update_disable_notifications_button(); + main_button->update(); + + return panel; +} + +void EditorToaster::popup_str(String p_message, Severity p_severity, String p_tooltip) { + // Check if we already have a popup with the given message. + Control *control = nullptr; + for (KeyValue<Control *, Toast> element : toasts) { + if (element.value.message == p_message && element.value.severity == p_severity && element.value.tooltip == p_tooltip) { + control = element.key; + break; + } + } + + // Create a new message if needed. + if (control == nullptr) { + Label *label = memnew(Label); + + control = popup(label, p_severity, default_message_duration, p_tooltip); + toasts[control].message = p_message; + toasts[control].tooltip = p_tooltip; + toasts[control].count = 1; + } else { + if (toasts[control].popped) { + toasts[control].count += 1; + } else { + toasts[control].count = 1; + } + toasts[control].remaining_time = toasts[control].duration; + toasts[control].popped = true; + control->show(); + vbox_container->move_child(control, vbox_container->get_child_count()); + _auto_hide_or_free_toasts(); + _update_vbox_position(); + _update_disable_notifications_button(); + main_button->update(); + } + + // Retrieve the label back then update the text. + Label *label = Object::cast_to<Label>(control->get_child(0)->get_child(0)); + ERR_FAIL_COND(!label); + if (toasts[control].count == 1) { + label->set_text(p_message); + } else { + label->set_text(vformat("%s (%d)", p_message, toasts[control].count)); + } +} + +void EditorToaster::close(Control *p_control) { + ERR_FAIL_COND(!toasts.has(p_control)); + toasts[p_control].remaining_time = -1.0; + toasts[p_control].popped = false; +} + +EditorToaster *EditorToaster::get_singleton() { + return singleton; +} + +EditorToaster::EditorToaster() { + set_notify_transform(true); + set_process_internal(true); + + // VBox. + vbox_container = memnew(VBoxContainer); + vbox_container->set_as_top_level(true); + vbox_container->connect("resized", callable_mp(this, &EditorToaster::_update_vbox_position)); + add_child(vbox_container); + + // Theming (background). + info_panel_style_background.instantiate(); + info_panel_style_background->set_corner_radius_all(stylebox_radius * EDSCALE); + + warning_panel_style_background.instantiate(); + warning_panel_style_background->set_border_width(SIDE_LEFT, stylebox_radius * EDSCALE); + warning_panel_style_background->set_corner_radius_all(stylebox_radius * EDSCALE); + + error_panel_style_background.instantiate(); + error_panel_style_background->set_border_width(SIDE_LEFT, stylebox_radius * EDSCALE); + error_panel_style_background->set_corner_radius_all(stylebox_radius * EDSCALE); + + Ref<StyleBoxFlat> boxes[] = { info_panel_style_background, warning_panel_style_background, error_panel_style_background }; + for (int i = 0; i < 3; i++) { + boxes[i]->set_default_margin(SIDE_LEFT, int(stylebox_radius * 2.5)); + boxes[i]->set_default_margin(SIDE_RIGHT, int(stylebox_radius * 2.5)); + boxes[i]->set_default_margin(SIDE_TOP, 3); + boxes[i]->set_default_margin(SIDE_BOTTOM, 3); + } + + // Theming (progress). + info_panel_style_progress.instantiate(); + info_panel_style_progress->set_corner_radius_all(stylebox_radius * EDSCALE); + + warning_panel_style_progress.instantiate(); + warning_panel_style_progress->set_border_width(SIDE_LEFT, stylebox_radius * EDSCALE); + warning_panel_style_progress->set_corner_radius_all(stylebox_radius * EDSCALE); + + error_panel_style_progress.instantiate(); + error_panel_style_progress->set_border_width(SIDE_LEFT, stylebox_radius * EDSCALE); + error_panel_style_progress->set_corner_radius_all(stylebox_radius * EDSCALE); + + // Main button. + main_button = memnew(Button); + main_button->set_flat(true); + main_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled), varray(true)); + main_button->connect("pressed", callable_mp(this, &EditorToaster::_repop_old)); + main_button->connect("draw", callable_mp(this, &EditorToaster::_draw_button)); + add_child(main_button); + + // Disable notification button. + disable_notifications_panel = memnew(PanelContainer); + disable_notifications_panel->set_as_top_level(true); + disable_notifications_panel->add_theme_style_override("panel", info_panel_style_background); + add_child(disable_notifications_panel); + + disable_notifications_button = memnew(Button); + disable_notifications_button->set_flat(true); + disable_notifications_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled), varray(false)); + disable_notifications_panel->add_child(disable_notifications_button); + + // Other + singleton = this; + + eh.errfunc = _error_handler; + add_error_handler(&eh); +}; + +EditorToaster::~EditorToaster() { + singleton = nullptr; + remove_error_handler(&eh); +} diff --git a/editor/editor_toaster.h b/editor/editor_toaster.h new file mode 100644 index 0000000000..aac80d8fb1 --- /dev/null +++ b/editor/editor_toaster.h @@ -0,0 +1,116 @@ +/*************************************************************************/ +/* editor_toaster.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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. */ +/*************************************************************************/ + +#ifndef EDITOR_TOASTER_H +#define EDITOR_TOASTER_H + +#include "scene/gui/box_container.h" +#include "scene/gui/button.h" +#include "scene/gui/popup.h" + +#include "core/string/ustring.h" +#include "core/templates/local_vector.h" + +class EditorToaster : public HBoxContainer { + GDCLASS(EditorToaster, HBoxContainer); + +public: + enum Severity { + SEVERITY_INFO = 0, + SEVERITY_WARNING, + SEVERITY_ERROR, + }; + +private: + ErrorHandlerList eh; + + const int stylebox_radius = 3; + + Ref<StyleBoxFlat> info_panel_style_background; + Ref<StyleBoxFlat> warning_panel_style_background; + Ref<StyleBoxFlat> error_panel_style_background; + + Ref<StyleBoxFlat> info_panel_style_progress; + Ref<StyleBoxFlat> warning_panel_style_progress; + Ref<StyleBoxFlat> error_panel_style_progress; + + Button *main_button; + PanelContainer *disable_notifications_panel; + Button *disable_notifications_button; + + VBoxContainer *vbox_container; + const int max_temporary_count = 5; + struct Toast { + Severity severity = SEVERITY_INFO; + + // Timing. + real_t duration = -1.0; + real_t remaining_time = 0.0; + bool popped = false; + + // Messages + String message; + String tooltip; + int count = 0; + }; + Map<Control *, Toast> toasts; + + const double default_message_duration = 5.0; + + static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type); + void _update_vbox_position(); + void _update_disable_notifications_button(); + void _auto_hide_or_free_toasts(); + + void _draw_button(); + void _draw_progress(Control *panel); + + void _set_notifications_enabled(bool p_enabled); + void _repop_old(); + +protected: + static EditorToaster *singleton; + + void _notification(int p_what); + +public: + static EditorToaster *get_singleton(); + + Control *popup(Control *p_control, Severity p_severity = SEVERITY_INFO, double p_time = 0.0, String p_tooltip = String()); + void popup_str(String p_message, Severity p_severity = SEVERITY_INFO, String p_tooltip = String()); + void close(Control *p_control); + + EditorToaster(); + ~EditorToaster(); +}; + +VARIANT_ENUM_CAST(EditorToaster::Severity); + +#endif // EDITOR_TOASTER_H diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 73bdd685b7..7c3851b94f 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -205,8 +205,6 @@ private: void _set_file_display(bool p_active); void _fs_changed(); - void _tree_toggle_collapsed(); - void _select_file(const String &p_path, bool p_select_in_favorites = false); void _tree_activate_file(); void _file_list_activate_file(int p_idx); @@ -228,8 +226,6 @@ private: void _file_removed(String p_file); void _folder_removed(String p_folder); - void _files_moved(String p_old_file, String p_new_file); - void _folder_moved(String p_old_folder, String p_new_folder); void _resource_created(); void _make_dir_confirm(); diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index 113306fc8a..f01c7f50f7 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -204,7 +204,8 @@ void GroupDialog::_add_group(String p_name) { TreeItem *new_group = groups->create_item(groups_root); new_group->set_text(0, name); - new_group->add_button(0, groups->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0); + new_group->add_button(0, groups->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), DELETE_GROUP); + new_group->add_button(0, groups->get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), COPY_GROUP); new_group->set_editable(0, true); new_group->select(0); groups->ensure_cursor_is_visible(); @@ -297,43 +298,50 @@ void GroupDialog::_load_groups(Node *p_current) { } } -void GroupDialog::_delete_group_pressed(Object *p_item, int p_column, int p_id) { +void GroupDialog::_modify_group_pressed(Object *p_item, int p_column, int p_id) { TreeItem *ti = Object::cast_to<TreeItem>(p_item); if (!ti) { return; } - String name = ti->get_text(0); + switch (p_id) { + case DELETE_GROUP: { + String name = ti->get_text(0); - undo_redo->create_action(TTR("Delete Group")); + undo_redo->create_action(TTR("Delete Group")); - List<Node *> nodes; - scene_tree->get_nodes_in_group(name, &nodes); - bool removed_all = true; - for (Node *E : nodes) { - if (_can_edit(E, name)) { - undo_redo->add_do_method(E, "remove_from_group", name); - undo_redo->add_undo_method(E, "add_to_group", name, true); - } else { - removed_all = false; - } - } + List<Node *> nodes; + scene_tree->get_nodes_in_group(name, &nodes); + bool removed_all = true; + for (Node *E : nodes) { + if (_can_edit(E, name)) { + undo_redo->add_do_method(E, "remove_from_group", name); + undo_redo->add_undo_method(E, "add_to_group", name, true); + } else { + removed_all = false; + } + } - if (removed_all) { - undo_redo->add_do_method(this, "_delete_group_item", name); - undo_redo->add_undo_method(this, "_add_group", name); - } + if (removed_all) { + undo_redo->add_do_method(this, "_delete_group_item", name); + undo_redo->add_undo_method(this, "_add_group", name); + } - undo_redo->add_do_method(this, "_group_selected"); - undo_redo->add_undo_method(this, "_group_selected"); - undo_redo->add_do_method(this, "emit_signal", "group_edited"); - undo_redo->add_undo_method(this, "emit_signal", "group_edited"); + undo_redo->add_do_method(this, "_group_selected"); + undo_redo->add_undo_method(this, "_group_selected"); + undo_redo->add_do_method(this, "emit_signal", "group_edited"); + undo_redo->add_undo_method(this, "emit_signal", "group_edited"); - // To force redraw of scene tree. - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + // To force redraw of scene tree. + undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); - undo_redo->commit_action(); + undo_redo->commit_action(); + } break; + case COPY_GROUP: { + DisplayServer::get_singleton()->clipboard_set(ti->get_text(p_column)); + } break; + } } void GroupDialog::_delete_group_item(const String &p_name) { @@ -437,7 +445,7 @@ GroupDialog::GroupDialog() { groups->set_v_size_flags(Control::SIZE_EXPAND_FILL); groups->add_theme_constant_override("draw_guides", 1); groups->connect("item_selected", callable_mp(this, &GroupDialog::_group_selected)); - groups->connect("button_pressed", callable_mp(this, &GroupDialog::_delete_group_pressed)); + groups->connect("button_pressed", callable_mp(this, &GroupDialog::_modify_group_pressed)); groups->connect("item_edited", callable_mp(this, &GroupDialog::_group_renamed)); HBoxContainer *chbc = memnew(HBoxContainer); @@ -582,7 +590,7 @@ void GroupsEditor::_add_group(const String &p_group) { group_name->clear(); } -void GroupsEditor::_remove_group(Object *p_item, int p_column, int p_id) { +void GroupsEditor::_modify_group(Object *p_item, int p_column, int p_id) { if (!node) { return; } @@ -591,21 +599,26 @@ void GroupsEditor::_remove_group(Object *p_item, int p_column, int p_id) { if (!ti) { return; } + switch (p_id) { + case DELETE_GROUP: { + String name = ti->get_text(0); + undo_redo->create_action(TTR("Remove from Group")); - String name = ti->get_text(0); - - undo_redo->create_action(TTR("Remove from Group")); - - undo_redo->add_do_method(node, "remove_from_group", name); - undo_redo->add_undo_method(node, "add_to_group", name, true); - undo_redo->add_do_method(this, "update_tree"); - undo_redo->add_undo_method(this, "update_tree"); + undo_redo->add_do_method(node, "remove_from_group", name); + undo_redo->add_undo_method(node, "add_to_group", name, true); + undo_redo->add_do_method(this, "update_tree"); + undo_redo->add_undo_method(this, "update_tree"); - // To force redraw of scene tree. - undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); - undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + // To force redraw of scene tree. + undo_redo->add_do_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); + undo_redo->add_undo_method(EditorNode::get_singleton()->get_scene_tree_dock()->get_tree_editor(), "update_tree"); - undo_redo->commit_action(); + undo_redo->commit_action(); + } break; + case COPY_GROUP: { + DisplayServer::get_singleton()->clipboard_set(ti->get_text(p_column)); + } break; + } } struct _GroupInfoComparator { @@ -653,7 +666,8 @@ void GroupsEditor::update_tree() { TreeItem *item = tree->create_item(root); item->set_text(0, gi.name); if (can_be_deleted) { - item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), 0); + item->add_button(0, get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), DELETE_GROUP); + item->add_button(0, get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), COPY_GROUP); } else { item->set_selectable(0, false); } @@ -706,7 +720,7 @@ GroupsEditor::GroupsEditor() { tree->set_hide_root(true); tree->set_v_size_flags(Control::SIZE_EXPAND_FILL); vbc->add_child(tree); - tree->connect("button_pressed", callable_mp(this, &GroupsEditor::_remove_group)); + tree->connect("button_pressed", callable_mp(this, &GroupsEditor::_modify_group)); tree->add_theme_constant_override("draw_guides", 1); add_theme_constant_override("separation", 3 * EDSCALE); } diff --git a/editor/groups_editor.h b/editor/groups_editor.h index 69f746801f..f0a5b4a794 100644 --- a/editor/groups_editor.h +++ b/editor/groups_editor.h @@ -82,7 +82,7 @@ class GroupDialog : public AcceptDialog { void _rename_group_item(const String &p_old_name, const String &p_new_name); void _add_group(String p_name); - void _delete_group_pressed(Object *p_item, int p_column, int p_id); + void _modify_group_pressed(Object *p_item, int p_column, int p_id); void _delete_group_item(const String &p_name); bool _can_edit(Node *p_node, String p_group); @@ -95,6 +95,11 @@ protected: static void _bind_methods(); public: + enum ModifyButton { + DELETE_GROUP, + COPY_GROUP, + }; + void edit(); void set_undo_redo(UndoRedo *p_undoredo) { undo_redo = p_undoredo; } @@ -116,8 +121,7 @@ class GroupsEditor : public VBoxContainer { void update_tree(); void _add_group(const String &p_group = ""); - void _remove_group(Object *p_item, int p_column, int p_id); - void _close(); + void _modify_group(Object *p_item, int p_column, int p_id); void _show_group_dialog(); @@ -125,6 +129,11 @@ protected: static void _bind_methods(); public: + enum ModifyButton { + DELETE_GROUP, + COPY_GROUP, + }; + void set_undo_redo(UndoRedo *p_undoredo) { undo_redo = p_undoredo; } void set_current(Node *p_node); diff --git a/editor/icons/Notification.svg b/editor/icons/Notification.svg new file mode 100644 index 0000000000..1f1f9c3e15 --- /dev/null +++ b/editor/icons/Notification.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m12.089506 1.2353795c-.498141-.2384823-1.095292-.027987-1.333775.4701537-.01372.028981-.02341.059557-.03428.089693-.01467.023016-.02777.046925-.04071.071459-.04899-.00527-.09728-.00862-.146087-.011473-1.4730257-.6255101-3.1777024.0153376-3.8738627 1.4563251l-1.7272425 3.6078572s-.3364181.7034345-.8079671 1.1268133c-.00105.0009371-.00239.00174-.00344.00268-.2721193.1337295-.5707545.185826-.8605632.0470816-.4981411-.2384824-1.0952924-.0279876-1.3337749.4701537-.01605.033526-.029907.066894-.041944.1011828-.018769.030371-.036749.06319-.052515.096122-.2384825.4981412-.027988 1.0952923.4701537 1.3337751l9.0196437 4.318106c.498141.238482 1.095292.02799 1.333775-.470154.01577-.03293.0301-.0675.04191-.1012.0192-.03086.0365-.06257.05255-.0961.238483-.498141.02799-1.095292-.470153-1.333775-.901965-.43181-.03834-2.235739-.03834-2.235739l1.727237-3.6078618c.715447-1.4944233.08396-3.2858776-1.410461-4.0013247.238482-.4981411.02799-1.0952926-.470154-1.333775zm-5.5145786 11.3714015c-.322341.673306-.037829 1.480435.6354753 1.802775.6733031.32234 1.4804334.03783 1.8027749-.635476z" fill="#e6e6e6"/></svg> diff --git a/editor/icons/NotificationDisabled.svg b/editor/icons/NotificationDisabled.svg new file mode 100644 index 0000000000..0e4465bee8 --- /dev/null +++ b/editor/icons/NotificationDisabled.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m11.705078 1.1386719c-.389281-.0180576-.770356.1928007-.949219.5664062-.01372.028981-.024286.0597078-.035156.0898438-.01467.023016-.026122.0477316-.039062.0722656-.04899-.00527-.097678-.0088657-.146485-.0117187-1.4730253-.6255102-3.1788394.0160437-3.8749998 1.4570312l-1.7265624 3.6074219s-.3370448.7035743-.8085938 1.1269531l-.0019531.0019531c-.2721193.1337295-.5715196.1856194-.8613281.046875-.4981413-.2384824-1.0955019-.0274382-1.3339844.4707031-.01605.0335262-.0289787.0672737-.0410156.1015626-.0187691.0303709-.0369684.0627711-.0527344.0957031-.2384825.4981412-.0293917 1.0955019.46875 1.3339841l.3398437.16211 10.8984379-6.9394535c-.263272-.3070418-.592225-.5660832-.980469-.7519531.238482-.4981411.027441-1.0935489-.470703-1.3320313-.124536-.0596206-.255006-.091637-.384766-.0976562zm2.435547 2.8652343a.94188849 1 0 0 0 -.566406.1386719l-12.1171878 7.7148439a.94188849 1 0 0 0 -.3222656 1.373047.94188849 1 0 0 0 1.2910156.341797l12.1171878-7.7148441a.94188849 1 0 0 0 .322265-1.3710938.94188849 1 0 0 0 -.724609-.4824219zm-.509766 3.2753907-7.3867184 4.7050781 5.0781254 2.431641c.498141.238482 1.095501.027442 1.333984-.470704.01577-.03293.031159-.067862.042969-.101562.0192-.03086.036684-.062173.052734-.095703.238483-.498141.02744-1.095501-.470703-1.333985-.901965-.431809-.039063-2.236328-.039062-2.236328zm-7.0566402 5.3281251c-.322341.673306-.0365856 1.480394.6367187 1.802734.6733031.32234 1.4803929.036588 1.8027344-.636718z" fill="#e6e6e6"/></svg> diff --git a/editor/icons/Tabs.svg b/editor/icons/TabBar.svg index e20a1a0131..e20a1a0131 100644 --- a/editor/icons/Tabs.svg +++ b/editor/icons/TabBar.svg diff --git a/editor/import/resource_importer_layered_texture.h b/editor/import/resource_importer_layered_texture.h index 86e9c5bde8..7d8fb3cac5 100644 --- a/editor/import/resource_importer_layered_texture.h +++ b/editor/import/resource_importer_layered_texture.h @@ -91,8 +91,6 @@ public: virtual Error import(const String &p_source_file, const String &p_save_path, const Map<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; - void update_imports(); - virtual bool are_import_settings_valid(const String &p_path) const override; virtual String get_import_settings_string() const override; diff --git a/editor/plugins/abstract_polygon_2d_editor.h b/editor/plugins/abstract_polygon_2d_editor.h index 4f9adfff25..5fea8b75d6 100644 --- a/editor/plugins/abstract_polygon_2d_editor.h +++ b/editor/plugins/abstract_polygon_2d_editor.h @@ -106,7 +106,6 @@ protected: void _wip_changed(); void _wip_close(); void _wip_cancel(); - bool _delete_point(const Vector2 &p_gpoint); void _notification(int p_what); void _node_removed(Node *p_node); diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h index fe98a91ab3..503e066894 100644 --- a/editor/plugins/animation_blend_space_1d_editor.h +++ b/editor/plugins/animation_blend_space_1d_editor.h @@ -109,8 +109,6 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { void _edit_point_pos(double); void _open_editor(); - void _goto_parent(); - EditorFileDialog *open_file; Ref<AnimationNode> file_loaded; void _file_opened(const String &p_file); diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h index eb8db2eaba..26bcff891d 100644 --- a/editor/plugins/animation_player_editor_plugin.h +++ b/editor/plugins/animation_player_editor_plugin.h @@ -187,7 +187,6 @@ class AnimationPlayerEditor : public VBoxContainer { void _scale_changed(const String &p_scale); void _save_animation(String p_file); void _load_animations(Vector<String> p_files); - void _seek_frame_changed(const String &p_frame); void _seek_value_changed(float p_value, bool p_set = false, bool p_timeline_only = false); void _blend_editor_next_changed(const int p_idx); @@ -217,7 +216,6 @@ class AnimationPlayerEditor : public VBoxContainer { void _pin_pressed(); - AnimationPlayerEditor(); ~AnimationPlayerEditor(); protected: diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h index 286546f962..5fbf2833b2 100644 --- a/editor/plugins/asset_library_editor_plugin.h +++ b/editor/plugins/asset_library_editor_plugin.h @@ -285,7 +285,6 @@ class EditorAssetLibrary : public PanelContainer { void _search_text_submitted(const String &p_text = ""); void _api_request(const String &p_request, RequestType p_request_type, const String &p_arguments = ""); void _http_request_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data); - void _http_download_completed(int p_status, int p_code, const PackedStringArray &headers, const PackedByteArray &p_data); void _filter_debounce_timer_timeout(); void _repository_changed(int p_repository_id); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 1965efbf30..286771ee08 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -421,8 +421,6 @@ private: CanvasItem *ref_item; - void _add_canvas_item(CanvasItem *p_canvas_item); - void _save_canvas_item_state(List<CanvasItem *> p_canvas_items, bool save_bones = false); void _restore_canvas_item_state(List<CanvasItem *> p_canvas_items, bool restore_bones = false); void _commit_canvas_item_state(List<CanvasItem *> p_canvas_items, String action_name, bool commit_bones = false); @@ -434,7 +432,6 @@ private: bool updating_scroll; void _update_scroll(real_t); void _update_scrollbars(); - void _append_canvas_item(CanvasItem *p_item); void _snap_changed(); void _selection_result_pressed(int); void _selection_menu_hide(); @@ -519,7 +516,6 @@ private: const Node *p_current); void _set_anchors_preset(Control::LayoutPreset p_preset); - void _set_offsets_preset(Control::LayoutPreset p_preset); void _set_anchors_and_offsets_preset(Control::LayoutPreset p_preset); void _set_anchors_and_offsets_to_keep_ratio(); @@ -551,15 +547,9 @@ protected: void _notification(int p_what); static void _bind_methods(); - void end_drag(); - void box_selection_start(Point2 &click); - bool box_selection_end(); HBoxContainer *get_panel_hb() { return hb; } - template <class P, class C> - void space_selected_items(); - static CanvasItemEditor *singleton; public: diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index 6e8b9a34cf..091feae5fb 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/editor/plugins/editor_preview_plugins.h @@ -173,4 +173,22 @@ public: EditorFontPreviewPlugin(); ~EditorFontPreviewPlugin(); }; + +class EditorTileMapPatternPreviewPlugin : public EditorResourcePreviewGenerator { + GDCLASS(EditorTileMapPatternPreviewPlugin, EditorResourcePreviewGenerator); + + mutable SafeFlag preview_done; + + void _preview_done(const Variant &p_udata); + +protected: + static void _bind_methods(); + +public: + virtual bool handles(const String &p_type) const override; + virtual Ref<Texture2D> generate(const RES &p_from, const Size2 &p_size) const override; + + EditorTileMapPatternPreviewPlugin(); + ~EditorTileMapPatternPreviewPlugin(); +}; #endif // EDITORPREVIEWPLUGINS_H diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 32a8bbf406..0096152cfe 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2228,18 +2228,28 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) { } if (ED_IS_SHORTCUT("spatial_editor/orbit_view_down", p_event)) { cursor.x_rot -= Math_PI / 12.0; + view_type = VIEW_TYPE_USER; + _update_name(); } if (ED_IS_SHORTCUT("spatial_editor/orbit_view_up", p_event)) { cursor.x_rot += Math_PI / 12.0; + view_type = VIEW_TYPE_USER; + _update_name(); } if (ED_IS_SHORTCUT("spatial_editor/orbit_view_right", p_event)) { cursor.y_rot -= Math_PI / 12.0; + view_type = VIEW_TYPE_USER; + _update_name(); } if (ED_IS_SHORTCUT("spatial_editor/orbit_view_left", p_event)) { cursor.y_rot += Math_PI / 12.0; + view_type = VIEW_TYPE_USER; + _update_name(); } if (ED_IS_SHORTCUT("spatial_editor/orbit_view_180", p_event)) { cursor.y_rot += Math_PI; + view_type = VIEW_TYPE_USER; + _update_name(); } if (ED_IS_SHORTCUT("spatial_editor/focus_origin", p_event)) { _menu_option(VIEW_CENTER_TO_ORIGIN); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index 2d5aeaa981..5290a8804b 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -677,8 +677,6 @@ private: void _register_all_gizmos(); - Node3DEditor(); - void _selection_changed(); void _refresh_menu_icons(); diff --git a/editor/plugins/resource_preloader_editor_plugin.h b/editor/plugins/resource_preloader_editor_plugin.h index 04ab458eb5..943765d4e0 100644 --- a/editor/plugins/resource_preloader_editor_plugin.h +++ b/editor/plugins/resource_preloader_editor_plugin.h @@ -59,7 +59,6 @@ class ResourcePreloaderEditor : public PanelContainer { ResourcePreloader *preloader; void _load_pressed(); - void _load_scene_pressed(); void _files_load_request(const Vector<String> &p_paths); void _paste_pressed(); void _remove_resource(const String &p_to_remove); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 8caebc1c8c..2b0bdfd109 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -371,14 +371,11 @@ class ScriptEditor : public PanelContainer { bool use_space_indentation; bool convert_indent_on_save; - void _trim_trailing_whitespace(TextEdit *tx); - void _goto_script_line2(int p_line); void _goto_script_line(REF p_script, int p_line); void _set_execution(REF p_script, int p_line); void _clear_execution(REF p_script); void _breaked(bool p_breaked, bool p_can_debug); - void _update_window_menu(); void _script_created(Ref<Script> p_script); void _set_breakpoint(REF p_scrpt, int p_line, bool p_enabled); void _clear_breakpoints(); @@ -430,7 +427,6 @@ class ScriptEditor : public PanelContainer { void _make_script_list_context_menu(); void _help_search(String p_text); - void _help_index(String p_text); void _history_forward(); void _history_back(); diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index 5e3b2fb8c1..9732384000 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -100,7 +100,6 @@ class SpriteFramesEditor : public HSplitContainer { float min_sheet_zoom; void _load_pressed(); - void _load_scene_pressed(); void _file_load_request(const Vector<String> &p_path, int p_at_pos = -1); void _copy_pressed(); void _paste_pressed(); @@ -128,7 +127,6 @@ class SpriteFramesEditor : public HSplitContainer { UndoRedo *undo_redo; - bool _is_drop_valid(const Dictionary &p_drag_data, const Dictionary &p_item_data) const; Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 19e1b40a0d..127219546d 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -3204,7 +3204,7 @@ void ThemeEditor::_add_preview_tab(ThemeEditorPreview *p_preview_tab, const Stri preview_tabs->add_tab(p_preview_name, p_icon); preview_tabs_content->add_child(p_preview_tab); - preview_tabs->set_tab_right_button(preview_tabs->get_tab_count() - 1, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("close"), SNAME("Tabs"))); + preview_tabs->set_tab_right_button(preview_tabs->get_tab_count() - 1, EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("close"), SNAME("TabBar"))); p_preview_tab->connect("control_picked", callable_mp(this, &ThemeEditor::_preview_control_picked)); preview_tabs->set_current_tab(preview_tabs->get_tab_count() - 1); @@ -3328,8 +3328,8 @@ ThemeEditor::ThemeEditor() { preview_tabs_content->set_draw_behind_parent(true); preview_tabs_vb->add_child(preview_tabs_content); - preview_tabs = memnew(Tabs); - preview_tabs->set_tab_align(Tabs::ALIGN_LEFT); + preview_tabs = memnew(TabBar); + preview_tabs->set_tab_align(TabBar::ALIGN_LEFT); preview_tabs->set_h_size_flags(SIZE_EXPAND_FILL); preview_tabbar_hb->add_child(preview_tabs); preview_tabs->connect("tab_changed", callable_mp(this, &ThemeEditor::_change_preview_tab)); diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h index 5b0357e3f8..b6becbb1c7 100644 --- a/editor/plugins/theme_editor_plugin.h +++ b/editor/plugins/theme_editor_plugin.h @@ -34,7 +34,7 @@ #include "scene/gui/margin_container.h" #include "scene/gui/option_button.h" #include "scene/gui/scroll_container.h" -#include "scene/gui/tabs.h" +#include "scene/gui/tab_bar.h" #include "scene/gui/texture_rect.h" #include "scene/resources/theme.h" #include "theme_editor_preview.h" @@ -347,7 +347,6 @@ class ThemeTypeEditor : public MarginContainer { void _update_type_items(); void _list_type_selected(int p_index); - void _select_type(String p_type_name); void _add_type_button_cbk(); void _add_default_type_items(); @@ -391,7 +390,7 @@ class ThemeEditor : public VBoxContainer { Ref<Theme> theme; - Tabs *preview_tabs; + TabBar *preview_tabs; PanelContainer *preview_tabs_content; Button *add_preview_button; EditorFileDialog *preview_scene_dialog; diff --git a/editor/plugins/tiles/atlas_merging_dialog.cpp b/editor/plugins/tiles/atlas_merging_dialog.cpp index 2a8a3216ed..efccac7b74 100644 --- a/editor/plugins/tiles/atlas_merging_dialog.cpp +++ b/editor/plugins/tiles/atlas_merging_dialog.cpp @@ -118,6 +118,7 @@ void AtlasMergingDialog::_generate_merged(Vector<Ref<TileSetAtlasSource>> p_atla output_image_texture.instantiate(); output_image_texture->create_from_image(output_image); + merged->set_name(p_atlas_sources[0]->get_name()); merged->set_texture(output_image_texture); merged->set_texture_region_size(new_texture_region_size); } diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 5ca39b82b2..5dfa44a353 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -36,6 +36,7 @@ #include "editor/editor_scale.h" #include "editor/plugins/canvas_item_editor_plugin.h" +#include "scene/2d/camera_2d.h" #include "scene/gui/center_container.h" #include "scene/gui/split_container.h" @@ -43,31 +44,11 @@ #include "core/math/geometry_2d.h" #include "core/os/keyboard.h" -void TileMapEditorTilesPlugin::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_THEME_CHANGED: - select_tool_button->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); - paint_tool_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); - line_tool_button->set_icon(get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons"))); - rect_tool_button->set_icon(get_theme_icon(SNAME("Rectangle"), SNAME("EditorIcons"))); - bucket_tool_button->set_icon(get_theme_icon(SNAME("Bucket"), SNAME("EditorIcons"))); - - picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons"))); - erase_button->set_icon(get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons"))); - - missing_atlas_texture_icon = get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons")); - break; - case NOTIFICATION_VISIBILITY_CHANGED: - _stop_dragging(); - break; - } -} - void TileMapEditorTilesPlugin::tile_set_changed() { _update_fix_selected_and_hovered(); _update_tile_set_sources_list(); - _update_bottom_panel(); + _update_source_display(); + _update_patterns_list(); } void TileMapEditorTilesPlugin::_on_random_tile_checkbox_toggled(bool p_pressed) { @@ -125,8 +106,19 @@ void TileMapEditorTilesPlugin::_update_toolbar() { } } -Control *TileMapEditorTilesPlugin::get_toolbar() const { - return toolbar; +Vector<TileMapEditorPlugin::TabData> TileMapEditorTilesPlugin::get_tabs() const { + Vector<TileMapEditorPlugin::TabData> tabs; + tabs.push_back({ toolbar, tiles_bottom_panel }); + tabs.push_back({ toolbar, patterns_bottom_panel }); + return tabs; +} + +void TileMapEditorTilesPlugin::_tab_changed() { + if (tiles_bottom_panel->is_visible_in_tree()) { + _update_selection_pattern_from_tileset_tiles_selection(); + } else if (patterns_bottom_panel->is_visible_in_tree()) { + _update_selection_pattern_from_tileset_pattern_selection(); + } } void TileMapEditorTilesPlugin::_update_tile_set_sources_list() { @@ -152,22 +144,31 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() { Ref<Texture2D> texture; String item_text; + // Common to all type of sources. + if (!source->get_name().is_empty()) { + item_text = vformat(TTR("%s (id:%d)"), source->get_name(), source_id); + } + // Atlas source. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); if (atlas_source) { texture = atlas_source->get_texture(); - if (texture.is_valid()) { - item_text = vformat("%s (ID: %d)", texture->get_path().get_file(), source_id); - } else { - item_text = vformat("No Texture Atlas Source (ID: %d)", source_id); + if (item_text.is_empty()) { + if (texture.is_valid()) { + item_text = vformat("%s (ID: %d)", texture->get_path().get_file(), source_id); + } else { + item_text = vformat("No Texture Atlas Source (ID: %d)", source_id); + } } } // Scene collection source. TileSetScenesCollectionSource *scene_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); if (scene_collection_source) { - texture = get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")); - item_text = vformat(TTR("Scene Collection Source (ID: %d)"), source_id); + texture = tiles_bottom_panel->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")); + if (item_text.is_empty()) { + item_text = vformat(TTR("Scene Collection Source (ID: %d)"), source_id); + } } // Use default if not valid. @@ -193,10 +194,10 @@ void TileMapEditorTilesPlugin::_update_tile_set_sources_list() { } // Synchronize - TilesEditor::get_singleton()->set_sources_lists_current(sources_list->get_current()); + TilesEditorPlugin::get_singleton()->set_sources_lists_current(sources_list->get_current()); } -void TileMapEditorTilesPlugin::_update_bottom_panel() { +void TileMapEditorTilesPlugin::_update_source_display() { // Update the atlas display. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { @@ -243,6 +244,81 @@ void TileMapEditorTilesPlugin::_update_bottom_panel() { } } +void TileMapEditorTilesPlugin::_patterns_item_list_gui_input(const Ref<InputEvent> &p_event) { + TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); + if (!tile_map) { + return; + } + + Ref<TileSet> tile_set = tile_map->get_tileset(); + if (!tile_set.is_valid()) { + return; + } + + if (ED_IS_SHORTCUT("tiles_editor/paste", p_event) && p_event->is_pressed() && !p_event->is_echo()) { + select_last_pattern = true; + int new_pattern_index = tile_set->get_patterns_count(); + undo_redo->create_action(TTR("Add TileSet pattern")); + undo_redo->add_do_method(*tile_set, "add_pattern", tile_map_clipboard, new_pattern_index); + undo_redo->add_undo_method(*tile_set, "remove_pattern", new_pattern_index); + undo_redo->commit_action(); + patterns_item_list->accept_event(); + } + + if (ED_IS_SHORTCUT("tiles_editor/delete", p_event) && p_event->is_pressed() && !p_event->is_echo()) { + Vector<int> selected = patterns_item_list->get_selected_items(); + undo_redo->create_action(TTR("Remove TileSet patterns")); + for (int i = 0; i < selected.size(); i++) { + int pattern_index = selected[i]; + undo_redo->add_do_method(*tile_set, "remove_pattern", pattern_index); + undo_redo->add_undo_method(*tile_set, "add_pattern", tile_set->get_pattern(pattern_index), pattern_index); + } + undo_redo->commit_action(); + patterns_item_list->accept_event(); + } +} + +void TileMapEditorTilesPlugin::_pattern_preview_done(Ref<TileMapPattern> p_pattern, Ref<Texture2D> p_texture) { + // TODO optimize ? + for (int i = 0; i < patterns_item_list->get_item_count(); i++) { + if (patterns_item_list->get_item_metadata(i) == p_pattern) { + patterns_item_list->set_item_icon(i, p_texture); + break; + } + } +} + +void TileMapEditorTilesPlugin::_update_patterns_list() { + TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); + if (!tile_map) { + return; + } + + Ref<TileSet> tile_set = tile_map->get_tileset(); + if (!tile_set.is_valid()) { + return; + } + + // Recreate the items. + patterns_item_list->clear(); + for (int i = 0; i < tile_set->get_patterns_count(); i++) { + int id = patterns_item_list->add_item(""); + patterns_item_list->set_item_metadata(id, tile_set->get_pattern(i)); + TilesEditorPlugin::get_singleton()->queue_pattern_preview(tile_set, tile_set->get_pattern(i), callable_mp(this, &TileMapEditorTilesPlugin::_pattern_preview_done)); + } + + // Update the label visibility. + patterns_help_label->set_visible(patterns_item_list->get_item_count() == 0); + + // Added a new pattern, thus select the last one. + if (select_last_pattern) { + patterns_item_list->select(tile_set->get_patterns_count() - 1); + patterns_item_list->grab_focus(); + _update_selection_pattern_from_tileset_pattern_selection(); + } + select_last_pattern = false; +} + void TileMapEditorTilesPlugin::_update_atlas_view() { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { @@ -260,7 +336,7 @@ void TileMapEditorTilesPlugin::_update_atlas_view() { ERR_FAIL_COND(!atlas_source); tile_atlas_view->set_atlas_source(*tile_map->get_tileset(), atlas_source, source_id); - TilesEditor::get_singleton()->synchronize_atlas_view(tile_atlas_view); + TilesEditorPlugin::get_singleton()->synchronize_atlas_view(tile_atlas_view); tile_atlas_control->update(); } @@ -295,7 +371,7 @@ void TileMapEditorTilesPlugin::_update_scenes_collection_view() { Variant udata = i; EditorResourcePreview::get_singleton()->queue_edited_resource_preview(scene, this, "_scene_thumbnail_done", udata); } else { - item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"))); + item_index = scene_tiles_list->add_item(TTR("Tile with Invalid Scene"), tiles_bottom_panel->get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons"))); } scene_tiles_list->set_item_metadata(item_index, scene_id); @@ -351,19 +427,32 @@ void TileMapEditorTilesPlugin::_scenes_list_multi_selected(int p_index, bool p_s } } - _update_selection_pattern_from_tileset_selection(); + _update_selection_pattern_from_tileset_tiles_selection(); } void TileMapEditorTilesPlugin::_scenes_list_nothing_selected() { scene_tiles_list->deselect_all(); tile_set_selection.clear(); tile_map_selection.clear(); - selection_pattern->clear(); - _update_selection_pattern_from_tileset_selection(); + selection_pattern.instantiate(); + _update_selection_pattern_from_tileset_tiles_selection(); +} + +void TileMapEditorTilesPlugin::_update_theme() { + select_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); + paint_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); + line_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons"))); + rect_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Rectangle"), SNAME("EditorIcons"))); + bucket_tool_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Bucket"), SNAME("EditorIcons"))); + + picker_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons"))); + erase_button->set_icon(tiles_bottom_panel->get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons"))); + + missing_atlas_texture_icon = tiles_bottom_panel->get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons")); } bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { - if (!is_visible_in_tree()) { + if (!(tiles_bottom_panel->is_visible_in_tree() || patterns_bottom_panel->is_visible_in_tree())) { // If the bottom editor is not visible, we ignore inputs. return false; } @@ -391,7 +480,7 @@ bool TileMapEditorTilesPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p if (ED_IS_SHORTCUT("tiles_editor/cut", p_event) || ED_IS_SHORTCUT("tiles_editor/copy", p_event)) { // Fill in the clipboard. if (!tile_map_selection.is_empty()) { - memdelete(tile_map_clipboard); + tile_map_clipboard.instantiate(); TypedArray<Vector2i> coords_array; for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { coords_array.push_back(E->get()); @@ -624,7 +713,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over Vector2i tile_shape_size = tile_set->get_tile_size(); // Draw the selection. - if (is_visible_in_tree() && tool_buttons_group->get_pressed_button() == select_tool_button) { + if ((tiles_bottom_panel->is_visible_in_tree() || patterns_bottom_panel->is_visible_in_tree()) && tool_buttons_group->get_pressed_button() == select_tool_button) { // In select mode, we only draw the current selection if we are modifying it (pressing control or shift). if (drag_type == DRAG_TYPE_MOVE || (drag_type == DRAG_TYPE_SELECT && !Input::get_singleton()->is_key_pressed(KEY_CTRL) && !Input::get_singleton()->is_key_pressed(KEY_SHIFT))) { // Do nothing @@ -636,7 +725,7 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over } // Handle the preview of the tiles to be placed. - if (is_visible_in_tree() && has_mouse) { // Only if the tilemap editor is opened and the viewport is hovered. + if ((tiles_bottom_panel->is_visible_in_tree() || patterns_bottom_panel->is_visible_in_tree()) && has_mouse) { // Only if the tilemap editor is opened and the viewport is hovered. Map<Vector2i, TileMapCell> preview; Rect2i drawn_grid_rect; @@ -670,21 +759,23 @@ void TileMapEditorTilesPlugin::forward_canvas_draw_over_viewport(Control *p_over } tile_map->draw_cells_outline(p_overlay, to_draw, Color(1.0, 1.0, 1.0), xform); } else if (drag_type == DRAG_TYPE_MOVE) { - // Preview when moving. - Vector2i top_left; - if (!tile_map_selection.is_empty()) { - top_left = tile_map_selection.front()->get(); - } - for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { - top_left = top_left.min(E->get()); - } - Vector2i offset = drag_start_mouse_pos - tile_map->map_to_world(top_left); - offset = tile_map->world_to_map(drag_last_mouse_pos - offset) - tile_map->world_to_map(drag_start_mouse_pos - offset); + if (!(patterns_item_list->is_visible_in_tree() && patterns_item_list->has_point(patterns_item_list->get_local_mouse_position()))) { + // Preview when moving. + Vector2i top_left; + if (!tile_map_selection.is_empty()) { + top_left = tile_map_selection.front()->get(); + } + for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { + top_left = top_left.min(E->get()); + } + Vector2i offset = drag_start_mouse_pos - tile_map->map_to_world(top_left); + offset = tile_map->world_to_map(drag_last_mouse_pos - offset) - tile_map->world_to_map(drag_start_mouse_pos - offset); - TypedArray<Vector2i> selection_used_cells = selection_pattern->get_used_cells(); - for (int i = 0; i < selection_used_cells.size(); i++) { - Vector2i coords = tile_map->map_pattern(offset + top_left, selection_used_cells[i], selection_pattern); - preview[coords] = TileMapCell(selection_pattern->get_cell_source_id(selection_used_cells[i]), selection_pattern->get_cell_atlas_coords(selection_used_cells[i]), selection_pattern->get_cell_alternative_tile(selection_used_cells[i])); + TypedArray<Vector2i> selection_used_cells = selection_pattern->get_used_cells(); + for (int i = 0; i < selection_used_cells.size(); i++) { + Vector2i coords = tile_map->map_pattern(offset + top_left, selection_used_cells[i], selection_pattern); + preview[coords] = TileMapCell(selection_pattern->get_cell_source_id(selection_used_cells[i]), selection_pattern->get_cell_atlas_coords(selection_used_cells[i]), selection_pattern->get_cell_alternative_tile(selection_used_cells[i])); + } } } else if (drag_type == DRAG_TYPE_CLIPBOARD_PASTE) { // Preview when pasting. @@ -823,7 +914,7 @@ void TileMapEditorTilesPlugin::_mouse_exited_viewport() { CanvasItemEditor::get_singleton()->update_viewport(); } -TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(const TileMapPattern *p_pattern) { +TileMapCell TileMapEditorTilesPlugin::_pick_random_tile(Ref<TileMapPattern> p_pattern) { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { return TileMapCell(); @@ -887,9 +978,10 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_line(Vector2 p_start_ } // Get or create the pattern. - TileMapPattern erase_pattern; - erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); - TileMapPattern *pattern = _is_erasing() ? &erase_pattern : selection_pattern; + Ref<TileMapPattern> erase_pattern; + erase_pattern.instantiate(); + erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); + Ref<TileMapPattern> pattern = _is_erasing() ? erase_pattern : selection_pattern; Map<Vector2i, TileMapCell> output; if (!pattern->is_empty()) { @@ -939,9 +1031,11 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_rect(Vector2i p_start rect.size += Vector2i(1, 1); // Get or create the pattern. - TileMapPattern erase_pattern; - erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); - TileMapPattern *pattern = _is_erasing() ? &erase_pattern : selection_pattern; + Ref<TileMapPattern> erase_pattern; + erase_pattern.instantiate(); + erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); + Ref<TileMapPattern> pattern = _is_erasing() ? erase_pattern : selection_pattern; + Map<Vector2i, TileMapCell> err_output; ERR_FAIL_COND_V(pattern->is_empty(), err_output); @@ -998,9 +1092,10 @@ Map<Vector2i, TileMapCell> TileMapEditorTilesPlugin::_draw_bucket_fill(Vector2i } // Get or create the pattern. - TileMapPattern erase_pattern; - erase_pattern.set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); - TileMapPattern *pattern = _is_erasing() ? &erase_pattern : selection_pattern; + Ref<TileMapPattern> erase_pattern; + erase_pattern.instantiate(); + erase_pattern->set_cell(Vector2i(0, 0), TileSet::INVALID_SOURCE, TileSetSource::INVALID_ATLAS_COORDS, TileSetSource::INVALID_TILE_ALTERNATIVE); + Ref<TileMapPattern> pattern = _is_erasing() ? erase_pattern : selection_pattern; if (!pattern->is_empty()) { TileMapCell source = tile_map->get_cell(tile_map_layer, p_coords); @@ -1144,60 +1239,80 @@ void TileMapEditorTilesPlugin::_stop_dragging() { _update_tileset_selection_from_selection_pattern(); } break; case DRAG_TYPE_MOVE: { - Vector2i top_left; - if (!tile_map_selection.is_empty()) { - top_left = tile_map_selection.front()->get(); - } - for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { - top_left = top_left.min(E->get()); - } + if (patterns_item_list->is_visible_in_tree() && patterns_item_list->has_point(patterns_item_list->get_local_mouse_position())) { + // Restore the cells. + for (KeyValue<Vector2i, TileMapCell> kv : drag_modified) { + tile_map->set_cell(tile_map_layer, kv.key, kv.value.source_id, kv.value.get_atlas_coords(), kv.value.alternative_tile); + } + + // Creating a pattern in the pattern list. + select_last_pattern = true; + int new_pattern_index = tile_set->get_patterns_count(); + undo_redo->create_action(TTR("Add TileSet pattern")); + undo_redo->add_do_method(*tile_set, "add_pattern", selection_pattern, new_pattern_index); + undo_redo->add_undo_method(*tile_set, "remove_pattern", new_pattern_index); + undo_redo->commit_action(); + } else { + // Get the top-left cell. + Vector2i top_left; + if (!tile_map_selection.is_empty()) { + top_left = tile_map_selection.front()->get(); + } + for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { + top_left = top_left.min(E->get()); + } - Vector2i offset = drag_start_mouse_pos - tile_map->map_to_world(top_left); - offset = tile_map->world_to_map(mpos - offset) - tile_map->world_to_map(drag_start_mouse_pos - offset); + // Get the offset from the mouse. + Vector2i offset = drag_start_mouse_pos - tile_map->map_to_world(top_left); + offset = tile_map->world_to_map(mpos - offset) - tile_map->world_to_map(drag_start_mouse_pos - offset); - TypedArray<Vector2i> selection_used_cells = selection_pattern->get_used_cells(); + TypedArray<Vector2i> selection_used_cells = selection_pattern->get_used_cells(); - Vector2i coords; - Map<Vector2i, TileMapCell> cells_undo; - for (int i = 0; i < selection_used_cells.size(); i++) { - coords = tile_map->map_pattern(top_left, selection_used_cells[i], selection_pattern); - cells_undo[coords] = TileMapCell(drag_modified[coords].source_id, drag_modified[coords].get_atlas_coords(), drag_modified[coords].alternative_tile); - coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern); - cells_undo[coords] = TileMapCell(tile_map->get_cell_source_id(tile_map_layer, coords), tile_map->get_cell_atlas_coords(tile_map_layer, coords), tile_map->get_cell_alternative_tile(tile_map_layer, coords)); - } + // Build the list of cells to undo. + Vector2i coords; + Map<Vector2i, TileMapCell> cells_undo; + for (int i = 0; i < selection_used_cells.size(); i++) { + coords = tile_map->map_pattern(top_left, selection_used_cells[i], selection_pattern); + cells_undo[coords] = TileMapCell(drag_modified[coords].source_id, drag_modified[coords].get_atlas_coords(), drag_modified[coords].alternative_tile); + coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern); + cells_undo[coords] = TileMapCell(tile_map->get_cell_source_id(tile_map_layer, coords), tile_map->get_cell_atlas_coords(tile_map_layer, coords), tile_map->get_cell_alternative_tile(tile_map_layer, coords)); + } - Map<Vector2i, TileMapCell> cells_do; - for (int i = 0; i < selection_used_cells.size(); i++) { - coords = tile_map->map_pattern(top_left, selection_used_cells[i], selection_pattern); - cells_do[coords] = TileMapCell(); - } - for (int i = 0; i < selection_used_cells.size(); i++) { - coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern); - cells_do[coords] = TileMapCell(selection_pattern->get_cell_source_id(selection_used_cells[i]), selection_pattern->get_cell_atlas_coords(selection_used_cells[i]), selection_pattern->get_cell_alternative_tile(selection_used_cells[i])); - } - undo_redo->create_action(TTR("Move tiles")); - // Move the tiles. - for (const KeyValue<Vector2i, TileMapCell> &E : cells_do) { - undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); - } - for (const KeyValue<Vector2i, TileMapCell> &E : cells_undo) { - undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E.key, E.value.source_id, E.value.get_atlas_coords(), E.value.alternative_tile); - } + // Build the list of cells to do. + Map<Vector2i, TileMapCell> cells_do; + for (int i = 0; i < selection_used_cells.size(); i++) { + coords = tile_map->map_pattern(top_left, selection_used_cells[i], selection_pattern); + cells_do[coords] = TileMapCell(); + } + for (int i = 0; i < selection_used_cells.size(); i++) { + coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern); + cells_do[coords] = TileMapCell(selection_pattern->get_cell_source_id(selection_used_cells[i]), selection_pattern->get_cell_atlas_coords(selection_used_cells[i]), selection_pattern->get_cell_alternative_tile(selection_used_cells[i])); + } - // Update the selection. - undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection()); - tile_map_selection.clear(); - for (int i = 0; i < selection_used_cells.size(); i++) { - coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern); - tile_map_selection.insert(coords); + // Move the tiles. + undo_redo->create_action(TTR("Move tiles")); + for (Map<Vector2i, TileMapCell>::Element *E = cells_do.front(); E; E = E->next()) { + undo_redo->add_do_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + } + for (Map<Vector2i, TileMapCell>::Element *E = cells_undo.front(); E; E = E->next()) { + undo_redo->add_undo_method(tile_map, "set_cell", tile_map_layer, E->key(), E->get().source_id, E->get().get_atlas_coords(), E->get().alternative_tile); + } + + // Update the selection. + undo_redo->add_undo_method(this, "_set_tile_map_selection", _get_tile_map_selection()); + tile_map_selection.clear(); + for (int i = 0; i < selection_used_cells.size(); i++) { + coords = tile_map->map_pattern(top_left + offset, selection_used_cells[i], selection_pattern); + tile_map_selection.insert(coords); + } + undo_redo->add_do_method(this, "_set_tile_map_selection", _get_tile_map_selection()); + undo_redo->commit_action(); } - undo_redo->add_do_method(this, "_set_tile_map_selection", _get_tile_map_selection()); - undo_redo->commit_action(); } break; case DRAG_TYPE_PICK: { Rect2i rect = Rect2i(tile_map->world_to_map(drag_start_mouse_pos), tile_map->world_to_map(mpos) - tile_map->world_to_map(drag_start_mouse_pos)).abs(); rect.size += Vector2i(1, 1); - memdelete(selection_pattern); + TypedArray<Vector2i> coords_array; for (int x = rect.position.x; x < rect.get_end().x; x++) { for (int y = rect.position.y; y < rect.get_end().y; y++) { @@ -1207,11 +1322,10 @@ void TileMapEditorTilesPlugin::_stop_dragging() { } } } - selection_pattern = tile_map->get_pattern(tile_map_layer, coords_array); - if (!selection_pattern->is_empty()) { + Ref<TileMapPattern> new_selection_pattern = tile_map->get_pattern(tile_map_layer, coords_array); + if (!new_selection_pattern->is_empty()) { + selection_pattern = new_selection_pattern; _update_tileset_selection_from_selection_pattern(); - } else { - _update_selection_pattern_from_tileset_selection(); } picker_button->set_pressed(false); } break; @@ -1279,8 +1393,9 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() { hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; tile_set_selection.clear(); + patterns_item_list->deselect_all(); tile_map_selection.clear(); - selection_pattern->clear(); + selection_pattern.instantiate(); return; } @@ -1290,8 +1405,9 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() { hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; tile_set_selection.clear(); + patterns_item_list->deselect_all(); tile_map_selection.clear(); - selection_pattern->clear(); + selection_pattern.instantiate(); return; } @@ -1301,8 +1417,9 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() { hovered_tile.set_atlas_coords(TileSetSource::INVALID_ATLAS_COORDS); hovered_tile.alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE; tile_set_selection.clear(); + patterns_item_list->deselect_all(); tile_map_selection.clear(); - selection_pattern->clear(); + selection_pattern.instantiate(); return; } @@ -1330,8 +1447,10 @@ void TileMapEditorTilesPlugin::_update_fix_selected_and_hovered() { if (!tile_map_selection.is_empty()) { _update_selection_pattern_from_tilemap_selection(); + } else if (tiles_bottom_panel->is_visible_in_tree()) { + _update_selection_pattern_from_tileset_tiles_selection(); } else { - _update_selection_pattern_from_tileset_selection(); + _update_selection_pattern_from_tileset_pattern_selection(); } } @@ -1364,9 +1483,14 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tilemap_selection( return; } + Ref<TileSet> tile_set = tile_map->get_tileset(); + if (!tile_set.is_valid()) { + return; + } + ERR_FAIL_INDEX(tile_map_layer, tile_map->get_layers_count()); - memdelete(selection_pattern); + selection_pattern.instantiate(); TypedArray<Vector2i> coords_array; for (Set<Vector2i>::Element *E = tile_map_selection.front(); E; E = E->next()) { @@ -1375,7 +1499,7 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tilemap_selection( selection_pattern = tile_map->get_pattern(tile_map_layer, coords_array); } -void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection() { +void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_tiles_selection() { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (!tile_map) { return; @@ -1390,7 +1514,7 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection( tile_map_selection.clear(); // Clear the selected pattern. - selection_pattern->clear(); + selection_pattern.instantiate(); // Group per source. Map<int, List<const TileMapCell *>> per_source; @@ -1448,6 +1572,30 @@ void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_selection( CanvasItemEditor::get_singleton()->update_viewport(); } +void TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection() { + TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); + if (!tile_map) { + return; + } + + Ref<TileSet> tile_set = tile_map->get_tileset(); + if (!tile_set.is_valid()) { + return; + } + + // Clear the tilemap selection. + tile_map_selection.clear(); + + // Clear the selected pattern. + selection_pattern.instantiate(); + + if (patterns_item_list->get_selected_items().size() >= 1) { + selection_pattern = patterns_item_list->get_item_metadata(patterns_item_list->get_selected_items()[0]); + } + + CanvasItemEditor::get_singleton()->update_viewport(); +} + void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern() { tile_set_selection.clear(); TypedArray<Vector2i> used_cells = selection_pattern->get_used_cells(); @@ -1457,7 +1605,7 @@ void TileMapEditorTilesPlugin::_update_tileset_selection_from_selection_pattern( tile_set_selection.insert(TileMapCell(selection_pattern->get_cell_source_id(coords), selection_pattern->get_cell_atlas_coords(coords), selection_pattern->get_cell_alternative_tile(coords))); } } - _update_bottom_panel(); + _update_source_display(); tile_atlas_control->update(); alternative_tiles_control->update(); } @@ -1607,7 +1755,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven tile_set_selection.insert(TileMapCell(source_id, hovered_tile.get_atlas_coords(), 0)); } } - _update_selection_pattern_from_tileset_selection(); + _update_selection_pattern_from_tileset_tiles_selection(); } else { // Released if (tile_set_dragging_selection) { if (!mb->is_shift_pressed()) { @@ -1644,7 +1792,7 @@ void TileMapEditorTilesPlugin::_tile_atlas_control_gui_input(const Ref<InputEven } } } - _update_selection_pattern_from_tileset_selection(); + _update_selection_pattern_from_tileset_tiles_selection(); } tile_set_dragging_selection = false; } @@ -1764,7 +1912,7 @@ void TileMapEditorTilesPlugin::_tile_alternatives_control_gui_input(const Ref<In tile_set_selection.insert(TileMapCell(source_id, hovered_tile.get_atlas_coords(), hovered_tile.alternative_tile)); } } - _update_selection_pattern_from_tileset_selection(); + _update_selection_pattern_from_tileset_tiles_selection(); } tile_atlas_control->update(); alternative_tiles_control->update(); @@ -1797,8 +1945,9 @@ void TileMapEditorTilesPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_layer // Clear the selection. tile_set_selection.clear(); + patterns_item_list->deselect_all(); tile_map_selection.clear(); - selection_pattern->clear(); + selection_pattern.instantiate(); } tile_map_layer = p_tile_map_layer; @@ -1820,9 +1969,13 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { ED_SHORTCUT("tiles_editor/cancel", TTR("Cancel"), KEY_ESCAPE); ED_SHORTCUT("tiles_editor/delete", TTR("Delete"), KEY_DELETE); + // --- Initialize references --- + tile_map_clipboard.instantiate(); + selection_pattern.instantiate(); + // --- Toolbar --- toolbar = memnew(HBoxContainer); - toolbar->set_h_size_flags(SIZE_EXPAND_FILL); + toolbar->set_h_size_flags(Control::SIZE_EXPAND_FILL); HBoxContainer *tilemap_tiles_tools_buttons = memnew(HBoxContainer); @@ -1933,42 +2086,47 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { paint_tool_button->set_pressed(true); _update_toolbar(); - // --- Bottom panel --- - set_name("Tiles"); + // --- Bottom panel tiles --- + tiles_bottom_panel = memnew(VBoxContainer); + tiles_bottom_panel->connect("tree_entered", callable_mp(this, &TileMapEditorTilesPlugin::_update_theme)); + tiles_bottom_panel->connect("theme_changed", callable_mp(this, &TileMapEditorTilesPlugin::_update_theme)); + tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_stop_dragging)); + tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_tab_changed)); + tiles_bottom_panel->set_name(TTR("Tiles")); missing_source_label = memnew(Label); missing_source_label->set_text(TTR("This TileMap's TileSet has no source configured. Edit the TileSet resource to add one.")); - missing_source_label->set_h_size_flags(SIZE_EXPAND_FILL); - missing_source_label->set_v_size_flags(SIZE_EXPAND_FILL); + missing_source_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); + missing_source_label->set_v_size_flags(Control::SIZE_EXPAND_FILL); missing_source_label->set_align(Label::ALIGN_CENTER); missing_source_label->set_valign(Label::VALIGN_CENTER); missing_source_label->hide(); - add_child(missing_source_label); + tiles_bottom_panel->add_child(missing_source_label); atlas_sources_split_container = memnew(HSplitContainer); - atlas_sources_split_container->set_h_size_flags(SIZE_EXPAND_FILL); - atlas_sources_split_container->set_v_size_flags(SIZE_EXPAND_FILL); - add_child(atlas_sources_split_container); + atlas_sources_split_container->set_h_size_flags(Control::SIZE_EXPAND_FILL); + atlas_sources_split_container->set_v_size_flags(Control::SIZE_EXPAND_FILL); + tiles_bottom_panel->add_child(atlas_sources_split_container); sources_list = memnew(ItemList); sources_list->set_fixed_icon_size(Size2i(60, 60) * EDSCALE); - sources_list->set_h_size_flags(SIZE_EXPAND_FILL); + sources_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); sources_list->set_stretch_ratio(0.25); sources_list->set_custom_minimum_size(Size2i(70, 0) * EDSCALE); sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_fix_selected_and_hovered).unbind(1)); - sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_bottom_panel).unbind(1)); - sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_sources_lists_current)); - sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_sources_list), varray(sources_list)); + sources_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_source_display).unbind(1)); + sources_list->connect("item_selected", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_sources_lists_current)); + sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list), varray(sources_list)); atlas_sources_split_container->add_child(sources_list); // Tile atlas source. tile_atlas_view = memnew(TileAtlasView); - tile_atlas_view->set_h_size_flags(SIZE_EXPAND_FILL); - tile_atlas_view->set_v_size_flags(SIZE_EXPAND_FILL); + tile_atlas_view->set_h_size_flags(Control::SIZE_EXPAND_FILL); + tile_atlas_view->set_v_size_flags(Control::SIZE_EXPAND_FILL); tile_atlas_view->set_texture_grid_visible(false); tile_atlas_view->set_tile_shape_grid_visible(false); - tile_atlas_view->connect("transform_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_view_transform)); + tile_atlas_view->connect("transform_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_atlas_view_transform)); atlas_sources_split_container->add_child(tile_atlas_view); tile_atlas_control = memnew(Control); @@ -1985,8 +2143,8 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { // Scenes collection source. scene_tiles_list = memnew(ItemList); - scene_tiles_list->set_h_size_flags(SIZE_EXPAND_FILL); - scene_tiles_list->set_v_size_flags(SIZE_EXPAND_FILL); + scene_tiles_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); + scene_tiles_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); scene_tiles_list->set_drag_forwarding(this); scene_tiles_list->set_select_mode(ItemList::SELECT_MULTI); scene_tiles_list->connect("multi_selected", callable_mp(this, &TileMapEditorTilesPlugin::_scenes_list_multi_selected)); @@ -1997,30 +2155,42 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { // Invalid source label. invalid_source_label = memnew(Label); invalid_source_label->set_text(TTR("Invalid source selected.")); - invalid_source_label->set_h_size_flags(SIZE_EXPAND_FILL); - invalid_source_label->set_v_size_flags(SIZE_EXPAND_FILL); + invalid_source_label->set_h_size_flags(Control::SIZE_EXPAND_FILL); + invalid_source_label->set_v_size_flags(Control::SIZE_EXPAND_FILL); invalid_source_label->set_align(Label::ALIGN_CENTER); invalid_source_label->set_valign(Label::VALIGN_CENTER); invalid_source_label->hide(); atlas_sources_split_container->add_child(invalid_source_label); - _update_bottom_panel(); + // --- Bottom panel patterns --- + patterns_bottom_panel = memnew(VBoxContainer); + patterns_bottom_panel->set_name(TTR("Patterns")); + patterns_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_tab_changed)); + + int thumbnail_size = 64; + patterns_item_list = memnew(ItemList); + patterns_item_list->set_max_columns(0); + patterns_item_list->set_icon_mode(ItemList::ICON_MODE_TOP); + patterns_item_list->set_fixed_column_width(thumbnail_size * 3 / 2); + patterns_item_list->set_max_text_lines(2); + patterns_item_list->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size)); + patterns_item_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + patterns_item_list->connect("gui_input", callable_mp(this, &TileMapEditorTilesPlugin::_patterns_item_list_gui_input)); + patterns_item_list->connect("item_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection).unbind(1)); + patterns_item_list->connect("item_activated", callable_mp(this, &TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection)); + patterns_item_list->connect("nothing_selected", callable_mp(this, &TileMapEditorTilesPlugin::_update_selection_pattern_from_tileset_pattern_selection)); + patterns_bottom_panel->add_child(patterns_item_list); + + patterns_help_label = memnew(Label); + patterns_help_label->set_text(TTR("Drag and drop or paste a TileMap selection here to store a pattern.")); + patterns_help_label->set_anchors_and_offsets_preset(Control::PRESET_CENTER); + patterns_item_list->add_child(patterns_help_label); + + // Update. + _update_source_display(); } TileMapEditorTilesPlugin::~TileMapEditorTilesPlugin() { - memdelete(selection_pattern); - memdelete(tile_map_clipboard); -} - -void TileMapEditorTerrainsPlugin::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_THEME_CHANGED: - paint_tool_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); - picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons"))); - erase_button->set_icon(get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons"))); - break; - } } void TileMapEditorTerrainsPlugin::tile_set_changed() { @@ -2043,8 +2213,10 @@ void TileMapEditorTerrainsPlugin::_update_toolbar() { } } -Control *TileMapEditorTerrainsPlugin::get_toolbar() const { - return toolbar; +Vector<TileMapEditorPlugin::TabData> TileMapEditorTerrainsPlugin::get_tabs() const { + Vector<TileMapEditorPlugin::TabData> tabs; + tabs.push_back({ toolbar, main_vbox_container }); + return tabs; } Map<Vector2i, TileSet::CellNeighbor> TileMapEditorTerrainsPlugin::Constraint::get_overlapping_coords_and_peering_bits() const { @@ -2802,7 +2974,7 @@ void TileMapEditorTerrainsPlugin::_stop_dragging() { } bool TileMapEditorTerrainsPlugin::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { - if (!is_visible_in_tree()) { + if (!main_vbox_container->is_visible_in_tree()) { // If the bottom editor is not visible, we ignore inputs. return false; } @@ -3074,13 +3246,13 @@ void TileMapEditorTerrainsPlugin::_update_terrains_tree() { TreeItem *terrain_set_tree_item = terrains_tree->create_item(); String matches; if (tile_set->get_terrain_set_mode(terrain_set_index) == TileSet::TERRAIN_MODE_MATCH_CORNERS_AND_SIDES) { - terrain_set_tree_item->set_icon(0, get_theme_icon(SNAME("TerrainMatchCornersAndSides"), SNAME("EditorIcons"))); + terrain_set_tree_item->set_icon(0, main_vbox_container->get_theme_icon(SNAME("TerrainMatchCornersAndSides"), SNAME("EditorIcons"))); matches = String(TTR("Matches Corners and Sides")); } else if (tile_set->get_terrain_set_mode(terrain_set_index) == TileSet::TERRAIN_MODE_MATCH_CORNERS) { - terrain_set_tree_item->set_icon(0, get_theme_icon(SNAME("TerrainMatchCorners"), SNAME("EditorIcons"))); + terrain_set_tree_item->set_icon(0, main_vbox_container->get_theme_icon(SNAME("TerrainMatchCorners"), SNAME("EditorIcons"))); matches = String(TTR("Matches Corners Only")); } else { - terrain_set_tree_item->set_icon(0, get_theme_icon(SNAME("TerrainMatchSides"), SNAME("EditorIcons"))); + terrain_set_tree_item->set_icon(0, main_vbox_container->get_theme_icon(SNAME("TerrainMatchSides"), SNAME("EditorIcons"))); matches = String(TTR("Matches Sides Only")); } terrain_set_tree_item->set_text(0, vformat("Terrain Set %d (%s)", terrain_set_index, matches)); @@ -3185,6 +3357,12 @@ void TileMapEditorTerrainsPlugin::_update_tiles_list() { } } +void TileMapEditorTerrainsPlugin::_update_theme() { + paint_tool_button->set_icon(main_vbox_container->get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); + picker_button->set_icon(main_vbox_container->get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons"))); + erase_button->set_icon(main_vbox_container->get_theme_icon(SNAME("Eraser"), SNAME("EditorIcons"))); +} + void TileMapEditorTerrainsPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_layer) { _stop_dragging(); // Avoids staying in a wrong drag state. @@ -3197,15 +3375,18 @@ void TileMapEditorTerrainsPlugin::edit(ObjectID p_tile_map_id, int p_tile_map_la } TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { - set_name("Terrains"); + main_vbox_container = memnew(VBoxContainer); + main_vbox_container->connect("tree_entered", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme)); + main_vbox_container->connect("theme_changed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme)); + main_vbox_container->set_name("Terrains"); HSplitContainer *tilemap_tab_terrains = memnew(HSplitContainer); - tilemap_tab_terrains->set_h_size_flags(SIZE_EXPAND_FILL); - tilemap_tab_terrains->set_v_size_flags(SIZE_EXPAND_FILL); - add_child(tilemap_tab_terrains); + tilemap_tab_terrains->set_h_size_flags(Control::SIZE_EXPAND_FILL); + tilemap_tab_terrains->set_v_size_flags(Control::SIZE_EXPAND_FILL); + main_vbox_container->add_child(tilemap_tab_terrains); terrains_tree = memnew(Tree); - terrains_tree->set_h_size_flags(SIZE_EXPAND_FILL); + terrains_tree->set_h_size_flags(Control::SIZE_EXPAND_FILL); terrains_tree->set_stretch_ratio(0.25); terrains_tree->set_custom_minimum_size(Size2i(70, 0) * EDSCALE); terrains_tree->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); @@ -3214,7 +3395,7 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { tilemap_tab_terrains->add_child(terrains_tree); terrains_tile_list = memnew(ItemList); - terrains_tile_list->set_h_size_flags(SIZE_EXPAND_FILL); + terrains_tile_list->set_h_size_flags(Control::SIZE_EXPAND_FILL); terrains_tile_list->set_max_columns(0); terrains_tile_list->set_same_column_width(true); terrains_tile_list->set_fixed_icon_size(Size2(30, 30) * EDSCALE); @@ -3281,7 +3462,7 @@ void TileMapEditor::_notification(int p_what) { if (is_visible_in_tree() && tileset_changed_needs_update) { _update_bottom_panel(); _update_layers_selection(); - tile_map_editor_plugins[tabs->get_current_tab()]->tile_set_changed(); + tabs_plugins[tabs_bar->get_current_tab()]->tile_set_changed(); CanvasItemEditor::get_singleton()->update_viewport(); tileset_changed_needs_update = false; } @@ -3405,14 +3586,11 @@ void TileMapEditor::_update_bottom_panel() { // Update the visibility of controls. missing_tileset_label->set_visible(!tile_set.is_valid()); - if (!tile_set.is_valid()) { - for (int i = 0; i < tile_map_editor_plugins.size(); i++) { - tile_map_editor_plugins[i]->hide(); - } - } else { - for (int i = 0; i < tile_map_editor_plugins.size(); i++) { - tile_map_editor_plugins[i]->set_visible(i == tabs->get_current_tab()); - } + for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) { + tabs_data[tab_index].panel->hide(); + } + if (tile_set.is_valid()) { + tabs_data[tabs_bar->get_current_tab()].panel->show(); } } @@ -3495,27 +3673,25 @@ void TileMapEditor::_tile_map_changed() { void TileMapEditor::_tab_changed(int p_tab_id) { // Make the plugin edit the correct tilemap. - tile_map_editor_plugins[tabs->get_current_tab()]->edit(tile_map_id, tile_map_layer); + tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer); // Update toolbar. - for (int i = 0; i < tile_map_editor_plugins.size(); i++) { - tile_map_editor_plugins[i]->get_toolbar()->set_visible(i == p_tab_id); + for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) { + tabs_data[tab_index].toolbar->hide(); } + tabs_data[p_tab_id].toolbar->show(); // Update visible panel. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); - if (!tile_map || !tile_map->get_tileset().is_valid()) { - for (int i = 0; i < tile_map_editor_plugins.size(); i++) { - tile_map_editor_plugins[i]->hide(); - } - } else { - for (int i = 0; i < tile_map_editor_plugins.size(); i++) { - tile_map_editor_plugins[i]->set_visible(i == tabs->get_current_tab()); - } + for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) { + tabs_data[tab_index].panel->hide(); + } + if (tile_map && tile_map->get_tileset().is_valid()) { + tabs_data[tabs_bar->get_current_tab()].panel->show(); } // Graphical update. - tile_map_editor_plugins[tabs->get_current_tab()]->update(); + tabs_data[tabs_bar->get_current_tab()].panel->update(); CanvasItemEditor::get_singleton()->update_viewport(); } @@ -3602,7 +3778,7 @@ void TileMapEditor::_update_layers_selection() { layers_selection_button->set_custom_minimum_size(min_button_size); layers_selection_button->update(); - tile_map_editor_plugins[tabs->get_current_tab()]->edit(tile_map_id, tile_map_layer); + tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer); } void TileMapEditor::_move_tile_map_array_element(Object *p_undo_redo, Object *p_edited, String p_array_prefix, int p_from_index, int p_to_pos) { @@ -3688,7 +3864,7 @@ bool TileMapEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return true; } - return tile_map_editor_plugins[tabs->get_current_tab()]->forward_canvas_gui_input(p_event); + return tabs_plugins[tabs_bar->get_current_tab()]->forward_canvas_gui_input(p_event); } void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { @@ -3823,7 +3999,7 @@ void TileMapEditor::forward_canvas_draw_over_viewport(Control *p_overlay) { }*/ // Draw the plugins. - tile_map_editor_plugins[tabs->get_current_tab()]->forward_canvas_draw_over_viewport(p_overlay); + tabs_plugins[tabs_bar->get_current_tab()]->forward_canvas_draw_over_viewport(p_overlay); } void TileMapEditor::edit(TileMap *p_tile_map) { @@ -3857,7 +4033,7 @@ void TileMapEditor::edit(TileMap *p_tile_map) { _update_layers_selection(); // Call the plugins. - tile_map_editor_plugins[tabs->get_current_tab()]->edit(tile_map_id, tile_map_layer); + tabs_plugins[tabs_bar->get_current_tab()]->edit(tile_map_id, tile_map_layer); _tile_map_changed(); } @@ -3873,25 +4049,33 @@ TileMapEditor::TileMapEditor() { tile_map_editor_plugins.push_back(memnew(TileMapEditorTilesPlugin)); tile_map_editor_plugins.push_back(memnew(TileMapEditorTerrainsPlugin)); - // Tabs. - tabs = memnew(Tabs); - tabs->set_clip_tabs(false); - for (int i = 0; i < tile_map_editor_plugins.size(); i++) { - tabs->add_tab(tile_map_editor_plugins[i]->get_name()); + // TabBar. + tabs_bar = memnew(TabBar); + tabs_bar->set_clip_tabs(false); + for (int plugin_index = 0; plugin_index < tile_map_editor_plugins.size(); plugin_index++) { + Vector<TileMapEditorPlugin::TabData> tabs_vector = tile_map_editor_plugins[plugin_index]->get_tabs(); + for (int tab_index = 0; tab_index < tabs_vector.size(); tab_index++) { + tabs_bar->add_tab(tabs_vector[tab_index].panel->get_name()); + tabs_data.push_back(tabs_vector[tab_index]); + tabs_plugins.push_back(tile_map_editor_plugins[plugin_index]); + } } - tabs->connect("tab_changed", callable_mp(this, &TileMapEditor::_tab_changed)); + tabs_bar->connect("tab_changed", callable_mp(this, &TileMapEditor::_tab_changed)); // --- TileMap toolbar --- tile_map_toolbar = memnew(HBoxContainer); tile_map_toolbar->set_h_size_flags(SIZE_EXPAND_FILL); + add_child(tile_map_toolbar); // Tabs. - tile_map_toolbar->add_child(tabs); + tile_map_toolbar->add_child(tabs_bar); // Tabs toolbars. - for (int i = 0; i < tile_map_editor_plugins.size(); i++) { - tile_map_editor_plugins[i]->get_toolbar()->hide(); - tile_map_toolbar->add_child(tile_map_editor_plugins[i]->get_toolbar()); + for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) { + tabs_data[tab_index].toolbar->hide(); + if (!tabs_data[tab_index].toolbar->get_parent()) { + tile_map_toolbar->add_child(tabs_data[tab_index].toolbar); + } } // Wide empty separation control. @@ -3947,11 +4131,11 @@ TileMapEditor::TileMapEditor() { missing_tileset_label->hide(); add_child(missing_tileset_label); - for (int i = 0; i < tile_map_editor_plugins.size(); i++) { - add_child(tile_map_editor_plugins[i]); - tile_map_editor_plugins[i]->set_h_size_flags(SIZE_EXPAND_FILL); - tile_map_editor_plugins[i]->set_v_size_flags(SIZE_EXPAND_FILL); - tile_map_editor_plugins[i]->set_visible(i == 0); + for (unsigned int tab_index = 0; tab_index < tabs_data.size(); tab_index++) { + add_child(tabs_data[tab_index].panel); + tabs_data[tab_index].panel->set_v_size_flags(SIZE_EXPAND_FILL); + tabs_data[tab_index].panel->set_visible(tab_index == 0); + tabs_data[tab_index].panel->set_h_size_flags(SIZE_EXPAND_FILL); } _tab_changed(0); @@ -3961,4 +4145,7 @@ TileMapEditor::TileMapEditor() { } TileMapEditor::~TileMapEditor() { + for (int i = 0; i < tile_map_editor_plugins.size(); i++) { + memdelete(tile_map_editor_plugins[i]); + } } diff --git a/editor/plugins/tiles/tile_map_editor.h b/editor/plugins/tiles/tile_map_editor.h index 5fbd9cada8..1f1a560113 100644 --- a/editor/plugins/tiles/tile_map_editor.h +++ b/editor/plugins/tiles/tile_map_editor.h @@ -33,17 +33,24 @@ #include "tile_atlas_view.h" +#include "core/os/thread.h" #include "core/typedefs.h" #include "editor/editor_node.h" #include "scene/2d/tile_map.h" #include "scene/gui/box_container.h" -#include "scene/gui/tabs.h" +#include "scene/gui/tab_bar.h" -class TileMapEditorPlugin : public VBoxContainer { +class TileMapEditorPlugin : public Object { public: - virtual Control *get_toolbar() const { - return memnew(Control); + struct TabData { + Control *toolbar; + Control *panel; }; + + virtual Vector<TabData> get_tabs() const { + return Vector<TabData>(); + }; + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return false; }; virtual void forward_canvas_draw_over_viewport(Control *p_overlay){}; virtual void tile_set_changed(){}; @@ -106,7 +113,7 @@ private: Map<Vector2i, TileMapCell> drag_modified; bool rmb_erasing = false; - TileMapCell _pick_random_tile(const TileMapPattern *p_pattern); + TileMapCell _pick_random_tile(Ref<TileMapPattern> p_pattern); Map<Vector2i, TileMapCell> _draw_line(Vector2 p_start_drag_mouse_pos, Vector2 p_from_mouse_pos, Vector2 p_to_mouse_pos); Map<Vector2i, TileMapCell> _draw_rect(Vector2i p_start_cell, Vector2i p_end_cell); Map<Vector2i, TileMapCell> _draw_bucket_fill(Vector2i p_coords, bool p_contiguous); @@ -115,20 +122,25 @@ private: ///// Selection system. ///// Set<Vector2i> tile_map_selection; - TileMapPattern *tile_map_clipboard = memnew(TileMapPattern); - TileMapPattern *selection_pattern = memnew(TileMapPattern); + Ref<TileMapPattern> tile_map_clipboard; + Ref<TileMapPattern> selection_pattern; void _set_tile_map_selection(const TypedArray<Vector2i> &p_selection); TypedArray<Vector2i> _get_tile_map_selection() const; Set<TileMapCell> tile_set_selection; void _update_selection_pattern_from_tilemap_selection(); - void _update_selection_pattern_from_tileset_selection(); + void _update_selection_pattern_from_tileset_tiles_selection(); + void _update_selection_pattern_from_tileset_pattern_selection(); void _update_tileset_selection_from_selection_pattern(); void _update_fix_selected_and_hovered(); void _fix_invalid_tiles_in_tile_map_selection(); - ///// Bottom panel. ////. + ///// Bottom panel common //// + void _tab_changed(); + + ///// Bottom panel tiles //// + VBoxContainer *tiles_bottom_panel; Label *missing_source_label; Label *invalid_source_label; @@ -137,7 +149,7 @@ private: Ref<Texture2D> missing_atlas_texture_icon; void _update_tile_set_sources_list(); - void _update_bottom_panel(); + void _update_source_display(); // Atlas sources. TileMapCell hovered_tile; @@ -167,15 +179,26 @@ private: void _scenes_list_multi_selected(int p_index, bool p_selected); void _scenes_list_nothing_selected(); + ///// Bottom panel patterns //// + VBoxContainer *patterns_bottom_panel; + ItemList *patterns_item_list; + Label *patterns_help_label; + void _patterns_item_list_gui_input(const Ref<InputEvent> &p_event); + void _pattern_preview_done(Ref<TileMapPattern> p_pattern, Ref<Texture2D> p_texture); + bool select_last_pattern = false; + void _update_patterns_list(); + + // General + void _update_theme(); + // Update callback virtual void tile_set_changed() override; protected: - void _notification(int p_what); static void _bind_methods(); public: - virtual Control *get_toolbar() const override; + virtual Vector<TabData> get_tabs() const override; virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override; virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override; @@ -205,6 +228,9 @@ private: void _update_toolbar(); + // Main vbox. + VBoxContainer *main_vbox_container; + // TileMap editing. enum DragType { DRAG_TYPE_NONE = 0, @@ -281,16 +307,13 @@ private: void _update_terrains_cache(); void _update_terrains_tree(); void _update_tiles_list(); + void _update_theme(); // Update callback virtual void tile_set_changed() override; -protected: - void _notification(int p_what); - // static void _bind_methods(); - public: - virtual Control *get_toolbar() const override; + virtual Vector<TabData> get_tabs() const override; virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override; //virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override; @@ -328,7 +351,9 @@ private: // Bottom panel. Label *missing_tileset_label; - Tabs *tabs; + TabBar *tabs_bar; + LocalVector<TileMapEditorPlugin::TabData> tabs_data; + LocalVector<TileMapEditorPlugin *> tabs_plugins; void _update_bottom_panel(); // TileMap. @@ -355,7 +380,6 @@ public: void forward_canvas_draw_over_viewport(Control *p_overlay); void edit(TileMap *p_tile_map); - Control *get_toolbar() { return tile_map_toolbar; }; TileMapEditor(); ~TileMapEditor(); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index c43a854d9a..c8892bceaa 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -66,10 +66,15 @@ int TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::get_id() { } bool TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_set(const StringName &p_name, const Variant &p_value) { + String name = p_name; + if (name == "name") { + // Use the resource_name property to store the source's name. + name = "resource_name"; + } bool valid = false; - tile_set_atlas_source->set(p_name, p_value, &valid); + tile_set_atlas_source->set(name, p_value, &valid); if (valid) { - emit_signal(SNAME("changed"), String(p_name).utf8().get_data()); + emit_signal(SNAME("changed"), String(name).utf8().get_data()); } return valid; } @@ -78,12 +83,18 @@ bool TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get(const StringN if (!tile_set_atlas_source) { return false; } + String name = p_name; + if (name == "name") { + // Use the resource_name property to store the source's name. + name = "resource_name"; + } bool valid = false; - r_ret = tile_set_atlas_source->get(p_name, &valid); + r_ret = tile_set_atlas_source->get(name, &valid); return valid; } void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::_get_property_list(List<PropertyInfo> *p_list) const { + p_list->push_back(PropertyInfo(Variant::STRING, "name", PROPERTY_HINT_NONE, "")); p_list->push_back(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D")); p_list->push_back(PropertyInfo(Variant::VECTOR2I, "margins", PROPERTY_HINT_NONE, "")); p_list->push_back(PropertyInfo(Variant::VECTOR2I, "separation", PROPERTY_HINT_NONE, "")); @@ -106,6 +117,10 @@ void TileSetAtlasSourceEditor::TileSetAtlasSourceProxyObject::edit(Ref<TileSet> ERR_FAIL_COND(p_source_id < 0); ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_atlas_source); + if (p_tile_set == tile_set && p_tile_set_atlas_source == tile_set_atlas_source && p_source_id == source_id) { + return; + } + // Disconnect to changes. if (tile_set_atlas_source) { tile_set_atlas_source->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed)); @@ -157,7 +172,7 @@ bool TileSetAtlasSourceEditor::AtlasTileProxyObject::_set(const StringName &p_na } else if (p_name == "size_in_atlas") { Vector2i as_vector2i = Vector2i(p_value); bool has_room_for_tile = tile_set_atlas_source->has_room_for_tile(coords, as_vector2i, tile_set_atlas_source->get_tile_animation_columns(coords), tile_set_atlas_source->get_tile_animation_separation(coords), tile_set_atlas_source->get_tile_animation_frames_count(coords), coords); - ERR_FAIL_COND_V(!has_room_for_tile, false); + ERR_FAIL_COND_V_EDMSG(!has_room_for_tile, false, "Invalid size or not enough room in the atlas for the tile."); tile_set_atlas_source->move_tile_in_atlas(coords, TileSetSource::INVALID_ATLAS_COORDS, as_vector2i); emit_signal(SNAME("changed"), "size_in_atlas"); return true; @@ -909,7 +924,7 @@ void TileSetAtlasSourceEditor::_update_atlas_view() { tile_atlas_view->update(); // Synchronize atlas view. - TilesEditor::get_singleton()->synchronize_atlas_view(tile_atlas_view); + TilesEditorPlugin::get_singleton()->synchronize_atlas_view(tile_atlas_view); } void TileSetAtlasSourceEditor::_update_toolbar() { @@ -2461,7 +2476,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tile_atlas_view = memnew(TileAtlasView); tile_atlas_view->set_h_size_flags(SIZE_EXPAND_FILL); tile_atlas_view->set_v_size_flags(SIZE_EXPAND_FILL); - tile_atlas_view->connect("transform_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_atlas_view_transform)); + tile_atlas_view->connect("transform_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_atlas_view_transform)); tile_atlas_view->connect("transform_changed", callable_mp(this, &TileSetAtlasSourceEditor::_tile_atlas_view_transform_changed).unbind(2)); right_panel->add_child(tile_atlas_view); diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index 48d0d9b333..0fbb9a98c7 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -145,14 +145,21 @@ void TileSetEditor::_update_sources_list(int force_selected_id) { Ref<Texture2D> texture; String item_text; + // Common to all type of sources. + if (!source->get_name().is_empty()) { + item_text = vformat(TTR("%s (id:%d)"), source->get_name(), source_id); + } + // Atlas source. TileSetAtlasSource *atlas_source = Object::cast_to<TileSetAtlasSource>(source); if (atlas_source) { texture = atlas_source->get_texture(); - if (texture.is_valid()) { - item_text = vformat("%s (id:%d)", texture->get_path().get_file(), source_id); - } else { - item_text = vformat(TTR("No Texture Atlas Source (id:%d)"), source_id); + if (item_text.is_empty()) { + if (texture.is_valid()) { + item_text = vformat("%s (ID:%d)", texture->get_path().get_file(), source_id); + } else { + item_text = vformat(TTR("No Texture Atlas Source (ID:%d)"), source_id); + } } } @@ -160,12 +167,14 @@ void TileSetEditor::_update_sources_list(int force_selected_id) { TileSetScenesCollectionSource *scene_collection_source = Object::cast_to<TileSetScenesCollectionSource>(source); if (scene_collection_source) { texture = get_theme_icon(SNAME("PackedScene"), SNAME("EditorIcons")); - item_text = vformat(TTR("Scene Collection Source (id:%d)"), source_id); + if (item_text.is_empty()) { + item_text = vformat(TTR("Scene Collection Source (ID:%d)"), source_id); + } } // Use default if not valid. if (item_text.is_empty()) { - item_text = vformat(TTR("Unknown Type Source (id:%d)"), source_id); + item_text = vformat(TTR("Unknown Type Source (ID:%d)"), source_id); } if (!texture.is_valid()) { texture = missing_texture_texture; @@ -200,7 +209,7 @@ void TileSetEditor::_update_sources_list(int force_selected_id) { _source_selected(sources_list->get_current()); // Synchronize the lists. - TilesEditor::get_singleton()->set_sources_lists_current(sources_list->get_current()); + TilesEditorPlugin::get_singleton()->set_sources_lists_current(sources_list->get_current()); } void TileSetEditor::_source_selected(int p_source_index) { @@ -318,6 +327,7 @@ void TileSetEditor::_notification(int p_what) { tile_set->set_edited(true); } _update_sources_list(); + _update_patterns_list(); tile_set_changed_needs_update = false; } break; @@ -326,10 +336,56 @@ void TileSetEditor::_notification(int p_what) { } } +void TileSetEditor::_patterns_item_list_gui_input(const Ref<InputEvent> &p_event) { + ERR_FAIL_COND(!tile_set.is_valid()); + + if (ED_IS_SHORTCUT("tiles_editor/delete", p_event) && p_event->is_pressed() && !p_event->is_echo()) { + Vector<int> selected = patterns_item_list->get_selected_items(); + undo_redo->create_action(TTR("Remove TileSet patterns")); + for (int i = 0; i < selected.size(); i++) { + int pattern_index = selected[i]; + undo_redo->add_do_method(*tile_set, "remove_pattern", pattern_index); + undo_redo->add_undo_method(*tile_set, "add_pattern", tile_set->get_pattern(pattern_index), pattern_index); + } + undo_redo->commit_action(); + patterns_item_list->accept_event(); + } +} + +void TileSetEditor::_pattern_preview_done(Ref<TileMapPattern> p_pattern, Ref<Texture2D> p_texture) { + // TODO optimize ? + for (int i = 0; i < patterns_item_list->get_item_count(); i++) { + if (patterns_item_list->get_item_metadata(i) == p_pattern) { + patterns_item_list->set_item_icon(i, p_texture); + break; + } + } +} + +void TileSetEditor::_update_patterns_list() { + ERR_FAIL_COND(!tile_set.is_valid()); + + // Recreate the items. + patterns_item_list->clear(); + for (int i = 0; i < tile_set->get_patterns_count(); i++) { + int id = patterns_item_list->add_item(""); + patterns_item_list->set_item_metadata(id, tile_set->get_pattern(i)); + TilesEditorPlugin::get_singleton()->queue_pattern_preview(tile_set, tile_set->get_pattern(i), callable_mp(this, &TileSetEditor::_pattern_preview_done)); + } + + // Update the label visibility. + patterns_help_label->set_visible(patterns_item_list->get_item_count() == 0); +} + void TileSetEditor::_tile_set_changed() { tile_set_changed_needs_update = true; } +void TileSetEditor::_tab_changed(int p_tab_changed) { + split_container->set_visible(p_tab_changed == 0); + patterns_item_list->set_visible(p_tab_changed == 1); +} + void TileSetEditor::_move_tile_set_array_element(Object *p_undo_redo, Object *p_edited, String p_array_prefix, int p_from_index, int p_to_pos) { UndoRedo *undo_redo = Object::cast_to<UndoRedo>(p_undo_redo); ERR_FAIL_COND(!undo_redo); @@ -573,6 +629,7 @@ void TileSetEditor::edit(Ref<TileSet> p_tile_set) { if (tile_set.is_valid()) { tile_set->connect("changed", callable_mp(this, &TileSetEditor::_tile_set_changed)); _update_sources_list(); + _update_patterns_list(); } tile_set_atlas_source_editor->hide(); @@ -585,8 +642,21 @@ TileSetEditor::TileSetEditor() { set_process_internal(true); + // TabBar. + tabs_bar = memnew(TabBar); + tabs_bar->set_clip_tabs(false); + tabs_bar->add_tab(TTR("Tiles")); + tabs_bar->add_tab(TTR("Patterns")); + tabs_bar->connect("tab_changed", callable_mp(this, &TileSetEditor::_tab_changed)); + + tile_set_toolbar = memnew(HBoxContainer); + tile_set_toolbar->set_h_size_flags(SIZE_EXPAND_FILL); + tile_set_toolbar->add_child(tabs_bar); + add_child(tile_set_toolbar); + + //// Tiles //// // Split container. - HSplitContainer *split_container = memnew(HSplitContainer); + split_container = memnew(HSplitContainer); split_container->set_name(TTR("Tiles")); split_container->set_h_size_flags(SIZE_EXPAND_FILL); split_container->set_v_size_flags(SIZE_EXPAND_FILL); @@ -605,8 +675,8 @@ TileSetEditor::TileSetEditor() { sources_list->set_h_size_flags(SIZE_EXPAND_FILL); sources_list->set_v_size_flags(SIZE_EXPAND_FILL); sources_list->connect("item_selected", callable_mp(this, &TileSetEditor::_source_selected)); - sources_list->connect("item_selected", callable_mp(TilesEditor::get_singleton(), &TilesEditor::set_sources_lists_current)); - sources_list->connect("visibility_changed", callable_mp(TilesEditor::get_singleton(), &TilesEditor::synchronize_sources_list), varray(sources_list)); + sources_list->connect("item_selected", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::set_sources_lists_current)); + sources_list->connect("visibility_changed", callable_mp(TilesEditorPlugin::get_singleton(), &TilesEditorPlugin::synchronize_sources_list), varray(sources_list)); sources_list->set_texture_filter(CanvasItem::TEXTURE_FILTER_NEAREST); sources_list->set_drag_forwarding(this); split_container_left_side->add_child(sources_list); @@ -672,6 +742,24 @@ TileSetEditor::TileSetEditor() { split_container_right_side->add_child(tile_set_scenes_collection_source_editor); tile_set_scenes_collection_source_editor->hide(); + //// Patterns //// + int thumbnail_size = 64; + patterns_item_list = memnew(ItemList); + patterns_item_list->set_max_columns(0); + patterns_item_list->set_icon_mode(ItemList::ICON_MODE_TOP); + patterns_item_list->set_fixed_column_width(thumbnail_size * 3 / 2); + patterns_item_list->set_max_text_lines(2); + patterns_item_list->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size)); + patterns_item_list->set_v_size_flags(Control::SIZE_EXPAND_FILL); + patterns_item_list->connect("gui_input", callable_mp(this, &TileSetEditor::_patterns_item_list_gui_input)); + add_child(patterns_item_list); + patterns_item_list->hide(); + + patterns_help_label = memnew(Label); + patterns_help_label->set_text(TTR("Add new patterns in the TileMap editing mode.")); + patterns_help_label->set_anchors_and_offsets_preset(Control::PRESET_CENTER); + patterns_item_list->add_child(patterns_help_label); + // Registers UndoRedo inspector callback. EditorNode::get_singleton()->get_editor_data().add_move_array_element_function(SNAME("TileSet"), callable_mp(this, &TileSetEditor::_move_tile_set_array_element)); EditorNode::get_singleton()->get_editor_data().add_undo_redo_inspector_hook_callback(callable_mp(this, &TileSetEditor::_undo_redo_inspector_callback)); diff --git a/editor/plugins/tiles/tile_set_editor.h b/editor/plugins/tiles/tile_set_editor.h index fe854b2281..cda38760cf 100644 --- a/editor/plugins/tiles/tile_set_editor.h +++ b/editor/plugins/tiles/tile_set_editor.h @@ -46,7 +46,13 @@ class TileSetEditor : public VBoxContainer { private: Ref<TileSet> tile_set; bool tile_set_changed_needs_update = false; + HSplitContainer *split_container; + // TabBar. + HBoxContainer *tile_set_toolbar; + TabBar *tabs_bar; + + // Tiles. Label *no_source_selected_label; TileSetAtlasSourceEditor *tile_set_atlas_source_editor; TileSetScenesCollectionSourceEditor *tile_set_scenes_collection_source_editor; @@ -69,7 +75,16 @@ private: AtlasMergingDialog *atlas_merging_dialog; TileProxiesManagerDialog *tile_proxies_manager_dialog; + // Patterns. + ItemList *patterns_item_list; + Label *patterns_help_label; + void _patterns_item_list_gui_input(const Ref<InputEvent> &p_event); + void _pattern_preview_done(Ref<TileMapPattern> p_pattern, Ref<Texture2D> p_texture); + bool select_last_pattern = false; + void _update_patterns_list(); + void _tile_set_changed(); + void _tab_changed(int p_tab_changed); void _move_tile_set_array_element(Object *p_undo_redo, Object *p_edited, String p_array_prefix, int p_from_index, int p_to_pos); void _undo_redo_inspector_callback(Object *p_undo_redo, Object *p_edited, String p_property, Variant p_new_value); @@ -82,6 +97,7 @@ public: _FORCE_INLINE_ static TileSetEditor *get_singleton() { return singleton; } void edit(Ref<TileSet> p_tile_set); + void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp index f74b3bf9c2..dc26d380b8 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp @@ -56,10 +56,15 @@ int TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::get } bool TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_set(const StringName &p_name, const Variant &p_value) { + String name = p_name; + if (name == "name") { + // Use the resource_name property to store the source's name. + name = "resource_name"; + } bool valid = false; - tile_set_scenes_collection_source->set(p_name, p_value, &valid); + tile_set_scenes_collection_source->set(name, p_value, &valid); if (valid) { - emit_signal(SNAME("changed"), String(p_name).utf8().get_data()); + emit_signal(SNAME("changed"), String(name).utf8().get_data()); } return valid; } @@ -68,11 +73,20 @@ bool TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_g if (!tile_set_scenes_collection_source) { return false; } + String name = p_name; + if (name == "name") { + // Use the resource_name property to store the source's name. + name = "resource_name"; + } bool valid = false; - r_ret = tile_set_scenes_collection_source->get(p_name, &valid); + r_ret = tile_set_scenes_collection_source->get(name, &valid); return valid; } +void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_get_property_list(List<PropertyInfo> *p_list) const { + p_list->push_back(PropertyInfo(Variant::STRING, "name", PROPERTY_HINT_NONE, "")); +} + void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::_bind_methods() { // -- Shape and layout -- ClassDB::bind_method(D_METHOD("set_id", "id"), &TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::set_id); @@ -89,6 +103,10 @@ void TileSetScenesCollectionSourceEditor::TileSetScenesCollectionProxyObject::ed ERR_FAIL_COND(p_source_id < 0); ERR_FAIL_COND(p_tile_set->get_source(p_source_id) != p_tile_set_scenes_collection_source); + if (tile_set == p_tile_set && tile_set_scenes_collection_source == p_tile_set_scenes_collection_source && source_id == p_source_id) { + return; + } + // Disconnect to changes. if (tile_set_scenes_collection_source) { tile_set_scenes_collection_source->disconnect(CoreStringNames::get_singleton()->property_list_changed, callable_mp((Object *)this, &Object::notify_property_list_changed)); @@ -174,6 +192,10 @@ void TileSetScenesCollectionSourceEditor::SceneTileProxyObject::edit(TileSetScen ERR_FAIL_COND(!p_tile_set_scenes_collection_source); ERR_FAIL_COND(!p_tile_set_scenes_collection_source->has_scene_tile_id(p_scene_id)); + if (tile_set_scenes_collection_source == p_tile_set_scenes_collection_source && scene_id == p_scene_id) { + return; + } + tile_set_scenes_collection_source = p_tile_set_scenes_collection_source; scene_id = p_scene_id; diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h index 195aa79bc4..3be7bee714 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.h @@ -51,6 +51,7 @@ private: protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; static void _bind_methods(); public: diff --git a/editor/plugins/tiles/tiles_editor_plugin.cpp b/editor/plugins/tiles/tiles_editor_plugin.cpp index d0d01a8d49..f1918073fb 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.cpp +++ b/editor/plugins/tiles/tiles_editor_plugin.cpp @@ -30,99 +30,183 @@ #include "tiles_editor_plugin.h" +#include "core/os/mutex.h" + #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor/plugins/canvas_item_editor_plugin.h" #include "scene/2d/tile_map.h" -#include "scene/resources/tile_set.h" - #include "scene/gui/box_container.h" #include "scene/gui/button.h" #include "scene/gui/control.h" #include "scene/gui/separator.h" +#include "scene/resources/tile_set.h" #include "tile_set_editor.h" -TilesEditor *TilesEditor::singleton = nullptr; +TilesEditorPlugin *TilesEditorPlugin::singleton = nullptr; + +void TilesEditorPlugin::_pattern_preview_done(const Variant &p_udata) { + pattern_preview_done.set(); +} + +void TilesEditorPlugin::_thread_func(void *ud) { + TilesEditorPlugin *te = (TilesEditorPlugin *)ud; + te->_thread(); +} + +void TilesEditorPlugin::_thread() { + pattern_thread_exited.clear(); + while (!pattern_thread_exit.is_set()) { + pattern_preview_sem.wait(); + + pattern_preview_mutex.lock(); + if (pattern_preview_queue.size()) { + QueueItem item = pattern_preview_queue.front()->get(); + pattern_preview_queue.pop_front(); + pattern_preview_mutex.unlock(); + + int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); + thumbnail_size *= EDSCALE; + Vector2 thumbnail_size2 = Vector2(thumbnail_size, thumbnail_size); + + if (item.pattern.is_valid() && !item.pattern->is_empty()) { + // Generate the pattern preview + SubViewport *viewport = memnew(SubViewport); + viewport->set_size(thumbnail_size2); + viewport->set_disable_input(true); + viewport->set_transparent_background(true); + viewport->set_update_mode(SubViewport::UPDATE_ONCE); + + TileMap *tile_map = memnew(TileMap); + tile_map->set_tileset(item.tile_set); + tile_map->set_pattern(0, Vector2(), item.pattern); + viewport->add_child(tile_map); + + TypedArray<Vector2i> used_cells = tile_map->get_used_cells(0); + + Rect2 encompassing_rect = Rect2(); + encompassing_rect.set_position(tile_map->map_to_world(used_cells[0])); + for (int i = 0; i < used_cells.size(); i++) { + Vector2i cell = used_cells[i]; + Vector2 world_pos = tile_map->map_to_world(cell); + encompassing_rect.expand_to(world_pos); + + // Texture. + Ref<TileSetAtlasSource> atlas_source = tile_set->get_source(tile_map->get_cell_source_id(0, cell)); + if (atlas_source.is_valid()) { + Vector2i coords = tile_map->get_cell_atlas_coords(0, cell); + int alternative = tile_map->get_cell_alternative_tile(0, cell); + + Vector2 center = world_pos - atlas_source->get_tile_effective_texture_offset(coords, alternative); + encompassing_rect.expand_to(center - atlas_source->get_tile_texture_region(coords).size / 2); + encompassing_rect.expand_to(center + atlas_source->get_tile_texture_region(coords).size / 2); + } + } + + Vector2 scale = thumbnail_size2 / MAX(encompassing_rect.size.x, encompassing_rect.size.y); + tile_map->set_scale(scale); + tile_map->set_position(-(scale * encompassing_rect.get_center()) + thumbnail_size2 / 2); -void TilesEditor::_notification(int p_what) { + // Add the viewport at the lasst moment to avoid rendering too early. + EditorNode::get_singleton()->add_child(viewport); + + pattern_preview_done.clear(); + RS::get_singleton()->request_frame_drawn_callback(const_cast<TilesEditorPlugin *>(this), "_pattern_preview_done", Variant()); + + while (!pattern_preview_done.is_set()) { + OS::get_singleton()->delay_usec(10); + } + + Ref<Image> image = viewport->get_texture()->get_image(); + Ref<ImageTexture> image_texture; + image_texture.instantiate(); + image_texture->create_from_image(image); + + // Find the index for the given pattern. TODO: optimize. + Variant args[] = { item.pattern, image_texture }; + const Variant *args_ptr[] = { &args[0], &args[1] }; + Variant r; + Callable::CallError error; + item.callback.call(args_ptr, 2, r, error); + + viewport->queue_delete(); + } else { + pattern_preview_mutex.unlock(); + } + } + } + pattern_thread_exited.set(); +} + +void TilesEditorPlugin::_tile_map_changed() { + tile_map_changed_needs_update = true; +} + +void TilesEditorPlugin::_update_editors() { + // If tile_map is not edited, we change the edited only if we are not editing a tile_set. + tileset_editor->edit(tile_set); + TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); + if (tile_map) { + tilemap_editor->edit(tile_map); + } else { + tilemap_editor->edit(nullptr); + } + + // Update the viewport. + CanvasItemEditor::get_singleton()->update_viewport(); +} + +void TilesEditorPlugin::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_THEME_CHANGED: { - tileset_tilemap_switch_button->set_icon(get_theme_icon(SNAME("TileSet"), SNAME("EditorIcons"))); - } break; case NOTIFICATION_INTERNAL_PROCESS: { if (tile_map_changed_needs_update) { TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (tile_map) { tile_set = tile_map->get_tileset(); } - _update_switch_button(); _update_editors(); + tile_map_changed_needs_update = false; } } break; } } -void TilesEditor::_tile_map_changed() { - tile_map_changed_needs_update = true; -} - -void TilesEditor::_update_switch_button() { - // Force the buttons status if needed. - TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); - if (tile_map && !tile_set.is_valid()) { - tileset_tilemap_switch_button->set_pressed(false); - } else if (!tile_map && tile_set.is_valid()) { - tileset_tilemap_switch_button->set_pressed(true); - } -} - -void TilesEditor::_update_editors() { - // Set editors visibility. - tilemap_toolbar->set_visible(!tileset_tilemap_switch_button->is_pressed()); - tilemap_editor->set_visible(!tileset_tilemap_switch_button->is_pressed()); - tileset_editor->set_visible(tileset_tilemap_switch_button->is_pressed()); - - // Enable/disable the switch button. - if (!tileset_tilemap_switch_button->is_pressed()) { - if (!tile_set.is_valid()) { - tileset_tilemap_switch_button->set_disabled(true); - tileset_tilemap_switch_button->set_tooltip(TTR("This TileMap has no assigned TileSet, assign a TileSet to this TileMap to edit it.")); - } else { - tileset_tilemap_switch_button->set_disabled(false); - tileset_tilemap_switch_button->set_tooltip(TTR("Switch between TileSet/TileMap editor.")); - } - } else { +void TilesEditorPlugin::make_visible(bool p_visible) { + if (p_visible) { + // Disable and hide invalid editors. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); - if (!tile_map) { - tileset_tilemap_switch_button->set_disabled(true); - tileset_tilemap_switch_button->set_tooltip(TTR("You are editing a TileSet resource. Select a TileMap node to paint.")); + tileset_editor_button->set_visible(tile_set.is_valid()); + tilemap_editor_button->set_visible(tile_map); + if (tile_map) { + editor_node->make_bottom_panel_item_visible(tilemap_editor); } else { - tileset_tilemap_switch_button->set_disabled(false); - tileset_tilemap_switch_button->set_tooltip(TTR("Switch between TileSet/TileMap editor.")); + editor_node->make_bottom_panel_item_visible(tileset_editor); } - } - // If tile_map is not edited, we change the edited only if we are not editing a tile_set. - TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); - if (tile_map) { - tilemap_editor->edit(tile_map); } else { - tilemap_editor->edit(nullptr); + tileset_editor_button->hide(); + tilemap_editor_button->hide(); + editor_node->hide_bottom_panel(); } - tileset_editor->edit(tile_set); +} - // Update the viewport - CanvasItemEditor::get_singleton()->update_viewport(); +void TilesEditorPlugin::queue_pattern_preview(Ref<TileSet> p_tile_set, Ref<TileMapPattern> p_pattern, Callable p_callback) { + ERR_FAIL_COND(!p_tile_set.is_valid()); + ERR_FAIL_COND(!p_pattern.is_valid()); + { + MutexLock lock(pattern_preview_mutex); + pattern_preview_queue.push_back({ p_tile_set, p_pattern, p_callback }); + } + pattern_preview_sem.post(); } -void TilesEditor::set_sources_lists_current(int p_current) { +void TilesEditorPlugin::set_sources_lists_current(int p_current) { atlas_sources_lists_current = p_current; } -void TilesEditor::synchronize_sources_list(Object *p_current) { +void TilesEditorPlugin::synchronize_sources_list(Object *p_current) { ItemList *item_list = Object::cast_to<ItemList>(p_current); ERR_FAIL_COND(!item_list); @@ -136,12 +220,12 @@ void TilesEditor::synchronize_sources_list(Object *p_current) { } } -void TilesEditor::set_atlas_view_transform(float p_zoom, Vector2 p_scroll) { +void TilesEditorPlugin::set_atlas_view_transform(float p_zoom, Vector2 p_scroll) { atlas_view_zoom = p_zoom; atlas_view_scroll = p_scroll; } -void TilesEditor::synchronize_atlas_view(Object *p_current) { +void TilesEditorPlugin::synchronize_atlas_view(Object *p_current) { TileAtlasView *tile_atlas_view = Object::cast_to<TileAtlasView>(p_current); ERR_FAIL_COND(!tile_atlas_view); @@ -150,11 +234,11 @@ void TilesEditor::synchronize_atlas_view(Object *p_current) { } } -void TilesEditor::edit(Object *p_object) { +void TilesEditorPlugin::edit(Object *p_object) { // Disconnect to changes. TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); if (tile_map) { - tile_map->disconnect("changed", callable_mp(this, &TilesEditor::_tile_map_changed)); + tile_map->disconnect("changed", callable_mp(this, &TilesEditorPlugin::_tile_map_changed)); } // Update edited objects. @@ -164,112 +248,79 @@ void TilesEditor::edit(Object *p_object) { tile_map_id = p_object->get_instance_id(); tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id)); tile_set = tile_map->get_tileset(); + editor_node->make_bottom_panel_item_visible(tilemap_editor); } else if (p_object->is_class("TileSet")) { tile_set = Ref<TileSet>(p_object); if (tile_map) { - if (tile_map->get_tileset() != tile_set) { + if (tile_map->get_tileset() != tile_set || !tile_map->is_inside_tree()) { tile_map = nullptr; + tile_map_id = ObjectID(); } } - } - - // Update pressed status button. - if (p_object->is_class("TileMap")) { - tileset_tilemap_switch_button->set_pressed(false); - } else if (p_object->is_class("TileSet")) { - tileset_tilemap_switch_button->set_pressed(true); + editor_node->make_bottom_panel_item_visible(tileset_editor); } } // Update the editors. - _update_switch_button(); _update_editors(); // Add change listener. if (tile_map) { - tile_map->connect("changed", callable_mp(this, &TilesEditor::_tile_map_changed)); + tile_map->connect("changed", callable_mp(this, &TilesEditorPlugin::_tile_map_changed)); } } -void TilesEditor::_bind_methods() { +bool TilesEditorPlugin::handles(Object *p_object) const { + return p_object->is_class("TileMap") || p_object->is_class("TileSet"); +} + +void TilesEditorPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("_pattern_preview_done", "pattern"), &TilesEditorPlugin::_pattern_preview_done); } -TilesEditor::TilesEditor(EditorNode *p_editor) { +TilesEditorPlugin::TilesEditorPlugin(EditorNode *p_node) { set_process_internal(true); // Update the singleton. singleton = this; - // Toolbar. - HBoxContainer *toolbar = memnew(HBoxContainer); - toolbar->set_h_size_flags(SIZE_EXPAND_FILL); - add_child(toolbar); + editor_node = p_node; - // Switch button. - tileset_tilemap_switch_button = memnew(Button); - tileset_tilemap_switch_button->set_flat(true); - tileset_tilemap_switch_button->set_toggle_mode(true); - tileset_tilemap_switch_button->connect("toggled", callable_mp(this, &TilesEditor::_update_editors).unbind(1)); - toolbar->add_child(tileset_tilemap_switch_button); + // Tileset editor. + tileset_editor = memnew(TileSetEditor); + tileset_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); + tileset_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); + tileset_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); + tileset_editor->hide(); // Tilemap editor. tilemap_editor = memnew(TileMapEditor); - tilemap_editor->set_h_size_flags(SIZE_EXPAND_FILL); - tilemap_editor->set_v_size_flags(SIZE_EXPAND_FILL); + tilemap_editor->set_h_size_flags(Control::SIZE_EXPAND_FILL); + tilemap_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL); + tilemap_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); tilemap_editor->hide(); - add_child(tilemap_editor); - tilemap_toolbar = tilemap_editor->get_toolbar(); - toolbar->add_child(tilemap_toolbar); + // Pattern preview generation thread. + pattern_preview_thread.start(_thread_func, this); - // Tileset editor. - tileset_editor = memnew(TileSetEditor); - tileset_editor->set_h_size_flags(SIZE_EXPAND_FILL); - tileset_editor->set_v_size_flags(SIZE_EXPAND_FILL); - tileset_editor->hide(); - add_child(tileset_editor); + // Bottom buttons. + tileset_editor_button = p_node->add_bottom_panel_item(TTR("TileSet"), tileset_editor); + tileset_editor_button->hide(); + tilemap_editor_button = p_node->add_bottom_panel_item(TTR("TileMap"), tilemap_editor); + tilemap_editor_button->hide(); // Initialization. - _update_switch_button(); _update_editors(); } -TilesEditor::~TilesEditor() { -} - -/////////////////////////////////////////////////////////////// - -void TilesEditorPlugin::_notification(int p_what) { -} - -void TilesEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { - tiles_editor_button->show(); - editor_node->make_bottom_panel_item_visible(tiles_editor); - } else { - editor_node->hide_bottom_panel(); - tiles_editor_button->hide(); - } -} - -void TilesEditorPlugin::edit(Object *p_object) { - tiles_editor->edit(p_object); -} - -bool TilesEditorPlugin::handles(Object *p_object) const { - return p_object->is_class("TileMap") || p_object->is_class("TileSet"); -} - -TilesEditorPlugin::TilesEditorPlugin(EditorNode *p_node) { - editor_node = p_node; - - tiles_editor = memnew(TilesEditor(p_node)); - tiles_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE); - tiles_editor->hide(); - - tiles_editor_button = p_node->add_bottom_panel_item(TTR("Tiles"), tiles_editor); - tiles_editor_button->hide(); -} - TilesEditorPlugin::~TilesEditorPlugin() { + if (pattern_preview_thread.is_started()) { + pattern_thread_exit.set(); + pattern_preview_sem.post(); + while (!pattern_thread_exited.is_set()) { + OS::get_singleton()->delay_usec(10000); + RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server + } + pattern_preview_thread.wait_to_finish(); + } } diff --git a/editor/plugins/tiles/tiles_editor_plugin.h b/editor/plugins/tiles/tiles_editor_plugin.h index f976d68938..dd52bdc31a 100644 --- a/editor/plugins/tiles/tiles_editor_plugin.h +++ b/editor/plugins/tiles/tiles_editor_plugin.h @@ -38,24 +38,24 @@ #include "tile_map_editor.h" #include "tile_set_editor.h" -class TilesEditor : public VBoxContainer { - GDCLASS(TilesEditor, VBoxContainer); +class TilesEditorPlugin : public EditorPlugin { + GDCLASS(TilesEditorPlugin, EditorPlugin); - static TilesEditor *singleton; + static TilesEditorPlugin *singleton; private: + EditorNode *editor_node; + bool tile_map_changed_needs_update = false; ObjectID tile_map_id; Ref<TileSet> tile_set; - Button *tileset_tilemap_switch_button; - - Control *tilemap_toolbar; + Button *tilemap_editor_button; TileMapEditor *tilemap_editor; + Button *tileset_editor_button; TileSetEditor *tileset_editor; - void _update_switch_button(); void _update_editors(); // For synchronization. @@ -65,15 +65,35 @@ private: void _tile_map_changed(); + // Patterns preview generation. + struct QueueItem { + Ref<TileSet> tile_set; + Ref<TileMapPattern> pattern; + Callable callback; + }; + List<QueueItem> pattern_preview_queue; + Mutex pattern_preview_mutex; + Semaphore pattern_preview_sem; + Thread pattern_preview_thread; + SafeFlag pattern_thread_exit; + SafeFlag pattern_thread_exited; + mutable SafeFlag pattern_preview_done; + void _pattern_preview_done(const Variant &p_udata); + static void _thread_func(void *ud); + void _thread(); + protected: void _notification(int p_what); static void _bind_methods(); public: - _FORCE_INLINE_ static TilesEditor *get_singleton() { return singleton; } + _FORCE_INLINE_ static TilesEditorPlugin *get_singleton() { return singleton; } - bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) { return tilemap_editor->forward_canvas_gui_input(p_event); } - void forward_canvas_draw_over_viewport(Control *p_overlay) { tilemap_editor->forward_canvas_draw_over_viewport(p_overlay); } + virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return tilemap_editor->forward_canvas_gui_input(p_event); } + virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { tilemap_editor->forward_canvas_draw_over_viewport(p_overlay); } + + // Pattern preview API. + void queue_pattern_preview(Ref<TileSet> p_tile_set, Ref<TileMapPattern> p_pattern, Callable p_callback); // To synchronize the atlas sources lists. void set_sources_lists_current(int p_current); @@ -82,27 +102,6 @@ public: void set_atlas_view_transform(float p_zoom, Vector2 p_scroll); void synchronize_atlas_view(Object *p_current); - void edit(Object *p_object); - - TilesEditor(EditorNode *p_editor); - ~TilesEditor(); -}; - -class TilesEditorPlugin : public EditorPlugin { - GDCLASS(TilesEditorPlugin, EditorPlugin); - -private: - EditorNode *editor_node; - TilesEditor *tiles_editor; - Button *tiles_editor_button; - -protected: - void _notification(int p_what); - -public: - virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return tiles_editor->forward_canvas_gui_input(p_event); } - virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { tiles_editor->forward_canvas_draw_over_viewport(p_overlay); } - virtual void edit(Object *p_object) override; virtual bool handles(Object *p_object) const override; virtual void make_visible(bool p_visible) override; diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 0a067dfc17..09ca1f7608 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -31,6 +31,7 @@ #include "visual_shader_editor_plugin.h" #include "core/config/project_settings.h" +#include "core/core_string_names.h" #include "core/input/input.h" #include "core/io/resource_loader.h" #include "core/math/math_defs.h" @@ -212,19 +213,27 @@ void VisualShaderGraphPlugin::set_uniform_name(VisualShader::Type p_type, int p_ void VisualShaderGraphPlugin::update_curve(int p_node_id) { if (links.has(p_node_id) && links[p_node_id].curve_editors[0]) { - if (((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture().is_valid()) { - links[p_node_id].curve_editors[0]->set_curve(((VisualShaderNodeCurveTexture *)links[p_node_id].visual_node)->get_texture()->get_curve()); + Ref<VisualShaderNodeCurveTexture> tex = Object::cast_to<VisualShaderNodeCurveTexture>(links[p_node_id].visual_node); + ERR_FAIL_COND(!tex.is_valid()); + + if (tex->get_texture().is_valid()) { + links[p_node_id].curve_editors[0]->set_curve(tex->get_texture()->get_curve()); } + tex->emit_signal(CoreStringNames::get_singleton()->changed); } } void VisualShaderGraphPlugin::update_curve_xyz(int p_node_id) { if (links.has(p_node_id) && links[p_node_id].curve_editors[0] && links[p_node_id].curve_editors[1] && links[p_node_id].curve_editors[2]) { - if (((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture().is_valid()) { - links[p_node_id].curve_editors[0]->set_curve(((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture()->get_curve_x()); - links[p_node_id].curve_editors[1]->set_curve(((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture()->get_curve_y()); - links[p_node_id].curve_editors[2]->set_curve(((VisualShaderNodeCurveXYZTexture *)links[p_node_id].visual_node)->get_texture()->get_curve_z()); + Ref<VisualShaderNodeCurveXYZTexture> tex = Object::cast_to<VisualShaderNodeCurveXYZTexture>(links[p_node_id].visual_node); + ERR_FAIL_COND(!tex.is_valid()); + + if (tex->get_texture().is_valid()) { + links[p_node_id].curve_editors[0]->set_curve(tex->get_texture()->get_curve_x()); + links[p_node_id].curve_editors[1]->set_curve(tex->get_texture()->get_curve_y()); + links[p_node_id].curve_editors[2]->set_curve(tex->get_texture()->get_curve_z()); } + tex->emit_signal(CoreStringNames::get_singleton()->changed); } } diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 9f24c5af72..5788959a77 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -335,8 +335,6 @@ class VisualShaderEditor : public VBoxContainer { void _delete_node_request(int p_type, int p_node); void _delete_nodes_request(); - void _removed_from_graph(); - void _node_changed(int p_id); void _edit_port_default_input(Object *p_button, int p_node, int p_port); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index eb6c300d5b..f90db02c46 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -100,8 +100,6 @@ class ProjectSettingsEditor : public AcceptDialog { void _action_reordered(const String &p_action_name, const String &p_relative_to, bool p_before); void _update_action_map_editor(); - ProjectSettingsEditor(); - protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index 9063b5c6f8..a5e1b0eab8 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -459,7 +459,7 @@ String RenameDialog::_substitute(const String &subject, const Node *node, int co return result; } -void RenameDialog::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type) { +void RenameDialog::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type) { RenameDialog *self = (RenameDialog *)p_self; String source_file(p_file); diff --git a/editor/rename_dialog.h b/editor/rename_dialog.h index 7990862b37..4db3ef6740 100644 --- a/editor/rename_dialog.h +++ b/editor/rename_dialog.h @@ -63,7 +63,7 @@ class RenameDialog : public ConfirmationDialog { String _postprocess(const String &subject); void _update_preview(String new_text = ""); void _update_preview_int(int new_value = 0); - static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type); + static void _error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type); SceneTreeEditor *scene_tree_editor; UndoRedo *undo_redo; diff --git a/editor/reparent_dialog.h b/editor/reparent_dialog.h index 5c3a65a522..3fcdda7bed 100644 --- a/editor/reparent_dialog.h +++ b/editor/reparent_dialog.h @@ -46,7 +46,6 @@ class ReparentDialog : public ConfirmationDialog { SceneTreeEditor *tree; CheckBox *keep_transform; - void update_tree(); void _reparent(); void _cancel(); @@ -56,7 +55,6 @@ protected: public: void set_current(const Set<Node *> &p_selection); - String get_selected_type(); ReparentDialog(); ~ReparentDialog(); diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h index 255e026887..66000602fa 100644 --- a/editor/scene_tree_dock.h +++ b/editor/scene_tree_dock.h @@ -246,8 +246,6 @@ class SceneTreeDock : public VBoxContainer { void _perform_instantiate_scenes(const Vector<String> &p_files, Node *parent, int p_pos); void _replace_with_branch_scene(const String &p_file, Node *base); - void _file_selected(String p_file); - void _remote_tree_selected(); void _local_tree_selected(); diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index 4acd5d8486..b4c40ab17a 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -114,8 +114,6 @@ class SceneTreeEditor : public Control { void _node_visibility_changed(Node *p_node); void _update_visibility_color(Node *p_node, TreeItem *p_item); - void _node_replace_owner(Node *p_base, Node *p_node, Node *p_root); - void _selection_changed(); Node *get_scene_node(); @@ -173,7 +171,6 @@ class SceneTreeDialog : public ConfirmationDialog { //Button *cancel; LineEdit *filter; - void update_tree(); void _select(); void _cancel(); void _filter_changed(const String &p_filter); diff --git a/editor/translations/Makefile b/editor/translations/Makefile index 1843114f06..82b3d49c59 100644 --- a/editor/translations/Makefile +++ b/editor/translations/Makefile @@ -18,3 +18,24 @@ merge: check: @for po in $(POFILES); do msgfmt -c $$po -o /dev/null; done + +# Generate completion ratio from statistics string such as: +# 2775 translated messages, 272 fuzzy translations, 151 untranslated messages. +# First number can be 0, second and third numbers are only present if non-zero. +include-list: + @list=""; \ + threshold=0.30; \ + for po in $(POFILES); do \ + res=`msgfmt --statistics $$po -o /dev/null 2>&1 | sed 's/[^0-9,]*//g'`; \ + complete=`cut -d',' -f1 <<< $$res`; \ + fuzzy_or_untranslated=`cut -d',' -f2 <<< $$res`; \ + untranslated_maybe=`cut -d',' -f3 <<< $$res`; \ + if [ -z "$$fuzzy_or_untranslated" ]; then fuzzy_or_untranslated=0; fi; \ + if [ -z "$$untranslated_maybe" ]; then untranslated_maybe=0; fi; \ + incomplete=`expr $$fuzzy_or_untranslated + $$untranslated_maybe`; \ + if `awk "BEGIN {exit !($$complete / ($$complete + $$incomplete) > $$threshold)}"`; then \ + lang=`basename $$po .po`; \ + list+="$$lang,"; \ + fi; \ + done; \ + echo $$list; diff --git a/main/main.cpp b/main/main.cpp index 3cc7923cc2..d4a6216e35 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -376,7 +376,9 @@ void Main::print_help(const char *p_binary) { OS::get_singleton()->print(" --doctool [<path>] Dump the engine API reference to the given <path> (defaults to current dir) in XML format, merging if existing files are found.\n"); OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n"); OS::get_singleton()->print(" --build-solutions Build the scripting solutions (e.g. for C# projects). Implies --editor and requires a valid project to edit.\n"); + OS::get_singleton()->print(" --dump-extension-api Generate JSON dump of the Godot API for GDExtension bindings named 'extension_api.json' in the current folder.\n"); #ifdef DEBUG_METHODS_ENABLED + // TODO: Should be removed together with nativescript eventually. OS::get_singleton()->print(" --gdnative-generate-json-api <path> Generate JSON dump of the Godot API for GDNative bindings and save it on the file specified in <path>.\n"); OS::get_singleton()->print(" --gdnative-generate-json-builtin-api <path> Generate JSON dump of the Godot API of the builtin Variant types and utility functions for GDNative bindings and save it on the file specified in <path>.\n"); #endif @@ -901,20 +903,24 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph auto_build_solutions = true; editor = true; cmdline_tool = true; - +#ifdef DEBUG_METHODS_ENABLED } else if (I->get() == "--gdnative-generate-json-api" || I->get() == "--gdnative-generate-json-builtin-api") { // Register as an editor instance to use low-end fallback if relevant. editor = true; cmdline_tool = true; - - // We still pass it to the main arguments since the argument handling itself is not done in this function + // We still pass it to the main arguments since the argument handling itself is not done in this function, + // it's done in nativescript init code. main_args.push_back(I->get()); +#endif } else if (I->get() == "--dump-extension-api") { // Register as an editor instance to use low-end fallback if relevant. editor = true; cmdline_tool = true; dump_extension_api = true; - print_line("dump extension?"); + print_line("Dumping Extension API"); + // Hack. Not needed but otherwise we end up detecting that this should + // run the project instead of a cmdline tool. + // Needs full refactoring to fix properly. main_args.push_back(I->get()); } else if (I->get() == "--export" || I->get() == "--export-debug" || I->get() == "--export-pack") { // Export project @@ -1341,8 +1347,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph display_driver_idx = 0; } - if (audio_driver == "") { // specified in project.godot - audio_driver = GLOBAL_DEF_RST_NOVAL("audio/driver/driver", AudioDriverManager::get_driver(0)->get_name()); + GLOBAL_DEF_RST_NOVAL("audio/driver/driver", AudioDriverManager::get_driver(0)->get_name()); + if (audio_driver == "") { // Specified in project.godot. + audio_driver = GLOBAL_GET("audio/driver/driver"); } for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) { @@ -2065,6 +2072,8 @@ bool Main::start() { if (check_only) { if (!script_res->is_valid()) { OS::get_singleton()->set_exit_code(EXIT_FAILURE); + } else { + OS::get_singleton()->set_exit_code(EXIT_SUCCESS); } return false; } @@ -2137,7 +2146,7 @@ bool Main::start() { } #endif - bool embed_subwindows = GLOBAL_DEF("display/window/subwindows/embed_subwindows", false); + bool embed_subwindows = GLOBAL_DEF("display/window/subwindows/embed_subwindows", true); if (OS::get_singleton()->is_single_window() || (!project_manager && !editor && embed_subwindows)) { sml->get_root()->set_embed_subwindows_hint(true); @@ -2522,6 +2531,9 @@ bool Main::iteration() { bool exit = false; + // process all our active interfaces + XRServer::get_singleton()->_process(); + for (int iters = 0; iters < advance.physics_steps; ++iters) { if (Input::get_singleton()->is_using_input_buffering() && agile_input_event_flushing) { Input::get_singleton()->flush_buffered_events(); diff --git a/misc/dist/html/editor.html b/misc/dist/html/editor.html index 2cae215951..69e267f665 100644 --- a/misc/dist/html/editor.html +++ b/misc/dist/html/editor.html @@ -14,7 +14,7 @@ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="msapplication-starturl" content="/latest" /> <meta property="og:site_name" content="Godot Engine Web Editor" /> - <meta property="og:url" name="twitter:url" content="https://editor.godotengine.org/releases/latest/" /> + <meta property="og:url" name="twitter:url" content="https://editor.godotengine.org/releases/latest/" /> <meta property="og:title" name="twitter:title" content="Free and open source 2D and 3D game engine" /> <meta property="og:description" name="twitter:description" content="Use the Godot Engine editor directly in your web browser, without having to install anything." /> <meta property="og:image" name="twitter:image" content="https://godotengine.org/themes/godotengine/assets/og_image.png" /> @@ -269,11 +269,6 @@ <div id="tabs"> <div id="tab-loader"> <div style="color: #e0e0e0;" id="persistence"> - <label for="videoMode" style="display: none;">Select video driver:</label><br /> - <select id="videoMode" style="display: none;"> - <option value="GLES2" selected="selected">WebGL</option> - <option value="GLES3">WebGL 2</option> - </select> <br /> <img src="logo.svg" alt="Godot Engine logo" width="1024" height="414" style="width: auto; height: auto; max-width: 85%; max-height: 250px" /> <br /> @@ -283,6 +278,14 @@ <br /> <br /> <br /> + <label for="videoMode" style="margin-right: 1rem">Video driver:</label> + <select id="videoMode"> + <option value="" selected="selected">Auto</option> + <option value="GLES2">WebGL</option> + <option value="GLES3">WebGL 2</option> + </select> + <br /> + <br /> <label for="zip-file" style="margin-right: 1rem">Preload project ZIP:</label> <input id="zip-file" type="file" name="files" style="margin-bottom: 1rem"/> <br /> <a href="demo.zip">(Try this for example)</a> @@ -348,7 +351,7 @@ var game = null; var setStatusMode; var setStatusNotice; - var video_driver = "GLES2"; + var video_driver = ""; function clearPersistence() { function deleteDB(path) { @@ -479,6 +482,15 @@ animationCallbacks.push(adjustCanvasDimensions); adjustCanvasDimensions(); + function replaceCanvas(from) { + const out = document.createElement("canvas"); + out.id = from.id; + out.tabIndex = from.tabIndex; + from.parentNode.replaceChild(out, from); + lastScale = 0; + return out; + } + setStatusMode = function setStatusMode(mode) { if (statusMode === mode || !initializing) return; @@ -534,6 +546,7 @@ 'canvas': gameCanvas, 'canvasResizePolicy': 1, 'onExit': function () { + gameCanvas = replaceCanvas(gameCanvas); setGameTabEnabled(false); showTab('editor'); game = null; @@ -548,7 +561,7 @@ const is_editor = args.filter(function(v) { return v == '--editor' || v == '-e' }).length != 0; const is_project_manager = args.filter(function(v) { return v == '--project-manager' }).length != 0; const is_game = !is_editor && !is_project_manager; - if (is_project_manager) { + if (video_driver) { args.push('--video-driver', video_driver); } if (is_game) { @@ -561,7 +574,7 @@ showTab('game'); game.init().then(function() { requestAnimationFrame(function() { - game.start({'args': args}).then(function() { + game.start({'args': args, 'canvas': gameCanvas}).then(function() { gameCanvas.focus(); }); }); @@ -576,7 +589,7 @@ showTab('loader'); setLoaderEnabled(true); }; - editor.start({'args': args, 'persistentDrops': is_project_manager}); + editor.start({'args': args, 'persistentDrops': is_project_manager, 'canvas': editorCanvas}); }); }, 0); OnEditorExit = null; @@ -603,6 +616,7 @@ 'canvas': editorCanvas, 'canvasResizePolicy': 0, 'onExit': function() { + editorCanvas = replaceCanvas(editorCanvas); if (OnEditorExit) { OnEditorExit(); } @@ -634,10 +648,14 @@ } catch(e) { // File exists } - //selectVideoMode(); + selectVideoMode(); showTab('editor'); setLoaderEnabled(false); - editor.start({'args': ['--project-manager', '--video-driver', video_driver], 'persistentDrops': true}).then(function() { + const args = ['--project-manager']; + if (video_driver) { + args.push('--video-driver', video_driver); + } + editor.start({'args': args, 'persistentDrops': true}).then(function() { setStatusMode('hidden'); initializing = false; }); diff --git a/misc/scripts/compare_extension_api.py b/misc/scripts/compare_extension_api.py new file mode 100755 index 0000000000..f96db4278c --- /dev/null +++ b/misc/scripts/compare_extension_api.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys + +# TODO: +# Add a process that compares the original godot-cpp/godot-headers/extension_api.json with the new extension_api.json (both passed as arguments) and reports any API calls that have been removed. +# If we only have additions or no changes to the file, we pass +# For now we deem this too early because the API isn't stable enough yet. + +sys.exit(0) diff --git a/modules/bullet/area_bullet.h b/modules/bullet/area_bullet.h index 7cf666c119..c8b516c951 100644 --- a/modules/bullet/area_bullet.h +++ b/modules/bullet/area_bullet.h @@ -145,7 +145,6 @@ public: virtual void dispatch_callbacks(); void call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3D::AreaBodyStatus p_status); - void set_on_state_change(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); void scratch(); void clear_overlaps(bool p_notify); diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp index 81b832fb42..3a2370ff31 100644 --- a/modules/bullet/soft_body_bullet.cpp +++ b/modules/bullet/soft_body_bullet.cpp @@ -116,6 +116,7 @@ void SoftBodyBullet::set_soft_mesh(RID p_mesh) { } Array arrays = RenderingServer::get_singleton()->mesh_surface_get_arrays(soft_mesh, 0); + ERR_FAIL_COND(arrays.is_empty()); bool success = set_trimesh_body_shape(arrays[RS::ARRAY_INDEX], arrays[RS::ARRAY_VERTEX]); if (!success) { diff --git a/modules/gdnative/gdnative/gdnative.cpp b/modules/gdnative/gdnative/gdnative.cpp index b84ce2d192..e0de1a0505 100644 --- a/modules/gdnative/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative/gdnative.cpp @@ -129,13 +129,13 @@ void GDAPI godot_free(void *p_ptr) { // Helper print functions. void GDAPI godot_print_error(const char *p_description, const char *p_function, const char *p_file, int p_line) { - _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_ERROR); + _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_ERROR); } void GDAPI godot_print_warning(const char *p_description, const char *p_function, const char *p_file, int p_line) { - _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_WARNING); + _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_WARNING); } void GDAPI godot_print_script_error(const char *p_description, const char *p_function, const char *p_file, int p_line) { - _err_print_error(p_function, p_file, p_line, p_description, ERR_HANDLER_SCRIPT); + _err_print_error(p_function, p_file, p_line, p_description, false, ERR_HANDLER_SCRIPT); } void _gdnative_report_version_mismatch(const godot_object *p_library, const char *p_ext, godot_gdnative_api_version p_want, godot_gdnative_api_version p_have) { diff --git a/modules/gdnative/nativescript/nativescript.cpp b/modules/gdnative/nativescript/nativescript.cpp index fb46bafb3c..368eb67fa6 100644 --- a/modules/gdnative/nativescript/nativescript.cpp +++ b/modules/gdnative/nativescript/nativescript.cpp @@ -1139,15 +1139,12 @@ void NativeScriptLanguage::profiling_start() { MutexLock lock(mutex); profile_data.clear(); - profiling = true; #endif } void NativeScriptLanguage::profiling_stop() { #ifdef DEBUG_ENABLED MutexLock lock(mutex); - - profiling = false; #endif } diff --git a/modules/gdnative/nativescript/nativescript.h b/modules/gdnative/nativescript/nativescript.h index a7647e8c59..2364c6c0f6 100644 --- a/modules/gdnative/nativescript/nativescript.h +++ b/modules/gdnative/nativescript/nativescript.h @@ -269,7 +269,6 @@ private: }; Map<StringName, ProfileData> profile_data; - bool profiling = false; public: // These two maps must only be touched on the main thread @@ -295,8 +294,6 @@ public: return singleton; } - void _hacky_api_anchor(); - _FORCE_INLINE_ void set_language_index(int p_idx) { lang_idx = p_idx; } #ifndef NO_THREADS diff --git a/modules/gdnative/pluginscript/pluginscript_instance.h b/modules/gdnative/pluginscript/pluginscript_instance.h index bdae265db2..81e711bafc 100644 --- a/modules/gdnative/pluginscript/pluginscript_instance.h +++ b/modules/gdnative/pluginscript/pluginscript_instance.h @@ -69,8 +69,6 @@ public: virtual ScriptLanguage *get_language(); - void set_path(const String &p_path); - virtual const Vector<Multiplayer::RPCConfig> get_rpc_methods() const; virtual void refcount_incremented(); diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index e9d3749a8d..42865242d3 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -835,7 +835,7 @@ Error GDScript::reload(bool p_keep_state) { GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), parser.get_errors().front()->get().line, "Parser Error: " + parser.get_errors().front()->get().message); } // TODO: Show all error messages. - _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_errors().front()->get().line, ("Parse Error: " + parser.get_errors().front()->get().message).utf8().get_data(), ERR_HANDLER_SCRIPT); + _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_errors().front()->get().line, ("Parse Error: " + parser.get_errors().front()->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT); ERR_FAIL_V(ERR_PARSE_ERROR); } @@ -849,7 +849,7 @@ Error GDScript::reload(bool p_keep_state) { const List<GDScriptParser::ParserError>::Element *e = parser.get_errors().front(); while (e != nullptr) { - _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), e->get().line, ("Parse Error: " + e->get().message).utf8().get_data(), ERR_HANDLER_SCRIPT); + _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), e->get().line, ("Parse Error: " + e->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT); e = e->next(); } ERR_FAIL_V(ERR_PARSE_ERROR); @@ -869,7 +869,7 @@ Error GDScript::reload(bool p_keep_state) { if (EngineDebugger::is_active()) { GDScriptLanguage::get_singleton()->debug_break_parse(get_path(), compiler.get_error_line(), "Parser Error: " + compiler.get_error()); } - _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), compiler.get_error_line(), ("Compile Error: " + compiler.get_error()).utf8().get_data(), ERR_HANDLER_SCRIPT); + _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), compiler.get_error_line(), ("Compile Error: " + compiler.get_error()).utf8().get_data(), false, ERR_HANDLER_SCRIPT); ERR_FAIL_V(ERR_COMPILATION_FAILED); } else { return err; @@ -879,7 +879,7 @@ Error GDScript::reload(bool p_keep_state) { for (const GDScriptWarning &warning : parser.get_warnings()) { if (EngineDebugger::is_active()) { Vector<ScriptLanguage::StackInfo> si; - EngineDebugger::get_script_debugger()->send_error("", get_path(), warning.start_line, warning.get_name(), warning.get_message(), ERR_HANDLER_WARNING, si); + EngineDebugger::get_script_debugger()->send_error("", get_path(), warning.start_line, warning.get_name(), warning.get_message(), false, ERR_HANDLER_WARNING, si); } } #endif diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 7018c339d7..40f03979c6 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -3315,7 +3315,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a if (!GDScriptLanguage::get_singleton()->debug_break(err_text, false)) { // debugger break did not happen - _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text.utf8().get_data(), ERR_HANDLER_SCRIPT); + _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text.utf8().get_data(), false, ERR_HANDLER_SCRIPT); } #endif diff --git a/modules/gdscript/language_server/gdscript_language_server.h b/modules/gdscript/language_server/gdscript_language_server.h index 85a44a8cc1..f1413f0133 100644 --- a/modules/gdscript/language_server/gdscript_language_server.h +++ b/modules/gdscript/language_server/gdscript_language_server.h @@ -50,10 +50,8 @@ class GDScriptLanguageServer : public EditorPlugin { private: void _notification(int p_what); - void _iteration(); public: - Error parse_script_file(const String &p_path); GDScriptLanguageServer(); void start(); void stop(); diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp index 50c1f68440..d2e71efee7 100644 --- a/modules/gdscript/tests/gdscript_test_runner.cpp +++ b/modules/gdscript/tests/gdscript_test_runner.cpp @@ -334,7 +334,7 @@ void GDScriptTest::print_handler(void *p_this, const String &p_message, bool p_e result->output += p_message + "\n"; } -void GDScriptTest::error_handler(void *p_this, const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_explanation, ErrorHandlerType p_type) { +void GDScriptTest::error_handler(void *p_this, const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_explanation, bool p_editor_notify, ErrorHandlerType p_type) { ErrorHandlerData *data = (ErrorHandlerData *)p_this; GDScriptTest *self = data->self; TestResult *result = data->result; diff --git a/modules/gdscript/tests/gdscript_test_runner.h b/modules/gdscript/tests/gdscript_test_runner.h index 9b2d14a371..98c57dc97c 100644 --- a/modules/gdscript/tests/gdscript_test_runner.h +++ b/modules/gdscript/tests/gdscript_test_runner.h @@ -87,7 +87,7 @@ private: public: static void print_handler(void *p_this, const String &p_message, bool p_error); - static void error_handler(void *p_this, const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_explanation, ErrorHandlerType p_type); + static void error_handler(void *p_this, const char *p_function, const char *p_file, int p_line, const char *p_error, const char *p_explanation, bool p_editor_notify, ErrorHandlerType p_type); TestResult run_test(); bool generate_output(); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 7d4bd998f5..b8da3a713b 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -247,7 +247,7 @@ Error GLTFDocument::_parse_json(const String &p_path, Ref<GLTFState> state) { JSON json; err = json.parse(text); if (err != OK) { - _err_print_error("", p_path.utf8().get_data(), json.get_error_line(), json.get_error_message().utf8().get_data(), ERR_HANDLER_SCRIPT); + _err_print_error("", p_path.utf8().get_data(), json.get_error_line(), json.get_error_message().utf8().get_data(), false, ERR_HANDLER_SCRIPT); return err; } state->json = json.get_data(); @@ -282,7 +282,7 @@ Error GLTFDocument::_parse_glb(const String &p_path, Ref<GLTFState> state) { JSON json; err = json.parse(text); if (err != OK) { - _err_print_error("", p_path.utf8().get_data(), json.get_error_line(), json.get_error_message().utf8().get_data(), ERR_HANDLER_SCRIPT); + _err_print_error("", p_path.utf8().get_data(), json.get_error_line(), json.get_error_message().utf8().get_data(), false, ERR_HANDLER_SCRIPT); return err; } diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index a1d82a4649..f2f0b439a5 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -269,8 +269,6 @@ private: Error _reparent_non_joint_skeleton_subtrees( Ref<GLTFState> state, Ref<GLTFSkeleton> skeleton, const Vector<GLTFNodeIndex> &non_joints); - Error _reparent_to_fake_joint(Ref<GLTFState> state, Ref<GLTFSkeleton> skeleton, - const GLTFNodeIndex node_index); Error _determine_skeleton_roots(Ref<GLTFState> state, const GLTFSkeletonIndex skel_i); Error _create_skeletons(Ref<GLTFState> state); diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index ba4ef3be8d..37e969db4d 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -611,6 +611,61 @@ void LightmapperRD::_raster_geometry(RenderingDevice *rd, Size2i atlas_size, int } } +LightmapperRD::BakeError LightmapperRD::_dilate(RenderingDevice *rd, Ref<RDShaderFile> &compute_shader, RID &compute_base_uniform_set, PushConstant &push_constant, RID &source_light_tex, RID &dest_light_tex, const Size2i &atlas_size, int atlas_slices) { + Vector<RD::Uniform> uniforms; + { + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(dest_light_tex); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + u.ids.push_back(source_light_tex); + uniforms.push_back(u); + } + } + + RID compute_shader_dilate = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("dilate")); + ERR_FAIL_COND_V(compute_shader_dilate.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen + RID compute_shader_dilate_pipeline = rd->compute_pipeline_create(compute_shader_dilate); + + RID dilate_uniform_set = rd->uniform_set_create(uniforms, compute_shader_dilate, 1); + + RD::ComputeListID compute_list = rd->compute_list_begin(); + rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_dilate_pipeline); + rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); + rd->compute_list_bind_uniform_set(compute_list, dilate_uniform_set, 1); + push_constant.region_ofs[0] = 0; + push_constant.region_ofs[1] = 0; + Vector3i group_size((atlas_size.x - 1) / 8 + 1, (atlas_size.y - 1) / 8 + 1, 1); //restore group size + + for (int i = 0; i < atlas_slices; i++) { + push_constant.atlas_slice = i; + rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); + rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z); + //no barrier, let them run all together + } + rd->compute_list_end(); + rd->free(compute_shader_dilate); + +#ifdef DEBUG_TEXTURES + for (int i = 0; i < atlas_slices; i++) { + Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); + Ref<Image> img; + img.instantiate(); + img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); + img->convert(Image::FORMAT_RGBA8); + img->save_png("res://5_dilated_" + itos(i) + ".png"); + } +#endif + return BAKE_OK; +} + LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata) { if (p_step_function) { p_step_function(0.0, TTR("Begin Bake"), p_bake_userdata, true); @@ -943,11 +998,6 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d ERR_FAIL_COND_V(compute_shader_secondary.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen RID compute_shader_secondary_pipeline = rd->compute_pipeline_create(compute_shader_secondary); - // Dilate - RID compute_shader_dilate = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("dilate")); - ERR_FAIL_COND_V(compute_shader_dilate.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen - RID compute_shader_dilate_pipeline = rd->compute_pipeline_create(compute_shader_dilate); - // Light probes RID compute_shader_light_probes = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("light_probes")); ERR_FAIL_COND_V(compute_shader_light_probes.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen @@ -959,7 +1009,6 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d rd->free(compute_shader_unocclude); \ rd->free(compute_shader_primary); \ rd->free(compute_shader_secondary); \ - rd->free(compute_shader_dilate); \ rd->free(compute_shader_light_probes); PushConstant push_constant; @@ -1270,7 +1319,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d push_constant.environment_xform[3] = 0.0f; } - /* LIGHPROBES */ + /* LIGHTPROBES */ RID light_probe_buffer; @@ -1377,6 +1426,14 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d } #endif + { + SWAP(light_accum_tex, light_accum_tex2); + BakeError error = _dilate(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, light_accum_tex, atlas_size, atlas_slices * (p_bake_sh ? 4 : 1)); + if (unlikely(error != BAKE_OK)) { + return error; + } + } + /* DENOISE */ if (p_use_denoiser) { @@ -1409,58 +1466,14 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d } } } - } -#ifdef DEBUG_TEXTURES - - for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { - Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i); - Ref<Image> img; - img.instantiate(); - img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); - img->save_exr("res://4_light_secondary_" + itos(i) + ".exr", false); - } -#endif - - /* DILATE LIGHTMAP */ - { - SWAP(light_accum_tex, light_accum_tex2); - - Vector<RD::Uniform> uniforms; { - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.ids.push_back(light_accum_tex); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.uniform_type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; - u.ids.push_back(light_accum_tex2); - uniforms.push_back(u); + SWAP(light_accum_tex, light_accum_tex2); + BakeError error = _dilate(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, light_accum_tex, atlas_size, atlas_slices * (p_bake_sh ? 4 : 1)); + if (unlikely(error != BAKE_OK)) { + return error; } } - - RID dilate_uniform_set = rd->uniform_set_create(uniforms, compute_shader_dilate, 1); - - RD::ComputeListID compute_list = rd->compute_list_begin(); - rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_dilate_pipeline); - rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0); - rd->compute_list_bind_uniform_set(compute_list, dilate_uniform_set, 1); - push_constant.region_ofs[0] = 0; - push_constant.region_ofs[1] = 0; - group_size = Vector3i((atlas_size.x - 1) / 8 + 1, (atlas_size.y - 1) / 8 + 1, 1); //restore group size - - for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) { - push_constant.atlas_slice = i; - rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant)); - rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z); - //no barrier, let them run all together - } - rd->compute_list_end(); } #ifdef DEBUG_TEXTURES @@ -1470,8 +1483,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d Ref<Image> img; img.instantiate(); img->create(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s); - img->convert(Image::FORMAT_RGBA8); - img->save_png("res://5_dilated_" + itos(i) + ".png"); + img->save_exr("res://4_light_secondary_" + itos(i) + ".exr", false); } #endif diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h index a6a3740051..e1657b2069 100644 --- a/modules/lightmapper_rd/lightmapper_rd.h +++ b/modules/lightmapper_rd/lightmapper_rd.h @@ -36,6 +36,7 @@ #include "scene/resources/mesh.h" #include "servers/rendering/rendering_device.h" +class RDShaderFile; class LightmapperRD : public Lightmapper { GDCLASS(LightmapperRD, Lightmapper) @@ -231,6 +232,8 @@ class LightmapperRD : public Lightmapper { void _create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, Vector<Probe> &probe_positions, GenerateProbes p_generate_probes, Vector<int> &slice_triangle_count, Vector<int> &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &lights_buffer, RID &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata); void _raster_geometry(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, int grid_size, AABB bounds, float p_bias, Vector<int> slice_triangle_count, RID position_tex, RID unocclude_tex, RID normal_tex, RID raster_depth_buffer, RID rasterize_shader, RID raster_base_uniform); + BakeError _dilate(RenderingDevice *rd, Ref<RDShaderFile> &compute_shader, RID &compute_base_uniform_set, PushConstant &push_constant, RID &source_light_tex, RID &dest_light_tex, const Size2i &atlas_size, int atlas_slices); + public: virtual void add_mesh(const MeshData &p_mesh) override; virtual void add_directional_light(bool p_static, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_angular_distance) override; diff --git a/modules/mbedtls/packet_peer_mbed_dtls.h b/modules/mbedtls/packet_peer_mbed_dtls.h index 6554c74a21..92e6ab88c4 100644 --- a/modules/mbedtls/packet_peer_mbed_dtls.h +++ b/modules/mbedtls/packet_peer_mbed_dtls.h @@ -59,8 +59,6 @@ protected: Ref<SSLContextMbedTLS> ssl_ctx; mbedtls_timing_delay_context timer; - static void _bind_methods(); - Error _do_handshake(); int _set_cookie(); diff --git a/modules/mbedtls/ssl_context_mbedtls.h b/modules/mbedtls/ssl_context_mbedtls.h index 1b55a54a10..5692dec1b6 100644 --- a/modules/mbedtls/ssl_context_mbedtls.h +++ b/modules/mbedtls/ssl_context_mbedtls.h @@ -67,8 +67,6 @@ class SSLContextMbedTLS : public RefCounted { protected: bool inited = false; - static PackedByteArray _read_file(String p_path); - public: static void print_mbedtls_error(int p_ret); diff --git a/modules/mbedtls/stream_peer_mbedtls.h b/modules/mbedtls/stream_peer_mbedtls.h index b89d7fb238..407479e3cc 100644 --- a/modules/mbedtls/stream_peer_mbedtls.h +++ b/modules/mbedtls/stream_peer_mbedtls.h @@ -50,8 +50,6 @@ private: protected: Ref<SSLContextMbedTLS> ssl_ctx; - static void _bind_methods(); - Error _do_handshake(); public: diff --git a/modules/mobile_vr/doc_classes/MobileVRInterface.xml b/modules/mobile_vr/doc_classes/MobileVRInterface.xml index 04ba82ef51..18a77c8b8d 100644 --- a/modules/mobile_vr/doc_classes/MobileVRInterface.xml +++ b/modules/mobile_vr/doc_classes/MobileVRInterface.xml @@ -37,5 +37,6 @@ <member name="oversample" type="float" setter="set_oversample" getter="get_oversample" default="1.5"> The oversample setting. Because of the lens distortion we have to render our buffers at a higher resolution then the screen can natively handle. A value between 1.5 and 2.0 often provides good results but at the cost of performance. </member> + <member name="xr_play_area_mode" type="int" setter="set_play_area_mode" getter="get_play_area_mode" override="true" enum="XRInterface.PlayAreaMode" default="1" /> </members> </class> diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp index fc1a118e4f..ba7353ace2 100644 --- a/modules/mobile_vr/mobile_vr_interface.cpp +++ b/modules/mobile_vr/mobile_vr_interface.cpp @@ -126,6 +126,8 @@ void MobileVRInterface::set_position_from_sensors() { // 9dof is a misleading marketing term coming from 3 accelerometer axis + 3 gyro axis + 3 magnetometer axis = 9 axis // but in reality this only offers 3 dof (yaw, pitch, roll) orientation + Basis orientation; + uint64_t ticks = OS::get_singleton()->get_ticks_usec(); uint64_t ticks_elapsed = ticks - last_ticks; float delta_time = (double)ticks_elapsed / 1000000.0; @@ -207,8 +209,8 @@ void MobileVRInterface::set_position_from_sensors() { }; }; - // JIC - orientation.orthonormalize(); + // and copy to our head transform + head_transform.basis = orientation.orthonormalized(); last_ticks = ticks; }; @@ -318,7 +320,7 @@ bool MobileVRInterface::initialize() { ERR_FAIL_NULL_V(xr_server, false); if (!initialized) { - // reset our sensor data and orientation + // reset our sensor data mag_count = 0; has_gyro = false; sensor_first = true; @@ -326,9 +328,15 @@ bool MobileVRInterface::initialize() { mag_next_max = Vector3(-10000, -10000, -10000); mag_current_min = Vector3(0, 0, 0); mag_current_max = Vector3(0, 0, 0); + head_transform.basis = Basis(); + head_transform.origin = Vector3(0.0, eye_height, 0.0); - // reset our orientation - orientation = Basis(); + // we must create a tracker for our head + head.instantiate(); + head->set_tracker_type(XRServer::TRACKER_HEAD); + head->set_tracker_name("head"); + head->set_tracker_desc("Players head"); + xr_server->add_tracker(head); // make this our primary interface xr_server->set_primary_interface(this); @@ -343,16 +351,38 @@ bool MobileVRInterface::initialize() { void MobileVRInterface::uninitialize() { if (initialized) { + // do any cleanup here... XRServer *xr_server = XRServer::get_singleton(); - if (xr_server != nullptr && xr_server->get_primary_interface() == this) { - // no longer our primary interface - xr_server->set_primary_interface(nullptr); + if (xr_server != nullptr) { + if (head.is_valid()) { + xr_server->remove_tracker(head); + + head.unref(); + } + + if (xr_server->get_primary_interface() == this) { + // no longer our primary interface + xr_server->set_primary_interface(nullptr); + } } initialized = false; }; }; +bool MobileVRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) { + // This interface has no positional tracking so fix this to 3DOF + return p_mode == XR_PLAY_AREA_3DOF; +} + +XRInterface::PlayAreaMode MobileVRInterface::get_play_area_mode() const { + return XR_PLAY_AREA_3DOF; +} + +bool MobileVRInterface::set_play_area_mode(XRInterface::PlayAreaMode p_mode) { + return p_mode == XR_PLAY_AREA_3DOF; +} + Size2 MobileVRInterface::get_render_target_size() { _THREAD_SAFE_METHOD_ @@ -377,11 +407,10 @@ Transform3D MobileVRInterface::get_camera_transform() { float world_scale = xr_server->get_world_scale(); // just scale our origin point of our transform - Transform3D hmd_transform; - hmd_transform.basis = orientation; - hmd_transform.origin = Vector3(0.0, eye_height * world_scale, 0.0); + Transform3D _head_transform = head_transform; + _head_transform.origin *= world_scale; - transform_for_eye = (xr_server->get_reference_frame()) * hmd_transform; + transform_for_eye = (xr_server->get_reference_frame()) * _head_transform; } return transform_for_eye; @@ -409,11 +438,10 @@ Transform3D MobileVRInterface::get_transform_for_view(uint32_t p_view, const Tra }; // just scale our origin point of our transform - Transform3D hmd_transform; - hmd_transform.basis = orientation; - hmd_transform.origin = Vector3(0.0, eye_height * world_scale, 0.0); + Transform3D _head_transform = head_transform; + _head_transform.origin *= world_scale; - transform_for_eye = p_cam_transform * (xr_server->get_reference_frame()) * hmd_transform * transform_for_eye; + transform_for_eye = p_cam_transform * (xr_server->get_reference_frame()) * _head_transform * transform_for_eye; } else { // huh? well just return what we got.... transform_for_eye = p_cam_transform; @@ -476,7 +504,16 @@ void MobileVRInterface::process() { _THREAD_SAFE_METHOD_ if (initialized) { + // update our head transform orientation set_position_from_sensors(); + + // update our head transform position (should be constant) + head_transform.origin = Vector3(0.0, eye_height, 0.0); + + if (head.is_valid()) { + // Set our head position, note in real space, reference frame and world scale is applied later + head->set_pose("default", head_transform, Vector3(), Vector3()); + } }; }; diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h index a843e1188b..b5bf966247 100644 --- a/modules/mobile_vr/mobile_vr_interface.h +++ b/modules/mobile_vr/mobile_vr_interface.h @@ -53,7 +53,6 @@ class MobileVRInterface : public XRInterface { private: bool initialized = false; XRInterface::TrackingStatus tracking_state; - Basis orientation; // Just set some defaults for these. At some point we need to look at adding a lookup table for common device + headset combos and/or support reading cardboard QR codes double eye_height = 1.85; @@ -68,6 +67,10 @@ private: double k2 = 0.215; double aspect = 1.0; + // at a minimum we need a tracker for our head + Ref<XRPositionalTracker> head; + Transform3D head_transform; + /* logic for processing our sensor data, this was originally in our positional tracker logic but I think that doesn't make sense in hindsight. It only makes marginally more sense to park it here for now, @@ -140,6 +143,10 @@ public: virtual bool initialize() override; virtual void uninitialize() override; + virtual bool supports_play_area_mode(XRInterface::PlayAreaMode p_mode) override; + virtual XRInterface::PlayAreaMode get_play_area_mode() const override; + virtual bool set_play_area_mode(XRInterface::PlayAreaMode p_mode) override; + virtual Size2 get_render_target_size() override; virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 247eee4280..26a04a358d 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -1660,7 +1660,7 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) { GDMonoProperty *property = top->get_property(p_name); if (property) { - property->set_value(mono_object, GDMonoMarshal::variant_to_mono_object(p_value, property->get_type())); + property->set_value_from_variant(mono_object, p_value); return true; } diff --git a/modules/mono/mono_gd/gd_mono_property.cpp b/modules/mono/mono_gd/gd_mono_property.cpp index 5391b7775e..5c7cf29e88 100644 --- a/modules/mono/mono_gd/gd_mono_property.cpp +++ b/modules/mono/mono_gd/gd_mono_property.cpp @@ -65,6 +65,8 @@ GDMonoProperty::GDMonoProperty(MonoProperty *p_mono_property, GDMonoClass *p_own type.type_class = GDMono::get_singleton()->get_class(param_type_class); } + param_buffer_size = GDMonoMarshal::variant_get_managed_unboxed_size(type); + attrs_fetched = false; attributes = nullptr; } @@ -147,24 +149,20 @@ bool GDMonoProperty::has_setter() { return mono_property_get_set_method(mono_property) != nullptr; } -void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc) { - MonoMethod *prop_method = mono_property_get_set_method(mono_property); - void *params[1] = { p_value }; - MonoException *exc = nullptr; - GDMonoUtils::runtime_invoke(prop_method, p_object, params, &exc); - if (exc) { - if (r_exc) { - *r_exc = exc; - } else { - GDMonoUtils::set_pending_exception(exc); - } - } -} +void GDMonoProperty::set_value_from_variant(MonoObject *p_object, const Variant &p_value, MonoException **r_exc) { + uint8_t *buffer = (uint8_t *)alloca(param_buffer_size); + unsigned int offset = 0; -void GDMonoProperty::set_value(MonoObject *p_object, void **p_params, MonoException **r_exc) { - MonoException *exc = nullptr; - GDMonoUtils::property_set_value(mono_property, p_object, p_params, &exc); + void *params[1] = { + GDMonoMarshal::variant_to_managed_unboxed(p_value, type, buffer, offset) + }; + +#ifdef DEBUG_ENABLED + CRASH_COND(offset != param_buffer_size); +#endif + MonoException *exc = nullptr; + GDMonoUtils::property_set_value(mono_property, p_object, params, &exc); if (exc) { if (r_exc) { *r_exc = exc; diff --git a/modules/mono/mono_gd/gd_mono_property.h b/modules/mono/mono_gd/gd_mono_property.h index af7a2c02e5..9bb1caa759 100644 --- a/modules/mono/mono_gd/gd_mono_property.h +++ b/modules/mono/mono_gd/gd_mono_property.h @@ -45,6 +45,8 @@ class GDMonoProperty : public IMonoClassMember { bool attrs_fetched; MonoCustomAttrInfo *attributes; + unsigned int param_buffer_size; + public: virtual GDMonoClass *get_enclosing_class() const final { return owner; } @@ -64,8 +66,7 @@ public: _FORCE_INLINE_ ManagedType get_type() const { return type; } - void set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc = nullptr); - void set_value(MonoObject *p_object, void **p_params, MonoException **r_exc = nullptr); + void set_value_from_variant(MonoObject *p_object, const Variant &p_value, MonoException **r_exc = nullptr); MonoObject *get_value(MonoObject *p_object, MonoException **r_exc = nullptr); bool get_bool_value(MonoObject *p_object); diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index 13939bd014..09aa9ad948 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -450,7 +450,7 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) { int line = si.size() ? si[0].line : __LINE__; String error_msg = "Unhandled exception"; - EngineDebugger::get_script_debugger()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si); + EngineDebugger::get_script_debugger()->send_error(func, file, line, error_msg, exc_msg, true, ERR_HANDLER_ERROR, si); #endif } diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp index bb6bc578a4..8fd3a13e1f 100644 --- a/modules/navigation/navigation_mesh_generator.cpp +++ b/modules/navigation/navigation_mesh_generator.cpp @@ -489,7 +489,7 @@ NavigationMeshGenerator::~NavigationMeshGenerator() { } void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) { - ERR_FAIL_COND(!p_nav_mesh.is_valid()); + ERR_FAIL_COND_MSG(!p_nav_mesh.is_valid(), "Invalid navigation mesh."); #ifdef TOOLS_ENABLED EditorProgress *ep(nullptr); diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 54d310e636..8f4e807295 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -1688,7 +1688,7 @@ Variant VisualScriptInstance::_call_internal(const StringName &p_method, void *p // debugger break did not happen if (!VisualScriptLanguage::singleton->debug_break(error_str, false)) { - _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, error_str.utf8().get_data(), ERR_HANDLER_SCRIPT); + _err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, error_str.utf8().get_data(), false, ERR_HANDLER_SCRIPT); } //} diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index bf2d8e9683..78881f0a53 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -90,12 +90,6 @@ public: void set_stack_size(int p_size); int get_stack_size() const; - void set_return_type_enabled(bool p_returns); - bool is_return_type_enabled() const; - - void set_return_type(Variant::Type p_type); - Variant::Type get_return_type() const; - void set_rpc_mode(Multiplayer::RPCMode p_mode); Multiplayer::RPCMode get_rpc_mode() const; diff --git a/modules/webxr/doc_classes/WebXRInterface.xml b/modules/webxr/doc_classes/WebXRInterface.xml index 16d671c9e9..6e224a8242 100644 --- a/modules/webxr/doc_classes/WebXRInterface.xml +++ b/modules/webxr/doc_classes/WebXRInterface.xml @@ -87,7 +87,7 @@ There are several ways to handle "controller" input: - Using [XRController3D] nodes and their [signal XRController3D.button_pressed] and [signal XRController3D.button_released] signals. This is how controllers are typically handled in AR/VR apps in Godot, however, this will only work with advanced VR controllers like the Oculus Touch or Index controllers, for example. The buttons codes are defined by [url=https://immersive-web.github.io/webxr-gamepads-module/#xr-standard-gamepad-mapping]Section 3.3 of the WebXR Gamepads Module[/url]. - Using [method Node._unhandled_input] and [InputEventJoypadButton] or [InputEventJoypadMotion]. This works the same as normal joypads, except the [member InputEvent.device] starts at 100, so the left controller is 100 and the right controller is 101, and the button codes are also defined by [url=https://immersive-web.github.io/webxr-gamepads-module/#xr-standard-gamepad-mapping]Section 3.3 of the WebXR Gamepads Module[/url]. - - Using the [signal select], [signal squeeze] and related signals. This method will work for both advanced VR controllers, and non-traditional "controllers" like a tap on the screen, a spoken voice command or a button press on the device itself. The [code]controller_id[/code] passed to these signals is the same id as used in [member XRController3D.controller_id]. + - Using the [signal select], [signal squeeze] and related signals. This method will work for both advanced VR controllers, and non-traditional "controllers" like a tap on the screen, a spoken voice command or a button press on the device itself. You can use one or all of these methods to allow your game or app to support a wider or narrower set of devices and input methods, or to allow more advanced interactions with more advanced devices. </description> <tutorials> diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp index 10c17aa672..2676b3cf80 100644 --- a/modules/webxr/webxr_interface_js.cpp +++ b/modules/webxr/webxr_interface_js.cpp @@ -163,9 +163,14 @@ String WebXRInterfaceJS::get_reference_space_type() const { Ref<XRPositionalTracker> WebXRInterfaceJS::get_controller(int p_controller_id) const { XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL_V(xr_server, nullptr); + ERR_FAIL_NULL_V(xr_server, Ref<XRPositionalTracker>()); - return xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id); + // TODO support more then two controllers + if (p_controller_id >= 0 && p_controller_id < 2) { + return controllers[p_controller_id]; + }; + + return Ref<XRPositionalTracker>(); } String WebXRInterfaceJS::get_visibility_state() const { @@ -224,6 +229,13 @@ bool WebXRInterfaceJS::initialize() { return false; } + // we must create a tracker for our head + head_tracker.instantiate(); + head_tracker->set_tracker_type(XRServer::TRACKER_HEAD); + head_tracker->set_tracker_name("head"); + head_tracker->set_tracker_desc("Players head"); + xr_server->add_tracker(head_tracker); + // make this our primary interface xr_server->set_primary_interface(this); @@ -254,9 +266,17 @@ bool WebXRInterfaceJS::initialize() { void WebXRInterfaceJS::uninitialize() { if (initialized) { XRServer *xr_server = XRServer::get_singleton(); - if (xr_server != nullptr && xr_server->get_primary_interface() == this) { - // no longer our primary interface - xr_server->set_primary_interface(nullptr); + if (xr_server != nullptr) { + if (head_tracker.is_valid()) { + xr_server->remove_tracker(head_tracker); + + head_tracker.unref(); + } + + if (xr_server->get_primary_interface() == this) { + // no longer our primary interface + xr_server->set_primary_interface(nullptr); + } } godot_webxr_uninitialize(); @@ -373,9 +393,9 @@ Vector<BlitToScreen> WebXRInterfaceJS::commit_views(RID p_render_target, const R } // @todo Refactor this to be based on "views" rather than "eyes". - godot_webxr_commit_for_eye(XRInterface::EYE_LEFT); + godot_webxr_commit_for_eye(1); if (godot_webxr_get_view_count() > 1) { - godot_webxr_commit_for_eye(XRInterface::EYE_RIGHT); + godot_webxr_commit_for_eye(2); } return blit_to_screen; @@ -385,6 +405,11 @@ void WebXRInterfaceJS::process() { if (initialized) { godot_webxr_sample_controller_data(); + if (head_tracker.is_valid()) { + // TODO set default pose to our head location (i.e. get_camera_transform without world scale and reference frame applied) + // head_tracker->set_pose("default", head_transform, Vector3(), Vector3()); + } + int controller_count = godot_webxr_get_controller_count(); if (controller_count == 0) { return; @@ -400,51 +425,70 @@ void WebXRInterfaceJS::_update_tracker(int p_controller_id) { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL(xr_server); - Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, p_controller_id + 1); + // need to support more then two controllers... + if (p_controller_id < 0 || p_controller_id > 1) { + return; + } + + Ref<XRPositionalTracker> tracker = controllers[p_controller_id]; if (godot_webxr_is_controller_connected(p_controller_id)) { if (tracker.is_null()) { tracker.instantiate(); tracker->set_tracker_type(XRServer::TRACKER_CONTROLLER); // Controller id's 0 and 1 are always the left and right hands. if (p_controller_id < 2) { - tracker->set_tracker_name(p_controller_id == 0 ? "Left" : "Right"); + tracker->set_tracker_name(p_controller_id == 0 ? "left_hand" : "right_hand"); + tracker->set_tracker_desc(p_controller_id == 0 ? "Left hand controller" : "Right hand controller"); tracker->set_tracker_hand(p_controller_id == 0 ? XRPositionalTracker::TRACKER_HAND_LEFT : XRPositionalTracker::TRACKER_HAND_RIGHT); + } else { + char name[1024]; + sprintf(name, "tracker_%i", p_controller_id); + tracker->set_tracker_name(name); + tracker->set_tracker_desc(name); } - // Use the ids we're giving to our "virtual" gamepads. - tracker->set_joy_id(p_controller_id + 100); xr_server->add_tracker(tracker); } - Input *input = Input::get_singleton(); - float *tracker_matrix = godot_webxr_get_controller_transform(p_controller_id); if (tracker_matrix) { + // Note, poses should NOT have world scale and our reference frame applied! Transform3D transform = _js_matrix_to_transform(tracker_matrix); - tracker->set_position(transform.origin); - tracker->set_orientation(transform.basis); + tracker->set_pose("default", transform, Vector3(), Vector3()); free(tracker_matrix); } + // TODO implement additional poses such as "aim" and "grip" + int *buttons = godot_webxr_get_controller_buttons(p_controller_id); if (buttons) { + // TODO buttons should be named properly, this is just a temporary fix for (int i = 0; i < buttons[0]; i++) { - input->joy_button(p_controller_id + 100, (JoyButton)i, *((float *)buttons + (i + 1))); + char name[1024]; + sprintf(name, "button_%i", i); + + float value = *((float *)buttons + (i + 1)); + bool state = value > 0.0; + tracker->set_input(name, state); } free(buttons); } int *axes = godot_webxr_get_controller_axes(p_controller_id); if (axes) { + // TODO again just a temporary fix, split these between proper float and vector2 inputs for (int i = 0; i < axes[0]; i++) { - Input::JoyAxisValue joy_axis; - joy_axis.min = -1; - joy_axis.value = *((float *)axes + (i + 1)); - input->joy_axis(p_controller_id + 100, (JoyAxis)i, joy_axis); + char name[1024]; + sprintf(name, "axis_%i", i); + + float value = *((float *)axes + (i + 1)); + ; + tracker->set_input(name, value); } free(axes); } } else if (tracker.is_valid()) { xr_server->remove_tracker(tracker); + controllers[p_controller_id].unref(); } } @@ -454,7 +498,7 @@ void WebXRInterfaceJS::_on_controller_changed() { for (int i = 0; i < 2; i++) { bool controller_connected = godot_webxr_is_controller_connected(i); if (controllers_state[i] != controller_connected) { - Input::get_singleton()->joy_connection_changed(i + 100, controller_connected, i == 0 ? "Left" : "Right", ""); + // Input::get_singleton()->joy_connection_changed(i + 100, controller_connected, i == 0 ? "Left" : "Right", ""); controllers_state[i] = controller_connected; } } diff --git a/modules/webxr/webxr_interface_js.h b/modules/webxr/webxr_interface_js.h index eb77f35f39..6e6548c946 100644 --- a/modules/webxr/webxr_interface_js.h +++ b/modules/webxr/webxr_interface_js.h @@ -46,6 +46,7 @@ class WebXRInterfaceJS : public WebXRInterface { private: bool initialized; + Ref<XRPositionalTracker> head_tracker; String session_mode; String required_features; @@ -53,7 +54,9 @@ private: String requested_reference_space_types; String reference_space_type; + // TODO maybe turn into a vector to support more then 2 controllers... bool controllers_state[2]; + Ref<XRPositionalTracker> controllers[2]; Size2 render_targetsize; Transform3D _js_matrix_to_transform(float *p_js_matrix); diff --git a/platform/android/audio_driver_opensl.h b/platform/android/audio_driver_opensl.h index e3efaddba2..fcc2513f3f 100644 --- a/platform/android/audio_driver_opensl.h +++ b/platform/android/audio_driver_opensl.h @@ -59,7 +59,6 @@ class AudioDriverOpenSL : public AudioDriver { SLObjectItf sl; SLEngineItf EngineItf; SLObjectItf OutputMix; - SLVolumeItf volumeItf; SLObjectItf player; SLObjectItf recorder; SLAndroidSimpleBufferQueueItf bufferQueueItf; @@ -68,7 +67,6 @@ class AudioDriverOpenSL : public AudioDriver { SLDataFormat_PCM pcm; SLDataSink audioSink; SLDataLocator_OutputMix locator_outputmix; - SLBufferQueueState state; static AudioDriverOpenSL *s_ad; @@ -89,8 +87,6 @@ class AudioDriverOpenSL : public AudioDriver { virtual Error capture_init_device(); public: - void set_singleton(); - virtual const char *get_name() const; virtual Error init(); diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 034885aa32..94ca51f75a 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -263,7 +263,6 @@ Size2i OS_Android::get_display_size() const { void OS_Android::set_context_is_16_bits(bool p_is_16) { #if defined(OPENGL_ENABLED) - //use_16bits_fbo = p_is_16; //if (rasterizer) // rasterizer->set_force_16_bits_fbo(p_is_16); #endif @@ -325,7 +324,6 @@ OS_Android::OS_Android(GodotJavaWrapper *p_godot_java, GodotIOJavaWrapper *p_god #if defined(OPENGL_ENABLED) gl_extensions = nullptr; use_gl2 = false; - use_16bits_fbo = false; #endif #if defined(VULKAN_ENABLED) diff --git a/platform/android/os_android.h b/platform/android/os_android.h index ce8083388f..9bb37325cf 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -48,7 +48,6 @@ private: bool use_apk_expansion; #if defined(OPENGL_ENABLED) - bool use_16bits_fbo; const char *gl_extensions; #endif diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index f2cd336b39..c0e5aac938 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -406,6 +406,20 @@ void DisplayServerX11::clipboard_set(const String &p_text) { XSetSelectionOwner(x11_display, XInternAtom(x11_display, "CLIPBOARD", 0), windows[MAIN_WINDOW_ID].x11_window, CurrentTime); } +void DisplayServerX11::clipboard_set_primary(const String &p_text) { + _THREAD_SAFE_METHOD_ + if (!p_text.is_empty()) { + { + // The clipboard content can be accessed while polling for events. + MutexLock mutex_lock(events_mutex); + internal_clipboard_primary = p_text; + } + + XSetSelectionOwner(x11_display, XA_PRIMARY, windows[MAIN_WINDOW_ID].x11_window, CurrentTime); + XSetSelectionOwner(x11_display, XInternAtom(x11_display, "PRIMARY", 0), windows[MAIN_WINDOW_ID].x11_window, CurrentTime); + } +} + Bool DisplayServerX11::_predicate_clipboard_selection(Display *display, XEvent *event, XPointer arg) { if (event->type == SelectionNotify && event->xselection.requestor == *(Window *)arg) { return True; @@ -427,7 +441,12 @@ String DisplayServerX11::_clipboard_get_impl(Atom p_source, Window x11_window, A Window selection_owner = XGetSelectionOwner(x11_display, p_source); if (selection_owner == x11_window) { - return internal_clipboard; + static const char *target_type = "PRIMARY"; + if (p_source != None && String(XGetAtomName(x11_display, p_source)) == target_type) { + return internal_clipboard_primary; + } else { + return internal_clipboard; + } } if (selection_owner != None) { @@ -580,6 +599,19 @@ String DisplayServerX11::clipboard_get() const { return ret; } +String DisplayServerX11::clipboard_get_primary() const { + _THREAD_SAFE_METHOD_ + + String ret; + ret = _clipboard_get(XInternAtom(x11_display, "PRIMARY", 0), windows[MAIN_WINDOW_ID].x11_window); + + if (ret.is_empty()) { + ret = _clipboard_get(XA_PRIMARY, windows[MAIN_WINDOW_ID].x11_window); + } + + return ret; +} + Bool DisplayServerX11::_predicate_clipboard_save_targets(Display *display, XEvent *event, XPointer arg) { if (event->xany.window == *(Window *)arg) { return (event->type == SelectionRequest) || @@ -2417,7 +2449,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, Input::get_singleton()->parse_input_event(k); } -Atom DisplayServerX11::_process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property) const { +Atom DisplayServerX11::_process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property, Atom p_selection) const { if (p_target == XInternAtom(x11_display, "TARGETS", 0)) { // Request to list all supported targets. Atom data[9]; @@ -2459,7 +2491,13 @@ Atom DisplayServerX11::_process_selection_request_target(Atom p_target, Window p p_target == XInternAtom(x11_display, "text/plain", 0)) { // Directly using internal clipboard because we know our window // is the owner during a selection request. - CharString clip = internal_clipboard.utf8(); + CharString clip; + static const char *target_type = "PRIMARY"; + if (p_selection != None && String(XGetAtomName(x11_display, p_selection)) == target_type) { + clip = internal_clipboard_primary.utf8(); + } else { + clip = internal_clipboard.utf8(); + } XChangeProperty(x11_display, p_requestor, p_property, @@ -2497,7 +2535,7 @@ void DisplayServerX11::_handle_selection_request_event(XSelectionRequestEvent *p for (uint64_t i = 0; i < len; i += 2) { Atom target = targets[i]; Atom &property = targets[i + 1]; - property = _process_selection_request_target(target, p_event->requestor, property); + property = _process_selection_request_target(target, p_event->requestor, property, p_event->selection); } XChangeProperty(x11_display, @@ -2515,7 +2553,7 @@ void DisplayServerX11::_handle_selection_request_event(XSelectionRequestEvent *p } } else { // Request for target conversion. - respond.xselection.property = _process_selection_request_target(p_event->target, p_event->requestor, p_event->property); + respond.xselection.property = _process_selection_request_target(p_event->target, p_event->requestor, p_event->property, p_event->selection); } respond.xselection.type = SelectionNotify; diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 1887c7105b..ded481f613 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -155,6 +155,7 @@ class DisplayServerX11 : public DisplayServer { WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect); String internal_clipboard; + String internal_clipboard_primary; Window xdnd_source_window; ::Display *x11_display; char *xmbstring; @@ -205,7 +206,7 @@ class DisplayServerX11 : public DisplayServer { void _handle_key_event(WindowID p_window, XKeyEvent *p_event, LocalVector<XEvent> &p_events, uint32_t &p_event_index, bool p_echo = false); - Atom _process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property) const; + Atom _process_selection_request_target(Atom p_target, Window p_requestor, Atom p_property, Atom p_selection) const; void _handle_selection_request_event(XSelectionRequestEvent *p_event) const; String _clipboard_get_impl(Atom p_source, Window x11_window, Atom target) const; @@ -290,6 +291,8 @@ public: virtual void clipboard_set(const String &p_text) override; virtual String clipboard_get() const override; + virtual void clipboard_set_primary(const String &p_text) override; + virtual String clipboard_get_primary() const override; virtual int get_screen_count() const override; virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; diff --git a/platform/osx/joypad_osx.h b/platform/osx/joypad_osx.h index c060c3d523..3048ecf39e 100644 --- a/platform/osx/joypad_osx.h +++ b/platform/osx/joypad_osx.h @@ -106,7 +106,6 @@ private: int get_joy_ref(IOHIDDeviceRef p_device) const; void poll_joypads() const; - void setup_joypad_objects(); void config_hid_manager(CFArrayRef p_matching_array) const; void joypad_vibration_start(int p_id, float p_magnitude, float p_duration, uint64_t p_timestamp); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index e9cb46ed21..489cbe074b 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -178,7 +178,7 @@ class OSXTerminalLogger : public StdLogger { public: - virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR) { + virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify, ErrorType p_type = ERR_ERROR) { if (!should_log(true)) { return; } diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 7945f409a1..9398573ee1 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -117,11 +117,6 @@ private: Windows::System::Display::DisplayRequest ^ display_request; - void _post_dpad(DWORD p_dpad, int p_device, bool p_pressed); - - void _drag_event(int idx, UINT uMsg, WPARAM wParam, LPARAM lParam); - void _touch_event(int idx, UINT uMsg, WPARAM wParam, LPARAM lParam); - ref class ManagedType { public: property bool alert_close_handle; diff --git a/scene/2d/audio_listener_2d.h b/scene/2d/audio_listener_2d.h index 875887acc6..454053bc4a 100644 --- a/scene/2d/audio_listener_2d.h +++ b/scene/2d/audio_listener_2d.h @@ -43,8 +43,6 @@ private: friend class Viewport; protected: - void _update_listener(); - bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 6916f832d0..28facd09ce 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -454,7 +454,7 @@ void CollisionObject2D::shape_owner_clear_shapes(uint32_t p_owner) { } uint32_t CollisionObject2D::shape_find_owner(int p_shape_index) const { - ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0); + ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, UINT32_MAX); for (const KeyValue<uint32_t, ShapeData> &E : shapes) { for (int i = 0; i < E.value.shapes.size(); i++) { @@ -465,7 +465,7 @@ uint32_t CollisionObject2D::shape_find_owner(int p_shape_index) const { } //in theory it should be unreachable - return 0; + ERR_FAIL_V_MSG(UINT32_MAX, "Can't find owner for shape index " + itos(p_shape_index) + "."); } void CollisionObject2D::set_pickable(bool p_enabled) { diff --git a/scene/2d/cpu_particles_2d.h b/scene/2d/cpu_particles_2d.h index 4990d443e3..391f51224e 100644 --- a/scene/2d/cpu_particles_2d.h +++ b/scene/2d/cpu_particles_2d.h @@ -201,7 +201,6 @@ public: void set_explosiveness_ratio(real_t p_ratio); void set_randomness_ratio(real_t p_ratio); void set_lifetime_randomness(double p_random); - void set_visibility_aabb(const Rect2 &p_aabb); void set_use_local_coordinates(bool p_enable); void set_speed_scale(double p_scale); @@ -213,7 +212,6 @@ public: real_t get_explosiveness_ratio() const; real_t get_randomness_ratio() const; double get_lifetime_randomness() const; - Rect2 get_visibility_aabb() const; bool get_use_local_coordinates() const; double get_speed_scale() const; @@ -226,9 +224,6 @@ public: void set_draw_order(DrawOrder p_order); DrawOrder get_draw_order() const; - void set_draw_passes(int p_count); - int get_draw_passes() const; - void set_texture(const Ref<Texture2D> &p_texture); Ref<Texture2D> get_texture() const; @@ -264,7 +259,6 @@ public: void set_emission_points(const Vector<Vector2> &p_points); void set_emission_normals(const Vector<Vector2> &p_normals); void set_emission_colors(const Vector<Color> &p_colors); - void set_emission_point_count(int p_count); void set_scale_curve_x(Ref<Curve> p_scale_curve); void set_scale_curve_y(Ref<Curve> p_scale_curve); void set_split_scale(bool p_split_scale); @@ -275,7 +269,6 @@ public: Vector<Vector2> get_emission_points() const; Vector<Vector2> get_emission_normals() const; Vector<Color> get_emission_colors() const; - int get_emission_point_count() const; Ref<Curve> get_scale_curve_x() const; Ref<Curve> get_scale_curve_y() const; bool get_split_scale(); diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index 3637594e1b..6950fefdbe 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -532,6 +532,7 @@ void GPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_trail_section_subdivisions"), &GPUParticles2D::get_trail_section_subdivisions); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false. ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); diff --git a/scene/2d/mesh_instance_2d.cpp b/scene/2d/mesh_instance_2d.cpp index 15008390b7..58bff97da9 100644 --- a/scene/2d/mesh_instance_2d.cpp +++ b/scene/2d/mesh_instance_2d.cpp @@ -96,6 +96,10 @@ Rect2 MeshInstance2D::_edit_get_rect() const { return Node2D::_edit_get_rect(); } + +bool MeshInstance2D::_edit_use_rect() const { + return mesh.is_valid(); +} #endif MeshInstance2D::MeshInstance2D() { diff --git a/scene/2d/mesh_instance_2d.h b/scene/2d/mesh_instance_2d.h index adfda4cf7f..f94d53da7d 100644 --- a/scene/2d/mesh_instance_2d.h +++ b/scene/2d/mesh_instance_2d.h @@ -48,6 +48,7 @@ protected: public: #ifdef TOOLS_ENABLED virtual Rect2 _edit_get_rect() const override; + virtual bool _edit_use_rect() const override; #endif void set_mesh(const Ref<Mesh> &p_mesh); diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index 2f00978123..7faa964407 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -184,7 +184,7 @@ Vector2 NavigationAgent2D::get_target_location() const { Vector2 NavigationAgent2D::get_next_location() { update_navigation(); if (navigation_path.size() == 0) { - ERR_FAIL_COND_V(agent_parent == nullptr, Vector2()); + ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector2(), "The agent has no parent."); return agent_parent->get_global_position(); } else { return navigation_path[nav_path_index]; @@ -192,7 +192,7 @@ Vector2 NavigationAgent2D::get_next_location() { } real_t NavigationAgent2D::distance_to_target() const { - ERR_FAIL_COND_V(agent_parent == nullptr, 0.0); + ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent."); return agent_parent->get_global_position().distance_to(target_location); } diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index c2f150ce00..b546eaefa6 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -34,98 +34,6 @@ #include "servers/navigation_server_2d.h" -void TileMapPattern::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) { - ERR_FAIL_COND_MSG(p_coords.x < 0 || p_coords.y < 0, vformat("Cannot set cell with negative coords in a TileMapPattern. Wrong coords: %s", p_coords)); - - size = size.max(p_coords + Vector2i(1, 1)); - pattern[p_coords] = TileMapCell(p_source_id, p_atlas_coords, p_alternative_tile); -} - -bool TileMapPattern::has_cell(const Vector2i &p_coords) const { - return pattern.has(p_coords); -} - -void TileMapPattern::remove_cell(const Vector2i &p_coords, bool p_update_size) { - ERR_FAIL_COND(!pattern.has(p_coords)); - - pattern.erase(p_coords); - if (p_update_size) { - size = Vector2i(); - for (const KeyValue<Vector2i, TileMapCell> &E : pattern) { - size = size.max(E.key + Vector2i(1, 1)); - } - } -} - -int TileMapPattern::get_cell_source_id(const Vector2i &p_coords) const { - ERR_FAIL_COND_V(!pattern.has(p_coords), TileSet::INVALID_SOURCE); - - return pattern[p_coords].source_id; -} - -Vector2i TileMapPattern::get_cell_atlas_coords(const Vector2i &p_coords) const { - ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetSource::INVALID_ATLAS_COORDS); - - return pattern[p_coords].get_atlas_coords(); -} - -int TileMapPattern::get_cell_alternative_tile(const Vector2i &p_coords) const { - ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetSource::INVALID_TILE_ALTERNATIVE); - - return pattern[p_coords].alternative_tile; -} - -TypedArray<Vector2i> TileMapPattern::get_used_cells() const { - // Returns the cells used in the tilemap. - TypedArray<Vector2i> a; - a.resize(pattern.size()); - int i = 0; - for (const KeyValue<Vector2i, TileMapCell> &E : pattern) { - Vector2i p(E.key.x, E.key.y); - a[i++] = p; - } - - return a; -} - -Vector2i TileMapPattern::get_size() const { - return size; -} - -void TileMapPattern::set_size(const Vector2i &p_size) { - for (const KeyValue<Vector2i, TileMapCell> &E : pattern) { - Vector2i coords = E.key; - if (p_size.x <= coords.x || p_size.y <= coords.y) { - ERR_FAIL_MSG(vformat("Cannot set pattern size to %s, it contains a tile at %s. Size can only be increased.", p_size, coords)); - }; - } - - size = p_size; -} - -bool TileMapPattern::is_empty() const { - return pattern.is_empty(); -}; - -void TileMapPattern::clear() { - size = Vector2i(); - pattern.clear(); -}; - -void TileMapPattern::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE)); - ClassDB::bind_method(D_METHOD("has_cell", "coords"), &TileMapPattern::has_cell); - ClassDB::bind_method(D_METHOD("remove_cell", "coords"), &TileMapPattern::remove_cell); - ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMapPattern::get_cell_source_id); - ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords"), &TileMapPattern::get_cell_atlas_coords); - ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords"), &TileMapPattern::get_cell_alternative_tile); - - ClassDB::bind_method(D_METHOD("get_used_cells"), &TileMapPattern::get_used_cells); - ClassDB::bind_method(D_METHOD("get_size"), &TileMapPattern::get_size); - ClassDB::bind_method(D_METHOD("set_size", "size"), &TileMapPattern::set_size); - ClassDB::bind_method(D_METHOD("is_empty"), &TileMapPattern::is_empty); -} - Vector2i TileMap::transform_coords_layout(Vector2i p_coords, TileSet::TileOffsetAxis p_offset_axis, TileSet::TileLayout p_from_layout, TileSet::TileLayout p_to_layout) { // Transform to stacked layout. Vector2i output = p_coords; @@ -1788,11 +1696,12 @@ int TileMap::get_cell_alternative_tile(int p_layer, const Vector2i &p_coords, bo return E->get().alternative_tile; } -TileMapPattern *TileMap::get_pattern(int p_layer, TypedArray<Vector2i> p_coords_array) { +Ref<TileMapPattern> TileMap::get_pattern(int p_layer, TypedArray<Vector2i> p_coords_array) { ERR_FAIL_INDEX_V(p_layer, (int)layers.size(), nullptr); ERR_FAIL_COND_V(!tile_set.is_valid(), nullptr); - TileMapPattern *output = memnew(TileMapPattern); + Ref<TileMapPattern> output; + output.instantiate(); if (p_coords_array.is_empty()) { return output; } @@ -1841,7 +1750,7 @@ TileMapPattern *TileMap::get_pattern(int p_layer, TypedArray<Vector2i> p_coords_ return output; } -Vector2i TileMap::map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_in_pattern, const TileMapPattern *p_pattern) { +Vector2i TileMap::map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_in_pattern, Ref<TileMapPattern> p_pattern) { ERR_FAIL_COND_V(!p_pattern->has_cell(p_coords_in_pattern), Vector2i()); Vector2i output = p_position_in_tilemap + p_coords_in_pattern; @@ -1864,7 +1773,7 @@ Vector2i TileMap::map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_ return output; } -void TileMap::set_pattern(int p_layer, Vector2i p_position, const TileMapPattern *p_pattern) { +void TileMap::set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPattern> p_pattern) { ERR_FAIL_INDEX(p_layer, (int)layers.size()); ERR_FAIL_COND(!tile_set.is_valid()); @@ -3076,6 +2985,10 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("get_coords_for_body_rid", "body"), &TileMap::get_coords_for_body_rid); + ClassDB::bind_method(D_METHOD("get_pattern", "layer", "coords_array"), &TileMap::get_pattern); + ClassDB::bind_method(D_METHOD("map_pattern", "position_in_tilemap", "coords_in_pattern", "pattern"), &TileMap::map_pattern); + ClassDB::bind_method(D_METHOD("set_pattern", "layer", "position", "pattern"), &TileMap::set_pattern); + ClassDB::bind_method(D_METHOD("fix_invalid_tiles"), &TileMap::fix_invalid_tiles); ClassDB::bind_method(D_METHOD("clear_layer", "layer"), &TileMap::clear_layer); ClassDB::bind_method(D_METHOD("clear"), &TileMap::clear); @@ -3092,7 +3005,7 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_dirty_quadrants"), &TileMap::_update_dirty_quadrants); - ClassDB::bind_method(D_METHOD("_set_tile_data", "layer"), &TileMap::_set_tile_data); + ClassDB::bind_method(D_METHOD("_set_tile_data", "layer", "data"), &TileMap::_set_tile_data); ClassDB::bind_method(D_METHOD("_get_tile_data", "layer"), &TileMap::_get_tile_data); ClassDB::bind_method(D_METHOD("_tile_set_changed_deferred_update"), &TileMap::_tile_set_changed_deferred_update); diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h index e5809deabb..e1f38a314c 100644 --- a/scene/2d/tile_map.h +++ b/scene/2d/tile_map.h @@ -37,51 +37,6 @@ class TileSetAtlasSource; -union TileMapCell { - struct { - int32_t source_id : 16; - int16_t coord_x : 16; - int16_t coord_y : 16; - int32_t alternative_tile : 16; - }; - - uint64_t _u64t; - TileMapCell(int p_source_id = -1, Vector2i p_atlas_coords = TileSetSource::INVALID_ATLAS_COORDS, int p_alternative_tile = TileSetSource::INVALID_TILE_ALTERNATIVE) { - source_id = p_source_id; - set_atlas_coords(p_atlas_coords); - alternative_tile = p_alternative_tile; - } - - Vector2i get_atlas_coords() const { - return Vector2i(coord_x, coord_y); - } - - void set_atlas_coords(const Vector2i &r_coords) { - coord_x = r_coords.x; - coord_y = r_coords.y; - } - - bool operator<(const TileMapCell &p_other) const { - if (source_id == p_other.source_id) { - if (coord_x == p_other.coord_x) { - if (coord_y == p_other.coord_y) { - return alternative_tile < p_other.alternative_tile; - } else { - return coord_y < p_other.coord_y; - } - } else { - return coord_x < p_other.coord_x; - } - } else { - return source_id < p_other.source_id; - } - } - - bool operator!=(const TileMapCell &p_other) const { - return !(source_id == p_other.source_id && coord_x == p_other.coord_x && coord_y == p_other.coord_y && alternative_tile == p_other.alternative_tile); - } -}; - struct TileMapQuadrant { struct CoordsWorldComparator { _ALWAYS_INLINE_ bool operator()(const Vector2i &p_a, const Vector2i &p_b) const { @@ -150,32 +105,6 @@ struct TileMapQuadrant { } }; -class TileMapPattern : public Object { - GDCLASS(TileMapPattern, Object); - - Vector2i size; - Map<Vector2i, TileMapCell> pattern; - -protected: - static void _bind_methods(); - -public: - void set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile = 0); - bool has_cell(const Vector2i &p_coords) const; - void remove_cell(const Vector2i &p_coords, bool p_update_size = true); - int get_cell_source_id(const Vector2i &p_coords) const; - Vector2i get_cell_atlas_coords(const Vector2i &p_coords) const; - int get_cell_alternative_tile(const Vector2i &p_coords) const; - - TypedArray<Vector2i> get_used_cells() const; - - Vector2i get_size() const; - void set_size(const Vector2i &p_size); - bool is_empty() const; - - void clear(); -}; - class TileMap : public Node2D { GDCLASS(TileMap, Node2D); @@ -349,9 +278,9 @@ public: Vector2i get_cell_atlas_coords(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const; int get_cell_alternative_tile(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const; - TileMapPattern *get_pattern(int p_layer, TypedArray<Vector2i> p_coords_array); - Vector2i map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_in_pattern, const TileMapPattern *p_pattern); - void set_pattern(int p_layer, Vector2i p_position, const TileMapPattern *p_pattern); + Ref<TileMapPattern> get_pattern(int p_layer, TypedArray<Vector2i> p_coords_array); + Vector2i map_pattern(Vector2i p_position_in_tilemap, Vector2i p_coords_in_pattern, Ref<TileMapPattern> p_pattern); + void set_pattern(int p_layer, Vector2i p_position, const Ref<TileMapPattern> p_pattern); // Not exposed to users TileMapCell get_cell(int p_layer, const Vector2i &p_coords, bool p_use_proxies = false) const; diff --git a/scene/3d/audio_listener_3d.h b/scene/3d/audio_listener_3d.h index 492cacb0e9..31de3b4fb1 100644 --- a/scene/3d/audio_listener_3d.h +++ b/scene/3d/audio_listener_3d.h @@ -63,9 +63,6 @@ public: virtual Transform3D get_listener_transform() const; - void set_visible_layers(uint32_t p_layers); - uint32_t get_visible_layers() const; - AudioListener3D(); ~AudioListener3D(); }; diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 814ed5c2a7..fd891a5e13 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -648,7 +648,7 @@ void CollisionObject3D::shape_owner_clear_shapes(uint32_t p_owner) { } uint32_t CollisionObject3D::shape_find_owner(int p_shape_index) const { - ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, 0); + ERR_FAIL_INDEX_V(p_shape_index, total_subshapes, UINT32_MAX); for (const KeyValue<uint32_t, ShapeData> &E : shapes) { for (int i = 0; i < E.value.shapes.size(); i++) { @@ -659,7 +659,7 @@ uint32_t CollisionObject3D::shape_find_owner(int p_shape_index) const { } //in theory it should be unreachable - return 0; + ERR_FAIL_V_MSG(UINT32_MAX, "Can't find owner for shape index " + itos(p_shape_index) + "."); } CollisionObject3D::CollisionObject3D(RID p_rid, bool p_area) { diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h index 160814ead4..aca7328a27 100644 --- a/scene/3d/cpu_particles_3d.h +++ b/scene/3d/cpu_particles_3d.h @@ -209,7 +209,6 @@ public: void set_explosiveness_ratio(real_t p_ratio); void set_randomness_ratio(real_t p_ratio); void set_lifetime_randomness(double p_random); - void set_visibility_aabb(const AABB &p_aabb); void set_use_local_coordinates(bool p_enable); void set_speed_scale(double p_scale); @@ -221,7 +220,6 @@ public: real_t get_explosiveness_ratio() const; real_t get_randomness_ratio() const; double get_lifetime_randomness() const; - AABB get_visibility_aabb() const; bool get_use_local_coordinates() const; double get_speed_scale() const; @@ -234,9 +232,6 @@ public: void set_draw_order(DrawOrder p_order); DrawOrder get_draw_order() const; - void set_draw_passes(int p_count); - int get_draw_passes() const; - void set_mesh(const Ref<Mesh> &p_mesh); Ref<Mesh> get_mesh() const; @@ -275,7 +270,6 @@ public: void set_emission_points(const Vector<Vector3> &p_points); void set_emission_normals(const Vector<Vector3> &p_normals); void set_emission_colors(const Vector<Color> &p_colors); - void set_emission_point_count(int p_count); void set_emission_ring_axis(Vector3 p_axis); void set_emission_ring_height(real_t p_height); void set_emission_ring_radius(real_t p_radius); @@ -291,7 +285,6 @@ public: Vector<Vector3> get_emission_points() const; Vector<Vector3> get_emission_normals() const; Vector<Color> get_emission_colors() const; - int get_emission_point_count() const; Vector3 get_emission_ring_axis() const; real_t get_emission_ring_height() const; real_t get_emission_ring_radius() const; diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index 32a62d8c7e..ea6242b669 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -562,6 +562,7 @@ void GPUParticles3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_transform_align"), &GPUParticles3D::get_transform_align); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); + ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false. ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles3D"), "set_sub_emitter", "get_sub_emitter"); ADD_GROUP("Time", ""); diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index c2d5c757db..1bc7d20c19 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -192,7 +192,7 @@ Vector3 NavigationAgent3D::get_target_location() const { Vector3 NavigationAgent3D::get_next_location() { update_navigation(); if (navigation_path.size() == 0) { - ERR_FAIL_COND_V(agent_parent == nullptr, Vector3()); + ERR_FAIL_COND_V_MSG(agent_parent == nullptr, Vector3(), "The agent has no parent."); return agent_parent->get_global_transform().origin; } else { return navigation_path[nav_path_index] - Vector3(0, navigation_height_offset, 0); @@ -200,7 +200,7 @@ Vector3 NavigationAgent3D::get_next_location() { } real_t NavigationAgent3D::distance_to_target() const { - ERR_FAIL_COND_V(agent_parent == nullptr, 0.0); + ERR_FAIL_COND_V_MSG(agent_parent == nullptr, 0.0, "The agent has no parent."); return agent_parent->get_global_transform().origin.distance_to(target_location); } diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 8a51a259f7..473368cf69 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -162,7 +162,7 @@ void _bake_navigation_mesh(void *p_user_data) { } void NavigationRegion3D::bake_navigation_mesh() { - ERR_FAIL_COND(bake_thread.is_started()); + ERR_FAIL_COND_MSG(bake_thread.is_started(), "Unable to start another bake request. The navigation mesh bake thread is already baking a navigation mesh."); BakeThreadsArgs *args = memnew(BakeThreadsArgs); args->nav_region = this; diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index c96204cf60..5293dd3f0a 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -484,14 +484,14 @@ void Node3D::_update_gizmos() { #endif } -#ifdef TOOLS_ENABLED void Node3D::set_disable_gizmos(bool p_enabled) { +#ifdef TOOLS_ENABLED data.gizmos_disabled = p_enabled; if (!p_enabled) { clear_gizmos(); } -} #endif +} void Node3D::set_disable_scale(bool p_enabled) { data.disable_scale = p_enabled; diff --git a/scene/3d/soft_dynamic_body_3d.cpp b/scene/3d/soft_dynamic_body_3d.cpp index 9fceb21790..903eedb58b 100644 --- a/scene/3d/soft_dynamic_body_3d.cpp +++ b/scene/3d/soft_dynamic_body_3d.cpp @@ -250,7 +250,7 @@ void SoftDynamicBody3D::_notification(int p_what) { RID space = get_world_3d()->get_space(); PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, space); - prepare_physics_server(); + _prepare_physics_server(); } break; case NOTIFICATION_READY: { @@ -284,13 +284,13 @@ void SoftDynamicBody3D::_notification(int p_what) { case NOTIFICATION_DISABLED: { if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) { - prepare_physics_server(); + _prepare_physics_server(); } } break; case NOTIFICATION_ENABLED: { if (is_inside_tree() && (disable_mode == DISABLE_MODE_REMOVE)) { - prepare_physics_server(); + _prepare_physics_server(); } } break; @@ -378,7 +378,7 @@ void SoftDynamicBody3D::_bind_methods() { TypedArray<String> SoftDynamicBody3D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); - if (get_mesh().is_null()) { + if (mesh.is_null()) { warnings.push_back(TTR("This body will be ignored until you set a mesh.")); } @@ -407,11 +407,17 @@ void SoftDynamicBody3D::_update_physics_server() { } void SoftDynamicBody3D::_draw_soft_mesh() { - if (get_mesh().is_null()) { + if (mesh.is_null()) { return; } - const RID mesh_rid = get_mesh()->get_rid(); + RID mesh_rid = mesh->get_rid(); + if (owned_mesh != mesh_rid) { + _become_mesh_owner(); + mesh_rid = mesh->get_rid(); + PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh_rid); + } + if (!rendering_server_handler.is_ready(mesh_rid)) { rendering_server_handler.prepare(mesh_rid, 0); @@ -430,11 +436,11 @@ void SoftDynamicBody3D::_draw_soft_mesh() { rendering_server_handler.commit_changes(); } -void SoftDynamicBody3D::prepare_physics_server() { +void SoftDynamicBody3D::_prepare_physics_server() { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { - if (get_mesh().is_valid()) { - PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()->get_rid()); + if (mesh.is_valid()) { + PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh->get_rid()); } else { PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, RID()); } @@ -443,9 +449,13 @@ void SoftDynamicBody3D::prepare_physics_server() { } #endif - if (get_mesh().is_valid() && (is_enabled() || (disable_mode != DISABLE_MODE_REMOVE))) { - become_mesh_owner(); - PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()->get_rid()); + if (mesh.is_valid() && (is_enabled() || (disable_mode != DISABLE_MODE_REMOVE))) { + RID mesh_rid = mesh->get_rid(); + if (owned_mesh != mesh_rid) { + _become_mesh_owner(); + mesh_rid = mesh->get_rid(); + } + PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh_rid); RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftDynamicBody3D::_draw_soft_mesh)); } else { PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, RID()); @@ -455,38 +465,32 @@ void SoftDynamicBody3D::prepare_physics_server() { } } -void SoftDynamicBody3D::become_mesh_owner() { - if (mesh.is_null()) { - return; - } +void SoftDynamicBody3D::_become_mesh_owner() { + Vector<Ref<Material>> copy_materials; + copy_materials.append_array(surface_override_materials); - if (!mesh_owner) { - mesh_owner = true; + ERR_FAIL_COND(!mesh->get_surface_count()); - Vector<Ref<Material>> copy_materials; - copy_materials.append_array(surface_override_materials); + // Get current mesh array and create new mesh array with necessary flag for SoftDynamicBody + Array surface_arrays = mesh->surface_get_arrays(0); + Array surface_blend_arrays = mesh->surface_get_blend_shape_arrays(0); + Dictionary surface_lods = mesh->surface_get_lods(0); + uint32_t surface_format = mesh->surface_get_format(0); - ERR_FAIL_COND(!mesh->get_surface_count()); + surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE; - // Get current mesh array and create new mesh array with necessary flag for SoftDynamicBody - Array surface_arrays = mesh->surface_get_arrays(0); - Array surface_blend_arrays = mesh->surface_get_blend_shape_arrays(0); - Dictionary surface_lods = mesh->surface_get_lods(0); - uint32_t surface_format = mesh->surface_get_format(0); + Ref<ArrayMesh> soft_mesh; + soft_mesh.instantiate(); + soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_lods, surface_format); + soft_mesh->surface_set_material(0, mesh->surface_get_material(0)); - surface_format |= Mesh::ARRAY_FLAG_USE_DYNAMIC_UPDATE; + set_mesh(soft_mesh); - Ref<ArrayMesh> soft_mesh; - soft_mesh.instantiate(); - soft_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, surface_arrays, surface_blend_arrays, surface_lods, surface_format); - soft_mesh->surface_set_material(0, mesh->surface_get_material(0)); - - set_mesh(soft_mesh); - - for (int i = copy_materials.size() - 1; 0 <= i; --i) { - set_surface_override_material(i, copy_materials[i]); - } + for (int i = copy_materials.size() - 1; 0 <= i; --i) { + set_surface_override_material(i, copy_materials[i]); } + + owned_mesh = soft_mesh->get_rid(); } void SoftDynamicBody3D::set_collision_mask(uint32_t p_mask) { @@ -548,16 +552,10 @@ void SoftDynamicBody3D::set_disable_mode(DisableMode p_mode) { return; } - bool inside_tree = is_inside_tree(); - - if (inside_tree && (disable_mode == DISABLE_MODE_REMOVE)) { - prepare_physics_server(); - } - disable_mode = p_mode; - if (inside_tree && (disable_mode == DISABLE_MODE_REMOVE)) { - prepare_physics_server(); + if (mesh.is_valid() && is_inside_tree() && !is_enabled()) { + _prepare_physics_server(); } } diff --git a/scene/3d/soft_dynamic_body_3d.h b/scene/3d/soft_dynamic_body_3d.h index 5e7fbfe29e..57e116aa05 100644 --- a/scene/3d/soft_dynamic_body_3d.h +++ b/scene/3d/soft_dynamic_body_3d.h @@ -90,7 +90,7 @@ private: DisableMode disable_mode = DISABLE_MODE_REMOVE; - bool mesh_owner = false; + RID owned_mesh; uint32_t collision_mask = 1; uint32_t collision_layer = 1; NodePath parent_collision_ignore; @@ -106,6 +106,12 @@ private: void _update_pickable(); + void _update_physics_server(); + void _draw_soft_mesh(); + + void _prepare_physics_server(); + void _become_mesh_owner(); + protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; @@ -120,14 +126,7 @@ protected: TypedArray<String> get_configuration_warnings() const override; -protected: - void _update_physics_server(); - void _draw_soft_mesh(); - public: - void prepare_physics_server(); - void become_mesh_owner(); - RID get_physics_rid() const { return physics_rid; } void set_collision_mask(uint32_t p_mask); diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 90c2a309e1..61448c0e32 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -118,12 +118,6 @@ public: void set_flip_v(bool p_flip); bool is_flipped_v() const; - void set_region_enabled(bool p_region); - bool is_region_enabled() const; - - void set_region_rect(const Rect2 &p_region_rect); - Rect2 get_region_rect() const; - void set_modulate(const Color &p_color); Color get_modulate() const; diff --git a/scene/3d/xr_nodes.cpp b/scene/3d/xr_nodes.cpp index 56edf100f6..9dbee58f0e 100644 --- a/scene/3d/xr_nodes.cpp +++ b/scene/3d/xr_nodes.cpp @@ -47,13 +47,45 @@ void XRCamera3D::_notification(int p_what) { case NOTIFICATION_EXIT_TREE: { // need to find our XROrigin3D parent and let it know we're no longer its camera! XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent()); - if (origin != nullptr) { - origin->clear_tracked_camera_if(this); + if (origin != nullptr && origin->get_tracked_camera() == this) { + origin->set_tracked_camera(nullptr); } }; break; }; }; +void XRCamera3D::_changed_tracker(const StringName p_tracker_name, int p_tracker_type) { + if (p_tracker_name == tracker_name) { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); + + tracker = xr_server->get_tracker(p_tracker_name); + if (tracker.is_valid()) { + tracker->connect("pose_changed", callable_mp(this, &XRCamera3D::_pose_changed)); + + Ref<XRPose> pose = tracker->get_pose(pose_name); + if (pose.is_valid()) { + set_transform(pose->get_adjusted_transform()); + } + } + } +} + +void XRCamera3D::_removed_tracker(const StringName p_tracker_name, int p_tracker_type) { + if (p_tracker_name == tracker_name) { + if (tracker.is_valid()) { + tracker->disconnect("pose_changed", callable_mp(this, &XRCamera3D::_pose_changed)); + } + tracker.unref(); + } +} + +void XRCamera3D::_pose_changed(const Ref<XRPose> &p_pose) { + if (p_pose->get_name() == pose_name) { + set_transform(p_pose->get_adjusted_transform()); + } +} + TypedArray<String> XRCamera3D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); @@ -172,195 +204,215 @@ Vector<Plane> XRCamera3D::get_frustum() const { return cm.get_projection_planes(get_camera_transform()); }; -//////////////////////////////////////////////////////////////////////////////////////////////////// +XRCamera3D::XRCamera3D() { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); -void XRController3D::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - set_process_internal(true); - }; break; - case NOTIFICATION_EXIT_TREE: { - set_process_internal(false); - }; break; - case NOTIFICATION_INTERNAL_PROCESS: { - // get our XRServer - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL(xr_server); - - // find the tracker for our controller - Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); - if (!tracker.is_valid()) { - // this controller is currently turned off - is_active = false; - button_states = 0; - } else { - is_active = true; - set_transform(tracker->get_transform(true)); - - int joy_id = tracker->get_joy_id(); - if (joy_id >= 0) { - int mask = 1; - // check button states - for (int i = 0; i < 16; i++) { - bool was_pressed = (button_states & mask) == mask; - bool is_pressed = Input::get_singleton()->is_joy_button_pressed(joy_id, (JoyButton)i); - - if (!was_pressed && is_pressed) { - emit_signal(SNAME("button_pressed"), i); - button_states += mask; - } else if (was_pressed && !is_pressed) { - emit_signal(SNAME("button_released"), i); - button_states -= mask; - }; - - mask = mask << 1; - }; - - } else { - button_states = 0; - }; - - // check for an updated mesh - Ref<Mesh> trackerMesh = tracker->get_mesh(); - if (mesh != trackerMesh) { - mesh = trackerMesh; - emit_signal(SNAME("mesh_updated"), mesh); - } - }; - }; break; - default: - break; - }; -}; + xr_server->connect("tracker_added", callable_mp(this, &XRCamera3D::_changed_tracker)); + xr_server->connect("tracker_updated", callable_mp(this, &XRCamera3D::_changed_tracker)); + xr_server->connect("tracker_removed", callable_mp(this, &XRCamera3D::_removed_tracker)); +} -void XRController3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_controller_id", "controller_id"), &XRController3D::set_controller_id); - ClassDB::bind_method(D_METHOD("get_controller_id"), &XRController3D::get_controller_id); - ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_id", PROPERTY_HINT_RANGE, "0,32,1"), "set_controller_id", "get_controller_id"); - ClassDB::bind_method(D_METHOD("get_controller_name"), &XRController3D::get_controller_name); +XRCamera3D::~XRCamera3D() { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); - // passthroughs to information about our related joystick - ClassDB::bind_method(D_METHOD("get_joystick_id"), &XRController3D::get_joystick_id); - ClassDB::bind_method(D_METHOD("is_button_pressed", "button"), &XRController3D::is_button_pressed); - ClassDB::bind_method(D_METHOD("get_joystick_axis", "axis"), &XRController3D::get_joystick_axis); + xr_server->disconnect("tracker_added", callable_mp(this, &XRCamera3D::_changed_tracker)); + xr_server->disconnect("tracker_updated", callable_mp(this, &XRCamera3D::_changed_tracker)); + xr_server->disconnect("tracker_removed", callable_mp(this, &XRCamera3D::_removed_tracker)); +} - ClassDB::bind_method(D_METHOD("get_is_active"), &XRController3D::get_is_active); - ClassDB::bind_method(D_METHOD("get_tracker_hand"), &XRController3D::get_tracker_hand); +//////////////////////////////////////////////////////////////////////////////////////////////////// +// XRNode3D is a node that has it's transform updated by an XRPositionalTracker. +// Note that trackers are only available in runtime and only after an XRInterface registers one. +// So we bind by name and as long as a tracker isn't available, our node remains inactive. - ClassDB::bind_method(D_METHOD("get_rumble"), &XRController3D::get_rumble); - ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &XRController3D::set_rumble); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rumble", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_rumble", "get_rumble"); - ADD_PROPERTY_DEFAULT("rumble", 0.0); +void XRNode3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_tracker", "tracker_name"), &XRNode3D::set_tracker); + ClassDB::bind_method(D_METHOD("get_tracker"), &XRNode3D::get_tracker); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "tracker", PROPERTY_HINT_ENUM_SUGGESTION), "set_tracker", "get_tracker"); - ClassDB::bind_method(D_METHOD("get_mesh"), &XRController3D::get_mesh); + ClassDB::bind_method(D_METHOD("set_pose_name", "pose"), &XRNode3D::set_pose_name); + ClassDB::bind_method(D_METHOD("get_pose_name"), &XRNode3D::get_pose_name); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "pose", PROPERTY_HINT_ENUM_SUGGESTION), "set_pose_name", "get_pose_name"); - ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::INT, "button"))); - ADD_SIGNAL(MethodInfo("button_released", PropertyInfo(Variant::INT, "button"))); - ADD_SIGNAL(MethodInfo("mesh_updated", PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"))); + ClassDB::bind_method(D_METHOD("get_is_active"), &XRNode3D::get_is_active); + ClassDB::bind_method(D_METHOD("get_has_tracking_data"), &XRNode3D::get_has_tracking_data); + ClassDB::bind_method(D_METHOD("get_pose"), &XRNode3D::get_pose); + ClassDB::bind_method(D_METHOD("trigger_haptic_pulse", "action_name", "frequency", "amplitude", "duration_sec", "delay_sec"), &XRNode3D::trigger_haptic_pulse); }; -void XRController3D::set_controller_id(int p_controller_id) { - // We don't check any bounds here, this controller may not yet be active and just be a place holder until it is. - // Note that setting this to 0 means this node is not bound to a controller yet. - controller_id = p_controller_id; - update_configuration_warnings(); -}; +void XRNode3D::_validate_property(PropertyInfo &property) const { + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); -int XRController3D::get_controller_id() const { - return controller_id; -}; + if (property.name == "tracker") { + PackedStringArray names = xr_server->get_suggested_tracker_names(); + String hint_string; + for (const String &name : names) { + hint_string += name + ","; + } + property.hint_string = hint_string; + } else if (property.name == "pose") { + PackedStringArray names = xr_server->get_suggested_pose_names(tracker_name); + String hint_string; + for (const String &name : names) { + hint_string += name + ","; + } + property.hint_string = hint_string; + } +} -String XRController3D::get_controller_name() const { - // get our XRServer - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL_V(xr_server, String()); +void XRNode3D::set_tracker(const StringName p_tracker_name) { + if (tracker.is_valid() && tracker->get_tracker_name() == p_tracker_name) { + // didn't change + return; + } - Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); - if (!tracker.is_valid()) { - return String("Not connected"); - }; + // just in case + _unbind_tracker(); - return tracker->get_tracker_name(); -}; + // copy the name + tracker_name = p_tracker_name; + pose_name = "default"; -int XRController3D::get_joystick_id() const { - // get our XRServer - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL_V(xr_server, 0); + // see if it's already available + _bind_tracker(); - Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); - if (!tracker.is_valid()) { - // No tracker? no joystick id... (0 is our first joystick) - return -1; - }; + update_configuration_warnings(); + notify_property_list_changed(); +} - return tracker->get_joy_id(); -}; +StringName XRNode3D::get_tracker() const { + return tracker_name; +} -bool XRController3D::is_button_pressed(int p_button) const { - int joy_id = get_joystick_id(); - if (joy_id == -1) { - return false; - }; +void XRNode3D::set_pose_name(const StringName p_pose_name) { + pose_name = p_pose_name; - return Input::get_singleton()->is_joy_button_pressed(joy_id, (JoyButton)p_button); -}; + // Update pose if we are bound to a tracker with a valid pose + Ref<XRPose> pose = get_pose(); + if (pose.is_valid()) { + set_transform(pose->get_adjusted_transform()); + } +} -float XRController3D::get_joystick_axis(int p_axis) const { - int joy_id = get_joystick_id(); - if (joy_id == -1) { - return 0.0; - }; +StringName XRNode3D::get_pose_name() const { + return pose_name; +} - return Input::get_singleton()->get_joy_axis(joy_id, (JoyAxis)p_axis); -}; +bool XRNode3D::get_is_active() const { + if (tracker.is_null()) { + return false; + } else if (!tracker->has_pose(pose_name)) { + return false; + } else { + return true; + } +} -real_t XRController3D::get_rumble() const { - // get our XRServer +bool XRNode3D::get_has_tracking_data() const { + if (tracker.is_null()) { + return false; + } else if (!tracker->has_pose(pose_name)) { + return false; + } else { + return tracker->get_pose(pose_name)->get_has_tracking_data(); + } +} + +void XRNode3D::trigger_haptic_pulse(const String &p_action_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec) { + // TODO need to link trackers to the interface that registered them so we can call this on the correct interface. + // For now this works fine as in 99% of the cases we only have our primary interface active XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL_V(xr_server, 0.0); + if (xr_server != nullptr) { + Ref<XRInterface> xr_interface = xr_server->get_primary_interface(); + if (xr_interface.is_valid()) { + xr_interface->trigger_haptic_pulse(p_action_name, tracker_name, p_frequency, p_amplitude, p_duration_sec, p_delay_sec); + } + } +} - Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); - if (!tracker.is_valid()) { - return 0.0; - }; +Ref<XRPose> XRNode3D::get_pose() { + if (tracker.is_valid()) { + return tracker->get_pose(pose_name); + } else { + return Ref<XRPose>(); + } +} - return tracker->get_rumble(); -}; +void XRNode3D::_bind_tracker() { + ERR_FAIL_COND_MSG(tracker.is_valid(), "Unbind the current tracker first"); -void XRController3D::set_rumble(real_t p_rumble) { - // get our XRServer XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL(xr_server); + if (xr_server != nullptr) { + tracker = xr_server->get_tracker(tracker_name); + if (tracker.is_null()) { + // It is possible and valid if the tracker isn't available (yet), in this case we just exit + return; + } + + tracker->connect("pose_changed", callable_mp(this, &XRNode3D::_pose_changed)); + + Ref<XRPose> pose = get_pose(); + if (pose.is_valid()) { + set_transform(pose->get_adjusted_transform()); + } + } +} - Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); +void XRNode3D::_unbind_tracker() { if (tracker.is_valid()) { - tracker->set_rumble(p_rumble); - }; -}; + tracker->disconnect("pose_changed", callable_mp(this, &XRNode3D::_pose_changed)); -Ref<Mesh> XRController3D::get_mesh() const { - return mesh; + tracker.unref(); + } } -bool XRController3D::get_is_active() const { - return is_active; -}; +void XRNode3D::_changed_tracker(const StringName p_tracker_name, int p_tracker_type) { + if (p_tracker_name == p_tracker_name) { + // just in case unref our current tracker + _unbind_tracker(); -XRPositionalTracker::TrackerHand XRController3D::get_tracker_hand() const { - // get our XRServer + // get our new tracker + _bind_tracker(); + } +} + +void XRNode3D::_removed_tracker(const StringName p_tracker_name, int p_tracker_type) { + if (p_tracker_name == p_tracker_name) { + // unref our tracker, it's no longer available + _unbind_tracker(); + } +} + +void XRNode3D::_pose_changed(const Ref<XRPose> &p_pose) { + if (p_pose.is_valid() && p_pose->get_name() == pose_name) { + set_transform(p_pose->get_adjusted_transform()); + } +} + +XRNode3D::XRNode3D() { XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL_V(xr_server, XRPositionalTracker::TRACKER_HAND_UNKNOWN); + ERR_FAIL_NULL(xr_server); - Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_CONTROLLER, controller_id); - if (!tracker.is_valid()) { - return XRPositionalTracker::TRACKER_HAND_UNKNOWN; - }; + xr_server->connect("tracker_added", callable_mp(this, &XRNode3D::_changed_tracker)); + xr_server->connect("tracker_updated", callable_mp(this, &XRNode3D::_changed_tracker)); + xr_server->connect("tracker_removed", callable_mp(this, &XRNode3D::_removed_tracker)); +} - return tracker->get_tracker_hand(); -}; +XRNode3D::~XRNode3D() { + _unbind_tracker(); + + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL(xr_server); + + xr_server->disconnect("tracker_added", callable_mp(this, &XRNode3D::_changed_tracker)); + xr_server->disconnect("tracker_updated", callable_mp(this, &XRNode3D::_changed_tracker)); + xr_server->disconnect("tracker_removed", callable_mp(this, &XRNode3D::_removed_tracker)); +} -TypedArray<String> XRController3D::get_configuration_warnings() const { +TypedArray<String> XRNode3D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (is_visible() && is_inside_tree()) { @@ -370,130 +422,171 @@ TypedArray<String> XRController3D::get_configuration_warnings() const { warnings.push_back(TTR("XRController3D must have an XROrigin3D node as its parent.")); } - if (controller_id == 0) { - warnings.push_back(TTR("The controller ID must not be 0 or this controller won't be bound to an actual controller.")); + if (tracker_name == "") { + warnings.push_back(TTR("No tracker name is set.")); + } + + if (pose_name == "") { + warnings.push_back(TTR("No pose is set.")); } } return warnings; -}; +} //////////////////////////////////////////////////////////////////////////////////////////////////// -void XRAnchor3D::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - set_process_internal(true); - }; break; - case NOTIFICATION_EXIT_TREE: { - set_process_internal(false); - }; break; - case NOTIFICATION_INTERNAL_PROCESS: { - // get our XRServer - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL(xr_server); - - // find the tracker for our anchor - Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_ANCHOR, anchor_id); - if (!tracker.is_valid()) { - // this anchor is currently not available - is_active = false; - } else { - is_active = true; - Transform3D transform; - - // we'll need our world_scale - real_t world_scale = xr_server->get_world_scale(); - - // get our info from our tracker - transform.basis = tracker->get_orientation(); - transform.origin = tracker->get_position(); // <-- already adjusted to world scale - - // our basis is scaled to the size of the plane the anchor is tracking - // extract the size from our basis and reset the scale - size = transform.basis.get_scale() * world_scale; - transform.basis.orthonormalize(); - - // apply our reference frame and set our transform - set_transform(xr_server->get_reference_frame() * transform); - - // check for an updated mesh - Ref<Mesh> trackerMesh = tracker->get_mesh(); - if (mesh != trackerMesh) { - mesh = trackerMesh; - emit_signal(SNAME("mesh_updated"), mesh); - } - }; - }; break; - default: - break; - }; -}; - -void XRAnchor3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_anchor_id", "anchor_id"), &XRAnchor3D::set_anchor_id); - ClassDB::bind_method(D_METHOD("get_anchor_id"), &XRAnchor3D::get_anchor_id); - ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_id", PROPERTY_HINT_RANGE, "0,32,1"), "set_anchor_id", "get_anchor_id"); - ClassDB::bind_method(D_METHOD("get_anchor_name"), &XRAnchor3D::get_anchor_name); +void XRController3D::_bind_methods() { + // passthroughs to information about our related joystick + ClassDB::bind_method(D_METHOD("is_button_pressed", "name"), &XRController3D::is_button_pressed); + ClassDB::bind_method(D_METHOD("get_value", "name"), &XRController3D::get_value); + ClassDB::bind_method(D_METHOD("get_axis", "name"), &XRController3D::get_axis); - ClassDB::bind_method(D_METHOD("get_is_active"), &XRAnchor3D::get_is_active); - ClassDB::bind_method(D_METHOD("get_size"), &XRAnchor3D::get_size); + ClassDB::bind_method(D_METHOD("get_tracker_hand"), &XRController3D::get_tracker_hand); - ClassDB::bind_method(D_METHOD("get_plane"), &XRAnchor3D::get_plane); + ClassDB::bind_method(D_METHOD("get_rumble"), &XRController3D::get_rumble); + ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &XRController3D::set_rumble); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rumble", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_rumble", "get_rumble"); + ADD_PROPERTY_DEFAULT("rumble", 0.0); - ClassDB::bind_method(D_METHOD("get_mesh"), &XRAnchor3D::get_mesh); - ADD_SIGNAL(MethodInfo("mesh_updated", PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"))); + ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::STRING, "name"))); + ADD_SIGNAL(MethodInfo("button_released", PropertyInfo(Variant::STRING, "name"))); + ADD_SIGNAL(MethodInfo("input_value_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value"))); + ADD_SIGNAL(MethodInfo("input_axis_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "value"))); }; -void XRAnchor3D::set_anchor_id(int p_anchor_id) { - // We don't check any bounds here, this anchor may not yet be active and just be a place holder until it is. - // Note that setting this to 0 means this node is not bound to an anchor yet. - anchor_id = p_anchor_id; - update_configuration_warnings(); -}; +void XRController3D::_bind_tracker() { + XRNode3D::_bind_tracker(); + if (tracker.is_valid()) { + // bind to input signals + tracker->connect("button_pressed", callable_mp(this, &XRController3D::_button_pressed)); + tracker->connect("button_released", callable_mp(this, &XRController3D::_button_released)); + tracker->connect("input_value_changed", callable_mp(this, &XRController3D::_input_value_changed)); + tracker->connect("input_axis_changed", callable_mp(this, &XRController3D::_input_axis_changed)); + } +} -int XRAnchor3D::get_anchor_id() const { - return anchor_id; -}; +void XRController3D::_unbind_tracker() { + if (tracker.is_valid()) { + // unbind input signals + tracker->disconnect("button_pressed", callable_mp(this, &XRController3D::_button_pressed)); + tracker->disconnect("button_released", callable_mp(this, &XRController3D::_button_released)); + tracker->disconnect("input_value_changed", callable_mp(this, &XRController3D::_input_value_changed)); + tracker->disconnect("input_axis_changed", callable_mp(this, &XRController3D::_input_axis_changed)); + } -Vector3 XRAnchor3D::get_size() const { - return size; -}; + XRNode3D::_unbind_tracker(); +} -String XRAnchor3D::get_anchor_name() const { - // get our XRServer - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL_V(xr_server, String()); +void XRController3D::_button_pressed(const String &p_name) { + // just pass it on... + emit_signal("button_pressed", p_name); +} - Ref<XRPositionalTracker> tracker = xr_server->find_by_type_and_id(XRServer::TRACKER_ANCHOR, anchor_id); - if (!tracker.is_valid()) { - return String("Not connected"); - }; +void XRController3D::_button_released(const String &p_name) { + // just pass it on... + emit_signal("button_released", p_name); +} - return tracker->get_tracker_name(); -}; +void XRController3D::_input_value_changed(const String &p_name, float p_value) { + // just pass it on... + emit_signal("input_value_changed", p_name, p_value); +} -bool XRAnchor3D::get_is_active() const { - return is_active; -}; +void XRController3D::_input_axis_changed(const String &p_name, Vector2 p_value) { + // just pass it on... + emit_signal("input_axis_changed", p_name, p_value); +} -TypedArray<String> XRAnchor3D::get_configuration_warnings() const { - TypedArray<String> warnings = Node::get_configuration_warnings(); +bool XRController3D::is_button_pressed(const StringName &p_name) const { + if (tracker.is_valid()) { + // Inputs should already be of the correct type, our XR runtime handles conversions between raw input and the desired type + bool pressed = tracker->get_input(p_name); + return pressed; + } else { + return false; + } +} - if (is_visible() && is_inside_tree()) { - // must be child node of XROrigin3D! - XROrigin3D *origin = Object::cast_to<XROrigin3D>(get_parent()); - if (origin == nullptr) { - warnings.push_back(TTR("XRAnchor3D must have an XROrigin3D node as its parent.")); - } +float XRController3D::get_value(const StringName &p_name) const { + if (tracker.is_valid()) { + // Inputs should already be of the correct type, our XR runtime handles conversions between raw input and the desired type, but just in case we convert + Variant input = tracker->get_input(p_name); + switch (input.get_type()) { + case Variant::BOOL: { + bool value = input; + return value ? 1.0 : 0.0; + } break; + case Variant::FLOAT: { + float value = input; + return value; + } break; + default: + return 0.0; + }; + } else { + return 0.0; + } +} - if (anchor_id == 0) { - warnings.push_back(TTR("The anchor ID must not be 0 or this anchor won't be bound to an actual anchor.")); +Vector2 XRController3D::get_axis(const StringName &p_name) const { + if (tracker.is_valid()) { + // Inputs should already be of the correct type, our XR runtime handles conversions between raw input and the desired type, but just in case we convert + Variant input = tracker->get_input(p_name); + switch (input.get_type()) { + case Variant::BOOL: { + bool value = input; + return Vector2(value ? 1.0 : 0.0, 0.0); + } break; + case Variant::FLOAT: { + float value = input; + return Vector2(value, 0.0); + } break; + case Variant::VECTOR2: { + Vector2 axis = input; + return axis; + } + default: + return Vector2(); } + } else { + return Vector2(); } +} - return warnings; -}; +real_t XRController3D::get_rumble() const { + if (!tracker.is_valid()) { + return 0.0; + } + + return tracker->get_rumble(); +} + +void XRController3D::set_rumble(real_t p_rumble) { + if (tracker.is_valid()) { + tracker->set_rumble(p_rumble); + } +} + +XRPositionalTracker::TrackerHand XRController3D::get_tracker_hand() const { + // get our XRServer + if (!tracker.is_valid()) { + return XRPositionalTracker::TRACKER_HAND_UNKNOWN; + } + + return tracker->get_tracker_hand(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void XRAnchor3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_size"), &XRAnchor3D::get_size); + ClassDB::bind_method(D_METHOD("get_plane"), &XRAnchor3D::get_plane); +} + +Vector3 XRAnchor3D::get_size() const { + return size; +} Plane XRAnchor3D::get_plane() const { Vector3 location = get_position(); @@ -502,10 +595,6 @@ Plane XRAnchor3D::get_plane() const { Plane plane(orientation.get_axis(1).normalized(), location); return plane; -}; - -Ref<Mesh> XRAnchor3D::get_mesh() const { - return mesh; } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -525,23 +614,21 @@ TypedArray<String> XROrigin3D::get_configuration_warnings() const { } return warnings; -}; +} void XROrigin3D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_world_scale", "world_scale"), &XROrigin3D::set_world_scale); ClassDB::bind_method(D_METHOD("get_world_scale"), &XROrigin3D::get_world_scale); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "world_scale"), "set_world_scale", "get_world_scale"); -}; +} void XROrigin3D::set_tracked_camera(XRCamera3D *p_tracked_camera) { tracked_camera = p_tracked_camera; -}; +} -void XROrigin3D::clear_tracked_camera_if(XRCamera3D *p_tracked_camera) { - if (tracked_camera == p_tracked_camera) { - tracked_camera = nullptr; - }; -}; +XRCamera3D *XROrigin3D::get_tracked_camera() const { + return tracked_camera; +} real_t XROrigin3D::get_world_scale() const { // get our XRServer @@ -549,7 +636,7 @@ real_t XROrigin3D::get_world_scale() const { ERR_FAIL_NULL_V(xr_server, 1.0); return xr_server->get_world_scale(); -}; +} void XROrigin3D::set_world_scale(real_t p_world_scale) { // get our XRServer @@ -557,7 +644,7 @@ void XROrigin3D::set_world_scale(real_t p_world_scale) { ERR_FAIL_NULL(xr_server); xr_server->set_world_scale(p_world_scale); -}; +} void XROrigin3D::_notification(int p_what) { // get our XRServer @@ -596,4 +683,4 @@ void XROrigin3D::_notification(int p_what) { interface->notification(p_what); } } -}; +} diff --git a/scene/3d/xr_nodes.h b/scene/3d/xr_nodes.h index 6e54ff83d7..5e7d06093d 100644 --- a/scene/3d/xr_nodes.h +++ b/scene/3d/xr_nodes.h @@ -45,8 +45,18 @@ class XRCamera3D : public Camera3D { GDCLASS(XRCamera3D, Camera3D); protected: + // The name and pose for our HMD tracker is currently the only hardcoded bit. + // If we ever are able to support multiple HMDs we may need to make this settable. + StringName tracker_name = "head"; + StringName pose_name = "default"; + Ref<XRPositionalTracker> tracker; + void _notification(int p_what); + void _changed_tracker(const StringName p_tracker_name, int p_tracker_type); + void _removed_tracker(const StringName p_tracker_name, int p_tracker_type); + void _pose_changed(const Ref<XRPose> &p_pose); + public: TypedArray<String> get_configuration_warnings() const override; @@ -55,48 +65,88 @@ public: virtual Vector3 project_position(const Point2 &p_point, real_t p_z_depth) const override; virtual Vector<Plane> get_frustum() const override; - XRCamera3D() {} - ~XRCamera3D() {} + XRCamera3D(); + ~XRCamera3D(); }; /* - XRController3D is a helper node that automatically updates its position based on tracker data. + XRNode3D is a helper node that implements binding to a tracker. It must be a child node of our XROrigin node */ -class XRController3D : public Node3D { - GDCLASS(XRController3D, Node3D); +class XRNode3D : public Node3D { + GDCLASS(XRNode3D, Node3D); private: - int controller_id = 1; + StringName tracker_name; + StringName pose_name = "default"; bool is_active = true; - int button_states = 0; - Ref<Mesh> mesh; protected: - void _notification(int p_what); + Ref<XRPositionalTracker> tracker; + static void _bind_methods(); -public: - void set_controller_id(int p_controller_id); - int get_controller_id() const; - String get_controller_name() const; + virtual void _bind_tracker(); + virtual void _unbind_tracker(); + void _changed_tracker(const StringName p_tracker_name, int p_tracker_type); + void _removed_tracker(const StringName p_tracker_name, int p_tracker_type); - int get_joystick_id() const; - bool is_button_pressed(int p_button) const; - float get_joystick_axis(int p_axis) const; + void _pose_changed(const Ref<XRPose> &p_pose); - real_t get_rumble() const; - void set_rumble(real_t p_rumble); +public: + virtual void _validate_property(PropertyInfo &property) const override; + void set_tracker(const StringName p_tracker_name); + StringName get_tracker() const; + + void set_pose_name(const StringName p_pose); + StringName get_pose_name() const; bool get_is_active() const; - XRPositionalTracker::TrackerHand get_tracker_hand() const; + bool get_has_tracking_data() const; - Ref<Mesh> get_mesh() const; + void trigger_haptic_pulse(const String &p_action_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec = 0); + + Ref<XRPose> get_pose(); TypedArray<String> get_configuration_warnings() const override; + XRNode3D(); + ~XRNode3D(); +}; + +/* + XRController3D is a helper node that automatically updates its position based on tracker data. + + It must be a child node of our XROrigin node +*/ + +class XRController3D : public XRNode3D { + GDCLASS(XRController3D, XRNode3D); + +private: +protected: + static void _bind_methods(); + + virtual void _bind_tracker() override; + virtual void _unbind_tracker() override; + + void _button_pressed(const String &p_name); + void _button_released(const String &p_name); + void _input_value_changed(const String &p_name, float p_value); + void _input_axis_changed(const String &p_name, Vector2 p_value); + +public: + bool is_button_pressed(const StringName &p_name) const; + float get_value(const StringName &p_name) const; + Vector2 get_axis(const StringName &p_name) const; + + real_t get_rumble() const; + void set_rumble(real_t p_rumble); + + XRPositionalTracker::TrackerHand get_tracker_hand() const; + XRController3D() {} ~XRController3D() {} }; @@ -106,33 +156,19 @@ public: It must be a child node of our XROrigin3D node */ -class XRAnchor3D : public Node3D { - GDCLASS(XRAnchor3D, Node3D); +class XRAnchor3D : public XRNode3D { + GDCLASS(XRAnchor3D, XRNode3D); private: - int anchor_id = 1; - bool is_active = true; Vector3 size; - Ref<Mesh> mesh; protected: - void _notification(int p_what); static void _bind_methods(); public: - void set_anchor_id(int p_anchor_id); - int get_anchor_id() const; - String get_anchor_name() const; - - bool get_is_active() const; Vector3 get_size() const; - Plane get_plane() const; - Ref<Mesh> get_mesh() const; - - TypedArray<String> get_configuration_warnings() const override; - XRAnchor3D() {} ~XRAnchor3D() {} }; @@ -159,7 +195,7 @@ public: TypedArray<String> get_configuration_warnings() const override; void set_tracked_camera(XRCamera3D *p_tracked_camera); - void clear_tracked_camera_if(XRCamera3D *p_tracked_camera); + XRCamera3D *get_tracked_camera() const; real_t get_world_scale() const; void set_world_scale(real_t p_world_scale); diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h index 21e309efe0..d9d88b5510 100644 --- a/scene/animation/animation_player.h +++ b/scene/animation/animation_player.h @@ -301,7 +301,6 @@ public: void set_current_animation(const String &p_anim); String get_assigned_animation() const; void set_assigned_animation(const String &p_anim); - void stop_all(); void set_active(bool p_active); bool is_active() const; bool is_valid() const; diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 21b49937a7..5abea39d20 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -57,8 +57,6 @@ public: Vector<Input> inputs; - real_t process_input(int p_input, real_t p_time, bool p_seek, real_t p_blend); - friend class AnimationTree; struct AnimationState { @@ -85,7 +83,6 @@ public: State *state = nullptr; real_t _pre_process(const StringName &p_base_path, AnimationNode *p_parent, State *p_state, real_t p_time, bool p_seek, const Vector<StringName> &p_connections); - void _pre_update_animations(HashMap<NodePath, int> *track_map); //all this is temporary StringName base_path; @@ -110,8 +107,6 @@ protected: void _validate_property(PropertyInfo &property) const override; - void _set_parent(Object *p_parent); - GDVIRTUAL0RC(Dictionary, _get_child_nodes) GDVIRTUAL0RC(Array, _get_parameter_list) GDVIRTUAL1RC(Ref<AnimationNode>, _get_child_by_name, StringName) @@ -265,7 +260,6 @@ private: AnimationNode::State state; bool cache_valid = false; void _node_removed(Node *p_node); - void _caches_cleared(); void _clear_caches(); bool _update_caches(AnimationPlayer *player); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 38da40a402..973074397b 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -740,7 +740,7 @@ bool Control::has_point(const Point2 &p_point) const { return Rect2(Point2(), get_size()).has_point(p_point); } -void Control::set_drag_forwarding(Node *p_target) { +void Control::set_drag_forwarding(Object *p_target) { if (p_target) { data.drag_owner = p_target->get_instance_id(); } else { diff --git a/scene/gui/control.h b/scene/gui/control.h index be692b6a0c..02ab336ef0 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -233,9 +233,6 @@ private: static constexpr unsigned properties_managed_by_container_count = 11; static String properties_managed_by_container[properties_managed_by_container_count]; - // used internally - Control *_find_control_at_pos(CanvasItem *p_node, const Point2 &p_pos, const Transform2D &p_xform, Transform2D &r_inv_xform); - void _window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, real_t p_min, real_t &r_closest_dist, Control **r_closest); Control *_get_focus_neighbor(Side p_side, int p_count = 0); @@ -250,7 +247,6 @@ private: void _update_minimum_size(); void _clear_size_warning(); - void _update_scroll(); void _compute_offsets(Rect2 p_rect, const real_t p_anchors[4], real_t (&r_offsets)[4]); void _compute_anchors(Rect2 p_rect, const real_t p_offsets[4], real_t (&r_anchors)[4]); @@ -355,7 +351,7 @@ public: virtual Size2 get_minimum_size() const; virtual Size2 get_combined_minimum_size() const; virtual bool has_point(const Point2 &p_point) const; - virtual void set_drag_forwarding(Node *p_target); + virtual void set_drag_forwarding(Object *p_target); virtual Variant get_drag_data(const Point2 &p_point); virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const; virtual void drop_data(const Point2 &p_point, const Variant &p_data); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 54e7d8f960..99c5e3bf0c 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -235,6 +235,25 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { return; } + if (is_middle_mouse_paste_enabled() && b->is_pressed() && b->get_button_index() == MOUSE_BUTTON_MIDDLE && is_editable()) { + String paste_buffer = DisplayServer::get_singleton()->clipboard_get_primary().strip_escapes(); + + deselect(); + set_caret_at_pixel_pos(b->get_position().x); + if (!paste_buffer.is_empty()) { + insert_text_at_caret(paste_buffer); + + if (!text_changed_dirty) { + if (is_inside_tree()) { + MessageQueue::get_singleton()->push_call(this, "_text_changed"); + } + text_changed_dirty = true; + } + } + grab_focus(); + return; + } + if (b->get_button_index() != MOUSE_BUTTON_LEFT) { return; } @@ -271,6 +290,9 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { selection.double_click = true; last_dblclk = 0; caret_column = selection.begin; + if (!pass) { + DisplayServer::get_singleton()->clipboard_set_primary(text); + } } else if (b->is_double_click()) { // Double-click select word. last_dblclk = OS::get_singleton()->get_ticks_msec(); @@ -286,6 +308,9 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { break; } } + if (!pass) { + DisplayServer::get_singleton()->clipboard_set_primary(text.substr(selection.begin, selection.end - selection.begin)); + } } } @@ -303,6 +328,9 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { update(); } else { + if (selection.enabled && !pass && b->get_button_index() == MOUSE_BUTTON_LEFT) { + DisplayServer::get_singleton()->clipboard_set_primary(text.substr(selection.begin, selection.end - selection.begin)); + } if (!text.is_empty() && is_editable() && clear_button_enabled) { bool press_attempt = clear_button_status.press_attempt; clear_button_status.press_attempt = false; @@ -1890,6 +1918,14 @@ bool LineEdit::is_virtual_keyboard_enabled() const { return virtual_keyboard_enabled; } +void LineEdit::set_middle_mouse_paste_enabled(bool p_enabled) { + middle_mouse_paste_enabled = p_enabled; +} + +bool LineEdit::is_middle_mouse_paste_enabled() const { + return middle_mouse_paste_enabled; +} + void LineEdit::set_selecting_enabled(bool p_enabled) { selecting_enabled = p_enabled; @@ -2156,6 +2192,8 @@ void LineEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("is_clear_button_enabled"), &LineEdit::is_clear_button_enabled); ClassDB::bind_method(D_METHOD("set_shortcut_keys_enabled", "enable"), &LineEdit::set_shortcut_keys_enabled); ClassDB::bind_method(D_METHOD("is_shortcut_keys_enabled"), &LineEdit::is_shortcut_keys_enabled); + ClassDB::bind_method(D_METHOD("set_middle_mouse_paste_enabled", "enable"), &LineEdit::set_middle_mouse_paste_enabled); + ClassDB::bind_method(D_METHOD("is_middle_mouse_paste_enabled"), &LineEdit::is_middle_mouse_paste_enabled); ClassDB::bind_method(D_METHOD("set_selecting_enabled", "enable"), &LineEdit::set_selecting_enabled); ClassDB::bind_method(D_METHOD("is_selecting_enabled"), &LineEdit::is_selecting_enabled); ClassDB::bind_method(D_METHOD("set_right_icon", "icon"), &LineEdit::set_right_icon); @@ -2211,6 +2249,7 @@ void LineEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "virtual_keyboard_enabled"), "set_virtual_keyboard_enabled", "is_virtual_keyboard_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clear_button_enabled"), "set_clear_button_enabled", "is_clear_button_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "right_icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_right_icon", "get_right_icon"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); @@ -2237,33 +2276,33 @@ void LineEdit::_ensure_menu() { menu_dir = memnew(PopupMenu); menu_dir->set_name("DirMenu"); - menu_dir->add_radio_check_item(RTR("Same as layout direction"), MENU_DIR_INHERITED); - menu_dir->add_radio_check_item(RTR("Auto-detect direction"), MENU_DIR_AUTO); - menu_dir->add_radio_check_item(RTR("Left-to-right"), MENU_DIR_LTR); - menu_dir->add_radio_check_item(RTR("Right-to-left"), MENU_DIR_RTL); - menu->add_child(menu_dir); + menu_dir->add_radio_check_item(RTR("Same as Layout Direction"), MENU_DIR_INHERITED); + menu_dir->add_radio_check_item(RTR("Auto-Detect Direction"), MENU_DIR_AUTO); + menu_dir->add_radio_check_item(RTR("Left-to-Right"), MENU_DIR_LTR); + menu_dir->add_radio_check_item(RTR("Right-to-Left"), MENU_DIR_RTL); + menu->add_child(menu_dir, false, INTERNAL_MODE_FRONT); menu_ctl = memnew(PopupMenu); menu_ctl->set_name("CTLMenu"); - menu_ctl->add_item(RTR("Left-to-right mark (LRM)"), MENU_INSERT_LRM); - menu_ctl->add_item(RTR("Right-to-left mark (RLM)"), MENU_INSERT_RLM); - menu_ctl->add_item(RTR("Start of left-to-right embedding (LRE)"), MENU_INSERT_LRE); - menu_ctl->add_item(RTR("Start of right-to-left embedding (RLE)"), MENU_INSERT_RLE); - menu_ctl->add_item(RTR("Start of left-to-right override (LRO)"), MENU_INSERT_LRO); - menu_ctl->add_item(RTR("Start of right-to-left override (RLO)"), MENU_INSERT_RLO); - menu_ctl->add_item(RTR("Pop direction formatting (PDF)"), MENU_INSERT_PDF); + menu_ctl->add_item(RTR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM); + menu_ctl->add_item(RTR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM); + menu_ctl->add_item(RTR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE); + menu_ctl->add_item(RTR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE); + menu_ctl->add_item(RTR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO); + menu_ctl->add_item(RTR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO); + menu_ctl->add_item(RTR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF); menu_ctl->add_separator(); - menu_ctl->add_item(RTR("Arabic letter mark (ALM)"), MENU_INSERT_ALM); - menu_ctl->add_item(RTR("Left-to-right isolate (LRI)"), MENU_INSERT_LRI); - menu_ctl->add_item(RTR("Right-to-left isolate (RLI)"), MENU_INSERT_RLI); - menu_ctl->add_item(RTR("First strong isolate (FSI)"), MENU_INSERT_FSI); - menu_ctl->add_item(RTR("Pop direction isolate (PDI)"), MENU_INSERT_PDI); + menu_ctl->add_item(RTR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM); + menu_ctl->add_item(RTR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI); + menu_ctl->add_item(RTR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI); + menu_ctl->add_item(RTR("First Strong Isolate (FSI)"), MENU_INSERT_FSI); + menu_ctl->add_item(RTR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI); menu_ctl->add_separator(); - menu_ctl->add_item(RTR("Zero width joiner (ZWJ)"), MENU_INSERT_ZWJ); - menu_ctl->add_item(RTR("Zero width non-joiner (ZWNJ)"), MENU_INSERT_ZWNJ); - menu_ctl->add_item(RTR("Word joiner (WJ)"), MENU_INSERT_WJ); - menu_ctl->add_item(RTR("Soft hyphen (SHY)"), MENU_INSERT_SHY); - menu->add_child(menu_ctl); + menu_ctl->add_item(RTR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ); + menu_ctl->add_item(RTR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ); + menu_ctl->add_item(RTR("Word Joiner (WJ)"), MENU_INSERT_WJ); + menu_ctl->add_item(RTR("Soft Hyphen (SHY)"), MENU_INSERT_SHY); + menu->add_child(menu_ctl, false, INTERNAL_MODE_FRONT); menu->connect("id_pressed", callable_mp(this, &LineEdit::menu_option)); menu_dir->connect("id_pressed", callable_mp(this, &LineEdit::menu_option)); @@ -2290,12 +2329,12 @@ void LineEdit::_ensure_menu() { menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0); } menu->add_separator(); - menu->add_submenu_item(RTR("Text writing direction"), "DirMenu"); + menu->add_submenu_item(RTR("Text Writing Direction"), "DirMenu"); menu->add_separator(); - menu->add_check_item(RTR("Display control characters"), MENU_DISPLAY_UCC); + menu->add_check_item(RTR("Display Control Characters"), MENU_DISPLAY_UCC); menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars); if (editable) { - menu->add_submenu_item(RTR("Insert control character"), "CTLMenu"); + menu->add_submenu_item(RTR("Insert Control Character"), "CTLMenu"); } menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED); menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 923024dd56..94179ce05b 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -126,6 +126,8 @@ private: bool virtual_keyboard_enabled = true; + bool middle_mouse_paste_enabled = true; + Ref<Texture2D> right_icon; struct Selection { @@ -187,7 +189,6 @@ private: void _toggle_draw_caret(); void clear_internal(); - void changed_internal(); void _editor_settings_changed(); @@ -318,6 +319,9 @@ public: void set_virtual_keyboard_enabled(bool p_enable); bool is_virtual_keyboard_enabled() const; + void set_middle_mouse_paste_enabled(bool p_enabled); + bool is_middle_mouse_paste_enabled() const; + void set_selecting_enabled(bool p_enabled); bool is_selecting_enabled() const; diff --git a/scene/gui/popup.h b/scene/gui/popup.h index c7090e7231..8458a75eef 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -80,7 +80,6 @@ protected: virtual Size2 _get_contents_minimum_size() const override; public: - void set_child_rect(Control *p_child); PopupPanel(); }; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 4588966d88..bc6552c208 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -486,7 +486,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> remaining_characters -= cell_ch; table->columns.write[column].min_width = MAX(table->columns[column].min_width, ceil(frame->lines[i].text_buf->get_size().x)); - table->columns.write[column].max_width = MAX(table->columns[column].max_width, ceil(frame->lines[i].text_buf->get_non_wraped_size().x)); + table->columns.write[column].max_width = MAX(table->columns[column].max_width, ceil(frame->lines[i].text_buf->get_non_wrapped_size().x)); } idx++; } @@ -1596,12 +1596,16 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) { selection.to_char = words[i + 1]; selection.active = true; + DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text()); update(); break; } } } } else if (!b->is_pressed()) { + if (selection.enabled) { + DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text()); + } selection.click_item = nullptr; if (!b->is_double_click() && !scroll_updated) { @@ -1719,6 +1723,7 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) { swap = true; } else if (selection.from_char == selection.to_char) { selection.active = false; + update(); return; } } diff --git a/scene/gui/tabs.cpp b/scene/gui/tab_bar.cpp index 0755a79eee..78b58c773a 100644 --- a/scene/gui/tabs.cpp +++ b/scene/gui/tab_bar.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* tabs.cpp */ +/* tab_bar.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "tabs.h" +#include "tab_bar.h" #include "core/object/message_queue.h" #include "core/string/translation.h" @@ -37,7 +37,7 @@ #include "scene/gui/label.h" #include "scene/gui/texture_rect.h" -Size2 Tabs::get_minimum_size() const { +Size2 TabBar::get_minimum_size() const { Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected")); Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected")); Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled")); @@ -90,7 +90,7 @@ Size2 Tabs::get_minimum_size() const { return ms; } -void Tabs::gui_input(const Ref<InputEvent> &p_event) { +void TabBar::gui_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); Ref<InputEventMouseMotion> mm = p_event; @@ -164,7 +164,7 @@ void Tabs::gui_input(const Ref<InputEvent> &p_event) { if (rb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (rb_hover != -1) { - //pressed + // pressed emit_signal(SNAME("tab_rmb_clicked"), rb_hover); } @@ -174,7 +174,7 @@ void Tabs::gui_input(const Ref<InputEvent> &p_event) { if (cb_pressing && !mb->is_pressed() && mb->get_button_index() == MOUSE_BUTTON_LEFT) { if (cb_hover != -1) { - //pressed + // pressed emit_signal(SNAME("tab_closed"), cb_hover); } @@ -222,6 +222,11 @@ void Tabs::gui_input(const Ref<InputEvent> &p_event) { } } + if (max_drawn_tab <= 0) { + // Return early if there are no actual tabs to handle input for. + return; + } + int found = -1; for (int i = offset; i <= max_drawn_tab; i++) { if (tabs[i].rb_rect.has_point(pos)) { @@ -252,7 +257,7 @@ void Tabs::gui_input(const Ref<InputEvent> &p_event) { } } -void Tabs::_shape(int p_tab) { +void TabBar::_shape(int p_tab) { Ref<Font> font = get_theme_font(SNAME("font")); int font_size = get_theme_font_size(SNAME("font_size")); @@ -268,7 +273,7 @@ void Tabs::_shape(int p_tab) { tabs.write[p_tab].text_buf->add_string(tabs.write[p_tab].xl_text, font, font_size, tabs[p_tab].opentype_features, (tabs[p_tab].language != "") ? tabs[p_tab].language : TranslationServer::get_singleton()->get_tool_locale()); } -void Tabs::_notification(int p_what) { +void TabBar::_notification(int p_what) { switch (p_what) { case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { _update_cache(); @@ -505,11 +510,11 @@ void Tabs::_notification(int p_what) { } } -int Tabs::get_tab_count() const { +int TabBar::get_tab_count() const { return tabs.size(); } -void Tabs::set_current_tab(int p_current) { +void TabBar::set_current_tab(int p_current) { if (current == p_current) { return; } @@ -524,27 +529,27 @@ void Tabs::set_current_tab(int p_current) { emit_signal(SNAME("tab_changed"), p_current); } -int Tabs::get_current_tab() const { +int TabBar::get_current_tab() const { return current; } -int Tabs::get_previous_tab() const { +int TabBar::get_previous_tab() const { return previous; } -int Tabs::get_hovered_tab() const { +int TabBar::get_hovered_tab() const { return hover; } -int Tabs::get_tab_offset() const { +int TabBar::get_tab_offset() const { return offset; } -bool Tabs::get_offset_buttons_visible() const { +bool TabBar::get_offset_buttons_visible() const { return buttons_visible; } -void Tabs::set_tab_title(int p_tab, const String &p_title) { +void TabBar::set_tab_title(int p_tab, const String &p_title) { ERR_FAIL_INDEX(p_tab, tabs.size()); tabs.write[p_tab].text = p_title; _shape(p_tab); @@ -552,12 +557,12 @@ void Tabs::set_tab_title(int p_tab, const String &p_title) { minimum_size_changed(); } -String Tabs::get_tab_title(int p_tab) const { +String TabBar::get_tab_title(int p_tab) const { ERR_FAIL_INDEX_V(p_tab, tabs.size(), ""); return tabs[p_tab].text; } -void Tabs::set_tab_text_direction(int p_tab, Control::TextDirection p_text_direction) { +void TabBar::set_tab_text_direction(int p_tab, Control::TextDirection p_text_direction) { ERR_FAIL_INDEX(p_tab, tabs.size()); ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3); if (tabs[p_tab].text_direction != p_text_direction) { @@ -567,19 +572,19 @@ void Tabs::set_tab_text_direction(int p_tab, Control::TextDirection p_text_direc } } -Control::TextDirection Tabs::get_tab_text_direction(int p_tab) const { +Control::TextDirection TabBar::get_tab_text_direction(int p_tab) const { ERR_FAIL_INDEX_V(p_tab, tabs.size(), Control::TEXT_DIRECTION_INHERITED); return tabs[p_tab].text_direction; } -void Tabs::clear_tab_opentype_features(int p_tab) { +void TabBar::clear_tab_opentype_features(int p_tab) { ERR_FAIL_INDEX(p_tab, tabs.size()); tabs.write[p_tab].opentype_features.clear(); _shape(p_tab); update(); } -void Tabs::set_tab_opentype_feature(int p_tab, const String &p_name, int p_value) { +void TabBar::set_tab_opentype_feature(int p_tab, const String &p_name, int p_value) { ERR_FAIL_INDEX(p_tab, tabs.size()); int32_t tag = TS->name_to_tag(p_name); if (!tabs[p_tab].opentype_features.has(tag) || (int)tabs[p_tab].opentype_features[tag] != p_value) { @@ -589,7 +594,7 @@ void Tabs::set_tab_opentype_feature(int p_tab, const String &p_name, int p_value } } -int Tabs::get_tab_opentype_feature(int p_tab, const String &p_name) const { +int TabBar::get_tab_opentype_feature(int p_tab, const String &p_name) const { ERR_FAIL_INDEX_V(p_tab, tabs.size(), -1); int32_t tag = TS->name_to_tag(p_name); if (!tabs[p_tab].opentype_features.has(tag)) { @@ -598,7 +603,7 @@ int Tabs::get_tab_opentype_feature(int p_tab, const String &p_name) const { return tabs[p_tab].opentype_features[tag]; } -void Tabs::set_tab_language(int p_tab, const String &p_language) { +void TabBar::set_tab_language(int p_tab, const String &p_language) { ERR_FAIL_INDEX(p_tab, tabs.size()); if (tabs[p_tab].language != p_language) { tabs.write[p_tab].language = p_language; @@ -607,35 +612,35 @@ void Tabs::set_tab_language(int p_tab, const String &p_language) { } } -String Tabs::get_tab_language(int p_tab) const { +String TabBar::get_tab_language(int p_tab) const { ERR_FAIL_INDEX_V(p_tab, tabs.size(), ""); return tabs[p_tab].language; } -void Tabs::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) { +void TabBar::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) { ERR_FAIL_INDEX(p_tab, tabs.size()); tabs.write[p_tab].icon = p_icon; update(); minimum_size_changed(); } -Ref<Texture2D> Tabs::get_tab_icon(int p_tab) const { +Ref<Texture2D> TabBar::get_tab_icon(int p_tab) const { ERR_FAIL_INDEX_V(p_tab, tabs.size(), Ref<Texture2D>()); return tabs[p_tab].icon; } -void Tabs::set_tab_disabled(int p_tab, bool p_disabled) { +void TabBar::set_tab_disabled(int p_tab, bool p_disabled) { ERR_FAIL_INDEX(p_tab, tabs.size()); tabs.write[p_tab].disabled = p_disabled; update(); } -bool Tabs::get_tab_disabled(int p_tab) const { +bool TabBar::get_tab_disabled(int p_tab) const { ERR_FAIL_INDEX_V(p_tab, tabs.size(), false); return tabs[p_tab].disabled; } -void Tabs::set_tab_right_button(int p_tab, const Ref<Texture2D> &p_right_button) { +void TabBar::set_tab_right_button(int p_tab, const Ref<Texture2D> &p_right_button) { ERR_FAIL_INDEX(p_tab, tabs.size()); tabs.write[p_tab].right_button = p_right_button; _update_cache(); @@ -643,12 +648,12 @@ void Tabs::set_tab_right_button(int p_tab, const Ref<Texture2D> &p_right_button) minimum_size_changed(); } -Ref<Texture2D> Tabs::get_tab_right_button(int p_tab) const { +Ref<Texture2D> TabBar::get_tab_right_button(int p_tab) const { ERR_FAIL_INDEX_V(p_tab, tabs.size(), Ref<Texture2D>()); return tabs[p_tab].right_button; } -void Tabs::_update_hover() { +void TabBar::_update_hover() { if (!is_inside_tree()) { return; } @@ -685,7 +690,7 @@ void Tabs::_update_hover() { } } -void Tabs::_update_cache() { +void TabBar::_update_cache() { Ref<StyleBox> tab_disabled = get_theme_stylebox(SNAME("tab_disabled")); Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected")); Ref<StyleBox> tab_selected = get_theme_stylebox(SNAME("tab_selected")); @@ -748,7 +753,7 @@ void Tabs::_update_cache() { } } -void Tabs::_on_mouse_exited() { +void TabBar::_on_mouse_exited() { rb_hover = -1; cb_hover = -1; hover = -1; @@ -756,7 +761,7 @@ void Tabs::_on_mouse_exited() { update(); } -void Tabs::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) { +void TabBar::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) { Tab t; t.text = p_str; t.xl_text = atr(p_str); @@ -775,7 +780,7 @@ void Tabs::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) { minimum_size_changed(); } -void Tabs::clear_tabs() { +void TabBar::clear_tabs() { tabs.clear(); current = 0; previous = 0; @@ -783,7 +788,7 @@ void Tabs::clear_tabs() { update(); } -void Tabs::remove_tab(int p_idx) { +void TabBar::remove_tab(int p_idx) { ERR_FAIL_INDEX(p_idx, tabs.size()); tabs.remove(p_idx); if (current >= p_idx) { @@ -805,7 +810,7 @@ void Tabs::remove_tab(int p_idx) { _ensure_no_over_offset(); } -Variant Tabs::get_drag_data(const Point2 &p_point) { +Variant TabBar::get_drag_data(const Point2 &p_point) { if (!drag_to_rearrange_enabled) { return Variant(); } @@ -839,7 +844,7 @@ Variant Tabs::get_drag_data(const Point2 &p_point) { return drag_data; } -bool Tabs::can_drop_data(const Point2 &p_point, const Variant &p_data) const { +bool TabBar::can_drop_data(const Point2 &p_point, const Variant &p_data) const { if (!drag_to_rearrange_enabled) { return false; } @@ -855,9 +860,9 @@ bool Tabs::can_drop_data(const Point2 &p_point, const Variant &p_data) const { if (from_path == to_path) { return true; } else if (get_tabs_rearrange_group() != -1) { - // drag and drop between other Tabs + // drag and drop between other TabBars Node *from_node = get_node(from_path); - Tabs *from_tabs = Object::cast_to<Tabs>(from_node); + TabBar *from_tabs = Object::cast_to<TabBar>(from_node); if (from_tabs && from_tabs->get_tabs_rearrange_group() == get_tabs_rearrange_group()) { return true; } @@ -866,7 +871,7 @@ bool Tabs::can_drop_data(const Point2 &p_point, const Variant &p_data) const { return false; } -void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) { +void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) { if (!drag_to_rearrange_enabled) { return; } @@ -892,7 +897,7 @@ void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) { } else if (get_tabs_rearrange_group() != -1) { // drag and drop between Tabs Node *from_node = get_node(from_path); - Tabs *from_tabs = Object::cast_to<Tabs>(from_node); + TabBar *from_tabs = Object::cast_to<TabBar>(from_node); if (from_tabs && from_tabs->get_tabs_rearrange_group() == get_tabs_rearrange_group()) { if (tab_from_id >= from_tabs->get_tab_count()) { return; @@ -912,7 +917,7 @@ void Tabs::drop_data(const Point2 &p_point, const Variant &p_data) { update(); } -int Tabs::get_tab_idx_at_point(const Point2 &p_point) const { +int TabBar::get_tab_idx_at_point(const Point2 &p_point) const { int hover_now = -1; for (int i = offset; i <= max_drawn_tab; i++) { Rect2 rect = get_tab_rect(i); @@ -924,17 +929,17 @@ int Tabs::get_tab_idx_at_point(const Point2 &p_point) const { return hover_now; } -void Tabs::set_tab_align(TabAlign p_align) { +void TabBar::set_tab_align(TabAlign p_align) { ERR_FAIL_INDEX(p_align, ALIGN_MAX); tab_align = p_align; update(); } -Tabs::TabAlign Tabs::get_tab_align() const { +TabBar::TabAlign TabBar::get_tab_align() const { return tab_align; } -void Tabs::set_clip_tabs(bool p_clip_tabs) { +void TabBar::set_clip_tabs(bool p_clip_tabs) { if (clip_tabs == p_clip_tabs) { return; } @@ -943,11 +948,11 @@ void Tabs::set_clip_tabs(bool p_clip_tabs) { minimum_size_changed(); } -bool Tabs::get_clip_tabs() const { +bool TabBar::get_clip_tabs() const { return clip_tabs; } -void Tabs::move_tab(int from, int to) { +void TabBar::move_tab(int from, int to) { if (from == to) { return; } @@ -963,7 +968,7 @@ void Tabs::move_tab(int from, int to) { update(); } -int Tabs::get_tab_width(int p_idx) const { +int TabBar::get_tab_width(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, tabs.size(), 0); Ref<StyleBox> tab_unselected = get_theme_stylebox(SNAME("tab_unselected")); @@ -1005,7 +1010,7 @@ int Tabs::get_tab_width(int p_idx) const { return x; } -void Tabs::_ensure_no_over_offset() { +void TabBar::_ensure_no_over_offset() { if (!is_inside_tree()) { return; } @@ -1031,7 +1036,7 @@ void Tabs::_ensure_no_over_offset() { } } -void Tabs::ensure_tab_visible(int p_idx) { +void TabBar::ensure_tab_visible(int p_idx) { if (!is_inside_tree()) { return; } @@ -1068,7 +1073,7 @@ void Tabs::ensure_tab_visible(int p_idx) { } } -Rect2 Tabs::get_tab_rect(int p_tab) const { +Rect2 TabBar::get_tab_rect(int p_tab) const { ERR_FAIL_INDEX_V(p_tab, tabs.size(), Rect2()); if (is_layout_rtl()) { return Rect2(get_size().width - tabs[p_tab].ofs_cache - tabs[p_tab].size_cache, 0, tabs[p_tab].size_cache, get_size().height); @@ -1077,93 +1082,93 @@ Rect2 Tabs::get_tab_rect(int p_tab) const { } } -void Tabs::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) { +void TabBar::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) { ERR_FAIL_INDEX(p_policy, CLOSE_BUTTON_MAX); cb_displaypolicy = p_policy; update(); } -Tabs::CloseButtonDisplayPolicy Tabs::get_tab_close_display_policy() const { +TabBar::CloseButtonDisplayPolicy TabBar::get_tab_close_display_policy() const { return cb_displaypolicy; } -void Tabs::set_min_width(int p_width) { +void TabBar::set_min_width(int p_width) { min_width = p_width; } -void Tabs::set_scrolling_enabled(bool p_enabled) { +void TabBar::set_scrolling_enabled(bool p_enabled) { scrolling_enabled = p_enabled; } -bool Tabs::get_scrolling_enabled() const { +bool TabBar::get_scrolling_enabled() const { return scrolling_enabled; } -void Tabs::set_drag_to_rearrange_enabled(bool p_enabled) { +void TabBar::set_drag_to_rearrange_enabled(bool p_enabled) { drag_to_rearrange_enabled = p_enabled; } -bool Tabs::get_drag_to_rearrange_enabled() const { +bool TabBar::get_drag_to_rearrange_enabled() const { return drag_to_rearrange_enabled; } -void Tabs::set_tabs_rearrange_group(int p_group_id) { +void TabBar::set_tabs_rearrange_group(int p_group_id) { tabs_rearrange_group = p_group_id; } -int Tabs::get_tabs_rearrange_group() const { +int TabBar::get_tabs_rearrange_group() const { return tabs_rearrange_group; } -void Tabs::set_select_with_rmb(bool p_enabled) { +void TabBar::set_select_with_rmb(bool p_enabled) { select_with_rmb = p_enabled; } -bool Tabs::get_select_with_rmb() const { +bool TabBar::get_select_with_rmb() const { return select_with_rmb; } -void Tabs::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_hover"), &Tabs::_update_hover); - ClassDB::bind_method(D_METHOD("get_tab_count"), &Tabs::get_tab_count); - ClassDB::bind_method(D_METHOD("set_current_tab", "tab_idx"), &Tabs::set_current_tab); - ClassDB::bind_method(D_METHOD("get_current_tab"), &Tabs::get_current_tab); - ClassDB::bind_method(D_METHOD("get_previous_tab"), &Tabs::get_previous_tab); - ClassDB::bind_method(D_METHOD("set_tab_title", "tab_idx", "title"), &Tabs::set_tab_title); - ClassDB::bind_method(D_METHOD("get_tab_title", "tab_idx"), &Tabs::get_tab_title); - ClassDB::bind_method(D_METHOD("set_tab_text_direction", "tab_idx", "direction"), &Tabs::set_tab_text_direction); - ClassDB::bind_method(D_METHOD("get_tab_text_direction", "tab_idx"), &Tabs::get_tab_text_direction); - ClassDB::bind_method(D_METHOD("set_tab_opentype_feature", "tab_idx", "tag", "values"), &Tabs::set_tab_opentype_feature); - ClassDB::bind_method(D_METHOD("get_tab_opentype_feature", "tab_idx", "tag"), &Tabs::get_tab_opentype_feature); - ClassDB::bind_method(D_METHOD("clear_tab_opentype_features", "tab_idx"), &Tabs::clear_tab_opentype_features); - ClassDB::bind_method(D_METHOD("set_tab_language", "tab_idx", "language"), &Tabs::set_tab_language); - ClassDB::bind_method(D_METHOD("get_tab_language", "tab_idx"), &Tabs::get_tab_language); - ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon"), &Tabs::set_tab_icon); - ClassDB::bind_method(D_METHOD("get_tab_icon", "tab_idx"), &Tabs::get_tab_icon); - ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &Tabs::set_tab_disabled); - ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &Tabs::get_tab_disabled); - ClassDB::bind_method(D_METHOD("remove_tab", "tab_idx"), &Tabs::remove_tab); - ClassDB::bind_method(D_METHOD("add_tab", "title", "icon"), &Tabs::add_tab, DEFVAL(""), DEFVAL(Ref<Texture2D>())); - ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &Tabs::set_tab_align); - ClassDB::bind_method(D_METHOD("get_tab_align"), &Tabs::get_tab_align); - ClassDB::bind_method(D_METHOD("set_clip_tabs", "clip_tabs"), &Tabs::set_clip_tabs); - ClassDB::bind_method(D_METHOD("get_clip_tabs"), &Tabs::get_clip_tabs); - ClassDB::bind_method(D_METHOD("get_tab_offset"), &Tabs::get_tab_offset); - ClassDB::bind_method(D_METHOD("get_offset_buttons_visible"), &Tabs::get_offset_buttons_visible); - ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &Tabs::ensure_tab_visible); - ClassDB::bind_method(D_METHOD("get_tab_rect", "tab_idx"), &Tabs::get_tab_rect); - ClassDB::bind_method(D_METHOD("move_tab", "from", "to"), &Tabs::move_tab); - ClassDB::bind_method(D_METHOD("set_tab_close_display_policy", "policy"), &Tabs::set_tab_close_display_policy); - ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &Tabs::get_tab_close_display_policy); - ClassDB::bind_method(D_METHOD("set_scrolling_enabled", "enabled"), &Tabs::set_scrolling_enabled); - ClassDB::bind_method(D_METHOD("get_scrolling_enabled"), &Tabs::get_scrolling_enabled); - ClassDB::bind_method(D_METHOD("set_drag_to_rearrange_enabled", "enabled"), &Tabs::set_drag_to_rearrange_enabled); - ClassDB::bind_method(D_METHOD("get_drag_to_rearrange_enabled"), &Tabs::get_drag_to_rearrange_enabled); - ClassDB::bind_method(D_METHOD("set_tabs_rearrange_group", "group_id"), &Tabs::set_tabs_rearrange_group); - ClassDB::bind_method(D_METHOD("get_tabs_rearrange_group"), &Tabs::get_tabs_rearrange_group); - - ClassDB::bind_method(D_METHOD("set_select_with_rmb", "enabled"), &Tabs::set_select_with_rmb); - ClassDB::bind_method(D_METHOD("get_select_with_rmb"), &Tabs::get_select_with_rmb); +void TabBar::_bind_methods() { + ClassDB::bind_method(D_METHOD("_update_hover"), &TabBar::_update_hover); + ClassDB::bind_method(D_METHOD("get_tab_count"), &TabBar::get_tab_count); + ClassDB::bind_method(D_METHOD("set_current_tab", "tab_idx"), &TabBar::set_current_tab); + ClassDB::bind_method(D_METHOD("get_current_tab"), &TabBar::get_current_tab); + ClassDB::bind_method(D_METHOD("get_previous_tab"), &TabBar::get_previous_tab); + ClassDB::bind_method(D_METHOD("set_tab_title", "tab_idx", "title"), &TabBar::set_tab_title); + ClassDB::bind_method(D_METHOD("get_tab_title", "tab_idx"), &TabBar::get_tab_title); + ClassDB::bind_method(D_METHOD("set_tab_text_direction", "tab_idx", "direction"), &TabBar::set_tab_text_direction); + ClassDB::bind_method(D_METHOD("get_tab_text_direction", "tab_idx"), &TabBar::get_tab_text_direction); + ClassDB::bind_method(D_METHOD("set_tab_opentype_feature", "tab_idx", "tag", "values"), &TabBar::set_tab_opentype_feature); + ClassDB::bind_method(D_METHOD("get_tab_opentype_feature", "tab_idx", "tag"), &TabBar::get_tab_opentype_feature); + ClassDB::bind_method(D_METHOD("clear_tab_opentype_features", "tab_idx"), &TabBar::clear_tab_opentype_features); + ClassDB::bind_method(D_METHOD("set_tab_language", "tab_idx", "language"), &TabBar::set_tab_language); + ClassDB::bind_method(D_METHOD("get_tab_language", "tab_idx"), &TabBar::get_tab_language); + ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon"), &TabBar::set_tab_icon); + ClassDB::bind_method(D_METHOD("get_tab_icon", "tab_idx"), &TabBar::get_tab_icon); + ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &TabBar::set_tab_disabled); + ClassDB::bind_method(D_METHOD("get_tab_disabled", "tab_idx"), &TabBar::get_tab_disabled); + ClassDB::bind_method(D_METHOD("remove_tab", "tab_idx"), &TabBar::remove_tab); + ClassDB::bind_method(D_METHOD("add_tab", "title", "icon"), &TabBar::add_tab, DEFVAL(""), DEFVAL(Ref<Texture2D>())); + ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &TabBar::set_tab_align); + ClassDB::bind_method(D_METHOD("get_tab_align"), &TabBar::get_tab_align); + ClassDB::bind_method(D_METHOD("set_clip_tabs", "clip_tabs"), &TabBar::set_clip_tabs); + ClassDB::bind_method(D_METHOD("get_clip_tabs"), &TabBar::get_clip_tabs); + ClassDB::bind_method(D_METHOD("get_tab_offset"), &TabBar::get_tab_offset); + ClassDB::bind_method(D_METHOD("get_offset_buttons_visible"), &TabBar::get_offset_buttons_visible); + ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &TabBar::ensure_tab_visible); + ClassDB::bind_method(D_METHOD("get_tab_rect", "tab_idx"), &TabBar::get_tab_rect); + ClassDB::bind_method(D_METHOD("move_tab", "from", "to"), &TabBar::move_tab); + ClassDB::bind_method(D_METHOD("set_tab_close_display_policy", "policy"), &TabBar::set_tab_close_display_policy); + ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &TabBar::get_tab_close_display_policy); + ClassDB::bind_method(D_METHOD("set_scrolling_enabled", "enabled"), &TabBar::set_scrolling_enabled); + ClassDB::bind_method(D_METHOD("get_scrolling_enabled"), &TabBar::get_scrolling_enabled); + ClassDB::bind_method(D_METHOD("set_drag_to_rearrange_enabled", "enabled"), &TabBar::set_drag_to_rearrange_enabled); + ClassDB::bind_method(D_METHOD("get_drag_to_rearrange_enabled"), &TabBar::get_drag_to_rearrange_enabled); + ClassDB::bind_method(D_METHOD("set_tabs_rearrange_group", "group_id"), &TabBar::set_tabs_rearrange_group); + ClassDB::bind_method(D_METHOD("get_tabs_rearrange_group"), &TabBar::get_tabs_rearrange_group); + + ClassDB::bind_method(D_METHOD("set_select_with_rmb", "enabled"), &TabBar::set_select_with_rmb); + ClassDB::bind_method(D_METHOD("get_select_with_rmb"), &TabBar::get_select_with_rmb); ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab"))); ADD_SIGNAL(MethodInfo("tab_rmb_clicked", PropertyInfo(Variant::INT, "tab"))); @@ -1190,6 +1195,6 @@ void Tabs::_bind_methods() { BIND_ENUM_CONSTANT(CLOSE_BUTTON_MAX); } -Tabs::Tabs() { - connect("mouse_exited", callable_mp(this, &Tabs::_on_mouse_exited)); +TabBar::TabBar() { + connect("mouse_exited", callable_mp(this, &TabBar::_on_mouse_exited)); } diff --git a/scene/gui/tabs.h b/scene/gui/tab_bar.h index b044453803..411a62b1d9 100644 --- a/scene/gui/tabs.h +++ b/scene/gui/tab_bar.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* tabs.h */ +/* tab_bar.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,14 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef TABS_H -#define TABS_H +#ifndef TAB_BAR_H +#define TAB_BAR_H #include "scene/gui/control.h" #include "scene/resources/text_line.h" -class Tabs : public Control { - GDCLASS(Tabs, Control); +class TabBar : public Control { + GDCLASS(TabBar, Control); public: enum TabAlign { @@ -83,7 +83,6 @@ private: Vector<Tab> tabs; int current = 0; int previous = 0; - int _get_top_margin() const; TabAlign tab_align = ALIGN_CENTER; bool clip_tabs = true; int rb_hover = -1; @@ -187,10 +186,10 @@ public: Rect2 get_tab_rect(int p_tab) const; Size2 get_minimum_size() const override; - Tabs(); + TabBar(); }; -VARIANT_ENUM_CAST(Tabs::TabAlign); -VARIANT_ENUM_CAST(Tabs::CloseButtonDisplayPolicy); +VARIANT_ENUM_CAST(TabBar::TabAlign); +VARIANT_ENUM_CAST(TabBar::CloseButtonDisplayPolicy); -#endif // TABS_H +#endif // TAB_BAR_H diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index f03eebd543..a1d66d8544 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1534,6 +1534,10 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { update(); } + if (is_middle_mouse_paste_enabled() && mb->get_button_index() == MOUSE_BUTTON_MIDDLE) { + paste_primary_clipboard(); + } + if (mb->get_button_index() == MOUSE_BUTTON_RIGHT && context_menu_enabled) { _reset_caret_blink_timer(); @@ -1571,6 +1575,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { dragging_selection = false; can_drag_minimap = false; click_select_held->stop(); + DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text()); } // Notify to show soft keyboard. @@ -2596,6 +2601,14 @@ bool TextEdit::is_virtual_keyboard_enabled() const { return virtual_keyboard_enabled; } +void TextEdit::set_middle_mouse_paste_enabled(bool p_enabled) { + middle_mouse_paste_enabled = p_enabled; +} + +bool TextEdit::is_middle_mouse_paste_enabled() const { + return middle_mouse_paste_enabled; +} + // Text manipulation void TextEdit::clear() { setting_text = true; @@ -2915,6 +2928,13 @@ void TextEdit::paste() { _paste_internal(); } +void TextEdit::paste_primary_clipboard() { + if (GDVIRTUAL_CALL(_paste_primary_clipboard)) { + return; + } + _paste_primary_clipboard_internal(); +} + // Context menu. PopupMenu *TextEdit::get_menu() const { const_cast<TextEdit *>(this)->_generate_context_menu(); @@ -4039,7 +4059,7 @@ int TextEdit::get_visible_line_count() const { } int TextEdit::get_total_visible_line_count() const { - /* Returns the total number of (lines + wraped - hidden). */ + /* Returns the total number of (lines + wrapped - hidden). */ if (!_is_hiding_enabled() && get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) { return text.size(); } @@ -4536,6 +4556,9 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_virtual_keyboard_enabled", "enabled"), &TextEdit::set_virtual_keyboard_enabled); ClassDB::bind_method(D_METHOD("is_virtual_keyboard_enabled"), &TextEdit::is_virtual_keyboard_enabled); + ClassDB::bind_method(D_METHOD("set_middle_mouse_paste_enabled", "enabled"), &TextEdit::set_middle_mouse_paste_enabled); + ClassDB::bind_method(D_METHOD("is_middle_mouse_paste_enabled"), &TextEdit::is_middle_mouse_paste_enabled); + // Text manipulation ClassDB::bind_method(D_METHOD("clear"), &TextEdit::clear); @@ -4575,6 +4598,7 @@ void TextEdit::_bind_methods() { GDVIRTUAL_BIND(_cut) GDVIRTUAL_BIND(_copy) GDVIRTUAL_BIND(_paste) + GDVIRTUAL_BIND(_paste_primary_clipboard) // Context Menu BIND_ENUM_CONSTANT(MENU_CUT); @@ -4850,6 +4874,7 @@ void TextEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selecting_enabled"), "set_selecting_enabled", "is_selecting_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "virtual_keyboard_enabled"), "set_virtual_keyboard_enabled", "is_virtual_keyboard_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_mode", PROPERTY_HINT_ENUM, "None,Boundary"), "set_line_wrapping_mode", "get_line_wrapping_mode"); @@ -5141,6 +5166,24 @@ void TextEdit::_paste_internal() { end_complex_operation(); } +void TextEdit::_paste_primary_clipboard_internal() { + if (!is_editable()) { + return; + } + + String paste_buffer = DisplayServer::get_singleton()->clipboard_get_primary(); + + Point2i pos = get_line_column_at_pos(get_local_mouse_pos()); + deselect(); + set_caret_line(pos.y, true, false); + set_caret_column(pos.x); + if (!paste_buffer.is_empty()) { + insert_text_at_caret(paste_buffer); + } + + grab_focus(); +} + /* Text. */ // Context menu. void TextEdit::_generate_context_menu() { @@ -5150,32 +5193,32 @@ void TextEdit::_generate_context_menu() { menu_dir = memnew(PopupMenu); menu_dir->set_name("DirMenu"); - menu_dir->add_radio_check_item(RTR("Same as layout direction"), MENU_DIR_INHERITED); - menu_dir->add_radio_check_item(RTR("Auto-detect direction"), MENU_DIR_AUTO); - menu_dir->add_radio_check_item(RTR("Left-to-right"), MENU_DIR_LTR); - menu_dir->add_radio_check_item(RTR("Right-to-left"), MENU_DIR_RTL); + menu_dir->add_radio_check_item(RTR("Same as Layout Direction"), MENU_DIR_INHERITED); + menu_dir->add_radio_check_item(RTR("Auto-Detect Direction"), MENU_DIR_AUTO); + menu_dir->add_radio_check_item(RTR("Left-to-Right"), MENU_DIR_LTR); + menu_dir->add_radio_check_item(RTR("Right-to-Left"), MENU_DIR_RTL); menu->add_child(menu_dir, false, INTERNAL_MODE_FRONT); menu_ctl = memnew(PopupMenu); menu_ctl->set_name("CTLMenu"); - menu_ctl->add_item(RTR("Left-to-right mark (LRM)"), MENU_INSERT_LRM); - menu_ctl->add_item(RTR("Right-to-left mark (RLM)"), MENU_INSERT_RLM); - menu_ctl->add_item(RTR("Start of left-to-right embedding (LRE)"), MENU_INSERT_LRE); - menu_ctl->add_item(RTR("Start of right-to-left embedding (RLE)"), MENU_INSERT_RLE); - menu_ctl->add_item(RTR("Start of left-to-right override (LRO)"), MENU_INSERT_LRO); - menu_ctl->add_item(RTR("Start of right-to-left override (RLO)"), MENU_INSERT_RLO); - menu_ctl->add_item(RTR("Pop direction formatting (PDF)"), MENU_INSERT_PDF); + menu_ctl->add_item(RTR("Left-to-Right Mark (LRM)"), MENU_INSERT_LRM); + menu_ctl->add_item(RTR("Right-to-Left Mark (RLM)"), MENU_INSERT_RLM); + menu_ctl->add_item(RTR("Start of Left-to-Right Embedding (LRE)"), MENU_INSERT_LRE); + menu_ctl->add_item(RTR("Start of Right-to-Left Embedding (RLE)"), MENU_INSERT_RLE); + menu_ctl->add_item(RTR("Start of Left-to-Right Override (LRO)"), MENU_INSERT_LRO); + menu_ctl->add_item(RTR("Start of Right-to-Left Override (RLO)"), MENU_INSERT_RLO); + menu_ctl->add_item(RTR("Pop Direction Formatting (PDF)"), MENU_INSERT_PDF); menu_ctl->add_separator(); - menu_ctl->add_item(RTR("Arabic letter mark (ALM)"), MENU_INSERT_ALM); - menu_ctl->add_item(RTR("Left-to-right isolate (LRI)"), MENU_INSERT_LRI); - menu_ctl->add_item(RTR("Right-to-left isolate (RLI)"), MENU_INSERT_RLI); - menu_ctl->add_item(RTR("First strong isolate (FSI)"), MENU_INSERT_FSI); - menu_ctl->add_item(RTR("Pop direction isolate (PDI)"), MENU_INSERT_PDI); + menu_ctl->add_item(RTR("Arabic Letter Mark (ALM)"), MENU_INSERT_ALM); + menu_ctl->add_item(RTR("Left-to-Right Isolate (LRI)"), MENU_INSERT_LRI); + menu_ctl->add_item(RTR("Right-to-Left Isolate (RLI)"), MENU_INSERT_RLI); + menu_ctl->add_item(RTR("First Strong Isolate (FSI)"), MENU_INSERT_FSI); + menu_ctl->add_item(RTR("Pop Direction Isolate (PDI)"), MENU_INSERT_PDI); menu_ctl->add_separator(); - menu_ctl->add_item(RTR("Zero width joiner (ZWJ)"), MENU_INSERT_ZWJ); - menu_ctl->add_item(RTR("Zero width non-joiner (ZWNJ)"), MENU_INSERT_ZWNJ); - menu_ctl->add_item(RTR("Word joiner (WJ)"), MENU_INSERT_WJ); - menu_ctl->add_item(RTR("Soft hyphen (SHY)"), MENU_INSERT_SHY); + menu_ctl->add_item(RTR("Zero-Width Joiner (ZWJ)"), MENU_INSERT_ZWJ); + menu_ctl->add_item(RTR("Zero-Width Non-Joiner (ZWNJ)"), MENU_INSERT_ZWNJ); + menu_ctl->add_item(RTR("Word Joiner (WJ)"), MENU_INSERT_WJ); + menu_ctl->add_item(RTR("Soft Hyphen (SHY)"), MENU_INSERT_SHY); menu->add_child(menu_ctl, false, INTERNAL_MODE_FRONT); menu->connect("id_pressed", callable_mp(this, &TextEdit::menu_option)); @@ -5203,12 +5246,12 @@ void TextEdit::_generate_context_menu() { menu->add_item(RTR("Redo"), MENU_REDO, is_shortcut_keys_enabled() ? _get_menu_action_accelerator("ui_redo") : 0); } menu->add_separator(); - menu->add_submenu_item(RTR("Text writing direction"), "DirMenu"); + menu->add_submenu_item(RTR("Text Writing Direction"), "DirMenu"); menu->add_separator(); - menu->add_check_item(RTR("Display control characters"), MENU_DISPLAY_UCC); + menu->add_check_item(RTR("Display Control Characters"), MENU_DISPLAY_UCC); menu->set_item_checked(menu->get_item_index(MENU_DISPLAY_UCC), draw_control_chars); if (editable) { - menu->add_submenu_item(RTR("Insert control character"), "CTLMenu"); + menu->add_submenu_item(RTR("Insert Control Character"), "CTLMenu"); } menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED); menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_AUTO), text_direction == TEXT_DIRECTION_AUTO); @@ -5477,6 +5520,8 @@ void TextEdit::_update_selection_mode_word() { } } + DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text()); + update(); click_select_held->start(); @@ -5504,6 +5549,8 @@ void TextEdit::_update_selection_mode_line() { set_caret_column(0); select(selection.selecting_line, selection.selecting_column, line, col); + DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text()); + update(); click_select_held->start(); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 16c1ee9ff9..8823e44c0d 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -269,6 +269,7 @@ private: bool context_menu_enabled = true; bool shortcut_keys_enabled = true; bool virtual_keyboard_enabled = true; + bool middle_mouse_paste_enabled = true; // Overridable actions String cut_copy_line = ""; @@ -586,12 +587,14 @@ protected: virtual void _cut_internal(); virtual void _copy_internal(); virtual void _paste_internal(); + virtual void _paste_primary_clipboard_internal(); GDVIRTUAL1(_handle_unicode_input, int) GDVIRTUAL0(_backspace) GDVIRTUAL0(_cut) GDVIRTUAL0(_copy) GDVIRTUAL0(_paste) + GDVIRTUAL0(_paste_primary_clipboard) public: /* General overrides. */ @@ -640,6 +643,9 @@ public: void set_virtual_keyboard_enabled(bool p_enabled); bool is_virtual_keyboard_enabled() const; + void set_middle_mouse_paste_enabled(bool p_enabled); + bool is_middle_mouse_paste_enabled() const; + // Text manipulation void clear(); @@ -674,6 +680,7 @@ public: void cut(); void copy(); void paste(); + void paste_primary_clipboard(); // Context menu. PopupMenu *get_menu() const; diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 4540e42b4c..26bff4494b 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -128,7 +128,7 @@ void CanvasLayer::_notification(int p_what) { } else { vp = Node::get_viewport(); } - ERR_FAIL_COND(!vp); + ERR_FAIL_NULL_MSG(vp, "Viewport is not initialized."); vp->_canvas_layer_add(this); viewport = vp->get_viewport_rid(); @@ -140,6 +140,8 @@ void CanvasLayer::_notification(int p_what) { } break; case NOTIFICATION_EXIT_TREE: { + ERR_FAIL_NULL_MSG(vp, "Viewport is not initialized."); + vp->_canvas_layer_remove(this); RenderingServer::get_singleton()->viewport_remove_canvas(viewport, canvas); viewport = RID(); @@ -160,6 +162,8 @@ Size2 CanvasLayer::get_viewport_size() const { return Size2(1, 1); } + ERR_FAIL_NULL_V_MSG(vp, Size2(1, 1), "Viewport is not initialized."); + Rect2 r = vp->get_visible_rect(); return r.size; } @@ -169,7 +173,7 @@ RID CanvasLayer::get_viewport() const { } void CanvasLayer::set_custom_viewport(Node *p_viewport) { - ERR_FAIL_NULL(p_viewport); + ERR_FAIL_NULL_MSG(p_viewport, "Cannot set viewport to nullptr."); if (is_inside_tree()) { vp->_canvas_layer_remove(this); RenderingServer::get_singleton()->viewport_remove_canvas(viewport, canvas); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 19331c1906..7a4f9f9c52 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -136,7 +136,6 @@ private: void _flush_ugc(); _FORCE_INLINE_ void _update_group_order(Group &g, bool p_use_priority = false); - void _update_listener(); Array _get_nodes_in_group(const StringName &p_group); @@ -265,9 +264,6 @@ public: void set_pause(bool p_enabled); bool is_paused() const; - void set_camera(const RID &p_camera); - RID get_camera() const; - #ifdef DEBUG_ENABLED void set_debug_collisions_hint(bool p_enabled); bool is_debugging_collisions_hint() const; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 0e62e6e30a..3280190250 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2192,7 +2192,10 @@ void Viewport::_drop_physics_mouseover(bool p_paused_only) { if (physics_object_over.is_valid()) { CollisionObject3D *co = Object::cast_to<CollisionObject3D>(ObjectDB::get_instance(physics_object_over)); if (co) { - if (!(p_paused_only && co->can_process())) { + if (!co->is_inside_tree()) { + physics_object_over = ObjectID(); + physics_object_capture = ObjectID(); + } else if (!(p_paused_only && co->can_process())) { co->_mouse_exit(); physics_object_over = ObjectID(); physics_object_capture = ObjectID(); @@ -2213,7 +2216,7 @@ void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paus Object *o = ObjectDB::get_instance(E->key()); if (o) { CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o); - if (co) { + if (co && co->is_inside_tree()) { if (p_clean_all_frames && p_paused_only && co->can_process()) { continue; } @@ -2239,7 +2242,7 @@ void Viewport::_cleanup_mouseover_colliders(bool p_clean_all_frames, bool p_paus Object *o = ObjectDB::get_instance(E->key().first); if (o) { CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o); - if (co) { + if (co && co->is_inside_tree()) { if (p_clean_all_frames && p_paused_only && co->can_process()) { continue; } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index bf8f7291be..33e0e2cad7 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -115,8 +115,8 @@ #include "scene/gui/spin_box.h" #include "scene/gui/split_container.h" #include "scene/gui/subviewport_container.h" +#include "scene/gui/tab_bar.h" #include "scene/gui/tab_container.h" -#include "scene/gui/tabs.h" #include "scene/gui/text_edit.h" #include "scene/gui/texture_button.h" #include "scene/gui/texture_progress_bar.h" @@ -262,7 +262,7 @@ static Ref<ResourceFormatLoaderShader> resource_loader_shader; void register_scene_types() { SceneStringNames::create(); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init Node::init_node_hrcr(); @@ -287,7 +287,7 @@ void register_scene_types() { resource_loader_shader.instantiate(); ResourceLoader::add_resource_format_loader(resource_loader_shader, true); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init GDREGISTER_CLASS(Object); @@ -309,7 +309,7 @@ void register_scene_types() { GDREGISTER_CLASS(ButtonGroup); GDREGISTER_VIRTUAL_CLASS(BaseButton); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init GDREGISTER_CLASS(Control); GDREGISTER_CLASS(Button); @@ -330,7 +330,7 @@ void register_scene_types() { GDREGISTER_CLASS(Panel); GDREGISTER_VIRTUAL_CLASS(Range); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init GDREGISTER_CLASS(TextureRect); GDREGISTER_CLASS(ColorRect); @@ -338,7 +338,7 @@ void register_scene_types() { GDREGISTER_CLASS(ReferenceRect); GDREGISTER_CLASS(AspectRatioContainer); GDREGISTER_CLASS(TabContainer); - GDREGISTER_CLASS(Tabs); + GDREGISTER_CLASS(TabBar); GDREGISTER_VIRTUAL_CLASS(Separator); GDREGISTER_CLASS(HSeparator); GDREGISTER_CLASS(VSeparator); @@ -352,7 +352,7 @@ void register_scene_types() { GDREGISTER_CLASS(ScrollContainer); GDREGISTER_CLASS(PanelContainer); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init GDREGISTER_CLASS(TextureProgressBar); GDREGISTER_CLASS(ItemList); @@ -391,7 +391,7 @@ void register_scene_types() { GDREGISTER_CLASS(GraphNode); GDREGISTER_CLASS(GraphEdit); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init bool swap_cancel_ok = false; if (DisplayServer::get_singleton()) { @@ -431,9 +431,9 @@ void register_scene_types() { GDREGISTER_CLASS(AnimationNodeTimeSeek); GDREGISTER_CLASS(AnimationNodeTransition); - GDREGISTER_CLASS(ShaderGlobalsOverride); //can be used in any shader + GDREGISTER_CLASS(ShaderGlobalsOverride); // can be used in any shader - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init /* REGISTER 3D */ @@ -450,6 +450,7 @@ void register_scene_types() { GDREGISTER_CLASS(Camera3D); GDREGISTER_CLASS(AudioListener3D); GDREGISTER_CLASS(XRCamera3D); + GDREGISTER_VIRTUAL_CLASS(XRNode3D); GDREGISTER_CLASS(XRController3D); GDREGISTER_CLASS(XRAnchor3D); GDREGISTER_CLASS(XROrigin3D); @@ -485,9 +486,9 @@ void register_scene_types() { GDREGISTER_CLASS(Position3D); GDREGISTER_CLASS(RootMotionView); - ClassDB::set_class_enabled("RootMotionView", false); //disabled by default, enabled by editor + ClassDB::set_class_enabled("RootMotionView", false); // disabled by default, enabled by editor - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init GDREGISTER_VIRTUAL_CLASS(CollisionObject3D); GDREGISTER_VIRTUAL_CLASS(PhysicsBody3D); @@ -532,7 +533,7 @@ void register_scene_types() { GDREGISTER_CLASS(NavigationAgent3D); GDREGISTER_CLASS(NavigationObstacle3D); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init #endif /* REGISTER SHADER */ @@ -672,7 +673,7 @@ void register_scene_types() { GDREGISTER_CLASS(OccluderPolygon2D); GDREGISTER_CLASS(BackBufferCopy); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init GDREGISTER_CLASS(Camera2D); GDREGISTER_CLASS(AudioListener2D); @@ -684,6 +685,7 @@ void register_scene_types() { GDREGISTER_VIRTUAL_CLASS(TileSetSource); GDREGISTER_CLASS(TileSetAtlasSource); GDREGISTER_CLASS(TileSetScenesCollectionSource); + GDREGISTER_CLASS(TileMapPattern); GDREGISTER_CLASS(TileData); GDREGISTER_CLASS(TileMap); GDREGISTER_CLASS(ParallaxBackground); @@ -703,7 +705,7 @@ void register_scene_types() { GDREGISTER_CLASS(PhysicalBone2D); GDREGISTER_CLASS(SkeletonModification2DPhysicalBones); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init /* REGISTER RESOURCES */ @@ -744,7 +746,7 @@ void register_scene_types() { GDREGISTER_CLASS(MeshLibrary); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init GDREGISTER_VIRTUAL_CLASS(Shape3D); GDREGISTER_CLASS(SeparationRayShape3D); @@ -766,7 +768,7 @@ void register_scene_types() { ClassDB::register_class<SkeletonModification3DTwoBoneIK>(); ClassDB::register_class<SkeletonModification3DStackHolder>(); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init GDREGISTER_CLASS(VelocityTracker3D); #endif @@ -821,7 +823,7 @@ void register_scene_types() { GDREGISTER_CLASS(BitMap); GDREGISTER_CLASS(Gradient); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init GDREGISTER_CLASS(AudioStreamPlayer); GDREGISTER_CLASS(AudioStreamPlayer2D); @@ -831,7 +833,7 @@ void register_scene_types() { GDREGISTER_VIRTUAL_CLASS(VideoStream); GDREGISTER_CLASS(AudioStreamSample); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init GDREGISTER_VIRTUAL_CLASS(Shape2D); GDREGISTER_CLASS(WorldBoundaryShape2D); @@ -852,13 +854,13 @@ void register_scene_types() { GDREGISTER_CLASS(NavigationAgent2D); GDREGISTER_CLASS(NavigationObstacle2D); - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init GDREGISTER_VIRTUAL_CLASS(SceneState); GDREGISTER_CLASS(PackedScene); GDREGISTER_CLASS(SceneTree); - GDREGISTER_VIRTUAL_CLASS(SceneTreeTimer); //sorry, you can't create it + GDREGISTER_VIRTUAL_CLASS(SceneTreeTimer); // sorry, you can't create it #ifndef DISABLE_DEPRECATED // Dropped in 4.0, near approximation. @@ -940,10 +942,8 @@ void register_scene_types() { ClassDB::add_compatibility_class("Path", "Path3D"); ClassDB::add_compatibility_class("PathFollow", "PathFollow3D"); ClassDB::add_compatibility_class("PhysicalBone", "PhysicalBone3D"); - ClassDB::add_compatibility_class("Physics2DDirectBodyStateSW", "PhysicsDirectBodyState2DSW"); ClassDB::add_compatibility_class("Physics2DDirectBodyState", "PhysicsDirectBodyState2D"); ClassDB::add_compatibility_class("Physics2DDirectSpaceState", "PhysicsDirectSpaceState2D"); - ClassDB::add_compatibility_class("Physics2DServerSW", "PhysicsServer2DSW"); ClassDB::add_compatibility_class("Physics2DServer", "PhysicsServer2D"); ClassDB::add_compatibility_class("Physics2DShapeQueryParameters", "PhysicsShapeQueryParameters2D"); ClassDB::add_compatibility_class("Physics2DTestMotionResult", "PhysicsTestMotionResult2D"); @@ -1008,7 +1008,7 @@ void register_scene_types() { #endif /* DISABLE_DEPRECATED */ - OS::get_singleton()->yield(); //may take time to init + OS::get_singleton()->yield(); // may take time to init for (int i = 0; i < 20; i++) { GLOBAL_DEF_BASIC(vformat("layer_names/2d_render/layer_%d", i + 1), ""); @@ -1086,7 +1086,7 @@ void unregister_scene_types() { ResourceLoader::remove_resource_format_loader(resource_loader_shader); resource_loader_shader.unref(); - //StandardMaterial3D is not initialised when 3D is disabled, so it shouldn't be cleaned up either + // StandardMaterial3D is not initialised when 3D is disabled, so it shouldn't be cleaned up either #ifndef _3D_DISABLED BaseMaterial3D::finish_shaders(); #endif // _3D_DISABLED diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 54bb7a82cf..9fdfd493c1 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -785,30 +785,30 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("icon_separation", "TabContainer", 4 * scale); theme->set_constant("outline_size", "TabContainer", 0); - // Tabs - - theme->set_stylebox("tab_selected", "Tabs", sb_expand(make_stylebox(tab_current_png, 4, 3, 4, 1, 16, 3, 16, 2), 2, 2, 2, 2)); - theme->set_stylebox("tab_unselected", "Tabs", sb_expand(make_stylebox(tab_behind_png, 5, 4, 5, 1, 16, 5, 16, 2), 3, 3, 3, 3)); - theme->set_stylebox("tab_disabled", "Tabs", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3)); - theme->set_stylebox("close_bg_pressed", "Tabs", make_stylebox(button_pressed_png, 4, 4, 4, 4)); - theme->set_stylebox("close_bg_highlight", "Tabs", make_stylebox(button_normal_png, 4, 4, 4, 4)); - - theme->set_icon("increment", "Tabs", make_icon(scroll_button_right_png)); - theme->set_icon("increment_highlight", "Tabs", make_icon(scroll_button_right_hl_png)); - theme->set_icon("decrement", "Tabs", make_icon(scroll_button_left_png)); - theme->set_icon("decrement_highlight", "Tabs", make_icon(scroll_button_left_hl_png)); - theme->set_icon("close", "Tabs", make_icon(tab_close_png)); - - theme->set_font("font", "Tabs", Ref<Font>()); - theme->set_font_size("font_size", "Tabs", -1); - - theme->set_color("font_selected_color", "Tabs", control_font_hover_color); - theme->set_color("font_unselected_color", "Tabs", control_font_low_color); - theme->set_color("font_disabled_color", "Tabs", control_font_disabled_color); - theme->set_color("font_outline_color", "Tabs", Color(1, 1, 1)); - - theme->set_constant("hseparation", "Tabs", 4 * scale); - theme->set_constant("outline_size", "Tabs", 0); + // TabBar + + theme->set_stylebox("tab_selected", "TabBar", sb_expand(make_stylebox(tab_current_png, 4, 3, 4, 1, 16, 3, 16, 2), 2, 2, 2, 2)); + theme->set_stylebox("tab_unselected", "TabBar", sb_expand(make_stylebox(tab_behind_png, 5, 4, 5, 1, 16, 5, 16, 2), 3, 3, 3, 3)); + theme->set_stylebox("tab_disabled", "TabBar", sb_expand(make_stylebox(tab_disabled_png, 5, 5, 5, 1, 16, 6, 16, 4), 3, 0, 3, 3)); + theme->set_stylebox("close_bg_pressed", "TabBar", make_stylebox(button_pressed_png, 4, 4, 4, 4)); + theme->set_stylebox("close_bg_highlight", "TabBar", make_stylebox(button_normal_png, 4, 4, 4, 4)); + + theme->set_icon("increment", "TabBar", make_icon(scroll_button_right_png)); + theme->set_icon("increment_highlight", "TabBar", make_icon(scroll_button_right_hl_png)); + theme->set_icon("decrement", "TabBar", make_icon(scroll_button_left_png)); + theme->set_icon("decrement_highlight", "TabBar", make_icon(scroll_button_left_hl_png)); + theme->set_icon("close", "TabBar", make_icon(tab_close_png)); + + theme->set_font("font", "TabBar", Ref<Font>()); + theme->set_font_size("font_size", "TabBar", -1); + + theme->set_color("font_selected_color", "TabBar", control_font_hover_color); + theme->set_color("font_unselected_color", "TabBar", control_font_low_color); + theme->set_color("font_disabled_color", "TabBar", control_font_disabled_color); + theme->set_color("font_outline_color", "TabBar", Color(1, 1, 1)); + + theme->set_constant("hseparation", "TabBar", 4 * scale); + theme->set_constant("outline_size", "TabBar", 0); // Separators diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 8d5571d67c..a95b4d4a5e 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -278,7 +278,6 @@ public: int surface_get_array_index_len(int p_idx) const override; uint32_t surface_get_format(int p_idx) const override; PrimitiveType surface_get_primitive_type(int p_idx) const override; - bool surface_is_alpha_sorting_enabled(int p_idx) const; virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) override; virtual Ref<Material> surface_get_material(int p_idx) const override; diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h index 1cdf7a07ed..009239838f 100644 --- a/scene/resources/navigation_mesh.h +++ b/scene/resources/navigation_mesh.h @@ -85,7 +85,7 @@ protected: float cell_size = 0.3f; float cell_height = 0.2f; float agent_height = 2.0f; - float agent_radius = 0.6f; + float agent_radius = 1.0f; float agent_max_climb = 0.9f; float agent_max_slope = 45.0f; float region_min_size = 8.0f; diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h index 14bdd60e4b..7c5d1344e8 100644 --- a/scene/resources/shape_2d.h +++ b/scene/resources/shape_2d.h @@ -64,7 +64,6 @@ public: static bool is_collision_outline_enabled(); - Shape2D(); ~Shape2D(); }; diff --git a/scene/resources/text_paragraph.cpp b/scene/resources/text_paragraph.cpp index b2e18e2451..fae1de94d3 100644 --- a/scene/resources/text_paragraph.cpp +++ b/scene/resources/text_paragraph.cpp @@ -84,7 +84,7 @@ void TextParagraph::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width"), "set_width", "get_width"); - ClassDB::bind_method(D_METHOD("get_non_wraped_size"), &TextParagraph::get_non_wraped_size); + ClassDB::bind_method(D_METHOD("get_non_wrapped_size"), &TextParagraph::get_non_wrapped_size); ClassDB::bind_method(D_METHOD("get_size"), &TextParagraph::get_size); ClassDB::bind_method(D_METHOD("get_rid"), &TextParagraph::get_rid); @@ -417,7 +417,7 @@ float TextParagraph::get_width() const { return width; } -Size2 TextParagraph::get_non_wraped_size() const { +Size2 TextParagraph::get_non_wrapped_size() const { const_cast<TextParagraph *>(this)->_shape_lines(); if (TS->shaped_text_get_orientation(rid) == TextServer::ORIENTATION_HORIZONTAL) { return Size2(TS->shaped_text_get_size(rid).x, TS->shaped_text_get_size(rid).y + spacing_top + spacing_bottom); diff --git a/scene/resources/text_paragraph.h b/scene/resources/text_paragraph.h index 69c50559df..701c9a17cd 100644 --- a/scene/resources/text_paragraph.h +++ b/scene/resources/text_paragraph.h @@ -120,7 +120,7 @@ public: void set_max_lines_visible(int p_lines); int get_max_lines_visible() const; - Size2 get_non_wraped_size() const; + Size2 get_non_wrapped_size() const; Size2 get_size() const; diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index b988b2ab3e..a45b6b8eb6 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -31,6 +31,7 @@ #include "tile_set.h" #include "core/core_string_names.h" +#include "core/io/marshalls.h" #include "core/math/geometry_2d.h" #include "core/templates/local_vector.h" @@ -39,6 +40,189 @@ #include "scene/resources/convex_polygon_shape_2d.h" #include "servers/navigation_server_2d.h" +/////////////////////////////// TileMapPattern ////////////////////////////////////// + +void TileMapPattern::_set_tile_data(const Vector<int> &p_data) { + int c = p_data.size(); + const int *r = p_data.ptr(); + + int offset = 3; + ERR_FAIL_COND_MSG(c % offset != 0, "Corrupted tile data."); + + clear(); + + for (int i = 0; i < c; i += offset) { + const uint8_t *ptr = (const uint8_t *)&r[i]; + uint8_t local[12]; + for (int j = 0; j < 12; j++) { + local[j] = ptr[j]; + } + +#ifdef BIG_ENDIAN_ENABLED + SWAP(local[0], local[3]); + SWAP(local[1], local[2]); + SWAP(local[4], local[7]); + SWAP(local[5], local[6]); + SWAP(local[8], local[11]); + SWAP(local[9], local[10]); +#endif + + int16_t x = decode_uint16(&local[0]); + int16_t y = decode_uint16(&local[2]); + uint16_t source_id = decode_uint16(&local[4]); + uint16_t atlas_coords_x = decode_uint16(&local[6]); + uint16_t atlas_coords_y = decode_uint16(&local[8]); + uint16_t alternative_tile = decode_uint16(&local[10]); + set_cell(Vector2i(x, y), source_id, Vector2i(atlas_coords_x, atlas_coords_y), alternative_tile); + } + emit_signal(SNAME("changed")); +} + +Vector<int> TileMapPattern::_get_tile_data() const { + // Export tile data to raw format + Vector<int> data; + data.resize(pattern.size() * 3); + int *w = data.ptrw(); + + // Save in highest format + + int idx = 0; + for (const KeyValue<Vector2i, TileMapCell> &E : pattern) { + uint8_t *ptr = (uint8_t *)&w[idx]; + encode_uint16((int16_t)(E.key.x), &ptr[0]); + encode_uint16((int16_t)(E.key.y), &ptr[2]); + encode_uint16(E.value.source_id, &ptr[4]); + encode_uint16(E.value.coord_x, &ptr[6]); + encode_uint16(E.value.coord_y, &ptr[8]); + encode_uint16(E.value.alternative_tile, &ptr[10]); + idx += 3; + } + + return data; +} + +void TileMapPattern::set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile) { + ERR_FAIL_COND_MSG(p_coords.x < 0 || p_coords.y < 0, vformat("Cannot set cell with negative coords in a TileMapPattern. Wrong coords: %s", p_coords)); + + size = size.max(p_coords + Vector2i(1, 1)); + pattern[p_coords] = TileMapCell(p_source_id, p_atlas_coords, p_alternative_tile); + emit_changed(); +} + +bool TileMapPattern::has_cell(const Vector2i &p_coords) const { + return pattern.has(p_coords); +} + +void TileMapPattern::remove_cell(const Vector2i &p_coords, bool p_update_size) { + ERR_FAIL_COND(!pattern.has(p_coords)); + + pattern.erase(p_coords); + if (p_update_size) { + size = Vector2i(); + for (const KeyValue<Vector2i, TileMapCell> &E : pattern) { + size = size.max(E.key + Vector2i(1, 1)); + } + } + emit_changed(); +} + +int TileMapPattern::get_cell_source_id(const Vector2i &p_coords) const { + ERR_FAIL_COND_V(!pattern.has(p_coords), TileSet::INVALID_SOURCE); + + return pattern[p_coords].source_id; +} + +Vector2i TileMapPattern::get_cell_atlas_coords(const Vector2i &p_coords) const { + ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetSource::INVALID_ATLAS_COORDS); + + return pattern[p_coords].get_atlas_coords(); +} + +int TileMapPattern::get_cell_alternative_tile(const Vector2i &p_coords) const { + ERR_FAIL_COND_V(!pattern.has(p_coords), TileSetSource::INVALID_TILE_ALTERNATIVE); + + return pattern[p_coords].alternative_tile; +} + +TypedArray<Vector2i> TileMapPattern::get_used_cells() const { + // Returns the cells used in the tilemap. + TypedArray<Vector2i> a; + a.resize(pattern.size()); + int i = 0; + for (const KeyValue<Vector2i, TileMapCell> &E : pattern) { + Vector2i p(E.key.x, E.key.y); + a[i++] = p; + } + + return a; +} + +Vector2i TileMapPattern::get_size() const { + return size; +} + +void TileMapPattern::set_size(const Vector2i &p_size) { + for (const KeyValue<Vector2i, TileMapCell> &E : pattern) { + Vector2i coords = E.key; + if (p_size.x <= coords.x || p_size.y <= coords.y) { + ERR_FAIL_MSG(vformat("Cannot set pattern size to %s, it contains a tile at %s. Size can only be increased.", p_size, coords)); + }; + } + + size = p_size; + emit_changed(); +} + +bool TileMapPattern::is_empty() const { + return pattern.is_empty(); +}; + +void TileMapPattern::clear() { + size = Vector2i(); + pattern.clear(); + emit_changed(); +}; + +bool TileMapPattern::_set(const StringName &p_name, const Variant &p_value) { + if (p_name == "tile_data") { + if (p_value.is_array()) { + _set_tile_data(p_value); + return true; + } + return false; + } + return false; +} + +bool TileMapPattern::_get(const StringName &p_name, Variant &r_ret) const { + if (p_name == "tile_data") { + r_ret = _get_tile_data(); + return true; + } + return false; +} + +void TileMapPattern::_get_property_list(List<PropertyInfo> *p_list) const { + p_list->push_back(PropertyInfo(Variant::OBJECT, "tile_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL)); +} + +void TileMapPattern::_bind_methods() { + ClassDB::bind_method(D_METHOD("_set_tile_data", "data"), &TileMapPattern::_set_tile_data); + ClassDB::bind_method(D_METHOD("_get_tile_data"), &TileMapPattern::_get_tile_data); + + ClassDB::bind_method(D_METHOD("set_cell", "coords", "source_id", "atlas_coords", "alternative_tile"), &TileMapPattern::set_cell, DEFVAL(TileSet::INVALID_SOURCE), DEFVAL(TileSetSource::INVALID_ATLAS_COORDS), DEFVAL(TileSetSource::INVALID_TILE_ALTERNATIVE)); + ClassDB::bind_method(D_METHOD("has_cell", "coords"), &TileMapPattern::has_cell); + ClassDB::bind_method(D_METHOD("remove_cell", "coords"), &TileMapPattern::remove_cell); + ClassDB::bind_method(D_METHOD("get_cell_source_id", "coords"), &TileMapPattern::get_cell_source_id); + ClassDB::bind_method(D_METHOD("get_cell_atlas_coords", "coords"), &TileMapPattern::get_cell_atlas_coords); + ClassDB::bind_method(D_METHOD("get_cell_alternative_tile", "coords"), &TileMapPattern::get_cell_alternative_tile); + + ClassDB::bind_method(D_METHOD("get_used_cells"), &TileMapPattern::get_used_cells); + ClassDB::bind_method(D_METHOD("get_size"), &TileMapPattern::get_size); + ClassDB::bind_method(D_METHOD("set_size", "size"), &TileMapPattern::set_size); + ClassDB::bind_method(D_METHOD("is_empty"), &TileMapPattern::is_empty); +} + /////////////////////////////// TileSet ////////////////////////////////////// const int TileSet::INVALID_SOURCE = -1; @@ -982,6 +1166,36 @@ void TileSet::clear_tile_proxies() { emit_changed(); } +int TileSet::add_pattern(Ref<TileMapPattern> p_pattern, int p_index) { + ERR_FAIL_COND_V(!p_pattern.is_valid(), -1); + ERR_FAIL_COND_V_MSG(p_pattern->is_empty(), -1, "Cannot add an empty pattern to the TileSet."); + for (unsigned int i = 0; i < patterns.size(); i++) { + ERR_FAIL_COND_V_MSG(patterns[i] == p_pattern, -1, "TileSet has already this pattern."); + } + ERR_FAIL_COND_V(p_index > (int)patterns.size(), -1); + if (p_index < 0) { + p_index = patterns.size(); + } + patterns.insert(p_index, p_pattern); + emit_changed(); + return p_index; +} + +Ref<TileMapPattern> TileSet::get_pattern(int p_index) { + ERR_FAIL_INDEX_V(p_index, (int)patterns.size(), Ref<TileMapPattern>()); + return patterns[p_index]; +} + +void TileSet::remove_pattern(int p_index) { + ERR_FAIL_INDEX(p_index, (int)patterns.size()); + patterns.remove(p_index); + emit_changed(); +} + +int TileSet::get_patterns_count() { + return patterns.size(); +} + Vector<Vector2> TileSet::get_tile_shape_polygon() { Vector<Vector2> points; if (tile_shape == TileSet::TILE_SHAPE_SQUARE) { @@ -2483,6 +2697,12 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) { return true; } return false; + } else if (components.size() == 1 && components[0].begins_with("pattern_") && components[0].trim_prefix("pattern_").is_valid_int()) { + int pattern_index = components[0].trim_prefix("pattern_").to_int(); + for (int i = patterns.size(); i <= pattern_index; i++) { + add_pattern(p_value); + } + return true; } #ifndef DISABLE_DEPRECATED @@ -2606,6 +2826,13 @@ bool TileSet::_get(const StringName &p_name, Variant &r_ret) const { return true; } return false; + } else if (components.size() == 1 && components[0].begins_with("pattern_") && components[0].trim_prefix("pattern_").is_valid_int()) { + int pattern_index = components[0].trim_prefix("pattern_").to_int(); + if (pattern_index < 0 || pattern_index >= (int)patterns.size()) { + return false; + } + r_ret = patterns[pattern_index]; + return true; } return false; @@ -2686,6 +2913,11 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/source_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/coords_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::ARRAY, "tile_proxies/alternative_level", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); + + // Patterns. + for (unsigned int pattern_index = 0; pattern_index < patterns.size(); pattern_index++) { + p_list->push_back(PropertyInfo(Variant::OBJECT, vformat("pattern_%d", pattern_index), PROPERTY_HINT_RESOURCE_TYPE, "TileMapPattern", PROPERTY_USAGE_NOEDITOR)); + } } void TileSet::_validate_property(PropertyInfo &property) const { @@ -2799,6 +3031,12 @@ void TileSet::_bind_methods() { ClassDB::bind_method(D_METHOD("cleanup_invalid_tile_proxies"), &TileSet::cleanup_invalid_tile_proxies); ClassDB::bind_method(D_METHOD("clear_tile_proxies"), &TileSet::clear_tile_proxies); + // Patterns + ClassDB::bind_method(D_METHOD("add_pattern", "pattern", "index"), &TileSet::add_pattern, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("get_pattern", "index"), &TileSet::get_pattern, DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("remove_pattern", "index"), &TileSet::remove_pattern); + ClassDB::bind_method(D_METHOD("get_patterns_count"), &TileSet::get_patterns_count); + ADD_GROUP("Rendering", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uv_clipping"), "set_uv_clipping", "is_uv_clipping"); ADD_ARRAY("occlusion_layers", "occlusion_layer_"); diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 351bdff89d..530c90920f 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -60,6 +60,84 @@ class TileSetPluginAtlasRendering; class TileSetPluginAtlasPhysics; class TileSetPluginAtlasNavigation; +union TileMapCell { + struct { + int32_t source_id : 16; + int16_t coord_x : 16; + int16_t coord_y : 16; + int32_t alternative_tile : 16; + }; + + uint64_t _u64t; + TileMapCell(int p_source_id = -1, Vector2i p_atlas_coords = Vector2i(-1, -1), int p_alternative_tile = -1) { // default are INVALID_SOURCE, INVALID_ATLAS_COORDS, INVALID_TILE_ALTERNATIVE + source_id = p_source_id; + set_atlas_coords(p_atlas_coords); + alternative_tile = p_alternative_tile; + } + + Vector2i get_atlas_coords() const { + return Vector2i(coord_x, coord_y); + } + + void set_atlas_coords(const Vector2i &r_coords) { + coord_x = r_coords.x; + coord_y = r_coords.y; + } + + bool operator<(const TileMapCell &p_other) const { + if (source_id == p_other.source_id) { + if (coord_x == p_other.coord_x) { + if (coord_y == p_other.coord_y) { + return alternative_tile < p_other.alternative_tile; + } else { + return coord_y < p_other.coord_y; + } + } else { + return coord_x < p_other.coord_x; + } + } else { + return source_id < p_other.source_id; + } + } + + bool operator!=(const TileMapCell &p_other) const { + return !(source_id == p_other.source_id && coord_x == p_other.coord_x && coord_y == p_other.coord_y && alternative_tile == p_other.alternative_tile); + } +}; + +class TileMapPattern : public Resource { + GDCLASS(TileMapPattern, Resource); + + Vector2i size; + Map<Vector2i, TileMapCell> pattern; + + void _set_tile_data(const Vector<int> &p_data); + Vector<int> _get_tile_data() const; + +protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + + static void _bind_methods(); + +public: + void set_cell(const Vector2i &p_coords, int p_source_id, const Vector2i p_atlas_coords, int p_alternative_tile = 0); + bool has_cell(const Vector2i &p_coords) const; + void remove_cell(const Vector2i &p_coords, bool p_update_size = true); + int get_cell_source_id(const Vector2i &p_coords) const; + Vector2i get_cell_atlas_coords(const Vector2i &p_coords) const; + int get_cell_alternative_tile(const Vector2i &p_coords) const; + + TypedArray<Vector2i> get_used_cells() const; + + Vector2i get_size() const; + void set_size(const Vector2i &p_size); + bool is_empty() const; + + void clear(); +}; + class TileSet : public Resource { GDCLASS(TileSet, Resource); @@ -245,6 +323,8 @@ private: int next_source_id = 0; // --------------------- + LocalVector<Ref<TileMapPattern>> patterns; + void _compute_next_source_id(); void _source_changed(); @@ -384,6 +464,12 @@ public: void cleanup_invalid_tile_proxies(); void clear_tile_proxies(); + // Patterns. + int add_pattern(Ref<TileMapPattern> p_pattern, int p_index = -1); + Ref<TileMapPattern> get_pattern(int p_index); + void remove_pattern(int p_index); + int get_patterns_count(); + // Helpers Vector<Vector2> get_tile_shape_polygon(); void draw_tile_shape(CanvasItem *p_canvas_item, Transform2D p_transform, Color p_color, bool p_filled = false, Ref<Texture2D> p_texture = Ref<Texture2D>()); diff --git a/servers/audio/effects/audio_effect_limiter.h b/servers/audio/effects/audio_effect_limiter.h index d5def670a4..398613aa44 100644 --- a/servers/audio/effects/audio_effect_limiter.h +++ b/servers/audio/effects/audio_effect_limiter.h @@ -72,8 +72,6 @@ public: float get_soft_clip_ratio() const; Ref<AudioEffectInstance> instantiate() override; - void set_volume_db(float p_volume); - float get_volume_db() const; AudioEffectLimiter(); }; diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h index 1a89821f80..6e862b1377 100644 --- a/servers/audio/effects/audio_effect_record.h +++ b/servers/audio/effects/audio_effect_record.h @@ -93,7 +93,6 @@ class AudioEffectRecord : public AudioEffect { protected: static void _bind_methods(); - static void debug(uint64_t time_diff, int p_frame_count); public: Ref<AudioEffectInstance> instantiate() override; diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h index d01d1120bd..eaa66352f6 100644 --- a/servers/audio/effects/audio_effect_reverb.h +++ b/servers/audio/effects/audio_effect_reverb.h @@ -90,8 +90,6 @@ public: float get_hpf() const; Ref<AudioEffectInstance> instantiate() override; - void set_volume_db(float p_volume); - float get_volume_db() const; AudioEffectReverb(); }; diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index a420134626..ab704c6f78 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1131,8 +1131,10 @@ void AudioServer::start_playback_stream(Ref<AudioStreamPlayback> p_playback, Map AudioStreamPlaybackBusDetails *new_bus_details = new AudioStreamPlaybackBusDetails(); int idx = 0; for (KeyValue<StringName, Vector<AudioFrame>> pair : p_bus_volumes) { - ERR_FAIL_COND(pair.value.size() < channel_count); - ERR_FAIL_COND(pair.value.size() != MAX_CHANNELS_PER_BUS); + if (pair.value.size() < channel_count || pair.value.size() != MAX_CHANNELS_PER_BUS) { + delete new_bus_details; + ERR_FAIL(); + } new_bus_details->bus_active[idx] = true; new_bus_details->bus[idx] = pair.key; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 3897e5e7c2..a6101530c8 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -159,6 +159,14 @@ String DisplayServer::clipboard_get() const { ERR_FAIL_V_MSG(String(), "Clipboard is not supported by this display server."); } +void DisplayServer::clipboard_set_primary(const String &p_text) { + WARN_PRINT("Primary clipboard is not supported by this display server."); +} + +String DisplayServer::clipboard_get_primary() const { + ERR_FAIL_V_MSG(String(), "Primary clipboard is not supported by this display server."); +} + void DisplayServer::screen_set_orientation(ScreenOrientation p_orientation, int p_screen) { WARN_PRINT("Orientation not supported by this display server."); } @@ -360,6 +368,8 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("clipboard_set", "clipboard"), &DisplayServer::clipboard_set); ClassDB::bind_method(D_METHOD("clipboard_get"), &DisplayServer::clipboard_get); + ClassDB::bind_method(D_METHOD("clipboard_set_primary", "clipboard_primary"), &DisplayServer::clipboard_set_primary); + ClassDB::bind_method(D_METHOD("clipboard_get_primary"), &DisplayServer::clipboard_get_primary); ClassDB::bind_method(D_METHOD("get_screen_count"), &DisplayServer::get_screen_count); ClassDB::bind_method(D_METHOD("screen_get_position", "screen"), &DisplayServer::screen_get_position, DEFVAL(SCREEN_OF_MAIN_WINDOW)); diff --git a/servers/display_server.h b/servers/display_server.h index f411a72aa3..8af7946a1e 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -161,6 +161,8 @@ public: virtual void clipboard_set(const String &p_text); virtual String clipboard_get() const; + virtual void clipboard_set_primary(const String &p_text); + virtual String clipboard_get_primary() const; enum { SCREEN_OF_MAIN_WINDOW = -1 diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/godot_area_2d.cpp index c85b1575e3..7cb202dd1f 100644 --- a/servers/physics_2d/area_2d_sw.cpp +++ b/servers/physics_2d/godot_area_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* area_2d_sw.cpp */ +/* godot_area_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,31 +28,31 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "area_2d_sw.h" -#include "body_2d_sw.h" -#include "space_2d_sw.h" +#include "godot_area_2d.h" +#include "godot_body_2d.h" +#include "godot_space_2d.h" -Area2DSW::BodyKey::BodyKey(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { +GodotArea2D::BodyKey::BodyKey(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { rid = p_body->get_self(); instance_id = p_body->get_instance_id(); body_shape = p_body_shape; area_shape = p_area_shape; } -Area2DSW::BodyKey::BodyKey(Area2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { +GodotArea2D::BodyKey::BodyKey(GodotArea2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { rid = p_body->get_self(); instance_id = p_body->get_instance_id(); body_shape = p_body_shape; area_shape = p_area_shape; } -void Area2DSW::_shapes_changed() { +void GodotArea2D::_shapes_changed() { if (!moved_list.in_list() && get_space()) { get_space()->area_add_to_moved_list(&moved_list); } } -void Area2DSW::set_transform(const Transform2D &p_transform) { +void GodotArea2D::set_transform(const Transform2D &p_transform) { if (!moved_list.in_list() && get_space()) { get_space()->area_add_to_moved_list(&moved_list); } @@ -61,7 +61,7 @@ void Area2DSW::set_transform(const Transform2D &p_transform) { _set_inv_transform(p_transform.affine_inverse()); } -void Area2DSW::set_space(Space2DSW *p_space) { +void GodotArea2D::set_space(GodotSpace2D *p_space) { if (get_space()) { if (monitor_query_list.in_list()) { get_space()->area_remove_from_monitor_query_list(&monitor_query_list); @@ -77,7 +77,7 @@ void Area2DSW::set_space(Space2DSW *p_space) { _set_space(p_space); } -void Area2DSW::set_monitor_callback(ObjectID p_id, const StringName &p_method) { +void GodotArea2D::set_monitor_callback(ObjectID p_id, const StringName &p_method) { if (p_id == monitor_callback_id) { monitor_callback_method = p_method; return; @@ -98,7 +98,7 @@ void Area2DSW::set_monitor_callback(ObjectID p_id, const StringName &p_method) { } } -void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName &p_method) { +void GodotArea2D::set_area_monitor_callback(ObjectID p_id, const StringName &p_method) { if (p_id == area_monitor_callback_id) { area_monitor_callback_method = p_method; return; @@ -119,7 +119,7 @@ void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName &p_meth } } -void Area2DSW::set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode) { +void GodotArea2D::set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode) { bool do_override = p_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; if (do_override == (space_override_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED)) { return; @@ -129,7 +129,7 @@ void Area2DSW::set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_ _shape_changed(); } -void Area2DSW::set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value) { +void GodotArea2D::set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value) { switch (p_param) { case PhysicsServer2D::AREA_PARAM_GRAVITY: gravity = p_value; @@ -158,7 +158,7 @@ void Area2DSW::set_param(PhysicsServer2D::AreaParameter p_param, const Variant & } } -Variant Area2DSW::get_param(PhysicsServer2D::AreaParameter p_param) const { +Variant GodotArea2D::get_param(PhysicsServer2D::AreaParameter p_param) const { switch (p_param) { case PhysicsServer2D::AREA_PARAM_GRAVITY: return gravity; @@ -181,7 +181,7 @@ Variant Area2DSW::get_param(PhysicsServer2D::AreaParameter p_param) const { return Variant(); } -void Area2DSW::_queue_monitor_update() { +void GodotArea2D::_queue_monitor_update() { ERR_FAIL_COND(!get_space()); if (!monitor_query_list.in_list()) { @@ -189,7 +189,7 @@ void Area2DSW::_queue_monitor_update() { } } -void Area2DSW::set_monitorable(bool p_monitorable) { +void GodotArea2D::set_monitorable(bool p_monitorable) { if (monitorable == p_monitorable) { return; } @@ -198,7 +198,7 @@ void Area2DSW::set_monitorable(bool p_monitorable) { _set_static(!monitorable); } -void Area2DSW::call_queries() { +void GodotArea2D::call_queries() { if (monitor_callback_id.is_valid() && !monitored_bodies.is_empty()) { Variant res[5]; Variant *resptr[5]; @@ -274,7 +274,7 @@ void Area2DSW::call_queries() { } } -void Area2DSW::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const { +void GodotArea2D::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const { if (is_gravity_point()) { const real_t gravity_distance_scale = get_gravity_distance_scale(); Vector2 v = get_transform().xform(get_gravity_vector()) - p_position; @@ -294,12 +294,12 @@ void Area2DSW::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) co } } -Area2DSW::Area2DSW() : - CollisionObject2DSW(TYPE_AREA), +GodotArea2D::GodotArea2D() : + GodotCollisionObject2D(TYPE_AREA), monitor_query_list(this), moved_list(this) { _set_static(true); //areas are not active by default } -Area2DSW::~Area2DSW() { +GodotArea2D::~GodotArea2D() { } diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/godot_area_2d.h index 0b7c791ed5..daa03d39e3 100644 --- a/servers/physics_2d/area_2d_sw.h +++ b/servers/physics_2d/godot_area_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* area_2d_sw.h */ +/* godot_area_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,18 +28,19 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AREA_2D_SW_H -#define AREA_2D_SW_H +#ifndef GODOT_AREA_2D_H +#define GODOT_AREA_2D_H + +#include "godot_collision_object_2d.h" -#include "collision_object_2d_sw.h" #include "core/templates/self_list.h" #include "servers/physics_server_2d.h" -class Space2DSW; -class Body2DSW; -class Constraint2DSW; +class GodotSpace2D; +class GodotBody2D; +class GodotConstraint2D; -class Area2DSW : public CollisionObject2DSW { +class GodotArea2D : public GodotCollisionObject2D { PhysicsServer2D::AreaSpaceOverrideMode space_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; real_t gravity = 9.80665; Vector2 gravity_vector = Vector2(0, -1); @@ -57,8 +58,8 @@ class Area2DSW : public CollisionObject2DSW { ObjectID area_monitor_callback_id; StringName area_monitor_callback_method; - SelfList<Area2DSW> monitor_query_list; - SelfList<Area2DSW> moved_list; + SelfList<GodotArea2D> monitor_query_list; + SelfList<GodotArea2D> moved_list; struct BodyKey { RID rid; @@ -79,8 +80,8 @@ class Area2DSW : public CollisionObject2DSW { } _FORCE_INLINE_ BodyKey() {} - BodyKey(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); - BodyKey(Area2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + BodyKey(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + BodyKey(GodotArea2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); }; struct BodyState { @@ -92,7 +93,7 @@ class Area2DSW : public CollisionObject2DSW { Map<BodyKey, BodyState> monitored_bodies; Map<BodyKey, BodyState> monitored_areas; - Set<Constraint2DSW *> constraints; + Set<GodotConstraint2D *> constraints; virtual void _shapes_changed(); void _queue_monitor_update(); @@ -104,11 +105,11 @@ public: void set_area_monitor_callback(ObjectID p_id, const StringName &p_method); _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); } - _FORCE_INLINE_ void add_body_to_query(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); - _FORCE_INLINE_ void remove_body_from_query(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + _FORCE_INLINE_ void add_body_to_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + _FORCE_INLINE_ void remove_body_from_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); - _FORCE_INLINE_ void add_area_to_query(Area2DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape); - _FORCE_INLINE_ void remove_area_from_query(Area2DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape); + _FORCE_INLINE_ void add_area_to_query(GodotArea2D *p_area, uint32_t p_area_shape, uint32_t p_self_shape); + _FORCE_INLINE_ void remove_area_from_query(GodotArea2D *p_area, uint32_t p_area_shape, uint32_t p_self_shape); void set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value); Variant get_param(PhysicsServer2D::AreaParameter p_param) const; @@ -140,9 +141,9 @@ public: _FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; } _FORCE_INLINE_ int get_priority() const { return priority; } - _FORCE_INLINE_ void add_constraint(Constraint2DSW *p_constraint) { constraints.insert(p_constraint); } - _FORCE_INLINE_ void remove_constraint(Constraint2DSW *p_constraint) { constraints.erase(p_constraint); } - _FORCE_INLINE_ const Set<Constraint2DSW *> &get_constraints() const { return constraints; } + _FORCE_INLINE_ void add_constraint(GodotConstraint2D *p_constraint) { constraints.insert(p_constraint); } + _FORCE_INLINE_ void remove_constraint(GodotConstraint2D *p_constraint) { constraints.erase(p_constraint); } + _FORCE_INLINE_ const Set<GodotConstraint2D *> &get_constraints() const { return constraints; } _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } void set_monitorable(bool p_monitorable); @@ -150,17 +151,17 @@ public: void set_transform(const Transform2D &p_transform); - void set_space(Space2DSW *p_space); + void set_space(GodotSpace2D *p_space); void call_queries(); void compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const; - Area2DSW(); - ~Area2DSW(); + GodotArea2D(); + ~GodotArea2D(); }; -void Area2DSW::add_body_to_query(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { +void GodotArea2D::add_body_to_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { BodyKey bk(p_body, p_body_shape, p_area_shape); monitored_bodies[bk].inc(); if (!monitor_query_list.in_list()) { @@ -168,7 +169,7 @@ void Area2DSW::add_body_to_query(Body2DSW *p_body, uint32_t p_body_shape, uint32 } } -void Area2DSW::remove_body_from_query(Body2DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { +void GodotArea2D::remove_body_from_query(GodotBody2D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { BodyKey bk(p_body, p_body_shape, p_area_shape); monitored_bodies[bk].dec(); if (!monitor_query_list.in_list()) { @@ -176,7 +177,7 @@ void Area2DSW::remove_body_from_query(Body2DSW *p_body, uint32_t p_body_shape, u } } -void Area2DSW::add_area_to_query(Area2DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { +void GodotArea2D::add_area_to_query(GodotArea2D *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { BodyKey bk(p_area, p_area_shape, p_self_shape); monitored_areas[bk].inc(); if (!monitor_query_list.in_list()) { @@ -184,7 +185,7 @@ void Area2DSW::add_area_to_query(Area2DSW *p_area, uint32_t p_area_shape, uint32 } } -void Area2DSW::remove_area_from_query(Area2DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { +void GodotArea2D::remove_area_from_query(GodotArea2D *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { BodyKey bk(p_area, p_area_shape, p_self_shape); monitored_areas[bk].dec(); if (!monitor_query_list.in_list()) { @@ -192,4 +193,4 @@ void Area2DSW::remove_area_from_query(Area2DSW *p_area, uint32_t p_area_shape, u } } -#endif // AREA_2D_SW_H +#endif // GODOT_AREA_2D_H diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/godot_area_pair_2d.cpp index 4f1148c26f..fdb95aa262 100644 --- a/servers/physics_2d/area_pair_2d_sw.cpp +++ b/servers/physics_2d/godot_area_pair_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* area_pair_2d_sw.cpp */ +/* godot_area_pair_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "area_pair_2d_sw.h" -#include "collision_solver_2d_sw.h" +#include "godot_area_pair_2d.h" +#include "godot_collision_solver_2d.h" -bool AreaPair2DSW::setup(real_t p_step) { +bool GodotAreaPair2D::setup(real_t p_step) { bool result = false; - if (area->collides_with(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) { + if (area->collides_with(body) && GodotCollisionSolver2D::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) { result = true; } @@ -51,7 +51,7 @@ bool AreaPair2DSW::setup(real_t p_step) { return process_collision; } -bool AreaPair2DSW::pre_solve(real_t p_step) { +bool GodotAreaPair2D::pre_solve(real_t p_step) { if (!process_collision) { return false; } @@ -77,11 +77,11 @@ bool AreaPair2DSW::pre_solve(real_t p_step) { return false; // Never do any post solving. } -void AreaPair2DSW::solve(real_t p_step) { +void GodotAreaPair2D::solve(real_t p_step) { // Nothing to do. } -AreaPair2DSW::AreaPair2DSW(Body2DSW *p_body, int p_body_shape, Area2DSW *p_area, int p_area_shape) { +GodotAreaPair2D::GodotAreaPair2D(GodotBody2D *p_body, int p_body_shape, GodotArea2D *p_area, int p_area_shape) { body = p_body; area = p_area; body_shape = p_body_shape; @@ -93,7 +93,7 @@ AreaPair2DSW::AreaPair2DSW(Body2DSW *p_body, int p_body_shape, Area2DSW *p_area, } } -AreaPair2DSW::~AreaPair2DSW() { +GodotAreaPair2D::~GodotAreaPair2D() { if (colliding) { if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) { body->remove_area(area); @@ -108,10 +108,10 @@ AreaPair2DSW::~AreaPair2DSW() { ////////////////////////////////// -bool Area2Pair2DSW::setup(real_t p_step) { +bool GodotArea2Pair2D::setup(real_t p_step) { bool result_a = area_a->collides_with(area_b); bool result_b = area_b->collides_with(area_a); - if ((result_a || result_b) && !CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) { + if ((result_a || result_b) && !GodotCollisionSolver2D::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) { result_a = false; result_b = false; } @@ -139,7 +139,7 @@ bool Area2Pair2DSW::setup(real_t p_step) { return process_collision; } -bool Area2Pair2DSW::pre_solve(real_t p_step) { +bool GodotArea2Pair2D::pre_solve(real_t p_step) { if (process_collision_a) { if (colliding_a) { area_a->add_area_to_query(area_b, shape_b, shape_a); @@ -159,11 +159,11 @@ bool Area2Pair2DSW::pre_solve(real_t p_step) { return false; // Never do any post solving. } -void Area2Pair2DSW::solve(real_t p_step) { +void GodotArea2Pair2D::solve(real_t p_step) { // Nothing to do. } -Area2Pair2DSW::Area2Pair2DSW(Area2DSW *p_area_a, int p_shape_a, Area2DSW *p_area_b, int p_shape_b) { +GodotArea2Pair2D::GodotArea2Pair2D(GodotArea2D *p_area_a, int p_shape_a, GodotArea2D *p_area_b, int p_shape_b) { area_a = p_area_a; area_b = p_area_b; shape_a = p_shape_a; @@ -172,7 +172,7 @@ Area2Pair2DSW::Area2Pair2DSW(Area2DSW *p_area_a, int p_shape_a, Area2DSW *p_area area_b->add_constraint(this); } -Area2Pair2DSW::~Area2Pair2DSW() { +GodotArea2Pair2D::~GodotArea2Pair2D() { if (colliding_a) { if (area_a->has_area_monitor_callback()) { area_a->remove_area_from_query(area_b, shape_b, shape_a); diff --git a/servers/physics_2d/area_pair_2d_sw.h b/servers/physics_2d/godot_area_pair_2d.h index 66e9f1afee..7a9677f714 100644 --- a/servers/physics_2d/area_pair_2d_sw.h +++ b/servers/physics_2d/godot_area_pair_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* area_pair_2d_sw.h */ +/* godot_area_pair_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,16 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AREA_PAIR_2D_SW_H -#define AREA_PAIR_2D_SW_H +#ifndef GODOT_AREA_PAIR_2D_H +#define GODOT_AREA_PAIR_2D_H -#include "area_2d_sw.h" -#include "body_2d_sw.h" -#include "constraint_2d_sw.h" +#include "godot_area_2d.h" +#include "godot_body_2d.h" +#include "godot_constraint_2d.h" -class AreaPair2DSW : public Constraint2DSW { - Body2DSW *body = nullptr; - Area2DSW *area = nullptr; +class GodotAreaPair2D : public GodotConstraint2D { + GodotBody2D *body = nullptr; + GodotArea2D *area = nullptr; int body_shape = 0; int area_shape = 0; bool colliding = false; @@ -48,13 +48,13 @@ public: virtual bool pre_solve(real_t p_step) override; virtual void solve(real_t p_step) override; - AreaPair2DSW(Body2DSW *p_body, int p_body_shape, Area2DSW *p_area, int p_area_shape); - ~AreaPair2DSW(); + GodotAreaPair2D(GodotBody2D *p_body, int p_body_shape, GodotArea2D *p_area, int p_area_shape); + ~GodotAreaPair2D(); }; -class Area2Pair2DSW : public Constraint2DSW { - Area2DSW *area_a = nullptr; - Area2DSW *area_b = nullptr; +class GodotArea2Pair2D : public GodotConstraint2D { + GodotArea2D *area_a = nullptr; + GodotArea2D *area_b = nullptr; int shape_a = 0; int shape_b = 0; bool colliding_a = false; @@ -67,8 +67,8 @@ public: virtual bool pre_solve(real_t p_step) override; virtual void solve(real_t p_step) override; - Area2Pair2DSW(Area2DSW *p_area_a, int p_shape_a, Area2DSW *p_area_b, int p_shape_b); - ~Area2Pair2DSW(); + GodotArea2Pair2D(GodotArea2D *p_area_a, int p_shape_a, GodotArea2D *p_area_b, int p_shape_b); + ~GodotArea2Pair2D(); }; -#endif // AREA_PAIR_2D_SW_H +#endif // GODOT_AREA_PAIR_2D_H diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/godot_body_2d.cpp index 38b98b7bca..a18c748e1d 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/godot_body_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_2d_sw.cpp */ +/* godot_body_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,19 +28,19 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "body_2d_sw.h" +#include "godot_body_2d.h" -#include "area_2d_sw.h" -#include "body_direct_state_2d_sw.h" -#include "space_2d_sw.h" +#include "godot_area_2d.h" +#include "godot_body_direct_state_2d.h" +#include "godot_space_2d.h" -void Body2DSW::_mass_properties_changed() { +void GodotBody2D::_mass_properties_changed() { if (get_space() && !mass_properties_update_list.in_list() && (calculate_inertia || calculate_center_of_mass)) { get_space()->body_add_to_mass_properties_update_list(&mass_properties_update_list); } } -void Body2DSW::update_mass_properties() { +void GodotBody2D::update_mass_properties() { //update shapes and motions switch (mode) { @@ -83,7 +83,7 @@ void Body2DSW::update_mass_properties() { continue; } - const Shape2DSW *shape = get_shape(i); + const GodotShape2D *shape = get_shape(i); real_t area = get_shape_aabb(i).get_area(); if (area == 0.0) { @@ -119,15 +119,17 @@ void Body2DSW::update_mass_properties() { } break; } + + _update_transform_dependent(); } -void Body2DSW::reset_mass_properties() { +void GodotBody2D::reset_mass_properties() { calculate_inertia = true; calculate_center_of_mass = true; _mass_properties_changed(); } -void Body2DSW::set_active(bool p_active) { +void GodotBody2D::set_active(bool p_active) { if (active == p_active) { return; } @@ -146,7 +148,7 @@ void Body2DSW::set_active(bool p_active) { } } -void Body2DSW::set_param(PhysicsServer2D::BodyParameter p_param, const Variant &p_value) { +void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Variant &p_value) { switch (p_param) { case PhysicsServer2D::BODY_PARAM_BOUNCE: { bounce = p_value; @@ -179,7 +181,8 @@ void Body2DSW::set_param(PhysicsServer2D::BodyParameter p_param, const Variant & } break; case PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS: { calculate_center_of_mass = false; - center_of_mass = p_value; + center_of_mass_local = p_value; + _update_transform_dependent(); } break; case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: { gravity_scale = p_value; @@ -195,7 +198,7 @@ void Body2DSW::set_param(PhysicsServer2D::BodyParameter p_param, const Variant & } } -Variant Body2DSW::get_param(PhysicsServer2D::BodyParameter p_param) const { +Variant GodotBody2D::get_param(PhysicsServer2D::BodyParameter p_param) const { switch (p_param) { case PhysicsServer2D::BODY_PARAM_BOUNCE: { return bounce; @@ -228,7 +231,7 @@ Variant Body2DSW::get_param(PhysicsServer2D::BodyParameter p_param) const { return 0; } -void Body2DSW::set_mode(PhysicsServer2D::BodyMode p_mode) { +void GodotBody2D::set_mode(PhysicsServer2D::BodyMode p_mode) { PhysicsServer2D::BodyMode prev = mode; mode = p_mode; @@ -267,16 +270,17 @@ void Body2DSW::set_mode(PhysicsServer2D::BodyMode p_mode) { } } -PhysicsServer2D::BodyMode Body2DSW::get_mode() const { +PhysicsServer2D::BodyMode GodotBody2D::get_mode() const { return mode; } -void Body2DSW::_shapes_changed() { +void GodotBody2D::_shapes_changed() { _mass_properties_changed(); + wakeup(); wakeup_neighbours(); } -void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_variant) { +void GodotBody2D::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_variant) { switch (p_state) { case PhysicsServer2D::BODY_STATE_TRANSFORM: { if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) { @@ -301,6 +305,7 @@ void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_va } _set_transform(t); _set_inv_transform(get_transform().inverse()); + _update_transform_dependent(); } wakeup(); @@ -344,7 +349,7 @@ void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_va } } -Variant Body2DSW::get_state(PhysicsServer2D::BodyState p_state) const { +Variant GodotBody2D::get_state(PhysicsServer2D::BodyState p_state) const { switch (p_state) { case PhysicsServer2D::BODY_STATE_TRANSFORM: { return get_transform(); @@ -366,7 +371,7 @@ Variant Body2DSW::get_state(PhysicsServer2D::BodyState p_state) const { return Variant(); } -void Body2DSW::set_space(Space2DSW *p_space) { +void GodotBody2D::set_space(GodotSpace2D *p_space) { if (get_space()) { wakeup_neighbours(); @@ -391,7 +396,7 @@ void Body2DSW::set_space(Space2DSW *p_space) { } } -void Body2DSW::_compute_area_gravity_and_damping(const Area2DSW *p_area) { +void GodotBody2D::_compute_area_gravity_and_damping(const GodotArea2D *p_area) { Vector2 area_gravity; p_area->compute_gravity(get_transform().get_origin(), area_gravity); gravity += area_gravity; @@ -400,13 +405,17 @@ void Body2DSW::_compute_area_gravity_and_damping(const Area2DSW *p_area) { area_angular_damp += p_area->get_angular_damp(); } -void Body2DSW::integrate_forces(real_t p_step) { +void GodotBody2D::_update_transform_dependent() { + center_of_mass = get_transform().basis_xform(center_of_mass_local); +} + +void GodotBody2D::integrate_forces(real_t p_step) { if (mode == PhysicsServer2D::BODY_MODE_STATIC) { return; } - Area2DSW *def_area = get_space()->get_default_area(); - // Area2DSW *damp_area = def_area; + GodotArea2D *def_area = get_space()->get_default_area(); + // GodotArea2D *damp_area = def_area; ERR_FAIL_COND(!def_area); int ac = areas.size(); @@ -528,7 +537,7 @@ void Body2DSW::integrate_forces(real_t p_step) { contact_count = 0; } -void Body2DSW::integrate_velocities(real_t p_step) { +void GodotBody2D::integrate_velocities(real_t p_step) { if (mode == PhysicsServer2D::BODY_MODE_STATIC) { return; } @@ -568,19 +577,21 @@ void Body2DSW::integrate_velocities(real_t p_step) { if (continuous_cd_mode != PhysicsServer2D::CCD_MODE_DISABLED) { new_transform = get_transform(); } + + _update_transform_dependent(); } -void Body2DSW::wakeup_neighbours() { - for (const Pair<Constraint2DSW *, int> &E : constraint_list) { - const Constraint2DSW *c = E.first; - Body2DSW **n = c->get_body_ptr(); +void GodotBody2D::wakeup_neighbours() { + for (const Pair<GodotConstraint2D *, int> &E : constraint_list) { + const GodotConstraint2D *c = E.first; + GodotBody2D **n = c->get_body_ptr(); int bc = c->get_body_count(); for (int i = 0; i < bc; i++) { if (i == E.second) { continue; } - Body2DSW *b = n[i]; + GodotBody2D *b = n[i]; if (b->mode < PhysicsServer2D::BODY_MODE_DYNAMIC) { continue; } @@ -592,7 +603,7 @@ void Body2DSW::wakeup_neighbours() { } } -void Body2DSW::call_queries() { +void GodotBody2D::call_queries() { if (fi_callback_data) { if (!fi_callback_data->callable.get_object()) { set_force_integration_callback(Callable()); @@ -616,7 +627,7 @@ void Body2DSW::call_queries() { } } -bool Body2DSW::sleep_test(real_t p_step) { +bool GodotBody2D::sleep_test(real_t p_step) { if (mode == PhysicsServer2D::BODY_MODE_STATIC || mode == PhysicsServer2D::BODY_MODE_KINEMATIC) { return true; } else if (!can_sleep) { @@ -633,12 +644,12 @@ bool Body2DSW::sleep_test(real_t p_step) { } } -void Body2DSW::set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback) { +void GodotBody2D::set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback) { body_state_callback_instance = p_instance; body_state_callback = p_callback; } -void Body2DSW::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) { +void GodotBody2D::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) { if (p_callable.get_object()) { if (!fi_callback_data) { fi_callback_data = memnew(ForceIntegrationCallbackData); @@ -651,23 +662,23 @@ void Body2DSW::set_force_integration_callback(const Callable &p_callable, const } } -PhysicsDirectBodyState2DSW *Body2DSW::get_direct_state() { +GodotPhysicsDirectBodyState2D *GodotBody2D::get_direct_state() { if (!direct_state) { - direct_state = memnew(PhysicsDirectBodyState2DSW); + direct_state = memnew(GodotPhysicsDirectBodyState2D); direct_state->body = this; } return direct_state; } -Body2DSW::Body2DSW() : - CollisionObject2DSW(TYPE_BODY), +GodotBody2D::GodotBody2D() : + GodotCollisionObject2D(TYPE_BODY), active_list(this), mass_properties_update_list(this), direct_state_query_list(this) { _set_static(false); } -Body2DSW::~Body2DSW() { +GodotBody2D::~GodotBody2D() { if (fi_callback_data) { memdelete(fi_callback_data); } diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/godot_body_2d.h index 822ff76fae..5fce362fa7 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/godot_body_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_2d_sw.h */ +/* godot_body_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,19 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BODY_2D_SW_H -#define BODY_2D_SW_H +#ifndef GODOT_BODY_2D_H +#define GODOT_BODY_2D_H + +#include "godot_area_2d.h" +#include "godot_collision_object_2d.h" -#include "area_2d_sw.h" -#include "collision_object_2d_sw.h" #include "core/templates/list.h" #include "core/templates/pair.h" #include "core/templates/vset.h" -class Constraint2DSW; -class PhysicsDirectBodyState2DSW; +class GodotConstraint2D; +class GodotPhysicsDirectBodyState2D; -class Body2DSW : public CollisionObject2DSW { +class GodotBody2D : public GodotCollisionObject2D { PhysicsServer2D::BodyMode mode = PhysicsServer2D::BODY_MODE_DYNAMIC; Vector2 biased_linear_velocity; @@ -65,6 +66,7 @@ class Body2DSW : public CollisionObject2DSW { real_t inertia = 0.0; real_t _inv_inertia = 0.0; + Vector2 center_of_mass_local; Vector2 center_of_mass; bool calculate_inertia = true; @@ -79,9 +81,9 @@ class Body2DSW : public CollisionObject2DSW { Vector2 applied_force; real_t applied_torque = 0.0; - SelfList<Body2DSW> active_list; - SelfList<Body2DSW> mass_properties_update_list; - SelfList<Body2DSW> direct_state_query_list; + SelfList<GodotBody2D> active_list; + SelfList<GodotBody2D> mass_properties_update_list; + SelfList<GodotBody2D> direct_state_query_list; VSet<RID> exceptions; PhysicsServer2D::CCDMode continuous_cd_mode = PhysicsServer2D::CCD_MODE_DISABLED; @@ -93,15 +95,15 @@ class Body2DSW : public CollisionObject2DSW { virtual void _shapes_changed(); Transform2D new_transform; - List<Pair<Constraint2DSW *, int>> constraint_list; + List<Pair<GodotConstraint2D *, int>> constraint_list; struct AreaCMP { - Area2DSW *area = nullptr; + GodotArea2D *area = nullptr; int refCount = 0; _FORCE_INLINE_ bool operator==(const AreaCMP &p_cmp) const { return area->get_self() == p_cmp.area->get_self(); } _FORCE_INLINE_ bool operator<(const AreaCMP &p_cmp) const { return area->get_priority() < p_cmp.area->get_priority(); } _FORCE_INLINE_ AreaCMP() {} - _FORCE_INLINE_ AreaCMP(Area2DSW *p_area) { + _FORCE_INLINE_ AreaCMP(GodotArea2D *p_area) { area = p_area; refCount = 1; } @@ -134,21 +136,23 @@ class Body2DSW : public CollisionObject2DSW { ForceIntegrationCallbackData *fi_callback_data = nullptr; - PhysicsDirectBodyState2DSW *direct_state = nullptr; + GodotPhysicsDirectBodyState2D *direct_state = nullptr; uint64_t island_step = 0; - _FORCE_INLINE_ void _compute_area_gravity_and_damping(const Area2DSW *p_area); + void _compute_area_gravity_and_damping(const GodotArea2D *p_area); + + void _update_transform_dependent(); - friend class PhysicsDirectBodyState2DSW; // i give up, too many functions to expose + friend class GodotPhysicsDirectBodyState2D; // i give up, too many functions to expose public: void set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback); void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant()); - PhysicsDirectBodyState2DSW *get_direct_state(); + GodotPhysicsDirectBodyState2D *get_direct_state(); - _FORCE_INLINE_ void add_area(Area2DSW *p_area) { + _FORCE_INLINE_ void add_area(GodotArea2D *p_area) { int index = areas.find(AreaCMP(p_area)); if (index > -1) { areas.write[index].refCount += 1; @@ -157,7 +161,7 @@ public: } } - _FORCE_INLINE_ void remove_area(Area2DSW *p_area) { + _FORCE_INLINE_ void remove_area(GodotArea2D *p_area) { int index = areas.find(AreaCMP(p_area)); if (index > -1) { areas.write[index].refCount -= 1; @@ -188,9 +192,9 @@ public: _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } - _FORCE_INLINE_ void add_constraint(Constraint2DSW *p_constraint, int p_pos) { constraint_list.push_back({ p_constraint, p_pos }); } - _FORCE_INLINE_ void remove_constraint(Constraint2DSW *p_constraint, int p_pos) { constraint_list.erase({ p_constraint, p_pos }); } - const List<Pair<Constraint2DSW *, int>> &get_constraint_list() const { return constraint_list; } + _FORCE_INLINE_ void add_constraint(GodotConstraint2D *p_constraint, int p_pos) { constraint_list.push_back({ p_constraint, p_pos }); } + _FORCE_INLINE_ void remove_constraint(GodotConstraint2D *p_constraint, int p_pos) { constraint_list.erase({ p_constraint, p_pos }); } + const List<Pair<GodotConstraint2D *, int>> &get_constraint_list() const { return constraint_list; } _FORCE_INLINE_ void clear_constraint_list() { constraint_list.clear(); } _FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; } @@ -267,7 +271,7 @@ public: _FORCE_INLINE_ void set_continuous_collision_detection_mode(PhysicsServer2D::CCDMode p_mode) { continuous_cd_mode = p_mode; } _FORCE_INLINE_ PhysicsServer2D::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; } - void set_space(Space2DSW *p_space); + void set_space(GodotSpace2D *p_space); void update_mass_properties(); void reset_mass_properties(); @@ -302,13 +306,13 @@ public: bool sleep_test(real_t p_step); - Body2DSW(); - ~Body2DSW(); + GodotBody2D(); + ~GodotBody2D(); }; //add contact inline -void Body2DSW::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_normal, real_t p_depth, int p_local_shape, const Vector2 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector2 &p_collider_velocity_at_pos) { +void GodotBody2D::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_normal, real_t p_depth, int p_local_shape, const Vector2 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector2 &p_collider_velocity_at_pos) { int c_max = contacts.size(); if (c_max == 0) { @@ -350,4 +354,4 @@ void Body2DSW::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_no c[idx].collider_velocity_at_pos = p_collider_velocity_at_pos; } -#endif // BODY_2D_SW_H +#endif // GODOT_BODY_2D_H diff --git a/servers/physics_2d/body_direct_state_2d_sw.cpp b/servers/physics_2d/godot_body_direct_state_2d.cpp index b0673b9006..300c302c79 100644 --- a/servers/physics_2d/body_direct_state_2d_sw.cpp +++ b/servers/physics_2d/godot_body_direct_state_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_direct_state_2d_sw.cpp */ +/* godot_body_direct_state_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,151 +28,151 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "body_direct_state_2d_sw.h" +#include "godot_body_direct_state_2d.h" -#include "body_2d_sw.h" -#include "physics_server_2d_sw.h" -#include "space_2d_sw.h" +#include "godot_body_2d.h" +#include "godot_physics_server_2d.h" +#include "godot_space_2d.h" -Vector2 PhysicsDirectBodyState2DSW::get_total_gravity() const { +Vector2 GodotPhysicsDirectBodyState2D::get_total_gravity() const { return body->gravity; } -real_t PhysicsDirectBodyState2DSW::get_total_angular_damp() const { +real_t GodotPhysicsDirectBodyState2D::get_total_angular_damp() const { return body->area_angular_damp; } -real_t PhysicsDirectBodyState2DSW::get_total_linear_damp() const { +real_t GodotPhysicsDirectBodyState2D::get_total_linear_damp() const { return body->area_linear_damp; } -Vector2 PhysicsDirectBodyState2DSW::get_center_of_mass() const { +Vector2 GodotPhysicsDirectBodyState2D::get_center_of_mass() const { return body->get_center_of_mass(); } -real_t PhysicsDirectBodyState2DSW::get_inverse_mass() const { +real_t GodotPhysicsDirectBodyState2D::get_inverse_mass() const { return body->get_inv_mass(); } -real_t PhysicsDirectBodyState2DSW::get_inverse_inertia() const { +real_t GodotPhysicsDirectBodyState2D::get_inverse_inertia() const { return body->get_inv_inertia(); } -void PhysicsDirectBodyState2DSW::set_linear_velocity(const Vector2 &p_velocity) { +void GodotPhysicsDirectBodyState2D::set_linear_velocity(const Vector2 &p_velocity) { body->wakeup(); body->set_linear_velocity(p_velocity); } -Vector2 PhysicsDirectBodyState2DSW::get_linear_velocity() const { +Vector2 GodotPhysicsDirectBodyState2D::get_linear_velocity() const { return body->get_linear_velocity(); } -void PhysicsDirectBodyState2DSW::set_angular_velocity(real_t p_velocity) { +void GodotPhysicsDirectBodyState2D::set_angular_velocity(real_t p_velocity) { body->wakeup(); body->set_angular_velocity(p_velocity); } -real_t PhysicsDirectBodyState2DSW::get_angular_velocity() const { +real_t GodotPhysicsDirectBodyState2D::get_angular_velocity() const { return body->get_angular_velocity(); } -void PhysicsDirectBodyState2DSW::set_transform(const Transform2D &p_transform) { +void GodotPhysicsDirectBodyState2D::set_transform(const Transform2D &p_transform) { body->set_state(PhysicsServer2D::BODY_STATE_TRANSFORM, p_transform); } -Transform2D PhysicsDirectBodyState2DSW::get_transform() const { +Transform2D GodotPhysicsDirectBodyState2D::get_transform() const { return body->get_transform(); } -Vector2 PhysicsDirectBodyState2DSW::get_velocity_at_local_position(const Vector2 &p_position) const { +Vector2 GodotPhysicsDirectBodyState2D::get_velocity_at_local_position(const Vector2 &p_position) const { return body->get_velocity_in_local_point(p_position); } -void PhysicsDirectBodyState2DSW::add_central_force(const Vector2 &p_force) { +void GodotPhysicsDirectBodyState2D::add_central_force(const Vector2 &p_force) { body->wakeup(); body->add_central_force(p_force); } -void PhysicsDirectBodyState2DSW::add_force(const Vector2 &p_force, const Vector2 &p_position) { +void GodotPhysicsDirectBodyState2D::add_force(const Vector2 &p_force, const Vector2 &p_position) { body->wakeup(); body->add_force(p_force, p_position); } -void PhysicsDirectBodyState2DSW::add_torque(real_t p_torque) { +void GodotPhysicsDirectBodyState2D::add_torque(real_t p_torque) { body->wakeup(); body->add_torque(p_torque); } -void PhysicsDirectBodyState2DSW::apply_central_impulse(const Vector2 &p_impulse) { +void GodotPhysicsDirectBodyState2D::apply_central_impulse(const Vector2 &p_impulse) { body->wakeup(); body->apply_central_impulse(p_impulse); } -void PhysicsDirectBodyState2DSW::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) { +void GodotPhysicsDirectBodyState2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) { body->wakeup(); body->apply_impulse(p_impulse, p_position); } -void PhysicsDirectBodyState2DSW::apply_torque_impulse(real_t p_torque) { +void GodotPhysicsDirectBodyState2D::apply_torque_impulse(real_t p_torque) { body->wakeup(); body->apply_torque_impulse(p_torque); } -void PhysicsDirectBodyState2DSW::set_sleep_state(bool p_enable) { +void GodotPhysicsDirectBodyState2D::set_sleep_state(bool p_enable) { body->set_active(!p_enable); } -bool PhysicsDirectBodyState2DSW::is_sleeping() const { +bool GodotPhysicsDirectBodyState2D::is_sleeping() const { return !body->is_active(); } -int PhysicsDirectBodyState2DSW::get_contact_count() const { +int GodotPhysicsDirectBodyState2D::get_contact_count() const { return body->contact_count; } -Vector2 PhysicsDirectBodyState2DSW::get_contact_local_position(int p_contact_idx) const { +Vector2 GodotPhysicsDirectBodyState2D::get_contact_local_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2()); return body->contacts[p_contact_idx].local_pos; } -Vector2 PhysicsDirectBodyState2DSW::get_contact_local_normal(int p_contact_idx) const { +Vector2 GodotPhysicsDirectBodyState2D::get_contact_local_normal(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2()); return body->contacts[p_contact_idx].local_normal; } -int PhysicsDirectBodyState2DSW::get_contact_local_shape(int p_contact_idx) const { +int GodotPhysicsDirectBodyState2D::get_contact_local_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1); return body->contacts[p_contact_idx].local_shape; } -RID PhysicsDirectBodyState2DSW::get_contact_collider(int p_contact_idx) const { +RID GodotPhysicsDirectBodyState2D::get_contact_collider(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID()); return body->contacts[p_contact_idx].collider; } -Vector2 PhysicsDirectBodyState2DSW::get_contact_collider_position(int p_contact_idx) const { +Vector2 GodotPhysicsDirectBodyState2D::get_contact_collider_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2()); return body->contacts[p_contact_idx].collider_pos; } -ObjectID PhysicsDirectBodyState2DSW::get_contact_collider_id(int p_contact_idx) const { +ObjectID GodotPhysicsDirectBodyState2D::get_contact_collider_id(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID()); return body->contacts[p_contact_idx].collider_instance_id; } -int PhysicsDirectBodyState2DSW::get_contact_collider_shape(int p_contact_idx) const { +int GodotPhysicsDirectBodyState2D::get_contact_collider_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0); return body->contacts[p_contact_idx].collider_shape; } -Vector2 PhysicsDirectBodyState2DSW::get_contact_collider_velocity_at_position(int p_contact_idx) const { +Vector2 GodotPhysicsDirectBodyState2D::get_contact_collider_velocity_at_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2()); return body->contacts[p_contact_idx].collider_velocity_at_pos; } -PhysicsDirectSpaceState2D *PhysicsDirectBodyState2DSW::get_space_state() { +PhysicsDirectSpaceState2D *GodotPhysicsDirectBodyState2D::get_space_state() { return body->get_space()->get_direct_state(); } -real_t PhysicsDirectBodyState2DSW::get_step() const { +real_t GodotPhysicsDirectBodyState2D::get_step() const { return body->get_space()->get_last_step(); } diff --git a/servers/physics_2d/body_direct_state_2d_sw.h b/servers/physics_2d/godot_body_direct_state_2d.h index 4266b24842..2f3e8e5095 100644 --- a/servers/physics_2d/body_direct_state_2d_sw.h +++ b/servers/physics_2d/godot_body_direct_state_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_direct_state_2d_sw.h */ +/* godot_body_direct_state_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,18 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BODY_DIRECT_STATE_2D_SW_H -#define BODY_DIRECT_STATE_2D_SW_H +#ifndef GODOT_BODY_DIRECT_STATE_2D_H +#define GODOT_BODY_DIRECT_STATE_2D_H #include "servers/physics_server_2d.h" -class Body2DSW; +class GodotBody2D; -class PhysicsDirectBodyState2DSW : public PhysicsDirectBodyState2D { - GDCLASS(PhysicsDirectBodyState2DSW, PhysicsDirectBodyState2D); +class GodotPhysicsDirectBodyState2D : public PhysicsDirectBodyState2D { + GDCLASS(GodotPhysicsDirectBodyState2D, PhysicsDirectBodyState2D); public: - Body2DSW *body = nullptr; + GodotBody2D *body = nullptr; virtual Vector2 get_total_gravity() const override; virtual real_t get_total_angular_damp() const override; @@ -88,4 +88,4 @@ public: virtual real_t get_step() const override; }; -#endif // BODY_2D_SW_H +#endif // GODOT_BODY_DIRECT_STATE_2D_H diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/godot_body_pair_2d.cpp index 8bcc4609f4..97eeefbfe6 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/godot_body_pair_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_pair_2d_sw.cpp */ +/* godot_body_pair_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,20 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "body_pair_2d_sw.h" -#include "collision_solver_2d_sw.h" -#include "space_2d_sw.h" +#include "godot_body_pair_2d.h" +#include "godot_collision_solver_2d.h" +#include "godot_space_2d.h" #define POSITION_CORRECTION #define ACCUMULATE_IMPULSES -void BodyPair2DSW::_add_contact(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_self) { - BodyPair2DSW *self = (BodyPair2DSW *)p_self; +void GodotBodyPair2D::_add_contact(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_self) { + GodotBodyPair2D *self = (GodotBodyPair2D *)p_self; self->_contact_added_callback(p_point_A, p_point_B); } -void BodyPair2DSW::_contact_added_callback(const Vector2 &p_point_A, const Vector2 &p_point_B) { +void GodotBodyPair2D::_contact_added_callback(const Vector2 &p_point_A, const Vector2 &p_point_B) { // check if we already have the contact Vector2 local_A = A->get_inv_transform().basis_xform(p_point_A); @@ -121,7 +121,7 @@ void BodyPair2DSW::_contact_added_callback(const Vector2 &p_point_A, const Vecto } } -void BodyPair2DSW::_validate_contacts() { +void GodotBodyPair2D::_validate_contacts() { //make sure to erase contacts that are no longer valid real_t max_separation = space->get_contact_max_separation(); @@ -164,7 +164,7 @@ void BodyPair2DSW::_validate_contacts() { } } -bool BodyPair2DSW::_test_ccd(real_t p_step, Body2DSW *p_A, int p_shape_A, const Transform2D &p_xform_A, Body2DSW *p_B, int p_shape_B, const Transform2D &p_xform_B, bool p_swap_result) { +bool GodotBodyPair2D::_test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A, const Transform2D &p_xform_A, GodotBody2D *p_B, int p_shape_B, const Transform2D &p_xform_B, bool p_swap_result) { Vector2 motion = p_A->get_linear_velocity() * p_step; real_t mlen = motion.length(); if (mlen < CMP_EPSILON) { @@ -217,15 +217,15 @@ bool BodyPair2DSW::_test_ccd(real_t p_step, Body2DSW *p_A, int p_shape_A, const return true; } -real_t combine_bounce(Body2DSW *A, Body2DSW *B) { +real_t combine_bounce(GodotBody2D *A, GodotBody2D *B) { return CLAMP(A->get_bounce() + B->get_bounce(), 0, 1); } -real_t combine_friction(Body2DSW *A, Body2DSW *B) { +real_t combine_friction(GodotBody2D *A, GodotBody2D *B) { return ABS(MIN(A->get_friction(), B->get_friction())); } -bool BodyPair2DSW::setup(real_t p_step) { +bool GodotBodyPair2D::setup(real_t p_step) { if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) { collided = false; return false; @@ -257,8 +257,8 @@ bool BodyPair2DSW::setup(real_t p_step) { xform_Bu.elements[2] -= offset_A; Transform2D xform_B = xform_Bu * B->get_shape_transform(shape_B); - Shape2DSW *shape_A_ptr = A->get_shape(shape_A); - Shape2DSW *shape_B_ptr = B->get_shape(shape_B); + GodotShape2D *shape_A_ptr = A->get_shape(shape_A); + GodotShape2D *shape_B_ptr = B->get_shape(shape_B); Vector2 motion_A, motion_B; @@ -271,7 +271,7 @@ bool BodyPair2DSW::setup(real_t p_step) { bool prev_collided = collided; - collided = CollisionSolver2DSW::solve(shape_A_ptr, xform_A, motion_A, shape_B_ptr, xform_B, motion_B, _add_contact, this, &sep_axis); + collided = GodotCollisionSolver2D::solve(shape_A_ptr, xform_A, motion_A, shape_B_ptr, xform_B, motion_B, _add_contact, this, &sep_axis); if (!collided) { //test ccd (currently just a raycast) @@ -344,7 +344,7 @@ bool BodyPair2DSW::setup(real_t p_step) { return true; } -bool BodyPair2DSW::pre_solve(real_t p_step) { +bool GodotBodyPair2D::pre_solve(real_t p_step) { if (!collided || oneway_disabled) { return false; } @@ -353,8 +353,8 @@ bool BodyPair2DSW::pre_solve(real_t p_step) { real_t bias = 0.3; - Shape2DSW *shape_A_ptr = A->get_shape(shape_A); - Shape2DSW *shape_B_ptr = B->get_shape(shape_B); + GodotShape2D *shape_A_ptr = A->get_shape(shape_A); + GodotShape2D *shape_B_ptr = B->get_shape(shape_B); if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) { if (shape_A_ptr->get_custom_bias() == 0) { @@ -466,7 +466,7 @@ bool BodyPair2DSW::pre_solve(real_t p_step) { return do_process; } -void BodyPair2DSW::solve(real_t p_step) { +void GodotBodyPair2D::solve(real_t p_step) { if (!collided || oneway_disabled) { return; } @@ -528,8 +528,8 @@ void BodyPair2DSW::solve(real_t p_step) { } } -BodyPair2DSW::BodyPair2DSW(Body2DSW *p_A, int p_shape_A, Body2DSW *p_B, int p_shape_B) : - Constraint2DSW(_arr, 2) { +GodotBodyPair2D::GodotBodyPair2D(GodotBody2D *p_A, int p_shape_A, GodotBody2D *p_B, int p_shape_B) : + GodotConstraint2D(_arr, 2) { A = p_A; B = p_B; shape_A = p_shape_A; @@ -539,7 +539,7 @@ BodyPair2DSW::BodyPair2DSW(Body2DSW *p_A, int p_shape_A, Body2DSW *p_B, int p_sh B->add_constraint(this, 1); } -BodyPair2DSW::~BodyPair2DSW() { +GodotBodyPair2D::~GodotBodyPair2D() { A->remove_constraint(this, 0); B->remove_constraint(this, 1); } diff --git a/servers/physics_2d/body_pair_2d_sw.h b/servers/physics_2d/godot_body_pair_2d.h index db4f3eba69..0938ab542b 100644 --- a/servers/physics_2d/body_pair_2d_sw.h +++ b/servers/physics_2d/godot_body_pair_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_pair_2d_sw.h */ +/* godot_body_pair_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,23 +28,23 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BODY_PAIR_2D_SW_H -#define BODY_PAIR_2D_SW_H +#ifndef GODOT_BODY_PAIR_2D_H +#define GODOT_BODY_PAIR_2D_H -#include "body_2d_sw.h" -#include "constraint_2d_sw.h" +#include "godot_body_2d.h" +#include "godot_constraint_2d.h" -class BodyPair2DSW : public Constraint2DSW { +class GodotBodyPair2D : public GodotConstraint2D { enum { MAX_CONTACTS = 2 }; union { struct { - Body2DSW *A; - Body2DSW *B; + GodotBody2D *A; + GodotBody2D *B; }; - Body2DSW *_arr[2] = { nullptr, nullptr }; + GodotBody2D *_arr[2] = { nullptr, nullptr }; }; int shape_A = 0; @@ -53,7 +53,7 @@ class BodyPair2DSW : public Constraint2DSW { bool collide_A = false; bool collide_B = false; - Space2DSW *space = nullptr; + GodotSpace2D *space = nullptr; struct Contact { Vector2 position; @@ -81,7 +81,7 @@ class BodyPair2DSW : public Constraint2DSW { bool oneway_disabled = false; bool report_contacts_only = false; - bool _test_ccd(real_t p_step, Body2DSW *p_A, int p_shape_A, const Transform2D &p_xform_A, Body2DSW *p_B, int p_shape_B, const Transform2D &p_xform_B, bool p_swap_result = false); + bool _test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A, const Transform2D &p_xform_A, GodotBody2D *p_B, int p_shape_B, const Transform2D &p_xform_B, bool p_swap_result = false); void _validate_contacts(); static void _add_contact(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_self); _FORCE_INLINE_ void _contact_added_callback(const Vector2 &p_point_A, const Vector2 &p_point_B); @@ -91,8 +91,8 @@ public: virtual bool pre_solve(real_t p_step) override; virtual void solve(real_t p_step) override; - BodyPair2DSW(Body2DSW *p_A, int p_shape_A, Body2DSW *p_B, int p_shape_B); - ~BodyPair2DSW(); + GodotBodyPair2D(GodotBody2D *p_A, int p_shape_A, GodotBody2D *p_B, int p_shape_B); + ~GodotBodyPair2D(); }; -#endif // BODY_PAIR_2D_SW_H +#endif // GODOT_BODY_PAIR_2D_H diff --git a/servers/physics_3d/broad_phase_3d_sw.cpp b/servers/physics_2d/godot_broad_phase_2d.cpp index 8aa64034ec..4b35f8d996 100644 --- a/servers/physics_3d/broad_phase_3d_sw.cpp +++ b/servers/physics_2d/godot_broad_phase_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* broad_phase_3d_sw.cpp */ +/* godot_broad_phase_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "broad_phase_3d_sw.h" +#include "godot_broad_phase_2d.h" -BroadPhase3DSW::CreateFunction BroadPhase3DSW::create_func = nullptr; +GodotBroadPhase2D::CreateFunction GodotBroadPhase2D::create_func = nullptr; -BroadPhase3DSW::~BroadPhase3DSW() { +GodotBroadPhase2D::~GodotBroadPhase2D() { } diff --git a/servers/physics_2d/broad_phase_2d_sw.h b/servers/physics_2d/godot_broad_phase_2d.h index 0f82f06b9c..7017a6e41f 100644 --- a/servers/physics_2d/broad_phase_2d_sw.h +++ b/servers/physics_2d/godot_broad_phase_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* broad_phase_2d_sw.h */ +/* godot_broad_phase_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,44 +28,44 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BROAD_PHASE_2D_SW_H -#define BROAD_PHASE_2D_SW_H +#ifndef GODOT_BROAD_PHASE_2D_H +#define GODOT_BROAD_PHASE_2D_H #include "core/math/math_funcs.h" #include "core/math/rect2.h" -class CollisionObject2DSW; +class GodotCollisionObject2D; -class BroadPhase2DSW { +class GodotBroadPhase2D { public: - typedef BroadPhase2DSW *(*CreateFunction)(); + typedef GodotBroadPhase2D *(*CreateFunction)(); static CreateFunction create_func; typedef uint32_t ID; - typedef void *(*PairCallback)(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_userdata); - typedef void (*UnpairCallback)(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_data, void *p_userdata); + typedef void *(*PairCallback)(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_userdata); + typedef void (*UnpairCallback)(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_data, void *p_userdata); // 0 is an invalid ID - virtual ID create(CollisionObject2DSW *p_object_, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false) = 0; + virtual ID create(GodotCollisionObject2D *p_object_, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false) = 0; virtual void move(ID p_id, const Rect2 &p_aabb) = 0; virtual void set_static(ID p_id, bool p_static) = 0; virtual void remove(ID p_id) = 0; - virtual CollisionObject2DSW *get_object(ID p_id) const = 0; + virtual GodotCollisionObject2D *get_object(ID p_id) const = 0; virtual bool is_static(ID p_id) const = 0; virtual int get_subindex(ID p_id) const = 0; - virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = nullptr) = 0; - virtual int cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = nullptr) = 0; + virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr) = 0; + virtual int cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr) = 0; virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) = 0; virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) = 0; virtual void update() = 0; - virtual ~BroadPhase2DSW(); + virtual ~GodotBroadPhase2D(); }; -#endif // BROAD_PHASE_2D_SW_H +#endif // GODOT_BROAD_PHASE_2D_H diff --git a/servers/physics_2d/broad_phase_2d_bvh.cpp b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp index 0df7086c5a..9ec6b0a6b7 100644 --- a/servers/physics_2d/broad_phase_2d_bvh.cpp +++ b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* broad_phase_2d_bvh.cpp */ +/* godot_broad_phase_2d_bvh.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,51 +28,51 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "broad_phase_2d_bvh.h" -#include "collision_object_2d_sw.h" +#include "godot_broad_phase_2d_bvh.h" +#include "godot_collision_object_2d.h" -BroadPhase2DSW::ID BroadPhase2DBVH::create(CollisionObject2DSW *p_object, int p_subindex, const Rect2 &p_aabb, bool p_static) { +GodotBroadPhase2D::ID GodotBroadPhase2DBVH::create(GodotCollisionObject2D *p_object, int p_subindex, const Rect2 &p_aabb, bool p_static) { ID oid = bvh.create(p_object, true, p_aabb, p_subindex, !p_static, 1 << p_object->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care? return oid + 1; } -void BroadPhase2DBVH::move(ID p_id, const Rect2 &p_aabb) { +void GodotBroadPhase2DBVH::move(ID p_id, const Rect2 &p_aabb) { bvh.move(p_id - 1, p_aabb); } -void BroadPhase2DBVH::set_static(ID p_id, bool p_static) { - CollisionObject2DSW *it = bvh.get(p_id - 1); +void GodotBroadPhase2DBVH::set_static(ID p_id, bool p_static) { + GodotCollisionObject2D *it = bvh.get(p_id - 1); bvh.set_pairable(p_id - 1, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF, false); // Pair everything, don't care? } -void BroadPhase2DBVH::remove(ID p_id) { +void GodotBroadPhase2DBVH::remove(ID p_id) { bvh.erase(p_id - 1); } -CollisionObject2DSW *BroadPhase2DBVH::get_object(ID p_id) const { - CollisionObject2DSW *it = bvh.get(p_id - 1); +GodotCollisionObject2D *GodotBroadPhase2DBVH::get_object(ID p_id) const { + GodotCollisionObject2D *it = bvh.get(p_id - 1); ERR_FAIL_COND_V(!it, nullptr); return it; } -bool BroadPhase2DBVH::is_static(ID p_id) const { +bool GodotBroadPhase2DBVH::is_static(ID p_id) const { return !bvh.is_pairable(p_id - 1); } -int BroadPhase2DBVH::get_subindex(ID p_id) const { +int GodotBroadPhase2DBVH::get_subindex(ID p_id) const { return bvh.get_subindex(p_id - 1); } -int BroadPhase2DBVH::cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) { +int GodotBroadPhase2DBVH::cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices) { return bvh.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices); } -int BroadPhase2DBVH::cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices) { +int GodotBroadPhase2DBVH::cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices) { return bvh.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices); } -void *BroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, CollisionObject2DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject2DSW *p_object_B, int subindex_B) { - BroadPhase2DBVH *bpo = (BroadPhase2DBVH *)(self); +void *GodotBroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollisionObject2D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject2D *p_object_B, int subindex_B) { + GodotBroadPhase2DBVH *bpo = (GodotBroadPhase2DBVH *)(self); if (!bpo->pair_callback) { return nullptr; } @@ -80,8 +80,8 @@ void *BroadPhase2DBVH::_pair_callback(void *self, uint32_t p_A, CollisionObject2 return bpo->pair_callback(p_object_A, subindex_A, p_object_B, subindex_B, bpo->pair_userdata); } -void BroadPhase2DBVH::_unpair_callback(void *self, uint32_t p_A, CollisionObject2DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject2DSW *p_object_B, int subindex_B, void *pairdata) { - BroadPhase2DBVH *bpo = (BroadPhase2DBVH *)(self); +void GodotBroadPhase2DBVH::_unpair_callback(void *self, uint32_t p_A, GodotCollisionObject2D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject2D *p_object_B, int subindex_B, void *pairdata) { + GodotBroadPhase2DBVH *bpo = (GodotBroadPhase2DBVH *)(self); if (!bpo->unpair_callback) { return; } @@ -89,25 +89,25 @@ void BroadPhase2DBVH::_unpair_callback(void *self, uint32_t p_A, CollisionObject bpo->unpair_callback(p_object_A, subindex_A, p_object_B, subindex_B, pairdata, bpo->unpair_userdata); } -void BroadPhase2DBVH::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { +void GodotBroadPhase2DBVH::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { pair_callback = p_pair_callback; pair_userdata = p_userdata; } -void BroadPhase2DBVH::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { +void GodotBroadPhase2DBVH::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { unpair_callback = p_unpair_callback; unpair_userdata = p_userdata; } -void BroadPhase2DBVH::update() { +void GodotBroadPhase2DBVH::update() { bvh.update(); } -BroadPhase2DSW *BroadPhase2DBVH::_create() { - return memnew(BroadPhase2DBVH); +GodotBroadPhase2D *GodotBroadPhase2DBVH::_create() { + return memnew(GodotBroadPhase2DBVH); } -BroadPhase2DBVH::BroadPhase2DBVH() { +GodotBroadPhase2DBVH::GodotBroadPhase2DBVH() { bvh.set_pair_callback(_pair_callback, this); bvh.set_unpair_callback(_unpair_callback, this); } diff --git a/servers/physics_2d/broad_phase_2d_bvh.h b/servers/physics_2d/godot_broad_phase_2d_bvh.h index ea02a98417..19b49f3499 100644 --- a/servers/physics_2d/broad_phase_2d_bvh.h +++ b/servers/physics_2d/godot_broad_phase_2d_bvh.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* broad_phase_2d_bvh.h */ +/* godot_broad_phase_2d_bvh.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,19 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BROAD_PHASE_2D_BVH_H -#define BROAD_PHASE_2D_BVH_H +#ifndef GODOT_BROAD_PHASE_2D_BVH_H +#define GODOT_BROAD_PHASE_2D_BVH_H + +#include "godot_broad_phase_2d.h" -#include "broad_phase_2d_sw.h" #include "core/math/bvh.h" #include "core/math/rect2.h" #include "core/math/vector2.h" -class BroadPhase2DBVH : public BroadPhase2DSW { - BVH_Manager<CollisionObject2DSW, true, 128, Rect2, Vector2> bvh; +class GodotBroadPhase2DBVH : public GodotBroadPhase2D { + BVH_Manager<GodotCollisionObject2D, true, 128, Rect2, Vector2> bvh; - static void *_pair_callback(void *, uint32_t, CollisionObject2DSW *, int, uint32_t, CollisionObject2DSW *, int); - static void _unpair_callback(void *, uint32_t, CollisionObject2DSW *, int, uint32_t, CollisionObject2DSW *, int, void *); + static void *_pair_callback(void *, uint32_t, GodotCollisionObject2D *, int, uint32_t, GodotCollisionObject2D *, int); + static void _unpair_callback(void *, uint32_t, GodotCollisionObject2D *, int, uint32_t, GodotCollisionObject2D *, int, void *); PairCallback pair_callback = nullptr; void *pair_userdata = nullptr; @@ -49,25 +50,25 @@ class BroadPhase2DBVH : public BroadPhase2DSW { public: // 0 is an invalid ID - virtual ID create(CollisionObject2DSW *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false); + virtual ID create(GodotCollisionObject2D *p_object, int p_subindex = 0, const Rect2 &p_aabb = Rect2(), bool p_static = false); virtual void move(ID p_id, const Rect2 &p_aabb); virtual void set_static(ID p_id, bool p_static); virtual void remove(ID p_id); - virtual CollisionObject2DSW *get_object(ID p_id) const; + virtual GodotCollisionObject2D *get_object(ID p_id) const; virtual bool is_static(ID p_id) const; virtual int get_subindex(ID p_id) const; - virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_aabb(const Rect2 &p_aabb, CollisionObject2DSW **p_results, int p_max_results, int *p_result_indices = nullptr); + virtual int cull_segment(const Vector2 &p_from, const Vector2 &p_to, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr); + virtual int cull_aabb(const Rect2 &p_aabb, GodotCollisionObject2D **p_results, int p_max_results, int *p_result_indices = nullptr); virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); virtual void update(); - static BroadPhase2DSW *_create(); - BroadPhase2DBVH(); + static GodotBroadPhase2D *_create(); + GodotBroadPhase2DBVH(); }; -#endif // BROAD_PHASE_2D_BVH_H +#endif // GODOT_BROAD_PHASE_2D_BVH_H diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/godot_collision_object_2d.cpp index bc7d277152..3d4ebbedcd 100644 --- a/servers/physics_2d/collision_object_2d_sw.cpp +++ b/servers/physics_2d/godot_collision_object_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_object_2d_sw.cpp */ +/* godot_collision_object_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "collision_object_2d_sw.h" -#include "servers/physics_2d/physics_server_2d_sw.h" -#include "space_2d_sw.h" +#include "godot_collision_object_2d.h" +#include "godot_physics_server_2d.h" +#include "godot_space_2d.h" -void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_transform, bool p_disabled) { +void GodotCollisionObject2D::add_shape(GodotShape2D *p_shape, const Transform2D &p_transform, bool p_disabled) { Shape s; s.shape = p_shape; s.xform = p_transform; @@ -45,11 +45,11 @@ void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_tra p_shape->add_owner(this); if (!pending_shape_update_list.in_list()) { - PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } } -void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) { +void GodotCollisionObject2D::set_shape(int p_index, GodotShape2D *p_shape) { ERR_FAIL_INDEX(p_index, shapes.size()); shapes[p_index].shape->remove_owner(this); shapes.write[p_index].shape = p_shape; @@ -57,25 +57,25 @@ void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) { p_shape->add_owner(this); if (!pending_shape_update_list.in_list()) { - PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } } -void CollisionObject2DSW::set_shape_transform(int p_index, const Transform2D &p_transform) { +void GodotCollisionObject2D::set_shape_transform(int p_index, const Transform2D &p_transform) { ERR_FAIL_INDEX(p_index, shapes.size()); shapes.write[p_index].xform = p_transform; shapes.write[p_index].xform_inv = p_transform.affine_inverse(); if (!pending_shape_update_list.in_list()) { - PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } } -void CollisionObject2DSW::set_shape_disabled(int p_idx, bool p_disabled) { +void GodotCollisionObject2D::set_shape_disabled(int p_idx, bool p_disabled) { ERR_FAIL_INDEX(p_idx, shapes.size()); - CollisionObject2DSW::Shape &shape = shapes.write[p_idx]; + GodotCollisionObject2D::Shape &shape = shapes.write[p_idx]; if (shape.disabled == p_disabled) { return; } @@ -90,16 +90,16 @@ void CollisionObject2DSW::set_shape_disabled(int p_idx, bool p_disabled) { space->get_broadphase()->remove(shape.bpid); shape.bpid = 0; if (!pending_shape_update_list.in_list()) { - PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } } else if (!p_disabled && shape.bpid == 0) { if (!pending_shape_update_list.in_list()) { - PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } } } -void CollisionObject2DSW::remove_shape(Shape2DSW *p_shape) { +void GodotCollisionObject2D::remove_shape(GodotShape2D *p_shape) { //remove a shape, all the times it appears for (int i = 0; i < shapes.size(); i++) { if (shapes[i].shape == p_shape) { @@ -109,7 +109,7 @@ void CollisionObject2DSW::remove_shape(Shape2DSW *p_shape) { } } -void CollisionObject2DSW::remove_shape(int p_index) { +void GodotCollisionObject2D::remove_shape(int p_index) { //remove anything from shape to be erased to end, so subindices don't change ERR_FAIL_INDEX(p_index, shapes.size()); for (int i = p_index; i < shapes.size(); i++) { @@ -124,13 +124,13 @@ void CollisionObject2DSW::remove_shape(int p_index) { shapes.remove(p_index); if (!pending_shape_update_list.in_list()) { - PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer2D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } // _update_shapes(); // _shapes_changed(); } -void CollisionObject2DSW::_set_static(bool p_static) { +void GodotCollisionObject2D::_set_static(bool p_static) { if (_static == p_static) { return; } @@ -147,7 +147,7 @@ void CollisionObject2DSW::_set_static(bool p_static) { } } -void CollisionObject2DSW::_unregister_shapes() { +void GodotCollisionObject2D::_unregister_shapes() { for (int i = 0; i < shapes.size(); i++) { Shape &s = shapes.write[i]; if (s.bpid > 0) { @@ -157,7 +157,7 @@ void CollisionObject2DSW::_unregister_shapes() { } } -void CollisionObject2DSW::_update_shapes() { +void GodotCollisionObject2D::_update_shapes() { if (!space) { return; } @@ -184,7 +184,7 @@ void CollisionObject2DSW::_update_shapes() { } } -void CollisionObject2DSW::_update_shapes_with_motion(const Vector2 &p_motion) { +void GodotCollisionObject2D::_update_shapes_with_motion(const Vector2 &p_motion) { if (!space) { return; } @@ -211,7 +211,7 @@ void CollisionObject2DSW::_update_shapes_with_motion(const Vector2 &p_motion) { } } -void CollisionObject2DSW::_set_space(Space2DSW *p_space) { +void GodotCollisionObject2D::_set_space(GodotSpace2D *p_space) { if (space) { space->remove_object(this); @@ -232,12 +232,12 @@ void CollisionObject2DSW::_set_space(Space2DSW *p_space) { } } -void CollisionObject2DSW::_shape_changed() { +void GodotCollisionObject2D::_shape_changed() { _update_shapes(); _shapes_changed(); } -CollisionObject2DSW::CollisionObject2DSW(Type p_type) : +GodotCollisionObject2D::GodotCollisionObject2D(Type p_type) : pending_shape_update_list(this) { type = p_type; } diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/godot_collision_object_2d.h index ca258a906a..7233857808 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/godot_collision_object_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_object_2d_sw.h */ +/* godot_collision_object_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COLLISION_OBJECT_2D_SW_H -#define COLLISION_OBJECT_2D_SW_H +#ifndef GODOT_COLLISION_OBJECT_2D_H +#define GODOT_COLLISION_OBJECT_2D_H + +#include "godot_broad_phase_2d.h" +#include "godot_shape_2d.h" -#include "broad_phase_2d_sw.h" #include "core/templates/self_list.h" #include "servers/physics_server_2d.h" -#include "shape_2d_sw.h" -class Space2DSW; +class GodotSpace2D; -class CollisionObject2DSW : public ShapeOwner2DSW { +class GodotCollisionObject2D : public GodotShapeOwner2D { public: enum Type { TYPE_AREA, @@ -55,23 +56,23 @@ private: struct Shape { Transform2D xform; Transform2D xform_inv; - BroadPhase2DSW::ID bpid = 0; + GodotBroadPhase2D::ID bpid = 0; Rect2 aabb_cache; //for rayqueries - Shape2DSW *shape = nullptr; + GodotShape2D *shape = nullptr; bool disabled = false; bool one_way_collision = false; real_t one_way_collision_margin = 0.0; }; Vector<Shape> shapes; - Space2DSW *space = nullptr; + GodotSpace2D *space = nullptr; Transform2D transform; Transform2D inv_transform; uint32_t collision_mask = 1; uint32_t collision_layer = 1; bool _static = true; - SelfList<CollisionObject2DSW> pending_shape_update_list; + SelfList<GodotCollisionObject2D> pending_shape_update_list; void _update_shapes(); @@ -89,9 +90,9 @@ protected: void _set_static(bool p_static); virtual void _shapes_changed() = 0; - void _set_space(Space2DSW *p_space); + void _set_space(GodotSpace2D *p_space); - CollisionObject2DSW(Type p_type); + GodotCollisionObject2D(Type p_type); public: _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } @@ -106,12 +107,12 @@ public: void _shape_changed(); _FORCE_INLINE_ Type get_type() const { return type; } - void add_shape(Shape2DSW *p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false); - void set_shape(int p_index, Shape2DSW *p_shape); + void add_shape(GodotShape2D *p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false); + void set_shape(int p_index, GodotShape2D *p_shape); void set_shape_transform(int p_index, const Transform2D &p_transform); _FORCE_INLINE_ int get_shape_count() const { return shapes.size(); } - _FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const { + _FORCE_INLINE_ GodotShape2D *get_shape(int p_index) const { CRASH_BAD_INDEX(p_index, shapes.size()); return shapes[p_index].shape; } @@ -130,7 +131,7 @@ public: _FORCE_INLINE_ const Transform2D &get_transform() const { return transform; } _FORCE_INLINE_ const Transform2D &get_inv_transform() const { return inv_transform; } - _FORCE_INLINE_ Space2DSW *get_space() const { return space; } + _FORCE_INLINE_ GodotSpace2D *get_space() const { return space; } void set_shape_disabled(int p_idx, bool p_disabled); _FORCE_INLINE_ bool is_shape_disabled(int p_idx) const { @@ -165,25 +166,25 @@ public: } _FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; } - void remove_shape(Shape2DSW *p_shape); + void remove_shape(GodotShape2D *p_shape); void remove_shape(int p_index); - virtual void set_space(Space2DSW *p_space) = 0; + virtual void set_space(GodotSpace2D *p_space) = 0; _FORCE_INLINE_ bool is_static() const { return _static; } void set_pickable(bool p_pickable) { pickable = p_pickable; } _FORCE_INLINE_ bool is_pickable() const { return pickable; } - _FORCE_INLINE_ bool collides_with(CollisionObject2DSW *p_other) const { + _FORCE_INLINE_ bool collides_with(GodotCollisionObject2D *p_other) const { return p_other->collision_layer & collision_mask; } - _FORCE_INLINE_ bool interacts_with(CollisionObject2DSW *p_other) const { + _FORCE_INLINE_ bool interacts_with(GodotCollisionObject2D *p_other) const { return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask; } - virtual ~CollisionObject2DSW() {} + virtual ~GodotCollisionObject2D() {} }; -#endif // COLLISION_OBJECT_2D_SW_H +#endif // GODOT_COLLISION_OBJECT_2D_H diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/godot_collision_solver_2d.cpp index 527bb1b0b2..25371b9885 100644 --- a/servers/physics_2d/collision_solver_2d_sw.cpp +++ b/servers/physics_2d/godot_collision_solver_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_solver_2d_sw.cpp */ +/* godot_collision_solver_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,14 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "collision_solver_2d_sw.h" -#include "collision_solver_2d_sat.h" +#include "godot_collision_solver_2d.h" +#include "godot_collision_solver_2d_sat.h" #define collision_solver sat_2d_calculate_penetration //#define collision_solver gjk_epa_calculate_penetration -bool CollisionSolver2DSW::solve_static_world_boundary(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { - const WorldBoundaryShape2DSW *world_boundary = static_cast<const WorldBoundaryShape2DSW *>(p_shape_A); +bool GodotCollisionSolver2D::solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { + const GodotWorldBoundaryShape2D *world_boundary = static_cast<const GodotWorldBoundaryShape2D *>(p_shape_A); if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_WORLD_BOUNDARY) { return false; } @@ -73,8 +73,8 @@ bool CollisionSolver2DSW::solve_static_world_boundary(const Shape2DSW *p_shape_A return found; } -bool CollisionSolver2DSW::solve_separation_ray(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis, real_t p_margin) { - const SeparationRayShape2DSW *ray = static_cast<const SeparationRayShape2DSW *>(p_shape_A); +bool GodotCollisionSolver2D::solve_separation_ray(const GodotShape2D *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis, real_t p_margin) { + const GodotSeparationRayShape2D *ray = static_cast<const GodotSeparationRayShape2D *>(p_shape_A); if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_SEPARATION_RAY) { return false; } @@ -134,13 +134,13 @@ bool CollisionSolver2DSW::solve_separation_ray(const Shape2DSW *p_shape_A, const struct _ConcaveCollisionInfo2D { const Transform2D *transform_A = nullptr; - const Shape2DSW *shape_A = nullptr; + const GodotShape2D *shape_A = nullptr; const Transform2D *transform_B = nullptr; Vector2 motion_A; Vector2 motion_B; real_t margin_A = 0.0; real_t margin_B = 0.0; - CollisionSolver2DSW::CallbackResult result_callback; + GodotCollisionSolver2D::CallbackResult result_callback; void *userdata = nullptr; bool swap_result = false; bool collided = false; @@ -149,7 +149,7 @@ struct _ConcaveCollisionInfo2D { Vector2 *sep_axis = nullptr; }; -bool CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex) { +bool GodotCollisionSolver2D::concave_callback(void *p_userdata, GodotShape2D *p_convex) { _ConcaveCollisionInfo2D &cinfo = *(_ConcaveCollisionInfo2D *)(p_userdata); cinfo.aabb_tests++; @@ -165,8 +165,8 @@ bool CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex return !cinfo.result_callback; } -bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) { - const ConcaveShape2DSW *concave_B = static_cast<const ConcaveShape2DSW *>(p_shape_B); +bool GodotCollisionSolver2D::solve_concave(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) { + const GodotConcaveShape2D *concave_B = static_cast<const GodotConcaveShape2D *>(p_shape_B); _ConcaveCollisionInfo2D cinfo; cinfo.transform_A = &p_transform_A; @@ -209,7 +209,7 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A, const Transf return cinfo.collided; } -bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) { +bool GodotCollisionSolver2D::solve(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) { PhysicsServer2D::ShapeType type_A = p_shape_A->get_type(); PhysicsServer2D::ShapeType type_B = p_shape_B->get_type(); bool concave_A = p_shape_A->is_concave(); diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/godot_collision_solver_2d.h index b87247b89a..f10815a444 100644 --- a/servers/physics_2d/collision_solver_2d_sw.h +++ b/servers/physics_2d/godot_collision_solver_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_solver_2d_sw.h */ +/* godot_collision_solver_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,23 +28,23 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COLLISION_SOLVER_2D_SW_H -#define COLLISION_SOLVER_2D_SW_H +#ifndef GODOT_COLLISION_SOLVER_2D_H +#define GODOT_COLLISION_SOLVER_2D_H -#include "shape_2d_sw.h" +#include "godot_shape_2d.h" -class CollisionSolver2DSW { +class GodotCollisionSolver2D { public: typedef void (*CallbackResult)(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata); private: - static bool solve_static_world_boundary(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); - static bool concave_callback(void *p_userdata, Shape2DSW *p_convex); - static bool solve_concave(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0); - static bool solve_separation_ray(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin = 0); + static bool solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); + static bool concave_callback(void *p_userdata, GodotShape2D *p_convex); + static bool solve_concave(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0); + static bool solve_separation_ray(const GodotShape2D *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin = 0); public: - static bool solve(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0); + static bool solve(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0); }; -#endif // COLLISION_SOLVER_2D_SW_H +#endif // GODOT_COLLISION_SOLVER_2D_H diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/godot_collision_solver_2d_sat.cpp index 2e67cc6520..63053e8259 100644 --- a/servers/physics_2d/collision_solver_2d_sat.cpp +++ b/servers/physics_2d/godot_collision_solver_2d_sat.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_solver_2d_sat.cpp */ +/* godot_collision_solver_2d_sat.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,12 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "collision_solver_2d_sat.h" +#include "godot_collision_solver_2d_sat.h" #include "core/math/geometry_2d.h" struct _CollectorCallback2D { - CollisionSolver2DSW::CallbackResult callback; + GodotCollisionSolver2D::CallbackResult callback; void *userdata = nullptr; bool swap = false; bool collided = false; @@ -384,14 +384,14 @@ public: (castB && !separator.test_axis(((m_a) - ((m_b) + p_motion_b)).normalized())) || \ (castA && castB && !separator.test_axis(((m_a) + p_motion_a - ((m_b) + p_motion_b)).normalized()))) -typedef void (*CollisionFunc)(const Shape2DSW *, const Transform2D &, const Shape2DSW *, const Transform2D &, _CollectorCallback2D *p_collector, const Vector2 &, const Vector2 &, real_t, real_t); +typedef void (*CollisionFunc)(const GodotShape2D *, const Transform2D &, const GodotShape2D *, const Transform2D &, _CollectorCallback2D *p_collector, const Vector2 &, const Vector2 &, real_t, real_t); template <bool castA, bool castB, bool withMargin> -static void _collision_segment_segment(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a); - const SegmentShape2DSW *segment_B = static_cast<const SegmentShape2DSW *>(p_b); +static void _collision_segment_segment(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotSegmentShape2D *segment_A = static_cast<const GodotSegmentShape2D *>(p_a); + const GodotSegmentShape2D *segment_B = static_cast<const GodotSegmentShape2D *>(p_b); - SeparatorAxisTest2D<SegmentShape2DSW, SegmentShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, segment_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotSegmentShape2D, GodotSegmentShape2D, castA, castB, withMargin> separator(segment_A, p_transform_a, segment_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -430,11 +430,11 @@ static void _collision_segment_segment(const Shape2DSW *p_a, const Transform2D & } template <bool castA, bool castB, bool withMargin> -static void _collision_segment_circle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a); - const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW *>(p_b); +static void _collision_segment_circle(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotSegmentShape2D *segment_A = static_cast<const GodotSegmentShape2D *>(p_a); + const GodotCircleShape2D *circle_B = static_cast<const GodotCircleShape2D *>(p_b); - SeparatorAxisTest2D<SegmentShape2DSW, CircleShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, circle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotSegmentShape2D, GodotCircleShape2D, castA, castB, withMargin> separator(segment_A, p_transform_a, circle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -463,11 +463,11 @@ static void _collision_segment_circle(const Shape2DSW *p_a, const Transform2D &p } template <bool castA, bool castB, bool withMargin> -static void _collision_segment_rectangle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a); - const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b); +static void _collision_segment_rectangle(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotSegmentShape2D *segment_A = static_cast<const GodotSegmentShape2D *>(p_a); + const GodotRectangleShape2D *rectangle_B = static_cast<const GodotRectangleShape2D *>(p_b); - SeparatorAxisTest2D<SegmentShape2DSW, RectangleShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotSegmentShape2D, GodotRectangleShape2D, castA, castB, withMargin> separator(segment_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -534,11 +534,11 @@ static void _collision_segment_rectangle(const Shape2DSW *p_a, const Transform2D } template <bool castA, bool castB, bool withMargin> -static void _collision_segment_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a); - const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b); +static void _collision_segment_capsule(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotSegmentShape2D *segment_A = static_cast<const GodotSegmentShape2D *>(p_a); + const GodotCapsuleShape2D *capsule_B = static_cast<const GodotCapsuleShape2D *>(p_b); - SeparatorAxisTest2D<SegmentShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotSegmentShape2D, GodotCapsuleShape2D, castA, castB, withMargin> separator(segment_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -575,11 +575,11 @@ static void _collision_segment_capsule(const Shape2DSW *p_a, const Transform2D & } template <bool castA, bool castB, bool withMargin> -static void _collision_segment_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a); - const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b); +static void _collision_segment_convex_polygon(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotSegmentShape2D *segment_A = static_cast<const GodotSegmentShape2D *>(p_a); + const GodotConvexPolygonShape2D *convex_B = static_cast<const GodotConvexPolygonShape2D *>(p_b); - SeparatorAxisTest2D<SegmentShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotSegmentShape2D, GodotConvexPolygonShape2D, castA, castB, withMargin> separator(segment_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -614,11 +614,11 @@ static void _collision_segment_convex_polygon(const Shape2DSW *p_a, const Transf ///////// template <bool castA, bool castB, bool withMargin> -static void _collision_circle_circle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a); - const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW *>(p_b); +static void _collision_circle_circle(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotCircleShape2D *circle_A = static_cast<const GodotCircleShape2D *>(p_a); + const GodotCircleShape2D *circle_B = static_cast<const GodotCircleShape2D *>(p_b); - SeparatorAxisTest2D<CircleShape2DSW, CircleShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, circle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotCircleShape2D, GodotCircleShape2D, castA, castB, withMargin> separator(circle_A, p_transform_a, circle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -636,11 +636,11 @@ static void _collision_circle_circle(const Shape2DSW *p_a, const Transform2D &p_ } template <bool castA, bool castB, bool withMargin> -static void _collision_circle_rectangle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a); - const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b); +static void _collision_circle_rectangle(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotCircleShape2D *circle_A = static_cast<const GodotCircleShape2D *>(p_a); + const GodotRectangleShape2D *rectangle_B = static_cast<const GodotRectangleShape2D *>(p_b); - SeparatorAxisTest2D<CircleShape2DSW, RectangleShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotCircleShape2D, GodotRectangleShape2D, castA, castB, withMargin> separator(circle_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -694,11 +694,11 @@ static void _collision_circle_rectangle(const Shape2DSW *p_a, const Transform2D } template <bool castA, bool castB, bool withMargin> -static void _collision_circle_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a); - const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b); +static void _collision_circle_capsule(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotCircleShape2D *circle_A = static_cast<const GodotCircleShape2D *>(p_a); + const GodotCapsuleShape2D *capsule_B = static_cast<const GodotCapsuleShape2D *>(p_b); - SeparatorAxisTest2D<CircleShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotCircleShape2D, GodotCapsuleShape2D, castA, castB, withMargin> separator(circle_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -727,11 +727,11 @@ static void _collision_circle_capsule(const Shape2DSW *p_a, const Transform2D &p } template <bool castA, bool castB, bool withMargin> -static void _collision_circle_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a); - const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b); +static void _collision_circle_convex_polygon(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotCircleShape2D *circle_A = static_cast<const GodotCircleShape2D *>(p_a); + const GodotConvexPolygonShape2D *convex_B = static_cast<const GodotConvexPolygonShape2D *>(p_b); - SeparatorAxisTest2D<CircleShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotCircleShape2D, GodotConvexPolygonShape2D, castA, castB, withMargin> separator(circle_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -758,11 +758,11 @@ static void _collision_circle_convex_polygon(const Shape2DSW *p_a, const Transfo ///////// template <bool castA, bool castB, bool withMargin> -static void _collision_rectangle_rectangle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a); - const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b); +static void _collision_rectangle_rectangle(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotRectangleShape2D *rectangle_A = static_cast<const GodotRectangleShape2D *>(p_a); + const GodotRectangleShape2D *rectangle_B = static_cast<const GodotRectangleShape2D *>(p_b); - SeparatorAxisTest2D<RectangleShape2DSW, RectangleShape2DSW, castA, castB, withMargin> separator(rectangle_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotRectangleShape2D, GodotRectangleShape2D, castA, castB, withMargin> separator(rectangle_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -832,11 +832,11 @@ static void _collision_rectangle_rectangle(const Shape2DSW *p_a, const Transform } template <bool castA, bool castB, bool withMargin> -static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a); - const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b); +static void _collision_rectangle_capsule(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotRectangleShape2D *rectangle_A = static_cast<const GodotRectangleShape2D *>(p_a); + const GodotCapsuleShape2D *capsule_B = static_cast<const GodotCapsuleShape2D *>(p_b); - SeparatorAxisTest2D<RectangleShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(rectangle_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotRectangleShape2D, GodotCapsuleShape2D, castA, castB, withMargin> separator(rectangle_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -910,11 +910,11 @@ static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D } template <bool castA, bool castB, bool withMargin> -static void _collision_rectangle_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a); - const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b); +static void _collision_rectangle_convex_polygon(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotRectangleShape2D *rectangle_A = static_cast<const GodotRectangleShape2D *>(p_a); + const GodotConvexPolygonShape2D *convex_B = static_cast<const GodotConvexPolygonShape2D *>(p_b); - SeparatorAxisTest2D<RectangleShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(rectangle_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotRectangleShape2D, GodotConvexPolygonShape2D, castA, castB, withMargin> separator(rectangle_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -972,11 +972,11 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW *p_a, const Tran ///////// template <bool castA, bool castB, bool withMargin> -static void _collision_capsule_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW *>(p_a); - const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b); +static void _collision_capsule_capsule(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotCapsuleShape2D *capsule_A = static_cast<const GodotCapsuleShape2D *>(p_a); + const GodotCapsuleShape2D *capsule_B = static_cast<const GodotCapsuleShape2D *>(p_b); - SeparatorAxisTest2D<CapsuleShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(capsule_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotCapsuleShape2D, GodotCapsuleShape2D, castA, castB, withMargin> separator(capsule_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -1020,11 +1020,11 @@ static void _collision_capsule_capsule(const Shape2DSW *p_a, const Transform2D & } template <bool castA, bool castB, bool withMargin> -static void _collision_capsule_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW *>(p_a); - const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b); +static void _collision_capsule_convex_polygon(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotCapsuleShape2D *capsule_A = static_cast<const GodotCapsuleShape2D *>(p_a); + const GodotConvexPolygonShape2D *convex_B = static_cast<const GodotConvexPolygonShape2D *>(p_b); - SeparatorAxisTest2D<CapsuleShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(capsule_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotCapsuleShape2D, GodotConvexPolygonShape2D, castA, castB, withMargin> separator(capsule_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -1066,11 +1066,11 @@ static void _collision_capsule_convex_polygon(const Shape2DSW *p_a, const Transf ///////// template <bool castA, bool castB, bool withMargin> -static void _collision_convex_polygon_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { - const ConvexPolygonShape2DSW *convex_A = static_cast<const ConvexPolygonShape2DSW *>(p_a); - const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b); +static void _collision_convex_polygon_convex_polygon(const GodotShape2D *p_a, const Transform2D &p_transform_a, const GodotShape2D *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) { + const GodotConvexPolygonShape2D *convex_A = static_cast<const GodotConvexPolygonShape2D *>(p_a); + const GodotConvexPolygonShape2D *convex_B = static_cast<const GodotConvexPolygonShape2D *>(p_b); - SeparatorAxisTest2D<ConvexPolygonShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(convex_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); + SeparatorAxisTest2D<GodotConvexPolygonShape2D, GodotConvexPolygonShape2D, castA, castB, withMargin> separator(convex_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B); if (!separator.test_previous_axis()) { return; @@ -1107,7 +1107,7 @@ static void _collision_convex_polygon_convex_polygon(const Shape2DSW *p_a, const //////// -bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector2 *sep_axis, real_t p_margin_A, real_t p_margin_B) { +bool sat_2d_calculate_penetration(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, GodotCollisionSolver2D::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector2 *sep_axis, real_t p_margin_A, real_t p_margin_B) { PhysicsServer2D::ShapeType type_A = p_shape_A->get_type(); ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_WORLD_BOUNDARY, false); @@ -1359,8 +1359,8 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D callback.collided = false; callback.sep_axis = sep_axis; - const Shape2DSW *A = p_shape_A; - const Shape2DSW *B = p_shape_B; + const GodotShape2D *A = p_shape_A; + const GodotShape2D *B = p_shape_B; const Transform2D *transform_A = &p_transform_A; const Transform2D *transform_B = &p_transform_B; const Vector2 *motion_A = &p_motion_A; diff --git a/servers/physics_2d/collision_solver_2d_sat.h b/servers/physics_2d/godot_collision_solver_2d_sat.h index 49cc5176f9..1517b90a19 100644 --- a/servers/physics_2d/collision_solver_2d_sat.h +++ b/servers/physics_2d/godot_collision_solver_2d_sat.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_solver_2d_sat.h */ +/* godot_collision_solver_2d_sat.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COLLISION_SOLVER_2D_SAT_H -#define COLLISION_SOLVER_2D_SAT_H +#ifndef GODOT_COLLISION_SOLVER_2D_SAT_H +#define GODOT_COLLISION_SOLVER_2D_SAT_H -#include "collision_solver_2d_sw.h" +#include "godot_collision_solver_2d.h" -bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector2 *sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0); +bool sat_2d_calculate_penetration(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, GodotCollisionSolver2D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector2 *sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0); -#endif // COLLISION_SOLVER_2D_SAT_H +#endif // GODOT_COLLISION_SOLVER_2D_SAT_H diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/godot_constraint_2d.h index df300d666d..84f975e583 100644 --- a/servers/physics_2d/constraint_2d_sw.h +++ b/servers/physics_2d/godot_constraint_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* constraint_2d_sw.h */ +/* godot_constraint_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CONSTRAINT_2D_SW_H -#define CONSTRAINT_2D_SW_H +#ifndef GODOT_CONSTRAINT_2D_H +#define GODOT_CONSTRAINT_2D_H -#include "body_2d_sw.h" +#include "godot_body_2d.h" -class Constraint2DSW { - Body2DSW **_body_ptr; +class GodotConstraint2D { + GodotBody2D **_body_ptr; int _body_count; uint64_t island_step = 0; bool disabled_collisions_between_bodies = true; @@ -42,7 +42,7 @@ class Constraint2DSW { RID self; protected: - Constraint2DSW(Body2DSW **p_body_ptr = nullptr, int p_body_count = 0) { + GodotConstraint2D(GodotBody2D **p_body_ptr = nullptr, int p_body_count = 0) { _body_ptr = p_body_ptr; _body_count = p_body_count; } @@ -54,7 +54,7 @@ public: _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } - _FORCE_INLINE_ Body2DSW **get_body_ptr() const { return _body_ptr; } + _FORCE_INLINE_ GodotBody2D **get_body_ptr() const { return _body_ptr; } _FORCE_INLINE_ int get_body_count() const { return _body_count; } _FORCE_INLINE_ void disable_collisions_between_bodies(const bool p_disabled) { disabled_collisions_between_bodies = p_disabled; } @@ -64,7 +64,7 @@ public: virtual bool pre_solve(real_t p_step) = 0; virtual void solve(real_t p_step) = 0; - virtual ~Constraint2DSW() {} + virtual ~GodotConstraint2D() {} }; -#endif // CONSTRAINT_2D_SW_H +#endif // GODOT_CONSTRAINT_2D_H diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/godot_joints_2d.cpp index b46397b8e6..7c08c2f4b4 100644 --- a/servers/physics_2d/joints_2d_sw.cpp +++ b/servers/physics_2d/godot_joints_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* joints_2d_sw.cpp */ +/* godot_joints_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "joints_2d_sw.h" +#include "godot_joints_2d.h" -#include "space_2d_sw.h" +#include "godot_space_2d.h" //based on chipmunk joint constraints @@ -55,7 +55,7 @@ * SOFTWARE. */ -void Joint2DSW::copy_settings_from(Joint2DSW *p_joint) { +void GodotJoint2D::copy_settings_from(GodotJoint2D *p_joint) { set_self(p_joint->get_self()); set_max_force(p_joint->get_max_force()); set_bias(p_joint->get_bias()); @@ -63,7 +63,7 @@ void Joint2DSW::copy_settings_from(Joint2DSW *p_joint) { disable_collisions_between_bodies(p_joint->is_disabled_collisions_between_bodies()); } -static inline real_t k_scalar(Body2DSW *a, Body2DSW *b, const Vector2 &rA, const Vector2 &rB, const Vector2 &n) { +static inline real_t k_scalar(GodotBody2D *a, GodotBody2D *b, const Vector2 &rA, const Vector2 &rB, const Vector2 &n) { real_t value = 0.0; { @@ -82,7 +82,7 @@ static inline real_t k_scalar(Body2DSW *a, Body2DSW *b, const Vector2 &rA, const } static inline Vector2 -relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB) { +relative_velocity(GodotBody2D *a, GodotBody2D *b, Vector2 rA, Vector2 rB) { Vector2 sum = a->get_linear_velocity() - (rA - a->get_center_of_mass()).orthogonal() * a->get_angular_velocity(); if (b) { return (b->get_linear_velocity() - (rB - b->get_center_of_mass()).orthogonal() * b->get_angular_velocity()) - sum; @@ -92,11 +92,11 @@ relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB) { } static inline real_t -normal_relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB, Vector2 n) { +normal_relative_velocity(GodotBody2D *a, GodotBody2D *b, Vector2 rA, Vector2 rB, Vector2 n) { return relative_velocity(a, b, rA, rB).dot(n); } -bool PinJoint2DSW::setup(real_t p_step) { +bool GodotPinJoint2D::setup(real_t p_step) { dynamic_A = (A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC); dynamic_B = (B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC); @@ -104,7 +104,7 @@ bool PinJoint2DSW::setup(real_t p_step) { return false; } - Space2DSW *space = A->get_space(); + GodotSpace2D *space = A->get_space(); ERR_FAIL_COND_V(!space, false); rA = A->get_transform().basis_xform(anchor_A); @@ -158,7 +158,7 @@ inline Vector2 custom_cross(const Vector2 &p_vec, real_t p_other) { return Vector2(p_other * p_vec.y, -p_other * p_vec.x); } -bool PinJoint2DSW::pre_solve(real_t p_step) { +bool GodotPinJoint2D::pre_solve(real_t p_step) { // Apply accumulated impulse. if (dynamic_A) { A->apply_impulse(-P, rA); @@ -170,7 +170,7 @@ bool PinJoint2DSW::pre_solve(real_t p_step) { return true; } -void PinJoint2DSW::solve(real_t p_step) { +void GodotPinJoint2D::solve(real_t p_step) { // compute relative velocity Vector2 vA = A->get_linear_velocity() - custom_cross(rA - A->get_center_of_mass(), A->get_angular_velocity()); @@ -193,21 +193,21 @@ void PinJoint2DSW::solve(real_t p_step) { P += impulse; } -void PinJoint2DSW::set_param(PhysicsServer2D::PinJointParam p_param, real_t p_value) { +void GodotPinJoint2D::set_param(PhysicsServer2D::PinJointParam p_param, real_t p_value) { if (p_param == PhysicsServer2D::PIN_JOINT_SOFTNESS) { softness = p_value; } } -real_t PinJoint2DSW::get_param(PhysicsServer2D::PinJointParam p_param) const { +real_t GodotPinJoint2D::get_param(PhysicsServer2D::PinJointParam p_param) const { if (p_param == PhysicsServer2D::PIN_JOINT_SOFTNESS) { return softness; } ERR_FAIL_V(0); } -PinJoint2DSW::PinJoint2DSW(const Vector2 &p_pos, Body2DSW *p_body_a, Body2DSW *p_body_b) : - Joint2DSW(_arr, p_body_b ? 2 : 1) { +GodotPinJoint2D::GodotPinJoint2D(const Vector2 &p_pos, GodotBody2D *p_body_a, GodotBody2D *p_body_b) : + GodotJoint2D(_arr, p_body_b ? 2 : 1) { A = p_body_a; B = p_body_b; anchor_A = p_body_a->get_inv_transform().xform(p_pos); @@ -224,7 +224,7 @@ PinJoint2DSW::PinJoint2DSW(const Vector2 &p_pos, Body2DSW *p_body_a, Body2DSW *p ////////////////////////////////////////////// static inline void -k_tensor(Body2DSW *a, Body2DSW *b, Vector2 r1, Vector2 r2, Vector2 *k1, Vector2 *k2) { +k_tensor(GodotBody2D *a, GodotBody2D *b, Vector2 r1, Vector2 r2, Vector2 *k1, Vector2 *k2) { // calculate mass matrix // If I wasn't lazy and wrote a proper matrix class, this wouldn't be so gross... real_t k11, k12, k21, k22; @@ -273,7 +273,7 @@ mult_k(const Vector2 &vr, const Vector2 &k1, const Vector2 &k2) { return Vector2(vr.dot(k1), vr.dot(k2)); } -bool GrooveJoint2DSW::setup(real_t p_step) { +bool GodotGrooveJoint2D::setup(real_t p_step) { dynamic_A = (A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC); dynamic_B = (B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC); @@ -281,7 +281,7 @@ bool GrooveJoint2DSW::setup(real_t p_step) { return false; } - Space2DSW *space = A->get_space(); + GodotSpace2D *space = A->get_space(); ERR_FAIL_COND_V(!space, false); // calculate endpoints in worldspace @@ -329,7 +329,7 @@ bool GrooveJoint2DSW::setup(real_t p_step) { return true; } -bool GrooveJoint2DSW::pre_solve(real_t p_step) { +bool GodotGrooveJoint2D::pre_solve(real_t p_step) { // Apply accumulated impulse. if (dynamic_A) { A->apply_impulse(-jn_acc, rA); @@ -341,7 +341,7 @@ bool GrooveJoint2DSW::pre_solve(real_t p_step) { return true; } -void GrooveJoint2DSW::solve(real_t p_step) { +void GodotGrooveJoint2D::solve(real_t p_step) { // compute impulse Vector2 vr = relative_velocity(A, B, rA, rB); @@ -361,8 +361,8 @@ void GrooveJoint2DSW::solve(real_t p_step) { } } -GrooveJoint2DSW::GrooveJoint2DSW(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, Body2DSW *p_body_a, Body2DSW *p_body_b) : - Joint2DSW(_arr, 2) { +GodotGrooveJoint2D::GodotGrooveJoint2D(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, GodotBody2D *p_body_a, GodotBody2D *p_body_b) : + GodotJoint2D(_arr, 2) { A = p_body_a; B = p_body_b; @@ -379,7 +379,7 @@ GrooveJoint2DSW::GrooveJoint2DSW(const Vector2 &p_a_groove1, const Vector2 &p_a_ ////////////////////////////////////////////// ////////////////////////////////////////////// -bool DampedSpringJoint2DSW::setup(real_t p_step) { +bool GodotDampedSpringJoint2D::setup(real_t p_step) { dynamic_A = (A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC); dynamic_B = (B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC); @@ -412,7 +412,7 @@ bool DampedSpringJoint2DSW::setup(real_t p_step) { return true; } -bool DampedSpringJoint2DSW::pre_solve(real_t p_step) { +bool GodotDampedSpringJoint2D::pre_solve(real_t p_step) { // Apply spring force. if (dynamic_A) { A->apply_impulse(-j, rA); @@ -424,7 +424,7 @@ bool DampedSpringJoint2DSW::pre_solve(real_t p_step) { return true; } -void DampedSpringJoint2DSW::solve(real_t p_step) { +void GodotDampedSpringJoint2D::solve(real_t p_step) { // compute relative velocity real_t vrn = normal_relative_velocity(A, B, rA, rB, n) - target_vrn; @@ -442,7 +442,7 @@ void DampedSpringJoint2DSW::solve(real_t p_step) { } } -void DampedSpringJoint2DSW::set_param(PhysicsServer2D::DampedSpringParam p_param, real_t p_value) { +void GodotDampedSpringJoint2D::set_param(PhysicsServer2D::DampedSpringParam p_param, real_t p_value) { switch (p_param) { case PhysicsServer2D::DAMPED_SPRING_REST_LENGTH: { rest_length = p_value; @@ -456,7 +456,7 @@ void DampedSpringJoint2DSW::set_param(PhysicsServer2D::DampedSpringParam p_param } } -real_t DampedSpringJoint2DSW::get_param(PhysicsServer2D::DampedSpringParam p_param) const { +real_t GodotDampedSpringJoint2D::get_param(PhysicsServer2D::DampedSpringParam p_param) const { switch (p_param) { case PhysicsServer2D::DAMPED_SPRING_REST_LENGTH: { return rest_length; @@ -472,8 +472,8 @@ real_t DampedSpringJoint2DSW::get_param(PhysicsServer2D::DampedSpringParam p_par ERR_FAIL_V(0); } -DampedSpringJoint2DSW::DampedSpringJoint2DSW(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, Body2DSW *p_body_a, Body2DSW *p_body_b) : - Joint2DSW(_arr, 2) { +GodotDampedSpringJoint2D::GodotDampedSpringJoint2D(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, GodotBody2D *p_body_a, GodotBody2D *p_body_b) : + GodotJoint2D(_arr, 2) { A = p_body_a; B = p_body_b; anchor_A = A->get_inv_transform().xform(p_anchor_a); diff --git a/servers/physics_2d/joints_2d_sw.h b/servers/physics_2d/godot_joints_2d.h index e2a7c0c91e..4c97190d01 100644 --- a/servers/physics_2d/joints_2d_sw.h +++ b/servers/physics_2d/godot_joints_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* joints_2d_sw.h */ +/* godot_joints_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef JOINTS_2D_SW_H -#define JOINTS_2D_SW_H +#ifndef GODOT_JOINTS_2D_H +#define GODOT_JOINTS_2D_H -#include "body_2d_sw.h" -#include "constraint_2d_sw.h" +#include "godot_body_2d.h" +#include "godot_constraint_2d.h" -class Joint2DSW : public Constraint2DSW { +class GodotJoint2D : public GodotConstraint2D { real_t bias = 0; real_t max_bias = 3.40282e+38; real_t max_force = 3.40282e+38; @@ -57,15 +57,15 @@ public: virtual bool pre_solve(real_t p_step) override { return false; } virtual void solve(real_t p_step) override {} - void copy_settings_from(Joint2DSW *p_joint); + void copy_settings_from(GodotJoint2D *p_joint); virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_TYPE_MAX; } - Joint2DSW(Body2DSW **p_body_ptr = nullptr, int p_body_count = 0) : - Constraint2DSW(p_body_ptr, p_body_count) {} + GodotJoint2D(GodotBody2D **p_body_ptr = nullptr, int p_body_count = 0) : + GodotConstraint2D(p_body_ptr, p_body_count) {} - virtual ~Joint2DSW() { + virtual ~GodotJoint2D() { for (int i = 0; i < get_body_count(); i++) { - Body2DSW *body = get_body_ptr()[i]; + GodotBody2D *body = get_body_ptr()[i]; if (body) { body->remove_constraint(this, i); } @@ -73,14 +73,14 @@ public: }; }; -class PinJoint2DSW : public Joint2DSW { +class GodotPinJoint2D : public GodotJoint2D { union { struct { - Body2DSW *A; - Body2DSW *B; + GodotBody2D *A; + GodotBody2D *B; }; - Body2DSW *_arr[2] = { nullptr, nullptr }; + GodotBody2D *_arr[2] = { nullptr, nullptr }; }; Transform2D M; @@ -101,17 +101,17 @@ public: void set_param(PhysicsServer2D::PinJointParam p_param, real_t p_value); real_t get_param(PhysicsServer2D::PinJointParam p_param) const; - PinJoint2DSW(const Vector2 &p_pos, Body2DSW *p_body_a, Body2DSW *p_body_b = nullptr); + GodotPinJoint2D(const Vector2 &p_pos, GodotBody2D *p_body_a, GodotBody2D *p_body_b = nullptr); }; -class GrooveJoint2DSW : public Joint2DSW { +class GodotGrooveJoint2D : public GodotJoint2D { union { struct { - Body2DSW *A; - Body2DSW *B; + GodotBody2D *A; + GodotBody2D *B; }; - Body2DSW *_arr[2] = { nullptr, nullptr }; + GodotBody2D *_arr[2] = { nullptr, nullptr }; }; Vector2 A_groove_1; @@ -135,17 +135,17 @@ public: virtual bool pre_solve(real_t p_step) override; virtual void solve(real_t p_step) override; - GrooveJoint2DSW(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, Body2DSW *p_body_a, Body2DSW *p_body_b); + GodotGrooveJoint2D(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, GodotBody2D *p_body_a, GodotBody2D *p_body_b); }; -class DampedSpringJoint2DSW : public Joint2DSW { +class GodotDampedSpringJoint2D : public GodotJoint2D { union { struct { - Body2DSW *A; - Body2DSW *B; + GodotBody2D *A; + GodotBody2D *B; }; - Body2DSW *_arr[2] = { nullptr, nullptr }; + GodotBody2D *_arr[2] = { nullptr, nullptr }; }; Vector2 anchor_A; @@ -172,7 +172,7 @@ public: void set_param(PhysicsServer2D::DampedSpringParam p_param, real_t p_value); real_t get_param(PhysicsServer2D::DampedSpringParam p_param) const; - DampedSpringJoint2DSW(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, Body2DSW *p_body_a, Body2DSW *p_body_b); + GodotDampedSpringJoint2D(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, GodotBody2D *p_body_a, GodotBody2D *p_body_b); }; -#endif // JOINTS_2D_SW_H +#endif // GODOT_JOINTS_2D_H diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp new file mode 100644 index 0000000000..c86f87fc03 --- /dev/null +++ b/servers/physics_2d/godot_physics_server_2d.cpp @@ -0,0 +1,1350 @@ +/*************************************************************************/ +/* godot_physics_server_2d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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 "godot_physics_server_2d.h" + +#include "godot_body_direct_state_2d.h" +#include "godot_broad_phase_2d_bvh.h" +#include "godot_collision_solver_2d.h" + +#include "core/config/project_settings.h" +#include "core/debugger/engine_debugger.h" +#include "core/os/os.h" + +#define FLUSH_QUERY_CHECK(m_object) \ + ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead."); + +RID GodotPhysicsServer2D::_shape_create(ShapeType p_shape) { + GodotShape2D *shape = nullptr; + switch (p_shape) { + case SHAPE_WORLD_BOUNDARY: { + shape = memnew(GodotWorldBoundaryShape2D); + } break; + case SHAPE_SEPARATION_RAY: { + shape = memnew(GodotSeparationRayShape2D); + } break; + case SHAPE_SEGMENT: { + shape = memnew(GodotSegmentShape2D); + } break; + case SHAPE_CIRCLE: { + shape = memnew(GodotCircleShape2D); + } break; + case SHAPE_RECTANGLE: { + shape = memnew(GodotRectangleShape2D); + } break; + case SHAPE_CAPSULE: { + shape = memnew(GodotCapsuleShape2D); + } break; + case SHAPE_CONVEX_POLYGON: { + shape = memnew(GodotConvexPolygonShape2D); + } break; + case SHAPE_CONCAVE_POLYGON: { + shape = memnew(GodotConcavePolygonShape2D); + } break; + case SHAPE_CUSTOM: { + ERR_FAIL_V(RID()); + + } break; + } + + RID id = shape_owner.make_rid(shape); + shape->set_self(id); + + return id; +} + +RID GodotPhysicsServer2D::world_boundary_shape_create() { + return _shape_create(SHAPE_WORLD_BOUNDARY); +} + +RID GodotPhysicsServer2D::separation_ray_shape_create() { + return _shape_create(SHAPE_SEPARATION_RAY); +} + +RID GodotPhysicsServer2D::segment_shape_create() { + return _shape_create(SHAPE_SEGMENT); +} + +RID GodotPhysicsServer2D::circle_shape_create() { + return _shape_create(SHAPE_CIRCLE); +} + +RID GodotPhysicsServer2D::rectangle_shape_create() { + return _shape_create(SHAPE_RECTANGLE); +} + +RID GodotPhysicsServer2D::capsule_shape_create() { + return _shape_create(SHAPE_CAPSULE); +} + +RID GodotPhysicsServer2D::convex_polygon_shape_create() { + return _shape_create(SHAPE_CONVEX_POLYGON); +} + +RID GodotPhysicsServer2D::concave_polygon_shape_create() { + return _shape_create(SHAPE_CONCAVE_POLYGON); +} + +void GodotPhysicsServer2D::shape_set_data(RID p_shape, const Variant &p_data) { + GodotShape2D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + shape->set_data(p_data); +}; + +void GodotPhysicsServer2D::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { + GodotShape2D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + shape->set_custom_bias(p_bias); +} + +PhysicsServer2D::ShapeType GodotPhysicsServer2D::shape_get_type(RID p_shape) const { + const GodotShape2D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM); + return shape->get_type(); +}; + +Variant GodotPhysicsServer2D::shape_get_data(RID p_shape) const { + const GodotShape2D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND_V(!shape, Variant()); + ERR_FAIL_COND_V(!shape->is_configured(), Variant()); + return shape->get_data(); +}; + +real_t GodotPhysicsServer2D::shape_get_custom_solver_bias(RID p_shape) const { + const GodotShape2D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND_V(!shape, 0); + return shape->get_custom_bias(); +} + +void GodotPhysicsServer2D::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) { + CollCbkData *cbk = (CollCbkData *)p_userdata; + + if (cbk->max == 0) { + return; + } + + Vector2 rel_dir = (p_point_A - p_point_B); + real_t rel_length2 = rel_dir.length_squared(); + if (cbk->valid_dir != Vector2()) { + if (cbk->valid_depth < 10e20) { + if (rel_length2 > cbk->valid_depth * cbk->valid_depth || + (rel_length2 > CMP_EPSILON && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON)) { + cbk->invalid_by_dir++; + return; + } + } else { + if (rel_length2 > 0 && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON) { + return; + } + } + } + + if (cbk->amount == cbk->max) { + //find least deep + real_t min_depth = 1e20; + int min_depth_idx = 0; + for (int i = 0; i < cbk->amount; i++) { + real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]); + if (d < min_depth) { + min_depth = d; + min_depth_idx = i; + } + } + + if (rel_length2 < min_depth) { + return; + } + cbk->ptr[min_depth_idx * 2 + 0] = p_point_A; + cbk->ptr[min_depth_idx * 2 + 1] = p_point_B; + cbk->passed++; + + } else { + cbk->ptr[cbk->amount * 2 + 0] = p_point_A; + cbk->ptr[cbk->amount * 2 + 1] = p_point_B; + cbk->amount++; + cbk->passed++; + } +} + +bool GodotPhysicsServer2D::shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) { + GodotShape2D *shape_A = shape_owner.get_or_null(p_shape_A); + ERR_FAIL_COND_V(!shape_A, false); + GodotShape2D *shape_B = shape_owner.get_or_null(p_shape_B); + ERR_FAIL_COND_V(!shape_B, false); + + if (p_result_max == 0) { + return GodotCollisionSolver2D::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, nullptr, nullptr); + } + + CollCbkData cbk; + cbk.max = p_result_max; + cbk.amount = 0; + cbk.passed = 0; + cbk.ptr = r_results; + + bool res = GodotCollisionSolver2D::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, _shape_col_cbk, &cbk); + r_result_count = cbk.amount; + return res; +} + +RID GodotPhysicsServer2D::space_create() { + GodotSpace2D *space = memnew(GodotSpace2D); + RID id = space_owner.make_rid(space); + space->set_self(id); + RID area_id = area_create(); + GodotArea2D *area = area_owner.get_or_null(area_id); + ERR_FAIL_COND_V(!area, RID()); + space->set_default_area(area); + area->set_space(space); + area->set_priority(-1); + + return id; +}; + +void GodotPhysicsServer2D::space_set_active(RID p_space, bool p_active) { + GodotSpace2D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND(!space); + if (p_active) { + active_spaces.insert(space); + } else { + active_spaces.erase(space); + } +} + +bool GodotPhysicsServer2D::space_is_active(RID p_space) const { + const GodotSpace2D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND_V(!space, false); + + return active_spaces.has(space); +} + +void GodotPhysicsServer2D::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { + GodotSpace2D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND(!space); + + space->set_param(p_param, p_value); +} + +real_t GodotPhysicsServer2D::space_get_param(RID p_space, SpaceParameter p_param) const { + const GodotSpace2D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND_V(!space, 0); + return space->get_param(p_param); +} + +void GodotPhysicsServer2D::space_set_debug_contacts(RID p_space, int p_max_contacts) { + GodotSpace2D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND(!space); + space->set_debug_contacts(p_max_contacts); +} + +Vector<Vector2> GodotPhysicsServer2D::space_get_contacts(RID p_space) const { + GodotSpace2D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND_V(!space, Vector<Vector2>()); + return space->get_debug_contacts(); +} + +int GodotPhysicsServer2D::space_get_contact_count(RID p_space) const { + GodotSpace2D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND_V(!space, 0); + return space->get_debug_contact_count(); +} + +PhysicsDirectSpaceState2D *GodotPhysicsServer2D::space_get_direct_state(RID p_space) { + GodotSpace2D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND_V(!space, nullptr); + ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification."); + + return space->get_direct_state(); +} + +RID GodotPhysicsServer2D::area_create() { + GodotArea2D *area = memnew(GodotArea2D); + RID rid = area_owner.make_rid(area); + area->set_self(rid); + return rid; +}; + +void GodotPhysicsServer2D::area_set_space(RID p_area, RID p_space) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + GodotSpace2D *space = nullptr; + if (p_space.is_valid()) { + space = space_owner.get_or_null(p_space); + ERR_FAIL_COND(!space); + } + + if (area->get_space() == space) { + return; //pointless + } + + area->clear_constraints(); + area->set_space(space); +}; + +RID GodotPhysicsServer2D::area_get_space(RID p_area) const { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, RID()); + + GodotSpace2D *space = area->get_space(); + if (!space) { + return RID(); + } + return space->get_self(); +}; + +void GodotPhysicsServer2D::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_space_override_mode(p_mode); +} + +PhysicsServer2D::AreaSpaceOverrideMode GodotPhysicsServer2D::area_get_space_override_mode(RID p_area) const { + const GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); + + return area->get_space_override_mode(); +} + +void GodotPhysicsServer2D::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + GodotShape2D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + + area->add_shape(shape, p_transform, p_disabled); +} + +void GodotPhysicsServer2D::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + GodotShape2D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + ERR_FAIL_COND(!shape->is_configured()); + + area->set_shape(p_shape_idx, shape); +} + +void GodotPhysicsServer2D::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_shape_transform(p_shape_idx, p_transform); +} + +void GodotPhysicsServer2D::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + ERR_FAIL_INDEX(p_shape, area->get_shape_count()); + FLUSH_QUERY_CHECK(area); + + area->set_shape_disabled(p_shape, p_disabled); +} + +int GodotPhysicsServer2D::area_get_shape_count(RID p_area) const { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, -1); + + return area->get_shape_count(); +} + +RID GodotPhysicsServer2D::area_get_shape(RID p_area, int p_shape_idx) const { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, RID()); + + GodotShape2D *shape = area->get_shape(p_shape_idx); + ERR_FAIL_COND_V(!shape, RID()); + + return shape->get_self(); +} + +Transform2D GodotPhysicsServer2D::area_get_shape_transform(RID p_area, int p_shape_idx) const { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, Transform2D()); + + return area->get_shape_transform(p_shape_idx); +} + +void GodotPhysicsServer2D::area_remove_shape(RID p_area, int p_shape_idx) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->remove_shape(p_shape_idx); +} + +void GodotPhysicsServer2D::area_clear_shapes(RID p_area) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + while (area->get_shape_count()) { + area->remove_shape(0); + } +} + +void GodotPhysicsServer2D::area_attach_object_instance_id(RID p_area, ObjectID p_id) { + if (space_owner.owns(p_area)) { + GodotSpace2D *space = space_owner.get_or_null(p_area); + p_area = space->get_default_area()->get_self(); + } + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + area->set_instance_id(p_id); +} + +ObjectID GodotPhysicsServer2D::area_get_object_instance_id(RID p_area) const { + if (space_owner.owns(p_area)) { + GodotSpace2D *space = space_owner.get_or_null(p_area); + p_area = space->get_default_area()->get_self(); + } + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, ObjectID()); + return area->get_instance_id(); +} + +void GodotPhysicsServer2D::area_attach_canvas_instance_id(RID p_area, ObjectID p_id) { + if (space_owner.owns(p_area)) { + GodotSpace2D *space = space_owner.get_or_null(p_area); + p_area = space->get_default_area()->get_self(); + } + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + area->set_canvas_instance_id(p_id); +} + +ObjectID GodotPhysicsServer2D::area_get_canvas_instance_id(RID p_area) const { + if (space_owner.owns(p_area)) { + GodotSpace2D *space = space_owner.get_or_null(p_area); + p_area = space->get_default_area()->get_self(); + } + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, ObjectID()); + return area->get_canvas_instance_id(); +} + +void GodotPhysicsServer2D::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { + if (space_owner.owns(p_area)) { + GodotSpace2D *space = space_owner.get_or_null(p_area); + p_area = space->get_default_area()->get_self(); + } + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + area->set_param(p_param, p_value); +}; + +void GodotPhysicsServer2D::area_set_transform(RID p_area, const Transform2D &p_transform) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + area->set_transform(p_transform); +}; + +Variant GodotPhysicsServer2D::area_get_param(RID p_area, AreaParameter p_param) const { + if (space_owner.owns(p_area)) { + GodotSpace2D *space = space_owner.get_or_null(p_area); + p_area = space->get_default_area()->get_self(); + } + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, Variant()); + + return area->get_param(p_param); +}; + +Transform2D GodotPhysicsServer2D::area_get_transform(RID p_area) const { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, Transform2D()); + + return area->get_transform(); +}; + +void GodotPhysicsServer2D::area_set_pickable(RID p_area, bool p_pickable) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + area->set_pickable(p_pickable); +} + +void GodotPhysicsServer2D::area_set_monitorable(RID p_area, bool p_monitorable) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + FLUSH_QUERY_CHECK(area); + + area->set_monitorable(p_monitorable); +} + +void GodotPhysicsServer2D::area_set_collision_mask(RID p_area, uint32_t p_mask) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_collision_mask(p_mask); +} + +void GodotPhysicsServer2D::area_set_collision_layer(RID p_area, uint32_t p_layer) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_collision_layer(p_layer); +} + +void GodotPhysicsServer2D::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); +} + +void GodotPhysicsServer2D::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { + GodotArea2D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); +} + +/* BODY API */ + +RID GodotPhysicsServer2D::body_create() { + GodotBody2D *body = memnew(GodotBody2D); + RID rid = body_owner.make_rid(body); + body->set_self(rid); + return rid; +} + +void GodotPhysicsServer2D::body_set_space(RID p_body, RID p_space) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + GodotSpace2D *space = nullptr; + if (p_space.is_valid()) { + space = space_owner.get_or_null(p_space); + ERR_FAIL_COND(!space); + } + + if (body->get_space() == space) { + return; //pointless + } + + body->clear_constraint_list(); + body->set_space(space); +}; + +RID GodotPhysicsServer2D::body_get_space(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, RID()); + + GodotSpace2D *space = body->get_space(); + if (!space) { + return RID(); + } + return space->get_self(); +}; + +void GodotPhysicsServer2D::body_set_mode(RID p_body, BodyMode p_mode) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + FLUSH_QUERY_CHECK(body); + + body->set_mode(p_mode); +}; + +PhysicsServer2D::BodyMode GodotPhysicsServer2D::body_get_mode(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, BODY_MODE_STATIC); + + return body->get_mode(); +}; + +void GodotPhysicsServer2D::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform, bool p_disabled) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + GodotShape2D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + + body->add_shape(shape, p_transform, p_disabled); +} + +void GodotPhysicsServer2D::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + GodotShape2D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + ERR_FAIL_COND(!shape->is_configured()); + + body->set_shape(p_shape_idx, shape); +} + +void GodotPhysicsServer2D::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_shape_transform(p_shape_idx, p_transform); +} + +int GodotPhysicsServer2D::body_get_shape_count(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, -1); + + return body->get_shape_count(); +} + +RID GodotPhysicsServer2D::body_get_shape(RID p_body, int p_shape_idx) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, RID()); + + GodotShape2D *shape = body->get_shape(p_shape_idx); + ERR_FAIL_COND_V(!shape, RID()); + + return shape->get_self(); +} + +Transform2D GodotPhysicsServer2D::body_get_shape_transform(RID p_body, int p_shape_idx) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, Transform2D()); + + return body->get_shape_transform(p_shape_idx); +} + +void GodotPhysicsServer2D::body_remove_shape(RID p_body, int p_shape_idx) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->remove_shape(p_shape_idx); +} + +void GodotPhysicsServer2D::body_clear_shapes(RID p_body) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + while (body->get_shape_count()) { + body->remove_shape(0); + } +} + +void GodotPhysicsServer2D::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); + FLUSH_QUERY_CHECK(body); + + body->set_shape_disabled(p_shape_idx, p_disabled); +} + +void GodotPhysicsServer2D::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, real_t p_margin) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); + FLUSH_QUERY_CHECK(body); + + body->set_shape_as_one_way_collision(p_shape_idx, p_enable, p_margin); +} + +void GodotPhysicsServer2D::body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + body->set_continuous_collision_detection_mode(p_mode); +} + +GodotPhysicsServer2D::CCDMode GodotPhysicsServer2D::body_get_continuous_collision_detection_mode(RID p_body) const { + const GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, CCD_MODE_DISABLED); + + return body->get_continuous_collision_detection_mode(); +} + +void GodotPhysicsServer2D::body_attach_object_instance_id(RID p_body, ObjectID p_id) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_instance_id(p_id); +}; + +ObjectID GodotPhysicsServer2D::body_get_object_instance_id(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, ObjectID()); + + return body->get_instance_id(); +}; + +void GodotPhysicsServer2D::body_attach_canvas_instance_id(RID p_body, ObjectID p_id) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_canvas_instance_id(p_id); +}; + +ObjectID GodotPhysicsServer2D::body_get_canvas_instance_id(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, ObjectID()); + + return body->get_canvas_instance_id(); +}; + +void GodotPhysicsServer2D::body_set_collision_layer(RID p_body, uint32_t p_layer) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + body->set_collision_layer(p_layer); +}; + +uint32_t GodotPhysicsServer2D::body_get_collision_layer(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_layer(); +}; + +void GodotPhysicsServer2D::body_set_collision_mask(RID p_body, uint32_t p_mask) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + body->set_collision_mask(p_mask); +}; + +uint32_t GodotPhysicsServer2D::body_get_collision_mask(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_mask(); +}; + +void GodotPhysicsServer2D::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_param(p_param, p_value); +}; + +Variant GodotPhysicsServer2D::body_get_param(RID p_body, BodyParameter p_param) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_param(p_param); +}; + +void GodotPhysicsServer2D::body_reset_mass_properties(RID p_body) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + return body->reset_mass_properties(); +} + +void GodotPhysicsServer2D::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_state(p_state, p_variant); +}; + +Variant GodotPhysicsServer2D::body_get_state(RID p_body, BodyState p_state) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, Variant()); + + return body->get_state(p_state); +}; + +void GodotPhysicsServer2D::body_set_applied_force(RID p_body, const Vector2 &p_force) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_applied_force(p_force); + body->wakeup(); +}; + +Vector2 GodotPhysicsServer2D::body_get_applied_force(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, Vector2()); + return body->get_applied_force(); +}; + +void GodotPhysicsServer2D::body_set_applied_torque(RID p_body, real_t p_torque) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_applied_torque(p_torque); + body->wakeup(); +}; + +real_t GodotPhysicsServer2D::body_get_applied_torque(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_applied_torque(); +}; + +void GodotPhysicsServer2D::body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->apply_central_impulse(p_impulse); + body->wakeup(); +} + +void GodotPhysicsServer2D::body_apply_torque_impulse(RID p_body, real_t p_torque) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + body->apply_torque_impulse(p_torque); + body->wakeup(); +} + +void GodotPhysicsServer2D::body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + body->apply_impulse(p_impulse, p_position); + body->wakeup(); +}; + +void GodotPhysicsServer2D::body_add_central_force(RID p_body, const Vector2 &p_force) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->add_central_force(p_force); + body->wakeup(); +}; + +void GodotPhysicsServer2D::body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->add_force(p_force, p_position); + body->wakeup(); +}; + +void GodotPhysicsServer2D::body_add_torque(RID p_body, real_t p_torque) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->add_torque(p_torque); + body->wakeup(); +}; + +void GodotPhysicsServer2D::body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + Vector2 v = body->get_linear_velocity(); + Vector2 axis = p_axis_velocity.normalized(); + v -= axis * axis.dot(v); + v += p_axis_velocity; + body->set_linear_velocity(v); + body->wakeup(); +}; + +void GodotPhysicsServer2D::body_add_collision_exception(RID p_body, RID p_body_b) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->add_exception(p_body_b); + body->wakeup(); +}; + +void GodotPhysicsServer2D::body_remove_collision_exception(RID p_body, RID p_body_b) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->remove_exception(p_body_b); + body->wakeup(); +}; + +void GodotPhysicsServer2D::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + for (int i = 0; i < body->get_exceptions().size(); i++) { + p_exceptions->push_back(body->get_exceptions()[i]); + } +}; + +void GodotPhysicsServer2D::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); +}; + +real_t GodotPhysicsServer2D::body_get_contacts_reported_depth_threshold(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + return 0; +}; + +void GodotPhysicsServer2D::body_set_omit_force_integration(RID p_body, bool p_omit) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_omit_force_integration(p_omit); +}; + +bool GodotPhysicsServer2D::body_is_omitting_force_integration(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, false); + return body->get_omit_force_integration(); +}; + +void GodotPhysicsServer2D::body_set_max_contacts_reported(RID p_body, int p_contacts) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + body->set_max_contacts_reported(p_contacts); +} + +int GodotPhysicsServer2D::body_get_max_contacts_reported(RID p_body) const { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, -1); + return body->get_max_contacts_reported(); +} + +void GodotPhysicsServer2D::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + body->set_state_sync_callback(p_instance, p_callback); +} + +void GodotPhysicsServer2D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + body->set_force_integration_callback(p_callable, p_udata); +} + +bool GodotPhysicsServer2D::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, false); + ERR_FAIL_INDEX_V(p_body_shape, body->get_shape_count(), false); + + return shape_collide(body->get_shape(p_body_shape)->get_self(), body->get_transform() * body->get_shape_transform(p_body_shape), Vector2(), p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count); +} + +void GodotPhysicsServer2D::body_set_pickable(RID p_body, bool p_pickable) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + body->set_pickable(p_pickable); +} + +bool GodotPhysicsServer2D::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) { + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, false); + ERR_FAIL_COND_V(!body->get_space(), false); + ERR_FAIL_COND_V(body->get_space()->is_locked(), false); + + _update_shapes(); + + return body->get_space()->test_body_motion(body, p_parameters, r_result); +} + +PhysicsDirectBodyState2D *GodotPhysicsServer2D::body_get_direct_state(RID p_body) { + ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); + + GodotBody2D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, nullptr); + + ERR_FAIL_COND_V(!body->get_space(), nullptr); + ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); + + return body->get_direct_state(); +} + +/* JOINT API */ + +RID GodotPhysicsServer2D::joint_create() { + GodotJoint2D *joint = memnew(GodotJoint2D); + RID joint_rid = joint_owner.make_rid(joint); + joint->set_self(joint_rid); + return joint_rid; +} + +void GodotPhysicsServer2D::joint_clear(RID p_joint) { + GodotJoint2D *joint = joint_owner.get_or_null(p_joint); + if (joint->get_type() != JOINT_TYPE_MAX) { + GodotJoint2D *empty_joint = memnew(GodotJoint2D); + empty_joint->copy_settings_from(joint); + + joint_owner.replace(p_joint, empty_joint); + memdelete(joint); + } +} + +void GodotPhysicsServer2D::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) { + GodotJoint2D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + + switch (p_param) { + case JOINT_PARAM_BIAS: + joint->set_bias(p_value); + break; + case JOINT_PARAM_MAX_BIAS: + joint->set_max_bias(p_value); + break; + case JOINT_PARAM_MAX_FORCE: + joint->set_max_force(p_value); + break; + } +} + +real_t GodotPhysicsServer2D::joint_get_param(RID p_joint, JointParam p_param) const { + const GodotJoint2D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, -1); + + switch (p_param) { + case JOINT_PARAM_BIAS: + return joint->get_bias(); + break; + case JOINT_PARAM_MAX_BIAS: + return joint->get_max_bias(); + break; + case JOINT_PARAM_MAX_FORCE: + return joint->get_max_force(); + break; + } + + return 0; +} + +void GodotPhysicsServer2D::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { + GodotJoint2D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + + joint->disable_collisions_between_bodies(p_disable); + + if (2 == joint->get_body_count()) { + GodotBody2D *body_a = *joint->get_body_ptr(); + GodotBody2D *body_b = *(joint->get_body_ptr() + 1); + + if (p_disable) { + body_add_collision_exception(body_a->get_self(), body_b->get_self()); + body_add_collision_exception(body_b->get_self(), body_a->get_self()); + } else { + body_remove_collision_exception(body_a->get_self(), body_b->get_self()); + body_remove_collision_exception(body_b->get_self(), body_a->get_self()); + } + } +} + +bool GodotPhysicsServer2D::joint_is_disabled_collisions_between_bodies(RID p_joint) const { + const GodotJoint2D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, true); + + return joint->is_disabled_collisions_between_bodies(); +} + +void GodotPhysicsServer2D::joint_make_pin(RID p_joint, const Vector2 &p_pos, RID p_body_a, RID p_body_b) { + GodotBody2D *A = body_owner.get_or_null(p_body_a); + ERR_FAIL_COND(!A); + GodotBody2D *B = nullptr; + if (body_owner.owns(p_body_b)) { + B = body_owner.get_or_null(p_body_b); + ERR_FAIL_COND(!B); + } + + GodotJoint2D *prev_joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(prev_joint == nullptr); + + GodotJoint2D *joint = memnew(GodotPinJoint2D(p_pos, A, B)); + + joint_owner.replace(p_joint, joint); + joint->copy_settings_from(prev_joint); + memdelete(prev_joint); +} + +void GodotPhysicsServer2D::joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) { + GodotBody2D *A = body_owner.get_or_null(p_body_a); + ERR_FAIL_COND(!A); + + GodotBody2D *B = body_owner.get_or_null(p_body_b); + ERR_FAIL_COND(!B); + + GodotJoint2D *prev_joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(prev_joint == nullptr); + + GodotJoint2D *joint = memnew(GodotGrooveJoint2D(p_a_groove1, p_a_groove2, p_b_anchor, A, B)); + + joint_owner.replace(p_joint, joint); + joint->copy_settings_from(prev_joint); + memdelete(prev_joint); +} + +void GodotPhysicsServer2D::joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) { + GodotBody2D *A = body_owner.get_or_null(p_body_a); + ERR_FAIL_COND(!A); + + GodotBody2D *B = body_owner.get_or_null(p_body_b); + ERR_FAIL_COND(!B); + + GodotJoint2D *prev_joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(prev_joint == nullptr); + + GodotJoint2D *joint = memnew(GodotDampedSpringJoint2D(p_anchor_a, p_anchor_b, A, B)); + + joint_owner.replace(p_joint, joint); + joint->copy_settings_from(prev_joint); + memdelete(prev_joint); +} + +void GodotPhysicsServer2D::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) { + GodotJoint2D *j = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!j); + ERR_FAIL_COND(j->get_type() != JOINT_TYPE_PIN); + + GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(j); + pin_joint->set_param(p_param, p_value); +} + +real_t GodotPhysicsServer2D::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { + GodotJoint2D *j = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!j, 0); + ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_PIN, 0); + + GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(j); + return pin_joint->get_param(p_param); +} + +void GodotPhysicsServer2D::damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) { + GodotJoint2D *j = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!j); + ERR_FAIL_COND(j->get_type() != JOINT_TYPE_DAMPED_SPRING); + + GodotDampedSpringJoint2D *dsj = static_cast<GodotDampedSpringJoint2D *>(j); + dsj->set_param(p_param, p_value); +} + +real_t GodotPhysicsServer2D::damped_spring_joint_get_param(RID p_joint, DampedSpringParam p_param) const { + GodotJoint2D *j = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!j, 0); + ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_DAMPED_SPRING, 0); + + GodotDampedSpringJoint2D *dsj = static_cast<GodotDampedSpringJoint2D *>(j); + return dsj->get_param(p_param); +} + +PhysicsServer2D::JointType GodotPhysicsServer2D::joint_get_type(RID p_joint) const { + GodotJoint2D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN); + + return joint->get_type(); +} + +void GodotPhysicsServer2D::free(RID p_rid) { + _update_shapes(); // just in case + + if (shape_owner.owns(p_rid)) { + GodotShape2D *shape = shape_owner.get_or_null(p_rid); + + while (shape->get_owners().size()) { + GodotShapeOwner2D *so = shape->get_owners().front()->key(); + so->remove_shape(shape); + } + + shape_owner.free(p_rid); + memdelete(shape); + } else if (body_owner.owns(p_rid)) { + GodotBody2D *body = body_owner.get_or_null(p_rid); + + /* + if (body->get_state_query()) + _clear_query(body->get_state_query()); + + if (body->get_direct_state_query()) + _clear_query(body->get_direct_state_query()); + */ + + body_set_space(p_rid, RID()); + + while (body->get_shape_count()) { + body->remove_shape(0); + } + + body_owner.free(p_rid); + memdelete(body); + + } else if (area_owner.owns(p_rid)) { + GodotArea2D *area = area_owner.get_or_null(p_rid); + + /* + if (area->get_monitor_query()) + _clear_query(area->get_monitor_query()); + */ + + area->set_space(nullptr); + + while (area->get_shape_count()) { + area->remove_shape(0); + } + + area_owner.free(p_rid); + memdelete(area); + } else if (space_owner.owns(p_rid)) { + GodotSpace2D *space = space_owner.get_or_null(p_rid); + + while (space->get_objects().size()) { + GodotCollisionObject2D *co = (GodotCollisionObject2D *)space->get_objects().front()->get(); + co->set_space(nullptr); + } + + active_spaces.erase(space); + free(space->get_default_area()->get_self()); + space_owner.free(p_rid); + memdelete(space); + } else if (joint_owner.owns(p_rid)) { + GodotJoint2D *joint = joint_owner.get_or_null(p_rid); + + joint_owner.free(p_rid); + memdelete(joint); + + } else { + ERR_FAIL_MSG("Invalid ID."); + } +}; + +void GodotPhysicsServer2D::set_active(bool p_active) { + active = p_active; +}; + +void GodotPhysicsServer2D::set_collision_iterations(int p_iterations) { + iterations = p_iterations; +}; + +void GodotPhysicsServer2D::init() { + doing_sync = false; + iterations = 8; // 8? + stepper = memnew(GodotStep2D); +}; + +void GodotPhysicsServer2D::step(real_t p_step) { + if (!active) { + return; + } + + _update_shapes(); + + island_count = 0; + active_objects = 0; + collision_pairs = 0; + for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { + stepper->step((GodotSpace2D *)E->get(), p_step, iterations); + island_count += E->get()->get_island_count(); + active_objects += E->get()->get_active_objects(); + collision_pairs += E->get()->get_collision_pairs(); + } +}; + +void GodotPhysicsServer2D::sync() { + doing_sync = true; +}; + +void GodotPhysicsServer2D::flush_queries() { + if (!active) { + return; + } + + flushing_queries = true; + + uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); + + for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { + GodotSpace2D *space = (GodotSpace2D *)E->get(); + space->call_queries(); + } + + flushing_queries = false; + + if (EngineDebugger::is_profiling("servers")) { + uint64_t total_time[GodotSpace2D::ELAPSED_TIME_MAX]; + static const char *time_name[GodotSpace2D::ELAPSED_TIME_MAX] = { + "integrate_forces", + "generate_islands", + "setup_constraints", + "solve_constraints", + "integrate_velocities" + }; + + for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) { + total_time[i] = 0; + } + + for (Set<const GodotSpace2D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) { + total_time[i] += E->get()->get_elapsed_time(GodotSpace2D::ElapsedTime(i)); + } + } + + Array values; + values.resize(GodotSpace2D::ELAPSED_TIME_MAX * 2); + for (int i = 0; i < GodotSpace2D::ELAPSED_TIME_MAX; i++) { + values[i * 2 + 0] = time_name[i]; + values[i * 2 + 1] = USEC_TO_SEC(total_time[i]); + } + values.push_back("flush_queries"); + values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg)); + + values.push_front("physics_2d"); + EngineDebugger::profiler_add_frame_data("servers", values); + } +} + +void GodotPhysicsServer2D::end_sync() { + doing_sync = false; +} + +void GodotPhysicsServer2D::finish() { + memdelete(stepper); +}; + +void GodotPhysicsServer2D::_update_shapes() { + while (pending_shape_update_list.first()) { + pending_shape_update_list.first()->self()->_shape_changed(); + pending_shape_update_list.remove(pending_shape_update_list.first()); + } +} + +int GodotPhysicsServer2D::get_process_info(ProcessInfo p_info) { + switch (p_info) { + case INFO_ACTIVE_OBJECTS: { + return active_objects; + } break; + case INFO_COLLISION_PAIRS: { + return collision_pairs; + } break; + case INFO_ISLAND_COUNT: { + return island_count; + } break; + } + + return 0; +} + +GodotPhysicsServer2D *GodotPhysicsServer2D::godot_singleton = nullptr; + +GodotPhysicsServer2D::GodotPhysicsServer2D(bool p_using_threads) { + godot_singleton = this; + GodotBroadPhase2D::create_func = GodotBroadPhase2DBVH::_create; + + using_threads = p_using_threads; +}; diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/godot_physics_server_2d.h index b8e375a087..a8a1e71d13 100644 --- a/servers/physics_2d/physics_server_2d_sw.h +++ b/servers/physics_2d/godot_physics_server_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* physics_server_2d_sw.h */ +/* godot_physics_server_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,21 +28,22 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PHYSICS_2D_SERVER_SW -#define PHYSICS_2D_SERVER_SW +#ifndef GODOT_PHYSICS_SERVER_2D_H +#define GODOT_PHYSICS_SERVER_2D_H + +#include "godot_joints_2d.h" +#include "godot_shape_2d.h" +#include "godot_space_2d.h" +#include "godot_step_2d.h" #include "core/templates/rid_owner.h" -#include "joints_2d_sw.h" #include "servers/physics_server_2d.h" -#include "shape_2d_sw.h" -#include "space_2d_sw.h" -#include "step_2d_sw.h" -class PhysicsServer2DSW : public PhysicsServer2D { - GDCLASS(PhysicsServer2DSW, PhysicsServer2D); +class GodotPhysicsServer2D : public PhysicsServer2D { + GDCLASS(GodotPhysicsServer2D, PhysicsServer2D); - friend class PhysicsDirectSpaceState2DSW; - friend class PhysicsDirectBodyState2DSW; + friend class GodotPhysicsDirectSpaceState2D; + friend class GodotPhysicsDirectBodyState2D; bool active = true; int iterations = 0; bool doing_sync = false; @@ -55,20 +56,19 @@ class PhysicsServer2DSW : public PhysicsServer2D { bool flushing_queries = false; - Step2DSW *stepper = nullptr; - Set<const Space2DSW *> active_spaces; + GodotStep2D *stepper = nullptr; + Set<const GodotSpace2D *> active_spaces; - mutable RID_PtrOwner<Shape2DSW, true> shape_owner; - mutable RID_PtrOwner<Space2DSW, true> space_owner; - mutable RID_PtrOwner<Area2DSW, true> area_owner; - mutable RID_PtrOwner<Body2DSW, true> body_owner; - mutable RID_PtrOwner<Joint2DSW, true> joint_owner; + mutable RID_PtrOwner<GodotShape2D, true> shape_owner; + mutable RID_PtrOwner<GodotSpace2D, true> space_owner; + mutable RID_PtrOwner<GodotArea2D, true> area_owner; + mutable RID_PtrOwner<GodotBody2D, true> body_owner; + mutable RID_PtrOwner<GodotJoint2D, true> joint_owner; - static PhysicsServer2DSW *singletonsw; + static GodotPhysicsServer2D *godot_singleton; - //void _clear_query(Query2DSW *p_query); - friend class CollisionObject2DSW; - SelfList<CollisionObject2DSW>::List pending_shape_update_list; + friend class GodotCollisionObject2D; + SelfList<GodotCollisionObject2D>::List pending_shape_update_list; void _update_shapes(); RID _shape_create(ShapeType p_shape); @@ -292,8 +292,8 @@ public: int get_process_info(ProcessInfo p_info) override; - PhysicsServer2DSW(bool p_using_threads = false); - ~PhysicsServer2DSW() {} + GodotPhysicsServer2D(bool p_using_threads = false); + ~GodotPhysicsServer2D() {} }; -#endif +#endif // GODOT_PHYSICS_SERVER_2D_H diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/godot_shape_2d.cpp index bde882ac24..3604004324 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/godot_shape_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* shape_2d_sw.cpp */ +/* godot_shape_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,29 +28,29 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "shape_2d_sw.h" +#include "godot_shape_2d.h" #include "core/math/geometry_2d.h" #include "core/templates/sort_array.h" -void Shape2DSW::configure(const Rect2 &p_aabb) { +void GodotShape2D::configure(const Rect2 &p_aabb) { aabb = p_aabb; configured = true; - for (const KeyValue<ShapeOwner2DSW *, int> &E : owners) { - ShapeOwner2DSW *co = (ShapeOwner2DSW *)E.key; + for (const KeyValue<GodotShapeOwner2D *, int> &E : owners) { + GodotShapeOwner2D *co = (GodotShapeOwner2D *)E.key; co->_shape_changed(); } } -Vector2 Shape2DSW::get_support(const Vector2 &p_normal) const { +Vector2 GodotShape2D::get_support(const Vector2 &p_normal) const { Vector2 res[2]; int amnt; get_supports(p_normal, res, amnt); return res[0]; } -void Shape2DSW::add_owner(ShapeOwner2DSW *p_owner) { - Map<ShapeOwner2DSW *, int>::Element *E = owners.find(p_owner); +void GodotShape2D::add_owner(GodotShapeOwner2D *p_owner) { + Map<GodotShapeOwner2D *, int>::Element *E = owners.find(p_owner); if (E) { E->get()++; } else { @@ -58,8 +58,8 @@ void Shape2DSW::add_owner(ShapeOwner2DSW *p_owner) { } } -void Shape2DSW::remove_owner(ShapeOwner2DSW *p_owner) { - Map<ShapeOwner2DSW *, int>::Element *E = owners.find(p_owner); +void GodotShape2D::remove_owner(GodotShapeOwner2D *p_owner) { + Map<GodotShapeOwner2D *, int>::Element *E = owners.find(p_owner); ERR_FAIL_COND(!E); E->get()--; if (E->get() == 0) { @@ -67,15 +67,15 @@ void Shape2DSW::remove_owner(ShapeOwner2DSW *p_owner) { } } -bool Shape2DSW::is_owner(ShapeOwner2DSW *p_owner) const { +bool GodotShape2D::is_owner(GodotShapeOwner2D *p_owner) const { return owners.has(p_owner); } -const Map<ShapeOwner2DSW *, int> &Shape2DSW::get_owners() const { +const Map<GodotShapeOwner2D *, int> &GodotShape2D::get_owners() const { return owners; } -Shape2DSW::~Shape2DSW() { +GodotShape2D::~GodotShape2D() { ERR_FAIL_COND(owners.size()); } @@ -83,15 +83,15 @@ Shape2DSW::~Shape2DSW() { /*********************************************************/ /*********************************************************/ -void WorldBoundaryShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { +void GodotWorldBoundaryShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { r_amount = 0; } -bool WorldBoundaryShape2DSW::contains_point(const Vector2 &p_point) const { +bool GodotWorldBoundaryShape2D::contains_point(const Vector2 &p_point) const { return normal.dot(p_point) < d; } -bool WorldBoundaryShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { +bool GodotWorldBoundaryShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { Vector2 segment = p_begin - p_end; real_t den = normal.dot(segment); @@ -113,11 +113,11 @@ bool WorldBoundaryShape2DSW::intersect_segment(const Vector2 &p_begin, const Vec return true; } -real_t WorldBoundaryShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { +real_t GodotWorldBoundaryShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { return 0; } -void WorldBoundaryShape2DSW::set_data(const Variant &p_data) { +void GodotWorldBoundaryShape2D::set_data(const Variant &p_data) { ERR_FAIL_COND(p_data.get_type() != Variant::ARRAY); Array arr = p_data; ERR_FAIL_COND(arr.size() != 2); @@ -126,7 +126,7 @@ void WorldBoundaryShape2DSW::set_data(const Variant &p_data) { configure(Rect2(Vector2(-1e4, -1e4), Vector2(1e4 * 2, 1e4 * 2))); } -Variant WorldBoundaryShape2DSW::get_data() const { +Variant GodotWorldBoundaryShape2D::get_data() const { Array arr; arr.resize(2); arr[0] = normal; @@ -138,7 +138,7 @@ Variant WorldBoundaryShape2DSW::get_data() const { /*********************************************************/ /*********************************************************/ -void SeparationRayShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { +void GodotSeparationRayShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { r_amount = 1; if (p_normal.y > 0) { @@ -148,26 +148,26 @@ void SeparationRayShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_su } } -bool SeparationRayShape2DSW::contains_point(const Vector2 &p_point) const { +bool GodotSeparationRayShape2D::contains_point(const Vector2 &p_point) const { return false; } -bool SeparationRayShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { +bool GodotSeparationRayShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { return false; //rays can't be intersected } -real_t SeparationRayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { +real_t GodotSeparationRayShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { return 0; //rays are mass-less } -void SeparationRayShape2DSW::set_data(const Variant &p_data) { +void GodotSeparationRayShape2D::set_data(const Variant &p_data) { Dictionary d = p_data; length = d["length"]; slide_on_slope = d["slide_on_slope"]; configure(Rect2(0, 0, 0.001, length)); } -Variant SeparationRayShape2DSW::get_data() const { +Variant GodotSeparationRayShape2D::get_data() const { Dictionary d; d["length"] = length; d["slide_on_slope"] = slide_on_slope; @@ -178,7 +178,7 @@ Variant SeparationRayShape2DSW::get_data() const { /*********************************************************/ /*********************************************************/ -void SegmentShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { +void GodotSegmentShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { if (Math::abs(p_normal.dot(n)) > _SEGMENT_IS_VALID_SUPPORT_THRESHOLD) { r_supports[0] = a; r_supports[1] = b; @@ -195,11 +195,11 @@ void SegmentShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports r_amount = 1; } -bool SegmentShape2DSW::contains_point(const Vector2 &p_point) const { +bool GodotSegmentShape2D::contains_point(const Vector2 &p_point) const { return false; } -bool SegmentShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { +bool GodotSegmentShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { if (!Geometry2D::segment_intersects_segment(p_begin, p_end, a, b, &r_point)) { return false; } @@ -213,11 +213,11 @@ bool SegmentShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 & return true; } -real_t SegmentShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { +real_t GodotSegmentShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { return p_mass * ((a * p_scale).distance_squared_to(b * p_scale)) / 12; } -void SegmentShape2DSW::set_data(const Variant &p_data) { +void GodotSegmentShape2D::set_data(const Variant &p_data) { ERR_FAIL_COND(p_data.get_type() != Variant::RECT2); Rect2 r = p_data; @@ -237,7 +237,7 @@ void SegmentShape2DSW::set_data(const Variant &p_data) { configure(aabb); } -Variant SegmentShape2DSW::get_data() const { +Variant GodotSegmentShape2D::get_data() const { Rect2 r; r.position = a; r.size = b; @@ -248,16 +248,16 @@ Variant SegmentShape2DSW::get_data() const { /*********************************************************/ /*********************************************************/ -void CircleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { +void GodotCircleShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { r_amount = 1; *r_supports = p_normal * radius; } -bool CircleShape2DSW::contains_point(const Vector2 &p_point) const { +bool GodotCircleShape2D::contains_point(const Vector2 &p_point) const { return p_point.length_squared() < radius * radius; } -bool CircleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { +bool GodotCircleShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { Vector2 line_vec = p_end - p_begin; real_t a, b, c; @@ -283,19 +283,19 @@ bool CircleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p return true; } -real_t CircleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { +real_t GodotCircleShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { real_t a = radius * p_scale.x; real_t b = radius * p_scale.y; return p_mass * (a * a + b * b) / 4; } -void CircleShape2DSW::set_data(const Variant &p_data) { +void GodotCircleShape2D::set_data(const Variant &p_data) { ERR_FAIL_COND(!p_data.is_num()); radius = p_data; configure(Rect2(-radius, -radius, radius * 2, radius * 2)); } -Variant CircleShape2DSW::get_data() const { +Variant GodotCircleShape2D::get_data() const { return radius; } @@ -303,7 +303,7 @@ Variant CircleShape2DSW::get_data() const { /*********************************************************/ /*********************************************************/ -void RectangleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { +void GodotRectangleShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { for (int i = 0; i < 2; i++) { Vector2 ag; ag[i] = 1.0; @@ -333,7 +333,7 @@ void RectangleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_suppor (p_normal.y < 0) ? -half_extents.y : half_extents.y); } -bool RectangleShape2DSW::contains_point(const Vector2 &p_point) const { +bool GodotRectangleShape2D::contains_point(const Vector2 &p_point) const { real_t x = p_point.x; real_t y = p_point.y; real_t edge_x = half_extents.x; @@ -341,23 +341,23 @@ bool RectangleShape2DSW::contains_point(const Vector2 &p_point) const { return (x >= -edge_x) && (x < edge_x) && (y >= -edge_y) && (y < edge_y); } -bool RectangleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { +bool GodotRectangleShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { return get_aabb().intersects_segment(p_begin, p_end, &r_point, &r_normal); } -real_t RectangleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { +real_t GodotRectangleShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { Vector2 he2 = half_extents * 2 * p_scale; return p_mass * he2.dot(he2) / 12.0; } -void RectangleShape2DSW::set_data(const Variant &p_data) { +void GodotRectangleShape2D::set_data(const Variant &p_data) { ERR_FAIL_COND(p_data.get_type() != Variant::VECTOR2); half_extents = p_data; configure(Rect2(-half_extents, half_extents * 2.0)); } -Variant RectangleShape2DSW::get_data() const { +Variant GodotRectangleShape2D::get_data() const { return half_extents; } @@ -365,7 +365,7 @@ Variant RectangleShape2DSW::get_data() const { /*********************************************************/ /*********************************************************/ -void CapsuleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { +void GodotCapsuleShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { Vector2 n = p_normal; real_t d = n.y; @@ -392,7 +392,7 @@ void CapsuleShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports } } -bool CapsuleShape2DSW::contains_point(const Vector2 &p_point) const { +bool GodotCapsuleShape2D::contains_point(const Vector2 &p_point) const { Vector2 p = p_point; p.y = Math::abs(p.y); p.y -= height * 0.5 - radius; @@ -403,7 +403,7 @@ bool CapsuleShape2DSW::contains_point(const Vector2 &p_point) const { return p.length_squared() < radius * radius; } -bool CapsuleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { +bool GodotCapsuleShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { real_t d = 1e10; Vector2 n = (p_end - p_begin).normalized(); bool collided = false; @@ -463,12 +463,12 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 & return collided; //todo } -real_t CapsuleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { +real_t GodotCapsuleShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { Vector2 he2 = Vector2(radius * 2, height) * p_scale; return p_mass * he2.dot(he2) / 12.0; } -void CapsuleShape2DSW::set_data(const Variant &p_data) { +void GodotCapsuleShape2D::set_data(const Variant &p_data) { ERR_FAIL_COND(p_data.get_type() != Variant::ARRAY && p_data.get_type() != Variant::VECTOR2); if (p_data.get_type() == Variant::ARRAY) { @@ -486,7 +486,7 @@ void CapsuleShape2DSW::set_data(const Variant &p_data) { configure(Rect2(-he, he * 2)); } -Variant CapsuleShape2DSW::get_data() const { +Variant GodotCapsuleShape2D::get_data() const { return Point2(height, radius); } @@ -494,7 +494,7 @@ Variant CapsuleShape2DSW::get_data() const { /*********************************************************/ /*********************************************************/ -void ConvexPolygonShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { +void GodotConvexPolygonShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { int support_idx = -1; real_t d = -1e10; r_amount = 0; @@ -522,7 +522,7 @@ void ConvexPolygonShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_su r_supports[0] = points[support_idx].pos; } -bool ConvexPolygonShape2DSW::contains_point(const Vector2 &p_point) const { +bool GodotConvexPolygonShape2D::contains_point(const Vector2 &p_point) const { bool out = false; bool in = false; @@ -538,7 +538,7 @@ bool ConvexPolygonShape2DSW::contains_point(const Vector2 &p_point) const { return in != out; } -bool ConvexPolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { +bool GodotConvexPolygonShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { Vector2 n = (p_end - p_begin).normalized(); real_t d = 1e10; bool inters = false; @@ -568,7 +568,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vec return inters; } -real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { +real_t GodotConvexPolygonShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { ERR_FAIL_COND_V_MSG(point_count == 0, 0, "Convex polygon shape has no points."); Rect2 aabb; aabb.position = points[0].pos * p_scale; @@ -579,7 +579,7 @@ real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 return p_mass * aabb.size.dot(aabb.size) / 12.0; } -void ConvexPolygonShape2DSW::set_data(const Variant &p_data) { +void GodotConvexPolygonShape2D::set_data(const Variant &p_data) { #ifdef REAL_T_IS_DOUBLE ERR_FAIL_COND(p_data.get_type() != Variant::PACKED_VECTOR2_ARRAY && p_data.get_type() != Variant::PACKED_FLOAT64_ARRAY); #else @@ -635,7 +635,7 @@ void ConvexPolygonShape2DSW::set_data(const Variant &p_data) { configure(aabb); } -Variant ConvexPolygonShape2DSW::get_data() const { +Variant GodotConvexPolygonShape2D::get_data() const { Vector<Vector2> dvr; dvr.resize(point_count); @@ -647,7 +647,7 @@ Variant ConvexPolygonShape2DSW::get_data() const { return dvr; } -ConvexPolygonShape2DSW::~ConvexPolygonShape2DSW() { +GodotConvexPolygonShape2D::~GodotConvexPolygonShape2D() { if (points) { memdelete_arr(points); } @@ -655,7 +655,7 @@ ConvexPolygonShape2DSW::~ConvexPolygonShape2DSW() { ////////////////////////////////////////////////// -void ConcavePolygonShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { +void GodotConcavePolygonShape2D::get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const { real_t d = -1e10; int idx = -1; for (int i = 0; i < points.size(); i++) { @@ -671,11 +671,11 @@ void ConcavePolygonShape2DSW::get_supports(const Vector2 &p_normal, Vector2 *r_s *r_supports = points[idx]; } -bool ConcavePolygonShape2DSW::contains_point(const Vector2 &p_point) const { +bool GodotConcavePolygonShape2D::contains_point(const Vector2 &p_point) const { return false; //sorry } -bool ConcavePolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { +bool GodotConcavePolygonShape2D::intersect_segment(const Vector2 &p_begin, const Vector2 &p_end, Vector2 &r_point, Vector2 &r_normal) const { if (segments.size() == 0 || points.size() == 0) { return false; } @@ -783,7 +783,7 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2 &p_begin, const Ve return inters; } -int ConcavePolygonShape2DSW::_generate_bvh(BVH *p_bvh, int p_len, int p_depth) { +int GodotConcavePolygonShape2D::_generate_bvh(BVH *p_bvh, int p_len, int p_depth) { if (p_len == 1) { bvh_depth = MAX(p_depth, bvh_depth); bvh.push_back(*p_bvh); @@ -821,7 +821,7 @@ int ConcavePolygonShape2DSW::_generate_bvh(BVH *p_bvh, int p_len, int p_depth) { return node_idx; } -void ConcavePolygonShape2DSW::set_data(const Variant &p_data) { +void GodotConcavePolygonShape2D::set_data(const Variant &p_data) { #ifdef REAL_T_IS_DOUBLE ERR_FAIL_COND(p_data.get_type() != Variant::PACKED_VECTOR2_ARRAY && p_data.get_type() != Variant::PACKED_FLOAT64_ARRAY); #else @@ -898,7 +898,7 @@ void ConcavePolygonShape2DSW::set_data(const Variant &p_data) { configure(aabb); } -Variant ConcavePolygonShape2DSW::get_data() const { +Variant GodotConcavePolygonShape2D::get_data() const { Vector<Vector2> rsegments; int len = segments.size(); rsegments.resize(len * 2); @@ -911,7 +911,7 @@ Variant ConcavePolygonShape2DSW::get_data() const { return rsegments; } -void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, QueryCallback p_callback, void *p_userdata) const { +void GodotConcavePolygonShape2D::cull(const Rect2 &p_local_aabb, QueryCallback p_callback, void *p_userdata) const { uint32_t *stack = (uint32_t *)alloca(sizeof(int) * bvh_depth); enum { @@ -957,7 +957,7 @@ void ConcavePolygonShape2DSW::cull(const Rect2 &p_local_aabb, QueryCallback p_ca Vector2 a = pointptr[s.points[0]]; Vector2 b = pointptr[s.points[1]]; - SegmentShape2DSW ss(a, b, (b - a).orthogonal().normalized()); + GodotSegmentShape2D ss(a, b, (b - a).orthogonal().normalized()); if (p_callback(p_userdata, &ss)) { return; diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/godot_shape_2d.h index c118826284..25d113aafb 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/godot_shape_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* shape_2d_sw.h */ +/* godot_shape_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,29 +28,29 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHAPE_2D_2DSW_H -#define SHAPE_2D_2DSW_H +#ifndef GODOT_SHAPE_2D_H +#define GODOT_SHAPE_2D_H #include "servers/physics_server_2d.h" #define _SEGMENT_IS_VALID_SUPPORT_THRESHOLD 0.99998 -class Shape2DSW; +class GodotShape2D; -class ShapeOwner2DSW { +class GodotShapeOwner2D { public: virtual void _shape_changed() = 0; - virtual void remove_shape(Shape2DSW *p_shape) = 0; + virtual void remove_shape(GodotShape2D *p_shape) = 0; - virtual ~ShapeOwner2DSW() {} + virtual ~GodotShapeOwner2D() {} }; -class Shape2DSW { +class GodotShape2D { RID self; Rect2 aabb; bool configured = false; real_t custom_bias = 0.0; - Map<ShapeOwner2DSW *, int> owners; + Map<GodotShapeOwner2D *, int> owners; protected: void configure(const Rect2 &p_aabb); @@ -83,10 +83,10 @@ public: _FORCE_INLINE_ void set_custom_bias(real_t p_bias) { custom_bias = p_bias; } _FORCE_INLINE_ real_t get_custom_bias() const { return custom_bias; } - void add_owner(ShapeOwner2DSW *p_owner); - void remove_owner(ShapeOwner2DSW *p_owner); - bool is_owner(ShapeOwner2DSW *p_owner) const; - const Map<ShapeOwner2DSW *, int> &get_owners() const; + void add_owner(GodotShapeOwner2D *p_owner); + void remove_owner(GodotShapeOwner2D *p_owner); + bool is_owner(GodotShapeOwner2D *p_owner) const; + const Map<GodotShapeOwner2D *, int> &get_owners() const; _FORCE_INLINE_ void get_supports_transformed_cast(const Vector2 &p_cast, const Vector2 &p_normal, const Transform2D &p_xform, Vector2 *r_supports, int &r_amount) const { get_supports(p_xform.basis_xform_inv(p_normal).normalized(), r_supports, r_amount); @@ -121,8 +121,8 @@ public: } } } - Shape2DSW() {} - virtual ~Shape2DSW(); + GodotShape2D() {} + virtual ~GodotShape2D(); }; //let the optimizer do the magic @@ -141,7 +141,7 @@ public: r_max = MAX(maxa, maxb); \ } -class WorldBoundaryShape2DSW : public Shape2DSW { +class GodotWorldBoundaryShape2D : public GodotShape2D { Vector2 normal; real_t d = 0.0; @@ -178,7 +178,7 @@ public: } }; -class SeparationRayShape2DSW : public Shape2DSW { +class GodotSeparationRayShape2D : public GodotShape2D { real_t length = 0.0; bool slide_on_slope = false; @@ -211,11 +211,11 @@ public: DEFAULT_PROJECT_RANGE_CAST - _FORCE_INLINE_ SeparationRayShape2DSW() {} - _FORCE_INLINE_ SeparationRayShape2DSW(real_t p_length) { length = p_length; } + _FORCE_INLINE_ GodotSeparationRayShape2D() {} + _FORCE_INLINE_ GodotSeparationRayShape2D(real_t p_length) { length = p_length; } }; -class SegmentShape2DSW : public Shape2DSW { +class GodotSegmentShape2D : public GodotShape2D { Vector2 a; Vector2 b; Vector2 n; @@ -251,15 +251,15 @@ public: DEFAULT_PROJECT_RANGE_CAST - _FORCE_INLINE_ SegmentShape2DSW() {} - _FORCE_INLINE_ SegmentShape2DSW(const Vector2 &p_a, const Vector2 &p_b, const Vector2 &p_n) { + _FORCE_INLINE_ GodotSegmentShape2D() {} + _FORCE_INLINE_ GodotSegmentShape2D(const Vector2 &p_a, const Vector2 &p_b, const Vector2 &p_n) { a = p_a; b = p_b; n = p_n; } }; -class CircleShape2DSW : public Shape2DSW { +class GodotCircleShape2D : public GodotShape2D { real_t radius; public: @@ -292,7 +292,7 @@ public: DEFAULT_PROJECT_RANGE_CAST }; -class RectangleShape2DSW : public Shape2DSW { +class GodotRectangleShape2D : public GodotShape2D { Vector2 half_extents; public: @@ -336,7 +336,7 @@ public: return (p_xform.xform(he) - p_circle).normalized(); } - _FORCE_INLINE_ Vector2 get_box_axis(const Transform2D &p_xform, const Transform2D &p_xform_inv, const RectangleShape2DSW *p_B, const Transform2D &p_B_xform, const Transform2D &p_B_xform_inv) const { + _FORCE_INLINE_ Vector2 get_box_axis(const Transform2D &p_xform, const Transform2D &p_xform_inv, const GodotRectangleShape2D *p_B, const Transform2D &p_B_xform, const Transform2D &p_B_xform_inv) const { Vector2 a, b; { @@ -364,7 +364,7 @@ public: DEFAULT_PROJECT_RANGE_CAST }; -class CapsuleShape2DSW : public Shape2DSW { +class GodotCapsuleShape2D : public GodotShape2D { real_t radius = 0.0; real_t height = 0.0; @@ -405,7 +405,7 @@ public: DEFAULT_PROJECT_RANGE_CAST }; -class ConvexPolygonShape2DSW : public Shape2DSW { +class GodotConvexPolygonShape2D : public GodotShape2D { struct Point { Vector2 pos; Vector2 normal; //normal to next segment @@ -457,21 +457,21 @@ public: DEFAULT_PROJECT_RANGE_CAST - ConvexPolygonShape2DSW() {} - ~ConvexPolygonShape2DSW(); + GodotConvexPolygonShape2D() {} + ~GodotConvexPolygonShape2D(); }; -class ConcaveShape2DSW : public Shape2DSW { +class GodotConcaveShape2D : public GodotShape2D { public: virtual bool is_concave() const override { return true; } // Returns true to stop the query. - typedef bool (*QueryCallback)(void *p_userdata, Shape2DSW *p_convex); + typedef bool (*QueryCallback)(void *p_userdata, GodotShape2D *p_convex); virtual void cull(const Rect2 &p_local_aabb, QueryCallback p_callback, void *p_userdata) const = 0; }; -class ConcavePolygonShape2DSW : public ConcaveShape2DSW { +class GodotConcavePolygonShape2D : public GodotConcaveShape2D { struct Segment { int points[2] = {}; }; @@ -507,13 +507,13 @@ public: virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const override { r_min = 0; r_max = 0; - ERR_FAIL_MSG("Unsupported call to project_rangev in ConcavePolygonShape2DSW"); + ERR_FAIL_MSG("Unsupported call to project_rangev in GodotConcavePolygonShape2D"); } void project_range(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { r_min = 0; r_max = 0; - ERR_FAIL_MSG("Unsupported call to project_range in ConcavePolygonShape2DSW"); + ERR_FAIL_MSG("Unsupported call to project_range in GodotConcavePolygonShape2D"); } virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const override; @@ -533,4 +533,4 @@ public: #undef DEFAULT_PROJECT_RANGE_CAST -#endif // SHAPE_2D_2DSW_H +#endif // GODOT_SHAPE_2D_H diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/godot_space_2d.cpp index dd0780b5ff..d72014a8ed 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* space_2d_sw.cpp */ +/* godot_space_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,32 +28,33 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "space_2d_sw.h" +#include "godot_space_2d.h" + +#include "godot_collision_solver_2d.h" +#include "godot_physics_server_2d.h" -#include "collision_solver_2d_sw.h" #include "core/os/os.h" #include "core/templates/pair.h" -#include "physics_server_2d_sw.h" #define TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR 0.05 -_FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +_FORCE_INLINE_ static bool _can_collide_with(GodotCollisionObject2D *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (!(p_object->get_collision_layer() & p_collision_mask)) { return false; } - if (p_object->get_type() == CollisionObject2DSW::TYPE_AREA && !p_collide_with_areas) { + if (p_object->get_type() == GodotCollisionObject2D::TYPE_AREA && !p_collide_with_areas) { return false; } - if (p_object->get_type() == CollisionObject2DSW::TYPE_BODY && !p_collide_with_bodies) { + if (p_object->get_type() == GodotCollisionObject2D::TYPE_BODY && !p_collide_with_bodies) { return false; } return true; } -int PhysicsDirectSpaceState2DSW::_intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) { +int GodotPhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) { if (p_result_max <= 0) { return 0; } @@ -62,7 +63,7 @@ int PhysicsDirectSpaceState2DSW::_intersect_point_impl(const Vector2 &p_point, S aabb.position = p_point - Vector2(0.00001, 0.00001); aabb.size = Vector2(0.00002, 0.00002); - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); int cc = 0; @@ -75,7 +76,7 @@ int PhysicsDirectSpaceState2DSW::_intersect_point_impl(const Vector2 &p_point, S continue; } - const CollisionObject2DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; if (p_pick_point && !col_obj->is_pickable()) { continue; @@ -87,7 +88,7 @@ int PhysicsDirectSpaceState2DSW::_intersect_point_impl(const Vector2 &p_point, S int shape_idx = space->intersection_query_subindex_results[i]; - Shape2DSW *shape = col_obj->get_shape(shape_idx); + GodotShape2D *shape = col_obj->get_shape(shape_idx); Vector2 local_point = (col_obj->get_transform() * col_obj->get_shape_transform(shape_idx)).affine_inverse().xform(p_point); @@ -112,15 +113,15 @@ int PhysicsDirectSpaceState2DSW::_intersect_point_impl(const Vector2 &p_point, S return cc; } -int PhysicsDirectSpaceState2DSW::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) { +int GodotPhysicsDirectSpaceState2D::intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) { return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point); } -int PhysicsDirectSpaceState2DSW::intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) { +int GodotPhysicsDirectSpaceState2D::intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point) { return _intersect_point_impl(p_point, r_results, p_result_max, p_exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas, p_pick_point, true, p_canvas_instance_id); } -bool PhysicsDirectSpaceState2DSW::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +bool GodotPhysicsDirectSpaceState2D::intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { ERR_FAIL_COND_V(space->locked, false); Vector2 begin, end; @@ -129,14 +130,14 @@ bool PhysicsDirectSpaceState2DSW::intersect_ray(const Vector2 &p_from, const Vec end = p_to; normal = (end - begin).normalized(); - int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); //todo, create another array that references results, compute AABBs and check closest point to ray origin, sort, and stop evaluating results when beyond first collision bool collided = false; Vector2 res_point, res_normal; int res_shape; - const CollisionObject2DSW *res_obj; + const GodotCollisionObject2D *res_obj; real_t min_d = 1e10; for (int i = 0; i < amount; i++) { @@ -148,7 +149,7 @@ bool PhysicsDirectSpaceState2DSW::intersect_ray(const Vector2 &p_from, const Vec continue; } - const CollisionObject2DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; int shape_idx = space->intersection_query_subindex_results[i]; Transform2D inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform(); @@ -162,7 +163,7 @@ bool PhysicsDirectSpaceState2DSW::intersect_ray(const Vector2 &p_from, const Vec local_to = col_obj->get_inv_transform().xform(end); local_to = col_obj->get_shape_inv_transform(shape_idx).xform(local_to);*/ - const Shape2DSW *shape = col_obj->get_shape(shape_idx); + const GodotShape2D *shape = col_obj->get_shape(shape_idx); Vector2 shape_point, shape_normal; @@ -199,18 +200,18 @@ bool PhysicsDirectSpaceState2DSW::intersect_ray(const Vector2 &p_from, const Vec return true; } -int PhysicsDirectSpaceState2DSW::intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +int GodotPhysicsDirectSpaceState2D::intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (p_result_max <= 0) { return 0; } - Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape); + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); ERR_FAIL_COND_V(!shape, 0); Rect2 aabb = p_xform.xform(shape->get_aabb()); aabb = aabb.grow(p_margin); - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); int cc = 0; @@ -227,10 +228,10 @@ int PhysicsDirectSpaceState2DSW::intersect_shape(const RID &p_shape, const Trans continue; } - const CollisionObject2DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; int shape_idx = space->intersection_query_subindex_results[i]; - if (!CollisionSolver2DSW::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), nullptr, nullptr, nullptr, p_margin)) { + if (!GodotCollisionSolver2D::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), nullptr, nullptr, nullptr, p_margin)) { continue; } @@ -247,15 +248,15 @@ int PhysicsDirectSpaceState2DSW::intersect_shape(const RID &p_shape, const Trans return cc; } -bool PhysicsDirectSpaceState2DSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState2D::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); ERR_FAIL_COND_V(!shape, false); Rect2 aabb = p_xform.xform(shape->get_aabb()); aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion aabb = aabb.grow(p_margin); - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); real_t best_safe = 1; real_t best_unsafe = 1; @@ -269,17 +270,17 @@ bool PhysicsDirectSpaceState2DSW::cast_motion(const RID &p_shape, const Transfor continue; //ignore excluded } - const CollisionObject2DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; int shape_idx = space->intersection_query_subindex_results[i]; Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? - if (!CollisionSolver2DSW::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) { + if (!GodotCollisionSolver2D::solve(shape, p_xform, p_motion, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) { continue; } //test initial overlap, ignore objects it's inside of. - if (CollisionSolver2DSW::solve(shape, p_xform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) { + if (GodotCollisionSolver2D::solve(shape, p_xform, Vector2(), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, nullptr, p_margin)) { continue; } @@ -293,7 +294,7 @@ bool PhysicsDirectSpaceState2DSW::cast_motion(const RID &p_shape, const Transfor real_t fraction = low + (hi - low) * fraction_coeff; Vector2 sep = mnormal; //important optimization for this to work fast enough - bool collided = CollisionSolver2DSW::solve(shape, p_xform, p_motion * fraction, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, &sep, p_margin); + bool collided = GodotCollisionSolver2D::solve(shape, p_xform, p_motion * fraction, col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), nullptr, nullptr, &sep, p_margin); if (collided) { hi = fraction; @@ -330,38 +331,38 @@ bool PhysicsDirectSpaceState2DSW::cast_motion(const RID &p_shape, const Transfor return true; } -bool PhysicsDirectSpaceState2DSW::collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +bool GodotPhysicsDirectSpaceState2D::collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (p_result_max <= 0) { return false; } - Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape); + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); ERR_FAIL_COND_V(!shape, 0); Rect2 aabb = p_shape_xform.xform(shape->get_aabb()); aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion aabb = aabb.grow(p_margin); - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); bool collided = false; r_result_count = 0; - PhysicsServer2DSW::CollCbkData cbk; + GodotPhysicsServer2D::CollCbkData cbk; cbk.max = p_result_max; cbk.amount = 0; cbk.passed = 0; cbk.ptr = r_results; - CollisionSolver2DSW::CallbackResult cbkres = PhysicsServer2DSW::_shape_col_cbk; + GodotCollisionSolver2D::CallbackResult cbkres = GodotPhysicsServer2D::_shape_col_cbk; - PhysicsServer2DSW::CollCbkData *cbkptr = &cbk; + GodotPhysicsServer2D::CollCbkData *cbkptr = &cbk; for (int i = 0; i < amount; i++) { if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { continue; } - const CollisionObject2DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; if (p_exclude.has(col_obj->get_self())) { continue; @@ -372,7 +373,7 @@ bool PhysicsDirectSpaceState2DSW::collide_shape(RID p_shape, const Transform2D & cbk.valid_dir = Vector2(); cbk.valid_depth = 0; - if (CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, nullptr, p_margin)) { + if (GodotCollisionSolver2D::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, nullptr, p_margin)) { collided = cbk.amount > 0; } } @@ -383,8 +384,8 @@ bool PhysicsDirectSpaceState2DSW::collide_shape(RID p_shape, const Transform2D & } struct _RestCallbackData2D { - const CollisionObject2DSW *object = nullptr; - const CollisionObject2DSW *best_object = nullptr; + const GodotCollisionObject2D *object = nullptr; + const GodotCollisionObject2D *best_object = nullptr; int local_shape = 0; int best_local_shape = 0; int shape = 0; @@ -431,8 +432,8 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, rd->best_local_shape = rd->local_shape; } -bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState2D::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { + GodotShape2D *shape = GodotPhysicsServer2D::godot_singleton->shape_owner.get_or_null(p_shape); ERR_FAIL_COND_V(!shape, 0); real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; @@ -441,7 +442,7 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh aabb = aabb.merge(Rect2(aabb.position + p_motion, aabb.size)); //motion aabb = aabb.grow(p_margin); - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace2D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); _RestCallbackData2D rcd; rcd.best_len = 0; @@ -454,7 +455,7 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh continue; } - const CollisionObject2DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject2D *col_obj = space->intersection_query_results[i]; if (p_exclude.has(col_obj->get_self())) { continue; @@ -466,7 +467,7 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh rcd.object = col_obj; rcd.shape = shape_idx; rcd.local_shape = 0; - bool sc = CollisionSolver2DSW::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, nullptr, p_margin); + bool sc = GodotCollisionSolver2D::solve(shape, p_shape_xform, p_motion, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, nullptr, p_margin); if (!sc) { continue; } @@ -481,8 +482,8 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh r_info->normal = rcd.best_normal; r_info->point = rcd.best_contact; r_info->rid = rcd.best_object->get_self(); - if (rcd.best_object->get_type() == CollisionObject2DSW::TYPE_BODY) { - const Body2DSW *body = static_cast<const Body2DSW *>(rcd.best_object); + if (rcd.best_object->get_type() == GodotCollisionObject2D::TYPE_BODY) { + const GodotBody2D *body = static_cast<const GodotBody2D *>(rcd.best_object); Vector2 rel_vec = r_info->point - (body->get_transform().get_origin() + body->get_center_of_mass()); r_info->linear_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); @@ -495,7 +496,7 @@ bool PhysicsDirectSpaceState2DSW::rest_info(RID p_shape, const Transform2D &p_sh //////////////////////////////////////////////////////////////////////////////////////////////////////////// -int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) { +int GodotSpace2D::_cull_aabb_for_body(GodotBody2D *p_body, const Rect2 &p_aabb) { int amount = broadphase->cull_aabb(p_aabb, intersection_query_results, INTERSECTION_QUERY_MAX, intersection_query_subindex_results); for (int i = 0; i < amount; i++) { @@ -503,11 +504,11 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) { if (intersection_query_results[i] == p_body) { keep = false; - } else if (intersection_query_results[i]->get_type() == CollisionObject2DSW::TYPE_AREA) { + } else if (intersection_query_results[i]->get_type() == GodotCollisionObject2D::TYPE_AREA) { keep = false; - } else if (!p_body->collides_with(static_cast<Body2DSW *>(intersection_query_results[i]))) { + } else if (!p_body->collides_with(static_cast<GodotBody2D *>(intersection_query_results[i]))) { keep = false; - } else if (static_cast<Body2DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) { + } else if (static_cast<GodotBody2D *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) { keep = false; } @@ -525,7 +526,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) { return amount; } -bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result) { +bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result) { //give me back regular physics engine logic //this is madness //and most people using this function will think @@ -587,7 +588,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion Vector2 sr[max_results * 2]; do { - PhysicsServer2DSW::CollCbkData cbk; + GodotPhysicsServer2D::CollCbkData cbk; cbk.max = max_results; cbk.amount = 0; cbk.passed = 0; @@ -595,8 +596,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion cbk.invalid_by_dir = 0; excluded_shape_pair_count = 0; //last step is the one valid - PhysicsServer2DSW::CollCbkData *cbkptr = &cbk; - CollisionSolver2DSW::CallbackResult cbkres = PhysicsServer2DSW::_shape_col_cbk; + GodotPhysicsServer2D::CollCbkData *cbkptr = &cbk; + GodotCollisionSolver2D::CallbackResult cbkres = GodotPhysicsServer2D::_shape_col_cbk; bool collided = false; @@ -607,11 +608,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion continue; } - Shape2DSW *body_shape = p_body->get_shape(j); + GodotShape2D *body_shape = p_body->get_shape(j); Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j); for (int i = 0; i < amount; i++) { - const CollisionObject2DSW *col_obj = intersection_query_results[i]; + const GodotCollisionObject2D *col_obj = intersection_query_results[i]; if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } @@ -630,8 +631,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion cbk.valid_depth = MAX(owc_margin, p_parameters.margin); //user specified, but never less than actual margin or it won't work cbk.invalid_by_dir = 0; - if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) { - const Body2DSW *b = static_cast<const Body2DSW *>(col_obj); + if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) { + const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj); if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) { //fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction Vector2 lv = b->get_linear_velocity(); @@ -651,8 +652,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion int current_passed = cbk.passed; //save how many points passed collision bool did_collide = false; - Shape2DSW *against_shape = col_obj->get_shape(shape_idx); - if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_parameters.margin)) { + GodotShape2D *against_shape = col_obj->get_shape(shape_idx); + if (GodotCollisionSolver2D::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, p_parameters.margin)) { did_collide = cbk.passed > current_passed; //more passed, so collision actually existed } @@ -727,13 +728,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion continue; } - Shape2DSW *body_shape = p_body->get_shape(body_shape_idx); + GodotShape2D *body_shape = p_body->get_shape(body_shape_idx); // Colliding separation rays allows to properly snap to the ground, // otherwise it's not needed in regular motion. if (!p_parameters.collide_separation_ray && (body_shape->get_type() == PhysicsServer2D::SHAPE_SEPARATION_RAY)) { // When slide on slope is on, separation ray shape acts like a regular shape. - if (!static_cast<SeparationRayShape2DSW *>(body_shape)->get_slide_on_slope()) { + if (!static_cast<GodotSeparationRayShape2D *>(body_shape)->get_slide_on_slope()) { continue; } } @@ -746,7 +747,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion real_t best_unsafe = 1; for (int i = 0; i < amount; i++) { - const CollisionObject2DSW *col_obj = intersection_query_results[i]; + const GodotCollisionObject2D *col_obj = intersection_query_results[i]; if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } @@ -755,7 +756,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion } int col_shape_idx = intersection_query_subindex_results[i]; - Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx); + GodotShape2D *against_shape = col_obj->get_shape(col_shape_idx); bool excluded = false; @@ -772,12 +773,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx); //test initial overlap, does it collide if going all the way? - if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) { + if (!GodotCollisionSolver2D::solve(body_shape, body_shape_xform, p_parameters.motion, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) { continue; } //test initial overlap - if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) { + if (GodotCollisionSolver2D::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, nullptr, 0)) { if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) { Vector2 direction = col_obj_shape_xform.get_axis(1).normalized(); if (motion_normal.dot(direction) < 0) { @@ -797,7 +798,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion real_t fraction = low + (hi - low) * fraction_coeff; Vector2 sep = motion_normal; //important optimization for this to work fast enough - bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion * fraction, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0); + bool collided = GodotCollisionSolver2D::solve(body_shape, body_shape_xform, p_parameters.motion * fraction, against_shape, col_obj_shape_xform, Vector2(), nullptr, nullptr, &sep, 0); if (collided) { hi = fraction; @@ -824,7 +825,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion if (body_shape->allows_one_way_collision() && col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) { Vector2 cd[2]; - PhysicsServer2DSW::CollCbkData cbk; + GodotPhysicsServer2D::CollCbkData cbk; cbk.max = 1; cbk.amount = 0; cbk.passed = 0; @@ -834,7 +835,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion cbk.valid_depth = 10e20; Vector2 sep = motion_normal; //important optimization for this to work fast enough - bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_parameters.motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), PhysicsServer2DSW::_shape_col_cbk, &cbk, &sep, 0); + bool collided = GodotCollisionSolver2D::solve(body_shape, body_shape_xform, p_parameters.motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), GodotPhysicsServer2D::_shape_col_cbk, &cbk, &sep, 0); if (!collided || cbk.amount == 0) { continue; } @@ -891,14 +892,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion } Transform2D body_shape_xform = ugt * p_body->get_shape_transform(j); - Shape2DSW *body_shape = p_body->get_shape(j); + GodotShape2D *body_shape = p_body->get_shape(j); body_aabb.position += p_parameters.motion * unsafe; int amount = _cull_aabb_for_body(p_body, body_aabb); for (int i = 0; i < amount; i++) { - const CollisionObject2DSW *col_obj = intersection_query_results[i]; + const GodotCollisionObject2D *col_obj = intersection_query_results[i]; if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } @@ -908,7 +909,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion int shape_idx = intersection_query_subindex_results[i]; - Shape2DSW *against_shape = col_obj->get_shape(shape_idx); + GodotShape2D *against_shape = col_obj->get_shape(shape_idx); bool excluded = false; for (int k = 0; k < excluded_shape_pair_count; k++) { @@ -929,8 +930,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion real_t owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx); rcd.valid_depth = MAX(owc_margin, p_parameters.margin); //user specified, but never less than actual margin or it won't work - if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) { - const Body2DSW *b = static_cast<const Body2DSW *>(col_obj); + if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) { + const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj); if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) { //fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction Vector2 lv = b->get_linear_velocity(); @@ -949,7 +950,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion rcd.object = col_obj; rcd.shape = shape_idx; rcd.local_shape = j; - bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, p_parameters.margin); + bool sc = GodotCollisionSolver2D::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, nullptr, p_parameters.margin); if (!sc) { continue; } @@ -968,7 +969,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion r_result->collision_safe_fraction = safe; r_result->collision_unsafe_fraction = unsafe; - const Body2DSW *body = static_cast<const Body2DSW *>(rcd.best_object); + const GodotBody2D *body = static_cast<const GodotBody2D *>(rcd.best_object); Vector2 rel_vec = r_result->collision_point - (body->get_transform().get_origin() + body->get_center_of_mass()); r_result->collider_velocity = Vector2(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); @@ -990,134 +991,134 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const PhysicsServer2D::Motion return collided; } -void *Space2DSW::_broadphase_pair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_self) { +void *GodotSpace2D::_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_self) { if (!A->interacts_with(B)) { return nullptr; } - CollisionObject2DSW::Type type_A = A->get_type(); - CollisionObject2DSW::Type type_B = B->get_type(); + GodotCollisionObject2D::Type type_A = A->get_type(); + GodotCollisionObject2D::Type type_B = B->get_type(); if (type_A > type_B) { SWAP(A, B); SWAP(p_subindex_A, p_subindex_B); SWAP(type_A, type_B); } - Space2DSW *self = (Space2DSW *)p_self; + GodotSpace2D *self = (GodotSpace2D *)p_self; self->collision_pairs++; - if (type_A == CollisionObject2DSW::TYPE_AREA) { - Area2DSW *area = static_cast<Area2DSW *>(A); - if (type_B == CollisionObject2DSW::TYPE_AREA) { - Area2DSW *area_b = static_cast<Area2DSW *>(B); - Area2Pair2DSW *area2_pair = memnew(Area2Pair2DSW(area_b, p_subindex_B, area, p_subindex_A)); + if (type_A == GodotCollisionObject2D::TYPE_AREA) { + GodotArea2D *area = static_cast<GodotArea2D *>(A); + if (type_B == GodotCollisionObject2D::TYPE_AREA) { + GodotArea2D *area_b = static_cast<GodotArea2D *>(B); + GodotArea2Pair2D *area2_pair = memnew(GodotArea2Pair2D(area_b, p_subindex_B, area, p_subindex_A)); return area2_pair; } else { - Body2DSW *body = static_cast<Body2DSW *>(B); - AreaPair2DSW *area_pair = memnew(AreaPair2DSW(body, p_subindex_B, area, p_subindex_A)); + GodotBody2D *body = static_cast<GodotBody2D *>(B); + GodotAreaPair2D *area_pair = memnew(GodotAreaPair2D(body, p_subindex_B, area, p_subindex_A)); return area_pair; } } else { - BodyPair2DSW *b = memnew(BodyPair2DSW((Body2DSW *)A, p_subindex_A, (Body2DSW *)B, p_subindex_B)); + GodotBodyPair2D *b = memnew(GodotBodyPair2D((GodotBody2D *)A, p_subindex_A, (GodotBody2D *)B, p_subindex_B)); return b; } return nullptr; } -void Space2DSW::_broadphase_unpair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_data, void *p_self) { +void GodotSpace2D::_broadphase_unpair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_data, void *p_self) { if (!p_data) { return; } - Space2DSW *self = (Space2DSW *)p_self; + GodotSpace2D *self = (GodotSpace2D *)p_self; self->collision_pairs--; - Constraint2DSW *c = (Constraint2DSW *)p_data; + GodotConstraint2D *c = (GodotConstraint2D *)p_data; memdelete(c); } -const SelfList<Body2DSW>::List &Space2DSW::get_active_body_list() const { +const SelfList<GodotBody2D>::List &GodotSpace2D::get_active_body_list() const { return active_list; } -void Space2DSW::body_add_to_active_list(SelfList<Body2DSW> *p_body) { +void GodotSpace2D::body_add_to_active_list(SelfList<GodotBody2D> *p_body) { active_list.add(p_body); } -void Space2DSW::body_remove_from_active_list(SelfList<Body2DSW> *p_body) { +void GodotSpace2D::body_remove_from_active_list(SelfList<GodotBody2D> *p_body) { active_list.remove(p_body); } -void Space2DSW::body_add_to_mass_properties_update_list(SelfList<Body2DSW> *p_body) { +void GodotSpace2D::body_add_to_mass_properties_update_list(SelfList<GodotBody2D> *p_body) { mass_properties_update_list.add(p_body); } -void Space2DSW::body_remove_from_mass_properties_update_list(SelfList<Body2DSW> *p_body) { +void GodotSpace2D::body_remove_from_mass_properties_update_list(SelfList<GodotBody2D> *p_body) { mass_properties_update_list.remove(p_body); } -BroadPhase2DSW *Space2DSW::get_broadphase() { +GodotBroadPhase2D *GodotSpace2D::get_broadphase() { return broadphase; } -void Space2DSW::add_object(CollisionObject2DSW *p_object) { +void GodotSpace2D::add_object(GodotCollisionObject2D *p_object) { ERR_FAIL_COND(objects.has(p_object)); objects.insert(p_object); } -void Space2DSW::remove_object(CollisionObject2DSW *p_object) { +void GodotSpace2D::remove_object(GodotCollisionObject2D *p_object) { ERR_FAIL_COND(!objects.has(p_object)); objects.erase(p_object); } -const Set<CollisionObject2DSW *> &Space2DSW::get_objects() const { +const Set<GodotCollisionObject2D *> &GodotSpace2D::get_objects() const { return objects; } -void Space2DSW::body_add_to_state_query_list(SelfList<Body2DSW> *p_body) { +void GodotSpace2D::body_add_to_state_query_list(SelfList<GodotBody2D> *p_body) { state_query_list.add(p_body); } -void Space2DSW::body_remove_from_state_query_list(SelfList<Body2DSW> *p_body) { +void GodotSpace2D::body_remove_from_state_query_list(SelfList<GodotBody2D> *p_body) { state_query_list.remove(p_body); } -void Space2DSW::area_add_to_monitor_query_list(SelfList<Area2DSW> *p_area) { +void GodotSpace2D::area_add_to_monitor_query_list(SelfList<GodotArea2D> *p_area) { monitor_query_list.add(p_area); } -void Space2DSW::area_remove_from_monitor_query_list(SelfList<Area2DSW> *p_area) { +void GodotSpace2D::area_remove_from_monitor_query_list(SelfList<GodotArea2D> *p_area) { monitor_query_list.remove(p_area); } -void Space2DSW::area_add_to_moved_list(SelfList<Area2DSW> *p_area) { +void GodotSpace2D::area_add_to_moved_list(SelfList<GodotArea2D> *p_area) { area_moved_list.add(p_area); } -void Space2DSW::area_remove_from_moved_list(SelfList<Area2DSW> *p_area) { +void GodotSpace2D::area_remove_from_moved_list(SelfList<GodotArea2D> *p_area) { area_moved_list.remove(p_area); } -const SelfList<Area2DSW>::List &Space2DSW::get_moved_area_list() const { +const SelfList<GodotArea2D>::List &GodotSpace2D::get_moved_area_list() const { return area_moved_list; } -void Space2DSW::call_queries() { +void GodotSpace2D::call_queries() { while (state_query_list.first()) { - Body2DSW *b = state_query_list.first()->self(); + GodotBody2D *b = state_query_list.first()->self(); state_query_list.remove(state_query_list.first()); b->call_queries(); } while (monitor_query_list.first()) { - Area2DSW *a = monitor_query_list.first()->self(); + GodotArea2D *a = monitor_query_list.first()->self(); monitor_query_list.remove(monitor_query_list.first()); a->call_queries(); } } -void Space2DSW::setup() { +void GodotSpace2D::setup() { contact_debug_count = 0; while (mass_properties_update_list.first()) { @@ -1126,11 +1127,11 @@ void Space2DSW::setup() { } } -void Space2DSW::update() { +void GodotSpace2D::update() { broadphase->update(); } -void Space2DSW::set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_value) { +void GodotSpace2D::set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_value) { switch (p_param) { case PhysicsServer2D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: contact_recycle_radius = p_value; @@ -1156,7 +1157,7 @@ void Space2DSW::set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_valu } } -real_t Space2DSW::get_param(PhysicsServer2D::SpaceParameter p_param) const { +real_t GodotSpace2D::get_param(PhysicsServer2D::SpaceParameter p_param) const { switch (p_param) { case PhysicsServer2D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: return contact_recycle_radius; @@ -1176,37 +1177,37 @@ real_t Space2DSW::get_param(PhysicsServer2D::SpaceParameter p_param) const { return 0; } -void Space2DSW::lock() { +void GodotSpace2D::lock() { locked = true; } -void Space2DSW::unlock() { +void GodotSpace2D::unlock() { locked = false; } -bool Space2DSW::is_locked() const { +bool GodotSpace2D::is_locked() const { return locked; } -PhysicsDirectSpaceState2DSW *Space2DSW::get_direct_state() { +GodotPhysicsDirectSpaceState2D *GodotSpace2D::get_direct_state() { return direct_access; } -Space2DSW::Space2DSW() { +GodotSpace2D::GodotSpace2D() { body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0); body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg2rad(8.0)); body_time_to_sleep = GLOBAL_DEF("physics/2d/time_before_sleep", 0.5); ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); - broadphase = BroadPhase2DSW::create_func(); + broadphase = GodotBroadPhase2D::create_func(); broadphase->set_pair_callback(_broadphase_pair, this); broadphase->set_unpair_callback(_broadphase_unpair, this); - direct_access = memnew(PhysicsDirectSpaceState2DSW); + direct_access = memnew(GodotPhysicsDirectSpaceState2D); direct_access->space = this; } -Space2DSW::~Space2DSW() { +GodotSpace2D::~GodotSpace2D() { memdelete(broadphase); memdelete(direct_access); } diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/godot_space_2d.h index 746b5c6c9a..97e2928a9d 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/godot_space_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* space_2d_sw.h */ +/* godot_space_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,26 +28,27 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SPACE_2D_SW_H -#define SPACE_2D_SW_H +#ifndef GODOT_SPACE_2D_H +#define GODOT_SPACE_2D_H + +#include "godot_area_2d.h" +#include "godot_area_pair_2d.h" +#include "godot_body_2d.h" +#include "godot_body_pair_2d.h" +#include "godot_broad_phase_2d.h" +#include "godot_collision_object_2d.h" -#include "area_2d_sw.h" -#include "area_pair_2d_sw.h" -#include "body_2d_sw.h" -#include "body_pair_2d_sw.h" -#include "broad_phase_2d_sw.h" -#include "collision_object_2d_sw.h" #include "core/config/project_settings.h" #include "core/templates/hash_map.h" #include "core/typedefs.h" -class PhysicsDirectSpaceState2DSW : public PhysicsDirectSpaceState2D { - GDCLASS(PhysicsDirectSpaceState2DSW, PhysicsDirectSpaceState2D); +class GodotPhysicsDirectSpaceState2D : public PhysicsDirectSpaceState2D { + GDCLASS(GodotPhysicsDirectSpaceState2D, PhysicsDirectSpaceState2D); int _intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID()); public: - Space2DSW *space = nullptr; + GodotSpace2D *space = nullptr; virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override; virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) override; @@ -57,10 +58,10 @@ public: virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; - PhysicsDirectSpaceState2DSW() {} + GodotPhysicsDirectSpaceState2D() {} }; -class Space2DSW { +class GodotSpace2D { public: enum ElapsedTime { ELAPSED_TIME_INTEGRATE_FORCES, @@ -74,29 +75,29 @@ public: private: struct ExcludedShapeSW { - Shape2DSW *local_shape = nullptr; - const CollisionObject2DSW *against_object = nullptr; + GodotShape2D *local_shape = nullptr; + const GodotCollisionObject2D *against_object = nullptr; int against_shape_index = 0; }; uint64_t elapsed_time[ELAPSED_TIME_MAX] = {}; - PhysicsDirectSpaceState2DSW *direct_access = nullptr; + GodotPhysicsDirectSpaceState2D *direct_access = nullptr; RID self; - BroadPhase2DSW *broadphase; - SelfList<Body2DSW>::List active_list; - SelfList<Body2DSW>::List mass_properties_update_list; - SelfList<Body2DSW>::List state_query_list; - SelfList<Area2DSW>::List monitor_query_list; - SelfList<Area2DSW>::List area_moved_list; + GodotBroadPhase2D *broadphase; + SelfList<GodotBody2D>::List active_list; + SelfList<GodotBody2D>::List mass_properties_update_list; + SelfList<GodotBody2D>::List state_query_list; + SelfList<GodotArea2D>::List monitor_query_list; + SelfList<GodotArea2D>::List area_moved_list; - static void *_broadphase_pair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_self); - static void _broadphase_unpair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_data, void *p_self); + static void *_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_self); + static void _broadphase_unpair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_data, void *p_self); - Set<CollisionObject2DSW *> objects; + Set<GodotCollisionObject2D *> objects; - Area2DSW *area = nullptr; + GodotArea2D *area = nullptr; real_t contact_recycle_radius = 1.0; real_t contact_max_separation = 1.5; @@ -107,7 +108,7 @@ private: INTERSECTION_QUERY_MAX = 2048 }; - CollisionObject2DSW *intersection_query_results[INTERSECTION_QUERY_MAX]; + GodotCollisionObject2D *intersection_query_results[INTERSECTION_QUERY_MAX]; int intersection_query_subindex_results[INTERSECTION_QUERY_MAX]; real_t body_linear_velocity_sleep_threshold = 0.0; @@ -122,40 +123,40 @@ private: int active_objects = 0; int collision_pairs = 0; - int _cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb); + int _cull_aabb_for_body(GodotBody2D *p_body, const Rect2 &p_aabb); Vector<Vector2> contact_debug; int contact_debug_count = 0; - friend class PhysicsDirectSpaceState2DSW; + friend class GodotPhysicsDirectSpaceState2D; public: _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } _FORCE_INLINE_ RID get_self() const { return self; } - void set_default_area(Area2DSW *p_area) { area = p_area; } - Area2DSW *get_default_area() const { return area; } + void set_default_area(GodotArea2D *p_area) { area = p_area; } + GodotArea2D *get_default_area() const { return area; } - const SelfList<Body2DSW>::List &get_active_body_list() const; - void body_add_to_active_list(SelfList<Body2DSW> *p_body); - void body_remove_from_active_list(SelfList<Body2DSW> *p_body); - void body_add_to_mass_properties_update_list(SelfList<Body2DSW> *p_body); - void body_remove_from_mass_properties_update_list(SelfList<Body2DSW> *p_body); - void area_add_to_moved_list(SelfList<Area2DSW> *p_area); - void area_remove_from_moved_list(SelfList<Area2DSW> *p_area); - const SelfList<Area2DSW>::List &get_moved_area_list() const; + const SelfList<GodotBody2D>::List &get_active_body_list() const; + void body_add_to_active_list(SelfList<GodotBody2D> *p_body); + void body_remove_from_active_list(SelfList<GodotBody2D> *p_body); + void body_add_to_mass_properties_update_list(SelfList<GodotBody2D> *p_body); + void body_remove_from_mass_properties_update_list(SelfList<GodotBody2D> *p_body); + void area_add_to_moved_list(SelfList<GodotArea2D> *p_area); + void area_remove_from_moved_list(SelfList<GodotArea2D> *p_area); + const SelfList<GodotArea2D>::List &get_moved_area_list() const; - void body_add_to_state_query_list(SelfList<Body2DSW> *p_body); - void body_remove_from_state_query_list(SelfList<Body2DSW> *p_body); + void body_add_to_state_query_list(SelfList<GodotBody2D> *p_body); + void body_remove_from_state_query_list(SelfList<GodotBody2D> *p_body); - void area_add_to_monitor_query_list(SelfList<Area2DSW> *p_area); - void area_remove_from_monitor_query_list(SelfList<Area2DSW> *p_area); + void area_add_to_monitor_query_list(SelfList<GodotArea2D> *p_area); + void area_remove_from_monitor_query_list(SelfList<GodotArea2D> *p_area); - BroadPhase2DSW *get_broadphase(); + GodotBroadPhase2D *get_broadphase(); - void add_object(CollisionObject2DSW *p_object); - void remove_object(CollisionObject2DSW *p_object); - const Set<CollisionObject2DSW *> &get_objects() const; + void add_object(GodotCollisionObject2D *p_object); + void remove_object(GodotCollisionObject2D *p_object); + const Set<GodotCollisionObject2D *> &get_objects() const; _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; } _FORCE_INLINE_ real_t get_contact_max_separation() const { return contact_max_separation; } @@ -187,7 +188,7 @@ public: int get_collision_pairs() const { return collision_pairs; } - bool test_body_motion(Body2DSW *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result); + bool test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::MotionParameters &p_parameters, PhysicsServer2D::MotionResult *r_result); void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); } _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.is_empty(); } @@ -199,13 +200,13 @@ public: _FORCE_INLINE_ Vector<Vector2> get_debug_contacts() { return contact_debug; } _FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; } - PhysicsDirectSpaceState2DSW *get_direct_state(); + GodotPhysicsDirectSpaceState2D *get_direct_state(); void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; } uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; } - Space2DSW(); - ~Space2DSW(); + GodotSpace2D(); + ~GodotSpace2D(); }; -#endif // SPACE_2D_SW_H +#endif // GODOT_SPACE_2D_H diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/godot_step_2d.cpp index a03e30f850..3010315571 100644 --- a/servers/physics_2d/step_2d_sw.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* step_2d_sw.cpp */ +/* godot_step_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,7 +28,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "step_2d_sw.h" +#include "godot_step_2d.h" #include "core/os/os.h" @@ -38,7 +38,7 @@ #define ISLAND_SIZE_RESERVE 512 #define CONSTRAINT_COUNT_RESERVE 1024 -void Step2DSW::_populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_body_island, LocalVector<Constraint2DSW *> &p_constraint_island) { +void GodotStep2D::_populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D *> &p_body_island, LocalVector<GodotConstraint2D *> &p_constraint_island) { p_body->set_island_step(_step); if (p_body->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) { @@ -46,8 +46,8 @@ void Step2DSW::_populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_bod p_body_island.push_back(p_body); } - for (const Pair<Constraint2DSW *, int> &E : p_body->get_constraint_list()) { - Constraint2DSW *constraint = (Constraint2DSW *)E.first; + for (const Pair<GodotConstraint2D *, int> &E : p_body->get_constraint_list()) { + GodotConstraint2D *constraint = (GodotConstraint2D *)E.first; if (constraint->get_island_step() == _step) { continue; // Already processed. } @@ -59,7 +59,7 @@ void Step2DSW::_populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_bod if (i == E.second) { continue; } - Body2DSW *other_body = constraint->get_body_ptr()[i]; + GodotBody2D *other_body = constraint->get_body_ptr()[i]; if (other_body->get_island_step() == _step) { continue; // Already processed. } @@ -71,16 +71,16 @@ void Step2DSW::_populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_bod } } -void Step2DSW::_setup_contraint(uint32_t p_constraint_index, void *p_userdata) { - Constraint2DSW *constraint = all_constraints[p_constraint_index]; +void GodotStep2D::_setup_contraint(uint32_t p_constraint_index, void *p_userdata) { + GodotConstraint2D *constraint = all_constraints[p_constraint_index]; constraint->setup(delta); } -void Step2DSW::_pre_solve_island(LocalVector<Constraint2DSW *> &p_constraint_island) const { +void GodotStep2D::_pre_solve_island(LocalVector<GodotConstraint2D *> &p_constraint_island) const { uint32_t constraint_count = p_constraint_island.size(); uint32_t valid_constraint_count = 0; for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) { - Constraint2DSW *constraint = p_constraint_island[constraint_index]; + GodotConstraint2D *constraint = p_constraint_island[constraint_index]; if (p_constraint_island[constraint_index]->pre_solve(delta)) { // Keep this constraint for solving. p_constraint_island[valid_constraint_count++] = constraint; @@ -89,8 +89,8 @@ void Step2DSW::_pre_solve_island(LocalVector<Constraint2DSW *> &p_constraint_isl p_constraint_island.resize(valid_constraint_count); } -void Step2DSW::_solve_island(uint32_t p_island_index, void *p_userdata) const { - const LocalVector<Constraint2DSW *> &constraint_island = constraint_islands[p_island_index]; +void GodotStep2D::_solve_island(uint32_t p_island_index, void *p_userdata) const { + const LocalVector<GodotConstraint2D *> &constraint_island = constraint_islands[p_island_index]; for (int i = 0; i < iterations; i++) { uint32_t constraint_count = constraint_island.size(); @@ -100,12 +100,12 @@ void Step2DSW::_solve_island(uint32_t p_island_index, void *p_userdata) const { } } -void Step2DSW::_check_suspend(LocalVector<Body2DSW *> &p_body_island) const { +void GodotStep2D::_check_suspend(LocalVector<GodotBody2D *> &p_body_island) const { bool can_sleep = true; uint32_t body_count = p_body_island.size(); for (uint32_t body_index = 0; body_index < body_count; ++body_index) { - Body2DSW *body = p_body_island[body_index]; + GodotBody2D *body = p_body_island[body_index]; if (!body->sleep_test(delta)) { can_sleep = false; @@ -114,7 +114,7 @@ void Step2DSW::_check_suspend(LocalVector<Body2DSW *> &p_body_island) const { // Put all to sleep or wake up everyone. for (uint32_t body_index = 0; body_index < body_count; ++body_index) { - Body2DSW *body = p_body_island[body_index]; + GodotBody2D *body = p_body_island[body_index]; bool active = body->is_active(); @@ -124,7 +124,7 @@ void Step2DSW::_check_suspend(LocalVector<Body2DSW *> &p_body_island) const { } } -void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { +void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta, int p_iterations) { p_space->lock(); // can't access space during this p_space->setup(); //update inertias, etc @@ -134,7 +134,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { iterations = p_iterations; delta = p_delta; - const SelfList<Body2DSW>::List *body_list = &p_space->get_active_body_list(); + const SelfList<GodotBody2D>::List *body_list = &p_space->get_active_body_list(); /* INTEGRATE FORCES */ @@ -143,7 +143,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { int active_count = 0; - const SelfList<Body2DSW> *b = body_list->first(); + const SelfList<GodotBody2D> *b = body_list->first(); while (b) { b->self()->integrate_forces(p_delta); b = b->next(); @@ -154,7 +154,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(Space2DSW::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime); + p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime); profile_begtime = profile_endtime; } @@ -162,11 +162,11 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { uint32_t island_count = 0; - const SelfList<Area2DSW>::List &aml = p_space->get_moved_area_list(); + const SelfList<GodotArea2D>::List &aml = p_space->get_moved_area_list(); while (aml.first()) { - for (const Set<Constraint2DSW *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { - Constraint2DSW *constraint = E->get(); + for (const Set<GodotConstraint2D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { + GodotConstraint2D *constraint = E->get(); if (constraint->get_island_step() == _step) { continue; } @@ -177,13 +177,13 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { if (constraint_islands.size() < island_count) { constraint_islands.resize(island_count); } - LocalVector<Constraint2DSW *> &constraint_island = constraint_islands[island_count - 1]; + LocalVector<GodotConstraint2D *> &constraint_island = constraint_islands[island_count - 1]; constraint_island.clear(); all_constraints.push_back(constraint); constraint_island.push_back(constraint); } - p_space->area_remove_from_moved_list((SelfList<Area2DSW> *)aml.first()); //faster to remove here + p_space->area_remove_from_moved_list((SelfList<GodotArea2D> *)aml.first()); //faster to remove here } /* GENERATE CONSTRAINT ISLANDS FOR ACTIVE RIGID BODIES */ @@ -193,14 +193,14 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { uint32_t body_island_count = 0; while (b) { - Body2DSW *body = b->self(); + GodotBody2D *body = b->self(); if (body->get_island_step() != _step) { ++body_island_count; if (body_islands.size() < body_island_count) { body_islands.resize(body_island_count); } - LocalVector<Body2DSW *> &body_island = body_islands[body_island_count - 1]; + LocalVector<GodotBody2D *> &body_island = body_islands[body_island_count - 1]; body_island.clear(); body_island.reserve(BODY_ISLAND_SIZE_RESERVE); @@ -208,7 +208,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { if (constraint_islands.size() < island_count) { constraint_islands.resize(island_count); } - LocalVector<Constraint2DSW *> &constraint_island = constraint_islands[island_count - 1]; + LocalVector<GodotConstraint2D *> &constraint_island = constraint_islands[island_count - 1]; constraint_island.clear(); constraint_island.reserve(ISLAND_SIZE_RESERVE); @@ -229,18 +229,18 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(Space2DSW::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime); + p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime); profile_begtime = profile_endtime; } /* SETUP CONSTRAINTS / PROCESS COLLISIONS */ uint32_t total_contraint_count = all_constraints.size(); - work_pool.do_work(total_contraint_count, this, &Step2DSW::_setup_contraint, nullptr); + work_pool.do_work(total_contraint_count, this, &GodotStep2D::_setup_contraint, nullptr); { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(Space2DSW::ELAPSED_TIME_SETUP_CONSTRAINTS, profile_endtime - profile_begtime); + p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_SETUP_CONSTRAINTS, profile_endtime - profile_begtime); profile_begtime = profile_endtime; } @@ -256,14 +256,14 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { // Warning: _solve_island modifies the constraint islands for optimization purpose, // their content is not reliable after these calls and shouldn't be used anymore. if (island_count > 1) { - work_pool.do_work(island_count, this, &Step2DSW::_solve_island, nullptr); + work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr); } else if (island_count > 0) { _solve_island(0); } { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(Space2DSW::ELAPSED_TIME_SOLVE_CONSTRAINTS, profile_endtime - profile_begtime); + p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_SOLVE_CONSTRAINTS, profile_endtime - profile_begtime); profile_begtime = profile_endtime; } @@ -271,7 +271,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { b = body_list->first(); while (b) { - const SelfList<Body2DSW> *n = b->next(); + const SelfList<GodotBody2D> *n = b->next(); b->self()->integrate_velocities(p_delta); b = n; // in case it shuts itself down } @@ -284,7 +284,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(Space2DSW::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime); + p_space->set_elapsed_time(GodotSpace2D::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime); //profile_begtime=profile_endtime; } @@ -295,7 +295,7 @@ void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) { _step++; } -Step2DSW::Step2DSW() { +GodotStep2D::GodotStep2D() { body_islands.reserve(BODY_ISLAND_COUNT_RESERVE); constraint_islands.reserve(ISLAND_COUNT_RESERVE); all_constraints.reserve(CONSTRAINT_COUNT_RESERVE); @@ -303,6 +303,6 @@ Step2DSW::Step2DSW() { work_pool.init(); } -Step2DSW::~Step2DSW() { +GodotStep2D::~GodotStep2D() { work_pool.finish(); } diff --git a/servers/physics_2d/step_2d_sw.h b/servers/physics_2d/godot_step_2d.h index de8e76cc99..efec243632 100644 --- a/servers/physics_2d/step_2d_sw.h +++ b/servers/physics_2d/godot_step_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* step_2d_sw.h */ +/* godot_step_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef STEP_2D_SW_H -#define STEP_2D_SW_H +#ifndef GODOT_STEP_2D_H +#define GODOT_STEP_2D_H -#include "space_2d_sw.h" +#include "godot_space_2d.h" #include "core/templates/local_vector.h" #include "core/templates/thread_work_pool.h" -class Step2DSW { +class GodotStep2D { uint64_t _step = 1; int iterations = 0; @@ -44,20 +44,20 @@ class Step2DSW { ThreadWorkPool work_pool; - LocalVector<LocalVector<Body2DSW *>> body_islands; - LocalVector<LocalVector<Constraint2DSW *>> constraint_islands; - LocalVector<Constraint2DSW *> all_constraints; + LocalVector<LocalVector<GodotBody2D *>> body_islands; + LocalVector<LocalVector<GodotConstraint2D *>> constraint_islands; + LocalVector<GodotConstraint2D *> all_constraints; - void _populate_island(Body2DSW *p_body, LocalVector<Body2DSW *> &p_body_island, LocalVector<Constraint2DSW *> &p_constraint_island); + void _populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D *> &p_body_island, LocalVector<GodotConstraint2D *> &p_constraint_island); void _setup_contraint(uint32_t p_constraint_index, void *p_userdata = nullptr); - void _pre_solve_island(LocalVector<Constraint2DSW *> &p_constraint_island) const; + void _pre_solve_island(LocalVector<GodotConstraint2D *> &p_constraint_island) const; void _solve_island(uint32_t p_island_index, void *p_userdata = nullptr) const; - void _check_suspend(LocalVector<Body2DSW *> &p_body_island) const; + void _check_suspend(LocalVector<GodotBody2D *> &p_body_island) const; public: - void step(Space2DSW *p_space, real_t p_delta, int p_iterations); - Step2DSW(); - ~Step2DSW(); + void step(GodotSpace2D *p_space, real_t p_delta, int p_iterations); + GodotStep2D(); + ~GodotStep2D(); }; -#endif // STEP_2D_SW_H +#endif // GODOT_STEP_2D_H diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp deleted file mode 100644 index c2205e33b0..0000000000 --- a/servers/physics_2d/physics_server_2d_sw.cpp +++ /dev/null @@ -1,1349 +0,0 @@ -/*************************************************************************/ -/* physics_server_2d_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 "physics_server_2d_sw.h" - -#include "body_direct_state_2d_sw.h" -#include "broad_phase_2d_bvh.h" -#include "collision_solver_2d_sw.h" -#include "core/config/project_settings.h" -#include "core/debugger/engine_debugger.h" -#include "core/os/os.h" - -#define FLUSH_QUERY_CHECK(m_object) \ - ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead."); - -RID PhysicsServer2DSW::_shape_create(ShapeType p_shape) { - Shape2DSW *shape = nullptr; - switch (p_shape) { - case SHAPE_WORLD_BOUNDARY: { - shape = memnew(WorldBoundaryShape2DSW); - } break; - case SHAPE_SEPARATION_RAY: { - shape = memnew(SeparationRayShape2DSW); - } break; - case SHAPE_SEGMENT: { - shape = memnew(SegmentShape2DSW); - } break; - case SHAPE_CIRCLE: { - shape = memnew(CircleShape2DSW); - } break; - case SHAPE_RECTANGLE: { - shape = memnew(RectangleShape2DSW); - } break; - case SHAPE_CAPSULE: { - shape = memnew(CapsuleShape2DSW); - } break; - case SHAPE_CONVEX_POLYGON: { - shape = memnew(ConvexPolygonShape2DSW); - } break; - case SHAPE_CONCAVE_POLYGON: { - shape = memnew(ConcavePolygonShape2DSW); - } break; - case SHAPE_CUSTOM: { - ERR_FAIL_V(RID()); - - } break; - } - - RID id = shape_owner.make_rid(shape); - shape->set_self(id); - - return id; -} - -RID PhysicsServer2DSW::world_boundary_shape_create() { - return _shape_create(SHAPE_WORLD_BOUNDARY); -} - -RID PhysicsServer2DSW::separation_ray_shape_create() { - return _shape_create(SHAPE_SEPARATION_RAY); -} - -RID PhysicsServer2DSW::segment_shape_create() { - return _shape_create(SHAPE_SEGMENT); -} - -RID PhysicsServer2DSW::circle_shape_create() { - return _shape_create(SHAPE_CIRCLE); -} - -RID PhysicsServer2DSW::rectangle_shape_create() { - return _shape_create(SHAPE_RECTANGLE); -} - -RID PhysicsServer2DSW::capsule_shape_create() { - return _shape_create(SHAPE_CAPSULE); -} - -RID PhysicsServer2DSW::convex_polygon_shape_create() { - return _shape_create(SHAPE_CONVEX_POLYGON); -} - -RID PhysicsServer2DSW::concave_polygon_shape_create() { - return _shape_create(SHAPE_CONCAVE_POLYGON); -} - -void PhysicsServer2DSW::shape_set_data(RID p_shape, const Variant &p_data) { - Shape2DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - shape->set_data(p_data); -}; - -void PhysicsServer2DSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { - Shape2DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - shape->set_custom_bias(p_bias); -} - -PhysicsServer2D::ShapeType PhysicsServer2DSW::shape_get_type(RID p_shape) const { - const Shape2DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM); - return shape->get_type(); -}; - -Variant PhysicsServer2DSW::shape_get_data(RID p_shape) const { - const Shape2DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND_V(!shape, Variant()); - ERR_FAIL_COND_V(!shape->is_configured(), Variant()); - return shape->get_data(); -}; - -real_t PhysicsServer2DSW::shape_get_custom_solver_bias(RID p_shape) const { - const Shape2DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND_V(!shape, 0); - return shape->get_custom_bias(); -} - -void PhysicsServer2DSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) { - CollCbkData *cbk = (CollCbkData *)p_userdata; - - if (cbk->max == 0) { - return; - } - - Vector2 rel_dir = (p_point_A - p_point_B); - real_t rel_length2 = rel_dir.length_squared(); - if (cbk->valid_dir != Vector2()) { - if (cbk->valid_depth < 10e20) { - if (rel_length2 > cbk->valid_depth * cbk->valid_depth || - (rel_length2 > CMP_EPSILON && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON)) { - cbk->invalid_by_dir++; - return; - } - } else { - if (rel_length2 > 0 && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON) { - return; - } - } - } - - if (cbk->amount == cbk->max) { - //find least deep - real_t min_depth = 1e20; - int min_depth_idx = 0; - for (int i = 0; i < cbk->amount; i++) { - real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]); - if (d < min_depth) { - min_depth = d; - min_depth_idx = i; - } - } - - if (rel_length2 < min_depth) { - return; - } - cbk->ptr[min_depth_idx * 2 + 0] = p_point_A; - cbk->ptr[min_depth_idx * 2 + 1] = p_point_B; - cbk->passed++; - - } else { - cbk->ptr[cbk->amount * 2 + 0] = p_point_A; - cbk->ptr[cbk->amount * 2 + 1] = p_point_B; - cbk->amount++; - cbk->passed++; - } -} - -bool PhysicsServer2DSW::shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) { - Shape2DSW *shape_A = shape_owner.get_or_null(p_shape_A); - ERR_FAIL_COND_V(!shape_A, false); - Shape2DSW *shape_B = shape_owner.get_or_null(p_shape_B); - ERR_FAIL_COND_V(!shape_B, false); - - if (p_result_max == 0) { - return CollisionSolver2DSW::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, nullptr, nullptr); - } - - CollCbkData cbk; - cbk.max = p_result_max; - cbk.amount = 0; - cbk.passed = 0; - cbk.ptr = r_results; - - bool res = CollisionSolver2DSW::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, _shape_col_cbk, &cbk); - r_result_count = cbk.amount; - return res; -} - -RID PhysicsServer2DSW::space_create() { - Space2DSW *space = memnew(Space2DSW); - RID id = space_owner.make_rid(space); - space->set_self(id); - RID area_id = area_create(); - Area2DSW *area = area_owner.get_or_null(area_id); - ERR_FAIL_COND_V(!area, RID()); - space->set_default_area(area); - area->set_space(space); - area->set_priority(-1); - - return id; -}; - -void PhysicsServer2DSW::space_set_active(RID p_space, bool p_active) { - Space2DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space); - if (p_active) { - active_spaces.insert(space); - } else { - active_spaces.erase(space); - } -} - -bool PhysicsServer2DSW::space_is_active(RID p_space) const { - const Space2DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND_V(!space, false); - - return active_spaces.has(space); -} - -void PhysicsServer2DSW::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { - Space2DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space); - - space->set_param(p_param, p_value); -} - -real_t PhysicsServer2DSW::space_get_param(RID p_space, SpaceParameter p_param) const { - const Space2DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND_V(!space, 0); - return space->get_param(p_param); -} - -void PhysicsServer2DSW::space_set_debug_contacts(RID p_space, int p_max_contacts) { - Space2DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space); - space->set_debug_contacts(p_max_contacts); -} - -Vector<Vector2> PhysicsServer2DSW::space_get_contacts(RID p_space) const { - Space2DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND_V(!space, Vector<Vector2>()); - return space->get_debug_contacts(); -} - -int PhysicsServer2DSW::space_get_contact_count(RID p_space) const { - Space2DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND_V(!space, 0); - return space->get_debug_contact_count(); -} - -PhysicsDirectSpaceState2D *PhysicsServer2DSW::space_get_direct_state(RID p_space) { - Space2DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND_V(!space, nullptr); - ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification."); - - return space->get_direct_state(); -} - -RID PhysicsServer2DSW::area_create() { - Area2DSW *area = memnew(Area2DSW); - RID rid = area_owner.make_rid(area); - area->set_self(rid); - return rid; -}; - -void PhysicsServer2DSW::area_set_space(RID p_area, RID p_space) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - Space2DSW *space = nullptr; - if (p_space.is_valid()) { - space = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space); - } - - if (area->get_space() == space) { - return; //pointless - } - - area->clear_constraints(); - area->set_space(space); -}; - -RID PhysicsServer2DSW::area_get_space(RID p_area) const { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, RID()); - - Space2DSW *space = area->get_space(); - if (!space) { - return RID(); - } - return space->get_self(); -}; - -void PhysicsServer2DSW::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_space_override_mode(p_mode); -} - -PhysicsServer2D::AreaSpaceOverrideMode PhysicsServer2DSW::area_get_space_override_mode(RID p_area) const { - const Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); - - return area->get_space_override_mode(); -} - -void PhysicsServer2DSW::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - Shape2DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - - area->add_shape(shape, p_transform, p_disabled); -} - -void PhysicsServer2DSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - Shape2DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - ERR_FAIL_COND(!shape->is_configured()); - - area->set_shape(p_shape_idx, shape); -} - -void PhysicsServer2DSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_shape_transform(p_shape_idx, p_transform); -} - -void PhysicsServer2DSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - ERR_FAIL_INDEX(p_shape, area->get_shape_count()); - FLUSH_QUERY_CHECK(area); - - area->set_shape_disabled(p_shape, p_disabled); -} - -int PhysicsServer2DSW::area_get_shape_count(RID p_area) const { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, -1); - - return area->get_shape_count(); -} - -RID PhysicsServer2DSW::area_get_shape(RID p_area, int p_shape_idx) const { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, RID()); - - Shape2DSW *shape = area->get_shape(p_shape_idx); - ERR_FAIL_COND_V(!shape, RID()); - - return shape->get_self(); -} - -Transform2D PhysicsServer2DSW::area_get_shape_transform(RID p_area, int p_shape_idx) const { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, Transform2D()); - - return area->get_shape_transform(p_shape_idx); -} - -void PhysicsServer2DSW::area_remove_shape(RID p_area, int p_shape_idx) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->remove_shape(p_shape_idx); -} - -void PhysicsServer2DSW::area_clear_shapes(RID p_area) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - while (area->get_shape_count()) { - area->remove_shape(0); - } -} - -void PhysicsServer2DSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) { - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.get_or_null(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - area->set_instance_id(p_id); -} - -ObjectID PhysicsServer2DSW::area_get_object_instance_id(RID p_area) const { - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.get_or_null(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, ObjectID()); - return area->get_instance_id(); -} - -void PhysicsServer2DSW::area_attach_canvas_instance_id(RID p_area, ObjectID p_id) { - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.get_or_null(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - area->set_canvas_instance_id(p_id); -} - -ObjectID PhysicsServer2DSW::area_get_canvas_instance_id(RID p_area) const { - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.get_or_null(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, ObjectID()); - return area->get_canvas_instance_id(); -} - -void PhysicsServer2DSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.get_or_null(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - area->set_param(p_param, p_value); -}; - -void PhysicsServer2DSW::area_set_transform(RID p_area, const Transform2D &p_transform) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - area->set_transform(p_transform); -}; - -Variant PhysicsServer2DSW::area_get_param(RID p_area, AreaParameter p_param) const { - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.get_or_null(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, Variant()); - - return area->get_param(p_param); -}; - -Transform2D PhysicsServer2DSW::area_get_transform(RID p_area) const { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, Transform2D()); - - return area->get_transform(); -}; - -void PhysicsServer2DSW::area_set_pickable(RID p_area, bool p_pickable) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - area->set_pickable(p_pickable); -} - -void PhysicsServer2DSW::area_set_monitorable(RID p_area, bool p_monitorable) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - FLUSH_QUERY_CHECK(area); - - area->set_monitorable(p_monitorable); -} - -void PhysicsServer2DSW::area_set_collision_mask(RID p_area, uint32_t p_mask) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_collision_mask(p_mask); -} - -void PhysicsServer2DSW::area_set_collision_layer(RID p_area, uint32_t p_layer) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_collision_layer(p_layer); -} - -void PhysicsServer2DSW::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); -} - -void PhysicsServer2DSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { - Area2DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); -} - -/* BODY API */ - -RID PhysicsServer2DSW::body_create() { - Body2DSW *body = memnew(Body2DSW); - RID rid = body_owner.make_rid(body); - body->set_self(rid); - return rid; -} - -void PhysicsServer2DSW::body_set_space(RID p_body, RID p_space) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - Space2DSW *space = nullptr; - if (p_space.is_valid()) { - space = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space); - } - - if (body->get_space() == space) { - return; //pointless - } - - body->clear_constraint_list(); - body->set_space(space); -}; - -RID PhysicsServer2DSW::body_get_space(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, RID()); - - Space2DSW *space = body->get_space(); - if (!space) { - return RID(); - } - return space->get_self(); -}; - -void PhysicsServer2DSW::body_set_mode(RID p_body, BodyMode p_mode) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - FLUSH_QUERY_CHECK(body); - - body->set_mode(p_mode); -}; - -PhysicsServer2D::BodyMode PhysicsServer2DSW::body_get_mode(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, BODY_MODE_STATIC); - - return body->get_mode(); -}; - -void PhysicsServer2DSW::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform, bool p_disabled) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - Shape2DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - - body->add_shape(shape, p_transform, p_disabled); -} - -void PhysicsServer2DSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - Shape2DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - ERR_FAIL_COND(!shape->is_configured()); - - body->set_shape(p_shape_idx, shape); -} - -void PhysicsServer2DSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_shape_transform(p_shape_idx, p_transform); -} - -int PhysicsServer2DSW::body_get_shape_count(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, -1); - - return body->get_shape_count(); -} - -RID PhysicsServer2DSW::body_get_shape(RID p_body, int p_shape_idx) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, RID()); - - Shape2DSW *shape = body->get_shape(p_shape_idx); - ERR_FAIL_COND_V(!shape, RID()); - - return shape->get_self(); -} - -Transform2D PhysicsServer2DSW::body_get_shape_transform(RID p_body, int p_shape_idx) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, Transform2D()); - - return body->get_shape_transform(p_shape_idx); -} - -void PhysicsServer2DSW::body_remove_shape(RID p_body, int p_shape_idx) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->remove_shape(p_shape_idx); -} - -void PhysicsServer2DSW::body_clear_shapes(RID p_body) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - while (body->get_shape_count()) { - body->remove_shape(0); - } -} - -void PhysicsServer2DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); - FLUSH_QUERY_CHECK(body); - - body->set_shape_disabled(p_shape_idx, p_disabled); -} - -void PhysicsServer2DSW::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, real_t p_margin) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); - FLUSH_QUERY_CHECK(body); - - body->set_shape_as_one_way_collision(p_shape_idx, p_enable, p_margin); -} - -void PhysicsServer2DSW::body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - body->set_continuous_collision_detection_mode(p_mode); -} - -PhysicsServer2DSW::CCDMode PhysicsServer2DSW::body_get_continuous_collision_detection_mode(RID p_body) const { - const Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, CCD_MODE_DISABLED); - - return body->get_continuous_collision_detection_mode(); -} - -void PhysicsServer2DSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_instance_id(p_id); -}; - -ObjectID PhysicsServer2DSW::body_get_object_instance_id(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, ObjectID()); - - return body->get_instance_id(); -}; - -void PhysicsServer2DSW::body_attach_canvas_instance_id(RID p_body, ObjectID p_id) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_canvas_instance_id(p_id); -}; - -ObjectID PhysicsServer2DSW::body_get_canvas_instance_id(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, ObjectID()); - - return body->get_canvas_instance_id(); -}; - -void PhysicsServer2DSW::body_set_collision_layer(RID p_body, uint32_t p_layer) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - body->set_collision_layer(p_layer); -}; - -uint32_t PhysicsServer2DSW::body_get_collision_layer(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_collision_layer(); -}; - -void PhysicsServer2DSW::body_set_collision_mask(RID p_body, uint32_t p_mask) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - body->set_collision_mask(p_mask); -}; - -uint32_t PhysicsServer2DSW::body_get_collision_mask(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_collision_mask(); -}; - -void PhysicsServer2DSW::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_param(p_param, p_value); -}; - -Variant PhysicsServer2DSW::body_get_param(RID p_body, BodyParameter p_param) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_param(p_param); -}; - -void PhysicsServer2DSW::body_reset_mass_properties(RID p_body) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - return body->reset_mass_properties(); -} - -void PhysicsServer2DSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_state(p_state, p_variant); -}; - -Variant PhysicsServer2DSW::body_get_state(RID p_body, BodyState p_state) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, Variant()); - - return body->get_state(p_state); -}; - -void PhysicsServer2DSW::body_set_applied_force(RID p_body, const Vector2 &p_force) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_applied_force(p_force); - body->wakeup(); -}; - -Vector2 PhysicsServer2DSW::body_get_applied_force(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, Vector2()); - return body->get_applied_force(); -}; - -void PhysicsServer2DSW::body_set_applied_torque(RID p_body, real_t p_torque) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_applied_torque(p_torque); - body->wakeup(); -}; - -real_t PhysicsServer2DSW::body_get_applied_torque(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_applied_torque(); -}; - -void PhysicsServer2DSW::body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->apply_central_impulse(p_impulse); - body->wakeup(); -} - -void PhysicsServer2DSW::body_apply_torque_impulse(RID p_body, real_t p_torque) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - body->apply_torque_impulse(p_torque); - body->wakeup(); -} - -void PhysicsServer2DSW::body_apply_impulse(RID p_body, const Vector2 &p_impulse, const Vector2 &p_position) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - body->apply_impulse(p_impulse, p_position); - body->wakeup(); -}; - -void PhysicsServer2DSW::body_add_central_force(RID p_body, const Vector2 &p_force) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->add_central_force(p_force); - body->wakeup(); -}; - -void PhysicsServer2DSW::body_add_force(RID p_body, const Vector2 &p_force, const Vector2 &p_position) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->add_force(p_force, p_position); - body->wakeup(); -}; - -void PhysicsServer2DSW::body_add_torque(RID p_body, real_t p_torque) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->add_torque(p_torque); - body->wakeup(); -}; - -void PhysicsServer2DSW::body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - Vector2 v = body->get_linear_velocity(); - Vector2 axis = p_axis_velocity.normalized(); - v -= axis * axis.dot(v); - v += p_axis_velocity; - body->set_linear_velocity(v); - body->wakeup(); -}; - -void PhysicsServer2DSW::body_add_collision_exception(RID p_body, RID p_body_b) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->add_exception(p_body_b); - body->wakeup(); -}; - -void PhysicsServer2DSW::body_remove_collision_exception(RID p_body, RID p_body_b) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->remove_exception(p_body_b); - body->wakeup(); -}; - -void PhysicsServer2DSW::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - for (int i = 0; i < body->get_exceptions().size(); i++) { - p_exceptions->push_back(body->get_exceptions()[i]); - } -}; - -void PhysicsServer2DSW::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); -}; - -real_t PhysicsServer2DSW::body_get_contacts_reported_depth_threshold(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, 0); - return 0; -}; - -void PhysicsServer2DSW::body_set_omit_force_integration(RID p_body, bool p_omit) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_omit_force_integration(p_omit); -}; - -bool PhysicsServer2DSW::body_is_omitting_force_integration(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, false); - return body->get_omit_force_integration(); -}; - -void PhysicsServer2DSW::body_set_max_contacts_reported(RID p_body, int p_contacts) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - body->set_max_contacts_reported(p_contacts); -} - -int PhysicsServer2DSW::body_get_max_contacts_reported(RID p_body) const { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, -1); - return body->get_max_contacts_reported(); -} - -void PhysicsServer2DSW::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - body->set_state_sync_callback(p_instance, p_callback); -} - -void PhysicsServer2DSW::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - body->set_force_integration_callback(p_callable, p_udata); -} - -bool PhysicsServer2DSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, false); - ERR_FAIL_INDEX_V(p_body_shape, body->get_shape_count(), false); - - return shape_collide(body->get_shape(p_body_shape)->get_self(), body->get_transform() * body->get_shape_transform(p_body_shape), Vector2(), p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count); -} - -void PhysicsServer2DSW::body_set_pickable(RID p_body, bool p_pickable) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - body->set_pickable(p_pickable); -} - -bool PhysicsServer2DSW::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) { - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, false); - ERR_FAIL_COND_V(!body->get_space(), false); - ERR_FAIL_COND_V(body->get_space()->is_locked(), false); - - _update_shapes(); - - return body->get_space()->test_body_motion(body, p_parameters, r_result); -} - -PhysicsDirectBodyState2D *PhysicsServer2DSW::body_get_direct_state(RID p_body) { - ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); - - Body2DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, nullptr); - - ERR_FAIL_COND_V(!body->get_space(), nullptr); - ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); - - return body->get_direct_state(); -} - -/* JOINT API */ - -RID PhysicsServer2DSW::joint_create() { - Joint2DSW *joint = memnew(Joint2DSW); - RID joint_rid = joint_owner.make_rid(joint); - joint->set_self(joint_rid); - return joint_rid; -} - -void PhysicsServer2DSW::joint_clear(RID p_joint) { - Joint2DSW *joint = joint_owner.get_or_null(p_joint); - if (joint->get_type() != JOINT_TYPE_MAX) { - Joint2DSW *empty_joint = memnew(Joint2DSW); - empty_joint->copy_settings_from(joint); - - joint_owner.replace(p_joint, empty_joint); - memdelete(joint); - } -} - -void PhysicsServer2DSW::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) { - Joint2DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - - switch (p_param) { - case JOINT_PARAM_BIAS: - joint->set_bias(p_value); - break; - case JOINT_PARAM_MAX_BIAS: - joint->set_max_bias(p_value); - break; - case JOINT_PARAM_MAX_FORCE: - joint->set_max_force(p_value); - break; - } -} - -real_t PhysicsServer2DSW::joint_get_param(RID p_joint, JointParam p_param) const { - const Joint2DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, -1); - - switch (p_param) { - case JOINT_PARAM_BIAS: - return joint->get_bias(); - break; - case JOINT_PARAM_MAX_BIAS: - return joint->get_max_bias(); - break; - case JOINT_PARAM_MAX_FORCE: - return joint->get_max_force(); - break; - } - - return 0; -} - -void PhysicsServer2DSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { - Joint2DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - - joint->disable_collisions_between_bodies(p_disable); - - if (2 == joint->get_body_count()) { - Body2DSW *body_a = *joint->get_body_ptr(); - Body2DSW *body_b = *(joint->get_body_ptr() + 1); - - if (p_disable) { - body_add_collision_exception(body_a->get_self(), body_b->get_self()); - body_add_collision_exception(body_b->get_self(), body_a->get_self()); - } else { - body_remove_collision_exception(body_a->get_self(), body_b->get_self()); - body_remove_collision_exception(body_b->get_self(), body_a->get_self()); - } - } -} - -bool PhysicsServer2DSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const { - const Joint2DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, true); - - return joint->is_disabled_collisions_between_bodies(); -} - -void PhysicsServer2DSW::joint_make_pin(RID p_joint, const Vector2 &p_pos, RID p_body_a, RID p_body_b) { - Body2DSW *A = body_owner.get_or_null(p_body_a); - ERR_FAIL_COND(!A); - Body2DSW *B = nullptr; - if (body_owner.owns(p_body_b)) { - B = body_owner.get_or_null(p_body_b); - ERR_FAIL_COND(!B); - } - - Joint2DSW *prev_joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(prev_joint == nullptr); - - Joint2DSW *joint = memnew(PinJoint2DSW(p_pos, A, B)); - - joint_owner.replace(p_joint, joint); - joint->copy_settings_from(prev_joint); - memdelete(prev_joint); -} - -void PhysicsServer2DSW::joint_make_groove(RID p_joint, const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) { - Body2DSW *A = body_owner.get_or_null(p_body_a); - ERR_FAIL_COND(!A); - - Body2DSW *B = body_owner.get_or_null(p_body_b); - ERR_FAIL_COND(!B); - - Joint2DSW *prev_joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(prev_joint == nullptr); - - Joint2DSW *joint = memnew(GrooveJoint2DSW(p_a_groove1, p_a_groove2, p_b_anchor, A, B)); - - joint_owner.replace(p_joint, joint); - joint->copy_settings_from(prev_joint); - memdelete(prev_joint); -} - -void PhysicsServer2DSW::joint_make_damped_spring(RID p_joint, const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) { - Body2DSW *A = body_owner.get_or_null(p_body_a); - ERR_FAIL_COND(!A); - - Body2DSW *B = body_owner.get_or_null(p_body_b); - ERR_FAIL_COND(!B); - - Joint2DSW *prev_joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(prev_joint == nullptr); - - Joint2DSW *joint = memnew(DampedSpringJoint2DSW(p_anchor_a, p_anchor_b, A, B)); - - joint_owner.replace(p_joint, joint); - joint->copy_settings_from(prev_joint); - memdelete(prev_joint); -} - -void PhysicsServer2DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) { - Joint2DSW *j = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!j); - ERR_FAIL_COND(j->get_type() != JOINT_TYPE_PIN); - - PinJoint2DSW *pin_joint = static_cast<PinJoint2DSW *>(j); - pin_joint->set_param(p_param, p_value); -} - -real_t PhysicsServer2DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { - Joint2DSW *j = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!j, 0); - ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_PIN, 0); - - PinJoint2DSW *pin_joint = static_cast<PinJoint2DSW *>(j); - return pin_joint->get_param(p_param); -} - -void PhysicsServer2DSW::damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) { - Joint2DSW *j = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!j); - ERR_FAIL_COND(j->get_type() != JOINT_TYPE_DAMPED_SPRING); - - DampedSpringJoint2DSW *dsj = static_cast<DampedSpringJoint2DSW *>(j); - dsj->set_param(p_param, p_value); -} - -real_t PhysicsServer2DSW::damped_spring_joint_get_param(RID p_joint, DampedSpringParam p_param) const { - Joint2DSW *j = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!j, 0); - ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_DAMPED_SPRING, 0); - - DampedSpringJoint2DSW *dsj = static_cast<DampedSpringJoint2DSW *>(j); - return dsj->get_param(p_param); -} - -PhysicsServer2D::JointType PhysicsServer2DSW::joint_get_type(RID p_joint) const { - Joint2DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN); - - return joint->get_type(); -} - -void PhysicsServer2DSW::free(RID p_rid) { - _update_shapes(); // just in case - - if (shape_owner.owns(p_rid)) { - Shape2DSW *shape = shape_owner.get_or_null(p_rid); - - while (shape->get_owners().size()) { - ShapeOwner2DSW *so = shape->get_owners().front()->key(); - so->remove_shape(shape); - } - - shape_owner.free(p_rid); - memdelete(shape); - } else if (body_owner.owns(p_rid)) { - Body2DSW *body = body_owner.get_or_null(p_rid); - - /* - if (body->get_state_query()) - _clear_query(body->get_state_query()); - - if (body->get_direct_state_query()) - _clear_query(body->get_direct_state_query()); - */ - - body_set_space(p_rid, RID()); - - while (body->get_shape_count()) { - body->remove_shape(0); - } - - body_owner.free(p_rid); - memdelete(body); - - } else if (area_owner.owns(p_rid)) { - Area2DSW *area = area_owner.get_or_null(p_rid); - - /* - if (area->get_monitor_query()) - _clear_query(area->get_monitor_query()); - */ - - area->set_space(nullptr); - - while (area->get_shape_count()) { - area->remove_shape(0); - } - - area_owner.free(p_rid); - memdelete(area); - } else if (space_owner.owns(p_rid)) { - Space2DSW *space = space_owner.get_or_null(p_rid); - - while (space->get_objects().size()) { - CollisionObject2DSW *co = (CollisionObject2DSW *)space->get_objects().front()->get(); - co->set_space(nullptr); - } - - active_spaces.erase(space); - free(space->get_default_area()->get_self()); - space_owner.free(p_rid); - memdelete(space); - } else if (joint_owner.owns(p_rid)) { - Joint2DSW *joint = joint_owner.get_or_null(p_rid); - - joint_owner.free(p_rid); - memdelete(joint); - - } else { - ERR_FAIL_MSG("Invalid ID."); - } -}; - -void PhysicsServer2DSW::set_active(bool p_active) { - active = p_active; -}; - -void PhysicsServer2DSW::set_collision_iterations(int p_iterations) { - iterations = p_iterations; -}; - -void PhysicsServer2DSW::init() { - doing_sync = false; - iterations = 8; // 8? - stepper = memnew(Step2DSW); -}; - -void PhysicsServer2DSW::step(real_t p_step) { - if (!active) { - return; - } - - _update_shapes(); - - island_count = 0; - active_objects = 0; - collision_pairs = 0; - for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) { - stepper->step((Space2DSW *)E->get(), p_step, iterations); - island_count += E->get()->get_island_count(); - active_objects += E->get()->get_active_objects(); - collision_pairs += E->get()->get_collision_pairs(); - } -}; - -void PhysicsServer2DSW::sync() { - doing_sync = true; -}; - -void PhysicsServer2DSW::flush_queries() { - if (!active) { - return; - } - - flushing_queries = true; - - uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); - - for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) { - Space2DSW *space = (Space2DSW *)E->get(); - space->call_queries(); - } - - flushing_queries = false; - - if (EngineDebugger::is_profiling("servers")) { - uint64_t total_time[Space2DSW::ELAPSED_TIME_MAX]; - static const char *time_name[Space2DSW::ELAPSED_TIME_MAX] = { - "integrate_forces", - "generate_islands", - "setup_constraints", - "solve_constraints", - "integrate_velocities" - }; - - for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) { - total_time[i] = 0; - } - - for (Set<const Space2DSW *>::Element *E = active_spaces.front(); E; E = E->next()) { - for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) { - total_time[i] += E->get()->get_elapsed_time(Space2DSW::ElapsedTime(i)); - } - } - - Array values; - values.resize(Space2DSW::ELAPSED_TIME_MAX * 2); - for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) { - values[i * 2 + 0] = time_name[i]; - values[i * 2 + 1] = USEC_TO_SEC(total_time[i]); - } - values.push_back("flush_queries"); - values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg)); - - values.push_front("physics_2d"); - EngineDebugger::profiler_add_frame_data("servers", values); - } -} - -void PhysicsServer2DSW::end_sync() { - doing_sync = false; -} - -void PhysicsServer2DSW::finish() { - memdelete(stepper); -}; - -void PhysicsServer2DSW::_update_shapes() { - while (pending_shape_update_list.first()) { - pending_shape_update_list.first()->self()->_shape_changed(); - pending_shape_update_list.remove(pending_shape_update_list.first()); - } -} - -int PhysicsServer2DSW::get_process_info(ProcessInfo p_info) { - switch (p_info) { - case INFO_ACTIVE_OBJECTS: { - return active_objects; - } break; - case INFO_COLLISION_PAIRS: { - return collision_pairs; - } break; - case INFO_ISLAND_COUNT: { - return island_count; - } break; - } - - return 0; -} - -PhysicsServer2DSW *PhysicsServer2DSW::singletonsw = nullptr; - -PhysicsServer2DSW::PhysicsServer2DSW(bool p_using_threads) { - singletonsw = this; - BroadPhase2DSW::create_func = BroadPhase2DBVH::_create; - - using_threads = p_using_threads; -}; diff --git a/servers/physics_3d/gjk_epa.cpp b/servers/physics_3d/gjk_epa.cpp index a1dbdd0a70..ef6535a878 100644 --- a/servers/physics_3d/gjk_epa.cpp +++ b/servers/physics_3d/gjk_epa.cpp @@ -105,7 +105,7 @@ typedef unsigned char U1; // MinkowskiDiff struct MinkowskiDiff { - const Shape3DSW* m_shapes[2]; + const GodotShape3D* m_shapes[2]; Transform3D transform_A; Transform3D transform_B; @@ -113,10 +113,10 @@ struct MinkowskiDiff { real_t margin_A = 0.0; real_t margin_B = 0.0; - Vector3 (*get_support)(const Shape3DSW*, const Vector3&, real_t); + Vector3 (*get_support)(const GodotShape3D*, const Vector3&, real_t); - void Initialize(const Shape3DSW* shape0, const Transform3D& wtrs0, const real_t margin0, - const Shape3DSW* shape1, const Transform3D& wtrs1, const real_t margin1) { + void Initialize(const GodotShape3D* shape0, const Transform3D& wtrs0, const real_t margin0, + const GodotShape3D* shape1, const Transform3D& wtrs1, const real_t margin1) { m_shapes[0] = shape0; m_shapes[1] = shape1; transform_A = wtrs0; @@ -131,11 +131,11 @@ struct MinkowskiDiff { } } - static Vector3 get_support_without_margin(const Shape3DSW* p_shape, const Vector3& p_dir, real_t p_margin) { + static Vector3 get_support_without_margin(const GodotShape3D* p_shape, const Vector3& p_dir, real_t p_margin) { return p_shape->get_support(p_dir.normalized()); } - static Vector3 get_support_with_margin(const Shape3DSW* p_shape, const Vector3& p_dir, real_t p_margin) { + static Vector3 get_support_with_margin(const GodotShape3D* p_shape, const Vector3& p_dir, real_t p_margin) { Vector3 local_dir_norm = p_dir; if (local_dir_norm.length_squared() < CMP_EPSILON2) { local_dir_norm = Vector3(-1.0, -1.0, -1.0); @@ -862,8 +862,8 @@ struct GJK }; // - static void Initialize( const Shape3DSW* shape0, const Transform3D& wtrs0, real_t margin0, - const Shape3DSW* shape1, const Transform3D& wtrs1, real_t margin1, + static void Initialize( const GodotShape3D* shape0, const Transform3D& wtrs0, real_t margin0, + const GodotShape3D* shape1, const Transform3D& wtrs1, real_t margin1, sResults& results, tShape& shape) { @@ -884,10 +884,10 @@ struct GJK // // -bool Distance( const Shape3DSW* shape0, +bool Distance( const GodotShape3D* shape0, const Transform3D& wtrs0, real_t margin0, - const Shape3DSW* shape1, + const GodotShape3D* shape1, const Transform3D& wtrs1, real_t margin1, const Vector3& guess, @@ -925,10 +925,10 @@ bool Distance( const Shape3DSW* shape0, // -bool Penetration( const Shape3DSW* shape0, +bool Penetration( const GodotShape3D* shape0, const Transform3D& wtrs0, real_t margin0, - const Shape3DSW* shape1, + const GodotShape3D* shape1, const Transform3D& wtrs1, real_t margin1, const Vector3& guess, @@ -993,7 +993,7 @@ bool Penetration( const Shape3DSW* shape0, /* clang-format on */ -bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B) { +bool gjk_epa_calculate_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B) { GjkEpa2::sResults res; if (GjkEpa2::Distance(p_shape_A, p_transform_A, 0.0, p_shape_B, p_transform_B, 0.0, p_transform_B.origin - p_transform_A.origin, res)) { @@ -1005,7 +1005,7 @@ bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform3D &p return false; } -bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, real_t p_margin_A, real_t p_margin_B) { +bool gjk_epa_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap, real_t p_margin_A, real_t p_margin_B) { GjkEpa2::sResults res; if (GjkEpa2::Penetration(p_shape_A, p_transform_A, p_margin_A, p_shape_B, p_transform_B, p_margin_B, p_transform_B.origin - p_transform_A.origin, res)) { diff --git a/servers/physics_3d/gjk_epa.h b/servers/physics_3d/gjk_epa.h index 69e85d2bc0..39a7d03435 100644 --- a/servers/physics_3d/gjk_epa.h +++ b/servers/physics_3d/gjk_epa.h @@ -31,10 +31,10 @@ #ifndef GJK_EPA_H #define GJK_EPA_H -#include "collision_solver_3d_sw.h" -#include "shape_3d_sw.h" +#include "godot_collision_solver_3d.h" +#include "godot_shape_3d.h" -bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0); -bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B); +bool gjk_epa_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0); +bool gjk_epa_calculate_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B); #endif diff --git a/servers/physics_3d/area_3d_sw.cpp b/servers/physics_3d/godot_area_3d.cpp index 630ab7e229..e115e17061 100644 --- a/servers/physics_3d/area_3d_sw.cpp +++ b/servers/physics_3d/godot_area_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* area_3d_sw.cpp */ +/* godot_area_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,39 +28,40 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "area_3d_sw.h" -#include "body_3d_sw.h" -#include "soft_body_3d_sw.h" -#include "space_3d_sw.h" +#include "godot_area_3d.h" -Area3DSW::BodyKey::BodyKey(SoftBody3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { +#include "godot_body_3d.h" +#include "godot_soft_body_3d.h" +#include "godot_space_3d.h" + +GodotArea3D::BodyKey::BodyKey(GodotSoftBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { rid = p_body->get_self(); instance_id = p_body->get_instance_id(); body_shape = p_body_shape; area_shape = p_area_shape; } -Area3DSW::BodyKey::BodyKey(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { +GodotArea3D::BodyKey::BodyKey(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { rid = p_body->get_self(); instance_id = p_body->get_instance_id(); body_shape = p_body_shape; area_shape = p_area_shape; } -Area3DSW::BodyKey::BodyKey(Area3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { +GodotArea3D::BodyKey::BodyKey(GodotArea3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { rid = p_body->get_self(); instance_id = p_body->get_instance_id(); body_shape = p_body_shape; area_shape = p_area_shape; } -void Area3DSW::_shapes_changed() { +void GodotArea3D::_shapes_changed() { if (!moved_list.in_list() && get_space()) { get_space()->area_add_to_moved_list(&moved_list); } } -void Area3DSW::set_transform(const Transform3D &p_transform) { +void GodotArea3D::set_transform(const Transform3D &p_transform) { if (!moved_list.in_list() && get_space()) { get_space()->area_add_to_moved_list(&moved_list); } @@ -69,7 +70,7 @@ void Area3DSW::set_transform(const Transform3D &p_transform) { _set_inv_transform(p_transform.affine_inverse()); } -void Area3DSW::set_space(Space3DSW *p_space) { +void GodotArea3D::set_space(GodotSpace3D *p_space) { if (get_space()) { if (monitor_query_list.in_list()) { get_space()->area_remove_from_monitor_query_list(&monitor_query_list); @@ -85,7 +86,7 @@ void Area3DSW::set_space(Space3DSW *p_space) { _set_space(p_space); } -void Area3DSW::set_monitor_callback(ObjectID p_id, const StringName &p_method) { +void GodotArea3D::set_monitor_callback(ObjectID p_id, const StringName &p_method) { if (p_id == monitor_callback_id) { monitor_callback_method = p_method; return; @@ -106,7 +107,7 @@ void Area3DSW::set_monitor_callback(ObjectID p_id, const StringName &p_method) { } } -void Area3DSW::set_area_monitor_callback(ObjectID p_id, const StringName &p_method) { +void GodotArea3D::set_area_monitor_callback(ObjectID p_id, const StringName &p_method) { if (p_id == area_monitor_callback_id) { area_monitor_callback_method = p_method; return; @@ -127,7 +128,7 @@ void Area3DSW::set_area_monitor_callback(ObjectID p_id, const StringName &p_meth } } -void Area3DSW::set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode) { +void GodotArea3D::set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode) { bool do_override = p_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; if (do_override == (space_override_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED)) { return; @@ -137,7 +138,7 @@ void Area3DSW::set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_ _shape_changed(); } -void Area3DSW::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) { +void GodotArea3D::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) { switch (p_param) { case PhysicsServer3D::AREA_PARAM_GRAVITY: gravity = p_value; @@ -180,7 +181,7 @@ void Area3DSW::set_param(PhysicsServer3D::AreaParameter p_param, const Variant & } } -Variant Area3DSW::get_param(PhysicsServer3D::AreaParameter p_param) const { +Variant GodotArea3D::get_param(PhysicsServer3D::AreaParameter p_param) const { switch (p_param) { case PhysicsServer3D::AREA_PARAM_GRAVITY: return gravity; @@ -211,7 +212,7 @@ Variant Area3DSW::get_param(PhysicsServer3D::AreaParameter p_param) const { return Variant(); } -void Area3DSW::_queue_monitor_update() { +void GodotArea3D::_queue_monitor_update() { ERR_FAIL_COND(!get_space()); if (!monitor_query_list.in_list()) { @@ -219,7 +220,7 @@ void Area3DSW::_queue_monitor_update() { } } -void Area3DSW::set_monitorable(bool p_monitorable) { +void GodotArea3D::set_monitorable(bool p_monitorable) { if (monitorable == p_monitorable) { return; } @@ -228,7 +229,7 @@ void Area3DSW::set_monitorable(bool p_monitorable) { _set_static(!monitorable); } -void Area3DSW::call_queries() { +void GodotArea3D::call_queries() { if (monitor_callback_id.is_valid() && !monitored_bodies.is_empty()) { Variant res[5]; Variant *resptr[5]; @@ -304,7 +305,7 @@ void Area3DSW::call_queries() { } } -void Area3DSW::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const { +void GodotArea3D::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const { if (is_gravity_point()) { const real_t gravity_distance_scale = get_gravity_distance_scale(); Vector3 v = get_transform().xform(get_gravity_vector()) - p_position; @@ -324,13 +325,13 @@ void Area3DSW::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) co } } -Area3DSW::Area3DSW() : - CollisionObject3DSW(TYPE_AREA), +GodotArea3D::GodotArea3D() : + GodotCollisionObject3D(TYPE_AREA), monitor_query_list(this), moved_list(this) { _set_static(true); //areas are never active set_ray_pickable(false); } -Area3DSW::~Area3DSW() { +GodotArea3D::~GodotArea3D() { } diff --git a/servers/physics_3d/area_3d_sw.h b/servers/physics_3d/godot_area_3d.h index af5c23949c..e8caa9221b 100644 --- a/servers/physics_3d/area_3d_sw.h +++ b/servers/physics_3d/godot_area_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* area_3d_sw.h */ +/* godot_area_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,19 +28,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AREA_SW_H -#define AREA_SW_H +#ifndef GODOT_AREA_3D_H +#define GODOT_AREA_3D_H + +#include "godot_collision_object_3d.h" -#include "collision_object_3d_sw.h" #include "core/templates/self_list.h" #include "servers/physics_server_3d.h" -class Space3DSW; -class Body3DSW; -class SoftBody3DSW; -class Constraint3DSW; +class GodotSpace3D; +class GodotBody3D; +class GodotSoftBody3D; +class GodotConstraint3D; -class Area3DSW : public CollisionObject3DSW { +class GodotArea3D : public GodotCollisionObject3D { PhysicsServer3D::AreaSpaceOverrideMode space_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; real_t gravity = 9.80665; Vector3 gravity_vector = Vector3(0, -1, 0); @@ -62,8 +63,8 @@ class Area3DSW : public CollisionObject3DSW { ObjectID area_monitor_callback_id; StringName area_monitor_callback_method; - SelfList<Area3DSW> monitor_query_list; - SelfList<Area3DSW> moved_list; + SelfList<GodotArea3D> monitor_query_list; + SelfList<GodotArea3D> moved_list; struct BodyKey { RID rid; @@ -84,9 +85,9 @@ class Area3DSW : public CollisionObject3DSW { } _FORCE_INLINE_ BodyKey() {} - BodyKey(SoftBody3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); - BodyKey(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); - BodyKey(Area3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + BodyKey(GodotSoftBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + BodyKey(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + BodyKey(GodotArea3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); }; struct BodyState { @@ -99,7 +100,7 @@ class Area3DSW : public CollisionObject3DSW { Map<BodyKey, BodyState> monitored_bodies; Map<BodyKey, BodyState> monitored_areas; - Set<Constraint3DSW *> constraints; + Set<GodotConstraint3D *> constraints; virtual void _shapes_changed(); void _queue_monitor_update(); @@ -111,14 +112,14 @@ public: void set_area_monitor_callback(ObjectID p_id, const StringName &p_method); _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); } - _FORCE_INLINE_ void add_body_to_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); - _FORCE_INLINE_ void remove_body_from_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + _FORCE_INLINE_ void add_body_to_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + _FORCE_INLINE_ void remove_body_from_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape); - _FORCE_INLINE_ void add_soft_body_to_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape); - _FORCE_INLINE_ void remove_soft_body_from_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape); + _FORCE_INLINE_ void add_soft_body_to_query(GodotSoftBody3D *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape); + _FORCE_INLINE_ void remove_soft_body_from_query(GodotSoftBody3D *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape); - _FORCE_INLINE_ void add_area_to_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape); - _FORCE_INLINE_ void remove_area_from_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape); + _FORCE_INLINE_ void add_area_to_query(GodotArea3D *p_area, uint32_t p_area_shape, uint32_t p_self_shape); + _FORCE_INLINE_ void remove_area_from_query(GodotArea3D *p_area, uint32_t p_area_shape, uint32_t p_self_shape); void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value); Variant get_param(PhysicsServer3D::AreaParameter p_param) const; @@ -162,9 +163,9 @@ public: _FORCE_INLINE_ void set_wind_direction(const Vector3 &p_wind_direction) { wind_direction = p_wind_direction; } _FORCE_INLINE_ const Vector3 &get_wind_direction() const { return wind_direction; } - _FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint) { constraints.insert(p_constraint); } - _FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraints.erase(p_constraint); } - _FORCE_INLINE_ const Set<Constraint3DSW *> &get_constraints() const { return constraints; } + _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint) { constraints.insert(p_constraint); } + _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraints.erase(p_constraint); } + _FORCE_INLINE_ const Set<GodotConstraint3D *> &get_constraints() const { return constraints; } _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } void set_monitorable(bool p_monitorable); @@ -172,17 +173,17 @@ public: void set_transform(const Transform3D &p_transform); - void set_space(Space3DSW *p_space); + void set_space(GodotSpace3D *p_space); void call_queries(); void compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const; - Area3DSW(); - ~Area3DSW(); + GodotArea3D(); + ~GodotArea3D(); }; -void Area3DSW::add_soft_body_to_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape) { +void GodotArea3D::add_soft_body_to_query(GodotSoftBody3D *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape) { BodyKey bk(p_soft_body, p_soft_body_shape, p_area_shape); monitored_soft_bodies[bk].inc(); if (!monitor_query_list.in_list()) { @@ -190,7 +191,7 @@ void Area3DSW::add_soft_body_to_query(SoftBody3DSW *p_soft_body, uint32_t p_soft } } -void Area3DSW::remove_soft_body_from_query(SoftBody3DSW *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape) { +void GodotArea3D::remove_soft_body_from_query(GodotSoftBody3D *p_soft_body, uint32_t p_soft_body_shape, uint32_t p_area_shape) { BodyKey bk(p_soft_body, p_soft_body_shape, p_area_shape); monitored_soft_bodies[bk].dec(); if (!monitor_query_list.in_list()) { @@ -198,7 +199,7 @@ void Area3DSW::remove_soft_body_from_query(SoftBody3DSW *p_soft_body, uint32_t p } } -void Area3DSW::add_body_to_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { +void GodotArea3D::add_body_to_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { BodyKey bk(p_body, p_body_shape, p_area_shape); monitored_bodies[bk].inc(); if (!monitor_query_list.in_list()) { @@ -206,7 +207,7 @@ void Area3DSW::add_body_to_query(Body3DSW *p_body, uint32_t p_body_shape, uint32 } } -void Area3DSW::remove_body_from_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { +void GodotArea3D::remove_body_from_query(GodotBody3D *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { BodyKey bk(p_body, p_body_shape, p_area_shape); monitored_bodies[bk].dec(); if (!monitor_query_list.in_list()) { @@ -214,7 +215,7 @@ void Area3DSW::remove_body_from_query(Body3DSW *p_body, uint32_t p_body_shape, u } } -void Area3DSW::add_area_to_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { +void GodotArea3D::add_area_to_query(GodotArea3D *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { BodyKey bk(p_area, p_area_shape, p_self_shape); monitored_areas[bk].inc(); if (!monitor_query_list.in_list()) { @@ -222,7 +223,7 @@ void Area3DSW::add_area_to_query(Area3DSW *p_area, uint32_t p_area_shape, uint32 } } -void Area3DSW::remove_area_from_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { +void GodotArea3D::remove_area_from_query(GodotArea3D *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { BodyKey bk(p_area, p_area_shape, p_self_shape); monitored_areas[bk].dec(); if (!monitor_query_list.in_list()) { @@ -231,15 +232,15 @@ void Area3DSW::remove_area_from_query(Area3DSW *p_area, uint32_t p_area_shape, u } struct AreaCMP { - Area3DSW *area = nullptr; + GodotArea3D *area = nullptr; int refCount = 0; _FORCE_INLINE_ bool operator==(const AreaCMP &p_cmp) const { return area->get_self() == p_cmp.area->get_self(); } _FORCE_INLINE_ bool operator<(const AreaCMP &p_cmp) const { return area->get_priority() < p_cmp.area->get_priority(); } _FORCE_INLINE_ AreaCMP() {} - _FORCE_INLINE_ AreaCMP(Area3DSW *p_area) { + _FORCE_INLINE_ AreaCMP(GodotArea3D *p_area) { area = p_area; refCount = 1; } }; -#endif // AREA__SW_H +#endif // GODOT_AREA_3D_H diff --git a/servers/physics_3d/area_pair_3d_sw.cpp b/servers/physics_3d/godot_area_pair_3d.cpp index bf4f0035b4..7453153de6 100644 --- a/servers/physics_3d/area_pair_3d_sw.cpp +++ b/servers/physics_3d/godot_area_pair_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* area_pair_3d_sw.cpp */ +/* godot_area_pair_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,12 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "area_pair_3d_sw.h" -#include "collision_solver_3d_sw.h" +#include "godot_area_pair_3d.h" -bool AreaPair3DSW::setup(real_t p_step) { +#include "godot_collision_solver_3d.h" + +bool GodotAreaPair3D::setup(real_t p_step) { bool result = false; - if (area->collides_with(body) && CollisionSolver3DSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) { + if (area->collides_with(body) && GodotCollisionSolver3D::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) { result = true; } @@ -51,7 +52,7 @@ bool AreaPair3DSW::setup(real_t p_step) { return process_collision; } -bool AreaPair3DSW::pre_solve(real_t p_step) { +bool GodotAreaPair3D::pre_solve(real_t p_step) { if (!process_collision) { return false; } @@ -77,11 +78,11 @@ bool AreaPair3DSW::pre_solve(real_t p_step) { return false; // Never do any post solving. } -void AreaPair3DSW::solve(real_t p_step) { +void GodotAreaPair3D::solve(real_t p_step) { // Nothing to do. } -AreaPair3DSW::AreaPair3DSW(Body3DSW *p_body, int p_body_shape, Area3DSW *p_area, int p_area_shape) { +GodotAreaPair3D::GodotAreaPair3D(GodotBody3D *p_body, int p_body_shape, GodotArea3D *p_area, int p_area_shape) { body = p_body; area = p_area; body_shape = p_body_shape; @@ -93,7 +94,7 @@ AreaPair3DSW::AreaPair3DSW(Body3DSW *p_body, int p_body_shape, Area3DSW *p_area, } } -AreaPair3DSW::~AreaPair3DSW() { +GodotAreaPair3D::~GodotAreaPair3D() { if (colliding) { if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { body->remove_area(area); @@ -108,10 +109,10 @@ AreaPair3DSW::~AreaPair3DSW() { //////////////////////////////////////////////////// -bool Area2Pair3DSW::setup(real_t p_step) { +bool GodotArea2Pair3D::setup(real_t p_step) { bool result_a = area_a->collides_with(area_b); bool result_b = area_b->collides_with(area_a); - if ((result_a || result_b) && !CollisionSolver3DSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) { + if ((result_a || result_b) && !GodotCollisionSolver3D::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) { result_a = false; result_b = false; } @@ -139,7 +140,7 @@ bool Area2Pair3DSW::setup(real_t p_step) { return process_collision; } -bool Area2Pair3DSW::pre_solve(real_t p_step) { +bool GodotArea2Pair3D::pre_solve(real_t p_step) { if (process_collision_a) { if (colliding_a) { area_a->add_area_to_query(area_b, shape_b, shape_a); @@ -159,11 +160,11 @@ bool Area2Pair3DSW::pre_solve(real_t p_step) { return false; // Never do any post solving. } -void Area2Pair3DSW::solve(real_t p_step) { +void GodotArea2Pair3D::solve(real_t p_step) { // Nothing to do. } -Area2Pair3DSW::Area2Pair3DSW(Area3DSW *p_area_a, int p_shape_a, Area3DSW *p_area_b, int p_shape_b) { +GodotArea2Pair3D::GodotArea2Pair3D(GodotArea3D *p_area_a, int p_shape_a, GodotArea3D *p_area_b, int p_shape_b) { area_a = p_area_a; area_b = p_area_b; shape_a = p_shape_a; @@ -172,7 +173,7 @@ Area2Pair3DSW::Area2Pair3DSW(Area3DSW *p_area_a, int p_shape_a, Area3DSW *p_area area_b->add_constraint(this); } -Area2Pair3DSW::~Area2Pair3DSW() { +GodotArea2Pair3D::~GodotArea2Pair3D() { if (colliding_a) { if (area_a->has_area_monitor_callback()) { area_a->remove_area_from_query(area_b, shape_b, shape_a); @@ -191,11 +192,11 @@ Area2Pair3DSW::~Area2Pair3DSW() { //////////////////////////////////////////////////// -bool AreaSoftBodyPair3DSW::setup(real_t p_step) { +bool GodotAreaSoftBodyPair3D::setup(real_t p_step) { bool result = false; if ( area->collides_with(soft_body) && - CollisionSolver3DSW::solve_static( + GodotCollisionSolver3D::solve_static( soft_body->get_shape(soft_body_shape), soft_body->get_transform() * soft_body->get_shape_transform(soft_body_shape), area->get_shape(area_shape), @@ -219,7 +220,7 @@ bool AreaSoftBodyPair3DSW::setup(real_t p_step) { return process_collision; } -bool AreaSoftBodyPair3DSW::pre_solve(real_t p_step) { +bool GodotAreaSoftBodyPair3D::pre_solve(real_t p_step) { if (!process_collision) { return false; } @@ -245,11 +246,11 @@ bool AreaSoftBodyPair3DSW::pre_solve(real_t p_step) { return false; // Never do any post solving. } -void AreaSoftBodyPair3DSW::solve(real_t p_step) { +void GodotAreaSoftBodyPair3D::solve(real_t p_step) { // Nothing to do. } -AreaSoftBodyPair3DSW::AreaSoftBodyPair3DSW(SoftBody3DSW *p_soft_body, int p_soft_body_shape, Area3DSW *p_area, int p_area_shape) { +GodotAreaSoftBodyPair3D::GodotAreaSoftBodyPair3D(GodotSoftBody3D *p_soft_body, int p_soft_body_shape, GodotArea3D *p_area, int p_area_shape) { soft_body = p_soft_body; area = p_area; soft_body_shape = p_soft_body_shape; @@ -258,7 +259,7 @@ AreaSoftBodyPair3DSW::AreaSoftBodyPair3DSW(SoftBody3DSW *p_soft_body, int p_soft area->add_constraint(this); } -AreaSoftBodyPair3DSW::~AreaSoftBodyPair3DSW() { +GodotAreaSoftBodyPair3D::~GodotAreaSoftBodyPair3D() { if (colliding) { if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) { soft_body->remove_area(area); diff --git a/servers/physics_3d/area_pair_3d_sw.h b/servers/physics_3d/godot_area_pair_3d.h index 4572dcbb23..f55c03be03 100644 --- a/servers/physics_3d/area_pair_3d_sw.h +++ b/servers/physics_3d/godot_area_pair_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* area_pair_3d_sw.h */ +/* godot_area_pair_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,17 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AREA_PAIR_SW_H -#define AREA_PAIR_SW_H +#ifndef GODOT_AREA_PAIR_3D_H +#define GODOT_AREA_PAIR_3D_H -#include "area_3d_sw.h" -#include "body_3d_sw.h" -#include "constraint_3d_sw.h" -#include "soft_body_3d_sw.h" +#include "godot_area_3d.h" +#include "godot_body_3d.h" +#include "godot_constraint_3d.h" +#include "godot_soft_body_3d.h" -class AreaPair3DSW : public Constraint3DSW { - Body3DSW *body; - Area3DSW *area; +class GodotAreaPair3D : public GodotConstraint3D { + GodotBody3D *body; + GodotArea3D *area; int body_shape; int area_shape; bool colliding = false; @@ -49,13 +49,13 @@ public: virtual bool pre_solve(real_t p_step) override; virtual void solve(real_t p_step) override; - AreaPair3DSW(Body3DSW *p_body, int p_body_shape, Area3DSW *p_area, int p_area_shape); - ~AreaPair3DSW(); + GodotAreaPair3D(GodotBody3D *p_body, int p_body_shape, GodotArea3D *p_area, int p_area_shape); + ~GodotAreaPair3D(); }; -class Area2Pair3DSW : public Constraint3DSW { - Area3DSW *area_a; - Area3DSW *area_b; +class GodotArea2Pair3D : public GodotConstraint3D { + GodotArea3D *area_a; + GodotArea3D *area_b; int shape_a; int shape_b; bool colliding_a = false; @@ -68,13 +68,13 @@ public: virtual bool pre_solve(real_t p_step) override; virtual void solve(real_t p_step) override; - Area2Pair3DSW(Area3DSW *p_area_a, int p_shape_a, Area3DSW *p_area_b, int p_shape_b); - ~Area2Pair3DSW(); + GodotArea2Pair3D(GodotArea3D *p_area_a, int p_shape_a, GodotArea3D *p_area_b, int p_shape_b); + ~GodotArea2Pair3D(); }; -class AreaSoftBodyPair3DSW : public Constraint3DSW { - SoftBody3DSW *soft_body; - Area3DSW *area; +class GodotAreaSoftBodyPair3D : public GodotConstraint3D { + GodotSoftBody3D *soft_body; + GodotArea3D *area; int soft_body_shape; int area_shape; bool colliding = false; @@ -85,8 +85,8 @@ public: virtual bool pre_solve(real_t p_step) override; virtual void solve(real_t p_step) override; - AreaSoftBodyPair3DSW(SoftBody3DSW *p_sof_body, int p_soft_body_shape, Area3DSW *p_area, int p_area_shape); - ~AreaSoftBodyPair3DSW(); + GodotAreaSoftBodyPair3D(GodotSoftBody3D *p_sof_body, int p_soft_body_shape, GodotArea3D *p_area, int p_area_shape); + ~GodotAreaSoftBodyPair3D(); }; -#endif // AREA_PAIR__SW_H +#endif // GODOT_AREA_PAIR_3D_H diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/godot_body_3d.cpp index 069374d122..02929eeaed 100644 --- a/servers/physics_3d/body_3d_sw.cpp +++ b/servers/physics_3d/godot_body_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_3d_sw.cpp */ +/* godot_body_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,19 +28,19 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "body_3d_sw.h" +#include "godot_body_3d.h" -#include "area_3d_sw.h" -#include "body_direct_state_3d_sw.h" -#include "space_3d_sw.h" +#include "godot_area_3d.h" +#include "godot_body_direct_state_3d.h" +#include "godot_space_3d.h" -void Body3DSW::_mass_properties_changed() { +void GodotBody3D::_mass_properties_changed() { if (get_space() && !mass_properties_update_list.in_list() && (calculate_inertia || calculate_center_of_mass)) { get_space()->body_add_to_mass_properties_update_list(&mass_properties_update_list); } } -void Body3DSW::_update_transform_dependant() { +void GodotBody3D::_update_transform_dependent() { center_of_mass = get_transform().basis.xform(center_of_mass_local); principal_inertia_axes = get_transform().basis * principal_inertia_axes_local; @@ -52,7 +52,7 @@ void Body3DSW::_update_transform_dependant() { _inv_inertia_tensor = tb * diag * tbt; } -void Body3DSW::update_mass_properties() { +void GodotBody3D::update_mass_properties() { // Update shapes and motions. switch (mode) { @@ -106,7 +106,7 @@ void Body3DSW::update_mass_properties() { inertia_set = true; - const Shape3DSW *shape = get_shape(i); + const GodotShape3D *shape = get_shape(i); real_t mass = area * this->mass / total_area; @@ -161,16 +161,16 @@ void Body3DSW::update_mass_properties() { } break; } - _update_transform_dependant(); + _update_transform_dependent(); } -void Body3DSW::reset_mass_properties() { +void GodotBody3D::reset_mass_properties() { calculate_inertia = true; calculate_center_of_mass = true; _mass_properties_changed(); } -void Body3DSW::set_active(bool p_active) { +void GodotBody3D::set_active(bool p_active) { if (active == p_active) { return; } @@ -189,7 +189,7 @@ void Body3DSW::set_active(bool p_active) { } } -void Body3DSW::set_param(PhysicsServer3D::BodyParameter p_param, const Variant &p_value) { +void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Variant &p_value) { switch (p_param) { case PhysicsServer3D::BODY_PARAM_BOUNCE: { bounce = p_value; @@ -217,14 +217,14 @@ void Body3DSW::set_param(PhysicsServer3D::BodyParameter p_param, const Variant & if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) { principal_inertia_axes_local = Basis(); _inv_inertia = inertia.inverse(); - _update_transform_dependant(); + _update_transform_dependent(); } } } break; case PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS: { calculate_center_of_mass = false; center_of_mass_local = p_value; - _update_transform_dependant(); + _update_transform_dependent(); } break; case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: { gravity_scale = p_value; @@ -240,7 +240,7 @@ void Body3DSW::set_param(PhysicsServer3D::BodyParameter p_param, const Variant & } } -Variant Body3DSW::get_param(PhysicsServer3D::BodyParameter p_param) const { +Variant GodotBody3D::get_param(PhysicsServer3D::BodyParameter p_param) const { switch (p_param) { case PhysicsServer3D::BODY_PARAM_BOUNCE: { return bounce; @@ -278,7 +278,7 @@ Variant Body3DSW::get_param(PhysicsServer3D::BodyParameter p_param) const { return 0; } -void Body3DSW::set_mode(PhysicsServer3D::BodyMode p_mode) { +void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) { PhysicsServer3D::BodyMode prev = mode; mode = p_mode; @@ -295,7 +295,7 @@ void Body3DSW::set_mode(PhysicsServer3D::BodyMode p_mode) { if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC && prev != mode) { first_time_kinematic = true; } - _update_transform_dependant(); + _update_transform_dependent(); } break; case PhysicsServer3D::BODY_MODE_DYNAMIC: { @@ -303,7 +303,7 @@ void Body3DSW::set_mode(PhysicsServer3D::BodyMode p_mode) { if (!calculate_inertia) { principal_inertia_axes_local = Basis(); _inv_inertia = inertia.inverse(); - _update_transform_dependant(); + _update_transform_dependent(); } _mass_properties_changed(); _set_static(false); @@ -314,22 +314,24 @@ void Body3DSW::set_mode(PhysicsServer3D::BodyMode p_mode) { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _inv_inertia = Vector3(); angular_velocity = Vector3(); - _update_transform_dependant(); + _update_transform_dependent(); _set_static(false); set_active(true); } } } -PhysicsServer3D::BodyMode Body3DSW::get_mode() const { +PhysicsServer3D::BodyMode GodotBody3D::get_mode() const { return mode; } -void Body3DSW::_shapes_changed() { +void GodotBody3D::_shapes_changed() { _mass_properties_changed(); + wakeup(); + wakeup_neighbours(); } -void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) { +void GodotBody3D::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) { switch (p_state) { case PhysicsServer3D::BODY_STATE_TRANSFORM: { if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC) { @@ -355,6 +357,7 @@ void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_va } _set_transform(t); _set_inv_transform(get_transform().inverse()); + _update_transform_dependent(); } wakeup(); @@ -395,7 +398,7 @@ void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_va } } -Variant Body3DSW::get_state(PhysicsServer3D::BodyState p_state) const { +Variant GodotBody3D::get_state(PhysicsServer3D::BodyState p_state) const { switch (p_state) { case PhysicsServer3D::BODY_STATE_TRANSFORM: { return get_transform(); @@ -417,7 +420,7 @@ Variant Body3DSW::get_state(PhysicsServer3D::BodyState p_state) const { return Variant(); } -void Body3DSW::set_space(Space3DSW *p_space) { +void GodotBody3D::set_space(GodotSpace3D *p_space) { if (get_space()) { if (mass_properties_update_list.in_list()) { get_space()->body_remove_from_mass_properties_update_list(&mass_properties_update_list); @@ -440,7 +443,7 @@ void Body3DSW::set_space(Space3DSW *p_space) { } } -void Body3DSW::_compute_area_gravity_and_damping(const Area3DSW *p_area) { +void GodotBody3D::_compute_area_gravity_and_damping(const GodotArea3D *p_area) { Vector3 area_gravity; p_area->compute_gravity(get_transform().get_origin(), area_gravity); gravity += area_gravity; @@ -449,7 +452,7 @@ void Body3DSW::_compute_area_gravity_and_damping(const Area3DSW *p_area) { area_angular_damp += p_area->get_angular_damp(); } -void Body3DSW::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) { +void GodotBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) { if (lock) { locked_axis |= p_axis; } else { @@ -457,17 +460,16 @@ void Body3DSW::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) { } } -bool Body3DSW::is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const { +bool GodotBody3D::is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const { return locked_axis & p_axis; } -void Body3DSW::integrate_forces(real_t p_step) { +void GodotBody3D::integrate_forces(real_t p_step) { if (mode == PhysicsServer3D::BODY_MODE_STATIC) { return; } - Area3DSW *def_area = get_space()->get_default_area(); - // AreaSW *damp_area = def_area; + GodotArea3D *def_area = get_space()->get_default_area(); ERR_FAIL_COND(!def_area); @@ -591,7 +593,7 @@ void Body3DSW::integrate_forces(real_t p_step) { contact_count = 0; } -void Body3DSW::integrate_velocities(real_t p_step) { +void GodotBody3D::integrate_velocities(real_t p_step) { if (mode == PhysicsServer3D::BODY_MODE_STATIC) { return; } @@ -652,52 +654,20 @@ void Body3DSW::integrate_velocities(real_t p_step) { _set_transform(transform); _set_inv_transform(get_transform().inverse()); - _update_transform_dependant(); + _update_transform_dependent(); } -/* -void BodySW::simulate_motion(const Transform3D& p_xform,real_t p_step) { - Transform3D inv_xform = p_xform.affine_inverse(); - if (!get_space()) { - _set_transform(p_xform); - _set_inv_transform(inv_xform); - - return; - } - - //compute a FAKE linear velocity - this is easy - - linear_velocity=(p_xform.origin - get_transform().origin)/p_step; - - //compute a FAKE angular velocity, not so easy - Basis rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized(); - Vector3 axis; - real_t angle; - - rot.get_axis_angle(axis,angle); - axis.normalize(); - angular_velocity=axis.normalized() * (angle/p_step); - linear_velocity = (p_xform.origin - get_transform().origin)/p_step; - - if (!direct_state_query_list.in_list())// - callalways, so lv and av are cleared && (state_query || direct_state_query)) - get_space()->body_add_to_state_query_list(&direct_state_query_list); - simulated_motion=true; - _set_transform(p_xform); -} - -*/ - -void Body3DSW::wakeup_neighbours() { - for (const KeyValue<Constraint3DSW *, int> &E : constraint_map) { - const Constraint3DSW *c = E.key; - Body3DSW **n = c->get_body_ptr(); +void GodotBody3D::wakeup_neighbours() { + for (const KeyValue<GodotConstraint3D *, int> &E : constraint_map) { + const GodotConstraint3D *c = E.key; + GodotBody3D **n = c->get_body_ptr(); int bc = c->get_body_count(); for (int i = 0; i < bc; i++) { if (i == E.value) { continue; } - Body3DSW *b = n[i]; + GodotBody3D *b = n[i]; if (b->mode < PhysicsServer3D::BODY_MODE_DYNAMIC) { continue; } @@ -709,7 +679,7 @@ void Body3DSW::wakeup_neighbours() { } } -void Body3DSW::call_queries() { +void GodotBody3D::call_queries() { if (fi_callback_data) { if (!fi_callback_data->callable.get_object()) { set_force_integration_callback(Callable()); @@ -729,7 +699,7 @@ void Body3DSW::call_queries() { } } -bool Body3DSW::sleep_test(real_t p_step) { +bool GodotBody3D::sleep_test(real_t p_step) { if (mode == PhysicsServer3D::BODY_MODE_STATIC || mode == PhysicsServer3D::BODY_MODE_KINEMATIC) { return true; } else if (!can_sleep) { @@ -746,12 +716,12 @@ bool Body3DSW::sleep_test(real_t p_step) { } } -void Body3DSW::set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback) { +void GodotBody3D::set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback) { body_state_callback_instance = p_instance; body_state_callback = p_callback; } -void Body3DSW::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) { +void GodotBody3D::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) { if (p_callable.get_object()) { if (!fi_callback_data) { fi_callback_data = memnew(ForceIntegrationCallbackData); @@ -764,23 +734,23 @@ void Body3DSW::set_force_integration_callback(const Callable &p_callable, const } } -PhysicsDirectBodyState3DSW *Body3DSW::get_direct_state() { +GodotPhysicsDirectBodyState3D *GodotBody3D::get_direct_state() { if (!direct_state) { - direct_state = memnew(PhysicsDirectBodyState3DSW); + direct_state = memnew(GodotPhysicsDirectBodyState3D); direct_state->body = this; } return direct_state; } -Body3DSW::Body3DSW() : - CollisionObject3DSW(TYPE_BODY), +GodotBody3D::GodotBody3D() : + GodotCollisionObject3D(TYPE_BODY), active_list(this), mass_properties_update_list(this), direct_state_query_list(this) { _set_static(false); } -Body3DSW::~Body3DSW() { +GodotBody3D::~GodotBody3D() { if (fi_callback_data) { memdelete(fi_callback_data); } diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/godot_body_3d.h index fc47040389..5acdab9d13 100644 --- a/servers/physics_3d/body_3d_sw.h +++ b/servers/physics_3d/godot_body_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_3d_sw.h */ +/* godot_body_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BODY_3D_SW_H -#define BODY_3D_SW_H +#ifndef GODOT_BODY_3D_H +#define GODOT_BODY_3D_H + +#include "godot_area_3d.h" +#include "godot_collision_object_3d.h" -#include "area_3d_sw.h" -#include "collision_object_3d_sw.h" #include "core/templates/vset.h" -class Constraint3DSW; -class PhysicsDirectBodyState3DSW; +class GodotConstraint3D; +class GodotPhysicsDirectBodyState3D; -class Body3DSW : public CollisionObject3DSW { +class GodotBody3D : public GodotCollisionObject3D { PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_DYNAMIC; Vector3 linear_velocity; @@ -85,9 +86,9 @@ class Body3DSW : public CollisionObject3DSW { real_t area_angular_damp = 0.0; real_t area_linear_damp = 0.0; - SelfList<Body3DSW> active_list; - SelfList<Body3DSW> mass_properties_update_list; - SelfList<Body3DSW> direct_state_query_list; + SelfList<GodotBody3D> active_list; + SelfList<GodotBody3D> mass_properties_update_list; + SelfList<GodotBody3D> direct_state_query_list; VSet<RID> exceptions; bool omit_force_integration = false; @@ -101,7 +102,7 @@ class Body3DSW : public CollisionObject3DSW { virtual void _shapes_changed(); Transform3D new_transform; - Map<Constraint3DSW *, int> constraint_map; + Map<GodotConstraint3D *, int> constraint_map; Vector<AreaCMP> areas; @@ -130,23 +131,23 @@ class Body3DSW : public CollisionObject3DSW { ForceIntegrationCallbackData *fi_callback_data = nullptr; - PhysicsDirectBodyState3DSW *direct_state = nullptr; + GodotPhysicsDirectBodyState3D *direct_state = nullptr; uint64_t island_step = 0; - _FORCE_INLINE_ void _compute_area_gravity_and_damping(const Area3DSW *p_area); + void _compute_area_gravity_and_damping(const GodotArea3D *p_area); - _FORCE_INLINE_ void _update_transform_dependant(); + void _update_transform_dependent(); - friend class PhysicsDirectBodyState3DSW; // i give up, too many functions to expose + friend class GodotPhysicsDirectBodyState3D; // i give up, too many functions to expose public: void set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback); void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant()); - PhysicsDirectBodyState3DSW *get_direct_state(); + GodotPhysicsDirectBodyState3D *get_direct_state(); - _FORCE_INLINE_ void add_area(Area3DSW *p_area) { + _FORCE_INLINE_ void add_area(GodotArea3D *p_area) { int index = areas.find(AreaCMP(p_area)); if (index > -1) { areas.write[index].refCount += 1; @@ -155,7 +156,7 @@ public: } } - _FORCE_INLINE_ void remove_area(Area3DSW *p_area) { + _FORCE_INLINE_ void remove_area(GodotArea3D *p_area) { int index = areas.find(AreaCMP(p_area)); if (index > -1) { areas.write[index].refCount -= 1; @@ -185,9 +186,9 @@ public: _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } - _FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; } - _FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraint_map.erase(p_constraint); } - const Map<Constraint3DSW *, int> &get_constraint_map() const { return constraint_map; } + _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; } + _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraint_map.erase(p_constraint); } + const Map<GodotConstraint3D *, int> &get_constraint_map() const { return constraint_map; } _FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); } _FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; } @@ -275,7 +276,7 @@ public: _FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd = p_enable; } _FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; } - void set_space(Space3DSW *p_space); + void set_space(GodotSpace3D *p_space); void update_mass_properties(); void reset_mass_properties(); @@ -317,13 +318,13 @@ public: bool sleep_test(real_t p_step); - Body3DSW(); - ~Body3DSW(); + GodotBody3D(); + ~GodotBody3D(); }; //add contact inline -void Body3DSW::add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_normal, real_t p_depth, int p_local_shape, const Vector3 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector3 &p_collider_velocity_at_pos) { +void GodotBody3D::add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_normal, real_t p_depth, int p_local_shape, const Vector3 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector3 &p_collider_velocity_at_pos) { int c_max = contacts.size(); if (c_max == 0) { @@ -365,4 +366,4 @@ void Body3DSW::add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_no c[idx].collider_velocity_at_pos = p_collider_velocity_at_pos; } -#endif // BODY_3D_SW_H +#endif // GODOT_BODY_3D_H diff --git a/servers/physics_3d/body_direct_state_3d_sw.cpp b/servers/physics_3d/godot_body_direct_state_3d.cpp index d61a6ac8e4..db09657f8a 100644 --- a/servers/physics_3d/body_direct_state_3d_sw.cpp +++ b/servers/physics_3d/godot_body_direct_state_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_direct_state_3d_sw.cpp */ +/* godot_body_direct_state_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,163 +28,163 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "body_direct_state_3d_sw.h" +#include "godot_body_direct_state_3d.h" -#include "body_3d_sw.h" -#include "space_3d_sw.h" +#include "godot_body_3d.h" +#include "godot_space_3d.h" -Vector3 PhysicsDirectBodyState3DSW::get_total_gravity() const { +Vector3 GodotPhysicsDirectBodyState3D::get_total_gravity() const { return body->gravity; } -real_t PhysicsDirectBodyState3DSW::get_total_angular_damp() const { +real_t GodotPhysicsDirectBodyState3D::get_total_angular_damp() const { return body->area_angular_damp; } -real_t PhysicsDirectBodyState3DSW::get_total_linear_damp() const { +real_t GodotPhysicsDirectBodyState3D::get_total_linear_damp() const { return body->area_linear_damp; } -Vector3 PhysicsDirectBodyState3DSW::get_center_of_mass() const { +Vector3 GodotPhysicsDirectBodyState3D::get_center_of_mass() const { return body->get_center_of_mass(); } -Basis PhysicsDirectBodyState3DSW::get_principal_inertia_axes() const { +Basis GodotPhysicsDirectBodyState3D::get_principal_inertia_axes() const { return body->get_principal_inertia_axes(); } -real_t PhysicsDirectBodyState3DSW::get_inverse_mass() const { +real_t GodotPhysicsDirectBodyState3D::get_inverse_mass() const { return body->get_inv_mass(); } -Vector3 PhysicsDirectBodyState3DSW::get_inverse_inertia() const { +Vector3 GodotPhysicsDirectBodyState3D::get_inverse_inertia() const { return body->get_inv_inertia(); } -Basis PhysicsDirectBodyState3DSW::get_inverse_inertia_tensor() const { +Basis GodotPhysicsDirectBodyState3D::get_inverse_inertia_tensor() const { return body->get_inv_inertia_tensor(); } -void PhysicsDirectBodyState3DSW::set_linear_velocity(const Vector3 &p_velocity) { +void GodotPhysicsDirectBodyState3D::set_linear_velocity(const Vector3 &p_velocity) { body->wakeup(); body->set_linear_velocity(p_velocity); } -Vector3 PhysicsDirectBodyState3DSW::get_linear_velocity() const { +Vector3 GodotPhysicsDirectBodyState3D::get_linear_velocity() const { return body->get_linear_velocity(); } -void PhysicsDirectBodyState3DSW::set_angular_velocity(const Vector3 &p_velocity) { +void GodotPhysicsDirectBodyState3D::set_angular_velocity(const Vector3 &p_velocity) { body->wakeup(); body->set_angular_velocity(p_velocity); } -Vector3 PhysicsDirectBodyState3DSW::get_angular_velocity() const { +Vector3 GodotPhysicsDirectBodyState3D::get_angular_velocity() const { return body->get_angular_velocity(); } -void PhysicsDirectBodyState3DSW::set_transform(const Transform3D &p_transform) { +void GodotPhysicsDirectBodyState3D::set_transform(const Transform3D &p_transform) { body->set_state(PhysicsServer3D::BODY_STATE_TRANSFORM, p_transform); } -Transform3D PhysicsDirectBodyState3DSW::get_transform() const { +Transform3D GodotPhysicsDirectBodyState3D::get_transform() const { return body->get_transform(); } -Vector3 PhysicsDirectBodyState3DSW::get_velocity_at_local_position(const Vector3 &p_position) const { +Vector3 GodotPhysicsDirectBodyState3D::get_velocity_at_local_position(const Vector3 &p_position) const { return body->get_velocity_in_local_point(p_position); } -void PhysicsDirectBodyState3DSW::add_central_force(const Vector3 &p_force) { +void GodotPhysicsDirectBodyState3D::add_central_force(const Vector3 &p_force) { body->wakeup(); body->add_central_force(p_force); } -void PhysicsDirectBodyState3DSW::add_force(const Vector3 &p_force, const Vector3 &p_position) { +void GodotPhysicsDirectBodyState3D::add_force(const Vector3 &p_force, const Vector3 &p_position) { body->wakeup(); body->add_force(p_force, p_position); } -void PhysicsDirectBodyState3DSW::add_torque(const Vector3 &p_torque) { +void GodotPhysicsDirectBodyState3D::add_torque(const Vector3 &p_torque) { body->wakeup(); body->add_torque(p_torque); } -void PhysicsDirectBodyState3DSW::apply_central_impulse(const Vector3 &p_impulse) { +void GodotPhysicsDirectBodyState3D::apply_central_impulse(const Vector3 &p_impulse) { body->wakeup(); body->apply_central_impulse(p_impulse); } -void PhysicsDirectBodyState3DSW::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) { +void GodotPhysicsDirectBodyState3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) { body->wakeup(); body->apply_impulse(p_impulse, p_position); } -void PhysicsDirectBodyState3DSW::apply_torque_impulse(const Vector3 &p_impulse) { +void GodotPhysicsDirectBodyState3D::apply_torque_impulse(const Vector3 &p_impulse) { body->wakeup(); body->apply_torque_impulse(p_impulse); } -void PhysicsDirectBodyState3DSW::set_sleep_state(bool p_sleep) { +void GodotPhysicsDirectBodyState3D::set_sleep_state(bool p_sleep) { body->set_active(!p_sleep); } -bool PhysicsDirectBodyState3DSW::is_sleeping() const { +bool GodotPhysicsDirectBodyState3D::is_sleeping() const { return !body->is_active(); } -int PhysicsDirectBodyState3DSW::get_contact_count() const { +int GodotPhysicsDirectBodyState3D::get_contact_count() const { return body->contact_count; } -Vector3 PhysicsDirectBodyState3DSW::get_contact_local_position(int p_contact_idx) const { +Vector3 GodotPhysicsDirectBodyState3D::get_contact_local_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); return body->contacts[p_contact_idx].local_pos; } -Vector3 PhysicsDirectBodyState3DSW::get_contact_local_normal(int p_contact_idx) const { +Vector3 GodotPhysicsDirectBodyState3D::get_contact_local_normal(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); return body->contacts[p_contact_idx].local_normal; } -real_t PhysicsDirectBodyState3DSW::get_contact_impulse(int p_contact_idx) const { +real_t GodotPhysicsDirectBodyState3D::get_contact_impulse(int p_contact_idx) const { return 0.0f; // Only implemented for bullet } -int PhysicsDirectBodyState3DSW::get_contact_local_shape(int p_contact_idx) const { +int GodotPhysicsDirectBodyState3D::get_contact_local_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1); return body->contacts[p_contact_idx].local_shape; } -RID PhysicsDirectBodyState3DSW::get_contact_collider(int p_contact_idx) const { +RID GodotPhysicsDirectBodyState3D::get_contact_collider(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID()); return body->contacts[p_contact_idx].collider; } -Vector3 PhysicsDirectBodyState3DSW::get_contact_collider_position(int p_contact_idx) const { +Vector3 GodotPhysicsDirectBodyState3D::get_contact_collider_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); return body->contacts[p_contact_idx].collider_pos; } -ObjectID PhysicsDirectBodyState3DSW::get_contact_collider_id(int p_contact_idx) const { +ObjectID GodotPhysicsDirectBodyState3D::get_contact_collider_id(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID()); return body->contacts[p_contact_idx].collider_instance_id; } -int PhysicsDirectBodyState3DSW::get_contact_collider_shape(int p_contact_idx) const { +int GodotPhysicsDirectBodyState3D::get_contact_collider_shape(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0); return body->contacts[p_contact_idx].collider_shape; } -Vector3 PhysicsDirectBodyState3DSW::get_contact_collider_velocity_at_position(int p_contact_idx) const { +Vector3 GodotPhysicsDirectBodyState3D::get_contact_collider_velocity_at_position(int p_contact_idx) const { ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); return body->contacts[p_contact_idx].collider_velocity_at_pos; } -PhysicsDirectSpaceState3D *PhysicsDirectBodyState3DSW::get_space_state() { +PhysicsDirectSpaceState3D *GodotPhysicsDirectBodyState3D::get_space_state() { return body->get_space()->get_direct_state(); } -real_t PhysicsDirectBodyState3DSW::get_step() const { +real_t GodotPhysicsDirectBodyState3D::get_step() const { return body->get_space()->get_last_step(); } diff --git a/servers/physics_3d/body_direct_state_3d_sw.h b/servers/physics_3d/godot_body_direct_state_3d.h index 5132376715..6c584a2634 100644 --- a/servers/physics_3d/body_direct_state_3d_sw.h +++ b/servers/physics_3d/godot_body_direct_state_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_direct_state_3d_sw.h */ +/* godot_body_direct_state_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,18 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BODY_DIRECT_STATE_3D_SW_H -#define BODY_DIRECT_STATE_3D_SW_H +#ifndef GODOT_BODY_DIRECT_STATE_3D_H +#define GODOT_BODY_DIRECT_STATE_3D_H #include "servers/physics_server_3d.h" -class Body3DSW; +class GodotBody3D; -class PhysicsDirectBodyState3DSW : public PhysicsDirectBodyState3D { - GDCLASS(PhysicsDirectBodyState3DSW, PhysicsDirectBodyState3D); +class GodotPhysicsDirectBodyState3D : public PhysicsDirectBodyState3D { + GDCLASS(GodotPhysicsDirectBodyState3D, PhysicsDirectBodyState3D); public: - Body3DSW *body = nullptr; + GodotBody3D *body = nullptr; virtual Vector3 get_total_gravity() const override; virtual real_t get_total_angular_damp() const override; @@ -91,4 +91,4 @@ public: virtual real_t get_step() const override; }; -#endif // BODY_DIRECT_STATE_3D_SW_H +#endif // GODOT_BODY_DIRECT_STATE_3D_H diff --git a/servers/physics_3d/body_pair_3d_sw.cpp b/servers/physics_3d/godot_body_pair_3d.cpp index c27a2ecced..457abfb71a 100644 --- a/servers/physics_3d/body_pair_3d_sw.cpp +++ b/servers/physics_3d/godot_body_pair_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_pair_3d_sw.cpp */ +/* godot_body_pair_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "body_pair_3d_sw.h" +#include "godot_body_pair_3d.h" + +#include "godot_collision_solver_3d.h" +#include "godot_space_3d.h" -#include "collision_solver_3d_sw.h" #include "core/os/os.h" -#include "space_3d_sw.h" /* #define NO_ACCUMULATE_IMPULSES @@ -49,12 +50,12 @@ #define MIN_VELOCITY 0.0001 #define MAX_BIAS_ROTATION (Math_PI / 8) -void BodyPair3DSW::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - BodyPair3DSW *pair = (BodyPair3DSW *)p_userdata; +void GodotBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { + GodotBodyPair3D *pair = (GodotBodyPair3D *)p_userdata; pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B); } -void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) { +void GodotBodyPair3D::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) { // check if we already have the contact //Vector3 local_A = A->get_inv_transform().xform(p_point_A); @@ -135,7 +136,7 @@ void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_ } } -void BodyPair3DSW::validate_contacts() { +void GodotBodyPair3D::validate_contacts() { //make sure to erase contacts that are no longer valid real_t contact_max_separation = space->get_contact_max_separation(); @@ -161,7 +162,7 @@ void BodyPair3DSW::validate_contacts() { } } -bool BodyPair3DSW::_test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform3D &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform3D &p_xform_B) { +bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, const Transform3D &p_xform_A, GodotBody3D *p_B, int p_shape_B, const Transform3D &p_xform_B) { Vector3 motion = p_A->get_linear_velocity() * p_step; real_t mlen = motion.length(); if (mlen < CMP_EPSILON) { @@ -203,15 +204,15 @@ bool BodyPair3DSW::_test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const return true; } -real_t combine_bounce(Body3DSW *A, Body3DSW *B) { +real_t combine_bounce(GodotBody3D *A, GodotBody3D *B) { return CLAMP(A->get_bounce() + B->get_bounce(), 0, 1); } -real_t combine_friction(Body3DSW *A, Body3DSW *B) { +real_t combine_friction(GodotBody3D *A, GodotBody3D *B) { return ABS(MIN(A->get_friction(), B->get_friction())); } -bool BodyPair3DSW::setup(real_t p_step) { +bool GodotBodyPair3D::setup(real_t p_step) { if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self())) { collided = false; return false; @@ -242,10 +243,10 @@ bool BodyPair3DSW::setup(real_t p_step) { xform_Bu.origin -= offset_A; Transform3D xform_B = xform_Bu * B->get_shape_transform(shape_B); - Shape3DSW *shape_A_ptr = A->get_shape(shape_A); - Shape3DSW *shape_B_ptr = B->get_shape(shape_B); + GodotShape3D *shape_A_ptr = A->get_shape(shape_A); + GodotShape3D *shape_B_ptr = B->get_shape(shape_B); - collided = CollisionSolver3DSW::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis); + collided = GodotCollisionSolver3D::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis); if (!collided) { //test ccd (currently just a raycast) @@ -264,7 +265,7 @@ bool BodyPair3DSW::setup(real_t p_step) { return true; } -bool BodyPair3DSW::pre_solve(real_t p_step) { +bool GodotBodyPair3D::pre_solve(real_t p_step) { if (!collided) { return false; } @@ -273,8 +274,8 @@ bool BodyPair3DSW::pre_solve(real_t p_step) { real_t bias = (real_t)0.3; - Shape3DSW *shape_A_ptr = A->get_shape(shape_A); - Shape3DSW *shape_B_ptr = B->get_shape(shape_B); + GodotShape3D *shape_A_ptr = A->get_shape(shape_A); + GodotShape3D *shape_B_ptr = B->get_shape(shape_B); if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) { if (shape_A_ptr->get_custom_bias() == 0) { @@ -380,7 +381,7 @@ bool BodyPair3DSW::pre_solve(real_t p_step) { return do_process; } -void BodyPair3DSW::solve(real_t p_step) { +void GodotBodyPair3D::solve(real_t p_step) { if (!collided) { return; } @@ -523,8 +524,8 @@ void BodyPair3DSW::solve(real_t p_step) { } } -BodyPair3DSW::BodyPair3DSW(Body3DSW *p_A, int p_shape_A, Body3DSW *p_B, int p_shape_B) : - BodyContact3DSW(_arr, 2) { +GodotBodyPair3D::GodotBodyPair3D(GodotBody3D *p_A, int p_shape_A, GodotBody3D *p_B, int p_shape_B) : + GodotBodyContact3D(_arr, 2) { A = p_A; B = p_B; shape_A = p_shape_A; @@ -534,17 +535,17 @@ BodyPair3DSW::BodyPair3DSW(Body3DSW *p_A, int p_shape_A, Body3DSW *p_B, int p_sh B->add_constraint(this, 1); } -BodyPair3DSW::~BodyPair3DSW() { +GodotBodyPair3D::~GodotBodyPair3D() { A->remove_constraint(this); B->remove_constraint(this); } -void BodySoftBodyPair3DSW::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - BodySoftBodyPair3DSW *pair = (BodySoftBodyPair3DSW *)p_userdata; +void GodotBodySoftBodyPair3D::_contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { + GodotBodySoftBodyPair3D *pair = (GodotBodySoftBodyPair3D *)p_userdata; pair->contact_added_callback(p_point_A, p_index_A, p_point_B, p_index_B); } -void BodySoftBodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) { +void GodotBodySoftBodyPair3D::contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B) { Vector3 local_A = body->get_inv_transform().xform(p_point_A); Vector3 local_B = p_point_B - soft_body->get_node_position(p_index_B); @@ -582,7 +583,7 @@ void BodySoftBodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, int contacts.push_back(contact); } -void BodySoftBodyPair3DSW::validate_contacts() { +void GodotBodySoftBodyPair3D::validate_contacts() { // Make sure to erase contacts that are no longer valid. const Transform3D &transform_A = body->get_transform(); @@ -612,7 +613,7 @@ void BodySoftBodyPair3DSW::validate_contacts() { contacts.resize(contact_count); } -bool BodySoftBodyPair3DSW::setup(real_t p_step) { +bool GodotBodySoftBodyPair3D::setup(real_t p_step) { if (!body->interacts_with(soft_body) || body->has_exception(soft_body->get_self()) || soft_body->has_exception(body->get_self())) { collided = false; return false; @@ -638,15 +639,15 @@ bool BodySoftBodyPair3DSW::setup(real_t p_step) { validate_contacts(); - Shape3DSW *shape_A_ptr = body->get_shape(body_shape); - Shape3DSW *shape_B_ptr = soft_body->get_shape(0); + GodotShape3D *shape_A_ptr = body->get_shape(body_shape); + GodotShape3D *shape_B_ptr = soft_body->get_shape(0); - collided = CollisionSolver3DSW::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis); + collided = GodotCollisionSolver3D::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis); return collided; } -bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) { +bool GodotBodySoftBodyPair3D::pre_solve(real_t p_step) { if (!collided) { return false; } @@ -655,7 +656,7 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) { real_t bias = (real_t)0.3; - Shape3DSW *shape_A_ptr = body->get_shape(body_shape); + GodotShape3D *shape_A_ptr = body->get_shape(body_shape); if (shape_A_ptr->get_custom_bias()) { bias = shape_A_ptr->get_custom_bias(); @@ -753,7 +754,7 @@ bool BodySoftBodyPair3DSW::pre_solve(real_t p_step) { return do_process; } -void BodySoftBodyPair3DSW::solve(real_t p_step) { +void GodotBodySoftBodyPair3D::solve(real_t p_step) { if (!collided) { return; } @@ -891,8 +892,8 @@ void BodySoftBodyPair3DSW::solve(real_t p_step) { } } -BodySoftBodyPair3DSW::BodySoftBodyPair3DSW(Body3DSW *p_A, int p_shape_A, SoftBody3DSW *p_B) : - BodyContact3DSW(&body, 1) { +GodotBodySoftBodyPair3D::GodotBodySoftBodyPair3D(GodotBody3D *p_A, int p_shape_A, GodotSoftBody3D *p_B) : + GodotBodyContact3D(&body, 1) { body = p_A; soft_body = p_B; body_shape = p_shape_A; @@ -901,7 +902,7 @@ BodySoftBodyPair3DSW::BodySoftBodyPair3DSW(Body3DSW *p_A, int p_shape_A, SoftBod soft_body->add_constraint(this); } -BodySoftBodyPair3DSW::~BodySoftBodyPair3DSW() { +GodotBodySoftBodyPair3D::~GodotBodySoftBodyPair3D() { body->remove_constraint(this); soft_body->remove_constraint(this); } diff --git a/servers/physics_3d/body_pair_3d_sw.h b/servers/physics_3d/godot_body_pair_3d.h index 01afb07e13..c0a2424e05 100644 --- a/servers/physics_3d/body_pair_3d_sw.h +++ b/servers/physics_3d/godot_body_pair_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* body_pair_3d_sw.h */ +/* godot_body_pair_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,15 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BODY_PAIR_3D_SW_H -#define BODY_PAIR_3D_SW_H +#ifndef GODOT_BODY_PAIR_3D_H +#define GODOT_BODY_PAIR_3D_H + +#include "godot_body_3d.h" +#include "godot_constraint_3d.h" +#include "godot_soft_body_3d.h" -#include "body_3d_sw.h" -#include "constraint_3d_sw.h" #include "core/templates/local_vector.h" -#include "soft_body_3d_sw.h" -class BodyContact3DSW : public Constraint3DSW { +class GodotBodyContact3D : public GodotConstraint3D { protected: struct Contact { Vector3 position; @@ -59,25 +60,25 @@ protected: Vector3 sep_axis; bool collided = false; - Space3DSW *space = nullptr; + GodotSpace3D *space = nullptr; - BodyContact3DSW(Body3DSW **p_body_ptr = nullptr, int p_body_count = 0) : - Constraint3DSW(p_body_ptr, p_body_count) { + GodotBodyContact3D(GodotBody3D **p_body_ptr = nullptr, int p_body_count = 0) : + GodotConstraint3D(p_body_ptr, p_body_count) { } }; -class BodyPair3DSW : public BodyContact3DSW { +class GodotBodyPair3D : public GodotBodyContact3D { enum { MAX_CONTACTS = 4 }; union { struct { - Body3DSW *A; - Body3DSW *B; + GodotBody3D *A; + GodotBody3D *B; }; - Body3DSW *_arr[2] = { nullptr, nullptr }; + GodotBody3D *_arr[2] = { nullptr, nullptr }; }; int shape_A = 0; @@ -98,20 +99,20 @@ class BodyPair3DSW : public BodyContact3DSW { void contact_added_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B); void validate_contacts(); - bool _test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform3D &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform3D &p_xform_B); + bool _test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A, const Transform3D &p_xform_A, GodotBody3D *p_B, int p_shape_B, const Transform3D &p_xform_B); public: virtual bool setup(real_t p_step) override; virtual bool pre_solve(real_t p_step) override; virtual void solve(real_t p_step) override; - BodyPair3DSW(Body3DSW *p_A, int p_shape_A, Body3DSW *p_B, int p_shape_B); - ~BodyPair3DSW(); + GodotBodyPair3D(GodotBody3D *p_A, int p_shape_A, GodotBody3D *p_B, int p_shape_B); + ~GodotBodyPair3D(); }; -class BodySoftBodyPair3DSW : public BodyContact3DSW { - Body3DSW *body = nullptr; - SoftBody3DSW *soft_body = nullptr; +class GodotBodySoftBodyPair3D : public GodotBodyContact3D { + GodotBody3D *body = nullptr; + GodotSoftBody3D *soft_body = nullptr; int body_shape = 0; @@ -133,11 +134,11 @@ public: virtual bool pre_solve(real_t p_step) override; virtual void solve(real_t p_step) override; - virtual SoftBody3DSW *get_soft_body_ptr(int p_index) const override { return soft_body; } + virtual GodotSoftBody3D *get_soft_body_ptr(int p_index) const override { return soft_body; } virtual int get_soft_body_count() const override { return 1; } - BodySoftBodyPair3DSW(Body3DSW *p_A, int p_shape_A, SoftBody3DSW *p_B); - ~BodySoftBodyPair3DSW(); + GodotBodySoftBodyPair3D(GodotBody3D *p_A, int p_shape_A, GodotSoftBody3D *p_B); + ~GodotBodySoftBodyPair3D(); }; -#endif // BODY_PAIR_3D_SW_H +#endif // GODOT_BODY_PAIR_3D_H diff --git a/servers/physics_2d/broad_phase_2d_sw.cpp b/servers/physics_3d/godot_broad_phase_3d.cpp index 7f0af48b1f..db51dfb2b6 100644 --- a/servers/physics_2d/broad_phase_2d_sw.cpp +++ b/servers/physics_3d/godot_broad_phase_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* broad_phase_2d_sw.cpp */ +/* godot_broad_phase_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "broad_phase_2d_sw.h" +#include "godot_broad_phase_3d.h" -BroadPhase2DSW::CreateFunction BroadPhase2DSW::create_func = nullptr; +GodotBroadPhase3D::CreateFunction GodotBroadPhase3D::create_func = nullptr; -BroadPhase2DSW::~BroadPhase2DSW() { +GodotBroadPhase3D::~GodotBroadPhase3D() { } diff --git a/servers/physics_3d/broad_phase_3d_sw.h b/servers/physics_3d/godot_broad_phase_3d.h index 98313cb216..65423f293c 100644 --- a/servers/physics_3d/broad_phase_3d_sw.h +++ b/servers/physics_3d/godot_broad_phase_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* broad_phase_3d_sw.h */ +/* godot_broad_phase_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,45 +28,45 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BROAD_PHASE_SW_H -#define BROAD_PHASE_SW_H +#ifndef GODOT_BROAD_PHASE_3D_H +#define GODOT_BROAD_PHASE_3D_H #include "core/math/aabb.h" #include "core/math/math_funcs.h" -class CollisionObject3DSW; +class GodotCollisionObject3D; -class BroadPhase3DSW { +class GodotBroadPhase3D { public: - typedef BroadPhase3DSW *(*CreateFunction)(); + typedef GodotBroadPhase3D *(*CreateFunction)(); static CreateFunction create_func; typedef uint32_t ID; - typedef void *(*PairCallback)(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_userdata); - typedef void (*UnpairCallback)(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_userdata); + typedef void *(*PairCallback)(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_userdata); + typedef void (*UnpairCallback)(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_data, void *p_userdata); // 0 is an invalid ID - virtual ID create(CollisionObject3DSW *p_object_, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false) = 0; + virtual ID create(GodotCollisionObject3D *p_object_, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false) = 0; virtual void move(ID p_id, const AABB &p_aabb) = 0; virtual void set_static(ID p_id, bool p_static) = 0; virtual void remove(ID p_id) = 0; - virtual CollisionObject3DSW *get_object(ID p_id) const = 0; + virtual GodotCollisionObject3D *get_object(ID p_id) const = 0; virtual bool is_static(ID p_id) const = 0; virtual int get_subindex(ID p_id) const = 0; - virtual int cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr) = 0; - virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr) = 0; - virtual int cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr) = 0; + virtual int cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) = 0; + virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) = 0; + virtual int cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr) = 0; virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) = 0; virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) = 0; virtual void update() = 0; - virtual ~BroadPhase3DSW(); + virtual ~GodotBroadPhase3D(); }; -#endif // BROAD_PHASE__SW_H +#endif // GODOT_BROAD_PHASE_3D_H diff --git a/servers/physics_3d/broad_phase_3d_bvh.cpp b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp index d89e0e1f6d..0f2061a1ea 100644 --- a/servers/physics_3d/broad_phase_3d_bvh.cpp +++ b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* broad_phase_3d_bvh.cpp */ +/* godot_broad_phase_3d_bvh.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,55 +28,56 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "broad_phase_3d_bvh.h" -#include "collision_object_3d_sw.h" +#include "godot_broad_phase_3d_bvh.h" -BroadPhase3DBVH::ID BroadPhase3DBVH::create(CollisionObject3DSW *p_object, int p_subindex, const AABB &p_aabb, bool p_static) { +#include "godot_collision_object_3d.h" + +GodotBroadPhase3DBVH::ID GodotBroadPhase3DBVH::create(GodotCollisionObject3D *p_object, int p_subindex, const AABB &p_aabb, bool p_static) { ID oid = bvh.create(p_object, true, p_aabb, p_subindex, !p_static, 1 << p_object->get_type(), p_static ? 0 : 0xFFFFF); // Pair everything, don't care? return oid + 1; } -void BroadPhase3DBVH::move(ID p_id, const AABB &p_aabb) { +void GodotBroadPhase3DBVH::move(ID p_id, const AABB &p_aabb) { bvh.move(p_id - 1, p_aabb); } -void BroadPhase3DBVH::set_static(ID p_id, bool p_static) { - CollisionObject3DSW *it = bvh.get(p_id - 1); +void GodotBroadPhase3DBVH::set_static(ID p_id, bool p_static) { + GodotCollisionObject3D *it = bvh.get(p_id - 1); bvh.set_pairable(p_id - 1, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF, false); // Pair everything, don't care? } -void BroadPhase3DBVH::remove(ID p_id) { +void GodotBroadPhase3DBVH::remove(ID p_id) { bvh.erase(p_id - 1); } -CollisionObject3DSW *BroadPhase3DBVH::get_object(ID p_id) const { - CollisionObject3DSW *it = bvh.get(p_id - 1); +GodotCollisionObject3D *GodotBroadPhase3DBVH::get_object(ID p_id) const { + GodotCollisionObject3D *it = bvh.get(p_id - 1); ERR_FAIL_COND_V(!it, nullptr); return it; } -bool BroadPhase3DBVH::is_static(ID p_id) const { +bool GodotBroadPhase3DBVH::is_static(ID p_id) const { return !bvh.is_pairable(p_id - 1); } -int BroadPhase3DBVH::get_subindex(ID p_id) const { +int GodotBroadPhase3DBVH::get_subindex(ID p_id) const { return bvh.get_subindex(p_id - 1); } -int BroadPhase3DBVH::cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { +int GodotBroadPhase3DBVH::cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) { return bvh.cull_point(p_point, p_results, p_max_results, p_result_indices); } -int BroadPhase3DBVH::cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { +int GodotBroadPhase3DBVH::cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) { return bvh.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices); } -int BroadPhase3DBVH::cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { +int GodotBroadPhase3DBVH::cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices) { return bvh.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices); } -void *BroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, CollisionObject3DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject3DSW *p_object_B, int subindex_B) { - BroadPhase3DBVH *bpo = (BroadPhase3DBVH *)(self); +void *GodotBroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, GodotCollisionObject3D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject3D *p_object_B, int subindex_B) { + GodotBroadPhase3DBVH *bpo = (GodotBroadPhase3DBVH *)(self); if (!bpo->pair_callback) { return nullptr; } @@ -84,8 +85,8 @@ void *BroadPhase3DBVH::_pair_callback(void *self, uint32_t p_A, CollisionObject3 return bpo->pair_callback(p_object_A, subindex_A, p_object_B, subindex_B, bpo->pair_userdata); } -void BroadPhase3DBVH::_unpair_callback(void *self, uint32_t p_A, CollisionObject3DSW *p_object_A, int subindex_A, uint32_t p_B, CollisionObject3DSW *p_object_B, int subindex_B, void *pairdata) { - BroadPhase3DBVH *bpo = (BroadPhase3DBVH *)(self); +void GodotBroadPhase3DBVH::_unpair_callback(void *self, uint32_t p_A, GodotCollisionObject3D *p_object_A, int subindex_A, uint32_t p_B, GodotCollisionObject3D *p_object_B, int subindex_B, void *pairdata) { + GodotBroadPhase3DBVH *bpo = (GodotBroadPhase3DBVH *)(self); if (!bpo->unpair_callback) { return; } @@ -93,25 +94,25 @@ void BroadPhase3DBVH::_unpair_callback(void *self, uint32_t p_A, CollisionObject bpo->unpair_callback(p_object_A, subindex_A, p_object_B, subindex_B, pairdata, bpo->unpair_userdata); } -void BroadPhase3DBVH::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { +void GodotBroadPhase3DBVH::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { pair_callback = p_pair_callback; pair_userdata = p_userdata; } -void BroadPhase3DBVH::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { +void GodotBroadPhase3DBVH::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { unpair_callback = p_unpair_callback; unpair_userdata = p_userdata; } -void BroadPhase3DBVH::update() { +void GodotBroadPhase3DBVH::update() { bvh.update(); } -BroadPhase3DSW *BroadPhase3DBVH::_create() { - return memnew(BroadPhase3DBVH); +GodotBroadPhase3D *GodotBroadPhase3DBVH::_create() { + return memnew(GodotBroadPhase3DBVH); } -BroadPhase3DBVH::BroadPhase3DBVH() { +GodotBroadPhase3DBVH::GodotBroadPhase3DBVH() { bvh.set_pair_callback(_pair_callback, this); bvh.set_unpair_callback(_unpair_callback, this); } diff --git a/servers/physics_3d/broad_phase_3d_bvh.h b/servers/physics_3d/godot_broad_phase_3d_bvh.h index 03131c9db2..61127e52c1 100644 --- a/servers/physics_3d/broad_phase_3d_bvh.h +++ b/servers/physics_3d/godot_broad_phase_3d_bvh.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* broad_phase_3d_bvh.h */ +/* godot_broad_phase_3d_bvh.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,18 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef BROAD_PHASE_3D_BVH_H -#define BROAD_PHASE_3D_BVH_H +#ifndef GODOT_BROAD_PHASE_3D_BVH_H +#define GODOT_BROAD_PHASE_3D_BVH_H + +#include "godot_broad_phase_3d.h" -#include "broad_phase_3d_sw.h" #include "core/math/bvh.h" -class BroadPhase3DBVH : public BroadPhase3DSW { - BVH_Manager<CollisionObject3DSW, true, 128> bvh; +class GodotBroadPhase3DBVH : public GodotBroadPhase3D { + BVH_Manager<GodotCollisionObject3D, true, 128> bvh; - static void *_pair_callback(void *, uint32_t, CollisionObject3DSW *, int, uint32_t, CollisionObject3DSW *, int); - static void _unpair_callback(void *, uint32_t, CollisionObject3DSW *, int, uint32_t, CollisionObject3DSW *, int, void *); + static void *_pair_callback(void *, uint32_t, GodotCollisionObject3D *, int, uint32_t, GodotCollisionObject3D *, int); + static void _unpair_callback(void *, uint32_t, GodotCollisionObject3D *, int, uint32_t, GodotCollisionObject3D *, int, void *); PairCallback pair_callback = nullptr; void *pair_userdata = nullptr; @@ -47,26 +48,26 @@ class BroadPhase3DBVH : public BroadPhase3DSW { public: // 0 is an invalid ID - virtual ID create(CollisionObject3DSW *p_object, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false); + virtual ID create(GodotCollisionObject3D *p_object, int p_subindex = 0, const AABB &p_aabb = AABB(), bool p_static = false); virtual void move(ID p_id, const AABB &p_aabb); virtual void set_static(ID p_id, bool p_static); virtual void remove(ID p_id); - virtual CollisionObject3DSW *get_object(ID p_id) const; + virtual GodotCollisionObject3D *get_object(ID p_id) const; virtual bool is_static(ID p_id) const; virtual int get_subindex(ID p_id) const; - virtual int cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr); - virtual int cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = nullptr); + virtual int cull_point(const Vector3 &p_point, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr); + virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr); + virtual int cull_aabb(const AABB &p_aabb, GodotCollisionObject3D **p_results, int p_max_results, int *p_result_indices = nullptr); virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); virtual void update(); - static BroadPhase3DSW *_create(); - BroadPhase3DBVH(); + static GodotBroadPhase3D *_create(); + GodotBroadPhase3DBVH(); }; -#endif // BROAD_PHASE_3D_BVH_H +#endif // GODOT_BROAD_PHASE_3D_BVH_H diff --git a/servers/physics_3d/collision_object_3d_sw.cpp b/servers/physics_3d/godot_collision_object_3d.cpp index 098f627d11..80a3d18ce0 100644 --- a/servers/physics_3d/collision_object_3d_sw.cpp +++ b/servers/physics_3d/godot_collision_object_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_object_3d_sw.cpp */ +/* godot_collision_object_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "collision_object_3d_sw.h" -#include "servers/physics_3d/physics_server_3d_sw.h" -#include "space_3d_sw.h" +#include "godot_collision_object_3d.h" -void CollisionObject3DSW::add_shape(Shape3DSW *p_shape, const Transform3D &p_transform, bool p_disabled) { +#include "godot_physics_server_3d.h" +#include "godot_space_3d.h" + +void GodotCollisionObject3D::add_shape(GodotShape3D *p_shape, const Transform3D &p_transform, bool p_disabled) { Shape s; s.shape = p_shape; s.xform = p_transform; @@ -43,35 +44,35 @@ void CollisionObject3DSW::add_shape(Shape3DSW *p_shape, const Transform3D &p_tra p_shape->add_owner(this); if (!pending_shape_update_list.in_list()) { - PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } } -void CollisionObject3DSW::set_shape(int p_index, Shape3DSW *p_shape) { +void GodotCollisionObject3D::set_shape(int p_index, GodotShape3D *p_shape) { ERR_FAIL_INDEX(p_index, shapes.size()); shapes[p_index].shape->remove_owner(this); shapes.write[p_index].shape = p_shape; p_shape->add_owner(this); if (!pending_shape_update_list.in_list()) { - PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } } -void CollisionObject3DSW::set_shape_transform(int p_index, const Transform3D &p_transform) { +void GodotCollisionObject3D::set_shape_transform(int p_index, const Transform3D &p_transform) { ERR_FAIL_INDEX(p_index, shapes.size()); shapes.write[p_index].xform = p_transform; shapes.write[p_index].xform_inv = p_transform.affine_inverse(); if (!pending_shape_update_list.in_list()) { - PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } } -void CollisionObject3DSW::set_shape_disabled(int p_idx, bool p_disabled) { +void GodotCollisionObject3D::set_shape_disabled(int p_idx, bool p_disabled) { ERR_FAIL_INDEX(p_idx, shapes.size()); - CollisionObject3DSW::Shape &shape = shapes.write[p_idx]; + GodotCollisionObject3D::Shape &shape = shapes.write[p_idx]; if (shape.disabled == p_disabled) { return; } @@ -86,16 +87,16 @@ void CollisionObject3DSW::set_shape_disabled(int p_idx, bool p_disabled) { space->get_broadphase()->remove(shape.bpid); shape.bpid = 0; if (!pending_shape_update_list.in_list()) { - PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } } else if (!p_disabled && shape.bpid == 0) { if (!pending_shape_update_list.in_list()) { - PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } } } -void CollisionObject3DSW::remove_shape(Shape3DSW *p_shape) { +void GodotCollisionObject3D::remove_shape(GodotShape3D *p_shape) { //remove a shape, all the times it appears for (int i = 0; i < shapes.size(); i++) { if (shapes[i].shape == p_shape) { @@ -105,7 +106,7 @@ void CollisionObject3DSW::remove_shape(Shape3DSW *p_shape) { } } -void CollisionObject3DSW::remove_shape(int p_index) { +void GodotCollisionObject3D::remove_shape(int p_index) { //remove anything from shape to be erased to end, so subindices don't change ERR_FAIL_INDEX(p_index, shapes.size()); for (int i = p_index; i < shapes.size(); i++) { @@ -120,11 +121,11 @@ void CollisionObject3DSW::remove_shape(int p_index) { shapes.remove(p_index); if (!pending_shape_update_list.in_list()) { - PhysicsServer3DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + GodotPhysicsServer3D::godot_singleton->pending_shape_update_list.add(&pending_shape_update_list); } } -void CollisionObject3DSW::_set_static(bool p_static) { +void GodotCollisionObject3D::_set_static(bool p_static) { if (_static == p_static) { return; } @@ -141,7 +142,7 @@ void CollisionObject3DSW::_set_static(bool p_static) { } } -void CollisionObject3DSW::_unregister_shapes() { +void GodotCollisionObject3D::_unregister_shapes() { for (int i = 0; i < shapes.size(); i++) { Shape &s = shapes.write[i]; if (s.bpid > 0) { @@ -151,7 +152,7 @@ void CollisionObject3DSW::_unregister_shapes() { } } -void CollisionObject3DSW::_update_shapes() { +void GodotCollisionObject3D::_update_shapes() { if (!space) { return; } @@ -181,7 +182,7 @@ void CollisionObject3DSW::_update_shapes() { } } -void CollisionObject3DSW::_update_shapes_with_motion(const Vector3 &p_motion) { +void GodotCollisionObject3D::_update_shapes_with_motion(const Vector3 &p_motion) { if (!space) { return; } @@ -208,7 +209,7 @@ void CollisionObject3DSW::_update_shapes_with_motion(const Vector3 &p_motion) { } } -void CollisionObject3DSW::_set_space(Space3DSW *p_space) { +void GodotCollisionObject3D::_set_space(GodotSpace3D *p_space) { if (space) { space->remove_object(this); @@ -229,12 +230,12 @@ void CollisionObject3DSW::_set_space(Space3DSW *p_space) { } } -void CollisionObject3DSW::_shape_changed() { +void GodotCollisionObject3D::_shape_changed() { _update_shapes(); _shapes_changed(); } -CollisionObject3DSW::CollisionObject3DSW(Type p_type) : +GodotCollisionObject3D::GodotCollisionObject3D(Type p_type) : pending_shape_update_list(this) { type = p_type; } diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/godot_collision_object_3d.h index 3aa48946b7..43558034e0 100644 --- a/servers/physics_3d/collision_object_3d_sw.h +++ b/servers/physics_3d/godot_collision_object_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_object_3d_sw.h */ +/* godot_collision_object_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COLLISION_OBJECT_SW_H -#define COLLISION_OBJECT_SW_H +#ifndef GODOT_COLLISION_OBJECT_3D_H +#define GODOT_COLLISION_OBJECT_3D_H + +#include "godot_broad_phase_3d.h" +#include "godot_shape_3d.h" -#include "broad_phase_3d_sw.h" #include "core/templates/self_list.h" #include "servers/physics_server_3d.h" -#include "shape_3d_sw.h" #ifdef DEBUG_ENABLED #define MAX_OBJECT_DISTANCE 3.1622776601683791e+18 @@ -42,9 +43,9 @@ #define MAX_OBJECT_DISTANCE_X2 (MAX_OBJECT_DISTANCE * MAX_OBJECT_DISTANCE) #endif -class Space3DSW; +class GodotSpace3D; -class CollisionObject3DSW : public ShapeOwner3DSW { +class GodotCollisionObject3D : public GodotShapeOwner3D { public: enum Type { TYPE_AREA, @@ -62,20 +63,20 @@ private: struct Shape { Transform3D xform; Transform3D xform_inv; - BroadPhase3DSW::ID bpid; + GodotBroadPhase3D::ID bpid; AABB aabb_cache; //for rayqueries real_t area_cache = 0.0; - Shape3DSW *shape = nullptr; + GodotShape3D *shape = nullptr; bool disabled = false; }; Vector<Shape> shapes; - Space3DSW *space = nullptr; + GodotSpace3D *space = nullptr; Transform3D transform; Transform3D inv_transform; bool _static = true; - SelfList<CollisionObject3DSW> pending_shape_update_list; + SelfList<GodotCollisionObject3D> pending_shape_update_list; void _update_shapes(); @@ -98,11 +99,11 @@ protected: void _set_static(bool p_static); virtual void _shapes_changed() = 0; - void _set_space(Space3DSW *p_space); + void _set_space(GodotSpace3D *p_space); bool ray_pickable = true; - CollisionObject3DSW(Type p_type); + GodotCollisionObject3D(Type p_type); public: _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } @@ -114,11 +115,11 @@ public: void _shape_changed(); _FORCE_INLINE_ Type get_type() const { return type; } - void add_shape(Shape3DSW *p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false); - void set_shape(int p_index, Shape3DSW *p_shape); + void add_shape(GodotShape3D *p_shape, const Transform3D &p_transform = Transform3D(), bool p_disabled = false); + void set_shape(int p_index, GodotShape3D *p_shape); void set_shape_transform(int p_index, const Transform3D &p_transform); _FORCE_INLINE_ int get_shape_count() const { return shapes.size(); } - _FORCE_INLINE_ Shape3DSW *get_shape(int p_index) const { + _FORCE_INLINE_ GodotShape3D *get_shape(int p_index) const { CRASH_BAD_INDEX(p_index, shapes.size()); return shapes[p_index].shape; } @@ -141,7 +142,7 @@ public: _FORCE_INLINE_ const Transform3D &get_transform() const { return transform; } _FORCE_INLINE_ const Transform3D &get_inv_transform() const { return inv_transform; } - _FORCE_INLINE_ Space3DSW *get_space() const { return space; } + _FORCE_INLINE_ GodotSpace3D *get_space() const { return space; } _FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; } _FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; } @@ -164,22 +165,22 @@ public: } _FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; } - _FORCE_INLINE_ bool collides_with(CollisionObject3DSW *p_other) const { + _FORCE_INLINE_ bool collides_with(GodotCollisionObject3D *p_other) const { return p_other->collision_layer & collision_mask; } - _FORCE_INLINE_ bool interacts_with(CollisionObject3DSW *p_other) const { + _FORCE_INLINE_ bool interacts_with(GodotCollisionObject3D *p_other) const { return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask; } - void remove_shape(Shape3DSW *p_shape); + void remove_shape(GodotShape3D *p_shape); void remove_shape(int p_index); - virtual void set_space(Space3DSW *p_space) = 0; + virtual void set_space(GodotSpace3D *p_space) = 0; _FORCE_INLINE_ bool is_static() const { return _static; } - virtual ~CollisionObject3DSW() {} + virtual ~GodotCollisionObject3D() {} }; -#endif // COLLISION_OBJECT_SW_H +#endif // GODOT_COLLISION_OBJECT_3D_H diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp index 96f1936668..b9f2f7506b 100644 --- a/servers/physics_3d/collision_solver_3d_sw.cpp +++ b/servers/physics_3d/godot_collision_solver_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_solver_3d_sw.cpp */ +/* godot_collision_solver_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,17 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "collision_solver_3d_sw.h" -#include "collision_solver_3d_sat.h" -#include "soft_body_3d_sw.h" +#include "godot_collision_solver_3d.h" +#include "godot_collision_solver_3d_sat.h" +#include "godot_soft_body_3d.h" #include "gjk_epa.h" #define collision_solver sat_calculate_penetration //#define collision_solver gjk_epa_calculate_penetration -bool CollisionSolver3DSW::solve_static_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { - const WorldBoundaryShape3DSW *world_boundary = static_cast<const WorldBoundaryShape3DSW *>(p_shape_A); +bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { + const GodotWorldBoundaryShape3D *world_boundary = static_cast<const GodotWorldBoundaryShape3D *>(p_shape_A); if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) { return false; } @@ -47,10 +47,10 @@ bool CollisionSolver3DSW::solve_static_world_boundary(const Shape3DSW *p_shape_A static const int max_supports = 16; Vector3 supports[max_supports]; int support_count; - Shape3DSW::FeatureType support_type; + GodotShape3D::FeatureType support_type; p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count, support_type); - if (support_type == Shape3DSW::FEATURE_CIRCLE) { + if (support_type == GodotShape3D::FEATURE_CIRCLE) { ERR_FAIL_COND_V(support_count != 3, false); Vector3 circle_pos = supports[0]; @@ -89,8 +89,8 @@ bool CollisionSolver3DSW::solve_static_world_boundary(const Shape3DSW *p_shape_A return found; } -bool CollisionSolver3DSW::solve_separation_ray(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin) { - const SeparationRayShape3DSW *ray = static_cast<const SeparationRayShape3DSW *>(p_shape_A); +bool GodotCollisionSolver3D::solve_separation_ray(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin) { + const GodotSeparationRayShape3D *ray = static_cast<const GodotSeparationRayShape3D *>(p_shape_A); Vector3 from = p_transform_A.origin; Vector3 to = from + p_transform_A.basis.get_axis(2) * (ray->get_length() + p_margin); @@ -134,13 +134,13 @@ bool CollisionSolver3DSW::solve_separation_ray(const Shape3DSW *p_shape_A, const struct _SoftBodyContactCollisionInfo { int node_index = 0; - CollisionSolver3DSW::CallbackResult result_callback = nullptr; + GodotCollisionSolver3D::CallbackResult result_callback = nullptr; void *userdata = nullptr; bool swap_result = false; int contact_count = 0; }; -void CollisionSolver3DSW::soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { +void GodotCollisionSolver3D::soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { _SoftBodyContactCollisionInfo &cinfo = *(_SoftBodyContactCollisionInfo *)(p_userdata); ++cinfo.contact_count; @@ -157,9 +157,9 @@ void CollisionSolver3DSW::soft_body_contact_callback(const Vector3 &p_point_A, i } struct _SoftBodyQueryInfo { - SoftBody3DSW *soft_body = nullptr; - const Shape3DSW *shape_A = nullptr; - const Shape3DSW *shape_B = nullptr; + GodotSoftBody3D *soft_body = nullptr; + const GodotShape3D *shape_A = nullptr; + const GodotShape3D *shape_B = nullptr; Transform3D transform_A; Transform3D node_transform; _SoftBodyContactCollisionInfo contact_info; @@ -169,7 +169,7 @@ struct _SoftBodyQueryInfo { #endif }; -bool CollisionSolver3DSW::soft_body_query_callback(uint32_t p_node_index, void *p_userdata) { +bool GodotCollisionSolver3D::soft_body_query_callback(uint32_t p_node_index, void *p_userdata) { _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata); Vector3 node_position = query_cinfo.soft_body->get_node_position(p_node_index); @@ -188,7 +188,7 @@ bool CollisionSolver3DSW::soft_body_query_callback(uint32_t p_node_index, void * return (collided && !query_cinfo.contact_info.result_callback); } -bool CollisionSolver3DSW::soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex) { +bool GodotCollisionSolver3D::soft_body_concave_callback(void *p_userdata, GodotShape3D *p_convex) { _SoftBodyQueryInfo &query_cinfo = *(_SoftBodyQueryInfo *)(p_userdata); query_cinfo.shape_A = p_convex; @@ -220,15 +220,15 @@ bool CollisionSolver3DSW::soft_body_concave_callback(void *p_userdata, Shape3DSW return (collided && !query_cinfo.contact_info.result_callback); } -bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { - const SoftBodyShape3DSW *soft_body_shape_B = static_cast<const SoftBodyShape3DSW *>(p_shape_B); +bool GodotCollisionSolver3D::solve_soft_body(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { + const GodotSoftBodyShape3D *soft_body_shape_B = static_cast<const GodotSoftBodyShape3D *>(p_shape_B); - SoftBody3DSW *soft_body = soft_body_shape_B->get_soft_body(); + GodotSoftBody3D *soft_body = soft_body_shape_B->get_soft_body(); const Transform3D &world_to_local = soft_body->get_inv_transform(); const real_t collision_margin = soft_body->get_collision_margin(); - SphereShape3DSW sphere_shape; + GodotSphereShape3D sphere_shape; sphere_shape.set_data(collision_margin); _SoftBodyQueryInfo query_cinfo; @@ -243,7 +243,7 @@ bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Tran if (p_shape_A->is_concave()) { // In case of concave shape, query convex shapes first. - const ConcaveShape3DSW *concave_shape_A = static_cast<const ConcaveShape3DSW *>(p_shape_A); + const GodotConcaveShape3D *concave_shape_A = static_cast<const GodotConcaveShape3D *>(p_shape_A); AABB soft_body_aabb = soft_body->get_bounds(); soft_body_aabb.grow_by(collision_margin); @@ -277,9 +277,9 @@ bool CollisionSolver3DSW::solve_soft_body(const Shape3DSW *p_shape_A, const Tran struct _ConcaveCollisionInfo { const Transform3D *transform_A; - const Shape3DSW *shape_A; + const GodotShape3D *shape_A; const Transform3D *transform_B; - CollisionSolver3DSW::CallbackResult result_callback; + GodotCollisionSolver3D::CallbackResult result_callback; void *userdata; bool swap_result; bool collided; @@ -291,7 +291,7 @@ struct _ConcaveCollisionInfo { Vector3 close_A, close_B; }; -bool CollisionSolver3DSW::concave_callback(void *p_userdata, Shape3DSW *p_convex) { +bool GodotCollisionSolver3D::concave_callback(void *p_userdata, GodotShape3D *p_convex) { _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata); cinfo.aabb_tests++; @@ -307,8 +307,8 @@ bool CollisionSolver3DSW::concave_callback(void *p_userdata, Shape3DSW *p_convex return !cinfo.result_callback; } -bool CollisionSolver3DSW::solve_concave(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A, real_t p_margin_B) { - const ConcaveShape3DSW *concave_B = static_cast<const ConcaveShape3DSW *>(p_shape_B); +bool GodotCollisionSolver3D::solve_concave(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A, real_t p_margin_B) { + const GodotConcaveShape3D *concave_B = static_cast<const GodotConcaveShape3D *>(p_shape_B); _ConcaveCollisionInfo cinfo; cinfo.transform_A = &p_transform_A; @@ -351,7 +351,7 @@ bool CollisionSolver3DSW::solve_concave(const Shape3DSW *p_shape_A, const Transf return cinfo.collided; } -bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) { +bool GodotCollisionSolver3D::solve_static(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) { PhysicsServer3D::ShapeType type_A = p_shape_A->get_type(); PhysicsServer3D::ShapeType type_B = p_shape_B->get_type(); bool concave_A = p_shape_A->is_concave(); @@ -421,7 +421,7 @@ bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transfo } } -bool CollisionSolver3DSW::concave_distance_callback(void *p_userdata, Shape3DSW *p_convex) { +bool GodotCollisionSolver3D::concave_distance_callback(void *p_userdata, GodotShape3D *p_convex) { _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata); cinfo.aabb_tests++; @@ -443,8 +443,8 @@ bool CollisionSolver3DSW::concave_distance_callback(void *p_userdata, Shape3DSW return false; } -bool CollisionSolver3DSW::solve_distance_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B) { - const WorldBoundaryShape3DSW *world_boundary = static_cast<const WorldBoundaryShape3DSW *>(p_shape_A); +bool GodotCollisionSolver3D::solve_distance_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B) { + const GodotWorldBoundaryShape3D *world_boundary = static_cast<const GodotWorldBoundaryShape3D *>(p_shape_A); if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) { return false; } @@ -453,11 +453,11 @@ bool CollisionSolver3DSW::solve_distance_world_boundary(const Shape3DSW *p_shape static const int max_supports = 16; Vector3 supports[max_supports]; int support_count; - Shape3DSW::FeatureType support_type; + GodotShape3D::FeatureType support_type; p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count, support_type); - if (support_type == Shape3DSW::FEATURE_CIRCLE) { + if (support_type == GodotShape3D::FEATURE_CIRCLE) { ERR_FAIL_COND_V(support_count != 3, false); Vector3 circle_pos = supports[0]; @@ -495,7 +495,7 @@ bool CollisionSolver3DSW::solve_distance_world_boundary(const Shape3DSW *p_shape return collided; } -bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis) { +bool GodotCollisionSolver3D::solve_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis) { if (p_shape_A->is_concave()) { return false; } @@ -512,7 +512,7 @@ bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Trans return false; } - const ConcaveShape3DSW *concave_B = static_cast<const ConcaveShape3DSW *>(p_shape_B); + const GodotConcaveShape3D *concave_B = static_cast<const GodotConcaveShape3D *>(p_shape_B); _ConcaveCollisionInfo cinfo; cinfo.transform_A = &p_transform_A; diff --git a/servers/physics_3d/collision_solver_3d_sw.h b/servers/physics_3d/godot_collision_solver_3d.h index 0a9ea7c0eb..133635ca7e 100644 --- a/servers/physics_3d/collision_solver_3d_sw.h +++ b/servers/physics_3d/godot_collision_solver_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_solver_3d_sw.h */ +/* godot_collision_solver_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,30 +28,30 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COLLISION_SOLVER_SW_H -#define COLLISION_SOLVER_SW_H +#ifndef GODOT_COLLISION_SOLVER_3D_H +#define GODOT_COLLISION_SOLVER_3D_H -#include "shape_3d_sw.h" +#include "godot_shape_3d.h" -class CollisionSolver3DSW { +class GodotCollisionSolver3D { public: typedef void (*CallbackResult)(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); private: static bool soft_body_query_callback(uint32_t p_node_index, void *p_userdata); static void soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); - static bool soft_body_concave_callback(void *p_userdata, Shape3DSW *p_convex); - static bool concave_callback(void *p_userdata, Shape3DSW *p_convex); - static bool solve_static_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); - static bool solve_separation_ray(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0); - static bool solve_soft_body(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); - static bool solve_concave(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0); - static bool concave_distance_callback(void *p_userdata, Shape3DSW *p_convex); - static bool solve_distance_world_boundary(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B); + static bool soft_body_concave_callback(void *p_userdata, GodotShape3D *p_convex); + static bool concave_callback(void *p_userdata, GodotShape3D *p_convex); + static bool solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); + static bool solve_separation_ray(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0); + static bool solve_soft_body(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); + static bool solve_concave(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0); + static bool concave_distance_callback(void *p_userdata, GodotShape3D *p_convex); + static bool solve_distance_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B); public: - static bool solve_static(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0); - static bool solve_distance(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis = nullptr); + static bool solve_static(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0); + static bool solve_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis = nullptr); }; -#endif // COLLISION_SOLVER__SW_H +#endif // GODOT_COLLISION_SOLVER_3D_H diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/godot_collision_solver_3d_sat.cpp index 86150f41a0..0790333f65 100644 --- a/servers/physics_3d/collision_solver_3d_sat.cpp +++ b/servers/physics_3d/godot_collision_solver_3d_sat.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_solver_3d_sat.cpp */ +/* godot_collision_solver_3d_sat.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,12 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "collision_solver_3d_sat.h" -#include "core/math/geometry_3d.h" +#include "godot_collision_solver_3d_sat.h" #include "gjk_epa.h" +#include "core/math/geometry_3d.h" + #define fallback_collision_solver gjk_epa_calculate_penetration // Cylinder SAT analytic methods and face-circle contact points for cylinder-trimesh and cylinder-box collision are based on ODE colliders. @@ -65,7 +66,7 @@ *************************************************************************/ struct _CollectorCallback { - CollisionSolver3DSW::CallbackResult callback; + GodotCollisionSolver3D::CallbackResult callback; void *userdata = nullptr; bool swap = false; bool collided = false; @@ -539,7 +540,7 @@ static void _generate_contacts_circle_circle(const Vector3 *p_points_A, int p_po } } -static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_point_count_A, Shape3DSW::FeatureType p_feature_type_A, const Vector3 *p_points_B, int p_point_count_B, Shape3DSW::FeatureType p_feature_type_B, _CollectorCallback *p_callback) { +static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_point_count_A, GodotShape3D::FeatureType p_feature_type_A, const Vector3 *p_points_B, int p_point_count_B, GodotShape3D::FeatureType p_feature_type_B, _CollectorCallback *p_callback) { #ifdef DEBUG_ENABLED ERR_FAIL_COND(p_point_count_A < 1); ERR_FAIL_COND(p_point_count_B < 1); @@ -713,7 +714,7 @@ public: Vector3 supports_A[max_supports]; int support_count_A; - Shape3DSW::FeatureType support_type_A; + GodotShape3D::FeatureType support_type_A; shape_A->get_supports(transform_A->basis.xform_inv(-best_axis).normalized(), max_supports, supports_A, support_count_A, support_type_A); for (int i = 0; i < support_count_A; i++) { supports_A[i] = transform_A->xform(supports_A[i]); @@ -727,7 +728,7 @@ public: Vector3 supports_B[max_supports]; int support_count_B; - Shape3DSW::FeatureType support_type_B; + GodotShape3D::FeatureType support_type_B; shape_B->get_supports(transform_B->basis.xform_inv(best_axis).normalized(), max_supports, supports_B, support_count_B, support_type_B); for (int i = 0; i < support_count_B; i++) { supports_B[i] = transform_B->xform(supports_B[i]); @@ -761,14 +762,14 @@ public: /****** SAT TESTS *******/ -typedef void (*CollisionFunc)(const Shape3DSW *, const Transform3D &, const Shape3DSW *, const Transform3D &, _CollectorCallback *p_callback, real_t, real_t); +typedef void (*CollisionFunc)(const GodotShape3D *, const Transform3D &, const GodotShape3D *, const Transform3D &, _CollectorCallback *p_callback, real_t, real_t); template <bool withMargin> -static void _collision_sphere_sphere(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a); - const SphereShape3DSW *sphere_B = static_cast<const SphereShape3DSW *>(p_b); +static void _collision_sphere_sphere(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a); + const GodotSphereShape3D *sphere_B = static_cast<const GodotSphereShape3D *>(p_b); - SeparatorAxisTest<SphereShape3DSW, SphereShape3DSW, withMargin> separator(sphere_A, p_transform_a, sphere_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotSphereShape3D, GodotSphereShape3D, withMargin> separator(sphere_A, p_transform_a, sphere_B, p_transform_b, p_collector, p_margin_a, p_margin_b); // previous axis @@ -784,11 +785,11 @@ static void _collision_sphere_sphere(const Shape3DSW *p_a, const Transform3D &p_ } template <bool withMargin> -static void _collision_sphere_box(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a); - const BoxShape3DSW *box_B = static_cast<const BoxShape3DSW *>(p_b); +static void _collision_sphere_box(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a); + const GodotBoxShape3D *box_B = static_cast<const GodotBoxShape3D *>(p_b); - SeparatorAxisTest<SphereShape3DSW, BoxShape3DSW, withMargin> separator(sphere_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotSphereShape3D, GodotBoxShape3D, withMargin> separator(sphere_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -835,11 +836,11 @@ static void _collision_sphere_box(const Shape3DSW *p_a, const Transform3D &p_tra } template <bool withMargin> -static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a); - const CapsuleShape3DSW *capsule_B = static_cast<const CapsuleShape3DSW *>(p_b); +static void _collision_sphere_capsule(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a); + const GodotCapsuleShape3D *capsule_B = static_cast<const GodotCapsuleShape3D *>(p_b); - SeparatorAxisTest<SphereShape3DSW, CapsuleShape3DSW, withMargin> separator(sphere_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotSphereShape3D, GodotCapsuleShape3D, withMargin> separator(sphere_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -877,11 +878,11 @@ static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform3D &p } template <bool withMargin> -static void _collision_sphere_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a); - const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b); +static void _collision_sphere_cylinder(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a); + const GodotCylinderShape3D *cylinder_B = static_cast<const GodotCylinderShape3D *>(p_b); - SeparatorAxisTest<SphereShape3DSW, CylinderShape3DSW, withMargin> separator(sphere_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotSphereShape3D, GodotCylinderShape3D, withMargin> separator(sphere_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -936,11 +937,11 @@ static void _collision_sphere_cylinder(const Shape3DSW *p_a, const Transform3D & } template <bool withMargin> -static void _collision_sphere_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a); - const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b); +static void _collision_sphere_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a); + const GodotConvexPolygonShape3D *convex_polygon_B = static_cast<const GodotConvexPolygonShape3D *>(p_b); - SeparatorAxisTest<SphereShape3DSW, ConvexPolygonShape3DSW, withMargin> separator(sphere_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotSphereShape3D, GodotConvexPolygonShape3D, withMargin> separator(sphere_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -999,11 +1000,11 @@ static void _collision_sphere_convex_polygon(const Shape3DSW *p_a, const Transfo } template <bool withMargin> -static void _collision_sphere_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const SphereShape3DSW *sphere_A = static_cast<const SphereShape3DSW *>(p_a); - const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b); +static void _collision_sphere_face(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotSphereShape3D *sphere_A = static_cast<const GodotSphereShape3D *>(p_a); + const GodotFaceShape3D *face_B = static_cast<const GodotFaceShape3D *>(p_b); - SeparatorAxisTest<SphereShape3DSW, FaceShape3DSW, withMargin> separator(sphere_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotSphereShape3D, GodotFaceShape3D, withMargin> separator(sphere_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); Vector3 vertex[3] = { p_transform_b.xform(face_B->vertex[0]), @@ -1044,11 +1045,11 @@ static void _collision_sphere_face(const Shape3DSW *p_a, const Transform3D &p_tr } template <bool withMargin> -static void _collision_box_box(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a); - const BoxShape3DSW *box_B = static_cast<const BoxShape3DSW *>(p_b); +static void _collision_box_box(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotBoxShape3D *box_A = static_cast<const GodotBoxShape3D *>(p_a); + const GodotBoxShape3D *box_B = static_cast<const GodotBoxShape3D *>(p_b); - SeparatorAxisTest<BoxShape3DSW, BoxShape3DSW, withMargin> separator(box_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotBoxShape3D, GodotBoxShape3D, withMargin> separator(box_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -1142,11 +1143,11 @@ static void _collision_box_box(const Shape3DSW *p_a, const Transform3D &p_transf } template <bool withMargin> -static void _collision_box_capsule(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a); - const CapsuleShape3DSW *capsule_B = static_cast<const CapsuleShape3DSW *>(p_b); +static void _collision_box_capsule(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotBoxShape3D *box_A = static_cast<const GodotBoxShape3D *>(p_a); + const GodotCapsuleShape3D *capsule_B = static_cast<const GodotCapsuleShape3D *>(p_b); - SeparatorAxisTest<BoxShape3DSW, CapsuleShape3DSW, withMargin> separator(box_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotBoxShape3D, GodotCapsuleShape3D, withMargin> separator(box_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -1240,11 +1241,11 @@ static void _collision_box_capsule(const Shape3DSW *p_a, const Transform3D &p_tr } template <bool withMargin> -static void _collision_box_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a); - const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b); +static void _collision_box_cylinder(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotBoxShape3D *box_A = static_cast<const GodotBoxShape3D *>(p_a); + const GodotCylinderShape3D *cylinder_B = static_cast<const GodotCylinderShape3D *>(p_b); - SeparatorAxisTest<BoxShape3DSW, CylinderShape3DSW, withMargin> separator(box_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotBoxShape3D, GodotCylinderShape3D, withMargin> separator(box_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -1353,11 +1354,11 @@ static void _collision_box_cylinder(const Shape3DSW *p_a, const Transform3D &p_t } template <bool withMargin> -static void _collision_box_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a); - const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b); +static void _collision_box_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotBoxShape3D *box_A = static_cast<const GodotBoxShape3D *>(p_a); + const GodotConvexPolygonShape3D *convex_polygon_B = static_cast<const GodotConvexPolygonShape3D *>(p_b); - SeparatorAxisTest<BoxShape3DSW, ConvexPolygonShape3DSW, withMargin> separator(box_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotBoxShape3D, GodotConvexPolygonShape3D, withMargin> separator(box_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -1471,11 +1472,11 @@ static void _collision_box_convex_polygon(const Shape3DSW *p_a, const Transform3 } template <bool withMargin> -static void _collision_box_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const BoxShape3DSW *box_A = static_cast<const BoxShape3DSW *>(p_a); - const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b); +static void _collision_box_face(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotBoxShape3D *box_A = static_cast<const GodotBoxShape3D *>(p_a); + const GodotFaceShape3D *face_B = static_cast<const GodotFaceShape3D *>(p_b); - SeparatorAxisTest<BoxShape3DSW, FaceShape3DSW, withMargin> separator(box_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotBoxShape3D, GodotFaceShape3D, withMargin> separator(box_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); Vector3 vertex[3] = { p_transform_b.xform(face_B->vertex[0]), @@ -1594,11 +1595,11 @@ static void _collision_box_face(const Shape3DSW *p_a, const Transform3D &p_trans } template <bool withMargin> -static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a); - const CapsuleShape3DSW *capsule_B = static_cast<const CapsuleShape3DSW *>(p_b); +static void _collision_capsule_capsule(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotCapsuleShape3D *capsule_A = static_cast<const GodotCapsuleShape3D *>(p_a); + const GodotCapsuleShape3D *capsule_B = static_cast<const GodotCapsuleShape3D *>(p_b); - SeparatorAxisTest<CapsuleShape3DSW, CapsuleShape3DSW, withMargin> separator(capsule_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotCapsuleShape3D, GodotCapsuleShape3D, withMargin> separator(capsule_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -1658,11 +1659,11 @@ static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform3D & } template <bool withMargin> -static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a); - const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b); +static void _collision_capsule_cylinder(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotCapsuleShape3D *capsule_A = static_cast<const GodotCapsuleShape3D *>(p_a); + const GodotCylinderShape3D *cylinder_B = static_cast<const GodotCylinderShape3D *>(p_b); - SeparatorAxisTest<CapsuleShape3DSW, CylinderShape3DSW, withMargin> separator(capsule_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotCapsuleShape3D, GodotCylinderShape3D, withMargin> separator(capsule_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -1709,7 +1710,7 @@ static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform3D return; } - CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CapsuleShape3DSW, CylinderShape3DSW, withMargin>::test_contact_points; + GodotCollisionSolver3D::CallbackResult callback = SeparatorAxisTest<GodotCapsuleShape3D, GodotCylinderShape3D, withMargin>::test_contact_points; // Fallback to generic algorithm to find the best separating axis. if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) { @@ -1720,11 +1721,11 @@ static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform3D } template <bool withMargin> -static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a); - const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b); +static void _collision_capsule_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotCapsuleShape3D *capsule_A = static_cast<const GodotCapsuleShape3D *>(p_a); + const GodotConvexPolygonShape3D *convex_polygon_B = static_cast<const GodotConvexPolygonShape3D *>(p_b); - SeparatorAxisTest<CapsuleShape3DSW, ConvexPolygonShape3DSW, withMargin> separator(capsule_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotCapsuleShape3D, GodotConvexPolygonShape3D, withMargin> separator(capsule_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -1787,11 +1788,11 @@ static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transf } template <bool withMargin> -static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const CapsuleShape3DSW *capsule_A = static_cast<const CapsuleShape3DSW *>(p_a); - const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b); +static void _collision_capsule_face(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotCapsuleShape3D *capsule_A = static_cast<const GodotCapsuleShape3D *>(p_a); + const GodotFaceShape3D *face_B = static_cast<const GodotFaceShape3D *>(p_b); - SeparatorAxisTest<CapsuleShape3DSW, FaceShape3DSW, withMargin> separator(capsule_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotCapsuleShape3D, GodotFaceShape3D, withMargin> separator(capsule_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); Vector3 vertex[3] = { p_transform_b.xform(face_B->vertex[0]), @@ -1861,11 +1862,11 @@ static void _collision_capsule_face(const Shape3DSW *p_a, const Transform3D &p_t } template <bool withMargin> -static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a); - const CylinderShape3DSW *cylinder_B = static_cast<const CylinderShape3DSW *>(p_b); +static void _collision_cylinder_cylinder(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotCylinderShape3D *cylinder_A = static_cast<const GodotCylinderShape3D *>(p_a); + const GodotCylinderShape3D *cylinder_B = static_cast<const GodotCylinderShape3D *>(p_b); - SeparatorAxisTest<CylinderShape3DSW, CylinderShape3DSW, withMargin> separator(cylinder_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotCylinderShape3D, GodotCylinderShape3D, withMargin> separator(cylinder_A, p_transform_a, cylinder_B, p_transform_b, p_collector, p_margin_a, p_margin_b); Vector3 cylinder_A_axis = p_transform_a.basis.get_axis(1); Vector3 cylinder_B_axis = p_transform_b.basis.get_axis(1); @@ -1904,7 +1905,7 @@ static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform3D return; } - CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CylinderShape3DSW, CylinderShape3DSW, withMargin>::test_contact_points; + GodotCollisionSolver3D::CallbackResult callback = SeparatorAxisTest<GodotCylinderShape3D, GodotCylinderShape3D, withMargin>::test_contact_points; // Fallback to generic algorithm to find the best separating axis. if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) { @@ -1915,13 +1916,13 @@ static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform3D } template <bool withMargin> -static void _collision_cylinder_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a); - const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b); +static void _collision_cylinder_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotCylinderShape3D *cylinder_A = static_cast<const GodotCylinderShape3D *>(p_a); + const GodotConvexPolygonShape3D *convex_polygon_B = static_cast<const GodotConvexPolygonShape3D *>(p_b); - SeparatorAxisTest<CylinderShape3DSW, ConvexPolygonShape3DSW, withMargin> separator(cylinder_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotCylinderShape3D, GodotConvexPolygonShape3D, withMargin> separator(cylinder_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - CollisionSolver3DSW::CallbackResult callback = SeparatorAxisTest<CylinderShape3DSW, ConvexPolygonShape3DSW, withMargin>::test_contact_points; + GodotCollisionSolver3D::CallbackResult callback = SeparatorAxisTest<GodotCylinderShape3D, GodotConvexPolygonShape3D, withMargin>::test_contact_points; // Fallback to generic algorithm to find the best separating axis. if (!fallback_collision_solver(p_a, p_transform_a, p_b, p_transform_b, callback, &separator, false, p_margin_a, p_margin_b)) { @@ -1932,11 +1933,11 @@ static void _collision_cylinder_convex_polygon(const Shape3DSW *p_a, const Trans } template <bool withMargin> -static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const CylinderShape3DSW *cylinder_A = static_cast<const CylinderShape3DSW *>(p_a); - const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b); +static void _collision_cylinder_face(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotCylinderShape3D *cylinder_A = static_cast<const GodotCylinderShape3D *>(p_a); + const GodotFaceShape3D *face_B = static_cast<const GodotFaceShape3D *>(p_b); - SeparatorAxisTest<CylinderShape3DSW, FaceShape3DSW, withMargin> separator(cylinder_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotCylinderShape3D, GodotFaceShape3D, withMargin> separator(cylinder_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -2037,11 +2038,11 @@ static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform3D &p_ } template <bool withMargin> -static void _collision_convex_polygon_convex_polygon(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const ConvexPolygonShape3DSW *convex_polygon_A = static_cast<const ConvexPolygonShape3DSW *>(p_a); - const ConvexPolygonShape3DSW *convex_polygon_B = static_cast<const ConvexPolygonShape3DSW *>(p_b); +static void _collision_convex_polygon_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotConvexPolygonShape3D *convex_polygon_A = static_cast<const GodotConvexPolygonShape3D *>(p_a); + const GodotConvexPolygonShape3D *convex_polygon_B = static_cast<const GodotConvexPolygonShape3D *>(p_b); - SeparatorAxisTest<ConvexPolygonShape3DSW, ConvexPolygonShape3DSW, withMargin> separator(convex_polygon_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotConvexPolygonShape3D, GodotConvexPolygonShape3D, withMargin> separator(convex_polygon_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); if (!separator.test_previous_axis()) { return; @@ -2150,11 +2151,11 @@ static void _collision_convex_polygon_convex_polygon(const Shape3DSW *p_a, const } template <bool withMargin> -static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform3D &p_transform_a, const Shape3DSW *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - const ConvexPolygonShape3DSW *convex_polygon_A = static_cast<const ConvexPolygonShape3DSW *>(p_a); - const FaceShape3DSW *face_B = static_cast<const FaceShape3DSW *>(p_b); +static void _collision_convex_polygon_face(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + const GodotConvexPolygonShape3D *convex_polygon_A = static_cast<const GodotConvexPolygonShape3D *>(p_a); + const GodotFaceShape3D *face_B = static_cast<const GodotFaceShape3D *>(p_b); - SeparatorAxisTest<ConvexPolygonShape3DSW, FaceShape3DSW, withMargin> separator(convex_polygon_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + SeparatorAxisTest<GodotConvexPolygonShape3D, GodotFaceShape3D, withMargin> separator(convex_polygon_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); const Geometry3D::MeshData &mesh = convex_polygon_A->get_mesh(); @@ -2268,7 +2269,7 @@ static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform separator.generate_contacts(); } -bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector3 *r_prev_axis, real_t p_margin_a, real_t p_margin_b) { +bool sat_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector3 *r_prev_axis, real_t p_margin_a, real_t p_margin_b) { PhysicsServer3D::ShapeType type_A = p_shape_A->get_type(); ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_WORLD_BOUNDARY, false); @@ -2366,8 +2367,8 @@ bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_ callback.collided = false; callback.prev_axis = r_prev_axis; - const Shape3DSW *A = p_shape_A; - const Shape3DSW *B = p_shape_B; + const GodotShape3D *A = p_shape_A; + const GodotShape3D *B = p_shape_B; const Transform3D *transform_A = &p_transform_A; const Transform3D *transform_B = &p_transform_B; real_t margin_A = p_margin_a; diff --git a/servers/physics_3d/collision_solver_3d_sat.h b/servers/physics_3d/godot_collision_solver_3d_sat.h index e50da7b101..069a701cba 100644 --- a/servers/physics_3d/collision_solver_3d_sat.h +++ b/servers/physics_3d/godot_collision_solver_3d_sat.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* collision_solver_3d_sat.h */ +/* godot_collision_solver_3d_sat.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef COLLISION_SOLVER_SAT_H -#define COLLISION_SOLVER_SAT_H +#ifndef GODOT_COLLISION_SOLVER_SAT_H +#define GODOT_COLLISION_SOLVER_SAT_H -#include "collision_solver_3d_sw.h" +#include "godot_collision_solver_3d.h" -bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform3D &p_transform_A, const Shape3DSW *p_shape_B, const Transform3D &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = nullptr, real_t p_margin_a = 0, real_t p_margin_b = 0); +bool sat_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = nullptr, real_t p_margin_a = 0, real_t p_margin_b = 0); -#endif // COLLISION_SOLVER_SAT_H +#endif // GODOT_COLLISION_SOLVER_SAT_H diff --git a/servers/physics_3d/constraint_3d_sw.h b/servers/physics_3d/godot_constraint_3d.h index 7b44726ef5..840c81716c 100644 --- a/servers/physics_3d/constraint_3d_sw.h +++ b/servers/physics_3d/godot_constraint_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* constraint_3d_sw.h */ +/* godot_constraint_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,14 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CONSTRAINT_SW_H -#define CONSTRAINT_SW_H +#ifndef GODOT_CONSTRAINT_3D_H +#define GODOT_CONSTRAINT_3D_H -class Body3DSW; -class SoftBody3DSW; +class GodotBody3D; +class GodotSoftBody3D; -class Constraint3DSW { - Body3DSW **_body_ptr; +class GodotConstraint3D { + GodotBody3D **_body_ptr; int _body_count; uint64_t island_step; int priority; @@ -44,7 +44,7 @@ class Constraint3DSW { RID self; protected: - Constraint3DSW(Body3DSW **p_body_ptr = nullptr, int p_body_count = 0) { + GodotConstraint3D(GodotBody3D **p_body_ptr = nullptr, int p_body_count = 0) { _body_ptr = p_body_ptr; _body_count = p_body_count; island_step = 0; @@ -59,10 +59,10 @@ public: _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } - _FORCE_INLINE_ Body3DSW **get_body_ptr() const { return _body_ptr; } + _FORCE_INLINE_ GodotBody3D **get_body_ptr() const { return _body_ptr; } _FORCE_INLINE_ int get_body_count() const { return _body_count; } - virtual SoftBody3DSW *get_soft_body_ptr(int p_index) const { return nullptr; } + virtual GodotSoftBody3D *get_soft_body_ptr(int p_index) const { return nullptr; } virtual int get_soft_body_count() const { return 0; } _FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; } @@ -75,7 +75,7 @@ public: virtual bool pre_solve(real_t p_step) = 0; virtual void solve(real_t p_step) = 0; - virtual ~Constraint3DSW() {} + virtual ~GodotConstraint3D() {} }; -#endif // CONSTRAINT__SW_H +#endif // GODOT_CONSTRAINT_3D_H diff --git a/servers/physics_3d/joints_3d_sw.h b/servers/physics_3d/godot_joint_3d.h index e2514674ea..4086bb53e1 100644 --- a/servers/physics_3d/joints_3d_sw.h +++ b/servers/physics_3d/godot_joint_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* joints_3d_sw.h */ +/* godot_joint_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef JOINTS_SW_H -#define JOINTS_SW_H +#ifndef GODOT_JOINT_3D_H +#define GODOT_JOINT_3D_H -#include "body_3d_sw.h" -#include "constraint_3d_sw.h" +#include "godot_body_3d.h" +#include "godot_constraint_3d.h" -class Joint3DSW : public Constraint3DSW { +class GodotJoint3D : public GodotConstraint3D { protected: bool dynamic_A = false; bool dynamic_B = false; @@ -44,20 +44,20 @@ public: virtual bool pre_solve(real_t p_step) override { return true; } virtual void solve(real_t p_step) override {} - void copy_settings_from(Joint3DSW *p_joint) { + void copy_settings_from(GodotJoint3D *p_joint) { set_self(p_joint->get_self()); set_priority(p_joint->get_priority()); disable_collisions_between_bodies(p_joint->is_disabled_collisions_between_bodies()); } virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_TYPE_MAX; } - _FORCE_INLINE_ Joint3DSW(Body3DSW **p_body_ptr = nullptr, int p_body_count = 0) : - Constraint3DSW(p_body_ptr, p_body_count) { + _FORCE_INLINE_ GodotJoint3D(GodotBody3D **p_body_ptr = nullptr, int p_body_count = 0) : + GodotConstraint3D(p_body_ptr, p_body_count) { } - virtual ~Joint3DSW() { + virtual ~GodotJoint3D() { for (int i = 0; i < get_body_count(); i++) { - Body3DSW *body = get_body_ptr()[i]; + GodotBody3D *body = get_body_ptr()[i]; if (body) { body->remove_constraint(this); } @@ -65,4 +65,4 @@ public: } }; -#endif // JOINTS_SW_H +#endif // GODOT_JOINT_3D_H diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp new file mode 100644 index 0000000000..79a2e0b0ea --- /dev/null +++ b/servers/physics_3d/godot_physics_server_3d.cpp @@ -0,0 +1,1747 @@ +/*************************************************************************/ +/* godot_physics_server_3d.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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 "godot_physics_server_3d.h" + +#include "godot_body_direct_state_3d.h" +#include "godot_broad_phase_3d_bvh.h" +#include "joints/godot_cone_twist_joint_3d.h" +#include "joints/godot_generic_6dof_joint_3d.h" +#include "joints/godot_hinge_joint_3d.h" +#include "joints/godot_pin_joint_3d.h" +#include "joints/godot_slider_joint_3d.h" + +#include "core/debugger/engine_debugger.h" +#include "core/os/os.h" + +#define FLUSH_QUERY_CHECK(m_object) \ + ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead."); + +RID GodotPhysicsServer3D::world_boundary_shape_create() { + GodotShape3D *shape = memnew(GodotWorldBoundaryShape3D); + RID rid = shape_owner.make_rid(shape); + shape->set_self(rid); + return rid; +} +RID GodotPhysicsServer3D::separation_ray_shape_create() { + GodotShape3D *shape = memnew(GodotSeparationRayShape3D); + RID rid = shape_owner.make_rid(shape); + shape->set_self(rid); + return rid; +} +RID GodotPhysicsServer3D::sphere_shape_create() { + GodotShape3D *shape = memnew(GodotSphereShape3D); + RID rid = shape_owner.make_rid(shape); + shape->set_self(rid); + return rid; +} +RID GodotPhysicsServer3D::box_shape_create() { + GodotShape3D *shape = memnew(GodotBoxShape3D); + RID rid = shape_owner.make_rid(shape); + shape->set_self(rid); + return rid; +} +RID GodotPhysicsServer3D::capsule_shape_create() { + GodotShape3D *shape = memnew(GodotCapsuleShape3D); + RID rid = shape_owner.make_rid(shape); + shape->set_self(rid); + return rid; +} +RID GodotPhysicsServer3D::cylinder_shape_create() { + GodotShape3D *shape = memnew(GodotCylinderShape3D); + RID rid = shape_owner.make_rid(shape); + shape->set_self(rid); + return rid; +} +RID GodotPhysicsServer3D::convex_polygon_shape_create() { + GodotShape3D *shape = memnew(GodotConvexPolygonShape3D); + RID rid = shape_owner.make_rid(shape); + shape->set_self(rid); + return rid; +} +RID GodotPhysicsServer3D::concave_polygon_shape_create() { + GodotShape3D *shape = memnew(GodotConcavePolygonShape3D); + RID rid = shape_owner.make_rid(shape); + shape->set_self(rid); + return rid; +} +RID GodotPhysicsServer3D::heightmap_shape_create() { + GodotShape3D *shape = memnew(GodotHeightMapShape3D); + RID rid = shape_owner.make_rid(shape); + shape->set_self(rid); + return rid; +} +RID GodotPhysicsServer3D::custom_shape_create() { + ERR_FAIL_V(RID()); +} + +void GodotPhysicsServer3D::shape_set_data(RID p_shape, const Variant &p_data) { + GodotShape3D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + shape->set_data(p_data); +}; + +void GodotPhysicsServer3D::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { + GodotShape3D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + shape->set_custom_bias(p_bias); +} + +PhysicsServer3D::ShapeType GodotPhysicsServer3D::shape_get_type(RID p_shape) const { + const GodotShape3D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM); + return shape->get_type(); +}; + +Variant GodotPhysicsServer3D::shape_get_data(RID p_shape) const { + const GodotShape3D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND_V(!shape, Variant()); + ERR_FAIL_COND_V(!shape->is_configured(), Variant()); + return shape->get_data(); +}; + +void GodotPhysicsServer3D::shape_set_margin(RID p_shape, real_t p_margin) { +} + +real_t GodotPhysicsServer3D::shape_get_margin(RID p_shape) const { + return 0.0; +} + +real_t GodotPhysicsServer3D::shape_get_custom_solver_bias(RID p_shape) const { + const GodotShape3D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND_V(!shape, 0); + return shape->get_custom_bias(); +} + +RID GodotPhysicsServer3D::space_create() { + GodotSpace3D *space = memnew(GodotSpace3D); + RID id = space_owner.make_rid(space); + space->set_self(id); + RID area_id = area_create(); + GodotArea3D *area = area_owner.get_or_null(area_id); + ERR_FAIL_COND_V(!area, RID()); + space->set_default_area(area); + area->set_space(space); + area->set_priority(-1); + RID sgb = body_create(); + body_set_space(sgb, id); + body_set_mode(sgb, BODY_MODE_STATIC); + space->set_static_global_body(sgb); + + return id; +}; + +void GodotPhysicsServer3D::space_set_active(RID p_space, bool p_active) { + GodotSpace3D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND(!space); + if (p_active) { + active_spaces.insert(space); + } else { + active_spaces.erase(space); + } +} + +bool GodotPhysicsServer3D::space_is_active(RID p_space) const { + const GodotSpace3D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND_V(!space, false); + + return active_spaces.has(space); +} + +void GodotPhysicsServer3D::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { + GodotSpace3D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND(!space); + + space->set_param(p_param, p_value); +} + +real_t GodotPhysicsServer3D::space_get_param(RID p_space, SpaceParameter p_param) const { + const GodotSpace3D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND_V(!space, 0); + return space->get_param(p_param); +} + +PhysicsDirectSpaceState3D *GodotPhysicsServer3D::space_get_direct_state(RID p_space) { + GodotSpace3D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND_V(!space, nullptr); + ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification."); + + return space->get_direct_state(); +} + +void GodotPhysicsServer3D::space_set_debug_contacts(RID p_space, int p_max_contacts) { + GodotSpace3D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND(!space); + space->set_debug_contacts(p_max_contacts); +} + +Vector<Vector3> GodotPhysicsServer3D::space_get_contacts(RID p_space) const { + GodotSpace3D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND_V(!space, Vector<Vector3>()); + return space->get_debug_contacts(); +} + +int GodotPhysicsServer3D::space_get_contact_count(RID p_space) const { + GodotSpace3D *space = space_owner.get_or_null(p_space); + ERR_FAIL_COND_V(!space, 0); + return space->get_debug_contact_count(); +} + +RID GodotPhysicsServer3D::area_create() { + GodotArea3D *area = memnew(GodotArea3D); + RID rid = area_owner.make_rid(area); + area->set_self(rid); + return rid; +}; + +void GodotPhysicsServer3D::area_set_space(RID p_area, RID p_space) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + GodotSpace3D *space = nullptr; + if (p_space.is_valid()) { + space = space_owner.get_or_null(p_space); + ERR_FAIL_COND(!space); + } + + if (area->get_space() == space) { + return; //pointless + } + + area->clear_constraints(); + area->set_space(space); +}; + +RID GodotPhysicsServer3D::area_get_space(RID p_area) const { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, RID()); + + GodotSpace3D *space = area->get_space(); + if (!space) { + return RID(); + } + return space->get_self(); +}; + +void GodotPhysicsServer3D::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_space_override_mode(p_mode); +} + +PhysicsServer3D::AreaSpaceOverrideMode GodotPhysicsServer3D::area_get_space_override_mode(RID p_area) const { + const GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); + + return area->get_space_override_mode(); +} + +void GodotPhysicsServer3D::area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform, bool p_disabled) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + GodotShape3D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + + area->add_shape(shape, p_transform, p_disabled); +} + +void GodotPhysicsServer3D::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + GodotShape3D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + ERR_FAIL_COND(!shape->is_configured()); + + area->set_shape(p_shape_idx, shape); +} + +void GodotPhysicsServer3D::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_shape_transform(p_shape_idx, p_transform); +} + +int GodotPhysicsServer3D::area_get_shape_count(RID p_area) const { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, -1); + + return area->get_shape_count(); +} + +RID GodotPhysicsServer3D::area_get_shape(RID p_area, int p_shape_idx) const { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, RID()); + + GodotShape3D *shape = area->get_shape(p_shape_idx); + ERR_FAIL_COND_V(!shape, RID()); + + return shape->get_self(); +} + +Transform3D GodotPhysicsServer3D::area_get_shape_transform(RID p_area, int p_shape_idx) const { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, Transform3D()); + + return area->get_shape_transform(p_shape_idx); +} + +void GodotPhysicsServer3D::area_remove_shape(RID p_area, int p_shape_idx) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->remove_shape(p_shape_idx); +} + +void GodotPhysicsServer3D::area_clear_shapes(RID p_area) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + while (area->get_shape_count()) { + area->remove_shape(0); + } +} + +void GodotPhysicsServer3D::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count()); + FLUSH_QUERY_CHECK(area); + area->set_shape_disabled(p_shape_idx, p_disabled); +} + +void GodotPhysicsServer3D::area_attach_object_instance_id(RID p_area, ObjectID p_id) { + if (space_owner.owns(p_area)) { + GodotSpace3D *space = space_owner.get_or_null(p_area); + p_area = space->get_default_area()->get_self(); + } + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + area->set_instance_id(p_id); +} + +ObjectID GodotPhysicsServer3D::area_get_object_instance_id(RID p_area) const { + if (space_owner.owns(p_area)) { + GodotSpace3D *space = space_owner.get_or_null(p_area); + p_area = space->get_default_area()->get_self(); + } + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, ObjectID()); + return area->get_instance_id(); +} + +void GodotPhysicsServer3D::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { + if (space_owner.owns(p_area)) { + GodotSpace3D *space = space_owner.get_or_null(p_area); + p_area = space->get_default_area()->get_self(); + } + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + area->set_param(p_param, p_value); +}; + +void GodotPhysicsServer3D::area_set_transform(RID p_area, const Transform3D &p_transform) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + area->set_transform(p_transform); +}; + +Variant GodotPhysicsServer3D::area_get_param(RID p_area, AreaParameter p_param) const { + if (space_owner.owns(p_area)) { + GodotSpace3D *space = space_owner.get_or_null(p_area); + p_area = space->get_default_area()->get_self(); + } + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, Variant()); + + return area->get_param(p_param); +}; + +Transform3D GodotPhysicsServer3D::area_get_transform(RID p_area) const { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND_V(!area, Transform3D()); + + return area->get_transform(); +}; + +void GodotPhysicsServer3D::area_set_collision_layer(RID p_area, uint32_t p_layer) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_collision_layer(p_layer); +} + +void GodotPhysicsServer3D::area_set_collision_mask(RID p_area, uint32_t p_mask) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_collision_mask(p_mask); +} + +void GodotPhysicsServer3D::area_set_monitorable(RID p_area, bool p_monitorable) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + FLUSH_QUERY_CHECK(area); + + area->set_monitorable(p_monitorable); +} + +void GodotPhysicsServer3D::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); +} + +void GodotPhysicsServer3D::area_set_ray_pickable(RID p_area, bool p_enable) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_ray_pickable(p_enable); +} + +void GodotPhysicsServer3D::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { + GodotArea3D *area = area_owner.get_or_null(p_area); + ERR_FAIL_COND(!area); + + area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); +} + +/* BODY API */ + +RID GodotPhysicsServer3D::body_create() { + GodotBody3D *body = memnew(GodotBody3D); + RID rid = body_owner.make_rid(body); + body->set_self(rid); + return rid; +}; + +void GodotPhysicsServer3D::body_set_space(RID p_body, RID p_space) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + GodotSpace3D *space = nullptr; + if (p_space.is_valid()) { + space = space_owner.get_or_null(p_space); + ERR_FAIL_COND(!space); + } + + if (body->get_space() == space) { + return; //pointless + } + + body->clear_constraint_map(); + body->set_space(space); +}; + +RID GodotPhysicsServer3D::body_get_space(RID p_body) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, RID()); + + GodotSpace3D *space = body->get_space(); + if (!space) { + return RID(); + } + return space->get_self(); +}; + +void GodotPhysicsServer3D::body_set_mode(RID p_body, BodyMode p_mode) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_mode(p_mode); +}; + +PhysicsServer3D::BodyMode GodotPhysicsServer3D::body_get_mode(RID p_body) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, BODY_MODE_STATIC); + + return body->get_mode(); +}; + +void GodotPhysicsServer3D::body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform, bool p_disabled) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + GodotShape3D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + + body->add_shape(shape, p_transform, p_disabled); +} + +void GodotPhysicsServer3D::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + GodotShape3D *shape = shape_owner.get_or_null(p_shape); + ERR_FAIL_COND(!shape); + ERR_FAIL_COND(!shape->is_configured()); + + body->set_shape(p_shape_idx, shape); +} +void GodotPhysicsServer3D::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_shape_transform(p_shape_idx, p_transform); +} + +int GodotPhysicsServer3D::body_get_shape_count(RID p_body) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, -1); + + return body->get_shape_count(); +} + +RID GodotPhysicsServer3D::body_get_shape(RID p_body, int p_shape_idx) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, RID()); + + GodotShape3D *shape = body->get_shape(p_shape_idx); + ERR_FAIL_COND_V(!shape, RID()); + + return shape->get_self(); +} + +void GodotPhysicsServer3D::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); + FLUSH_QUERY_CHECK(body); + + body->set_shape_disabled(p_shape_idx, p_disabled); +} + +Transform3D GodotPhysicsServer3D::body_get_shape_transform(RID p_body, int p_shape_idx) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, Transform3D()); + + return body->get_shape_transform(p_shape_idx); +} + +void GodotPhysicsServer3D::body_remove_shape(RID p_body, int p_shape_idx) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->remove_shape(p_shape_idx); +} + +void GodotPhysicsServer3D::body_clear_shapes(RID p_body) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + while (body->get_shape_count()) { + body->remove_shape(0); + } +} + +void GodotPhysicsServer3D::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_continuous_collision_detection(p_enable); +} + +bool GodotPhysicsServer3D::body_is_continuous_collision_detection_enabled(RID p_body) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, false); + + return body->is_continuous_collision_detection_enabled(); +} + +void GodotPhysicsServer3D::body_set_collision_layer(RID p_body, uint32_t p_layer) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_collision_layer(p_layer); +} + +uint32_t GodotPhysicsServer3D::body_get_collision_layer(RID p_body) const { + const GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_layer(); +} + +void GodotPhysicsServer3D::body_set_collision_mask(RID p_body, uint32_t p_mask) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_collision_mask(p_mask); +} + +uint32_t GodotPhysicsServer3D::body_get_collision_mask(RID p_body) const { + const GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_mask(); +} + +void GodotPhysicsServer3D::body_attach_object_instance_id(RID p_body, ObjectID p_id) { + GodotBody3D *body = body_owner.get_or_null(p_body); + if (body) { + body->set_instance_id(p_id); + return; + } + + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + if (soft_body) { + soft_body->set_instance_id(p_id); + return; + } + + ERR_FAIL_MSG("Invalid ID."); +}; + +ObjectID GodotPhysicsServer3D::body_get_object_instance_id(RID p_body) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, ObjectID()); + + return body->get_instance_id(); +}; + +void GodotPhysicsServer3D::body_set_user_flags(RID p_body, uint32_t p_flags) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); +}; + +uint32_t GodotPhysicsServer3D::body_get_user_flags(RID p_body) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + + return 0; +}; + +void GodotPhysicsServer3D::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_param(p_param, p_value); +}; + +Variant GodotPhysicsServer3D::body_get_param(RID p_body, BodyParameter p_param) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_param(p_param); +}; + +void GodotPhysicsServer3D::body_reset_mass_properties(RID p_body) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + return body->reset_mass_properties(); +} + +void GodotPhysicsServer3D::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_state(p_state, p_variant); +}; + +Variant GodotPhysicsServer3D::body_get_state(RID p_body, BodyState p_state) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, Variant()); + + return body->get_state(p_state); +}; + +void GodotPhysicsServer3D::body_set_applied_force(RID p_body, const Vector3 &p_force) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_applied_force(p_force); + body->wakeup(); +}; + +Vector3 GodotPhysicsServer3D::body_get_applied_force(RID p_body) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, Vector3()); + return body->get_applied_force(); +}; + +void GodotPhysicsServer3D::body_set_applied_torque(RID p_body, const Vector3 &p_torque) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_applied_torque(p_torque); + body->wakeup(); +}; + +Vector3 GodotPhysicsServer3D::body_get_applied_torque(RID p_body) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, Vector3()); + + return body->get_applied_torque(); +}; + +void GodotPhysicsServer3D::body_add_central_force(RID p_body, const Vector3 &p_force) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->add_central_force(p_force); + body->wakeup(); +} + +void GodotPhysicsServer3D::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->add_force(p_force, p_position); + body->wakeup(); +}; + +void GodotPhysicsServer3D::body_add_torque(RID p_body, const Vector3 &p_torque) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->add_torque(p_torque); + body->wakeup(); +}; + +void GodotPhysicsServer3D::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + body->apply_central_impulse(p_impulse); + body->wakeup(); +} + +void GodotPhysicsServer3D::body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + body->apply_impulse(p_impulse, p_position); + body->wakeup(); +}; + +void GodotPhysicsServer3D::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + body->apply_torque_impulse(p_impulse); + body->wakeup(); +}; + +void GodotPhysicsServer3D::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + Vector3 v = body->get_linear_velocity(); + Vector3 axis = p_axis_velocity.normalized(); + v -= axis * axis.dot(v); + v += p_axis_velocity; + body->set_linear_velocity(v); + body->wakeup(); +}; + +void GodotPhysicsServer3D::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_axis_lock(p_axis, p_lock); + body->wakeup(); +} + +bool GodotPhysicsServer3D::body_is_axis_locked(RID p_body, BodyAxis p_axis) const { + const GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + return body->is_axis_locked(p_axis); +} + +void GodotPhysicsServer3D::body_add_collision_exception(RID p_body, RID p_body_b) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->add_exception(p_body_b); + body->wakeup(); +}; + +void GodotPhysicsServer3D::body_remove_collision_exception(RID p_body, RID p_body_b) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->remove_exception(p_body_b); + body->wakeup(); +}; + +void GodotPhysicsServer3D::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + for (int i = 0; i < body->get_exceptions().size(); i++) { + p_exceptions->push_back(body->get_exceptions()[i]); + } +}; + +void GodotPhysicsServer3D::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); +}; + +real_t GodotPhysicsServer3D::body_get_contacts_reported_depth_threshold(RID p_body) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, 0); + return 0; +}; + +void GodotPhysicsServer3D::body_set_omit_force_integration(RID p_body, bool p_omit) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + + body->set_omit_force_integration(p_omit); +}; + +bool GodotPhysicsServer3D::body_is_omitting_force_integration(RID p_body) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, false); + return body->get_omit_force_integration(); +}; + +void GodotPhysicsServer3D::body_set_max_contacts_reported(RID p_body, int p_contacts) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + body->set_max_contacts_reported(p_contacts); +} + +int GodotPhysicsServer3D::body_get_max_contacts_reported(RID p_body) const { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, -1); + return body->get_max_contacts_reported(); +} + +void GodotPhysicsServer3D::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + body->set_state_sync_callback(p_instance, p_callback); +} + +void GodotPhysicsServer3D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + body->set_force_integration_callback(p_callable, p_udata); +} + +void GodotPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND(!body); + body->set_ray_pickable(p_enable); +} + +bool GodotPhysicsServer3D::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) { + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!body, false); + ERR_FAIL_COND_V(!body->get_space(), false); + ERR_FAIL_COND_V(body->get_space()->is_locked(), false); + + _update_shapes(); + + return body->get_space()->test_body_motion(body, p_parameters, r_result); +} + +PhysicsDirectBodyState3D *GodotPhysicsServer3D::body_get_direct_state(RID p_body) { + ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); + + GodotBody3D *body = body_owner.get_or_null(p_body); + ERR_FAIL_NULL_V(body, nullptr); + + ERR_FAIL_NULL_V(body->get_space(), nullptr); + ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); + + return body->get_direct_state(); +} + +/* SOFT BODY */ + +RID GodotPhysicsServer3D::soft_body_create() { + GodotSoftBody3D *soft_body = memnew(GodotSoftBody3D); + RID rid = soft_body_owner.make_rid(soft_body); + soft_body->set_self(rid); + return rid; +} + +void GodotPhysicsServer3D::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->update_rendering_server(p_rendering_server_handler); +} + +void GodotPhysicsServer3D::soft_body_set_space(RID p_body, RID p_space) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + GodotSpace3D *space = nullptr; + if (p_space.is_valid()) { + space = space_owner.get_or_null(p_space); + ERR_FAIL_COND(!space); + } + + if (soft_body->get_space() == space) { + return; + } + + soft_body->set_space(space); +} + +RID GodotPhysicsServer3D::soft_body_get_space(RID p_body) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, RID()); + + GodotSpace3D *space = soft_body->get_space(); + if (!space) { + return RID(); + } + return space->get_self(); +} + +void GodotPhysicsServer3D::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_collision_layer(p_layer); +} + +uint32_t GodotPhysicsServer3D::soft_body_get_collision_layer(RID p_body) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, 0); + + return soft_body->get_collision_layer(); +} + +void GodotPhysicsServer3D::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_collision_mask(p_mask); +} + +uint32_t GodotPhysicsServer3D::soft_body_get_collision_mask(RID p_body) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, 0); + + return soft_body->get_collision_mask(); +} + +void GodotPhysicsServer3D::soft_body_add_collision_exception(RID p_body, RID p_body_b) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->add_exception(p_body_b); +} + +void GodotPhysicsServer3D::soft_body_remove_collision_exception(RID p_body, RID p_body_b) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->remove_exception(p_body_b); +} + +void GodotPhysicsServer3D::soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + for (int i = 0; i < soft_body->get_exceptions().size(); i++) { + p_exceptions->push_back(soft_body->get_exceptions()[i]); + } +} + +void GodotPhysicsServer3D::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_state(p_state, p_variant); +} + +Variant GodotPhysicsServer3D::soft_body_get_state(RID p_body, BodyState p_state) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, Variant()); + + return soft_body->get_state(p_state); +} + +void GodotPhysicsServer3D::soft_body_set_transform(RID p_body, const Transform3D &p_transform) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_state(BODY_STATE_TRANSFORM, p_transform); +} + +void GodotPhysicsServer3D::soft_body_set_ray_pickable(RID p_body, bool p_enable) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_ray_pickable(p_enable); +} + +void GodotPhysicsServer3D::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_iteration_count(p_simulation_precision); +} + +int GodotPhysicsServer3D::soft_body_get_simulation_precision(RID p_body) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_iteration_count(); +} + +void GodotPhysicsServer3D::soft_body_set_total_mass(RID p_body, real_t p_total_mass) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_total_mass(p_total_mass); +} + +real_t GodotPhysicsServer3D::soft_body_get_total_mass(RID p_body) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_total_mass(); +} + +void GodotPhysicsServer3D::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_linear_stiffness(p_stiffness); +} + +real_t GodotPhysicsServer3D::soft_body_get_linear_stiffness(RID p_body) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_linear_stiffness(); +} + +void GodotPhysicsServer3D::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_pressure_coefficient(p_pressure_coefficient); +} + +real_t GodotPhysicsServer3D::soft_body_get_pressure_coefficient(RID p_body) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_pressure_coefficient(); +} + +void GodotPhysicsServer3D::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_damping_coefficient(p_damping_coefficient); +} + +real_t GodotPhysicsServer3D::soft_body_get_damping_coefficient(RID p_body) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_damping_coefficient(); +} + +void GodotPhysicsServer3D::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_drag_coefficient(p_drag_coefficient); +} + +real_t GodotPhysicsServer3D::soft_body_get_drag_coefficient(RID p_body) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, 0.f); + + return soft_body->get_drag_coefficient(); +} + +void GodotPhysicsServer3D::soft_body_set_mesh(RID p_body, RID p_mesh) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_mesh(p_mesh); +} + +AABB GodotPhysicsServer3D::soft_body_get_bounds(RID p_body) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, AABB()); + + return soft_body->get_bounds(); +} + +void GodotPhysicsServer3D::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->set_vertex_position(p_point_index, p_global_position); +} + +Vector3 GodotPhysicsServer3D::soft_body_get_point_global_position(RID p_body, int p_point_index) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, Vector3()); + + return soft_body->get_vertex_position(p_point_index); +} + +void GodotPhysicsServer3D::soft_body_remove_all_pinned_points(RID p_body) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + soft_body->unpin_all_vertices(); +} + +void GodotPhysicsServer3D::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND(!soft_body); + + if (p_pin) { + soft_body->pin_vertex(p_point_index); + } else { + soft_body->unpin_vertex(p_point_index); + } +} + +bool GodotPhysicsServer3D::soft_body_is_point_pinned(RID p_body, int p_point_index) const { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_body); + ERR_FAIL_COND_V(!soft_body, false); + + return soft_body->is_vertex_pinned(p_point_index); +} + +/* JOINT API */ + +RID GodotPhysicsServer3D::joint_create() { + GodotJoint3D *joint = memnew(GodotJoint3D); + RID rid = joint_owner.make_rid(joint); + joint->set_self(rid); + return rid; +} + +void GodotPhysicsServer3D::joint_clear(RID p_joint) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + if (joint->get_type() != JOINT_TYPE_MAX) { + GodotJoint3D *empty_joint = memnew(GodotJoint3D); + empty_joint->copy_settings_from(joint); + + joint_owner.replace(p_joint, empty_joint); + memdelete(joint); + } +} + +void GodotPhysicsServer3D::joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { + GodotBody3D *body_A = body_owner.get_or_null(p_body_A); + ERR_FAIL_COND(!body_A); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND(!body_A->get_space()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + GodotBody3D *body_B = body_owner.get_or_null(p_body_B); + ERR_FAIL_COND(!body_B); + + ERR_FAIL_COND(body_A == body_B); + + GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(prev_joint == nullptr); + + GodotJoint3D *joint = memnew(GodotPinJoint3D(body_A, p_local_A, body_B, p_local_B)); + + joint->copy_settings_from(prev_joint); + joint_owner.replace(p_joint, joint); + memdelete(prev_joint); +} + +void GodotPhysicsServer3D::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN); + GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); + pin_joint->set_param(p_param, p_value); +} + +real_t GodotPhysicsServer3D::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, 0); + ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0); + GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); + return pin_joint->get_param(p_param); +} + +void GodotPhysicsServer3D::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN); + GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); + pin_joint->set_pos_a(p_A); +} + +Vector3 GodotPhysicsServer3D::pin_joint_get_local_a(RID p_joint) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, Vector3()); + ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3()); + GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); + return pin_joint->get_position_a(); +} + +void GodotPhysicsServer3D::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN); + GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); + pin_joint->set_pos_b(p_B); +} + +Vector3 GodotPhysicsServer3D::pin_joint_get_local_b(RID p_joint) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, Vector3()); + ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3()); + GodotPinJoint3D *pin_joint = static_cast<GodotPinJoint3D *>(joint); + return pin_joint->get_position_b(); +} + +void GodotPhysicsServer3D::joint_make_hinge(RID p_joint, RID p_body_A, const Transform3D &p_frame_A, RID p_body_B, const Transform3D &p_frame_B) { + GodotBody3D *body_A = body_owner.get_or_null(p_body_A); + ERR_FAIL_COND(!body_A); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND(!body_A->get_space()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + GodotBody3D *body_B = body_owner.get_or_null(p_body_B); + ERR_FAIL_COND(!body_B); + + ERR_FAIL_COND(body_A == body_B); + + GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(prev_joint == nullptr); + + GodotJoint3D *joint = memnew(GodotHingeJoint3D(body_A, body_B, p_frame_A, p_frame_B)); + + joint->copy_settings_from(prev_joint); + joint_owner.replace(p_joint, joint); + memdelete(prev_joint); +} + +void GodotPhysicsServer3D::joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) { + GodotBody3D *body_A = body_owner.get_or_null(p_body_A); + ERR_FAIL_COND(!body_A); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND(!body_A->get_space()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + GodotBody3D *body_B = body_owner.get_or_null(p_body_B); + ERR_FAIL_COND(!body_B); + + ERR_FAIL_COND(body_A == body_B); + + GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(prev_joint == nullptr); + + GodotJoint3D *joint = memnew(GodotHingeJoint3D(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B)); + + joint->copy_settings_from(prev_joint); + joint_owner.replace(p_joint, joint); + memdelete(prev_joint); +} + +void GodotPhysicsServer3D::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE); + GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint); + hinge_joint->set_param(p_param, p_value); +} + +real_t GodotPhysicsServer3D::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, 0); + ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, 0); + GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint); + return hinge_joint->get_param(p_param); +} + +void GodotPhysicsServer3D::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE); + GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint); + hinge_joint->set_flag(p_flag, p_value); +} + +bool GodotPhysicsServer3D::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, false); + ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, false); + GodotHingeJoint3D *hinge_joint = static_cast<GodotHingeJoint3D *>(joint); + return hinge_joint->get_flag(p_flag); +} + +void GodotPhysicsServer3D::joint_set_solver_priority(RID p_joint, int p_priority) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + joint->set_priority(p_priority); +} + +int GodotPhysicsServer3D::joint_get_solver_priority(RID p_joint) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, 0); + return joint->get_priority(); +} + +void GodotPhysicsServer3D::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + + joint->disable_collisions_between_bodies(p_disable); + + if (2 == joint->get_body_count()) { + GodotBody3D *body_a = *joint->get_body_ptr(); + GodotBody3D *body_b = *(joint->get_body_ptr() + 1); + + if (p_disable) { + body_add_collision_exception(body_a->get_self(), body_b->get_self()); + body_add_collision_exception(body_b->get_self(), body_a->get_self()); + } else { + body_remove_collision_exception(body_a->get_self(), body_b->get_self()); + body_remove_collision_exception(body_b->get_self(), body_a->get_self()); + } + } +} + +bool GodotPhysicsServer3D::joint_is_disabled_collisions_between_bodies(RID p_joint) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, true); + + return joint->is_disabled_collisions_between_bodies(); +} + +GodotPhysicsServer3D::JointType GodotPhysicsServer3D::joint_get_type(RID p_joint) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN); + return joint->get_type(); +} + +void GodotPhysicsServer3D::joint_make_slider(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) { + GodotBody3D *body_A = body_owner.get_or_null(p_body_A); + ERR_FAIL_COND(!body_A); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND(!body_A->get_space()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + GodotBody3D *body_B = body_owner.get_or_null(p_body_B); + ERR_FAIL_COND(!body_B); + + ERR_FAIL_COND(body_A == body_B); + + GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(prev_joint == nullptr); + + GodotJoint3D *joint = memnew(GodotSliderJoint3D(body_A, body_B, p_local_frame_A, p_local_frame_B)); + + joint->copy_settings_from(prev_joint); + joint_owner.replace(p_joint, joint); + memdelete(prev_joint); +} + +void GodotPhysicsServer3D::slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_SLIDER); + GodotSliderJoint3D *slider_joint = static_cast<GodotSliderJoint3D *>(joint); + slider_joint->set_param(p_param, p_value); +} + +real_t GodotPhysicsServer3D::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, 0); + ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0); + GodotSliderJoint3D *slider_joint = static_cast<GodotSliderJoint3D *>(joint); + return slider_joint->get_param(p_param); +} + +void GodotPhysicsServer3D::joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) { + GodotBody3D *body_A = body_owner.get_or_null(p_body_A); + ERR_FAIL_COND(!body_A); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND(!body_A->get_space()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + GodotBody3D *body_B = body_owner.get_or_null(p_body_B); + ERR_FAIL_COND(!body_B); + + ERR_FAIL_COND(body_A == body_B); + + GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(prev_joint == nullptr); + + GodotJoint3D *joint = memnew(GodotConeTwistJoint3D(body_A, body_B, p_local_frame_A, p_local_frame_B)); + + joint->copy_settings_from(prev_joint); + joint_owner.replace(p_joint, joint); + memdelete(prev_joint); +} + +void GodotPhysicsServer3D::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_CONE_TWIST); + GodotConeTwistJoint3D *cone_twist_joint = static_cast<GodotConeTwistJoint3D *>(joint); + cone_twist_joint->set_param(p_param, p_value); +} + +real_t GodotPhysicsServer3D::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, 0); + ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0); + GodotConeTwistJoint3D *cone_twist_joint = static_cast<GodotConeTwistJoint3D *>(joint); + return cone_twist_joint->get_param(p_param); +} + +void GodotPhysicsServer3D::joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) { + GodotBody3D *body_A = body_owner.get_or_null(p_body_A); + ERR_FAIL_COND(!body_A); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND(!body_A->get_space()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + GodotBody3D *body_B = body_owner.get_or_null(p_body_B); + ERR_FAIL_COND(!body_B); + + ERR_FAIL_COND(body_A == body_B); + + GodotJoint3D *prev_joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(prev_joint == nullptr); + + GodotJoint3D *joint = memnew(GodotGeneric6DOFJoint3D(body_A, body_B, p_local_frame_A, p_local_frame_B, true)); + + joint->copy_settings_from(prev_joint); + joint_owner.replace(p_joint, joint); + memdelete(prev_joint); +} + +void GodotPhysicsServer3D::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF); + GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint); + generic_6dof_joint->set_param(p_axis, p_param, p_value); +} + +real_t GodotPhysicsServer3D::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, 0); + ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, 0); + GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint); + return generic_6dof_joint->get_param(p_axis, p_param); +} + +void GodotPhysicsServer3D::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF); + GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint); + generic_6dof_joint->set_flag(p_axis, p_flag, p_enable); +} + +bool GodotPhysicsServer3D::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) const { + GodotJoint3D *joint = joint_owner.get_or_null(p_joint); + ERR_FAIL_COND_V(!joint, false); + ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, false); + GodotGeneric6DOFJoint3D *generic_6dof_joint = static_cast<GodotGeneric6DOFJoint3D *>(joint); + return generic_6dof_joint->get_flag(p_axis, p_flag); +} + +void GodotPhysicsServer3D::free(RID p_rid) { + _update_shapes(); //just in case + + if (shape_owner.owns(p_rid)) { + GodotShape3D *shape = shape_owner.get_or_null(p_rid); + + while (shape->get_owners().size()) { + GodotShapeOwner3D *so = shape->get_owners().front()->key(); + so->remove_shape(shape); + } + + shape_owner.free(p_rid); + memdelete(shape); + } else if (body_owner.owns(p_rid)) { + GodotBody3D *body = body_owner.get_or_null(p_rid); + + /* + if (body->get_state_query()) + _clear_query(body->get_state_query()); + + if (body->get_direct_state_query()) + _clear_query(body->get_direct_state_query()); + */ + + body->set_space(nullptr); + + while (body->get_shape_count()) { + body->remove_shape(0); + } + + body_owner.free(p_rid); + memdelete(body); + } else if (soft_body_owner.owns(p_rid)) { + GodotSoftBody3D *soft_body = soft_body_owner.get_or_null(p_rid); + + soft_body->set_space(nullptr); + + soft_body_owner.free(p_rid); + memdelete(soft_body); + } else if (area_owner.owns(p_rid)) { + GodotArea3D *area = area_owner.get_or_null(p_rid); + + /* + if (area->get_monitor_query()) + _clear_query(area->get_monitor_query()); + */ + + area->set_space(nullptr); + + while (area->get_shape_count()) { + area->remove_shape(0); + } + + area_owner.free(p_rid); + memdelete(area); + } else if (space_owner.owns(p_rid)) { + GodotSpace3D *space = space_owner.get_or_null(p_rid); + + while (space->get_objects().size()) { + GodotCollisionObject3D *co = (GodotCollisionObject3D *)space->get_objects().front()->get(); + co->set_space(nullptr); + } + + active_spaces.erase(space); + free(space->get_default_area()->get_self()); + free(space->get_static_global_body()); + + space_owner.free(p_rid); + memdelete(space); + } else if (joint_owner.owns(p_rid)) { + GodotJoint3D *joint = joint_owner.get_or_null(p_rid); + + joint_owner.free(p_rid); + memdelete(joint); + + } else { + ERR_FAIL_MSG("Invalid ID."); + } +}; + +void GodotPhysicsServer3D::set_active(bool p_active) { + active = p_active; +}; + +void GodotPhysicsServer3D::set_collision_iterations(int p_iterations) { + iterations = p_iterations; +}; + +void GodotPhysicsServer3D::init() { + iterations = 8; // 8? + stepper = memnew(GodotStep3D); +}; + +void GodotPhysicsServer3D::step(real_t p_step) { +#ifndef _3D_DISABLED + + if (!active) { + return; + } + + _update_shapes(); + + island_count = 0; + active_objects = 0; + collision_pairs = 0; + for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { + stepper->step((GodotSpace3D *)E->get(), p_step, iterations); + island_count += E->get()->get_island_count(); + active_objects += E->get()->get_active_objects(); + collision_pairs += E->get()->get_collision_pairs(); + } +#endif +} + +void GodotPhysicsServer3D::sync() { + doing_sync = true; +}; + +void GodotPhysicsServer3D::flush_queries() { +#ifndef _3D_DISABLED + + if (!active) { + return; + } + + flushing_queries = true; + + uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); + + for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { + GodotSpace3D *space = (GodotSpace3D *)E->get(); + space->call_queries(); + } + + flushing_queries = false; + + if (EngineDebugger::is_profiling("servers")) { + uint64_t total_time[GodotSpace3D::ELAPSED_TIME_MAX]; + static const char *time_name[GodotSpace3D::ELAPSED_TIME_MAX] = { + "integrate_forces", + "generate_islands", + "setup_constraints", + "solve_constraints", + "integrate_velocities" + }; + + for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) { + total_time[i] = 0; + } + + for (Set<const GodotSpace3D *>::Element *E = active_spaces.front(); E; E = E->next()) { + for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) { + total_time[i] += E->get()->get_elapsed_time(GodotSpace3D::ElapsedTime(i)); + } + } + + Array values; + values.resize(GodotSpace3D::ELAPSED_TIME_MAX * 2); + for (int i = 0; i < GodotSpace3D::ELAPSED_TIME_MAX; i++) { + values[i * 2 + 0] = time_name[i]; + values[i * 2 + 1] = USEC_TO_SEC(total_time[i]); + } + values.push_back("flush_queries"); + values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg)); + + values.push_front("physics"); + EngineDebugger::profiler_add_frame_data("servers", values); + } +#endif +}; + +void GodotPhysicsServer3D::end_sync() { + doing_sync = false; +}; + +void GodotPhysicsServer3D::finish() { + memdelete(stepper); +}; + +int GodotPhysicsServer3D::get_process_info(ProcessInfo p_info) { + switch (p_info) { + case INFO_ACTIVE_OBJECTS: { + return active_objects; + } break; + case INFO_COLLISION_PAIRS: { + return collision_pairs; + } break; + case INFO_ISLAND_COUNT: { + return island_count; + } break; + } + + return 0; +} + +void GodotPhysicsServer3D::_update_shapes() { + while (pending_shape_update_list.first()) { + pending_shape_update_list.first()->self()->_shape_changed(); + pending_shape_update_list.remove(pending_shape_update_list.first()); + } +} + +void GodotPhysicsServer3D::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { + CollCbkData *cbk = (CollCbkData *)p_userdata; + + if (cbk->max == 0) { + return; + } + + if (cbk->amount == cbk->max) { + //find least deep + real_t min_depth = 1e20; + int min_depth_idx = 0; + for (int i = 0; i < cbk->amount; i++) { + real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]); + if (d < min_depth) { + min_depth = d; + min_depth_idx = i; + } + } + + real_t d = p_point_A.distance_squared_to(p_point_B); + if (d < min_depth) { + return; + } + cbk->ptr[min_depth_idx * 2 + 0] = p_point_A; + cbk->ptr[min_depth_idx * 2 + 1] = p_point_B; + + } else { + cbk->ptr[cbk->amount * 2 + 0] = p_point_A; + cbk->ptr[cbk->amount * 2 + 1] = p_point_B; + cbk->amount++; + } +} + +GodotPhysicsServer3D *GodotPhysicsServer3D::godot_singleton = nullptr; +GodotPhysicsServer3D::GodotPhysicsServer3D(bool p_using_threads) { + godot_singleton = this; + GodotBroadPhase3D::create_func = GodotBroadPhase3DBVH::_create; + + using_threads = p_using_threads; +}; diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/godot_physics_server_3d.h index 54a787198d..3ed9e320dc 100644 --- a/servers/physics_3d/physics_server_3d_sw.h +++ b/servers/physics_3d/godot_physics_server_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* physics_server_3d_sw.h */ +/* godot_physics_server_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,20 +28,21 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PHYSICS_SERVER_SW -#define PHYSICS_SERVER_SW +#ifndef GODOT_PHYSICS_SERVER_3D_H +#define GODOT_PHYSICS_SERVER_3D_H + +#include "godot_joint_3d.h" +#include "godot_shape_3d.h" +#include "godot_space_3d.h" +#include "godot_step_3d.h" #include "core/templates/rid_owner.h" -#include "joints_3d_sw.h" #include "servers/physics_server_3d.h" -#include "shape_3d_sw.h" -#include "space_3d_sw.h" -#include "step_3d_sw.h" -class PhysicsServer3DSW : public PhysicsServer3D { - GDCLASS(PhysicsServer3DSW, PhysicsServer3D); +class GodotPhysicsServer3D : public PhysicsServer3D { + GDCLASS(GodotPhysicsServer3D, PhysicsServer3D); - friend class PhysicsDirectSpaceState3DSW; + friend class GodotPhysicsDirectSpaceState3D; bool active = true; int iterations = 0; @@ -53,22 +54,22 @@ class PhysicsServer3DSW : public PhysicsServer3D { bool doing_sync = false; bool flushing_queries = false; - Step3DSW *stepper = nullptr; - Set<const Space3DSW *> active_spaces; + GodotStep3D *stepper = nullptr; + Set<const GodotSpace3D *> active_spaces; - mutable RID_PtrOwner<Shape3DSW, true> shape_owner; - mutable RID_PtrOwner<Space3DSW, true> space_owner; - mutable RID_PtrOwner<Area3DSW, true> area_owner; - mutable RID_PtrOwner<Body3DSW, true> body_owner; - mutable RID_PtrOwner<SoftBody3DSW, true> soft_body_owner; - mutable RID_PtrOwner<Joint3DSW, true> joint_owner; + mutable RID_PtrOwner<GodotShape3D, true> shape_owner; + mutable RID_PtrOwner<GodotSpace3D, true> space_owner; + mutable RID_PtrOwner<GodotArea3D, true> area_owner; + mutable RID_PtrOwner<GodotBody3D, true> body_owner; + mutable RID_PtrOwner<GodotSoftBody3D, true> soft_body_owner; + mutable RID_PtrOwner<GodotJoint3D, true> joint_owner; //void _clear_query(QuerySW *p_query); - friend class CollisionObject3DSW; - SelfList<CollisionObject3DSW>::List pending_shape_update_list; + friend class GodotCollisionObject3D; + SelfList<GodotCollisionObject3D>::List pending_shape_update_list; void _update_shapes(); - static PhysicsServer3DSW *singletonsw; + static GodotPhysicsServer3D *godot_singleton; public: struct CollCbkData { @@ -372,8 +373,8 @@ public: int get_process_info(ProcessInfo p_info) override; - PhysicsServer3DSW(bool p_using_threads = false); - ~PhysicsServer3DSW() {} + GodotPhysicsServer3D(bool p_using_threads = false); + ~GodotPhysicsServer3D() {} }; -#endif +#endif // GODOT_PHYSICS_SERVER_3D_H diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/godot_shape_3d.cpp index 789fc6ab33..4c12a5a948 100644 --- a/servers/physics_3d/shape_3d_sw.cpp +++ b/servers/physics_3d/godot_shape_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* shape_3d_sw.cpp */ +/* godot_shape_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,14 +28,14 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "shape_3d_sw.h" +#include "godot_shape_3d.h" #include "core/io/image.h" #include "core/math/convex_hull.h" #include "core/math/geometry_3d.h" #include "core/templates/sort_array.h" -// HeightMapShape3DSW is based on Bullet btHeightfieldTerrainShape. +// GodotHeightMapShape3D is based on Bullet btHeightfieldTerrainShape. /* Bullet Continuous Collision Detection and Physics Library @@ -58,16 +58,16 @@ subject to the following restrictions: #define _CYLINDER_EDGE_IS_VALID_SUPPORT_THRESHOLD 0.002 #define _CYLINDER_FACE_IS_VALID_SUPPORT_THRESHOLD 0.999 -void Shape3DSW::configure(const AABB &p_aabb) { +void GodotShape3D::configure(const AABB &p_aabb) { aabb = p_aabb; configured = true; - for (const KeyValue<ShapeOwner3DSW *, int> &E : owners) { - ShapeOwner3DSW *co = (ShapeOwner3DSW *)E.key; + for (const KeyValue<GodotShapeOwner3D *, int> &E : owners) { + GodotShapeOwner3D *co = (GodotShapeOwner3D *)E.key; co->_shape_changed(); } } -Vector3 Shape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 GodotShape3D::get_support(const Vector3 &p_normal) const { Vector3 res; int amnt; FeatureType type; @@ -75,8 +75,8 @@ Vector3 Shape3DSW::get_support(const Vector3 &p_normal) const { return res; } -void Shape3DSW::add_owner(ShapeOwner3DSW *p_owner) { - Map<ShapeOwner3DSW *, int>::Element *E = owners.find(p_owner); +void GodotShape3D::add_owner(GodotShapeOwner3D *p_owner) { + Map<GodotShapeOwner3D *, int>::Element *E = owners.find(p_owner); if (E) { E->get()++; } else { @@ -84,8 +84,8 @@ void Shape3DSW::add_owner(ShapeOwner3DSW *p_owner) { } } -void Shape3DSW::remove_owner(ShapeOwner3DSW *p_owner) { - Map<ShapeOwner3DSW *, int>::Element *E = owners.find(p_owner); +void GodotShape3D::remove_owner(GodotShapeOwner3D *p_owner) { + Map<GodotShapeOwner3D *, int>::Element *E = owners.find(p_owner); ERR_FAIL_COND(!E); E->get()--; if (E->get() == 0) { @@ -93,33 +93,33 @@ void Shape3DSW::remove_owner(ShapeOwner3DSW *p_owner) { } } -bool Shape3DSW::is_owner(ShapeOwner3DSW *p_owner) const { +bool GodotShape3D::is_owner(GodotShapeOwner3D *p_owner) const { return owners.has(p_owner); } -const Map<ShapeOwner3DSW *, int> &Shape3DSW::get_owners() const { +const Map<GodotShapeOwner3D *, int> &GodotShape3D::get_owners() const { return owners; } -Shape3DSW::~Shape3DSW() { +GodotShape3D::~GodotShape3D() { ERR_FAIL_COND(owners.size()); } -Plane WorldBoundaryShape3DSW::get_plane() const { +Plane GodotWorldBoundaryShape3D::get_plane() const { return plane; } -void WorldBoundaryShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { +void GodotWorldBoundaryShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { // gibberish, a plane is infinity r_min = -1e7; r_max = 1e7; } -Vector3 WorldBoundaryShape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 GodotWorldBoundaryShape3D::get_support(const Vector3 &p_normal) const { return p_normal * 1e15; } -bool WorldBoundaryShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotWorldBoundaryShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool inters = plane.intersects_segment(p_begin, p_end, &r_result); if (inters) { r_normal = plane.normal; @@ -127,11 +127,11 @@ bool WorldBoundaryShape3DSW::intersect_segment(const Vector3 &p_begin, const Vec return inters; } -bool WorldBoundaryShape3DSW::intersect_point(const Vector3 &p_point) const { +bool GodotWorldBoundaryShape3D::intersect_point(const Vector3 &p_point) const { return plane.distance_to(p_point) < 0; } -Vector3 WorldBoundaryShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 GodotWorldBoundaryShape3D::get_closest_point_to(const Vector3 &p_point) const { if (plane.is_point_over(p_point)) { return plane.project(p_point); } else { @@ -139,43 +139,43 @@ Vector3 WorldBoundaryShape3DSW::get_closest_point_to(const Vector3 &p_point) con } } -Vector3 WorldBoundaryShape3DSW::get_moment_of_inertia(real_t p_mass) const { +Vector3 GodotWorldBoundaryShape3D::get_moment_of_inertia(real_t p_mass) const { return Vector3(); // not applicable. } -void WorldBoundaryShape3DSW::_setup(const Plane &p_plane) { +void GodotWorldBoundaryShape3D::_setup(const Plane &p_plane) { plane = p_plane; configure(AABB(Vector3(-1e4, -1e4, -1e4), Vector3(1e4 * 2, 1e4 * 2, 1e4 * 2))); } -void WorldBoundaryShape3DSW::set_data(const Variant &p_data) { +void GodotWorldBoundaryShape3D::set_data(const Variant &p_data) { _setup(p_data); } -Variant WorldBoundaryShape3DSW::get_data() const { +Variant GodotWorldBoundaryShape3D::get_data() const { return plane; } -WorldBoundaryShape3DSW::WorldBoundaryShape3DSW() { +GodotWorldBoundaryShape3D::GodotWorldBoundaryShape3D() { } // -real_t SeparationRayShape3DSW::get_length() const { +real_t GodotSeparationRayShape3D::get_length() const { return length; } -bool SeparationRayShape3DSW::get_slide_on_slope() const { +bool GodotSeparationRayShape3D::get_slide_on_slope() const { return slide_on_slope; } -void SeparationRayShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { +void GodotSeparationRayShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { // don't think this will be even used r_min = 0; r_max = 1; } -Vector3 SeparationRayShape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 GodotSeparationRayShape3D::get_support(const Vector3 &p_normal) const { if (p_normal.z > 0) { return Vector3(0, 0, length); } else { @@ -183,7 +183,7 @@ Vector3 SeparationRayShape3DSW::get_support(const Vector3 &p_normal) const { } } -void SeparationRayShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { +void GodotSeparationRayShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { if (Math::abs(p_normal.z) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { r_amount = 2; r_type = FEATURE_EDGE; @@ -200,15 +200,15 @@ void SeparationRayShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Ve } } -bool SeparationRayShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotSeparationRayShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { return false; //simply not possible } -bool SeparationRayShape3DSW::intersect_point(const Vector3 &p_point) const { +bool GodotSeparationRayShape3D::intersect_point(const Vector3 &p_point) const { return false; //simply not possible } -Vector3 SeparationRayShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 GodotSeparationRayShape3D::get_closest_point_to(const Vector3 &p_point) const { Vector3 s[2] = { Vector3(0, 0, 0), Vector3(0, 0, length) @@ -217,37 +217,37 @@ Vector3 SeparationRayShape3DSW::get_closest_point_to(const Vector3 &p_point) con return Geometry3D::get_closest_point_to_segment(p_point, s); } -Vector3 SeparationRayShape3DSW::get_moment_of_inertia(real_t p_mass) const { +Vector3 GodotSeparationRayShape3D::get_moment_of_inertia(real_t p_mass) const { return Vector3(); } -void SeparationRayShape3DSW::_setup(real_t p_length, bool p_slide_on_slope) { +void GodotSeparationRayShape3D::_setup(real_t p_length, bool p_slide_on_slope) { length = p_length; slide_on_slope = p_slide_on_slope; configure(AABB(Vector3(0, 0, 0), Vector3(0.1, 0.1, length))); } -void SeparationRayShape3DSW::set_data(const Variant &p_data) { +void GodotSeparationRayShape3D::set_data(const Variant &p_data) { Dictionary d = p_data; _setup(d["length"], d["slide_on_slope"]); } -Variant SeparationRayShape3DSW::get_data() const { +Variant GodotSeparationRayShape3D::get_data() const { Dictionary d; d["length"] = length; d["slide_on_slope"] = slide_on_slope; return d; } -SeparationRayShape3DSW::SeparationRayShape3DSW() {} +GodotSeparationRayShape3D::GodotSeparationRayShape3D() {} /********** SPHERE *************/ -real_t SphereShape3DSW::get_radius() const { +real_t GodotSphereShape3D::get_radius() const { return radius; } -void SphereShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { +void GodotSphereShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { real_t d = p_normal.dot(p_transform.origin); // figure out scale at point @@ -258,25 +258,25 @@ void SphereShape3DSW::project_range(const Vector3 &p_normal, const Transform3D & r_max = d + (radius)*scale; } -Vector3 SphereShape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 GodotSphereShape3D::get_support(const Vector3 &p_normal) const { return p_normal * radius; } -void SphereShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { +void GodotSphereShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { *r_supports = p_normal * radius; r_amount = 1; r_type = FEATURE_POINT; } -bool SphereShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotSphereShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { return Geometry3D::segment_intersects_sphere(p_begin, p_end, Vector3(), radius, &r_result, &r_normal); } -bool SphereShape3DSW::intersect_point(const Vector3 &p_point) const { +bool GodotSphereShape3D::intersect_point(const Vector3 &p_point) const { return p_point.length() < radius; } -Vector3 SphereShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 GodotSphereShape3D::get_closest_point_to(const Vector3 &p_point) const { Vector3 p = p_point; real_t l = p.length(); if (l < radius) { @@ -285,29 +285,29 @@ Vector3 SphereShape3DSW::get_closest_point_to(const Vector3 &p_point) const { return (p / l) * radius; } -Vector3 SphereShape3DSW::get_moment_of_inertia(real_t p_mass) const { +Vector3 GodotSphereShape3D::get_moment_of_inertia(real_t p_mass) const { real_t s = 0.4 * p_mass * radius * radius; return Vector3(s, s, s); } -void SphereShape3DSW::_setup(real_t p_radius) { +void GodotSphereShape3D::_setup(real_t p_radius) { radius = p_radius; configure(AABB(Vector3(-radius, -radius, -radius), Vector3(radius * 2.0, radius * 2.0, radius * 2.0))); } -void SphereShape3DSW::set_data(const Variant &p_data) { +void GodotSphereShape3D::set_data(const Variant &p_data) { _setup(p_data); } -Variant SphereShape3DSW::get_data() const { +Variant GodotSphereShape3D::get_data() const { return radius; } -SphereShape3DSW::SphereShape3DSW() {} +GodotSphereShape3D::GodotSphereShape3D() {} /********** BOX *************/ -void BoxShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { +void GodotBoxShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { // no matter the angle, the box is mirrored anyway Vector3 local_normal = p_transform.basis.xform_inv(p_normal); @@ -318,7 +318,7 @@ void BoxShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_t r_max = distance + length; } -Vector3 BoxShape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 GodotBoxShape3D::get_support(const Vector3 &p_normal) const { Vector3 point( (p_normal.x < 0) ? -half_extents.x : half_extents.x, (p_normal.y < 0) ? -half_extents.y : half_extents.y, @@ -327,7 +327,7 @@ Vector3 BoxShape3DSW::get_support(const Vector3 &p_normal) const { return point; } -void BoxShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { +void GodotBoxShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { static const int next[3] = { 1, 2, 0 }; static const int next2[3] = { 2, 0, 1 }; @@ -410,17 +410,17 @@ void BoxShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_s r_supports[0] = point; } -bool BoxShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotBoxShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { AABB aabb(-half_extents, half_extents * 2.0); return aabb.intersects_segment(p_begin, p_end, &r_result, &r_normal); } -bool BoxShape3DSW::intersect_point(const Vector3 &p_point) const { +bool GodotBoxShape3D::intersect_point(const Vector3 &p_point) const { return (Math::abs(p_point.x) < half_extents.x && Math::abs(p_point.y) < half_extents.y && Math::abs(p_point.z) < half_extents.z); } -Vector3 BoxShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 GodotBoxShape3D::get_closest_point_to(const Vector3 &p_point) const { int outside = 0; Vector3 min_point; @@ -470,7 +470,7 @@ Vector3 BoxShape3DSW::get_closest_point_to(const Vector3 &p_point) const { return min_point; } -Vector3 BoxShape3DSW::get_moment_of_inertia(real_t p_mass) const { +Vector3 GodotBoxShape3D::get_moment_of_inertia(real_t p_mass) const { real_t lx = half_extents.x; real_t ly = half_extents.y; real_t lz = half_extents.z; @@ -478,25 +478,25 @@ Vector3 BoxShape3DSW::get_moment_of_inertia(real_t p_mass) const { return Vector3((p_mass / 3.0) * (ly * ly + lz * lz), (p_mass / 3.0) * (lx * lx + lz * lz), (p_mass / 3.0) * (lx * lx + ly * ly)); } -void BoxShape3DSW::_setup(const Vector3 &p_half_extents) { +void GodotBoxShape3D::_setup(const Vector3 &p_half_extents) { half_extents = p_half_extents.abs(); configure(AABB(-half_extents, half_extents * 2)); } -void BoxShape3DSW::set_data(const Variant &p_data) { +void GodotBoxShape3D::set_data(const Variant &p_data) { _setup(p_data); } -Variant BoxShape3DSW::get_data() const { +Variant GodotBoxShape3D::get_data() const { return half_extents; } -BoxShape3DSW::BoxShape3DSW() {} +GodotBoxShape3D::GodotBoxShape3D() {} /********** CAPSULE *************/ -void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { +void GodotCapsuleShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { Vector3 n = p_transform.basis.xform_inv(p_normal).normalized(); real_t h = height * 0.5 - radius; @@ -507,7 +507,7 @@ void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform3D r_min = p_normal.dot(p_transform.xform(-n)); } -Vector3 CapsuleShape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 GodotCapsuleShape3D::get_support(const Vector3 &p_normal) const { Vector3 n = p_normal; real_t h = height * 0.5 - radius; @@ -517,7 +517,7 @@ Vector3 CapsuleShape3DSW::get_support(const Vector3 &p_normal) const { return n; } -void CapsuleShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { +void GodotCapsuleShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { Vector3 n = p_normal; real_t d = n.y; @@ -546,7 +546,7 @@ void CapsuleShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 } } -bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotCapsuleShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { Vector3 norm = (p_end - p_begin).normalized(); real_t min_d = 1e20; @@ -602,7 +602,7 @@ bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 & return collision; } -bool CapsuleShape3DSW::intersect_point(const Vector3 &p_point) const { +bool GodotCapsuleShape3D::intersect_point(const Vector3 &p_point) const { if (Math::abs(p_point.y) < height * 0.5 - radius) { return Vector3(p_point.x, 0, p_point.z).length() < radius; } else { @@ -612,7 +612,7 @@ bool CapsuleShape3DSW::intersect_point(const Vector3 &p_point) const { } } -Vector3 CapsuleShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 GodotCapsuleShape3D::get_closest_point_to(const Vector3 &p_point) const { Vector3 s[2] = { Vector3(0, -height * 0.5 + radius, 0), Vector3(0, height * 0.5 - radius, 0), @@ -627,7 +627,7 @@ Vector3 CapsuleShape3DSW::get_closest_point_to(const Vector3 &p_point) const { return p + (p_point - p).normalized() * radius; } -Vector3 CapsuleShape3DSW::get_moment_of_inertia(real_t p_mass) const { +Vector3 GodotCapsuleShape3D::get_moment_of_inertia(real_t p_mass) const { // use bad AABB approximation Vector3 extents = get_aabb().size * 0.5; @@ -637,31 +637,31 @@ Vector3 CapsuleShape3DSW::get_moment_of_inertia(real_t p_mass) const { (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y)); } -void CapsuleShape3DSW::_setup(real_t p_height, real_t p_radius) { +void GodotCapsuleShape3D::_setup(real_t p_height, real_t p_radius) { height = p_height; radius = p_radius; configure(AABB(Vector3(-radius, -height * 0.5, -radius), Vector3(radius * 2, height, radius * 2))); } -void CapsuleShape3DSW::set_data(const Variant &p_data) { +void GodotCapsuleShape3D::set_data(const Variant &p_data) { Dictionary d = p_data; ERR_FAIL_COND(!d.has("radius")); ERR_FAIL_COND(!d.has("height")); _setup(d["height"], d["radius"]); } -Variant CapsuleShape3DSW::get_data() const { +Variant GodotCapsuleShape3D::get_data() const { Dictionary d; d["radius"] = radius; d["height"] = height; return d; } -CapsuleShape3DSW::CapsuleShape3DSW() {} +GodotCapsuleShape3D::GodotCapsuleShape3D() {} /********** CYLINDER *************/ -void CylinderShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { +void GodotCylinderShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { Vector3 cylinder_axis = p_transform.basis.get_axis(1).normalized(); real_t axis_dot = cylinder_axis.dot(p_normal); @@ -683,7 +683,7 @@ void CylinderShape3DSW::project_range(const Vector3 &p_normal, const Transform3D r_max = distance + length; } -Vector3 CylinderShape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 GodotCylinderShape3D::get_support(const Vector3 &p_normal) const { Vector3 n = p_normal; real_t h = (n.y > 0) ? height : -height; real_t s = Math::sqrt(n.x * n.x + n.z * n.z); @@ -701,7 +701,7 @@ Vector3 CylinderShape3DSW::get_support(const Vector3 &p_normal) const { return n; } -void CylinderShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { +void GodotCylinderShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { real_t d = p_normal.y; if (Math::abs(d) > _CYLINDER_FACE_IS_VALID_SUPPORT_THRESHOLD) { real_t h = (d > 0) ? height : -height; @@ -761,18 +761,18 @@ void CylinderShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 } } -bool CylinderShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotCylinderShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { return Geometry3D::segment_intersects_cylinder(p_begin, p_end, height, radius, &r_result, &r_normal, 1); } -bool CylinderShape3DSW::intersect_point(const Vector3 &p_point) const { +bool GodotCylinderShape3D::intersect_point(const Vector3 &p_point) const { if (Math::abs(p_point.y) < height * 0.5) { return Vector3(p_point.x, 0, p_point.z).length() < radius; } return false; } -Vector3 CylinderShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 GodotCylinderShape3D::get_closest_point_to(const Vector3 &p_point) const { if (Math::absf(p_point.y) > height * 0.5) { // Project point to top disk. real_t dir = p_point.y > 0.0 ? 1.0 : -1.0; @@ -805,7 +805,7 @@ Vector3 CylinderShape3DSW::get_closest_point_to(const Vector3 &p_point) const { } } -Vector3 CylinderShape3DSW::get_moment_of_inertia(real_t p_mass) const { +Vector3 GodotCylinderShape3D::get_moment_of_inertia(real_t p_mass) const { // use bad AABB approximation Vector3 extents = get_aabb().size * 0.5; @@ -815,31 +815,31 @@ Vector3 CylinderShape3DSW::get_moment_of_inertia(real_t p_mass) const { (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y)); } -void CylinderShape3DSW::_setup(real_t p_height, real_t p_radius) { +void GodotCylinderShape3D::_setup(real_t p_height, real_t p_radius) { height = p_height; radius = p_radius; configure(AABB(Vector3(-radius, -height * 0.5, -radius), Vector3(radius * 2.0, height, radius * 2.0))); } -void CylinderShape3DSW::set_data(const Variant &p_data) { +void GodotCylinderShape3D::set_data(const Variant &p_data) { Dictionary d = p_data; ERR_FAIL_COND(!d.has("radius")); ERR_FAIL_COND(!d.has("height")); _setup(d["height"], d["radius"]); } -Variant CylinderShape3DSW::get_data() const { +Variant GodotCylinderShape3D::get_data() const { Dictionary d; d["radius"] = radius; d["height"] = height; return d; } -CylinderShape3DSW::CylinderShape3DSW() {} +GodotCylinderShape3D::GodotCylinderShape3D() {} /********** CONVEX POLYGON *************/ -void ConvexPolygonShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { +void GodotConvexPolygonShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { int vertex_count = mesh.vertices.size(); if (vertex_count == 0) { return; @@ -859,7 +859,7 @@ void ConvexPolygonShape3DSW::project_range(const Vector3 &p_normal, const Transf } } -Vector3 ConvexPolygonShape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 GodotConvexPolygonShape3D::get_support(const Vector3 &p_normal) const { Vector3 n = p_normal; int vert_support_idx = -1; @@ -884,7 +884,7 @@ Vector3 ConvexPolygonShape3DSW::get_support(const Vector3 &p_normal) const { return vrts[vert_support_idx]; } -void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { +void GodotConvexPolygonShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { const Geometry3D::MeshData::Face *faces = mesh.faces.ptr(); int fc = mesh.faces.size(); @@ -954,7 +954,7 @@ void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Ve r_type = FEATURE_POINT; } -bool ConvexPolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotConvexPolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { const Geometry3D::MeshData::Face *faces = mesh.faces.ptr(); int fc = mesh.faces.size(); @@ -992,7 +992,7 @@ bool ConvexPolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Vec return col; } -bool ConvexPolygonShape3DSW::intersect_point(const Vector3 &p_point) const { +bool GodotConvexPolygonShape3D::intersect_point(const Vector3 &p_point) const { const Geometry3D::MeshData::Face *faces = mesh.faces.ptr(); int fc = mesh.faces.size(); @@ -1005,7 +1005,7 @@ bool ConvexPolygonShape3DSW::intersect_point(const Vector3 &p_point) const { return true; } -Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 GodotConvexPolygonShape3D::get_closest_point_to(const Vector3 &p_point) const { const Geometry3D::MeshData::Face *faces = mesh.faces.ptr(); int fc = mesh.faces.size(); const Vector3 *vertices = mesh.vertices.ptr(); @@ -1063,7 +1063,7 @@ Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) con return min_point; } -Vector3 ConvexPolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const { +Vector3 GodotConvexPolygonShape3D::get_moment_of_inertia(real_t p_mass) const { // use bad AABB approximation Vector3 extents = get_aabb().size * 0.5; @@ -1073,7 +1073,7 @@ Vector3 ConvexPolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const { (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y)); } -void ConvexPolygonShape3DSW::_setup(const Vector<Vector3> &p_vertices) { +void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) { Error err = ConvexHullComputer::convex_hull(p_vertices, mesh); if (err != OK) { ERR_PRINT("Failed to build convex hull"); @@ -1092,20 +1092,20 @@ void ConvexPolygonShape3DSW::_setup(const Vector<Vector3> &p_vertices) { configure(_aabb); } -void ConvexPolygonShape3DSW::set_data(const Variant &p_data) { +void GodotConvexPolygonShape3D::set_data(const Variant &p_data) { _setup(p_data); } -Variant ConvexPolygonShape3DSW::get_data() const { +Variant GodotConvexPolygonShape3D::get_data() const { return mesh.vertices; } -ConvexPolygonShape3DSW::ConvexPolygonShape3DSW() { +GodotConvexPolygonShape3D::GodotConvexPolygonShape3D() { } /********** FACE POLYGON *************/ -void FaceShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { +void GodotFaceShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { for (int i = 0; i < 3; i++) { Vector3 v = p_transform.xform(vertex[i]); real_t d = p_normal.dot(v); @@ -1120,7 +1120,7 @@ void FaceShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_ } } -Vector3 FaceShape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 GodotFaceShape3D::get_support(const Vector3 &p_normal) const { int vert_support_idx = -1; real_t support_max = 0; @@ -1136,7 +1136,7 @@ Vector3 FaceShape3DSW::get_support(const Vector3 &p_normal) const { return vertex[vert_support_idx]; } -void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { +void GodotFaceShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const { Vector3 n = p_normal; /** TEST FACE AS SUPPORT **/ @@ -1188,7 +1188,7 @@ void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_ r_supports[0] = vertex[vert_support_idx]; } -bool FaceShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotFaceShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { bool c = Geometry3D::segment_intersects_triangle(p_begin, p_end, vertex[0], vertex[1], vertex[2], &r_result); if (c) { r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal; @@ -1204,23 +1204,23 @@ bool FaceShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_e return c; } -bool FaceShape3DSW::intersect_point(const Vector3 &p_point) const { +bool GodotFaceShape3D::intersect_point(const Vector3 &p_point) const { return false; //face is flat } -Vector3 FaceShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 GodotFaceShape3D::get_closest_point_to(const Vector3 &p_point) const { return Face3(vertex[0], vertex[1], vertex[2]).get_closest_point_to(p_point); } -Vector3 FaceShape3DSW::get_moment_of_inertia(real_t p_mass) const { +Vector3 GodotFaceShape3D::get_moment_of_inertia(real_t p_mass) const { return Vector3(); // Sorry, but i don't think anyone cares, FaceShape! } -FaceShape3DSW::FaceShape3DSW() { +GodotFaceShape3D::GodotFaceShape3D() { configure(AABB()); } -Vector<Vector3> ConcavePolygonShape3DSW::get_faces() const { +Vector<Vector3> GodotConcavePolygonShape3D::get_faces() const { Vector<Vector3> rfaces; rfaces.resize(faces.size() * 3); @@ -1235,7 +1235,7 @@ Vector<Vector3> ConcavePolygonShape3DSW::get_faces() const { return rfaces; } -void ConcavePolygonShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { +void GodotConcavePolygonShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { int count = vertices.size(); if (count == 0) { r_min = 0; @@ -1256,7 +1256,7 @@ void ConcavePolygonShape3DSW::project_range(const Vector3 &p_normal, const Trans } } -Vector3 ConcavePolygonShape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 GodotConcavePolygonShape3D::get_support(const Vector3 &p_normal) const { int count = vertices.size(); if (count == 0) { return Vector3(); @@ -1281,7 +1281,7 @@ Vector3 ConcavePolygonShape3DSW::get_support(const Vector3 &p_normal) const { return vptr[vert_support_idx]; } -void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_params) const { +void GodotConcavePolygonShape3D::_cull_segment(int p_idx, _SegmentCullParams *p_params) const { const BVH *bvh = &p_params->bvh[p_idx]; /* @@ -1296,7 +1296,7 @@ void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_par if (bvh->face_index >= 0) { const Face *f = &p_params->faces[bvh->face_index]; - FaceShape3DSW *face = p_params->face; + GodotFaceShape3D *face = p_params->face; face->normal = f->normal; face->vertex[0] = p_params->vertices[f->indices[0]]; face->vertex[1] = p_params->vertices[f->indices[1]]; @@ -1323,7 +1323,7 @@ void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_par } } -bool ConcavePolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotConcavePolygonShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { if (faces.size() == 0) { return false; } @@ -1333,7 +1333,7 @@ bool ConcavePolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Ve const Vector3 *vr = vertices.ptr(); const BVH *br = bvh.ptr(); - FaceShape3DSW face; + GodotFaceShape3D face; face.backface_collision = backface_collision; _SegmentCullParams params; @@ -1359,15 +1359,15 @@ bool ConcavePolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Ve } } -bool ConcavePolygonShape3DSW::intersect_point(const Vector3 &p_point) const { +bool GodotConcavePolygonShape3D::intersect_point(const Vector3 &p_point) const { return false; //face is flat } -Vector3 ConcavePolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 GodotConcavePolygonShape3D::get_closest_point_to(const Vector3 &p_point) const { return Vector3(); } -bool ConcavePolygonShape3DSW::_cull(int p_idx, _CullParams *p_params) const { +bool GodotConcavePolygonShape3D::_cull(int p_idx, _CullParams *p_params) const { const BVH *bvh = &p_params->bvh[p_idx]; if (!p_params->aabb.intersects(bvh->aabb)) { @@ -1376,7 +1376,7 @@ bool ConcavePolygonShape3DSW::_cull(int p_idx, _CullParams *p_params) const { if (bvh->face_index >= 0) { const Face *f = &p_params->faces[bvh->face_index]; - FaceShape3DSW *face = p_params->face; + GodotFaceShape3D *face = p_params->face; face->normal = f->normal; face->vertex[0] = p_params->vertices[f->indices[0]]; face->vertex[1] = p_params->vertices[f->indices[1]]; @@ -1401,7 +1401,7 @@ bool ConcavePolygonShape3DSW::_cull(int p_idx, _CullParams *p_params) const { return false; } -void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const { +void GodotConcavePolygonShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const { // make matrix local to concave if (faces.size() == 0) { return; @@ -1414,7 +1414,7 @@ void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_cal const Vector3 *vr = vertices.ptr(); const BVH *br = bvh.ptr(); - FaceShape3DSW face; // use this to send in the callback + GodotFaceShape3D face; // use this to send in the callback face.backface_collision = backface_collision; _CullParams params; @@ -1430,7 +1430,7 @@ void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_cal _cull(0, ¶ms); } -Vector3 ConcavePolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const { +Vector3 GodotConcavePolygonShape3D::get_moment_of_inertia(real_t p_mass) const { // use bad AABB approximation Vector3 extents = get_aabb().size * 0.5; @@ -1440,40 +1440,40 @@ Vector3 ConcavePolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const { (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y)); } -struct _VolumeSW_BVH_Element { +struct _Volume_BVH_Element { AABB aabb; Vector3 center; int face_index; }; -struct _VolumeSW_BVH_CompareX { - _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const { +struct _Volume_BVH_CompareX { + _FORCE_INLINE_ bool operator()(const _Volume_BVH_Element &a, const _Volume_BVH_Element &b) const { return a.center.x < b.center.x; } }; -struct _VolumeSW_BVH_CompareY { - _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const { +struct _Volume_BVH_CompareY { + _FORCE_INLINE_ bool operator()(const _Volume_BVH_Element &a, const _Volume_BVH_Element &b) const { return a.center.y < b.center.y; } }; -struct _VolumeSW_BVH_CompareZ { - _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const { +struct _Volume_BVH_CompareZ { + _FORCE_INLINE_ bool operator()(const _Volume_BVH_Element &a, const _Volume_BVH_Element &b) const { return a.center.z < b.center.z; } }; -struct _VolumeSW_BVH { +struct _Volume_BVH { AABB aabb; - _VolumeSW_BVH *left; - _VolumeSW_BVH *right; + _Volume_BVH *left; + _Volume_BVH *right; int face_index; }; -_VolumeSW_BVH *_volume_sw_build_bvh(_VolumeSW_BVH_Element *p_elements, int p_size, int &count) { - _VolumeSW_BVH *bvh = memnew(_VolumeSW_BVH); +_Volume_BVH *_volume_build_bvh(_Volume_BVH_Element *p_elements, int p_size, int &count) { + _Volume_BVH *bvh = memnew(_Volume_BVH); if (p_size == 1) { //leaf @@ -1498,30 +1498,30 @@ _VolumeSW_BVH *_volume_sw_build_bvh(_VolumeSW_BVH_Element *p_elements, int p_siz bvh->aabb = aabb; switch (aabb.get_longest_axis_index()) { case 0: { - SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareX> sort_x; + SortArray<_Volume_BVH_Element, _Volume_BVH_CompareX> sort_x; sort_x.sort(p_elements, p_size); } break; case 1: { - SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareY> sort_y; + SortArray<_Volume_BVH_Element, _Volume_BVH_CompareY> sort_y; sort_y.sort(p_elements, p_size); } break; case 2: { - SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareZ> sort_z; + SortArray<_Volume_BVH_Element, _Volume_BVH_CompareZ> sort_z; sort_z.sort(p_elements, p_size); } break; } int split = p_size / 2; - bvh->left = _volume_sw_build_bvh(p_elements, split, count); - bvh->right = _volume_sw_build_bvh(&p_elements[split], p_size - split, count); + bvh->left = _volume_build_bvh(p_elements, split, count); + bvh->right = _volume_build_bvh(&p_elements[split], p_size - split, count); //printf("branch at %p - %i: %i\n",bvh,count,bvh->face_index); count++; return bvh; } -void ConcavePolygonShape3DSW::_fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx) { +void GodotConcavePolygonShape3D::_fill_bvh(_Volume_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx) { int idx = p_idx; p_bvh_array[idx].aabb = p_bvh_tree->aabb; @@ -1547,7 +1547,7 @@ void ConcavePolygonShape3DSW::_fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_ar memdelete(p_bvh_tree); } -void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_backface_collision) { +void GodotConcavePolygonShape3D::_setup(const Vector<Vector3> &p_faces, bool p_backface_collision) { int src_face_count = p_faces.size(); if (src_face_count == 0) { configure(AABB()); @@ -1558,10 +1558,10 @@ void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_back const Vector3 *facesr = p_faces.ptr(); - Vector<_VolumeSW_BVH_Element> bvh_array; + Vector<_Volume_BVH_Element> bvh_array; bvh_array.resize(src_face_count); - _VolumeSW_BVH_Element *bvh_arrayw = bvh_array.ptrw(); + _Volume_BVH_Element *bvh_arrayw = bvh_array.ptrw(); faces.resize(src_face_count); Face *facesw = faces.ptrw(); @@ -1593,7 +1593,7 @@ void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_back } int count = 0; - _VolumeSW_BVH *bvh_tree = _volume_sw_build_bvh(bvh_arrayw, src_face_count, count); + _Volume_BVH *bvh_tree = _volume_build_bvh(bvh_arrayw, src_face_count, count); bvh.resize(count + 1); @@ -1607,14 +1607,14 @@ void ConcavePolygonShape3DSW::_setup(const Vector<Vector3> &p_faces, bool p_back configure(_aabb); // this type of shape has no margin } -void ConcavePolygonShape3DSW::set_data(const Variant &p_data) { +void GodotConcavePolygonShape3D::set_data(const Variant &p_data) { Dictionary d = p_data; ERR_FAIL_COND(!d.has("faces")); _setup(d["faces"], d["backface_collision"]); } -Variant ConcavePolygonShape3DSW::get_data() const { +Variant GodotConcavePolygonShape3D::get_data() const { Dictionary d; d["faces"] = get_faces(); d["backface_collision"] = backface_collision; @@ -1622,29 +1622,29 @@ Variant ConcavePolygonShape3DSW::get_data() const { return d; } -ConcavePolygonShape3DSW::ConcavePolygonShape3DSW() { +GodotConcavePolygonShape3D::GodotConcavePolygonShape3D() { } /* HEIGHT MAP SHAPE */ -Vector<real_t> HeightMapShape3DSW::get_heights() const { +Vector<real_t> GodotHeightMapShape3D::get_heights() const { return heights; } -int HeightMapShape3DSW::get_width() const { +int GodotHeightMapShape3D::get_width() const { return width; } -int HeightMapShape3DSW::get_depth() const { +int GodotHeightMapShape3D::get_depth() const { return depth; } -void HeightMapShape3DSW::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { +void GodotHeightMapShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { //not very useful, but not very used either p_transform.xform(get_aabb()).project_range_in_plane(Plane(p_normal), r_min, r_max); } -Vector3 HeightMapShape3DSW::get_support(const Vector3 &p_normal) const { +Vector3 GodotHeightMapShape3D::get_support(const Vector3 &p_normal) const { //not very useful, but not very used either return get_aabb().get_support(p_normal); } @@ -1657,8 +1657,8 @@ struct _HeightmapSegmentCullParams { Vector3 result; Vector3 normal; - const HeightMapShape3DSW *heightmap = nullptr; - FaceShape3DSW *face = nullptr; + const GodotHeightMapShape3D *heightmap = nullptr; + GodotFaceShape3D *face = nullptr; }; struct _HeightmapGridCullState { @@ -1706,7 +1706,7 @@ _FORCE_INLINE_ bool _heightmap_cell_cull_segment(_HeightmapSegmentCullParams &p_ } _FORCE_INLINE_ bool _heightmap_chunk_cull_segment(_HeightmapSegmentCullParams &p_params, const _HeightmapGridCullState &p_state) { - const HeightMapShape3DSW::Range &chunk = p_params.heightmap->_get_bounds_chunk(p_state.x, p_state.z); + const GodotHeightMapShape3D::Range &chunk = p_params.heightmap->_get_bounds_chunk(p_state.x, p_state.z); Vector3 enter_pos; Vector3 exit_pos; @@ -1725,8 +1725,8 @@ _FORCE_INLINE_ bool _heightmap_chunk_cull_segment(_HeightmapSegmentCullParams &p } // Transform positions to heightmap space. - enter_pos *= HeightMapShape3DSW::BOUNDS_CHUNK_SIZE; - exit_pos *= HeightMapShape3DSW::BOUNDS_CHUNK_SIZE; + enter_pos *= GodotHeightMapShape3D::BOUNDS_CHUNK_SIZE; + exit_pos *= GodotHeightMapShape3D::BOUNDS_CHUNK_SIZE; // We did enter the flat projection of the AABB, // but we have to check if we intersect it on the vertical axis. @@ -1741,7 +1741,7 @@ _FORCE_INLINE_ bool _heightmap_chunk_cull_segment(_HeightmapSegmentCullParams &p } template <typename ProcessFunction> -bool HeightMapShape3DSW::_intersect_grid_segment(ProcessFunction &p_process, const Vector3 &p_begin, const Vector3 &p_end, int p_width, int p_depth, const Vector3 &offset, Vector3 &r_point, Vector3 &r_normal) const { +bool GodotHeightMapShape3D::_intersect_grid_segment(ProcessFunction &p_process, const Vector3 &p_begin, const Vector3 &p_end, int p_width, int p_depth, const Vector3 &offset, Vector3 &r_point, Vector3 &r_normal) const { Vector3 delta = (p_end - p_begin); real_t length = delta.length(); @@ -1751,7 +1751,7 @@ bool HeightMapShape3DSW::_intersect_grid_segment(ProcessFunction &p_process, con Vector3 local_begin = p_begin + offset; - FaceShape3DSW face; + GodotFaceShape3D face; face.backface_collision = false; _HeightmapSegmentCullParams params; @@ -1881,7 +1881,7 @@ bool HeightMapShape3DSW::_intersect_grid_segment(ProcessFunction &p_process, con return false; } -bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const { +bool GodotHeightMapShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const { if (heights.is_empty()) { return false; } @@ -1898,7 +1898,7 @@ bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 if ((begin_x == end_x) && (begin_z == end_z)) { // Simple case for rays that don't traverse the grid horizontally. // Just perform a test on the given cell. - FaceShape3DSW face; + GodotFaceShape3D face; face.backface_collision = false; _HeightmapSegmentCullParams params; @@ -1938,15 +1938,15 @@ bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 return false; } -bool HeightMapShape3DSW::intersect_point(const Vector3 &p_point) const { +bool GodotHeightMapShape3D::intersect_point(const Vector3 &p_point) const { return false; } -Vector3 HeightMapShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 GodotHeightMapShape3D::get_closest_point_to(const Vector3 &p_point) const { return Vector3(); } -void HeightMapShape3DSW::_get_cell(const Vector3 &p_point, int &r_x, int &r_y, int &r_z) const { +void GodotHeightMapShape3D::_get_cell(const Vector3 &p_point, int &r_x, int &r_y, int &r_z) const { const AABB &aabb = get_aabb(); Vector3 pos_local = aabb.position + local_origin; @@ -1961,7 +1961,7 @@ void HeightMapShape3DSW::_get_cell(const Vector3 &p_point, int &r_x, int &r_y, i r_z = (clamped_point.z < 0.0) ? (clamped_point.z - 0.5) : (clamped_point.z + 0.5); } -void HeightMapShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const { +void GodotHeightMapShape3D::cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const { if (heights.is_empty()) { return; } @@ -1987,7 +1987,7 @@ void HeightMapShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_callback int start_z = MAX(0, aabb_min[2]); int end_z = MIN(depth - 1, aabb_max[2]); - FaceShape3DSW face; + GodotFaceShape3D face; face.backface_collision = true; for (int z = start_z; z < end_z; z++) { @@ -2012,7 +2012,7 @@ void HeightMapShape3DSW::cull(const AABB &p_local_aabb, QueryCallback p_callback } } -Vector3 HeightMapShape3DSW::get_moment_of_inertia(real_t p_mass) const { +Vector3 GodotHeightMapShape3D::get_moment_of_inertia(real_t p_mass) const { // use bad AABB approximation Vector3 extents = get_aabb().size * 0.5; @@ -2022,7 +2022,7 @@ Vector3 HeightMapShape3DSW::get_moment_of_inertia(real_t p_mass) const { (p_mass / 3.0) * (extents.x * extents.x + extents.y * extents.y)); } -void HeightMapShape3DSW::_build_accelerator() { +void GodotHeightMapShape3D::_build_accelerator() { bounds_grid.clear(); bounds_grid_width = width / BOUNDS_CHUNK_SIZE; @@ -2091,7 +2091,7 @@ void HeightMapShape3DSW::_build_accelerator() { } } -void HeightMapShape3DSW::_setup(const Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) { +void GodotHeightMapShape3D::_setup(const Vector<real_t> &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) { heights = p_heights; width = p_width; depth = p_depth; @@ -2112,7 +2112,7 @@ void HeightMapShape3DSW::_setup(const Vector<real_t> &p_heights, int p_width, in configure(aabb); } -void HeightMapShape3DSW::set_data(const Variant &p_data) { +void GodotHeightMapShape3D::set_data(const Variant &p_data) { ERR_FAIL_COND(p_data.get_type() != Variant::DICTIONARY); Dictionary d = p_data; @@ -2184,7 +2184,7 @@ void HeightMapShape3DSW::set_data(const Variant &p_data) { _setup(heights_buffer, width, depth, min_height, max_height); } -Variant HeightMapShape3DSW::get_data() const { +Variant GodotHeightMapShape3D::get_data() const { Dictionary d; d["width"] = width; d["depth"] = depth; @@ -2198,5 +2198,5 @@ Variant HeightMapShape3DSW::get_data() const { return d; } -HeightMapShape3DSW::HeightMapShape3DSW() { +GodotHeightMapShape3D::GodotHeightMapShape3D() { } diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/godot_shape_3d.h index 061d66a085..8822d9487b 100644 --- a/servers/physics_3d/shape_3d_sw.h +++ b/servers/physics_3d/godot_shape_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* shape_3d_sw.h */ +/* godot_shape_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,30 +28,30 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHAPE_SW_H -#define SHAPE_SW_H +#ifndef GODOT_SHAPE_3D_H +#define GODOT_SHAPE_3D_H #include "core/math/geometry_3d.h" #include "core/templates/local_vector.h" #include "servers/physics_server_3d.h" -class Shape3DSW; +class GodotShape3D; -class ShapeOwner3DSW { +class GodotShapeOwner3D { public: virtual void _shape_changed() = 0; - virtual void remove_shape(Shape3DSW *p_shape) = 0; + virtual void remove_shape(GodotShape3D *p_shape) = 0; - virtual ~ShapeOwner3DSW() {} + virtual ~GodotShapeOwner3D() {} }; -class Shape3DSW { +class GodotShape3D { RID self; AABB aabb; bool configured = false; real_t custom_bias = 0.0; - Map<ShapeOwner3DSW *, int> owners; + Map<GodotShapeOwner3D *, int> owners; protected: void configure(const AABB &p_aabb); @@ -90,29 +90,29 @@ public: _FORCE_INLINE_ void set_custom_bias(real_t p_bias) { custom_bias = p_bias; } _FORCE_INLINE_ real_t get_custom_bias() const { return custom_bias; } - void add_owner(ShapeOwner3DSW *p_owner); - void remove_owner(ShapeOwner3DSW *p_owner); - bool is_owner(ShapeOwner3DSW *p_owner) const; - const Map<ShapeOwner3DSW *, int> &get_owners() const; + void add_owner(GodotShapeOwner3D *p_owner); + void remove_owner(GodotShapeOwner3D *p_owner); + bool is_owner(GodotShapeOwner3D *p_owner) const; + const Map<GodotShapeOwner3D *, int> &get_owners() const; - Shape3DSW() {} - virtual ~Shape3DSW(); + GodotShape3D() {} + virtual ~GodotShape3D(); }; -class ConcaveShape3DSW : public Shape3DSW { +class GodotConcaveShape3D : public GodotShape3D { public: virtual bool is_concave() const override { return true; } virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const override { r_amount = 0; } // Returns true to stop the query. - typedef bool (*QueryCallback)(void *p_userdata, Shape3DSW *p_convex); + typedef bool (*QueryCallback)(void *p_userdata, GodotShape3D *p_convex); virtual void cull(const AABB &p_local_aabb, QueryCallback p_callback, void *p_userdata) const = 0; - ConcaveShape3DSW() {} + GodotConcaveShape3D() {} }; -class WorldBoundaryShape3DSW : public Shape3DSW { +class GodotWorldBoundaryShape3D : public GodotShape3D { Plane plane; void _setup(const Plane &p_plane); @@ -134,10 +134,10 @@ public: virtual void set_data(const Variant &p_data) override; virtual Variant get_data() const override; - WorldBoundaryShape3DSW(); + GodotWorldBoundaryShape3D(); }; -class SeparationRayShape3DSW : public Shape3DSW { +class GodotSeparationRayShape3D : public GodotShape3D { real_t length = 1.0; bool slide_on_slope = false; @@ -162,10 +162,10 @@ public: virtual void set_data(const Variant &p_data) override; virtual Variant get_data() const override; - SeparationRayShape3DSW(); + GodotSeparationRayShape3D(); }; -class SphereShape3DSW : public Shape3DSW { +class GodotSphereShape3D : public GodotShape3D { real_t radius = 0.0; void _setup(real_t p_radius); @@ -189,10 +189,10 @@ public: virtual void set_data(const Variant &p_data) override; virtual Variant get_data() const override; - SphereShape3DSW(); + GodotSphereShape3D(); }; -class BoxShape3DSW : public Shape3DSW { +class GodotBoxShape3D : public GodotShape3D { Vector3 half_extents; void _setup(const Vector3 &p_half_extents); @@ -214,10 +214,10 @@ public: virtual void set_data(const Variant &p_data) override; virtual Variant get_data() const override; - BoxShape3DSW(); + GodotBoxShape3D(); }; -class CapsuleShape3DSW : public Shape3DSW { +class GodotCapsuleShape3D : public GodotShape3D { real_t height = 0.0; real_t radius = 0.0; @@ -243,10 +243,10 @@ public: virtual void set_data(const Variant &p_data) override; virtual Variant get_data() const override; - CapsuleShape3DSW(); + GodotCapsuleShape3D(); }; -class CylinderShape3DSW : public Shape3DSW { +class GodotCylinderShape3D : public GodotShape3D { real_t height = 0.0; real_t radius = 0.0; @@ -272,10 +272,10 @@ public: virtual void set_data(const Variant &p_data) override; virtual Variant get_data() const override; - CylinderShape3DSW(); + GodotCylinderShape3D(); }; -struct ConvexPolygonShape3DSW : public Shape3DSW { +struct GodotConvexPolygonShape3D : public GodotShape3D { Geometry3D::MeshData mesh; void _setup(const Vector<Vector3> &p_vertices); @@ -297,13 +297,13 @@ public: virtual void set_data(const Variant &p_data) override; virtual Variant get_data() const override; - ConvexPolygonShape3DSW(); + GodotConvexPolygonShape3D(); }; -struct _VolumeSW_BVH; -struct FaceShape3DSW; +struct _Volume_BVH; +struct GodotFaceShape3D; -struct ConcavePolygonShape3DSW : public ConcaveShape3DSW { +struct GodotConcavePolygonShape3D : public GodotConcaveShape3D { // always a trimesh struct Face { @@ -331,7 +331,7 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW { const Face *faces = nullptr; const Vector3 *vertices = nullptr; const BVH *bvh = nullptr; - FaceShape3DSW *face = nullptr; + GodotFaceShape3D *face = nullptr; }; struct _SegmentCullParams { @@ -341,7 +341,7 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW { const Face *faces = nullptr; const Vector3 *vertices = nullptr; const BVH *bvh = nullptr; - FaceShape3DSW *face = nullptr; + GodotFaceShape3D *face = nullptr; Vector3 result; Vector3 normal; @@ -354,7 +354,7 @@ struct ConcavePolygonShape3DSW : public ConcaveShape3DSW { void _cull_segment(int p_idx, _SegmentCullParams *p_params) const; bool _cull(int p_idx, _CullParams *p_params) const; - void _fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx); + void _fill_bvh(_Volume_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx); void _setup(const Vector<Vector3> &p_faces, bool p_backface_collision); @@ -377,10 +377,10 @@ public: virtual void set_data(const Variant &p_data) override; virtual Variant get_data() const override; - ConcavePolygonShape3DSW(); + GodotConcavePolygonShape3D(); }; -struct HeightMapShape3DSW : public ConcaveShape3DSW { +struct GodotHeightMapShape3D : public GodotConcaveShape3D { Vector<real_t> heights; int width = 0; int depth = 0; @@ -440,11 +440,11 @@ public: virtual void set_data(const Variant &p_data) override; virtual Variant get_data() const override; - HeightMapShape3DSW(); + GodotHeightMapShape3D(); }; //used internally -struct FaceShape3DSW : public Shape3DSW { +struct GodotFaceShape3D : public GodotShape3D { Vector3 normal; //cache Vector3 vertex[3]; bool backface_collision = false; @@ -465,11 +465,11 @@ struct FaceShape3DSW : public Shape3DSW { virtual void set_data(const Variant &p_data) override {} virtual Variant get_data() const override { return Variant(); } - FaceShape3DSW(); + GodotFaceShape3D(); }; -struct MotionShape3DSW : public Shape3DSW { - Shape3DSW *shape = nullptr; +struct GodotMotionShape3D : public GodotShape3D { + GodotShape3D *shape = nullptr; Vector3 motion; virtual PhysicsServer3D::ShapeType get_type() const override { return PhysicsServer3D::SHAPE_CONVEX_POLYGON; } @@ -504,7 +504,7 @@ struct MotionShape3DSW : public Shape3DSW { virtual void set_data(const Variant &p_data) override {} virtual Variant get_data() const override { return Variant(); } - MotionShape3DSW() { configure(AABB()); } + GodotMotionShape3D() { configure(AABB()); } }; -#endif // SHAPE_SW_H +#endif // GODOT_SHAPE_3D_H diff --git a/servers/physics_3d/soft_body_3d_sw.cpp b/servers/physics_3d/godot_soft_body_3d.cpp index c9166810fe..f214e3603a 100644 --- a/servers/physics_3d/soft_body_3d_sw.cpp +++ b/servers/physics_3d/godot_soft_body_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* soft_body_3d_sw.cpp */ +/* godot_soft_body_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "soft_body_3d_sw.h" -#include "space_3d_sw.h" +#include "godot_soft_body_3d.h" + +#include "godot_space_3d.h" #include "core/math/geometry_3d.h" #include "core/templates/map.h" @@ -53,16 +54,16 @@ subject to the following restrictions: */ ///btSoftBody implementation by Nathanael Presson -SoftBody3DSW::SoftBody3DSW() : - CollisionObject3DSW(TYPE_SOFT_BODY), +GodotSoftBody3D::GodotSoftBody3D() : + GodotCollisionObject3D(TYPE_SOFT_BODY), active_list(this) { _set_static(false); } -void SoftBody3DSW::_shapes_changed() { +void GodotSoftBody3D::_shapes_changed() { } -void SoftBody3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) { +void GodotSoftBody3D::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) { switch (p_state) { case PhysicsServer3D::BODY_STATE_TRANSFORM: { _set_transform(p_variant); @@ -87,7 +88,7 @@ void SoftBody3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant & } } -Variant SoftBody3DSW::get_state(PhysicsServer3D::BodyState p_state) const { +Variant GodotSoftBody3D::get_state(PhysicsServer3D::BodyState p_state) const { switch (p_state) { case PhysicsServer3D::BODY_STATE_TRANSFORM: { return get_transform(); @@ -110,7 +111,7 @@ Variant SoftBody3DSW::get_state(PhysicsServer3D::BodyState p_state) const { return Variant(); } -void SoftBody3DSW::set_space(Space3DSW *p_space) { +void GodotSoftBody3D::set_space(GodotSpace3D *p_space) { if (get_space()) { get_space()->soft_body_remove_from_active_list(&active_list); @@ -128,7 +129,7 @@ void SoftBody3DSW::set_space(Space3DSW *p_space) { } } -void SoftBody3DSW::set_mesh(RID p_mesh) { +void GodotSoftBody3D::set_mesh(RID p_mesh) { destroy(); soft_mesh = p_mesh; @@ -138,6 +139,7 @@ void SoftBody3DSW::set_mesh(RID p_mesh) { } Array arrays = RenderingServer::get_singleton()->mesh_surface_get_arrays(soft_mesh, 0); + ERR_FAIL_COND(arrays.is_empty()); bool success = create_from_trimesh(arrays[RenderingServer::ARRAY_INDEX], arrays[RenderingServer::ARRAY_VERTEX]); if (!success) { @@ -145,7 +147,7 @@ void SoftBody3DSW::set_mesh(RID p_mesh) { } } -void SoftBody3DSW::update_rendering_server(RenderingServerHandler *p_rendering_server_handler) { +void GodotSoftBody3D::update_rendering_server(RenderingServerHandler *p_rendering_server_handler) { if (soft_mesh.is_null()) { return; } @@ -164,7 +166,7 @@ void SoftBody3DSW::update_rendering_server(RenderingServerHandler *p_rendering_s p_rendering_server_handler->set_aabb(bounds); } -void SoftBody3DSW::update_normals_and_centroids() { +void GodotSoftBody3D::update_normals_and_centroids() { uint32_t i, ni; for (i = 0, ni = nodes.size(); i < ni; ++i) { @@ -191,7 +193,7 @@ void SoftBody3DSW::update_normals_and_centroids() { } } -void SoftBody3DSW::update_bounds() { +void GodotSoftBody3D::update_bounds() { AABB prev_bounds = bounds; prev_bounds.grow_by(collision_margin); @@ -223,13 +225,13 @@ void SoftBody3DSW::update_bounds() { } } -void SoftBody3DSW::update_constants() { +void GodotSoftBody3D::update_constants() { reset_link_rest_lengths(); update_link_constants(); update_area(); } -void SoftBody3DSW::update_area() { +void GodotSoftBody3D::update_area() { int i, ni; // Face area. @@ -275,7 +277,7 @@ void SoftBody3DSW::update_area() { } } -void SoftBody3DSW::reset_link_rest_lengths() { +void GodotSoftBody3D::reset_link_rest_lengths() { for (uint32_t i = 0, ni = links.size(); i < ni; ++i) { Link &link = links[i]; link.rl = (link.n[0]->x - link.n[1]->x).length(); @@ -283,7 +285,7 @@ void SoftBody3DSW::reset_link_rest_lengths() { } } -void SoftBody3DSW::update_link_constants() { +void GodotSoftBody3D::update_link_constants() { real_t inv_linear_stiffness = 1.0 / linear_stiffness; for (uint32_t i = 0, ni = links.size(); i < ni; ++i) { Link &link = links[i]; @@ -291,7 +293,7 @@ void SoftBody3DSW::update_link_constants() { } } -void SoftBody3DSW::apply_nodes_transform(const Transform3D &p_transform) { +void GodotSoftBody3D::apply_nodes_transform(const Transform3D &p_transform) { if (soft_mesh.is_null()) { return; } @@ -317,7 +319,7 @@ void SoftBody3DSW::apply_nodes_transform(const Transform3D &p_transform) { update_constants(); } -Vector3 SoftBody3DSW::get_vertex_position(int p_index) const { +Vector3 GodotSoftBody3D::get_vertex_position(int p_index) const { ERR_FAIL_COND_V(p_index < 0, Vector3()); if (soft_mesh.is_null()) { @@ -331,7 +333,7 @@ Vector3 SoftBody3DSW::get_vertex_position(int p_index) const { return nodes[node_index].x; } -void SoftBody3DSW::set_vertex_position(int p_index, const Vector3 &p_position) { +void GodotSoftBody3D::set_vertex_position(int p_index, const Vector3 &p_position) { ERR_FAIL_COND(p_index < 0); if (soft_mesh.is_null()) { @@ -347,7 +349,7 @@ void SoftBody3DSW::set_vertex_position(int p_index, const Vector3 &p_position) { node.x = p_position; } -void SoftBody3DSW::pin_vertex(int p_index) { +void GodotSoftBody3D::pin_vertex(int p_index) { ERR_FAIL_COND(p_index < 0); if (is_vertex_pinned(p_index)) { @@ -366,7 +368,7 @@ void SoftBody3DSW::pin_vertex(int p_index) { } } -void SoftBody3DSW::unpin_vertex(int p_index) { +void GodotSoftBody3D::unpin_vertex(int p_index) { ERR_FAIL_COND(p_index < 0); uint32_t pinned_count = pinned_vertices.size(); @@ -390,7 +392,7 @@ void SoftBody3DSW::unpin_vertex(int p_index) { } } -void SoftBody3DSW::unpin_all_vertices() { +void GodotSoftBody3D::unpin_all_vertices() { if (!soft_mesh.is_null()) { real_t inv_node_mass = nodes.size() * inv_total_mass; uint32_t pinned_count = pinned_vertices.size(); @@ -409,7 +411,7 @@ void SoftBody3DSW::unpin_all_vertices() { pinned_vertices.clear(); } -bool SoftBody3DSW::is_vertex_pinned(int p_index) const { +bool GodotSoftBody3D::is_vertex_pinned(int p_index) const { ERR_FAIL_COND_V(p_index < 0, false); uint32_t pinned_count = pinned_vertices.size(); @@ -422,47 +424,47 @@ bool SoftBody3DSW::is_vertex_pinned(int p_index) const { return false; } -uint32_t SoftBody3DSW::get_node_count() const { +uint32_t GodotSoftBody3D::get_node_count() const { return nodes.size(); } -real_t SoftBody3DSW::get_node_inv_mass(uint32_t p_node_index) const { +real_t GodotSoftBody3D::get_node_inv_mass(uint32_t p_node_index) const { ERR_FAIL_COND_V(p_node_index >= nodes.size(), 0.0); return nodes[p_node_index].im; } -Vector3 SoftBody3DSW::get_node_position(uint32_t p_node_index) const { +Vector3 GodotSoftBody3D::get_node_position(uint32_t p_node_index) const { ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3()); return nodes[p_node_index].x; } -Vector3 SoftBody3DSW::get_node_velocity(uint32_t p_node_index) const { +Vector3 GodotSoftBody3D::get_node_velocity(uint32_t p_node_index) const { ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3()); return nodes[p_node_index].v; } -Vector3 SoftBody3DSW::get_node_biased_velocity(uint32_t p_node_index) const { +Vector3 GodotSoftBody3D::get_node_biased_velocity(uint32_t p_node_index) const { ERR_FAIL_COND_V(p_node_index >= nodes.size(), Vector3()); return nodes[p_node_index].bv; } -void SoftBody3DSW::apply_node_impulse(uint32_t p_node_index, const Vector3 &p_impulse) { +void GodotSoftBody3D::apply_node_impulse(uint32_t p_node_index, const Vector3 &p_impulse) { ERR_FAIL_COND(p_node_index >= nodes.size()); Node &node = nodes[p_node_index]; node.v += p_impulse * node.im; } -void SoftBody3DSW::apply_node_bias_impulse(uint32_t p_node_index, const Vector3 &p_impulse) { +void GodotSoftBody3D::apply_node_bias_impulse(uint32_t p_node_index, const Vector3 &p_impulse) { ERR_FAIL_COND(p_node_index >= nodes.size()); Node &node = nodes[p_node_index]; node.bv += p_impulse * node.im; } -uint32_t SoftBody3DSW::get_face_count() const { +uint32_t GodotSoftBody3D::get_face_count() const { return faces.size(); } -void SoftBody3DSW::get_face_points(uint32_t p_face_index, Vector3 &r_point_1, Vector3 &r_point_2, Vector3 &r_point_3) const { +void GodotSoftBody3D::get_face_points(uint32_t p_face_index, Vector3 &r_point_1, Vector3 &r_point_2, Vector3 &r_point_3) const { ERR_FAIL_COND(p_face_index >= faces.size()); const Face &face = faces[p_face_index]; r_point_1 = face.n[0]->x; @@ -470,12 +472,12 @@ void SoftBody3DSW::get_face_points(uint32_t p_face_index, Vector3 &r_point_1, Ve r_point_3 = face.n[2]->x; } -Vector3 SoftBody3DSW::get_face_normal(uint32_t p_face_index) const { +Vector3 GodotSoftBody3D::get_face_normal(uint32_t p_face_index) const { ERR_FAIL_COND_V(p_face_index >= faces.size(), Vector3()); return faces[p_face_index].normal; } -bool SoftBody3DSW::create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices) { +bool GodotSoftBody3D::create_from_trimesh(const Vector<int> &p_indices, const Vector<Vector3> &p_vertices) { ERR_FAIL_COND_V(p_indices.is_empty(), false); ERR_FAIL_COND_V(p_vertices.is_empty(), false); @@ -595,7 +597,7 @@ bool SoftBody3DSW::create_from_trimesh(const Vector<int> &p_indices, const Vecto return true; } -void SoftBody3DSW::generate_bending_constraints(int p_distance) { +void GodotSoftBody3D::generate_bending_constraints(int p_distance) { uint32_t i, j; if (p_distance > 1) { @@ -714,7 +716,7 @@ public: }; typedef LinkDeps *LinkDepsPtr; -void SoftBody3DSW::reoptimize_link_order() { +void GodotSoftBody3D::reoptimize_link_order() { const int reop_not_dependent = -1; const int reop_node_complete = -2; @@ -823,7 +825,7 @@ void SoftBody3DSW::reoptimize_link_order() { memdelete_arr(link_buffer); } -void SoftBody3DSW::append_link(uint32_t p_node1, uint32_t p_node2) { +void GodotSoftBody3D::append_link(uint32_t p_node1, uint32_t p_node2) { if (p_node1 == p_node2) { return; } @@ -839,7 +841,7 @@ void SoftBody3DSW::append_link(uint32_t p_node1, uint32_t p_node2) { links.push_back(link); } -void SoftBody3DSW::append_face(uint32_t p_node1, uint32_t p_node2, uint32_t p_node3) { +void GodotSoftBody3D::append_face(uint32_t p_node1, uint32_t p_node2, uint32_t p_node3) { if (p_node1 == p_node2) { return; } @@ -864,11 +866,11 @@ void SoftBody3DSW::append_face(uint32_t p_node1, uint32_t p_node2, uint32_t p_no faces.push_back(face); } -void SoftBody3DSW::set_iteration_count(int p_val) { +void GodotSoftBody3D::set_iteration_count(int p_val) { iteration_count = p_val; } -void SoftBody3DSW::set_total_mass(real_t p_val) { +void GodotSoftBody3D::set_total_mass(real_t p_val) { ERR_FAIL_COND(p_val < 0.0); inv_total_mass = 1.0 / p_val; @@ -884,27 +886,27 @@ void SoftBody3DSW::set_total_mass(real_t p_val) { update_constants(); } -void SoftBody3DSW::set_collision_margin(real_t p_val) { +void GodotSoftBody3D::set_collision_margin(real_t p_val) { collision_margin = p_val; } -void SoftBody3DSW::set_linear_stiffness(real_t p_val) { +void GodotSoftBody3D::set_linear_stiffness(real_t p_val) { linear_stiffness = p_val; } -void SoftBody3DSW::set_pressure_coefficient(real_t p_val) { +void GodotSoftBody3D::set_pressure_coefficient(real_t p_val) { pressure_coefficient = p_val; } -void SoftBody3DSW::set_damping_coefficient(real_t p_val) { +void GodotSoftBody3D::set_damping_coefficient(real_t p_val) { damping_coefficient = p_val; } -void SoftBody3DSW::set_drag_coefficient(real_t p_val) { +void GodotSoftBody3D::set_drag_coefficient(real_t p_val) { drag_coefficient = p_val; } -void SoftBody3DSW::add_velocity(const Vector3 &p_velocity) { +void GodotSoftBody3D::add_velocity(const Vector3 &p_velocity) { for (uint32_t i = 0, ni = nodes.size(); i < ni; ++i) { Node &node = nodes[i]; if (node.im > 0) { @@ -913,7 +915,7 @@ void SoftBody3DSW::add_velocity(const Vector3 &p_velocity) { } } -void SoftBody3DSW::apply_forces(bool p_has_wind_forces) { +void GodotSoftBody3D::apply_forces(bool p_has_wind_forces) { int ac = areas.size(); if (nodes.is_empty()) { @@ -977,13 +979,13 @@ void SoftBody3DSW::apply_forces(bool p_has_wind_forces) { } } -void SoftBody3DSW::_compute_area_gravity(const Area3DSW *p_area) { +void GodotSoftBody3D::_compute_area_gravity(const GodotArea3D *p_area) { Vector3 area_gravity; p_area->compute_gravity(get_transform().get_origin(), area_gravity); gravity += area_gravity; } -Vector3 SoftBody3DSW::_compute_area_windforce(const Area3DSW *p_area, const Face *p_face) { +Vector3 GodotSoftBody3D::_compute_area_windforce(const GodotArea3D *p_area, const Face *p_face) { real_t wfm = p_area->get_wind_force_magnitude(); real_t waf = p_area->get_wind_attenuation_factor(); const Vector3 &wd = p_area->get_wind_direction(); @@ -995,12 +997,12 @@ Vector3 SoftBody3DSW::_compute_area_windforce(const Area3DSW *p_area, const Face return nodal_force_magnitude * p_face->normal; } -void SoftBody3DSW::predict_motion(real_t p_delta) { +void GodotSoftBody3D::predict_motion(real_t p_delta) { const real_t inv_delta = 1.0 / p_delta; ERR_FAIL_COND(!get_space()); - Area3DSW *def_area = get_space()->get_default_area(); + GodotArea3D *def_area = get_space()->get_default_area(); ERR_FAIL_COND(!def_area); gravity = def_area->get_gravity_vector() * def_area->get_gravity(); @@ -1083,7 +1085,7 @@ void SoftBody3DSW::predict_motion(real_t p_delta) { face_tree.optimize_incremental(1); } -void SoftBody3DSW::solve_constraints(real_t p_delta) { +void GodotSoftBody3D::solve_constraints(real_t p_delta) { const real_t inv_delta = 1.0 / p_delta; uint32_t i, ni; @@ -1120,7 +1122,7 @@ void SoftBody3DSW::solve_constraints(real_t p_delta) { update_normals_and_centroids(); } -void SoftBody3DSW::solve_links(real_t kst, real_t ti) { +void GodotSoftBody3D::solve_links(real_t kst, real_t ti) { for (uint32_t i = 0, ni = links.size(); i < ni; ++i) { Link &link = links[i]; if (link.c0 > 0) { @@ -1138,16 +1140,16 @@ void SoftBody3DSW::solve_links(real_t kst, real_t ti) { } struct AABBQueryResult { - const SoftBody3DSW *soft_body = nullptr; + const GodotSoftBody3D *soft_body = nullptr; void *userdata = nullptr; - SoftBody3DSW::QueryResultCallback result_callback = nullptr; + GodotSoftBody3D::QueryResultCallback result_callback = nullptr; _FORCE_INLINE_ bool operator()(void *p_data) { return result_callback(soft_body->get_node_index(p_data), userdata); }; }; -void SoftBody3DSW::query_aabb(const AABB &p_aabb, SoftBody3DSW::QueryResultCallback p_result_callback, void *p_userdata) { +void GodotSoftBody3D::query_aabb(const AABB &p_aabb, GodotSoftBody3D::QueryResultCallback p_result_callback, void *p_userdata) { AABBQueryResult query_result; query_result.soft_body = this; query_result.result_callback = p_result_callback; @@ -1157,16 +1159,16 @@ void SoftBody3DSW::query_aabb(const AABB &p_aabb, SoftBody3DSW::QueryResultCallb } struct RayQueryResult { - const SoftBody3DSW *soft_body = nullptr; + const GodotSoftBody3D *soft_body = nullptr; void *userdata = nullptr; - SoftBody3DSW::QueryResultCallback result_callback = nullptr; + GodotSoftBody3D::QueryResultCallback result_callback = nullptr; _FORCE_INLINE_ bool operator()(void *p_data) { return result_callback(soft_body->get_face_index(p_data), userdata); }; }; -void SoftBody3DSW::query_ray(const Vector3 &p_from, const Vector3 &p_to, SoftBody3DSW::QueryResultCallback p_result_callback, void *p_userdata) { +void GodotSoftBody3D::query_ray(const Vector3 &p_from, const Vector3 &p_to, GodotSoftBody3D::QueryResultCallback p_result_callback, void *p_userdata) { if (face_tree.is_empty()) { initialize_face_tree(); } @@ -1179,7 +1181,7 @@ void SoftBody3DSW::query_ray(const Vector3 &p_from, const Vector3 &p_to, SoftBod face_tree.ray_query(p_from, p_to, query_result); } -void SoftBody3DSW::initialize_face_tree() { +void GodotSoftBody3D::initialize_face_tree() { face_tree.clear(); for (uint32_t i = 0; i < faces.size(); ++i) { Face &face = faces[i]; @@ -1196,7 +1198,7 @@ void SoftBody3DSW::initialize_face_tree() { } } -void SoftBody3DSW::update_face_tree(real_t p_delta) { +void GodotSoftBody3D::update_face_tree(real_t p_delta) { for (uint32_t i = 0; i < faces.size(); ++i) { const Face &face = faces[i]; @@ -1220,25 +1222,25 @@ void SoftBody3DSW::update_face_tree(real_t p_delta) { } } -void SoftBody3DSW::initialize_shape(bool p_force_move) { +void GodotSoftBody3D::initialize_shape(bool p_force_move) { if (get_shape_count() == 0) { - SoftBodyShape3DSW *soft_body_shape = memnew(SoftBodyShape3DSW(this)); + GodotSoftBodyShape3D *soft_body_shape = memnew(GodotSoftBodyShape3D(this)); add_shape(soft_body_shape); } else if (p_force_move) { - SoftBodyShape3DSW *soft_body_shape = static_cast<SoftBodyShape3DSW *>(get_shape(0)); + GodotSoftBodyShape3D *soft_body_shape = static_cast<GodotSoftBodyShape3D *>(get_shape(0)); soft_body_shape->update_bounds(); } } -void SoftBody3DSW::deinitialize_shape() { +void GodotSoftBody3D::deinitialize_shape() { if (get_shape_count() > 0) { - Shape3DSW *shape = get_shape(0); + GodotShape3D *shape = get_shape(0); remove_shape(shape); memdelete(shape); } } -void SoftBody3DSW::destroy() { +void GodotSoftBody3D::destroy() { soft_mesh = RID(); map_visual_to_physics.clear(); @@ -1254,7 +1256,7 @@ void SoftBody3DSW::destroy() { deinitialize_shape(); } -void SoftBodyShape3DSW::update_bounds() { +void GodotSoftBodyShape3D::update_bounds() { ERR_FAIL_COND(!soft_body); AABB collision_aabb = soft_body->get_bounds(); @@ -1262,13 +1264,13 @@ void SoftBodyShape3DSW::update_bounds() { configure(collision_aabb); } -SoftBodyShape3DSW::SoftBodyShape3DSW(SoftBody3DSW *p_soft_body) { +GodotSoftBodyShape3D::GodotSoftBodyShape3D(GodotSoftBody3D *p_soft_body) { soft_body = p_soft_body; update_bounds(); } struct _SoftBodyIntersectSegmentInfo { - const SoftBody3DSW *soft_body = nullptr; + const GodotSoftBody3D *soft_body = nullptr; Vector3 from; Vector3 dir; Vector3 hit_position; @@ -1296,7 +1298,7 @@ struct _SoftBodyIntersectSegmentInfo { } }; -bool SoftBodyShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { +bool GodotSoftBodyShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { _SoftBodyIntersectSegmentInfo query_info; query_info.soft_body = soft_body; query_info.from = p_begin; @@ -1313,10 +1315,10 @@ bool SoftBodyShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 return false; } -bool SoftBodyShape3DSW::intersect_point(const Vector3 &p_point) const { +bool GodotSoftBodyShape3D::intersect_point(const Vector3 &p_point) const { return false; } -Vector3 SoftBodyShape3DSW::get_closest_point_to(const Vector3 &p_point) const { +Vector3 GodotSoftBodyShape3D::get_closest_point_to(const Vector3 &p_point) const { ERR_FAIL_V_MSG(Vector3(), "Get closest point is not supported for soft bodies."); } diff --git a/servers/physics_3d/soft_body_3d_sw.h b/servers/physics_3d/godot_soft_body_3d.h index 7d4b83d0ee..008d5dddb8 100644 --- a/servers/physics_3d/soft_body_3d_sw.h +++ b/servers/physics_3d/godot_soft_body_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* soft_body_3d_sw.h */ +/* godot_soft_body_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SOFT_BODY_3D_SW_H -#define SOFT_BODY_3D_SW_H +#ifndef GODOT_SOFT_BODY_3D_H +#define GODOT_SOFT_BODY_3D_H -#include "area_3d_sw.h" -#include "collision_object_3d_sw.h" +#include "godot_area_3d.h" +#include "godot_collision_object_3d.h" #include "core/math/aabb.h" #include "core/math/dynamic_bvh.h" @@ -41,9 +41,9 @@ #include "core/templates/set.h" #include "core/templates/vset.h" -class Constraint3DSW; +class GodotConstraint3D; -class SoftBody3DSW : public CollisionObject3DSW { +class GodotSoftBody3D : public GodotCollisionObject3D { RID soft_mesh; struct Node { @@ -103,9 +103,9 @@ class SoftBody3DSW : public CollisionObject3DSW { Vector3 gravity; - SelfList<SoftBody3DSW> active_list; + SelfList<GodotSoftBody3D> active_list; - Set<Constraint3DSW *> constraints; + Set<GodotConstraint3D *> constraints; Vector<AreaCMP> areas; @@ -113,20 +113,20 @@ class SoftBody3DSW : public CollisionObject3DSW { uint64_t island_step = 0; - _FORCE_INLINE_ void _compute_area_gravity(const Area3DSW *p_area); - _FORCE_INLINE_ Vector3 _compute_area_windforce(const Area3DSW *p_area, const Face *p_face); + _FORCE_INLINE_ void _compute_area_gravity(const GodotArea3D *p_area); + _FORCE_INLINE_ Vector3 _compute_area_windforce(const GodotArea3D *p_area, const Face *p_face); public: - SoftBody3DSW(); + GodotSoftBody3D(); const AABB &get_bounds() const { return bounds; } void set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant); Variant get_state(PhysicsServer3D::BodyState p_state) const; - _FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint) { constraints.insert(p_constraint); } - _FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraints.erase(p_constraint); } - _FORCE_INLINE_ const Set<Constraint3DSW *> &get_constraints() const { return constraints; } + _FORCE_INLINE_ void add_constraint(GodotConstraint3D *p_constraint) { constraints.insert(p_constraint); } + _FORCE_INLINE_ void remove_constraint(GodotConstraint3D *p_constraint) { constraints.erase(p_constraint); } + _FORCE_INLINE_ const Set<GodotConstraint3D *> &get_constraints() const { return constraints; } _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } _FORCE_INLINE_ void add_exception(const RID &p_exception) { exceptions.insert(p_exception); } @@ -137,7 +137,7 @@ public: _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } - _FORCE_INLINE_ void add_area(Area3DSW *p_area) { + _FORCE_INLINE_ void add_area(GodotArea3D *p_area) { int index = areas.find(AreaCMP(p_area)); if (index > -1) { areas.write[index].refCount += 1; @@ -146,7 +146,7 @@ public: } } - _FORCE_INLINE_ void remove_area(Area3DSW *p_area) { + _FORCE_INLINE_ void remove_area(GodotArea3D *p_area) { int index = areas.find(AreaCMP(p_area)); if (index > -1) { areas.write[index].refCount -= 1; @@ -156,7 +156,7 @@ public: } } - virtual void set_space(Space3DSW *p_space); + virtual void set_space(GodotSpace3D *p_space); void set_mesh(RID p_mesh); @@ -251,11 +251,11 @@ private: void destroy(); }; -class SoftBodyShape3DSW : public Shape3DSW { - SoftBody3DSW *soft_body = nullptr; +class GodotSoftBodyShape3D : public GodotShape3D { + GodotSoftBody3D *soft_body = nullptr; public: - SoftBody3DSW *get_soft_body() const { return soft_body; } + GodotSoftBody3D *get_soft_body() const { return soft_body; } virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_SOFT_BODY; } virtual void project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const { r_min = r_max = 0.0; } @@ -272,8 +272,8 @@ public: void update_bounds(); - SoftBodyShape3DSW(SoftBody3DSW *p_soft_body); - ~SoftBodyShape3DSW() {} + GodotSoftBodyShape3D(GodotSoftBody3D *p_soft_body); + ~GodotSoftBodyShape3D() {} }; -#endif // SOFT_BODY_3D_SW_H +#endif // GODOT_SOFT_BODY_3D_H diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/godot_space_3d.cpp index c88747c017..750bf3a16d 100644 --- a/servers/physics_3d/space_3d_sw.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* space_3d_sw.cpp */ +/* godot_space_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,37 +28,38 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "space_3d_sw.h" +#include "godot_space_3d.h" + +#include "godot_collision_solver_3d.h" +#include "godot_physics_server_3d.h" -#include "collision_solver_3d_sw.h" #include "core/config/project_settings.h" -#include "physics_server_3d_sw.h" #define TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR 0.05 -_FORCE_INLINE_ static bool _can_collide_with(CollisionObject3DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +_FORCE_INLINE_ static bool _can_collide_with(GodotCollisionObject3D *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (!(p_object->get_collision_layer() & p_collision_mask)) { return false; } - if (p_object->get_type() == CollisionObject3DSW::TYPE_AREA && !p_collide_with_areas) { + if (p_object->get_type() == GodotCollisionObject3D::TYPE_AREA && !p_collide_with_areas) { return false; } - if (p_object->get_type() == CollisionObject3DSW::TYPE_BODY && !p_collide_with_bodies) { + if (p_object->get_type() == GodotCollisionObject3D::TYPE_BODY && !p_collide_with_bodies) { return false; } - if (p_object->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY && !p_collide_with_bodies) { + if (p_object->get_type() == GodotCollisionObject3D::TYPE_SOFT_BODY && !p_collide_with_bodies) { return false; } return true; } -int PhysicsDirectSpaceState3DSW::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +int GodotPhysicsDirectSpaceState3D::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { ERR_FAIL_COND_V(space->locked, false); - int amount = space->broadphase->cull_point(p_point, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_point(p_point, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); int cc = 0; //Transform3D ai = p_xform.affine_inverse(); @@ -78,7 +79,7 @@ int PhysicsDirectSpaceState3DSW::intersect_point(const Vector3 &p_point, ShapeRe continue; } - const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; int shape_idx = space->intersection_query_subindex_results[i]; Transform3D inv_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); @@ -103,7 +104,7 @@ int PhysicsDirectSpaceState3DSW::intersect_point(const Vector3 &p_point, ShapeRe return cc; } -bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) { +bool GodotPhysicsDirectSpaceState3D::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) { ERR_FAIL_COND_V(space->locked, false); Vector3 begin, end; @@ -112,14 +113,14 @@ bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vec end = p_to; normal = (end - begin).normalized(); - int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); //todo, create another array that references results, compute AABBs and check closest point to ray origin, sort, and stop evaluating results when beyond first collision bool collided = false; Vector3 res_point, res_normal; int res_shape; - const CollisionObject3DSW *res_obj; + const GodotCollisionObject3D *res_obj; real_t min_d = 1e10; for (int i = 0; i < amount; i++) { @@ -135,7 +136,7 @@ bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vec continue; } - const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; int shape_idx = space->intersection_query_subindex_results[i]; Transform3D inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform(); @@ -143,7 +144,7 @@ bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vec Vector3 local_from = inv_xform.xform(begin); Vector3 local_to = inv_xform.xform(end); - const Shape3DSW *shape = col_obj->get_shape(shape_idx); + const GodotShape3D *shape = col_obj->get_shape(shape_idx); Vector3 shape_point, shape_normal; @@ -182,17 +183,17 @@ bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vec return true; } -int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +int GodotPhysicsDirectSpaceState3D::intersect_shape(const RID &p_shape, const Transform3D &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (p_result_max <= 0) { return 0; } - Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape); + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); ERR_FAIL_COND_V(!shape, 0); AABB aabb = p_xform.xform(shape->get_aabb()); - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); int cc = 0; @@ -213,10 +214,10 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans continue; } - const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; int shape_idx = space->intersection_query_subindex_results[i]; - if (!CollisionSolver3DSW::solve_static(shape, p_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), nullptr, nullptr, nullptr, p_margin, 0)) { + if (!GodotCollisionSolver3D::solve_static(shape, p_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), nullptr, nullptr, nullptr, p_margin, 0)) { continue; } @@ -237,21 +238,21 @@ int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Trans return cc; } -bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) { - Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState3D::cast_motion(const RID &p_shape, const Transform3D &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) { + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); ERR_FAIL_COND_V(!shape, false); AABB aabb = p_xform.xform(shape->get_aabb()); aabb = aabb.merge(AABB(aabb.position + p_motion, aabb.size)); //motion aabb = aabb.grow(p_margin); - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); real_t best_safe = 1; real_t best_unsafe = 1; Transform3D xform_inv = p_xform.affine_inverse(); - MotionShape3DSW mshape; + GodotMotionShape3D mshape; mshape.shape = shape; mshape.motion = xform_inv.basis.xform(p_motion); @@ -270,7 +271,7 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor continue; //ignore excluded } - const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; int shape_idx = space->intersection_query_subindex_results[i]; Vector3 point_A, point_B; @@ -278,14 +279,14 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor Transform3D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? - if (CollisionSolver3DSW::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { + if (GodotCollisionSolver3D::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { continue; } //test initial overlap, ignore objects it's inside of. sep_axis = motion_normal; - if (!CollisionSolver3DSW::solve_distance(shape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { + if (!GodotCollisionSolver3D::solve_distance(shape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { continue; } @@ -300,7 +301,7 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor Vector3 lA, lB; Vector3 sep = motion_normal; //important optimization for this to work fast enough - bool collided = !CollisionSolver3DSW::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, aabb, &sep); + bool collided = !GodotCollisionSolver3D::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, aabb, &sep); if (collided) { hi = fraction; @@ -342,8 +343,8 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor r_info->point = closest_B; r_info->normal = (closest_A - closest_B).normalized(); best_first = false; - if (col_obj->get_type() == CollisionObject3DSW::TYPE_BODY) { - const Body3DSW *body = static_cast<const Body3DSW *>(col_obj); + if (col_obj->get_type() == GodotCollisionObject3D::TYPE_BODY) { + const GodotBody3D *body = static_cast<const GodotBody3D *>(col_obj); Vector3 rel_vec = closest_B - (body->get_transform().origin + body->get_center_of_mass()); r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec); } @@ -356,36 +357,36 @@ bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transfor return true; } -bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { +bool GodotPhysicsDirectSpaceState3D::collide_shape(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (p_result_max <= 0) { return false; } - Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape); + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); ERR_FAIL_COND_V(!shape, 0); AABB aabb = p_shape_xform.xform(shape->get_aabb()); aabb = aabb.grow(p_margin); - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); bool collided = false; r_result_count = 0; - PhysicsServer3DSW::CollCbkData cbk; + GodotPhysicsServer3D::CollCbkData cbk; cbk.max = p_result_max; cbk.amount = 0; cbk.ptr = r_results; - CollisionSolver3DSW::CallbackResult cbkres = PhysicsServer3DSW::_shape_col_cbk; + GodotCollisionSolver3D::CallbackResult cbkres = GodotPhysicsServer3D::_shape_col_cbk; - PhysicsServer3DSW::CollCbkData *cbkptr = &cbk; + GodotPhysicsServer3D::CollCbkData *cbkptr = &cbk; for (int i = 0; i < amount; i++) { if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) { continue; } - const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; if (p_exclude.has(col_obj->get_self())) { continue; @@ -393,7 +394,7 @@ bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform3D & int shape_idx = space->intersection_query_subindex_results[i]; - if (CollisionSolver3DSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) { + if (GodotCollisionSolver3D::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_margin)) { collided = true; } } @@ -404,7 +405,7 @@ bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform3D & } struct _RestResultData { - const CollisionObject3DSW *object = nullptr; + const GodotCollisionObject3D *object = nullptr; int local_shape = 0; int shape = 0; Vector3 contact; @@ -413,7 +414,7 @@ struct _RestResultData { }; struct _RestCallbackData { - const CollisionObject3DSW *object = nullptr; + const GodotCollisionObject3D *object = nullptr; int local_shape = 0; int shape = 0; @@ -486,8 +487,8 @@ static void _rest_cbk_result(const Vector3 &p_point_A, int p_index_A, const Vect rd->best_result.local_shape = rd->local_shape; } -bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - Shape3DSW *shape = PhysicsServer3DSW::singletonsw->shape_owner.get_or_null(p_shape); +bool GodotPhysicsDirectSpaceState3D::rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { + GodotShape3D *shape = GodotPhysicsServer3D::godot_singleton->shape_owner.get_or_null(p_shape); ERR_FAIL_COND_V(!shape, 0); real_t min_contact_depth = p_margin * TEST_MOTION_MIN_CONTACT_DEPTH_FACTOR; @@ -495,7 +496,7 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_sh AABB aabb = p_shape_xform.xform(shape->get_aabb()); aabb = aabb.grow(p_margin); - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, GodotSpace3D::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); _RestCallbackData rcd; rcd.min_allowed_depth = min_contact_depth; @@ -505,7 +506,7 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_sh continue; } - const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + const GodotCollisionObject3D *col_obj = space->intersection_query_results[i]; if (p_exclude.has(col_obj->get_self())) { continue; @@ -515,7 +516,7 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_sh rcd.object = col_obj; rcd.shape = shape_idx; - bool sc = CollisionSolver3DSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin); + bool sc = GodotCollisionSolver3D::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_margin); if (!sc) { continue; } @@ -530,8 +531,8 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_sh r_info->normal = rcd.best_result.normal; r_info->point = rcd.best_result.contact; r_info->rid = rcd.best_result.object->get_self(); - if (rcd.best_result.object->get_type() == CollisionObject3DSW::TYPE_BODY) { - const Body3DSW *body = static_cast<const Body3DSW *>(rcd.best_result.object); + if (rcd.best_result.object->get_type() == GodotCollisionObject3D::TYPE_BODY) { + const GodotBody3D *body = static_cast<const GodotBody3D *>(rcd.best_result.object); Vector3 rel_vec = rcd.best_result.contact - (body->get_transform().origin + body->get_center_of_mass()); r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec); @@ -542,10 +543,10 @@ bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform3D &p_sh return true; } -Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const { - CollisionObject3DSW *obj = PhysicsServer3DSW::singletonsw->area_owner.get_or_null(p_object); +Vector3 GodotPhysicsDirectSpaceState3D::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const { + GodotCollisionObject3D *obj = GodotPhysicsServer3D::godot_singleton->area_owner.get_or_null(p_object); if (!obj) { - obj = PhysicsServer3DSW::singletonsw->body_owner.get_or_null(p_object); + obj = GodotPhysicsServer3D::godot_singleton->body_owner.get_or_null(p_object); } ERR_FAIL_COND_V(!obj, Vector3()); @@ -562,7 +563,7 @@ Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_ob } Transform3D shape_xform = obj->get_transform() * obj->get_shape_transform(i); - Shape3DSW *shape = obj->get_shape(i); + GodotShape3D *shape = obj->get_shape(i); Vector3 point = shape->get_closest_point_to(shape_xform.affine_inverse().xform(p_point)); point = shape_xform.xform(point); @@ -582,13 +583,13 @@ Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_ob } } -PhysicsDirectSpaceState3DSW::PhysicsDirectSpaceState3DSW() { +GodotPhysicsDirectSpaceState3D::GodotPhysicsDirectSpaceState3D() { space = nullptr; } //////////////////////////////////////////////////////////////////////////////////////////////////////////// -int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) { +int GodotSpace3D::_cull_aabb_for_body(GodotBody3D *p_body, const AABB &p_aabb) { int amount = broadphase->cull_aabb(p_aabb, intersection_query_results, INTERSECTION_QUERY_MAX, intersection_query_subindex_results); for (int i = 0; i < amount; i++) { @@ -596,13 +597,13 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) { if (intersection_query_results[i] == p_body) { keep = false; - } else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_AREA) { + } else if (intersection_query_results[i]->get_type() == GodotCollisionObject3D::TYPE_AREA) { keep = false; - } else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY) { + } else if (intersection_query_results[i]->get_type() == GodotCollisionObject3D::TYPE_SOFT_BODY) { keep = false; - } else if (!p_body->collides_with(static_cast<Body3DSW *>(intersection_query_results[i]))) { + } else if (!p_body->collides_with(static_cast<GodotBody3D *>(intersection_query_results[i]))) { keep = false; - } else if (static_cast<Body3DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) { + } else if (static_cast<GodotBody3D *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) { keep = false; } @@ -620,7 +621,7 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) { return amount; } -bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result) { +bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result) { //give me back regular physics engine logic //this is madness //and most people using this function will think @@ -679,13 +680,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion Vector3 sr[max_results * 2]; do { - PhysicsServer3DSW::CollCbkData cbk; + GodotPhysicsServer3D::CollCbkData cbk; cbk.max = max_results; cbk.amount = 0; cbk.ptr = sr; - PhysicsServer3DSW::CollCbkData *cbkptr = &cbk; - CollisionSolver3DSW::CallbackResult cbkres = PhysicsServer3DSW::_shape_col_cbk; + GodotPhysicsServer3D::CollCbkData *cbkptr = &cbk; + GodotCollisionSolver3D::CallbackResult cbkres = GodotPhysicsServer3D::_shape_col_cbk; bool collided = false; @@ -697,10 +698,10 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion } Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j); - Shape3DSW *body_shape = p_body->get_shape(j); + GodotShape3D *body_shape = p_body->get_shape(j); for (int i = 0; i < amount; i++) { - const CollisionObject3DSW *col_obj = intersection_query_results[i]; + const GodotCollisionObject3D *col_obj = intersection_query_results[i]; if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } @@ -710,7 +711,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion int shape_idx = intersection_query_subindex_results[i]; - if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_parameters.margin)) { + if (GodotCollisionSolver3D::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, p_parameters.margin)) { collided = cbk.amount > 0; } } @@ -770,13 +771,13 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion continue; } - Shape3DSW *body_shape = p_body->get_shape(j); + GodotShape3D *body_shape = p_body->get_shape(j); // Colliding separation rays allows to properly snap to the ground, // otherwise it's not needed in regular motion. if (!p_parameters.collide_separation_ray && (body_shape->get_type() == PhysicsServer3D::SHAPE_SEPARATION_RAY)) { // When slide on slope is on, separation ray shape acts like a regular shape. - if (!static_cast<SeparationRayShape3DSW *>(body_shape)->get_slide_on_slope()) { + if (!static_cast<GodotSeparationRayShape3D *>(body_shape)->get_slide_on_slope()) { continue; } } @@ -784,7 +785,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion Transform3D body_shape_xform = body_transform * p_body->get_shape_transform(j); Transform3D body_shape_xform_inv = body_shape_xform.affine_inverse(); - MotionShape3DSW mshape; + GodotMotionShape3D mshape; mshape.shape = body_shape; mshape.motion = body_shape_xform_inv.basis.xform(p_parameters.motion); @@ -794,7 +795,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion real_t best_unsafe = 1; for (int i = 0; i < amount; i++) { - const CollisionObject3DSW *col_obj = intersection_query_results[i]; + const GodotCollisionObject3D *col_obj = intersection_query_results[i]; if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } @@ -810,12 +811,12 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion Transform3D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? - if (CollisionSolver3DSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) { + if (GodotCollisionSolver3D::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) { continue; } sep_axis = motion_normal; - if (!CollisionSolver3DSW::solve_distance(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) { + if (!GodotCollisionSolver3D::solve_distance(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) { stuck = true; break; } @@ -831,7 +832,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion Vector3 lA, lB; Vector3 sep = motion_normal; //important optimization for this to work fast enough - bool collided = !CollisionSolver3DSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, motion_aabb, &sep); + bool collided = !GodotCollisionSolver3D::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, motion_aabb, &sep); if (collided) { hi = fraction; @@ -911,14 +912,14 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion } Transform3D body_shape_xform = ugt * p_body->get_shape_transform(j); - Shape3DSW *body_shape = p_body->get_shape(j); + GodotShape3D *body_shape = p_body->get_shape(j); body_aabb.position += p_parameters.motion * unsafe; int amount = _cull_aabb_for_body(p_body, body_aabb); for (int i = 0; i < amount; i++) { - const CollisionObject3DSW *col_obj = intersection_query_results[i]; + const GodotCollisionObject3D *col_obj = intersection_query_results[i]; if (p_parameters.exclude_bodies.has(col_obj->get_self())) { continue; } @@ -930,7 +931,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion rcd.object = col_obj; rcd.shape = shape_idx; - bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_parameters.margin); + bool sc = GodotCollisionSolver3D::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, nullptr, p_parameters.margin); if (!sc) { continue; } @@ -952,7 +953,7 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion collision.position = result.contact; collision.depth = result.len; - const Body3DSW *body = static_cast<const Body3DSW *>(result.object); + const GodotBody3D *body = static_cast<const GodotBody3D *>(result.object); Vector3 rel_vec = result.contact - (body->get_transform().origin + body->get_center_of_mass()); collision.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(rel_vec); @@ -984,44 +985,44 @@ bool Space3DSW::test_body_motion(Body3DSW *p_body, const PhysicsServer3D::Motion return collided; } -void *Space3DSW::_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_self) { +void *GodotSpace3D::_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_self) { if (!A->interacts_with(B)) { return nullptr; } - CollisionObject3DSW::Type type_A = A->get_type(); - CollisionObject3DSW::Type type_B = B->get_type(); + GodotCollisionObject3D::Type type_A = A->get_type(); + GodotCollisionObject3D::Type type_B = B->get_type(); if (type_A > type_B) { SWAP(A, B); SWAP(p_subindex_A, p_subindex_B); SWAP(type_A, type_B); } - Space3DSW *self = (Space3DSW *)p_self; + GodotSpace3D *self = (GodotSpace3D *)p_self; self->collision_pairs++; - if (type_A == CollisionObject3DSW::TYPE_AREA) { - Area3DSW *area = static_cast<Area3DSW *>(A); - if (type_B == CollisionObject3DSW::TYPE_AREA) { - Area3DSW *area_b = static_cast<Area3DSW *>(B); - Area2Pair3DSW *area2_pair = memnew(Area2Pair3DSW(area_b, p_subindex_B, area, p_subindex_A)); + if (type_A == GodotCollisionObject3D::TYPE_AREA) { + GodotArea3D *area = static_cast<GodotArea3D *>(A); + if (type_B == GodotCollisionObject3D::TYPE_AREA) { + GodotArea3D *area_b = static_cast<GodotArea3D *>(B); + GodotArea2Pair3D *area2_pair = memnew(GodotArea2Pair3D(area_b, p_subindex_B, area, p_subindex_A)); return area2_pair; - } else if (type_B == CollisionObject3DSW::TYPE_SOFT_BODY) { - SoftBody3DSW *softbody = static_cast<SoftBody3DSW *>(B); - AreaSoftBodyPair3DSW *soft_area_pair = memnew(AreaSoftBodyPair3DSW(softbody, p_subindex_B, area, p_subindex_A)); + } else if (type_B == GodotCollisionObject3D::TYPE_SOFT_BODY) { + GodotSoftBody3D *softbody = static_cast<GodotSoftBody3D *>(B); + GodotAreaSoftBodyPair3D *soft_area_pair = memnew(GodotAreaSoftBodyPair3D(softbody, p_subindex_B, area, p_subindex_A)); return soft_area_pair; } else { - Body3DSW *body = static_cast<Body3DSW *>(B); - AreaPair3DSW *area_pair = memnew(AreaPair3DSW(body, p_subindex_B, area, p_subindex_A)); + GodotBody3D *body = static_cast<GodotBody3D *>(B); + GodotAreaPair3D *area_pair = memnew(GodotAreaPair3D(body, p_subindex_B, area, p_subindex_A)); return area_pair; } - } else if (type_A == CollisionObject3DSW::TYPE_BODY) { - if (type_B == CollisionObject3DSW::TYPE_SOFT_BODY) { - BodySoftBodyPair3DSW *soft_pair = memnew(BodySoftBodyPair3DSW((Body3DSW *)A, p_subindex_A, (SoftBody3DSW *)B)); + } else if (type_A == GodotCollisionObject3D::TYPE_BODY) { + if (type_B == GodotCollisionObject3D::TYPE_SOFT_BODY) { + GodotBodySoftBodyPair3D *soft_pair = memnew(GodotBodySoftBodyPair3D((GodotBody3D *)A, p_subindex_A, (GodotSoftBody3D *)B)); return soft_pair; } else { - BodyPair3DSW *b = memnew(BodyPair3DSW((Body3DSW *)A, p_subindex_A, (Body3DSW *)B, p_subindex_B)); + GodotBodyPair3D *b = memnew(GodotBodyPair3D((GodotBody3D *)A, p_subindex_A, (GodotBody3D *)B, p_subindex_B)); return b; } } else { @@ -1031,110 +1032,110 @@ void *Space3DSW::_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, Coll return nullptr; } -void Space3DSW::_broadphase_unpair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_self) { +void GodotSpace3D::_broadphase_unpair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_data, void *p_self) { if (!p_data) { return; } - Space3DSW *self = (Space3DSW *)p_self; + GodotSpace3D *self = (GodotSpace3D *)p_self; self->collision_pairs--; - Constraint3DSW *c = (Constraint3DSW *)p_data; + GodotConstraint3D *c = (GodotConstraint3D *)p_data; memdelete(c); } -const SelfList<Body3DSW>::List &Space3DSW::get_active_body_list() const { +const SelfList<GodotBody3D>::List &GodotSpace3D::get_active_body_list() const { return active_list; } -void Space3DSW::body_add_to_active_list(SelfList<Body3DSW> *p_body) { +void GodotSpace3D::body_add_to_active_list(SelfList<GodotBody3D> *p_body) { active_list.add(p_body); } -void Space3DSW::body_remove_from_active_list(SelfList<Body3DSW> *p_body) { +void GodotSpace3D::body_remove_from_active_list(SelfList<GodotBody3D> *p_body) { active_list.remove(p_body); } -void Space3DSW::body_add_to_mass_properties_update_list(SelfList<Body3DSW> *p_body) { +void GodotSpace3D::body_add_to_mass_properties_update_list(SelfList<GodotBody3D> *p_body) { mass_properties_update_list.add(p_body); } -void Space3DSW::body_remove_from_mass_properties_update_list(SelfList<Body3DSW> *p_body) { +void GodotSpace3D::body_remove_from_mass_properties_update_list(SelfList<GodotBody3D> *p_body) { mass_properties_update_list.remove(p_body); } -BroadPhase3DSW *Space3DSW::get_broadphase() { +GodotBroadPhase3D *GodotSpace3D::get_broadphase() { return broadphase; } -void Space3DSW::add_object(CollisionObject3DSW *p_object) { +void GodotSpace3D::add_object(GodotCollisionObject3D *p_object) { ERR_FAIL_COND(objects.has(p_object)); objects.insert(p_object); } -void Space3DSW::remove_object(CollisionObject3DSW *p_object) { +void GodotSpace3D::remove_object(GodotCollisionObject3D *p_object) { ERR_FAIL_COND(!objects.has(p_object)); objects.erase(p_object); } -const Set<CollisionObject3DSW *> &Space3DSW::get_objects() const { +const Set<GodotCollisionObject3D *> &GodotSpace3D::get_objects() const { return objects; } -void Space3DSW::body_add_to_state_query_list(SelfList<Body3DSW> *p_body) { +void GodotSpace3D::body_add_to_state_query_list(SelfList<GodotBody3D> *p_body) { state_query_list.add(p_body); } -void Space3DSW::body_remove_from_state_query_list(SelfList<Body3DSW> *p_body) { +void GodotSpace3D::body_remove_from_state_query_list(SelfList<GodotBody3D> *p_body) { state_query_list.remove(p_body); } -void Space3DSW::area_add_to_monitor_query_list(SelfList<Area3DSW> *p_area) { +void GodotSpace3D::area_add_to_monitor_query_list(SelfList<GodotArea3D> *p_area) { monitor_query_list.add(p_area); } -void Space3DSW::area_remove_from_monitor_query_list(SelfList<Area3DSW> *p_area) { +void GodotSpace3D::area_remove_from_monitor_query_list(SelfList<GodotArea3D> *p_area) { monitor_query_list.remove(p_area); } -void Space3DSW::area_add_to_moved_list(SelfList<Area3DSW> *p_area) { +void GodotSpace3D::area_add_to_moved_list(SelfList<GodotArea3D> *p_area) { area_moved_list.add(p_area); } -void Space3DSW::area_remove_from_moved_list(SelfList<Area3DSW> *p_area) { +void GodotSpace3D::area_remove_from_moved_list(SelfList<GodotArea3D> *p_area) { area_moved_list.remove(p_area); } -const SelfList<Area3DSW>::List &Space3DSW::get_moved_area_list() const { +const SelfList<GodotArea3D>::List &GodotSpace3D::get_moved_area_list() const { return area_moved_list; } -const SelfList<SoftBody3DSW>::List &Space3DSW::get_active_soft_body_list() const { +const SelfList<GodotSoftBody3D>::List &GodotSpace3D::get_active_soft_body_list() const { return active_soft_body_list; } -void Space3DSW::soft_body_add_to_active_list(SelfList<SoftBody3DSW> *p_soft_body) { +void GodotSpace3D::soft_body_add_to_active_list(SelfList<GodotSoftBody3D> *p_soft_body) { active_soft_body_list.add(p_soft_body); } -void Space3DSW::soft_body_remove_from_active_list(SelfList<SoftBody3DSW> *p_soft_body) { +void GodotSpace3D::soft_body_remove_from_active_list(SelfList<GodotSoftBody3D> *p_soft_body) { active_soft_body_list.remove(p_soft_body); } -void Space3DSW::call_queries() { +void GodotSpace3D::call_queries() { while (state_query_list.first()) { - Body3DSW *b = state_query_list.first()->self(); + GodotBody3D *b = state_query_list.first()->self(); state_query_list.remove(state_query_list.first()); b->call_queries(); } while (monitor_query_list.first()) { - Area3DSW *a = monitor_query_list.first()->self(); + GodotArea3D *a = monitor_query_list.first()->self(); monitor_query_list.remove(monitor_query_list.first()); a->call_queries(); } } -void Space3DSW::setup() { +void GodotSpace3D::setup() { contact_debug_count = 0; while (mass_properties_update_list.first()) { mass_properties_update_list.first()->self()->update_mass_properties(); @@ -1142,11 +1143,11 @@ void Space3DSW::setup() { } } -void Space3DSW::update() { +void GodotSpace3D::update() { broadphase->update(); } -void Space3DSW::set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value) { +void GodotSpace3D::set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value) { switch (p_param) { case PhysicsServer3D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: contact_recycle_radius = p_value; @@ -1175,7 +1176,7 @@ void Space3DSW::set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_valu } } -real_t Space3DSW::get_param(PhysicsServer3D::SpaceParameter p_param) const { +real_t GodotSpace3D::get_param(PhysicsServer3D::SpaceParameter p_param) const { switch (p_param) { case PhysicsServer3D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: return contact_recycle_radius; @@ -1197,38 +1198,38 @@ real_t Space3DSW::get_param(PhysicsServer3D::SpaceParameter p_param) const { return 0; } -void Space3DSW::lock() { +void GodotSpace3D::lock() { locked = true; } -void Space3DSW::unlock() { +void GodotSpace3D::unlock() { locked = false; } -bool Space3DSW::is_locked() const { +bool GodotSpace3D::is_locked() const { return locked; } -PhysicsDirectSpaceState3DSW *Space3DSW::get_direct_state() { +GodotPhysicsDirectSpaceState3D *GodotSpace3D::get_direct_state() { return direct_access; } -Space3DSW::Space3DSW() { +GodotSpace3D::GodotSpace3D() { body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1); body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg2rad(8.0)); body_time_to_sleep = GLOBAL_DEF("physics/3d/time_before_sleep", 0.5); ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); body_angular_velocity_damp_ratio = 10; - broadphase = BroadPhase3DSW::create_func(); + broadphase = GodotBroadPhase3D::create_func(); broadphase->set_pair_callback(_broadphase_pair, this); broadphase->set_unpair_callback(_broadphase_unpair, this); - direct_access = memnew(PhysicsDirectSpaceState3DSW); + direct_access = memnew(GodotPhysicsDirectSpaceState3D); direct_access->space = this; } -Space3DSW::~Space3DSW() { +GodotSpace3D::~GodotSpace3D() { memdelete(broadphase); memdelete(direct_access); } diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/godot_space_3d.h index 69cc3c4bbd..3b36dd346c 100644 --- a/servers/physics_3d/space_3d_sw.h +++ b/servers/physics_3d/godot_space_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* space_3d_sw.h */ +/* godot_space_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,25 +28,26 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SPACE_SW_H -#define SPACE_SW_H +#ifndef GODOT_SPACE_3D_H +#define GODOT_SPACE_3D_H + +#include "godot_area_3d.h" +#include "godot_area_pair_3d.h" +#include "godot_body_3d.h" +#include "godot_body_pair_3d.h" +#include "godot_broad_phase_3d.h" +#include "godot_collision_object_3d.h" +#include "godot_soft_body_3d.h" -#include "area_3d_sw.h" -#include "area_pair_3d_sw.h" -#include "body_3d_sw.h" -#include "body_pair_3d_sw.h" -#include "broad_phase_3d_sw.h" -#include "collision_object_3d_sw.h" #include "core/config/project_settings.h" #include "core/templates/hash_map.h" #include "core/typedefs.h" -#include "soft_body_3d_sw.h" -class PhysicsDirectSpaceState3DSW : public PhysicsDirectSpaceState3D { - GDCLASS(PhysicsDirectSpaceState3DSW, PhysicsDirectSpaceState3D); +class GodotPhysicsDirectSpaceState3D : public PhysicsDirectSpaceState3D { + GDCLASS(GodotPhysicsDirectSpaceState3D, PhysicsDirectSpaceState3D); public: - Space3DSW *space; + GodotSpace3D *space; virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) override; @@ -56,10 +57,10 @@ public: virtual bool rest_info(RID p_shape, const Transform3D &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set<RID> &p_exclude = Set<RID>(), uint32_t p_collision_mask = UINT32_MAX, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) override; virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const override; - PhysicsDirectSpaceState3DSW(); + GodotPhysicsDirectSpaceState3D(); }; -class Space3DSW { +class GodotSpace3D { public: enum ElapsedTime { ELAPSED_TIME_INTEGRATE_FORCES, @@ -74,23 +75,23 @@ public: private: uint64_t elapsed_time[ELAPSED_TIME_MAX] = {}; - PhysicsDirectSpaceState3DSW *direct_access; + GodotPhysicsDirectSpaceState3D *direct_access; RID self; - BroadPhase3DSW *broadphase; - SelfList<Body3DSW>::List active_list; - SelfList<Body3DSW>::List mass_properties_update_list; - SelfList<Body3DSW>::List state_query_list; - SelfList<Area3DSW>::List monitor_query_list; - SelfList<Area3DSW>::List area_moved_list; - SelfList<SoftBody3DSW>::List active_soft_body_list; + GodotBroadPhase3D *broadphase; + SelfList<GodotBody3D>::List active_list; + SelfList<GodotBody3D>::List mass_properties_update_list; + SelfList<GodotBody3D>::List state_query_list; + SelfList<GodotArea3D>::List monitor_query_list; + SelfList<GodotArea3D>::List area_moved_list; + SelfList<GodotSoftBody3D>::List active_soft_body_list; - static void *_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_self); - static void _broadphase_unpair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_self); + static void *_broadphase_pair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_self); + static void _broadphase_unpair(GodotCollisionObject3D *A, int p_subindex_A, GodotCollisionObject3D *B, int p_subindex_B, void *p_data, void *p_self); - Set<CollisionObject3DSW *> objects; + Set<GodotCollisionObject3D *> objects; - Area3DSW *area = nullptr; + GodotArea3D *area = nullptr; real_t contact_recycle_radius = 0.01; real_t contact_max_separation = 0.05; @@ -101,7 +102,7 @@ private: INTERSECTION_QUERY_MAX = 2048 }; - CollisionObject3DSW *intersection_query_results[INTERSECTION_QUERY_MAX]; + GodotCollisionObject3D *intersection_query_results[INTERSECTION_QUERY_MAX]; int intersection_query_subindex_results[INTERSECTION_QUERY_MAX]; real_t body_linear_velocity_sleep_threshold; @@ -122,41 +123,41 @@ private: Vector<Vector3> contact_debug; int contact_debug_count = 0; - friend class PhysicsDirectSpaceState3DSW; + friend class GodotPhysicsDirectSpaceState3D; - int _cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb); + int _cull_aabb_for_body(GodotBody3D *p_body, const AABB &p_aabb); public: _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } _FORCE_INLINE_ RID get_self() const { return self; } - void set_default_area(Area3DSW *p_area) { area = p_area; } - Area3DSW *get_default_area() const { return area; } + void set_default_area(GodotArea3D *p_area) { area = p_area; } + GodotArea3D *get_default_area() const { return area; } - const SelfList<Body3DSW>::List &get_active_body_list() const; - void body_add_to_active_list(SelfList<Body3DSW> *p_body); - void body_remove_from_active_list(SelfList<Body3DSW> *p_body); - void body_add_to_mass_properties_update_list(SelfList<Body3DSW> *p_body); - void body_remove_from_mass_properties_update_list(SelfList<Body3DSW> *p_body); + const SelfList<GodotBody3D>::List &get_active_body_list() const; + void body_add_to_active_list(SelfList<GodotBody3D> *p_body); + void body_remove_from_active_list(SelfList<GodotBody3D> *p_body); + void body_add_to_mass_properties_update_list(SelfList<GodotBody3D> *p_body); + void body_remove_from_mass_properties_update_list(SelfList<GodotBody3D> *p_body); - void body_add_to_state_query_list(SelfList<Body3DSW> *p_body); - void body_remove_from_state_query_list(SelfList<Body3DSW> *p_body); + void body_add_to_state_query_list(SelfList<GodotBody3D> *p_body); + void body_remove_from_state_query_list(SelfList<GodotBody3D> *p_body); - void area_add_to_monitor_query_list(SelfList<Area3DSW> *p_area); - void area_remove_from_monitor_query_list(SelfList<Area3DSW> *p_area); - void area_add_to_moved_list(SelfList<Area3DSW> *p_area); - void area_remove_from_moved_list(SelfList<Area3DSW> *p_area); - const SelfList<Area3DSW>::List &get_moved_area_list() const; + void area_add_to_monitor_query_list(SelfList<GodotArea3D> *p_area); + void area_remove_from_monitor_query_list(SelfList<GodotArea3D> *p_area); + void area_add_to_moved_list(SelfList<GodotArea3D> *p_area); + void area_remove_from_moved_list(SelfList<GodotArea3D> *p_area); + const SelfList<GodotArea3D>::List &get_moved_area_list() const; - const SelfList<SoftBody3DSW>::List &get_active_soft_body_list() const; - void soft_body_add_to_active_list(SelfList<SoftBody3DSW> *p_soft_body); - void soft_body_remove_from_active_list(SelfList<SoftBody3DSW> *p_soft_body); + const SelfList<GodotSoftBody3D>::List &get_active_soft_body_list() const; + void soft_body_add_to_active_list(SelfList<GodotSoftBody3D> *p_soft_body); + void soft_body_remove_from_active_list(SelfList<GodotSoftBody3D> *p_soft_body); - BroadPhase3DSW *get_broadphase(); + GodotBroadPhase3D *get_broadphase(); - void add_object(CollisionObject3DSW *p_object); - void remove_object(CollisionObject3DSW *p_object); - const Set<CollisionObject3DSW *> &get_objects() const; + void add_object(GodotCollisionObject3D *p_object); + void remove_object(GodotCollisionObject3D *p_object); + const Set<GodotCollisionObject3D *> &get_objects() const; _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; } _FORCE_INLINE_ real_t get_contact_max_separation() const { return contact_max_separation; } @@ -189,7 +190,7 @@ public: int get_collision_pairs() const { return collision_pairs; } - PhysicsDirectSpaceState3DSW *get_direct_state(); + GodotPhysicsDirectSpaceState3D *get_direct_state(); void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); } _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.is_empty(); } @@ -207,10 +208,10 @@ public: void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; } uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; } - bool test_body_motion(Body3DSW *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result); + bool test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::MotionParameters &p_parameters, PhysicsServer3D::MotionResult *r_result); - Space3DSW(); - ~Space3DSW(); + GodotSpace3D(); + ~GodotSpace3D(); }; -#endif // SPACE__SW_H +#endif // GODOT_SPACE_3D_H diff --git a/servers/physics_3d/step_3d_sw.cpp b/servers/physics_3d/godot_step_3d.cpp index 6572d58c91..a8654c617b 100644 --- a/servers/physics_3d/step_3d_sw.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* step_3d_sw.cpp */ +/* godot_step_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,8 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "step_3d_sw.h" -#include "joints_3d_sw.h" +#include "godot_step_3d.h" + +#include "godot_joint_3d.h" #include "core/os/os.h" @@ -39,7 +40,7 @@ #define ISLAND_SIZE_RESERVE 512 #define CONSTRAINT_COUNT_RESERVE 1024 -void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_body_island, LocalVector<Constraint3DSW *> &p_constraint_island) { +void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island) { p_body->set_island_step(_step); if (p_body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) { @@ -47,8 +48,8 @@ void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_bod p_body_island.push_back(p_body); } - for (const KeyValue<Constraint3DSW *, int> &E : p_body->get_constraint_map()) { - Constraint3DSW *constraint = (Constraint3DSW *)E.key; + for (const KeyValue<GodotConstraint3D *, int> &E : p_body->get_constraint_map()) { + GodotConstraint3D *constraint = (GodotConstraint3D *)E.key; if (constraint->get_island_step() == _step) { continue; // Already processed. } @@ -62,7 +63,7 @@ void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_bod if (i == E.value) { continue; } - Body3DSW *other_body = constraint->get_body_ptr()[i]; + GodotBody3D *other_body = constraint->get_body_ptr()[i]; if (other_body->get_island_step() == _step) { continue; // Already processed. } @@ -74,7 +75,7 @@ void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_bod // Find connected soft bodies. for (int i = 0; i < constraint->get_soft_body_count(); i++) { - SoftBody3DSW *soft_body = constraint->get_soft_body_ptr(i); + GodotSoftBody3D *soft_body = constraint->get_soft_body_ptr(i); if (soft_body->get_island_step() == _step) { continue; // Already processed. } @@ -83,11 +84,11 @@ void Step3DSW::_populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_bod } } -void Step3DSW::_populate_island_soft_body(SoftBody3DSW *p_soft_body, LocalVector<Body3DSW *> &p_body_island, LocalVector<Constraint3DSW *> &p_constraint_island) { +void GodotStep3D::_populate_island_soft_body(GodotSoftBody3D *p_soft_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island) { p_soft_body->set_island_step(_step); - for (Set<Constraint3DSW *>::Element *E = p_soft_body->get_constraints().front(); E; E = E->next()) { - Constraint3DSW *constraint = (Constraint3DSW *)E->get(); + for (Set<GodotConstraint3D *>::Element *E = p_soft_body->get_constraints().front(); E; E = E->next()) { + GodotConstraint3D *constraint = (GodotConstraint3D *)E->get(); if (constraint->get_island_step() == _step) { continue; // Already processed. } @@ -98,7 +99,7 @@ void Step3DSW::_populate_island_soft_body(SoftBody3DSW *p_soft_body, LocalVector // Find connected rigid bodies. for (int i = 0; i < constraint->get_body_count(); i++) { - Body3DSW *body = constraint->get_body_ptr()[i]; + GodotBody3D *body = constraint->get_body_ptr()[i]; if (body->get_island_step() == _step) { continue; // Already processed. } @@ -110,16 +111,16 @@ void Step3DSW::_populate_island_soft_body(SoftBody3DSW *p_soft_body, LocalVector } } -void Step3DSW::_setup_contraint(uint32_t p_constraint_index, void *p_userdata) { - Constraint3DSW *constraint = all_constraints[p_constraint_index]; +void GodotStep3D::_setup_contraint(uint32_t p_constraint_index, void *p_userdata) { + GodotConstraint3D *constraint = all_constraints[p_constraint_index]; constraint->setup(delta); } -void Step3DSW::_pre_solve_island(LocalVector<Constraint3DSW *> &p_constraint_island) const { +void GodotStep3D::_pre_solve_island(LocalVector<GodotConstraint3D *> &p_constraint_island) const { uint32_t constraint_count = p_constraint_island.size(); uint32_t valid_constraint_count = 0; for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) { - Constraint3DSW *constraint = p_constraint_island[constraint_index]; + GodotConstraint3D *constraint = p_constraint_island[constraint_index]; if (p_constraint_island[constraint_index]->pre_solve(delta)) { // Keep this constraint for solving. p_constraint_island[valid_constraint_count++] = constraint; @@ -128,8 +129,8 @@ void Step3DSW::_pre_solve_island(LocalVector<Constraint3DSW *> &p_constraint_isl p_constraint_island.resize(valid_constraint_count); } -void Step3DSW::_solve_island(uint32_t p_island_index, void *p_userdata) { - LocalVector<Constraint3DSW *> &constraint_island = constraint_islands[p_island_index]; +void GodotStep3D::_solve_island(uint32_t p_island_index, void *p_userdata) { + LocalVector<GodotConstraint3D *> &constraint_island = constraint_islands[p_island_index]; int current_priority = 1; @@ -146,7 +147,7 @@ void Step3DSW::_solve_island(uint32_t p_island_index, void *p_userdata) { uint32_t priority_constraint_count = 0; ++current_priority; for (uint32_t constraint_index = 0; constraint_index < constraint_count; ++constraint_index) { - Constraint3DSW *constraint = constraint_island[constraint_index]; + GodotConstraint3D *constraint = constraint_island[constraint_index]; if (constraint->get_priority() >= current_priority) { // Keep this constraint for the next iteration. constraint_island[priority_constraint_count++] = constraint; @@ -156,12 +157,12 @@ void Step3DSW::_solve_island(uint32_t p_island_index, void *p_userdata) { } } -void Step3DSW::_check_suspend(const LocalVector<Body3DSW *> &p_body_island) const { +void GodotStep3D::_check_suspend(const LocalVector<GodotBody3D *> &p_body_island) const { bool can_sleep = true; uint32_t body_count = p_body_island.size(); for (uint32_t body_index = 0; body_index < body_count; ++body_index) { - Body3DSW *body = p_body_island[body_index]; + GodotBody3D *body = p_body_island[body_index]; if (!body->sleep_test(delta)) { can_sleep = false; @@ -170,7 +171,7 @@ void Step3DSW::_check_suspend(const LocalVector<Body3DSW *> &p_body_island) cons // Put all to sleep or wake up everyone. for (uint32_t body_index = 0; body_index < body_count; ++body_index) { - Body3DSW *body = p_body_island[body_index]; + GodotBody3D *body = p_body_island[body_index]; bool active = body->is_active(); @@ -180,7 +181,7 @@ void Step3DSW::_check_suspend(const LocalVector<Body3DSW *> &p_body_island) cons } } -void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { +void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta, int p_iterations) { p_space->lock(); // can't access space during this p_space->setup(); //update inertias, etc @@ -190,9 +191,9 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { iterations = p_iterations; delta = p_delta; - const SelfList<Body3DSW>::List *body_list = &p_space->get_active_body_list(); + const SelfList<GodotBody3D>::List *body_list = &p_space->get_active_body_list(); - const SelfList<SoftBody3DSW>::List *soft_body_list = &p_space->get_active_soft_body_list(); + const SelfList<GodotSoftBody3D>::List *soft_body_list = &p_space->get_active_soft_body_list(); /* INTEGRATE FORCES */ @@ -201,7 +202,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { int active_count = 0; - const SelfList<Body3DSW> *b = body_list->first(); + const SelfList<GodotBody3D> *b = body_list->first(); while (b) { b->self()->integrate_forces(p_delta); b = b->next(); @@ -210,7 +211,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { /* UPDATE SOFT BODY MOTION */ - const SelfList<SoftBody3DSW> *sb = soft_body_list->first(); + const SelfList<GodotSoftBody3D> *sb = soft_body_list->first(); while (sb) { sb->self()->predict_motion(p_delta); sb = sb->next(); @@ -221,7 +222,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime); + p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime); profile_begtime = profile_endtime; } @@ -229,11 +230,11 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { uint32_t island_count = 0; - const SelfList<Area3DSW>::List &aml = p_space->get_moved_area_list(); + const SelfList<GodotArea3D>::List &aml = p_space->get_moved_area_list(); while (aml.first()) { - for (const Set<Constraint3DSW *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { - Constraint3DSW *constraint = E->get(); + for (const Set<GodotConstraint3D *>::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { + GodotConstraint3D *constraint = E->get(); if (constraint->get_island_step() == _step) { continue; } @@ -244,13 +245,13 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { if (constraint_islands.size() < island_count) { constraint_islands.resize(island_count); } - LocalVector<Constraint3DSW *> &constraint_island = constraint_islands[island_count - 1]; + LocalVector<GodotConstraint3D *> &constraint_island = constraint_islands[island_count - 1]; constraint_island.clear(); all_constraints.push_back(constraint); constraint_island.push_back(constraint); } - p_space->area_remove_from_moved_list((SelfList<Area3DSW> *)aml.first()); //faster to remove here + p_space->area_remove_from_moved_list((SelfList<GodotArea3D> *)aml.first()); //faster to remove here } /* GENERATE CONSTRAINT ISLANDS FOR ACTIVE RIGID BODIES */ @@ -260,14 +261,14 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { uint32_t body_island_count = 0; while (b) { - Body3DSW *body = b->self(); + GodotBody3D *body = b->self(); if (body->get_island_step() != _step) { ++body_island_count; if (body_islands.size() < body_island_count) { body_islands.resize(body_island_count); } - LocalVector<Body3DSW *> &body_island = body_islands[body_island_count - 1]; + LocalVector<GodotBody3D *> &body_island = body_islands[body_island_count - 1]; body_island.clear(); body_island.reserve(BODY_ISLAND_SIZE_RESERVE); @@ -275,7 +276,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { if (constraint_islands.size() < island_count) { constraint_islands.resize(island_count); } - LocalVector<Constraint3DSW *> &constraint_island = constraint_islands[island_count - 1]; + LocalVector<GodotConstraint3D *> &constraint_island = constraint_islands[island_count - 1]; constraint_island.clear(); constraint_island.reserve(ISLAND_SIZE_RESERVE); @@ -296,14 +297,14 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { sb = soft_body_list->first(); while (sb) { - SoftBody3DSW *soft_body = sb->self(); + GodotSoftBody3D *soft_body = sb->self(); if (soft_body->get_island_step() != _step) { ++body_island_count; if (body_islands.size() < body_island_count) { body_islands.resize(body_island_count); } - LocalVector<Body3DSW *> &body_island = body_islands[body_island_count - 1]; + LocalVector<GodotBody3D *> &body_island = body_islands[body_island_count - 1]; body_island.clear(); body_island.reserve(BODY_ISLAND_SIZE_RESERVE); @@ -311,7 +312,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { if (constraint_islands.size() < island_count) { constraint_islands.resize(island_count); } - LocalVector<Constraint3DSW *> &constraint_island = constraint_islands[island_count - 1]; + LocalVector<GodotConstraint3D *> &constraint_island = constraint_islands[island_count - 1]; constraint_island.clear(); constraint_island.reserve(ISLAND_SIZE_RESERVE); @@ -332,18 +333,18 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime); + p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime); profile_begtime = profile_endtime; } /* SETUP CONSTRAINTS / PROCESS COLLISIONS */ uint32_t total_contraint_count = all_constraints.size(); - work_pool.do_work(total_contraint_count, this, &Step3DSW::_setup_contraint, nullptr); + work_pool.do_work(total_contraint_count, this, &GodotStep3D::_setup_contraint, nullptr); { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_SETUP_CONSTRAINTS, profile_endtime - profile_begtime); + p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_SETUP_CONSTRAINTS, profile_endtime - profile_begtime); profile_begtime = profile_endtime; } @@ -359,14 +360,14 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { // Warning: _solve_island modifies the constraint islands for optimization purpose, // their content is not reliable after these calls and shouldn't be used anymore. if (island_count > 1) { - work_pool.do_work(island_count, this, &Step3DSW::_solve_island, nullptr); + work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr); } else if (island_count > 0) { _solve_island(0); } { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_SOLVE_CONSTRAINTS, profile_endtime - profile_begtime); + p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_SOLVE_CONSTRAINTS, profile_endtime - profile_begtime); profile_begtime = profile_endtime; } @@ -374,7 +375,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { b = body_list->first(); while (b) { - const SelfList<Body3DSW> *n = b->next(); + const SelfList<GodotBody3D> *n = b->next(); b->self()->integrate_velocities(p_delta); b = n; } @@ -395,7 +396,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { { //profile profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime); + p_space->set_elapsed_time(GodotSpace3D::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime); profile_begtime = profile_endtime; } @@ -406,7 +407,7 @@ void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { _step++; } -Step3DSW::Step3DSW() { +GodotStep3D::GodotStep3D() { body_islands.reserve(BODY_ISLAND_COUNT_RESERVE); constraint_islands.reserve(ISLAND_COUNT_RESERVE); all_constraints.reserve(CONSTRAINT_COUNT_RESERVE); @@ -414,6 +415,6 @@ Step3DSW::Step3DSW() { work_pool.init(); } -Step3DSW::~Step3DSW() { +GodotStep3D::~GodotStep3D() { work_pool.finish(); } diff --git a/servers/physics_3d/step_3d_sw.h b/servers/physics_3d/godot_step_3d.h index f2f879104a..23ede4feff 100644 --- a/servers/physics_3d/step_3d_sw.h +++ b/servers/physics_3d/godot_step_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* step_3d_sw.h */ +/* godot_step_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,15 +28,15 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef STEP_SW_H -#define STEP_SW_H +#ifndef GODOT_STEP_3D_H +#define GODOT_STEP_3D_H -#include "space_3d_sw.h" +#include "godot_space_3d.h" #include "core/templates/local_vector.h" #include "core/templates/thread_work_pool.h" -class Step3DSW { +class GodotStep3D { uint64_t _step = 1; int iterations = 0; @@ -44,21 +44,21 @@ class Step3DSW { ThreadWorkPool work_pool; - LocalVector<LocalVector<Body3DSW *>> body_islands; - LocalVector<LocalVector<Constraint3DSW *>> constraint_islands; - LocalVector<Constraint3DSW *> all_constraints; + LocalVector<LocalVector<GodotBody3D *>> body_islands; + LocalVector<LocalVector<GodotConstraint3D *>> constraint_islands; + LocalVector<GodotConstraint3D *> all_constraints; - void _populate_island(Body3DSW *p_body, LocalVector<Body3DSW *> &p_body_island, LocalVector<Constraint3DSW *> &p_constraint_island); - void _populate_island_soft_body(SoftBody3DSW *p_soft_body, LocalVector<Body3DSW *> &p_body_island, LocalVector<Constraint3DSW *> &p_constraint_island); + void _populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island); + void _populate_island_soft_body(GodotSoftBody3D *p_soft_body, LocalVector<GodotBody3D *> &p_body_island, LocalVector<GodotConstraint3D *> &p_constraint_island); void _setup_contraint(uint32_t p_constraint_index, void *p_userdata = nullptr); - void _pre_solve_island(LocalVector<Constraint3DSW *> &p_constraint_island) const; + void _pre_solve_island(LocalVector<GodotConstraint3D *> &p_constraint_island) const; void _solve_island(uint32_t p_island_index, void *p_userdata = nullptr); - void _check_suspend(const LocalVector<Body3DSW *> &p_body_island) const; + void _check_suspend(const LocalVector<GodotBody3D *> &p_body_island) const; public: - void step(Space3DSW *p_space, real_t p_delta, int p_iterations); - Step3DSW(); - ~Step3DSW(); + void step(GodotSpace3D *p_space, real_t p_delta, int p_iterations); + GodotStep3D(); + ~GodotStep3D(); }; -#endif // STEP__SW_H +#endif // GODOT_STEP_3D_H diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp b/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp index bb9cc1bf67..31a87fc595 100644 --- a/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/godot_cone_twist_joint_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* cone_twist_joint_3d_sw.cpp */ +/* godot_cone_twist_joint_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -49,7 +49,7 @@ subject to the following restrictions: Written by: Marcus Hennix */ -#include "cone_twist_joint_3d_sw.h" +#include "godot_cone_twist_joint_3d.h" static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) { if (Math::abs(n.z) > Math_SQRT12) { @@ -84,8 +84,8 @@ static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { return (y < 0.0f) ? -angle : angle; } -ConeTwistJoint3DSW::ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame) : - Joint3DSW(_arr, 2) { +GodotConeTwistJoint3D::GodotConeTwistJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame) : + GodotJoint3D(_arr, 2) { A = rbA; B = rbB; @@ -96,7 +96,7 @@ ConeTwistJoint3DSW::ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Trans B->add_constraint(this, 1); } -bool ConeTwistJoint3DSW::setup(real_t p_timestep) { +bool GodotConeTwistJoint3D::setup(real_t p_timestep) { dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); @@ -129,7 +129,7 @@ bool ConeTwistJoint3DSW::setup(real_t p_timestep) { plane_space(normal[0], normal[1], normal[2]); for (int i = 0; i < 3; i++) { - memnew_placement(&m_jac[i], JacobianEntry3DSW( + memnew_placement(&m_jac[i], GodotJacobianEntry3D( A->get_principal_inertia_axes().transposed(), B->get_principal_inertia_axes().transposed(), pivotAInW - A->get_transform().origin - A->get_center_of_mass(), @@ -230,7 +230,7 @@ bool ConeTwistJoint3DSW::setup(real_t p_timestep) { return true; } -void ConeTwistJoint3DSW::solve(real_t p_timestep) { +void GodotConeTwistJoint3D::solve(real_t p_timestep) { Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin); Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin); @@ -312,7 +312,7 @@ void ConeTwistJoint3DSW::solve(real_t p_timestep) { } } -void ConeTwistJoint3DSW::set_param(PhysicsServer3D::ConeTwistJointParam p_param, real_t p_value) { +void GodotConeTwistJoint3D::set_param(PhysicsServer3D::ConeTwistJointParam p_param, real_t p_value) { switch (p_param) { case PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN: { m_swingSpan1 = p_value; @@ -335,7 +335,7 @@ void ConeTwistJoint3DSW::set_param(PhysicsServer3D::ConeTwistJointParam p_param, } } -real_t ConeTwistJoint3DSW::get_param(PhysicsServer3D::ConeTwistJointParam p_param) const { +real_t GodotConeTwistJoint3D::get_param(PhysicsServer3D::ConeTwistJointParam p_param) const { switch (p_param) { case PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN: { return m_swingSpan1; diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.h b/servers/physics_3d/joints/godot_cone_twist_joint_3d.h index bf7e593820..999d0f0692 100644 --- a/servers/physics_3d/joints/cone_twist_joint_3d_sw.h +++ b/servers/physics_3d/joints/godot_cone_twist_joint_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* cone_twist_joint_3d_sw.h */ +/* godot_cone_twist_joint_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -34,7 +34,7 @@ Adapted to Godot from the Bullet library. /* Bullet Continuous Collision Detection and Physics Library -ConeTwistJointSW is Copyright (c) 2007 Starbreeze Studios +GodotConeTwistJoint3D is Copyright (c) 2007 Starbreeze Studios This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. @@ -49,28 +49,28 @@ subject to the following restrictions: Written by: Marcus Hennix */ -#ifndef CONE_TWIST_JOINT_SW_H -#define CONE_TWIST_JOINT_SW_H +#ifndef GODOT_CONE_TWIST_JOINT_3D_H +#define GODOT_CONE_TWIST_JOINT_3D_H -#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h" -#include "servers/physics_3d/joints_3d_sw.h" +#include "servers/physics_3d/godot_joint_3d.h" +#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h" -///ConeTwistJointSW can be used to simulate ragdoll joints (upper arm, leg etc) -class ConeTwistJoint3DSW : public Joint3DSW { +// GodotConeTwistJoint3D can be used to simulate ragdoll joints (upper arm, leg etc). +class GodotConeTwistJoint3D : public GodotJoint3D { #ifdef IN_PARALLELL_SOLVER public: #endif union { struct { - Body3DSW *A; - Body3DSW *B; + GodotBody3D *A; + GodotBody3D *B; }; - Body3DSW *_arr[2] = { nullptr, nullptr }; + GodotBody3D *_arr[2] = { nullptr, nullptr }; }; - JacobianEntry3DSW m_jac[3] = {}; //3 orthogonal linear constraints + GodotJacobianEntry3D m_jac[3] = {}; //3 orthogonal linear constraints real_t m_appliedImpulse = 0.0; Transform3D m_rbAFrame; @@ -107,7 +107,7 @@ public: virtual bool setup(real_t p_step) override; virtual void solve(real_t p_step) override; - ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame); + GodotConeTwistJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &rbAFrame, const Transform3D &rbBFrame); void setAngularOnly(bool angularOnly) { m_angularOnly = angularOnly; @@ -139,4 +139,4 @@ public: real_t get_param(PhysicsServer3D::ConeTwistJointParam p_param) const; }; -#endif // CONE_TWIST_JOINT_SW_H +#endif // GODOT_CONE_TWIST_JOINT_3D_H diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp index 56aba24b42..d7e0537439 100644 --- a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* generic_6dof_joint_3d_sw.cpp */ +/* godot_generic_6dof_joint_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -49,18 +49,18 @@ subject to the following restrictions: /* 2007-09-09 -Generic6DOFJointSW Refactored by Francisco Le?n +GodotGeneric6DOFJoint3D Refactored by Francisco Le?n email: projectileman@yahoo.com http://gimpact.sf.net */ -#include "generic_6dof_joint_3d_sw.h" +#include "godot_generic_6dof_joint_3d.h" #define GENERIC_D6_DISABLE_WARMSTARTING 1 -//////////////////////////// G6DOFRotationalLimitMotorSW //////////////////////////////////// +//////////////////////////// GodotG6DOFRotationalLimitMotor3D //////////////////////////////////// -int G6DOFRotationalLimitMotor3DSW::testLimitValue(real_t test_value) { +int GodotG6DOFRotationalLimitMotor3D::testLimitValue(real_t test_value) { if (m_loLimit > m_hiLimit) { m_currentLimit = 0; //Free from violation return 0; @@ -80,9 +80,9 @@ int G6DOFRotationalLimitMotor3DSW::testLimitValue(real_t test_value) { return 0; } -real_t G6DOFRotationalLimitMotor3DSW::solveAngularLimits( +real_t GodotG6DOFRotationalLimitMotor3D::solveAngularLimits( real_t timeStep, Vector3 &axis, real_t jacDiagABInv, - Body3DSW *body0, Body3DSW *body1, bool p_body0_dynamic, bool p_body1_dynamic) { + GodotBody3D *body0, GodotBody3D *body1, bool p_body0_dynamic, bool p_body1_dynamic) { if (!needApplyTorques()) { return 0.0f; } @@ -148,14 +148,13 @@ real_t G6DOFRotationalLimitMotor3DSW::solveAngularLimits( return clippedMotorImpulse; } -//////////////////////////// End G6DOFRotationalLimitMotorSW //////////////////////////////////// +//////////////////////////// GodotG6DOFTranslationalLimitMotor3D //////////////////////////////////// -//////////////////////////// G6DOFTranslationalLimitMotorSW //////////////////////////////////// -real_t G6DOFTranslationalLimitMotor3DSW::solveLinearAxis( +real_t GodotG6DOFTranslationalLimitMotor3D::solveLinearAxis( real_t timeStep, real_t jacDiagABInv, - Body3DSW *body1, const Vector3 &pointInA, - Body3DSW *body2, const Vector3 &pointInB, + GodotBody3D *body1, const Vector3 &pointInA, + GodotBody3D *body2, const Vector3 &pointInB, bool p_body1_dynamic, bool p_body2_dynamic, int limit_index, const Vector3 &axis_normal_on_a, @@ -217,10 +216,10 @@ real_t G6DOFTranslationalLimitMotor3DSW::solveLinearAxis( return normalImpulse; } -//////////////////////////// G6DOFTranslationalLimitMotorSW //////////////////////////////////// +//////////////////////////// GodotGeneric6DOFJoint3D //////////////////////////////////// -Generic6DOFJoint3DSW::Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB, bool useLinearReferenceFrameA) : - Joint3DSW(_arr, 2), +GodotGeneric6DOFJoint3D::GodotGeneric6DOFJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameInA, const Transform3D &frameInB, bool useLinearReferenceFrameA) : + GodotJoint3D(_arr, 2), m_frameInA(frameInA), m_frameInB(frameInB), m_useLinearReferenceFrameA(useLinearReferenceFrameA) { @@ -230,7 +229,7 @@ Generic6DOFJoint3DSW::Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const T B->add_constraint(this, 1); } -void Generic6DOFJoint3DSW::calculateAngleInfo() { +void GodotGeneric6DOFJoint3D::calculateAngleInfo() { Basis relative_frame = m_calculatedTransformB.basis.inverse() * m_calculatedTransformA.basis; m_calculatedAxisAngleDiff = relative_frame.get_euler_xyz(); @@ -270,17 +269,17 @@ void Generic6DOFJoint3DSW::calculateAngleInfo() { */ } -void Generic6DOFJoint3DSW::calculateTransforms() { +void GodotGeneric6DOFJoint3D::calculateTransforms() { m_calculatedTransformA = A->get_transform() * m_frameInA; m_calculatedTransformB = B->get_transform() * m_frameInB; calculateAngleInfo(); } -void Generic6DOFJoint3DSW::buildLinearJacobian( - JacobianEntry3DSW &jacLinear, const Vector3 &normalWorld, +void GodotGeneric6DOFJoint3D::buildLinearJacobian( + GodotJacobianEntry3D &jacLinear, const Vector3 &normalWorld, const Vector3 &pivotAInW, const Vector3 &pivotBInW) { - memnew_placement(&jacLinear, JacobianEntry3DSW( + memnew_placement(&jacLinear, GodotJacobianEntry3D( A->get_principal_inertia_axes().transposed(), B->get_principal_inertia_axes().transposed(), pivotAInW - A->get_transform().origin - A->get_center_of_mass(), @@ -292,16 +291,16 @@ void Generic6DOFJoint3DSW::buildLinearJacobian( B->get_inv_mass())); } -void Generic6DOFJoint3DSW::buildAngularJacobian( - JacobianEntry3DSW &jacAngular, const Vector3 &jointAxisW) { - memnew_placement(&jacAngular, JacobianEntry3DSW(jointAxisW, +void GodotGeneric6DOFJoint3D::buildAngularJacobian( + GodotJacobianEntry3D &jacAngular, const Vector3 &jointAxisW) { + memnew_placement(&jacAngular, GodotJacobianEntry3D(jointAxisW, A->get_principal_inertia_axes().transposed(), B->get_principal_inertia_axes().transposed(), A->get_inv_inertia(), B->get_inv_inertia())); } -bool Generic6DOFJoint3DSW::testAngularLimitMotor(int axis_index) { +bool GodotGeneric6DOFJoint3D::testAngularLimitMotor(int axis_index) { real_t angle = m_calculatedAxisAngleDiff[axis_index]; //test limits @@ -309,7 +308,7 @@ bool Generic6DOFJoint3DSW::testAngularLimitMotor(int axis_index) { return m_angularLimits[axis_index].needApplyTorques(); } -bool Generic6DOFJoint3DSW::setup(real_t p_timestep) { +bool GodotGeneric6DOFJoint3D::setup(real_t p_timestep) { dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); @@ -365,7 +364,7 @@ bool Generic6DOFJoint3DSW::setup(real_t p_timestep) { return true; } -void Generic6DOFJoint3DSW::solve(real_t p_timestep) { +void GodotGeneric6DOFJoint3D::solve(real_t p_timestep) { m_timeStep = p_timestep; //calculateTransforms(); @@ -414,19 +413,19 @@ void Generic6DOFJoint3DSW::solve(real_t p_timestep) { } } -void Generic6DOFJoint3DSW::updateRHS(real_t timeStep) { +void GodotGeneric6DOFJoint3D::updateRHS(real_t timeStep) { (void)timeStep; } -Vector3 Generic6DOFJoint3DSW::getAxis(int axis_index) const { +Vector3 GodotGeneric6DOFJoint3D::getAxis(int axis_index) const { return m_calculatedAxis[axis_index]; } -real_t Generic6DOFJoint3DSW::getAngle(int axis_index) const { +real_t GodotGeneric6DOFJoint3D::getAngle(int axis_index) const { return m_calculatedAxisAngleDiff[axis_index]; } -void Generic6DOFJoint3DSW::calcAnchorPos() { +void GodotGeneric6DOFJoint3D::calcAnchorPos() { real_t imA = A->get_inv_mass(); real_t imB = B->get_inv_mass(); real_t weight; @@ -438,9 +437,9 @@ void Generic6DOFJoint3DSW::calcAnchorPos() { const Vector3 &pA = m_calculatedTransformA.origin; const Vector3 &pB = m_calculatedTransformB.origin; m_AnchorPos = pA * weight + pB * (real_t(1.0) - weight); -} // Generic6DOFJointSW::calcAnchorPos() +} -void Generic6DOFJoint3DSW::set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param, real_t p_value) { +void GodotGeneric6DOFJoint3D::set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param, real_t p_value) { ERR_FAIL_INDEX(p_axis, 3); switch (p_param) { case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: { @@ -527,7 +526,7 @@ void Generic6DOFJoint3DSW::set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DO } } -real_t Generic6DOFJoint3DSW::get_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param) const { +real_t GodotGeneric6DOFJoint3D::get_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param) const { ERR_FAIL_INDEX_V(p_axis, 3, 0); switch (p_param) { case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: { @@ -615,7 +614,7 @@ real_t Generic6DOFJoint3DSW::get_param(Vector3::Axis p_axis, PhysicsServer3D::G6 return 0; } -void Generic6DOFJoint3DSW::set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag, bool p_value) { +void GodotGeneric6DOFJoint3D::set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag, bool p_value) { ERR_FAIL_INDEX(p_axis, 3); switch (p_flag) { @@ -642,7 +641,7 @@ void Generic6DOFJoint3DSW::set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOF } } -bool Generic6DOFJoint3DSW::get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const { +bool GodotGeneric6DOFJoint3D::get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const { ERR_FAIL_INDEX_V(p_axis, 3, 0); switch (p_flag) { case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: { diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.h index 6492e40393..729b3fa1f9 100644 --- a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h +++ b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* generic_6dof_joint_3d_sw.h */ +/* godot_generic_6dof_joint_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -32,11 +32,11 @@ Adapted to Godot from the Bullet library. */ -#ifndef GENERIC_6DOF_JOINT_SW_H -#define GENERIC_6DOF_JOINT_SW_H +#ifndef GODOT_GENERIC_6DOF_JOINT_3D_H +#define GODOT_GENERIC_6DOF_JOINT_3D_H -#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h" -#include "servers/physics_3d/joints_3d_sw.h" +#include "servers/physics_3d/godot_joint_3d.h" +#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h" /* Bullet Continuous Collision Detection and Physics Library @@ -55,13 +55,13 @@ subject to the following restrictions: /* 2007-09-09 -Generic6DOFJointSW Refactored by Francisco Le?n +GodotGeneric6DOFJoint3D Refactored by Francisco Le?n email: projectileman@yahoo.com http://gimpact.sf.net */ //! Rotation Limit structure for generic joints -class G6DOFRotationalLimitMotor3DSW { +class GodotG6DOFRotationalLimitMotor3D { public: //! limit_parameters //!@{ @@ -86,29 +86,25 @@ public: real_t m_accumulatedImpulse = 0.0; //!@} - G6DOFRotationalLimitMotor3DSW() {} + GodotG6DOFRotationalLimitMotor3D() {} - //! Is limited bool isLimited() { return (m_loLimit < m_hiLimit); } - //! Need apply correction + // Need apply correction. bool needApplyTorques() { return (m_enableMotor || m_currentLimit != 0); } - //! calculates error - /*! - calculates m_currentLimit and m_currentLimitError. - */ + // Calculates m_currentLimit and m_currentLimitError. int testLimitValue(real_t test_value); - //! apply the correction impulses for two bodies - real_t solveAngularLimits(real_t timeStep, Vector3 &axis, real_t jacDiagABInv, Body3DSW *body0, Body3DSW *body1, bool p_body0_dynamic, bool p_body1_dynamic); + // Apply the correction impulses for two bodies. + real_t solveAngularLimits(real_t timeStep, Vector3 &axis, real_t jacDiagABInv, GodotBody3D *body0, GodotBody3D *body1, bool p_body0_dynamic, bool p_body1_dynamic); }; -class G6DOFTranslationalLimitMotor3DSW { +class GodotG6DOFTranslationalLimitMotor3D { public: Vector3 m_lowerLimit = Vector3(0.0, 0.0, 0.0); //!< the constraint lower limits Vector3 m_upperLimit = Vector3(0.0, 0.0, 0.0); //!< the constraint upper limits @@ -135,23 +131,23 @@ public: real_t solveLinearAxis( real_t timeStep, real_t jacDiagABInv, - Body3DSW *body1, const Vector3 &pointInA, - Body3DSW *body2, const Vector3 &pointInB, + GodotBody3D *body1, const Vector3 &pointInA, + GodotBody3D *body2, const Vector3 &pointInB, bool p_body1_dynamic, bool p_body2_dynamic, int limit_index, const Vector3 &axis_normal_on_a, const Vector3 &anchorPos); }; -class Generic6DOFJoint3DSW : public Joint3DSW { +class GodotGeneric6DOFJoint3D : public GodotJoint3D { protected: union { struct { - Body3DSW *A; - Body3DSW *B; + GodotBody3D *A; + GodotBody3D *B; }; - Body3DSW *_arr[2] = { nullptr, nullptr }; + GodotBody3D *_arr[2] = { nullptr, nullptr }; }; //! relative_frames @@ -162,18 +158,18 @@ protected: //! Jacobians //!@{ - JacobianEntry3DSW m_jacLinear[3]; //!< 3 orthogonal linear constraints - JacobianEntry3DSW m_jacAng[3]; //!< 3 orthogonal angular constraints + GodotJacobianEntry3D m_jacLinear[3]; //!< 3 orthogonal linear constraints + GodotJacobianEntry3D m_jacAng[3]; //!< 3 orthogonal angular constraints //!@} //! Linear_Limit_parameters //!@{ - G6DOFTranslationalLimitMotor3DSW m_linearLimits; + GodotG6DOFTranslationalLimitMotor3D m_linearLimits; //!@} //! hinge_parameters //!@{ - G6DOFRotationalLimitMotor3DSW m_angularLimits[3]; + GodotG6DOFRotationalLimitMotor3D m_angularLimits[3]; //!@} protected: @@ -191,45 +187,35 @@ protected: //!@} - Generic6DOFJoint3DSW(Generic6DOFJoint3DSW const &) = delete; - void operator=(Generic6DOFJoint3DSW const &) = delete; + GodotGeneric6DOFJoint3D(GodotGeneric6DOFJoint3D const &) = delete; + void operator=(GodotGeneric6DOFJoint3D const &) = delete; void buildLinearJacobian( - JacobianEntry3DSW &jacLinear, const Vector3 &normalWorld, + GodotJacobianEntry3D &jacLinear, const Vector3 &normalWorld, const Vector3 &pivotAInW, const Vector3 &pivotBInW); - void buildAngularJacobian(JacobianEntry3DSW &jacAngular, const Vector3 &jointAxisW); + void buildAngularJacobian(GodotJacobianEntry3D &jacAngular, const Vector3 &jointAxisW); //! calcs the euler angles between the two bodies. void calculateAngleInfo(); public: - Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB, bool useLinearReferenceFrameA); + GodotGeneric6DOFJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameInA, const Transform3D &frameInB, bool useLinearReferenceFrameA); virtual PhysicsServer3D::JointType get_type() const override { return PhysicsServer3D::JOINT_TYPE_6DOF; } virtual bool setup(real_t p_step) override; virtual void solve(real_t p_step) override; - //! Calcs global transform of the offsets - /*! - Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies. - \sa Generic6DOFJointSW.getCalculatedTransformA , Generic6DOFJointSW.getCalculatedTransformB, Generic6DOFJointSW.calculateAngleInfo - */ + // Calcs the global transform for the joint offset for body A an B, and also calcs the angle differences between the bodies. void calculateTransforms(); - //! Gets the global transform of the offset for body A - /*! - \sa Generic6DOFJointSW.getFrameOffsetA, Generic6DOFJointSW.getFrameOffsetB, Generic6DOFJointSW.calculateAngleInfo. - */ + // Gets the global transform of the offset for body A. const Transform3D &getCalculatedTransformA() const { return m_calculatedTransformA; } - //! Gets the global transform of the offset for body B - /*! - \sa Generic6DOFJointSW.getFrameOffsetA, Generic6DOFJointSW.getFrameOffsetB, Generic6DOFJointSW.calculateAngleInfo. - */ + // Gets the global transform of the offset for body B. const Transform3D &getCalculatedTransformB() const { return m_calculatedTransformB; } @@ -250,27 +236,16 @@ public: return m_frameInB; } - //! performs Jacobian calculation, and also calculates angle differences and axis - + // Performs Jacobian calculation, and also calculates angle differences and axis. void updateRHS(real_t timeStep); - //! Get the rotation axis in global coordinates - /*! - \pre Generic6DOFJointSW.buildJacobian must be called previously. - */ + // Get the rotation axis in global coordinates. Vector3 getAxis(int axis_index) const; - //! Get the relative Euler angle - /*! - \pre Generic6DOFJointSW.buildJacobian must be called previously. - */ + // Get the relative Euler angle. real_t getAngle(int axis_index) const; - //! Test angular limit. - /*! - Calculates angular correction and returns true if limit needs to be corrected. - \pre Generic6DOFJointSW.buildJacobian must be called previously. - */ + // Calculates angular correction and returns true if limit needs to be corrected. bool testAngularLimitMotor(int axis_index); void setLinearLowerLimit(const Vector3 &linearLower) { @@ -293,17 +268,17 @@ public: m_angularLimits[2].m_hiLimit = angularUpper.z; } - //! Retrieves the angular limit information. - G6DOFRotationalLimitMotor3DSW *getRotationalLimitMotor(int index) { + // Retrieves the angular limit information. + GodotG6DOFRotationalLimitMotor3D *getRotationalLimitMotor(int index) { return &m_angularLimits[index]; } - //! Retrieves the limit information. - G6DOFTranslationalLimitMotor3DSW *getTranslationalLimitMotor() { + // Retrieves the limit information. + GodotG6DOFTranslationalLimitMotor3D *getTranslationalLimitMotor() { return &m_linearLimits; } - //first 3 are linear, next 3 are angular + // First 3 are linear, next 3 are angular. void setLimit(int axis, real_t lo, real_t hi) { if (axis < 3) { m_linearLimits.m_lowerLimit[axis] = lo; @@ -328,10 +303,10 @@ public: return m_angularLimits[limitIndex - 3].isLimited(); } - const Body3DSW *getRigidBodyA() const { + const GodotBody3D *getRigidBodyA() const { return A; } - const Body3DSW *getRigidBodyB() const { + const GodotBody3D *getRigidBodyB() const { return B; } @@ -344,4 +319,4 @@ public: bool get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const; }; -#endif // GENERIC_6DOF_JOINT_SW_H +#endif // GODOT_GENERIC_6DOF_JOINT_3D_H diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp b/servers/physics_3d/joints/godot_hinge_joint_3d.cpp index a45fcf7eb5..7b7ca1b3ac 100644 --- a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/godot_hinge_joint_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* hinge_joint_3d_sw.cpp */ +/* godot_hinge_joint_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -47,7 +47,7 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#include "hinge_joint_3d_sw.h" +#include "godot_hinge_joint_3d.h" static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) { if (Math::abs(n.z) > Math_SQRT12) { @@ -67,8 +67,8 @@ static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) { } } -HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameA, const Transform3D &frameB) : - Joint3DSW(_arr, 2) { +GodotHingeJoint3D::GodotHingeJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameA, const Transform3D &frameB) : + GodotJoint3D(_arr, 2) { A = rbA; B = rbB; @@ -83,9 +83,9 @@ HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D & B->add_constraint(this, 1); } -HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, +GodotHingeJoint3D::GodotHingeJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB) : - Joint3DSW(_arr, 2) { + GodotJoint3D(_arr, 2) { A = rbA; B = rbB; @@ -124,7 +124,7 @@ HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Vector3 &pivo B->add_constraint(this, 1); } -bool HingeJoint3DSW::setup(real_t p_step) { +bool GodotHingeJoint3D::setup(real_t p_step) { dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); @@ -149,7 +149,7 @@ bool HingeJoint3DSW::setup(real_t p_step) { plane_space(normal[0], normal[1], normal[2]); for (int i = 0; i < 3; i++) { - memnew_placement(&m_jac[i], JacobianEntry3DSW( + memnew_placement(&m_jac[i], GodotJacobianEntry3D( A->get_principal_inertia_axes().transposed(), B->get_principal_inertia_axes().transposed(), pivotAInW - A->get_transform().origin - A->get_center_of_mass(), @@ -175,19 +175,19 @@ bool HingeJoint3DSW::setup(real_t p_step) { Vector3 jointAxis1 = A->get_transform().basis.xform(jointAxis1local); Vector3 hingeAxisWorld = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2)); - memnew_placement(&m_jacAng[0], JacobianEntry3DSW(jointAxis0, + memnew_placement(&m_jacAng[0], GodotJacobianEntry3D(jointAxis0, A->get_principal_inertia_axes().transposed(), B->get_principal_inertia_axes().transposed(), A->get_inv_inertia(), B->get_inv_inertia())); - memnew_placement(&m_jacAng[1], JacobianEntry3DSW(jointAxis1, + memnew_placement(&m_jacAng[1], GodotJacobianEntry3D(jointAxis1, A->get_principal_inertia_axes().transposed(), B->get_principal_inertia_axes().transposed(), A->get_inv_inertia(), B->get_inv_inertia())); - memnew_placement(&m_jacAng[2], JacobianEntry3DSW(hingeAxisWorld, + memnew_placement(&m_jacAng[2], GodotJacobianEntry3D(hingeAxisWorld, A->get_principal_inertia_axes().transposed(), B->get_principal_inertia_axes().transposed(), A->get_inv_inertia(), @@ -226,7 +226,7 @@ bool HingeJoint3DSW::setup(real_t p_step) { return true; } -void HingeJoint3DSW::solve(real_t p_step) { +void GodotHingeJoint3D::solve(real_t p_step) { Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin); Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin); @@ -377,7 +377,7 @@ static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { return (y < 0.0f) ? -angle : angle; } -real_t HingeJoint3DSW::get_hinge_angle() { +real_t GodotHingeJoint3D::get_hinge_angle() { const Vector3 refAxis0 = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(0)); const Vector3 refAxis1 = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(1)); const Vector3 swingAxis = B->get_transform().basis.xform(m_rbBFrame.basis.get_axis(1)); @@ -385,7 +385,7 @@ real_t HingeJoint3DSW::get_hinge_angle() { return atan2fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); } -void HingeJoint3DSW::set_param(PhysicsServer3D::HingeJointParam p_param, real_t p_value) { +void GodotHingeJoint3D::set_param(PhysicsServer3D::HingeJointParam p_param, real_t p_value) { switch (p_param) { case PhysicsServer3D::HINGE_JOINT_BIAS: tau = p_value; @@ -416,7 +416,7 @@ void HingeJoint3DSW::set_param(PhysicsServer3D::HingeJointParam p_param, real_t } } -real_t HingeJoint3DSW::get_param(PhysicsServer3D::HingeJointParam p_param) const { +real_t GodotHingeJoint3D::get_param(PhysicsServer3D::HingeJointParam p_param) const { switch (p_param) { case PhysicsServer3D::HINGE_JOINT_BIAS: return tau; @@ -441,7 +441,7 @@ real_t HingeJoint3DSW::get_param(PhysicsServer3D::HingeJointParam p_param) const return 0; } -void HingeJoint3DSW::set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value) { +void GodotHingeJoint3D::set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value) { switch (p_flag) { case PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT: m_useLimit = p_value; @@ -454,7 +454,7 @@ void HingeJoint3DSW::set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_val } } -bool HingeJoint3DSW::get_flag(PhysicsServer3D::HingeJointFlag p_flag) const { +bool GodotHingeJoint3D::get_flag(PhysicsServer3D::HingeJointFlag p_flag) const { switch (p_flag) { case PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT: return m_useLimit; diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.h b/servers/physics_3d/joints/godot_hinge_joint_3d.h index a4ceff9ffe..ff1fbe0f25 100644 --- a/servers/physics_3d/joints/hinge_joint_3d_sw.h +++ b/servers/physics_3d/joints/godot_hinge_joint_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* hinge_joint_3d_sw.h */ +/* godot_hinge_joint_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -32,11 +32,11 @@ Adapted to Godot from the Bullet library. */ -#ifndef HINGE_JOINT_SW_H -#define HINGE_JOINT_SW_H +#ifndef GODOT_HINGE_JOINT_3D_H +#define GODOT_HINGE_JOINT_3D_H -#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h" -#include "servers/physics_3d/joints_3d_sw.h" +#include "servers/physics_3d/godot_joint_3d.h" +#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h" /* Bullet Continuous Collision Detection and Physics Library @@ -53,18 +53,18 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -class HingeJoint3DSW : public Joint3DSW { +class GodotHingeJoint3D : public GodotJoint3D { union { struct { - Body3DSW *A; - Body3DSW *B; + GodotBody3D *A; + GodotBody3D *B; }; - Body3DSW *_arr[2] = {}; + GodotBody3D *_arr[2] = {}; }; - JacobianEntry3DSW m_jac[3]; //3 orthogonal linear constraints - JacobianEntry3DSW m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor + GodotJacobianEntry3D m_jac[3]; //3 orthogonal linear constraints + GodotJacobianEntry3D m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor Transform3D m_rbAFrame; // constraint axii. Assumes z is hinge axis. Transform3D m_rbBFrame; @@ -109,8 +109,8 @@ public: void set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value); bool get_flag(PhysicsServer3D::HingeJointFlag p_flag) const; - HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameA, const Transform3D &frameB); - HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB); + GodotHingeJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameA, const Transform3D &frameB); + GodotHingeJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB); }; -#endif // HINGE_JOINT_SW_H +#endif // GODOT_HINGE_JOINT_3D_H diff --git a/servers/physics_3d/joints/jacobian_entry_3d_sw.h b/servers/physics_3d/joints/godot_jacobian_entry_3d.h index 7294ff78e3..90a77a9b61 100644 --- a/servers/physics_3d/joints/jacobian_entry_3d_sw.h +++ b/servers/physics_3d/joints/godot_jacobian_entry_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* jacobian_entry_3d_sw.h */ +/* godot_jacobian_entry_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -32,8 +32,8 @@ Adapted to Godot from the Bullet library. */ -#ifndef JACOBIAN_ENTRY_SW_H -#define JACOBIAN_ENTRY_SW_H +#ifndef GODOT_JACOBIAN_ENTRY_3D_H +#define GODOT_JACOBIAN_ENTRY_3D_H /* Bullet Continuous Collision Detection and Physics Library @@ -52,11 +52,11 @@ subject to the following restrictions: #include "core/math/transform_3d.h" -class JacobianEntry3DSW { +class GodotJacobianEntry3D { public: - JacobianEntry3DSW() {} + GodotJacobianEntry3D() {} //constraint between two different rigidbodies - JacobianEntry3DSW( + GodotJacobianEntry3D( const Basis &world2A, const Basis &world2B, const Vector3 &rel_pos1, const Vector3 &rel_pos2, @@ -76,7 +76,7 @@ public: } //angular constraint between two different rigidbodies - JacobianEntry3DSW(const Vector3 &jointAxis, + GodotJacobianEntry3D(const Vector3 &jointAxis, const Basis &world2A, const Basis &world2B, const Vector3 &inertiaInvA, @@ -92,7 +92,7 @@ public: } //angular constraint between two different rigidbodies - JacobianEntry3DSW(const Vector3 &axisInA, + GodotJacobianEntry3D(const Vector3 &axisInA, const Vector3 &axisInB, const Vector3 &inertiaInvA, const Vector3 &inertiaInvB) : @@ -107,7 +107,7 @@ public: } //constraint on one rigidbody - JacobianEntry3DSW( + GodotJacobianEntry3D( const Basis &world2A, const Vector3 &rel_pos1, const Vector3 &rel_pos2, const Vector3 &jointAxis, @@ -126,16 +126,16 @@ public: real_t getDiagonal() const { return m_Adiag; } // for two constraints on the same rigidbody (for example vehicle friction) - real_t getNonDiagonal(const JacobianEntry3DSW &jacB, const real_t massInvA) const { - const JacobianEntry3DSW &jacA = *this; + real_t getNonDiagonal(const GodotJacobianEntry3D &jacB, const real_t massInvA) const { + const GodotJacobianEntry3D &jacA = *this; real_t lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis); real_t ang = jacA.m_0MinvJt.dot(jacB.m_aJ); return lin + ang; } // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies) - real_t getNonDiagonal(const JacobianEntry3DSW &jacB, const real_t massInvA, const real_t massInvB) const { - const JacobianEntry3DSW &jacA = *this; + real_t getNonDiagonal(const GodotJacobianEntry3D &jacB, const real_t massInvA, const real_t massInvB) const { + const GodotJacobianEntry3D &jacA = *this; Vector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis; Vector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ; Vector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ; @@ -166,4 +166,4 @@ public: real_t m_Adiag = 1.0; }; -#endif // JACOBIAN_ENTRY_SW_H +#endif // GODOT_JACOBIAN_ENTRY_3D_H diff --git a/servers/physics_3d/joints/pin_joint_3d_sw.cpp b/servers/physics_3d/joints/godot_pin_joint_3d.cpp index f41151ec0e..10d52ad5e9 100644 --- a/servers/physics_3d/joints/pin_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/godot_pin_joint_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* pin_joint_3d_sw.cpp */ +/* godot_pin_joint_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -47,9 +47,9 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#include "pin_joint_3d_sw.h" +#include "godot_pin_joint_3d.h" -bool PinJoint3DSW::setup(real_t p_step) { +bool GodotPinJoint3D::setup(real_t p_step) { dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); @@ -63,7 +63,7 @@ bool PinJoint3DSW::setup(real_t p_step) { for (int i = 0; i < 3; i++) { normal[i] = 1; - memnew_placement(&m_jac[i], JacobianEntry3DSW( + memnew_placement(&m_jac[i], GodotJacobianEntry3D( A->get_principal_inertia_axes().transposed(), B->get_principal_inertia_axes().transposed(), A->get_transform().xform(m_pivotInA) - A->get_transform().origin - A->get_center_of_mass(), @@ -79,7 +79,7 @@ bool PinJoint3DSW::setup(real_t p_step) { return true; } -void PinJoint3DSW::solve(real_t p_step) { +void GodotPinJoint3D::solve(real_t p_step) { Vector3 pivotAInW = A->get_transform().xform(m_pivotInA); Vector3 pivotBInW = B->get_transform().xform(m_pivotInB); @@ -137,7 +137,7 @@ void PinJoint3DSW::solve(real_t p_step) { } } -void PinJoint3DSW::set_param(PhysicsServer3D::PinJointParam p_param, real_t p_value) { +void GodotPinJoint3D::set_param(PhysicsServer3D::PinJointParam p_param, real_t p_value) { switch (p_param) { case PhysicsServer3D::PIN_JOINT_BIAS: m_tau = p_value; @@ -151,7 +151,7 @@ void PinJoint3DSW::set_param(PhysicsServer3D::PinJointParam p_param, real_t p_va } } -real_t PinJoint3DSW::get_param(PhysicsServer3D::PinJointParam p_param) const { +real_t GodotPinJoint3D::get_param(PhysicsServer3D::PinJointParam p_param) const { switch (p_param) { case PhysicsServer3D::PIN_JOINT_BIAS: return m_tau; @@ -164,8 +164,8 @@ real_t PinJoint3DSW::get_param(PhysicsServer3D::PinJointParam p_param) const { return 0; } -PinJoint3DSW::PinJoint3DSW(Body3DSW *p_body_a, const Vector3 &p_pos_a, Body3DSW *p_body_b, const Vector3 &p_pos_b) : - Joint3DSW(_arr, 2) { +GodotPinJoint3D::GodotPinJoint3D(GodotBody3D *p_body_a, const Vector3 &p_pos_a, GodotBody3D *p_body_b, const Vector3 &p_pos_b) : + GodotJoint3D(_arr, 2) { A = p_body_a; B = p_body_b; m_pivotInA = p_pos_a; @@ -175,5 +175,5 @@ PinJoint3DSW::PinJoint3DSW(Body3DSW *p_body_a, const Vector3 &p_pos_a, Body3DSW B->add_constraint(this, 1); } -PinJoint3DSW::~PinJoint3DSW() { +GodotPinJoint3D::~GodotPinJoint3D() { } diff --git a/servers/physics_3d/joints/pin_joint_3d_sw.h b/servers/physics_3d/joints/godot_pin_joint_3d.h index 79af48f2a5..17e2e6e973 100644 --- a/servers/physics_3d/joints/pin_joint_3d_sw.h +++ b/servers/physics_3d/joints/godot_pin_joint_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* pin_joint_3d_sw.h */ +/* godot_pin_joint_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -32,11 +32,11 @@ Adapted to Godot from the Bullet library. */ -#ifndef PIN_JOINT_SW_H -#define PIN_JOINT_SW_H +#ifndef GODOT_PIN_JOINT_3D_H +#define GODOT_PIN_JOINT_3D_H -#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h" -#include "servers/physics_3d/joints_3d_sw.h" +#include "servers/physics_3d/godot_joint_3d.h" +#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h" /* Bullet Continuous Collision Detection and Physics Library @@ -53,14 +53,14 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -class PinJoint3DSW : public Joint3DSW { +class GodotPinJoint3D : public GodotJoint3D { union { struct { - Body3DSW *A; - Body3DSW *B; + GodotBody3D *A; + GodotBody3D *B; }; - Body3DSW *_arr[2] = {}; + GodotBody3D *_arr[2] = {}; }; real_t m_tau = 0.3; //bias @@ -68,7 +68,7 @@ class PinJoint3DSW : public Joint3DSW { real_t m_impulseClamp = 0.0; real_t m_appliedImpulse = 0.0; - JacobianEntry3DSW m_jac[3] = {}; //3 orthogonal linear constraints + GodotJacobianEntry3D m_jac[3] = {}; //3 orthogonal linear constraints Vector3 m_pivotInA; Vector3 m_pivotInB; @@ -88,8 +88,8 @@ public: Vector3 get_position_a() { return m_pivotInA; } Vector3 get_position_b() { return m_pivotInB; } - PinJoint3DSW(Body3DSW *p_body_a, const Vector3 &p_pos_a, Body3DSW *p_body_b, const Vector3 &p_pos_b); - ~PinJoint3DSW(); + GodotPinJoint3D(GodotBody3D *p_body_a, const Vector3 &p_pos_a, GodotBody3D *p_body_b, const Vector3 &p_pos_b); + ~GodotPinJoint3D(); }; -#endif // PIN_JOINT_SW_H +#endif // GODOT_PIN_JOINT_3D_H diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.cpp b/servers/physics_3d/joints/godot_slider_joint_3d.cpp index e10ed436d5..3be111ac92 100644 --- a/servers/physics_3d/joints/slider_joint_3d_sw.cpp +++ b/servers/physics_3d/joints/godot_slider_joint_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* slider_joint_3d_sw.cpp */ +/* godot_slider_joint_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -53,7 +53,7 @@ April 04, 2008 */ -#include "slider_joint_3d_sw.h" +#include "godot_slider_joint_3d.h" //----------------------------------------------------------------------------- @@ -76,8 +76,8 @@ static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { //----------------------------------------------------------------------------- -SliderJoint3DSW::SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB) : - Joint3DSW(_arr, 2), +GodotSliderJoint3D::GodotSliderJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameInA, const Transform3D &frameInB) : + GodotJoint3D(_arr, 2), m_frameInA(frameInA), m_frameInB(frameInB) { A = rbA; @@ -85,11 +85,11 @@ SliderJoint3DSW::SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D A->add_constraint(this, 0); B->add_constraint(this, 1); -} // SliderJointSW::SliderJointSW() +} //----------------------------------------------------------------------------- -bool SliderJoint3DSW::setup(real_t p_step) { +bool GodotSliderJoint3D::setup(real_t p_step) { dynamic_A = (A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); dynamic_B = (B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC); @@ -112,7 +112,7 @@ bool SliderJoint3DSW::setup(real_t p_step) { //linear part for (i = 0; i < 3; i++) { normalWorld = m_calculatedTransformA.basis.get_axis(i); - memnew_placement(&m_jacLin[i], JacobianEntry3DSW( + memnew_placement(&m_jacLin[i], GodotJacobianEntry3D( A->get_principal_inertia_axes().transposed(), B->get_principal_inertia_axes().transposed(), m_relPosA - A->get_center_of_mass(), @@ -129,7 +129,7 @@ bool SliderJoint3DSW::setup(real_t p_step) { // angular part for (i = 0; i < 3; i++) { normalWorld = m_calculatedTransformA.basis.get_axis(i); - memnew_placement(&m_jacAng[i], JacobianEntry3DSW( + memnew_placement(&m_jacAng[i], GodotJacobianEntry3D( normalWorld, A->get_principal_inertia_axes().transposed(), B->get_principal_inertia_axes().transposed(), @@ -144,11 +144,11 @@ bool SliderJoint3DSW::setup(real_t p_step) { m_accumulatedAngMotorImpulse = real_t(0.0); return true; -} // SliderJointSW::buildJacobianInt() +} //----------------------------------------------------------------------------- -void SliderJoint3DSW::solve(real_t p_step) { +void GodotSliderJoint3D::solve(real_t p_step) { int i; // linear Vector3 velA = A->get_velocity_in_local_point(m_relPosA); @@ -284,13 +284,11 @@ void SliderJoint3DSW::solve(real_t p_step) { } } } -} // SliderJointSW::solveConstraint() - -//----------------------------------------------------------------------------- +} //----------------------------------------------------------------------------- -void SliderJoint3DSW::calculateTransforms() { +void GodotSliderJoint3D::calculateTransforms() { m_calculatedTransformA = A->get_transform() * m_frameInA; m_calculatedTransformB = B->get_transform() * m_frameInB; m_realPivotAInW = m_calculatedTransformA.origin; @@ -305,11 +303,11 @@ void SliderJoint3DSW::calculateTransforms() { normalWorld = m_calculatedTransformA.basis.get_axis(i); m_depth[i] = m_delta.dot(normalWorld); } -} // SliderJointSW::calculateTransforms() +} //----------------------------------------------------------------------------- -void SliderJoint3DSW::testLinLimits() { +void GodotSliderJoint3D::testLinLimits() { m_solveLinLim = false; m_linPos = m_depth[0]; if (m_lowerLinLimit <= m_upperLinLimit) { @@ -325,11 +323,11 @@ void SliderJoint3DSW::testLinLimits() { } else { m_depth[0] = real_t(0.); } -} // SliderJointSW::testLinLimits() +} //----------------------------------------------------------------------------- -void SliderJoint3DSW::testAngLimits() { +void GodotSliderJoint3D::testAngLimits() { m_angDepth = real_t(0.); m_solveAngLim = false; if (m_lowerAngLimit <= m_upperAngLimit) { @@ -345,26 +343,26 @@ void SliderJoint3DSW::testAngLimits() { m_solveAngLim = true; } } -} // SliderJointSW::testAngLimits() +} //----------------------------------------------------------------------------- -Vector3 SliderJoint3DSW::getAncorInA() { +Vector3 GodotSliderJoint3D::getAncorInA() { Vector3 ancorInA; ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * real_t(0.5) * m_sliderAxis; ancorInA = A->get_transform().inverse().xform(ancorInA); return ancorInA; -} // SliderJointSW::getAncorInA() +} //----------------------------------------------------------------------------- -Vector3 SliderJoint3DSW::getAncorInB() { +Vector3 GodotSliderJoint3D::getAncorInB() { Vector3 ancorInB; ancorInB = m_frameInB.origin; return ancorInB; -} // SliderJointSW::getAncorInB(); +} -void SliderJoint3DSW::set_param(PhysicsServer3D::SliderJointParam p_param, real_t p_value) { +void GodotSliderJoint3D::set_param(PhysicsServer3D::SliderJointParam p_param, real_t p_value) { switch (p_param) { case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER: m_upperLinLimit = p_value; @@ -439,7 +437,7 @@ void SliderJoint3DSW::set_param(PhysicsServer3D::SliderJointParam p_param, real_ } } -real_t SliderJoint3DSW::get_param(PhysicsServer3D::SliderJointParam p_param) const { +real_t GodotSliderJoint3D::get_param(PhysicsServer3D::SliderJointParam p_param) const { switch (p_param) { case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER: return m_upperLinLimit; diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.h b/servers/physics_3d/joints/godot_slider_joint_3d.h index d32ad9469e..9baaf1fa40 100644 --- a/servers/physics_3d/joints/slider_joint_3d_sw.h +++ b/servers/physics_3d/joints/godot_slider_joint_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* slider_joint_3d_sw.h */ +/* godot_slider_joint_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -32,11 +32,11 @@ Adapted to Godot from the Bullet library. */ -#ifndef SLIDER_JOINT_SW_H -#define SLIDER_JOINT_SW_H +#ifndef GODOT_SLIDER_JOINT_3D_H +#define GODOT_SLIDER_JOINT_3D_H -#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h" -#include "servers/physics_3d/joints_3d_sw.h" +#include "servers/physics_3d/godot_joint_3d.h" +#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h" /* Bullet Continuous Collision Detection and Physics Library @@ -65,15 +65,15 @@ April 04, 2008 //----------------------------------------------------------------------------- -class SliderJoint3DSW : public Joint3DSW { +class GodotSliderJoint3D : public GodotJoint3D { protected: union { struct { - Body3DSW *A; - Body3DSW *B; + GodotBody3D *A; + GodotBody3D *B; }; - Body3DSW *_arr[2] = { nullptr, nullptr }; + GodotBody3D *_arr[2] = { nullptr, nullptr }; }; Transform3D m_frameInA; @@ -114,10 +114,10 @@ protected: bool m_solveLinLim = false; bool m_solveAngLim = false; - JacobianEntry3DSW m_jacLin[3] = {}; + GodotJacobianEntry3D m_jacLin[3] = {}; real_t m_jacLinDiagABInv[3] = {}; - JacobianEntry3DSW m_jacAng[3] = {}; + GodotJacobianEntry3D m_jacAng[3] = {}; real_t m_timeStep = 0.0; Transform3D m_calculatedTransformA; @@ -149,13 +149,13 @@ protected: public: // constructors - SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform3D &frameInA, const Transform3D &frameInB); + GodotSliderJoint3D(GodotBody3D *rbA, GodotBody3D *rbB, const Transform3D &frameInA, const Transform3D &frameInB); //SliderJointSW(); // overrides // access - const Body3DSW *getRigidBodyA() const { return A; } - const Body3DSW *getRigidBodyB() const { return B; } + const GodotBody3D *getRigidBodyA() const { return A; } + const GodotBody3D *getRigidBodyB() const { return B; } const Transform3D &getCalculatedTransformA() const { return m_calculatedTransformA; } const Transform3D &getCalculatedTransformB() const { return m_calculatedTransformB; } const Transform3D &getFrameOffsetA() const { return m_frameInA; } @@ -243,4 +243,4 @@ public: virtual PhysicsServer3D::JointType get_type() const override { return PhysicsServer3D::JOINT_TYPE_SLIDER; } }; -#endif // SLIDER_JOINT_SW_H +#endif // GODOT_SLIDER_JOINT_3D_H diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp deleted file mode 100644 index b16e199a03..0000000000 --- a/servers/physics_3d/physics_server_3d_sw.cpp +++ /dev/null @@ -1,1748 +0,0 @@ -/*************************************************************************/ -/* physics_server_3d_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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 "physics_server_3d_sw.h" - -#include "body_direct_state_3d_sw.h" -#include "broad_phase_3d_bvh.h" -#include "core/debugger/engine_debugger.h" -#include "core/os/os.h" -#include "joints/cone_twist_joint_3d_sw.h" -#include "joints/generic_6dof_joint_3d_sw.h" -#include "joints/hinge_joint_3d_sw.h" -#include "joints/pin_joint_3d_sw.h" -#include "joints/slider_joint_3d_sw.h" - -#define FLUSH_QUERY_CHECK(m_object) \ - ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead."); - -RID PhysicsServer3DSW::world_boundary_shape_create() { - Shape3DSW *shape = memnew(WorldBoundaryShape3DSW); - RID rid = shape_owner.make_rid(shape); - shape->set_self(rid); - return rid; -} -RID PhysicsServer3DSW::separation_ray_shape_create() { - Shape3DSW *shape = memnew(SeparationRayShape3DSW); - RID rid = shape_owner.make_rid(shape); - shape->set_self(rid); - return rid; -} -RID PhysicsServer3DSW::sphere_shape_create() { - Shape3DSW *shape = memnew(SphereShape3DSW); - RID rid = shape_owner.make_rid(shape); - shape->set_self(rid); - return rid; -} -RID PhysicsServer3DSW::box_shape_create() { - Shape3DSW *shape = memnew(BoxShape3DSW); - RID rid = shape_owner.make_rid(shape); - shape->set_self(rid); - return rid; -} -RID PhysicsServer3DSW::capsule_shape_create() { - Shape3DSW *shape = memnew(CapsuleShape3DSW); - RID rid = shape_owner.make_rid(shape); - shape->set_self(rid); - return rid; -} -RID PhysicsServer3DSW::cylinder_shape_create() { - Shape3DSW *shape = memnew(CylinderShape3DSW); - RID rid = shape_owner.make_rid(shape); - shape->set_self(rid); - return rid; -} -RID PhysicsServer3DSW::convex_polygon_shape_create() { - Shape3DSW *shape = memnew(ConvexPolygonShape3DSW); - RID rid = shape_owner.make_rid(shape); - shape->set_self(rid); - return rid; -} -RID PhysicsServer3DSW::concave_polygon_shape_create() { - Shape3DSW *shape = memnew(ConcavePolygonShape3DSW); - RID rid = shape_owner.make_rid(shape); - shape->set_self(rid); - return rid; -} -RID PhysicsServer3DSW::heightmap_shape_create() { - Shape3DSW *shape = memnew(HeightMapShape3DSW); - RID rid = shape_owner.make_rid(shape); - shape->set_self(rid); - return rid; -} -RID PhysicsServer3DSW::custom_shape_create() { - ERR_FAIL_V(RID()); -} - -void PhysicsServer3DSW::shape_set_data(RID p_shape, const Variant &p_data) { - Shape3DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - shape->set_data(p_data); -}; - -void PhysicsServer3DSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { - Shape3DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - shape->set_custom_bias(p_bias); -} - -PhysicsServer3D::ShapeType PhysicsServer3DSW::shape_get_type(RID p_shape) const { - const Shape3DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM); - return shape->get_type(); -}; - -Variant PhysicsServer3DSW::shape_get_data(RID p_shape) const { - const Shape3DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND_V(!shape, Variant()); - ERR_FAIL_COND_V(!shape->is_configured(), Variant()); - return shape->get_data(); -}; - -void PhysicsServer3DSW::shape_set_margin(RID p_shape, real_t p_margin) { -} - -real_t PhysicsServer3DSW::shape_get_margin(RID p_shape) const { - return 0.0; -} - -real_t PhysicsServer3DSW::shape_get_custom_solver_bias(RID p_shape) const { - const Shape3DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND_V(!shape, 0); - return shape->get_custom_bias(); -} - -RID PhysicsServer3DSW::space_create() { - Space3DSW *space = memnew(Space3DSW); - RID id = space_owner.make_rid(space); - space->set_self(id); - RID area_id = area_create(); - Area3DSW *area = area_owner.get_or_null(area_id); - ERR_FAIL_COND_V(!area, RID()); - space->set_default_area(area); - area->set_space(space); - area->set_priority(-1); - RID sgb = body_create(); - body_set_space(sgb, id); - body_set_mode(sgb, BODY_MODE_STATIC); - space->set_static_global_body(sgb); - - return id; -}; - -void PhysicsServer3DSW::space_set_active(RID p_space, bool p_active) { - Space3DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space); - if (p_active) { - active_spaces.insert(space); - } else { - active_spaces.erase(space); - } -} - -bool PhysicsServer3DSW::space_is_active(RID p_space) const { - const Space3DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND_V(!space, false); - - return active_spaces.has(space); -} - -void PhysicsServer3DSW::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { - Space3DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space); - - space->set_param(p_param, p_value); -} - -real_t PhysicsServer3DSW::space_get_param(RID p_space, SpaceParameter p_param) const { - const Space3DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND_V(!space, 0); - return space->get_param(p_param); -} - -PhysicsDirectSpaceState3D *PhysicsServer3DSW::space_get_direct_state(RID p_space) { - Space3DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND_V(!space, nullptr); - ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), nullptr, "Space state is inaccessible right now, wait for iteration or physics process notification."); - - return space->get_direct_state(); -} - -void PhysicsServer3DSW::space_set_debug_contacts(RID p_space, int p_max_contacts) { - Space3DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space); - space->set_debug_contacts(p_max_contacts); -} - -Vector<Vector3> PhysicsServer3DSW::space_get_contacts(RID p_space) const { - Space3DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND_V(!space, Vector<Vector3>()); - return space->get_debug_contacts(); -} - -int PhysicsServer3DSW::space_get_contact_count(RID p_space) const { - Space3DSW *space = space_owner.get_or_null(p_space); - ERR_FAIL_COND_V(!space, 0); - return space->get_debug_contact_count(); -} - -RID PhysicsServer3DSW::area_create() { - Area3DSW *area = memnew(Area3DSW); - RID rid = area_owner.make_rid(area); - area->set_self(rid); - return rid; -}; - -void PhysicsServer3DSW::area_set_space(RID p_area, RID p_space) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - Space3DSW *space = nullptr; - if (p_space.is_valid()) { - space = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space); - } - - if (area->get_space() == space) { - return; //pointless - } - - area->clear_constraints(); - area->set_space(space); -}; - -RID PhysicsServer3DSW::area_get_space(RID p_area) const { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, RID()); - - Space3DSW *space = area->get_space(); - if (!space) { - return RID(); - } - return space->get_self(); -}; - -void PhysicsServer3DSW::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_space_override_mode(p_mode); -} - -PhysicsServer3D::AreaSpaceOverrideMode PhysicsServer3DSW::area_get_space_override_mode(RID p_area) const { - const Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); - - return area->get_space_override_mode(); -} - -void PhysicsServer3DSW::area_add_shape(RID p_area, RID p_shape, const Transform3D &p_transform, bool p_disabled) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - Shape3DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - - area->add_shape(shape, p_transform, p_disabled); -} - -void PhysicsServer3DSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - Shape3DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - ERR_FAIL_COND(!shape->is_configured()); - - area->set_shape(p_shape_idx, shape); -} - -void PhysicsServer3DSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform3D &p_transform) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_shape_transform(p_shape_idx, p_transform); -} - -int PhysicsServer3DSW::area_get_shape_count(RID p_area) const { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, -1); - - return area->get_shape_count(); -} - -RID PhysicsServer3DSW::area_get_shape(RID p_area, int p_shape_idx) const { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, RID()); - - Shape3DSW *shape = area->get_shape(p_shape_idx); - ERR_FAIL_COND_V(!shape, RID()); - - return shape->get_self(); -} - -Transform3D PhysicsServer3DSW::area_get_shape_transform(RID p_area, int p_shape_idx) const { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, Transform3D()); - - return area->get_shape_transform(p_shape_idx); -} - -void PhysicsServer3DSW::area_remove_shape(RID p_area, int p_shape_idx) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->remove_shape(p_shape_idx); -} - -void PhysicsServer3DSW::area_clear_shapes(RID p_area) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - while (area->get_shape_count()) { - area->remove_shape(0); - } -} - -void PhysicsServer3DSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count()); - FLUSH_QUERY_CHECK(area); - area->set_shape_disabled(p_shape_idx, p_disabled); -} - -void PhysicsServer3DSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) { - if (space_owner.owns(p_area)) { - Space3DSW *space = space_owner.get_or_null(p_area); - p_area = space->get_default_area()->get_self(); - } - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - area->set_instance_id(p_id); -} - -ObjectID PhysicsServer3DSW::area_get_object_instance_id(RID p_area) const { - if (space_owner.owns(p_area)) { - Space3DSW *space = space_owner.get_or_null(p_area); - p_area = space->get_default_area()->get_self(); - } - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, ObjectID()); - return area->get_instance_id(); -} - -void PhysicsServer3DSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { - if (space_owner.owns(p_area)) { - Space3DSW *space = space_owner.get_or_null(p_area); - p_area = space->get_default_area()->get_self(); - } - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - area->set_param(p_param, p_value); -}; - -void PhysicsServer3DSW::area_set_transform(RID p_area, const Transform3D &p_transform) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - area->set_transform(p_transform); -}; - -Variant PhysicsServer3DSW::area_get_param(RID p_area, AreaParameter p_param) const { - if (space_owner.owns(p_area)) { - Space3DSW *space = space_owner.get_or_null(p_area); - p_area = space->get_default_area()->get_self(); - } - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, Variant()); - - return area->get_param(p_param); -}; - -Transform3D PhysicsServer3DSW::area_get_transform(RID p_area) const { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND_V(!area, Transform3D()); - - return area->get_transform(); -}; - -void PhysicsServer3DSW::area_set_collision_layer(RID p_area, uint32_t p_layer) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_collision_layer(p_layer); -} - -void PhysicsServer3DSW::area_set_collision_mask(RID p_area, uint32_t p_mask) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_collision_mask(p_mask); -} - -void PhysicsServer3DSW::area_set_monitorable(RID p_area, bool p_monitorable) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - FLUSH_QUERY_CHECK(area); - - area->set_monitorable(p_monitorable); -} - -void PhysicsServer3DSW::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); -} - -void PhysicsServer3DSW::area_set_ray_pickable(RID p_area, bool p_enable) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_ray_pickable(p_enable); -} - -void PhysicsServer3DSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { - Area3DSW *area = area_owner.get_or_null(p_area); - ERR_FAIL_COND(!area); - - area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); -} - -/* BODY API */ - -RID PhysicsServer3DSW::body_create() { - Body3DSW *body = memnew(Body3DSW); - RID rid = body_owner.make_rid(body); - body->set_self(rid); - return rid; -}; - -void PhysicsServer3DSW::body_set_space(RID p_body, RID p_space) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - Space3DSW *space = nullptr; - if (p_space.is_valid()) { - space = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space); - } - - if (body->get_space() == space) { - return; //pointless - } - - body->clear_constraint_map(); - body->set_space(space); -}; - -RID PhysicsServer3DSW::body_get_space(RID p_body) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, RID()); - - Space3DSW *space = body->get_space(); - if (!space) { - return RID(); - } - return space->get_self(); -}; - -void PhysicsServer3DSW::body_set_mode(RID p_body, BodyMode p_mode) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_mode(p_mode); -}; - -PhysicsServer3D::BodyMode PhysicsServer3DSW::body_get_mode(RID p_body) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, BODY_MODE_STATIC); - - return body->get_mode(); -}; - -void PhysicsServer3DSW::body_add_shape(RID p_body, RID p_shape, const Transform3D &p_transform, bool p_disabled) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - Shape3DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - - body->add_shape(shape, p_transform, p_disabled); -} - -void PhysicsServer3DSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - Shape3DSW *shape = shape_owner.get_or_null(p_shape); - ERR_FAIL_COND(!shape); - ERR_FAIL_COND(!shape->is_configured()); - - body->set_shape(p_shape_idx, shape); -} -void PhysicsServer3DSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform3D &p_transform) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_shape_transform(p_shape_idx, p_transform); -} - -int PhysicsServer3DSW::body_get_shape_count(RID p_body) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, -1); - - return body->get_shape_count(); -} - -RID PhysicsServer3DSW::body_get_shape(RID p_body, int p_shape_idx) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, RID()); - - Shape3DSW *shape = body->get_shape(p_shape_idx); - ERR_FAIL_COND_V(!shape, RID()); - - return shape->get_self(); -} - -void PhysicsServer3DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); - FLUSH_QUERY_CHECK(body); - - body->set_shape_disabled(p_shape_idx, p_disabled); -} - -Transform3D PhysicsServer3DSW::body_get_shape_transform(RID p_body, int p_shape_idx) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, Transform3D()); - - return body->get_shape_transform(p_shape_idx); -} - -void PhysicsServer3DSW::body_remove_shape(RID p_body, int p_shape_idx) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->remove_shape(p_shape_idx); -} - -void PhysicsServer3DSW::body_clear_shapes(RID p_body) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - while (body->get_shape_count()) { - body->remove_shape(0); - } -} - -void PhysicsServer3DSW::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_continuous_collision_detection(p_enable); -} - -bool PhysicsServer3DSW::body_is_continuous_collision_detection_enabled(RID p_body) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, false); - - return body->is_continuous_collision_detection_enabled(); -} - -void PhysicsServer3DSW::body_set_collision_layer(RID p_body, uint32_t p_layer) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_collision_layer(p_layer); - body->wakeup(); -} - -uint32_t PhysicsServer3DSW::body_get_collision_layer(RID p_body) const { - const Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_collision_layer(); -} - -void PhysicsServer3DSW::body_set_collision_mask(RID p_body, uint32_t p_mask) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_collision_mask(p_mask); - body->wakeup(); -} - -uint32_t PhysicsServer3DSW::body_get_collision_mask(RID p_body) const { - const Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_collision_mask(); -} - -void PhysicsServer3DSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) { - Body3DSW *body = body_owner.get_or_null(p_body); - if (body) { - body->set_instance_id(p_id); - return; - } - - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - if (soft_body) { - soft_body->set_instance_id(p_id); - return; - } - - ERR_FAIL_MSG("Invalid ID."); -}; - -ObjectID PhysicsServer3DSW::body_get_object_instance_id(RID p_body) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, ObjectID()); - - return body->get_instance_id(); -}; - -void PhysicsServer3DSW::body_set_user_flags(RID p_body, uint32_t p_flags) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); -}; - -uint32_t PhysicsServer3DSW::body_get_user_flags(RID p_body) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, 0); - - return 0; -}; - -void PhysicsServer3DSW::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_param(p_param, p_value); -}; - -Variant PhysicsServer3DSW::body_get_param(RID p_body, BodyParameter p_param) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_param(p_param); -}; - -void PhysicsServer3DSW::body_reset_mass_properties(RID p_body) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - return body->reset_mass_properties(); -} - -void PhysicsServer3DSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_state(p_state, p_variant); -}; - -Variant PhysicsServer3DSW::body_get_state(RID p_body, BodyState p_state) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, Variant()); - - return body->get_state(p_state); -}; - -void PhysicsServer3DSW::body_set_applied_force(RID p_body, const Vector3 &p_force) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_applied_force(p_force); - body->wakeup(); -}; - -Vector3 PhysicsServer3DSW::body_get_applied_force(RID p_body) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, Vector3()); - return body->get_applied_force(); -}; - -void PhysicsServer3DSW::body_set_applied_torque(RID p_body, const Vector3 &p_torque) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_applied_torque(p_torque); - body->wakeup(); -}; - -Vector3 PhysicsServer3DSW::body_get_applied_torque(RID p_body) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, Vector3()); - - return body->get_applied_torque(); -}; - -void PhysicsServer3DSW::body_add_central_force(RID p_body, const Vector3 &p_force) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->add_central_force(p_force); - body->wakeup(); -} - -void PhysicsServer3DSW::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_position) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->add_force(p_force, p_position); - body->wakeup(); -}; - -void PhysicsServer3DSW::body_add_torque(RID p_body, const Vector3 &p_torque) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->add_torque(p_torque); - body->wakeup(); -}; - -void PhysicsServer3DSW::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - body->apply_central_impulse(p_impulse); - body->wakeup(); -} - -void PhysicsServer3DSW::body_apply_impulse(RID p_body, const Vector3 &p_impulse, const Vector3 &p_position) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - body->apply_impulse(p_impulse, p_position); - body->wakeup(); -}; - -void PhysicsServer3DSW::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - body->apply_torque_impulse(p_impulse); - body->wakeup(); -}; - -void PhysicsServer3DSW::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - Vector3 v = body->get_linear_velocity(); - Vector3 axis = p_axis_velocity.normalized(); - v -= axis * axis.dot(v); - v += p_axis_velocity; - body->set_linear_velocity(v); - body->wakeup(); -}; - -void PhysicsServer3DSW::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_axis_lock(p_axis, p_lock); - body->wakeup(); -} - -bool PhysicsServer3DSW::body_is_axis_locked(RID p_body, BodyAxis p_axis) const { - const Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, 0); - return body->is_axis_locked(p_axis); -} - -void PhysicsServer3DSW::body_add_collision_exception(RID p_body, RID p_body_b) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->add_exception(p_body_b); - body->wakeup(); -}; - -void PhysicsServer3DSW::body_remove_collision_exception(RID p_body, RID p_body_b) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->remove_exception(p_body_b); - body->wakeup(); -}; - -void PhysicsServer3DSW::body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - for (int i = 0; i < body->get_exceptions().size(); i++) { - p_exceptions->push_back(body->get_exceptions()[i]); - } -}; - -void PhysicsServer3DSW::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); -}; - -real_t PhysicsServer3DSW::body_get_contacts_reported_depth_threshold(RID p_body) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, 0); - return 0; -}; - -void PhysicsServer3DSW::body_set_omit_force_integration(RID p_body, bool p_omit) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - - body->set_omit_force_integration(p_omit); -}; - -bool PhysicsServer3DSW::body_is_omitting_force_integration(RID p_body) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, false); - return body->get_omit_force_integration(); -}; - -void PhysicsServer3DSW::body_set_max_contacts_reported(RID p_body, int p_contacts) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - body->set_max_contacts_reported(p_contacts); -} - -int PhysicsServer3DSW::body_get_max_contacts_reported(RID p_body) const { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, -1); - return body->get_max_contacts_reported(); -} - -void PhysicsServer3DSW::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - body->set_state_sync_callback(p_instance, p_callback); -} - -void PhysicsServer3DSW::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - body->set_force_integration_callback(p_callable, p_udata); -} - -void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND(!body); - body->set_ray_pickable(p_enable); -} - -bool PhysicsServer3DSW::body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result) { - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!body, false); - ERR_FAIL_COND_V(!body->get_space(), false); - ERR_FAIL_COND_V(body->get_space()->is_locked(), false); - - _update_shapes(); - - return body->get_space()->test_body_motion(body, p_parameters, r_result); -} - -PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) { - ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); - - Body3DSW *body = body_owner.get_or_null(p_body); - ERR_FAIL_NULL_V(body, nullptr); - - ERR_FAIL_NULL_V(body->get_space(), nullptr); - ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification."); - - return body->get_direct_state(); -} - -/* SOFT BODY */ - -RID PhysicsServer3DSW::soft_body_create() { - SoftBody3DSW *soft_body = memnew(SoftBody3DSW); - RID rid = soft_body_owner.make_rid(soft_body); - soft_body->set_self(rid); - return rid; -} - -void PhysicsServer3DSW::soft_body_update_rendering_server(RID p_body, RenderingServerHandler *p_rendering_server_handler) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->update_rendering_server(p_rendering_server_handler); -} - -void PhysicsServer3DSW::soft_body_set_space(RID p_body, RID p_space) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - Space3DSW *space = nullptr; - if (p_space.is_valid()) { - space = space_owner.get_or_null(p_space); - ERR_FAIL_COND(!space); - } - - if (soft_body->get_space() == space) { - return; - } - - soft_body->set_space(space); -} - -RID PhysicsServer3DSW::soft_body_get_space(RID p_body) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, RID()); - - Space3DSW *space = soft_body->get_space(); - if (!space) { - return RID(); - } - return space->get_self(); -} - -void PhysicsServer3DSW::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_collision_layer(p_layer); -} - -uint32_t PhysicsServer3DSW::soft_body_get_collision_layer(RID p_body) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, 0); - - return soft_body->get_collision_layer(); -} - -void PhysicsServer3DSW::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_collision_mask(p_mask); -} - -uint32_t PhysicsServer3DSW::soft_body_get_collision_mask(RID p_body) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, 0); - - return soft_body->get_collision_mask(); -} - -void PhysicsServer3DSW::soft_body_add_collision_exception(RID p_body, RID p_body_b) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->add_exception(p_body_b); -} - -void PhysicsServer3DSW::soft_body_remove_collision_exception(RID p_body, RID p_body_b) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->remove_exception(p_body_b); -} - -void PhysicsServer3DSW::soft_body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - for (int i = 0; i < soft_body->get_exceptions().size(); i++) { - p_exceptions->push_back(soft_body->get_exceptions()[i]); - } -} - -void PhysicsServer3DSW::soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_state(p_state, p_variant); -} - -Variant PhysicsServer3DSW::soft_body_get_state(RID p_body, BodyState p_state) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, Variant()); - - return soft_body->get_state(p_state); -} - -void PhysicsServer3DSW::soft_body_set_transform(RID p_body, const Transform3D &p_transform) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_state(BODY_STATE_TRANSFORM, p_transform); -} - -void PhysicsServer3DSW::soft_body_set_ray_pickable(RID p_body, bool p_enable) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_ray_pickable(p_enable); -} - -void PhysicsServer3DSW::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_iteration_count(p_simulation_precision); -} - -int PhysicsServer3DSW::soft_body_get_simulation_precision(RID p_body) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, 0.f); - - return soft_body->get_iteration_count(); -} - -void PhysicsServer3DSW::soft_body_set_total_mass(RID p_body, real_t p_total_mass) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_total_mass(p_total_mass); -} - -real_t PhysicsServer3DSW::soft_body_get_total_mass(RID p_body) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, 0.f); - - return soft_body->get_total_mass(); -} - -void PhysicsServer3DSW::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_linear_stiffness(p_stiffness); -} - -real_t PhysicsServer3DSW::soft_body_get_linear_stiffness(RID p_body) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, 0.f); - - return soft_body->get_linear_stiffness(); -} - -void PhysicsServer3DSW::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_pressure_coefficient(p_pressure_coefficient); -} - -real_t PhysicsServer3DSW::soft_body_get_pressure_coefficient(RID p_body) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, 0.f); - - return soft_body->get_pressure_coefficient(); -} - -void PhysicsServer3DSW::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_damping_coefficient(p_damping_coefficient); -} - -real_t PhysicsServer3DSW::soft_body_get_damping_coefficient(RID p_body) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, 0.f); - - return soft_body->get_damping_coefficient(); -} - -void PhysicsServer3DSW::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_drag_coefficient(p_drag_coefficient); -} - -real_t PhysicsServer3DSW::soft_body_get_drag_coefficient(RID p_body) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, 0.f); - - return soft_body->get_drag_coefficient(); -} - -void PhysicsServer3DSW::soft_body_set_mesh(RID p_body, RID p_mesh) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_mesh(p_mesh); -} - -AABB PhysicsServer3DSW::soft_body_get_bounds(RID p_body) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, AABB()); - - return soft_body->get_bounds(); -} - -void PhysicsServer3DSW::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->set_vertex_position(p_point_index, p_global_position); -} - -Vector3 PhysicsServer3DSW::soft_body_get_point_global_position(RID p_body, int p_point_index) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, Vector3()); - - return soft_body->get_vertex_position(p_point_index); -} - -void PhysicsServer3DSW::soft_body_remove_all_pinned_points(RID p_body) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - soft_body->unpin_all_vertices(); -} - -void PhysicsServer3DSW::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND(!soft_body); - - if (p_pin) { - soft_body->pin_vertex(p_point_index); - } else { - soft_body->unpin_vertex(p_point_index); - } -} - -bool PhysicsServer3DSW::soft_body_is_point_pinned(RID p_body, int p_point_index) const { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_body); - ERR_FAIL_COND_V(!soft_body, false); - - return soft_body->is_vertex_pinned(p_point_index); -} - -/* JOINT API */ - -RID PhysicsServer3DSW::joint_create() { - Joint3DSW *joint = memnew(Joint3DSW); - RID rid = joint_owner.make_rid(joint); - joint->set_self(rid); - return rid; -} - -void PhysicsServer3DSW::joint_clear(RID p_joint) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - if (joint->get_type() != JOINT_TYPE_MAX) { - Joint3DSW *empty_joint = memnew(Joint3DSW); - empty_joint->copy_settings_from(joint); - - joint_owner.replace(p_joint, empty_joint); - memdelete(joint); - } -} - -void PhysicsServer3DSW::joint_make_pin(RID p_joint, RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { - Body3DSW *body_A = body_owner.get_or_null(p_body_A); - ERR_FAIL_COND(!body_A); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND(!body_A->get_space()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - Body3DSW *body_B = body_owner.get_or_null(p_body_B); - ERR_FAIL_COND(!body_B); - - ERR_FAIL_COND(body_A == body_B); - - Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(prev_joint == nullptr); - - Joint3DSW *joint = memnew(PinJoint3DSW(body_A, p_local_A, body_B, p_local_B)); - - joint->copy_settings_from(prev_joint); - joint_owner.replace(p_joint, joint); - memdelete(prev_joint); -} - -void PhysicsServer3DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN); - PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint); - pin_joint->set_param(p_param, p_value); -} - -real_t PhysicsServer3DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, 0); - ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0); - PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint); - return pin_joint->get_param(p_param); -} - -void PhysicsServer3DSW::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN); - PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint); - pin_joint->set_pos_a(p_A); -} - -Vector3 PhysicsServer3DSW::pin_joint_get_local_a(RID p_joint) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, Vector3()); - ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3()); - PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint); - return pin_joint->get_position_a(); -} - -void PhysicsServer3DSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN); - PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint); - pin_joint->set_pos_b(p_B); -} - -Vector3 PhysicsServer3DSW::pin_joint_get_local_b(RID p_joint) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, Vector3()); - ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, Vector3()); - PinJoint3DSW *pin_joint = static_cast<PinJoint3DSW *>(joint); - return pin_joint->get_position_b(); -} - -void PhysicsServer3DSW::joint_make_hinge(RID p_joint, RID p_body_A, const Transform3D &p_frame_A, RID p_body_B, const Transform3D &p_frame_B) { - Body3DSW *body_A = body_owner.get_or_null(p_body_A); - ERR_FAIL_COND(!body_A); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND(!body_A->get_space()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - Body3DSW *body_B = body_owner.get_or_null(p_body_B); - ERR_FAIL_COND(!body_B); - - ERR_FAIL_COND(body_A == body_B); - - Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(prev_joint == nullptr); - - Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_frame_A, p_frame_B)); - - joint->copy_settings_from(prev_joint); - joint_owner.replace(p_joint, joint); - memdelete(prev_joint); -} - -void PhysicsServer3DSW::joint_make_hinge_simple(RID p_joint, RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) { - Body3DSW *body_A = body_owner.get_or_null(p_body_A); - ERR_FAIL_COND(!body_A); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND(!body_A->get_space()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - Body3DSW *body_B = body_owner.get_or_null(p_body_B); - ERR_FAIL_COND(!body_B); - - ERR_FAIL_COND(body_A == body_B); - - Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(prev_joint == nullptr); - - Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B)); - - joint->copy_settings_from(prev_joint); - joint_owner.replace(p_joint, joint); - memdelete(prev_joint); -} - -void PhysicsServer3DSW::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE); - HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint); - hinge_joint->set_param(p_param, p_value); -} - -real_t PhysicsServer3DSW::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, 0); - ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, 0); - HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint); - return hinge_joint->get_param(p_param); -} - -void PhysicsServer3DSW::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_HINGE); - HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint); - hinge_joint->set_flag(p_flag, p_value); -} - -bool PhysicsServer3DSW::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, false); - ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_HINGE, false); - HingeJoint3DSW *hinge_joint = static_cast<HingeJoint3DSW *>(joint); - return hinge_joint->get_flag(p_flag); -} - -void PhysicsServer3DSW::joint_set_solver_priority(RID p_joint, int p_priority) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - joint->set_priority(p_priority); -} - -int PhysicsServer3DSW::joint_get_solver_priority(RID p_joint) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, 0); - return joint->get_priority(); -} - -void PhysicsServer3DSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - - joint->disable_collisions_between_bodies(p_disable); - - if (2 == joint->get_body_count()) { - Body3DSW *body_a = *joint->get_body_ptr(); - Body3DSW *body_b = *(joint->get_body_ptr() + 1); - - if (p_disable) { - body_add_collision_exception(body_a->get_self(), body_b->get_self()); - body_add_collision_exception(body_b->get_self(), body_a->get_self()); - } else { - body_remove_collision_exception(body_a->get_self(), body_b->get_self()); - body_remove_collision_exception(body_b->get_self(), body_a->get_self()); - } - } -} - -bool PhysicsServer3DSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, true); - - return joint->is_disabled_collisions_between_bodies(); -} - -PhysicsServer3DSW::JointType PhysicsServer3DSW::joint_get_type(RID p_joint) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, JOINT_TYPE_PIN); - return joint->get_type(); -} - -void PhysicsServer3DSW::joint_make_slider(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) { - Body3DSW *body_A = body_owner.get_or_null(p_body_A); - ERR_FAIL_COND(!body_A); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND(!body_A->get_space()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - Body3DSW *body_B = body_owner.get_or_null(p_body_B); - ERR_FAIL_COND(!body_B); - - ERR_FAIL_COND(body_A == body_B); - - Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(prev_joint == nullptr); - - Joint3DSW *joint = memnew(SliderJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B)); - - joint->copy_settings_from(prev_joint); - joint_owner.replace(p_joint, joint); - memdelete(prev_joint); -} - -void PhysicsServer3DSW::slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_SLIDER); - SliderJoint3DSW *slider_joint = static_cast<SliderJoint3DSW *>(joint); - slider_joint->set_param(p_param, p_value); -} - -real_t PhysicsServer3DSW::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, 0); - ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0); - SliderJoint3DSW *slider_joint = static_cast<SliderJoint3DSW *>(joint); - return slider_joint->get_param(p_param); -} - -void PhysicsServer3DSW::joint_make_cone_twist(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) { - Body3DSW *body_A = body_owner.get_or_null(p_body_A); - ERR_FAIL_COND(!body_A); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND(!body_A->get_space()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - Body3DSW *body_B = body_owner.get_or_null(p_body_B); - ERR_FAIL_COND(!body_B); - - ERR_FAIL_COND(body_A == body_B); - - Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(prev_joint == nullptr); - - Joint3DSW *joint = memnew(ConeTwistJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B)); - - joint->copy_settings_from(prev_joint); - joint_owner.replace(p_joint, joint); - memdelete(prev_joint); -} - -void PhysicsServer3DSW::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_CONE_TWIST); - ConeTwistJoint3DSW *cone_twist_joint = static_cast<ConeTwistJoint3DSW *>(joint); - cone_twist_joint->set_param(p_param, p_value); -} - -real_t PhysicsServer3DSW::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, 0); - ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_CONE_TWIST, 0); - ConeTwistJoint3DSW *cone_twist_joint = static_cast<ConeTwistJoint3DSW *>(joint); - return cone_twist_joint->get_param(p_param); -} - -void PhysicsServer3DSW::joint_make_generic_6dof(RID p_joint, RID p_body_A, const Transform3D &p_local_frame_A, RID p_body_B, const Transform3D &p_local_frame_B) { - Body3DSW *body_A = body_owner.get_or_null(p_body_A); - ERR_FAIL_COND(!body_A); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND(!body_A->get_space()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - Body3DSW *body_B = body_owner.get_or_null(p_body_B); - ERR_FAIL_COND(!body_B); - - ERR_FAIL_COND(body_A == body_B); - - Joint3DSW *prev_joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(prev_joint == nullptr); - - Joint3DSW *joint = memnew(Generic6DOFJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B, true)); - - joint->copy_settings_from(prev_joint); - joint_owner.replace(p_joint, joint); - memdelete(prev_joint); -} - -void PhysicsServer3DSW::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF); - Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint); - generic_6dof_joint->set_param(p_axis, p_param, p_value); -} - -real_t PhysicsServer3DSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, 0); - ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, 0); - Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint); - return generic_6dof_joint->get_param(p_axis, p_param); -} - -void PhysicsServer3DSW::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_6DOF); - Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint); - generic_6dof_joint->set_flag(p_axis, p_flag, p_enable); -} - -bool PhysicsServer3DSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) const { - Joint3DSW *joint = joint_owner.get_or_null(p_joint); - ERR_FAIL_COND_V(!joint, false); - ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_6DOF, false); - Generic6DOFJoint3DSW *generic_6dof_joint = static_cast<Generic6DOFJoint3DSW *>(joint); - return generic_6dof_joint->get_flag(p_axis, p_flag); -} - -void PhysicsServer3DSW::free(RID p_rid) { - _update_shapes(); //just in case - - if (shape_owner.owns(p_rid)) { - Shape3DSW *shape = shape_owner.get_or_null(p_rid); - - while (shape->get_owners().size()) { - ShapeOwner3DSW *so = shape->get_owners().front()->key(); - so->remove_shape(shape); - } - - shape_owner.free(p_rid); - memdelete(shape); - } else if (body_owner.owns(p_rid)) { - Body3DSW *body = body_owner.get_or_null(p_rid); - - /* - if (body->get_state_query()) - _clear_query(body->get_state_query()); - - if (body->get_direct_state_query()) - _clear_query(body->get_direct_state_query()); - */ - - body->set_space(nullptr); - - while (body->get_shape_count()) { - body->remove_shape(0); - } - - body_owner.free(p_rid); - memdelete(body); - } else if (soft_body_owner.owns(p_rid)) { - SoftBody3DSW *soft_body = soft_body_owner.get_or_null(p_rid); - - soft_body->set_space(nullptr); - - soft_body_owner.free(p_rid); - memdelete(soft_body); - } else if (area_owner.owns(p_rid)) { - Area3DSW *area = area_owner.get_or_null(p_rid); - - /* - if (area->get_monitor_query()) - _clear_query(area->get_monitor_query()); - */ - - area->set_space(nullptr); - - while (area->get_shape_count()) { - area->remove_shape(0); - } - - area_owner.free(p_rid); - memdelete(area); - } else if (space_owner.owns(p_rid)) { - Space3DSW *space = space_owner.get_or_null(p_rid); - - while (space->get_objects().size()) { - CollisionObject3DSW *co = (CollisionObject3DSW *)space->get_objects().front()->get(); - co->set_space(nullptr); - } - - active_spaces.erase(space); - free(space->get_default_area()->get_self()); - free(space->get_static_global_body()); - - space_owner.free(p_rid); - memdelete(space); - } else if (joint_owner.owns(p_rid)) { - Joint3DSW *joint = joint_owner.get_or_null(p_rid); - - joint_owner.free(p_rid); - memdelete(joint); - - } else { - ERR_FAIL_MSG("Invalid ID."); - } -}; - -void PhysicsServer3DSW::set_active(bool p_active) { - active = p_active; -}; - -void PhysicsServer3DSW::set_collision_iterations(int p_iterations) { - iterations = p_iterations; -}; - -void PhysicsServer3DSW::init() { - iterations = 8; // 8? - stepper = memnew(Step3DSW); -}; - -void PhysicsServer3DSW::step(real_t p_step) { -#ifndef _3D_DISABLED - - if (!active) { - return; - } - - _update_shapes(); - - island_count = 0; - active_objects = 0; - collision_pairs = 0; - for (Set<const Space3DSW *>::Element *E = active_spaces.front(); E; E = E->next()) { - stepper->step((Space3DSW *)E->get(), p_step, iterations); - island_count += E->get()->get_island_count(); - active_objects += E->get()->get_active_objects(); - collision_pairs += E->get()->get_collision_pairs(); - } -#endif -} - -void PhysicsServer3DSW::sync() { - doing_sync = true; -}; - -void PhysicsServer3DSW::flush_queries() { -#ifndef _3D_DISABLED - - if (!active) { - return; - } - - flushing_queries = true; - - uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); - - for (Set<const Space3DSW *>::Element *E = active_spaces.front(); E; E = E->next()) { - Space3DSW *space = (Space3DSW *)E->get(); - space->call_queries(); - } - - flushing_queries = false; - - if (EngineDebugger::is_profiling("servers")) { - uint64_t total_time[Space3DSW::ELAPSED_TIME_MAX]; - static const char *time_name[Space3DSW::ELAPSED_TIME_MAX] = { - "integrate_forces", - "generate_islands", - "setup_constraints", - "solve_constraints", - "integrate_velocities" - }; - - for (int i = 0; i < Space3DSW::ELAPSED_TIME_MAX; i++) { - total_time[i] = 0; - } - - for (Set<const Space3DSW *>::Element *E = active_spaces.front(); E; E = E->next()) { - for (int i = 0; i < Space3DSW::ELAPSED_TIME_MAX; i++) { - total_time[i] += E->get()->get_elapsed_time(Space3DSW::ElapsedTime(i)); - } - } - - Array values; - values.resize(Space3DSW::ELAPSED_TIME_MAX * 2); - for (int i = 0; i < Space3DSW::ELAPSED_TIME_MAX; i++) { - values[i * 2 + 0] = time_name[i]; - values[i * 2 + 1] = USEC_TO_SEC(total_time[i]); - } - values.push_back("flush_queries"); - values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg)); - - values.push_front("physics"); - EngineDebugger::profiler_add_frame_data("servers", values); - } -#endif -}; - -void PhysicsServer3DSW::end_sync() { - doing_sync = false; -}; - -void PhysicsServer3DSW::finish() { - memdelete(stepper); -}; - -int PhysicsServer3DSW::get_process_info(ProcessInfo p_info) { - switch (p_info) { - case INFO_ACTIVE_OBJECTS: { - return active_objects; - } break; - case INFO_COLLISION_PAIRS: { - return collision_pairs; - } break; - case INFO_ISLAND_COUNT: { - return island_count; - } break; - } - - return 0; -} - -void PhysicsServer3DSW::_update_shapes() { - while (pending_shape_update_list.first()) { - pending_shape_update_list.first()->self()->_shape_changed(); - pending_shape_update_list.remove(pending_shape_update_list.first()); - } -} - -void PhysicsServer3DSW::_shape_col_cbk(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata) { - CollCbkData *cbk = (CollCbkData *)p_userdata; - - if (cbk->max == 0) { - return; - } - - if (cbk->amount == cbk->max) { - //find least deep - real_t min_depth = 1e20; - int min_depth_idx = 0; - for (int i = 0; i < cbk->amount; i++) { - real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]); - if (d < min_depth) { - min_depth = d; - min_depth_idx = i; - } - } - - real_t d = p_point_A.distance_squared_to(p_point_B); - if (d < min_depth) { - return; - } - cbk->ptr[min_depth_idx * 2 + 0] = p_point_A; - cbk->ptr[min_depth_idx * 2 + 1] = p_point_B; - - } else { - cbk->ptr[cbk->amount * 2 + 0] = p_point_A; - cbk->ptr[cbk->amount * 2 + 1] = p_point_B; - cbk->amount++; - } -} - -PhysicsServer3DSW *PhysicsServer3DSW::singletonsw = nullptr; -PhysicsServer3DSW::PhysicsServer3DSW(bool p_using_threads) { - singletonsw = this; - BroadPhase3DSW::create_func = BroadPhase3DBVH::_create; - - using_threads = p_using_threads; -}; diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index 26e1411111..f83c57407d 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PHYSICS_2D_SERVER_H -#define PHYSICS_2D_SERVER_H +#ifndef PHYSICS_SERVER_2D_H +#define PHYSICS_SERVER_2D_H #include "core/io/resource.h" #include "core/object/class_db.h" @@ -701,4 +701,4 @@ VARIANT_ENUM_CAST(PhysicsServer2D::DampedSpringParam); VARIANT_ENUM_CAST(PhysicsServer2D::AreaBodyStatus); VARIANT_ENUM_CAST(PhysicsServer2D::ProcessInfo); -#endif +#endif // PHYSICS_SERVER_2D_H diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.cpp b/servers/physics_server_2d_wrap_mt.cpp index 33070bf42d..33070bf42d 100644 --- a/servers/physics_2d/physics_server_2d_wrap_mt.cpp +++ b/servers/physics_server_2d_wrap_mt.cpp diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h index 8d9e366661..4a2f07ab1e 100644 --- a/servers/physics_2d/physics_server_2d_wrap_mt.h +++ b/servers/physics_server_2d_wrap_mt.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PHYSICS2DSERVERWRAPMT_H -#define PHYSICS2DSERVERWRAPMT_H +#ifndef PHYSICS_SERVER_2D_WRAP_MT_H +#define PHYSICS_SERVER_2D_WRAP_MT_H #include "core/config/project_settings.h" #include "core/os/thread.h" @@ -59,9 +59,7 @@ class PhysicsServer2DWrapMT : public PhysicsServer2D { bool create_thread = false; Semaphore step_sem; - int step_pending = 0; void thread_step(real_t p_delta); - void thread_flush(); void thread_exit(); @@ -330,4 +328,4 @@ public: #endif #undef SYNC_DEBUG -#endif // PHYSICS2DSERVERWRAPMT_H +#endif // PHYSICS_SERVER_2D_WRAP_MT_H diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index c609afc11e..6f55e287c9 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PHYSICS_SERVER_H -#define PHYSICS_SERVER_H +#ifndef PHYSICS_SERVER_3D_H +#define PHYSICS_SERVER_3D_H #include "core/io/resource.h" #include "core/object/class_db.h" @@ -903,4 +903,4 @@ VARIANT_ENUM_CAST(PhysicsServer3D::G6DOFJointAxisFlag); VARIANT_ENUM_CAST(PhysicsServer3D::AreaBodyStatus); VARIANT_ENUM_CAST(PhysicsServer3D::ProcessInfo); -#endif +#endif // PHYSICS_SERVER_3D_H diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.cpp b/servers/physics_server_3d_wrap_mt.cpp index c424100bba..c424100bba 100644 --- a/servers/physics_3d/physics_server_3d_wrap_mt.cpp +++ b/servers/physics_server_3d_wrap_mt.cpp diff --git a/servers/physics_3d/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h index 17d02addda..4c88ef2642 100644 --- a/servers/physics_3d/physics_server_3d_wrap_mt.h +++ b/servers/physics_server_3d_wrap_mt.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PHYSICS3DSERVERWRAPMT_H -#define PHYSICS3DSERVERWRAPMT_H +#ifndef PHYSICS_SERVER_3D_WRAP_MT_H +#define PHYSICS_SERVER_3D_WRAP_MT_H #include "core/config/project_settings.h" #include "core/os/thread.h" @@ -58,9 +58,7 @@ class PhysicsServer3DWrapMT : public PhysicsServer3D { bool create_thread = false; Semaphore step_sem; - int step_pending = 0; void thread_step(real_t p_delta); - void thread_flush(); void thread_exit(); @@ -406,4 +404,4 @@ public: #endif #undef SYNC_DEBUG -#endif // PHYSICS3DSERVERWRAPMT_H +#endif // PHYSICS_SERVER_3D_WRAP_MT_H diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 28cd8374c0..8be9c2114f 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -59,12 +59,12 @@ #include "display_server.h" #include "navigation_server_2d.h" #include "navigation_server_3d.h" -#include "physics_2d/physics_server_2d_sw.h" -#include "physics_2d/physics_server_2d_wrap_mt.h" -#include "physics_3d/physics_server_3d_sw.h" -#include "physics_3d/physics_server_3d_wrap_mt.h" +#include "physics_2d/godot_physics_server_2d.h" +#include "physics_3d/godot_physics_server_3d.h" #include "physics_server_2d.h" +#include "physics_server_2d_wrap_mt.h" #include "physics_server_3d.h" +#include "physics_server_3d_wrap_mt.h" #include "rendering/renderer_compositor.h" #include "rendering/rendering_device.h" #include "rendering/rendering_device_binds.h" @@ -82,7 +82,7 @@ ShaderTypes *shader_types = nullptr; PhysicsServer3D *_createGodotPhysics3DCallback() { bool using_threads = GLOBAL_GET("physics/3d/run_on_thread"); - PhysicsServer3D *physics_server = memnew(PhysicsServer3DSW(using_threads)); + PhysicsServer3D *physics_server = memnew(GodotPhysicsServer3D(using_threads)); return memnew(PhysicsServer3DWrapMT(physics_server, using_threads)); } @@ -90,7 +90,7 @@ PhysicsServer3D *_createGodotPhysics3DCallback() { PhysicsServer2D *_createGodotPhysics2DCallback() { bool using_threads = GLOBAL_GET("physics/2d/run_on_thread"); - PhysicsServer2D *physics_server = memnew(PhysicsServer2DSW(using_threads)); + PhysicsServer2D *physics_server = memnew(GodotPhysicsServer2D(using_threads)); return memnew(PhysicsServer2DWrapMT(physics_server, using_threads)); } @@ -133,6 +133,7 @@ void register_server_types() { GDREGISTER_VIRTUAL_CLASS(XRInterface); GDREGISTER_CLASS(XRInterfaceExtension); // can't register this as virtual because we need a creation function for our extensions. + GDREGISTER_CLASS(XRPose); GDREGISTER_CLASS(XRPositionalTracker); GDREGISTER_CLASS(AudioStream); diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 6b84ab908d..0deb822e86 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -328,6 +328,8 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p push_constant.uv_offset = 0; } + bool should_request_redraw = false; + for (uint32_t i = p_from_element; i < p_to_element; i++) { const GeometryInstanceSurfaceDataCache *surf = p_params->elements[i]; const RenderElementInfo &element_info = p_params->element_info[i]; @@ -365,6 +367,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p continue; } + //request a redraw if one of the shaders uses TIME + if (shader->uses_time) { + should_request_redraw = true; + } + //find cull variant SceneShaderForwardClustered::ShaderData::CullVariant cull_variant; @@ -500,6 +507,11 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count); i += element_info.repeat - 1; //skip equal elements } + + // Make the actual redraw request + if (should_request_redraw) { + RenderingServerDefault::redraw_request(); + } } void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) { diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index a1c3481ed6..d05cfdc386 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -657,6 +657,10 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; } + actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; // linear filter with mipmaps + actions.custom_samplers["DEPTH_TEXTURE"] = "material_samplers[3]"; + actions.custom_samplers["NORMAL_ROUGHNESS_TEXTURE"] = "material_samplers[1]"; // linear filter + actions.render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; actions.render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 329deeb1ae..d128578d0b 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -3026,7 +3026,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const RS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base); int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3); - light_data.blend_splits = storage->light_directional_get_blend_splits(base); + light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && storage->light_directional_get_blend_splits(base); for (int j = 0; j < 4; j++) { Rect2 atlas_rect = li->shadow_transform[j].atlas_rect; CameraMatrix matrix = li->shadow_transform[j].camera; diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp index a7bfea455d..3e68a2b622 100644 --- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_storage_rd.cpp @@ -2672,9 +2672,11 @@ void RendererStorageRD::MaterialData::update_textures(const Map<StringName, Vari if (uniform_array_size > 0) { if (textures.size() < uniform_array_size) { const Map<StringName, RID>::Element *W = p_default_textures.find(uniform_name); - if (W) { - for (int j = textures.size(); j < uniform_array_size; j++) { + for (int j = textures.size(); j < uniform_array_size; j++) { + if (W) { textures.push_back(W->get()); + } else { + textures.push_back(RID()); } } } diff --git a/servers/rendering/renderer_rd/shader_compiler_rd.cpp b/servers/rendering/renderer_rd/shader_compiler_rd.cpp index 42d11d8bc1..215959bb6a 100644 --- a/servers/rendering/renderer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/renderer_rd/shader_compiler_rd.cpp @@ -1421,7 +1421,7 @@ Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, Ide } } - _err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER); + _err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER); return err; } diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl index 5261868155..987960069b 100644 --- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl @@ -1270,21 +1270,21 @@ void main() { float shadow = 1.0; - //version with soft shadows, more expensive if (directional_lights.data[i].shadow_enabled) { - if (sc_use_directional_soft_shadows && directional_lights.data[i].softshadow_angle > 0) { - float depth_z = -vertex.z; - - vec3 shadow_color = vec3(0.0); - vec3 light_dir = directional_lights.data[i].direction; + float depth_z = -vertex.z; + vec3 light_dir = directional_lights.data[i].direction; + vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))); -#define BIAS_FUNC(m_var, m_idx) \ - m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \ - vec3 normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))) * directional_lights.data[i].shadow_normal_bias[m_idx]; \ - normal_bias -= light_dir * dot(light_dir, normal_bias); \ +#define BIAS_FUNC(m_var, m_idx) \ + m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \ + vec3 normal_bias = base_normal_bias * directional_lights.data[i].shadow_normal_bias[m_idx]; \ + normal_bias -= light_dir * dot(light_dir, normal_bias); \ m_var.xyz += normal_bias; - uint blend_index = 0; + //version with soft shadows, more expensive + if (sc_use_directional_soft_shadows && directional_lights.data[i].softshadow_angle > 0) { + uint blend_count = 0; + const uint blend_max = directional_lights.data[i].blend_splits ? 2 : 1; if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { vec4 v = vec4(vertex, 1.0); @@ -1299,10 +1299,10 @@ void main() { float test_radius = (range_pos - range_begin) * directional_lights.data[i].softshadow_angle; vec2 tex_scale = directional_lights.data[i].uv_scale1 * test_radius; shadow = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - blend_index++; + blend_count++; } - if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.y) { + if (blend_count < blend_max && depth_z < directional_lights.data[i].shadow_split_offsets.y) { vec4 v = vec4(vertex, 1.0); BIAS_FUNC(v, 1) @@ -1316,7 +1316,7 @@ void main() { vec2 tex_scale = directional_lights.data[i].uv_scale2 * test_radius; float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - if (blend_index == 0) { + if (blend_count == 0) { shadow = s; } else { //blend @@ -1324,10 +1324,10 @@ void main() { shadow = mix(shadow, s, blend); } - blend_index++; + blend_count++; } - if (blend_index < 2 && depth_z < directional_lights.data[i].shadow_split_offsets.z) { + if (blend_count < blend_max && depth_z < directional_lights.data[i].shadow_split_offsets.z) { vec4 v = vec4(vertex, 1.0); BIAS_FUNC(v, 2) @@ -1341,7 +1341,7 @@ void main() { vec2 tex_scale = directional_lights.data[i].uv_scale3 * test_radius; float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - if (blend_index == 0) { + if (blend_count == 0) { shadow = s; } else { //blend @@ -1349,10 +1349,10 @@ void main() { shadow = mix(shadow, s, blend); } - blend_index++; + blend_count++; } - if (blend_index < 2) { + if (blend_count < blend_max) { vec4 v = vec4(vertex, 1.0); BIAS_FUNC(v, 3) @@ -1366,7 +1366,7 @@ void main() { vec2 tex_scale = directional_lights.data[i].uv_scale4 * test_radius; float s = sample_directional_soft_shadow(directional_shadow_atlas, pssm_coord.xyz, tex_scale * directional_lights.data[i].soft_shadow_scale); - if (blend_index == 0) { + if (blend_count == 0) { shadow = s; } else { //blend @@ -1375,21 +1375,9 @@ void main() { } } -#undef BIAS_FUNC } else { //no soft shadows - float depth_z = -vertex.z; - vec4 pssm_coord; - vec3 light_dir = directional_lights.data[i].direction; - vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp)))); - -#define BIAS_FUNC(m_var, m_idx) \ - m_var.xyz += light_dir * directional_lights.data[i].shadow_bias[m_idx]; \ - vec3 normal_bias = base_normal_bias * directional_lights.data[i].shadow_normal_bias[m_idx]; \ - normal_bias -= light_dir * dot(light_dir, normal_bias); \ - m_var.xyz += normal_bias; - if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { vec4 v = vec4(vertex, 1.0); @@ -1448,11 +1436,11 @@ void main() { float shadow2 = sample_directional_pcf_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size * directional_lights.data[i].soft_shadow_scale, pssm_coord); shadow = mix(shadow, shadow2, pssm_blend); } + } - shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance + shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance #undef BIAS_FUNC - } } // shadows if (i < 4) { diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index bae98f8884..a7886bb6b1 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -2076,7 +2076,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in // This trick here is what stabilizes the shadow (make potential jaggies to not move) // at the cost of some wasted resolution. Still, the quality increase is very well worth it. - const real_t unit = radius * 2.0 / texture_size; + const real_t unit = (radius + soft_shadow_expand) * 2.0 / texture_size; x_max_cam = Math::snapped(x_vec.dot(center) + radius + soft_shadow_expand, unit); x_min_cam = Math::snapped(x_vec.dot(center) - radius - soft_shadow_expand, unit); y_max_cam = Math::snapped(y_vec.dot(center) + radius + soft_shadow_expand, unit); diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 835d552fd4..347238cdaa 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -495,9 +495,6 @@ void RendererViewport::draw_viewports() { if (XRServer::get_singleton() != nullptr) { xr_interface = XRServer::get_singleton()->get_primary_interface(); - - // process all our active interfaces - XRServer::get_singleton()->_process(); } if (Engine::get_singleton()->is_editor_hint()) { diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 9c38bf7606..53f2d96f52 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -2763,6 +2763,7 @@ bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const FunctionI bool is_const = false; ConstantNode::Value value; + value.sint = -1; _find_identifier(p_block, false, p_function_info, vn->name, nullptr, nullptr, &is_const, nullptr, nullptr, &value); if (!is_const || value.sint < min || value.sint > max) { diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index b3efe840b6..348d46545b 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2810,6 +2810,12 @@ RenderingServer::RenderingServer() { PropertyInfo(Variant::INT, "rendering/vulkan/rendering/back_end", PROPERTY_HINT_ENUM, "Forward Clustered (Supports Desktop Only),Forward Mobile (Supports Desktop and Mobile)")); + // Already defined in RenderingDeviceVulkan::initialize which runs before this code. + // We re-define them here just for doctool's sake. Make sure to keep default values in sync. + GLOBAL_DEF("rendering/vulkan/staging_buffer/block_size_kb", 256); + GLOBAL_DEF("rendering/vulkan/staging_buffer/max_size_mb", 128); + GLOBAL_DEF("rendering/vulkan/staging_buffer/texture_upload_region_size_px", 64); + GLOBAL_DEF("rendering/vulkan/descriptor_pools/max_descriptors_per_pool", 64); GLOBAL_DEF("rendering/3d/viewport/scale", 1.0); ProjectSettings::get_singleton()->set_custom_property_info("rendering/3d/viewport/scale", diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp index bf54158905..ca11df439c 100644 --- a/servers/xr/xr_interface.cpp +++ b/servers/xr/xr_interface.cpp @@ -32,6 +32,8 @@ // #include "servers/rendering/renderer_compositor.h" void XRInterface::_bind_methods() { + ADD_SIGNAL(MethodInfo("play_area_changed", PropertyInfo(Variant::INT, "mode"))); + ClassDB::bind_method(D_METHOD("get_name"), &XRInterface::get_name); ClassDB::bind_method(D_METHOD("get_capabilities"), &XRInterface::get_capabilities); @@ -47,12 +49,21 @@ void XRInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("get_render_target_size"), &XRInterface::get_render_target_size); ClassDB::bind_method(D_METHOD("get_view_count"), &XRInterface::get_view_count); + ClassDB::bind_method(D_METHOD("trigger_haptic_pulse", "action_name", "tracker_name", "frequency", "amplitude", "duration_sec", "delay_sec"), &XRInterface::trigger_haptic_pulse); + ADD_GROUP("Interface", "interface_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interface_is_primary"), "set_primary", "is_primary"); - // we don't have any properties specific to VR yet.... + // methods and properties specific to VR... + ClassDB::bind_method(D_METHOD("supports_play_area_mode", "mode"), &XRInterface::supports_play_area_mode); + ClassDB::bind_method(D_METHOD("get_play_area_mode"), &XRInterface::get_play_area_mode); + ClassDB::bind_method(D_METHOD("set_play_area_mode", "mode"), &XRInterface::set_play_area_mode); + ClassDB::bind_method(D_METHOD("get_play_area"), &XRInterface::get_play_area); + + ADD_GROUP("XR", "xr_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "xr_play_area_mode", PROPERTY_HINT_ENUM, "Unknown,3DOF,Sitting,Roomscale,Stage"), "set_play_area_mode", "get_play_area_mode"); - // but we do have properties specific to AR.... + // methods and properties specific to AR.... ClassDB::bind_method(D_METHOD("get_anchor_detection_is_enabled"), &XRInterface::get_anchor_detection_is_enabled); ClassDB::bind_method(D_METHOD("set_anchor_detection_is_enabled", "enable"), &XRInterface::set_anchor_detection_is_enabled); ClassDB::bind_method(D_METHOD("get_camera_feed_id"), &XRInterface::get_camera_feed_id); @@ -63,19 +74,23 @@ void XRInterface::_bind_methods() { BIND_ENUM_CONSTANT(XR_NONE); BIND_ENUM_CONSTANT(XR_MONO); BIND_ENUM_CONSTANT(XR_STEREO); + BIND_ENUM_CONSTANT(XR_QUAD); + BIND_ENUM_CONSTANT(XR_VR); BIND_ENUM_CONSTANT(XR_AR); BIND_ENUM_CONSTANT(XR_EXTERNAL); - BIND_ENUM_CONSTANT(EYE_MONO); - BIND_ENUM_CONSTANT(EYE_LEFT); - BIND_ENUM_CONSTANT(EYE_RIGHT); - BIND_ENUM_CONSTANT(XR_NORMAL_TRACKING); BIND_ENUM_CONSTANT(XR_EXCESSIVE_MOTION); BIND_ENUM_CONSTANT(XR_INSUFFICIENT_FEATURES); BIND_ENUM_CONSTANT(XR_UNKNOWN_TRACKING); BIND_ENUM_CONSTANT(XR_NOT_TRACKING); -} + + BIND_ENUM_CONSTANT(XR_PLAY_AREA_UNKNOWN); + BIND_ENUM_CONSTANT(XR_PLAY_AREA_3DOF); + BIND_ENUM_CONSTANT(XR_PLAY_AREA_SITTING); + BIND_ENUM_CONSTANT(XR_PLAY_AREA_ROOMSCALE); + BIND_ENUM_CONSTANT(XR_PLAY_AREA_STAGE); +}; bool XRInterface::is_primary() { XRServer *xr_server = XRServer::get_singleton(); @@ -101,6 +116,29 @@ XRInterface::XRInterface() {} XRInterface::~XRInterface() {} +// query if this interface supports this play area mode +bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) { + return p_mode == XR_PLAY_AREA_UNKNOWN; +} + +// get the current play area mode +XRInterface::PlayAreaMode XRInterface::get_play_area_mode() const { + return XR_PLAY_AREA_UNKNOWN; +} + +// change the play area mode, note that this should return false if the mode is not available +bool XRInterface::set_play_area_mode(XRInterface::PlayAreaMode p_mode) { + return p_mode == XR_PLAY_AREA_UNKNOWN; +} + +// if available, returns an array of vectors denoting the play area the player can move around in +PackedVector3Array XRInterface::get_play_area() const { + // Return an empty array by default. + // Note implementation is responsible for applying our reference frame and world scale to the raw data. + // `play_area_changed` should be emitted if play area data is available and either the reference frame or world scale changes. + return PackedVector3Array(); +}; + /** these will only be implemented on AR interfaces, so we want dummies for VR **/ bool XRInterface::get_anchor_detection_is_enabled() const { return false; @@ -114,9 +152,24 @@ int XRInterface::get_camera_feed_id() { } /** these are optional, so we want dummies **/ +PackedStringArray XRInterface::get_suggested_tracker_names() const { + PackedStringArray arr; + + return arr; +} + +PackedStringArray XRInterface::get_suggested_pose_names(const StringName &p_tracker_name) const { + PackedStringArray arr; + + return arr; +} + XRInterface::TrackingStatus XRInterface::get_tracking_status() const { return XR_UNKNOWN_TRACKING; } void XRInterface::notification(int p_what) { } + +void XRInterface::trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec) { +} diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h index 534fa18d8a..b489481f75 100644 --- a/servers/xr/xr_interface.h +++ b/servers/xr/xr_interface.h @@ -58,14 +58,10 @@ public: XR_NONE = 0, /* no capabilities */ XR_MONO = 1, /* can be used with mono output */ XR_STEREO = 2, /* can be used with stereo output */ - XR_AR = 4, /* offers a camera feed for AR */ - XR_EXTERNAL = 8 /* renders to external device */ - }; - - enum Eyes { - EYE_MONO, /* my son says we should call this EYE_CYCLOPS */ - EYE_LEFT, - EYE_RIGHT + XR_QUAD = 4, /* can be used with quad output (not currently supported) */ + XR_VR = 8, /* offers VR support */ + XR_AR = 16, /* offers AR support */ + XR_EXTERNAL = 32 /* renders to external device */ }; enum TrackingStatus { /* tracking status currently based on AR but we can start doing more with this for VR as well */ @@ -76,7 +72,14 @@ public: XR_NOT_TRACKING }; -private: + enum PlayAreaMode { /* defines the mode used by the XR interface for tracking */ + XR_PLAY_AREA_UNKNOWN, /* Area mode not set or not available */ + XR_PLAY_AREA_3DOF, /* Only support orientation tracking, no positional tracking, area will center around player */ + XR_PLAY_AREA_SITTING, /* Player is in seated position, limited positional tracking, fixed guardian around player */ + XR_PLAY_AREA_ROOMSCALE, /* Player is free to move around, full positional tracking */ + XR_PLAY_AREA_STAGE, /* Same as roomscale but origin point is fixed to the center of the physical space, XRServer.center_on_hmd disabled */ + }; + protected: _THREAD_SAFE_CLASS_ @@ -94,10 +97,18 @@ public: virtual bool initialize() = 0; /* initialize this interface, if this has an HMD it becomes the primary interface */ virtual void uninitialize() = 0; /* deinitialize this interface */ + /** input and output **/ + + virtual PackedStringArray get_suggested_tracker_names() const; /* return a list of likely/suggested tracker names */ + virtual PackedStringArray get_suggested_pose_names(const StringName &p_tracker_name) const; /* return a list of likely/suggested action names for this tracker */ virtual TrackingStatus get_tracking_status() const; /* get the status of our current tracking */ + virtual void trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec = 0); /* trigger a haptic pulse */ /** specific to VR **/ - // nothing yet + virtual bool supports_play_area_mode(XRInterface::PlayAreaMode p_mode); /* query if this interface supports this play area mode */ + virtual XRInterface::PlayAreaMode get_play_area_mode() const; /* get the current play area mode */ + virtual bool set_play_area_mode(XRInterface::PlayAreaMode p_mode); /* change the play area mode, note that this should return false if the mode is not available */ + virtual PackedVector3Array get_play_area() const; /* if available, returns an array of vectors denoting the play area the player can move around in */ /** specific to AR **/ virtual bool get_anchor_detection_is_enabled() const; @@ -124,7 +135,7 @@ public: }; VARIANT_ENUM_CAST(XRInterface::Capabilities); -VARIANT_ENUM_CAST(XRInterface::Eyes); VARIANT_ENUM_CAST(XRInterface::TrackingStatus); +VARIANT_ENUM_CAST(XRInterface::PlayAreaMode); #endif // !XR_INTERFACE_H diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp index 7fdf90770d..80576ac607 100644 --- a/servers/xr/xr_interface_extension.cpp +++ b/servers/xr/xr_interface_extension.cpp @@ -41,7 +41,10 @@ void XRInterfaceExtension::_bind_methods() { GDVIRTUAL_BIND(_initialize); GDVIRTUAL_BIND(_uninitialize); - GDVIRTUAL_BIND(_get_tracking_status); + GDVIRTUAL_BIND(_supports_play_area_mode, "mode"); + GDVIRTUAL_BIND(_get_play_area_mode); + GDVIRTUAL_BIND(_set_play_area_mode, "mode"); + GDVIRTUAL_BIND(_get_play_area); GDVIRTUAL_BIND(_get_render_target_size); GDVIRTUAL_BIND(_get_view_count); @@ -54,6 +57,13 @@ void XRInterfaceExtension::_bind_methods() { GDVIRTUAL_BIND(_process); GDVIRTUAL_BIND(_notification, "what"); + /** input and output **/ + + GDVIRTUAL_BIND(_get_suggested_tracker_names); + GDVIRTUAL_BIND(_get_suggested_pose_names, "tracker_name"); + GDVIRTUAL_BIND(_get_tracking_status); + GDVIRTUAL_BIND(_trigger_haptic_pulse, "action_name", "tracker_name", "frequency", "amplitude", "duration_sec", "delay_sec"); + // we don't have any properties specific to VR yet.... // but we do have properties specific to AR.... @@ -111,6 +121,22 @@ void XRInterfaceExtension::uninitialize() { GDVIRTUAL_CALL(_uninitialize); } +PackedStringArray XRInterfaceExtension::get_suggested_tracker_names() const { + PackedStringArray arr; + + GDVIRTUAL_CALL(_get_suggested_tracker_names, arr); + + return arr; +} + +PackedStringArray XRInterfaceExtension::get_suggested_pose_names(const StringName &p_tracker_name) const { + PackedStringArray arr; + + GDVIRTUAL_CALL(_get_suggested_pose_names, p_tracker_name, arr); + + return arr; +} + XRInterface::TrackingStatus XRInterfaceExtension::get_tracking_status() const { uint32_t status; @@ -121,6 +147,48 @@ XRInterface::TrackingStatus XRInterfaceExtension::get_tracking_status() const { return XR_UNKNOWN_TRACKING; } +void XRInterfaceExtension::trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec) { + GDVIRTUAL_CALL(_trigger_haptic_pulse, p_action_name, p_tracker_name, p_frequency, p_amplitude, p_duration_sec, p_delay_sec); +} + +bool XRInterfaceExtension::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) { + bool is_supported; + + if (GDVIRTUAL_CALL(_supports_play_area_mode, p_mode, is_supported)) { + return is_supported; + } + + return false; +} + +XRInterface::PlayAreaMode XRInterfaceExtension::get_play_area_mode() const { + uint32_t mode; + + if (GDVIRTUAL_CALL(_get_play_area_mode, mode)) { + return XRInterface::PlayAreaMode(mode); + } + + return XRInterface::XR_PLAY_AREA_UNKNOWN; +} + +bool XRInterfaceExtension::set_play_area_mode(XRInterface::PlayAreaMode p_mode) { + bool success; + + if (GDVIRTUAL_CALL(_set_play_area_mode, p_mode, success)) { + return success; + } + + return false; +} + +PackedVector3Array XRInterfaceExtension::get_play_area() const { + PackedVector3Array arr; + + GDVIRTUAL_CALL(_get_play_area, arr); + + return arr; +} + /** these will only be implemented on AR interfaces, so we want dummies for VR **/ bool XRInterfaceExtension::get_anchor_detection_is_enabled() const { bool enabled; diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h index 3b7af4c0a2..763526de96 100644 --- a/servers/xr/xr_interface_extension.h +++ b/servers/xr/xr_interface_extension.h @@ -62,11 +62,28 @@ public: GDVIRTUAL0R(bool, _initialize); GDVIRTUAL0(_uninitialize); + /** input and output **/ + + virtual PackedStringArray get_suggested_tracker_names() const override; /* return a list of likely/suggested tracker names */ + virtual PackedStringArray get_suggested_pose_names(const StringName &p_tracker_name) const override; /* return a list of likely/suggested action names for this tracker */ virtual TrackingStatus get_tracking_status() const override; + virtual void trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec = 0) override; + + GDVIRTUAL0RC(PackedStringArray, _get_suggested_tracker_names); + GDVIRTUAL1RC(PackedStringArray, _get_suggested_pose_names, const StringName &); GDVIRTUAL0RC(uint32_t, _get_tracking_status); + GDVIRTUAL6(_trigger_haptic_pulse, const String &, const StringName &, double, double, double, double); /** specific to VR **/ - // nothing yet + virtual bool supports_play_area_mode(XRInterface::PlayAreaMode p_mode) override; /* query if this interface supports this play area mode */ + virtual XRInterface::PlayAreaMode get_play_area_mode() const override; /* get the current play area mode */ + virtual bool set_play_area_mode(XRInterface::PlayAreaMode p_mode) override; /* change the play area mode, note that this should return false if the mode is not available */ + virtual PackedVector3Array get_play_area() const override; /* if available, returns an array of vectors denoting the play area the player can move around in */ + + GDVIRTUAL1RC(bool, _supports_play_area_mode, XRInterface::PlayAreaMode); + GDVIRTUAL0RC(uint32_t, _get_play_area_mode); + GDVIRTUAL1RC(bool, _set_play_area_mode, uint32_t); + GDVIRTUAL0RC(PackedVector3Array, _get_play_area); /** specific to AR **/ virtual bool get_anchor_detection_is_enabled() const override; diff --git a/servers/xr/xr_pose.cpp b/servers/xr/xr_pose.cpp new file mode 100644 index 0000000000..0d05e62b46 --- /dev/null +++ b/servers/xr/xr_pose.cpp @@ -0,0 +1,110 @@ +/*************************************************************************/ +/* xr_pose.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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 "xr_pose.h" + +#include "servers/xr_server.h" + +void XRPose::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_has_tracking_data", "has_tracking_data"), &XRPose::set_has_tracking_data); + ClassDB::bind_method(D_METHOD("get_has_tracking_data"), &XRPose::get_has_tracking_data); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "has_tracking_data"), "set_has_tracking_data", "get_has_tracking_data"); + + ClassDB::bind_method(D_METHOD("set_name", "name"), &XRPose::set_name); + ClassDB::bind_method(D_METHOD("get_name"), &XRPose::get_name); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "name"), "set_name", "get_name"); + + ClassDB::bind_method(D_METHOD("set_transform", "transform"), &XRPose::set_transform); + ClassDB::bind_method(D_METHOD("get_transform"), &XRPose::get_transform); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "transform"), "set_transform", "get_transform"); + ClassDB::bind_method(D_METHOD("get_adjusted_transform"), &XRPose::get_adjusted_transform); + + ClassDB::bind_method(D_METHOD("set_linear_velocity", "velocity"), &XRPose::set_linear_velocity); + ClassDB::bind_method(D_METHOD("get_linear_velocity"), &XRPose::get_linear_velocity); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); + + ClassDB::bind_method(D_METHOD("set_angular_velocity", "velocity"), &XRPose::set_angular_velocity); + ClassDB::bind_method(D_METHOD("get_angular_velocity"), &XRPose::get_angular_velocity); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); +} + +void XRPose::set_has_tracking_data(const bool p_has_tracking_data) { + has_tracking_data = p_has_tracking_data; +} +bool XRPose::get_has_tracking_data() const { + return has_tracking_data; +} + +void XRPose::set_name(const StringName &p_name) { + name = p_name; +} + +StringName XRPose::get_name() const { + return name; +} + +void XRPose::set_transform(const Transform3D p_transform) { + transform = p_transform; +} + +Transform3D XRPose::get_transform() const { + return transform; +} + +Transform3D XRPose::get_adjusted_transform() const { + Transform3D adjusted_transform = transform; + + XRServer *xr_server = XRServer::get_singleton(); + ERR_FAIL_NULL_V(xr_server, transform); + + // apply world scale + adjusted_transform.origin *= xr_server->get_world_scale(); + + // apply reference frame + adjusted_transform = xr_server->get_reference_frame() * adjusted_transform; + + return adjusted_transform; +} + +void XRPose::set_linear_velocity(const Vector3 p_velocity) { + linear_velocity = p_velocity; +} + +Vector3 XRPose::get_linear_velocity() const { + return linear_velocity; +} + +void XRPose::set_angular_velocity(const Vector3 p_velocity) { + angular_velocity = p_velocity; +} + +Vector3 XRPose::get_angular_velocity() const { + return angular_velocity; +} diff --git a/servers/xr/xr_pose.h b/servers/xr/xr_pose.h new file mode 100644 index 0000000000..223e95ddfe --- /dev/null +++ b/servers/xr/xr_pose.h @@ -0,0 +1,68 @@ +/*************************************************************************/ +/* xr_pose.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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. */ +/*************************************************************************/ + +#ifndef XR_POSE_H +#define XR_POSE_H + +#include "core/object/ref_counted.h" + +class XRPose : public RefCounted { + GDCLASS(XRPose, RefCounted); + +public: +private: + bool has_tracking_data = false; + StringName name; + Transform3D transform; + Vector3 linear_velocity; + Vector3 angular_velocity; + +protected: + static void _bind_methods(); + +public: + void set_has_tracking_data(const bool p_has_tracking_data); + bool get_has_tracking_data() const; + + void set_name(const StringName &p_name); + StringName get_name() const; + + void set_transform(const Transform3D p_transform); + Transform3D get_transform() const; + Transform3D get_adjusted_transform() const; + + void set_linear_velocity(const Vector3 p_velocity); + Vector3 get_linear_velocity() const; + + void set_angular_velocity(const Vector3 p_velocity); + Vector3 get_angular_velocity() const; +}; + +#endif diff --git a/servers/xr/xr_positional_tracker.cpp b/servers/xr/xr_positional_tracker.cpp index e9383db941..1313a91172 100644 --- a/servers/xr/xr_positional_tracker.cpp +++ b/servers/xr/xr_positional_tracker.cpp @@ -37,29 +37,37 @@ void XRPositionalTracker::_bind_methods() { BIND_ENUM_CONSTANT(TRACKER_HAND_LEFT); BIND_ENUM_CONSTANT(TRACKER_HAND_RIGHT); - // this class is read only from GDScript, so we only have access to getters.. ClassDB::bind_method(D_METHOD("get_tracker_type"), &XRPositionalTracker::get_tracker_type); - ClassDB::bind_method(D_METHOD("get_tracker_id"), &XRPositionalTracker::get_tracker_id); + ClassDB::bind_method(D_METHOD("set_tracker_type", "type"), &XRPositionalTracker::set_tracker_type); + ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_tracker_type", "get_tracker_type"); + ClassDB::bind_method(D_METHOD("get_tracker_name"), &XRPositionalTracker::get_tracker_name); - ClassDB::bind_method(D_METHOD("get_joy_id"), &XRPositionalTracker::get_joy_id); - ClassDB::bind_method(D_METHOD("is_tracking_orientation"), &XRPositionalTracker::is_tracking_orientation); - ClassDB::bind_method(D_METHOD("get_orientation"), &XRPositionalTracker::get_orientation); - ClassDB::bind_method(D_METHOD("is_tracking_position"), &XRPositionalTracker::is_tracking_position); - ClassDB::bind_method(D_METHOD("get_position"), &XRPositionalTracker::get_position); + ClassDB::bind_method(D_METHOD("set_tracker_name", "name"), &XRPositionalTracker::set_tracker_name); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "name"), "set_tracker_name", "get_tracker_name"); + + ClassDB::bind_method(D_METHOD("get_tracker_desc"), &XRPositionalTracker::get_tracker_desc); + ClassDB::bind_method(D_METHOD("set_tracker_desc", "description"), &XRPositionalTracker::set_tracker_desc); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "description"), "set_tracker_desc", "get_tracker_desc"); + ClassDB::bind_method(D_METHOD("get_tracker_hand"), &XRPositionalTracker::get_tracker_hand); - ClassDB::bind_method(D_METHOD("get_transform", "adjust_by_reference_frame"), &XRPositionalTracker::get_transform); - ClassDB::bind_method(D_METHOD("get_mesh"), &XRPositionalTracker::get_mesh); - - // these functions we don't want to expose to normal users but do need to be callable from GDNative - ClassDB::bind_method(D_METHOD("_set_tracker_type", "type"), &XRPositionalTracker::set_tracker_type); - ClassDB::bind_method(D_METHOD("_set_tracker_name", "name"), &XRPositionalTracker::set_tracker_name); - ClassDB::bind_method(D_METHOD("_set_joy_id", "joy_id"), &XRPositionalTracker::set_joy_id); - ClassDB::bind_method(D_METHOD("_set_orientation", "orientation"), &XRPositionalTracker::set_orientation); - ClassDB::bind_method(D_METHOD("_set_rw_position", "rw_position"), &XRPositionalTracker::set_rw_position); - ClassDB::bind_method(D_METHOD("_set_mesh", "mesh"), &XRPositionalTracker::set_mesh); + ClassDB::bind_method(D_METHOD("set_tracker_hand", "hand"), &XRPositionalTracker::set_tracker_hand); + ADD_PROPERTY(PropertyInfo(Variant::INT, "hand", PROPERTY_HINT_ENUM, "Unknown,Left,Right"), "set_tracker_hand", "get_tracker_hand"); + + ClassDB::bind_method(D_METHOD("has_pose", "name"), &XRPositionalTracker::has_pose); + ClassDB::bind_method(D_METHOD("get_pose", "name"), &XRPositionalTracker::get_pose); + ClassDB::bind_method(D_METHOD("invalidate_pose", "name"), &XRPositionalTracker::invalidate_pose); + ClassDB::bind_method(D_METHOD("set_pose", "name", "transform", "linear_velocity", "angular_velocity"), &XRPositionalTracker::set_pose); + ADD_SIGNAL(MethodInfo("pose_changed", PropertyInfo(Variant::OBJECT, "pose", PROPERTY_HINT_RESOURCE_TYPE, "XRPose"))); + + ClassDB::bind_method(D_METHOD("get_input", "name"), &XRPositionalTracker::get_input); + ClassDB::bind_method(D_METHOD("set_input", "name", "value"), &XRPositionalTracker::set_input); + ADD_SIGNAL(MethodInfo("button_pressed", PropertyInfo(Variant::STRING, "name"))); + ADD_SIGNAL(MethodInfo("button_released", PropertyInfo(Variant::STRING, "name"))); + ADD_SIGNAL(MethodInfo("input_value_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::FLOAT, "value"))); + ADD_SIGNAL(MethodInfo("input_axis_changed", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::VECTOR2, "vector"))); + ClassDB::bind_method(D_METHOD("get_rumble"), &XRPositionalTracker::get_rumble); ClassDB::bind_method(D_METHOD("set_rumble", "rumble"), &XRPositionalTracker::set_rumble); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rumble"), "set_rumble", "get_rumble"); }; @@ -67,13 +75,6 @@ void XRPositionalTracker::set_tracker_type(XRServer::TrackerType p_type) { if (type != p_type) { type = p_type; hand = XRPositionalTracker::TRACKER_HAND_UNKNOWN; - - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL(xr_server); - - // get a tracker id for our type - // note if this is a controller this will be 3 or higher but we may change it later. - tracker_id = xr_server->get_free_tracker_id_for_type(p_type); }; }; @@ -81,7 +82,8 @@ XRServer::TrackerType XRPositionalTracker::get_tracker_type() const { return type; }; -void XRPositionalTracker::set_tracker_name(const String &p_name) { +void XRPositionalTracker::set_tracker_name(const StringName &p_name) { + // Note: this should not be changed after the tracker is registered with the XRServer! name = p_name; }; @@ -89,85 +91,13 @@ StringName XRPositionalTracker::get_tracker_name() const { return name; }; -int XRPositionalTracker::get_tracker_id() const { - return tracker_id; -}; - -void XRPositionalTracker::set_joy_id(int p_joy_id) { - joy_id = p_joy_id; -}; - -int XRPositionalTracker::get_joy_id() const { - return joy_id; -}; - -bool XRPositionalTracker::is_tracking_orientation() const { - return tracking_orientation; -}; - -void XRPositionalTracker::set_orientation(const Basis &p_orientation) { - _THREAD_SAFE_METHOD_ - - tracking_orientation = true; // obviously we have this - orientation = p_orientation; -}; - -Basis XRPositionalTracker::get_orientation() const { - _THREAD_SAFE_METHOD_ - - return orientation; -}; - -bool XRPositionalTracker::is_tracking_position() const { - return tracking_position; -}; - -void XRPositionalTracker::set_position(const Vector3 &p_position) { - _THREAD_SAFE_METHOD_ - - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL(xr_server); - real_t world_scale = xr_server->get_world_scale(); - ERR_FAIL_COND(world_scale == 0); - - tracking_position = true; // obviously we have this - rw_position = p_position / world_scale; -}; - -Vector3 XRPositionalTracker::get_position() const { - _THREAD_SAFE_METHOD_ - - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL_V(xr_server, rw_position); - real_t world_scale = xr_server->get_world_scale(); - - return rw_position * world_scale; -}; - -void XRPositionalTracker::set_rw_position(const Vector3 &p_rw_position) { - _THREAD_SAFE_METHOD_ - - tracking_position = true; // obviously we have this - rw_position = p_rw_position; -}; - -Vector3 XRPositionalTracker::get_rw_position() const { - _THREAD_SAFE_METHOD_ - - return rw_position; -}; - -void XRPositionalTracker::set_mesh(const Ref<Mesh> &p_mesh) { - _THREAD_SAFE_METHOD_ - - mesh = p_mesh; -}; - -Ref<Mesh> XRPositionalTracker::get_mesh() const { - _THREAD_SAFE_METHOD_ +void XRPositionalTracker::set_tracker_desc(const String &p_desc) { + description = p_desc; +} - return mesh; -}; +String XRPositionalTracker::get_tracker_desc() const { + return description; +} XRPositionalTracker::TrackerHand XRPositionalTracker::get_tracker_hand() const { return hand; @@ -182,33 +112,98 @@ void XRPositionalTracker::set_tracker_hand(const XRPositionalTracker::TrackerHan ERR_FAIL_COND((type != XRServer::TRACKER_CONTROLLER) && (p_hand != XRPositionalTracker::TRACKER_HAND_UNKNOWN)); hand = p_hand; - if (hand == XRPositionalTracker::TRACKER_HAND_LEFT) { - if (!xr_server->is_tracker_id_in_use_for_type(type, 1)) { - tracker_id = 1; - }; - } else if (hand == XRPositionalTracker::TRACKER_HAND_RIGHT) { - if (!xr_server->is_tracker_id_in_use_for_type(type, 2)) { - tracker_id = 2; - }; - }; }; }; -Transform3D XRPositionalTracker::get_transform(bool p_adjust_by_reference_frame) const { - Transform3D new_transform; +bool XRPositionalTracker::has_pose(const StringName &p_action_name) const { + return poses.has(p_action_name); +} - new_transform.basis = get_orientation(); - new_transform.origin = get_position(); +Ref<XRPose> XRPositionalTracker::get_pose(const StringName &p_action_name) const { + Ref<XRPose> pose; - if (p_adjust_by_reference_frame) { - XRServer *xr_server = XRServer::get_singleton(); - ERR_FAIL_NULL_V(xr_server, new_transform); + if (poses.has(p_action_name)) { + pose = poses[p_action_name]; + } - new_transform = xr_server->get_reference_frame() * new_transform; - }; + return pose; +} - return new_transform; -}; +void XRPositionalTracker::invalidate_pose(const StringName &p_action_name) { + // only update this if we were tracking this pose + if (poses.has(p_action_name)) { + // We just set tracking data as invalid, we leave our current transform and velocity data as is so controllers don't suddenly jump to origin. + poses[p_action_name]->set_has_tracking_data(false); + } +} + +void XRPositionalTracker::set_pose(const StringName &p_action_name, const Transform3D &p_transform, const Vector3 &p_linear_velocity, const Vector3 &p_angular_velocity) { + Ref<XRPose> new_pose; + + new_pose.instantiate(); + new_pose->set_name(p_action_name); + new_pose->set_has_tracking_data(true); + new_pose->set_transform(p_transform); + new_pose->set_linear_velocity(p_linear_velocity); + new_pose->set_angular_velocity(p_angular_velocity); + + poses[p_action_name] = new_pose; + emit_signal("pose_changed", new_pose); + + // TODO discuss whether we also want to create and emit an InputEventXRPose event +} + +Variant XRPositionalTracker::get_input(const StringName &p_action_name) const { + if (inputs.has(p_action_name)) { + return inputs[p_action_name]; + } else { + return Variant(); + } +} + +void XRPositionalTracker::set_input(const StringName &p_action_name, const Variant &p_value) { + bool changed = false; + + // XR inputs + + if (inputs.has(p_action_name)) { + changed = inputs[p_action_name] != p_value; + } else { + changed = true; + } + + if (changed) { + // store the new value + inputs[p_action_name] = p_value; + + // emit signals to let the rest of the world know + switch (p_value.get_type()) { + case Variant::BOOL: { + bool pressed = p_value; + if (pressed) { + emit_signal("button_pressed", p_action_name); + } else { + emit_signal("button_released", p_action_name); + } + + // TODO discuss whether we also want to create and emit an InputEventXRButton event + } break; + case Variant::FLOAT: { + emit_signal("input_value_changed", p_action_name, p_value); + + // TODO discuss whether we also want to create and emit an InputEventXRValue event + } break; + case Variant::VECTOR2: { + emit_signal("input_axis_changed", p_action_name, p_value); + + // TODO discuss whether we also want to create and emit an InputEventXRAxis event + } break; + default: { + // ??? + } break; + } + } +} real_t XRPositionalTracker::get_rumble() const { return rumble; @@ -225,10 +220,6 @@ void XRPositionalTracker::set_rumble(real_t p_rumble) { XRPositionalTracker::XRPositionalTracker() { type = XRServer::TRACKER_UNKNOWN; name = "Unknown"; - joy_id = -1; - tracker_id = 0; - tracking_orientation = false; - tracking_position = false; hand = TRACKER_HAND_UNKNOWN; rumble = 0.0; }; diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h index 5577582929..69eb105b5a 100644 --- a/servers/xr/xr_positional_tracker.h +++ b/servers/xr/xr_positional_tracker.h @@ -33,6 +33,7 @@ #include "core/os/thread_safe.h" #include "scene/resources/mesh.h" +#include "servers/xr/xr_pose.h" #include "servers/xr_server.h" /** @@ -57,14 +58,14 @@ public: private: XRServer::TrackerType type; // type of tracker StringName name; // (unique) name of the tracker - int tracker_id; // tracker index id that is unique per type + String description; // description of the tracker, this is interface dependent, for OpenXR this will be the interaction profile bound for to the tracker + TrackerHand hand; // if known, the hand this tracker is held in + + Map<StringName, Ref<XRPose>> poses; + Map<StringName, Variant> inputs; + int joy_id; // if we also have a related joystick entity, the id of the joystick - bool tracking_orientation; // do we track orientation? - Basis orientation; // our orientation - bool tracking_position; // do we track position? - Vector3 rw_position; // our position "in the real world, so without world_scale applied" Ref<Mesh> mesh; // when available, a mesh that can be used to render this tracker - TrackerHand hand; // if known, the hand this tracker is held in real_t rumble; // rumble strength, 0.0 is off, 1.0 is maximum, note that we only record here, xr_interface is responsible for execution protected: @@ -73,27 +74,24 @@ protected: public: void set_tracker_type(XRServer::TrackerType p_type); XRServer::TrackerType get_tracker_type() const; - void set_tracker_name(const String &p_name); + void set_tracker_name(const StringName &p_name); StringName get_tracker_name() const; - int get_tracker_id() const; - void set_joy_id(int p_joy_id); - int get_joy_id() const; - bool is_tracking_orientation() const; - void set_orientation(const Basis &p_orientation); - Basis get_orientation() const; - bool is_tracking_position() const; - void set_position(const Vector3 &p_position); // set position with world_scale applied - Vector3 get_position() const; // get position with world_scale applied - void set_rw_position(const Vector3 &p_rw_position); - Vector3 get_rw_position() const; + void set_tracker_desc(const String &p_desc); + String get_tracker_desc() const; XRPositionalTracker::TrackerHand get_tracker_hand() const; void set_tracker_hand(const XRPositionalTracker::TrackerHand p_hand); + + bool has_pose(const StringName &p_action_name) const; + Ref<XRPose> get_pose(const StringName &p_action_name) const; + void invalidate_pose(const StringName &p_action_name); + void set_pose(const StringName &p_action_name, const Transform3D &p_transform, const Vector3 &p_linear_velocity, const Vector3 &p_angular_velocity); + + Variant get_input(const StringName &p_action_name) const; + void set_input(const StringName &p_action_name, const Variant &p_value); + + // TODO replace by new implementation real_t get_rumble() const; void set_rumble(real_t p_rumble); - void set_mesh(const Ref<Mesh> &p_mesh); - Ref<Mesh> get_mesh() const; - - Transform3D get_transform(bool p_adjust_by_reference_frame) const; XRPositionalTracker(); ~XRPositionalTracker() {} diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp index 780bd10fc5..d0367ba95e 100644 --- a/servers/xr_server.cpp +++ b/servers/xr_server.cpp @@ -54,10 +54,11 @@ void XRServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_interface", "idx"), &XRServer::get_interface); ClassDB::bind_method(D_METHOD("get_interfaces"), &XRServer::get_interfaces); ClassDB::bind_method(D_METHOD("find_interface", "name"), &XRServer::find_interface); - ClassDB::bind_method(D_METHOD("get_tracker_count"), &XRServer::get_tracker_count); - ClassDB::bind_method(D_METHOD("get_tracker", "idx"), &XRServer::get_tracker); + ClassDB::bind_method(D_METHOD("add_tracker", "tracker"), &XRServer::add_tracker); ClassDB::bind_method(D_METHOD("remove_tracker", "tracker"), &XRServer::remove_tracker); + ClassDB::bind_method(D_METHOD("get_trackers", "tracker_types"), &XRServer::get_trackers); + ClassDB::bind_method(D_METHOD("get_tracker", "tracker_name"), &XRServer::get_tracker); ClassDB::bind_method(D_METHOD("get_primary_interface"), &XRServer::get_primary_interface); ClassDB::bind_method(D_METHOD("set_primary_interface", "interface"), &XRServer::set_primary_interface); @@ -68,6 +69,7 @@ void XRServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_last_commit_usec"), &XRServer::get_last_commit_usec); ClassDB::bind_method(D_METHOD("get_last_frame_usec"), &XRServer::get_last_frame_usec); + BIND_ENUM_CONSTANT(TRACKER_HEAD); BIND_ENUM_CONSTANT(TRACKER_CONTROLLER); BIND_ENUM_CONSTANT(TRACKER_BASESTATION); BIND_ENUM_CONSTANT(TRACKER_ANCHOR); @@ -82,8 +84,9 @@ void XRServer::_bind_methods() { ADD_SIGNAL(MethodInfo("interface_added", PropertyInfo(Variant::STRING_NAME, "interface_name"))); ADD_SIGNAL(MethodInfo("interface_removed", PropertyInfo(Variant::STRING_NAME, "interface_name"))); - ADD_SIGNAL(MethodInfo("tracker_added", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type"), PropertyInfo(Variant::INT, "id"))); - ADD_SIGNAL(MethodInfo("tracker_removed", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type"), PropertyInfo(Variant::INT, "id"))); + ADD_SIGNAL(MethodInfo("tracker_added", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type"))); + ADD_SIGNAL(MethodInfo("tracker_updated", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type"))); + ADD_SIGNAL(MethodInfo("tracker_removed", PropertyInfo(Variant::STRING_NAME, "tracker_name"), PropertyInfo(Variant::INT, "type"))); }; double XRServer::get_world_scale() const { @@ -113,35 +116,43 @@ Transform3D XRServer::get_reference_frame() const { }; void XRServer::center_on_hmd(RotationMode p_rotation_mode, bool p_keep_height) { - if (primary_interface != nullptr) { - // clear our current reference frame or we'll end up double adjusting it + if (primary_interface == nullptr) { + return; + } + + if (primary_interface->get_play_area_mode() == XRInterface::XR_PLAY_AREA_STAGE) { + // center_on_hmd is not available in this mode reference_frame = Transform3D(); + return; + } - // requesting our EYE_MONO transform should return our current HMD position - Transform3D new_reference_frame = primary_interface->get_camera_transform(); + // clear our current reference frame or we'll end up double adjusting it + reference_frame = Transform3D(); - // remove our tilt - if (p_rotation_mode == 1) { - // take the Y out of our Z - new_reference_frame.basis.set_axis(2, Vector3(new_reference_frame.basis.elements[0][2], 0.0, new_reference_frame.basis.elements[2][2]).normalized()); + // requesting our EYE_MONO transform should return our current HMD position + Transform3D new_reference_frame = primary_interface->get_camera_transform(); - // Y is straight up - new_reference_frame.basis.set_axis(1, Vector3(0.0, 1.0, 0.0)); + // remove our tilt + if (p_rotation_mode == 1) { + // take the Y out of our Z + new_reference_frame.basis.set_axis(2, Vector3(new_reference_frame.basis.elements[0][2], 0.0, new_reference_frame.basis.elements[2][2]).normalized()); - // and X is our cross reference - new_reference_frame.basis.set_axis(0, new_reference_frame.basis.get_axis(1).cross(new_reference_frame.basis.get_axis(2)).normalized()); - } else if (p_rotation_mode == 2) { - // remove our rotation, we're only interesting in centering on position - new_reference_frame.basis = Basis(); - }; + // Y is straight up + new_reference_frame.basis.set_axis(1, Vector3(0.0, 1.0, 0.0)); - // don't negate our height - if (p_keep_height) { - new_reference_frame.origin.y = 0.0; - }; + // and X is our cross reference + new_reference_frame.basis.set_axis(0, new_reference_frame.basis.get_axis(1).cross(new_reference_frame.basis.get_axis(2)).normalized()); + } else if (p_rotation_mode == 2) { + // remove our rotation, we're only interesting in centering on position + new_reference_frame.basis = Basis(); + }; - reference_frame = new_reference_frame.inverse(); + // don't negate our height + if (p_keep_height) { + new_reference_frame.origin.y = 0.0; }; + + reference_frame = new_reference_frame.inverse(); }; Transform3D XRServer::get_hmd_transform() { @@ -224,106 +235,121 @@ Array XRServer::get_interfaces() const { return ret; }; -/* - A little extra info on the tracker ids, these are unique per tracker type so we get some consistency in recognising our trackers, specifically controllers. - - The first controller that is turned of will get ID 1, the second will get ID 2, etc. - The magic happens when one of the controllers is turned off, say controller 1 turns off, controller 2 will remain controller 2, controller 3 will remain controller 3. - If controller number 1 is turned on again it again gets ID 1 unless another new controller was turned on since. - - The most likely scenario however is a controller that runs out of battery and another controller being used to replace it. - Because the controllers are often linked to physical objects, say you're holding a shield in controller 1, your left hand, and a gun in controller 2, your right hand, and controller 1 dies: - - using our tracker index would suddenly make the gun disappear and the shield jump into your right hand because controller 2 becomes controller 1. - - using this approach the shield disappears or is no longer tracked, but the gun stays firmly in your right hand because that is still controller 2, further more, if controller 1 is replaced the shield will return. -*/ - -bool XRServer::is_tracker_id_in_use_for_type(TrackerType p_tracker_type, int p_tracker_id) const { - for (int i = 0; i < trackers.size(); i++) { - if (trackers[i]->get_tracker_type() == p_tracker_type && trackers[i]->get_tracker_id() == p_tracker_id) { - return true; - }; - }; - - // all good - return false; +Ref<XRInterface> XRServer::get_primary_interface() const { + return primary_interface; }; -int XRServer::get_free_tracker_id_for_type(TrackerType p_tracker_type) { - // We start checking at 1, 0 means that it's not a controller.. - // Note that for controller we reserve: - // - 1 for the left hand controller and - // - 2 for the right hand controller - // so we start at 3 :) - int tracker_id = p_tracker_type == XRServer::TRACKER_CONTROLLER ? 3 : 1; - - while (is_tracker_id_in_use_for_type(p_tracker_type, tracker_id)) { - // try the next one - tracker_id++; - }; +void XRServer::set_primary_interface(const Ref<XRInterface> &p_primary_interface) { + if (p_primary_interface.is_null()) { + print_verbose("XR: Clearing primary interface"); + primary_interface.unref(); + } else { + primary_interface = p_primary_interface; - return tracker_id; + print_verbose("XR: Primary interface set to: " + primary_interface->get_name()); + } }; void XRServer::add_tracker(Ref<XRPositionalTracker> p_tracker) { ERR_FAIL_COND(p_tracker.is_null()); - trackers.push_back(p_tracker); - emit_signal(SNAME("tracker_added"), p_tracker->get_tracker_name(), p_tracker->get_tracker_type(), p_tracker->get_tracker_id()); + StringName tracker_name = p_tracker->get_tracker_name(); + if (trackers.has(tracker_name)) { + if (trackers[tracker_name] != p_tracker) { + // We already have a tracker with this name, we're going to replace it + trackers[tracker_name] = p_tracker; + emit_signal(SNAME("tracker_updated"), tracker_name, p_tracker->get_tracker_type()); + } + } else { + trackers[tracker_name] = p_tracker; + emit_signal(SNAME("tracker_added"), tracker_name, p_tracker->get_tracker_type()); + } }; void XRServer::remove_tracker(Ref<XRPositionalTracker> p_tracker) { ERR_FAIL_COND(p_tracker.is_null()); - int idx = -1; - for (int i = 0; i < trackers.size(); i++) { - if (trackers[i] == p_tracker) { - idx = i; - break; - }; - }; - - ERR_FAIL_COND(idx == -1); + StringName tracker_name = p_tracker->get_tracker_name(); + if (trackers.has(tracker_name)) { + // we send the signal right before removing it + emit_signal(SNAME("tracker_removed"), p_tracker->get_tracker_name(), p_tracker->get_tracker_type()); - emit_signal(SNAME("tracker_removed"), p_tracker->get_tracker_name(), p_tracker->get_tracker_type(), p_tracker->get_tracker_id()); - trackers.remove(idx); + // and remove it + trackers.erase(tracker_name); + } }; -int XRServer::get_tracker_count() const { - return trackers.size(); -}; +Dictionary XRServer::get_trackers(int p_tracker_types) { + Dictionary res; -Ref<XRPositionalTracker> XRServer::get_tracker(int p_index) const { - ERR_FAIL_INDEX_V(p_index, trackers.size(), Ref<XRPositionalTracker>()); + for (int i = 0; i < trackers.size(); i++) { + Ref<XRPositionalTracker> tracker = trackers.get_value_at_index(i); + if (tracker.is_valid() && (tracker->get_tracker_type() & p_tracker_types) != 0) { + res[tracker->get_tracker_name()] = tracker; + } + } - return trackers[p_index]; + return res; +} + +Ref<XRPositionalTracker> XRServer::get_tracker(const StringName &p_name) const { + if (trackers.has(p_name)) { + return trackers[p_name]; + } else { + // tracker hasn't been registered yet, which is fine, no need to spam the error log... + return Ref<XRPositionalTracker>(); + } }; -Ref<XRPositionalTracker> XRServer::find_by_type_and_id(TrackerType p_tracker_type, int p_tracker_id) const { - ERR_FAIL_COND_V(p_tracker_id == 0, Ref<XRPositionalTracker>()); +PackedStringArray XRServer::get_suggested_tracker_names() const { + PackedStringArray arr; - for (int i = 0; i < trackers.size(); i++) { - if (trackers[i]->get_tracker_type() == p_tracker_type && trackers[i]->get_tracker_id() == p_tracker_id) { - return trackers[i]; - }; - }; + for (int i = 0; i < interfaces.size(); i++) { + Ref<XRInterface> interface = interfaces[i]; + PackedStringArray interface_arr = interface->get_suggested_tracker_names(); + for (int a = 0; a < interface_arr.size(); a++) { + if (!arr.has(interface_arr[a])) { + arr.push_back(interface_arr[a]); + } + } + } - return Ref<XRPositionalTracker>(); -}; + if (arr.size() == 0) { + // no suggestions from our tracker? include our defaults + arr.push_back(String("head")); + arr.push_back(String("left_hand")); + arr.push_back(String("right_hand")); + } -Ref<XRInterface> XRServer::get_primary_interface() const { - return primary_interface; -}; + return arr; +} -void XRServer::set_primary_interface(const Ref<XRInterface> &p_primary_interface) { - if (p_primary_interface.is_null()) { - print_verbose("XR: Clearing primary interface"); - primary_interface.unref(); - } else { - primary_interface = p_primary_interface; +PackedStringArray XRServer::get_suggested_pose_names(const StringName &p_tracker_name) const { + PackedStringArray arr; - print_verbose("XR: Primary interface set to: " + primary_interface->get_name()); + for (int i = 0; i < interfaces.size(); i++) { + Ref<XRInterface> interface = interfaces[i]; + PackedStringArray interface_arr = interface->get_suggested_pose_names(p_tracker_name); + for (int a = 0; a < interface_arr.size(); a++) { + if (!arr.has(interface_arr[a])) { + arr.push_back(interface_arr[a]); + } + } } -}; + + if (arr.size() == 0) { + // no suggestions from our tracker? include our defaults + arr.push_back(String("default")); + + if ((p_tracker_name == "left_hand") || (p_tracker_name == "right_hand")) { + arr.push_back(String("aim")); + arr.push_back(String("grip")); + arr.push_back(String("skeleton")); + } + } + + return arr; +} uint64_t XRServer::get_last_process_usec() { return last_process_usec; @@ -373,8 +399,9 @@ XRServer::~XRServer() { interfaces.remove(0); } + // TODO pretty sure there is a clear function or something... while (trackers.size() > 0) { - trackers.remove(0); + trackers.erase(trackers.get_key_at_index(0)); } singleton = nullptr; diff --git a/servers/xr_server.h b/servers/xr_server.h index 6d07263755..48d73cac9a 100644 --- a/servers/xr_server.h +++ b/servers/xr_server.h @@ -60,9 +60,10 @@ class XRServer : public Object { public: enum TrackerType { - TRACKER_CONTROLLER = 0x01, /* tracks a controller */ - TRACKER_BASESTATION = 0x02, /* tracks location of a base station */ - TRACKER_ANCHOR = 0x04, /* tracks an anchor point, used in AR to track a real live location */ + TRACKER_HEAD = 0x01, /* tracks the position of the players head (or in case of handheld AR, location of the phone) */ + TRACKER_CONTROLLER = 0x02, /* tracks a controller */ + TRACKER_BASESTATION = 0x04, /* tracks location of a base station */ + TRACKER_ANCHOR = 0x08, /* tracks an anchor point, used in AR to track a real live location */ TRACKER_UNKNOWN = 0x80, /* unknown tracker */ TRACKER_ANY_KNOWN = 0x7f, /* all except unknown */ @@ -77,7 +78,7 @@ public: private: Vector<Ref<XRInterface>> interfaces; - Vector<Ref<XRPositionalTracker>> trackers; + Dictionary trackers; Ref<XRInterface> primary_interface; /* we'll identify one interface as primary, this will be used by our viewports */ @@ -164,13 +165,17 @@ public: Our trackers are objects that expose the orientation and position of physical devices such as controller, anchor points, etc. They are created and managed by our active AR/VR interfaces. */ - bool is_tracker_id_in_use_for_type(TrackerType p_tracker_type, int p_tracker_id) const; - int get_free_tracker_id_for_type(TrackerType p_tracker_type); void add_tracker(Ref<XRPositionalTracker> p_tracker); void remove_tracker(Ref<XRPositionalTracker> p_tracker); - int get_tracker_count() const; - Ref<XRPositionalTracker> get_tracker(int p_index) const; - Ref<XRPositionalTracker> find_by_type_and_id(TrackerType p_tracker_type, int p_tracker_id) const; + Dictionary get_trackers(int p_tracker_types); + Ref<XRPositionalTracker> get_tracker(const StringName &p_name) const; + + /* + We don't know which trackers and actions will existing during runtime but we can request suggested names from our interfaces to help our IDE UI. + */ + PackedStringArray get_suggested_tracker_names() const; + PackedStringArray get_suggested_pose_names(const StringName &p_tracker_name) const; + // Q: Should we add get_suggested_input_names and get_suggested_haptic_names even though we don't use them for the IDE? uint64_t get_last_process_usec(); uint64_t get_last_commit_usec(); diff --git a/tests/test_tools.h b/tests/test_tools.h index 3ea953cb07..ec18610f04 100644 --- a/tests/test_tools.h +++ b/tests/test_tools.h @@ -49,7 +49,7 @@ struct ErrorDetector { has_error = false; } - static void _detect_error(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type) { + static void _detect_error(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, bool p_editor_notify, ErrorHandlerType p_type) { ErrorDetector *self = (ErrorDetector *)p_self; self->has_error = true; } |