diff options
author | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2019-02-06 15:57:06 +0200 |
---|---|---|
committer | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2019-08-26 16:45:49 +0300 |
commit | db6d4352ea528e925c69ee94f6fb9bc0942719ec (patch) | |
tree | 864bb7a3b90ea000ec0b1881f670f4596133aadd | |
parent | 4b53fdb25d545b0a2fc73f6a46775ced586994b7 (diff) |
[macOS] Add methods to modify global and dock menus. Add ability to open multiple editor/project manager instances, recent/favourite project list to project manager dock menu and opened scene list to editor dock menu.
-rw-r--r-- | core/bind/core_bind.cpp | 30 | ||||
-rw-r--r-- | core/bind/core_bind.h | 5 | ||||
-rw-r--r-- | core/os/main_loop.cpp | 8 | ||||
-rw-r--r-- | core/os/main_loop.h | 1 | ||||
-rw-r--r-- | core/os/os.h | 5 | ||||
-rw-r--r-- | doc/classes/MainLoop.xml | 10 | ||||
-rw-r--r-- | doc/classes/OS.xml | 44 | ||||
-rw-r--r-- | doc/classes/SceneTree.xml | 9 | ||||
-rw-r--r-- | editor/editor_node.cpp | 26 | ||||
-rw-r--r-- | editor/editor_node.h | 4 | ||||
-rw-r--r-- | editor/project_manager.cpp | 35 | ||||
-rw-r--r-- | editor/project_manager.h | 2 | ||||
-rw-r--r-- | platform/osx/os_osx.h | 25 | ||||
-rw-r--r-- | platform/osx/os_osx.mm | 94 | ||||
-rw-r--r-- | scene/main/scene_tree.cpp | 7 | ||||
-rw-r--r-- | scene/main/scene_tree.h | 1 |
16 files changed, 305 insertions, 1 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/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/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/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/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 |