feat: modules moved and engine moved to submodule

This commit is contained in:
Jan van der Weide 2025-04-12 18:40:44 +02:00
parent dfb5e645cd
commit c33d2130cc
5136 changed files with 225275 additions and 64485 deletions

View file

@ -307,6 +307,7 @@ EditorBottomPanel::EditorBottomPanel() {
left_button = memnew(Button);
left_button->set_tooltip_text(TTR("Scroll Left\nHold Ctrl to scroll to the begin.\nHold Shift to scroll one page."));
left_button->set_accessibility_name(TTRC("Scroll Left"));
left_button->set_theme_type_variation("BottomPanelButton");
left_button->set_focus_mode(Control::FOCUS_NONE);
left_button->connect(SceneStringName(pressed), callable_mp(this, &EditorBottomPanel::_scroll).bind(false));
@ -323,6 +324,7 @@ EditorBottomPanel::EditorBottomPanel() {
right_button = memnew(Button);
right_button->set_tooltip_text(TTR("Scroll Right\nHold Ctrl to scroll to the end.\nHold Shift to scroll one page."));
right_button->set_accessibility_name(TTRC("Scroll Right"));
right_button->set_theme_type_variation("BottomPanelButton");
right_button->set_focus_mode(Control::FOCUS_NONE);
right_button->connect(SceneStringName(pressed), callable_mp(this, &EditorBottomPanel::_scroll).bind(true));
@ -354,6 +356,7 @@ EditorBottomPanel::EditorBottomPanel() {
pin_button->set_theme_type_variation("FlatMenuButton");
pin_button->set_toggle_mode(true);
pin_button->set_tooltip_text(TTR("Pin Bottom Panel Switching"));
pin_button->set_accessibility_name(TTRC("Pin Bottom Panel"));
pin_button->connect(SceneStringName(toggled), callable_mp(this, &EditorBottomPanel::_pin_button_toggled));
expand_button = memnew(Button);
@ -361,6 +364,7 @@ EditorBottomPanel::EditorBottomPanel() {
expand_button->hide();
expand_button->set_theme_type_variation("FlatMenuButton");
expand_button->set_toggle_mode(true);
expand_button->set_accessibility_name(TTRC("Expand Bottom Panel"));
expand_button->set_shortcut(ED_SHORTCUT_AND_COMMAND("editor/bottom_panel_expand", TTRC("Expand Bottom Panel"), KeyModifierMask::SHIFT | Key::F12));
expand_button->connect(SceneStringName(toggled), callable_mp(this, &EditorBottomPanel::_expand_button_toggled));
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_BOTTOM_PANEL_H
#define EDITOR_BOTTOM_PANEL_H
#pragma once
#include "scene/gui/panel_container.h"
@ -90,5 +89,3 @@ public:
EditorBottomPanel();
};
#endif // EDITOR_BOTTOM_PANEL_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_DIR_DIALOG_H
#define EDITOR_DIR_DIALOG_H
#pragma once
#include "scene/gui/dialogs.h"
@ -73,5 +72,3 @@ public:
EditorDirDialog();
};
#endif // EDITOR_DIR_DIALOG_H

View file

@ -65,7 +65,15 @@ void EditorFileDialog::_native_popup() {
} else if (access == ACCESS_USERDATA) {
root = OS::get_singleton()->get_user_data_dir();
}
DisplayServer::get_singleton()->file_dialog_with_options_show(get_translated_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), root, file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, _get_options(), callable_mp(this, &EditorFileDialog::_native_dialog_cb));
// Attach native file dialog to first persistent parent window.
Window *w = (is_transient() || is_transient_to_focused()) ? get_parent_visible_window() : nullptr;
while (w && w->get_flag(FLAG_POPUP) && w->get_parent_visible_window()) {
w = w->get_parent_visible_window();
}
DisplayServer::WindowID wid = w ? w->get_window_id() : DisplayServer::INVALID_WINDOW_ID;
DisplayServer::get_singleton()->file_dialog_with_options_show(get_translated_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), root, file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, _get_options(), callable_mp(this, &EditorFileDialog::_native_dialog_cb), wid);
}
void EditorFileDialog::popup(const Rect2i &p_rect) {
@ -134,9 +142,9 @@ void EditorFileDialog::_native_dialog_cb(bool p_ok, const Vector<String> &p_file
} else if (filters.size() > 1 && p_filter == 0) {
// Match all filters.
for (int i = 0; i < filters.size(); i++) {
String flt = filters[i].get_slice(";", 0);
String flt = filters[i].get_slicec(';', 0);
for (int j = 0; j < flt.get_slice_count(","); j++) {
String str = flt.get_slice(",", j).strip_edges();
String str = flt.get_slicec(',', j).strip_edges();
if (f.matchn(str)) {
valid = true;
break;
@ -152,10 +160,10 @@ void EditorFileDialog::_native_dialog_cb(bool p_ok, const Vector<String> &p_file
idx--;
}
if (idx >= 0 && idx < filters.size()) {
String flt = filters[idx].get_slice(";", 0);
String flt = filters[idx].get_slicec(';', 0);
int filter_slice_count = flt.get_slice_count(",");
for (int j = 0; j < filter_slice_count; j++) {
String str = (flt.get_slice(",", j).strip_edges());
String str = flt.get_slicec(',', j).strip_edges();
if (f.matchn(str)) {
valid = true;
break;
@ -163,8 +171,8 @@ void EditorFileDialog::_native_dialog_cb(bool p_ok, const Vector<String> &p_file
}
if (!valid && filter_slice_count > 0) {
String str = (flt.get_slice(",", 0).strip_edges());
f += str.substr(1, str.length() - 1);
String str = flt.get_slicec(',', 0).strip_edges();
f += str.substr(1);
file->set_text(f.get_file());
valid = true;
}
@ -176,8 +184,8 @@ void EditorFileDialog::_native_dialog_cb(bool p_ok, const Vector<String> &p_file
// Add first extension of filter if no valid extension is found.
if (!valid) {
int idx = p_filter;
String flt = filters[idx].get_slice(";", 0);
String ext = flt.get_slice(",", 0).strip_edges().get_extension();
String flt = filters[idx].get_slicec(';', 0);
String ext = flt.get_slicec(',', 0).strip_edges().get_extension();
f += "." + ext;
}
emit_signal(SNAME("file_selected"), f);
@ -586,7 +594,7 @@ void EditorFileDialog::_action_pressed() {
} else if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_DIR) {
String path = dir_access->get_current_dir();
path = path.replace("\\", "/");
path = path.replace_char('\\', '/');
for (int i = 0; i < item_list->get_item_count(); i++) {
if (item_list->is_selected(i)) {
@ -612,9 +620,9 @@ void EditorFileDialog::_action_pressed() {
} else if (filters.size() > 1 && filter->get_selected() == 0) {
// Match all filters.
for (int i = 0; i < filters.size(); i++) {
String flt = filters[i].get_slice(";", 0);
String flt = filters[i].get_slicec(';', 0);
for (int j = 0; j < flt.get_slice_count(","); j++) {
String str = flt.get_slice(",", j).strip_edges();
String str = flt.get_slicec(',', j).strip_edges();
if (f.matchn(str)) {
valid = true;
break;
@ -630,10 +638,10 @@ void EditorFileDialog::_action_pressed() {
idx--;
}
if (idx >= 0 && idx < filters.size()) {
String flt = filters[idx].get_slice(";", 0);
String flt = filters[idx].get_slicec(';', 0);
int filter_slice_count = flt.get_slice_count(",");
for (int j = 0; j < filter_slice_count; j++) {
String str = (flt.get_slice(",", j).strip_edges());
String str = (flt.get_slicec(',', j).strip_edges());
if (f.matchn(str)) {
valid = true;
break;
@ -641,8 +649,8 @@ void EditorFileDialog::_action_pressed() {
}
if (!valid && filter_slice_count > 0) {
String str = (flt.get_slice(",", 0).strip_edges());
f += str.substr(1, str.length() - 1);
String str = flt.get_slicec(',', 0).strip_edges();
f += str.substr(1);
_request_single_thumbnail(get_current_dir().path_join(f.get_file()));
file->set_text(f.get_file());
valid = true;
@ -663,8 +671,8 @@ void EditorFileDialog::_action_pressed() {
// Add first extension of filter if no valid extension is found.
if (!valid) {
int idx = filter->get_selected();
String flt = filters[idx].get_slice(";", 0);
String ext = flt.get_slice(",", 0).strip_edges().get_extension();
String flt = filters[idx].get_slicec(';', 0);
String ext = flt.get_slicec(',', 0).strip_edges().get_extension();
f += "." + ext;
}
@ -762,7 +770,7 @@ void EditorFileDialog::_items_clear_selection(const Vector2 &p_pos, MouseButton
void EditorFileDialog::_push_history() {
local_history.resize(local_history_pos + 1);
String new_path = dir_access->get_current_dir();
if (local_history.size() == 0 || new_path != local_history[local_history_pos]) {
if (local_history.is_empty() || new_path != local_history[local_history_pos]) {
local_history.push_back(new_path);
local_history_pos++;
dir_prev->set_disabled(local_history_pos == 0);
@ -932,7 +940,7 @@ bool EditorFileDialog::_is_open_should_be_disabled() {
}
Vector<int> items = item_list->get_selected_items();
if (items.size() == 0) {
if (items.is_empty()) {
return mode != FILE_MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder.
}
@ -1097,9 +1105,9 @@ void EditorFileDialog::update_file_list() {
} else if (filters.size() > 1 && filter->get_selected() == 0) {
// match all filters
for (int i = 0; i < filters.size(); i++) {
String f = filters[i].get_slice(";", 0);
String f = filters[i].get_slicec(';', 0);
for (int j = 0; j < f.get_slice_count(","); j++) {
patterns.push_back(f.get_slice(",", j).strip_edges());
patterns.push_back(f.get_slicec(',', j).strip_edges());
}
}
} else {
@ -1109,9 +1117,9 @@ void EditorFileDialog::update_file_list() {
}
if (idx >= 0 && idx < filters.size()) {
String f = filters[idx].get_slice(";", 0);
String f = filters[idx].get_slicec(';', 0);
for (int j = 0; j < f.get_slice_count(","); j++) {
patterns.push_back(f.get_slice(",", j).strip_edges());
patterns.push_back(f.get_slicec(',', j).strip_edges());
}
}
}
@ -1428,7 +1436,7 @@ void EditorFileDialog::set_current_path(const String &p_path) {
set_current_file(p_path);
} else {
String path_dir = p_path.substr(0, pos);
String path_file = p_path.substr(pos + 1, p_path.length());
String path_file = p_path.substr(pos + 1);
set_current_dir(path_dir);
set_current_file(path_file);
}
@ -2040,6 +2048,7 @@ void EditorFileDialog::_update_option_controls() {
for (const EditorFileDialog::Option &opt : options) {
if (opt.values.is_empty()) {
CheckBox *cb = memnew(CheckBox);
cb->set_accessibility_name(opt.name);
cb->set_pressed(opt.default_idx);
cb->set_text(opt.name);
flow_checkbox_options->add_child(cb);
@ -2048,12 +2057,14 @@ void EditorFileDialog::_update_option_controls() {
} else {
Label *lbl = memnew(Label);
lbl->set_text(opt.name);
lbl->set_focus_mode(Control::FOCUS_NONE);
grid_select_options->add_child(lbl);
OptionButton *ob = memnew(OptionButton);
for (const String &val : opt.values) {
ob->add_item(val);
}
ob->set_accessibility_name(opt.name);
ob->select(opt.default_idx);
grid_select_options->add_child(ob);
ob->connect(SceneStringName(item_selected), callable_mp(this, &EditorFileDialog::_option_changed_item_selected).bind(opt.name));
@ -2393,12 +2404,15 @@ EditorFileDialog::EditorFileDialog() {
dir_prev = memnew(Button);
dir_prev->set_theme_type_variation(SceneStringName(FlatButton));
dir_prev->set_accessibility_name(TTRC("Previous"));
dir_prev->set_tooltip_text(TTR("Go to previous folder."));
dir_next = memnew(Button);
dir_next->set_theme_type_variation(SceneStringName(FlatButton));
dir_next->set_accessibility_name(TTRC("Next"));
dir_next->set_tooltip_text(TTR("Go to next folder."));
dir_up = memnew(Button);
dir_up->set_theme_type_variation(SceneStringName(FlatButton));
dir_up->set_accessibility_name(TTRC("Parent Folder"));
dir_up->set_tooltip_text(TTR("Go to parent folder."));
pathhb->add_child(dir_prev);
@ -2410,6 +2424,7 @@ EditorFileDialog::EditorFileDialog() {
dir_up->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::_go_up));
Label *l = memnew(Label(TTR("Path:")));
l->set_focus_mode(Control::FOCUS_NONE);
l->set_theme_type_variation("HeaderSmall");
pathhb->add_child(l);
@ -2418,10 +2433,12 @@ EditorFileDialog::EditorFileDialog() {
dir = memnew(LineEdit);
dir->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
dir->set_accessibility_name(TTRC("Directory Path"));
pathhb->add_child(dir);
refresh = memnew(Button);
refresh->set_theme_type_variation(SceneStringName(FlatButton));
refresh->set_accessibility_name(TTRC("Refresh Files"));
refresh->set_tooltip_text(TTR("Refresh files."));
refresh->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::update_file_list));
pathhb->add_child(refresh);
@ -2429,6 +2446,7 @@ EditorFileDialog::EditorFileDialog() {
favorite = memnew(Button);
favorite->set_theme_type_variation(SceneStringName(FlatButton));
favorite->set_toggle_mode(true);
favorite->set_accessibility_name(TTRC("(Un)favorite Folder"));
favorite->set_tooltip_text(TTR("(Un)favorite current folder."));
favorite->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::_favorite_pressed));
pathhb->add_child(favorite);
@ -2438,6 +2456,7 @@ EditorFileDialog::EditorFileDialog() {
drives = memnew(OptionButton);
drives->connect(SceneStringName(item_selected), callable_mp(this, &EditorFileDialog::_select_drive));
drives->set_accessibility_name(TTRC("Current Drive"));
pathhb->add_child(drives);
makedir_sep = memnew(VSeparator);
@ -2445,6 +2464,7 @@ EditorFileDialog::EditorFileDialog() {
makedir = memnew(Button);
makedir->set_theme_type_variation(SceneStringName(FlatButton));
makedir->set_accessibility_name(TTRC("Create Folder"));
makedir->set_tooltip_text(TTR("Create a new folder."));
makedir->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::_make_dir));
pathhb->add_child(makedir);
@ -2480,16 +2500,19 @@ EditorFileDialog::EditorFileDialog() {
fav_vb->add_child(fav_hb);
l = memnew(Label(TTR("Favorites:")));
l->set_focus_mode(Control::FOCUS_NONE);
l->set_theme_type_variation("HeaderSmall");
fav_hb->add_child(l);
fav_hb->add_spacer();
fav_up = memnew(Button);
fav_up->set_theme_type_variation(SceneStringName(FlatButton));
fav_up->set_accessibility_name(TTRC("Move Up"));
fav_hb->add_child(fav_up);
fav_up->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::_favorite_move_up));
fav_down = memnew(Button);
fav_down->set_theme_type_variation(SceneStringName(FlatButton));
fav_down->set_accessibility_name(TTRC("Move Down"));
fav_hb->add_child(fav_down);
fav_down->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::_favorite_move_down));
@ -2498,6 +2521,7 @@ EditorFileDialog::EditorFileDialog() {
fav_vb->add_child(favorites);
favorites->set_v_size_flags(Control::SIZE_EXPAND_FILL);
favorites->set_theme_type_variation("ItemListSecondary");
favorites->set_accessibility_name(TTRC("Favorites"));
favorites->connect(SceneStringName(item_selected), callable_mp(this, &EditorFileDialog::_favorite_selected));
VBoxContainer *rec_vb = memnew(VBoxContainer);
@ -2508,6 +2532,7 @@ EditorFileDialog::EditorFileDialog() {
recent->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
recent->set_allow_reselect(true);
recent->set_theme_type_variation("ItemListSecondary");
recent->set_accessibility_name(TTRC("Recent"));
rec_vb->add_margin_child(TTR("Recent:"), recent, true);
recent->connect(SceneStringName(item_selected), callable_mp(this, &EditorFileDialog::_recent_selected));
@ -2526,6 +2551,7 @@ EditorFileDialog::EditorFileDialog() {
lower_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
l = memnew(Label(TTR("Directories & Files:")));
l->set_focus_mode(Control::FOCUS_NONE);
l->set_theme_type_variation("HeaderSmall");
l->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@ -2535,6 +2561,7 @@ EditorFileDialog::EditorFileDialog() {
show_hidden->set_theme_type_variation(SceneStringName(FlatButton));
show_hidden->set_toggle_mode(true);
show_hidden->set_pressed(is_showing_hidden_files());
show_hidden->set_accessibility_name(TTRC("Show Hidden Files"));
show_hidden->set_tooltip_text(TTR("Toggle the visibility of hidden files."));
show_hidden->connect(SceneStringName(toggled), callable_mp(this, &EditorFileDialog::set_show_hidden_files));
lower_hb->add_child(show_hidden);
@ -2550,6 +2577,7 @@ EditorFileDialog::EditorFileDialog() {
mode_thumbnails->set_toggle_mode(true);
mode_thumbnails->set_pressed(display_mode == DISPLAY_THUMBNAILS);
mode_thumbnails->set_button_group(view_mode_group);
mode_thumbnails->set_accessibility_name(TTRC("View as Thumbnails"));
mode_thumbnails->set_tooltip_text(TTR("View items as a grid of thumbnails."));
lower_hb->add_child(mode_thumbnails);
@ -2559,6 +2587,7 @@ EditorFileDialog::EditorFileDialog() {
mode_list->set_toggle_mode(true);
mode_list->set_pressed(display_mode == DISPLAY_LIST);
mode_list->set_button_group(view_mode_group);
mode_list->set_accessibility_name(TTRC("View as List"));
mode_list->set_tooltip_text(TTR("View items as a list."));
lower_hb->add_child(mode_list);
@ -2568,12 +2597,14 @@ EditorFileDialog::EditorFileDialog() {
file_sort_button->set_flat(false);
file_sort_button->set_theme_type_variation("FlatMenuButton");
file_sort_button->set_tooltip_text(TTR("Sort files"));
file_sort_button->set_accessibility_name(TTRC("Sort Files"));
show_search_filter_button = memnew(Button);
show_search_filter_button->set_theme_type_variation(SceneStringName(FlatButton));
show_search_filter_button->set_toggle_mode(true);
show_search_filter_button->set_pressed(false);
show_search_filter_button->set_tooltip_text(TTR("Toggle the visibility of the filter for file names."));
show_search_filter_button->set_accessibility_name(TTRC("Show Search Filters"));
show_search_filter_button->connect(SceneStringName(toggled), callable_mp(this, &EditorFileDialog::set_show_search_filter));
lower_hb->add_child(show_search_filter_button);
@ -2599,6 +2630,7 @@ EditorFileDialog::EditorFileDialog() {
item_list->connect("item_clicked", callable_mp(this, &EditorFileDialog::_item_list_item_rmb_clicked));
item_list->connect("empty_clicked", callable_mp(this, &EditorFileDialog::_item_list_empty_clicked));
item_list->set_allow_rmb_select(true);
item_list->set_accessibility_name(TTRC("Directories and Files"));
list_vb->add_child(item_list);
@ -2621,6 +2653,7 @@ EditorFileDialog::EditorFileDialog() {
filter_box = memnew(LineEdit);
filter_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
filter_box->set_placeholder(TTR("Filter"));
filter_box->set_accessibility_name(TTRC("Filename Filter"));
filter_hb->add_child(filter_box);
filter_hb->set_visible(false);
item_vb->add_child(filter_hb);
@ -2628,6 +2661,7 @@ EditorFileDialog::EditorFileDialog() {
file_box = memnew(HBoxContainer);
l = memnew(Label(TTR("File:")));
l->set_focus_mode(Control::FOCUS_NONE);
l->set_theme_type_variation("HeaderSmall");
file_box->add_child(l);
@ -2635,11 +2669,13 @@ EditorFileDialog::EditorFileDialog() {
file->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
file->set_stretch_ratio(4);
file->set_h_size_flags(Control::SIZE_EXPAND_FILL);
file->set_accessibility_name(TTRC("File Name"));
file_box->add_child(file);
filter = memnew(OptionButton);
filter->set_stretch_ratio(3);
filter->set_h_size_flags(Control::SIZE_EXPAND_FILL);
filter->set_clip_text(true); // Too many extensions overflow it.
filter->set_accessibility_name(TTRC("File Type Filter"));
file_box->add_child(filter);
file_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
item_vb->add_child(file_box);
@ -2677,6 +2713,7 @@ EditorFileDialog::EditorFileDialog() {
makedirname = memnew(LineEdit);
makedirname->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
makedirname->set_accessibility_name(TTRC("Name"));
makevb->add_margin_child(TTR("Name:"), makedirname);
add_child(makedialog);
makedialog->register_text_enter(makedirname);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_FILE_DIALOG_H
#define EDITOR_FILE_DIALOG_H
#pragma once
#include "core/io/dir_access.h"
#include "editor/file_info.h"
@ -378,5 +377,3 @@ public:
VARIANT_ENUM_CAST(EditorFileDialog::FileMode);
VARIANT_ENUM_CAST(EditorFileDialog::Access);
VARIANT_ENUM_CAST(EditorFileDialog::DisplayMode);
#endif // EDITOR_FILE_DIALOG_H

View file

@ -128,7 +128,6 @@ void EditorObjectSelector::update_path() {
}
Ref<Texture2D> obj_icon = EditorNode::get_singleton()->get_object_icon(obj);
if (obj_icon.is_valid()) {
current_object_icon->set_texture(obj_icon);
}
@ -148,7 +147,7 @@ void EditorObjectSelector::update_path() {
if (name.is_empty()) {
name = r->get_class();
}
} else if (obj->is_class("EditorDebuggerRemoteObject")) {
} else if (obj->is_class("EditorDebuggerRemoteObjects")) {
name = obj->call("get_title");
} else if (Object::cast_to<Node>(obj)) {
name = Object::cast_to<Node>(obj)->get_name();

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_OBJECT_SELECTOR_H
#define EDITOR_OBJECT_SELECTOR_H
#pragma once
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
@ -68,5 +67,3 @@ public:
EditorObjectSelector(EditorSelectionHistory *p_history);
};
#endif // EDITOR_OBJECT_SELECTOR_H

View file

@ -115,6 +115,7 @@ EditorQuickOpenDialog::EditorQuickOpenDialog() {
search_box = memnew(LineEdit);
search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
search_box->set_placeholder(TTR("Search files..."));
search_box->set_accessibility_name(TTRC("Search"));
search_box->set_clear_button_enabled(true);
mc->add_child(search_box);
}
@ -278,6 +279,7 @@ QuickOpenResultContainer::QuickOpenResultContainer() {
bottom_bar->add_child(vsep);
display_mode_toggle = memnew(Button);
display_mode_toggle->set_accessibility_name(TTRC("Display Mode"));
style_button(display_mode_toggle);
display_mode_toggle->connect(SceneStringName(pressed), callable_mp(this, &QuickOpenResultContainer::_toggle_display_mode));
bottom_bar->add_child(display_mode_toggle);
@ -343,18 +345,31 @@ void QuickOpenResultContainer::init(const Vector<StringName> &p_base_types) {
// Load history when opening for the first time.
file_type_icons.insert(SNAME("__default_icon"), get_editor_theme_icon(SNAME("Object")));
bool history_modified = false;
List<String> history_keys;
history_file->get_section_keys("selected_history", &history_keys);
for (const String &type : history_keys) {
const StringName type_name = type;
const PackedStringArray paths = history_file->get_value("selected_history", type);
PackedStringArray cleaned_paths;
cleaned_paths.resize(paths.size());
Vector<QuickOpenResultCandidate> loaded_candidates;
loaded_candidates.resize(paths.size());
{
QuickOpenResultCandidate *candidates_write = loaded_candidates.ptrw();
String *cleanup_write = cleaned_paths.ptrw();
int i = 0;
for (const String &path : paths) {
for (String path : paths) {
if (path.begins_with("uid://")) {
ResourceUID::ID id = ResourceUID::get_singleton()->text_to_id(path);
if (!ResourceUID::get_singleton()->has_id(id)) {
continue;
}
path = ResourceUID::get_singleton()->get_id_path(id);
}
if (!ResourceLoader::exists(path)) {
continue;
}
@ -363,22 +378,62 @@ void QuickOpenResultContainer::init(const Vector<StringName> &p_base_types) {
QuickOpenResultCandidate candidate;
_setup_candidate(candidate, path);
candidates_write[i] = candidate;
cleanup_write[i] = path;
i++;
}
loaded_candidates.resize(i);
cleaned_paths.resize(i);
selected_history.insert(type, loaded_candidates);
if (i < paths.size()) {
// Some paths removed, need to update history.
if (i == 0) {
history_file->erase_section_key("selected_history", type);
} else {
history_file->set_value("selected_history", type, cleaned_paths);
}
history_modified = true;
}
}
}
if (history_modified) {
history_file->save(_get_cache_file_path());
}
}
_create_initial_results();
}
void QuickOpenResultContainer::_sort_filepaths(int p_max_results) {
struct FilepathComparator {
bool operator()(const String &p_lhs, const String &p_rhs) const {
// Sort on (length, alphanumeric) to prioritize shorter filepaths
return p_lhs.length() == p_rhs.length() ? p_lhs < p_rhs : p_lhs.length() < p_rhs.length();
}
};
SortArray<String, FilepathComparator> sorter;
if (filepaths.size() > p_max_results) {
sorter.partial_sort(0, filepaths.size(), p_max_results, filepaths.ptrw());
} else {
sorter.sort(filepaths.ptrw(), filepaths.size());
}
}
void QuickOpenResultContainer::_create_initial_results() {
file_type_icons.clear();
file_type_icons.insert(SNAME("__default_icon"), get_editor_theme_icon(SNAME("Object")));
filepaths.clear();
filetypes.clear();
history_set.clear();
Vector<QuickOpenResultCandidate> *history = _get_history();
if (history) {
for (const QuickOpenResultCandidate &candidate : *history) {
history_set.insert(candidate.file_path);
}
}
_find_filepaths_in_folder(EditorFileSystem::get_singleton()->get_filesystem(), include_addons_toggle->is_pressed());
_sort_filepaths(result_items.size());
max_total_results = MIN(filepaths.size(), result_items.size());
update_results();
}
@ -416,25 +471,26 @@ void QuickOpenResultContainer::set_query_and_update(const String &p_query) {
update_results();
}
void QuickOpenResultContainer::_setup_candidate(QuickOpenResultCandidate &p_candidate, const String &p_filepath) {
ResourceUID::ID id = EditorFileSystem::get_singleton()->get_file_uid(p_filepath);
if (id == ResourceUID::INVALID_ID) {
p_candidate.file_path = p_filepath;
} else {
p_candidate.file_path = ResourceUID::get_singleton()->id_to_text(id);
Vector<QuickOpenResultCandidate> *QuickOpenResultContainer::_get_history() {
if (base_types.size() == 1) {
return selected_history.lookup_ptr(base_types[0]);
}
p_candidate.result = nullptr;
return nullptr;
}
void QuickOpenResultContainer::_setup_candidate(QuickOpenResultCandidate &p_candidate, const String &p_filepath) {
p_candidate.file_path = ResourceUID::ensure_path(p_filepath);
p_candidate.result = nullptr;
StringName actual_type;
{
StringName *actual_type_ptr = filetypes.lookup_ptr(p_filepath);
if (actual_type_ptr) {
actual_type = *actual_type_ptr;
} else {
ERR_PRINT(vformat("EditorQuickOpenDialog: No type for path %s.", p_filepath));
ERR_PRINT(vformat("EditorQuickOpenDialog: No type for path %s.", p_candidate.file_path));
}
}
EditorResourcePreview::PreviewItem item = EditorResourcePreview::get_singleton()->get_resource_preview_if_available(p_filepath);
EditorResourcePreview::PreviewItem item = EditorResourcePreview::get_singleton()->get_resource_preview_if_available(p_candidate.file_path);
if (item.preview.is_valid()) {
p_candidate.thumbnail = item.preview;
} else if (file_type_icons.has(actual_type)) {
@ -453,7 +509,6 @@ void QuickOpenResultContainer::_setup_candidate(QuickOpenResultCandidate &p_cand
}
void QuickOpenResultContainer::update_results() {
showing_history = false;
candidates.clear();
if (query.is_empty()) {
_use_default_candidates();
@ -464,17 +519,18 @@ void QuickOpenResultContainer::update_results() {
}
void QuickOpenResultContainer::_use_default_candidates() {
if (filepaths.size() <= SHOW_ALL_FILES_THRESHOLD) {
candidates.resize(filepaths.size());
QuickOpenResultCandidate *candidates_write = candidates.ptrw();
for (const String &filepath : filepaths) {
_setup_candidate(*candidates_write++, filepath);
Vector<QuickOpenResultCandidate> *history = _get_history();
if (history) {
candidates.append_array(*history);
}
int count = candidates.size();
candidates.resize(MIN(max_total_results, filepaths.size()));
for (const String &filepath : filepaths) {
if (count >= max_total_results) {
break;
}
} else if (base_types.size() == 1) {
Vector<QuickOpenResultCandidate> *history = selected_history.lookup_ptr(base_types[0]);
if (history) {
showing_history = true;
candidates.append_array(*history);
if (!history || !history_set.has(filepath)) {
_setup_candidate(candidates.write[count++], filepath);
}
}
}
@ -524,8 +580,6 @@ void QuickOpenResultContainer::_update_result_items(int p_new_visible_results_co
if (!any_results) {
if (filepaths.is_empty()) {
no_results_label->set_text(TTR("No files found for this type"));
} else if (query.is_empty()) {
no_results_label->set_text(TTR("Start searching to find files..."));
} else {
no_results_label->set_text(TTR("No results found"));
}
@ -552,7 +606,7 @@ void QuickOpenResultContainer::handle_search_box_input(const Ref<InputEvent> &p_
case Key::RIGHT: {
if (content_display_mode == QuickOpenDisplayMode::GRID) {
// Maybe strip off the shift modifier to allow non-selecting navigation by character?
if (key_event->get_modifiers_mask() == 0) {
if (key_event->get_modifiers_mask().is_empty()) {
move_selection = true;
}
}
@ -621,7 +675,8 @@ void QuickOpenResultContainer::_select_item(int p_index) {
}
result_items[selection_index]->highlight_item(true);
file_details_path->set_text(get_selected() + (showing_history ? TTR(" (recently opened)") : ""));
bool in_history = history_set.has(candidates[selection_index].file_path);
file_details_path->set_text(get_selected() + (in_history ? TTR(" (recently opened)") : ""));
const QuickOpenResultItem *item = result_items[selection_index];
@ -727,7 +782,7 @@ bool QuickOpenResultContainer::has_nothing_selected() const {
String QuickOpenResultContainer::get_selected() const {
ERR_FAIL_COND_V_MSG(has_nothing_selected(), String(), "Tried to get selected file, but nothing was selected.");
return ResourceUID::ensure_path(candidates[selection_index].file_path);
return candidates[selection_index].file_path;
}
QuickOpenDisplayMode QuickOpenResultContainer::get_adaptive_display_mode(const Vector<StringName> &p_base_types) {
@ -749,6 +804,11 @@ QuickOpenDisplayMode QuickOpenResultContainer::get_adaptive_display_mode(const V
return QuickOpenDisplayMode::LIST;
}
String _get_uid_string(const String &p_filepath) {
ResourceUID::ID id = EditorFileSystem::get_singleton()->get_file_uid(p_filepath);
return id == ResourceUID::INVALID_ID ? p_filepath : ResourceUID::get_singleton()->id_to_text(id);
}
void QuickOpenResultContainer::save_selected_item() {
if (base_types.size() > 1) {
// Getting the type of the file and checking which base type it belongs to should be possible.
@ -773,6 +833,7 @@ void QuickOpenResultContainer::save_selected_item() {
}
selected.result = nullptr;
history_set.insert(selected.file_path);
type_history->insert(0, selected);
if (type_history->size() > MAX_HISTORY_SIZE) {
type_history->resize(MAX_HISTORY_SIZE);
@ -785,7 +846,7 @@ void QuickOpenResultContainer::save_selected_item() {
int i = 0;
for (const QuickOpenResultCandidate &candidate : *type_history) {
paths_write[i] = candidate.file_path;
paths_write[i] = _get_uid_string(candidate.file_path);
i++;
}
}
@ -796,6 +857,7 @@ void QuickOpenResultContainer::save_selected_item() {
void QuickOpenResultContainer::cleanup() {
num_visible_results = 0;
candidates.clear();
history_set.clear();
_select_item(-1);
for (QuickOpenResultItem *item : result_items) {
@ -981,9 +1043,8 @@ QuickOpenResultListItem::QuickOpenResultListItem() {
void QuickOpenResultListItem::set_content(const QuickOpenResultCandidate &p_candidate, bool p_highlight) {
thumbnail->set_texture(p_candidate.thumbnail);
const String file_path = ResourceUID::ensure_path(p_candidate.file_path);
name->set_text(file_path.get_file());
path->set_text(file_path.get_base_dir());
name->set_text(p_candidate.file_path.get_file());
path->set_text(p_candidate.file_path.get_base_dir());
name->reset_highlights();
path->reset_highlights();
@ -1053,9 +1114,8 @@ QuickOpenResultGridItem::QuickOpenResultGridItem() {
void QuickOpenResultGridItem::set_content(const QuickOpenResultCandidate &p_candidate, bool p_highlight) {
thumbnail->set_texture(p_candidate.thumbnail);
const String file_path = ResourceUID::ensure_path(p_candidate.file_path);
name->set_text(file_path.get_file());
name->set_tooltip_text(file_path);
name->set_text(p_candidate.file_path.get_file());
name->set_tooltip_text(p_candidate.file_path);
name->reset_highlights();
if (p_highlight && p_candidate.result != nullptr) {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_QUICK_OPEN_DIALOG_H
#define EDITOR_QUICK_OPEN_DIALOG_H
#pragma once
#include "core/templates/oa_hash_map.h"
#include "scene/gui/dialogs.h"
@ -107,7 +106,6 @@ protected:
void _notification(int p_what);
private:
static constexpr int SHOW_ALL_FILES_THRESHOLD = 30;
static constexpr int MAX_HISTORY_SIZE = 20;
Vector<FuzzySearchResult> search_results;
@ -117,13 +115,13 @@ private:
Vector<QuickOpenResultCandidate> candidates;
OAHashMap<StringName, Vector<QuickOpenResultCandidate>> selected_history;
HashSet<String> history_set;
String query;
int selection_index = -1;
int num_visible_results = 0;
int max_total_results = 0;
bool showing_history = false;
bool never_opened = true;
Ref<ConfigFile> history_file;
@ -149,9 +147,11 @@ private:
static QuickOpenDisplayMode get_adaptive_display_mode(const Vector<StringName> &p_base_types);
void _ensure_result_vector_capacity();
void _sort_filepaths(int p_max_results);
void _create_initial_results();
void _find_filepaths_in_folder(EditorFileSystemDirectory *p_directory, bool p_include_addons);
Vector<QuickOpenResultCandidate> *_get_history();
void _setup_candidate(QuickOpenResultCandidate &p_candidate, const String &p_filepath);
void _setup_candidate(QuickOpenResultCandidate &p_candidate, const FuzzySearchResult &p_result);
void _update_fuzzy_search_results();
@ -268,5 +268,3 @@ private:
void _search_box_text_changed(const String &p_query);
};
#endif // EDITOR_QUICK_OPEN_DIALOG_H

View file

@ -47,9 +47,9 @@
#include "scene/gui/menu_button.h"
#include "scene/gui/panel_container.h"
#ifndef _3D_DISABLED
#ifndef XR_DISABLED
#include "servers/xr_server.h"
#endif // _3D_DISABLED
#endif // XR_DISABLED
EditorRunBar *EditorRunBar::singleton = nullptr;
@ -218,6 +218,10 @@ void EditorRunBar::_run_scene(const String &p_scene_path, const Vector<String> &
return;
}
if (!EditorNode::get_singleton()->validate_custom_directory()) {
return;
}
_reset_play_buttons();
String write_movie_file;
@ -255,7 +259,7 @@ void EditorRunBar::_run_scene(const String &p_scene_path, const Vector<String> &
String run_filename;
switch (current_mode) {
case RUN_CUSTOM: {
run_filename = p_scene_path;
run_filename = ResourceUID::ensure_path(p_scene_path);
run_custom_filename = run_filename;
} break;
@ -530,6 +534,7 @@ EditorRunBar::EditorRunBar() {
recovery_mode_reload_button->set_theme_type_variation("RunBarButton");
recovery_mode_reload_button->set_focus_mode(Control::FOCUS_NONE);
recovery_mode_reload_button->set_tooltip_text(TTR("Disable recovery mode and reload the project."));
recovery_mode_reload_button->set_accessibility_name(TTRC("Disable Recovery Mode"));
recovery_mode_reload_button->connect(SceneStringName(pressed), callable_mp(this, &EditorRunBar::recovery_mode_reload_project));
recovery_mode_panel = memnew(PanelContainer);
@ -552,6 +557,7 @@ EditorRunBar::EditorRunBar() {
play_button->set_toggle_mode(true);
play_button->set_focus_mode(Control::FOCUS_NONE);
play_button->set_tooltip_text(TTRC("Run the project's default scene."));
play_button->set_accessibility_name(TTRC("Run Default Scene"));
play_button->connect(SceneStringName(pressed), callable_mp(this, &EditorRunBar::play_main_scene).bind(false));
ED_SHORTCUT_AND_COMMAND("editor/run_project", TTRC("Run Project"), Key::F5);
@ -564,6 +570,7 @@ EditorRunBar::EditorRunBar() {
pause_button->set_toggle_mode(true);
pause_button->set_focus_mode(Control::FOCUS_NONE);
pause_button->set_tooltip_text(TTRC("Pause the running project's execution for debugging."));
pause_button->set_accessibility_name(TTRC("Pause"));
pause_button->set_disabled(true);
ED_SHORTCUT("editor/pause_running_project", TTRC("Pause Running Project"), Key::F7);
@ -575,6 +582,7 @@ EditorRunBar::EditorRunBar() {
stop_button->set_theme_type_variation("RunBarButton");
stop_button->set_focus_mode(Control::FOCUS_NONE);
stop_button->set_tooltip_text(TTRC("Stop the currently running project."));
stop_button->set_accessibility_name(TTRC("Stop"));
stop_button->set_disabled(true);
stop_button->connect(SceneStringName(pressed), callable_mp(this, &EditorRunBar::stop_playing));
@ -587,7 +595,7 @@ EditorRunBar::EditorRunBar() {
run_native->connect("native_run", callable_mp(this, &EditorRunBar::_run_native));
bool add_play_xr_mode_options = false;
#ifndef _3D_DISABLED
#ifndef XR_DISABLED
if (OS::get_singleton()->has_feature("xr_editor") &&
(XRServer::get_xr_mode() == XRServer::XRMODE_ON ||
(XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT && GLOBAL_GET("xr/openxr/enabled")))) {
@ -596,7 +604,7 @@ EditorRunBar::EditorRunBar() {
// either regular mode or XR mode.
add_play_xr_mode_options = true;
}
#endif // _3D_DISABLED
#endif // XR_DISABLED
if (add_play_xr_mode_options) {
MenuButton *menu_button = memnew(MenuButton);
@ -614,6 +622,7 @@ EditorRunBar::EditorRunBar() {
play_scene_button->set_theme_type_variation("RunBarButton");
play_scene_button->set_focus_mode(Control::FOCUS_NONE);
play_scene_button->set_tooltip_text(TTRC("Run the currently edited scene."));
play_scene_button->set_accessibility_name(TTRC("Run Edited Scene"));
ED_SHORTCUT_AND_COMMAND("editor/run_current_scene", TTRC("Run Current Scene"), Key::F6);
ED_SHORTCUT_OVERRIDE("editor/run_current_scene", "macos", KeyModifierMask::META | Key::R);
@ -635,6 +644,7 @@ EditorRunBar::EditorRunBar() {
play_custom_scene_button->set_theme_type_variation("RunBarButton");
play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE);
play_custom_scene_button->set_tooltip_text(TTRC("Run a specific scene."));
play_custom_scene_button->set_accessibility_name(TTRC("Run Specific Scene"));
ED_SHORTCUT_AND_COMMAND("editor/run_specific_scene", TTRC("Run Specific Scene"), KeyModifierMask::CTRL | KeyModifierMask::SHIFT | Key::F5);
ED_SHORTCUT_OVERRIDE("editor/run_specific_scene", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::R);
@ -650,5 +660,6 @@ EditorRunBar::EditorRunBar() {
write_movie_button->set_pressed(false);
write_movie_button->set_focus_mode(Control::FOCUS_NONE);
write_movie_button->set_tooltip_text(TTR("Enable Movie Maker mode.\nThe project will run at stable FPS and the visual and audio output will be recorded to a video file."));
write_movie_button->set_accessibility_name(TTRC("Enable Movie Maker Mode"));
write_movie_button->connect(SceneStringName(toggled), callable_mp(this, &EditorRunBar::_write_movie_toggled));
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_RUN_BAR_H
#define EDITOR_RUN_BAR_H
#pragma once
#include "editor/editor_run.h"
#include "editor/export/editor_export.h"
@ -132,5 +131,3 @@ public:
EditorRunBar();
};
#endif // EDITOR_RUN_BAR_H

View file

@ -67,6 +67,11 @@ void EditorSceneTabs::_notification(int p_what) {
_scene_tabs_resized();
}
} break;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_TRANSLATION_CHANGED: {
_scene_tabs_resized();
} break;
}
}
@ -116,15 +121,10 @@ void EditorSceneTabs::_scene_tab_exit() {
}
void EditorSceneTabs::_scene_tab_input(const Ref<InputEvent> &p_input) {
int tab_id = scene_tabs->get_hovered_tab();
Ref<InputEventMouseButton> mb = p_input;
if (mb.is_valid()) {
if (tab_id >= 0) {
if (mb->get_button_index() == MouseButton::MIDDLE && mb->is_pressed()) {
_scene_tab_closed(tab_id);
}
} else if (mb->get_button_index() == MouseButton::LEFT && mb->is_double_click()) {
if (mb->get_button_index() == MouseButton::LEFT && mb->is_double_click()) {
int tab_buttons = 0;
if (scene_tabs->get_offset_buttons_visible()) {
tab_buttons = get_theme_icon(SNAME("increment"), SNAME("TabBar"))->get_width() + get_theme_icon(SNAME("decrement"), SNAME("TabBar"))->get_width();
@ -203,7 +203,7 @@ void EditorSceneTabs::_update_context_menu() {
scene_tabs_context_menu->set_item_text(-1, TTR("Close Tab"));
scene_tabs_context_menu->add_shortcut(ED_GET_SHORTCUT("editor/reopen_closed_scene"), EditorNode::FILE_OPEN_PREV);
scene_tabs_context_menu->set_item_text(-1, TTR("Undo Close Tab"));
DISABLE_LAST_OPTION_IF(!EditorNode::get_singleton()->has_previous_scenes());
DISABLE_LAST_OPTION_IF(!EditorNode::get_singleton()->has_previous_closed_scenes());
scene_tabs_context_menu->add_item(TTR("Close Other Tabs"), SCENE_CLOSE_OTHERS);
DISABLE_LAST_OPTION_IF(EditorNode::get_editor_data().get_edited_scene_count() <= 1);
scene_tabs_context_menu->add_item(TTR("Close Tabs to the Right"), SCENE_CLOSE_RIGHT);
@ -437,6 +437,7 @@ EditorSceneTabs::EditorSceneTabs() {
scene_tab_add = memnew(Button);
scene_tab_add->set_flat(true);
scene_tab_add->set_tooltip_text(TTR("Add a new scene."));
scene_tab_add->set_accessibility_name(TTRC("Add Scene"));
scene_tabs->add_child(scene_tab_add);
scene_tab_add->connect(SceneStringName(pressed), callable_mp(EditorNode::get_singleton(), &EditorNode::trigger_menu_option).bind(EditorNode::FILE_NEW_SCENE, false));

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_SCENE_TABS_H
#define EDITOR_SCENE_TABS_H
#pragma once
#include "scene/gui/margin_container.h"
@ -106,5 +105,3 @@ public:
EditorSceneTabs();
};
#endif // EDITOR_SCENE_TABS_H

View file

@ -95,7 +95,7 @@ void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) {
}
grabbing_spinner_dist_cache += diff_x * grabbing_spinner_speed;
if (!grabbing_spinner && ABS(grabbing_spinner_dist_cache) > 4 * grabbing_spinner_speed * EDSCALE) {
if (!grabbing_spinner && Math::abs(grabbing_spinner_dist_cache) > 4 * grabbing_spinner_speed * EDSCALE) {
Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
grabbing_spinner = true;
}
@ -187,9 +187,11 @@ void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) {
if (mb->get_button_index() == MouseButton::WHEEL_UP) {
set_value(get_value() + get_step());
mousewheel_over_grabber = true;
accept_event();
} else if (mb->get_button_index() == MouseButton::WHEEL_DOWN) {
set_value(get_value() - get_step());
mousewheel_over_grabber = true;
accept_event();
}
}
}
@ -435,13 +437,11 @@ void EditorSpinSlider::_draw_spin_slider() {
grabber->set_texture(grabber_tex);
}
Vector2 scale = get_global_transform_with_canvas().get_scale();
grabber->set_scale(scale);
grabber->reset_size();
grabber->set_position((grabber_rect.get_center() - grabber->get_size() * 0.5) * scale);
grabber->set_position(grabber_rect.get_center() - grabber->get_size() * 0.5);
if (mousewheel_over_grabber) {
Input::get_singleton()->warp_mouse(grabber->get_position() + grabber_rect.size);
Input::get_singleton()->warp_mouse(grabber->get_global_position() + grabber_rect.size);
}
grabber_range = width;
@ -457,6 +457,8 @@ void EditorSpinSlider::_notification(int p_what) {
_update_value_input_stylebox();
} break;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
_update_value_input_stylebox();
} break;
@ -566,8 +568,8 @@ void EditorSpinSlider::_evaluate_input_text() {
expr.instantiate();
// Convert commas ',' to dots '.' for French/German etc. keyboard layouts.
String text = value_input->get_text().replace(",", ".");
text = text.replace(";", ",");
String text = value_input->get_text().replace_char(',', '.');
text = text.replace_char(';', ',');
text = TS->parse_number(text);
Error err = expr->parse(text);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_SPIN_SLIDER_H
#define EDITOR_SPIN_SLIDER_H
#pragma once
#include "scene/gui/line_edit.h"
#include "scene/gui/range.h"
@ -131,5 +130,3 @@ public:
virtual Size2 get_minimum_size() const override;
EditorSpinSlider();
};
#endif // EDITOR_SPIN_SLIDER_H

View file

@ -80,6 +80,53 @@ void EditorTitleBar::gui_input(const Ref<InputEvent> &p_event) {
}
}
void EditorTitleBar::set_center_control(Control *p_center_control) {
center_control = p_center_control;
}
Control *EditorTitleBar::get_center_control() const {
return center_control;
}
void EditorTitleBar::_notification(int p_what) {
if (!center_control || p_what != NOTIFICATION_SORT_CHILDREN) {
return;
}
Control *prev = nullptr;
Control *base = nullptr;
Control *next = nullptr;
for (int i = 0; i < get_child_count(); i++) {
Control *c = as_sortable_control(get_child(i));
if (!c) {
continue;
}
if (base) {
next = c;
break;
}
if (c != center_control) {
prev = c;
continue;
}
base = c;
}
if (base && prev && next) {
Size2i title_size = get_size();
Size2i c_size = base->get_combined_minimum_size();
int min_offset = prev->get_position().x + prev->get_combined_minimum_size().x;
int max_offset = next->get_position().x + next->get_size().x - next->get_combined_minimum_size().x - c_size.x;
int offset = (title_size.width - c_size.width) / 2;
offset = CLAMP(offset, min_offset, max_offset);
fit_child_in_rect(prev, Rect2i(prev->get_position().x, 0, offset - prev->get_position().x, title_size.height));
fit_child_in_rect(base, Rect2i(offset, 0, c_size.width, title_size.height));
fit_child_in_rect(next, Rect2i(offset + c_size.width, 0, next->get_position().x + next->get_size().x - (offset + c_size.width), title_size.height));
}
}
void EditorTitleBar::set_can_move_window(bool p_enabled) {
can_move = p_enabled;
set_process_input(can_move);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_TITLE_BAR_H
#define EDITOR_TITLE_BAR_H
#pragma once
#include "scene/gui/box_container.h"
#include "scene/main/window.h"
@ -40,14 +39,18 @@ class EditorTitleBar : public HBoxContainer {
Point2i click_pos;
bool moving = false;
bool can_move = false;
Control *center_control = nullptr;
protected:
void _notification(int p_what);
virtual void gui_input(const Ref<InputEvent> &p_event) override;
static void _bind_methods() {}
public:
void set_center_control(Control *p_center_control);
Control *get_center_control() const;
void set_can_move_window(bool p_enabled);
bool get_can_move_window() const;
};
#endif // EDITOR_TITLE_BAR_H

View file

@ -374,11 +374,13 @@ Control *EditorToaster::popup(Control *p_control, Severity p_severity, double p_
// Add buttons.
if (p_time > 0.0) {
Button *copy_button = memnew(Button);
copy_button->set_accessibility_name(TTRC("Copy"));
copy_button->set_flat(true);
copy_button->connect(SceneStringName(pressed), callable_mp(this, &EditorToaster::copy).bind(panel));
hbox_container->add_child(copy_button);
Button *close_button = memnew(Button);
close_button->set_accessibility_name(TTRC("Close"));
close_button->set_flat(true);
close_button->connect(SceneStringName(pressed), callable_mp(this, &EditorToaster::instant_close).bind(panel));
hbox_container->add_child(close_button);
@ -572,6 +574,7 @@ EditorToaster::EditorToaster() {
// Main button.
main_button = memnew(Button);
main_button->set_accessibility_name(TTRC("Notifications"));
main_button->set_tooltip_text(TTR("No notifications."));
main_button->set_modulate(Color(0.5, 0.5, 0.5));
main_button->set_disabled(true);
@ -588,6 +591,7 @@ EditorToaster::EditorToaster() {
add_child(disable_notifications_panel);
disable_notifications_button = memnew(Button);
disable_notifications_button->set_accessibility_name(TTRC("Silence Notifications"));
disable_notifications_button->set_tooltip_text(TTR("Silence the notifications."));
disable_notifications_button->set_flat(true);
disable_notifications_button->connect(SceneStringName(pressed), callable_mp(this, &EditorToaster::_set_notifications_enabled).bind(false));

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_TOASTER_H
#define EDITOR_TOASTER_H
#pragma once
#include "scene/gui/box_container.h"
@ -125,5 +124,3 @@ public:
};
VARIANT_ENUM_CAST(EditorToaster::Severity);
#endif // EDITOR_TOASTER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_VALIDATION_PANEL_H
#define EDITOR_VALIDATION_PANEL_H
#pragma once
#include "scene/gui/panel_container.h"
@ -84,5 +83,3 @@ public:
EditorValidationPanel();
};
#endif // EDITOR_VALIDATION_PANEL_H

View file

@ -37,20 +37,20 @@ String _get_version_string(EditorVersionButton::VersionFormat p_format) {
String main;
switch (p_format) {
case EditorVersionButton::FORMAT_BASIC: {
return VERSION_FULL_CONFIG;
return GODOT_VERSION_FULL_CONFIG;
} break;
case EditorVersionButton::FORMAT_WITH_BUILD: {
main = "v" VERSION_FULL_BUILD;
main = "v" GODOT_VERSION_FULL_BUILD;
} break;
case EditorVersionButton::FORMAT_WITH_NAME_AND_BUILD: {
main = VERSION_FULL_NAME;
main = GODOT_VERSION_FULL_NAME;
} break;
default: {
ERR_FAIL_V_MSG(VERSION_FULL_NAME, "Unexpected format: " + itos(p_format));
ERR_FAIL_V_MSG(GODOT_VERSION_FULL_NAME, "Unexpected format: " + itos(p_format));
} break;
}
String hash = VERSION_HASH;
String hash = GODOT_VERSION_HASH;
if (!hash.is_empty()) {
hash = vformat(" [%s]", hash.left(9));
}
@ -76,8 +76,8 @@ EditorVersionButton::EditorVersionButton(VersionFormat p_format) {
set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER);
String build_date;
if (VERSION_TIMESTAMP > 0) {
build_date = Time::get_singleton()->get_datetime_string_from_unix_time(VERSION_TIMESTAMP, true) + " UTC";
if (GODOT_VERSION_TIMESTAMP > 0) {
build_date = Time::get_singleton()->get_datetime_string_from_unix_time(GODOT_VERSION_TIMESTAMP, true) + " UTC";
} else {
build_date = TTR("(unknown)");
}

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_VERSION_BUTTON_H
#define EDITOR_VERSION_BUTTON_H
#pragma once
#include "scene/gui/link_button.h"
@ -57,5 +56,3 @@ protected:
public:
EditorVersionButton(VersionFormat p_format);
};
#endif // EDITOR_VERSION_BUTTON_H

View file

@ -187,6 +187,7 @@ void EditorZoomWidget::set_shortcut_context(Node *p_node) const {
EditorZoomWidget::EditorZoomWidget() {
// Zoom buttons
zoom_minus = memnew(Button);
zoom_minus->set_accessibility_name(TTRC("Zoom Out"));
zoom_minus->set_flat(true);
zoom_minus->set_shortcut(ED_SHORTCUT_ARRAY("canvas_item_editor/zoom_minus", TTRC("Zoom Out"), { int32_t(KeyModifierMask::CMD_OR_CTRL | Key::MINUS), int32_t(KeyModifierMask::CMD_OR_CTRL | Key::KP_SUBTRACT) }));
zoom_minus->set_shortcut_context(this);
@ -196,6 +197,7 @@ EditorZoomWidget::EditorZoomWidget() {
zoom_reset = memnew(Button);
zoom_reset->set_flat(true);
zoom_reset->set_accessibility_name(TTRC("Reset Zoom"));
Ref<StyleBoxEmpty> empty_stylebox = memnew(StyleBoxEmpty);
zoom_reset->add_theme_style_override(CoreStringName(normal), empty_stylebox);
@ -216,6 +218,7 @@ EditorZoomWidget::EditorZoomWidget() {
zoom_reset->connect(SceneStringName(pressed), callable_mp(this, &EditorZoomWidget::_button_zoom_reset));
zoom_plus = memnew(Button);
zoom_plus->set_accessibility_name(TTRC("Zoom In"));
zoom_plus->set_flat(true);
zoom_plus->set_shortcut(ED_SHORTCUT_ARRAY("canvas_item_editor/zoom_plus", TTRC("Zoom In"), { int32_t(KeyModifierMask::CMD_OR_CTRL | Key::EQUAL), int32_t(KeyModifierMask::CMD_OR_CTRL | Key::KP_ADD) }));
zoom_plus->set_shortcut_context(this);

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef EDITOR_ZOOM_WIDGET_H
#define EDITOR_ZOOM_WIDGET_H
#pragma once
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
@ -67,5 +66,3 @@ public:
// Sets the shortcut context for the zoom buttons. By default their context is this EditorZoomWidget control.
void set_shortcut_context(Node *p_node) const;
};
#endif // EDITOR_ZOOM_WIDGET_H

View file

@ -63,13 +63,13 @@ PackedStringArray SceneTreeEditor::_get_node_configuration_warnings(Node *p_node
if (node_2d) {
// Note: Warn for Node2D but not all CanvasItems, don't warn for Control nodes.
// Control nodes may have reasons to use a transformed root node like anchors.
if (!node_2d->get_transform().is_equal_approx(Transform2D())) {
if (!node_2d->get_position().is_zero_approx()) {
warnings.append(TTR("The root node of a scene is recommended to not be transformed, since instances of the scene will usually override this. Reset the transform and reload the scene to remove this warning."));
}
}
Node3D *node_3d = Object::cast_to<Node3D>(p_node);
if (node_3d) {
if (!node_3d->get_transform().is_equal_approx(Transform3D())) {
if (!node_3d->get_position().is_zero_approx()) {
warnings.append(TTR("The root node of a scene is recommended to not be transformed, since instances of the scene will usually override this. Reset the transform and reload the scene to remove this warning."));
}
}
@ -77,6 +77,12 @@ PackedStringArray SceneTreeEditor::_get_node_configuration_warnings(Node *p_node
return warnings;
}
PackedStringArray SceneTreeEditor::_get_node_accessibility_configuration_warnings(Node *p_node) {
PackedStringArray warnings = p_node->get_accessibility_configuration_warnings();
return warnings;
}
void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button) {
if (p_button != MouseButton::LEFT) {
return;
@ -112,7 +118,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
} else if (p_id == BUTTON_VISIBILITY) {
undo_redo->create_action(TTR("Toggle Visible"));
_toggle_visible(n);
List<Node *> selection = editor_selection->get_selected_node_list();
List<Node *> selection = editor_selection->get_top_selected_node_list();
if (selection.size() > 1 && selection.find(n) != nullptr) {
for (Node *nv : selection) {
ERR_FAIL_NULL(nv);
@ -151,8 +157,10 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i
}
undo_redo->commit_action();
} else if (p_id == BUTTON_WARNING) {
const PackedStringArray warnings = _get_node_configuration_warnings(n);
PackedStringArray warnings = _get_node_configuration_warnings(n);
if (accessibility_warnings) {
warnings.append_array(_get_node_accessibility_configuration_warnings(n));
}
if (warnings.is_empty()) {
return;
}
@ -447,7 +455,7 @@ void SceneTreeEditor::_update_node(Node *p_node, TreeItem *p_item, bool p_part_o
_set_item_custom_color(p_item, accent);
}
} else if (p_part_of_subscene) {
if (valid_types.size() == 0) {
if (valid_types.is_empty()) {
_set_item_custom_color(p_item, get_theme_color(SNAME("warning_color"), EditorStringName(Editor)));
}
} else if (marked.has(p_node)) {
@ -473,7 +481,11 @@ void SceneTreeEditor::_update_node(Node *p_node, TreeItem *p_item, bool p_part_o
}
if (can_rename) { // TODO Should be can edit..
const PackedStringArray warnings = _get_node_configuration_warnings(p_node);
PackedStringArray warnings = _get_node_configuration_warnings(p_node);
if (accessibility_warnings) {
warnings.append_array(_get_node_accessibility_configuration_warnings(p_node));
}
const int num_warnings = warnings.size();
if (num_warnings > 0) {
StringName warning_icon;
@ -512,8 +524,7 @@ void SceneTreeEditor::_update_node(Node *p_node, TreeItem *p_item, bool p_part_o
String msg_temp;
if (num_connections >= 1) {
Array arr;
arr.push_back(num_connections);
Array arr = { num_connections };
msg_temp += TTRN("Node has one connection.", "Node has {num} connections.", num_connections).format(arr, "{num}");
if (num_groups >= 1) {
msg_temp += "\n";
@ -1291,7 +1302,7 @@ void SceneTreeEditor::_cell_multi_selected(Object *p_object, int p_cell, bool p_
void SceneTreeEditor::_tree_scroll_to_item(ObjectID p_item_id) {
ERR_FAIL_NULL(tree);
TreeItem *item = Object::cast_to<TreeItem>(ObjectDB::get_instance(p_item_id));
TreeItem *item = ObjectDB::get_instance<TreeItem>(p_item_id);
if (item) {
tree->scroll_to_item(item, true);
}
@ -1840,7 +1851,7 @@ Variant SceneTreeEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from
}
bool SceneTreeEditor::_is_script_type(const StringName &p_type) const {
return (script_types->find(p_type));
return (script_types->has(p_type));
}
bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const {
@ -1853,12 +1864,12 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_d
return false;
}
TreeItem *item = tree->get_item_at_position(p_point);
TreeItem *item = (p_point == Vector2(Math::INF, Math::INF)) ? tree->get_selected() : tree->get_item_at_position(p_point);
if (!item) {
return false;
}
int section = tree->get_drop_section_at_position(p_point);
int section = (p_point == Vector2(Math::INF, Math::INF)) ? tree->get_drop_section_at_position(tree->get_item_rect(item).position) : tree->get_drop_section_at_position(p_point);
if (section < -1 || (section == -1 && !item->get_parent())) {
return false;
}
@ -1866,7 +1877,7 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_d
if (String(d["type"]) == "files") {
Vector<String> files = d["files"];
if (files.size() == 0) {
if (files.is_empty()) {
return false; // TODO Weird?
}
@ -1942,11 +1953,11 @@ void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data,
return;
}
TreeItem *item = tree->get_item_at_position(p_point);
TreeItem *item = (p_point == Vector2(Math::INF, Math::INF)) ? tree->get_selected() : tree->get_item_at_position(p_point);
if (!item) {
return;
}
int section = tree->get_drop_section_at_position(p_point);
int section = (p_point == Vector2(Math::INF, Math::INF)) ? tree->get_drop_section_at_position(tree->get_item_rect(item).position) : tree->get_drop_section_at_position(p_point);
if (section < -1) {
return;
}
@ -2036,6 +2047,13 @@ void SceneTreeEditor::set_hide_filtered_out_parents(bool p_hide, bool p_update_s
}
}
void SceneTreeEditor::set_accessibility_warnings(bool p_enable, bool p_update_settings) {
if (p_update_settings) {
EditorSettings::get_singleton()->set("docks/scene_tree/accessibility_warnings", p_enable);
}
accessibility_warnings = p_enable;
}
void SceneTreeEditor::set_connect_to_script_mode(bool p_enable) {
connect_to_script_mode = p_enable;
_update_tree();
@ -2145,8 +2163,8 @@ SceneTreeEditor::SceneTreeEditor(bool p_label, bool p_can_rename, bool p_can_ope
ask_before_revoke_checkbox->set_tooltip_text(TTR("This dialog can also be enabled/disabled in the Editor Settings: Docks > Scene Tree > Ask Before Revoking Unique Name."));
vb->add_child(ask_before_revoke_checkbox);
script_types = memnew(List<StringName>);
ClassDB::get_inheriters_from_class("Script", script_types);
script_types = memnew(LocalVector<StringName>);
ClassDB::get_inheriters_from_class("Script", *script_types);
}
SceneTreeEditor::~SceneTreeEditor() {
@ -2341,9 +2359,6 @@ SceneTreeDialog::SceneTreeDialog() {
tree->connect("node_selected", callable_mp(this, &SceneTreeDialog::_selected_changed));
}
SceneTreeDialog::~SceneTreeDialog() {
}
/******** CACHE *********/
HashMap<Node *, SceneTreeEditor::CachedNode>::Iterator SceneTreeEditor::NodeCache::add(Node *p_node, TreeItem *p_item) {

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef SCENE_TREE_EDITOR_H
#define SCENE_TREE_EDITOR_H
#pragma once
#include "scene/gui/check_box.h"
#include "scene/gui/check_button.h"
@ -128,6 +127,7 @@ class SceneTreeEditor : public Control {
bool auto_expand_selected = true;
bool hide_filtered_out_parents = false;
bool accessibility_warnings = false;
bool connect_to_script_mode = false;
bool connecting_signal = false;
bool update_when_invisible = true;
@ -137,6 +137,7 @@ class SceneTreeEditor : public Control {
void _compute_hash(Node *p_node, uint64_t &hash);
void _reset();
PackedStringArray _get_node_configuration_warnings(Node *p_node);
PackedStringArray _get_node_accessibility_configuration_warnings(Node *p_node);
void _update_node_path(Node *p_node, bool p_recursive = true);
void _update_node_subtree(Node *p_node, TreeItem *p_parent, bool p_force = false);
@ -213,7 +214,7 @@ class SceneTreeEditor : public Control {
Timer *update_timer = nullptr;
List<StringName> *script_types;
LocalVector<StringName> *script_types;
bool _is_script_type(const StringName &p_type) const;
Vector<StringName> valid_types;
@ -249,6 +250,7 @@ public:
void set_auto_expand_selected(bool p_auto, bool p_update_settings);
void set_hide_filtered_out_parents(bool p_hide, bool p_update_settings);
void set_accessibility_warnings(bool p_enable, bool p_update_settings);
void set_connect_to_script_mode(bool p_enable);
void set_connecting_signal(bool p_enable);
void set_update_when_invisible(bool p_enable);
@ -291,7 +293,4 @@ public:
LineEdit *get_filter_line_edit() { return filter; }
SceneTreeDialog();
~SceneTreeDialog();
};
#endif // SCENE_TREE_EDITOR_H

View file

@ -0,0 +1,184 @@
/**************************************************************************/
/* touch_actions_panel.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "touch_actions_panel.h"
#include "core/input/input.h"
#include "editor/editor_settings.h"
#include "editor/editor_string_names.h"
#include "scene/gui/box_container.h"
#include "scene/gui/button.h"
#include "scene/gui/color_rect.h"
#include "scene/gui/texture_rect.h"
#include "scene/resources/style_box_flat.h"
void TouchActionsPanel::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_ENTER_TREE: {
DisplayServer::get_singleton()->set_hardware_keyboard_connection_change_callback(callable_mp(this, &TouchActionsPanel::_hardware_keyboard_connected));
_hardware_keyboard_connected(DisplayServer::get_singleton()->has_hardware_keyboard());
} break;
case NOTIFICATION_THEME_CHANGED: {
drag_handle->set_texture(get_editor_theme_icon(SNAME("DragHandle")));
layout_toggle_button->set_button_icon(get_editor_theme_icon(SNAME("Orientation")));
lock_panel_button->set_button_icon(get_editor_theme_icon(SNAME("Lock")));
save_button->set_button_icon(get_editor_theme_icon(SNAME("Save")));
delete_button->set_button_icon(get_editor_theme_icon(SNAME("Remove")));
undo_button->set_button_icon(get_editor_theme_icon(SNAME("UndoRedo")));
redo_button->set_button_icon(get_editor_theme_icon(SNAME("Redo")));
} break;
}
}
void TouchActionsPanel::_hardware_keyboard_connected(bool p_connected) {
set_visible(!p_connected);
}
void TouchActionsPanel::_simulate_editor_shortcut(const String &p_shortcut_name) {
Ref<Shortcut> shortcut = ED_GET_SHORTCUT(p_shortcut_name);
if (shortcut.is_valid() && !shortcut->get_events().is_empty()) {
Ref<InputEventKey> event = shortcut->get_events()[0];
if (event.is_valid()) {
event->set_pressed(true);
Input::get_singleton()->parse_input_event(event);
}
}
}
void TouchActionsPanel::_simulate_key_press(Key p_keycode) {
Ref<InputEventKey> event;
event.instantiate();
event->set_keycode(p_keycode);
event->set_pressed(true);
Input::get_singleton()->parse_input_event(event);
}
Button *TouchActionsPanel::_add_new_action_button(const String &p_shortcut, const String &p_name, Key p_keycode) {
Button *action_button = memnew(Button);
action_button->set_focus_mode(Control::FOCUS_NONE);
action_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
action_button->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
action_button->set_accessibility_name(p_name);
if (p_keycode == Key::NONE) {
action_button->connect(SceneStringName(pressed), callable_mp(this, &TouchActionsPanel::_simulate_editor_shortcut).bind(p_shortcut));
} else {
action_button->connect(SceneStringName(pressed), callable_mp(this, &TouchActionsPanel::_simulate_key_press).bind(p_keycode));
}
box->add_child(action_button);
return action_button;
}
void TouchActionsPanel::_on_drag_handle_gui_input(const Ref<InputEvent> &p_event) {
if (lock_panel_position) {
return;
}
Ref<InputEventMouseButton> mouse_button_event = p_event;
if (mouse_button_event.is_valid() && mouse_button_event->get_button_index() == MouseButton::LEFT) {
if (mouse_button_event->is_pressed()) {
dragging = true;
drag_offset = mouse_button_event->get_position();
} else {
dragging = false;
}
}
Ref<InputEventMouseMotion> mouse_motion_event = p_event;
if (dragging && mouse_motion_event.is_valid()) {
Vector2 new_position = get_position() + mouse_motion_event->get_relative();
const float margin = 25.0;
Vector2 parent_size = get_parent_area_size();
Vector2 panel_size = get_size();
new_position = new_position.clamp(Vector2(margin, margin), parent_size - panel_size - Vector2(margin, margin));
set_position(new_position);
}
}
void TouchActionsPanel::_switch_layout() {
box->set_vertical(!box->is_vertical());
reset_size();
}
void TouchActionsPanel::_lock_panel_toggled(bool p_pressed) {
lock_panel_position = p_pressed;
layout_toggle_button->set_disabled(p_pressed);
}
TouchActionsPanel::TouchActionsPanel() {
Ref<StyleBoxFlat> panel_style;
panel_style.instantiate();
panel_style->set_bg_color(Color(0.1, 0.1, 0.1, 1));
panel_style->set_border_color(Color(0.3, 0.3, 0.3, 1));
panel_style->set_border_width_all(3);
panel_style->set_corner_radius_all(10);
panel_style->set_content_margin_all(12);
add_theme_style_override(SceneStringName(panel), panel_style);
set_anchors_and_offsets_preset(Control::PRESET_CENTER_BOTTOM, Control::PRESET_MODE_MINSIZE, 80);
box = memnew(BoxContainer);
box->set_alignment(BoxContainer::ALIGNMENT_CENTER);
box->add_theme_constant_override("separation", 15);
add_child(box);
drag_handle = memnew(TextureRect);
drag_handle->set_custom_minimum_size(Size2(40, 40));
drag_handle->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
drag_handle->connect(SceneStringName(gui_input), callable_mp(this, &TouchActionsPanel::_on_drag_handle_gui_input));
box->add_child(drag_handle);
layout_toggle_button = memnew(Button);
layout_toggle_button->set_accessibility_name(TTRC("Switch Layout"));
layout_toggle_button->set_focus_mode(Control::FOCUS_NONE);
layout_toggle_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
layout_toggle_button->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
layout_toggle_button->connect(SceneStringName(pressed), callable_mp(this, &TouchActionsPanel::_switch_layout));
box->add_child(layout_toggle_button);
lock_panel_button = memnew(Button);
lock_panel_button->set_toggle_mode(true);
lock_panel_button->set_accessibility_name(TTRC("Lock Panel"));
lock_panel_button->set_focus_mode(Control::FOCUS_NONE);
lock_panel_button->set_h_size_flags(Control::SIZE_SHRINK_CENTER);
lock_panel_button->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
lock_panel_button->connect(SceneStringName(toggled), callable_mp(this, &TouchActionsPanel::_lock_panel_toggled));
box->add_child(lock_panel_button);
ColorRect *separator = memnew(ColorRect);
separator->set_color(Color(0.5, 0.5, 0.5));
separator->set_custom_minimum_size(Size2(2, 2));
box->add_child(separator);
// Add action buttons.
save_button = _add_new_action_button("editor/save_scene", TTR("Save"));
delete_button = _add_new_action_button("", TTR("Delete"), Key::KEY_DELETE);
undo_button = _add_new_action_button("ui_undo", TTR("Undo"));
redo_button = _add_new_action_button("ui_redo", TTR("Redo"));
}

View file

@ -0,0 +1,70 @@
/**************************************************************************/
/* touch_actions_panel.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "scene/gui/panel_container.h"
class BoxContainer;
class Button;
class TextureRect;
class TouchActionsPanel : public PanelContainer {
GDCLASS(TouchActionsPanel, PanelContainer);
private:
BoxContainer *box = nullptr;
Button *save_button = nullptr;
Button *delete_button = nullptr;
Button *undo_button = nullptr;
Button *redo_button = nullptr;
TextureRect *drag_handle = nullptr;
Button *layout_toggle_button = nullptr;
Button *lock_panel_button = nullptr;
bool lock_panel_position = false;
bool dragging = false;
Vector2 drag_offset;
void _notification(int p_what);
void _simulate_editor_shortcut(const String &p_shortcut_name);
void _simulate_key_press(Key p_keycode);
void _on_drag_handle_gui_input(const Ref<InputEvent> &p_event);
void _switch_layout();
void _lock_panel_toggled(bool p_pressed);
Button *_add_new_action_button(const String &p_shortcut, const String &p_name, Key p_keycode = Key::NONE);
void _hardware_keyboard_connected(bool p_connected);
public:
TouchActionsPanel();
};