Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow contextual plugins to persist temporarily #81523

Merged
merged 1 commit into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions editor/editor_inspector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3391,11 +3391,16 @@ Object *EditorInspector::get_edited_object() {
return object;
}

Object *EditorInspector::get_next_edited_object() {
return next_object;
}

void EditorInspector::edit(Object *p_object) {
if (object == p_object) {
return;
}

next_object = p_object; // Some plugins need to know the next edited object when clearing the inspector.
if (object) {
_clear();
object->disconnect("property_list_changed", callable_mp(this, &EditorInspector::_changed_callback));
Expand All @@ -3412,6 +3417,10 @@ void EditorInspector::edit(Object *p_object) {
object->connect("property_list_changed", callable_mp(this, &EditorInspector::_changed_callback));
update_tree();
}

// Keep it available until the end so it works with both main and sub inspectors.
next_object = nullptr;

emit_signal(SNAME("edited_object_changed"));
}

Expand Down
2 changes: 2 additions & 0 deletions editor/editor_inspector.h
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ class EditorInspector : public ScrollContainer {

void _clear(bool p_hide_plugins = true);
Object *object = nullptr;
Object *next_object = nullptr;

//

Expand Down Expand Up @@ -576,6 +577,7 @@ class EditorInspector : public ScrollContainer {
void update_property(const String &p_prop);
void edit(Object *p_object);
Object *get_edited_object();
Object *get_next_edited_object();

void set_keying(bool p_active);
void set_read_only(bool p_read_only);
Expand Down
40 changes: 36 additions & 4 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,10 @@ void EditorNode::_plugin_over_edit(EditorPlugin *p_plugin, Object *p_object) {
}
}

void EditorNode::_plugin_over_self_own(EditorPlugin *p_plugin) {
active_plugins[p_plugin->get_instance_id()].insert(p_plugin);
}

void EditorNode::_resources_changed(const Vector<String> &p_resources) {
List<Ref<Resource>> changed;

Expand Down Expand Up @@ -2135,7 +2139,12 @@ void EditorNode::edit_item(Object *p_object, Object *p_editing_owner) {
for (EditorPlugin *plugin : active_plugins[owner_id]) {
if (!available_plugins.has(plugin)) {
to_remove.push_back(plugin);
_plugin_over_edit(plugin, nullptr);
if (plugin->can_auto_hide()) {
_plugin_over_edit(plugin, nullptr);
} else {
// If plugin can't be hidden, make it own itself and become responsible for closing.
_plugin_over_self_own(plugin);
}
}
}

Expand All @@ -2151,6 +2160,12 @@ void EditorNode::edit_item(Object *p_object, Object *p_editing_owner) {
continue;
}

if (active_plugins.has(plugin->get_instance_id())) {
// Plugin is already active, but as self-owning, so it needs a separate check.
plugin->edit(p_object);
continue;
}

// If plugin is already associated with another owner, remove it from there first.
for (KeyValue<ObjectID, HashSet<EditorPlugin *>> &kv : active_plugins) {
if (kv.key != owner_id) {
Expand Down Expand Up @@ -2214,18 +2229,35 @@ void EditorNode::hide_unused_editors(const Object *p_editing_owner) {
if (p_editing_owner) {
const ObjectID id = p_editing_owner->get_instance_id();
for (EditorPlugin *plugin : active_plugins[id]) {
_plugin_over_edit(plugin, nullptr);
if (plugin->can_auto_hide()) {
_plugin_over_edit(plugin, nullptr);
} else {
_plugin_over_self_own(plugin);
}
}
active_plugins.erase(id);
} else {
// If no editing owner is provided, this method will go over all owners and check if they are valid.
// This is to sweep properties that were removed from the inspector.
List<ObjectID> to_remove;
for (KeyValue<ObjectID, HashSet<EditorPlugin *>> &kv : active_plugins) {
if (!ObjectDB::get_instance(kv.key)) {
const Object *context = ObjectDB::get_instance(kv.key);
if (context) {
// In case of self-owning plugins, they are disabled here if they can auto hide.
const EditorPlugin *self_owning = Object::cast_to<EditorPlugin>(context);
if (self_owning && self_owning->can_auto_hide()) {
context = nullptr;
}
}

if (!context) {
to_remove.push_back(kv.key);
for (EditorPlugin *plugin : kv.value) {
_plugin_over_edit(plugin, nullptr);
if (plugin->can_auto_hide()) {
_plugin_over_edit(plugin, nullptr);
} else {
_plugin_over_self_own(plugin);
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions editor/editor_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ class EditorNode : public Node {

void _remove_plugin_from_enabled(const String &p_name);
void _plugin_over_edit(EditorPlugin *p_plugin, Object *p_object);
void _plugin_over_self_own(EditorPlugin *p_plugin);

void _fs_changed();
void _resources_reimported(const Vector<String> &p_resources);
Expand Down
4 changes: 4 additions & 0 deletions editor/editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ bool EditorPlugin::handles(Object *p_object) const {
return success;
}

bool EditorPlugin::can_auto_hide() const {
return true;
}

Dictionary EditorPlugin::get_state() const {
Dictionary state;
GDVIRTUAL_CALL(_get_state, state);
Expand Down
1 change: 1 addition & 0 deletions editor/editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ class EditorPlugin : public Node {
virtual void selected_notify() {} //notify that it was raised by the user, not the editor
virtual void edit(Object *p_object);
virtual bool handles(Object *p_object) const;
virtual bool can_auto_hide() const;
virtual Dictionary get_state() const; //save editor state so it can't be reloaded when reloading scene
virtual void set_state(const Dictionary &p_state); //restore editor state (likely was saved with the scene)
virtual void clear(); // clear any temporary data in the editor, reset it (likely new scene or load another scene)
Expand Down
102 changes: 90 additions & 12 deletions editor/plugins/theme_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "editor/editor_string_names.h"
#include "editor/editor_undo_redo_manager.h"
#include "editor/gui/editor_file_dialog.h"
#include "editor/inspector_dock.h"
#include "editor/progress_dialog.h"
#include "scene/gui/check_button.h"
#include "scene/gui/color_picker.h"
Expand Down Expand Up @@ -3528,6 +3529,16 @@ void ThemeEditor::_theme_edit_button_cbk() {
theme_edit_dialog->popup_centered(Size2(850, 700) * EDSCALE);
}

void ThemeEditor::_theme_close_button_cbk() {
plugin->make_visible(false); // Enables auto hide.
if (theme.is_valid() && InspectorDock::get_inspector_singleton()->get_edited_object() == theme.ptr()) {
EditorNode::get_singleton()->push_item(nullptr);
} else {
theme = Ref<Theme>();
EditorNode::get_singleton()->hide_unused_editors(plugin);
}
}

void ThemeEditor::_add_preview_button_cbk() {
preview_scene_dialog->popup_file_dialog();
}
Expand Down Expand Up @@ -3645,6 +3656,12 @@ ThemeEditor::ThemeEditor() {
theme_save_as_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_save_button_cbk).bind(true));
top_menu->add_child(theme_save_as_button);

Button *theme_close_button = memnew(Button);
theme_close_button->set_text(TTR("Close"));
theme_close_button->set_flat(true);
theme_close_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_close_button_cbk));
top_menu->add_child(theme_close_button);

top_menu->add_child(memnew(VSeparator));

Button *theme_edit_button = memnew(Button);
Expand Down Expand Up @@ -3711,20 +3728,12 @@ ThemeEditor::ThemeEditor() {

///////////////////////

void ThemeEditorPlugin::edit(Object *p_node) {
if (Object::cast_to<Theme>(p_node)) {
theme_editor->edit(Object::cast_to<Theme>(p_node));
} else {
// We intentionally keep a reference to the last used theme to work around
// the the editor being hidden while base resources are edited. Uncomment
// the following line again and remove this comment once that bug has been
// fixed (scheduled for Godot 4.1 in PR 73098):
// theme_editor->edit(Ref<Theme>());
}
void ThemeEditorPlugin::edit(Object *p_object) {
theme_editor->edit(Ref<Theme>(p_object));
}

bool ThemeEditorPlugin::handles(Object *p_node) const {
return Object::cast_to<Theme>(p_node) != nullptr;
bool ThemeEditorPlugin::handles(Object *p_object) const {
return Object::cast_to<Theme>(p_object) != nullptr;
}

void ThemeEditorPlugin::make_visible(bool p_visible) {
Expand All @@ -3740,8 +3749,77 @@ void ThemeEditorPlugin::make_visible(bool p_visible) {
}
}

bool ThemeEditorPlugin::can_auto_hide() const {
Ref<Theme> edited_theme = theme_editor->theme;
if (edited_theme.is_null()) {
return true;
}

Ref<Resource> edited_resource = Ref<Resource>(InspectorDock::get_inspector_singleton()->get_next_edited_object());
if (edited_resource.is_null()) {
return true;
}

// Don't hide if edited resource used by this theme.
Ref<StyleBox> sbox = edited_resource;
if (sbox.is_valid()) {
List<StringName> type_list;
edited_theme->get_stylebox_type_list(&type_list);

for (const StringName &E : type_list) {
List<StringName> list;
edited_theme->get_stylebox_list(E, &list);

for (const StringName &F : list) {
if (edited_theme->get_stylebox(F, E) == sbox) {
return false;
}
}
}
return true;
}

Ref<Texture2D> tex = edited_resource;
if (tex.is_valid()) {
List<StringName> type_list;
edited_theme->get_icon_type_list(&type_list);

for (const StringName &E : type_list) {
List<StringName> list;
edited_theme->get_icon_list(E, &list);

for (const StringName &F : list) {
if (edited_theme->get_icon(F, E) == tex) {
return false;
}
}
}
return true;
}

Ref<Font> fnt = edited_resource;
if (fnt.is_valid()) {
List<StringName> type_list;
edited_theme->get_font_type_list(&type_list);

for (const StringName &E : type_list) {
List<StringName> list;
edited_theme->get_font_list(E, &list);

for (const StringName &F : list) {
if (edited_theme->get_font(F, E) == fnt) {
return false;
}
}
}
return true;
}
return true;
}

ThemeEditorPlugin::ThemeEditorPlugin() {
theme_editor = memnew(ThemeEditor);
theme_editor->plugin = this;
theme_editor->set_custom_minimum_size(Size2(0, 200) * EDSCALE);

button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Theme"), theme_editor);
Expand Down
10 changes: 8 additions & 2 deletions editor/plugins/theme_editor_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class OptionButton;
class PanelContainer;
class TabBar;
class TabContainer;
class ThemeEditorPlugin;
class TextureRect;

class ThemeItemImportTree : public VBoxContainer {
Expand Down Expand Up @@ -419,6 +420,9 @@ class ThemeTypeEditor : public MarginContainer {
class ThemeEditor : public VBoxContainer {
GDCLASS(ThemeEditor, VBoxContainer);

friend class ThemeEditorPlugin;
KoBeWi marked this conversation as resolved.
Show resolved Hide resolved
ThemeEditorPlugin *plugin = nullptr;

Ref<Theme> theme;

TabBar *preview_tabs = nullptr;
Expand All @@ -433,6 +437,7 @@ class ThemeEditor : public VBoxContainer {

void _theme_save_button_cbk(bool p_save_as);
void _theme_edit_button_cbk();
void _theme_close_button_cbk();

void _add_preview_button_cbk();
void _preview_scene_dialog_cbk(const String &p_path);
Expand Down Expand Up @@ -462,9 +467,10 @@ class ThemeEditorPlugin : public EditorPlugin {
public:
virtual String get_name() const override { return "Theme"; }
bool has_main_screen() const override { return false; }
virtual void edit(Object *p_node) override;
virtual bool handles(Object *p_node) const override;
virtual void edit(Object *p_object) override;
virtual bool handles(Object *p_object) const override;
virtual void make_visible(bool p_visible) override;
virtual bool can_auto_hide() const override;

ThemeEditorPlugin();
};
Expand Down
Loading