summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/io/resource_loader.cpp3
-rw-r--r--core/os/file_access.cpp2
-rw-r--r--core/os/os.cpp7
-rw-r--r--core/os/os.h9
-rw-r--r--core/reference.cpp3
-rw-r--r--core/script_debugger_remote.cpp2
-rw-r--r--doc/base/classes.xml4
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp2
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp21
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp22
-rw-r--r--editor/property_editor.cpp3
-rw-r--r--modules/gdnative/godot/gdnative.cpp5
-rw-r--r--modules/gdnative/godot/gdnative.h4
-rw-r--r--modules/gdscript/gd_parser.cpp3
-rw-r--r--modules/nativescript/nativescript.cpp214
-rw-r--r--modules/nativescript/nativescript.h31
-rw-r--r--modules/nativescript/register_types.cpp29
-rw-r--r--platform/iphone/export/export.cpp14
-rw-r--r--platform/iphone/os_iphone.cpp7
-rw-r--r--scene/3d/mesh_instance.cpp6
-rw-r--r--scene/3d/mesh_instance.h2
-rw-r--r--scene/gui/texture_button.cpp2
-rw-r--r--servers/visual_server.cpp2
23 files changed, 330 insertions, 67 deletions
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 285cc6e3c2..9b89fa3399 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -430,6 +430,9 @@ void ResourceLoader::reload_translation_remaps() {
void ResourceLoader::load_translation_remaps() {
+ if (!ProjectSettings::get_singleton()->has("locale/translation_remaps"))
+ return;
+
Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps");
List<Variant> keys;
remaps.get_key_list(&keys);
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index 2bb676381f..7f5a84843c 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -300,6 +300,8 @@ Vector<String> FileAccess::get_csv_line(String delim) const {
String l;
int qc = 0;
do {
+ ERR_FAIL_COND_V(eof_reached(), Vector<String>());
+
l += get_line() + "\n";
qc = 0;
for (int i = 0; i < l.length(); i++) {
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 5a9766891d..8e4c357195 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -512,7 +512,13 @@ bool OS::check_feature_support(const String &p_feature) {
return false;
}
+void *OS::get_stack_bottom() const {
+ return _stack_bottom;
+}
+
OS::OS() {
+ void *volatile stack_bottom;
+
last_error = NULL;
singleton = this;
_keep_screen_on = true; // set default value to true, because this had been true before godot 2.0.
@@ -525,6 +531,7 @@ OS::OS() {
_render_thread_mode = RENDER_THREAD_SAFE;
_allow_hidpi = true;
+ _stack_bottom = (void *)(&stack_bottom);
}
OS::~OS() {
diff --git a/core/os/os.h b/core/os/os.h
index 362fec8a9e..957c1d0ba7 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -60,6 +60,8 @@ class OS {
char *last_error;
+ void *_stack_bottom;
+
public:
enum RenderThreadMode {
@@ -411,6 +413,13 @@ public:
bool check_feature_support(const String &p_feature);
+ /**
+ * Returns the stack bottom of the main thread of the application.
+ * This may be of use when integrating languages with garbage collectors that
+ * need to check whether a pointer is on the stack.
+ */
+ virtual void *get_stack_bottom() const;
+
bool is_hidpi_allowed() const { return _allow_hidpi; }
OS();
virtual ~OS();
diff --git a/core/reference.cpp b/core/reference.cpp
index c55f8a7fe3..060608eacb 100644
--- a/core/reference.cpp
+++ b/core/reference.cpp
@@ -74,7 +74,8 @@ bool Reference::unreference() {
bool die = refcount.unref();
if (get_script_instance()) {
- die = die && get_script_instance()->refcount_decremented();
+ bool script_ret = get_script_instance()->refcount_decremented();
+ die = die && script_ret;
}
return die;
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index a7b6f25590..dec41e7976 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -74,7 +74,7 @@ Error ScriptDebuggerRemote::connect_to_host(const String &p_host, uint16_t p_por
} else {
OS::get_singleton()->delay_usec(1000000);
- print_line("Remote Debugger: Connection failed with status: " + String::num(tcp_client->get_status()) + "'', retrying in 1 sec.");
+ print_line("Remote Debugger: Connection failed with status: '" + String::num(tcp_client->get_status()) + "', retrying in 1 sec.");
};
};
diff --git a/doc/base/classes.xml b/doc/base/classes.xml
index 2075f30b36..4b2f3336cd 100644
--- a/doc/base/classes.xml
+++ b/doc/base/classes.xml
@@ -14062,7 +14062,7 @@
<description>
Add a custom type, which will appear in the list of nodes or resources. An icon can be optionally passed.
When given node or resource is selected, the base type will be instanced (ie, "Spatial", "Control", "Resource"), then the script will be loaded and set to this object.
- You can use the [method EditorPlugin.handles] to check if your custom object is being edited by checking the script or using 'extends' keyword.
+ You can use the [method EditorPlugin.handles] to check if your custom object is being edited by checking the script or using 'is' keyword.
During run-time, this will be a simple object with a script so this function does not need to be called then.
</description>
</method>
@@ -24770,7 +24770,7 @@
<description>
</description>
</method>
- <method name="create_debug_tagents">
+ <method name="create_debug_tangents">
<description>
</description>
</method>
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 4eb44197a7..2a9f078d8c 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -6915,7 +6915,7 @@ void RasterizerStorageGLES3::initialize() {
config.use_anisotropic_filter = config.extensions.has("GL_EXT_texture_filter_anisotropic");
if (config.use_anisotropic_filter) {
glGetFloatv(_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &config.anisotropic_level);
- config.anisotropic_level = MIN(int(ProjectSettings::get_singleton()->get("rendering/quality/anisotropic_filter_level")), config.anisotropic_level);
+ config.anisotropic_level = MIN(int(ProjectSettings::get_singleton()->get("rendering/quality/filters/anisotropic_filter_level")), config.anisotropic_level);
}
frame.clear_request = false;
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 4c4cd88dfb..a809a68c23 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -176,7 +176,6 @@ void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) {
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Node2D *n2d = E->get()->cast_to<Node2D>();
-
if (n2d && n2d->edit_has_pivot()) {
Vector2 offset = n2d->edit_get_pivot();
@@ -1736,11 +1735,9 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
}
Ref<InputEventKey> k = p_event;
-
if (k.is_valid()) {
-
if (k->is_pressed() && drag == DRAG_NONE) {
-
+ // Move the object with the arrow keys
KeyMoveMODE move_mode = MOVE_VIEW_BASE;
if (k->get_alt()) move_mode = MOVE_LOCAL_BASE;
if (k->get_control() || k->get_metakey()) move_mode = MOVE_LOCAL_WITH_ROT;
@@ -1773,13 +1770,23 @@ void CanvasItemEditor::_viewport_draw() {
RID ci = viewport->get_canvas_item();
if (snap_show_grid) {
+ //Draw the grid
Size2 s = viewport->get_size();
int last_cell;
Transform2D xform = transform.affine_inverse();
+ Vector2 grid_offset;
+ if (snap_relative && snap_grid && get_item_count() > 0) {
+ Vector2 topleft = _find_topleftmost_point();
+ grid_offset.x = fmod(topleft.x, snap_step.x);
+ grid_offset.y = fmod(topleft.y, snap_step.y);
+ } else {
+ grid_offset = snap_offset;
+ }
+
if (snap_step.x != 0) {
for (int i = 0; i < s.width; i++) {
- int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - snap_offset.x) / snap_step.x));
+ int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - grid_offset.x) / snap_step.x));
if (i == 0)
last_cell = cell;
if (last_cell != cell)
@@ -1790,7 +1797,7 @@ void CanvasItemEditor::_viewport_draw() {
if (snap_step.y != 0) {
for (int i = 0; i < s.height; i++) {
- int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - snap_offset.y) / snap_step.y));
+ int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - grid_offset.y) / snap_step.y));
if (i == 0)
last_cell = cell;
if (last_cell != cell)
@@ -2383,6 +2390,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
snap_grid = !snap_grid;
int idx = edit_menu->get_popup()->get_item_index(SNAP_USE);
edit_menu->get_popup()->set_item_checked(idx, snap_grid);
+ viewport->update();
} break;
case SNAP_SHOW_GRID: {
snap_show_grid = !snap_show_grid;
@@ -2399,6 +2407,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
snap_relative = !snap_relative;
int idx = edit_menu->get_popup()->get_item_index(SNAP_RELATIVE);
edit_menu->get_popup()->set_item_checked(idx, snap_relative);
+ viewport->update();
} break;
case SNAP_USE_PIXEL: {
snap_pixel = !snap_pixel;
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index ef7ed5f7f6..c31e11cc38 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -1563,13 +1563,13 @@ void SpatialEditorViewport::_update_freelook(real_t delta) {
Vector3 right = camera->get_transform().basis.xform(Vector3(1, 0, 0));
Vector3 up = camera->get_transform().basis.xform(Vector3(0, 1, 0));
- int key_left = ED_SHORTCUT("spatial_editor/freelook_left", TTR("Freelook Left"), KEY_A)->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
- int key_right = ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), KEY_D)->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
- int key_forward = ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), KEY_W)->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
- int key_backwards = ED_SHORTCUT("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), KEY_S)->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
- int key_up = ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_Q)->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
- int key_down = ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_E)->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
- int key_speed_modifier = ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), KEY_SHIFT)->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
+ int key_left = ED_GET_SHORTCUT("spatial_editor/freelook_left")->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
+ int key_right = ED_GET_SHORTCUT("spatial_editor/freelook_right")->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
+ int key_forward = ED_GET_SHORTCUT("spatial_editor/freelook_forward")->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
+ int key_backwards = ED_GET_SHORTCUT("spatial_editor/freelook_backwards")->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
+ int key_up = ED_GET_SHORTCUT("spatial_editor/freelook_up")->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
+ int key_down = ED_GET_SHORTCUT("spatial_editor/freelook_down")->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
+ int key_speed_modifier = ED_GET_SHORTCUT("spatial_editor/freelook_speed_modifier")->get_shortcut()->cast_to<InputEventKey>()->get_scancode();
Vector3 velocity;
bool pressed = false;
@@ -2424,6 +2424,14 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_selection_with_view"), VIEW_ALIGN_SELECTION_WITH_VIEW);
view_menu->get_popup()->connect("id_pressed", this, "_menu_option");
+ ED_SHORTCUT("spatial_editor/freelook_left", TTR("Freelook Left"), KEY_A);
+ ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), KEY_D);
+ ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), KEY_W);
+ ED_SHORTCUT("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), KEY_S);
+ ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_Q);
+ ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_E);
+ ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), KEY_SHIFT);
+
preview_camera = memnew(Button);
preview_camera->set_toggle_mode(true);
preview_camera->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, 90);
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index c2af2445cc..71afa8ac79 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -2199,6 +2199,7 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String &p
case Variant::BOOL: {
p_item->set_checked(1, obj->get(p_name));
+ p_item->set_text(1, obj->get(p_name) ? TTR("On") : TTR("Off"));
} break;
case Variant::REAL:
case Variant::INT: {
@@ -3141,7 +3142,7 @@ void PropertyEditor::update_tree() {
case Variant::BOOL: {
item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK);
- item->set_text(1, TTR("On"));
+ item->set_text(1, obj->get(p.name) ? TTR("On") : TTR("Off"));
item->set_tooltip(1, obj->get(p.name) ? "True" : "False");
item->set_checked(1, obj->get(p.name));
if (show_type_icons)
diff --git a/modules/gdnative/godot/gdnative.cpp b/modules/gdnative/godot/gdnative.cpp
index 7b94b75a52..29b499ebab 100644
--- a/modules/gdnative/godot/gdnative.cpp
+++ b/modules/gdnative/godot/gdnative.cpp
@@ -33,6 +33,7 @@
#include "error_macros.h"
#include "gdnative.h"
#include "global_constants.h"
+#include "os/os.h"
#include "project_settings.h"
#include "variant.h"
@@ -89,6 +90,10 @@ godot_object GDAPI *godot_global_get_singleton(char *p_name) {
return (godot_object *)ProjectSettings::get_singleton()->get_singleton_object(String(p_name));
} // result shouldn't be freed
+void GDAPI *godot_get_stack_bottom() {
+ return OS::get_singleton()->get_stack_bottom();
+}
+
// MethodBind API
godot_method_bind GDAPI *godot_method_bind_get_method(const char *p_classname, const char *p_methodname) {
diff --git a/modules/gdnative/godot/gdnative.h b/modules/gdnative/godot/gdnative.h
index 4b79706b52..510bf36cd4 100644
--- a/modules/gdnative/godot/gdnative.h
+++ b/modules/gdnative/godot/gdnative.h
@@ -245,6 +245,10 @@ void GDAPI godot_object_destroy(godot_object *p_o);
godot_object GDAPI *godot_global_get_singleton(char *p_name); // result shouldn't be freed
+////// OS API
+
+void GDAPI *godot_get_stack_bottom(); // returns stack bottom of the main thread
+
////// MethodBind API
typedef struct {
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index ba0413a5a9..36aa249398 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -314,9 +314,10 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
path += String(tokenizer->get_token_literal());
tokenizer->advance();
need_identifier = false;
+ } else {
+ done = true;
}
- done = true;
break;
}
}
diff --git a/modules/nativescript/nativescript.cpp b/modules/nativescript/nativescript.cpp
index fd83b74727..271f5bde1c 100644
--- a/modules/nativescript/nativescript.cpp
+++ b/modules/nativescript/nativescript.cpp
@@ -40,6 +40,10 @@
#include "scene/main/scene_tree.h"
#include "scene/resources/scene_format_text.h"
+#ifndef NO_THREADS
+#include "os/thread.h"
+#endif
+
#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED)
#include "api_generator.h"
#endif
@@ -106,42 +110,16 @@ void NativeScript::set_library(Ref<GDNativeLibrary> p_library) {
return;
}
library = p_library;
-
- // See if this library was "registered" already.
-
lib_path = library->get_active_library_path();
- Map<String, Ref<GDNative> >::Element *E = NSL->library_gdnatives.find(lib_path);
-
- if (!E) {
- Ref<GDNative> gdn;
- gdn.instance();
- gdn->set_library(library);
-
- // TODO(karroffel): check the return value?
- gdn->initialize();
-
- NSL->library_gdnatives.insert(lib_path, gdn);
-
- NSL->library_classes.insert(lib_path, Map<StringName, NativeScriptDesc>());
- if (!NSL->library_script_users.has(lib_path))
- NSL->library_script_users.insert(lib_path, Set<NativeScript *>());
-
- NSL->library_script_users[lib_path].insert(this);
-
- void *args[1] = {
- (void *)&lib_path
- };
-
- // here the library registers all the classes and stuff.
- gdn->call_native_raw(NSL->_init_call_type,
- NSL->_init_call_name,
- NULL,
- 1,
- args,
- NULL);
- } else {
- // already initialized. Nice.
+#ifndef NO_THREADS
+ if (Thread::get_caller_ID() != Thread::get_main_ID()) {
+ NSL->defer_init_library(p_library, this);
+ } else
+#endif
+ {
+ NSL->init_library(p_library);
+ NSL->register_script(this);
}
}
@@ -445,7 +423,7 @@ NativeScript::NativeScript() {
// TODO(karroffel): implement this
NativeScript::~NativeScript() {
- NSL->library_script_users[lib_path].erase(this);
+ NSL->unregister_script(this);
}
////// ScriptInstance stuff
@@ -650,6 +628,28 @@ void NativeScriptInstance::notification(int p_notification) {
call_multilevel("_notification", args, 1);
}
+void NativeScriptInstance::refcount_incremented() {
+ Variant::CallError err;
+ call("_refcount_incremented", NULL, 0, err);
+ if (err.error != Variant::CallError::CALL_OK && err.error != Variant::CallError::CALL_ERROR_INVALID_METHOD) {
+ ERR_PRINT("Failed to invoke _refcount_incremented - should not happen");
+ }
+}
+
+bool NativeScriptInstance::refcount_decremented() {
+ Variant::CallError err;
+ Variant ret = call("_refcount_decremented", NULL, 0, err);
+ if (err.error != Variant::CallError::CALL_OK && err.error != Variant::CallError::CALL_ERROR_INVALID_METHOD) {
+ ERR_PRINT("Failed to invoke _refcount_decremented - should not happen");
+ return true; // assume we can destroy the object
+ }
+ if (err.error == Variant::CallError::CALL_ERROR_INVALID_METHOD) {
+ // the method does not exist, default is true
+ return true;
+ }
+ return ret;
+}
+
Ref<Script> NativeScriptInstance::get_script() const {
return script;
}
@@ -798,6 +798,9 @@ void NativeScriptLanguage::_unload_stuff() {
NativeScriptLanguage::NativeScriptLanguage() {
NativeScriptLanguage::singleton = this;
+#ifndef NO_THREADS
+ mutex = Mutex::create();
+#endif
}
// TODO(karroffel): implement this
@@ -811,6 +814,10 @@ NativeScriptLanguage::~NativeScriptLanguage() {
NSL->library_gdnatives.clear();
NSL->library_script_users.clear();
}
+
+#ifndef NO_THREADS
+ memdelete(mutex);
+#endif
}
String NativeScriptLanguage::get_name() const {
@@ -948,6 +955,134 @@ int NativeScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, in
return -1;
}
+#ifndef NO_THREADS
+void NativeScriptLanguage::defer_init_library(Ref<GDNativeLibrary> lib, NativeScript *script) {
+ MutexLock lock(mutex);
+ libs_to_init.insert(lib);
+ scripts_to_register.insert(script);
+ has_objects_to_register = true;
+}
+#endif
+
+void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) {
+#ifndef NO_THREADS
+ MutexLock lock(mutex);
+#endif
+ // See if this library was "registered" already.
+ const String &lib_path = lib->get_active_library_path();
+ Map<String, Ref<GDNative> >::Element *E = library_gdnatives.find(lib_path);
+
+ if (!E) {
+ Ref<GDNative> gdn;
+ gdn.instance();
+ gdn->set_library(lib);
+
+ // TODO(karroffel): check the return value?
+ gdn->initialize();
+
+ library_gdnatives.insert(lib_path, gdn);
+
+ library_classes.insert(lib_path, Map<StringName, NativeScriptDesc>());
+
+ if (!library_script_users.has(lib_path))
+ library_script_users.insert(lib_path, Set<NativeScript *>());
+
+ void *args[1] = {
+ (void *)&lib_path
+ };
+
+ // here the library registers all the classes and stuff.
+ gdn->call_native_raw(_init_call_type,
+ _init_call_name,
+ NULL,
+ 1,
+ args,
+ NULL);
+ } else {
+ // already initialized. Nice.
+ }
+}
+
+void NativeScriptLanguage::register_script(NativeScript *script) {
+#ifndef NO_THREADS
+ MutexLock lock(mutex);
+#endif
+ library_script_users[script->lib_path].insert(script);
+}
+
+void NativeScriptLanguage::unregister_script(NativeScript *script) {
+#ifndef NO_THREADS
+ MutexLock lock(mutex);
+#endif
+ Map<String, Set<NativeScript *> >::Element *S = library_script_users.find(script->lib_path);
+ if (S) {
+ S->get().erase(script);
+ if (S->get().size() == 0) {
+ library_script_users.erase(S);
+ }
+ }
+#ifndef NO_THREADS
+ scripts_to_register.erase(script);
+#endif
+}
+
+#ifndef NO_THREADS
+
+void NativeScriptLanguage::frame() {
+ if (has_objects_to_register) {
+ MutexLock lock(mutex);
+ for (Set<Ref<GDNativeLibrary> >::Element *L = libs_to_init.front(); L; L = L->next()) {
+ init_library(L->get());
+ }
+ libs_to_init.clear();
+ for (Set<NativeScript *>::Element *S = scripts_to_register.front(); S; S = S->next()) {
+ register_script(S->get());
+ }
+ scripts_to_register.clear();
+ has_objects_to_register = false;
+ }
+}
+
+void NativeScriptLanguage::thread_enter() {
+ Vector<Ref<GDNative> > libs;
+ {
+ MutexLock lock(mutex);
+ for (Map<String, Ref<GDNative> >::Element *L = library_gdnatives.front(); L; L = L->next()) {
+ libs.push_back(L->get());
+ }
+ }
+ for (int i = 0; i < libs.size(); ++i) {
+ libs[i]->call_native_raw(
+ _thread_cb_call_type,
+ _thread_enter_call_name,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ }
+}
+
+void NativeScriptLanguage::thread_exit() {
+ Vector<Ref<GDNative> > libs;
+ {
+ MutexLock lock(mutex);
+ for (Map<String, Ref<GDNative> >::Element *L = library_gdnatives.front(); L; L = L->next()) {
+ libs.push_back(L->get());
+ }
+ }
+ for (int i = 0; i < libs.size(); ++i) {
+ libs[i]->call_native_raw(
+ _thread_cb_call_type,
+ _thread_exit_call_name,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ }
+}
+
+#endif // NO_THREADS
+
void NativeReloadNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_notification"), &NativeReloadNode::_notification);
}
@@ -960,7 +1095,9 @@ void NativeReloadNode::_notification(int p_what) {
if (unloaded)
break;
-
+#ifndef NO_THREADS
+ MutexLock lock(NSL->mutex);
+#endif
NSL->_unload_stuff();
for (Map<String, Ref<GDNative> >::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) {
@@ -976,9 +1113,10 @@ void NativeReloadNode::_notification(int p_what) {
if (!unloaded)
break;
-
+#ifndef NO_THREADS
+ MutexLock lock(NSL->mutex);
+#endif
Set<StringName> libs_to_remove;
-
for (Map<String, Ref<GDNative> >::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) {
if (!L->get()->initialize()) {
diff --git a/modules/nativescript/nativescript.h b/modules/nativescript/nativescript.h
index bc7a6e3ed6..05e2d361d3 100644
--- a/modules/nativescript/nativescript.h
+++ b/modules/nativescript/nativescript.h
@@ -41,6 +41,10 @@
#include "godot_nativescript.h"
#include "modules/gdnative/gdnative.h"
+#ifndef NO_THREADS
+#include "os/mutex.h"
+#endif
+
struct NativeScriptDesc {
struct Method {
@@ -181,6 +185,9 @@ public:
virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount);
+ virtual void refcount_incremented();
+ virtual bool refcount_decremented();
+
~NativeScriptInstance();
};
@@ -197,6 +204,19 @@ private:
void _unload_stuff();
+#ifndef NO_THREADS
+ Mutex *mutex;
+
+ Set<Ref<GDNativeLibrary> > libs_to_init;
+ Set<NativeScript *> scripts_to_register;
+ volatile bool has_objects_to_register; // so that we don't lock mutex every frame - it's rarely needed
+ void defer_init_library(Ref<GDNativeLibrary> lib, NativeScript *script);
+#endif
+
+ void init_library(const Ref<GDNativeLibrary> &lib);
+ void register_script(NativeScript *script);
+ void unregister_script(NativeScript *script);
+
public:
Map<String, Map<StringName, NativeScriptDesc> > library_classes;
Map<String, Ref<GDNative> > library_gdnatives;
@@ -206,6 +226,10 @@ public:
const StringName _init_call_type = "nativescript_init";
const StringName _init_call_name = "godot_nativescript_init";
+ const StringName _thread_cb_call_type = "godot_nativescript_thread_cb";
+ const StringName _thread_enter_call_name = "godot_nativescript_thread_enter";
+ const StringName _thread_exit_call_name = "godot_nativescript_thread_exit";
+
NativeScriptLanguage();
~NativeScriptLanguage();
@@ -215,6 +239,13 @@ public:
void _hacky_api_anchor();
+#ifndef NO_THREADS
+ virtual void thread_enter();
+ virtual void thread_exit();
+
+ virtual void frame();
+#endif
+
virtual String get_name() const;
virtual void init();
virtual String get_type() const;
diff --git a/modules/nativescript/register_types.cpp b/modules/nativescript/register_types.cpp
index 6c88b04a56..a8a931343b 100644
--- a/modules/nativescript/register_types.cpp
+++ b/modules/nativescript/register_types.cpp
@@ -61,6 +61,32 @@ void init_call_cb(void *p_handle, godot_string *p_proc_name, void *p_data, int p
fn(args[0]);
}
+#ifndef NO_THREADS
+
+typedef void (*native_script_empty_callback)();
+
+void thread_call_cb(void *p_handle, godot_string *p_proc_name, void *p_data, int p_num_args, void **args, void *r_ret) {
+ if (p_handle == NULL) {
+ ERR_PRINT("No valid library handle, can't call nativescript thread enter/exit callback");
+ return;
+ }
+
+ void *library_proc;
+ Error err = OS::get_singleton()->get_dynamic_library_symbol_handle(
+ p_handle,
+ *(String *)p_proc_name,
+ library_proc);
+ if (err != OK) {
+ // it's fine if thread callbacks are not present in the library.
+ return;
+ }
+
+ native_script_empty_callback fn = (native_script_empty_callback)library_proc;
+ fn();
+}
+
+#endif // NO_THREADS
+
ResourceFormatLoaderNativeScript *resource_loader_gdns = NULL;
ResourceFormatSaverNativeScript *resource_saver_gdns = NULL;
@@ -72,6 +98,9 @@ void register_nativescript_types() {
ScriptServer::register_language(native_script_language);
GDNativeCallRegistry::singleton->register_native_raw_call_type(native_script_language->_init_call_type, init_call_cb);
+#ifndef NO_THREADS
+ GDNativeCallRegistry::singleton->register_native_raw_call_type(native_script_language->_thread_cb_call_type, thread_call_cb);
+#endif
resource_saver_gdns = memnew(ResourceFormatSaverNativeScript);
ResourceSaver::add_resource_format_saver(resource_saver_gdns);
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index a5efae8678..6ae2a0692d 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -80,7 +80,15 @@ public:
void EditorExportPlatformIOS::get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) {
- // what does this need to do?
+ if (p_preset->get("texture_format/s3tc")) {
+ r_features->push_back("s3tc");
+ }
+ if (p_preset->get("texture_format/etc")) {
+ r_features->push_back("etc");
+ }
+ if (p_preset->get("texture_format/etc2")) {
+ r_features->push_back("etc2");
+ }
}
void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) {
@@ -98,6 +106,10 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/bits_mode", PROPERTY_HINT_ENUM, "Fat (32 & 64 bits),64 bits,32 bits"), 1));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), true));
+
/* probably need some more info */
}
diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp
index 1329c94198..cb5c022764 100644
--- a/platform/iphone/os_iphone.cpp
+++ b/platform/iphone/os_iphone.cpp
@@ -109,7 +109,6 @@ void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
- RasterizerStorageGLES3::system_fbo = gl_view_base_fb;
visual_server = memnew(VisualServerRaster());
/*
@@ -122,6 +121,9 @@ void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_
visual_server->init();
visual_server->cursor_set_visible(false, 0);
+ // reset this to what it should be, it will have been set to 0 after visual_server->init() is called
+ RasterizerStorageGLES3::system_fbo = gl_view_base_fb;
+
audio_driver = memnew(AudioDriverIphone);
audio_driver->set_singleton();
audio_driver->init();
@@ -434,7 +436,8 @@ bool OSIPhone::can_draw() const {
int OSIPhone::set_base_framebuffer(int p_fb) {
- RasterizerStorageGLES3::system_fbo = gl_view_base_fb;
+ // gl_view_base_fb has not been updated yet
+ RasterizerStorageGLES3::system_fbo = p_fb;
return 0;
};
diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp
index 558932ceb9..51237c0bc3 100644
--- a/scene/3d/mesh_instance.cpp
+++ b/scene/3d/mesh_instance.cpp
@@ -275,7 +275,7 @@ void MeshInstance::_mesh_changed() {
materials.resize(mesh->get_surface_count());
}
-void MeshInstance::create_debug_tagents() {
+void MeshInstance::create_debug_tangents() {
Vector<Vector3> lines;
Vector<Color> colors;
@@ -366,8 +366,8 @@ void MeshInstance::_bind_methods() {
ClassDB::set_method_flags("MeshInstance", "create_convex_collision", METHOD_FLAGS_DEFAULT);
ClassDB::bind_method(D_METHOD("_mesh_changed"), &MeshInstance::_mesh_changed);
- ClassDB::bind_method(D_METHOD("create_debug_tagents"), &MeshInstance::create_debug_tagents);
- ClassDB::set_method_flags("MeshInstance", "create_debug_tagents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
+ ClassDB::bind_method(D_METHOD("create_debug_tangents"), &MeshInstance::create_debug_tangents);
+ ClassDB::set_method_flags("MeshInstance", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton"), "set_skeleton_path", "get_skeleton_path");
diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h
index be328084af..1bb2c97d10 100644
--- a/scene/3d/mesh_instance.h
+++ b/scene/3d/mesh_instance.h
@@ -83,7 +83,7 @@ public:
Node *create_convex_collision_node();
void create_convex_collision();
- void create_debug_tagents();
+ void create_debug_tangents();
virtual Rect3 get_aabb() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp
index 33d9b76b70..2912aa82fc 100644
--- a/scene/gui/texture_button.cpp
+++ b/scene/gui/texture_button.cpp
@@ -206,7 +206,7 @@ void TextureButton::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_focused", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_focused_texture", "get_focused_texture");
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_click_mask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_click_mask", "get_click_mask");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "expand", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_expand", "get_expand");
- ADD_PROPERTYNO(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode");
BIND_CONSTANT(STRETCH_SCALE);
BIND_CONSTANT(STRETCH_TILE);
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 080e538cbf..307f4107eb 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -1576,7 +1576,7 @@ VisualServer::VisualServer() {
GLOBAL_DEF("rendering/quality/directional_shadow/size.mobile", 2048);
GLOBAL_DEF("rendering/quality/shadow_atlas/size", 4096);
GLOBAL_DEF("rendering/quality/shadow_atlas/size.mobile", 2048);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384"));
GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_0_subdiv", 1);
GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_1_subdiv", 2);
GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_2_subdiv", 3);