Fix theme propagation in various parts of the editor

This commit is contained in:
Yuri Sizov 2022-09-01 18:52:49 +03:00
parent 9142904c24
commit fc7cef8dec
9 changed files with 382 additions and 245 deletions

View file

@ -69,13 +69,49 @@ VBoxContainer *EditorFileDialog::get_vbox() {
return vbox;
}
void EditorFileDialog::_update_theme_item_cache() {
ConfirmationDialog::_update_theme_item_cache();
theme_cache.parent_folder = get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons"));
theme_cache.forward_folder = get_theme_icon(SNAME("Forward"), SNAME("EditorIcons"));
theme_cache.back_folder = get_theme_icon(SNAME("Back"), SNAME("EditorIcons"));
theme_cache.reload = get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"));
theme_cache.toggle_hidden = get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons"));
theme_cache.favorite = get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons"));
theme_cache.mode_thumbnails = get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons"));
theme_cache.mode_list = get_theme_icon(SNAME("FileList"), SNAME("EditorIcons"));
theme_cache.favorites_up = get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons"));
theme_cache.favorites_down = get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons"));
theme_cache.folder = get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"));
theme_cache.folder_icon_modulate = get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
theme_cache.action_copy = get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons"));
theme_cache.action_delete = get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"));
theme_cache.filesystem = get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons"));
theme_cache.folder_medium_thumbnail = get_theme_icon(SNAME("FolderMediumThumb"), SNAME("EditorIcons"));
theme_cache.file_medium_thumbnail = get_theme_icon(SNAME("FileMediumThumb"), SNAME("EditorIcons"));
theme_cache.folder_big_thumbnail = get_theme_icon(SNAME("FolderBigThumb"), SNAME("EditorIcons"));
theme_cache.file_big_thumbnail = get_theme_icon(SNAME("FileBigThumb"), SNAME("EditorIcons"));
theme_cache.progress[0] = get_theme_icon("Progress1", SNAME("EditorIcons"));
theme_cache.progress[1] = get_theme_icon("Progress2", SNAME("EditorIcons"));
theme_cache.progress[2] = get_theme_icon("Progress3", SNAME("EditorIcons"));
theme_cache.progress[3] = get_theme_icon("Progress4", SNAME("EditorIcons"));
theme_cache.progress[4] = get_theme_icon("Progress5", SNAME("EditorIcons"));
theme_cache.progress[5] = get_theme_icon("Progress6", SNAME("EditorIcons"));
theme_cache.progress[6] = get_theme_icon("Progress7", SNAME("EditorIcons"));
theme_cache.progress[7] = get_theme_icon("Progress8", SNAME("EditorIcons"));
}
void EditorFileDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY:
case NOTIFICATION_THEME_CHANGED:
case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_TRANSLATION_CHANGED: {
_update_icons();
invalidate();
} break;
case NOTIFICATION_PROCESS: {
@ -86,7 +122,8 @@ void EditorFileDialog::_notification(int p_what) {
if (preview_wheel_index >= 8) {
preview_wheel_index = 0;
}
Ref<Texture2D> frame = item_list->get_theme_icon("Progress" + itos(preview_wheel_index + 1), SNAME("EditorIcons"));
Ref<Texture2D> frame = theme_cache.progress[preview_wheel_index];
preview->set_texture(frame);
preview_wheel_timeout = 0.1;
}
@ -100,7 +137,6 @@ void EditorFileDialog::_notification(int p_what) {
}
set_display_mode((DisplayMode)EditorSettings::get_singleton()->get("filesystem/file_dialog/display_mode").operator int());
_update_icons();
// DO NOT CALL UPDATE FILE LIST HERE, ALL HUNDREDS OF HIDDEN DIALOGS WILL RESPOND, CALL INVALIDATE INSTEAD
invalidate();
} break;
@ -289,49 +325,7 @@ void EditorFileDialog::_post_popup() {
}
if (is_visible()) {
Ref<Texture2D> folder = item_list->get_theme_icon(SNAME("folder"), SNAME("FileDialog"));
const Color folder_color = item_list->get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
recent->clear();
bool res = (access == ACCESS_RESOURCES);
Vector<String> recentd = EditorSettings::get_singleton()->get_recent_dirs();
Vector<String> recentd_paths;
Vector<String> recentd_names;
for (int i = 0; i < recentd.size(); i++) {
bool cres = recentd[i].begins_with("res://");
if (cres != res) {
continue;
}
if (!dir_access->dir_exists(recentd[i])) {
// Remove invalid directory from the list of Recent directories.
recentd.remove_at(i--);
continue;
}
// Compute recent directory display text.
String name = recentd[i];
if (res && name == "res://") {
name = "/";
} else {
if (name.ends_with("/")) {
name = name.substr(0, name.length() - 1);
}
name = name.get_file();
}
recentd_paths.append(recentd[i]);
recentd_names.append(name);
}
EditorNode::disambiguate_filenames(recentd_paths, recentd_names);
for (int i = 0; i < recentd_paths.size(); i++) {
recent->add_item(recentd_names[i], folder);
recent->set_item_metadata(-1, recentd_paths[i]);
recent->set_item_icon_modulate(-1, folder_color);
}
EditorSettings::get_singleton()->set_recent_dirs(recentd);
_update_recent();
local_history.clear();
local_history_pos = -1;
@ -626,16 +620,16 @@ void EditorFileDialog::_item_list_item_rmb_clicked(int p_item, const Vector2 &p_
}
if (single_item_selected) {
item_menu->add_icon_item(item_list->get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), TTR("Copy Path"), ITEM_MENU_COPY_PATH);
item_menu->add_icon_item(theme_cache.action_copy, TTR("Copy Path"), ITEM_MENU_COPY_PATH);
}
if (allow_delete) {
item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons")), TTR("Delete"), ITEM_MENU_DELETE, Key::KEY_DELETE);
item_menu->add_icon_item(theme_cache.action_delete, TTR("Delete"), ITEM_MENU_DELETE, Key::KEY_DELETE);
}
if (single_item_selected) {
item_menu->add_separator();
Dictionary item_meta = item_list->get_item_metadata(p_item);
String item_text = item_meta["dir"] ? TTR("Open in File Manager") : TTR("Show in File Manager");
item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), item_text, ITEM_MENU_SHOW_IN_EXPLORER);
item_menu->add_icon_item(theme_cache.filesystem, item_text, ITEM_MENU_SHOW_IN_EXPLORER);
}
if (item_menu->get_item_count() > 0) {
@ -663,11 +657,11 @@ void EditorFileDialog::_item_list_empty_clicked(const Vector2 &p_pos, MouseButto
item_menu->reset_size();
if (can_create_dir) {
item_menu->add_icon_item(item_list->get_theme_icon(SNAME("folder"), SNAME("FileDialog")), TTR("New Folder..."), ITEM_MENU_NEW_FOLDER, KeyModifierMask::CMD | Key::N);
item_menu->add_icon_item(theme_cache.folder, TTR("New Folder..."), ITEM_MENU_NEW_FOLDER, KeyModifierMask::CMD | Key::N);
}
item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")), TTR("Refresh"), ITEM_MENU_REFRESH, Key::F5);
item_menu->add_icon_item(theme_cache.reload, TTR("Refresh"), ITEM_MENU_REFRESH, Key::F5);
item_menu->add_separator();
item_menu->add_icon_item(item_list->get_theme_icon(SNAME("Filesystem"), SNAME("EditorIcons")), TTR("Open in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER);
item_menu->add_icon_item(theme_cache.filesystem, TTR("Open in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER);
item_menu->set_position(item_list->get_screen_position() + p_pos);
item_menu->reset_size();
@ -773,11 +767,11 @@ void EditorFileDialog::update_file_list() {
item_list->set_fixed_icon_size(Size2(thumbnail_size, thumbnail_size));
if (thumbnail_size < 64) {
folder_thumbnail = item_list->get_theme_icon(SNAME("FolderMediumThumb"), SNAME("EditorIcons"));
file_thumbnail = item_list->get_theme_icon(SNAME("FileMediumThumb"), SNAME("EditorIcons"));
folder_thumbnail = theme_cache.folder_medium_thumbnail;
file_thumbnail = theme_cache.file_medium_thumbnail;
} else {
folder_thumbnail = item_list->get_theme_icon(SNAME("FolderBigThumb"), SNAME("EditorIcons"));
file_thumbnail = item_list->get_theme_icon(SNAME("FileBigThumb"), SNAME("EditorIcons"));
folder_thumbnail = theme_cache.folder_big_thumbnail;
file_thumbnail = theme_cache.file_big_thumbnail;
}
preview_vb->hide();
@ -797,8 +791,6 @@ void EditorFileDialog::update_file_list() {
dir_access->list_dir_begin();
Ref<Texture2D> folder = item_list->get_theme_icon(SNAME("folder"), SNAME("FileDialog"));
const Color folder_color = item_list->get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
List<String> files;
List<String> dirs;
@ -838,7 +830,7 @@ void EditorFileDialog::update_file_list() {
if (display_mode == DISPLAY_THUMBNAILS) {
item_list->set_item_icon(-1, folder_thumbnail);
} else {
item_list->set_item_icon(-1, folder);
item_list->set_item_icon(-1, theme_cache.folder);
}
Dictionary d;
@ -847,7 +839,7 @@ void EditorFileDialog::update_file_list() {
d["dir"] = true;
item_list->set_item_metadata(-1, d);
item_list->set_item_icon_modulate(-1, folder_color);
item_list->set_item_icon_modulate(-1, theme_cache.folder_icon_modulate);
dirs.pop_front();
}
@ -1120,6 +1112,7 @@ void EditorFileDialog::invalidate() {
if (is_visible()) {
update_file_list();
_update_favorites();
_update_recent();
invalidated = false;
} else {
invalidated = true;
@ -1235,22 +1228,25 @@ void EditorFileDialog::_update_drives(bool p_select) {
void EditorFileDialog::_update_icons() {
// Update icons.
mode_thumbnails->set_icon(item_list->get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons")));
mode_list->set_icon(item_list->get_theme_icon(SNAME("FileList"), SNAME("EditorIcons")));
if (is_layout_rtl()) {
dir_prev->set_icon(item_list->get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
dir_next->set_icon(item_list->get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
} else {
dir_prev->set_icon(item_list->get_theme_icon(SNAME("Back"), SNAME("EditorIcons")));
dir_next->set_icon(item_list->get_theme_icon(SNAME("Forward"), SNAME("EditorIcons")));
}
dir_up->set_icon(item_list->get_theme_icon(SNAME("ArrowUp"), SNAME("EditorIcons")));
refresh->set_icon(item_list->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons")));
favorite->set_icon(item_list->get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons")));
show_hidden->set_icon(item_list->get_theme_icon(SNAME("GuiVisibilityVisible"), SNAME("EditorIcons")));
fav_up->set_icon(item_list->get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons")));
fav_down->set_icon(item_list->get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons")));
mode_thumbnails->set_icon(theme_cache.mode_thumbnails);
mode_list->set_icon(theme_cache.mode_list);
if (is_layout_rtl()) {
dir_prev->set_icon(theme_cache.forward_folder);
dir_next->set_icon(theme_cache.back_folder);
} else {
dir_prev->set_icon(theme_cache.back_folder);
dir_next->set_icon(theme_cache.forward_folder);
}
dir_up->set_icon(theme_cache.parent_folder);
refresh->set_icon(theme_cache.reload);
favorite->set_icon(theme_cache.favorite);
show_hidden->set_icon(theme_cache.toggle_hidden);
fav_up->set_icon(theme_cache.favorites_up);
fav_down->set_icon(theme_cache.favorites_down);
}
void EditorFileDialog::_favorite_selected(int p_idx) {
@ -1335,8 +1331,6 @@ void EditorFileDialog::_update_favorites() {
bool res = (access == ACCESS_RESOURCES);
String current = get_current_dir();
Ref<Texture2D> folder_icon = item_list->get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"));
const Color folder_color = item_list->get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog"));
favorites->clear();
favorite->set_pressed(false);
@ -1389,9 +1383,9 @@ void EditorFileDialog::_update_favorites() {
EditorNode::disambiguate_filenames(favorited_paths, favorited_names);
for (int i = 0; i < favorited_paths.size(); i++) {
favorites->add_item(favorited_names[i], folder_icon);
favorites->add_item(favorited_names[i], theme_cache.folder);
favorites->set_item_metadata(-1, favorited_paths[i]);
favorites->set_item_icon_modulate(-1, folder_color);
favorites->set_item_icon_modulate(-1, theme_cache.folder_icon_modulate);
if (i == current_favorite) {
favorite->set_pressed(true);
@ -1435,6 +1429,50 @@ void EditorFileDialog::_favorite_pressed() {
_update_favorites();
}
void EditorFileDialog::_update_recent() {
recent->clear();
bool res = (access == ACCESS_RESOURCES);
Vector<String> recentd = EditorSettings::get_singleton()->get_recent_dirs();
Vector<String> recentd_paths;
Vector<String> recentd_names;
for (int i = 0; i < recentd.size(); i++) {
bool cres = recentd[i].begins_with("res://");
if (cres != res) {
continue;
}
if (!dir_access->dir_exists(recentd[i])) {
// Remove invalid directory from the list of Recent directories.
recentd.remove_at(i--);
continue;
}
// Compute recent directory display text.
String name = recentd[i];
if (res && name == "res://") {
name = "/";
} else {
if (name.ends_with("/")) {
name = name.substr(0, name.length() - 1);
}
name = name.get_file();
}
recentd_paths.append(recentd[i]);
recentd_names.append(name);
}
EditorNode::disambiguate_filenames(recentd_paths, recentd_names);
for (int i = 0; i < recentd_paths.size(); i++) {
recent->add_item(recentd_names[i], theme_cache.folder);
recent->set_item_metadata(-1, recentd_paths[i]);
recent->set_item_icon_modulate(-1, theme_cache.folder_icon_modulate);
}
EditorSettings::get_singleton()->set_recent_dirs(recentd);
}
void EditorFileDialog::_recent_selected(int p_idx) {
Vector<String> recentd = EditorSettings::get_singleton()->get_recent_dirs();
ERR_FAIL_INDEX(p_idx, recentd.size());

View file

@ -148,6 +148,33 @@ private:
bool disable_overwrite_warning = false;
bool invalidated = true;
struct ThemeCache {
Ref<Texture2D> parent_folder;
Ref<Texture2D> forward_folder;
Ref<Texture2D> back_folder;
Ref<Texture2D> reload;
Ref<Texture2D> toggle_hidden;
Ref<Texture2D> favorite;
Ref<Texture2D> mode_thumbnails;
Ref<Texture2D> mode_list;
Ref<Texture2D> favorites_up;
Ref<Texture2D> favorites_down;
Ref<Texture2D> folder;
Color folder_icon_modulate;
Ref<Texture2D> action_copy;
Ref<Texture2D> action_delete;
Ref<Texture2D> filesystem;
Ref<Texture2D> folder_medium_thumbnail;
Ref<Texture2D> file_medium_thumbnail;
Ref<Texture2D> folder_big_thumbnail;
Ref<Texture2D> file_big_thumbnail;
Ref<Texture2D> progress[8]{};
} theme_cache;
void update_dir();
void update_file_name();
void update_file_list();
@ -161,6 +188,7 @@ private:
void _favorite_move_up();
void _favorite_move_down();
void _update_recent();
void _recent_selected(int p_idx);
void _item_selected(int p_item);
@ -206,6 +234,8 @@ private:
bool _is_open_should_be_disabled();
protected:
virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();

View file

@ -40,33 +40,39 @@
#include "scene/resources/particle_process_material.h"
#include "scene/resources/sky_material.h"
void MaterialEditor::_update_theme_item_cache() {
Control::_update_theme_item_cache();
theme_cache.light_1_on = get_theme_icon(SNAME("MaterialPreviewLight1"), SNAME("EditorIcons"));
theme_cache.light_1_off = get_theme_icon(SNAME("MaterialPreviewLight1Off"), SNAME("EditorIcons"));
theme_cache.light_2_on = get_theme_icon(SNAME("MaterialPreviewLight2"), SNAME("EditorIcons"));
theme_cache.light_2_off = get_theme_icon(SNAME("MaterialPreviewLight2Off"), SNAME("EditorIcons"));
theme_cache.sphere_on = get_theme_icon(SNAME("MaterialPreviewSphere"), SNAME("EditorIcons"));
theme_cache.sphere_off = get_theme_icon(SNAME("MaterialPreviewSphereOff"), SNAME("EditorIcons"));
theme_cache.box_on = get_theme_icon(SNAME("MaterialPreviewCube"), SNAME("EditorIcons"));
theme_cache.box_off = get_theme_icon(SNAME("MaterialPreviewCubeOff"), SNAME("EditorIcons"));
theme_cache.checkerboard = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons"));
}
void MaterialEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
//get_scene()->connect("node_removed",this,"_node_removed");
case NOTIFICATION_THEME_CHANGED: {
light_1_switch->set_normal_texture(theme_cache.light_1_on);
light_1_switch->set_pressed_texture(theme_cache.light_1_off);
light_2_switch->set_normal_texture(theme_cache.light_2_on);
light_2_switch->set_pressed_texture(theme_cache.light_2_off);
if (first_enter) {
//it's in propertyeditor so.. could be moved around
light_1_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewLight1"), SNAME("EditorIcons")));
light_1_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewLight1Off"), SNAME("EditorIcons")));
light_2_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewLight2"), SNAME("EditorIcons")));
light_2_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewLight2Off"), SNAME("EditorIcons")));
sphere_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewSphereOff"), SNAME("EditorIcons")));
sphere_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewSphere"), SNAME("EditorIcons")));
box_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewCubeOff"), SNAME("EditorIcons")));
box_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewCube"), SNAME("EditorIcons")));
first_enter = false;
}
sphere_switch->set_normal_texture(theme_cache.sphere_off);
sphere_switch->set_pressed_texture(theme_cache.sphere_on);
box_switch->set_normal_texture(theme_cache.box_off);
box_switch->set_pressed_texture(theme_cache.box_on);
} break;
case NOTIFICATION_DRAW: {
Ref<Texture2D> checkerboard = get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons"));
Size2 size = get_size();
draw_texture_rect(checkerboard, Rect2(Point2(), size), true);
draw_texture_rect(theme_cache.checkerboard, Rect2(Point2(), size), true);
} break;
}
}
@ -231,8 +237,6 @@ MaterialEditor::MaterialEditor() {
vb_light->add_child(light_2_switch);
light_2_switch->connect("pressed", callable_mp(this, &MaterialEditor::_button_pressed).bind(light_2_switch));
first_enter = true;
if (EditorSettings::get_singleton()->get_project_metadata("inspector_options", "material_preview_on_sphere", true)) {
box_instance->hide();
} else {

View file

@ -70,12 +70,23 @@ class MaterialEditor : public Control {
Ref<Material> material;
struct ThemeCache {
Ref<Texture2D> light_1_on;
Ref<Texture2D> light_1_off;
Ref<Texture2D> light_2_on;
Ref<Texture2D> light_2_off;
Ref<Texture2D> sphere_on;
Ref<Texture2D> sphere_off;
Ref<Texture2D> box_on;
Ref<Texture2D> box_off;
Ref<Texture2D> checkerboard;
} theme_cache;
void _button_pressed(Node *p_button);
bool first_enter;
protected:
virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
public:

View file

@ -49,20 +49,22 @@ void MeshEditor::gui_input(const Ref<InputEvent> &p_event) {
}
}
void MeshEditor::_update_theme_item_cache() {
SubViewportContainer::_update_theme_item_cache();
theme_cache.light_1_on = get_theme_icon(SNAME("MaterialPreviewLight1"), SNAME("EditorIcons"));
theme_cache.light_1_off = get_theme_icon(SNAME("MaterialPreviewLight1Off"), SNAME("EditorIcons"));
theme_cache.light_2_on = get_theme_icon(SNAME("MaterialPreviewLight2"), SNAME("EditorIcons"));
theme_cache.light_2_off = get_theme_icon(SNAME("MaterialPreviewLight2Off"), SNAME("EditorIcons"));
}
void MeshEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_READY: {
//get_scene()->connect("node_removed",this,"_node_removed");
if (first_enter) {
//it's in propertyeditor so. could be moved around
light_1_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewLight1"), SNAME("EditorIcons")));
light_1_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewLight1Off"), SNAME("EditorIcons")));
light_2_switch->set_normal_texture(get_theme_icon(SNAME("MaterialPreviewLight2"), SNAME("EditorIcons")));
light_2_switch->set_pressed_texture(get_theme_icon(SNAME("MaterialPreviewLight2Off"), SNAME("EditorIcons")));
first_enter = false;
}
case NOTIFICATION_THEME_CHANGED: {
light_1_switch->set_normal_texture(theme_cache.light_1_on);
light_1_switch->set_pressed_texture(theme_cache.light_1_off);
light_2_switch->set_normal_texture(theme_cache.light_2_on);
light_2_switch->set_pressed_texture(theme_cache.light_2_off);
} break;
}
}
@ -160,8 +162,6 @@ MeshEditor::MeshEditor() {
vb_light->add_child(light_2_switch);
light_2_switch->connect("pressed", callable_mp(this, &MeshEditor::_button_pressed).bind(light_2_switch));
first_enter = true;
rot_x = 0;
rot_y = 0;
}

View file

@ -58,12 +58,18 @@ class MeshEditor : public SubViewportContainer {
TextureButton *light_1_switch = nullptr;
TextureButton *light_2_switch = nullptr;
void _button_pressed(Node *p_button);
bool first_enter;
struct ThemeCache {
Ref<Texture2D> light_1_on;
Ref<Texture2D> light_1_off;
Ref<Texture2D> light_2_on;
Ref<Texture2D> light_2_off;
} theme_cache;
void _button_pressed(Node *p_button);
void _update_rotation();
protected:
virtual void _update_theme_item_cache() override;
void _notification(int p_what);
void gui_input(const Ref<InputEvent> &p_event) override;

View file

@ -196,7 +196,7 @@ private:
Color clear_button_color;
Color clear_button_color_pressed;
int base_scale = 0;
float base_scale = 1.0;
} theme_cache;
bool _is_over_clear_button(const Point2 &p_pos) const;

View file

@ -134,8 +134,7 @@ RichTextLabel::Item *RichTextLabel::_get_prev_item(Item *p_item, bool p_free) co
}
Rect2 RichTextLabel::_get_text_rect() {
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
return Rect2(style->get_offset(), get_size() - style->get_minimum_size());
return Rect2(theme_cache.normal_style->get_offset(), get_size() - theme_cache.normal_style->get_minimum_size());
}
RichTextLabel::Item *RichTextLabel::_get_item_at_pos(RichTextLabel::Item *p_item_from, RichTextLabel::Item *p_item_to, int p_position) {
@ -287,8 +286,6 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
switch (it->type) {
case ITEM_TABLE: {
ItemTable *table = static_cast<ItemTable *>(it);
int hseparation = get_theme_constant(SNAME("table_h_separation"));
int vseparation = get_theme_constant(SNAME("table_v_separation"));
int col_count = table->columns.size();
for (int i = 0; i < col_count; i++) {
@ -309,12 +306,12 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
}
// Compute minimum width for each cell.
const int available_width = p_width - hseparation * (col_count - 1);
const int available_width = p_width - theme_cache.table_h_separation * (col_count - 1);
// Compute available width and total ratio (for expanders).
int total_ratio = 0;
int remaining_width = available_width;
table->total_width = hseparation;
table->total_width = theme_cache.table_h_separation;
for (int i = 0; i < col_count; i++) {
remaining_width -= table->columns[i].min_width;
@ -332,7 +329,7 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
if (table->columns[i].expand && total_ratio > 0 && remaining_width > 0) {
table->columns[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio;
}
table->total_width += table->columns[i].width + hseparation;
table->total_width += table->columns[i].width + theme_cache.table_h_separation;
}
// Resize to max_width if needed and distribute the remaining space.
@ -394,9 +391,9 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
frame->lines[i].offset.y = prev_h;
frame->lines[i].offset += offset;
float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * get_theme_constant(SNAME("line_separation"));
float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * theme_cache.line_separation;
if (i > 0) {
h += get_theme_constant(SNAME("line_separation"));
h += theme_cache.line_separation;
}
if (frame->min_size_over.y > 0) {
h = MAX(h, frame->min_size_over.y);
@ -405,15 +402,15 @@ float RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font
h = MIN(h, frame->max_size_over.y);
}
yofs += h;
prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + frame->lines[i].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + frame->lines[i].text_buf->get_line_count() * theme_cache.line_separation;
}
yofs += frame->padding.size.y;
offset.x += table->columns[column].width + hseparation + frame->padding.size.x;
offset.x += table->columns[column].width + theme_cache.table_h_separation + frame->padding.size.x;
row_height = MAX(yofs, row_height);
if (column == col_count - 1) {
offset.x = 0;
row_height += vseparation;
row_height += theme_cache.table_v_separation;
table->total_height += row_height;
offset.y += row_height;
table->rows.push_back(row_height);
@ -551,8 +548,6 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
} break;
case ITEM_TABLE: {
ItemTable *table = static_cast<ItemTable *>(it);
int hseparation = get_theme_constant(SNAME("table_h_separation"));
int vseparation = get_theme_constant(SNAME("table_v_separation"));
int col_count = table->columns.size();
int t_char_count = 0;
// Set minimums to zero.
@ -562,7 +557,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
table->columns[i].width = 0;
}
// Compute minimum width for each cell.
const int available_width = p_width - hseparation * (col_count - 1);
const int available_width = p_width - theme_cache.table_h_separation * (col_count - 1);
int idx = 0;
for (Item *E : table->subitems) {
@ -591,7 +586,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
// Compute available width and total ratio (for expanders).
int total_ratio = 0;
int remaining_width = available_width;
table->total_width = hseparation;
table->total_width = theme_cache.table_h_separation;
for (int i = 0; i < col_count; i++) {
remaining_width -= table->columns[i].min_width;
@ -609,7 +604,7 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
if (table->columns[i].expand && total_ratio > 0 && remaining_width > 0) {
table->columns[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio;
}
table->total_width += table->columns[i].width + hseparation;
table->total_width += table->columns[i].width + theme_cache.table_h_separation;
}
// Resize to max_width if needed and distribute the remaining space.
@ -672,9 +667,9 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
frame->lines[i].offset.y = prev_h;
frame->lines[i].offset += offset;
float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * get_theme_constant(SNAME("line_separation"));
float h = frame->lines[i].text_buf->get_size().y + (frame->lines[i].text_buf->get_line_count() - 1) * theme_cache.line_separation;
if (i > 0) {
h += get_theme_constant(SNAME("line_separation"));
h += theme_cache.line_separation;
}
if (frame->min_size_over.y > 0) {
h = MAX(h, frame->min_size_over.y);
@ -683,16 +678,16 @@ float RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font>
h = MIN(h, frame->max_size_over.y);
}
yofs += h;
prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + frame->lines[i].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
prev_h = frame->lines[i].offset.y + frame->lines[i].text_buf->get_size().y + frame->lines[i].text_buf->get_line_count() * theme_cache.line_separation;
}
yofs += frame->padding.size.y;
offset.x += table->columns[column].width + hseparation + frame->padding.size.x;
offset.x += table->columns[column].width + theme_cache.table_h_separation + frame->padding.size.x;
row_height = MAX(yofs, row_height);
// Add row height after last column of the row or last cell of the table.
if (column == col_count - 1 || E->next() == nullptr) {
offset.x = 0;
row_height += vseparation;
row_height += theme_cache.table_v_separation;
table->total_height += row_height;
offset.y += row_height;
table->rows.push_back(row_height);
@ -723,7 +718,6 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
ERR_FAIL_COND_V(p_line < 0 || p_line >= (int)p_frame->lines.size(), 0);
Vector2 off;
int line_spacing = get_theme_constant(SNAME("line_separation"));
Line &l = p_frame->lines[p_line];
MutexLock lock(l.text_buf->get_mutex());
@ -775,8 +769,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
}
}
if (!prefix.is_empty()) {
Ref<Font> font = get_theme_font(SNAME("normal_font"));
int font_size = get_theme_font_size(SNAME("normal_font_size"));
Ref<Font> font = theme_cache.normal_font;
int font_size = theme_cache.normal_font_size;
ItemFont *font_it = _find_font(l.from);
if (font_it) {
@ -819,7 +813,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
// Draw text.
for (int line = 0; line < l.text_buf->get_line_count(); line++) {
if (line > 0) {
off.y += line_spacing;
off.y += theme_cache.line_separation;
}
if (p_ofs.y + off.y >= ctrl_size.height) {
@ -894,10 +888,11 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} break;
case ITEM_TABLE: {
ItemTable *table = static_cast<ItemTable *>(it);
Color odd_row_bg = get_theme_color(SNAME("table_odd_row_bg"));
Color even_row_bg = get_theme_color(SNAME("table_even_row_bg"));
Color border = get_theme_color(SNAME("table_border"));
int hseparation = get_theme_constant(SNAME("table_h_separation"));
Color odd_row_bg = theme_cache.table_odd_row_bg;
Color even_row_bg = theme_cache.table_even_row_bg;
Color border = theme_cache.table_border;
int hseparation = theme_cache.table_h_separation;
int col_count = table->columns.size();
int row_count = table->rows.size();
@ -1093,8 +1088,8 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
_draw_fbg_boxes(ci, rid, fbg_line_off, it_from, it_to, chr_range.x, chr_range.y, 0);
// Draw main text.
Color selection_fg = get_theme_color(SNAME("font_selected_color"));
Color selection_bg = get_theme_color(SNAME("selection_color"));
Color selection_fg = theme_cache.font_selected_color;
Color selection_bg = theme_cache.selection_color;
int sel_start = -1;
int sel_end = -1;
@ -1136,7 +1131,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} else if (ul_started) {
ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width);
}
if (_find_hint(it, nullptr) && underline_hint) {
@ -1149,7 +1144,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} else if (dot_ul_started) {
dot_ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2);
}
if (_find_strikethrough(it)) {
@ -1162,7 +1157,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
} else if (st_started) {
st_started = false;
float y_off = -TS->shaped_text_get_ascent(rid) + TS->shaped_text_get_size(rid).y / 2;
float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(st_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), st_color, underline_width);
}
@ -1301,19 +1296,19 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
if (ul_started) {
ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width);
}
if (dot_ul_started) {
dot_ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2);
}
if (st_started) {
st_started = false;
float y_off = -TS->shaped_text_get_ascent(rid) + TS->shaped_text_get_size(rid).y / 2;
float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(st_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), st_color, underline_width);
}
}
@ -1323,19 +1318,19 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
if (ul_started) {
ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), ul_color, underline_width);
}
if (dot_ul_started) {
dot_ul_started = false;
float y_off = TS->shaped_text_get_underline_position(rid);
float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_dashed_line(dot_ul_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), dot_ul_color, underline_width, underline_width * 2);
}
if (st_started) {
st_started = false;
float y_off = -TS->shaped_text_get_ascent(rid) + TS->shaped_text_get_size(rid).y / 2;
float underline_width = TS->shaped_text_get_underline_thickness(rid) * get_theme_default_base_scale();
float underline_width = TS->shaped_text_get_underline_thickness(rid) * theme_cache.base_scale;
draw_line(st_start + Vector2(0, y_off), p_ofs + Vector2(off.x, off.y + y_off), st_color, underline_width);
}
// Draw foreground color box
@ -1371,7 +1366,7 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
while (ofs.y < size.height && from_line < to_line) {
MutexLock lock(main->lines[from_line].text_buf->get_mutex());
_find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, p_click, r_click_frame, r_click_line, r_click_item, r_click_char, false, p_meta);
ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * theme_cache.line_separation;
if (((r_click_item != nullptr) && ((*r_click_item) != nullptr)) || ((r_click_frame != nullptr) && ((*r_click_frame) != nullptr))) {
if (r_outside != nullptr) {
*r_outside = false;
@ -1449,9 +1444,6 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
if (p_click.y >= rect.position.y && p_click.y <= rect.position.y + rect.size.y) {
switch (it->type) {
case ITEM_TABLE: {
int hseparation = get_theme_constant(SNAME("table_h_separation"));
int vseparation = get_theme_constant(SNAME("table_v_separation"));
ItemTable *table = static_cast<ItemTable *>(it);
int idx = 0;
@ -1469,7 +1461,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
if (rtl) {
coff.x = rect.size.width - table->columns[col].width - coff.x;
}
Rect2 crect = Rect2(rect.position + coff - frame->padding.position, Size2(table->columns[col].width + hseparation, table->rows[row] + vseparation) + frame->padding.position + frame->padding.size);
Rect2 crect = Rect2(rect.position + coff - frame->padding.position, Size2(table->columns[col].width + theme_cache.table_h_separation, table->rows[row] + theme_cache.table_v_separation) + frame->padding.position + frame->padding.size);
if (col == col_count - 1) {
if (rtl) {
crect.size.x = crect.position.x + crect.size.x;
@ -1508,7 +1500,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
}
Rect2 rect = Rect2(p_ofs + off - Vector2(0, TS->shaped_text_get_ascent(rid)) - p_frame->padding.position, TS->shaped_text_get_size(rid) + p_frame->padding.position + p_frame->padding.size);
if (p_table) {
rect.size.y += get_theme_constant(SNAME("table_v_separation"));
rect.size.y += theme_cache.table_v_separation;
}
if (p_click.y >= rect.position.y && p_click.y <= rect.position.y + rect.size.y) {
@ -1547,7 +1539,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
return table_offy;
}
off.y += TS->shaped_text_get_descent(rid) + get_theme_constant(SNAME("line_separation"));
off.y += TS->shaped_text_get_descent(rid) + theme_cache.line_separation;
}
// Text line hit.
@ -1562,8 +1554,8 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V
int stop = text_rect_begin;
*r_click_item = _find_indentable(it);
while (*r_click_item) {
Ref<Font> font = get_theme_font(SNAME("normal_font"));
int font_size = get_theme_font_size(SNAME("normal_font_size"));
Ref<Font> font = theme_cache.normal_font;
int font_size = theme_cache.normal_font_size;
ItemFont *font_it = _find_font(*r_click_item);
if (font_it) {
if (font_it->font.is_valid()) {
@ -1676,7 +1668,49 @@ int RichTextLabel::_find_first_line(int p_from, int p_to, int p_vofs) const {
}
_FORCE_INLINE_ float RichTextLabel::_calculate_line_vertical_offset(const RichTextLabel::Line &line) const {
return line.get_height(get_theme_constant(SNAME("line_separation")));
return line.get_height(theme_cache.line_separation);
}
void RichTextLabel::_update_theme_item_cache() {
Control::_update_theme_item_cache();
theme_cache.normal_style = get_theme_stylebox(SNAME("normal"));
theme_cache.focus_style = get_theme_stylebox(SNAME("focus"));
theme_cache.progress_bg_style = get_theme_stylebox(SNAME("bg"), SNAME("ProgressBar"));
theme_cache.progress_fg_style = get_theme_stylebox(SNAME("fg"), SNAME("ProgressBar"));
theme_cache.line_separation = get_theme_constant(SNAME("line_separation"));
theme_cache.normal_font = get_theme_font(SNAME("normal_font"));
theme_cache.normal_font_size = get_theme_font_size(SNAME("normal_font_size"));
theme_cache.default_color = get_theme_color(SNAME("default_color"));
theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color"));
theme_cache.selection_color = get_theme_color(SNAME("selection_color"));
theme_cache.font_outline_color = get_theme_color(SNAME("font_outline_color"));
theme_cache.font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
theme_cache.shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size"));
theme_cache.shadow_offset_x = get_theme_constant(SNAME("shadow_offset_x"));
theme_cache.shadow_offset_y = get_theme_constant(SNAME("shadow_offset_y"));
theme_cache.outline_size = get_theme_constant(SNAME("outline_size"));
theme_cache.outline_color = get_theme_color(SNAME("outline_color"));
theme_cache.bold_font = get_theme_font(SNAME("bold_font"));
theme_cache.bold_font_size = get_theme_font_size(SNAME("bold_font_size"));
theme_cache.bold_italics_font = get_theme_font(SNAME("bold_italics_font"));
theme_cache.bold_italics_font_size = get_theme_font_size(SNAME("bold_italics_font_size"));
theme_cache.italics_font = get_theme_font(SNAME("italics_font"));
theme_cache.italics_font_size = get_theme_font_size(SNAME("italics_font_size"));
theme_cache.mono_font = get_theme_font(SNAME("mono_font"));
theme_cache.mono_font_size = get_theme_font_size(SNAME("mono_font_size"));
theme_cache.table_h_separation = get_theme_constant(SNAME("table_h_separation"));
theme_cache.table_v_separation = get_theme_constant(SNAME("table_v_separation"));
theme_cache.table_odd_row_bg = get_theme_color(SNAME("table_odd_row_bg"));
theme_cache.table_even_row_bg = get_theme_color(SNAME("table_even_row_bg"));
theme_cache.table_border = get_theme_color(SNAME("table_border"));
theme_cache.base_scale = get_theme_default_base_scale();
}
void RichTextLabel::_notification(int p_what) {
@ -1732,11 +1766,11 @@ void RichTextLabel::_notification(int p_what) {
RID ci = get_canvas_item();
Size2 size = get_size();
draw_style_box(get_theme_stylebox(SNAME("normal")), Rect2(Point2(), size));
draw_style_box(theme_cache.normal_style, Rect2(Point2(), size));
if (has_focus()) {
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true);
draw_style_box(get_theme_stylebox(SNAME("focus")), Rect2(Point2(), size));
draw_style_box(theme_cache.focus_style, Rect2(Point2(), size));
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
}
@ -1746,24 +1780,20 @@ void RichTextLabel::_notification(int p_what) {
} else {
// Draw loading progress bar.
if ((progress_delay > 0) && (OS::get_singleton()->get_ticks_msec() - loading_started >= (uint64_t)progress_delay)) {
Ref<StyleBox> bg = get_theme_stylebox(SNAME("bg"), SNAME("ProgressBar"));
Ref<StyleBox> fg = get_theme_stylebox(SNAME("fg"), SNAME("ProgressBar"));
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
Vector2 p_size = Vector2(size.width - (theme_cache.normal_style->get_offset().x + vscroll->get_combined_minimum_size().width) * 2, vscroll->get_combined_minimum_size().width);
Vector2 p_pos = Vector2(theme_cache.normal_style->get_offset().x, size.height - theme_cache.normal_style->get_offset().y - vscroll->get_combined_minimum_size().width);
Vector2 p_size = Vector2(size.width - (style->get_offset().x + vscroll->get_combined_minimum_size().width) * 2, vscroll->get_combined_minimum_size().width);
Vector2 p_pos = Vector2(style->get_offset().x, size.height - style->get_offset().y - vscroll->get_combined_minimum_size().width);
draw_style_box(bg, Rect2(p_pos, p_size));
draw_style_box(theme_cache.progress_bg_style, Rect2(p_pos, p_size));
bool right_to_left = is_layout_rtl();
double r = loaded.load();
int mp = fg->get_minimum_size().width;
int mp = theme_cache.progress_fg_style->get_minimum_size().width;
int p = round(r * (p_size.width - mp));
if (right_to_left) {
int p_remaining = round((1.0 - r) * (p_size.width - mp));
draw_style_box(fg, Rect2(p_pos + Point2(p_remaining, 0), Size2(p + fg->get_minimum_size().width, p_size.height)));
draw_style_box(theme_cache.progress_fg_style, Rect2(p_pos + Point2(p_remaining, 0), Size2(p + theme_cache.progress_fg_style->get_minimum_size().width, p_size.height)));
} else {
draw_style_box(fg, Rect2(p_pos, Size2(p + fg->get_minimum_size().width, p_size.height)));
draw_style_box(theme_cache.progress_fg_style, Rect2(p_pos, Size2(p + theme_cache.progress_fg_style->get_minimum_size().width, p_size.height)));
}
}
}
@ -1776,13 +1806,7 @@ void RichTextLabel::_notification(int p_what) {
int to_line = main->first_invalid_line.load();
int from_line = _find_first_line(0, to_line, vofs);
Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
Color base_color = get_theme_color(SNAME("default_color"));
Color outline_color = get_theme_color(SNAME("font_outline_color"));
int outline_size = get_theme_constant(SNAME("outline_size"));
Color font_shadow_color = get_theme_color(SNAME("font_shadow_color"));
int shadow_outline_size = get_theme_constant(SNAME("shadow_outline_size"));
Point2 shadow_ofs(get_theme_constant(SNAME("shadow_offset_x")), get_theme_constant(SNAME("shadow_offset_y")));
Point2 shadow_ofs(theme_cache.shadow_offset_x, theme_cache.shadow_offset_y);
visible_paragraph_count = 0;
visible_line_count = 0;
@ -1794,8 +1818,8 @@ void RichTextLabel::_notification(int p_what) {
MutexLock lock(main->lines[from_line].text_buf->get_mutex());
visible_paragraph_count++;
visible_line_count += _draw_line(main, from_line, ofs, text_rect.size.x, base_color, outline_size, outline_color, font_shadow_color, shadow_outline_size, shadow_ofs, processed_glyphs);
ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
visible_line_count += _draw_line(main, from_line, ofs, text_rect.size.x, theme_cache.default_color, theme_cache.outline_size, theme_cache.font_outline_color, theme_cache.font_shadow_color, theme_cache.shadow_outline_size, shadow_ofs, processed_glyphs);
ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * theme_cache.line_separation;
from_line++;
}
} break;
@ -2003,11 +2027,11 @@ void RichTextLabel::gui_input(const Ref<InputEvent> &p_event) {
handled = true;
}
if (k->is_action("ui_up") && vscroll->is_visible_in_tree()) {
vscroll->set_value(vscroll->get_value() - get_theme_font(SNAME("normal_font"))->get_height(get_theme_font_size(SNAME("normal_font_size"))));
vscroll->set_value(vscroll->get_value() - theme_cache.normal_font->get_height(theme_cache.normal_font_size));
handled = true;
}
if (k->is_action("ui_down") && vscroll->is_visible_in_tree()) {
vscroll->set_value(vscroll->get_value() + get_theme_font(SNAME("normal_font"))->get_height(get_theme_font_size(SNAME("normal_font_size"))));
vscroll->set_value(vscroll->get_value() + theme_cache.normal_font->get_height(theme_cache.normal_font_size));
handled = true;
}
if (k->is_action("ui_home") && vscroll->is_visible_in_tree()) {
@ -2587,14 +2611,12 @@ bool RichTextLabel::_validate_line_caches() {
MutexLock data_lock(data_mutex);
Rect2 text_rect = _get_text_rect();
Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
int base_font_size = get_theme_font_size(SNAME("normal_font_size"));
int ctrl_height = get_size().height;
// Update fonts.
if (main->first_invalid_font_line.load() != (int)main->lines.size()) {
for (int i = main->first_invalid_font_line.load(); i < (int)main->lines.size(); i++) {
_update_line_font(main, i, base_font, base_font_size);
_update_line_font(main, i, theme_cache.normal_font, theme_cache.normal_font_size);
}
main->first_resized_line.store(main->first_invalid_font_line.load());
main->first_invalid_font_line.store(main->lines.size());
@ -2609,7 +2631,7 @@ bool RichTextLabel::_validate_line_caches() {
float total_height = (fi == 0) ? 0 : _calculate_line_vertical_offset(main->lines[fi - 1]);
for (int i = fi; i < (int)main->lines.size(); i++) {
total_height = _resize_line(main, i, base_font, base_font_size, text_rect.get_size().width - scroll_w, total_height);
total_height = _resize_line(main, i, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height);
updating_scroll = true;
bool exceeds = total_height > ctrl_height && scroll_active;
@ -2629,7 +2651,7 @@ bool RichTextLabel::_validate_line_caches() {
total_height = 0;
for (int j = 0; j <= i; j++) {
total_height = _resize_line(main, j, base_font, base_font_size, text_rect.get_size().width - scroll_w, total_height);
total_height = _resize_line(main, j, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height);
main->first_resized_line.store(j);
}
@ -2676,15 +2698,13 @@ void RichTextLabel::_process_line_caches() {
MutexLock data_lock(data_mutex);
Rect2 text_rect = _get_text_rect();
int base_font_size = get_theme_font_size(SNAME("normal_font_size"));
Ref<Font> base_font = get_theme_font(SNAME("normal_font"));
int ctrl_height = get_size().height;
int fi = main->first_invalid_line.load();
int total_chars = (fi == 0) ? 0 : (main->lines[fi].char_offset + main->lines[fi].char_count);
float total_height = (fi == 0) ? 0 : _calculate_line_vertical_offset(main->lines[fi - 1]);
for (int i = fi; i < (int)main->lines.size(); i++) {
total_height = _shape_line(main, i, base_font, base_font_size, text_rect.get_size().width - scroll_w, total_height, &total_chars);
total_height = _shape_line(main, i, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height, &total_chars);
updating_scroll = true;
bool exceeds = total_height > ctrl_height && scroll_active;
if (exceeds != scroll_visible) {
@ -2705,7 +2725,7 @@ void RichTextLabel::_process_line_caches() {
// since scroll was added or removed we need to resize all lines
total_height = 0;
for (int j = 0; j <= i; j++) {
total_height = _resize_line(main, j, base_font, base_font_size, text_rect.get_size().width - scroll_w, total_height);
total_height = _resize_line(main, j, theme_cache.normal_font, theme_cache.normal_font_size, text_rect.get_size().width - scroll_w, total_height);
main->first_invalid_line.store(j);
main->first_resized_line.store(j);
@ -2998,38 +3018,33 @@ void RichTextLabel::push_font(const Ref<Font> &p_font, int p_size) {
}
void RichTextLabel::push_normal() {
Ref<Font> normal_font = get_theme_font(SNAME("normal_font"));
ERR_FAIL_COND(normal_font.is_null());
ERR_FAIL_COND(theme_cache.normal_font.is_null());
push_font(normal_font, get_theme_font_size(SNAME("normal_font_size")));
push_font(theme_cache.normal_font, theme_cache.normal_font_size);
}
void RichTextLabel::push_bold() {
Ref<Font> bold_font = get_theme_font(SNAME("bold_font"));
ERR_FAIL_COND(bold_font.is_null());
ERR_FAIL_COND(theme_cache.bold_font.is_null());
push_font(bold_font, get_theme_font_size(SNAME("bold_font_size")));
push_font(theme_cache.bold_font, theme_cache.bold_font_size);
}
void RichTextLabel::push_bold_italics() {
Ref<Font> bold_italics_font = get_theme_font(SNAME("bold_italics_font"));
ERR_FAIL_COND(bold_italics_font.is_null());
ERR_FAIL_COND(theme_cache.bold_italics_font.is_null());
push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size")));
push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size);
}
void RichTextLabel::push_italics() {
Ref<Font> italics_font = get_theme_font(SNAME("italics_font"));
ERR_FAIL_COND(italics_font.is_null());
ERR_FAIL_COND(theme_cache.italics_font.is_null());
push_font(italics_font, get_theme_font_size(SNAME("italics_font_size")));
push_font(theme_cache.italics_font, theme_cache.italics_font_size);
}
void RichTextLabel::push_mono() {
Ref<Font> mono_font = get_theme_font(SNAME("mono_font"));
ERR_FAIL_COND(mono_font.is_null());
ERR_FAIL_COND(theme_cache.mono_font.is_null());
push_font(mono_font, get_theme_font_size(SNAME("mono_font_size")));
push_font(theme_cache.mono_font, theme_cache.mono_font_size);
}
void RichTextLabel::push_font_size(int p_font_size) {
@ -3476,13 +3491,6 @@ void RichTextLabel::append_text(const String &p_bbcode) {
int pos = 0;
List<String> tag_stack;
Ref<Font> normal_font = get_theme_font(SNAME("normal_font"));
Ref<Font> bold_font = get_theme_font(SNAME("bold_font"));
Ref<Font> italics_font = get_theme_font(SNAME("italics_font"));
Ref<Font> bold_italics_font = get_theme_font(SNAME("bold_italics_font"));
Ref<Font> mono_font = get_theme_font(SNAME("mono_font"));
Color base_color = get_theme_color(SNAME("default_color"));
int indent_level = 0;
@ -3627,9 +3635,9 @@ void RichTextLabel::append_text(const String &p_bbcode) {
//use bold font
in_bold = true;
if (in_italics) {
push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size")));
push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size);
} else {
push_font(bold_font, get_theme_font_size(SNAME("bold_font_size")));
push_font(theme_cache.bold_font, theme_cache.bold_font_size);
}
pos = brk_end + 1;
tag_stack.push_front(tag);
@ -3637,15 +3645,15 @@ void RichTextLabel::append_text(const String &p_bbcode) {
//use italics font
in_italics = true;
if (in_bold) {
push_font(bold_italics_font, get_theme_font_size(SNAME("bold_italics_font_size")));
push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size);
} else {
push_font(italics_font, get_theme_font_size(SNAME("italics_font_size")));
push_font(theme_cache.italics_font, theme_cache.italics_font_size);
}
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag == "code") {
//use monospace font
push_font(mono_font, get_theme_font_size(SNAME("mono_font_size")));
push_font(theme_cache.mono_font, theme_cache.mono_font_size);
pos = brk_end + 1;
tag_stack.push_front(tag);
} else if (tag.begins_with("table=")) {
@ -3930,11 +3938,11 @@ void RichTextLabel::append_text(const String &p_bbcode) {
tag_stack.push_front("hint");
} else if (tag.begins_with("dropcap")) {
Vector<String> subtag = tag.substr(5, tag.length()).split(" ");
int fs = get_theme_font_size(SNAME("normal_font_size")) * 3;
Ref<Font> f = get_theme_font(SNAME("normal_font"));
Color color = get_theme_color(SNAME("default_color"));
Color outline_color = get_theme_color(SNAME("outline_color"));
int outline_size = get_theme_constant(SNAME("outline_size"));
int fs = theme_cache.normal_font_size * 3;
Ref<Font> f = theme_cache.normal_font;
Color color = theme_cache.default_color;
Color outline_color = theme_cache.outline_color;
int outline_size = theme_cache.outline_size;
Rect2 dropcap_margins = Rect2();
for (int i = 0; i < subtag.size(); i++) {
@ -4052,14 +4060,14 @@ void RichTextLabel::append_text(const String &p_bbcode) {
tag_stack.push_front(bbcode_name);
} else if (tag.begins_with("color=")) {
String color_str = tag.substr(6, tag.length());
Color color = Color::from_string(color_str, base_color);
Color color = Color::from_string(color_str, theme_cache.default_color);
push_color(color);
pos = brk_end + 1;
tag_stack.push_front("color");
} else if (tag.begins_with("outline_color=")) {
String color_str = tag.substr(14, tag.length());
Color color = Color::from_string(color_str, base_color);
Color color = Color::from_string(color_str, theme_cache.default_color);
push_outline_color(color);
pos = brk_end + 1;
tag_stack.push_front("outline_color");
@ -4074,7 +4082,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
String fnt_ftr = tag.substr(18, tag.length());
Vector<String> subtag = fnt_ftr.split(",");
if (subtag.size() > 0) {
Ref<Font> font = normal_font;
Ref<Font> font = theme_cache.normal_font;
int font_size = 0;
ItemFont *font_it = _find_font(current);
if (font_it) {
@ -4286,7 +4294,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
} else if (tag.begins_with("bgcolor=")) {
String color_str = tag.substr(8, tag.length());
Color color = Color::from_string(color_str, base_color);
Color color = Color::from_string(color_str, theme_cache.default_color);
push_bgcolor(color);
pos = brk_end + 1;
@ -4294,7 +4302,7 @@ void RichTextLabel::append_text(const String &p_bbcode) {
} else if (tag.begins_with("fgcolor=")) {
String color_str = tag.substr(8, tag.length());
Color color = Color::from_string(color_str, base_color);
Color color = Color::from_string(color_str, theme_cache.default_color);
push_fgcolor(color);
pos = brk_end + 1;
@ -4373,7 +4381,7 @@ void RichTextLabel::scroll_to_line(int p_line) {
if ((line_count <= p_line) && (line_count + main->lines[i].text_buf->get_line_count() >= p_line)) {
float line_offset = 0.f;
for (int j = 0; j < p_line - line_count; j++) {
line_offset += main->lines[i].text_buf->get_line_size(j).y + get_theme_constant(SNAME("line_separation"));
line_offset += main->lines[i].text_buf->get_line_size(j).y + theme_cache.line_separation;
}
vscroll->set_value(main->lines[i].offset.y + line_offset);
return;
@ -4391,7 +4399,7 @@ float RichTextLabel::get_line_offset(int p_line) {
if ((line_count <= p_line) && (p_line <= line_count + main->lines[i].text_buf->get_line_count())) {
float line_offset = 0.f;
for (int j = 0; j < p_line - line_count; j++) {
line_offset += main->lines[i].text_buf->get_line_size(j).y + get_theme_constant(SNAME("line_separation"));
line_offset += main->lines[i].text_buf->get_line_size(j).y + theme_cache.line_separation;
}
return main->lines[i].offset.y + line_offset;
}
@ -4997,7 +5005,7 @@ int RichTextLabel::get_content_height() const {
int to_line = main->first_invalid_line.load();
if (to_line) {
MutexLock lock(main->lines[to_line - 1].text_buf->get_mutex());
total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + main->lines[to_line - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation"));
total_height = main->lines[to_line - 1].offset.y + main->lines[to_line - 1].text_buf->get_size().y + main->lines[to_line - 1].text_buf->get_line_count() * theme_cache.line_separation;
}
return total_height;
}
@ -5367,8 +5375,7 @@ void RichTextLabel::set_fixed_size_to_width(int p_width) {
}
Size2 RichTextLabel::get_minimum_size() const {
Ref<StyleBox> style = get_theme_stylebox(SNAME("normal"));
Size2 size = style->get_minimum_size();
Size2 size = theme_cache.normal_style->get_minimum_size();
if (fixed_width != -1) {
size.x += fixed_width;

View file

@ -83,6 +83,7 @@ public:
};
protected:
virtual void _update_theme_item_cache() override;
void _notification(int p_what);
static void _bind_methods();
@ -512,6 +513,46 @@ private:
bool fit_content_height = false;
struct ThemeCache {
Ref<StyleBox> normal_style;
Ref<StyleBox> focus_style;
Ref<StyleBox> progress_bg_style;
Ref<StyleBox> progress_fg_style;
int line_separation;
Ref<Font> normal_font;
int normal_font_size;
Color default_color;
Color font_selected_color;
Color selection_color;
Color font_outline_color;
Color font_shadow_color;
int shadow_outline_size;
int shadow_offset_x;
int shadow_offset_y;
int outline_size;
Color outline_color;
Ref<Font> bold_font;
int bold_font_size;
Ref<Font> bold_italics_font;
int bold_italics_font_size;
Ref<Font> italics_font;
int italics_font_size;
Ref<Font> mono_font;
int mono_font_size;
int table_h_separation;
int table_v_separation;
Color table_odd_row_bg;
Color table_even_row_bg;
Color table_border;
float base_scale = 1.0;
} theme_cache;
public:
String get_parsed_text() const;
void add_text(const String &p_text);