summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/object/object.cpp11
-rw-r--r--core/object/object.h4
-rw-r--r--doc/classes/CharacterBody2D.xml3
-rw-r--r--doc/classes/StaticBody2D.xml3
-rw-r--r--editor/editor_node.cpp16
-rw-r--r--editor/editor_node.h4
-rw-r--r--editor/export_template_manager.cpp12
-rw-r--r--editor/export_template_manager.h2
-rw-r--r--editor/plugin_config_dialog.cpp102
-rw-r--r--editor/plugin_config_dialog.h5
-rw-r--r--platform/android/export/export.cpp3
-rw-r--r--scene/2d/collision_object_2d.h2
-rw-r--r--scene/2d/physics_body_2d.cpp167
-rw-r--r--scene/2d/physics_body_2d.h19
14 files changed, 261 insertions, 92 deletions
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 296d876701..0644012318 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1769,6 +1769,17 @@ uint32_t Object::get_edited_version() const {
}
#endif
+void Object::set_instance_binding(void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks) {
+ // This is only meant to be used on creation by the binder.
+ ERR_FAIL_COND(_instance_bindings != nullptr);
+ _instance_bindings = (InstanceBinding *)memalloc(sizeof(InstanceBinding));
+ _instance_bindings[0].binding = p_binding;
+ _instance_bindings[0].free_callback = p_callbacks->free_callback;
+ _instance_bindings[0].reference_callback = p_callbacks->reference_callback;
+ _instance_bindings[0].token = p_token;
+ _instance_binding_count = 1;
+}
+
void *Object::get_instance_binding(void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks) {
void *binding = nullptr;
_instance_binding_mutex.lock();
diff --git a/core/object/object.h b/core/object/object.h
index 33d9b627f6..89385b81a3 100644
--- a/core/object/object.h
+++ b/core/object/object.h
@@ -804,8 +804,10 @@ public:
#endif
- //used by script languages to store binding data
+ // Used by script languages to store binding data.
void *get_instance_binding(void *p_token, const GDNativeInstanceBindingCallbacks *p_callbacks);
+ // Used on creation by binding only.
+ void set_instance_binding(void *p_token, void *p_binding, const GDNativeInstanceBindingCallbacks *p_callbacks);
void clear_internal_resource_paths();
diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml
index b2d8aba174..e184e7dc82 100644
--- a/doc/classes/CharacterBody2D.xml
+++ b/doc/classes/CharacterBody2D.xml
@@ -110,9 +110,6 @@
<member name="max_slides" type="int" setter="set_max_slides" getter="get_max_slides" default="4">
Maximum number of times the body can change direction before it stops when calling [method move_and_slide].
</member>
- <member name="motion/sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
- If [code]true[/code], the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method move_and_slide] or [method PhysicsBody2D.move_and_collide] functions.
- </member>
<member name="snap" type="Vector2" setter="set_snap" getter="get_snap" default="Vector2(0, 0)">
When set to a value different from [code]Vector2(0, 0)[/code], the body is kept attached to slopes when calling [method move_and_slide].
As long as the [code]snap[/code] vector is in contact with the ground, the body will remain attached to the surface. This means you must disable snap in order to jump, for example. You can do this by setting [code]snap[/code] to [code]Vector2(0, 0)[/code].
diff --git a/doc/classes/StaticBody2D.xml b/doc/classes/StaticBody2D.xml
index 85915a53fe..326bf58e22 100644
--- a/doc/classes/StaticBody2D.xml
+++ b/doc/classes/StaticBody2D.xml
@@ -29,6 +29,9 @@
The physics material override for the body.
If a material is assigned to this property, it will be used instead of any other physics material, such as an inherited one.
</member>
+ <member name="sync_to_physics" type="bool" setter="set_sync_to_physics" getter="is_sync_to_physics_enabled" default="false">
+ If [code]true[/code] and [member kinematic_motion] is enabled, the body's movement will be synchronized to the physics frame. This is useful when animating movement via [AnimationPlayer], for example on moving platforms. Do [b]not[/b] use together with [method PhysicsBody2D.move_and_collide].
+ </member>
</members>
<constants>
</constants>
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index f09a6f678a..128908c132 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -2329,6 +2329,9 @@ void EditorNode::_run_native(const Ref<EditorExportPreset> &p_preset) {
}
}
+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..
current_option = (MenuOptions)p_option;
@@ -2753,6 +2756,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
export_template_manager->popup_manager();
} break;
+ case SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE: {
+ custom_build_manage_templates->hide();
+ file_android_build_source->popup_centered_ratio();
+ } break;
case SETTINGS_MANAGE_FEATURE_PROFILES: {
feature_profile_manager->popup_centered_clamped(Size2(900, 800) * EDSCALE, 0.8);
} break;
@@ -6678,9 +6685,18 @@ EditorNode::EditorNode() {
custom_build_manage_templates = memnew(ConfirmationDialog);
custom_build_manage_templates->set_text(TTR("Android build template is missing, please install relevant templates."));
custom_build_manage_templates->get_ok_button()->set_text(TTR("Manage Templates"));
+ custom_build_manage_templates->add_button(TTR("Install from file"))->connect("pressed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE));
custom_build_manage_templates->connect("confirmed", callable_mp(this, &EditorNode::_menu_option), varray(SETTINGS_MANAGE_EXPORT_TEMPLATES));
gui_base->add_child(custom_build_manage_templates);
+ file_android_build_source = memnew(EditorFileDialog);
+ file_android_build_source->set_title(TTR("Select android sources file"));
+ file_android_build_source->set_access(EditorFileDialog::ACCESS_FILESYSTEM);
+ file_android_build_source->set_file_mode(EditorFileDialog::FILE_MODE_OPEN_FILE);
+ file_android_build_source->add_filter("*.zip");
+ file_android_build_source->connect("file_selected", callable_mp(this, &EditorNode::_android_build_source_selected));
+ gui_base->add_child(file_android_build_source);
+
install_android_build_template = memnew(ConfirmationDialog);
install_android_build_template->set_text(TTR("This will set up your project for custom Android builds by installing the source template to \"res://android/build\".\nYou can then apply modifications and build your own custom APK on export (adding modules, changing the AndroidManifest.xml, etc.).\nNote that in order to make custom builds instead of using pre-built APKs, the \"Use Custom Build\" option should be enabled in the Android export preset."));
install_android_build_template->get_ok_button()->set_text(TTR("Install"));
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 07bed6999b..6b91856a59 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -181,6 +181,7 @@ private:
SETTINGS_EDITOR_CONFIG_FOLDER,
SETTINGS_MANAGE_EXPORT_TEMPLATES,
SETTINGS_MANAGE_FEATURE_PROFILES,
+ SETTINGS_INSTALL_ANDROID_BUILD_TEMPLATE,
SETTINGS_PICK_MAIN_SCENE,
SETTINGS_TOGGLE_CONSOLE,
SETTINGS_TOGGLE_FULLSCREEN,
@@ -327,6 +328,7 @@ private:
EditorFileDialog *file_templates;
EditorFileDialog *file_export_lib;
EditorFileDialog *file_script;
+ EditorFileDialog *file_android_build_source;
CheckBox *file_export_lib_merge;
String current_path;
MenuButton *update_spinner;
@@ -455,6 +457,8 @@ private:
void _menu_confirm_current();
void _menu_option_confirm(int p_option, bool p_confirmed);
+ void _android_build_source_selected(const String &p_file);
+
void _request_screenshot();
void _screenshot(bool p_use_utc = false);
void _save_screenshot(NodePath p_path);
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index 112a9e92a8..e24f6a11ed 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -630,6 +630,12 @@ bool ExportTemplateManager::can_install_android_template() {
}
Error ExportTemplateManager::install_android_template() {
+ const String &templates_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
+ const String &source_zip = templates_path.plus_file("android_source.zip");
+ ERR_FAIL_COND_V(!FileAccess::exists(source_zip), ERR_CANT_OPEN);
+ return install_android_template_from_file(source_zip);
+}
+Error ExportTemplateManager::install_android_template_from_file(const String &p_file) {
// To support custom Android builds, we install the Java source code and buildsystem
// from android_source.zip to the project's res://android folder.
@@ -662,14 +668,10 @@ Error ExportTemplateManager::install_android_template() {
// Uncompress source template.
- const String &templates_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
- const String &source_zip = templates_path.plus_file("android_source.zip");
- ERR_FAIL_COND_V(!FileAccess::exists(source_zip), ERR_CANT_OPEN);
-
FileAccess *src_f = nullptr;
zlib_filefunc_def io = zipio_create_io_from_file(&src_f);
- unzFile pkg = unzOpen2(source_zip.utf8().get_data(), &io);
+ unzFile pkg = unzOpen2(p_file.utf8().get_data(), &io);
ERR_FAIL_COND_V_MSG(!pkg, ERR_CANT_OPEN, "Android sources not in ZIP format.");
int ret = unzGoToFirstFile(pkg);
diff --git a/editor/export_template_manager.h b/editor/export_template_manager.h
index f145c6c0f5..ebadb88c36 100644
--- a/editor/export_template_manager.h
+++ b/editor/export_template_manager.h
@@ -124,6 +124,8 @@ public:
bool can_install_android_template();
Error install_android_template();
+ Error install_android_template_from_file(const String &p_file);
+
void popup_manager();
ExportTemplateManager();
diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp
index cbcc3c9880..e2938c8156 100644
--- a/editor/plugin_config_dialog.cpp
+++ b/editor/plugin_config_dialog.cpp
@@ -127,7 +127,51 @@ void PluginConfigDialog::_on_cancelled() {
void PluginConfigDialog::_on_required_text_changed(const String &) {
int lang_idx = script_option_edit->get_selected();
String ext = ScriptServer::get_language(lang_idx)->get_extension();
- get_ok_button()->set_disabled(script_edit->get_text().get_basename().is_empty() || script_edit->get_text().get_extension() != ext || name_edit->get_text().is_empty());
+
+ Ref<Texture2D> valid_icon = get_theme_icon("StatusSuccess", "EditorIcons");
+ Ref<Texture2D> invalid_icon = get_theme_icon("StatusWarning", "EditorIcons");
+
+ // Set variables to assume all is valid
+ bool is_valid = true;
+ name_validation->set_texture(valid_icon);
+ subfolder_validation->set_texture(valid_icon);
+ script_validation->set_texture(valid_icon);
+ name_validation->set_tooltip("");
+ subfolder_validation->set_tooltip("");
+ script_validation->set_tooltip("");
+
+ // Change valid status to invalid depending on conditions.
+ Vector<String> errors;
+ if (name_edit->get_text().is_empty()) {
+ is_valid = false;
+ name_validation->set_texture(invalid_icon);
+ name_validation->set_tooltip(TTR("Plugin name cannot not be blank."));
+ }
+ if (script_edit->get_text().get_extension() != ext) {
+ is_valid = false;
+ script_validation->set_texture(invalid_icon);
+ script_validation->set_tooltip(vformat(TTR("Script extension must match chosen langauge extension (.%s)."), ext));
+ }
+ if (script_edit->get_text().get_basename().is_empty()) {
+ is_valid = false;
+ script_validation->set_texture(invalid_icon);
+ script_validation->set_tooltip(TTR("Script name cannot not be blank."));
+ }
+ if (subfolder_edit->get_text().is_empty()) {
+ is_valid = false;
+ subfolder_validation->set_texture(invalid_icon);
+ subfolder_validation->set_tooltip(TTR("Subfolder cannot be blank."));
+ } else {
+ DirAccessRef dir = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ String path = "res://addons/" + subfolder_edit->get_text();
+ if (dir->dir_exists(path) && !_edit_mode) { // Only show this error if in "create" mode.
+ is_valid = false;
+ subfolder_validation->set_texture(invalid_icon);
+ subfolder_validation->set_tooltip(TTR("Subfolder cannot be one which already exists."));
+ }
+ }
+
+ get_ok_button()->set_disabled(!is_valid);
}
String PluginConfigDialog::_to_absolute_plugin_path(const String &p_plugin_name) {
@@ -163,19 +207,22 @@ void PluginConfigDialog::config(const String &p_config_path) {
_edit_mode = true;
active_edit->hide();
- Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 1))->hide();
+ Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 2))->hide();
subfolder_edit->hide();
- Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 1))->hide();
+ Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 2))->hide();
set_title(TTR("Edit a Plugin"));
} else {
_clear_fields();
_edit_mode = false;
active_edit->show();
- Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 1))->show();
+ Object::cast_to<Label>(active_edit->get_parent()->get_child(active_edit->get_index() - 2))->show();
subfolder_edit->show();
- Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 1))->show();
+ Object::cast_to<Label>(subfolder_edit->get_parent()->get_child(subfolder_edit->get_index() - 2))->show();
set_title(TTR("Create a Plugin"));
}
+ // Simulate text changing so the errors populate.
+ _on_required_text_changed("");
+
get_ok_button()->set_disabled(!_edit_mode);
get_ok_button()->set_text(_edit_mode ? TTR("Update") : TTR("Create"));
}
@@ -188,56 +235,88 @@ PluginConfigDialog::PluginConfigDialog() {
get_ok_button()->set_disabled(true);
set_hide_on_ok(true);
+ VBoxContainer *vbox = memnew(VBoxContainer);
+ vbox->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ vbox->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ add_child(vbox);
+
GridContainer *grid = memnew(GridContainer);
- grid->set_columns(2);
- add_child(grid);
+ grid->set_columns(3);
+ vbox->add_child(grid);
+ // Plugin Name
Label *name_lb = memnew(Label);
name_lb->set_text(TTR("Plugin Name:"));
grid->add_child(name_lb);
+ name_validation = memnew(TextureRect);
+ name_validation->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ grid->add_child(name_validation);
+
name_edit = memnew(LineEdit);
name_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed));
name_edit->set_placeholder("MyPlugin");
grid->add_child(name_edit);
+ // Subfolder
Label *subfolder_lb = memnew(Label);
subfolder_lb->set_text(TTR("Subfolder:"));
grid->add_child(subfolder_lb);
+ subfolder_validation = memnew(TextureRect);
+ subfolder_validation->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ grid->add_child(subfolder_validation);
+
subfolder_edit = memnew(LineEdit);
subfolder_edit->set_placeholder("\"my_plugin\" -> res://addons/my_plugin");
+ subfolder_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed));
grid->add_child(subfolder_edit);
+ // Description
Label *desc_lb = memnew(Label);
desc_lb->set_text(TTR("Description:"));
grid->add_child(desc_lb);
+ Control *desc_spacer = memnew(Control);
+ grid->add_child(desc_spacer);
+
desc_edit = memnew(TextEdit);
desc_edit->set_custom_minimum_size(Size2(400, 80) * EDSCALE);
desc_edit->set_wrap_enabled(true);
grid->add_child(desc_edit);
+ // Author
Label *author_lb = memnew(Label);
author_lb->set_text(TTR("Author:"));
grid->add_child(author_lb);
+ Control *author_spacer = memnew(Control);
+ grid->add_child(author_spacer);
+
author_edit = memnew(LineEdit);
author_edit->set_placeholder("Godette");
grid->add_child(author_edit);
+ // Version
Label *version_lb = memnew(Label);
version_lb->set_text(TTR("Version:"));
grid->add_child(version_lb);
+ Control *version_spacer = memnew(Control);
+ grid->add_child(version_spacer);
+
version_edit = memnew(LineEdit);
version_edit->set_placeholder("1.0");
grid->add_child(version_edit);
+ // Language dropdown
Label *script_option_lb = memnew(Label);
script_option_lb->set_text(TTR("Language:"));
grid->add_child(script_option_lb);
+ Control *script_opt_spacer = memnew(Control);
+ grid->add_child(script_opt_spacer);
+
script_option_edit = memnew(OptionButton);
int default_lang = 0;
for (int i = 0; i < ScriptServer::get_language_count(); i++) {
@@ -252,20 +331,29 @@ PluginConfigDialog::PluginConfigDialog() {
script_option_edit->select(default_lang);
grid->add_child(script_option_edit);
+ // Plugin Script Name
Label *script_lb = memnew(Label);
script_lb->set_text(TTR("Script Name:"));
grid->add_child(script_lb);
+ script_validation = memnew(TextureRect);
+ script_validation->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
+ grid->add_child(script_validation);
+
script_edit = memnew(LineEdit);
script_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed));
script_edit->set_placeholder("\"plugin.gd\" -> res://addons/my_plugin/plugin.gd");
grid->add_child(script_edit);
+ // Activate now checkbox
// TODO Make this option work better with languages like C#. Right now, it does not work because the C# project must be compiled first.
Label *active_lb = memnew(Label);
active_lb->set_text(TTR("Activate now?"));
grid->add_child(active_lb);
+ Control *active_spacer = memnew(Control);
+ grid->add_child(active_spacer);
+
active_edit = memnew(CheckBox);
active_edit->set_pressed(true);
grid->add_child(active_edit);
diff --git a/editor/plugin_config_dialog.h b/editor/plugin_config_dialog.h
index f49f14c881..ad5b96735f 100644
--- a/editor/plugin_config_dialog.h
+++ b/editor/plugin_config_dialog.h
@@ -36,6 +36,7 @@
#include "scene/gui/line_edit.h"
#include "scene/gui/option_button.h"
#include "scene/gui/text_edit.h"
+#include "scene/gui/texture_rect.h"
class PluginConfigDialog : public ConfirmationDialog {
GDCLASS(PluginConfigDialog, ConfirmationDialog);
@@ -49,6 +50,10 @@ class PluginConfigDialog : public ConfirmationDialog {
LineEdit *script_edit;
CheckBox *active_edit;
+ TextureRect *name_validation;
+ TextureRect *subfolder_validation;
+ TextureRect *script_validation;
+
bool _edit_mode;
void _clear_fields();
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 6661698d3e..956b59ce80 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -2064,10 +2064,9 @@ public:
err += template_err;
}
} else {
- r_missing_templates = !exists_export_template("android_source.zip", &err);
-
bool installed_android_build_template = FileAccess::exists("res://android/build/build.gradle");
if (!installed_android_build_template) {
+ r_missing_templates = !exists_export_template("android_source.zip", &err);
err += TTR("Android build template not installed in the project. Install it from the Project menu.") + "\n";
}
diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h
index 7a71affbb5..057eb7f635 100644
--- a/scene/2d/collision_object_2d.h
+++ b/scene/2d/collision_object_2d.h
@@ -75,7 +75,7 @@ private:
int total_subshapes = 0;
Map<uint32_t, ShapeData> shapes;
- bool only_update_transform_changes = false; //this is used for sync physics in CharacterBody2D
+ bool only_update_transform_changes = false; // This is used for sync to physics.
void _apply_disabled();
void _apply_enabled();
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index b68f0312fc..5b12da8b57 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -229,6 +229,13 @@ void StaticBody2D::set_kinematic_motion_enabled(bool p_enabled) {
set_body_mode(PhysicsServer2D::BODY_MODE_STATIC);
}
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ return;
+ }
+#endif
+
_update_kinematic_motion();
}
@@ -236,8 +243,75 @@ bool StaticBody2D::is_kinematic_motion_enabled() const {
return kinematic_motion;
}
+void StaticBody2D::set_sync_to_physics(bool p_enable) {
+ if (sync_to_physics == p_enable) {
+ return;
+ }
+
+ sync_to_physics = p_enable;
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_configuration_warnings();
+ return;
+ }
+#endif
+
+ if (kinematic_motion) {
+ _update_kinematic_motion();
+ }
+}
+
+bool StaticBody2D::is_sync_to_physics_enabled() const {
+ return sync_to_physics;
+}
+
+void StaticBody2D::_direct_state_changed(Object *p_state) {
+ if (!sync_to_physics) {
+ return;
+ }
+
+ PhysicsDirectBodyState2D *state = Object::cast_to<PhysicsDirectBodyState2D>(p_state);
+ ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState2D object as argument");
+
+ last_valid_transform = state->get_transform();
+ set_notify_local_transform(false);
+ set_global_transform(last_valid_transform);
+ set_notify_local_transform(true);
+}
+
+TypedArray<String> StaticBody2D::get_configuration_warnings() const {
+ TypedArray<String> warnings = PhysicsBody2D::get_configuration_warnings();
+
+ if (sync_to_physics && !kinematic_motion) {
+ warnings.push_back(TTR("Sync to physics works only when kinematic motion is enabled."));
+ }
+
+ return warnings;
+}
+
void StaticBody2D::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_ENTER_TREE: {
+ last_valid_transform = get_global_transform();
+ } break;
+
+ case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
+ // Used by sync to physics, send the new transform to the physics...
+ Transform2D new_transform = get_global_transform();
+
+ real_t delta_time = get_physics_process_delta_time();
+ new_transform.translate(constant_linear_velocity * delta_time);
+ new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time);
+
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
+
+ // ... but then revert changes.
+ set_notify_local_transform(false);
+ set_global_transform(last_valid_transform);
+ set_notify_local_transform(true);
+ } break;
+
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_editor_hint()) {
@@ -247,19 +321,23 @@ void StaticBody2D::_notification(int p_what) {
ERR_FAIL_COND(!kinematic_motion);
- real_t delta_time = get_physics_process_delta_time();
-
Transform2D new_transform = get_global_transform();
+ real_t delta_time = get_physics_process_delta_time();
new_transform.translate(constant_linear_velocity * delta_time);
new_transform.set_rotation(new_transform.get_rotation() + constant_angular_velocity * delta_time);
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
+ if (sync_to_physics) {
+ // Propagate transform change to node.
+ set_global_transform(new_transform);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
- // Propagate transform change to node.
- set_block_transform_notify(true);
- set_global_transform(new_transform);
- set_block_transform_notify(false);
+ // Propagate transform change to node.
+ set_block_transform_notify(true);
+ set_global_transform(new_transform);
+ set_block_transform_notify(false);
+ }
} break;
}
}
@@ -276,10 +354,14 @@ void StaticBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &StaticBody2D::set_physics_material_override);
ClassDB::bind_method(D_METHOD("get_physics_material_override"), &StaticBody2D::get_physics_material_override);
+ ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &StaticBody2D::set_sync_to_physics);
+ ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &StaticBody2D::is_sync_to_physics_enabled);
+
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "physics_material_override", PROPERTY_HINT_RESOURCE_TYPE, "PhysicsMaterial"), "set_physics_material_override", "get_physics_material_override");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "constant_linear_velocity"), "set_constant_linear_velocity", "get_constant_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "constant_angular_velocity"), "set_constant_angular_velocity", "get_constant_angular_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "kinematic_motion"), "set_kinematic_motion_enabled", "is_kinematic_motion_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
}
StaticBody2D::StaticBody2D() :
@@ -303,14 +385,24 @@ void StaticBody2D::_update_kinematic_motion() {
}
#endif
+ if (kinematic_motion && sync_to_physics) {
+ PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &StaticBody2D::_direct_state_changed));
+ set_only_update_transform_changes(true);
+ set_notify_local_transform(true);
+ } else {
+ PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), Callable());
+ set_only_update_transform_changes(false);
+ set_notify_local_transform(false);
+ }
+
+ bool needs_physics_process = false;
if (kinematic_motion) {
if (!Math::is_zero_approx(constant_angular_velocity) || !constant_linear_velocity.is_equal_approx(Vector2())) {
- set_physics_process_internal(true);
- return;
+ needs_physics_process = true;
}
}
- set_physics_process_internal(false);
+ set_physics_process_internal(needs_physics_process);
}
void RigidBody2D::_body_enter_tree(ObjectID p_id) {
@@ -1206,45 +1298,6 @@ Ref<KinematicCollision2D> CharacterBody2D::_get_slide_collision(int p_bounce) {
return slide_colliders[p_bounce];
}
-void CharacterBody2D::set_sync_to_physics(bool p_enable) {
- if (sync_to_physics == p_enable) {
- return;
- }
- sync_to_physics = p_enable;
-
- if (Engine::get_singleton()->is_editor_hint()) {
- return;
- }
-
- if (p_enable) {
- PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), callable_mp(this, &CharacterBody2D::_direct_state_changed));
- set_only_update_transform_changes(true);
- set_notify_local_transform(true);
- } else {
- PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), Callable());
- set_only_update_transform_changes(false);
- set_notify_local_transform(false);
- }
-}
-
-bool CharacterBody2D::is_sync_to_physics_enabled() const {
- return sync_to_physics;
-}
-
-void CharacterBody2D::_direct_state_changed(Object *p_state) {
- if (!sync_to_physics) {
- return;
- }
-
- PhysicsDirectBodyState2D *state = Object::cast_to<PhysicsDirectBodyState2D>(p_state);
- ERR_FAIL_NULL_MSG(state, "Method '_direct_state_changed' must receive a valid PhysicsDirectBodyState2D object as argument");
-
- last_valid_transform = state->get_transform();
- set_notify_local_transform(false);
- set_global_transform(last_valid_transform);
- set_notify_local_transform(true);
-}
-
void CharacterBody2D::set_safe_margin(real_t p_margin) {
margin = p_margin;
}
@@ -1304,8 +1357,6 @@ void CharacterBody2D::set_up_direction(const Vector2 &p_up_direction) {
void CharacterBody2D::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
- last_valid_transform = get_global_transform();
-
// Reset move_and_slide() data.
on_floor = false;
on_floor_body = RID();
@@ -1314,16 +1365,6 @@ void CharacterBody2D::_notification(int p_what) {
motion_results.clear();
floor_velocity = Vector2();
} break;
-
- case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
- // Used by sync to physics, send the new transform to the physics.
- Transform2D new_transform = get_global_transform();
- PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform);
- // But then revert changes.
- set_notify_local_transform(false);
- set_global_transform(last_valid_transform);
- set_notify_local_transform(true);
- } break;
}
}
@@ -1356,9 +1397,6 @@ void CharacterBody2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_slide_count"), &CharacterBody2D::get_slide_count);
ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody2D::_get_slide_collision);
- ClassDB::bind_method(D_METHOD("set_sync_to_physics", "enable"), &CharacterBody2D::set_sync_to_physics);
- ClassDB::bind_method(D_METHOD("is_sync_to_physics_enabled"), &CharacterBody2D::is_sync_to_physics_enabled);
-
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stop_on_slope"), "set_stop_on_slope_enabled", "is_stop_on_slope_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "infinite_inertia"), "set_infinite_inertia_enabled", "is_infinite_inertia_enabled");
@@ -1367,7 +1405,6 @@ void CharacterBody2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "snap"), "set_snap", "get_snap");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "motion/sync_to_physics"), "set_sync_to_physics", "is_sync_to_physics_enabled");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin");
}
diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h
index 52e432f005..7a319aabc9 100644
--- a/scene/2d/physics_body_2d.h
+++ b/scene/2d/physics_body_2d.h
@@ -69,6 +69,11 @@ class StaticBody2D : public PhysicsBody2D {
Ref<PhysicsMaterial> physics_material_override;
bool kinematic_motion = false;
+ bool sync_to_physics = false;
+
+ Transform2D last_valid_transform;
+
+ void _direct_state_changed(Object *p_state);
protected:
void _notification(int p_what);
@@ -84,6 +89,8 @@ public:
Vector2 get_constant_linear_velocity() const;
real_t get_constant_angular_velocity() const;
+ virtual TypedArray<String> get_configuration_warnings() const override;
+
StaticBody2D();
private:
@@ -93,6 +100,9 @@ private:
void set_kinematic_motion_enabled(bool p_enabled);
bool is_kinematic_motion_enabled() const;
+
+ void set_sync_to_physics(bool p_enable);
+ bool is_sync_to_physics_enabled() const;
};
class RigidBody2D : public PhysicsBody2D {
@@ -243,7 +253,7 @@ public:
TypedArray<Node2D> get_colliding_bodies() const; //function for script
- TypedArray<String> get_configuration_warnings() const override;
+ virtual TypedArray<String> get_configuration_warnings() const override;
RigidBody2D();
~RigidBody2D();
@@ -276,7 +286,6 @@ private:
bool on_floor = false;
bool on_ceiling = false;
bool on_wall = false;
- bool sync_to_physics = false;
Vector<PhysicsServer2D::MotionResult> motion_results;
Vector<Ref<KinematicCollision2D>> slide_colliders;
@@ -285,9 +294,6 @@ private:
bool separate_raycast_shapes(PhysicsServer2D::MotionResult &r_result);
- Transform2D last_valid_transform;
- void _direct_state_changed(Object *p_state);
-
void set_safe_margin(real_t p_margin);
real_t get_safe_margin() const;
@@ -329,9 +335,6 @@ public:
int get_slide_count() const;
PhysicsServer2D::MotionResult get_slide_collision(int p_bounce) const;
- void set_sync_to_physics(bool p_enable);
- bool is_sync_to_physics_enabled() const;
-
CharacterBody2D();
~CharacterBody2D();
};