You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-15 13:51:40 +00:00
Add toggle for instant preview Always keep search box selected so that keyboard navigation works Add default setting for Instant Preview Directly set property value for resource via Quick Load menu (no undo/redo or dirty-scene functionality yet) Add undo/redo functionality Update class reference Update doc/classes/EditorSettings.xml Co-authored-by: Micky <66727710+Mickeon@users.noreply.github.com> Slight improvement(?) to wording of setting Allow previewing without committing change Address various suggestions/improvements Only allow Instant Preview to be used if Quick Open menu is being used to modify a property Only allow property-based Quick Load when resource to modify is defined (otherwise default to old behavior) Apply suggestions from code review Co-authored-by: Tomasz Chabora <kobewi4e@gmail.com> Address comments/suggestions Get rid of duplicated code and use original callback strategy (Attempt to) fix Instant Preview for editing multiple nodes at once and undo/redo stack for single nodes Fix cancelling Quick Open when multiple nodes are selected Prevent initially selected item in Quick Open dialog from overwriting the currently selected property Apply suggestions from code review Co-authored-by: Tomasz Chabora <kobewi4e@gmail.com> Co-authored-by: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> Make a few changes/improvements based on feedback - Combine some duplicated code into `_finish_dialog_setup()` - Move `ERR_FAIL_NULL(p_obj);` to top of checks - Fix renaming of `is_instant_preview_enabled()` across code, and remove now-redundant conditions where it is used - Make `EditorResourcePicker::property_path` be `StringName` not `String`
288 lines
9.0 KiB
C++
288 lines
9.0 KiB
C++
/**************************************************************************/
|
|
/* editor_quick_open_dialog.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 "core/templates/a_hash_map.h"
|
|
#include "scene/gui/dialogs.h"
|
|
#include "scene/gui/margin_container.h"
|
|
|
|
class Button;
|
|
class CenterContainer;
|
|
class CheckButton;
|
|
class ConfigFile;
|
|
class EditorFileSystemDirectory;
|
|
class LineEdit;
|
|
class HFlowContainer;
|
|
class MarginContainer;
|
|
class PanelContainer;
|
|
class PopupMenu;
|
|
class ScrollContainer;
|
|
class StringName;
|
|
class Texture2D;
|
|
class TextureRect;
|
|
class VBoxContainer;
|
|
|
|
class FuzzySearchResult;
|
|
|
|
class QuickOpenResultItem;
|
|
|
|
enum class QuickOpenDisplayMode {
|
|
GRID,
|
|
LIST,
|
|
};
|
|
|
|
struct QuickOpenResultCandidate {
|
|
String file_path;
|
|
Ref<Texture2D> thumbnail;
|
|
const FuzzySearchResult *result = nullptr;
|
|
};
|
|
|
|
class HighlightedLabel : public Label {
|
|
GDCLASS(HighlightedLabel, Label)
|
|
|
|
Vector<Vector2i> highlights;
|
|
|
|
void draw_substr_rects(const Vector2i &p_substr, Vector2 p_offset, int p_line_limit, int line_spacing);
|
|
|
|
public:
|
|
void add_highlight(const Vector2i &p_interval);
|
|
void reset_highlights();
|
|
|
|
protected:
|
|
void _notification(int p_notification);
|
|
};
|
|
|
|
class QuickOpenResultContainer : public VBoxContainer {
|
|
GDCLASS(QuickOpenResultContainer, VBoxContainer)
|
|
|
|
enum {
|
|
FILE_SHOW_IN_FILESYSTEM,
|
|
FILE_SHOW_IN_FILE_MANAGER
|
|
};
|
|
|
|
public:
|
|
void init(const Vector<StringName> &p_base_types);
|
|
void handle_search_box_input(const Ref<InputEvent> &p_ie);
|
|
void set_query_and_update(const String &p_query);
|
|
void update_results();
|
|
|
|
bool has_nothing_selected() const;
|
|
String get_selected() const;
|
|
|
|
bool is_instant_preview_enabled() const;
|
|
void set_instant_preview_toggle_visible(bool p_visible);
|
|
|
|
void save_selected_item();
|
|
void cleanup();
|
|
|
|
QuickOpenResultContainer();
|
|
|
|
protected:
|
|
void _notification(int p_what);
|
|
|
|
private:
|
|
static constexpr int MAX_HISTORY_SIZE = 20;
|
|
|
|
Vector<FuzzySearchResult> search_results;
|
|
Vector<StringName> base_types;
|
|
Vector<String> filepaths;
|
|
AHashMap<String, StringName> filetypes;
|
|
Vector<QuickOpenResultCandidate> candidates;
|
|
|
|
AHashMap<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 never_opened = true;
|
|
Ref<ConfigFile> history_file;
|
|
|
|
QuickOpenDisplayMode content_display_mode = QuickOpenDisplayMode::LIST;
|
|
Vector<QuickOpenResultItem *> result_items;
|
|
|
|
ScrollContainer *scroll_container = nullptr;
|
|
VBoxContainer *list = nullptr;
|
|
HFlowContainer *grid = nullptr;
|
|
PopupMenu *file_context_menu = nullptr;
|
|
|
|
PanelContainer *panel_container = nullptr;
|
|
CenterContainer *no_results_container = nullptr;
|
|
Label *no_results_label = nullptr;
|
|
|
|
Label *file_details_path = nullptr;
|
|
Button *display_mode_toggle = nullptr;
|
|
CheckButton *instant_preview_toggle = nullptr;
|
|
CheckButton *include_addons_toggle = nullptr;
|
|
CheckButton *fuzzy_search_toggle = nullptr;
|
|
|
|
AHashMap<StringName, Ref<Texture2D>> file_type_icons;
|
|
|
|
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();
|
|
void _use_default_candidates();
|
|
void _score_and_sort_candidates();
|
|
void _update_result_items(int p_new_visible_results_count, int p_new_selection_index);
|
|
|
|
void _move_selection_index(Key p_key);
|
|
void _select_item(int p_index);
|
|
|
|
void _item_input(const Ref<InputEvent> &p_ev, int p_index);
|
|
|
|
CanvasItem *_get_result_root();
|
|
void _layout_result_item(QuickOpenResultItem *p_item);
|
|
void _set_display_mode(QuickOpenDisplayMode p_display_mode);
|
|
void _toggle_display_mode();
|
|
void _toggle_instant_preview(bool p_pressed);
|
|
void _toggle_include_addons(bool p_pressed);
|
|
void _toggle_fuzzy_search(bool p_pressed);
|
|
void _menu_option(int p_option);
|
|
|
|
String _get_cache_file_path() const;
|
|
|
|
static void _bind_methods();
|
|
};
|
|
|
|
class QuickOpenResultGridItem : public MarginContainer {
|
|
GDCLASS(QuickOpenResultGridItem, MarginContainer)
|
|
|
|
public:
|
|
QuickOpenResultGridItem();
|
|
|
|
void reset();
|
|
void set_content(const QuickOpenResultCandidate &p_candidate, bool p_highlight);
|
|
void highlight_item(const Color &p_color);
|
|
void remove_highlight();
|
|
|
|
private:
|
|
VBoxContainer *vbc = nullptr;
|
|
TextureRect *thumbnail = nullptr;
|
|
HighlightedLabel *name = nullptr;
|
|
};
|
|
|
|
class QuickOpenResultListItem : public MarginContainer {
|
|
GDCLASS(QuickOpenResultListItem, MarginContainer)
|
|
|
|
public:
|
|
QuickOpenResultListItem();
|
|
|
|
void reset();
|
|
void set_content(const QuickOpenResultCandidate &p_candidate, bool p_highlight);
|
|
void highlight_item(const Color &p_color);
|
|
void remove_highlight();
|
|
|
|
protected:
|
|
void _notification(int p_what);
|
|
|
|
private:
|
|
HBoxContainer *hbc = nullptr;
|
|
VBoxContainer *text_container = nullptr;
|
|
|
|
TextureRect *thumbnail = nullptr;
|
|
HighlightedLabel *name = nullptr;
|
|
HighlightedLabel *path = nullptr;
|
|
};
|
|
|
|
class QuickOpenResultItem : public HBoxContainer {
|
|
GDCLASS(QuickOpenResultItem, HBoxContainer)
|
|
|
|
public:
|
|
QuickOpenResultItem();
|
|
|
|
bool enable_highlights = true;
|
|
|
|
void reset();
|
|
void set_content(const QuickOpenResultCandidate &p_candidate);
|
|
void set_display_mode(QuickOpenDisplayMode p_display_mode);
|
|
void highlight_item(bool p_enabled);
|
|
|
|
protected:
|
|
void _notification(int p_what);
|
|
|
|
private:
|
|
QuickOpenResultListItem *list_item = nullptr;
|
|
QuickOpenResultGridItem *grid_item = nullptr;
|
|
|
|
Ref<StyleBox> selected_stylebox;
|
|
Ref<StyleBox> hovering_stylebox;
|
|
Color highlighted_font_color;
|
|
|
|
bool is_hovering = false;
|
|
bool is_selected = false;
|
|
|
|
void _set_enabled(bool p_enabled);
|
|
};
|
|
|
|
class EditorQuickOpenDialog : public AcceptDialog {
|
|
GDCLASS(EditorQuickOpenDialog, AcceptDialog);
|
|
|
|
public:
|
|
void popup_dialog(const Vector<StringName> &p_base_types, const Callable &p_item_selected_callback);
|
|
void popup_dialog_for_property(const Vector<StringName> &p_base_types, Object *p_obj, const StringName &p_path, const Callable &p_item_selected_callback);
|
|
EditorQuickOpenDialog();
|
|
|
|
protected:
|
|
virtual void cancel_pressed() override;
|
|
virtual void ok_pressed() override;
|
|
void item_pressed(bool p_double_click);
|
|
void selection_changed();
|
|
|
|
private:
|
|
static String get_dialog_title(const Vector<StringName> &p_base_types);
|
|
|
|
LineEdit *search_box = nullptr;
|
|
QuickOpenResultContainer *container = nullptr;
|
|
|
|
Callable item_selected_callback;
|
|
|
|
Object *property_object = nullptr;
|
|
StringName property_path;
|
|
Variant initial_property_value;
|
|
bool initial_selection_performed = false;
|
|
bool _is_instant_preview_active() const;
|
|
void _search_box_text_changed(const String &p_query);
|
|
void _finish_dialog_setup(const Vector<StringName> &p_base_types);
|
|
|
|
void preview_property();
|
|
void update_property();
|
|
};
|