summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/bind/core_bind.cpp30
-rw-r--r--core/bind/core_bind.h5
-rw-r--r--core/image.cpp12
-rw-r--r--core/image.h2
-rw-r--r--core/os/main_loop.cpp8
-rw-r--r--core/os/main_loop.h1
-rw-r--r--core/os/os.h5
-rw-r--r--doc/classes/MainLoop.xml10
-rw-r--r--doc/classes/OS.xml44
-rw-r--r--doc/classes/SceneTree.xml9
-rw-r--r--editor/editor_node.cpp26
-rw-r--r--editor/editor_node.h4
-rw-r--r--editor/find_in_files.cpp8
-rw-r--r--editor/plugins/shader_editor_plugin.cpp1
-rw-r--r--editor/project_manager.cpp35
-rw-r--r--editor/project_manager.h2
-rw-r--r--modules/gdscript/gdscript_parser.cpp448
-rw-r--r--platform/android/java/src/org/godotengine/godot/Godot.java68
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotLib.java148
-rw-r--r--platform/android/java/src/org/godotengine/godot/xr/XRMode.java8
-rw-r--r--platform/android/java_godot_lib_jni.cpp2
-rw-r--r--platform/android/java_godot_lib_jni.h2
-rw-r--r--platform/android/java_godot_wrapper.cpp11
-rw-r--r--platform/android/java_godot_wrapper.h2
-rw-r--r--platform/android/os_android.cpp2
-rw-r--r--platform/osx/os_osx.h25
-rw-r--r--platform/osx/os_osx.mm94
-rw-r--r--scene/gui/text_edit.cpp2
-rw-r--r--scene/main/scene_tree.cpp7
-rw-r--r--scene/main/scene_tree.h1
30 files changed, 736 insertions, 286 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 8e0d156438..b5e84d49a0 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -185,10 +185,31 @@ _ResourceSaver::_ResourceSaver() {
/////////////////OS
+void _OS::global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta) {
+
+ OS::get_singleton()->global_menu_add_item(p_menu, p_label, p_signal, p_meta);
+}
+
+void _OS::global_menu_add_separator(const String &p_menu) {
+
+ OS::get_singleton()->global_menu_add_separator(p_menu);
+}
+
+void _OS::global_menu_remove_item(const String &p_menu, int p_idx) {
+
+ OS::get_singleton()->global_menu_remove_item(p_menu, p_idx);
+}
+
+void _OS::global_menu_clear(const String &p_menu) {
+
+ OS::get_singleton()->global_menu_clear(p_menu);
+}
+
Point2 _OS::get_mouse_position() const {
return OS::get_singleton()->get_mouse_position();
}
+
void _OS::set_window_title(const String &p_title) {
OS::get_singleton()->set_window_title(p_title);
@@ -202,6 +223,7 @@ int _OS::get_mouse_button_state() const {
String _OS::get_unique_id() const {
return OS::get_singleton()->get_unique_id();
}
+
bool _OS::has_touchscreen_ui_hint() const {
return OS::get_singleton()->has_touchscreen_ui_hint();
@@ -211,6 +233,7 @@ void _OS::set_clipboard(const String &p_text) {
OS::get_singleton()->set_clipboard(p_text);
}
+
String _OS::get_clipboard() const {
return OS::get_singleton()->get_clipboard();
@@ -257,12 +280,14 @@ void _OS::set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeab
vm.resizable = p_resizeable;
OS::get_singleton()->set_video_mode(vm, p_screen);
}
+
Size2 _OS::get_video_mode(int p_screen) const {
OS::VideoMode vm;
vm = OS::get_singleton()->get_video_mode(p_screen);
return Size2(vm.width, vm.height);
}
+
bool _OS::is_video_mode_fullscreen(int p_screen) const {
OS::VideoMode vm;
@@ -1125,6 +1150,11 @@ void _OS::_bind_methods() {
//ClassDB::bind_method(D_METHOD("is_video_mode_resizable","screen"),&_OS::is_video_mode_resizable,DEFVAL(0));
//ClassDB::bind_method(D_METHOD("get_fullscreen_mode_list","screen"),&_OS::get_fullscreen_mode_list,DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu", "label", "id", "meta"), &_OS::global_menu_add_item);
+ ClassDB::bind_method(D_METHOD("global_menu_add_separator", "menu"), &_OS::global_menu_add_separator);
+ ClassDB::bind_method(D_METHOD("global_menu_remove_item", "menu", "idx"), &_OS::global_menu_remove_item);
+ ClassDB::bind_method(D_METHOD("global_menu_clear", "menu"), &_OS::global_menu_clear);
+
ClassDB::bind_method(D_METHOD("get_video_driver_count"), &_OS::get_video_driver_count);
ClassDB::bind_method(D_METHOD("get_video_driver_name", "driver"), &_OS::get_video_driver_name);
ClassDB::bind_method(D_METHOD("get_current_video_driver"), &_OS::get_current_video_driver);
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index f0f86e003f..76ba2dc0a5 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -143,6 +143,11 @@ public:
MONTH_DECEMBER
};
+ void global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta);
+ void global_menu_add_separator(const String &p_menu);
+ void global_menu_remove_item(const String &p_menu, int p_idx);
+ void global_menu_clear(const String &p_menu);
+
Point2 get_mouse_position() const;
void set_window_title(const String &p_title);
int get_mouse_button_state() const;
diff --git a/core/image.cpp b/core/image.cpp
index d8d667dbd5..900efb0eb0 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -863,7 +863,7 @@ bool Image::is_size_po2() const {
void Image::resize_to_po2(bool p_square) {
- ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in indexed, compressed or custom image formats.");
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats.");
int w = next_power_of_2(width);
int h = next_power_of_2(height);
@@ -881,7 +881,7 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
ERR_FAIL_COND_MSG(data.size() == 0, "Cannot resize image before creating it, use create() or create_from_data() first.");
- ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in indexed, compressed or custom image formats.");
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot resize in compressed or custom image formats.");
bool mipmap_aware = p_interpolation == INTERPOLATE_TRILINEAR /* || p_interpolation == INTERPOLATE_TRICUBIC */;
@@ -1094,7 +1094,7 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
- ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot crop in indexed, compressed or custom image formats.");
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot crop in compressed or custom image formats.");
ERR_FAIL_COND(p_x < 0);
ERR_FAIL_COND(p_y < 0);
@@ -1149,7 +1149,7 @@ void Image::crop(int p_width, int p_height) {
void Image::flip_y() {
- ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_y in indexed, compressed or custom image formats.");
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_y in compressed or custom image formats.");
bool used_mipmaps = has_mipmaps();
if (used_mipmaps) {
@@ -1182,7 +1182,7 @@ void Image::flip_y() {
void Image::flip_x() {
- ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_x in indexed, compressed or custom image formats.");
+ ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot flip_x in compressed or custom image formats.");
bool used_mipmaps = has_mipmaps();
if (used_mipmaps) {
@@ -1441,7 +1441,7 @@ void Image::normalize() {
Error Image::generate_mipmaps(bool p_renormalize) {
- ERR_FAIL_COND_V_MSG(!_can_modify(format), ERR_UNAVAILABLE, "Cannot generate mipmaps in indexed, compressed or custom image formats.");
+ ERR_FAIL_COND_V_MSG(!_can_modify(format), ERR_UNAVAILABLE, "Cannot generate mipmaps in compressed or custom image formats.");
ERR_FAIL_COND_V_MSG(width == 0 || height == 0, ERR_UNCONFIGURED, "Cannot generate mipmaps with width or height equal to 0.");
diff --git a/core/image.h b/core/image.h
index d17571399d..f29a30cda0 100644
--- a/core/image.h
+++ b/core/image.h
@@ -220,9 +220,7 @@ public:
/**
* Resize the image, using the preferred interpolation method.
- * Indexed-Color images always use INTERPOLATE_NEAREST.
*/
-
void resize_to_po2(bool p_square = false);
void resize(int p_width, int p_height, Interpolation p_interpolation = INTERPOLATE_BILINEAR);
void shrink_x2();
diff --git a/core/os/main_loop.cpp b/core/os/main_loop.cpp
index 9946ced2f3..eca3b2a7f4 100644
--- a/core/os/main_loop.cpp
+++ b/core/os/main_loop.cpp
@@ -49,6 +49,8 @@ void MainLoop::_bind_methods() {
BIND_VMETHOD(MethodInfo("_drop_files", PropertyInfo(Variant::POOL_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "from_screen")));
BIND_VMETHOD(MethodInfo("_finalize"));
+ BIND_VMETHOD(MethodInfo("_global_menu_action", PropertyInfo(Variant::NIL, "id"), PropertyInfo(Variant::NIL, "meta")));
+
BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER);
BIND_CONSTANT(NOTIFICATION_WM_MOUSE_EXIT);
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN);
@@ -115,6 +117,12 @@ void MainLoop::drop_files(const Vector<String> &p_files, int p_from_screen) {
get_script_instance()->call("_drop_files", p_files, p_from_screen);
}
+void MainLoop::global_menu_action(const Variant &p_id, const Variant &p_meta) {
+
+ if (get_script_instance())
+ get_script_instance()->call("_global_menu_action", p_id, p_meta);
+}
+
void MainLoop::finish() {
if (get_script_instance()) {
diff --git a/core/os/main_loop.h b/core/os/main_loop.h
index 6ddaf5bee7..54e61fd2fa 100644
--- a/core/os/main_loop.h
+++ b/core/os/main_loop.h
@@ -71,6 +71,7 @@ public:
virtual void finish();
virtual void drop_files(const Vector<String> &p_files, int p_from_screen = 0);
+ virtual void global_menu_action(const Variant &p_id, const Variant &p_meta);
void set_init_script(const Ref<Script> &p_init_script);
diff --git a/core/os/os.h b/core/os/os.h
index e627773d88..9b46b43081 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -143,6 +143,11 @@ public:
static OS *get_singleton();
+ virtual void global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta){};
+ virtual void global_menu_add_separator(const String &p_menu){};
+ virtual void global_menu_remove_item(const String &p_menu, int p_idx){};
+ virtual void global_menu_clear(const String &p_menu){};
+
void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type = Logger::ERR_ERROR);
void print(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
void printerr(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
diff --git a/doc/classes/MainLoop.xml b/doc/classes/MainLoop.xml
index fedf77bfd2..181a99590a 100644
--- a/doc/classes/MainLoop.xml
+++ b/doc/classes/MainLoop.xml
@@ -61,6 +61,16 @@
Called before the program exits.
</description>
</method>
+ <method name="_global_menu_action" qualifiers="virtual">
+ <return type="void">
+ </return>
+ <argument index="0" name="id" type="Variant">
+ </argument>
+ <argument index="1" name="meta" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="_idle" qualifiers="virtual">
<return type="bool">
</return>
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index c770e78c7c..938777a36b 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -497,6 +497,50 @@
Returns unobscured area of the window where interactive controls should be rendered.
</description>
</method>
+ <method name="global_menu_add_item">
+ <return type="void">
+ </return>
+ <argument index="0" name="menu" type="String">
+ </argument>
+ <argument index="1" name="label" type="String">
+ </argument>
+ <argument index="2" name="id" type="Variant">
+ </argument>
+ <argument index="3" name="meta" type="Variant">
+ </argument>
+ <description>
+ Add a new item with text "label" to global menu. Use "_dock" menu to add item to the macOS dock icon menu.
+ </description>
+ </method>
+ <method name="global_menu_add_separator">
+ <return type="void">
+ </return>
+ <argument index="0" name="menu" type="String">
+ </argument>
+ <description>
+ Add a separator between items. Separators also occupy an index.
+ </description>
+ </method>
+ <method name="global_menu_clear">
+ <return type="void">
+ </return>
+ <argument index="0" name="menu" type="String">
+ </argument>
+ <description>
+ Clear the global menu, in effect removing all items.
+ </description>
+ </method>
+ <method name="global_menu_remove_item">
+ <return type="void">
+ </return>
+ <argument index="0" name="menu" type="String">
+ </argument>
+ <argument index="1" name="idx" type="int">
+ </argument>
+ <description>
+ Removes the item at index "idx" from the global menu. Note that the indexes of items after the removed item are going to be shifted by one.
+ </description>
+ </method>
<method name="has_environment" qualifiers="const">
<return type="bool">
</return>
diff --git a/doc/classes/SceneTree.xml b/doc/classes/SceneTree.xml
index 1302c1e6bf..ed43f83f05 100644
--- a/doc/classes/SceneTree.xml
+++ b/doc/classes/SceneTree.xml
@@ -324,6 +324,15 @@
Emitted when files are dragged from the OS file manager and dropped in the game window. The arguments are a list of file paths and the identifier of the screen where the drag originated.
</description>
</signal>
+ <signal name="global_menu_action">
+ <argument index="0" name="id" type="Nil">
+ </argument>
+ <argument index="1" name="meta" type="Nil">
+ </argument>
+ <description>
+ Emitted whenever global menu item is clicked.
+ </description>
+ </signal>
<signal name="idle_frame">
<description>
Emitted immediately before [method Node._process] is called on every node in the [SceneTree].
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 3e97dbd96c..635f6d4fc7 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -135,6 +135,8 @@ void EditorNode::_update_scene_tabs() {
bool show_rb = EditorSettings::get_singleton()->get("interface/scene_tabs/show_script_button");
+ OS::get_singleton()->global_menu_clear("_dock");
+
scene_tabs->clear_tabs();
Ref<Texture> script_icon = gui_base->get_icon("Script", "EditorIcons");
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
@@ -149,11 +151,16 @@ void EditorNode::_update_scene_tabs() {
bool unsaved = (i == current) ? saved_version != editor_data.get_undo_redo().get_version() : editor_data.get_scene_version(i) != 0;
scene_tabs->add_tab(editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), icon);
+ OS::get_singleton()->global_menu_add_item("_dock", editor_data.get_scene_title(i) + (unsaved ? "(*)" : ""), GLOBAL_SCENE, i);
+
if (show_rb && editor_data.get_scene_root_script(i).is_valid()) {
scene_tabs->set_tab_right_button(i, script_icon);
}
}
+ OS::get_singleton()->global_menu_add_separator("_dock");
+ OS::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant());
+
scene_tabs->set_current_tab(editor_data.get_edited_scene());
if (scene_tabs->get_offset_buttons_visible()) {
@@ -290,6 +297,7 @@ void EditorNode::_notification(int p_what) {
get_tree()->get_root()->set_as_audio_listener_2d(false);
get_tree()->set_auto_accept_quit(false);
get_tree()->connect("files_dropped", this, "_dropped_files");
+ get_tree()->connect("global_menu_action", this, "_global_menu_action");
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
} break;
@@ -4941,6 +4949,23 @@ void EditorNode::remove_tool_menu_item(const String &p_name) {
}
}
+void EditorNode::_global_menu_action(const Variant &p_id, const Variant &p_meta) {
+
+ int id = (int)p_id;
+ if (id == GLOBAL_NEW_WINDOW) {
+ if (OS::get_singleton()->get_main_loop()) {
+ List<String> args;
+ String exec = OS::get_singleton()->get_executable_path();
+
+ OS::ProcessID pid = 0;
+ OS::get_singleton()->execute(exec, args, false, &pid);
+ }
+ } else if (id == GLOBAL_SCENE) {
+ int idx = (int)p_meta;
+ scene_tabs->set_current_tab(idx);
+ }
+}
+
void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) {
String to_path = ProjectSettings::get_singleton()->globalize_path(get_filesystem_dock()->get_selected_path());
@@ -5322,6 +5347,7 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method("_clear_undo_history", &EditorNode::_clear_undo_history);
ClassDB::bind_method("_dropped_files", &EditorNode::_dropped_files);
+ ClassDB::bind_method(D_METHOD("_global_menu_action"), &EditorNode::_global_menu_action, DEFVAL(Variant()));
ClassDB::bind_method("_toggle_distraction_free_mode", &EditorNode::_toggle_distraction_free_mode);
ClassDB::bind_method("edit_item_resource", &EditorNode::edit_item_resource);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index a8443549ed..61bbb7b86d 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -207,6 +207,9 @@ private:
SET_VIDEO_DRIVER_SAVE_AND_RESTART,
+ GLOBAL_NEW_WINDOW,
+ GLOBAL_SCENE,
+
IMPORT_PLUGIN_BASE = 100,
TOOL_MENU_BASE = 1000
@@ -504,6 +507,7 @@ private:
void _add_to_recent_scenes(const String &p_scene);
void _update_recent_scenes();
void _open_recent_scene(int p_idx);
+ void _global_menu_action(const Variant &p_id, const Variant &p_meta);
void _dropped_files(const Vector<String> &p_files, int p_screen);
void _add_dropped_files_recursive(const Vector<String> &p_files, String to_path);
String _recent_scene;
diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp
index cc2efb92ae..def22d07de 100644
--- a/editor/find_in_files.cpp
+++ b/editor/find_in_files.cpp
@@ -221,8 +221,8 @@ float FindInFiles::get_progress() const {
void FindInFiles::_scan_dir(String path, PoolStringArray &out_folders) {
- DirAccess *dir = DirAccess::open(path);
- if (dir == NULL) {
+ DirAccessRef dir = DirAccess::open(path);
+ if (!dir) {
print_verbose("Cannot open directory! " + path);
return;
}
@@ -253,8 +253,8 @@ void FindInFiles::_scan_dir(String path, PoolStringArray &out_folders) {
void FindInFiles::_scan_file(String fpath) {
- FileAccess *f = FileAccess::open(fpath, FileAccess::READ);
- if (f == NULL) {
+ FileAccessRef f = FileAccess::open(fpath, FileAccess::READ);
+ if (!f) {
print_verbose(String("Cannot open file ") + fpath);
return;
}
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 04820b8a8f..938dc8a1e7 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -55,6 +55,7 @@ void ShaderTextEditor::set_edited_shader(const Ref<Shader> &p_shader) {
_load_theme_settings();
get_text_edit()->set_text(p_shader->get_code());
+ get_text_edit()->clear_undo_history();
_validate_script();
_line_col_changed();
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 5709bdc3fa..fbaa90c3d7 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -946,6 +946,11 @@ public:
static const char *SIGNAL_SELECTION_CHANGED;
static const char *SIGNAL_PROJECT_ASK_OPEN;
+ enum MenuOptions {
+ GLOBAL_NEW_WINDOW,
+ GLOBAL_OPEN_PROJECT
+ };
+
// Can often be passed by copy
struct Item {
String project_key;
@@ -1181,6 +1186,7 @@ void ProjectList::load_projects() {
_projects.clear();
_last_clicked = "";
_selected_project_keys.clear();
+ OS::get_singleton()->global_menu_clear("_dock");
// Load data
// TODO Would be nice to change how projects and favourites are stored... it complicates things a bit.
@@ -1218,6 +1224,9 @@ void ProjectList::load_projects() {
create_project_item_control(i);
}
+ OS::get_singleton()->global_menu_add_separator("_dock");
+ OS::get_singleton()->global_menu_add_item("_dock", TTR("New Window"), GLOBAL_NEW_WINDOW, Variant());
+
sort_projects();
set_v_scroll(0);
@@ -1305,6 +1314,7 @@ void ProjectList::create_project_item_control(int p_index) {
fpath->set_clip_text(true);
_scroll_children->add_child(hb);
+ OS::get_singleton()->global_menu_add_item("_dock", item.project_name + " ( " + item.path + " )", GLOBAL_OPEN_PROJECT, Variant(item.path.plus_file("project.godot")));
item.control = hb;
}
@@ -1894,6 +1904,29 @@ void ProjectManager::_confirm_update_settings() {
_open_selected_projects();
}
+void ProjectManager::_global_menu_action(const Variant &p_id, const Variant &p_meta) {
+
+ int id = (int)p_id;
+ if (id == ProjectList::GLOBAL_NEW_WINDOW) {
+ List<String> args;
+ String exec = OS::get_singleton()->get_executable_path();
+
+ OS::ProcessID pid = 0;
+ OS::get_singleton()->execute(exec, args, false, &pid);
+ } else if (id == ProjectList::GLOBAL_OPEN_PROJECT) {
+ String conf = (String)p_meta;
+
+ if (conf != String()) {
+ List<String> args;
+ args.push_back(conf);
+ String exec = OS::get_singleton()->get_executable_path();
+
+ OS::ProcessID pid = 0;
+ OS::get_singleton()->execute(exec, args, false, &pid);
+ }
+ }
+}
+
void ProjectManager::_open_selected_projects() {
const Set<String> &selected_list = _project_list->get_selected_project_keys();
@@ -2236,6 +2269,7 @@ void ProjectManager::_bind_methods() {
ClassDB::bind_method("_open_selected_projects_ask", &ProjectManager::_open_selected_projects_ask);
ClassDB::bind_method("_open_selected_projects", &ProjectManager::_open_selected_projects);
+ ClassDB::bind_method(D_METHOD("_global_menu_action"), &ProjectManager::_global_menu_action, DEFVAL(Variant()));
ClassDB::bind_method("_run_project", &ProjectManager::_run_project);
ClassDB::bind_method("_run_project_confirm", &ProjectManager::_run_project_confirm);
ClassDB::bind_method("_scan_projects", &ProjectManager::_scan_projects);
@@ -2561,6 +2595,7 @@ ProjectManager::ProjectManager() {
}
SceneTree::get_singleton()->connect("files_dropped", this, "_files_dropped");
+ SceneTree::get_singleton()->connect("global_menu_action", this, "_global_menu_action");
run_error_diag = memnew(AcceptDialog);
gui_base->add_child(run_error_diag);
diff --git a/editor/project_manager.h b/editor/project_manager.h
index 2a5fd02892..cf0b8b8801 100644
--- a/editor/project_manager.h
+++ b/editor/project_manager.h
@@ -43,6 +43,7 @@ class ProjectList;
class ProjectListFilter;
class ProjectManager : public Control {
+
GDCLASS(ProjectManager, Control);
Button *erase_btn;
@@ -96,6 +97,7 @@ class ProjectManager : public Control {
void _restart_confirm();
void _exit_dialog();
void _scan_begin(const String &p_base);
+ void _global_menu_action(const Variant &p_id, const Variant &p_meta);
void _confirm_update_settings();
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 764f57aaa1..a07b575c6e 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -504,7 +504,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
Ref<GDScript> gds = res;
if (gds.is_valid() && !gds->is_valid()) {
- _set_error("Could not fully preload the script, possible cyclic reference or compilation error. Use 'load()' instead if a cyclic reference is intended.");
+ _set_error("Couldn't fully preload the script, possible cyclic reference or compilation error. Use \"load()\" instead if a cyclic reference is intended.");
return NULL;
}
@@ -518,7 +518,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
} else if (tokenizer->get_token() == GDScriptTokenizer::TK_PR_YIELD) {
if (!current_function) {
- _set_error("yield() can only be used inside function blocks.");
+ _set_error("\"yield()\" can only be used inside function blocks.");
return NULL;
}
@@ -526,7 +526,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after 'yield'");
+ _set_error("Expected \"(\" after \"yield\".");
return NULL;
}
@@ -552,7 +552,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
yield->arguments.push_back(object);
if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
- _set_error("Expected ',' after first argument of 'yield'");
+ _set_error("Expected \",\" after the first argument of \"yield\".");
return NULL;
}
@@ -578,7 +578,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
yield->arguments.push_back(signal);
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' after second argument of 'yield'");
+ _set_error("Expected \")\" after the second argument of \"yield\".");
return NULL;
}
@@ -592,7 +592,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
} else if (tokenizer->get_token() == GDScriptTokenizer::TK_SELF) {
if (p_static) {
- _set_error("'self'' not allowed in static function or constant expression");
+ _set_error("\"self\" isn't allowed in a static function or constant expression.");
return NULL;
}
//constant defined by tokenizer
@@ -613,7 +613,7 @@ GDScriptParser::Node *GDScriptParser::_parse_expression(Node *p_parent, bool p_s
if (identifier == StringName()) {
- _set_error("Built-in type constant or static function expected after '.'");
+ _set_error("Built-in type constant or static function expected after \".\".");
return NULL;
}
if (!Variant::has_constant(bi_type, identifier)) {
@@ -2309,7 +2309,7 @@ void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_m
// static type check if possible
if (pattern_type.has_type && to_match_type.has_type) {
if (!_is_type_compatible(to_match_type, pattern_type) && !_is_type_compatible(pattern_type, to_match_type)) {
- _set_error("Pattern type (" + pattern_type.to_string() + ") is not compatible with the type of the value to match (" + to_match_type.to_string() + ").",
+ _set_error("The pattern type (" + pattern_type.to_string() + ") isn't compatible with the type of the value to match (" + to_match_type.to_string() + ").",
p_pattern->line);
return;
}
@@ -2761,7 +2761,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
case GDScriptTokenizer::TK_CF_PASS: {
if (tokenizer->get_token(1) != GDScriptTokenizer::TK_SEMICOLON && tokenizer->get_token(1) != GDScriptTokenizer::TK_NEWLINE && tokenizer->get_token(1) != GDScriptTokenizer::TK_EOF) {
- _set_error("Expected ';' or <NewLine>.");
+ _set_error("Expected \";\" or a line break.");
return;
}
_mark_line_as_safe(tokenizer->get_token_line());
@@ -2778,7 +2778,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
int var_line = tokenizer->get_token_line();
if (!tokenizer->is_token_literal(0, true)) {
- _set_error("Expected identifier for local variable name.");
+ _set_error("Expected an identifier for the local variable name.");
return;
}
StringName n = tokenizer->get_token_literal();
@@ -2786,7 +2786,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
if (current_function) {
for (int i = 0; i < current_function->arguments.size(); i++) {
if (n == current_function->arguments[i]) {
- _set_error("Variable '" + String(n) + "' already defined in the scope (at line: " + itos(current_function->line) + ").");
+ _set_error("Variable \"" + String(n) + "\" already defined in the scope (at line " + itos(current_function->line) + ").");
return;
}
}
@@ -2794,7 +2794,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
BlockNode *check_block = p_block;
while (check_block) {
if (check_block->variables.has(n)) {
- _set_error("Variable '" + String(n) + "' already defined in the scope (at line: " + itos(check_block->variables[n]->line) + ").");
+ _set_error("Variable \"" + String(n) + "\" already defined in the scope (at line " + itos(check_block->variables[n]->line) + ").");
return;
}
check_block = check_block->parent_block;
@@ -2816,7 +2816,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
#endif
tokenizer->advance();
} else if (!_parse_type(lv->datatype)) {
- _set_error("Expected type for variable.");
+ _set_error("Expected a type for the variable.");
return;
}
}
@@ -2865,7 +2865,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
lv->assign = assigned;
if (!_end_statement()) {
- _set_error("Expected end of statement (var)");
+ _set_error("Expected end of statement (\"var\").");
return;
}
@@ -2894,7 +2894,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
p_block->sub_blocks.push_back(cf_if->body);
if (!_enter_indent_block(cf_if->body)) {
- _set_error("Expected indented block after 'if'");
+ _set_error("Expected an indented block after \"if\".");
p_block->end_line = tokenizer->get_token_line();
return;
}
@@ -2924,7 +2924,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
if (tab_level.back()->get() > indent_level) {
- _set_error("Invalid indent");
+ _set_error("Invalid indentation.");
return;
}
@@ -2955,7 +2955,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
p_block->sub_blocks.push_back(cf_if->body);
if (!_enter_indent_block(cf_if->body)) {
- _set_error("Expected indented block after 'elif'");
+ _set_error("Expected an indented block after \"elif\".");
p_block->end_line = tokenizer->get_token_line();
return;
}
@@ -2971,7 +2971,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
} else if (tokenizer->get_token() == GDScriptTokenizer::TK_CF_ELSE) {
if (tab_level.back()->get() > indent_level) {
- _set_error("Invalid indent");
+ _set_error("Invalid indentation.");
return;
}
@@ -2981,7 +2981,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
p_block->sub_blocks.push_back(cf_if->body_else);
if (!_enter_indent_block(cf_if->body_else)) {
- _set_error("Expected indented block after 'else'");
+ _set_error("Expected an indented block after \"else\".");
p_block->end_line = tokenizer->get_token_line();
return;
}
@@ -3026,7 +3026,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
p_block->sub_blocks.push_back(cf_while->body);
if (!_enter_indent_block(cf_while->body)) {
- _set_error("Expected indented block after 'while'");
+ _set_error("Expected an indented block after \"while\".");
p_block->end_line = tokenizer->get_token_line();
return;
}
@@ -3045,7 +3045,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
if (!tokenizer->is_token_literal(0, true)) {
- _set_error("identifier expected after 'for'");
+ _set_error("Identifier expected after \"for\".");
}
IdentifierNode *id = alloc_node<IdentifierNode>();
@@ -3054,7 +3054,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_OP_IN) {
- _set_error("'in' expected after identifier");
+ _set_error("\"in\" expected after identifier.");
return;
}
@@ -3144,7 +3144,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
p_block->sub_blocks.push_back(cf_for->body);
if (!_enter_indent_block(cf_for->body)) {
- _set_error("Expected indented block after 'for'");
+ _set_error("Expected indented block after \"for\".");
p_block->end_line = tokenizer->get_token_line();
return;
}
@@ -3176,7 +3176,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
cf_continue->cf_type = ControlFlowNode::CF_CONTINUE;
p_block->statements.push_back(cf_continue);
if (!_end_statement()) {
- _set_error("Expected end of statement (continue)");
+ _set_error("Expected end of statement (\"continue\").");
return;
}
} break;
@@ -3187,7 +3187,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
cf_break->cf_type = ControlFlowNode::CF_BREAK;
p_block->statements.push_back(cf_break);
if (!_end_statement()) {
- _set_error("Expected end of statement (break)");
+ _set_error("Expected end of statement (\"break\").");
return;
}
} break;
@@ -3241,7 +3241,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
match_node->val_to_match = val_to_match;
if (!_enter_indent_block()) {
- _set_error("Expected indented pattern matching block after 'match'");
+ _set_error("Expected indented pattern matching block after \"match\".");
return;
}
@@ -3280,7 +3280,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
p_block->statements.push_back(an);
if (!_end_statement()) {
- _set_error("Expected end of statement after assert.");
+ _set_error("Expected end of statement after \"assert\".");
return;
}
} break;
@@ -3291,7 +3291,7 @@ void GDScriptParser::_parse_block(BlockNode *p_block, bool p_static) {
p_block->statements.push_back(bn);
if (!_end_statement()) {
- _set_error("Expected end of statement after breakpoint.");
+ _set_error("Expected end of statement after \"breakpoint\".");
return;
}
} break;
@@ -3323,7 +3323,7 @@ bool GDScriptParser::_parse_newline() {
int current_indent = tab_level.back()->get();
if (indent > current_indent) {
- _set_error("Unexpected indent.");
+ _set_error("Unexpected indentation.");
return false;
}
@@ -3333,7 +3333,7 @@ bool GDScriptParser::_parse_newline() {
//exit block
if (tab_level.size() == 1) {
- _set_error("Invalid indent. BUG?");
+ _set_error("Invalid indentation. Bug?");
return false;
}
@@ -3360,13 +3360,13 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) {
if (p_class->extends_used) {
- _set_error("'extends' already used for this class.");
+ _set_error("\"extends\" can only be present once per script.");
return;
}
if (!p_class->constant_expressions.empty() || !p_class->subclasses.empty() || !p_class->functions.empty() || !p_class->variables.empty() || p_class->classname_used) {
- _set_error("'extends' must be used before anything else.");
+ _set_error("\"extends\" must be used before anything else.");
return;
}
@@ -3386,7 +3386,7 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) {
Variant constant = tokenizer->get_token_constant();
if (constant.get_type() != Variant::STRING) {
- _set_error("'extends' constant must be a string.");
+ _set_error("\"extends\" constant must be a string.");
return;
}
@@ -3421,7 +3421,7 @@ void GDScriptParser::_parse_extends(ClassNode *p_class) {
default: {
- _set_error("Invalid 'extends' syntax, expected string constant (path) and/or identifier (parent class).");
+ _set_error("Invalid \"extends\" syntax, expected string constant (path) and/or identifier (parent class).");
return;
}
}
@@ -3481,7 +3481,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (error_set)
return;
if (!_end_statement()) {
- _set_error("Expected end of statement after extends");
+ _set_error("Expected end of statement after \"extends\".");
return;
}
@@ -3490,20 +3490,20 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
_mark_line_as_safe(tokenizer->get_token_line());
if (p_class->owner) {
- _set_error("'class_name' is only valid for the main class namespace.");
+ _set_error("\"class_name\" is only valid for the main class namespace.");
return;
}
if (self_path.begins_with("res://") && self_path.find("::") != -1) {
- _set_error("'class_name' not allowed in built-in scripts.");
+ _set_error("\"class_name\" isn't allowed in built-in scripts.");
return;
}
if (tokenizer->get_token(1) != GDScriptTokenizer::TK_IDENTIFIER) {
- _set_error("'class_name' syntax: 'class_name <UniqueName>'");
+ _set_error("\"class_name\" syntax: \"class_name <UniqueName>\"");
return;
}
if (p_class->classname_used) {
- _set_error("'class_name' already used for this class.");
+ _set_error("\"class_name\" can only be present once per script.");
return;
}
@@ -3512,12 +3512,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
p_class->name = tokenizer->get_token_identifier(1);
if (self_path != String() && ScriptServer::is_global_class(p_class->name) && ScriptServer::get_global_class_path(p_class->name) != self_path) {
- _set_error("Unique global class '" + p_class->name + "' already exists at path: " + ScriptServer::get_global_class_path(p_class->name));
+ _set_error("Unique global class \"" + p_class->name + "\" already exists at path: " + ScriptServer::get_global_class_path(p_class->name));
return;
}
if (ClassDB::class_exists(p_class->name)) {
- _set_error("Class '" + p_class->name + "' shadows a native class.");
+ _set_error("The class \"" + p_class->name + "\" shadows a native class.");
return;
}
@@ -3544,12 +3544,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
} else {
- _set_error("Optional parameter after 'class_name' must be a string constant file path to an icon.");
+ _set_error("The optional parameter after \"class_name\" must be a string constant file path to an icon.");
return;
}
} else if (tokenizer->get_token() == GDScriptTokenizer::TK_CONSTANT) {
- _set_error("Class icon must be separated by a comma.");
+ _set_error("The class icon must be separated by a comma.");
return;
}
@@ -3558,7 +3558,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (p_class->tool) {
- _set_error("tool used more than once");
+ _set_error("The \"tool\" keyword can only be present once per script.");
return;
}
@@ -3573,7 +3573,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token(1) != GDScriptTokenizer::TK_IDENTIFIER) {
- _set_error("'class' syntax: 'class <Name>:' or 'class <Name> extends <BaseClass>:'");
+ _set_error("\"class\" syntax: \"class <Name>:\" or \"class <Name> extends <BaseClass>:\"");
return;
}
name = tokenizer->get_token_identifier(1);
@@ -3581,23 +3581,23 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
// Check if name is shadowing something else
if (ClassDB::class_exists(name) || ClassDB::class_exists("_" + name.operator String())) {
- _set_error("Class '" + String(name) + "' shadows a native class.");
+ _set_error("The class \"" + String(name) + "\" shadows a native class.");
return;
}
if (ScriptServer::is_global_class(name)) {
- _set_error("Can't override name of unique global class '" + name + "' already exists at path: " + ScriptServer::get_global_class_path(p_class->name));
+ _set_error("Can't override name of the unique global class \"" + name + "\". It already exists at: " + ScriptServer::get_global_class_path(p_class->name));
return;
}
ClassNode *outer_class = p_class;
while (outer_class) {
for (int i = 0; i < outer_class->subclasses.size(); i++) {
if (outer_class->subclasses[i]->name == name) {
- _set_error("Another class named '" + String(name) + "' already exists in this scope (at line " + itos(outer_class->subclasses[i]->line) + ").");
+ _set_error("Another class named \"" + String(name) + "\" already exists in this scope (at line " + itos(outer_class->subclasses[i]->line) + ").");
return;
}
}
if (outer_class->constant_expressions.has(name)) {
- _set_error("A constant named '" + String(name) + "' already exists in the outer class scope (at line" + itos(outer_class->constant_expressions[name].expression->line) + ").");
+ _set_error("A constant named \"" + String(name) + "\" already exists in the outer class scope (at line" + itos(outer_class->constant_expressions[name].expression->line) + ").");
return;
}
@@ -3641,7 +3641,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
- _set_error("Expected 'func'.");
+ _set_error("Expected \"func\".");
return;
}
@@ -3665,18 +3665,18 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (name == StringName()) {
- _set_error("Expected identifier after 'func' (syntax: 'func <identifier>([arguments]):' ).");
+ _set_error("Expected an identifier after \"func\" (syntax: \"func <identifier>([arguments]):\").");
return;
}
for (int i = 0; i < p_class->functions.size(); i++) {
if (p_class->functions[i]->name == name) {
- _set_error("Function '" + String(name) + "' already exists in this class (at line: " + itos(p_class->functions[i]->line) + ").");
+ _set_error("The function \"" + String(name) + "\" already exists in this class (at line " + itos(p_class->functions[i]->line) + ").");
}
}
for (int i = 0; i < p_class->static_functions.size(); i++) {
if (p_class->static_functions[i]->name == name) {
- _set_error("Function '" + String(name) + "' already exists in this class (at line: " + itos(p_class->static_functions[i]->line) + ").");
+ _set_error("The function \"" + String(name) + "\" already exists in this class (at line " + itos(p_class->static_functions[i]->line) + ").");
}
}
@@ -3698,7 +3698,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
- _set_error("Expected '(' after identifier (syntax: 'func <identifier>([arguments]):' ).");
+ _set_error("Expected \"(\" after the identifier (syntax: \"func <identifier>([arguments]):\" ).");
return;
}
@@ -3730,7 +3730,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (!tokenizer->is_token_literal(0, true)) {
- _set_error("Expected identifier for argument.");
+ _set_error("Expected an identifier for an argument.");
return;
}
@@ -3748,7 +3748,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
argtype.infer_type = true;
tokenizer->advance();
} else if (!_parse_type(argtype)) {
- _set_error("Expected type for argument.");
+ _set_error("Expected a type for an argument.");
return;
}
}
@@ -3797,7 +3797,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
continue;
} else if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ',' or ')'.");
+ _set_error("Expected \",\" or \")\".");
return;
}
@@ -3826,7 +3826,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (name == "_init") {
if (_static) {
- _set_error("Constructor cannot be static.");
+ _set_error("The constructor cannot be static.");
return;
}
@@ -3843,7 +3843,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_PERIOD) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_OPEN) {
- _set_error("expected '(' for parent constructor arguments.");
+ _set_error("Expected \"(\" for parent constructor arguments.");
return;
}
tokenizer->advance();
@@ -3863,7 +3863,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
continue;
} else if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ',' or ')'.");
+ _set_error("Expected \",\" or \")\".");
return;
}
@@ -3888,7 +3888,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_FORWARD_ARROW) {
if (!_parse_type(return_type, true)) {
- _set_error("Expected return type for function.");
+ _set_error("Expected a return type for the function.");
return;
}
}
@@ -3918,7 +3918,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (!tokenizer->is_token_literal()) {
- _set_error("Expected identifier after 'signal'.");
+ _set_error("Expected an identifier after \"signal\".");
return;
}
@@ -3942,7 +3942,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
if (!tokenizer->is_token_literal(0, true)) {
- _set_error("Expected identifier in signal argument.");
+ _set_error("Expected an identifier in a \"signal\" argument.");
return;
}
@@ -3956,7 +3956,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
} else if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ',' or ')' after signal parameter identifier.");
+ _set_error("Expected \",\" or \")\" after a \"signal\" parameter identifier.");
return;
}
}
@@ -3965,7 +3965,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
p_class->_signals.push_back(sig);
if (!_end_statement()) {
- _set_error("Expected end of statement (signal)");
+ _set_error("Expected end of statement (\"signal\").");
return;
}
} break;
@@ -4024,7 +4024,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
break;
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
- _set_error("Expected ',' in bit flags hint.");
+ _set_error("Expected \",\" in the bit flags hint.");
return;
}
@@ -4036,7 +4036,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
current_export = PropertyInfo();
- _set_error("Expected a string constant in named bit flags hint.");
+ _set_error("Expected a string constant in the named bit flags hint.");
return;
}
@@ -4054,7 +4054,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
current_export = PropertyInfo();
- _set_error("Expected ')' or ',' in named bit flags hint.");
+ _set_error("Expected \")\" or \",\" in the named bit flags hint.");
return;
}
tokenizer->advance();
@@ -4067,7 +4067,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in layers 2D render hint.");
+ _set_error("Expected \")\" in the layers 2D render hint.");
return;
}
current_export.hint = PROPERTY_HINT_LAYERS_2D_RENDER;
@@ -4078,7 +4078,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in layers 2D physics hint.");
+ _set_error("Expected \")\" in the layers 2D physics hint.");
return;
}
current_export.hint = PROPERTY_HINT_LAYERS_2D_PHYSICS;
@@ -4089,7 +4089,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in layers 3D render hint.");
+ _set_error("Expected \")\" in the layers 3D render hint.");
return;
}
current_export.hint = PROPERTY_HINT_LAYERS_3D_RENDER;
@@ -4100,7 +4100,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in layers 3D physics hint.");
+ _set_error("Expected \")\" in the layers 3D physics hint.");
return;
}
current_export.hint = PROPERTY_HINT_LAYERS_3D_PHYSICS;
@@ -4116,7 +4116,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
current_export = PropertyInfo();
- _set_error("Expected a string constant in enumeration hint.");
+ _set_error("Expected a string constant in the enumeration hint.");
return;
}
@@ -4134,7 +4134,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
current_export = PropertyInfo();
- _set_error("Expected ')' or ',' in enumeration hint.");
+ _set_error("Expected \")\" or \",\" in the enumeration hint.");
return;
}
@@ -4152,7 +4152,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
current_export.hint = PROPERTY_HINT_EXP_EASING;
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in hint.");
+ _set_error("Expected \")\" in the hint.");
return;
}
break;
@@ -4167,7 +4167,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_PARENTHESIS_CLOSE)
break;
else if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
- _set_error("Expected ')' or ',' in exponential range hint.");
+ _set_error("Expected \")\" or \",\" in the exponential range hint.");
return;
}
tokenizer->advance();
@@ -4183,7 +4183,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
current_export = PropertyInfo();
- _set_error("Expected a range in numeric hint.");
+ _set_error("Expected a range in the numeric hint.");
return;
}
@@ -4198,7 +4198,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
current_export = PropertyInfo();
- _set_error("Expected ',' or ')' in numeric range hint.");
+ _set_error("Expected \",\" or \")\" in the numeric range hint.");
return;
}
@@ -4213,7 +4213,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
current_export = PropertyInfo();
- _set_error("Expected a number as upper bound in numeric range hint.");
+ _set_error("Expected a number as upper bound in the numeric range hint.");
return;
}
@@ -4226,7 +4226,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
current_export = PropertyInfo();
- _set_error("Expected ',' or ')' in numeric range hint.");
+ _set_error("Expected \",\" or \")\" in the numeric range hint.");
return;
}
@@ -4240,7 +4240,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || !tokenizer->get_token_constant().is_num()) {
current_export = PropertyInfo();
- _set_error("Expected a number as step in numeric range hint.");
+ _set_error("Expected a number as step in the numeric range hint.");
return;
}
@@ -4259,7 +4259,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
current_export = PropertyInfo();
- _set_error("Expected a string constant in enumeration hint.");
+ _set_error("Expected a string constant in the enumeration hint.");
return;
}
@@ -4276,7 +4276,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
current_export = PropertyInfo();
- _set_error("Expected ')' or ',' in enumeration hint.");
+ _set_error("Expected \")\" or \",\" in the enumeration hint.");
return;
}
tokenizer->advance();
@@ -4296,7 +4296,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_IDENTIFIER || !(tokenizer->get_token_identifier() == "GLOBAL")) {
- _set_error("Expected 'GLOBAL' after comma in directory hint.");
+ _set_error("Expected \"GLOBAL\" after comma in the directory hint.");
return;
}
if (!p_class->tool) {
@@ -4307,11 +4307,11 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in hint.");
+ _set_error("Expected \")\" in the hint.");
return;
}
} else {
- _set_error("Expected ')' or ',' in hint.");
+ _set_error("Expected \")\" or \",\" in the hint.");
return;
}
break;
@@ -4340,7 +4340,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
else if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA)
tokenizer->advance();
else {
- _set_error("Expected ')' or ',' in hint.");
+ _set_error("Expected \")\" or \",\" in the hint.");
return;
}
}
@@ -4348,9 +4348,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_CONSTANT || tokenizer->get_token_constant().get_type() != Variant::STRING) {
if (current_export.hint == PROPERTY_HINT_GLOBAL_FILE)
- _set_error("Expected string constant with filter");
+ _set_error("Expected string constant with filter.");
else
- _set_error("Expected 'GLOBAL' or string constant with filter");
+ _set_error("Expected \"GLOBAL\" or string constant with filter.");
return;
}
current_export.hint_string = tokenizer->get_token_constant();
@@ -4358,7 +4358,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in hint.");
+ _set_error("Expected \")\" in the hint.");
return;
}
break;
@@ -4369,7 +4369,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
current_export.hint = PROPERTY_HINT_MULTILINE_TEXT;
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
- _set_error("Expected ')' in hint.");
+ _set_error("Expected \")\" in the hint.");
return;
}
break;
@@ -4380,7 +4380,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_IDENTIFIER) {
current_export = PropertyInfo();
- _set_error("Color type hint expects RGB or RGBA as hints");
+ _set_error("Color type hint expects RGB or RGBA as hints.");
return;
}
@@ -4391,7 +4391,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
//none
} else {
current_export = PropertyInfo();
- _set_error("Color type hint expects RGB or RGBA as hints");
+ _set_error("Color type hint expects RGB or RGBA as hints.");
return;
}
tokenizer->advance();
@@ -4400,7 +4400,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
default: {
current_export = PropertyInfo();
- _set_error("Type '" + Variant::get_type_name(type) + "' can't take hints.");
+ _set_error("Type \"" + Variant::get_type_name(type) + "\" can't take hints.");
return;
} break;
}
@@ -4438,7 +4438,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
} else {
current_export = PropertyInfo();
- _set_error("Export hint not a resource type.");
+ _set_error("The export hint isn't a resource type.");
}
} else if (constant.get_type() == Variant::DICTIONARY) {
// Enumeration
@@ -4452,7 +4452,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
} else {
current_export = PropertyInfo();
- _set_error("Expected 'FLAGS' after comma.");
+ _set_error("Expected \"FLAGS\" after comma.");
}
}
@@ -4489,7 +4489,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_PARENTHESIS_CLOSE) {
current_export = PropertyInfo();
- _set_error("Expected ')' or ',' after export hint.");
+ _set_error("Expected \")\" or \",\" after the export hint.");
return;
}
@@ -4509,7 +4509,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_ONREADY && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTE && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTER && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPET && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_REMOTESYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_MASTERSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_PUPPETSYNC && tokenizer->get_token() != GDScriptTokenizer::TK_PR_SLAVE) {
current_export = PropertyInfo();
- _set_error("Expected 'var', 'onready', 'remote', 'master', 'puppet', 'sync', 'remotesync', 'mastersync', 'puppetsync'.");
+ _set_error("Expected \"var\", \"onready\", \"remote\", \"master\", \"puppet\", \"sync\", \"remotesync\", \"mastersync\", \"puppetsync\".");
return;
}
@@ -4520,7 +4520,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
//may be fallthrough from export, ignore if so
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR) {
- _set_error("Expected 'var'.");
+ _set_error("Expected \"var\".");
return;
}
@@ -4532,13 +4532,13 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (current_export.type) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR) {
- _set_error("Expected 'var'.");
+ _set_error("Expected \"var\".");
return;
}
} else {
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
- _set_error("Expected 'var' or 'func'.");
+ _set_error("Expected \"var\" or \"func\".");
return;
}
}
@@ -4552,13 +4552,13 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (current_export.type) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR) {
- _set_error("Expected 'var'.");
+ _set_error("Expected \"var\".");
return;
}
} else {
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
- _set_error("Expected 'var' or 'func'.");
+ _set_error("Expected \"var\" or \"func\".");
return;
}
}
@@ -4577,13 +4577,13 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (current_export.type) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR) {
- _set_error("Expected 'var'.");
+ _set_error("Expected \"var\".");
return;
}
} else {
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
- _set_error("Expected 'var' or 'func'.");
+ _set_error("Expected \"var\" or \"func\".");
return;
}
}
@@ -4598,9 +4598,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
if (current_export.type)
- _set_error("Expected 'var'.");
+ _set_error("Expected \"var\".");
else
- _set_error("Expected 'var' or 'func'.");
+ _set_error("Expected \"var\" or \"func\".");
return;
}
@@ -4613,9 +4613,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
if (current_export.type)
- _set_error("Expected 'var'.");
+ _set_error("Expected \"var\".");
else
- _set_error("Expected 'var' or 'func'.");
+ _set_error("Expected \"var\" or \"func\".");
return;
}
@@ -4628,9 +4628,9 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (tokenizer->get_token() != GDScriptTokenizer::TK_PR_VAR && tokenizer->get_token() != GDScriptTokenizer::TK_PR_FUNCTION) {
if (current_export.type)
- _set_error("Expected 'var'.");
+ _set_error("Expected \"var\".");
else
- _set_error("Expected 'var' or 'func'.");
+ _set_error("Expected \"var\" or \"func\".");
return;
}
@@ -4653,7 +4653,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (!tokenizer->is_token_literal(0, true)) {
- _set_error("Expected identifier for member variable name.");
+ _set_error("Expected an identifier for the member variable name.");
return;
}
@@ -4669,14 +4669,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
#endif
if (current_class->constant_expressions.has(member.identifier)) {
- _set_error("A constant named '" + String(member.identifier) + "' already exists in this class (at line: " +
+ _set_error("A constant named \"" + String(member.identifier) + "\" already exists in this class (at line: " +
itos(current_class->constant_expressions[member.identifier].expression->line) + ").");
return;
}
for (int i = 0; i < current_class->variables.size(); i++) {
if (current_class->variables[i].identifier == member.identifier) {
- _set_error("Variable '" + String(member.identifier) + "' already exists in this class (at line: " +
+ _set_error("Variable \"" + String(member.identifier) + "\" already exists in this class (at line: " +
itos(current_class->variables[i].line) + ").");
return;
}
@@ -4684,7 +4684,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
for (int i = 0; i < current_class->subclasses.size(); i++) {
if (current_class->subclasses[i]->name == member.identifier) {
- _set_error("A class named '" + String(member.identifier) + "' already exists in this class (at line " + itos(current_class->subclasses[i]->line) + ").");
+ _set_error("A class named \"" + String(member.identifier) + "\" already exists in this class (at line " + itos(current_class->subclasses[i]->line) + ").");
return;
}
}
@@ -4714,7 +4714,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
#endif
tokenizer->advance();
} else if (!_parse_type(member.data_type)) {
- _set_error("Expected type for class variable.");
+ _set_error("Expected a type for the class variable.");
return;
}
}
@@ -4742,7 +4742,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
IdentifierNode *id = static_cast<IdentifierNode *>(op->arguments[1]);
if (id->name == "get_node") {
- _set_error("Use 'onready var " + String(member.identifier) + " = get_node(..)' instead");
+ _set_error("Use \"onready var " + String(member.identifier) + " = get_node(...)\" instead.");
return;
}
}
@@ -4770,7 +4770,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
Object *obj = cn->value;
Resource *res = Object::cast_to<Resource>(obj);
if (res == NULL) {
- _set_error("Exported constant not a type or resource.");
+ _set_error("The exported constant isn't a type or resource.");
return;
}
member._export.hint = PROPERTY_HINT_RESOURCE_TYPE;
@@ -4788,7 +4788,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
const Variant *args = &cn->value;
cn->value = Variant::construct(member._export.type, &args, 1, err);
} else {
- _set_error("Cannot convert the provided value to the export type.");
+ _set_error("Can't convert the provided value to the export type.");
return;
}
}
@@ -4886,7 +4886,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() != GDScriptTokenizer::TK_COMMA) {
//just comma means using only getter
if (!tokenizer->is_token_literal()) {
- _set_error("Expected identifier for setter function after 'setget'.");
+ _set_error("Expected an identifier for the setter function after \"setget\".");
}
member.setter = tokenizer->get_token_literal();
@@ -4899,7 +4899,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (!tokenizer->is_token_literal()) {
- _set_error("Expected identifier for getter function after ','.");
+ _set_error("Expected an identifier for the getter function after \",\".");
}
member.getter = tokenizer->get_token_literal();
@@ -4910,7 +4910,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
p_class->variables.push_back(member);
if (!_end_statement()) {
- _set_error("Expected end of statement (continue)");
+ _set_error("Expected end of statement (\"continue\").");
return;
}
} break;
@@ -4922,7 +4922,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
if (!tokenizer->is_token_literal(0, true)) {
- _set_error("Expected name (identifier) for constant.");
+ _set_error("Expected an identifier for the constant.");
return;
}
@@ -4930,14 +4930,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
int line = tokenizer->get_token_line();
if (current_class->constant_expressions.has(const_id)) {
- _set_error("Constant '" + String(const_id) + "' already exists in this class (at line: " +
+ _set_error("Constant \"" + String(const_id) + "\" already exists in this class (at line " +
itos(current_class->constant_expressions[const_id].expression->line) + ").");
return;
}
for (int i = 0; i < current_class->variables.size(); i++) {
if (current_class->variables[i].identifier == const_id) {
- _set_error("A variable named '" + String(const_id) + "' already exists in this class (at line: " +
+ _set_error("A variable named \"" + String(const_id) + "\" already exists in this class (at line " +
itos(current_class->variables[i].line) + ").");
return;
}
@@ -4945,7 +4945,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
for (int i = 0; i < current_class->subclasses.size(); i++) {
if (current_class->subclasses[i]->name == const_id) {
- _set_error("A class named '" + String(const_id) + "' already exists in this class (at line " + itos(current_class->subclasses[i]->line) + ").");
+ _set_error("A class named \"" + String(const_id) + "\" already exists in this class (at line " + itos(current_class->subclasses[i]->line) + ").");
return;
}
}
@@ -4960,13 +4960,13 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
#endif
tokenizer->advance();
} else if (!_parse_type(constant.type)) {
- _set_error("Expected type for class constant.");
+ _set_error("Expected a type for the class constant.");
return;
}
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_OP_ASSIGN) {
- _set_error("Constant expects assignment.");
+ _set_error("Constants must be assigned immediately.");
return;
}
@@ -4981,7 +4981,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
if (subexpr->type != Node::TYPE_CONSTANT) {
- _set_error("Expected constant expression", line);
+ _set_error("Expected a constant expression.", line);
return;
}
subexpr->line = line;
@@ -4990,7 +4990,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
p_class->constant_expressions.insert(const_id, constant);
if (!_end_statement()) {
- _set_error("Expected end of statement (constant)", line);
+ _set_error("Expected end of statement (constant).", line);
return;
}
@@ -5007,14 +5007,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
enum_name = tokenizer->get_token_literal();
if (current_class->constant_expressions.has(enum_name)) {
- _set_error("A constant named '" + String(enum_name) + "' already exists in this class (at line: " +
+ _set_error("A constant named \"" + String(enum_name) + "\" already exists in this class (at line " +
itos(current_class->constant_expressions[enum_name].expression->line) + ").");
return;
}
for (int i = 0; i < current_class->variables.size(); i++) {
if (current_class->variables[i].identifier == enum_name) {
- _set_error("A variable named '" + String(enum_name) + "' already exists in this class (at line: " +
+ _set_error("A variable named \"" + String(enum_name) + "\" already exists in this class (at line " +
itos(current_class->variables[i].line) + ").");
return;
}
@@ -5022,7 +5022,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
for (int i = 0; i < current_class->subclasses.size(); i++) {
if (current_class->subclasses[i]->name == enum_name) {
- _set_error("A class named '" + String(enum_name) + "' already exists in this class (at line " + itos(current_class->subclasses[i]->line) + ").");
+ _set_error("A class named \"" + String(enum_name) + "\" already exists in this class (at line " + itos(current_class->subclasses[i]->line) + ").");
return;
}
}
@@ -5030,7 +5030,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
tokenizer->advance();
}
if (tokenizer->get_token() != GDScriptTokenizer::TK_CURLY_BRACKET_OPEN) {
- _set_error("Expected '{' in enum declaration");
+ _set_error("Expected \"{\" in the enum declaration.");
return;
}
tokenizer->advance();
@@ -5048,7 +5048,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_EOF) {
_set_error("Unexpected end of file.");
} else {
- _set_error(String("Unexpected ") + GDScriptTokenizer::get_token_name(tokenizer->get_token()) + ", expected identifier");
+ _set_error(String("Unexpected ") + GDScriptTokenizer::get_token_name(tokenizer->get_token()) + ", expected an identifier.");
}
return;
@@ -5071,14 +5071,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
if (subexpr->type != Node::TYPE_CONSTANT) {
- _set_error("Expected constant expression");
+ _set_error("Expected a constant expression.");
return;
}
enum_value_expr = static_cast<ConstantNode *>(subexpr);
if (enum_value_expr->value.get_type() != Variant::INT) {
- _set_error("Expected an int value for enum");
+ _set_error("Expected an integer value for \"enum\".");
return;
}
@@ -5094,7 +5094,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
} else if (tokenizer->is_token_literal(0, true)) {
- _set_error("Unexpected identifier");
+ _set_error("Unexpected identifier.");
return;
}
@@ -5102,14 +5102,14 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
enum_dict[const_id] = enum_value_expr->value;
} else {
if (current_class->constant_expressions.has(const_id)) {
- _set_error("A constant named '" + String(const_id) + "' already exists in this class (at line: " +
+ _set_error("A constant named \"" + String(const_id) + "\" already exists in this class (at line " +
itos(current_class->constant_expressions[const_id].expression->line) + ").");
return;
}
for (int i = 0; i < current_class->variables.size(); i++) {
if (current_class->variables[i].identifier == const_id) {
- _set_error("A variable named '" + String(const_id) + "' already exists in this class (at line: " +
+ _set_error("A variable named \"" + String(const_id) + "\" already exists in this class (at line " +
itos(current_class->variables[i].line) + ").");
return;
}
@@ -5117,7 +5117,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
for (int i = 0; i < current_class->subclasses.size(); i++) {
if (current_class->subclasses[i]->name == const_id) {
- _set_error("A class named '" + String(const_id) + "' already exists in this class (at line " + itos(current_class->subclasses[i]->line) + ").");
+ _set_error("A class named \"" + String(const_id) + "\" already exists in this class (at line " + itos(current_class->subclasses[i]->line) + ").");
return;
}
}
@@ -5144,7 +5144,7 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
}
if (!_end_statement()) {
- _set_error("Expected end of statement (enum)");
+ _set_error("Expected end of statement (\"enum\").");
return;
}
@@ -5190,19 +5190,19 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive
String base = base_path;
if (base == "" || base.is_rel_path()) {
- _set_error("Could not resolve relative path for parent class: " + path, p_class->line);
+ _set_error("Couldn't resolve relative path for the parent class: " + path, p_class->line);
return;
}
path = base.plus_file(path).simplify_path();
}
script = ResourceLoader::load(path);
if (script.is_null()) {
- _set_error("Could not load base class: " + path, p_class->line);
+ _set_error("Couldn't load the base class: " + path, p_class->line);
return;
}
if (!script->is_valid()) {
- _set_error("Script not fully loaded (cyclic preload?): " + path, p_class->line);
+ _set_error("Script isn't fully loaded (cyclic preload?): " + path, p_class->line);
return;
}
@@ -5217,7 +5217,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive
script = subclass;
} else {
- _set_error("Could not find subclass: " + sub, p_class->line);
+ _set_error("Couldn't find the subclass: " + sub, p_class->line);
return;
}
}
@@ -5239,7 +5239,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive
if (ScriptServer::is_global_class(base)) {
base_script = ResourceLoader::load(ScriptServer::get_global_class_path(base));
if (!base_script.is_valid()) {
- _set_error("Class '" + base + "' could not be fully loaded (script error or cyclic dependency).", p_class->line);
+ _set_error("The class \"" + base + "\" couldn't be fully loaded (script error or cyclic dependency).", p_class->line);
return;
}
p = NULL;
@@ -5280,13 +5280,13 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive
if (p->constant_expressions.has(base)) {
if (p->constant_expressions[base].expression->type != Node::TYPE_CONSTANT) {
- _set_error("Could not resolve constant '" + base + "'.", p_class->line);
+ _set_error("Couldn't resolve the constant \"" + base + "\".", p_class->line);
return;
}
const ConstantNode *cn = static_cast<const ConstantNode *>(p->constant_expressions[base].expression);
base_script = cn->value;
if (base_script.is_null()) {
- _set_error("Constant is not a class: " + base, p_class->line);
+ _set_error("Constant isn't a class: " + base, p_class->line);
return;
}
break;
@@ -5313,13 +5313,13 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive
Ref<GDScript> new_base_class = base_script->get_constants()[subclass];
if (new_base_class.is_null()) {
- _set_error("Constant is not a class: " + ident, p_class->line);
+ _set_error("Constant isn't a class: " + ident, p_class->line);
return;
}
find_subclass = new_base_class;
} else {
- _set_error("Could not find subclass: " + ident, p_class->line);
+ _set_error("Couldn't find the subclass: " + ident, p_class->line);
return;
}
}
@@ -5330,13 +5330,13 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive
if (p_class->extends_class.size() > 1) {
- _set_error("Invalid inheritance (unknown class + subclasses)", p_class->line);
+ _set_error("Invalid inheritance (unknown class + subclasses).", p_class->line);
return;
}
//if not found, try engine classes
if (!GDScriptLanguage::get_singleton()->get_global_map().has(base)) {
- _set_error("Unknown class: '" + base + "'", p_class->line);
+ _set_error("Unknown class: \"" + base + "\"", p_class->line);
return;
}
@@ -5358,7 +5358,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class, bool p_recursive
p_class->base_type.kind = DataType::NATIVE;
p_class->base_type.native_type = native;
} else {
- _set_error("Could not determine inheritance", p_class->line);
+ _set_error("Couldn't determine inheritance.", p_class->line);
return;
}
@@ -5503,7 +5503,7 @@ bool GDScriptParser::_parse_type(DataType &r_type, bool p_can_be_void) {
switch (tokenizer->get_token()) {
case GDScriptTokenizer::TK_PERIOD: {
if (!can_index) {
- _set_error("Unexpected '.'.");
+ _set_error("Unexpected \".\".");
return false;
}
can_index = false;
@@ -5534,7 +5534,7 @@ bool GDScriptParser::_parse_type(DataType &r_type, bool p_can_be_void) {
}
if (tokenizer->get_token(-1) == GDScriptTokenizer::TK_PERIOD) {
- _set_error("Expected subclass identifier.");
+ _set_error("Expected a subclass identifier.");
return false;
}
@@ -5572,7 +5572,7 @@ GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source,
Ref<GDScript> gds = script;
if (gds.is_valid()) {
if (!gds->is_valid()) {
- _set_error("Class '" + id + "' could not be fully loaded (script error or cyclic dependency).", p_line);
+ _set_error("The class \"" + id + "\" couldn't be fully loaded (script error or cyclic dependency).", p_line);
return DataType();
}
result.kind = DataType::GDSCRIPT;
@@ -5581,7 +5581,7 @@ GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source,
result.kind = DataType::SCRIPT;
result.script_type = script;
} else {
- _set_error("Class '" + id + "' was found in global scope but its script could not be loaded.", p_line);
+ _set_error("The class \"" + id + "\" was found in global scope, but its script couldn't be loaded.", p_line);
return DataType();
}
}
@@ -5682,8 +5682,8 @@ GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source,
} else {
base = result.to_string();
}
- _set_error("Identifier '" + String(id) + "' is not a valid type (not a script or class), or could not be found on base '" +
- base + "'.",
+ _set_error("The identifier \"" + String(id) + "\" isn't a valid type (not a script or class), or couldn't be found on base \"" +
+ base + "\".",
p_line);
return DataType();
}
@@ -6147,8 +6147,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
}
if (!valid) {
- _set_error("Invalid cast. Cannot convert from '" + source_type.to_string() +
- "' to '" + cn->cast_type.to_string() + "'.",
+ _set_error("Invalid cast. Cannot convert from \"" + source_type.to_string() +
+ "\" to \"" + cn->cast_type.to_string() + "\".",
cn->line);
return DataType();
}
@@ -6177,11 +6177,11 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
DataType signal_type = _reduce_node_type(op->arguments[1]);
// TODO: Check if signal exists when it's a constant
if (base_type.has_type && base_type.kind == DataType::BUILTIN && base_type.builtin_type != Variant::NIL && base_type.builtin_type != Variant::OBJECT) {
- _set_error("First argument of 'yield()' must be an object.", op->line);
+ _set_error("The first argument of \"yield()\" must be an object.", op->line);
return DataType();
}
if (signal_type.has_type && (signal_type.kind != DataType::BUILTIN || signal_type.builtin_type != Variant::STRING)) {
- _set_error("Second argument of 'yield()' must be a string.", op->line);
+ _set_error("The second argument of \"yield()\" must be a string.", op->line);
return DataType();
}
}
@@ -6201,15 +6201,15 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
if (check_types && type_type.has_type) {
if (!type_type.is_meta_type && (type_type.kind != DataType::NATIVE || !ClassDB::is_parent_class(type_type.native_type, "Script"))) {
- _set_error("Invalid 'is' test: right operand is not a type (not a native type nor a script).", op->line);
+ _set_error("Invalid \"is\" test: the right operand isn't a type (neither a native type nor a script).", op->line);
return DataType();
}
type_type.is_meta_type = false; // Test the actual type
if (!_is_type_compatible(type_type, value_type) && !_is_type_compatible(value_type, type_type)) {
if (op->op == OperatorNode::OP_IS) {
- _set_error("A value of type '" + value_type.to_string() + "' will never be an instance of '" + type_type.to_string() + "'.", op->line);
+ _set_error("A value of type \"" + value_type.to_string() + "\" will never be an instance of \"" + type_type.to_string() + "\".", op->line);
} else {
- _set_error("A value of type '" + value_type.to_string() + "' will never be of type '" + type_type.to_string() + "'.", op->line);
+ _set_error("A value of type \"" + value_type.to_string() + "\" will never be of type \"" + type_type.to_string() + "\".", op->line);
}
return DataType();
}
@@ -6237,8 +6237,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
node_type = _get_operation_type(var_op, argument_type, argument_type, valid);
if (check_types && !valid) {
- _set_error("Invalid operand type ('" + argument_type.to_string() +
- "') to unary operator '" + Variant::get_operator_name(var_op) + "'.",
+ _set_error("Invalid operand type (\"" + argument_type.to_string() +
+ "\") to unary operator \"" + Variant::get_operator_name(var_op) + "\".",
op->line, op->column);
return DataType();
}
@@ -6282,8 +6282,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
node_type = _get_operation_type(var_op, argument_a_type, argument_b_type, valid);
if (check_types && !valid) {
- _set_error("Invalid operand types ('" + argument_a_type.to_string() + "' and '" +
- argument_b_type.to_string() + "') to operator '" + Variant::get_operator_name(var_op) + "'.",
+ _set_error("Invalid operand types (\"" + argument_a_type.to_string() + "\" and \"" +
+ argument_b_type.to_string() + "\") to operator \"" + Variant::get_operator_name(var_op) + "\".",
op->line, op->column);
return DataType();
}
@@ -6298,7 +6298,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
// Ternary operators
case OperatorNode::OP_TERNARY_IF: {
if (op->arguments.size() != 3) {
- _set_error("Parser bug: ternary operation without 3 arguments");
+ _set_error("Parser bug: ternary operation without 3 arguments.");
ERR_FAIL_V(DataType());
}
@@ -6331,7 +6331,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
case OperatorNode::OP_ASSIGN_BIT_XOR:
case OperatorNode::OP_INIT_ASSIGN: {
- _set_error("Assignment inside expression is not allowed (parser bug?).", op->line);
+ _set_error("Assignment inside an expression isn't allowed (parser bug?).", op->line);
return DataType();
} break;
@@ -6367,8 +6367,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
if (valid) {
result = _type_from_variant(res);
} else if (check_types) {
- _set_error("Can't get index '" + String(member_id->name.operator String()) + "' on base '" +
- base_type.to_string() + "'.",
+ _set_error("Can't get index \"" + String(member_id->name.operator String()) + "\" on base \"" +
+ base_type.to_string() + "\".",
op->line);
return DataType();
}
@@ -6460,7 +6460,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
}
}
if (error) {
- _set_error("Invalid index type (" + index_type.to_string() + ") for base '" + base_type.to_string() + "'.",
+ _set_error("Invalid index type (" + index_type.to_string() + ") for base \"" + base_type.to_string() + "\".",
op->line);
return DataType();
}
@@ -6493,8 +6493,8 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
node_type = _type_from_variant(res);
node_type.is_constant = false;
} else if (check_types) {
- _set_error("Can't get index '" + String(cn->value) + "' on base '" +
- base_type.to_string() + "'.",
+ _set_error("Can't get index \"" + String(cn->value) + "\" on base \"" +
+ base_type.to_string() + "\".",
op->line);
return DataType();
}
@@ -6504,7 +6504,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
_mark_line_as_unsafe(op->line);
}
} else if (!for_completion && (index_type.kind != DataType::BUILTIN || index_type.builtin_type != Variant::STRING)) {
- _set_error("Only strings can be used as index in the base type '" + base_type.to_string() + "'.", op->line);
+ _set_error("Only strings can be used as an index in the base type \"" + base_type.to_string() + "\".", op->line);
return DataType();
}
}
@@ -6521,7 +6521,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
case Variant::REAL:
case Variant::NODE_PATH:
case Variant::_RID: {
- _set_error("Can't index on a value of type '" + base_type.to_string() + "'.", op->line);
+ _set_error("Can't index on a value of type \"" + base_type.to_string() + "\".", op->line);
return DataType();
} break;
// Return int
@@ -6919,7 +6919,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
if (check_types) {
if (!tmp.has_method(callee_name)) {
- _set_error("Method '" + callee_name + "' is not declared on base '" + base_type.to_string() + "'.", p_call->line);
+ _set_error("The method \"" + callee_name + "\" isn't declared on base \"" + base_type.to_string() + "\".", p_call->line);
return DataType();
}
@@ -6979,7 +6979,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
if (!valid) {
#ifdef DEBUG_ENABLED
if (p_call->arguments[0]->type == Node::TYPE_SELF) {
- _set_error("Method '" + callee_name + "' is not declared in the current class.", p_call->line);
+ _set_error("The method \"" + callee_name + "\" isn't declared in the current class.", p_call->line);
return DataType();
}
DataType tmp_type;
@@ -7004,7 +7004,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
}
if (check_types && !is_static && !is_initializer && base_type.is_meta_type) {
- _set_error("Non-static function '" + String(callee_name) + "' can only be called from an instance.", p_call->line);
+ _set_error("Non-static function \"" + String(callee_name) + "\" can only be called from an instance.", p_call->line);
return DataType();
}
@@ -7029,11 +7029,11 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
}
if (arg_count < arg_types.size() - default_args_count) {
- _set_error("Too few arguments for '" + callee_name + "()' call. Expected at least " + itos(arg_types.size() - default_args_count) + ".", p_call->line);
+ _set_error("Too few arguments for \"" + callee_name + "()\" call. Expected at least " + itos(arg_types.size() - default_args_count) + ".", p_call->line);
return return_type;
}
if (!is_vararg && arg_count > arg_types.size()) {
- _set_error("Too many arguments for '" + callee_name + "()' call. Expected at most " + itos(arg_types.size()) + ".", p_call->line);
+ _set_error("Too many arguments for \"" + callee_name + "()\" call. Expected at most " + itos(arg_types.size()) + ".", p_call->line);
return return_type;
}
@@ -7055,7 +7055,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
} else if (!_is_type_compatible(arg_types[i - arg_diff], par_type, true)) {
// Supertypes are acceptable for dynamic compliance
if (!_is_type_compatible(par_type, arg_types[i - arg_diff])) {
- _set_error("At '" + callee_name + "()' call, argument " + itos(i - arg_diff + 1) + ". Assigned type (" +
+ _set_error("At \"" + callee_name + "()\" call, argument " + itos(i - arg_diff + 1) + ". Assigned type (" +
par_type.to_string() + ") doesn't match the function argument's type (" +
arg_types[i - arg_diff].to_string() + ").",
p_call->line);
@@ -7203,7 +7203,7 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
}
if (!ClassDB::class_exists(native)) {
if (!check_types) return false;
- ERR_FAIL_V_MSG(false, "Parser bug: Class '" + String(native) + "' not found.");
+ ERR_FAIL_V_MSG(false, "Parser bug: Class \"" + String(native) + "\" not found.");
}
bool valid = false;
@@ -7373,7 +7373,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType
Ref<GDScript> gds = scr;
if (gds.is_valid()) {
if (!gds->is_valid()) {
- _set_error("Class '" + p_identifier + "' could not be fully loaded (script error or cyclic dependency).");
+ _set_error("The class \"" + p_identifier + "\" couldn't be fully loaded (script error or cyclic dependency).");
return DataType();
}
result.kind = DataType::GDSCRIPT;
@@ -7382,7 +7382,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType
}
return result;
}
- _set_error("Class '" + p_identifier + "' was found in global scope but its script could not be loaded.");
+ _set_error("The class \"" + p_identifier + "\" was found in global scope, but its script couldn't be loaded.");
return DataType();
}
@@ -7425,7 +7425,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType
Ref<GDScript> gds = singleton;
if (gds.is_valid()) {
if (!gds->is_valid()) {
- _set_error("Couldn't fully load singleton script '" + p_identifier + "' (possible cyclic reference or parse error).", p_line);
+ _set_error("Couldn't fully load the singleton script \"" + p_identifier + "\" (possible cyclic reference or parse error).", p_line);
return DataType();
}
result.kind = DataType::GDSCRIPT;
@@ -7437,7 +7437,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType
}
// This means looking in the current class, which type is always known
- _set_error("Identifier '" + p_identifier.operator String() + "' is not declared in the current scope.", p_line);
+ _set_error("The identifier \"" + p_identifier.operator String() + "\" isn't declared in the current scope.", p_line);
}
#ifdef DEBUG_ENABLED
@@ -7469,7 +7469,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
DataType expr = _resolve_type(c.expression->get_datatype(), c.expression->line);
if (check_types && !_is_type_compatible(cont, expr)) {
- _set_error("Constant value type (" + expr.to_string() + ") is not compatible with declared type (" + cont.to_string() + ").",
+ _set_error("The constant value type (" + expr.to_string() + ") isn't compatible with declared type (" + cont.to_string() + ").",
c.expression->line);
return;
}
@@ -7480,7 +7480,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
DataType tmp;
if (_get_member_type(p_class->base_type, E->key(), tmp)) {
- _set_error("Member '" + String(E->key()) + "' already exists in parent class.", c.expression->line);
+ _set_error("The member \"" + String(E->key()) + "\" already exists in a parent class.", c.expression->line);
return;
}
}
@@ -7502,7 +7502,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
DataType tmp;
if (_get_member_type(p_class->base_type, v.identifier, tmp)) {
- _set_error("Member '" + String(v.identifier) + "' already exists in parent class.", v.line);
+ _set_error("The member \"" + String(v.identifier) + "\" already exists in a parent class.", v.line);
return;
}
@@ -7519,7 +7519,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
} else {
// Try with implicit conversion
if (v.data_type.kind != DataType::BUILTIN || !_is_type_compatible(v.data_type, expr_type, true)) {
- _set_error("Assigned expression type (" + expr_type.to_string() + ") doesn't match the variable's type (" +
+ _set_error("The assigned expression's type (" + expr_type.to_string() + ") doesn't match the variable's type (" +
v.data_type.to_string() + ").",
v.line);
return;
@@ -7548,7 +7548,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
if (v.data_type.infer_type) {
if (!expr_type.has_type) {
- _set_error("Assigned value does not have a set type, variable type cannot be inferred.", v.line);
+ _set_error("The assigned value doesn't have a set type; the variable type can't be inferred.", v.line);
return;
}
v.data_type = expr_type;
@@ -7560,7 +7560,7 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
if (v.data_type.has_type && v._export.type != Variant::NIL) {
DataType export_type = _type_from_property(v._export);
if (!_is_type_compatible(v.data_type, export_type, true)) {
- _set_error("Export hint type (" + export_type.to_string() + ") doesn't match the variable's type (" +
+ _set_error("The export hint's type (" + export_type.to_string() + ") doesn't match the variable's type (" +
v.data_type.to_string() + ").",
v.line);
return;
@@ -7579,15 +7579,15 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
if (setter->get_required_argument_count() != 1 &&
!(setter->get_required_argument_count() == 0 && setter->default_values.size() > 0)) {
- _set_error("Setter function needs to receive exactly 1 argument. See '" + setter->name +
- "()' definition at line " + itos(setter->line) + ".",
+ _set_error("The setter function needs to receive exactly 1 argument. See \"" + setter->name +
+ "()\" definition at line " + itos(setter->line) + ".",
v.line);
return;
}
if (!_is_type_compatible(v.data_type, setter->argument_types[0])) {
- _set_error("Setter argument type (" + setter->argument_types[0].to_string() +
- ") doesn't match the variable's type (" + v.data_type.to_string() + "). See '" +
- setter->name + "()' definition at line " + itos(setter->line) + ".",
+ _set_error("The setter argument's type (" + setter->argument_types[0].to_string() +
+ ") doesn't match the variable's type (" + v.data_type.to_string() + "). See \"" +
+ setter->name + "()\" definition at line " + itos(setter->line) + ".",
v.line);
return;
}
@@ -7598,15 +7598,15 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
FunctionNode *getter = p_class->functions[j];
if (getter->get_required_argument_count() != 0) {
- _set_error("Getter function can't receive arguments. See '" + getter->name +
- "()' definition at line " + itos(getter->line) + ".",
+ _set_error("The getter function can't receive arguments. See \"" + getter->name +
+ "()\" definition at line " + itos(getter->line) + ".",
v.line);
return;
}
if (!_is_type_compatible(v.data_type, getter->get_datatype())) {
- _set_error("Getter return type (" + getter->get_datatype().to_string() +
+ _set_error("The getter return type (" + getter->get_datatype().to_string() +
") doesn't match the variable's type (" + v.data_type.to_string() +
- "). See '" + getter->name + "()' definition at line " + itos(getter->line) + ".",
+ "). See \"" + getter->name + "()\" definition at line " + itos(getter->line) + ".",
v.line);
return;
}
@@ -7620,23 +7620,23 @@ void GDScriptParser::_check_class_level_types(ClassNode *p_class) {
for (int j = 0; j < p_class->static_functions.size(); j++) {
if (v.setter == p_class->static_functions[j]->name) {
FunctionNode *setter = p_class->static_functions[j];
- _set_error("Setter can't be a static function. See '" + setter->name + "()' definition at line " + itos(setter->line) + ".", v.line);
+ _set_error("The setter can't be a static function. See \"" + setter->name + "()\" definition at line " + itos(setter->line) + ".", v.line);
return;
}
if (v.getter == p_class->static_functions[j]->name) {
FunctionNode *getter = p_class->static_functions[j];
- _set_error("Getter can't be a static function. See '" + getter->name + "()' definition at line " + itos(getter->line) + ".", v.line);
+ _set_error("The getter can't be a static function. See \"" + getter->name + "()\" definition at line " + itos(getter->line) + ".", v.line);
return;
}
}
if (!found_setter && v.setter != StringName()) {
- _set_error("Setter function is not defined.", v.line);
+ _set_error("The setter function isn't defined.", v.line);
return;
}
if (!found_getter && v.getter != StringName()) {
- _set_error("Getter function is not defined.", v.line);
+ _set_error("The getter function isn't defined.", v.line);
return;
}
}
@@ -7683,7 +7683,7 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) {
if (!_is_type_compatible(p_function->argument_types[i], def_type, true)) {
String arg_name = p_function->arguments[i];
_set_error("Value type (" + def_type.to_string() + ") doesn't match the type of argument '" +
- arg_name + "' (" + p_function->arguments[i] + ")",
+ arg_name + "' (" + p_function->arguments[i] + ").",
p_function->line);
}
}
@@ -7746,21 +7746,21 @@ void GDScriptParser::_check_function_types(FunctionNode *p_function) {
}
}
parent_signature += ")";
- _set_error("Function signature doesn't match the parent. Parent signature is: '" + parent_signature + "'.", p_function->line);
+ _set_error("The function signature doesn't match the parent. Parent signature is: \"" + parent_signature + "\".", p_function->line);
return;
}
}
#endif // DEBUG_ENABLED
} else {
if (p_function->return_type.has_type && (p_function->return_type.kind != DataType::BUILTIN || p_function->return_type.builtin_type != Variant::NIL)) {
- _set_error("Constructor cannot return a value.", p_function->line);
+ _set_error("The constructor can't return a value.", p_function->line);
return;
}
}
if (p_function->return_type.has_type && (p_function->return_type.kind != DataType::BUILTIN || p_function->return_type.builtin_type != Variant::NIL)) {
if (!p_function->body->has_return) {
- _set_error("Non-void function must return a value in all possible paths.", p_function->line);
+ _set_error("A non-void function must return a value in all possible paths.", p_function->line);
return;
}
}
@@ -7891,7 +7891,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
} else {
// Try implicit conversion
if (lv->datatype.kind != DataType::BUILTIN || !_is_type_compatible(lv->datatype, assign_type, true)) {
- _set_error("Assigned value type (" + assign_type.to_string() + ") doesn't match the variable's type (" +
+ _set_error("The assigned value type (" + assign_type.to_string() + ") doesn't match the variable's type (" +
lv->datatype.to_string() + ").",
lv->line);
return;
@@ -7923,7 +7923,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
}
if (lv->datatype.infer_type) {
if (!assign_type.has_type) {
- _set_error("Assigned value does not have a set type, variable type cannot be inferred.", lv->line);
+ _set_error("The assigned value doesn't have a set type; the variable type can't be inferred.", lv->line);
return;
}
lv->datatype = assign_type;
@@ -7974,7 +7974,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
}
}
if (lh_type.is_constant) {
- _set_error("Cannot assign a new value to a constant.", op->line);
+ _set_error("Can't assign a new value to a constant.", op->line);
return;
}
}
@@ -7993,8 +7993,8 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
rh_type = _get_operation_type(oper, lh_type, arg_type, valid);
if (check_types && !valid) {
- _set_error("Invalid operand types ('" + lh_type.to_string() + "' and '" + arg_type.to_string() +
- "') to assignment operator '" + Variant::get_operator_name(oper) + "'.",
+ _set_error("Invalid operand types (\"" + lh_type.to_string() + "\" and \"" + arg_type.to_string() +
+ "\") to assignment operator \"" + Variant::get_operator_name(oper) + "\".",
op->line);
return;
}
@@ -8022,7 +8022,7 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
} else {
// Try implicit conversion
if (lh_type.kind != DataType::BUILTIN || !_is_type_compatible(lh_type, rh_type, true)) {
- _set_error("Assigned value type (" + rh_type.to_string() + ") doesn't match the variable's type (" +
+ _set_error("The assigned value's type (" + rh_type.to_string() + ") doesn't match the variable's type (" +
lh_type.to_string() + ").",
op->line);
return;
@@ -8107,18 +8107,18 @@ void GDScriptParser::_check_block_types(BlockNode *p_block) {
if (function_type.kind == DataType::BUILTIN && function_type.builtin_type == Variant::NIL) {
// Return void, should not have arguments
if (cf->arguments.size() > 0) {
- _set_error("Void function cannot return a value.", cf->line, cf->column);
+ _set_error("A void function cannot return a value.", cf->line, cf->column);
return;
}
} else {
// Return something, cannot be empty
if (cf->arguments.size() == 0) {
- _set_error("Non-void function must return a value.", cf->line, cf->column);
+ _set_error("A non-void function must return a value.", cf->line, cf->column);
return;
}
if (!_is_type_compatible(function_type, ret_type)) {
- _set_error("Returned value type (" + ret_type.to_string() + ") doesn't match the function return type (" +
+ _set_error("The returned value type (" + ret_type.to_string() + ") doesn't match the function return type (" +
function_type.to_string() + ").",
cf->line, cf->column);
return;
@@ -8271,7 +8271,7 @@ Error GDScriptParser::_parse(const String &p_base_path) {
if (tokenizer->get_token() == GDScriptTokenizer::TK_ERROR) {
error_set = false;
- _set_error("Parse Error: " + tokenizer->get_token_error());
+ _set_error("Parse error: " + tokenizer->get_token_error());
}
if (error_set && !for_completion) {
diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java
index f493b5f33f..7f71430805 100644
--- a/platform/android/java/src/org/godotengine/godot/Godot.java
+++ b/platform/android/java/src/org/godotengine/godot/Godot.java
@@ -58,6 +58,7 @@ import android.os.Environment;
import android.os.Messenger;
import android.os.Vibrator;
import android.provider.Settings.Secure;
+import android.support.annotation.Keep;
import android.support.v4.content.ContextCompat;
import android.view.Display;
import android.view.KeyEvent;
@@ -101,7 +102,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
static final int REQUEST_CAMERA_PERMISSION = 2;
static final int REQUEST_VIBRATE_PERMISSION = 3;
private IStub mDownloaderClientStub;
- private IDownloaderService mRemoteService;
private TextView mStatusText;
private TextView mProgressFraction;
private TextView mProgressPercent;
@@ -224,15 +224,9 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
private Sensor mMagnetometer;
private Sensor mGyroscope;
- public FrameLayout layout;
-
public static GodotIO io;
- public static void setWindowTitle(String title) {
- //setTitle(title);
- }
-
- static SingletonBase singletons[] = new SingletonBase[MAX_SINGLETONS];
+ static SingletonBase[] singletons = new SingletonBase[MAX_SINGLETONS];
static int singleton_count = 0;
public interface ResultCallback {
@@ -268,13 +262,14 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
}
};
- public void onVideoInit() {
+ /**
+ * Used by the native code (java_godot_lib_jni.cpp) to complete initialization of the GLSurfaceView view and renderer.
+ */
+ @Keep
+ private void onVideoInit() {
boolean use_gl3 = getGLESVersionCode() >= 0x00030000;
- //mView = new GodotView(getApplication(),io,use_gl3);
- //setContentView(mView);
-
- layout = new FrameLayout(this);
+ final FrameLayout layout = new FrameLayout(this);
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
setContentView(layout);
@@ -326,11 +321,16 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
});
}
- public void vibrate(int p_duration_ms) {
+ /**
+ * Used by the native code (java_godot_wrapper.h) to vibrate the device.
+ * @param durationMs
+ */
+ @Keep
+ private void vibrate(int durationMs) {
if (requestPermission("VIBRATE")) {
Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
if (v != null) {
- v.vibrate(p_duration_ms);
+ v.vibrate(durationMs);
}
}
}
@@ -416,6 +416,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
/**
* Used by the native code (java_godot_wrapper.h) to check whether the activity is resumed or paused.
*/
+ @Keep
private boolean isActivityResumed() {
return activityResumed;
}
@@ -423,10 +424,20 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
/**
* Used by the native code (java_godot_wrapper.h) to access the Android surface.
*/
+ @Keep
private Surface getSurface() {
return mView.getHolder().getSurface();
}
+ /**
+ * Used by the native code (java_godot_wrapper.h) to access the input fallback mapping.
+ * @return The input fallback mapping for the current XR mode.
+ */
+ @Keep
+ private String getInputFallbackMapping() {
+ return xrMode.inputFallbackMapping;
+ }
+
String expansion_pack_path;
private void initializeGodot() {
@@ -474,8 +485,8 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
@Override
public void onServiceConnected(Messenger m) {
- mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
- mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
+ IDownloaderService remoteService = DownloaderServiceMarshaller.CreateProxy(m);
+ remoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
}
@Override
@@ -483,7 +494,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
super.onCreate(icicle);
Window window = getWindow();
- //window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
mClipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
@@ -609,7 +619,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
mWiFiSettingsButton = (Button)findViewById(com.godot.game.R.id.wifiSettingsButton);
return;
- } else {
}
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
@@ -621,8 +630,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
mCurrentIntent = getIntent();
initializeGodot();
-
- //instanceSingleton( new GodotFacebook(this) );
}
@Override
@@ -831,8 +838,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
}
}
- public void forceQuit() {
-
+ private void forceQuit() {
System.exit(0);
}
@@ -879,7 +885,6 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
}
}
- //@Override public boolean dispatchTouchEvent (MotionEvent event) {
public boolean gotTouchEvent(final MotionEvent event) {
final int evcount = event.getPointerCount();
@@ -950,8 +955,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
for (int i = cc.length; --i >= 0; cnt += cc[i] != 0 ? 1 : 0)
;
if (cnt == 0) return super.onKeyMultiple(inKeyCode, repeatCount, event);
- final Activity me = this;
- queueEvent(new Runnable() {
+ mView.queueEvent(new Runnable() {
// This method will be called on the rendering thread:
public void run() {
for (int i = 0, n = cc.length; i < n; i++) {
@@ -967,20 +971,10 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
return true;
}
- private void queueEvent(Runnable runnable) {
- // TODO Auto-generated method stub
- }
-
public PaymentsManager getPaymentsManager() {
return mPaymentsManager;
}
- /*
- public void setPaymentsManager(PaymentsManager mPaymentsManager) {
- this.mPaymentsManager = mPaymentsManager;
- }
- */
-
public boolean requestPermission(String p_name) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// Not necessary, asked on install already
@@ -1025,7 +1019,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC
switch (newState) {
case IDownloaderClient.STATE_IDLE:
// STATE_IDLE means the service is listening, so it's
- // safe to start making calls via mRemoteService.
+ // safe to start making remote service calls.
paused = false;
indeterminate = true;
break;
diff --git a/platform/android/java/src/org/godotengine/godot/GodotLib.java b/platform/android/java/src/org/godotengine/godot/GodotLib.java
index 81c98bcc79..af51c840cb 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotLib.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotLib.java
@@ -30,8 +30,14 @@
package org.godotengine.godot;
-// Wrapper for native library
+import android.app.Activity;
+import android.hardware.SensorEvent;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+/**
+ * Wrapper for native library
+ */
public class GodotLib {
public static GodotIO io;
@@ -41,36 +47,168 @@ public class GodotLib {
}
/**
- * @param width the current view width
- * @param height the current view height
- */
-
+ * Invoked on the main thread to initialize Godot native layer.
+ */
public static native void initialize(Godot p_instance, Object p_asset_manager, boolean use_apk_expansion);
+
+ /**
+ * Invoked on the main thread to clean up Godot native layer.
+ * @see Activity#onDestroy()
+ */
public static native void ondestroy(Godot p_instance);
+
+ /**
+ * Invoked on the GL thread to complete setup for the Godot native layer logic.
+ * @param p_cmdline Command line arguments used to configure Godot native layer components.
+ */
public static native void setup(String[] p_cmdline);
+
+ /**
+ * Invoked on the GL thread when the underlying Android surface has changed size.
+ * @param width
+ * @param height
+ * @see android.opengl.GLSurfaceView.Renderer#onSurfaceChanged(GL10, int, int)
+ */
public static native void resize(int width, int height);
+
+ /**
+ * Invoked on the GL thread when the underlying Android surface is created or recreated.
+ * @param p_32_bits
+ * @see android.opengl.GLSurfaceView.Renderer#onSurfaceCreated(GL10, EGLConfig)
+ */
public static native void newcontext(boolean p_32_bits);
+
+ /**
+ * Forward {@link Activity#onBackPressed()} event from the main thread to the GL thread.
+ */
public static native void back();
+
+ /**
+ * Invoked on the GL thread to draw the current frame.
+ * @see android.opengl.GLSurfaceView.Renderer#onDrawFrame(GL10)
+ */
public static native void step();
+
+ /**
+ * Forward touch events from the main thread to the GL thread.
+ */
public static native void touch(int what, int pointer, int howmany, int[] arr);
+
+ /**
+ * Forward accelerometer sensor events from the main thread to the GL thread.
+ * @see android.hardware.SensorEventListener#onSensorChanged(SensorEvent)
+ */
public static native void accelerometer(float x, float y, float z);
+
+ /**
+ * Forward gravity sensor events from the main thread to the GL thread.
+ * @see android.hardware.SensorEventListener#onSensorChanged(SensorEvent)
+ */
public static native void gravity(float x, float y, float z);
+
+ /**
+ * Forward magnetometer sensor events from the main thread to the GL thread.
+ * @see android.hardware.SensorEventListener#onSensorChanged(SensorEvent)
+ */
public static native void magnetometer(float x, float y, float z);
+
+ /**
+ * Forward gyroscope sensor events from the main thread to the GL thread.
+ * @see android.hardware.SensorEventListener#onSensorChanged(SensorEvent)
+ */
public static native void gyroscope(float x, float y, float z);
+
+ /**
+ * Forward regular key events from the main thread to the GL thread.
+ */
public static native void key(int p_scancode, int p_unicode_char, boolean p_pressed);
+
+ /**
+ * Forward game device's key events from the main thread to the GL thread.
+ */
public static native void joybutton(int p_device, int p_but, boolean p_pressed);
+
+ /**
+ * Forward joystick devices axis motion events from the main thread to the GL thread.
+ */
public static native void joyaxis(int p_device, int p_axis, float p_value);
+
+ /**
+ * Forward joystick devices hat motion events from the main thread to the GL thread.
+ */
public static native void joyhat(int p_device, int p_hat_x, int p_hat_y);
+
+ /**
+ * Fires when a joystick device is added or removed.
+ */
public static native void joyconnectionchanged(int p_device, boolean p_connected, String p_name);
+
+ /**
+ * Invoked when the Android activity resumes.
+ * @see Activity#onResume()
+ */
public static native void focusin();
+
+ /**
+ * Invoked when the Android activity pauses.
+ * @see Activity#onPause()
+ */
public static native void focusout();
+
+ /**
+ * Invoked when the audio thread is started.
+ */
public static native void audio();
+
+ /**
+ * Used to setup a {@link org.godotengine.godot.Godot.SingletonBase} instance.
+ * @param p_name Name of the instance.
+ * @param p_object Reference to the singleton instance.
+ */
public static native void singleton(String p_name, Object p_object);
+
+ /**
+ * Used to complete registration of the {@link org.godotengine.godot.Godot.SingletonBase} instance's methods.
+ * @param p_sname Name of the instance
+ * @param p_name Name of the method to register
+ * @param p_ret Return type of the registered method
+ * @param p_params Method parameters types
+ */
public static native void method(String p_sname, String p_name, String p_ret, String[] p_params);
+
+ /**
+ * Used to access Godot global properties.
+ * @param p_key Property key
+ * @return String value of the property
+ */
public static native String getGlobal(String p_key);
+
+ /**
+ * Invoke method |p_method| on the Godot object specified by |p_id|
+ * @param p_id Id of the Godot object to invoke
+ * @param p_method Name of the method to invoke
+ * @param p_params Parameters to use for method invocation
+ */
public static native void callobject(int p_id, String p_method, Object[] p_params);
+
+ /**
+ * Invoke method |p_method| on the Godot object specified by |p_id| during idle time.
+ * @param p_id Id of the Godot object to invoke
+ * @param p_method Name of the method to invoke
+ * @param p_params Parameters to use for method invocation
+ */
public static native void calldeferred(int p_id, String p_method, Object[] p_params);
+
+ /**
+ * Forward the results from a permission request.
+ * @see Activity#onRequestPermissionsResult(int, String[], int[])
+ * @param p_permission Request permission
+ * @param p_result True if the permission was granted, false otherwise
+ */
public static native void requestPermissionResult(String p_permission, boolean p_result);
+ /**
+ * Invoked on the GL thread to configure the height of the virtual keyboard.
+ */
public static native void setVirtualKeyboardHeight(int p_height);
}
diff --git a/platform/android/java/src/org/godotengine/godot/xr/XRMode.java b/platform/android/java/src/org/godotengine/godot/xr/XRMode.java
index dd5701af7d..5896b23ac3 100644
--- a/platform/android/java/src/org/godotengine/godot/xr/XRMode.java
+++ b/platform/android/java/src/org/godotengine/godot/xr/XRMode.java
@@ -34,16 +34,18 @@ package org.godotengine.godot.xr;
* Godot available XR modes.
*/
public enum XRMode {
- REGULAR(0, "Regular", "--xr_mode_regular"), // Regular/flatscreen
- OVR(1, "Oculus Mobile VR", "--xr_mode_ovr");
+ REGULAR(0, "Regular", "--xr_mode_regular", "Default Android Gamepad"), // Regular/flatscreen
+ OVR(1, "Oculus Mobile VR", "--xr_mode_ovr", "");
final int index;
final String label;
public final String cmdLineArg;
+ public final String inputFallbackMapping;
- XRMode(int index, String label, String cmdLineArg) {
+ XRMode(int index, String label, String cmdLineArg, String inputFallbackMapping) {
this.index = index;
this.label = label;
this.cmdLineArg = cmdLineArg;
+ this.inputFallbackMapping = inputFallbackMapping;
}
}
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 1159e93166..f53df7afe9 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -644,7 +644,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en
godot_java->on_video_init(env);
}
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env) {
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jobject obj, jobject activity) {
// lets cleanup
if (godot_io_java) {
delete godot_io_java;
diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h
index f99935bf7c..66591a2cb2 100644
--- a/platform/android/java_godot_lib_jni.h
+++ b/platform/android/java_godot_lib_jni.h
@@ -38,7 +38,7 @@
// See java/src/org/godotengine/godot/GodotLib.java for the JAVA side of this (yes that's why we have the long names)
extern "C" {
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jobject obj, jobject activity, jobject p_asset_manager, jboolean p_use_apk_expansion);
-JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jobject obj, jobject activity);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jobject obj, jobjectArray p_cmdline);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jobject obj, jint width, jint height);
JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_newcontext(JNIEnv *env, jobject obj, bool p_32_bits);
diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp
index c7dc1d124c..8194ee6ecf 100644
--- a/platform/android/java_godot_wrapper.cpp
+++ b/platform/android/java_godot_wrapper.cpp
@@ -63,6 +63,7 @@ GodotJavaWrapper::GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance) {
_get_surface = p_env->GetMethodID(cls, "getSurface", "()Landroid/view/Surface;");
_is_activity_resumed = p_env->GetMethodID(cls, "isActivityResumed", "()Z");
_vibrate = p_env->GetMethodID(cls, "vibrate", "(I)V");
+ _get_input_fallback_mapping = p_env->GetMethodID(cls, "getInputFallbackMapping", "()Ljava/lang/String;");
}
GodotJavaWrapper::~GodotJavaWrapper() {
@@ -166,6 +167,16 @@ String GodotJavaWrapper::get_clipboard() {
}
}
+String GodotJavaWrapper::get_input_fallback_mapping() {
+ if (_get_input_fallback_mapping) {
+ JNIEnv *env = ThreadAndroid::get_env();
+ jstring fallback_mapping = (jstring)env->CallObjectMethod(godot_instance, _get_input_fallback_mapping);
+ return jstring_to_string(fallback_mapping, env);
+ } else {
+ return String();
+ }
+}
+
bool GodotJavaWrapper::has_set_clipboard() {
return _set_clipboard != 0;
}
diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h
index 3e0e950180..b1bd9b7f48 100644
--- a/platform/android/java_godot_wrapper.h
+++ b/platform/android/java_godot_wrapper.h
@@ -58,6 +58,7 @@ private:
jmethodID _get_surface = 0;
jmethodID _is_activity_resumed = 0;
jmethodID _vibrate = 0;
+ jmethodID _get_input_fallback_mapping = 0;
public:
GodotJavaWrapper(JNIEnv *p_env, jobject p_godot_instance);
@@ -84,6 +85,7 @@ public:
jobject get_surface();
bool is_activity_resumed();
void vibrate(int p_duration_ms);
+ String get_input_fallback_mapping();
};
#endif /* !JAVA_GODOT_WRAPPER_H */
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 9b2df50f6c..49ab0ea84a 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -173,7 +173,7 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int
AudioDriverManager::initialize(p_audio_driver);
input = memnew(InputDefault);
- input->set_fallback_mapping("Default Android Gamepad");
+ input->set_fallback_mapping(godot_java->get_input_fallback_mapping());
///@TODO implement a subclass for Android and instantiate that instead
camera_server = memnew(CameraServer);
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 9cb2915701..f1f37e24d2 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -157,6 +157,26 @@ public:
int video_driver_index;
virtual int get_current_video_driver() const;
+ struct GlobalMenuItem {
+ String label;
+ Variant signal;
+ Variant meta;
+
+ GlobalMenuItem() {
+ //NOP
+ }
+
+ GlobalMenuItem(const String &p_label, const Variant &p_signal, const Variant &p_meta) {
+ label = p_label;
+ signal = p_signal;
+ meta = p_meta;
+ }
+ };
+
+ Map<String, Vector<GlobalMenuItem> > global_menus;
+
+ void _update_global_menu();
+
protected:
virtual void initialize_core();
virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@@ -168,6 +188,11 @@ protected:
public:
static OS_OSX *singleton;
+ void global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta);
+ void global_menu_add_separator(const String &p_menu);
+ void global_menu_remove_item(const String &p_menu, int p_idx);
+ void global_menu_clear(const String &p_menu);
+
void wm_minimized(bool p_minimized);
virtual String get_name() const;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index ab77897b08..f48d4a307d 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -204,11 +204,53 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
}
}
+- (void)globalMenuCallback:(id)sender {
+
+ if (![sender representedObject])
+ return;
+
+ OS_OSX::GlobalMenuItem *item = (OS_OSX::GlobalMenuItem *)[[sender representedObject] pointerValue];
+
+ if (!item)
+ return;
+
+ OS_OSX::singleton->main_loop->global_menu_action(item->signal, item->meta);
+}
+
+- (NSMenu *)applicationDockMenu:(NSApplication *)sender {
+
+ NSMenu *menu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
+
+ Vector<OS_OSX::GlobalMenuItem> &E = OS_OSX::singleton->global_menus["_dock"];
+ for (int i = 0; i < E.size(); i++) {
+ if (E[i].label == String()) {
+ [menu addItem:[NSMenuItem separatorItem]];
+ } else {
+ NSMenuItem *menu_item = [menu addItemWithTitle:[NSString stringWithUTF8String:E[i].label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:@""];
+ [menu_item setRepresentedObject:[NSValue valueWithPointer:&(E[i])]];
+ }
+ }
+
+ return menu;
+}
+
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
- // Note: called before main loop init!
+ // Note: may be called called before main loop init!
char *utfs = strdup([filename UTF8String]);
OS_OSX::singleton->open_with_filename.parse_utf8(utfs);
free(utfs);
+
+#ifdef TOOLS_ENABLED
+ // Open new instance
+ if (OS_OSX::singleton->get_main_loop()) {
+ List<String> args;
+ args.push_back(OS_OSX::singleton->open_with_filename);
+ String exec = OS::get_singleton()->get_executable_path();
+
+ OS::ProcessID pid = 0;
+ OS::get_singleton()->execute(exec, args, false, &pid);
+ }
+#endif
return YES;
}
@@ -1266,6 +1308,56 @@ inline void sendPanEvent(double dx, double dy, int modifierFlags) {
@end
+void OS_OSX::_update_global_menu() {
+
+ NSMenu *main_menu = [NSApp mainMenu];
+
+ for (int i = 1; i < [main_menu numberOfItems]; i++) {
+ [main_menu removeItemAtIndex:i];
+ }
+ for (Map<String, Vector<GlobalMenuItem> >::Element *E = global_menus.front(); E; E = E->next()) {
+ if (E->key() != "_dock") {
+ NSMenu *menu = [[[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:E->key().utf8().get_data()]] autorelease];
+ for (int i = 0; i < E->get().size(); i++) {
+ if (E->get()[i].label == String()) {
+ [menu addItem:[NSMenuItem separatorItem]];
+ } else {
+ NSMenuItem *menu_item = [menu addItemWithTitle:[NSString stringWithUTF8String:E->get()[i].label.utf8().get_data()] action:@selector(globalMenuCallback:) keyEquivalent:@""];
+ [menu_item setRepresentedObject:[NSValue valueWithPointer:&(E->get()[i])]];
+ }
+ }
+ NSMenuItem *menu_item = [main_menu addItemWithTitle:[NSString stringWithUTF8String:E->key().utf8().get_data()] action:nil keyEquivalent:@""];
+ [main_menu setSubmenu:menu forItem:menu_item];
+ }
+ }
+}
+
+void OS_OSX::global_menu_add_item(const String &p_menu, const String &p_label, const Variant &p_signal, const Variant &p_meta) {
+
+ global_menus[p_menu].push_back(GlobalMenuItem(p_label, p_signal, p_meta));
+ _update_global_menu();
+}
+
+void OS_OSX::global_menu_add_separator(const String &p_menu) {
+
+ global_menus[p_menu].push_back(GlobalMenuItem());
+ _update_global_menu();
+}
+
+void OS_OSX::global_menu_remove_item(const String &p_menu, int p_idx) {
+
+ ERR_FAIL_INDEX(p_idx, global_menus[p_menu].size());
+
+ global_menus[p_menu].remove(p_idx);
+ _update_global_menu();
+}
+
+void OS_OSX::global_menu_clear(const String &p_menu) {
+
+ global_menus[p_menu].clear();
+ _update_global_menu();
+}
+
Point2 OS_OSX::get_ime_selection() const {
return im_selection;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 7d1895a67a..1d434e5a2a 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -616,7 +616,7 @@ void TextEdit::_notification(int p_what) {
case NOTIFICATION_RESIZED: {
_update_scrollbars();
- call_deferred("_update_wrap_at");
+ _update_wrap_at();
} break;
case NOTIFICATION_THEME_CHANGED: {
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 98d63650d3..617a703855 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -1673,6 +1673,12 @@ void SceneTree::drop_files(const Vector<String> &p_files, int p_from_screen) {
MainLoop::drop_files(p_files, p_from_screen);
}
+void SceneTree::global_menu_action(const Variant &p_id, const Variant &p_meta) {
+
+ emit_signal("global_menu_action", p_id, p_meta);
+ MainLoop::global_menu_action(p_id, p_meta);
+}
+
Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_pause) {
Ref<SceneTreeTimer> stt;
@@ -1894,6 +1900,7 @@ void SceneTree::_bind_methods() {
ADD_SIGNAL(MethodInfo("physics_frame"));
ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::POOL_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "screen")));
+ ADD_SIGNAL(MethodInfo("global_menu_action", PropertyInfo(Variant::NIL, "id"), PropertyInfo(Variant::NIL, "meta")));
ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("connected_to_server"));
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index afb653e242..42a87545a6 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -407,6 +407,7 @@ public:
static SceneTree *get_singleton() { return singleton; }
void drop_files(const Vector<String> &p_files, int p_from_screen = 0);
+ void global_menu_action(const Variant &p_id, const Variant &p_meta);
//network API