initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
6
editor/scene/gui/SCsub
Normal file
6
editor/scene/gui/SCsub
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
env.add_source_files(env.editor_sources, "*.cpp")
|
1163
editor/scene/gui/control_editor_plugin.cpp
Normal file
1163
editor/scene/gui/control_editor_plugin.cpp
Normal file
File diff suppressed because it is too large
Load Diff
257
editor/scene/gui/control_editor_plugin.h
Normal file
257
editor/scene/gui/control_editor_plugin.h
Normal file
@@ -0,0 +1,257 @@
|
||||
/**************************************************************************/
|
||||
/* control_editor_plugin.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 "editor/inspector/editor_inspector.h"
|
||||
#include "editor/plugins/editor_plugin.h"
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/margin_container.h"
|
||||
|
||||
class CheckBox;
|
||||
class CheckButton;
|
||||
class EditorSelection;
|
||||
class GridContainer;
|
||||
class Label;
|
||||
class OptionButton;
|
||||
class PanelContainer;
|
||||
class PopupPanel;
|
||||
class Separator;
|
||||
class TextureRect;
|
||||
|
||||
// Inspector controls.
|
||||
class ControlPositioningWarning : public MarginContainer {
|
||||
GDCLASS(ControlPositioningWarning, MarginContainer);
|
||||
|
||||
Control *control_node = nullptr;
|
||||
|
||||
PanelContainer *bg_panel = nullptr;
|
||||
GridContainer *grid = nullptr;
|
||||
TextureRect *title_icon = nullptr;
|
||||
TextureRect *hint_icon = nullptr;
|
||||
Label *title_label = nullptr;
|
||||
Label *hint_label = nullptr;
|
||||
Control *hint_filler_left = nullptr;
|
||||
Control *hint_filler_right = nullptr;
|
||||
|
||||
void _update_warning();
|
||||
void _update_toggler();
|
||||
virtual void gui_input(const Ref<InputEvent> &p_event) override;
|
||||
|
||||
protected:
|
||||
void _notification(int p_notification);
|
||||
|
||||
public:
|
||||
void set_control(Control *p_node);
|
||||
|
||||
ControlPositioningWarning();
|
||||
};
|
||||
|
||||
class EditorPropertyAnchorsPreset : public EditorProperty {
|
||||
GDCLASS(EditorPropertyAnchorsPreset, EditorProperty);
|
||||
OptionButton *options = nullptr;
|
||||
|
||||
void _option_selected(int p_which);
|
||||
|
||||
protected:
|
||||
virtual void _set_read_only(bool p_read_only) override;
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
void setup(const Vector<String> &p_options);
|
||||
virtual void update_property() override;
|
||||
EditorPropertyAnchorsPreset();
|
||||
};
|
||||
|
||||
class EditorPropertySizeFlags : public EditorProperty {
|
||||
GDCLASS(EditorPropertySizeFlags, EditorProperty);
|
||||
|
||||
enum FlagPreset {
|
||||
SIZE_FLAGS_PRESET_FILL,
|
||||
SIZE_FLAGS_PRESET_SHRINK_BEGIN,
|
||||
SIZE_FLAGS_PRESET_SHRINK_CENTER,
|
||||
SIZE_FLAGS_PRESET_SHRINK_END,
|
||||
SIZE_FLAGS_PRESET_CUSTOM,
|
||||
};
|
||||
|
||||
OptionButton *flag_presets = nullptr;
|
||||
CheckBox *flag_expand = nullptr;
|
||||
VBoxContainer *flag_options = nullptr;
|
||||
Vector<CheckBox *> flag_checks;
|
||||
|
||||
bool vertical = false;
|
||||
|
||||
bool keep_selected_preset = false;
|
||||
|
||||
void _preset_selected(int p_which);
|
||||
void _expand_toggled();
|
||||
void _flag_toggled();
|
||||
|
||||
protected:
|
||||
virtual void _set_read_only(bool p_read_only) override;
|
||||
|
||||
public:
|
||||
void setup(const Vector<String> &p_options, bool p_vertical);
|
||||
virtual void update_property() override;
|
||||
EditorPropertySizeFlags();
|
||||
};
|
||||
|
||||
class EditorInspectorPluginControl : public EditorInspectorPlugin {
|
||||
GDCLASS(EditorInspectorPluginControl, EditorInspectorPlugin);
|
||||
|
||||
bool inside_control_category = false;
|
||||
|
||||
public:
|
||||
virtual bool can_handle(Object *p_object) override;
|
||||
virtual void parse_category(Object *p_object, const String &p_category) override;
|
||||
virtual void parse_group(Object *p_object, const String &p_group) override;
|
||||
virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override;
|
||||
};
|
||||
|
||||
// Toolbar controls.
|
||||
class ControlEditorPopupButton : public Button {
|
||||
GDCLASS(ControlEditorPopupButton, Button);
|
||||
|
||||
Ref<Texture2D> arrow_icon;
|
||||
|
||||
PopupPanel *popup_panel = nullptr;
|
||||
VBoxContainer *popup_vbox = nullptr;
|
||||
|
||||
void _popup_visibility_changed(bool p_visible);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual void toggled(bool p_pressed) override;
|
||||
|
||||
VBoxContainer *get_popup_hbox() const { return popup_vbox; }
|
||||
|
||||
ControlEditorPopupButton();
|
||||
};
|
||||
|
||||
class ControlEditorPresetPicker : public MarginContainer {
|
||||
GDCLASS(ControlEditorPresetPicker, MarginContainer);
|
||||
|
||||
virtual void _preset_button_pressed(const int p_preset) {}
|
||||
|
||||
protected:
|
||||
static constexpr int grid_separation = 0;
|
||||
HashMap<int, Button *> preset_buttons;
|
||||
|
||||
void _add_row_button(HBoxContainer *p_row, const int p_preset, const String &p_name);
|
||||
void _add_separator(BoxContainer *p_box, Separator *p_separator);
|
||||
};
|
||||
|
||||
class AnchorPresetPicker : public ControlEditorPresetPicker {
|
||||
GDCLASS(AnchorPresetPicker, ControlEditorPresetPicker);
|
||||
|
||||
virtual void _preset_button_pressed(const int p_preset) override;
|
||||
|
||||
protected:
|
||||
void _notification(int p_notification);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
AnchorPresetPicker();
|
||||
};
|
||||
|
||||
class SizeFlagPresetPicker : public ControlEditorPresetPicker {
|
||||
GDCLASS(SizeFlagPresetPicker, ControlEditorPresetPicker);
|
||||
|
||||
CheckButton *expand_button = nullptr;
|
||||
|
||||
bool vertical = false;
|
||||
|
||||
virtual void _preset_button_pressed(const int p_preset) override;
|
||||
void _expand_button_pressed();
|
||||
|
||||
protected:
|
||||
void _notification(int p_notification);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_allowed_flags(Vector<SizeFlags> &p_flags);
|
||||
void set_expand_flag(bool p_expand);
|
||||
|
||||
SizeFlagPresetPicker(bool p_vertical);
|
||||
};
|
||||
|
||||
class ControlEditorToolbar : public HBoxContainer {
|
||||
GDCLASS(ControlEditorToolbar, HBoxContainer);
|
||||
|
||||
EditorSelection *editor_selection = nullptr;
|
||||
|
||||
ControlEditorPopupButton *anchors_button = nullptr;
|
||||
ControlEditorPopupButton *containers_button = nullptr;
|
||||
Button *anchor_mode_button = nullptr;
|
||||
|
||||
SizeFlagPresetPicker *container_h_picker = nullptr;
|
||||
SizeFlagPresetPicker *container_v_picker = nullptr;
|
||||
|
||||
bool anchors_mode = false;
|
||||
|
||||
void _anchors_preset_selected(int p_preset);
|
||||
void _anchors_to_current_ratio();
|
||||
void _anchor_mode_toggled(bool p_status);
|
||||
void _container_flags_selected(int p_flags, bool p_vertical);
|
||||
void _expand_flag_toggled(bool p_expand, bool p_vertical);
|
||||
|
||||
Vector2 _position_to_anchor(const Control *p_control, Vector2 position);
|
||||
bool _is_node_locked(const Node *p_node);
|
||||
List<Control *> _get_edited_controls();
|
||||
void _selection_changed();
|
||||
|
||||
protected:
|
||||
void _notification(int p_notification);
|
||||
|
||||
static ControlEditorToolbar *singleton;
|
||||
|
||||
public:
|
||||
bool is_anchors_mode_enabled() { return anchors_mode; }
|
||||
|
||||
static ControlEditorToolbar *get_singleton() { return singleton; }
|
||||
|
||||
ControlEditorToolbar();
|
||||
};
|
||||
|
||||
// Editor plugin.
|
||||
class ControlEditorPlugin : public EditorPlugin {
|
||||
GDCLASS(ControlEditorPlugin, EditorPlugin);
|
||||
|
||||
ControlEditorToolbar *toolbar = nullptr;
|
||||
|
||||
public:
|
||||
virtual String get_plugin_name() const override { return "Control"; }
|
||||
|
||||
ControlEditorPlugin();
|
||||
};
|
1062
editor/scene/gui/font_config_plugin.cpp
Normal file
1062
editor/scene/gui/font_config_plugin.cpp
Normal file
File diff suppressed because it is too large
Load Diff
268
editor/scene/gui/font_config_plugin.h
Normal file
268
editor/scene/gui/font_config_plugin.h
Normal file
@@ -0,0 +1,268 @@
|
||||
/**************************************************************************/
|
||||
/* font_config_plugin.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 "editor/inspector/editor_properties.h"
|
||||
#include "editor/inspector/editor_properties_array_dict.h"
|
||||
#include "editor/plugins/editor_plugin.h"
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class EditorPropertyFontMetaObject : public RefCounted {
|
||||
GDCLASS(EditorPropertyFontMetaObject, RefCounted);
|
||||
|
||||
Dictionary dict;
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
|
||||
public:
|
||||
void set_dict(const Dictionary &p_dict);
|
||||
Dictionary get_dict();
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class EditorPropertyFontOTObject : public RefCounted {
|
||||
GDCLASS(EditorPropertyFontOTObject, RefCounted);
|
||||
|
||||
Dictionary dict;
|
||||
Dictionary defaults_dict;
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
bool _property_can_revert(const StringName &p_name) const;
|
||||
bool _property_get_revert(const StringName &p_name, Variant &r_property) const;
|
||||
|
||||
public:
|
||||
void set_dict(const Dictionary &p_dict);
|
||||
Dictionary get_dict();
|
||||
|
||||
void set_defaults(const Dictionary &p_dict);
|
||||
Dictionary get_defaults();
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class EditorPropertyFontMetaOverride : public EditorProperty {
|
||||
GDCLASS(EditorPropertyFontMetaOverride, EditorProperty);
|
||||
|
||||
Ref<EditorPropertyFontMetaObject> object;
|
||||
|
||||
MarginContainer *container = nullptr;
|
||||
VBoxContainer *property_vbox = nullptr;
|
||||
|
||||
Button *edit = nullptr;
|
||||
PopupMenu *menu = nullptr;
|
||||
EditorLocaleDialog *locale_select = nullptr;
|
||||
|
||||
Vector<String> script_codes;
|
||||
|
||||
bool script_editor = false;
|
||||
bool updating = false;
|
||||
int page_length = 20;
|
||||
int page_index = 0;
|
||||
EditorPaginator *paginator = nullptr;
|
||||
|
||||
protected:
|
||||
void _edit_pressed();
|
||||
void _page_changed(int p_page);
|
||||
void _property_changed(const String &p_property, const Variant &p_value, const String &p_name = "", bool p_changing = false);
|
||||
void _remove(Object *p_button, const String &p_key);
|
||||
void _add_menu();
|
||||
void _add_script(int p_option);
|
||||
void _add_lang(const String &p_locale);
|
||||
void _object_id_selected(const StringName &p_property, ObjectID p_id);
|
||||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
|
||||
EditorPropertyFontMetaOverride(bool p_script);
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class EditorPropertyOTVariation : public EditorProperty {
|
||||
GDCLASS(EditorPropertyOTVariation, EditorProperty);
|
||||
|
||||
Ref<EditorPropertyFontOTObject> object;
|
||||
|
||||
MarginContainer *container = nullptr;
|
||||
VBoxContainer *property_vbox = nullptr;
|
||||
|
||||
Button *edit = nullptr;
|
||||
|
||||
bool updating = false;
|
||||
int page_length = 20;
|
||||
int page_index = 0;
|
||||
EditorPaginator *paginator = nullptr;
|
||||
|
||||
protected:
|
||||
static void _bind_methods() {}
|
||||
|
||||
void _edit_pressed();
|
||||
void _page_changed(int p_page);
|
||||
void _property_changed(const String &p_property, const Variant &p_value, const String &p_name = "", bool p_changing = false);
|
||||
void _object_id_selected(const StringName &p_property, ObjectID p_id);
|
||||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
|
||||
EditorPropertyOTVariation();
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class EditorPropertyOTFeatures : public EditorProperty {
|
||||
GDCLASS(EditorPropertyOTFeatures, EditorProperty);
|
||||
|
||||
enum FeatureGroups {
|
||||
FGRP_STYLISTIC_SET,
|
||||
FGRP_CHARACTER_VARIANT,
|
||||
FGRP_CAPITLS,
|
||||
FGRP_LIGATURES,
|
||||
FGRP_ALTERNATES,
|
||||
FGRP_EAL,
|
||||
FGRP_EAW,
|
||||
FGRP_NUMAL,
|
||||
FGRP_CUSTOM,
|
||||
FGRP_MAX,
|
||||
};
|
||||
|
||||
Ref<EditorPropertyFontOTObject> object;
|
||||
|
||||
MarginContainer *container = nullptr;
|
||||
VBoxContainer *property_vbox = nullptr;
|
||||
|
||||
Button *edit = nullptr;
|
||||
PopupMenu *menu = nullptr;
|
||||
PopupMenu *menu_sub[FGRP_MAX];
|
||||
String group_names[FGRP_MAX];
|
||||
|
||||
bool updating = false;
|
||||
int page_length = 20;
|
||||
int page_index = 0;
|
||||
EditorPaginator *paginator = nullptr;
|
||||
|
||||
protected:
|
||||
void _edit_pressed();
|
||||
void _page_changed(int p_page);
|
||||
void _property_changed(const String &p_property, const Variant &p_value, const String &p_name = "", bool p_changing = false);
|
||||
void _remove(Object *p_button, int p_key);
|
||||
void _add_menu();
|
||||
void _add_feature(int p_option);
|
||||
void _object_id_selected(const StringName &p_property, ObjectID p_id);
|
||||
|
||||
public:
|
||||
virtual void update_property() override;
|
||||
|
||||
EditorPropertyOTFeatures();
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class EditorInspectorPluginFontVariation : public EditorInspectorPlugin {
|
||||
GDCLASS(EditorInspectorPluginFontVariation, EditorInspectorPlugin);
|
||||
|
||||
public:
|
||||
virtual bool can_handle(Object *p_object) override;
|
||||
virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class FontPreview : public Control {
|
||||
GDCLASS(FontPreview, Control);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
Ref<Font> prev_font;
|
||||
|
||||
void _preview_changed();
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
|
||||
void set_data(const Ref<Font> &p_f);
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class EditorInspectorPluginFontPreview : public EditorInspectorPlugin {
|
||||
GDCLASS(EditorInspectorPluginFontPreview, EditorInspectorPlugin);
|
||||
|
||||
public:
|
||||
virtual bool can_handle(Object *p_object) override;
|
||||
virtual void parse_begin(Object *p_object) override;
|
||||
virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class EditorPropertyFontNamesArray : public EditorPropertyArray {
|
||||
GDCLASS(EditorPropertyFontNamesArray, EditorPropertyArray);
|
||||
|
||||
PopupMenu *menu = nullptr;
|
||||
|
||||
protected:
|
||||
virtual void _add_element() override;
|
||||
|
||||
void _add_font(int p_option);
|
||||
static void _bind_methods() {}
|
||||
|
||||
public:
|
||||
EditorPropertyFontNamesArray();
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class EditorInspectorPluginSystemFont : public EditorInspectorPlugin {
|
||||
GDCLASS(EditorInspectorPluginSystemFont, EditorInspectorPlugin);
|
||||
|
||||
public:
|
||||
virtual bool can_handle(Object *p_object) override;
|
||||
virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide = false) override;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
class FontEditorPlugin : public EditorPlugin {
|
||||
GDCLASS(FontEditorPlugin, EditorPlugin);
|
||||
|
||||
public:
|
||||
FontEditorPlugin();
|
||||
|
||||
virtual String get_plugin_name() const override { return "Font"; }
|
||||
};
|
138
editor/scene/gui/style_box_editor_plugin.cpp
Normal file
138
editor/scene/gui/style_box_editor_plugin.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/**************************************************************************/
|
||||
/* style_box_editor_plugin.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 "style_box_editor_plugin.h"
|
||||
|
||||
#include "editor/themes/editor_scale.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/resources/style_box_texture.h"
|
||||
|
||||
bool StyleBoxPreview::grid_preview_enabled = true;
|
||||
|
||||
void StyleBoxPreview::_grid_preview_toggled(bool p_active) {
|
||||
grid_preview_enabled = p_active;
|
||||
queue_redraw();
|
||||
}
|
||||
|
||||
void StyleBoxPreview::edit(const Ref<StyleBox> &p_stylebox) {
|
||||
if (stylebox.is_valid()) {
|
||||
stylebox->disconnect_changed(callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw));
|
||||
}
|
||||
stylebox = p_stylebox;
|
||||
if (stylebox.is_valid()) {
|
||||
stylebox->connect_changed(callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw));
|
||||
}
|
||||
Ref<StyleBoxTexture> sbt = stylebox;
|
||||
grid_preview->set_visible(sbt.is_valid());
|
||||
queue_redraw();
|
||||
}
|
||||
|
||||
void StyleBoxPreview::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
set_texture(get_editor_theme_icon(SNAME("Checkerboard")));
|
||||
grid_preview->set_button_icon(get_editor_theme_icon(SNAME("StyleBoxGrid")));
|
||||
} break;
|
||||
case NOTIFICATION_DRAW: {
|
||||
_redraw();
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void StyleBoxPreview::_redraw() {
|
||||
if (stylebox.is_valid()) {
|
||||
float grid_button_width = get_editor_theme_icon(SNAME("StyleBoxGrid"))->get_size().x;
|
||||
Rect2 preview_rect = get_rect();
|
||||
preview_rect = preview_rect.grow(-grid_button_width);
|
||||
|
||||
// Re-adjust preview panel to fit all drawn content.
|
||||
Rect2 drawing_rect = stylebox->get_draw_rect(preview_rect);
|
||||
preview_rect.size -= drawing_rect.size - preview_rect.size;
|
||||
preview_rect.position -= drawing_rect.position - preview_rect.position;
|
||||
|
||||
draw_style_box(stylebox, preview_rect);
|
||||
|
||||
Ref<StyleBoxTexture> sbt = stylebox;
|
||||
// Draw the "grid". Use white lines, as well as subtle black lines to ensure contrast.
|
||||
if (sbt.is_valid() && grid_preview->is_pressed()) {
|
||||
const Color dark_color = Color(0, 0, 0, 0.4);
|
||||
const Color bright_color = Color(1, 1, 1, 0.8);
|
||||
int x_left = drawing_rect.position.x + sbt->get_margin(SIDE_LEFT);
|
||||
int x_right = drawing_rect.position.x + drawing_rect.size.width - sbt->get_margin(SIDE_RIGHT);
|
||||
int y_top = drawing_rect.position.y + sbt->get_margin(SIDE_TOP);
|
||||
int y_bottom = drawing_rect.position.y + drawing_rect.size.height - sbt->get_margin(SIDE_BOTTOM);
|
||||
|
||||
draw_line(Point2(x_left + 2, 0), Point2(x_left + 2, get_size().height), dark_color);
|
||||
draw_line(Point2(x_right + 1, 0), Point2(x_right + 1, get_size().height), dark_color);
|
||||
draw_line(Point2(0, y_top + 2), Point2(get_size().width, y_top + 2), dark_color);
|
||||
draw_line(Point2(0, y_bottom + 1), Point2(get_size().width, y_bottom + 1), dark_color);
|
||||
|
||||
draw_line(Point2(x_left + 1, 0), Point2(x_left + 1, get_size().height), bright_color);
|
||||
draw_line(Point2(x_right, 0), Point2(x_right, get_size().height), bright_color);
|
||||
draw_line(Point2(0, y_top + 1), Point2(get_size().width, y_top + 1), bright_color);
|
||||
draw_line(Point2(0, y_bottom), Point2(get_size().width, y_bottom), bright_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StyleBoxPreview::StyleBoxPreview() {
|
||||
set_clip_contents(true);
|
||||
set_custom_minimum_size(Size2(0, 150) * EDSCALE);
|
||||
set_stretch_mode(TextureRect::STRETCH_TILE);
|
||||
set_texture_repeat(CanvasItem::TEXTURE_REPEAT_ENABLED);
|
||||
set_anchors_and_offsets_preset(PRESET_FULL_RECT);
|
||||
|
||||
grid_preview = memnew(Button);
|
||||
// This theme variation works better than the normal theme because there's no focus highlight.
|
||||
grid_preview->set_theme_type_variation("PreviewLightButton");
|
||||
grid_preview->set_tooltip_text(TTRC("Toggle margins preview grid."));
|
||||
grid_preview->set_toggle_mode(true);
|
||||
grid_preview->connect(SceneStringName(toggled), callable_mp(this, &StyleBoxPreview::_grid_preview_toggled));
|
||||
grid_preview->set_pressed(grid_preview_enabled);
|
||||
add_child(grid_preview);
|
||||
}
|
||||
|
||||
bool EditorInspectorPluginStyleBox::can_handle(Object *p_object) {
|
||||
return Object::cast_to<StyleBox>(p_object) != nullptr;
|
||||
}
|
||||
|
||||
void EditorInspectorPluginStyleBox::parse_begin(Object *p_object) {
|
||||
Ref<StyleBox> sb = Ref<StyleBox>(Object::cast_to<StyleBox>(p_object));
|
||||
|
||||
StyleBoxPreview *preview = memnew(StyleBoxPreview);
|
||||
preview->edit(sb);
|
||||
add_custom_control(preview);
|
||||
}
|
||||
|
||||
StyleBoxEditorPlugin::StyleBoxEditorPlugin() {
|
||||
Ref<EditorInspectorPluginStyleBox> inspector_plugin;
|
||||
inspector_plugin.instantiate();
|
||||
add_inspector_plugin(inspector_plugin);
|
||||
}
|
75
editor/scene/gui/style_box_editor_plugin.h
Normal file
75
editor/scene/gui/style_box_editor_plugin.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/**************************************************************************/
|
||||
/* style_box_editor_plugin.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 "editor/inspector/editor_inspector.h"
|
||||
#include "editor/plugins/editor_plugin.h"
|
||||
#include "scene/gui/texture_rect.h"
|
||||
|
||||
class Button;
|
||||
class StyleBox;
|
||||
|
||||
class StyleBoxPreview : public TextureRect {
|
||||
GDCLASS(StyleBoxPreview, TextureRect);
|
||||
|
||||
Button *grid_preview = nullptr;
|
||||
Ref<StyleBox> stylebox;
|
||||
|
||||
void _sb_changed();
|
||||
void _redraw();
|
||||
static bool grid_preview_enabled;
|
||||
void _grid_preview_toggled(bool p_active);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
void edit(const Ref<StyleBox> &p_stylebox);
|
||||
|
||||
StyleBoxPreview();
|
||||
};
|
||||
|
||||
class EditorInspectorPluginStyleBox : public EditorInspectorPlugin {
|
||||
GDCLASS(EditorInspectorPluginStyleBox, EditorInspectorPlugin);
|
||||
|
||||
public:
|
||||
virtual bool can_handle(Object *p_object) override;
|
||||
virtual void parse_begin(Object *p_object) override;
|
||||
};
|
||||
|
||||
class StyleBoxEditorPlugin : public EditorPlugin {
|
||||
GDCLASS(StyleBoxEditorPlugin, EditorPlugin);
|
||||
|
||||
public:
|
||||
virtual String get_plugin_name() const override { return "StyleBox"; }
|
||||
|
||||
StyleBoxEditorPlugin();
|
||||
};
|
4034
editor/scene/gui/theme_editor_plugin.cpp
Normal file
4034
editor/scene/gui/theme_editor_plugin.cpp
Normal file
File diff suppressed because it is too large
Load Diff
498
editor/scene/gui/theme_editor_plugin.h
Normal file
498
editor/scene/gui/theme_editor_plugin.h
Normal file
@@ -0,0 +1,498 @@
|
||||
/**************************************************************************/
|
||||
/* theme_editor_plugin.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 "editor/plugins/editor_plugin.h"
|
||||
#include "editor/scene/gui/theme_editor_preview.h"
|
||||
#include "scene/gui/dialogs.h"
|
||||
#include "scene/gui/margin_container.h"
|
||||
#include "scene/gui/tree.h"
|
||||
#include "scene/resources/theme.h"
|
||||
|
||||
class Button;
|
||||
class CheckButton;
|
||||
class EditorFileDialog;
|
||||
class ItemList;
|
||||
class Label;
|
||||
class LineEdit;
|
||||
class OptionButton;
|
||||
class PanelContainer;
|
||||
class TabBar;
|
||||
class TabContainer;
|
||||
class ThemeEditorPlugin;
|
||||
class TextureRect;
|
||||
|
||||
class ThemeItemImportTree : public VBoxContainer {
|
||||
GDCLASS(ThemeItemImportTree, VBoxContainer);
|
||||
|
||||
Ref<Theme> edited_theme;
|
||||
Ref<Theme> base_theme;
|
||||
|
||||
struct ThemeItem {
|
||||
String type_name;
|
||||
Theme::DataType data_type;
|
||||
String item_name;
|
||||
|
||||
bool operator<(const ThemeItem &p_item) const {
|
||||
if (type_name == p_item.type_name && data_type == p_item.data_type) {
|
||||
return item_name < p_item.item_name;
|
||||
}
|
||||
if (type_name == p_item.type_name) {
|
||||
return data_type < p_item.data_type;
|
||||
}
|
||||
return type_name < p_item.type_name;
|
||||
}
|
||||
};
|
||||
|
||||
enum ItemCheckedState {
|
||||
SELECT_IMPORT_DEFINITION,
|
||||
SELECT_IMPORT_FULL,
|
||||
};
|
||||
|
||||
RBMap<ThemeItem, ItemCheckedState> selected_items;
|
||||
|
||||
LineEdit *import_items_filter = nullptr;
|
||||
|
||||
Tree *import_items_tree = nullptr;
|
||||
List<TreeItem *> tree_color_items;
|
||||
List<TreeItem *> tree_constant_items;
|
||||
List<TreeItem *> tree_font_items;
|
||||
List<TreeItem *> tree_font_size_items;
|
||||
List<TreeItem *> tree_icon_items;
|
||||
List<TreeItem *> tree_stylebox_items;
|
||||
|
||||
bool updating_tree = false;
|
||||
|
||||
enum ItemActionFlag {
|
||||
IMPORT_ITEM = 1,
|
||||
IMPORT_ITEM_DATA = 2,
|
||||
};
|
||||
|
||||
TextureRect *select_colors_icon = nullptr;
|
||||
Label *select_colors_label = nullptr;
|
||||
Button *select_all_colors_button = nullptr;
|
||||
Button *select_full_colors_button = nullptr;
|
||||
Button *deselect_all_colors_button = nullptr;
|
||||
Label *total_selected_colors_label = nullptr;
|
||||
|
||||
TextureRect *select_constants_icon = nullptr;
|
||||
Label *select_constants_label = nullptr;
|
||||
Button *select_all_constants_button = nullptr;
|
||||
Button *select_full_constants_button = nullptr;
|
||||
Button *deselect_all_constants_button = nullptr;
|
||||
Label *total_selected_constants_label = nullptr;
|
||||
|
||||
TextureRect *select_fonts_icon = nullptr;
|
||||
Label *select_fonts_label = nullptr;
|
||||
Button *select_all_fonts_button = nullptr;
|
||||
Button *select_full_fonts_button = nullptr;
|
||||
Button *deselect_all_fonts_button = nullptr;
|
||||
Label *total_selected_fonts_label = nullptr;
|
||||
|
||||
TextureRect *select_font_sizes_icon = nullptr;
|
||||
Label *select_font_sizes_label = nullptr;
|
||||
Button *select_all_font_sizes_button = nullptr;
|
||||
Button *select_full_font_sizes_button = nullptr;
|
||||
Button *deselect_all_font_sizes_button = nullptr;
|
||||
Label *total_selected_font_sizes_label = nullptr;
|
||||
|
||||
TextureRect *select_icons_icon = nullptr;
|
||||
Label *select_icons_label = nullptr;
|
||||
Button *select_all_icons_button = nullptr;
|
||||
Button *select_full_icons_button = nullptr;
|
||||
Button *deselect_all_icons_button = nullptr;
|
||||
Label *total_selected_icons_label = nullptr;
|
||||
|
||||
TextureRect *select_styleboxes_icon = nullptr;
|
||||
Label *select_styleboxes_label = nullptr;
|
||||
Button *select_all_styleboxes_button = nullptr;
|
||||
Button *select_full_styleboxes_button = nullptr;
|
||||
Button *deselect_all_styleboxes_button = nullptr;
|
||||
Label *total_selected_styleboxes_label = nullptr;
|
||||
|
||||
HBoxContainer *select_icons_warning_hb = nullptr;
|
||||
TextureRect *select_icons_warning_icon = nullptr;
|
||||
Label *select_icons_warning = nullptr;
|
||||
|
||||
Button *import_collapse_types_button = nullptr;
|
||||
Button *import_expand_types_button = nullptr;
|
||||
Button *import_select_all_button = nullptr;
|
||||
Button *import_select_full_button = nullptr;
|
||||
Button *import_deselect_all_button = nullptr;
|
||||
|
||||
void _update_items_tree();
|
||||
void _toggle_type_items(bool p_collapse);
|
||||
void _filter_text_changed(const String &p_value);
|
||||
|
||||
void _store_selected_item(TreeItem *p_tree_item);
|
||||
void _restore_selected_item(TreeItem *p_tree_item);
|
||||
void _update_total_selected(Theme::DataType p_data_type);
|
||||
|
||||
void _tree_item_edited();
|
||||
void _check_propagated_to_tree_item(Object *p_obj, int p_column);
|
||||
void _select_all_subitems(TreeItem *p_root_item, bool p_select_with_data);
|
||||
void _deselect_all_subitems(TreeItem *p_root_item, bool p_deselect_completely);
|
||||
|
||||
void _select_all_items_pressed();
|
||||
void _select_full_items_pressed();
|
||||
void _deselect_all_items_pressed();
|
||||
|
||||
void _select_all_data_type_pressed(int p_data_type);
|
||||
void _select_full_data_type_pressed(int p_data_type);
|
||||
void _deselect_all_data_type_pressed(int p_data_type);
|
||||
|
||||
void _import_selected();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_edited_theme(const Ref<Theme> &p_theme);
|
||||
void set_base_theme(const Ref<Theme> &p_theme);
|
||||
void reset_item_tree();
|
||||
|
||||
bool has_selected_items() const;
|
||||
|
||||
ThemeItemImportTree();
|
||||
};
|
||||
|
||||
class ThemeTypeEditor;
|
||||
|
||||
class ThemeItemEditorDialog : public AcceptDialog {
|
||||
GDCLASS(ThemeItemEditorDialog, AcceptDialog);
|
||||
|
||||
ThemeTypeEditor *theme_type_editor = nullptr;
|
||||
|
||||
Ref<Theme> edited_theme;
|
||||
|
||||
TabContainer *tc = nullptr;
|
||||
|
||||
enum TypesTreeAction {
|
||||
TYPES_TREE_REMOVE_ITEM,
|
||||
};
|
||||
|
||||
Tree *edit_type_list = nullptr;
|
||||
LineEdit *edit_add_type_value = nullptr;
|
||||
Button *edit_add_type_button = nullptr;
|
||||
String edited_item_type;
|
||||
|
||||
Button *edit_items_add_color = nullptr;
|
||||
Button *edit_items_add_constant = nullptr;
|
||||
Button *edit_items_add_font = nullptr;
|
||||
Button *edit_items_add_font_size = nullptr;
|
||||
Button *edit_items_add_icon = nullptr;
|
||||
Button *edit_items_add_stylebox = nullptr;
|
||||
Button *edit_items_remove_class = nullptr;
|
||||
Button *edit_items_remove_custom = nullptr;
|
||||
Button *edit_items_remove_all = nullptr;
|
||||
Tree *edit_items_tree = nullptr;
|
||||
Label *edit_items_message = nullptr;
|
||||
|
||||
enum ItemsTreeAction {
|
||||
ITEMS_TREE_RENAME_ITEM,
|
||||
ITEMS_TREE_REMOVE_ITEM,
|
||||
ITEMS_TREE_REMOVE_DATA_TYPE,
|
||||
};
|
||||
|
||||
ConfirmationDialog *edit_theme_item_dialog = nullptr;
|
||||
VBoxContainer *edit_theme_item_old_vb = nullptr;
|
||||
Label *theme_item_old_name = nullptr;
|
||||
LineEdit *theme_item_name = nullptr;
|
||||
|
||||
enum ItemPopupMode {
|
||||
CREATE_THEME_ITEM,
|
||||
RENAME_THEME_ITEM,
|
||||
ITEM_POPUP_MODE_MAX
|
||||
};
|
||||
|
||||
ItemPopupMode item_popup_mode = ITEM_POPUP_MODE_MAX;
|
||||
String edit_item_old_name;
|
||||
Theme::DataType edit_item_data_type = Theme::DATA_TYPE_MAX;
|
||||
|
||||
ThemeItemImportTree *import_default_theme_items = nullptr;
|
||||
ThemeItemImportTree *import_editor_theme_items = nullptr;
|
||||
ThemeItemImportTree *import_other_theme_items = nullptr;
|
||||
|
||||
LineEdit *import_another_theme_value = nullptr;
|
||||
Button *import_another_theme_button = nullptr;
|
||||
EditorFileDialog *import_another_theme_dialog = nullptr;
|
||||
|
||||
ConfirmationDialog *confirm_closing_dialog = nullptr;
|
||||
|
||||
void ok_pressed() override;
|
||||
void _close_dialog();
|
||||
|
||||
void _dialog_about_to_show();
|
||||
void _update_edit_types();
|
||||
void _edited_type_selected();
|
||||
void _edited_type_edited();
|
||||
void _edited_type_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button);
|
||||
|
||||
void _update_edit_item_tree(String p_item_type);
|
||||
void _item_tree_button_pressed(Object *p_item, int p_column, int p_id, MouseButton p_button);
|
||||
|
||||
void _add_theme_type();
|
||||
void _add_theme_item(Theme::DataType p_data_type, const String &p_item_name, const String &p_item_type);
|
||||
void _remove_theme_type(const String &p_theme_type);
|
||||
void _remove_data_type_items(Theme::DataType p_data_type, String p_item_type);
|
||||
void _remove_class_items();
|
||||
void _remove_custom_items();
|
||||
void _remove_all_items();
|
||||
|
||||
void _open_add_theme_item_dialog(int p_data_type);
|
||||
void _open_rename_theme_item_dialog(Theme::DataType p_data_type, String p_item_name);
|
||||
void _confirm_edit_theme_item();
|
||||
void _edit_theme_item_gui_input(const Ref<InputEvent> &p_event);
|
||||
|
||||
void _open_select_another_theme();
|
||||
void _select_another_theme_cbk(const String &p_path);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_edited_theme(const Ref<Theme> &p_theme);
|
||||
|
||||
ThemeItemEditorDialog(ThemeTypeEditor *p_theme_editor);
|
||||
};
|
||||
|
||||
class ThemeTypeDialog : public ConfirmationDialog {
|
||||
GDCLASS(ThemeTypeDialog, ConfirmationDialog);
|
||||
|
||||
Ref<Theme> edited_theme;
|
||||
bool include_own_types = false;
|
||||
|
||||
String pre_submitted_value;
|
||||
|
||||
LineEdit *add_type_filter = nullptr;
|
||||
ItemList *add_type_options = nullptr;
|
||||
ConfirmationDialog *add_type_confirmation = nullptr;
|
||||
|
||||
void _dialog_about_to_show();
|
||||
void ok_pressed() override;
|
||||
|
||||
void _update_add_type_options(const String &p_filter = "");
|
||||
|
||||
void _add_type_filter_cbk(const String &p_value);
|
||||
void _type_filter_input(const Ref<InputEvent> &p_event);
|
||||
void _add_type_options_cbk(int p_index);
|
||||
void _add_type_dialog_entered(const String &p_value);
|
||||
void _add_type_dialog_activated(int p_index);
|
||||
|
||||
void _add_type_selected(const String &p_type_name);
|
||||
void _add_type_confirmed();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_edited_theme(const Ref<Theme> &p_theme);
|
||||
void set_include_own_types(bool p_enable);
|
||||
|
||||
ThemeTypeDialog();
|
||||
};
|
||||
|
||||
// Custom `Label` needed to use `EditorHelpBit` to display theme item documentation.
|
||||
class ThemeItemLabel : public Label {
|
||||
virtual Control *make_custom_tooltip(const String &p_text) const;
|
||||
};
|
||||
|
||||
class ThemeTypeEditor : public MarginContainer {
|
||||
GDCLASS(ThemeTypeEditor, MarginContainer);
|
||||
|
||||
Ref<Theme> edited_theme;
|
||||
String edited_type;
|
||||
bool updating = false;
|
||||
|
||||
struct LeadingStylebox {
|
||||
bool pinned = false;
|
||||
StringName item_name;
|
||||
Ref<StyleBox> stylebox;
|
||||
Ref<StyleBox> ref_stylebox;
|
||||
};
|
||||
|
||||
LeadingStylebox leading_stylebox;
|
||||
|
||||
OptionButton *theme_type_list = nullptr;
|
||||
Button *add_type_button = nullptr;
|
||||
Button *rename_type_button = nullptr;
|
||||
ConfirmationDialog *theme_type_rename_dialog = nullptr;
|
||||
LineEdit *theme_type_rename_line_edit = nullptr;
|
||||
Button *remove_type_button = nullptr;
|
||||
|
||||
CheckButton *show_default_items_button = nullptr;
|
||||
|
||||
TabContainer *data_type_tabs = nullptr;
|
||||
VBoxContainer *color_items_list = nullptr;
|
||||
VBoxContainer *constant_items_list = nullptr;
|
||||
VBoxContainer *font_items_list = nullptr;
|
||||
VBoxContainer *font_size_items_list = nullptr;
|
||||
VBoxContainer *icon_items_list = nullptr;
|
||||
VBoxContainer *stylebox_items_list = nullptr;
|
||||
|
||||
LineEdit *type_variation_edit = nullptr;
|
||||
Button *type_variation_button = nullptr;
|
||||
Label *type_variation_locked = nullptr;
|
||||
|
||||
enum TypeDialogMode {
|
||||
ADD_THEME_TYPE,
|
||||
ADD_VARIATION_BASE,
|
||||
};
|
||||
|
||||
TypeDialogMode add_type_mode = ADD_THEME_TYPE;
|
||||
ThemeTypeDialog *add_type_dialog = nullptr;
|
||||
|
||||
Vector<Control *> focusables;
|
||||
Timer *update_debounce_timer = nullptr;
|
||||
|
||||
VBoxContainer *_create_item_list(Theme::DataType p_data_type);
|
||||
void _update_type_list();
|
||||
void _update_type_list_debounced();
|
||||
HashMap<StringName, bool> _get_type_items(String p_type_name, Theme::DataType p_type, bool p_include_default);
|
||||
HBoxContainer *_create_property_control(Theme::DataType p_data_type, String p_item_name, bool p_editable);
|
||||
void _add_focusable(Control *p_control);
|
||||
void _update_type_items();
|
||||
|
||||
void _list_type_selected(int p_index);
|
||||
void _add_type_button_cbk();
|
||||
void _rename_type_button_cbk();
|
||||
void _theme_type_rename_dialog_confirmed();
|
||||
void _remove_type_button_cbk();
|
||||
void _add_default_type_items();
|
||||
|
||||
void _update_add_button(const String &p_text, LineEdit *p_for_edit);
|
||||
void _item_add_cbk(int p_data_type, Control *p_control);
|
||||
void _item_add_lineedit_cbk(String p_value, int p_data_type, Control *p_control);
|
||||
void _item_override_cbk(int p_data_type, String p_item_name);
|
||||
void _item_remove_cbk(int p_data_type, String p_item_name);
|
||||
void _item_rename_cbk(int p_data_type, String p_item_name, Control *p_control);
|
||||
void _item_rename_confirmed(int p_data_type, String p_item_name, Control *p_control);
|
||||
void _item_rename_entered(String p_value, int p_data_type, String p_item_name, Control *p_control);
|
||||
void _item_rename_canceled(int p_data_type, String p_item_name, Control *p_control);
|
||||
|
||||
void _color_item_changed(Color p_value, String p_item_name);
|
||||
void _constant_item_changed(float p_value, String p_item_name);
|
||||
void _font_size_item_changed(float p_value, String p_item_name);
|
||||
void _edit_resource_item(Ref<Resource> p_resource, bool p_edit);
|
||||
void _font_item_changed(Ref<Font> p_value, String p_item_name);
|
||||
void _icon_item_changed(Ref<Texture2D> p_value, String p_item_name);
|
||||
void _stylebox_item_changed(Ref<StyleBox> p_value, String p_item_name);
|
||||
void _change_pinned_stylebox();
|
||||
void _on_pin_leader_button_pressed(Control *p_editor, String p_item_name);
|
||||
void _pin_leading_stylebox(String p_item_name, Ref<StyleBox> p_stylebox);
|
||||
void _on_unpin_leader_button_pressed();
|
||||
void _unpin_leading_stylebox();
|
||||
void _update_stylebox_from_leading();
|
||||
|
||||
void _type_variation_changed(const String p_value);
|
||||
void _add_type_variation_cbk();
|
||||
|
||||
void _add_type_dialog_selected(const String p_type_name);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_edited_theme(const Ref<Theme> &p_theme);
|
||||
void select_type(String p_type_name);
|
||||
bool is_stylebox_pinned(Ref<StyleBox> p_stylebox);
|
||||
|
||||
ThemeTypeEditor();
|
||||
};
|
||||
|
||||
class ThemeEditor : public VBoxContainer {
|
||||
GDCLASS(ThemeEditor, VBoxContainer);
|
||||
|
||||
friend class ThemeEditorPlugin;
|
||||
ThemeEditorPlugin *plugin = nullptr;
|
||||
|
||||
Ref<Theme> theme;
|
||||
|
||||
TabBar *preview_tabs = nullptr;
|
||||
PanelContainer *preview_tabs_content = nullptr;
|
||||
Button *add_preview_button = nullptr;
|
||||
EditorFileDialog *preview_scene_dialog = nullptr;
|
||||
|
||||
ThemeTypeEditor *theme_type_editor = nullptr;
|
||||
|
||||
Label *theme_name = nullptr;
|
||||
ThemeItemEditorDialog *theme_edit_dialog = nullptr;
|
||||
|
||||
void _theme_save_button_cbk(bool p_save_as);
|
||||
void _theme_edit_button_cbk();
|
||||
void _theme_close_button_cbk();
|
||||
void _scene_closed(const String &p_path);
|
||||
void _resource_saved(const Ref<Resource> &p_resource);
|
||||
void _files_moved(const String &p_old_path, const String &p_new_path);
|
||||
void _update_theme_name(const String &p_name);
|
||||
|
||||
void _add_preview_button_cbk();
|
||||
void _preview_scene_dialog_cbk(const String &p_path);
|
||||
void _add_preview_tab(ThemeEditorPreview *p_preview_tab, const String &p_preview_name, const Ref<Texture2D> &p_icon);
|
||||
void _change_preview_tab(int p_tab);
|
||||
void _remove_preview_tab(int p_tab);
|
||||
void _remove_preview_tab_invalid(Node *p_tab_control);
|
||||
void _update_preview_tab(Node *p_tab_control);
|
||||
void _preview_control_picked(String p_class_name);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
void edit(const Ref<Theme> &p_theme);
|
||||
Ref<Theme> get_edited_theme();
|
||||
|
||||
bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
|
||||
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
|
||||
|
||||
ThemeEditor();
|
||||
};
|
||||
|
||||
class ThemeEditorPlugin : public EditorPlugin {
|
||||
GDCLASS(ThemeEditorPlugin, EditorPlugin);
|
||||
|
||||
ThemeEditor *theme_editor = nullptr;
|
||||
Button *button = nullptr;
|
||||
|
||||
public:
|
||||
virtual String get_plugin_name() const override { return "Theme"; }
|
||||
bool has_main_screen() const override { return false; }
|
||||
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();
|
||||
};
|
545
editor/scene/gui/theme_editor_preview.cpp
Normal file
545
editor/scene/gui/theme_editor_preview.cpp
Normal file
@@ -0,0 +1,545 @@
|
||||
/**************************************************************************/
|
||||
/* theme_editor_preview.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 "theme_editor_preview.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
#include "editor/themes/editor_scale.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/check_box.h"
|
||||
#include "scene/gui/check_button.h"
|
||||
#include "scene/gui/color_picker.h"
|
||||
#include "scene/gui/color_rect.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/gui/margin_container.h"
|
||||
#include "scene/gui/menu_button.h"
|
||||
#include "scene/gui/option_button.h"
|
||||
#include "scene/gui/panel.h"
|
||||
#include "scene/gui/progress_bar.h"
|
||||
#include "scene/gui/scroll_container.h"
|
||||
#include "scene/gui/separator.h"
|
||||
#include "scene/gui/slider.h"
|
||||
#include "scene/gui/spin_box.h"
|
||||
#include "scene/gui/tab_container.h"
|
||||
#include "scene/gui/text_edit.h"
|
||||
#include "scene/gui/tree.h"
|
||||
#include "scene/resources/packed_scene.h"
|
||||
#include "scene/theme/theme_db.h"
|
||||
|
||||
constexpr double REFRESH_TIMER = 1.5;
|
||||
|
||||
void ThemeEditorPreview::set_preview_theme(const Ref<Theme> &p_theme) {
|
||||
preview_content->set_theme(p_theme);
|
||||
}
|
||||
|
||||
void ThemeEditorPreview::add_preview_overlay(Control *p_overlay) {
|
||||
preview_overlay->add_child(p_overlay);
|
||||
p_overlay->hide();
|
||||
}
|
||||
|
||||
void ThemeEditorPreview::_propagate_redraw(Control *p_at) {
|
||||
p_at->notification(NOTIFICATION_THEME_CHANGED);
|
||||
p_at->update_minimum_size();
|
||||
p_at->queue_redraw();
|
||||
for (int i = 0; i < p_at->get_child_count(); i++) {
|
||||
Control *a = Object::cast_to<Control>(p_at->get_child(i));
|
||||
if (a) {
|
||||
_propagate_redraw(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThemeEditorPreview::_refresh_interval() {
|
||||
// In case the project settings have changed.
|
||||
preview_bg->set_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
|
||||
|
||||
_propagate_redraw(preview_bg);
|
||||
_propagate_redraw(preview_content);
|
||||
}
|
||||
|
||||
void ThemeEditorPreview::_preview_visibility_changed() {
|
||||
set_process(is_visible_in_tree());
|
||||
}
|
||||
|
||||
void ThemeEditorPreview::_picker_button_cbk() {
|
||||
picker_overlay->set_visible(picker_button->is_pressed());
|
||||
if (picker_button->is_pressed()) {
|
||||
_reset_picker_overlay();
|
||||
}
|
||||
}
|
||||
|
||||
Control *ThemeEditorPreview::_find_hovered_control(Control *p_parent, Vector2 p_mouse_position) {
|
||||
Control *found = nullptr;
|
||||
|
||||
for (int i = p_parent->get_child_count() - 1; i >= 0; i--) {
|
||||
Control *cc = Object::cast_to<Control>(p_parent->get_child(i));
|
||||
if (!cc || !cc->is_visible()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Rect2 crect = cc->get_rect();
|
||||
if (crect.has_point(p_mouse_position)) {
|
||||
// Check if there is a child control under mouse.
|
||||
if (cc->get_child_count() > 0) {
|
||||
found = _find_hovered_control(cc, p_mouse_position - cc->get_position());
|
||||
}
|
||||
|
||||
// If there are no applicable children, use the control itself.
|
||||
if (!found) {
|
||||
found = cc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void ThemeEditorPreview::_draw_picker_overlay() {
|
||||
if (!picker_button->is_pressed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
picker_overlay->draw_rect(Rect2(Vector2(0.0, 0.0), picker_overlay->get_size()), theme_cache.preview_picker_overlay_color);
|
||||
if (hovered_control) {
|
||||
Rect2 highlight_rect = hovered_control->get_global_rect();
|
||||
highlight_rect.position = picker_overlay->get_global_transform().affine_inverse().xform(highlight_rect.position);
|
||||
picker_overlay->draw_style_box(theme_cache.preview_picker_overlay, highlight_rect);
|
||||
|
||||
String highlight_name = hovered_control->get_theme_type_variation();
|
||||
if (highlight_name == StringName()) {
|
||||
highlight_name = hovered_control->get_class_name();
|
||||
}
|
||||
|
||||
Rect2 highlight_label_rect = highlight_rect;
|
||||
highlight_label_rect.size = theme_cache.preview_picker_font->get_string_size(highlight_name, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size);
|
||||
|
||||
int margin_top = theme_cache.preview_picker_label->get_margin(SIDE_TOP);
|
||||
int margin_left = theme_cache.preview_picker_label->get_margin(SIDE_LEFT);
|
||||
int margin_bottom = theme_cache.preview_picker_label->get_margin(SIDE_BOTTOM);
|
||||
int margin_right = theme_cache.preview_picker_label->get_margin(SIDE_RIGHT);
|
||||
highlight_label_rect.size.x += margin_left + margin_right;
|
||||
highlight_label_rect.size.y += margin_top + margin_bottom;
|
||||
|
||||
highlight_label_rect.position = highlight_label_rect.position.clamp(Vector2(), picker_overlay->get_size());
|
||||
|
||||
picker_overlay->draw_style_box(theme_cache.preview_picker_label, highlight_label_rect);
|
||||
|
||||
Point2 label_pos = highlight_label_rect.position;
|
||||
label_pos.y += highlight_label_rect.size.y - margin_bottom;
|
||||
label_pos.x += margin_left;
|
||||
picker_overlay->draw_string(theme_cache.preview_picker_font, label_pos, highlight_name, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size);
|
||||
}
|
||||
}
|
||||
|
||||
void ThemeEditorPreview::_gui_input_picker_overlay(const Ref<InputEvent> &p_event) {
|
||||
if (!picker_button->is_pressed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<InputEventMouseButton> mb = p_event;
|
||||
|
||||
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
|
||||
if (hovered_control) {
|
||||
StringName theme_type = hovered_control->get_theme_type_variation();
|
||||
if (theme_type == StringName()) {
|
||||
theme_type = hovered_control->get_class_name();
|
||||
}
|
||||
|
||||
emit_signal(SNAME("control_picked"), theme_type);
|
||||
picker_button->set_pressed(false);
|
||||
picker_overlay->set_visible(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Ref<InputEventMouseMotion> mm = p_event;
|
||||
|
||||
if (mm.is_valid()) {
|
||||
Vector2 mp = preview_content->get_local_mouse_position();
|
||||
hovered_control = _find_hovered_control(preview_content, mp);
|
||||
picker_overlay->queue_redraw();
|
||||
}
|
||||
|
||||
// Forward input to the scroll container underneath to allow scrolling.
|
||||
preview_container->gui_input(p_event);
|
||||
}
|
||||
|
||||
void ThemeEditorPreview::_reset_picker_overlay() {
|
||||
hovered_control = nullptr;
|
||||
picker_overlay->queue_redraw();
|
||||
}
|
||||
|
||||
void ThemeEditorPreview::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
if (is_visible_in_tree()) {
|
||||
set_process(true);
|
||||
}
|
||||
|
||||
connect(SceneStringName(visibility_changed), callable_mp(this, &ThemeEditorPreview::_preview_visibility_changed));
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_READY: {
|
||||
Vector<Ref<Theme>> preview_themes;
|
||||
preview_themes.push_back(ThemeDB::get_singleton()->get_default_theme());
|
||||
ThemeDB::get_singleton()->create_theme_context(preview_root, preview_themes);
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
picker_button->set_button_icon(get_editor_theme_icon(SNAME("ColorPick")));
|
||||
|
||||
theme_cache.preview_picker_overlay = get_theme_stylebox(SNAME("preview_picker_overlay"), SNAME("ThemeEditor"));
|
||||
theme_cache.preview_picker_overlay_color = get_theme_color(SNAME("preview_picker_overlay_color"), SNAME("ThemeEditor"));
|
||||
theme_cache.preview_picker_label = get_theme_stylebox(SNAME("preview_picker_label"), SNAME("ThemeEditor"));
|
||||
theme_cache.preview_picker_font = get_theme_font(SNAME("status_source"), EditorStringName(EditorFonts));
|
||||
theme_cache.font_size = get_theme_default_font_size();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_PROCESS: {
|
||||
time_left -= get_process_delta_time();
|
||||
if (time_left < 0) {
|
||||
time_left = REFRESH_TIMER;
|
||||
_refresh_interval();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void ThemeEditorPreview::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo("control_picked", PropertyInfo(Variant::STRING, "class_name")));
|
||||
}
|
||||
|
||||
ThemeEditorPreview::ThemeEditorPreview() {
|
||||
preview_toolbar = memnew(HBoxContainer);
|
||||
add_child(preview_toolbar);
|
||||
|
||||
picker_button = memnew(Button);
|
||||
preview_toolbar->add_child(picker_button);
|
||||
picker_button->set_theme_type_variation(SceneStringName(FlatButton));
|
||||
picker_button->set_toggle_mode(true);
|
||||
picker_button->set_tooltip_text(TTR("Toggle the control picker, allowing to visually select control types for edit."));
|
||||
picker_button->connect(SceneStringName(pressed), callable_mp(this, &ThemeEditorPreview::_picker_button_cbk));
|
||||
|
||||
MarginContainer *preview_body = memnew(MarginContainer);
|
||||
preview_body->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
|
||||
preview_body->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
add_child(preview_body);
|
||||
|
||||
preview_container = memnew(ScrollContainer);
|
||||
preview_body->add_child(preview_container);
|
||||
|
||||
preview_root = memnew(MarginContainer);
|
||||
preview_container->add_child(preview_root);
|
||||
preview_root->set_clip_contents(true);
|
||||
preview_root->set_custom_minimum_size(Size2(450, 0) * EDSCALE);
|
||||
preview_root->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
preview_root->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
|
||||
preview_bg = memnew(ColorRect);
|
||||
preview_bg->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
|
||||
preview_bg->set_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
|
||||
preview_root->add_child(preview_bg);
|
||||
|
||||
preview_content = memnew(MarginContainer);
|
||||
preview_content->add_theme_constant_override("margin_right", 4 * EDSCALE);
|
||||
preview_content->add_theme_constant_override("margin_top", 4 * EDSCALE);
|
||||
preview_content->add_theme_constant_override("margin_left", 4 * EDSCALE);
|
||||
preview_content->add_theme_constant_override("margin_bottom", 4 * EDSCALE);
|
||||
preview_root->add_child(preview_content);
|
||||
|
||||
preview_overlay = memnew(MarginContainer);
|
||||
preview_overlay->set_mouse_filter(MOUSE_FILTER_IGNORE);
|
||||
preview_overlay->set_clip_contents(true);
|
||||
preview_body->add_child(preview_overlay);
|
||||
|
||||
picker_overlay = memnew(Control);
|
||||
add_preview_overlay(picker_overlay);
|
||||
picker_overlay->connect(SceneStringName(draw), callable_mp(this, &ThemeEditorPreview::_draw_picker_overlay));
|
||||
picker_overlay->connect(SceneStringName(gui_input), callable_mp(this, &ThemeEditorPreview::_gui_input_picker_overlay));
|
||||
picker_overlay->connect(SceneStringName(mouse_exited), callable_mp(this, &ThemeEditorPreview::_reset_picker_overlay));
|
||||
}
|
||||
|
||||
void DefaultThemeEditorPreview::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
test_color_picker_button->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), EditorStringName(Editor))));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
DefaultThemeEditorPreview::DefaultThemeEditorPreview() {
|
||||
Panel *main_panel = memnew(Panel);
|
||||
preview_content->add_child(main_panel);
|
||||
|
||||
MarginContainer *main_mc = memnew(MarginContainer);
|
||||
main_mc->add_theme_constant_override("margin_right", 4 * EDSCALE);
|
||||
main_mc->add_theme_constant_override("margin_top", 4 * EDSCALE);
|
||||
main_mc->add_theme_constant_override("margin_left", 4 * EDSCALE);
|
||||
main_mc->add_theme_constant_override("margin_bottom", 4 * EDSCALE);
|
||||
preview_content->add_child(main_mc);
|
||||
|
||||
HBoxContainer *main_hb = memnew(HBoxContainer);
|
||||
main_mc->add_child(main_hb);
|
||||
main_hb->add_theme_constant_override("separation", 20 * EDSCALE);
|
||||
|
||||
VBoxContainer *first_vb = memnew(VBoxContainer);
|
||||
main_hb->add_child(first_vb);
|
||||
first_vb->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
first_vb->add_theme_constant_override("separation", 10 * EDSCALE);
|
||||
|
||||
first_vb->add_child(memnew(Label("Label")));
|
||||
|
||||
first_vb->add_child(memnew(Button("Button")));
|
||||
Button *bt = memnew(Button);
|
||||
bt->set_text(TTR("Toggle Button"));
|
||||
bt->set_toggle_mode(true);
|
||||
bt->set_pressed(true);
|
||||
first_vb->add_child(bt);
|
||||
bt = memnew(Button);
|
||||
bt->set_text(TTR("Disabled Button"));
|
||||
bt->set_disabled(true);
|
||||
first_vb->add_child(bt);
|
||||
Button *tb = memnew(Button);
|
||||
tb->set_flat(true);
|
||||
tb->set_text("Flat Button");
|
||||
first_vb->add_child(tb);
|
||||
|
||||
CheckButton *cb = memnew(CheckButton);
|
||||
cb->set_text("CheckButton");
|
||||
first_vb->add_child(cb);
|
||||
CheckBox *cbx = memnew(CheckBox);
|
||||
cbx->set_text("CheckBox");
|
||||
first_vb->add_child(cbx);
|
||||
|
||||
MenuButton *test_menu_button = memnew(MenuButton);
|
||||
test_menu_button->set_text("MenuButton");
|
||||
test_menu_button->get_popup()->add_item(TTR("Item"));
|
||||
test_menu_button->get_popup()->add_item(TTR("Disabled Item"));
|
||||
test_menu_button->get_popup()->set_item_disabled(1, true);
|
||||
test_menu_button->get_popup()->add_separator();
|
||||
test_menu_button->get_popup()->add_check_item(TTR("Check Item"));
|
||||
test_menu_button->get_popup()->add_check_item(TTR("Checked Item"));
|
||||
test_menu_button->get_popup()->set_item_checked(4, true);
|
||||
test_menu_button->get_popup()->add_separator();
|
||||
test_menu_button->get_popup()->add_radio_check_item(TTR("Radio Item"));
|
||||
test_menu_button->get_popup()->add_radio_check_item(TTR("Checked Radio Item"));
|
||||
test_menu_button->get_popup()->set_item_checked(7, true);
|
||||
test_menu_button->get_popup()->add_separator(TTR("Named Separator"));
|
||||
|
||||
PopupMenu *test_submenu = memnew(PopupMenu);
|
||||
test_menu_button->get_popup()->add_submenu_node_item(TTR("Submenu"), test_submenu);
|
||||
test_submenu->add_item(TTR("Subitem 1"));
|
||||
test_submenu->add_item(TTR("Subitem 2"));
|
||||
first_vb->add_child(test_menu_button);
|
||||
|
||||
OptionButton *test_option_button = memnew(OptionButton);
|
||||
test_option_button->add_item("OptionButton");
|
||||
test_option_button->add_separator();
|
||||
test_option_button->add_item(TTR("Has"));
|
||||
test_option_button->add_item(TTR("Many"));
|
||||
test_option_button->add_item(TTR("Options"));
|
||||
first_vb->add_child(test_option_button);
|
||||
test_color_picker_button = memnew(ColorPickerButton);
|
||||
first_vb->add_child(test_color_picker_button);
|
||||
|
||||
VBoxContainer *second_vb = memnew(VBoxContainer);
|
||||
second_vb->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
main_hb->add_child(second_vb);
|
||||
second_vb->add_theme_constant_override("separation", 10 * EDSCALE);
|
||||
LineEdit *le = memnew(LineEdit);
|
||||
le->set_text("LineEdit");
|
||||
second_vb->add_child(le);
|
||||
le = memnew(LineEdit);
|
||||
le->set_text(TTR("Disabled LineEdit"));
|
||||
le->set_editable(false);
|
||||
second_vb->add_child(le);
|
||||
TextEdit *te = memnew(TextEdit);
|
||||
te->set_text("TextEdit");
|
||||
te->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
|
||||
second_vb->add_child(te);
|
||||
second_vb->add_child(memnew(SpinBox));
|
||||
|
||||
HBoxContainer *vhb = memnew(HBoxContainer);
|
||||
second_vb->add_child(vhb);
|
||||
vhb->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
|
||||
vhb->add_child(memnew(VSlider));
|
||||
VScrollBar *vsb = memnew(VScrollBar);
|
||||
vsb->set_page(25);
|
||||
vhb->add_child(vsb);
|
||||
vhb->add_child(memnew(VSeparator));
|
||||
VBoxContainer *hvb = memnew(VBoxContainer);
|
||||
vhb->add_child(hvb);
|
||||
hvb->set_alignment(BoxContainer::ALIGNMENT_CENTER);
|
||||
hvb->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
hvb->add_child(memnew(HSlider));
|
||||
HScrollBar *hsb = memnew(HScrollBar);
|
||||
hsb->set_page(25);
|
||||
hvb->add_child(hsb);
|
||||
HSlider *hs = memnew(HSlider);
|
||||
hs->set_editable(false);
|
||||
hvb->add_child(hs);
|
||||
hvb->add_child(memnew(HSeparator));
|
||||
ProgressBar *pb = memnew(ProgressBar);
|
||||
pb->set_value(50);
|
||||
hvb->add_child(pb);
|
||||
|
||||
VBoxContainer *third_vb = memnew(VBoxContainer);
|
||||
third_vb->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
third_vb->add_theme_constant_override("separation", 10 * EDSCALE);
|
||||
main_hb->add_child(third_vb);
|
||||
|
||||
TabContainer *tc = memnew(TabContainer);
|
||||
third_vb->add_child(tc);
|
||||
tc->set_custom_minimum_size(Size2(0, 135) * EDSCALE);
|
||||
Control *tcc = memnew(Control);
|
||||
tcc->set_name(TTR("Tab 1"));
|
||||
tc->add_child(tcc);
|
||||
tcc = memnew(Control);
|
||||
tcc->set_name(TTR("Tab 2"));
|
||||
tc->add_child(tcc);
|
||||
tcc = memnew(Control);
|
||||
tcc->set_name(TTR("Tab 3"));
|
||||
tc->add_child(tcc);
|
||||
tc->set_tab_disabled(2, true);
|
||||
|
||||
Tree *test_tree = memnew(Tree);
|
||||
third_vb->add_child(test_tree);
|
||||
test_tree->set_custom_minimum_size(Size2(0, 175) * EDSCALE);
|
||||
|
||||
TreeItem *item = test_tree->create_item();
|
||||
item->set_text(0, "Tree");
|
||||
item = test_tree->create_item(test_tree->get_root());
|
||||
item->set_text(0, "Item");
|
||||
item = test_tree->create_item(test_tree->get_root());
|
||||
item->set_editable(0, true);
|
||||
item->set_text(0, TTR("Editable Item"));
|
||||
TreeItem *sub_tree = test_tree->create_item(test_tree->get_root());
|
||||
sub_tree->set_text(0, TTR("Subtree"));
|
||||
item = test_tree->create_item(sub_tree);
|
||||
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
|
||||
item->set_editable(0, true);
|
||||
item->set_text(0, "Check Item");
|
||||
item = test_tree->create_item(sub_tree);
|
||||
item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
|
||||
item->set_editable(0, true);
|
||||
item->set_range_config(0, 0, 20, 0.1);
|
||||
item->set_range(0, 2);
|
||||
item = test_tree->create_item(sub_tree);
|
||||
item->set_cell_mode(0, TreeItem::CELL_MODE_RANGE);
|
||||
item->set_editable(0, true);
|
||||
item->set_text(0, TTR("Has,Many,Options"));
|
||||
item->set_range(0, 2);
|
||||
}
|
||||
|
||||
void SceneThemeEditorPreview::_reload_scene() {
|
||||
if (loaded_scene.is_null()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (loaded_scene->get_path().is_empty() || !ResourceLoader::exists(loaded_scene->get_path())) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("Invalid path, the PackedScene resource was probably moved or removed."));
|
||||
emit_signal(SNAME("scene_invalidated"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = preview_content->get_child_count() - 1; i >= 0; i--) {
|
||||
Node *node = preview_content->get_child(i);
|
||||
node->queue_free();
|
||||
preview_content->remove_child(node);
|
||||
}
|
||||
|
||||
Node *instance = loaded_scene->instantiate();
|
||||
if (!instance || !Object::cast_to<Control>(instance)) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("Invalid PackedScene resource, must have a Control node at its root."));
|
||||
emit_signal(SNAME("scene_invalidated"));
|
||||
return;
|
||||
}
|
||||
|
||||
preview_content->add_child(instance);
|
||||
emit_signal(SNAME("scene_reloaded"));
|
||||
}
|
||||
|
||||
void SceneThemeEditorPreview::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
reload_scene_button->set_button_icon(get_editor_theme_icon(SNAME("Reload")));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void SceneThemeEditorPreview::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo("scene_invalidated"));
|
||||
ADD_SIGNAL(MethodInfo("scene_reloaded"));
|
||||
}
|
||||
|
||||
bool SceneThemeEditorPreview::set_preview_scene(const String &p_path) {
|
||||
loaded_scene = ResourceLoader::load(p_path);
|
||||
if (loaded_scene.is_null()) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("Invalid file, not a PackedScene resource."));
|
||||
return false;
|
||||
}
|
||||
|
||||
Node *instance = loaded_scene->instantiate();
|
||||
|
||||
if (!instance) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("Invalid PackedScene resource, could not instantiate it."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Object::cast_to<Control>(instance)) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("Invalid PackedScene resource, must have a Control node at its root."));
|
||||
memdelete(instance);
|
||||
return false;
|
||||
}
|
||||
|
||||
preview_content->add_child(instance);
|
||||
return true;
|
||||
}
|
||||
|
||||
String SceneThemeEditorPreview::get_preview_scene_path() const {
|
||||
if (loaded_scene.is_null()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return loaded_scene->get_path();
|
||||
}
|
||||
|
||||
SceneThemeEditorPreview::SceneThemeEditorPreview() {
|
||||
preview_toolbar->add_child(memnew(VSeparator));
|
||||
|
||||
reload_scene_button = memnew(Button);
|
||||
reload_scene_button->set_flat(true);
|
||||
reload_scene_button->set_tooltip_text(TTR("Reload the scene to reflect its most actual state."));
|
||||
preview_toolbar->add_child(reload_scene_button);
|
||||
reload_scene_button->connect(SceneStringName(pressed), callable_mp(this, &SceneThemeEditorPreview::_reload_scene));
|
||||
}
|
119
editor/scene/gui/theme_editor_preview.h
Normal file
119
editor/scene/gui/theme_editor_preview.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/**************************************************************************/
|
||||
/* theme_editor_preview.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/box_container.h"
|
||||
#include "scene/resources/theme.h"
|
||||
|
||||
class Button;
|
||||
class ColorPickerButton;
|
||||
class ColorRect;
|
||||
class MarginContainer;
|
||||
class ScrollContainer;
|
||||
|
||||
class ThemeEditorPreview : public VBoxContainer {
|
||||
GDCLASS(ThemeEditorPreview, VBoxContainer);
|
||||
|
||||
ScrollContainer *preview_container = nullptr;
|
||||
MarginContainer *preview_root = nullptr;
|
||||
ColorRect *preview_bg = nullptr;
|
||||
MarginContainer *preview_overlay = nullptr;
|
||||
Control *picker_overlay = nullptr;
|
||||
Control *hovered_control = nullptr;
|
||||
|
||||
struct ThemeCache {
|
||||
Ref<StyleBox> preview_picker_overlay;
|
||||
Color preview_picker_overlay_color;
|
||||
Ref<StyleBox> preview_picker_label;
|
||||
Ref<Font> preview_picker_font;
|
||||
int font_size = 16;
|
||||
} theme_cache;
|
||||
|
||||
double time_left = 0;
|
||||
|
||||
void _propagate_redraw(Control *p_at);
|
||||
void _refresh_interval();
|
||||
void _preview_visibility_changed();
|
||||
|
||||
void _picker_button_cbk();
|
||||
Control *_find_hovered_control(Control *p_parent, Vector2 p_mouse_position);
|
||||
|
||||
void _draw_picker_overlay();
|
||||
void _gui_input_picker_overlay(const Ref<InputEvent> &p_event);
|
||||
void _reset_picker_overlay();
|
||||
|
||||
protected:
|
||||
HBoxContainer *preview_toolbar = nullptr;
|
||||
MarginContainer *preview_content = nullptr;
|
||||
Button *picker_button = nullptr;
|
||||
|
||||
void add_preview_overlay(Control *p_overlay);
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void set_preview_theme(const Ref<Theme> &p_theme);
|
||||
|
||||
ThemeEditorPreview();
|
||||
};
|
||||
|
||||
class DefaultThemeEditorPreview : public ThemeEditorPreview {
|
||||
GDCLASS(DefaultThemeEditorPreview, ThemeEditorPreview);
|
||||
|
||||
ColorPickerButton *test_color_picker_button = nullptr;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
DefaultThemeEditorPreview();
|
||||
};
|
||||
|
||||
class SceneThemeEditorPreview : public ThemeEditorPreview {
|
||||
GDCLASS(SceneThemeEditorPreview, ThemeEditorPreview);
|
||||
|
||||
Ref<PackedScene> loaded_scene;
|
||||
|
||||
Button *reload_scene_button = nullptr;
|
||||
|
||||
void _reload_scene();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
bool set_preview_scene(const String &p_path);
|
||||
String get_preview_scene_path() const;
|
||||
|
||||
SceneThemeEditorPreview();
|
||||
};
|
Reference in New Issue
Block a user