summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/object.cpp7
-rw-r--r--core/object.h6
-rw-r--r--core/reference.cpp29
-rw-r--r--core/script_language.h2
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.cpp67
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp5
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp5
-rw-r--r--editor/import/resource_importer_layered_texture.cpp1
-rw-r--r--editor/plugins/material_editor_plugin.cpp6
-rw-r--r--editor/plugins/material_editor_plugin.h6
-rw-r--r--editor/plugins/script_editor_plugin.cpp9
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp157
-rw-r--r--editor/plugins/texture_region_editor_plugin.h3
-rw-r--r--editor/spatial_editor_gizmos.cpp8
-rw-r--r--modules/bullet/cone_twist_joint_bullet.cpp10
-rw-r--r--modules/bullet/generic_6dof_joint_bullet.cpp18
-rw-r--r--modules/bullet/hinge_joint_bullet.cpp15
-rw-r--r--modules/bullet/pin_joint_bullet.cpp6
-rw-r--r--modules/bullet/space_bullet.cpp4
-rw-r--r--modules/gdscript/gdscript.cpp26
-rw-r--r--modules/gdscript/gdscript_compiler.cpp9
-rw-r--r--modules/mono/csharp_script.cpp75
-rw-r--r--modules/mono/csharp_script.h2
-rw-r--r--modules/mono/editor/bindings_generator.cpp22
-rw-r--r--modules/mono/glue/collections_glue.cpp56
-rw-r--r--modules/mono/glue/cs_files/Array.cs2
-rw-r--r--modules/mono/glue/cs_files/Dictionary.cs2
-rw-r--r--modules/mono/glue/cs_files/MarshalUtils.cs1
-rw-r--r--modules/mono/godotsharp_defs.h1
-rw-r--r--modules/mono/mono_gc_handle.cpp7
-rw-r--r--modules/mono/mono_gc_handle.h15
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp9
-rw-r--r--modules/mono/signal_awaiter_utils.cpp7
-rw-r--r--modules/mono/signal_awaiter_utils.h2
-rw-r--r--modules/regex/regex.cpp6
-rw-r--r--platform/android/export/export.cpp3
-rw-r--r--platform/x11/os_x11.cpp64
-rw-r--r--scene/animation/skeleton_ik.cpp20
-rw-r--r--scene/animation/skeleton_ik.h2
-rw-r--r--scene/gui/file_dialog.cpp16
-rw-r--r--scene/gui/file_dialog.h1
-rw-r--r--scene/gui/line_edit.cpp5
-rw-r--r--scene/resources/tile_set.cpp8
43 files changed, 509 insertions, 216 deletions
diff --git a/core/object.cpp b/core/object.cpp
index e83abaece7..24a31930a0 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -1916,7 +1916,11 @@ void *Object::get_script_instance_binding(int p_script_language_index) {
//as it should not really affect performance much (won't be called too often), as in far most caes the condition below will be false afterwards
if (!_script_instance_bindings[p_script_language_index]) {
- _script_instance_bindings[p_script_language_index] = ScriptServer::get_language(p_script_language_index)->alloc_instance_binding_data(this);
+ void *script_data = ScriptServer::get_language(p_script_language_index)->alloc_instance_binding_data(this);
+ if (script_data) {
+ atomic_increment(&instance_binding_count);
+ _script_instance_bindings[p_script_language_index] = script_data;
+ }
}
return _script_instance_bindings[p_script_language_index];
@@ -1931,6 +1935,7 @@ Object::Object() {
_instance_ID = ObjectDB::add_instance(this);
_can_translate = true;
_is_queued_for_deletion = false;
+ instance_binding_count = 0;
memset(_script_instance_bindings, 0, sizeof(void *) * MAX_SCRIPT_INSTANCE_BINDINGS);
script_instance = NULL;
#ifdef TOOLS_ENABLED
diff --git a/core/object.h b/core/object.h
index d741371306..43e1cf4785 100644
--- a/core/object.h
+++ b/core/object.h
@@ -490,10 +490,12 @@ private:
void _set_indexed_bind(const NodePath &p_name, const Variant &p_value);
Variant _get_indexed_bind(const NodePath &p_name) const;
- void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
-
void property_list_changed_notify();
+ friend class Reference;
+ uint32_t instance_binding_count;
+ void *_script_instance_bindings[MAX_SCRIPT_INSTANCE_BINDINGS];
+
protected:
virtual void _initialize_classv() { initialize_class(); }
virtual bool _setv(const StringName &p_name, const Variant &p_property) { return false; };
diff --git a/core/reference.cpp b/core/reference.cpp
index c33a7c683c..6e1520d81d 100644
--- a/core/reference.cpp
+++ b/core/reference.cpp
@@ -66,8 +66,17 @@ int Reference::reference_get_count() const {
bool Reference::reference() {
bool success = refcount.ref();
- if (success && get_script_instance()) {
- get_script_instance()->refcount_incremented();
+ if (success && refcount.get() <= 2 /* higher is not relevant */) {
+ if (get_script_instance()) {
+ get_script_instance()->refcount_incremented();
+ }
+ if (instance_binding_count > 0) {
+ for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
+ if (_script_instance_bindings[i]) {
+ ScriptServer::get_language(i)->refcount_incremented_instance_binding(this);
+ }
+ }
+ }
}
return success;
@@ -77,9 +86,19 @@ bool Reference::unreference() {
bool die = refcount.unref();
- if (get_script_instance()) {
- bool script_ret = get_script_instance()->refcount_decremented();
- die = die && script_ret;
+ if (refcount.get() <= 1 /* higher is not relevant */) {
+ if (get_script_instance()) {
+ bool script_ret = get_script_instance()->refcount_decremented();
+ die = die && script_ret;
+ }
+ if (instance_binding_count > 0) {
+ for (int i = 0; i < MAX_SCRIPT_INSTANCE_BINDINGS; i++) {
+ if (_script_instance_bindings[i]) {
+ bool script_ret = ScriptServer::get_language(i)->refcount_decremented_instance_binding(this);
+ die = die && script_ret;
+ }
+ }
+ }
}
return die;
diff --git a/core/script_language.h b/core/script_language.h
index 71b705e960..573e7b4fa1 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -311,6 +311,8 @@ public:
virtual void *alloc_instance_binding_data(Object *p_object) { return NULL; } //optional, not used by all languages
virtual void free_instance_binding_data(void *p_data) {} //optional, not used by all languages
+ virtual void refcount_incremented_instance_binding(Object *p_object) {} //optional, not used by all languages
+ virtual bool refcount_decremented_instance_binding(Object *p_object) { return true; } //return true if it can die //optional, not used by all languages
virtual void frame();
diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp
index 689f1f462d..45d62e797f 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.cpp
+++ b/drivers/coreaudio/audio_driver_coreaudio.cpp
@@ -331,55 +331,57 @@ bool AudioDriverCoreAudio::try_lock() {
}
void AudioDriverCoreAudio::finish() {
- OSStatus result;
+ if (audio_unit) {
+ OSStatus result;
- lock();
+ lock();
- AURenderCallbackStruct callback;
- zeromem(&callback, sizeof(AURenderCallbackStruct));
- result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback));
- if (result != noErr) {
- ERR_PRINT("AudioUnitSetProperty failed");
- }
-
- if (active) {
- result = AudioOutputUnitStop(audio_unit);
+ AURenderCallbackStruct callback;
+ zeromem(&callback, sizeof(AURenderCallbackStruct));
+ result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback));
if (result != noErr) {
- ERR_PRINT("AudioOutputUnitStop failed");
+ ERR_PRINT("AudioUnitSetProperty failed");
}
- active = false;
- }
+ if (active) {
+ result = AudioOutputUnitStop(audio_unit);
+ if (result != noErr) {
+ ERR_PRINT("AudioOutputUnitStop failed");
+ }
- result = AudioUnitUninitialize(audio_unit);
- if (result != noErr) {
- ERR_PRINT("AudioUnitUninitialize failed");
- }
+ active = false;
+ }
+
+ result = AudioUnitUninitialize(audio_unit);
+ if (result != noErr) {
+ ERR_PRINT("AudioUnitUninitialize failed");
+ }
#ifdef OSX_ENABLED
- AudioObjectPropertyAddress prop;
- prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
- prop.mScope = kAudioObjectPropertyScopeGlobal;
- prop.mElement = kAudioObjectPropertyElementMaster;
+ AudioObjectPropertyAddress prop;
+ prop.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
+ prop.mScope = kAudioObjectPropertyScopeGlobal;
+ prop.mElement = kAudioObjectPropertyElementMaster;
- result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &prop, &output_device_address_cb, this);
- if (result != noErr) {
- ERR_PRINT("AudioObjectRemovePropertyListener failed");
- }
+ result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &prop, &output_device_address_cb, this);
+ if (result != noErr) {
+ ERR_PRINT("AudioObjectRemovePropertyListener failed");
+ }
#endif
- result = AudioComponentInstanceDispose(audio_unit);
- if (result != noErr) {
- ERR_PRINT("AudioComponentInstanceDispose failed");
- }
+ result = AudioComponentInstanceDispose(audio_unit);
+ if (result != noErr) {
+ ERR_PRINT("AudioComponentInstanceDispose failed");
+ }
- unlock();
+ unlock();
+ }
if (mutex) {
memdelete(mutex);
mutex = NULL;
}
-};
+}
Error AudioDriverCoreAudio::capture_start() {
@@ -576,6 +578,7 @@ String AudioDriverCoreAudio::capture_get_device() {
#endif
AudioDriverCoreAudio::AudioDriverCoreAudio() {
+ audio_unit = NULL;
active = false;
mutex = NULL;
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index eebdbe9493..88f14890ef 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1008,7 +1008,10 @@ RID RasterizerSceneGLES3::light_instance_create(RID p_light) {
light_instance->light = p_light;
light_instance->light_ptr = storage->light_owner.getornull(p_light);
- ERR_FAIL_COND_V(!light_instance->light_ptr, RID());
+ if (!light_instance->light_ptr) {
+ memdelete(light_instance);
+ ERR_FAIL_COND_V(!light_instance->light_ptr, RID());
+ }
light_instance->self = light_instance_owner.make_rid(light_instance);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 3697cccef4..0bb0e12b8e 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -6998,7 +6998,10 @@ RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) {
//printf("errnum: %x\n",status);
glBindFramebuffer(GL_FRAMEBUFFER, RasterizerStorageGLES3::system_fbo);
- ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID());
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ memdelete(cls);
+ ERR_FAIL_COND_V(status != GL_FRAMEBUFFER_COMPLETE, RID());
+ }
return canvas_light_shadow_owner.make_rid(cls);
}
diff --git a/editor/import/resource_importer_layered_texture.cpp b/editor/import/resource_importer_layered_texture.cpp
index 211bb7bcc9..db16f20ade 100644
--- a/editor/import/resource_importer_layered_texture.cpp
+++ b/editor/import/resource_importer_layered_texture.cpp
@@ -52,6 +52,7 @@ String ResourceImporterLayeredTexture::get_preset_name(int p_idx) const {
void ResourceImporterLayeredTexture::get_import_options(List<ImportOption> *r_options, int p_preset) const {
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Lossless,Video RAM,Uncompressed", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), p_preset == PRESET_3D ? 1 : 0));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "compress/no_bptc_if_rgb"), false));
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "flags/repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirrored"), 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "flags/filter"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "flags/mipmaps"), p_preset == PRESET_COLOR_CORRECT ? 0 : 1));
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index 27a16fd3dd..f282d391ff 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -429,7 +429,7 @@ bool SpatialMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) c
Ref<SpatialMaterial> mat = p_resource;
return mat.is_valid();
}
-Ref<Resource> SpatialMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) {
+Ref<Resource> SpatialMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) const {
Ref<SpatialMaterial> mat = p_resource;
ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>());
@@ -475,7 +475,7 @@ bool ParticlesMaterialConversionPlugin::handles(const Ref<Resource> &p_resource)
Ref<ParticlesMaterial> mat = p_resource;
return mat.is_valid();
}
-Ref<Resource> ParticlesMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) {
+Ref<Resource> ParticlesMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) const {
Ref<ParticlesMaterial> mat = p_resource;
ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>());
@@ -513,7 +513,7 @@ bool CanvasItemMaterialConversionPlugin::handles(const Ref<Resource> &p_resource
Ref<CanvasItemMaterial> mat = p_resource;
return mat.is_valid();
}
-Ref<Resource> CanvasItemMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) {
+Ref<Resource> CanvasItemMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) const {
Ref<CanvasItemMaterial> mat = p_resource;
ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>());
diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h
index 80a5c535b8..31a927d83f 100644
--- a/editor/plugins/material_editor_plugin.h
+++ b/editor/plugins/material_editor_plugin.h
@@ -109,7 +109,7 @@ class SpatialMaterialConversionPlugin : public EditorResourceConversionPlugin {
public:
virtual String converts_to() const;
virtual bool handles(const Ref<Resource> &p_resource) const;
- virtual Ref<Resource> convert(const Ref<Resource> &p_resource);
+ virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const;
};
class ParticlesMaterialConversionPlugin : public EditorResourceConversionPlugin {
@@ -117,7 +117,7 @@ class ParticlesMaterialConversionPlugin : public EditorResourceConversionPlugin
public:
virtual String converts_to() const;
virtual bool handles(const Ref<Resource> &p_resource) const;
- virtual Ref<Resource> convert(const Ref<Resource> &p_resource);
+ virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const;
};
class CanvasItemMaterialConversionPlugin : public EditorResourceConversionPlugin {
@@ -125,7 +125,7 @@ class CanvasItemMaterialConversionPlugin : public EditorResourceConversionPlugin
public:
virtual String converts_to() const;
virtual bool handles(const Ref<Resource> &p_resource) const;
- virtual Ref<Resource> convert(const Ref<Resource> &p_resource);
+ virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const;
};
#endif // MATERIAL_EDITOR_PLUGIN_H
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 1bb7c98114..fa034c97c0 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1692,7 +1692,6 @@ void ScriptEditor::_update_script_names() {
if (restoring_layout)
return;
- waiting_update_names = false;
Set<Ref<Script> > used;
Node *edited = EditorNode::get_singleton()->get_edited_scene();
if (edited) {
@@ -1816,8 +1815,12 @@ void ScriptEditor::_update_script_names() {
}
}
- _update_members_overview();
- _update_help_overview();
+ if (!waiting_update_names) {
+ _update_members_overview();
+ _update_help_overview();
+ } else {
+ waiting_update_names = false;
+ }
_update_members_overview_visibility();
_update_help_overview_visibility();
_update_script_colors();
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 4a9cbfe535..4390b94ece 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -356,8 +356,6 @@ void TextureRegionEditor::_region_input(const Ref<InputEvent> &p_input) {
undo_redo->add_do_method(atlas_tex.ptr(), "set_region", atlas_tex->get_region());
undo_redo->add_undo_method(atlas_tex.ptr(), "set_region", rect_prev);
} else if (node_ninepatch) {
- // FIXME: Is this intentional?
- } else if (node_ninepatch) {
undo_redo->add_do_method(node_ninepatch, "set_region_rect", node_ninepatch->get_region_rect());
undo_redo->add_undo_method(node_ninepatch, "set_region_rect", rect_prev);
} else if (obj_styleBox.is_valid()) {
@@ -521,6 +519,10 @@ void TextureRegionEditor::_set_snap_mode(int p_mode) {
else
hb_grid->hide();
+ if (snap_mode == SNAP_AUTOSLICE && is_visible() && autoslice_is_dirty) {
+ _update_autoslice();
+ }
+
edit_draw->update();
}
@@ -562,7 +564,8 @@ void TextureRegionEditor::_zoom_in() {
}
void TextureRegionEditor::_zoom_reset() {
- if (draw_zoom == 1) return;
+ if (draw_zoom == 1)
+ return;
draw_zoom = 1;
edit_draw->update();
}
@@ -585,25 +588,91 @@ void TextureRegionEditor::apply_rect(const Rect2 &rect) {
atlas_tex->set_region(rect);
}
-void TextureRegionEditor::_notification(int p_what) {
- switch (p_what) {
- case NOTIFICATION_PROCESS: {
- if (node_sprite) {
- if (node_sprite->is_region()) {
+void TextureRegionEditor::_update_autoslice() {
+ autoslice_is_dirty = false;
+ autoslice_cache.clear();
- set_process(false);
- EditorNode::get_singleton()->make_bottom_panel_item_visible(this);
+ Ref<Texture> texture = NULL;
+ if (node_sprite)
+ texture = node_sprite->get_texture();
+ else if (node_ninepatch)
+ texture = node_ninepatch->get_texture();
+ else if (obj_styleBox.is_valid())
+ texture = obj_styleBox->get_texture();
+ else if (atlas_tex.is_valid())
+ texture = atlas_tex->get_atlas();
+
+ if (texture.is_null()) {
+ return;
+ }
+
+ for (int y = 0; y < texture->get_height(); y++) {
+ for (int x = 0; x < texture->get_width(); x++) {
+ if (texture->is_pixel_opaque(x, y)) {
+ bool found = false;
+ for (List<Rect2>::Element *E = autoslice_cache.front(); E; E = E->next()) {
+ Rect2 grown = E->get().grow(1.5);
+ if (grown.has_point(Point2(x, y))) {
+ E->get().expand_to(Point2(x, y));
+ E->get().expand_to(Point2(x + 1, y + 1));
+ x = E->get().position.x + E->get().size.x - 1;
+ bool merged = true;
+ while (merged) {
+ merged = false;
+ bool queue_erase = false;
+ for (List<Rect2>::Element *F = autoslice_cache.front(); F; F = F->next()) {
+ if (queue_erase) {
+ autoslice_cache.erase(F->prev());
+ queue_erase = false;
+ }
+ if (F == E)
+ continue;
+ if (E->get().grow(1).intersects(F->get())) {
+ E->get().expand_to(F->get().position);
+ E->get().expand_to(F->get().position + F->get().size);
+ if (F->prev()) {
+ F = F->prev();
+ autoslice_cache.erase(F->next());
+ } else {
+ queue_erase = true;
+ // Can't delete the first rect in the list.
+ }
+ merged = true;
+ }
+ }
+ }
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ Rect2 new_rect(x, y, 1, 1);
+ autoslice_cache.push_back(new_rect);
}
- } else {
- set_process(false);
}
- } break;
- case NOTIFICATION_THEME_CHANGED:
+ }
+ }
+ cache_map[texture->get_rid()] = autoslice_cache;
+}
+
+void TextureRegionEditor::_notification(int p_what) {
+ switch (p_what) {
case NOTIFICATION_READY: {
zoom_out->set_icon(get_icon("ZoomLess", "EditorIcons"));
zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons"));
zoom_in->set_icon(get_icon("ZoomMore", "EditorIcons"));
} break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (snap_mode == SNAP_AUTOSLICE && is_visible() && autoslice_is_dirty) {
+ _update_autoslice();
+ }
+ } break;
+ case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
+ // This happens when the user leaves the Editor and returns,
+ // he/she could have changed the textures, so the cache is cleared
+ cache_map.clear();
+ _edit_region();
+ } break;
}
}
@@ -709,57 +778,15 @@ void TextureRegionEditor::_edit_region() {
return;
}
- autoslice_cache.clear();
- Ref<Image> i;
- i.instance();
- if (i->load(texture->get_path()) == OK) {
- BitMap bm;
- bm.create_from_image_alpha(i);
- for (int y = 0; y < i->get_height(); y++) {
- for (int x = 0; x < i->get_width(); x++) {
- if (bm.get_bit(Point2(x, y))) {
- bool found = false;
- for (List<Rect2>::Element *E = autoslice_cache.front(); E; E = E->next()) {
- Rect2 grown = E->get().grow(1.5);
- if (grown.has_point(Point2(x, y))) {
- E->get().expand_to(Point2(x, y));
- E->get().expand_to(Point2(x + 1, y + 1));
- x = E->get().position.x + E->get().size.x - 1;
- bool merged = true;
- while (merged) {
- merged = false;
- bool queue_erase = false;
- for (List<Rect2>::Element *F = autoslice_cache.front(); F; F = F->next()) {
- if (queue_erase) {
- autoslice_cache.erase(F->prev());
- queue_erase = false;
- }
- if (F == E)
- continue;
- if (E->get().grow(1).intersects(F->get())) {
- E->get().expand_to(F->get().position);
- E->get().expand_to(F->get().position + F->get().size);
- if (F->prev()) {
- F = F->prev();
- autoslice_cache.erase(F->next());
- } else {
- queue_erase = true;
- //Can't delete the first rect in the list.
- }
- merged = true;
- }
- }
- }
- found = true;
- break;
- }
- }
- if (!found) {
- Rect2 new_rect(x, y, 1, 1);
- autoslice_cache.push_back(new_rect);
- }
- }
- }
+ if (cache_map.has(texture->get_rid())) {
+ autoslice_cache = cache_map[texture->get_rid()];
+ autoslice_is_dirty = false;
+ return;
+ } else {
+ if (is_visible() && snap_mode == SNAP_AUTOSLICE) {
+ _update_autoslice();
+ } else {
+ autoslice_is_dirty = true;
}
}
diff --git a/editor/plugins/texture_region_editor_plugin.h b/editor/plugins/texture_region_editor_plugin.h
index 670cc86bbb..61ef769f89 100644
--- a/editor/plugins/texture_region_editor_plugin.h
+++ b/editor/plugins/texture_region_editor_plugin.h
@@ -92,7 +92,9 @@ class TextureRegionEditor : public Control {
Rect2 rect_prev;
float prev_margin;
int edited_margin;
+ Map<RID, List<Rect2> > cache_map;
List<Rect2> autoslice_cache;
+ bool autoslice_is_dirty;
bool drag;
bool creating;
@@ -110,6 +112,7 @@ class TextureRegionEditor : public Control {
void _zoom_reset();
void _zoom_out();
void apply_rect(const Rect2 &rect);
+ void _update_autoslice();
protected:
void _notification(int p_what);
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index 64638cdb1e..07b3c44807 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -1722,8 +1722,16 @@ void PhysicalBoneSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
return;
Skeleton *sk(physical_bone->find_skeleton_parent());
+ if (!sk)
+ return;
+
PhysicalBone *pb(sk->get_physical_bone(physical_bone->get_bone_id()));
+ if (!pb)
+ return;
+
PhysicalBone *pbp(sk->get_physical_bone_parent(physical_bone->get_bone_id()));
+ if (!pbp)
+ return;
Vector<Vector3> points;
diff --git a/modules/bullet/cone_twist_joint_bullet.cpp b/modules/bullet/cone_twist_joint_bullet.cpp
index 6b5438c60f..9346f2d336 100644
--- a/modules/bullet/cone_twist_joint_bullet.cpp
+++ b/modules/bullet/cone_twist_joint_bullet.cpp
@@ -82,8 +82,11 @@ void ConeTwistJointBullet::set_param(PhysicsServer::ConeTwistJointParam p_param,
case PhysicsServer::CONE_TWIST_JOINT_RELAXATION:
coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), coneConstraint->getLimitSoftness(), coneConstraint->getBiasFactor(), p_value);
break;
+#ifndef DISABLE_DEPRECATED
default:
- WARN_PRINT("This parameter is not supported by Bullet engine");
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED
+#endif // DISABLE_DEPRECATED
}
}
@@ -99,8 +102,11 @@ real_t ConeTwistJointBullet::get_param(PhysicsServer::ConeTwistJointParam p_para
return coneConstraint->getLimitSoftness();
case PhysicsServer::CONE_TWIST_JOINT_RELAXATION:
return coneConstraint->getRelaxationFactor();
+#ifndef DISABLE_DEPRECATED
default:
- WARN_PRINT("This parameter is not supported by Bullet engine");
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED;
return 0;
+#endif // DISABLE_DEPRECATED
}
}
diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp
index 6275a0d2ed..123b5d717e 100644
--- a/modules/bullet/generic_6dof_joint_bullet.cpp
+++ b/modules/bullet/generic_6dof_joint_bullet.cpp
@@ -152,8 +152,11 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO
case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT:
sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce = p_value;
break;
+#ifndef DISABLE_DEPRECATED
default:
- WARN_PRINT("This parameter is not supported");
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED
+#endif // DISABLE_DEPRECATED
}
}
@@ -180,9 +183,12 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6
return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity;
case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT:
return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce;
+#ifndef DISABLE_DEPRECATED
default:
- WARN_PRINT("This parameter is not supported");
- return 0.;
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED;
+ return 0;
+#endif // DISABLE_DEPRECATED
}
}
@@ -212,9 +218,11 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF
case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR:
sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] = flags[p_axis][p_flag];
break;
+#ifndef DISABLE_DEPRECATED
default:
- WARN_PRINT("This flag is not supported by Bullet engine");
- return;
+ ERR_EXPLAIN("This flag " + itos(p_flag) + " is deprecated");
+ WARN_DEPRECATED
+#endif // DISABLE_DEPRECATED
}
}
diff --git a/modules/bullet/hinge_joint_bullet.cpp b/modules/bullet/hinge_joint_bullet.cpp
index 07fde6efb9..bfdc5aafc1 100644
--- a/modules/bullet/hinge_joint_bullet.cpp
+++ b/modules/bullet/hinge_joint_bullet.cpp
@@ -95,11 +95,6 @@ real_t HingeJointBullet::get_hinge_angle() {
void HingeJointBullet::set_param(PhysicsServer::HingeJointParam p_param, real_t p_value) {
switch (p_param) {
- case PhysicsServer::HINGE_JOINT_BIAS:
- if (0 < p_value) {
- WARN_PRINTS("HingeJoint doesn't support bias in the Bullet backend, so it's always 0.");
- }
- break;
case PhysicsServer::HINGE_JOINT_LIMIT_UPPER:
hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), p_value, hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor());
break;
@@ -121,8 +116,11 @@ void HingeJointBullet::set_param(PhysicsServer::HingeJointParam p_param, real_t
case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE:
hingeConstraint->setMaxMotorImpulse(p_value);
break;
+#ifndef DISABLE_DEPRECATED
default:
- WARN_PRINTS("HingeJoint doesn't support this parameter in the Bullet backend: " + itos(p_param) + ", value: " + itos(p_value));
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED
+#endif // DISABLE_DEPRECATED
}
}
@@ -145,9 +143,12 @@ real_t HingeJointBullet::get_param(PhysicsServer::HingeJointParam p_param) const
return hingeConstraint->getMotorTargetVelocity();
case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE:
return hingeConstraint->getMaxMotorImpulse();
+#ifndef DISABLE_DEPRECATED
default:
- WARN_PRINTS("HingeJoint doesn't support this parameter in the Bullet backend: " + itos(p_param));
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED;
return 0;
+#endif // DISABLE_DEPRECATED
}
}
diff --git a/modules/bullet/pin_joint_bullet.cpp b/modules/bullet/pin_joint_bullet.cpp
index c4e5b8cdbe..63e22d7dab 100644
--- a/modules/bullet/pin_joint_bullet.cpp
+++ b/modules/bullet/pin_joint_bullet.cpp
@@ -84,9 +84,11 @@ real_t PinJointBullet::get_param(PhysicsServer::PinJointParam p_param) const {
return p2pConstraint->m_setting.m_damping;
case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP:
return p2pConstraint->m_setting.m_impulseClamp;
+#ifndef DISABLE_DEPRECATED
default:
- WARN_PRINTS("This get parameter is not supported");
- return 0;
+ ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated");
+ WARN_DEPRECATED
+#endif // DISABLE_DEPRECATED
}
}
diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp
index b5329bc347..4a11bec5af 100644
--- a/modules/bullet/space_bullet.cpp
+++ b/modules/bullet/space_bullet.cpp
@@ -178,7 +178,9 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf
space->dynamicsWorld->convexSweepTest(bt_convex_shape, bt_xform_from, bt_xform_to, btResult, 0.002);
if (btResult.hasHit()) {
- p_closest_safe = p_closest_unsafe = btResult.m_closestHitFraction;
+ const btScalar l = bt_motion.length();
+ p_closest_unsafe = btResult.m_closestHitFraction;
+ p_closest_safe = MAX(p_closest_unsafe - (1 - ((l - 0.01) / l)), 0);
if (r_info) {
if (btCollisionObject::CO_RIGID_BODY == btResult.m_hitCollisionObject->getInternalType()) {
B_TO_G(static_cast<const btRigidBody *>(btResult.m_hitCollisionObject)->getVelocityInLocalPoint(btResult.m_hitPointWorld), r_info->linear_velocity);
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index e05bc7d591..33d9c011f2 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -126,7 +126,10 @@ GDScriptInstance *GDScript::_create_instance(const Variant **p_args, int p_argco
GDScriptLanguage::singleton->lock->unlock();
#endif
- ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing
+ if (r_error.error != Variant::CallError::CALL_OK) {
+ memdelete(instance);
+ ERR_FAIL_COND_V(r_error.error != Variant::CallError::CALL_OK, NULL); //error constructing
+ }
}
//@TODO make thread safe
@@ -719,22 +722,36 @@ Error GDScript::load_byte_code(const String &p_path) {
FileAccess *fa = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V(!fa, ERR_CANT_OPEN);
+
FileAccessEncrypted *fae = memnew(FileAccessEncrypted);
ERR_FAIL_COND_V(!fae, ERR_CANT_OPEN);
+
Vector<uint8_t> key;
key.resize(32);
for (int i = 0; i < key.size(); i++) {
key.write[i] = script_encryption_key[i];
}
+
Error err = fae->open_and_parse(fa, key, FileAccessEncrypted::MODE_READ);
- ERR_FAIL_COND_V(err, err);
+
+ if (err) {
+ fa->close();
+ memdelete(fa);
+ memdelete(fae);
+
+ ERR_FAIL_COND_V(err, err);
+ }
+
bytecode.resize(fae->get_len());
fae->get_buffer(bytecode.ptrw(), bytecode.size());
+ fae->close();
memdelete(fae);
+
} else {
bytecode = FileAccess::get_file_as_array(p_path);
}
+
ERR_FAIL_COND_V(bytecode.size() == 0, ERR_PARSE_ERROR);
path = p_path;
@@ -2097,7 +2114,7 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_ori
Error err = script->load_byte_code(p_path);
if (err != OK) {
-
+ memdelete(script);
ERR_FAIL_COND_V(err != OK, RES());
}
@@ -2105,7 +2122,7 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_ori
Error err = script->load_source_code(p_path);
if (err != OK) {
-
+ memdelete(script);
ERR_FAIL_COND_V(err != OK, RES());
}
@@ -2120,6 +2137,7 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path, const String &p_ori
return scriptres;
}
+
void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_extensions) const {
p_extensions->push_back("gd");
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 1403184557..3b494dbae7 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -1322,6 +1322,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
int ret = _parse_expression(codegen, op, p_stack_level);
if (ret < 0) {
+ memdelete(id);
+ memdelete(op);
return ERR_PARSE_ERROR;
}
@@ -1341,6 +1343,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
// compile the condition
int ret = _parse_expression(codegen, branch.compiled_pattern, p_stack_level);
if (ret < 0) {
+ memdelete(id);
+ memdelete(op);
return ERR_PARSE_ERROR;
}
@@ -1353,6 +1357,8 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
Error err = _parse_block(codegen, branch.body, p_stack_level, p_break_addr, continue_addr);
if (err) {
+ memdelete(id);
+ memdelete(op);
return ERR_PARSE_ERROR;
}
@@ -1364,6 +1370,9 @@ Error GDScriptCompiler::_parse_block(CodeGen &codegen, const GDScriptParser::Blo
codegen.opcodes.write[break_addr + 1] = codegen.opcodes.size();
+ memdelete(id);
+ memdelete(op);
+
} break;
case GDScriptParser::ControlFlowNode::CF_IF: {
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index b8b77924f7..d2a861dbe8 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -1013,6 +1013,69 @@ void CSharpLanguage::free_instance_binding_data(void *p_data) {
#endif
}
+void CSharpLanguage::refcount_incremented_instance_binding(Object *p_object) {
+
+ Reference *ref_owner = Object::cast_to<Reference>(p_object);
+
+#ifdef DEBUG_ENABLED
+ CRASH_COND(!ref_owner);
+#endif
+
+ void *data = p_object->get_script_instance_binding(get_language_index());
+ if (!data)
+ return;
+ Ref<MonoGCHandle> &gchandle = ((Map<Object *, Ref<MonoGCHandle> >::Element *)data)->get();
+
+ if (ref_owner->reference_get_count() > 1 && gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ // The reference count was increased after the managed side was the only one referencing our owner.
+ // This means the owner is being referenced again by the unmanaged side,
+ // so the owner must hold the managed side alive again to avoid it from being GCed.
+
+ MonoObject *target = gchandle->get_target();
+ if (!target)
+ return; // Called after the managed side was collected, so nothing to do here
+
+ // Release the current weak handle and replace it with a strong handle.
+ uint32_t strong_gchandle = MonoGCHandle::make_strong_handle(target);
+ gchandle->release();
+ gchandle->set_handle(strong_gchandle, MonoGCHandle::STRONG_HANDLE);
+ }
+}
+
+bool CSharpLanguage::refcount_decremented_instance_binding(Object *p_object) {
+
+ Reference *ref_owner = Object::cast_to<Reference>(p_object);
+
+#ifdef DEBUG_ENABLED
+ CRASH_COND(!ref_owner);
+#endif
+
+ int refcount = ref_owner->reference_get_count();
+
+ void *data = p_object->get_script_instance_binding(get_language_index());
+ if (!data)
+ return refcount == 0;
+ Ref<MonoGCHandle> &gchandle = ((Map<Object *, Ref<MonoGCHandle> >::Element *)data)->get();
+
+ if (refcount == 1 && !gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
+ // If owner owner is no longer referenced by the unmanaged side,
+ // the managed instance takes responsibility of deleting the owner when GCed.
+
+ MonoObject *target = gchandle->get_target();
+ if (!target)
+ return refcount == 0; // Called after the managed side was collected, so nothing to do here
+
+ // Release the current strong handle and replace it with a weak handle.
+ uint32_t weak_gchandle = MonoGCHandle::make_weak_handle(target);
+ gchandle->release();
+ gchandle->set_handle(weak_gchandle, MonoGCHandle::WEAK_HANDLE);
+
+ return false;
+ }
+
+ return refcount == 0;
+}
+
CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpScript *p_script, const Ref<MonoGCHandle> &p_gchandle) {
CSharpInstance *instance = memnew(CSharpInstance);
@@ -1303,11 +1366,13 @@ void CSharpInstance::mono_object_disposed() {
void CSharpInstance::refcount_incremented() {
+#ifdef DEBUG_ENABLED
CRASH_COND(!base_ref);
+#endif
Reference *ref_owner = Object::cast_to<Reference>(owner);
- if (ref_owner->reference_get_count() > 1) { // The managed side also holds a reference, hence 1 instead of 0
+ if (ref_owner->reference_get_count() > 1 && gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
// The reference count was increased after the managed side was the only one referencing our owner.
// This means the owner is being referenced again by the unmanaged side,
// so the owner must hold the managed side alive again to avoid it from being GCed.
@@ -1315,26 +1380,28 @@ void CSharpInstance::refcount_incremented() {
// Release the current weak handle and replace it with a strong handle.
uint32_t strong_gchandle = MonoGCHandle::make_strong_handle(gchandle->get_target());
gchandle->release();
- gchandle->set_handle(strong_gchandle);
+ gchandle->set_handle(strong_gchandle, MonoGCHandle::STRONG_HANDLE);
}
}
bool CSharpInstance::refcount_decremented() {
+#ifdef DEBUG_ENABLED
CRASH_COND(!base_ref);
+#endif
Reference *ref_owner = Object::cast_to<Reference>(owner);
int refcount = ref_owner->reference_get_count();
- if (refcount == 1) { // The managed side also holds a reference, hence 1 instead of 0
+ if (refcount == 1 && !gchandle->is_weak()) { // The managed side also holds a reference, hence 1 instead of 0
// If owner owner is no longer referenced by the unmanaged side,
// the managed instance takes responsibility of deleting the owner when GCed.
// Release the current strong handle and replace it with a weak handle.
uint32_t weak_gchandle = MonoGCHandle::make_weak_handle(gchandle->get_target());
gchandle->release();
- gchandle->set_handle(weak_gchandle);
+ gchandle->set_handle(weak_gchandle, MonoGCHandle::WEAK_HANDLE);
return false;
}
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 53644eafae..1a5d0c8a69 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -346,6 +346,8 @@ public:
// Don't use these. I'm watching you
virtual void *alloc_instance_binding_data(Object *p_object);
virtual void free_instance_binding_data(void *p_data);
+ virtual void refcount_incremented_instance_binding(Object *p_object);
+ virtual bool refcount_decremented_instance_binding(Object *p_object);
#ifdef DEBUG_ENABLED
Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace);
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index b97bb5e95f..4185f3407d 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -533,7 +533,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
cs_icalls_content.push_back("using System;\n"
"using System.Runtime.CompilerServices;\n"
- "using System.Collections.Generic;\n"
+ "using " BINDINGS_NAMESPACE_COLLECTIONS ";\n"
"\n");
cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK);
@@ -638,7 +638,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
cs_icalls_content.push_back("using System;\n"
"using System.Runtime.CompilerServices;\n"
- "using System.Collections.Generic;\n"
+ "using " BINDINGS_NAMESPACE_COLLECTIONS ";\n"
"\n");
cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS_EDITOR "\n" INDENT1 OPEN_BLOCK);
@@ -713,7 +713,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.push_back("using System;\n"); // IntPtr
if (itype.requires_collections)
- output.push_back("using System.Collections.Generic;\n"); // Dictionary
+ output.push_back("using " BINDINGS_NAMESPACE_COLLECTIONS ";\n"); // Dictionary
output.push_back("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
@@ -1922,7 +1922,7 @@ void BindingsGenerator::_populate_object_type_interfaces() {
imethod.return_type.cname = Variant::get_type_name(return_info.type);
}
- if (!itype.requires_collections && imethod.return_type.cname == name_cache.type_Dictionary)
+ if (!itype.requires_collections && imethod.return_type.cname == name_cache.type_Dictionary || imethod.return_type.cname == name_cache.type_Array)
itype.requires_collections = true;
for (int i = 0; i < argc; i++) {
@@ -1946,7 +1946,7 @@ void BindingsGenerator::_populate_object_type_interfaces() {
iarg.name = escape_csharp_keyword(snake_to_camel_case(iarg.name));
- if (!itype.requires_collections && iarg.type.cname == name_cache.type_Dictionary)
+ if (!itype.requires_collections && iarg.type.cname == name_cache.type_Dictionary || imethod.return_type.cname == name_cache.type_Array)
itype.requires_collections = true;
if (m && m->has_default_argument(i)) {
@@ -2371,14 +2371,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype = TypeInterface();
itype.name = "Array";
itype.cname = itype.name;
- itype.proxy_name = "Array";
+ itype.proxy_name = "Collections.Array";
itype.c_out = "\treturn memnew(Array(%1));\n";
itype.c_type = itype.name;
itype.c_type_in = itype.c_type + "*";
itype.c_type_out = itype.c_type + "*";
itype.cs_type = itype.proxy_name;
itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()";
- itype.cs_out = "return new Array(%0);";
+ itype.cs_out = "return new Collections.Array(%0);";
itype.im_type_in = "IntPtr";
itype.im_type_out = "IntPtr";
builtin_types.insert(itype.cname, itype);
@@ -2387,14 +2387,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype = TypeInterface();
itype.name = "Dictionary";
itype.cname = itype.name;
- itype.proxy_name = "Dictionary";
+ itype.proxy_name = "Collections.Dictionary";
itype.c_out = "\treturn memnew(Dictionary(%1));\n";
itype.c_type = itype.name;
itype.c_type_in = itype.c_type + "*";
itype.c_type_out = itype.c_type + "*";
itype.cs_type = itype.proxy_name;
itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()";
- itype.cs_out = "return new Dictionary(%0);";
+ itype.cs_out = "return new Collections.Dictionary(%0);";
itype.im_type_in = "IntPtr";
itype.im_type_out = "IntPtr";
builtin_types.insert(itype.cname, itype);
@@ -2441,7 +2441,7 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::
else
iarg.type.cname = Variant::get_type_name(pi.type);
- if (!r_itype.requires_collections && iarg.type.cname == name_cache.type_Dictionary)
+ if (!r_itype.requires_collections && iarg.type.cname == name_cache.type_Dictionary || imethod.return_type.cname == name_cache.type_Array)
r_itype.requires_collections = true;
if ((mi.default_arguments.size() - mi.arguments.size() + i) >= 0)
@@ -2457,7 +2457,7 @@ void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::
imethod.return_type.cname = Variant::get_type_name(mi.return_val.type);
}
- if (!r_itype.requires_collections && imethod.return_type.cname == name_cache.type_Dictionary)
+ if (!r_itype.requires_collections && imethod.return_type.cname == name_cache.type_Dictionary || imethod.return_type.cname == name_cache.type_Array)
r_itype.requires_collections = true;
if (r_itype.class_doc) {
diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp
index 148bb32398..bb218b49b7 100644
--- a/modules/mono/glue/collections_glue.cpp
+++ b/modules/mono/glue/collections_glue.cpp
@@ -209,32 +209,32 @@ bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoOb
}
void godot_register_collections_icalls() {
- mono_add_internal_call("Godot.Array::godot_icall_Array_Ctor", (void *)godot_icall_Array_Ctor);
- mono_add_internal_call("Godot.Array::godot_icall_Array_Dtor", (void *)godot_icall_Array_Dtor);
- mono_add_internal_call("Godot.Array::godot_icall_Array_At", (void *)godot_icall_Array_At);
- mono_add_internal_call("Godot.Array::godot_icall_Array_SetAt", (void *)godot_icall_Array_SetAt);
- mono_add_internal_call("Godot.Array::godot_icall_Array_Count", (void *)godot_icall_Array_Count);
- mono_add_internal_call("Godot.Array::godot_icall_Array_Add", (void *)godot_icall_Array_Add);
- mono_add_internal_call("Godot.Array::godot_icall_Array_Clear", (void *)godot_icall_Array_Clear);
- mono_add_internal_call("Godot.Array::godot_icall_Array_Contains", (void *)godot_icall_Array_Contains);
- mono_add_internal_call("Godot.Array::godot_icall_Array_CopyTo", (void *)godot_icall_Array_CopyTo);
- mono_add_internal_call("Godot.Array::godot_icall_Array_IndexOf", (void *)godot_icall_Array_IndexOf);
- mono_add_internal_call("Godot.Array::godot_icall_Array_Insert", (void *)godot_icall_Array_Insert);
- mono_add_internal_call("Godot.Array::godot_icall_Array_Remove", (void *)godot_icall_Array_Remove);
- mono_add_internal_call("Godot.Array::godot_icall_Array_RemoveAt", (void *)godot_icall_Array_RemoveAt);
-
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Ctor", (void *)godot_icall_Dictionary_Ctor);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Dtor", (void *)godot_icall_Dictionary_Dtor);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_GetValue", (void *)godot_icall_Dictionary_GetValue);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_SetValue", (void *)godot_icall_Dictionary_SetValue);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Keys", (void *)godot_icall_Dictionary_Keys);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Values", (void *)godot_icall_Dictionary_Values);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Count", (void *)godot_icall_Dictionary_Count);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Add", (void *)godot_icall_Dictionary_Add);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Clear", (void *)godot_icall_Dictionary_Clear);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Contains", (void *)godot_icall_Dictionary_Contains);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_ContainsKey", (void *)godot_icall_Dictionary_ContainsKey);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_RemoveKey", (void *)godot_icall_Dictionary_RemoveKey);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Remove", (void *)godot_icall_Dictionary_Remove);
- mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_TryGetValue", (void *)godot_icall_Dictionary_TryGetValue);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor", (void *)godot_icall_Array_Ctor);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Dtor", (void *)godot_icall_Array_Dtor);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_At", (void *)godot_icall_Array_At);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_SetAt", (void *)godot_icall_Array_SetAt);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Count", (void *)godot_icall_Array_Count);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Add", (void *)godot_icall_Array_Add);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Clear", (void *)godot_icall_Array_Clear);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Contains", (void *)godot_icall_Array_Contains);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_CopyTo", (void *)godot_icall_Array_CopyTo);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_IndexOf", (void *)godot_icall_Array_IndexOf);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Insert", (void *)godot_icall_Array_Insert);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Remove", (void *)godot_icall_Array_Remove);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_RemoveAt", (void *)godot_icall_Array_RemoveAt);
+
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Ctor", (void *)godot_icall_Dictionary_Ctor);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Dtor", (void *)godot_icall_Dictionary_Dtor);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue", (void *)godot_icall_Dictionary_GetValue);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_SetValue", (void *)godot_icall_Dictionary_SetValue);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Keys", (void *)godot_icall_Dictionary_Keys);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Values", (void *)godot_icall_Dictionary_Values);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Count", (void *)godot_icall_Dictionary_Count);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Add", (void *)godot_icall_Dictionary_Add);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Clear", (void *)godot_icall_Dictionary_Clear);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Contains", (void *)godot_icall_Dictionary_Contains);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ContainsKey", (void *)godot_icall_Dictionary_ContainsKey);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_RemoveKey", (void *)godot_icall_Dictionary_RemoveKey);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Remove", (void *)godot_icall_Dictionary_Remove);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue", (void *)godot_icall_Dictionary_TryGetValue);
}
diff --git a/modules/mono/glue/cs_files/Array.cs b/modules/mono/glue/cs_files/Array.cs
index 1ec4d7d20a..2f0185b1e3 100644
--- a/modules/mono/glue/cs_files/Array.cs
+++ b/modules/mono/glue/cs_files/Array.cs
@@ -4,7 +4,7 @@ using System.Collections;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-namespace Godot
+namespace Godot.Collections
{
class ArraySafeHandle : SafeHandle
{
diff --git a/modules/mono/glue/cs_files/Dictionary.cs b/modules/mono/glue/cs_files/Dictionary.cs
index 30d17c2a59..64cb9f935d 100644
--- a/modules/mono/glue/cs_files/Dictionary.cs
+++ b/modules/mono/glue/cs_files/Dictionary.cs
@@ -4,7 +4,7 @@ using System.Collections;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-namespace Godot
+namespace Godot.Collections
{
class DictionarySafeHandle : SafeHandle
{
diff --git a/modules/mono/glue/cs_files/MarshalUtils.cs b/modules/mono/glue/cs_files/MarshalUtils.cs
index 6ad4b3dcb2..f7699a15bf 100644
--- a/modules/mono/glue/cs_files/MarshalUtils.cs
+++ b/modules/mono/glue/cs_files/MarshalUtils.cs
@@ -1,4 +1,5 @@
using System;
+using Godot.Collections;
namespace Godot
{
diff --git a/modules/mono/godotsharp_defs.h b/modules/mono/godotsharp_defs.h
index f604464e8f..39d608de9f 100644
--- a/modules/mono/godotsharp_defs.h
+++ b/modules/mono/godotsharp_defs.h
@@ -32,6 +32,7 @@
#define GODOTSHARP_DEFS_H
#define BINDINGS_NAMESPACE "Godot"
+#define BINDINGS_NAMESPACE_COLLECTIONS BINDINGS_NAMESPACE ".Collections"
#define BINDINGS_GLOBAL_SCOPE_CLASS "GD"
#define BINDINGS_PTR_FIELD "ptr"
#define BINDINGS_NATIVE_NAME_FIELD "nativeName"
diff --git a/modules/mono/mono_gc_handle.cpp b/modules/mono/mono_gc_handle.cpp
index 12109045e0..9f0e933a8c 100644
--- a/modules/mono/mono_gc_handle.cpp
+++ b/modules/mono/mono_gc_handle.cpp
@@ -44,12 +44,12 @@ uint32_t MonoGCHandle::make_weak_handle(MonoObject *p_object) {
Ref<MonoGCHandle> MonoGCHandle::create_strong(MonoObject *p_object) {
- return memnew(MonoGCHandle(make_strong_handle(p_object)));
+ return memnew(MonoGCHandle(make_strong_handle(p_object), STRONG_HANDLE));
}
Ref<MonoGCHandle> MonoGCHandle::create_weak(MonoObject *p_object) {
- return memnew(MonoGCHandle(make_weak_handle(p_object)));
+ return memnew(MonoGCHandle(make_weak_handle(p_object), WEAK_HANDLE));
}
void MonoGCHandle::release() {
@@ -64,9 +64,10 @@ void MonoGCHandle::release() {
}
}
-MonoGCHandle::MonoGCHandle(uint32_t p_handle) {
+MonoGCHandle::MonoGCHandle(uint32_t p_handle, HandleType p_handle_type) {
released = false;
+ weak = p_handle_type == WEAK_HANDLE;
handle = p_handle;
}
diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h
index 9cb3ef0fbb..7eeaba30e0 100644
--- a/modules/mono/mono_gc_handle.h
+++ b/modules/mono/mono_gc_handle.h
@@ -40,24 +40,33 @@ class MonoGCHandle : public Reference {
GDCLASS(MonoGCHandle, Reference)
bool released;
+ bool weak;
uint32_t handle;
public:
+ enum HandleType {
+ STRONG_HANDLE,
+ WEAK_HANDLE
+ };
+
static uint32_t make_strong_handle(MonoObject *p_object);
static uint32_t make_weak_handle(MonoObject *p_object);
static Ref<MonoGCHandle> create_strong(MonoObject *p_object);
static Ref<MonoGCHandle> create_weak(MonoObject *p_object);
+ _FORCE_INLINE_ bool is_weak() { return weak; }
+
_FORCE_INLINE_ MonoObject *get_target() const { return released ? NULL : mono_gchandle_get_target(handle); }
- _FORCE_INLINE_ void set_handle(uint32_t p_handle) {
- handle = p_handle;
+ _FORCE_INLINE_ void set_handle(uint32_t p_handle, HandleType p_handle_type) {
released = false;
+ weak = p_handle_type == WEAK_HANDLE;
+ handle = p_handle;
}
void release();
- MonoGCHandle(uint32_t p_handle);
+ MonoGCHandle(uint32_t p_handle, HandleType p_handle_type);
~MonoGCHandle();
};
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index bebc3b863f..c1f56bc3d2 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -156,6 +156,7 @@ void MonoCache::cleanup() {
}
#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class))
+#define GODOT_API_NS_CLAS(m_ns, m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(m_ns, #m_class))
void update_corlib_cache() {
@@ -206,8 +207,8 @@ void update_godot_api_cache() {
CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control));
CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial));
CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef));
- CACHE_CLASS_AND_CHECK(Array, GODOT_API_CLASS(Array));
- CACHE_CLASS_AND_CHECK(Dictionary, GODOT_API_CLASS(Dictionary));
+ CACHE_CLASS_AND_CHECK(Array, GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Array));
+ CACHE_CLASS_AND_CHECK(Dictionary, GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary));
CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils));
#ifdef DEBUG_ENABLED
@@ -234,8 +235,8 @@ void update_godot_api_cache() {
CACHE_FIELD_AND_CHECK(NodePath, ptr, CACHED_CLASS(NodePath)->get_field(BINDINGS_PTR_FIELD));
CACHE_FIELD_AND_CHECK(RID, ptr, CACHED_CLASS(RID)->get_field(BINDINGS_PTR_FIELD));
- CACHE_METHOD_THUNK_AND_CHECK(Array, GetPtr, (Array_GetPtr)GODOT_API_CLASS(Array)->get_method_thunk("GetPtr", 0));
- CACHE_METHOD_THUNK_AND_CHECK(Dictionary, GetPtr, (Dictionary_GetPtr)GODOT_API_CLASS(Dictionary)->get_method_thunk("GetPtr", 0));
+ CACHE_METHOD_THUNK_AND_CHECK(Array, GetPtr, (Array_GetPtr)GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Array)->get_method_thunk("GetPtr", 0));
+ CACHE_METHOD_THUNK_AND_CHECK(Dictionary, GetPtr, (Dictionary_GetPtr)GODOT_API_NS_CLAS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary)->get_method_thunk("GetPtr", 0));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IsArrayGenericType, (IsArrayGenericType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IsArrayGenericType", 1));
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IsDictionaryGenericType, (IsDictionaryGenericType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("IsDictionaryGenericType", 1));
CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, (SignalAwaiter_SignalCallback)GODOT_API_CLASS(SignalAwaiter)->get_method_thunk("SignalCallback", 1));
diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp
index 54720652fa..add1e506ea 100644
--- a/modules/mono/signal_awaiter_utils.cpp
+++ b/modules/mono/signal_awaiter_utils.cpp
@@ -42,8 +42,7 @@ Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p
ERR_FAIL_NULL_V(p_source, ERR_INVALID_DATA);
ERR_FAIL_NULL_V(p_target, ERR_INVALID_DATA);
- uint32_t awaiter_handle = MonoGCHandle::make_strong_handle(p_awaiter);
- Ref<SignalAwaiterHandle> sa_con = memnew(SignalAwaiterHandle(awaiter_handle));
+ Ref<SignalAwaiterHandle> sa_con = memnew(SignalAwaiterHandle(p_awaiter));
#ifdef DEBUG_ENABLED
sa_con->set_connection_target(p_target);
#endif
@@ -119,8 +118,8 @@ void SignalAwaiterHandle::_bind_methods() {
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &SignalAwaiterHandle::_signal_callback, MethodInfo("_signal_callback"));
}
-SignalAwaiterHandle::SignalAwaiterHandle(uint32_t p_managed_handle) :
- MonoGCHandle(p_managed_handle) {
+SignalAwaiterHandle::SignalAwaiterHandle(MonoObject *p_managed) :
+ MonoGCHandle(MonoGCHandle::make_strong_handle(p_managed), STRONG_HANDLE) {
#ifdef DEBUG_ENABLED
conn_target_id = 0;
diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h
index a6a205ff8d..1920432709 100644
--- a/modules/mono/signal_awaiter_utils.h
+++ b/modules/mono/signal_awaiter_utils.h
@@ -64,7 +64,7 @@ public:
}
#endif
- SignalAwaiterHandle(uint32_t p_managed_handle);
+ SignalAwaiterHandle(MonoObject *p_managed);
~SignalAwaiterHandle();
};
diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp
index 733f32277b..bdd3e31eb8 100644
--- a/modules/regex/regex.cpp
+++ b/modules/regex/regex.cpp
@@ -205,6 +205,8 @@ Error RegEx::compile(const String &p_pattern) {
code = pcre2_compile_16(p, pattern.length(), flags, &err, &offset, cctx);
+ pcre2_compile_context_free_16(cctx);
+
if (!code) {
PCRE2_UCHAR16 buf[256];
pcre2_get_error_message_16(err, buf, 256);
@@ -221,6 +223,8 @@ Error RegEx::compile(const String &p_pattern) {
code = pcre2_compile_32(p, pattern.length(), flags, &err, &offset, cctx);
+ pcre2_compile_context_free_32(cctx);
+
if (!code) {
PCRE2_UCHAR32 buf[256];
pcre2_get_error_message_32(err, buf, 256);
@@ -285,6 +289,8 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end)
if (res < 0) {
pcre2_match_data_free_32(match);
+ pcre2_match_context_free_32(mctx);
+
return NULL;
}
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index b76b0d5dbe..5c8d9e078f 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -1591,8 +1591,11 @@ public:
String apkfname = "main." + itos(version_code) + "." + get_package_name(package_name) + ".obb";
String fullpath = p_path.get_base_dir().plus_file(apkfname);
err = save_pack(p_preset, fullpath);
+
if (err != OK) {
+ unzClose(pkg);
EditorNode::add_io_error("Could not write expansion package file: " + apkfname);
+
return OK;
}
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 56b0c975c4..ca9fd68412 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -2564,14 +2564,68 @@ void OS_X11::swap_buffers() {
}
void OS_X11::alert(const String &p_alert, const String &p_title) {
+ const char *message_programs[] = { "zenity", "kdialog", "Xdialog", "xmessage" };
+
+ String path = get_environment("PATH");
+ Vector<String> path_elems = path.split(":", false);
+ String program;
+
+ for (int i = 0; i < path_elems.size(); i++) {
+ for (unsigned int k = 0; k < sizeof(message_programs) / sizeof(char *); k++) {
+ String tested_path = path_elems[i] + "/" + message_programs[k];
+
+ if (FileAccess::exists(tested_path)) {
+ program = tested_path;
+ break;
+ }
+ }
+
+ if (program.length())
+ break;
+ }
List<String> args;
- args.push_back("-center");
- args.push_back("-title");
- args.push_back(p_title);
- args.push_back(p_alert);
- execute("xmessage", args, true);
+ if (program.ends_with("zenity")) {
+ args.push_back("--error");
+ args.push_back("--width");
+ args.push_back("500");
+ args.push_back("--title");
+ args.push_back(p_title);
+ args.push_back("--text");
+ args.push_back(p_alert);
+ }
+
+ if (program.ends_with("kdialog")) {
+ args.push_back("--error");
+ args.push_back(p_alert);
+ args.push_back("--title");
+ args.push_back(p_title);
+ }
+
+ if (program.ends_with("Xdialog")) {
+ args.push_back("--title");
+ args.push_back(p_title);
+ args.push_back("--msgbox");
+ args.push_back(p_alert);
+ args.push_back("0");
+ args.push_back("0");
+ }
+
+ if (program.ends_with("xmessage")) {
+ args.push_back("-center");
+ args.push_back("-title");
+ args.push_back(p_title);
+ args.push_back(p_alert);
+ }
+
+ if (program.length()) {
+ execute(program, args, true);
+ } else {
+ print_line(p_alert);
+ }
+
+ return;
}
void OS_X11::set_icon(const Ref<Image> &p_icon) {
diff --git a/scene/animation/skeleton_ik.cpp b/scene/animation/skeleton_ik.cpp
index 9b1cb1369a..69975e6195 100644
--- a/scene/animation/skeleton_ik.cpp
+++ b/scene/animation/skeleton_ik.cpp
@@ -54,9 +54,9 @@ FabrikInverseKinematic::ChainItem *FabrikInverseKinematic::ChainItem::add_child(
}
/// Build a chain that starts from the root to tip
-void FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain) {
+bool FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain) {
- ERR_FAIL_COND(-1 == p_task->root_bone);
+ ERR_FAIL_COND_V(-1 == p_task->root_bone, false);
Chain &chain(p_task->chain);
@@ -77,8 +77,8 @@ void FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
for (int x = p_task->end_effectors.size() - 1; 0 <= x; --x) {
const EndEffector *ee(&p_task->end_effectors[x]);
- ERR_FAIL_COND(p_task->root_bone >= ee->tip_bone);
- ERR_FAIL_INDEX(ee->tip_bone, p_task->skeleton->get_bone_count());
+ ERR_FAIL_COND_V(p_task->root_bone >= ee->tip_bone, false);
+ ERR_FAIL_INDEX_V(ee->tip_bone, p_task->skeleton->get_bone_count(), false);
sub_chain_size = 0;
// Picks all IDs that composing a single chain in reverse order (except the root)
@@ -133,6 +133,7 @@ void FabrikInverseKinematic::build_chain(Task *p_task, bool p_force_simple_chain
break;
}
}
+ return true;
}
void FabrikInverseKinematic::update_chain(const Skeleton *p_sk, ChainItem *p_chain_item) {
@@ -247,7 +248,10 @@ FabrikInverseKinematic::Task *FabrikInverseKinematic::create_simple_task(Skeleto
task->end_effectors.push_back(ee);
task->goal_global_transform = goal_transform;
- build_chain(task);
+ if (!build_chain(task)) {
+ free_task(task);
+ return NULL;
+ }
return task;
}
@@ -535,8 +539,10 @@ void SkeletonIK::reload_chain() {
return;
task = FabrikInverseKinematic::create_simple_task(skeleton, skeleton->find_bone(root_bone), skeleton->find_bone(tip_bone), _get_target_transform());
- task->max_iterations = max_iterations;
- task->min_distance = min_distance;
+ if (task) {
+ task->max_iterations = max_iterations;
+ task->min_distance = min_distance;
+ }
}
void SkeletonIK::reload_goal() {
diff --git a/scene/animation/skeleton_ik.h b/scene/animation/skeleton_ik.h
index 08fb00e798..202d6959bb 100644
--- a/scene/animation/skeleton_ik.h
+++ b/scene/animation/skeleton_ik.h
@@ -123,7 +123,7 @@ public:
private:
/// Init a chain that starts from the root to tip
- static void build_chain(Task *p_task, bool p_force_simple_chain = true);
+ static bool build_chain(Task *p_task, bool p_force_simple_chain = true);
static void update_chain(const Skeleton *p_sk, ChainItem *p_chain_item);
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 635f812805..9bddaa7d29 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -284,7 +284,13 @@ bool FileDialog::_is_open_should_be_disabled() {
if (mode == MODE_OPEN_ANY || mode == MODE_SAVE_FILE)
return false;
- TreeItem *ti = tree->get_selected();
+ TreeItem *ti = tree->get_next_selected(tree->get_root());
+ while (ti) {
+ TreeItem *prev_ti = ti;
+ ti = tree->get_next_selected(tree->get_root());
+ if (ti == prev_ti)
+ break;
+ }
// We have something that we can't select?
if (!ti)
return mode != MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder.
@@ -328,6 +334,10 @@ void FileDialog::deselect_items() {
}
}
+void FileDialog::_tree_multi_selected(Object *p_object, int p_cell, bool p_selected) {
+ _tree_selected();
+}
+
void FileDialog::_tree_selected() {
TreeItem *ti = tree->get_selected();
@@ -754,6 +764,7 @@ void FileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("_unhandled_input"), &FileDialog::_unhandled_input);
+ ClassDB::bind_method(D_METHOD("_tree_multi_selected"), &FileDialog::_tree_multi_selected);
ClassDB::bind_method(D_METHOD("_tree_selected"), &FileDialog::_tree_selected);
ClassDB::bind_method(D_METHOD("_tree_item_activated"), &FileDialog::_tree_item_activated);
ClassDB::bind_method(D_METHOD("_dir_entered"), &FileDialog::_dir_entered);
@@ -794,7 +805,7 @@ void FileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("invalidate"), &FileDialog::invalidate);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_overrides_title"), "set_mode_overrides_title", "is_mode_overriding_title");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open one,Open many,Open folder,Open any,Save"), "set_mode", "get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Open Any,Save"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access");
ADD_PROPERTY(PropertyInfo(Variant::POOL_STRING_ARRAY, "filters"), "set_filters", "get_filters");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files");
@@ -890,6 +901,7 @@ FileDialog::FileDialog() {
_update_drives();
connect("confirmed", this, "_action_pressed");
+ tree->connect("multi_selected", this, "_tree_multi_selected", varray(), CONNECT_DEFERRED);
tree->connect("cell_selected", this, "_tree_selected", varray(), CONNECT_DEFERRED);
tree->connect("item_activated", this, "_tree_item_activated", varray());
tree->connect("nothing_selected", this, "deselect_items");
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index ad483d5dab..3227f1c3a8 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -104,6 +104,7 @@ private:
void update_file_list();
void update_filters();
+ void _tree_multi_selected(Object *p_object, int p_cell, bool p_selected);
void _tree_selected();
void _select_drive(int p_idx);
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 549daecdae..1f3d5e6e13 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -866,15 +866,14 @@ void LineEdit::_notification(int p_what) {
void LineEdit::copy_text() {
- if (selection.enabled) {
-
+ if (selection.enabled && !pass) {
OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin));
}
}
void LineEdit::cut_text() {
- if (selection.enabled) {
+ if (selection.enabled && !pass) {
OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin));
selection_delete();
}
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 3d2b6c36de..c85f672ebf 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -59,7 +59,13 @@ bool TileSet::_set(const StringName &p_name, const Variant &p_value) {
tile_set_region(id, p_value);
else if (what == "tile_mode")
tile_set_tile_mode(id, (TileMode)((int)p_value));
- else if (what.left(9) == "autotile/") {
+ else if (what == "is_autotile") {
+ // backward compatibility for Godot 3.0.x
+ // autotile used to be a bool, it's now an enum
+ bool is_autotile = p_value;
+ if (is_autotile)
+ tile_set_tile_mode(id, AUTO_TILE);
+ } else if (what.left(9) == "autotile/") {
what = what.right(9);
if (what == "bitmask_mode")
autotile_set_bitmask_mode(id, (BitmaskMode)((int)p_value));