Skip to content

Commit 44cda51

Browse files
committed
Merge pull request godotengine#98812 from bruvzg/macos_bundles_as_file
[macOS] Handle bundles as files in the embedded file dialogs.
2 parents 1719f8e + d5e599f commit 44cda51

File tree

9 files changed

+213
-47
lines changed

9 files changed

+213
-47
lines changed

core/io/dir_access.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,8 @@ void DirAccess::_bind_methods() {
663663
ClassDB::bind_method(D_METHOD("read_link", "path"), &DirAccess::read_link);
664664
ClassDB::bind_method(D_METHOD("create_link", "source", "target"), &DirAccess::create_link);
665665

666+
ClassDB::bind_method(D_METHOD("is_bundle", "path"), &DirAccess::is_bundle);
667+
666668
ClassDB::bind_method(D_METHOD("set_include_navigational", "enable"), &DirAccess::set_include_navigational);
667669
ClassDB::bind_method(D_METHOD("get_include_navigational"), &DirAccess::get_include_navigational);
668670
ClassDB::bind_method(D_METHOD("set_include_hidden", "enable"), &DirAccess::set_include_hidden);

core/io/dir_access.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ class DirAccess : public RefCounted {
168168
bool get_include_hidden() const;
169169

170170
virtual bool is_case_sensitive(const String &p_path) const;
171+
virtual bool is_bundle(const String &p_file) const { return false; }
171172

172173
public:
173174
DirAccess() {}

doc/classes/DirAccess.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,14 @@
232232
Returns the available space on the current directory's disk, in bytes. Returns [code]0[/code] if the platform-specific method to query the available space fails.
233233
</description>
234234
</method>
235+
<method name="is_bundle" qualifiers="const">
236+
<return type="bool" />
237+
<param index="0" name="path" type="String" />
238+
<description>
239+
Returns [code]true[/code] if the directory is a macOS bundle.
240+
[b]Note:[/b] This method is implemented on macOS.
241+
</description>
242+
</method>
235243
<method name="is_case_sensitive" qualifiers="const">
236244
<return type="bool" />
237245
<param index="0" name="path" type="String" />

editor/gui/editor_file_dialog.cpp

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ void EditorFileDialog::_update_theme_item_cache() {
191191
theme_cache.favorites_up = get_editor_theme_icon(SNAME("MoveUp"));
192192
theme_cache.favorites_down = get_editor_theme_icon(SNAME("MoveDown"));
193193
theme_cache.create_folder = get_editor_theme_icon(SNAME("FolderCreate"));
194+
theme_cache.open_folder = get_editor_theme_icon(SNAME("FolderBrowse"));
194195

195196
theme_cache.filter_box = get_editor_theme_icon(SNAME("Search"));
196197
theme_cache.file_sort_button = get_editor_theme_icon(SNAME("Sort"));
@@ -541,7 +542,7 @@ void EditorFileDialog::_action_pressed() {
541542
String file_text = file->get_text();
542543
String f = file_text.is_absolute_path() ? file_text : dir_access->get_current_dir().path_join(file_text);
543544

544-
if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) {
545+
if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && (dir_access->file_exists(f) || dir_access->is_bundle(f))) {
545546
_save_to_recent();
546547
hide();
547548
emit_signal(SNAME("file_selected"), f);
@@ -793,6 +794,12 @@ void EditorFileDialog::_item_list_item_rmb_clicked(int p_item, const Vector2 &p_
793794
item_menu->add_icon_item(theme_cache.filesystem, item_text, ITEM_MENU_SHOW_IN_EXPLORER);
794795
}
795796
#endif
797+
if (single_item_selected) {
798+
Dictionary item_meta = item_list->get_item_metadata(p_item);
799+
if (item_meta["bundle"]) {
800+
item_menu->add_icon_item(theme_cache.open_folder, TTR("Show Package Contents"), ITEM_MENU_SHOW_BUNDLE_CONTENT);
801+
}
802+
}
796803

797804
if (item_menu->get_item_count() > 0) {
798805
item_menu->set_position(item_list->get_screen_position() + p_pos);
@@ -855,7 +862,7 @@ void EditorFileDialog::_item_menu_id_pressed(int p_option) {
855862
case ITEM_MENU_SHOW_IN_EXPLORER: {
856863
String path;
857864
int idx = item_list->get_current();
858-
if (idx == -1 || item_list->get_selected_items().size() == 0) {
865+
if (idx == -1 || !item_list->is_anything_selected()) {
859866
// Folder background was clicked. Open this folder.
860867
path = ProjectSettings::get_singleton()->globalize_path(dir_access->get_current_dir());
861868
} else {
@@ -865,6 +872,20 @@ void EditorFileDialog::_item_menu_id_pressed(int p_option) {
865872
}
866873
OS::get_singleton()->shell_show_in_file_manager(path, true);
867874
} break;
875+
876+
case ITEM_MENU_SHOW_BUNDLE_CONTENT: {
877+
String path;
878+
int idx = item_list->get_current();
879+
if (idx == -1 || !item_list->is_anything_selected()) {
880+
return;
881+
}
882+
Dictionary item_meta = item_list->get_item_metadata(idx);
883+
dir_access->change_dir(item_meta["path"]);
884+
callable_mp(this, &EditorFileDialog::update_file_list).call_deferred();
885+
callable_mp(this, &EditorFileDialog::update_dir).call_deferred();
886+
887+
_push_history();
888+
} break;
868889
}
869890
}
870891

@@ -1032,28 +1053,6 @@ void EditorFileDialog::update_file_list() {
10321053
}
10331054
sort_file_info_list(file_infos, file_sort);
10341055

1035-
while (!dirs.is_empty()) {
1036-
const String &dir_name = dirs.front()->get();
1037-
1038-
item_list->add_item(dir_name);
1039-
1040-
if (display_mode == DISPLAY_THUMBNAILS) {
1041-
item_list->set_item_icon(-1, folder_thumbnail);
1042-
} else {
1043-
item_list->set_item_icon(-1, theme_cache.folder);
1044-
}
1045-
1046-
Dictionary d;
1047-
d["name"] = dir_name;
1048-
d["path"] = cdir.path_join(dir_name);
1049-
d["dir"] = true;
1050-
1051-
item_list->set_item_metadata(-1, d);
1052-
item_list->set_item_icon_modulate(-1, get_dir_icon_color(String(d["path"])));
1053-
1054-
dirs.pop_front();
1055-
}
1056-
10571056
List<String> patterns;
10581057
// build filter
10591058
if (filter->get_selected() == filter->get_item_count() - 1) {
@@ -1080,6 +1079,44 @@ void EditorFileDialog::update_file_list() {
10801079
}
10811080
}
10821081

1082+
while (!dirs.is_empty()) {
1083+
const String &dir_name = dirs.front()->get();
1084+
1085+
bool bundle = dir_access->is_bundle(dir_name);
1086+
bool found = true;
1087+
if (bundle) {
1088+
bool match = patterns.is_empty();
1089+
for (const String &E : patterns) {
1090+
if (dir_name.matchn(E)) {
1091+
match = true;
1092+
break;
1093+
}
1094+
}
1095+
found = match;
1096+
}
1097+
1098+
if (found) {
1099+
item_list->add_item(dir_name);
1100+
1101+
if (display_mode == DISPLAY_THUMBNAILS) {
1102+
item_list->set_item_icon(-1, folder_thumbnail);
1103+
} else {
1104+
item_list->set_item_icon(-1, theme_cache.folder);
1105+
}
1106+
1107+
Dictionary d;
1108+
d["name"] = dir_name;
1109+
d["path"] = cdir.path_join(dir_name);
1110+
d["dir"] = !bundle;
1111+
d["bundle"] = bundle;
1112+
1113+
item_list->set_item_metadata(-1, d);
1114+
item_list->set_item_icon_modulate(-1, get_dir_icon_color(String(d["path"])));
1115+
}
1116+
1117+
dirs.pop_front();
1118+
}
1119+
10831120
while (!file_infos.is_empty()) {
10841121
bool match = patterns.is_empty();
10851122

@@ -1115,6 +1152,7 @@ void EditorFileDialog::update_file_list() {
11151152
Dictionary d;
11161153
d["name"] = file_info.name;
11171154
d["dir"] = false;
1155+
d["bundle"] = false;
11181156
d["path"] = file_info.path;
11191157
item_list->set_item_metadata(-1, d);
11201158

editor/gui/editor_file_dialog.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ class EditorFileDialog : public ConfirmationDialog {
8282
ITEM_MENU_DELETE,
8383
ITEM_MENU_REFRESH,
8484
ITEM_MENU_NEW_FOLDER,
85-
ITEM_MENU_SHOW_IN_EXPLORER
85+
ITEM_MENU_SHOW_IN_EXPLORER,
86+
ITEM_MENU_SHOW_BUNDLE_CONTENT,
8687
};
8788

8889
ConfirmationDialog *makedialog = nullptr;
@@ -167,6 +168,7 @@ class EditorFileDialog : public ConfirmationDialog {
167168
Ref<Texture2D> parent_folder;
168169
Ref<Texture2D> forward_folder;
169170
Ref<Texture2D> back_folder;
171+
Ref<Texture2D> open_folder;
170172
Ref<Texture2D> reload;
171173
Ref<Texture2D> toggle_hidden;
172174
Ref<Texture2D> toggle_filename_filter;

platform/macos/dir_access_macos.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class DirAccessMacOS : public DirAccessUnix {
5050

5151
virtual bool is_hidden(const String &p_name) override;
5252
virtual bool is_case_sensitive(const String &p_path) const override;
53+
54+
virtual bool is_bundle(const String &p_file) const override;
5355
};
5456

5557
#endif // UNIX ENABLED

platform/macos/dir_access_macos.mm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,14 @@
9696
return [cs boolValue];
9797
}
9898

99+
bool DirAccessMacOS::is_bundle(const String &p_file) const {
100+
String f = p_file;
101+
if (!f.is_absolute_path()) {
102+
f = get_current_dir().path_join(f);
103+
}
104+
f = fix_path(f);
105+
106+
return [[NSWorkspace sharedWorkspace] isFilePackageAtPath:[NSString stringWithUTF8String:f.utf8().get_data()]];
107+
}
108+
99109
#endif // UNIX_ENABLED

0 commit comments

Comments
 (0)