1 | /**************************************************************************/ |
2 | /* style_box_editor_plugin.cpp */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #include "style_box_editor_plugin.h" |
32 | |
33 | #include "editor/editor_scale.h" |
34 | #include "scene/gui/button.h" |
35 | #include "scene/resources/style_box_texture.h" |
36 | |
37 | bool StyleBoxPreview::grid_preview_enabled = true; |
38 | |
39 | void StyleBoxPreview::_grid_preview_toggled(bool p_active) { |
40 | grid_preview_enabled = p_active; |
41 | queue_redraw(); |
42 | } |
43 | |
44 | void StyleBoxPreview::edit(const Ref<StyleBox> &p_stylebox) { |
45 | if (stylebox.is_valid()) { |
46 | stylebox->disconnect_changed(callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw)); |
47 | } |
48 | stylebox = p_stylebox; |
49 | if (stylebox.is_valid()) { |
50 | stylebox->connect_changed(callable_mp((CanvasItem *)this, &CanvasItem::queue_redraw)); |
51 | } |
52 | Ref<StyleBoxTexture> sbt = stylebox; |
53 | grid_preview->set_visible(sbt.is_valid()); |
54 | queue_redraw(); |
55 | } |
56 | |
57 | void StyleBoxPreview::_notification(int p_what) { |
58 | switch (p_what) { |
59 | case NOTIFICATION_THEME_CHANGED: { |
60 | set_texture(get_editor_theme_icon(SNAME("Checkerboard" ))); |
61 | grid_preview->set_icon(get_editor_theme_icon(SNAME("StyleBoxGrid" ))); |
62 | } break; |
63 | case NOTIFICATION_DRAW: { |
64 | _redraw(); |
65 | } break; |
66 | } |
67 | } |
68 | |
69 | void StyleBoxPreview::_redraw() { |
70 | if (stylebox.is_valid()) { |
71 | float grid_button_width = get_editor_theme_icon(SNAME("StyleBoxGrid" ))->get_size().x; |
72 | Rect2 preview_rect = get_rect(); |
73 | preview_rect = preview_rect.grow(-grid_button_width); |
74 | |
75 | // Re-adjust preview panel to fit all drawn content. |
76 | Rect2 drawing_rect = stylebox->get_draw_rect(preview_rect); |
77 | preview_rect.size -= drawing_rect.size - preview_rect.size; |
78 | preview_rect.position -= drawing_rect.position - preview_rect.position; |
79 | |
80 | draw_style_box(stylebox, preview_rect); |
81 | |
82 | Ref<StyleBoxTexture> sbt = stylebox; |
83 | // Draw the "grid". Use white lines, as well as subtle black lines to ensure contrast. |
84 | if (sbt.is_valid() && grid_preview->is_pressed()) { |
85 | const Color dark_color = Color(0, 0, 0, 0.4); |
86 | const Color bright_color = Color(1, 1, 1, 0.8); |
87 | int x_left = drawing_rect.position.x + sbt->get_margin(SIDE_LEFT); |
88 | int x_right = drawing_rect.position.x + drawing_rect.size.width - sbt->get_margin(SIDE_RIGHT); |
89 | int y_top = drawing_rect.position.y + sbt->get_margin(SIDE_TOP); |
90 | int y_bottom = drawing_rect.position.y + drawing_rect.size.height - sbt->get_margin(SIDE_BOTTOM); |
91 | |
92 | draw_line(Point2(x_left + 2, 0), Point2(x_left + 2, get_size().height), dark_color); |
93 | draw_line(Point2(x_right + 1, 0), Point2(x_right + 1, get_size().height), dark_color); |
94 | draw_line(Point2(0, y_top + 2), Point2(get_size().width, y_top + 2), dark_color); |
95 | draw_line(Point2(0, y_bottom + 1), Point2(get_size().width, y_bottom + 1), dark_color); |
96 | |
97 | draw_line(Point2(x_left + 1, 0), Point2(x_left + 1, get_size().height), bright_color); |
98 | draw_line(Point2(x_right, 0), Point2(x_right, get_size().height), bright_color); |
99 | draw_line(Point2(0, y_top + 1), Point2(get_size().width, y_top + 1), bright_color); |
100 | draw_line(Point2(0, y_bottom), Point2(get_size().width, y_bottom), bright_color); |
101 | } |
102 | } |
103 | } |
104 | |
105 | StyleBoxPreview::StyleBoxPreview() { |
106 | set_clip_contents(true); |
107 | set_custom_minimum_size(Size2(0, 150) * EDSCALE); |
108 | set_stretch_mode(TextureRect::STRETCH_TILE); |
109 | set_texture_repeat(CanvasItem::TEXTURE_REPEAT_ENABLED); |
110 | set_anchors_and_offsets_preset(PRESET_FULL_RECT); |
111 | |
112 | grid_preview = memnew(Button); |
113 | // This theme variation works better than the normal theme because there's no focus highlight. |
114 | grid_preview->set_theme_type_variation("PreviewLightButton" ); |
115 | grid_preview->set_toggle_mode(true); |
116 | grid_preview->connect("toggled" , callable_mp(this, &StyleBoxPreview::_grid_preview_toggled)); |
117 | grid_preview->set_pressed(grid_preview_enabled); |
118 | add_child(grid_preview); |
119 | } |
120 | |
121 | bool EditorInspectorPluginStyleBox::can_handle(Object *p_object) { |
122 | return Object::cast_to<StyleBox>(p_object) != nullptr; |
123 | } |
124 | |
125 | void EditorInspectorPluginStyleBox::parse_begin(Object *p_object) { |
126 | Ref<StyleBox> sb = Ref<StyleBox>(Object::cast_to<StyleBox>(p_object)); |
127 | |
128 | StyleBoxPreview *preview = memnew(StyleBoxPreview); |
129 | preview->edit(sb); |
130 | add_custom_control(preview); |
131 | } |
132 | |
133 | StyleBoxEditorPlugin::StyleBoxEditorPlugin() { |
134 | Ref<EditorInspectorPluginStyleBox> inspector_plugin; |
135 | inspector_plugin.instantiate(); |
136 | add_inspector_plugin(inspector_plugin); |
137 | } |
138 | |