Skip to content

Commit d5e599f

Browse files
committed
[macOS] Handle bundles as files in the embedded file dialogs.
1 parent 0f20e67 commit d5e599f

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
@@ -588,6 +588,8 @@ void DirAccess::_bind_methods() {
588588
ClassDB::bind_method(D_METHOD("read_link", "path"), &DirAccess::read_link);
589589
ClassDB::bind_method(D_METHOD("create_link", "source", "target"), &DirAccess::create_link);
590590

591+
ClassDB::bind_method(D_METHOD("is_bundle", "path"), &DirAccess::is_bundle);
592+
591593
ClassDB::bind_method(D_METHOD("set_include_navigational", "enable"), &DirAccess::set_include_navigational);
592594
ClassDB::bind_method(D_METHOD("get_include_navigational"), &DirAccess::get_include_navigational);
593595
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
@@ -160,6 +160,7 @@ class DirAccess : public RefCounted {
160160
bool get_include_hidden() const;
161161

162162
virtual bool is_case_sensitive(const String &p_path) const;
163+
virtual bool is_bundle(const String &p_file) const { return false; }
163164

164165
DirAccess() {}
165166
virtual ~DirAccess() {}

doc/classes/DirAccess.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,14 @@
221221
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.
222222
</description>
223223
</method>
224+
<method name="is_bundle" qualifiers="const">
225+
<return type="bool" />
226+
<param index="0" name="path" type="String" />
227+
<description>
228+
Returns [code]true[/code] if the directory is a macOS bundle.
229+
[b]Note:[/b] This method is implemented on macOS.
230+
</description>
231+
</method>
224232
<method name="is_case_sensitive" qualifiers="const">
225233
<return type="bool" />
226234
<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
@@ -185,6 +185,7 @@ void EditorFileDialog::_update_theme_item_cache() {
185185
theme_cache.favorites_up = get_editor_theme_icon(SNAME("MoveUp"));
186186
theme_cache.favorites_down = get_editor_theme_icon(SNAME("MoveDown"));
187187
theme_cache.create_folder = get_editor_theme_icon(SNAME("FolderCreate"));
188+
theme_cache.open_folder = get_editor_theme_icon(SNAME("FolderBrowse"));
188189

189190
theme_cache.filter_box = get_editor_theme_icon(SNAME("Search"));
190191
theme_cache.file_sort_button = get_editor_theme_icon(SNAME("Sort"));
@@ -535,7 +536,7 @@ void EditorFileDialog::_action_pressed() {
535536
String file_text = file->get_text();
536537
String f = file_text.is_absolute_path() ? file_text : dir_access->get_current_dir().path_join(file_text);
537538

538-
if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) {
539+
if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && (dir_access->file_exists(f) || dir_access->is_bundle(f))) {
539540
_save_to_recent();
540541
hide();
541542
emit_signal(SNAME("file_selected"), f);
@@ -787,6 +788,12 @@ void EditorFileDialog::_item_list_item_rmb_clicked(int p_item, const Vector2 &p_
787788
item_menu->add_icon_item(theme_cache.filesystem, item_text, ITEM_MENU_SHOW_IN_EXPLORER);
788789
}
789790
#endif
791+
if (single_item_selected) {
792+
Dictionary item_meta = item_list->get_item_metadata(p_item);
793+
if (item_meta["bundle"]) {
794+
item_menu->add_icon_item(theme_cache.open_folder, TTR("Show Package Contents"), ITEM_MENU_SHOW_BUNDLE_CONTENT);
795+
}
796+
}
790797

791798
if (item_menu->get_item_count() > 0) {
792799
item_menu->set_position(item_list->get_screen_position() + p_pos);
@@ -849,7 +856,7 @@ void EditorFileDialog::_item_menu_id_pressed(int p_option) {
849856
case ITEM_MENU_SHOW_IN_EXPLORER: {
850857
String path;
851858
int idx = item_list->get_current();
852-
if (idx == -1 || item_list->get_selected_items().size() == 0) {
859+
if (idx == -1 || !item_list->is_anything_selected()) {
853860
// Folder background was clicked. Open this folder.
854861
path = ProjectSettings::get_singleton()->globalize_path(dir_access->get_current_dir());
855862
} else {
@@ -859,6 +866,20 @@ void EditorFileDialog::_item_menu_id_pressed(int p_option) {
859866
}
860867
OS::get_singleton()->shell_show_in_file_manager(path, true);
861868
} break;
869+
870+
case ITEM_MENU_SHOW_BUNDLE_CONTENT: {
871+
String path;
872+
int idx = item_list->get_current();
873+
if (idx == -1 || !item_list->is_anything_selected()) {
874+
return;
875+
}
876+
Dictionary item_meta = item_list->get_item_metadata(idx);
877+
dir_access->change_dir(item_meta["path"]);
878+
callable_mp(this, &EditorFileDialog::update_file_list).call_deferred();
879+
callable_mp(this, &EditorFileDialog::update_dir).call_deferred();
880+
881+
_push_history();
882+
} break;
862883
}
863884
}
864885

@@ -1026,28 +1047,6 @@ void EditorFileDialog::update_file_list() {
10261047
}
10271048
sort_file_info_list(file_infos, file_sort);
10281049

1029-
while (!dirs.is_empty()) {
1030-
const String &dir_name = dirs.front()->get();
1031-
1032-
item_list->add_item(dir_name);
1033-
1034-
if (display_mode == DISPLAY_THUMBNAILS) {
1035-
item_list->set_item_icon(-1, folder_thumbnail);
1036-
} else {
1037-
item_list->set_item_icon(-1, theme_cache.folder);
1038-
}
1039-
1040-
Dictionary d;
1041-
d["name"] = dir_name;
1042-
d["path"] = cdir.path_join(dir_name);
1043-
d["dir"] = true;
1044-
1045-
item_list->set_item_metadata(-1, d);
1046-
item_list->set_item_icon_modulate(-1, get_dir_icon_color(String(d["path"])));
1047-
1048-
dirs.pop_front();
1049-
}
1050-
10511050
List<String> patterns;
10521051
// build filter
10531052
if (filter->get_selected() == filter->get_item_count() - 1) {
@@ -1074,6 +1073,44 @@ void EditorFileDialog::update_file_list() {
10741073
}
10751074
}
10761075

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

@@ -1109,6 +1146,7 @@ void EditorFileDialog::update_file_list() {
11091146
Dictionary d;
11101147
d["name"] = file_info.name;
11111148
d["dir"] = false;
1149+
d["bundle"] = false;
11121150
d["path"] = file_info.path;
11131151
item_list->set_item_metadata(-1, d);
11141152

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)