Bind remaining theme properties to their respective classes

This adds binds for GraphEdit/GraphElement/GraphNode, which were
skipped before due to a rework. This also adds binds for Window,
which was skipped before due to a complicated code organization.

Also adds theme cache entries/direct cache access to a few places
that previously missed it. Some theme properties are now exposed
to other classes via friendships or public getters for convenience.

This removes all string-based theme access from scene/ classes.
This commit is contained in:
Yuri Sizov 2023-09-12 15:01:42 +02:00
parent 98b50eb308
commit fe000277ea
26 changed files with 356 additions and 189 deletions

View file

@ -2399,6 +2399,19 @@ void CodeEdit::set_symbol_lookup_word_as_valid(bool p_valid) {
}
}
/* Visual */
Color CodeEdit::_get_brace_mismatch_color() const {
return theme_cache.brace_mismatch_color;
}
Color CodeEdit::_get_code_folding_color() const {
return theme_cache.code_folding_color;
}
Ref<Texture2D> CodeEdit::_get_folded_eol_icon() const {
return theme_cache.folded_eol_icon;
}
void CodeEdit::_bind_methods() {
/* Indent management */
ClassDB::bind_method(D_METHOD("set_indent_size", "size"), &CodeEdit::set_indent_size);
@ -2644,7 +2657,7 @@ void CodeEdit::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, CodeEdit, folded_eol_icon);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, CodeEdit, breakpoint_color);
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_COLOR, CodeEdit, breakpoint_icon, "breakpoint");
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, CodeEdit, breakpoint_icon, "breakpoint");
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, CodeEdit, bookmark_color);
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, CodeEdit, bookmark_icon, "bookmark");
@ -2677,6 +2690,8 @@ void CodeEdit::_bind_methods() {
/* Other visuals */
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, CodeEdit, style_normal, "normal");
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, CodeEdit, brace_mismatch_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, CodeEdit, font);
BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, CodeEdit, font_size);

View file

@ -278,11 +278,17 @@ private:
/* Other visuals */
Ref<StyleBox> style_normal;
Color brace_mismatch_color;
Ref<Font> font;
int font_size = 16;
int line_spacing = 1;
} theme_cache;
virtual Color _get_brace_mismatch_color() const override;
virtual Color _get_code_folding_color() const override;
virtual Ref<Texture2D> _get_folded_eol_icon() const override;
/* Callbacks */
int lines_edited_changed = 0;
int lines_edited_from = -1;

View file

@ -73,10 +73,10 @@ void ColorModeRGB::slider_draw(int p_which) {
Color left_color;
Color right_color;
Color color = color_picker->get_pick_color();
const real_t margin = 16 * color_picker->get_theme_default_base_scale();
const real_t margin = 16 * color_picker->theme_cache.base_scale;
if (p_which == ColorPicker::SLIDER_COUNT) {
slider->draw_texture_rect(color_picker->get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, 0), Size2(size.x, margin)), true);
slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(0, 0), Size2(size.x, margin)), true);
left_color = color;
left_color.a = 0;
@ -168,10 +168,10 @@ void ColorModeHSV::slider_draw(int p_which) {
Color left_color;
Color right_color;
Color color = color_picker->get_pick_color();
const real_t margin = 16 * color_picker->get_theme_default_base_scale();
const real_t margin = 16 * color_picker->theme_cache.base_scale;
if (p_which == ColorPicker::SLIDER_COUNT) {
slider->draw_texture_rect(color_picker->get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, 0), Size2(size.x, margin)), true);
slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(0, 0), Size2(size.x, margin)), true);
left_color = color;
left_color.a = 0;
@ -204,7 +204,7 @@ void ColorModeHSV::slider_draw(int p_which) {
slider->draw_polygon(pos, col);
if (p_which == 0) { // H
Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
Ref<Texture2D> hue = color_picker->theme_cache.color_hue;
slider->draw_texture_rect(hue, Rect2(Vector2(), Vector2(size.x, margin)), false, Color::from_hsv(0, 0, color.get_v(), color.get_s()));
}
}
@ -243,10 +243,10 @@ void ColorModeRAW::slider_draw(int p_which) {
Color left_color;
Color right_color;
Color color = color_picker->get_pick_color();
const real_t margin = 16 * color_picker->get_theme_default_base_scale();
const real_t margin = 16 * color_picker->theme_cache.base_scale;
if (p_which == ColorPicker::SLIDER_COUNT) {
slider->draw_texture_rect(color_picker->get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, 0), Size2(size.x, margin)), true);
slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(0, 0), Size2(size.x, margin)), true);
left_color = color;
left_color.a = 0;
@ -334,7 +334,7 @@ Color ColorModeOKHSL::get_color() const {
void ColorModeOKHSL::slider_draw(int p_which) {
HSlider *slider = color_picker->get_slider(p_which);
Size2 size = slider->get_size();
const real_t margin = 16 * color_picker->get_theme_default_base_scale();
const real_t margin = 16 * color_picker->theme_cache.base_scale;
Vector<Vector2> pos;
Vector<Color> col;
@ -370,7 +370,7 @@ void ColorModeOKHSL::slider_draw(int p_which) {
col.resize(4);
if (p_which == ColorPicker::SLIDER_COUNT) {
slider->draw_texture_rect(color_picker->get_theme_icon(SNAME("sample_bg"), SNAME("ColorPicker")), Rect2(Point2(0, 0), Size2(size.x, margin)), true);
slider->draw_texture_rect(color_picker->theme_cache.sample_bg, Rect2(Point2(0, 0), Size2(size.x, margin)), true);
left_color = color;
left_color.a = 0;
@ -399,7 +399,7 @@ void ColorModeOKHSL::slider_draw(int p_which) {
slider->draw_polygon(pos, col);
if (p_which == 0) { // H
Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_okhsl_hue"), SNAME("ColorPicker"));
Ref<Texture2D> hue = color_picker->theme_cache.color_okhsl_hue;
slider->draw_texture_rect(hue, Rect2(Vector2(), Vector2(size.x, margin)), false, Color::from_hsv(0, 0, color.get_ok_hsl_l() * 2.0, color.get_ok_hsl_s()));
return;
}

View file

@ -673,7 +673,7 @@ ColorPicker::PickerShapeType ColorPicker::get_picker_shape() const {
}
inline int ColorPicker::_get_preset_size() {
return (int(get_minimum_size().width) - (preset_container->get_theme_constant(SNAME("h_separation")) * (PRESET_COLUMN_COUNT - 1))) / PRESET_COLUMN_COUNT;
return (int(get_minimum_size().width) - (preset_container->get_h_separation() * (PRESET_COLUMN_COUNT - 1))) / PRESET_COLUMN_COUNT;
}
void ColorPicker::_add_preset_button(int p_size, const Color &p_color) {
@ -997,7 +997,7 @@ void ColorPicker::_sample_draw() {
const Rect2 rect_old = Rect2(Point2(), Size2(sample->get_size().width * 0.5, sample->get_size().height * 0.95));
if (old_color.a < 1.0) {
sample->draw_texture_rect(theme_cache.sample_background_icon, rect_old, true);
sample->draw_texture_rect(theme_cache.sample_bg, rect_old, true);
}
sample->draw_rect(rect_old, old_color);
@ -1011,7 +1011,7 @@ void ColorPicker::_sample_draw() {
}
if (color.a < 1.0) {
sample->draw_texture_rect(theme_cache.sample_background_icon, rect_new, true);
sample->draw_texture_rect(theme_cache.sample_bg, rect_new, true);
}
sample->draw_rect(rect_new, color);
@ -1125,7 +1125,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
} else if (p_which == 1) {
if (actual_shape == SHAPE_HSV_RECTANGLE) {
c->draw_set_transform(Point2(), -Math_PI / 2, Size2(c->get_size().x, -c->get_size().y));
c->draw_texture_rect(theme_cache.color_hue_icon, Rect2(Point2(), Size2(1, 1)));
c->draw_texture_rect(theme_cache.color_hue, Rect2(Point2(), Size2(1, 1)));
c->draw_set_transform(Point2(), 0, Size2(1, 1));
int y = c->get_size().y - c->get_size().y * (1.0 - h);
Color col;
@ -1703,10 +1703,11 @@ void ColorPicker::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, shape_circle);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, bar_arrow);
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ColorPicker, sample_background_icon, "sample_bg");
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, sample_bg);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, overbright_indicator);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, picker_cursor);
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, ColorPicker, color_hue_icon, "color_hue");
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, color_hue);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ColorPicker, color_okhsl_hue);
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, ColorPicker, mode_button_normal, "tab_unselected", "TabContainer");
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_STYLEBOX, ColorPicker, mode_button_pressed, "tab_selected", "TabContainer");

View file

@ -81,6 +81,12 @@ public:
class ColorPicker : public VBoxContainer {
GDCLASS(ColorPicker, VBoxContainer);
// These classes poke into theme items for their internal logic.
friend class ColorModeRGB;
friend class ColorModeHSV;
friend class ColorModeRAW;
friend class ColorModeOKHSL;
public:
enum ColorModeType {
MODE_RGB,
@ -229,10 +235,11 @@ private:
Ref<Texture2D> shape_circle;
Ref<Texture2D> bar_arrow;
Ref<Texture2D> sample_background_icon;
Ref<Texture2D> sample_bg;
Ref<Texture2D> overbright_indicator;
Ref<Texture2D> picker_cursor;
Ref<Texture2D> color_hue_icon;
Ref<Texture2D> color_hue;
Ref<Texture2D> color_okhsl_hue;
/* Mode buttons */
Ref<StyleBox> mode_button_normal;

View file

@ -38,6 +38,7 @@
#include "scene/gui/graph_edit_arranger.h"
#include "scene/gui/view_panner.h"
#include "scene/resources/style_box_flat.h"
#include "scene/theme/theme_db.h"
constexpr int MINIMAP_OFFSET = 12;
constexpr int MINIMAP_PADDING = 5;
@ -56,23 +57,8 @@ GraphEditFilter::GraphEditFilter(GraphEdit *p_edit) {
ge = p_edit;
}
GraphEditMinimap::GraphEditMinimap(GraphEdit *p_edit) {
ge = p_edit;
graph_proportions = Vector2(1, 1);
graph_padding = Vector2(0, 0);
camera_position = Vector2(100, 50);
camera_size = Vector2(200, 200);
minimap_padding = Vector2(MINIMAP_PADDING, MINIMAP_PADDING);
minimap_offset = minimap_padding + _convert_from_graph_position(graph_padding);
is_pressing = false;
is_resizing = false;
}
Control::CursorShape GraphEditMinimap::get_cursor_shape(const Point2 &p_pos) const {
Ref<Texture2D> resizer = get_theme_icon(SNAME("resizer"));
if (is_resizing || (p_pos.x < resizer->get_width() && p_pos.y < resizer->get_height())) {
if (is_resizing || (p_pos.x < theme_cache.resizer->get_width() && p_pos.y < theme_cache.resizer->get_height())) {
return CURSOR_FDIAGSIZE;
}
@ -172,8 +158,7 @@ void GraphEditMinimap::gui_input(const Ref<InputEvent> &p_ev) {
if (mb->is_pressed()) {
is_pressing = true;
Ref<Texture2D> resizer = get_theme_icon(SNAME("resizer"));
Rect2 resizer_hitbox = Rect2(Point2(), resizer->get_size());
Rect2 resizer_hitbox = Rect2(Point2(), theme_cache.resizer->get_size());
if (resizer_hitbox.has_point(mb->get_position())) {
is_resizing = true;
} else {
@ -207,6 +192,21 @@ void GraphEditMinimap::_adjust_graph_scroll(const Vector2 &p_offset) {
ge->set_scroll_offset(p_offset + graph_offset - camera_size / 2);
}
void GraphEditMinimap::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, GraphEditMinimap, panel);
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, GraphEditMinimap, node_style, "node");
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, GraphEditMinimap, camera_style, "camera");
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphEditMinimap, resizer);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, GraphEditMinimap, resizer_color);
}
GraphEditMinimap::GraphEditMinimap(GraphEdit *p_edit) {
ge = p_edit;
minimap_padding = Vector2(MINIMAP_PADDING, MINIMAP_PADDING);
minimap_offset = minimap_padding + _convert_from_graph_position(graph_padding);
}
Control::CursorShape GraphEdit::get_cursor_shape(const Point2 &p_pos) const {
if (moving_selection) {
return CURSOR_MOVE;
@ -493,22 +493,25 @@ void GraphEdit::remove_child_notify(Node *p_child) {
}
}
void GraphEdit::_update_theme_item_cache() {
Control::_update_theme_item_cache();
theme_cache.base_scale = get_theme_default_base_scale();
}
void GraphEdit::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
port_hotzone_inner_extent = get_theme_constant("port_hotzone_inner_extent");
port_hotzone_outer_extent = get_theme_constant("port_hotzone_outer_extent");
zoom_minus_button->set_icon(theme_cache.zoom_out);
zoom_reset_button->set_icon(theme_cache.zoom_reset);
zoom_plus_button->set_icon(theme_cache.zoom_in);
zoom_minus_button->set_icon(get_theme_icon(SNAME("zoom_out")));
zoom_reset_button->set_icon(get_theme_icon(SNAME("zoom_reset")));
zoom_plus_button->set_icon(get_theme_icon(SNAME("zoom_in")));
toggle_snapping_button->set_icon(theme_cache.snapping_toggle);
show_grid_button->set_icon(theme_cache.grid_toggle);
minimap_button->set_icon(theme_cache.minimap_toggle);
layout_button->set_icon(theme_cache.layout);
toggle_snapping_button->set_icon(get_theme_icon(SNAME("snapping_toggle")));
show_grid_button->set_icon(get_theme_icon(SNAME("grid_toggle")));
minimap_button->set_icon(get_theme_icon(SNAME("minimap_toggle")));
layout_button->set_icon(get_theme_icon(SNAME("layout")));
zoom_label->set_custom_minimum_size(Size2(48, 0) * get_theme_default_base_scale());
zoom_label->set_custom_minimum_size(Size2(48, 0) * theme_cache.base_scale);
} break;
case NOTIFICATION_READY: {
@ -528,7 +531,7 @@ void GraphEdit::_notification(int p_what) {
case NOTIFICATION_DRAW: {
// Draw background fill.
draw_style_box(get_theme_stylebox(SNAME("panel")), Rect2(Point2(), get_size()));
draw_style_box(theme_cache.panel, Rect2(Point2(), get_size()));
// Draw background grid.
if (show_grid) {
@ -538,16 +541,13 @@ void GraphEdit::_notification(int p_what) {
Point2i from_pos = (offset / float(snapping_distance)).floor();
Point2i len = (size / float(snapping_distance)).floor() + Vector2(1, 1);
Color grid_minor = get_theme_color(SNAME("grid_minor"));
Color grid_major = get_theme_color(SNAME("grid_major"));
for (int i = from_pos.x; i < from_pos.x + len.x; i++) {
Color color;
if (ABS(i) % GRID_MINOR_STEPS_PER_MAJOR_LINE == 0) {
color = grid_major;
color = theme_cache.grid_major;
} else {
color = grid_minor;
color = theme_cache.grid_minor;
}
float base_offset = i * snapping_distance * zoom - offset.x * zoom;
@ -558,9 +558,9 @@ void GraphEdit::_notification(int p_what) {
Color color;
if (ABS(i) % GRID_MINOR_STEPS_PER_MAJOR_LINE == 0) {
color = grid_major;
color = theme_cache.grid_major;
} else {
color = grid_minor;
color = theme_cache.grid_minor;
}
float base_offset = i * snapping_distance * zoom - offset.y * zoom;
@ -578,14 +578,14 @@ void GraphEdit::_notification(int p_what) {
}
bool GraphEdit::_filter_input(const Point2 &p_point) {
Ref<Texture2D> port_icon = get_theme_icon(SNAME("port"), SNAME("GraphNode"));
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *graph_node = Object::cast_to<GraphNode>(get_child(i));
if (!graph_node || !graph_node->is_visible_in_tree()) {
continue;
}
Ref<Texture2D> port_icon = graph_node->theme_cache.port;
for (int j = 0; j < graph_node->get_input_port_count(); j++) {
Vector2i port_size = Vector2i(port_icon->get_width(), port_icon->get_height());
@ -620,8 +620,6 @@ bool GraphEdit::_filter_input(const Point2 &p_point) {
void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventMouseButton> mb = p_ev;
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed()) {
Ref<Texture2D> port_icon = get_theme_icon(SNAME("port"), SNAME("GraphNode"));
connecting_valid = false;
click_pos = mb->get_position() / zoom;
for (int i = get_child_count() - 1; i >= 0; i--) {
@ -630,6 +628,8 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
continue;
}
Ref<Texture2D> port_icon = graph_node->theme_cache.port;
for (int j = 0; j < graph_node->get_output_port_count(); j++) {
Vector2 pos = graph_node->get_output_port_position(j) * zoom + graph_node->get_position();
Vector2i port_size = Vector2i(port_icon->get_width(), port_icon->get_height());
@ -756,12 +756,13 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
if (connecting_valid) {
Vector2 mpos = mm->get_position() / zoom;
for (int i = get_child_count() - 1; i >= 0; i--) {
Ref<Texture2D> port_icon = get_theme_icon(SNAME("port"), SNAME("GraphNode"));
GraphNode *graph_node = Object::cast_to<GraphNode>(get_child(i));
if (!graph_node || !graph_node->is_visible_in_tree()) {
continue;
}
Ref<Texture2D> port_icon = graph_node->theme_cache.port;
if (!connecting_out) {
for (int j = 0; j < graph_node->get_output_port_count(); j++) {
Vector2 pos = graph_node->get_output_port_position(j) * zoom + graph_node->get_position();
@ -877,7 +878,7 @@ bool GraphEdit::is_in_input_hotzone(GraphNode *p_graph_node, int p_port_idx, con
bool GraphEdit::is_in_output_hotzone(GraphNode *p_graph_node, int p_port_idx, const Vector2 &p_mouse_pos, const Vector2i &p_port_size) {
if (p_graph_node->is_resizable()) {
Ref<Texture2D> resizer = p_graph_node->get_theme_icon(SNAME("resizer"));
Ref<Texture2D> resizer = p_graph_node->theme_cache.resizer;
Rect2 resizer_rect = Rect2(p_graph_node->get_position() / zoom + p_graph_node->get_size() - resizer->get_size(), resizer->get_size());
if (resizer_rect.has_point(p_mouse_pos)) {
return false;
@ -895,9 +896,9 @@ bool GraphEdit::is_in_output_hotzone(GraphNode *p_graph_node, int p_port_idx, co
bool GraphEdit::is_in_port_hotzone(const Vector2 &p_pos, const Vector2 &p_mouse_pos, const Vector2i &p_port_size, bool p_left) {
Rect2 hotzone = Rect2(
p_pos.x - (p_left ? port_hotzone_outer_extent : port_hotzone_inner_extent),
p_pos.x - (p_left ? theme_cache.port_hotzone_outer_extent : theme_cache.port_hotzone_inner_extent),
p_pos.y - p_port_size.height / 2.0,
port_hotzone_inner_extent + port_hotzone_outer_extent,
theme_cache.port_hotzone_inner_extent + theme_cache.port_hotzone_outer_extent,
p_port_size.height);
if (!hotzone.has_point(p_mouse_pos)) {
@ -965,12 +966,10 @@ void GraphEdit::_draw_connection_line(CanvasItem *p_where, const Vector2 &p_from
}
// Thickness below 0.5 doesn't look good on the graph or its minimap.
p_where->draw_polyline_colors(scaled_points, colors, MAX(0.5, Math::floor(p_width * get_theme_default_base_scale())), lines_antialiased);
p_where->draw_polyline_colors(scaled_points, colors, MAX(0.5, Math::floor(p_width * theme_cache.base_scale)), lines_antialiased);
}
void GraphEdit::_connections_layer_draw() {
Color activity_color = get_theme_color(SNAME("activity"));
// Draw connections.
List<List<Connection>::Element *> to_erase;
for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
@ -998,8 +997,8 @@ void GraphEdit::_connections_layer_draw() {
Color tocolor = gnode_to->get_input_port_color(c.to_port);
if (c.activity > 0) {
color = color.lerp(activity_color, c.activity);
tocolor = tocolor.lerp(activity_color, c.activity);
color = color.lerp(theme_cache.activity_color, c.activity);
tocolor = tocolor.lerp(theme_cache.activity_color, c.activity);
}
_draw_connection_line(connections_layer, frompos, topos, color, tocolor, lines_thickness, zoom);
}
@ -1042,8 +1041,8 @@ void GraphEdit::_top_layer_draw() {
}
if (box_selecting) {
top_layer->draw_rect(box_selecting_rect, get_theme_color(SNAME("selection_fill")));
top_layer->draw_rect(box_selecting_rect, get_theme_color(SNAME("selection_stroke")), false);
top_layer->draw_rect(box_selecting_rect, theme_cache.selection_fill);
top_layer->draw_rect(box_selecting_rect, theme_cache.selection_stroke, false);
}
}
@ -1056,7 +1055,7 @@ void GraphEdit::_minimap_draw() {
// Draw the minimap background.
Rect2 minimap_rect = Rect2(Point2(), minimap->get_size());
minimap->draw_style_box(minimap->get_theme_stylebox(SNAME("panel")), minimap_rect);
minimap->draw_style_box(minimap->theme_cache.panel, minimap_rect);
Vector2 graph_offset = minimap->_get_graph_offset();
Vector2 minimap_offset = minimap->minimap_offset;
@ -1072,10 +1071,10 @@ void GraphEdit::_minimap_draw() {
Vector2 node_size = minimap->_convert_from_graph_position(graph_node->get_size() * zoom);
Rect2 node_rect = Rect2(node_position, node_size);
Ref<StyleBoxFlat> sb_minimap = minimap->get_theme_stylebox(SNAME("node"))->duplicate();
Ref<StyleBoxFlat> sb_minimap = minimap->theme_cache.node_style->duplicate();
// Override default values with colors provided by the GraphNode's stylebox, if possible.
Ref<StyleBoxFlat> sb_frame = graph_node->get_theme_stylebox(graph_node->is_selected() ? "panel_selected" : "panel");
Ref<StyleBoxFlat> sb_frame = graph_node->is_selected() ? graph_node->theme_cache.panel_selected : graph_node->theme_cache.panel;
if (sb_frame.is_valid()) {
Color node_color = sb_frame->get_bg_color();
sb_minimap->set_bg_color(node_color);
@ -1085,7 +1084,6 @@ void GraphEdit::_minimap_draw() {
}
// Draw node connections.
Color activity_color = get_theme_color(SNAME("activity"));
for (const Connection &E : connections) {
Node *from = get_node(NodePath(E.from_node));
GraphNode *graph_node_from = Object::cast_to<GraphNode>(from);
@ -1107,19 +1105,19 @@ void GraphEdit::_minimap_draw() {
Color to_color = graph_node_to->get_input_port_color(E.to_port);
if (E.activity > 0) {
from_color = from_color.lerp(activity_color, E.activity);
to_color = to_color.lerp(activity_color, E.activity);
from_color = from_color.lerp(theme_cache.activity_color, E.activity);
to_color = to_color.lerp(theme_cache.activity_color, E.activity);
}
_draw_connection_line(minimap, from_position, to_position, from_color, to_color, 0.5, minimap->_convert_from_graph_position(Vector2(zoom, zoom)).length());
}
// Draw the "camera" viewport.
Rect2 camera_rect = minimap->get_camera_rect();
minimap->draw_style_box(minimap->get_theme_stylebox(SNAME("camera")), camera_rect);
minimap->draw_style_box(minimap->theme_cache.camera_style, camera_rect);
// Draw the resizer control.
Ref<Texture2D> resizer = minimap->get_theme_icon(SNAME("resizer"));
Color resizer_color = minimap->get_theme_color(SNAME("resizer_color"));
Ref<Texture2D> resizer = minimap->theme_cache.resizer;
Color resizer_color = minimap->theme_cache.resizer_color;
minimap->draw_texture(resizer, Point2(), resizer_color);
}
@ -1909,6 +1907,26 @@ void GraphEdit::_bind_methods() {
BIND_ENUM_CONSTANT(SCROLL_ZOOMS);
BIND_ENUM_CONSTANT(SCROLL_PANS);
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, GraphEdit, panel);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, GraphEdit, grid_major);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, GraphEdit, grid_minor);
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_COLOR, GraphEdit, activity_color, "activity");
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, GraphEdit, selection_fill);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, GraphEdit, selection_stroke);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphEdit, zoom_in);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphEdit, zoom_out);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphEdit, zoom_reset);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphEdit, snapping_toggle);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphEdit, grid_toggle);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphEdit, minimap_toggle);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphEdit, layout);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, GraphEdit, port_hotzone_inner_extent);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, GraphEdit, port_hotzone_outer_extent);
}
GraphEdit::GraphEdit() {

View file

@ -47,6 +47,7 @@ class GraphEditFilter : public Control {
friend class GraphEdit;
friend class GraphEditMinimap;
GraphEdit *ge = nullptr;
virtual bool has_point(const Point2 &p_point) const override;
@ -63,24 +64,24 @@ class GraphEditMinimap : public Control {
GraphEdit *ge = nullptr;
public:
GraphEditMinimap(GraphEdit *p_edit);
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
void update_minimap();
Rect2 get_camera_rect();
private:
Vector2 minimap_padding;
Vector2 minimap_offset;
Vector2 graph_proportions;
Vector2 graph_padding;
Vector2 camera_position;
Vector2 camera_size;
Vector2 graph_proportions = Vector2(1, 1);
Vector2 graph_padding = Vector2(0, 0);
Vector2 camera_position = Vector2(100, 50);
Vector2 camera_size = Vector2(200, 200);
bool is_pressing;
bool is_resizing;
bool is_pressing = false;
bool is_resizing = false;
struct ThemeCache {
Ref<StyleBox> panel;
Ref<StyleBox> node_style;
Ref<StyleBox> camera_style;
Ref<Texture2D> resizer;
Color resizer_color;
} theme_cache;
Vector2 _get_render_size();
Vector2 _get_graph_offset();
@ -92,6 +93,17 @@ private:
virtual void gui_input(const Ref<InputEvent> &p_ev) override;
void _adjust_graph_scroll(const Vector2 &p_offset);
protected:
static void _bind_methods();
public:
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
void update_minimap();
Rect2 get_camera_rect();
GraphEditMinimap(GraphEdit *p_edit);
};
class GraphEdit : public Control {
@ -150,9 +162,6 @@ private:
HScrollBar *h_scrollbar = nullptr;
VScrollBar *v_scrollbar = nullptr;
float port_hotzone_inner_extent = 0.0;
float port_hotzone_outer_extent = 0.0;
Ref<ViewPanner> panner;
bool warped_panning = true;
@ -218,7 +227,30 @@ private:
HashSet<int> valid_left_disconnect_types;
HashSet<int> valid_right_disconnect_types;
void _scroll_callback(Vector2 p_scroll_vec, bool p_alt);
struct ThemeCache {
float base_scale = 1.0;
Ref<StyleBox> panel;
Color grid_major;
Color grid_minor;
Color activity_color;
Color selection_fill;
Color selection_stroke;
Ref<Texture2D> zoom_in;
Ref<Texture2D> zoom_out;
Ref<Texture2D> zoom_reset;
Ref<Texture2D> snapping_toggle;
Ref<Texture2D> grid_toggle;
Ref<Texture2D> minimap_toggle;
Ref<Texture2D> layout;
float port_hotzone_inner_extent = 0.0;
float port_hotzone_outer_extent = 0.0;
} theme_cache;
void _pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event);
void _zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event);
@ -262,12 +294,13 @@ private:
bool _check_clickable_control(Control *p_control, const Vector2 &r_mouse_pos, const Vector2 &p_offset);
protected:
static void _bind_methods();
virtual void _update_theme_item_cache() override;
virtual void add_child_notify(Node *p_child) override;
virtual void remove_child_notify(Node *p_child) override;
void _notification(int p_what);
static void _bind_methods();
virtual bool is_in_input_hotzone(GraphNode *p_graph_node, int p_port_idx, const Vector2 &p_mouse_pos, const Vector2i &p_port_size);
virtual bool is_in_output_hotzone(GraphNode *p_graph_node, int p_port_idx, const Vector2 &p_mouse_pos, const Vector2i &p_port_size);

View file

@ -32,6 +32,7 @@
#include "core/string/translation.h"
#include "scene/gui/graph_edit.h"
#include "scene/theme/theme_db.h"
#ifdef TOOLS_ENABLED
void GraphElement::_edit_set_position(const Point2 &p_position) {
@ -154,9 +155,7 @@ void GraphElement::gui_input(const Ref<InputEvent> &p_ev) {
if (mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) {
Vector2 mpos = mb->get_position();
Ref<Texture2D> resizer = get_theme_icon(SNAME("resizer"));
if (resizable && mpos.x > get_size().x - resizer->get_width() && mpos.y > get_size().y - resizer->get_height()) {
if (resizable && mpos.x > get_size().x - theme_cache.resizer->get_width() && mpos.y > get_size().y - theme_cache.resizer->get_height()) {
resizing = true;
resizing_from = mpos;
resizing_from_size = get_size();
@ -241,4 +240,6 @@ void GraphElement::_bind_methods() {
ADD_SIGNAL(MethodInfo("raise_request"));
ADD_SIGNAL(MethodInfo("close_request"));
ADD_SIGNAL(MethodInfo("resize_request", PropertyInfo(Variant::VECTOR2, "new_minsize")));
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphElement, resizer);
}

View file

@ -49,6 +49,10 @@ protected:
Vector2 position_offset;
struct ThemeCache {
Ref<Texture2D> resizer;
} theme_cache;
#ifdef TOOLS_ENABLED
void _edit_set_position(const Point2 &p_position) override;
#endif

View file

@ -33,6 +33,7 @@
#include "core/string/translation.h"
#include "scene/gui/box_container.h"
#include "scene/gui/label.h"
#include "scene/theme/theme_db.h"
bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
@ -151,8 +152,8 @@ void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const {
void GraphNode::_resort() {
Size2 new_size = get_size();
Ref<StyleBox> sb_panel = get_theme_stylebox(SNAME("panel"));
Ref<StyleBox> sb_titlebar = get_theme_stylebox(SNAME("titlebar"));
Ref<StyleBox> sb_panel = theme_cache.panel;
Ref<StyleBox> sb_titlebar = theme_cache.titlebar;
// Resort titlebar first.
Size2 titlebar_size = Size2(new_size.width, titlebar_hbox->get_size().height);
@ -164,8 +165,8 @@ void GraphNode::_resort() {
Size2i titlebar_min_size = titlebar_hbox->get_combined_minimum_size();
// First pass, determine minimum size AND amount of stretchable elements.
Ref<StyleBox> sb_slot = get_theme_stylebox(SNAME("slot"));
int separation = get_theme_constant(SNAME("separation"));
Ref<StyleBox> sb_slot = theme_cache.slot;
int separation = theme_cache.separation;
int children_count = 0;
int stretch_min = 0;
@ -300,7 +301,7 @@ void GraphNode::draw_port(int p_slot_index, Point2i p_pos, bool p_left, const Co
Point2 icon_offset;
if (!port_icon.is_valid()) {
port_icon = get_theme_icon(SNAME("port"));
port_icon = theme_cache.port;
}
icon_offset = -port_icon->get_size() * 0.5;
@ -311,19 +312,15 @@ void GraphNode::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
// Used for layout calculations.
Ref<StyleBox> sb_panel = get_theme_stylebox(SNAME("panel"));
Ref<StyleBox> sb_titlebar = get_theme_stylebox(SNAME("titlebar"));
Ref<StyleBox> sb_panel = theme_cache.panel;
Ref<StyleBox> sb_titlebar = theme_cache.titlebar;
// Used for drawing.
Ref<StyleBox> sb_to_draw_panel = get_theme_stylebox(selected ? SNAME("panel_selected") : SNAME("panel"));
Ref<StyleBox> sb_to_draw_titlebar = get_theme_stylebox(selected ? SNAME("titlebar_selected") : SNAME("titlebar"));
Ref<StyleBox> sb_to_draw_panel = selected ? theme_cache.panel_selected : theme_cache.panel;
Ref<StyleBox> sb_to_draw_titlebar = selected ? theme_cache.titlebar_selected : theme_cache.titlebar;
Ref<StyleBox> sb_slot = get_theme_stylebox(SNAME("slot"));
Ref<StyleBox> sb_slot = theme_cache.slot;
int port_h_offset = get_theme_constant(SNAME("port_h_offset"));
Ref<Texture2D> resizer_icon = get_theme_icon(SNAME("resizer"));
Color resizer_color = get_theme_color(SNAME("resizer_color"));
int port_h_offset = theme_cache.port_h_offset;
Rect2 titlebar_rect(Point2(), titlebar_hbox->get_size() + sb_titlebar->get_minimum_size());
Size2 body_size = get_size();
@ -377,7 +374,7 @@ void GraphNode::_notification(int p_what) {
}
if (resizable) {
draw_texture(resizer_icon, get_size() - resizer_icon->get_size(), resizer_color);
draw_texture(theme_cache.resizer, get_size() - theme_cache.resizer->get_size(), theme_cache.resizer_color);
}
} break;
}
@ -566,11 +563,11 @@ void GraphNode::set_slot_draw_stylebox(int p_slot_index, bool p_enable) {
}
Size2 GraphNode::get_minimum_size() const {
Ref<StyleBox> sb_panel = get_theme_stylebox(SNAME("panel"));
Ref<StyleBox> sb_titlebar = get_theme_stylebox(SNAME("titlebar"));
Ref<StyleBox> sb_slot = get_theme_stylebox(SNAME("slot"));
Ref<StyleBox> sb_panel = theme_cache.panel;
Ref<StyleBox> sb_titlebar = theme_cache.titlebar;
Ref<StyleBox> sb_slot = theme_cache.slot;
int separation = get_theme_constant(SNAME("separation"));
int separation = theme_cache.separation;
Size2 minsize = titlebar_hbox->get_minimum_size() + sb_titlebar->get_minimum_size();
for (int i = 0; i < get_child_count(false); i++) {
@ -599,11 +596,11 @@ Size2 GraphNode::get_minimum_size() const {
}
void GraphNode::_port_pos_update() {
int edgeofs = get_theme_constant(SNAME("port_h_offset"));
int separation = get_theme_constant(SNAME("separation"));
int edgeofs = theme_cache.port_h_offset;
int separation = theme_cache.separation;
Ref<StyleBox> sb_panel = get_theme_stylebox(SNAME("panel"));
Ref<StyleBox> sb_titlebar = get_theme_stylebox(SNAME("titlebar"));
Ref<StyleBox> sb_panel = theme_cache.panel;
Ref<StyleBox> sb_titlebar = theme_cache.titlebar;
left_port_cache.clear();
right_port_cache.clear();
@ -754,9 +751,7 @@ HBoxContainer *GraphNode::get_titlebar_hbox() {
Control::CursorShape GraphNode::get_cursor_shape(const Point2 &p_pos) const {
if (resizable) {
Ref<Texture2D> resizer = get_theme_icon(SNAME("resizer"));
if (resizing || (p_pos.x > get_size().x - resizer->get_width() && p_pos.y > get_size().y - resizer->get_height())) {
if (resizing || (p_pos.x > get_size().x - theme_cache.resizer->get_width() && p_pos.y > get_size().y - theme_cache.resizer->get_height())) {
return CURSOR_FDIAGSIZE;
}
}
@ -830,6 +825,19 @@ void GraphNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
ADD_SIGNAL(MethodInfo("slot_updated", PropertyInfo(Variant::INT, "slot_index")));
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, GraphNode, panel);
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, GraphNode, panel_selected);
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, GraphNode, titlebar);
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, GraphNode, titlebar_selected);
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, GraphNode, slot);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, GraphNode, separation);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, GraphNode, port_h_offset);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphNode, port);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, GraphNode, resizer);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, GraphNode, resizer_color);
}
GraphNode::GraphNode() {

View file

@ -38,6 +38,8 @@ class HBoxContainer;
class GraphNode : public GraphElement {
GDCLASS(GraphNode, GraphElement);
friend class GraphEdit;
struct Slot {
bool enable_left = false;
int type_left = 0;
@ -74,9 +76,23 @@ class GraphNode : public GraphElement {
Vector<PortCache> right_port_cache;
HashMap<int, Slot> slot_table;
Vector<int> slot_y_cache;
struct ThemeCache {
Ref<StyleBox> panel;
Ref<StyleBox> panel_selected;
Ref<StyleBox> titlebar;
Ref<StyleBox> titlebar_selected;
Ref<StyleBox> slot;
int separation = 0;
int port_h_offset = 0;
Ref<Texture2D> port;
Ref<Texture2D> resizer;
Color resizer_color;
} theme_cache;
bool port_pos_dirty = true;
void _port_pos_update();

View file

@ -259,6 +259,10 @@ int GridContainer::get_columns() const {
return columns;
}
int GridContainer::get_h_separation() const {
return theme_cache.h_separation;
}
void GridContainer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_columns", "columns"), &GridContainer::set_columns);
ClassDB::bind_method(D_METHOD("get_columns"), &GridContainer::get_columns);

View file

@ -52,6 +52,8 @@ public:
int get_columns() const;
virtual Size2 get_minimum_size() const override;
int get_h_separation() const;
GridContainer();
};

View file

@ -80,6 +80,23 @@ Vector<int> MarginContainer::get_allowed_size_flags_vertical() const {
return flags;
}
int MarginContainer::get_margin_size(Side p_side) const {
ERR_FAIL_INDEX_V((int)p_side, 4, 0);
switch (p_side) {
case SIDE_LEFT:
return theme_cache.margin_left;
case SIDE_RIGHT:
return theme_cache.margin_right;
case SIDE_TOP:
return theme_cache.margin_top;
case SIDE_BOTTOM:
return theme_cache.margin_bottom;
}
return 0;
}
void MarginContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {

View file

@ -53,6 +53,8 @@ public:
virtual Vector<int> get_allowed_size_flags_horizontal() const override;
virtual Vector<int> get_allowed_size_flags_vertical() const override;
int get_margin_size(Side p_side) const;
MarginContainer();
};

View file

@ -559,8 +559,8 @@ void PopupMenu::_draw_items() {
RID ci = control->get_canvas_item();
Size2 margin_size;
margin_size.width = margin_container->get_theme_constant(SNAME("margin_right")) + margin_container->get_theme_constant(SNAME("margin_left"));
margin_size.height = margin_container->get_theme_constant(SNAME("margin_top")) + margin_container->get_theme_constant(SNAME("margin_bottom"));
margin_size.width = margin_container->get_margin_size(SIDE_LEFT) + margin_container->get_margin_size(SIDE_RIGHT);
margin_size.height = margin_container->get_margin_size(SIDE_TOP) + margin_container->get_margin_size(SIDE_BOTTOM);
// Space between the item content and the sides of popup menu.
bool rtl = control->is_layout_rtl();

View file

@ -5817,6 +5817,9 @@ void RichTextLabel::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, RichTextLabel, mono_font);
BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, RichTextLabel, mono_font_size);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, text_highlight_h_padding);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, text_highlight_v_padding);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, table_h_separation);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, RichTextLabel, table_v_separation);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, RichTextLabel, table_odd_row_bg);
@ -6029,8 +6032,6 @@ void RichTextLabel::_draw_fbg_boxes(RID p_ci, RID p_rid, Vector2 line_off, Item
Vector2i fbg_index = Vector2i(end, start);
Color last_color = Color(0, 0, 0, 0);
bool draw_box = false;
int hpad = get_theme_constant(SNAME("text_highlight_h_padding"));
int vpad = get_theme_constant(SNAME("text_highlight_v_padding"));
// Draw a box based on color tags associated with glyphs
for (int i = start; i < end; i++) {
Item *it = _get_item_at_pos(it_from, it_to, i);
@ -6060,8 +6061,8 @@ void RichTextLabel::_draw_fbg_boxes(RID p_ci, RID p_rid, Vector2 line_off, Item
if (draw_box) {
Vector<Vector2> sel = TS->shaped_text_get_selection(p_rid, fbg_index.x, fbg_index.y);
for (int j = 0; j < sel.size(); j++) {
Vector2 rect_off = line_off + Vector2(sel[j].x - hpad, -TS->shaped_text_get_ascent(p_rid) - vpad);
Vector2 rect_size = Vector2(sel[j].y - sel[j].x + 2 * hpad, TS->shaped_text_get_size(p_rid).y + 2 * vpad);
Vector2 rect_off = line_off + Vector2(sel[j].x - theme_cache.text_highlight_h_padding, -TS->shaped_text_get_ascent(p_rid) - theme_cache.text_highlight_v_padding);
Vector2 rect_size = Vector2(sel[j].y - sel[j].x + 2 * theme_cache.text_highlight_h_padding, TS->shaped_text_get_size(p_rid).y + 2 * theme_cache.text_highlight_v_padding);
RenderingServer::get_singleton()->canvas_item_add_rect(p_ci, Rect2(rect_off, rect_size), last_color);
}
fbg_index = Vector2i(end, start);
@ -6079,8 +6080,8 @@ void RichTextLabel::_draw_fbg_boxes(RID p_ci, RID p_rid, Vector2 line_off, Item
if (last_color.a > 0) {
Vector<Vector2> sel = TS->shaped_text_get_selection(p_rid, fbg_index.x, end);
for (int i = 0; i < sel.size(); i++) {
Vector2 rect_off = line_off + Vector2(sel[i].x - hpad, -TS->shaped_text_get_ascent(p_rid) - vpad);
Vector2 rect_size = Vector2(sel[i].y - sel[i].x + 2 * hpad, TS->shaped_text_get_size(p_rid).y + 2 * vpad);
Vector2 rect_off = line_off + Vector2(sel[i].x - theme_cache.text_highlight_h_padding, -TS->shaped_text_get_ascent(p_rid) - theme_cache.text_highlight_v_padding);
Vector2 rect_size = Vector2(sel[i].y - sel[i].x + 2 * theme_cache.text_highlight_h_padding, TS->shaped_text_get_size(p_rid).y + 2 * theme_cache.text_highlight_v_padding);
RenderingServer::get_singleton()->canvas_item_add_rect(p_ci, Rect2(rect_off, rect_size), last_color);
}
}

View file

@ -592,6 +592,9 @@ private:
Ref<Font> mono_font;
int mono_font_size;
int text_highlight_h_padding;
int text_highlight_v_padding;
int table_h_separation;
int table_v_separation;
Color table_odd_row_bg;

View file

@ -97,7 +97,7 @@ void SplitContainerDragger::_notification(int p_what) {
case NOTIFICATION_MOUSE_ENTER: {
mouse_inside = true;
SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent());
if (sc->get_theme_constant(SNAME("autohide"))) {
if (sc->theme_cache.autohide) {
queue_redraw();
}
} break;
@ -105,14 +105,14 @@ void SplitContainerDragger::_notification(int p_what) {
case NOTIFICATION_MOUSE_EXIT: {
mouse_inside = false;
SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent());
if (sc->get_theme_constant(SNAME("autohide"))) {
if (sc->theme_cache.autohide) {
queue_redraw();
}
} break;
case NOTIFICATION_DRAW: {
SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent());
if (!dragging && !mouse_inside && sc->get_theme_constant(SNAME("autohide"))) {
if (!dragging && !mouse_inside && sc->theme_cache.autohide) {
return;
}

View file

@ -73,7 +73,7 @@ private:
struct ThemeCache {
int separation = 0;
int minimum_grab_thickness = 0;
int autohide = 0;
bool autohide = false;
Ref<Texture2D> grabber_icon;
Ref<Texture2D> grabber_icon_h;
Ref<Texture2D> grabber_icon_v;
@ -85,8 +85,6 @@ private:
void _compute_middle_sep(bool p_clamp);
void _resort();
void _dragging_area_gui_input(const Ref<InputEvent> &p_event);
protected:
bool is_fixed = false;

View file

@ -1254,7 +1254,7 @@ void TextEdit::_notification(int p_what) {
if ((brace_matching[c].open_match_line == line && brace_matching[c].open_match_column == glyphs[j].start) ||
(get_caret_column(c) == glyphs[j].start && get_caret_line(c) == line && carets_wrap_index[c] == line_wrap_index && (brace_matching[c].open_matching || brace_matching[c].open_mismatch))) {
if (brace_matching[c].open_mismatch) {
gl_color = theme_cache.brace_mismatch_color;
gl_color = _get_brace_mismatch_color();
}
Rect2 rect = Rect2(char_pos, ofs_y + theme_cache.font->get_underline_position(theme_cache.font_size), glyphs[j].advance * glyphs[j].repeat, MAX(theme_cache.font->get_underline_thickness(theme_cache.font_size) * theme_cache.base_scale, 1));
draw_rect(rect, gl_color);
@ -1263,7 +1263,7 @@ void TextEdit::_notification(int p_what) {
if ((brace_matching[c].close_match_line == line && brace_matching[c].close_match_column == glyphs[j].start) ||
(get_caret_column(c) == glyphs[j].start + 1 && get_caret_line(c) == line && carets_wrap_index[c] == line_wrap_index && (brace_matching[c].close_matching || brace_matching[c].close_mismatch))) {
if (brace_matching[c].close_mismatch) {
gl_color = theme_cache.brace_mismatch_color;
gl_color = _get_brace_mismatch_color();
}
Rect2 rect = Rect2(char_pos, ofs_y + theme_cache.font->get_underline_position(theme_cache.font_size), glyphs[j].advance * glyphs[j].repeat, MAX(theme_cache.font->get_underline_thickness(theme_cache.font_size) * theme_cache.base_scale, 1));
draw_rect(rect, gl_color);
@ -1313,12 +1313,12 @@ void TextEdit::_notification(int p_what) {
// is_line_folded
if (line_wrap_index == line_wrap_amount && line < text.size() - 1 && _is_line_hidden(line + 1)) {
int xofs = char_ofs + char_margin + ofs_x + (theme_cache.folded_eol_icon->get_width() / 2);
int xofs = char_ofs + char_margin + ofs_x + (_get_folded_eol_icon()->get_width() / 2);
if (xofs >= xmargin_beg && xofs < xmargin_end) {
int yofs = (text_height - theme_cache.folded_eol_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index);
Color eol_color = theme_cache.code_folding_color;
int yofs = (text_height - _get_folded_eol_icon()->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index);
Color eol_color = _get_code_folding_color();
eol_color.a = 1;
theme_cache.folded_eol_icon->draw(ci, Point2(xofs, ofs_y + yofs), eol_color);
_get_folded_eol_icon()->draw(ci, Point2(xofs, ofs_y + yofs), eol_color);
}
}
@ -3000,7 +3000,6 @@ void TextEdit::_update_theme_item_cache() {
Control::_update_theme_item_cache();
theme_cache.base_scale = get_theme_default_base_scale();
theme_cache.folded_code_region_color = get_theme_color(SNAME("folded_code_region_color"), SNAME("CodeEdit"));
use_selected_font_color = theme_cache.font_selected_color != Color(0, 0, 0, 0);
if (text.get_line_height() + theme_cache.line_spacing < 1) {
@ -6474,12 +6473,6 @@ void TextEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("gutter_removed"));
/* Theme items */
/* Internal API for CodeEdit */
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, TextEdit, brace_mismatch_color, "brace_mismatch_color", "CodeEdit");
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, TextEdit, code_folding_color, "code_folding_color", "CodeEdit");
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_COLOR, TextEdit, folded_code_region_color, "folded_code_region_color", "CodeEdit");
BIND_THEME_ITEM_EXT(Theme::DATA_TYPE_ICON, TextEdit, folded_eol_icon, "folded_eol_icon", "CodeEdit");
/* Search */
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, search_result_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, search_result_border_color);

View file

@ -41,6 +41,8 @@
class TextEdit : public Control {
GDCLASS(TextEdit, Control);
friend class CodeHighlighter;
public:
/* Edit Actions. */
enum EditAction {
@ -543,12 +545,6 @@ private:
struct ThemeCache {
float base_scale = 1.0;
/* Internal API for CodeEdit */
Color brace_mismatch_color;
Color code_folding_color = Color(1, 1, 1);
Color folded_code_region_color = Color(1, 1, 1);
Ref<Texture2D> folded_eol_icon;
/* Search */
Color search_result_color = Color(1, 1, 1);
Color search_result_border_color = Color(1, 1, 1);
@ -633,7 +629,7 @@ protected:
virtual void _update_theme_item_cache() override;
/* Internal API for CodeEdit, pending public API. */
// brace matching
// Brace matching.
struct BraceMatchingData {
int open_match_line = -1;
int open_match_column = -1;
@ -662,6 +658,11 @@ protected:
String lookup_symbol_word;
void _set_symbol_lookup_word(const String &p_symbol);
// Theme items.
virtual Color _get_brace_mismatch_color() const { return Color(); };
virtual Color _get_code_folding_color() const { return Color(); };
virtual Ref<Texture2D> _get_folded_eol_icon() const { return Ref<Texture2D>(); };
/* Text manipulation */
// Overridable actions

View file

@ -319,16 +319,16 @@ void Viewport::_sub_window_update(Window *p_window) {
Rect2i r = Rect2i(p_window->get_position(), sw.window->get_size());
if (!p_window->get_flag(Window::FLAG_BORDERLESS)) {
Ref<StyleBox> panel = p_window->get_theme_stylebox(gui.subwindow_focused == p_window ? SNAME("embedded_border") : SNAME("embedded_unfocused_border"));
Ref<StyleBox> panel = gui.subwindow_focused == p_window ? p_window->theme_cache.embedded_border : p_window->theme_cache.embedded_unfocused_border;
panel->draw(sw.canvas_item, r);
// Draw the title bar text.
Ref<Font> title_font = p_window->get_theme_font(SNAME("title_font"));
int font_size = p_window->get_theme_font_size(SNAME("title_font_size"));
Color title_color = p_window->get_theme_color(SNAME("title_color"));
int title_height = p_window->get_theme_constant(SNAME("title_height"));
int close_h_ofs = p_window->get_theme_constant(SNAME("close_h_offset"));
int close_v_ofs = p_window->get_theme_constant(SNAME("close_v_offset"));
Ref<Font> title_font = p_window->theme_cache.title_font;
int font_size = p_window->theme_cache.title_font_size;
Color title_color = p_window->theme_cache.title_color;
int title_height = p_window->theme_cache.title_height;
int close_h_ofs = p_window->theme_cache.close_h_offset;
int close_v_ofs = p_window->theme_cache.close_v_offset;
TextLine title_text = TextLine(p_window->atr(p_window->get_title()), title_font, font_size);
title_text.set_width(r.size.width - panel->get_minimum_size().x - close_h_ofs);
@ -336,15 +336,15 @@ void Viewport::_sub_window_update(Window *p_window) {
int x = (r.size.width - title_text.get_size().x) / 2;
int y = (-title_height - title_text.get_size().y) / 2;
Color font_outline_color = p_window->get_theme_color(SNAME("title_outline_modulate"));
int outline_size = p_window->get_theme_constant(SNAME("title_outline_size"));
Color font_outline_color = p_window->theme_cache.title_outline_modulate;
int outline_size = p_window->theme_cache.title_outline_size;
if (outline_size > 0 && font_outline_color.a > 0) {
title_text.draw_outline(sw.canvas_item, r.position + Point2(x, y), outline_size, font_outline_color);
}
title_text.draw(sw.canvas_item, r.position + Point2(x, y), title_color);
bool pressed = gui.subwindow_focused == sw.window && gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE && gui.subwindow_drag_close_inside;
Ref<Texture2D> close_icon = p_window->get_theme_icon(pressed ? "close_pressed" : "close");
Ref<Texture2D> close_icon = pressed ? p_window->theme_cache.close_pressed : p_window->theme_cache.close;
close_icon->draw(sw.canvas_item, r.position + Vector2(r.size.width - close_h_ofs, -close_v_ofs));
}
@ -2039,7 +2039,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Window *sw = embedder->gui.sub_windows[i].window;
Rect2 swrect = Rect2i(sw->get_position(), sw->get_size());
if (!sw->get_flag(Window::FLAG_BORDERLESS)) {
int title_height = sw->get_theme_constant(SNAME("title_height"));
int title_height = sw->theme_cache.title_height;
swrect.position.y -= title_height;
swrect.size.y += title_height;
}
@ -2669,7 +2669,7 @@ Viewport::SubWindowResize Viewport::_sub_window_get_resize_margin(Window *p_subw
Rect2i r = Rect2i(p_subwindow->get_position(), p_subwindow->get_size());
int title_height = p_subwindow->get_theme_constant(SNAME("title_height"));
int title_height = p_subwindow->theme_cache.title_height;
r.position.y -= title_height;
r.size.y += title_height;
@ -2681,7 +2681,7 @@ Viewport::SubWindowResize Viewport::_sub_window_get_resize_margin(Window *p_subw
int dist_x = p_point.x < r.position.x ? (p_point.x - r.position.x) : (p_point.x > (r.position.x + r.size.x) ? (p_point.x - (r.position.x + r.size.x)) : 0);
int dist_y = p_point.y < r.position.y ? (p_point.y - r.position.y) : (p_point.y > (r.position.y + r.size.y) ? (p_point.y - (r.position.y + r.size.y)) : 0);
int limit = p_subwindow->get_theme_constant(SNAME("resize_margin"));
int limit = p_subwindow->theme_cache.resize_margin;
if (ABS(dist_x) > limit) {
return SUB_WINDOW_RESIZE_DISABLED;
@ -2866,7 +2866,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
if (!sw.window->get_flag(Window::FLAG_BORDERLESS)) {
// Check top bar.
int title_height = sw.window->get_theme_constant(SNAME("title_height"));
int title_height = sw.window->theme_cache.title_height;
Rect2i title_bar = r;
title_bar.position.y -= title_height;
title_bar.size.y = title_height;
@ -2874,9 +2874,9 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
if (title_bar.size.y > 0 && title_bar.has_point(mb->get_position())) {
click_on_window = sw.window;
int close_h_ofs = sw.window->get_theme_constant(SNAME("close_h_offset"));
int close_v_ofs = sw.window->get_theme_constant(SNAME("close_v_offset"));
Ref<Texture2D> close_icon = sw.window->get_theme_icon(SNAME("close"));
int close_h_ofs = sw.window->theme_cache.close_h_offset;
int close_v_ofs = sw.window->theme_cache.close_v_offset;
Ref<Texture2D> close_icon = sw.window->theme_cache.close;
Rect2 close_rect;
close_rect.position = Vector2(r.position.x + r.size.x - close_h_ofs, r.position.y - close_v_ofs);
@ -3016,8 +3016,8 @@ void Viewport::_update_mouse_over(Vector2 p_pos) {
Rect2 swrect_border = swrect;
if (!sw->get_flag(Window::FLAG_BORDERLESS)) {
int title_height = sw->get_theme_constant(SNAME("title_height"));
int margin = sw->get_theme_constant(SNAME("resize_margin"));
int title_height = sw->theme_cache.title_height;
int margin = sw->theme_cache.resize_margin;
swrect_border.position.y -= title_height + margin;
swrect_border.size.y += title_height + margin * 2;
swrect_border.position.x -= margin;

View file

@ -1804,7 +1804,7 @@ Rect2i Window::fit_rect_in_parent(Rect2i p_rect, const Rect2i &p_parent_rect) co
p_rect.position.x = 0;
}
int title_height = get_flag(Window::FLAG_BORDERLESS) ? 0 : get_theme_constant(SNAME("title_height"));
int title_height = get_flag(Window::FLAG_BORDERLESS) ? 0 : theme_cache.title_height;
if (p_rect.position.y < title_height) {
p_rect.position.y = title_height;
@ -2910,6 +2910,23 @@ void Window::_bind_methods() {
BIND_ENUM_CONSTANT(WINDOW_INITIAL_POSITION_CENTER_SCREEN_WITH_KEYBOARD_FOCUS);
GDVIRTUAL_BIND(_get_contents_minimum_size);
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Window, embedded_border);
BIND_THEME_ITEM(Theme::DATA_TYPE_STYLEBOX, Window, embedded_unfocused_border);
BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, Window, title_font);
BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, Window, title_font_size);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Window, title_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Window, title_height);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, Window, title_outline_modulate);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Window, title_outline_size);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Window, close);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, Window, close_pressed);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Window, close_h_offset);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Window, close_v_offset);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, Window, resize_margin);
}
Window::Window() {

View file

@ -42,7 +42,8 @@ class ThemeOwner;
class ThemeContext;
class Window : public Viewport {
GDCLASS(Window, Viewport)
GDCLASS(Window, Viewport);
public:
// Keep synced with enum hint for `mode` property.
enum Mode {
@ -191,6 +192,25 @@ private:
void _notify_theme_override_changed();
void _invalidate_theme_cache();
struct ThemeCache {
Ref<StyleBox> embedded_border;
Ref<StyleBox> embedded_unfocused_border;
Ref<Font> title_font;
int title_font_size = 0;
Color title_color;
int title_height = 0;
Color title_outline_modulate;
int title_outline_size = 0;
Ref<Texture2D> close;
Ref<Texture2D> close_pressed;
int close_h_offset = 0;
int close_v_offset = 0;
int resize_margin = 0;
} theme_cache;
Viewport *embedder = nullptr;
Transform2D window_transform;
@ -212,12 +232,12 @@ private:
protected:
virtual Rect2i _popup_adjust_rect() const { return Rect2i(); }
virtual void _post_popup() {}
virtual void _update_theme_item_cache();
virtual void _post_popup() {}
static void _bind_methods();
void _notification(int p_what);
static void _bind_methods();
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;

View file

@ -419,7 +419,7 @@ void CodeHighlighter::_clear_highlighting_cache() {
}
void CodeHighlighter::_update_cache() {
font_color = text_edit->get_theme_color(SNAME("font_color"));
font_color = text_edit->theme_cache.font_color;
}
void CodeHighlighter::add_keyword_color(const String &p_keyword, const Color &p_color) {