diff options
35 files changed, 471 insertions, 125 deletions
diff --git a/core/global_constants.cpp b/core/global_constants.cpp index 4f535fb05e..18071d7748 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -106,7 +106,6 @@ static _GlobalConstant _global_constants[] = { BIND_GLOBAL_CONSTANT(KEY_F14), BIND_GLOBAL_CONSTANT(KEY_F15), BIND_GLOBAL_CONSTANT(KEY_F16), - BIND_GLOBAL_CONSTANT(KEY_KP_ENTER), BIND_GLOBAL_CONSTANT(KEY_KP_MULTIPLY), BIND_GLOBAL_CONSTANT(KEY_KP_DIVIDE), BIND_GLOBAL_CONSTANT(KEY_KP_SUBTRACT), 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/keyboard.cpp b/core/os/keyboard.cpp index 2f5dc03614..e154b1934d 100644 --- a/core/os/keyboard.cpp +++ b/core/os/keyboard.cpp @@ -81,7 +81,6 @@ static const _KeyCodeText _keycodes[] = { {KEY_F14 ,"F14"}, {KEY_F15 ,"F15"}, {KEY_F16 ,"F16"}, - {KEY_KP_ENTER ,"Kp Enter"}, {KEY_KP_MULTIPLY ,"Kp Multiply"}, {KEY_KP_DIVIDE ,"Kp Divide"}, {KEY_KP_SUBTRACT ,"Kp Subtract"}, @@ -334,7 +333,6 @@ bool keycode_has_unicode(uint32_t p_keycode) { case KEY_F14: case KEY_F15: case KEY_F16: - case KEY_KP_ENTER: case KEY_SUPER_L: case KEY_SUPER_R: case KEY_MENU: diff --git a/core/os/keyboard.h b/core/os/keyboard.h index 0a72663867..c6985c887d 100644 --- a/core/os/keyboard.h +++ b/core/os/keyboard.h @@ -96,7 +96,6 @@ enum KeyList { KEY_F14 = SPKEY | 0x29, KEY_F15 = SPKEY | 0x2A, KEY_F16 = SPKEY | 0x2B, - KEY_KP_ENTER = SPKEY | 0x80, KEY_KP_MULTIPLY = SPKEY | 0x81, KEY_KP_DIVIDE = SPKEY | 0x82, KEY_KP_SUBTRACT = SPKEY | 0x83, 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..703c6a6bcd 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 { @@ -182,9 +184,9 @@ public: virtual void set_ime_position(const Point2 &p_pos) {} - virtual Error open_dynamic_library(const String p_path, void *&p_library_handle) { return ERR_UNAVAILABLE; }; - virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; }; - virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle) { return ERR_UNAVAILABLE; }; + virtual Error open_dynamic_library(const String p_path, void *&p_library_handle) { return ERR_UNAVAILABLE; } + virtual Error close_dynamic_library(void *p_library_handle) { return ERR_UNAVAILABLE; } + virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false) { return ERR_UNAVAILABLE; } virtual void set_keep_screen_on(bool p_enabled); virtual bool is_keep_screen_on() const; @@ -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 fdc6b301de..058753132e 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -957,9 +957,6 @@ <constant name="KEY_F16" value="16777259"> F16 Key </constant> - <constant name="KEY_KP_ENTER" value="16777344"> - Enter Key on Numpad - </constant> <constant name="KEY_KP_MULTIPLY" value="16777345"> Multiply Key on Numpad </constant> @@ -14062,7 +14059,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> @@ -24788,7 +24785,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/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index d05529ef9a..e424590881 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -453,7 +453,7 @@ Error OS_Unix::close_dynamic_library(void *p_library_handle) { return OK; } -Error OS_Unix::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle) { +Error OS_Unix::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) { const char *error; dlerror(); // Clear existing errors @@ -461,8 +461,12 @@ Error OS_Unix::get_dynamic_library_symbol_handle(void *p_library_handle, const S error = dlerror(); if (error != NULL) { - ERR_EXPLAIN("Can't resolve symbol " + p_name + ". Error: " + error); - ERR_FAIL_V(ERR_CANT_RESOLVE); + if (!p_optional) { + ERR_EXPLAIN("Can't resolve symbol " + p_name + ". Error: " + error); + ERR_FAIL_V(ERR_CANT_RESOLVE); + } else { + return ERR_CANT_RESOLVE; + } } return OK; } diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 953b0f0431..fdc6d6e28f 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -85,7 +85,7 @@ public: virtual Error open_dynamic_library(const String p_path, void *&p_library_handle); virtual Error close_dynamic_library(void *p_library_handle); - virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle); + virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false); virtual Error set_cwd(const String &p_cwd); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 0c47daf5e6..0cdb981306 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1949,7 +1949,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case FILE_CLOSE: { if (!p_confirmed && (unsaved_cache || p_option == FILE_CLOSE_ALL_AND_QUIT || p_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER)) { - tab_closing = p_option == FILE_CLOSE ? editor_data.get_edited_scene() : _next_unsaved_scene(); + tab_closing = p_option == FILE_CLOSE ? editor_data.get_edited_scene() : _next_unsaved_scene(false); String scene_filename = editor_data.get_edited_scene_root(tab_closing)->get_filename(); save_confirmation->get_ok()->set_text(TTR("Save & Close")); save_confirmation->set_text(vformat(TTR("Save changes to '%s' before closing?"), scene_filename != "" ? scene_filename : "unsaved scene")); @@ -2481,7 +2481,8 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case RUN_PROJECT_MANAGER: { if (!p_confirmed) { - if (_next_unsaved_scene() == -1) { + bool save_each = EDITOR_DEF("interface/save_each_scene_on_quit", true); + if (_next_unsaved_scene(!save_each) == -1) { bool confirm = EDITOR_DEF("interface/quit_confirmation", true); if (confirm) { @@ -2495,21 +2496,16 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } } else { - bool save_each = EDITOR_DEF("interface/save_each_scene_on_quit", true); if (save_each) { _menu_option_confirm(p_option == FILE_QUIT ? FILE_CLOSE_ALL_AND_QUIT : FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER, false); } else { String unsaved_scenes; - for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { - int current = editor_data.get_edited_scene(); - bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0; - if (unsaved) { - - String scene_filename = editor_data.get_edited_scene_root(i)->get_filename(); - unsaved_scenes += "\n " + scene_filename; - } + int i = _next_unsaved_scene(true, 0); + while (i != -1) { + unsaved_scenes += "\n " + editor_data.get_edited_scene_root(i)->get_filename(); + i = _next_unsaved_scene(true, ++i); } save_confirmation->get_ok()->set_text(TTR("Save & Quit")); @@ -2522,7 +2518,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { break; } - if (_next_unsaved_scene() != -1) { + if (_next_unsaved_scene(true) != -1) { _save_all_scenes(); } _discard_changes(); @@ -2751,15 +2747,18 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } } -int EditorNode::_next_unsaved_scene() { +int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) { - for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { + for (int i = p_start; i < editor_data.get_edited_scene_count(); i++) { if (!editor_data.get_edited_scene_root(i)) continue; int current = editor_data.get_edited_scene(); bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0; if (unsaved) { + String scene_filename = editor_data.get_edited_scene_root(i)->get_filename(); + if (p_valid_filename && scene_filename.length() == 0) + continue; return i; } } @@ -2779,7 +2778,7 @@ void EditorNode::_discard_changes(const String &p_str) { _update_scene_tabs(); if (current_option == FILE_CLOSE_ALL_AND_QUIT || current_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) { - if (_next_unsaved_scene() == -1) { + if (_next_unsaved_scene(false) == -1) { current_option = current_option == FILE_CLOSE_ALL_AND_QUIT ? FILE_QUIT : RUN_PROJECT_MANAGER; _discard_changes(); } else { diff --git a/editor/editor_node.h b/editor/editor_node.h index 6553d3eee2..a440aaa1e6 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -464,7 +464,7 @@ private: void _save_scene(String p_file, int idx = -1); void _save_all_scenes(); - int _next_unsaved_scene(); + int _next_unsaved_scene(bool p_valid_filename, int p_start = 0); void _discard_changes(const String &p_str = String()); void _instance_request(const Vector<String> &p_files); 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/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 20ac1ecc0c..d180d5aada 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -47,7 +47,8 @@ godot_variant cb_standard_varcall(void *handle, godot_string *p_procedure, godot Error err = OS::get_singleton()->get_dynamic_library_symbol_handle( handle, *(String *)p_procedure, - library_proc); + library_proc, + true); // we roll our own message if (err != OK) { ERR_PRINT((String("GDNative procedure \"" + *(String *)p_procedure) + "\" does not exists and can't be called").utf8().get_data()); godot_variant ret; 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..c4cbfcce51 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); } } @@ -225,7 +203,21 @@ ScriptInstance *NativeScript::instance_create(Object *p_this) { nsi->userdata = script_data->create_func.create_func((godot_object *)p_this, script_data->create_func.method_data); #endif +#ifndef NO_THREADS + owners_lock->lock(); +#endif + instance_owners.insert(p_this); + +#ifndef NO_THREADS + owners_lock->unlock(); +#endif + + // try to call _init + // we don't care if it doesn't exist, so we ignore errors. + Variant::CallError err; + call("_init", NULL, 0, err); + return nsi; } @@ -415,9 +407,6 @@ Variant NativeScript::_new(const Variant **p_args, int p_argcount, Variant::Call ref = REF(r); } - // GDScript does it like this: _create_instance(p_args, p_argcount, owner, r != NULL, r_error); - // TODO(karroffel): support varargs for constructors. - NativeScriptInstance *instance = (NativeScriptInstance *)instance_create(owner); owner->set_script_instance(instance); @@ -441,11 +430,18 @@ NativeScript::NativeScript() { library = Ref<GDNative>(); lib_path = ""; class_name = ""; +#ifndef NO_THREADS + owners_lock = Mutex::create(); +#endif } // TODO(karroffel): implement this NativeScript::~NativeScript() { - NSL->library_script_users[lib_path].erase(this); + NSL->unregister_script(this); + +#ifndef NO_THREADS + memdelete(owners_lock); +#endif } ////// ScriptInstance stuff @@ -650,6 +646,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; } @@ -754,7 +772,16 @@ NativeScriptInstance::~NativeScriptInstance() { script_data->destroy_func.destroy_func((godot_object *)owner, script_data->destroy_func.method_data, userdata); if (owner) { + +#ifndef NO_THREADS + script->owners_lock->lock(); +#endif + script->instance_owners.erase(owner); + +#ifndef NO_THREADS + script->owners_lock->unlock(); +#endif } } @@ -798,6 +825,9 @@ void NativeScriptLanguage::_unload_stuff() { NativeScriptLanguage::NativeScriptLanguage() { NativeScriptLanguage::singleton = this; +#ifndef NO_THREADS + mutex = Mutex::create(); +#endif } // TODO(karroffel): implement this @@ -811,6 +841,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 +982,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 +1122,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 +1140,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..95b4954171 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 { @@ -102,6 +106,9 @@ class NativeScript : public Script { String class_name; +#ifndef NO_THREADS + Mutex *owners_lock; +#endif Set<Object *> instance_owners; protected: @@ -181,6 +188,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 +207,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 +229,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 +242,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..dfa16d8a2a 100644 --- a/modules/nativescript/register_types.cpp +++ b/modules/nativescript/register_types.cpp @@ -50,7 +50,8 @@ void init_call_cb(void *p_handle, godot_string *p_proc_name, void *p_data, int p Error err = OS::get_singleton()->get_dynamic_library_symbol_handle( p_handle, *(String *)p_proc_name, - library_proc); + library_proc, + true); // we print our own message if (err != OK) { ERR_PRINT((String("GDNative procedure \"" + *(String *)p_proc_name) + "\" does not exists and can't be called").utf8().get_data()); return; @@ -61,6 +62,33 @@ 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, + true); + 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 +100,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/osx/os_osx.h b/platform/osx/os_osx.h index 44f4334786..fc80088846 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -105,7 +105,6 @@ public: Vector<int> screen_dpi; Size2 window_size; - int current_screen; Rect2 restore_rect; power_osx *power_manager; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 82c1313326..fce38b6a8b 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -152,6 +152,16 @@ static bool mouse_down_control = false; return NO; } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 +- (void)windowDidEnterFullScreen:(NSNotification *)notification { + OS_OSX::singleton->zoomed = true; +} + +- (void)windowDidExitFullScreen:(NSNotification *)notification { + OS_OSX::singleton->zoomed = false; +} +#endif // MAC_OS_X_VERSION_MAX_ALLOWED + - (void)windowDidResize:(NSNotification *)notification { [OS_OSX::singleton->context update]; @@ -161,6 +171,12 @@ static bool mouse_down_control = false; OS_OSX::singleton->window_size.width = fbRect.size.width * OS_OSX::singleton->display_scale; OS_OSX::singleton->window_size.height = fbRect.size.height * OS_OSX::singleton->display_scale; + if (OS_OSX::singleton->main_loop) { + Main::force_redraw(); + //Event retrieval blocks until resize is over. Call Main::iteration() directly. + Main::iteration(); + } + /* _GodotInputFramebufferSize(window, fbRect.size.width, fbRect.size.height); _GodotInputWindowSize(window, contentRect.size.width, contentRect.size.height); @@ -512,7 +528,7 @@ static int translateKey(unsigned int key) { /* 49 */ KEY_UNKNOWN, /* VolumeDown */ /* 4a */ KEY_UNKNOWN, /* Mute */ /* 4b */ KEY_KP_DIVIDE, - /* 4c */ KEY_KP_ENTER, + /* 4c */ KEY_ENTER, /* 4d */ KEY_UNKNOWN, /* 4e */ KEY_KP_SUBTRACT, /* 4f */ KEY_UNKNOWN, @@ -1233,13 +1249,21 @@ int OS_OSX::get_screen_count() const { }; int OS_OSX::get_current_screen() const { - - return current_screen; + Vector2 wpos = get_window_position(); + + int count = get_screen_count(); + for (int i = 0; i < count; i++) { + Point2 pos = get_screen_position(i); + Size2 size = get_screen_size(i); + if ((wpos.x >= pos.x && wpos.x < pos.x + size.width) && (wpos.y >= pos.y && wpos.y < pos.y + size.height)) + return i; + } + return 0; }; void OS_OSX::set_current_screen(int p_screen) { - - current_screen = p_screen; + Vector2 wpos = get_window_position() - get_screen_position(get_current_screen()); + set_window_position(wpos + get_screen_position(p_screen)); }; Point2 OS_OSX::get_screen_position(int p_screen) const { @@ -1383,7 +1407,7 @@ void OS_OSX::set_window_maximized(bool p_enabled) { if (p_enabled) { restore_rect = Rect2(get_window_position(), get_window_size()); - [window_object setFrame:[[[NSScreen screens] objectAtIndex:current_screen] visibleFrame] display:YES]; + [window_object setFrame:[[[NSScreen screens] objectAtIndex:get_current_screen()] visibleFrame] display:YES]; } else { set_window_size(restore_rect.size); set_window_position(restore_rect.position); @@ -1661,12 +1685,52 @@ OS_OSX::OS_OSX() { // In case we are unbundled, make us a proper UI application [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; -#if 0 // Menu bar setup must go between sharedApplication above and // finishLaunching below, in order to properly emulate the behavior // of NSApplicationMain - createMenuBar(); -#endif + NSMenuItem *menu_item; + NSString *title; + + NSString *nsappname = [[[NSBundle mainBundle] performSelector:@selector(localizedInfoDictionary)] objectForKey:@"CFBundleName"]; + if (nsappname == nil) + nsappname = [[NSProcessInfo processInfo] processName]; + + // Setup Apple menu + NSMenu *apple_menu = [[NSMenu alloc] initWithTitle:@""]; + title = [NSString stringWithFormat:NSLocalizedString(@"About %@", nil), nsappname]; + [apple_menu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + + [apple_menu addItem:[NSMenuItem separatorItem]]; + + NSMenu *services = [[NSMenu alloc] initWithTitle:@""]; + menu_item = [apple_menu addItemWithTitle:NSLocalizedString(@"Services", nil) action:nil keyEquivalent:@""]; + [apple_menu setSubmenu:services forItem:menu_item]; + [NSApp setServicesMenu:services]; + [services release]; + + [apple_menu addItem:[NSMenuItem separatorItem]]; + + title = [NSString stringWithFormat:NSLocalizedString(@"Hide %@", nil), nsappname]; + [apple_menu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; + + menu_item = [apple_menu addItemWithTitle:NSLocalizedString(@"Hide Others", nil) action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + [menu_item setKeyEquivalentModifierMask:(NSAlternateKeyMask | NSCommandKeyMask)]; + + [apple_menu addItemWithTitle:NSLocalizedString(@"Show all", nil) action:@selector(unhideAllApplications:) keyEquivalent:@""]; + + [apple_menu addItem:[NSMenuItem separatorItem]]; + + title = [NSString stringWithFormat:NSLocalizedString(@"Quit %@", nil), nsappname]; + [apple_menu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; + + // Setup menu bar + NSMenu *main_menu = [[NSMenu alloc] initWithTitle:@""]; + menu_item = [main_menu addItemWithTitle:@"" action:nil keyEquivalent:@""]; + [main_menu setSubmenu:apple_menu forItem:menu_item]; + [NSApp setMainMenu:main_menu]; + + [main_menu release]; + [apple_menu release]; [NSApp finishLaunching]; @@ -1676,8 +1740,6 @@ OS_OSX::OS_OSX() { cursor_shape = CURSOR_ARROW; - current_screen = 0; - maximized = false; minimized = false; window_size = Vector2(1024, 600); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 3413050f4a..c091c7d022 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1569,12 +1569,16 @@ Error OS_Windows::close_dynamic_library(void *p_library_handle) { return OK; } -Error OS_Windows::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle) { +Error OS_Windows::get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional) { char *error; p_symbol_handle = (void *)GetProcAddress((HMODULE)p_library_handle, p_name.utf8().get_data()); if (!p_symbol_handle) { - ERR_EXPLAIN("Can't resolve symbol " + p_name + ". Error: " + String::num(GetLastError())); - ERR_FAIL_V(ERR_CANT_RESOLVE); + if (!p_optional) { + ERR_EXPLAIN("Can't resolve symbol " + p_name + ". Error: " + String::num(GetLastError())); + ERR_FAIL_V(ERR_CANT_RESOLVE); + } else { + return ERR_CANT_RESOLVE; + } } return OK; } diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index e6589ddfad..6856e7e9b8 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -227,7 +227,7 @@ public: virtual Error open_dynamic_library(const String p_path, void *&p_library_handle); virtual Error close_dynamic_library(void *p_library_handle); - virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle); + virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false); virtual MainLoop *get_main_loop() const; diff --git a/platform/x11/key_mapping_x11.cpp b/platform/x11/key_mapping_x11.cpp index 362fc3618a..1d7eb1692c 100644 --- a/platform/x11/key_mapping_x11.cpp +++ b/platform/x11/key_mapping_x11.cpp @@ -94,7 +94,6 @@ static _XTranslatePair _xkeysym_to_keycode[] = { //{ XK_KP_Separator, KEY_COMMA }, { XK_KP_Decimal, KEY_KP_PERIOD }, { XK_KP_Delete, KEY_KP_PERIOD }, - { XK_KP_Enter, KEY_KP_ENTER }, { XK_KP_Multiply, KEY_KP_MULTIPLY }, { XK_KP_Divide, KEY_KP_DIVIDE }, { XK_KP_Subtract, KEY_KP_SUBTRACT }, diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 5bfe31b8c2..1dde328eda 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -497,6 +497,8 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au joypad = memnew(JoypadLinux(input)); #endif _ensure_data_dir(); + + power_manager = memnew(PowerX11); } void OS_X11::xim_destroy_callback(::XIM im, ::XPointer client_data, diff --git a/platform/x11/power_x11.cpp b/platform/x11/power_x11.cpp index 093d24f406..8e69a2223f 100644 --- a/platform/x11/power_x11.cpp +++ b/platform/x11/power_x11.cpp @@ -171,25 +171,18 @@ void PowerX11::check_proc_acpi_battery(const char *node, bool *have_battery, boo charge = true; } } else if (String(key) == "remaining capacity") { - char *endptr = NULL; - //const int cvt = (int) strtol(val, &endptr, 10); String sval = val; const int cvt = sval.to_int(); - if (*endptr == ' ') { - remaining = cvt; - } + remaining = cvt; } } ptr = &info[0]; while (make_proc_acpi_key_val(&ptr, &key, &val)) { if (String(key) == "design capacity") { - char *endptr = NULL; String sval = val; const int cvt = sval.to_int(); - if (*endptr == ' ') { - maximum = cvt; - } + maximum = cvt; } } 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/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); |