[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.
This commit is contained in:
parent
4b53fdb25d
commit
db6d4352ea
16 changed files with 305 additions and 1 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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].
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue