diff options
Diffstat (limited to 'editor/plugins')
-rw-r--r-- | editor/plugins/abstract_polygon_2d_editor.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/animation_state_machine_editor.cpp | 4 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.cpp | 46 | ||||
-rw-r--r-- | editor/plugins/editor_preview_plugins.cpp | 19 | ||||
-rw-r--r-- | editor/plugins/font_config_plugin.cpp | 979 | ||||
-rw-r--r-- | editor/plugins/font_config_plugin.h | 261 | ||||
-rw-r--r-- | editor/plugins/font_editor_plugin.cpp | 106 | ||||
-rw-r--r-- | editor/plugins/font_editor_plugin.h | 77 | ||||
-rw-r--r-- | editor/plugins/node_3d_editor_plugin.cpp | 5 | ||||
-rw-r--r-- | editor/plugins/ot_features_plugin.cpp | 235 | ||||
-rw-r--r-- | editor/plugins/ot_features_plugin.h | 102 | ||||
-rw-r--r-- | editor/plugins/text_control_editor_plugin.cpp | 660 | ||||
-rw-r--r-- | editor/plugins/text_control_editor_plugin.h | 115 | ||||
-rw-r--r-- | editor/plugins/theme_editor_plugin.cpp | 6 | ||||
-rw-r--r-- | editor/plugins/theme_editor_preview.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/tiles/tile_data_editors.cpp | 17 |
16 files changed, 1292 insertions, 1344 deletions
diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index ad6d8e6379..affe46aaae 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -565,7 +565,7 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); String num = String::num(vertex.vertex); - Size2 num_size = font->get_string_size(num, font_size); + Size2 num_size = font->get_string_size(num, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); p_overlay->draw_string(font, point - num_size * 0.5, num, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1.0, 1.0, 1.0, 0.5)); } } diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index 00cc5a6ca0..05d7a5f973 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -1224,7 +1224,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() { Ref<StyleBox> sb = selected_nodes.has(E) ? style_selected : style; Size2 s = sb->get_minimum_size(); - int strsize = font->get_string_size(name, font_size).width; + int strsize = font->get_string_size(name, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width; s.width += strsize; s.height += MAX(font->get_height(font_size), play->get_height()); s.width += sep + play->get_width(); @@ -1379,7 +1379,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() { Ref<AnimationNode> anode = state_machine->get_node(name); bool needs_editor = AnimationTreeEditor::get_singleton()->can_edit(anode); Ref<StyleBox> sb = selected_nodes.has(name) ? style_selected : style; - int strsize = font->get_string_size(name, font_size).width; + int strsize = font->get_string_size(name, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size).width; NodeRect &nr = node_rects.write[i]; Vector2 offset = nr.node.position; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 22788913d4..9ff32203f7 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -2677,7 +2677,7 @@ void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string color.a = 0.8; Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); - Size2 text_size = font->get_string_size(p_string, font_size); + Size2 text_size = font->get_string_size(p_string, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); switch (p_side) { case SIDE_LEFT: p_position += Vector2(-text_size.x - 5, text_size.y / 2); @@ -2749,16 +2749,18 @@ void CanvasItemEditor::_draw_guides() { String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x))); Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts")); int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts")); - Size2 text_size = font->get_string_size(str, font_size); - viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color, outline_size, outline_color); + Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); + viewport->draw_string_outline(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color); viewport->draw_line(Point2(dragged_guide_pos.x, 0), Point2(dragged_guide_pos.x, viewport->get_size().y), guide_color, Math::round(EDSCALE)); } if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_H_GUIDE) { String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y))); Ref<Font> font = get_theme_font(SNAME("bold"), SNAME("EditorFonts")); int font_size = get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts")); - Size2 text_size = font->get_string_size(str, font_size); - viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color, outline_size, outline_color); + Size2 text_size = font->get_string_size(str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); + viewport->draw_string_outline(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, text_color); viewport->draw_line(Point2(0, dragged_guide_pos.y), Point2(viewport->get_size().x, dragged_guide_pos.y), guide_color, Math::round(EDSCALE)); } } @@ -2970,13 +2972,15 @@ void CanvasItemEditor::_draw_ruler_tool() { text_pos.y = CLAMP(text_pos.y, text_height * 1.5, viewport->get_rect().size.y - text_height * 1.5); if (begin.is_equal_approx(end)) { - viewport->draw_string(font, text_pos, (String)ruler_tool_origin, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color); + viewport->draw_string_outline(font, text_pos, (String)ruler_tool_origin, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, text_pos, (String)ruler_tool_origin, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); Ref<Texture2D> position_icon = get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons")); viewport->draw_texture(get_theme_icon(SNAME("EditorPosition"), SNAME("EditorIcons")), (ruler_tool_origin - view_offset) * zoom - position_icon->get_size() / 2); return; } - viewport->draw_string(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color); + viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); bool draw_secondary_lines = !(Math::is_equal_approx(begin.y, corner.y) || Math::is_equal_approx(end.x, corner.x)); @@ -2994,16 +2998,19 @@ void CanvasItemEditor::_draw_ruler_tool() { Point2 text_pos2 = text_pos; text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2); - viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color); + viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); Point2 v_angle_text_pos = Point2(); v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width); v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5); - viewport->draw_string(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color); + viewport->draw_string_outline(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); text_pos2 = text_pos; text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y - text_height / 2) : MAX(text_pos.y + text_height * 2, end.y - text_height / 2); - viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color); + viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); Point2 h_angle_text_pos = Point2(); h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width); @@ -3020,7 +3027,8 @@ void CanvasItemEditor::_draw_ruler_tool() { h_angle_text_pos.y = MIN(text_pos.y - height_multiplier * text_height, MIN(end.y - text_height * 0.5, text_pos2.y - height_multiplier * text_height)); } } - viewport->draw_string(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color); + viewport->draw_string_outline(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); // Angle arcs int arc_point_count = 8; @@ -3055,17 +3063,21 @@ void CanvasItemEditor::_draw_ruler_tool() { text_pos.y = CLAMP(text_pos.y, text_height * 2.5, viewport->get_rect().size.y - text_height / 2); if (draw_secondary_lines) { - viewport->draw_string(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color); + viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); Point2 text_pos2 = text_pos; text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2); - viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color); + viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); text_pos2 = text_pos; text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y + text_height / 2) : MAX(text_pos.y + text_height * 2, end.y + text_height / 2); - viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color); + viewport->draw_string_outline(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_secondary_color); } else { - viewport->draw_string(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color, outline_size, outline_color); + viewport->draw_string_outline(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, outline_size, outline_color); + viewport->draw_string(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); } } } else { @@ -3611,7 +3623,7 @@ void CanvasItemEditor::_draw_hover() { Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); - Size2 node_name_size = font->get_string_size(node_name, font_size); + Size2 node_name_size = font->get_string_size(node_name, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); Size2 item_size = Size2(node_icon->get_size().x + 4 + node_name_size.x, MAX(node_icon->get_size().y, node_name_size.y - 3)); Point2 pos = transform.xform(hovering_results[i].position) - Point2(0, item_size.y) + (Point2(node_icon->get_size().x, -node_icon->get_size().y) / 4); @@ -3685,7 +3697,7 @@ void CanvasItemEditor::_draw_transform_message() { return; } - Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); + Ref<FontFile> font = get_theme_font(SNAME("font"), SNAME("Label")); int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); Point2 msgpos = Point2(RULER_WIDTH + 5 * EDSCALE, viewport->get_size().y - 20 * EDSCALE); viewport->draw_string(font, msgpos + Point2(1, 1), transform_message, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(0, 0, 0, 0.8)); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index bb0cfcba25..a00ed1e49a 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -812,19 +812,12 @@ void EditorFontPreviewPlugin::_preview_done() { } bool EditorFontPreviewPlugin::handles(const String &p_type) const { - return ClassDB::is_parent_class(p_type, "FontData") || ClassDB::is_parent_class(p_type, "Font"); + return ClassDB::is_parent_class(p_type, "Font"); } Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path, const Size2 &p_size) const { - Ref<Resource> res = ResourceLoader::load(p_path); - ERR_FAIL_COND_V(res.is_null(), Ref<Texture2D>()); - Ref<Font> sampled_font; - if (res->is_class("Font")) { - sampled_font = res->duplicate(); - } else if (res->is_class("FontData")) { - sampled_font.instantiate(); - sampled_font->add_data(res->duplicate()); - } + Ref<Font> sampled_font = ResourceLoader::load(p_path); + ERR_FAIL_COND_V(sampled_font.is_null(), Ref<Texture2D>()); String sample; static const String sample_base = U"12漢字ԱբΑαАбΑαאבابܐܒހށआআਆઆଆஆఆಆആආกิກິༀကႠა한글ሀᎣᐁᚁᚠᜀᜠᝀᝠកᠠᤁᥐAb😀"; @@ -836,18 +829,16 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path, if (sample.is_empty()) { sample = sampled_font->get_supported_chars().substr(0, 6); } - Vector2 size = sampled_font->get_string_size(sample, 50); + Vector2 size = sampled_font->get_string_size(sample, HORIZONTAL_ALIGNMENT_LEFT, -1, 50); Vector2 pos; pos.x = 64 - size.x / 2; pos.y = 80; - Ref<Font> font = sampled_font; - const Color c = GLOBAL_GET("rendering/environment/defaults/default_clear_color"); const float fg = c.get_luminance() < 0.5 ? 1.0 : 0.0; - font->draw_string(canvas_item, pos, sample, HORIZONTAL_ALIGNMENT_LEFT, -1.f, 50, Color(fg, fg, fg)); + sampled_font->draw_string(canvas_item, pos, sample, HORIZONTAL_ALIGNMENT_LEFT, -1.f, 50, Color(fg, fg, fg)); RS::get_singleton()->connect(SNAME("frame_pre_draw"), callable_mp(const_cast<EditorFontPreviewPlugin *>(this), &EditorFontPreviewPlugin::_generate_frame_started), Vector<Variant>(), Object::CONNECT_ONESHOT); diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp new file mode 100644 index 0000000000..848fb5887d --- /dev/null +++ b/editor/plugins/font_config_plugin.cpp @@ -0,0 +1,979 @@ +/*************************************************************************/ +/* font_config_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "font_config_plugin.h" + +#include "editor/editor_scale.h" +#include "editor/import/dynamic_font_import_settings.h" + +/*************************************************************************/ +/* EditorPropertyFontMetaObject */ +/*************************************************************************/ + +bool EditorPropertyFontMetaObject::_set(const StringName &p_name, const Variant &p_value) { + String name = p_name; + + if (name.begins_with("keys")) { + String key = name.get_slicec('/', 1); + dict[key] = p_value; + return true; + } + + return false; +} + +bool EditorPropertyFontMetaObject::_get(const StringName &p_name, Variant &r_ret) const { + String name = p_name; + + if (name.begins_with("keys")) { + String key = name.get_slicec('/', 1); + r_ret = dict[key]; + return true; + } + + return false; +} + +void EditorPropertyFontMetaObject::_bind_methods() { +} + +void EditorPropertyFontMetaObject::set_dict(const Dictionary &p_dict) { + dict = p_dict; +} + +Dictionary EditorPropertyFontMetaObject::get_dict() { + return dict; +} + +/*************************************************************************/ +/* EditorPropertyFontOTObject */ +/*************************************************************************/ + +bool EditorPropertyFontOTObject::_set(const StringName &p_name, const Variant &p_value) { + String name = p_name; + + if (name.begins_with("keys")) { + int key = name.get_slicec('/', 1).to_int(); + dict[key] = p_value; + return true; + } + + return false; +} + +bool EditorPropertyFontOTObject::_get(const StringName &p_name, Variant &r_ret) const { + String name = p_name; + + if (name.begins_with("keys")) { + int key = name.get_slicec('/', 1).to_int(); + r_ret = dict[key]; + return true; + } + + return false; +} + +void EditorPropertyFontOTObject::_bind_methods() { + ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &EditorPropertyFontOTObject::property_can_revert); + ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorPropertyFontOTObject::property_get_revert); +} + +void EditorPropertyFontOTObject::set_dict(const Dictionary &p_dict) { + dict = p_dict; +} + +Dictionary EditorPropertyFontOTObject::get_dict() { + return dict; +} + +void EditorPropertyFontOTObject::set_defaults(const Dictionary &p_dict) { + defaults_dict = p_dict; +} + +Dictionary EditorPropertyFontOTObject::get_defaults() { + return defaults_dict; +} + +bool EditorPropertyFontOTObject::property_can_revert(const String &p_name) { + String name = p_name; + + if (name.begins_with("keys")) { + int key = name.get_slicec('/', 1).to_int(); + if (defaults_dict.has(key) && dict.has(key)) { + int value = dict[key]; + Vector3i range = defaults_dict[key]; + return range.z != value; + } + } + + return false; +} + +Variant EditorPropertyFontOTObject::property_get_revert(const String &p_name) { + String name = p_name; + + if (name.begins_with("keys")) { + int key = name.get_slicec('/', 1).to_int(); + if (defaults_dict.has(key)) { + Vector3i range = defaults_dict[key]; + return range.z; + } + } + + return Variant(); +} + +/*************************************************************************/ +/* EditorPropertyFontMetaOverride */ +/*************************************************************************/ + +void EditorPropertyFontMetaOverride::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + if (Object::cast_to<Button>(button_add)) { + button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + } + } break; + } +} + +void EditorPropertyFontMetaOverride::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) { + if (p_property.begins_with("keys")) { + Dictionary dict = object->get_dict(); + String key = p_property.get_slice("/", 1); + dict[key] = (bool)p_value; + + emit_changed(get_edited_property(), dict, "", true); + + dict = dict.duplicate(); // Duplicate, so undo/redo works better. + object->set_dict(dict); + } +} + +void EditorPropertyFontMetaOverride::_remove(Object *p_button, const String &p_key) { + Dictionary dict = object->get_dict(); + + dict.erase(p_key); + + emit_changed(get_edited_property(), dict, "", false); + + dict = dict.duplicate(); // Duplicate, so undo/redo works better. + object->set_dict(dict); + update_property(); +} + +void EditorPropertyFontMetaOverride::_add_menu() { + if (script_editor) { + Size2 size = get_size(); + menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y)); + menu->reset_size(); + menu->popup(); + } else { + locale_select->popup_locale_dialog(); + } +} + +void EditorPropertyFontMetaOverride::_add_script(int p_option) { + Dictionary dict = object->get_dict(); + + dict[script_codes[p_option]] = true; + + emit_changed(get_edited_property(), dict, "", false); + + dict = dict.duplicate(); // Duplicate, so undo/redo works better. + object->set_dict(dict); + update_property(); +} + +void EditorPropertyFontMetaOverride::_add_lang(const String &p_locale) { + Dictionary dict = object->get_dict(); + + dict[p_locale] = true; + + emit_changed(get_edited_property(), dict, "", false); + + dict = dict.duplicate(); // Duplicate, so undo/redo works better. + object->set_dict(dict); + update_property(); +} + +void EditorPropertyFontMetaOverride::_object_id_selected(const StringName &p_property, ObjectID p_id) { + emit_signal(SNAME("object_id_selected"), p_property, p_id); +} + +void EditorPropertyFontMetaOverride::update_property() { + Variant updated_val = get_edited_object()->get(get_edited_property()); + + Dictionary dict = updated_val; + + edit->set_text(vformat(TTR("Overrides (%d)"), dict.size())); + + bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); + if (edit->is_pressed() != unfolded) { + edit->set_pressed(unfolded); + } + + if (unfolded) { + updating = true; + + if (!container) { + container = memnew(MarginContainer); + container->set_theme_type_variation("MarginContainer4px"); + add_child(container); + set_bottom_editor(container); + + VBoxContainer *vbox = memnew(VBoxContainer); + vbox->set_v_size_flags(SIZE_EXPAND_FILL); + container->add_child(vbox); + + property_vbox = memnew(VBoxContainer); + property_vbox->set_h_size_flags(SIZE_EXPAND_FILL); + vbox->add_child(property_vbox); + + paginator = memnew(EditorPaginator); + paginator->connect("page_changed", callable_mp(this, &EditorPropertyFontMetaOverride::_page_changed)); + vbox->add_child(paginator); + } else { + // Queue children for deletion, deleting immediately might cause errors. + for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) { + property_vbox->get_child(i)->queue_delete(); + } + button_add = nullptr; + } + + int size = dict.size(); + + int max_page = MAX(0, size - 1) / page_length; + page_index = MIN(page_index, max_page); + + paginator->update(page_index, max_page); + paginator->set_visible(max_page > 0); + + int offset = page_index * page_length; + + int amount = MIN(size - offset, page_length); + + dict = dict.duplicate(); + object->set_dict(dict); + + for (int i = 0; i < amount; i++) { + String name = dict.get_key_at_index(i); + EditorProperty *prop = memnew(EditorPropertyCheck); + prop->set_object_and_property(object.ptr(), "keys/" + name); + + if (script_editor) { + prop->set_label(TranslationServer::get_singleton()->get_script_name(name)); + } else { + prop->set_label(TranslationServer::get_singleton()->get_locale_name(name)); + } + prop->set_tooltip(name); + prop->set_selectable(false); + + prop->connect("property_changed", callable_mp(this, &EditorPropertyFontMetaOverride::_property_changed)); + prop->connect("object_id_selected", callable_mp(this, &EditorPropertyFontMetaOverride::_object_id_selected)); + + HBoxContainer *hbox = memnew(HBoxContainer); + property_vbox->add_child(hbox); + hbox->add_child(prop); + prop->set_h_size_flags(SIZE_EXPAND_FILL); + Button *remove = memnew(Button); + remove->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); + hbox->add_child(remove); + remove->connect("pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_remove), varray(remove, name)); + + prop->update_property(); + } + + if (script_editor) { + button_add = EditorInspector::create_inspector_action_button(TTR("Add Script")); + } else { + button_add = EditorInspector::create_inspector_action_button(TTR("Add Locale")); + } + button_add->connect("pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_add_menu)); + property_vbox->add_child(button_add); + + updating = false; + } else { + if (container) { + set_bottom_editor(nullptr); + memdelete(container); + button_add = nullptr; + container = nullptr; + } + } +} + +void EditorPropertyFontMetaOverride::_edit_pressed() { + Variant prop_val = get_edited_object()->get(get_edited_property()); + if (prop_val.get_type() == Variant::NIL) { + Callable::CallError ce; + Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce); + get_edited_object()->set(get_edited_property(), prop_val); + } + + get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed()); + update_property(); +} + +void EditorPropertyFontMetaOverride::_page_changed(int p_page) { + if (updating) { + return; + } + page_index = p_page; + update_property(); +} + +EditorPropertyFontMetaOverride::EditorPropertyFontMetaOverride(bool p_script) { + script_editor = p_script; + + object.instantiate(); + page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page")); + + edit = memnew(Button); + edit->set_h_size_flags(SIZE_EXPAND_FILL); + edit->set_clip_text(true); + edit->connect("pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_edit_pressed)); + edit->set_toggle_mode(true); + add_child(edit); + add_focusable(edit); + + menu = memnew(PopupMenu); + if (script_editor) { + script_codes = TranslationServer::get_singleton()->get_all_scripts(); + for (int i = 0; i < script_codes.size(); i++) { + menu->add_item(TranslationServer::get_singleton()->get_script_name(script_codes[i]) + " (" + script_codes[i] + ")", i); + } + } + add_child(menu); + menu->connect("id_pressed", callable_mp(this, &EditorPropertyFontMetaOverride::_add_script)); + + locale_select = memnew(EditorLocaleDialog); + locale_select->connect("locale_selected", callable_mp(this, &EditorPropertyFontMetaOverride::_add_lang)); + add_child(locale_select); +} + +/*************************************************************************/ +/* EditorPropertyOTVariation */ +/*************************************************************************/ + +void EditorPropertyOTVariation::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + } break; + } +} + +void EditorPropertyOTVariation::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) { + if (p_property.begins_with("keys")) { + Dictionary dict = object->get_dict(); + Dictionary defaults_dict = object->get_defaults(); + int key = p_property.get_slice("/", 1).to_int(); + dict[key] = (int)p_value; + if (defaults_dict.has(key)) { + Vector3i range = defaults_dict[key]; + if (range.z == (int)p_value) { + dict.erase(key); + } + } + + emit_changed(get_edited_property(), dict, "", true); + + dict = dict.duplicate(); // Duplicate, so undo/redo works better. + object->set_dict(dict); + } +} + +void EditorPropertyOTVariation::_object_id_selected(const StringName &p_property, ObjectID p_id) { + emit_signal(SNAME("object_id_selected"), p_property, p_id); +} + +void EditorPropertyOTVariation::update_property() { + Variant updated_val = get_edited_object()->get(get_edited_property()); + + Dictionary dict = updated_val; + + Ref<Font> fd; + if (Object::cast_to<Font>(get_edited_object()) != nullptr) { + fd = get_edited_object(); + } else if (Object::cast_to<DynamicFontImportSettingsData>(get_edited_object()) != nullptr) { + Ref<DynamicFontImportSettingsData> imp = Object::cast_to<DynamicFontImportSettingsData>(get_edited_object()); + fd = imp->get_font(); + } + + Dictionary supported = (fd.is_valid()) ? fd->get_supported_variation_list() : Dictionary(); + + edit->set_text(vformat(TTR("Variation Coordinates (%d)"), supported.size())); + + bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); + if (edit->is_pressed() != unfolded) { + edit->set_pressed(unfolded); + } + + if (unfolded) { + updating = true; + + if (!container) { + container = memnew(MarginContainer); + container->set_theme_type_variation("MarginContainer4px"); + add_child(container); + set_bottom_editor(container); + + VBoxContainer *vbox = memnew(VBoxContainer); + vbox->set_v_size_flags(SIZE_EXPAND_FILL); + container->add_child(vbox); + + property_vbox = memnew(VBoxContainer); + property_vbox->set_h_size_flags(SIZE_EXPAND_FILL); + vbox->add_child(property_vbox); + + paginator = memnew(EditorPaginator); + paginator->connect("page_changed", callable_mp(this, &EditorPropertyOTVariation::_page_changed)); + vbox->add_child(paginator); + } else { + // Queue children for deletion, deleting immediately might cause errors. + for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) { + property_vbox->get_child(i)->queue_delete(); + } + } + + int size = supported.size(); + + int max_page = MAX(0, size - 1) / page_length; + page_index = MIN(page_index, max_page); + + paginator->update(page_index, max_page); + paginator->set_visible(max_page > 0); + + int offset = page_index * page_length; + + int amount = MIN(size - offset, page_length); + + dict = dict.duplicate(); + object->set_dict(dict); + object->set_defaults(supported); + + for (int i = 0; i < amount; i++) { + int name_tag = supported.get_key_at_index(i); + Vector3i range = supported.get_value_at_index(i); + + EditorPropertyInteger *prop = memnew(EditorPropertyInteger); + prop->setup(range.x, range.y, 1, false, false); + prop->set_object_and_property(object.ptr(), "keys/" + itos(name_tag)); + + String name = TS->tag_to_name(name_tag); + prop->set_label(name.capitalize()); + prop->set_tooltip(name); + prop->set_selectable(false); + + prop->connect("property_changed", callable_mp(this, &EditorPropertyOTVariation::_property_changed)); + prop->connect("object_id_selected", callable_mp(this, &EditorPropertyOTVariation::_object_id_selected)); + + property_vbox->add_child(prop); + + prop->update_property(); + } + + updating = false; + } else { + if (container) { + set_bottom_editor(nullptr); + memdelete(container); + container = nullptr; + } + } +} + +void EditorPropertyOTVariation::_edit_pressed() { + Variant prop_val = get_edited_object()->get(get_edited_property()); + if (prop_val.get_type() == Variant::NIL) { + Callable::CallError ce; + Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce); + get_edited_object()->set(get_edited_property(), prop_val); + } + + get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed()); + update_property(); +} + +void EditorPropertyOTVariation::_page_changed(int p_page) { + if (updating) { + return; + } + page_index = p_page; + update_property(); +} + +EditorPropertyOTVariation::EditorPropertyOTVariation() { + object.instantiate(); + page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page")); + + edit = memnew(Button); + edit->set_h_size_flags(SIZE_EXPAND_FILL); + edit->set_clip_text(true); + edit->connect("pressed", callable_mp(this, &EditorPropertyOTVariation::_edit_pressed)); + edit->set_toggle_mode(true); + add_child(edit); + add_focusable(edit); +} + +/*************************************************************************/ +/* EditorPropertyOTFeatures */ +/*************************************************************************/ + +void EditorPropertyOTFeatures::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_THEME_CHANGED: { + if (Object::cast_to<Button>(button_add)) { + button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + } + } break; + } +} + +void EditorPropertyOTFeatures::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) { + if (p_property.begins_with("keys")) { + Dictionary dict = object->get_dict(); + int key = p_property.get_slice("/", 1).to_int(); + dict[key] = (int)p_value; + + emit_changed(get_edited_property(), dict, "", true); + + dict = dict.duplicate(); // Duplicate, so undo/redo works better. + object->set_dict(dict); + } +} + +void EditorPropertyOTFeatures::_remove(Object *p_button, int p_key) { + Dictionary dict = object->get_dict(); + + dict.erase(p_key); + + emit_changed(get_edited_property(), dict, "", false); + + dict = dict.duplicate(); // Duplicate, so undo/redo works better. + object->set_dict(dict); + update_property(); +} + +void EditorPropertyOTFeatures::_add_menu() { + Size2 size = get_size(); + menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y)); + menu->reset_size(); + menu->popup(); +} + +void EditorPropertyOTFeatures::_add_feature(int p_option) { + Dictionary dict = object->get_dict(); + + dict[p_option] = 1; + + emit_changed(get_edited_property(), dict, "", false); + + dict = dict.duplicate(); // Duplicate, so undo/redo works better. + object->set_dict(dict); + update_property(); +} + +void EditorPropertyOTFeatures::_object_id_selected(const StringName &p_property, ObjectID p_id) { + emit_signal(SNAME("object_id_selected"), p_property, p_id); +} + +void EditorPropertyOTFeatures::update_property() { + Variant updated_val = get_edited_object()->get(get_edited_property()); + + Dictionary dict = updated_val; + + Ref<Font> fd; + if (Object::cast_to<FontVariation>(get_edited_object()) != nullptr) { + fd = get_edited_object(); + } else if (Object::cast_to<DynamicFontImportSettingsData>(get_edited_object()) != nullptr) { + Ref<DynamicFontImportSettingsData> imp = Object::cast_to<DynamicFontImportSettingsData>(get_edited_object()); + fd = imp->get_font(); + } + + Dictionary supported; + if (fd.is_valid()) { + supported = fd->get_supported_feature_list(); + } + + edit->set_text(vformat(TTR("Features (%d of %d set)"), dict.size(), supported.size())); + + bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); + if (edit->is_pressed() != unfolded) { + edit->set_pressed(unfolded); + } + + if (unfolded) { + updating = true; + + if (!container) { + container = memnew(MarginContainer); + container->set_theme_type_variation("MarginContainer4px"); + add_child(container); + set_bottom_editor(container); + + VBoxContainer *vbox = memnew(VBoxContainer); + vbox->set_v_size_flags(SIZE_EXPAND_FILL); + container->add_child(vbox); + + property_vbox = memnew(VBoxContainer); + property_vbox->set_h_size_flags(SIZE_EXPAND_FILL); + vbox->add_child(property_vbox); + + paginator = memnew(EditorPaginator); + paginator->connect("page_changed", callable_mp(this, &EditorPropertyOTFeatures::_page_changed)); + vbox->add_child(paginator); + } else { + // Queue children for deletion, deleting immediately might cause errors. + for (int i = property_vbox->get_child_count() - 1; i >= 0; i--) { + property_vbox->get_child(i)->queue_delete(); + } + button_add = nullptr; + } + + // Update add menu items. + menu->clear(); + bool have_sub[FGRP_MAX]; + for (int i = 0; i < FGRP_MAX; i++) { + menu_sub[i]->clear(); + have_sub[i] = false; + } + + bool show_hidden = EDITOR_GET("interface/inspector/show_low_level_opentype_features"); + + for (int i = 0; i < supported.size(); i++) { + int name_tag = supported.get_key_at_index(i); + Dictionary info = supported.get_value_at_index(i); + bool hidden = info["hidden"].operator bool(); + String name = TS->tag_to_name(name_tag); + FeatureGroups grp = FGRP_MAX; + + if (hidden && !show_hidden) { + continue; + } + + if (name.begins_with("stylistic_set_")) { + grp = FGRP_STYLISTIC_SET; + } else if (name.begins_with("character_variant_")) { + grp = FGRP_CHARACTER_VARIANT; + } else if (name.ends_with("_capitals")) { + grp = FGRP_CAPITLS; + } else if (name.ends_with("_ligatures")) { + grp = FGRP_LIGATURES; + } else if (name.ends_with("_alternates")) { + grp = FGRP_ALTERNATES; + } else if (name.ends_with("_kanji_forms") || name.begins_with("jis") || name == "simplified_forms" || name == "traditional_name_forms" || name == "traditional_forms") { + grp = FGRP_EAL; + } else if (name.ends_with("_widths")) { + grp = FGRP_EAW; + } else if (name == "tabular_figures" || name == "proportional_figures") { + grp = FGRP_NUMAL; + } else if (name.begins_with("custom_")) { + grp = FGRP_CUSTOM; + } + String disp_name = name.capitalize(); + if (info.has("label")) { + disp_name = vformat("%s (%s)", disp_name, info["label"].operator String()); + } + + if (grp == FGRP_MAX) { + menu->add_item(disp_name, name_tag); + } else { + menu_sub[grp]->add_item(disp_name, name_tag); + have_sub[grp] = true; + } + } + for (int i = 0; i < FGRP_MAX; i++) { + if (have_sub[i]) { + menu->add_submenu_item(RTR(group_names[i]), "FTRMenu_" + itos(i)); + } + } + + int size = dict.size(); + + int max_page = MAX(0, size - 1) / page_length; + page_index = MIN(page_index, max_page); + + paginator->update(page_index, max_page); + paginator->set_visible(max_page > 0); + + int offset = page_index * page_length; + + int amount = MIN(size - offset, page_length); + + dict = dict.duplicate(); + object->set_dict(dict); + + for (int i = 0; i < amount; i++) { + int name_tag = dict.get_key_at_index(i); + + if (supported.has(name_tag)) { + Dictionary info = supported[name_tag]; + Variant::Type vtype = Variant::Type(info["type"].operator int()); + bool hidden = info["hidden"].operator bool(); + if (hidden && !show_hidden) { + continue; + } + + EditorProperty *prop = nullptr; + switch (vtype) { + case Variant::NIL: { + prop = memnew(EditorPropertyNil); + } break; + case Variant::BOOL: { + prop = memnew(EditorPropertyCheck); + } break; + case Variant::INT: { + EditorPropertyInteger *editor = memnew(EditorPropertyInteger); + editor->setup(0, 255, 1, false, false); + prop = editor; + } break; + default: { + ERR_CONTINUE_MSG(true, vformat("Unsupported OT feature data type %s", Variant::get_type_name(vtype))); + } + } + prop->set_object_and_property(object.ptr(), "keys/" + itos(name_tag)); + + String name = TS->tag_to_name(name_tag); + String disp_name = name.capitalize(); + if (info.has("label")) { + disp_name = vformat("%s (%s)", disp_name, info["label"].operator String()); + } + prop->set_label(disp_name); + prop->set_tooltip(name); + prop->set_selectable(false); + + prop->connect("property_changed", callable_mp(this, &EditorPropertyOTFeatures::_property_changed)); + prop->connect("object_id_selected", callable_mp(this, &EditorPropertyOTFeatures::_object_id_selected)); + + HBoxContainer *hbox = memnew(HBoxContainer); + property_vbox->add_child(hbox); + hbox->add_child(prop); + prop->set_h_size_flags(SIZE_EXPAND_FILL); + Button *remove = memnew(Button); + remove->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); + hbox->add_child(remove); + remove->connect("pressed", callable_mp(this, &EditorPropertyOTFeatures::_remove), varray(remove, name_tag)); + + prop->update_property(); + } + } + + button_add = EditorInspector::create_inspector_action_button(TTR("Add Feature")); + button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + button_add->connect("pressed", callable_mp(this, &EditorPropertyOTFeatures::_add_menu)); + property_vbox->add_child(button_add); + + updating = false; + } else { + if (container) { + set_bottom_editor(nullptr); + memdelete(container); + button_add = nullptr; + container = nullptr; + } + } +} + +void EditorPropertyOTFeatures::_edit_pressed() { + Variant prop_val = get_edited_object()->get(get_edited_property()); + if (prop_val.get_type() == Variant::NIL) { + Callable::CallError ce; + Variant::construct(Variant::DICTIONARY, prop_val, nullptr, 0, ce); + get_edited_object()->set(get_edited_property(), prop_val); + } + + get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed()); + update_property(); +} + +void EditorPropertyOTFeatures::_page_changed(int p_page) { + if (updating) { + return; + } + page_index = p_page; + update_property(); +} + +EditorPropertyOTFeatures::EditorPropertyOTFeatures() { + object.instantiate(); + page_length = int(EDITOR_GET("interface/inspector/max_array_dictionary_items_per_page")); + + edit = memnew(Button); + edit->set_h_size_flags(SIZE_EXPAND_FILL); + edit->set_clip_text(true); + edit->connect("pressed", callable_mp(this, &EditorPropertyOTFeatures::_edit_pressed)); + edit->set_toggle_mode(true); + add_child(edit); + add_focusable(edit); + + menu = memnew(PopupMenu); + add_child(menu); + menu->connect("id_pressed", callable_mp(this, &EditorPropertyOTFeatures::_add_feature)); + + for (int i = 0; i < FGRP_MAX; i++) { + menu_sub[i] = memnew(PopupMenu); + menu_sub[i]->set_name("FTRMenu_" + itos(i)); + menu->add_child(menu_sub[i]); + menu_sub[i]->connect("id_pressed", callable_mp(this, &EditorPropertyOTFeatures::_add_feature)); + } + + group_names[FGRP_STYLISTIC_SET] = "Stylistic Sets"; + group_names[FGRP_CHARACTER_VARIANT] = "Character Variants"; + group_names[FGRP_CAPITLS] = "Capitals"; + group_names[FGRP_LIGATURES] = "Ligatures"; + group_names[FGRP_ALTERNATES] = "Alternates"; + group_names[FGRP_EAL] = "East Asian Language"; + group_names[FGRP_EAW] = "East Asian Widths"; + group_names[FGRP_NUMAL] = "Numeral Alignment"; + group_names[FGRP_CUSTOM] = "Custom"; +} + +/*************************************************************************/ +/* EditorInspectorPluginFontVariation */ +/*************************************************************************/ + +bool EditorInspectorPluginFontVariation::can_handle(Object *p_object) { + return (Object::cast_to<FontVariation>(p_object) != nullptr) || (Object::cast_to<DynamicFontImportSettingsData>(p_object) != nullptr); +} + +bool EditorInspectorPluginFontVariation::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { + if (p_path == "variation_opentype") { + add_property_editor(p_path, memnew(EditorPropertyOTVariation)); + return true; + } else if (p_path == "opentype_features") { + add_property_editor(p_path, memnew(EditorPropertyOTFeatures)); + return true; + } else if (p_path == "language_support") { + add_property_editor(p_path, memnew(EditorPropertyFontMetaOverride(false))); + return true; + } else if (p_path == "script_support") { + add_property_editor(p_path, memnew(EditorPropertyFontMetaOverride(true))); + return true; + } + return false; +} + +/*************************************************************************/ +/* FontPreview */ +/*************************************************************************/ + +void FontPreview::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_DRAW: { + // Draw font name (style). + Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); + int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); + Color text_color = get_theme_color(SNAME("font_color"), SNAME("Label")); + font->draw_string(get_canvas_item(), Point2(0, font->get_height(font_size) + 2 * EDSCALE), name, HORIZONTAL_ALIGNMENT_CENTER, get_size().x, font_size, text_color); + + // Draw font preview. + Vector2 pos = Vector2(0, font->get_height(font_size)) + (get_size() - Vector2(0, font->get_height(font_size)) - line->get_size()) / 2; + line->draw(get_canvas_item(), pos, text_color); + + // Draw font baseline. + Color line_color = text_color; + line_color.a *= 0.6; + draw_line(Vector2(0, pos.y + line->get_line_ascent()), Vector2(pos.x - 5, pos.y + line->get_line_ascent()), line_color); + draw_line(Vector2(pos.x + line->get_size().x + 5, pos.y + line->get_line_ascent()), Vector2(get_size().x, pos.y + line->get_line_ascent()), line_color); + } break; + } +} + +void FontPreview::_bind_methods() {} + +Size2 FontPreview::get_minimum_size() const { + return Vector2(64, 64) * EDSCALE; +} + +void FontPreview::set_data(const Ref<Font> &p_f) { + line->clear(); + if (p_f.is_valid()) { + name = vformat("%s (%s)", p_f->get_font_name(), p_f->get_font_style_name()); + if (p_f->is_class("FontVariation")) { + name += " " + TTR(" - Variation"); + } + String sample; + static const String sample_base = U"12漢字ԱբΑαАбΑαאבابܐܒހށआআਆઆଆஆఆಆആආกิກິༀကႠა한글ሀᎣᐁᚁᚠᜀᜠᝀᝠកᠠᤁᥐAb😀"; + for (int i = 0; i < sample_base.length(); i++) { + if (p_f->has_char(sample_base[i])) { + sample += sample_base[i]; + } + } + if (sample.is_empty()) { + sample = p_f->get_supported_chars().substr(0, 6); + } + line->add_string(sample, p_f, 50); + } + + update(); +} + +FontPreview::FontPreview() { + line.instantiate(); +} + +/*************************************************************************/ +/* EditorInspectorPluginFontPreview */ +/*************************************************************************/ + +bool EditorInspectorPluginFontPreview::can_handle(Object *p_object) { + return Object::cast_to<Font>(p_object) != nullptr; +} + +void EditorInspectorPluginFontPreview::parse_begin(Object *p_object) { + Font *fd = Object::cast_to<Font>(p_object); + ERR_FAIL_COND(!fd); + + FontPreview *editor = memnew(FontPreview); + editor->set_data(fd); + add_custom_control(editor); +} + +bool EditorInspectorPluginFontPreview::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { + return false; +} + +/*************************************************************************/ +/* FontEditorPlugin */ +/*************************************************************************/ + +FontEditorPlugin::FontEditorPlugin() { + Ref<EditorInspectorPluginFontVariation> fc_plugin; + fc_plugin.instantiate(); + EditorInspector::add_inspector_plugin(fc_plugin); + + Ref<EditorInspectorPluginFontPreview> fp_plugin; + fp_plugin.instantiate(); + EditorInspector::add_inspector_plugin(fp_plugin); +} diff --git a/editor/plugins/font_config_plugin.h b/editor/plugins/font_config_plugin.h new file mode 100644 index 0000000000..9b7ee55870 --- /dev/null +++ b/editor/plugins/font_config_plugin.h @@ -0,0 +1,261 @@ +/*************************************************************************/ +/* font_config_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef OT_FEATURES_PLUGIN_H +#define OT_FEATURES_PLUGIN_H + +#include "core/io/marshalls.h" +#include "editor/editor_plugin.h" +#include "editor/editor_properties.h" + +/*************************************************************************/ + +class EditorPropertyFontMetaObject : public RefCounted { + GDCLASS(EditorPropertyFontMetaObject, RefCounted); + + Dictionary dict; + +protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + static void _bind_methods(); + +public: + void set_dict(const Dictionary &p_dict); + Dictionary get_dict(); + + EditorPropertyFontMetaObject(){}; +}; + +/*************************************************************************/ + +class EditorPropertyFontOTObject : public RefCounted { + GDCLASS(EditorPropertyFontOTObject, RefCounted); + + Dictionary dict; + Dictionary defaults_dict; + +protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + static void _bind_methods(); + +public: + void set_dict(const Dictionary &p_dict); + Dictionary get_dict(); + + void set_defaults(const Dictionary &p_dict); + Dictionary get_defaults(); + + bool property_can_revert(const String &p_name); + Variant property_get_revert(const String &p_name); + + EditorPropertyFontOTObject(){}; +}; + +/*************************************************************************/ + +class EditorPropertyFontMetaOverride : public EditorProperty { + GDCLASS(EditorPropertyFontMetaOverride, EditorProperty); + + Ref<EditorPropertyFontMetaObject> object; + + MarginContainer *container = nullptr; + VBoxContainer *property_vbox = nullptr; + + Button *button_add = nullptr; + Button *edit = nullptr; + PopupMenu *menu = nullptr; + EditorLocaleDialog *locale_select = nullptr; + + Vector<String> script_codes; + + bool script_editor = false; + bool updating = false; + int page_length = 20; + int page_index = 0; + EditorPaginator *paginator = nullptr; + +protected: + void _notification(int p_what); + static void _bind_methods(){}; + + void _edit_pressed(); + void _page_changed(int p_page); + void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false); + void _remove(Object *p_button, const String &p_key); + void _add_menu(); + void _add_script(int p_option); + void _add_lang(const String &p_locale); + void _object_id_selected(const StringName &p_property, ObjectID p_id); + +public: + virtual void update_property() override; + + EditorPropertyFontMetaOverride(bool p_script); +}; + +/*************************************************************************/ + +class EditorPropertyOTVariation : public EditorProperty { + GDCLASS(EditorPropertyOTVariation, EditorProperty); + + Ref<EditorPropertyFontOTObject> object; + + MarginContainer *container = nullptr; + VBoxContainer *property_vbox = nullptr; + + Button *edit = nullptr; + + bool updating = false; + int page_length = 20; + int page_index = 0; + EditorPaginator *paginator = nullptr; + +protected: + void _notification(int p_what); + static void _bind_methods(){}; + + void _edit_pressed(); + void _page_changed(int p_page); + void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false); + void _object_id_selected(const StringName &p_property, ObjectID p_id); + +public: + virtual void update_property() override; + + EditorPropertyOTVariation(); +}; + +/*************************************************************************/ + +class EditorPropertyOTFeatures : public EditorProperty { + GDCLASS(EditorPropertyOTFeatures, EditorProperty); + + enum FeatureGroups { + FGRP_STYLISTIC_SET, + FGRP_CHARACTER_VARIANT, + FGRP_CAPITLS, + FGRP_LIGATURES, + FGRP_ALTERNATES, + FGRP_EAL, + FGRP_EAW, + FGRP_NUMAL, + FGRP_CUSTOM, + FGRP_MAX, + }; + + Ref<EditorPropertyFontOTObject> object; + + MarginContainer *container = nullptr; + VBoxContainer *property_vbox = nullptr; + + Button *button_add = nullptr; + Button *edit = nullptr; + PopupMenu *menu = nullptr; + PopupMenu *menu_sub[FGRP_MAX]; + String group_names[FGRP_MAX]; + + bool updating = false; + int page_length = 20; + int page_index = 0; + EditorPaginator *paginator = nullptr; + +protected: + void _notification(int p_what); + static void _bind_methods(){}; + + void _edit_pressed(); + void _page_changed(int p_page); + void _property_changed(const String &p_property, Variant p_value, const String &p_name = "", bool p_changing = false); + void _remove(Object *p_button, int p_key); + void _add_menu(); + void _add_feature(int p_option); + void _object_id_selected(const StringName &p_property, ObjectID p_id); + +public: + virtual void update_property() override; + + EditorPropertyOTFeatures(); +}; + +/*************************************************************************/ + +class EditorInspectorPluginFontVariation : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginFontVariation, EditorInspectorPlugin); + +public: + virtual bool can_handle(Object *p_object) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; +}; + +/*************************************************************************/ + +class FontPreview : public Control { + GDCLASS(FontPreview, Control); + +protected: + void _notification(int p_what); + static void _bind_methods(); + + String name; + Ref<TextLine> line; + +public: + virtual Size2 get_minimum_size() const override; + + void set_data(const Ref<Font> &p_f); + + FontPreview(); +}; + +/*************************************************************************/ + +class EditorInspectorPluginFontPreview : public EditorInspectorPlugin { + GDCLASS(EditorInspectorPluginFontPreview, EditorInspectorPlugin); + +public: + virtual bool can_handle(Object *p_object) override; + virtual void parse_begin(Object *p_object) override; + virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; +}; + +/*************************************************************************/ + +class FontEditorPlugin : public EditorPlugin { + GDCLASS(FontEditorPlugin, EditorPlugin); + +public: + FontEditorPlugin(); + + virtual String get_name() const override { return "Font"; } +}; + +#endif // OT_FEATURES_PLUGIN_H diff --git a/editor/plugins/font_editor_plugin.cpp b/editor/plugins/font_editor_plugin.cpp deleted file mode 100644 index b9de621bcb..0000000000 --- a/editor/plugins/font_editor_plugin.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/*************************************************************************/ -/* font_editor_plugin.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "font_editor_plugin.h" - -#include "editor/editor_scale.h" - -void FontDataPreview::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_DRAW: { - Color text_color = get_theme_color(SNAME("font_color"), SNAME("Label")); - Color line_color = text_color; - line_color.a *= 0.6; - Vector2 pos = (get_size() - line->get_size()) / 2; - line->draw(get_canvas_item(), pos, text_color); - draw_line(Vector2(0, pos.y + line->get_line_ascent()), Vector2(pos.x - 5, pos.y + line->get_line_ascent()), line_color); - draw_line(Vector2(pos.x + line->get_size().x + 5, pos.y + line->get_line_ascent()), Vector2(get_size().x, pos.y + line->get_line_ascent()), line_color); - } break; - } -} - -void FontDataPreview::_bind_methods() {} - -Size2 FontDataPreview::get_minimum_size() const { - return Vector2(64, 64) * EDSCALE; -} - -void FontDataPreview::set_data(const Ref<FontData> &p_data) { - Ref<Font> f = memnew(Font); - f->add_data(p_data); - - line->clear(); - if (p_data.is_valid()) { - String sample; - static const String sample_base = U"12漢字ԱբΑαАбΑαאבابܐܒހށआআਆઆଆஆఆಆആආกิກິༀကႠა한글ሀᎣᐁᚁᚠᜀᜠᝀᝠកᠠᤁᥐAb😀"; - for (int i = 0; i < sample_base.length(); i++) { - if (p_data->has_char(sample_base[i])) { - sample += sample_base[i]; - } - } - if (sample.is_empty()) { - sample = p_data->get_supported_chars().substr(0, 6); - } - line->add_string(sample, f, 72); - } - - update(); -} - -FontDataPreview::FontDataPreview() { - line.instantiate(); -} - -/*************************************************************************/ - -bool EditorInspectorPluginFont::can_handle(Object *p_object) { - return Object::cast_to<FontData>(p_object) != nullptr; -} - -void EditorInspectorPluginFont::parse_begin(Object *p_object) { - FontData *fd = Object::cast_to<FontData>(p_object); - ERR_FAIL_COND(!fd); - - FontDataPreview *editor = memnew(FontDataPreview); - editor->set_data(fd); - add_custom_control(editor); -} - -bool EditorInspectorPluginFont::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { - return false; -} - -/*************************************************************************/ - -FontEditorPlugin::FontEditorPlugin() { - Ref<EditorInspectorPluginFont> fd_plugin; - fd_plugin.instantiate(); - EditorInspector::add_inspector_plugin(fd_plugin); -} diff --git a/editor/plugins/font_editor_plugin.h b/editor/plugins/font_editor_plugin.h deleted file mode 100644 index 3f0700d880..0000000000 --- a/editor/plugins/font_editor_plugin.h +++ /dev/null @@ -1,77 +0,0 @@ -/*************************************************************************/ -/* font_editor_plugin.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef FONT_EDITOR_PLUGIN_H -#define FONT_EDITOR_PLUGIN_H - -#include "editor/editor_plugin.h" -#include "scene/resources/font.h" -#include "scene/resources/text_line.h" - -class FontDataPreview : public Control { - GDCLASS(FontDataPreview, Control); - -protected: - void _notification(int p_what); - static void _bind_methods(); - - Ref<TextLine> line; - -public: - virtual Size2 get_minimum_size() const override; - - void set_data(const Ref<FontData> &p_data); - - FontDataPreview(); -}; - -/*************************************************************************/ - -class EditorInspectorPluginFont : public EditorInspectorPlugin { - GDCLASS(EditorInspectorPluginFont, EditorInspectorPlugin); - -public: - virtual bool can_handle(Object *p_object) override; - virtual void parse_begin(Object *p_object) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; -}; - -/*************************************************************************/ - -class FontEditorPlugin : public EditorPlugin { - GDCLASS(FontEditorPlugin, EditorPlugin); - -public: - FontEditorPlugin(); - - virtual String get_name() const override { return "Font"; } -}; - -#endif // FONT_EDITOR_PLUGIN_H diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 7730f7f294..99c492379d 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -145,7 +145,7 @@ void ViewportRotationControl::_draw_axis(const Axis2D &p_axis) { // Draw the axis letter for the positive axes. const String axis_name = direction == 0 ? "X" : (direction == 1 ? "Y" : "Z"); - draw_char(get_theme_font(SNAME("rotation_control"), SNAME("EditorFonts")), p_axis.screen_point + Vector2i(Math::round(-4.0 * EDSCALE), Math::round(5.0 * EDSCALE)), axis_name, "", get_theme_font_size(SNAME("rotation_control_size"), SNAME("EditorFonts")), Color(0.0, 0.0, 0.0, alpha)); + draw_char(get_theme_font(SNAME("rotation_control"), SNAME("EditorFonts")), p_axis.screen_point + Vector2i(Math::round(-4.0 * EDSCALE), Math::round(5.0 * EDSCALE)), axis_name, get_theme_font_size(SNAME("rotation_control_size"), SNAME("EditorFonts")), Color(0.0, 0.0, 0.0, alpha)); } else { // Draw an outline around the negative axes. draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS, c); @@ -2725,7 +2725,8 @@ static void draw_indicator_bar(Control &p_surface, real_t p_fill, const Ref<Text p_surface.draw_texture(p_icon, icon_pos, p_color); // Draw text below the bar (for speed/zoom information). - p_surface.draw_string(p_font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), p_text, HORIZONTAL_ALIGNMENT_LEFT, -1.f, p_font_size, p_color, Math::round(2 * EDSCALE), Color(0, 0, 0)); + p_surface.draw_string_outline(p_font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), p_text, HORIZONTAL_ALIGNMENT_LEFT, -1.f, p_font_size, Math::round(2 * EDSCALE), Color(0, 0, 0)); + p_surface.draw_string(p_font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), p_text, HORIZONTAL_ALIGNMENT_LEFT, -1.f, p_font_size, p_color); } void Node3DEditorViewport::_draw() { diff --git a/editor/plugins/ot_features_plugin.cpp b/editor/plugins/ot_features_plugin.cpp deleted file mode 100644 index f8526fb715..0000000000 --- a/editor/plugins/ot_features_plugin.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/*************************************************************************/ -/* ot_features_plugin.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "ot_features_plugin.h" - -#include "scene/3d/label_3d.h" -#include "scene/resources/primitive_meshes.h" - -void OpenTypeFeaturesEditor::_value_changed(double val) { - if (setting) { - return; - } - - emit_changed(get_edited_property(), spin->get_value()); -} - -void OpenTypeFeaturesEditor::update_property() { - double val = get_edited_object()->get(get_edited_property()); - setting = true; - spin->set_value(val); - setting = false; -} - -void OpenTypeFeaturesEditor::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_THEME_CHANGED: { - Color base = get_theme_color(SNAME("accent_color"), SNAME("Editor")); - - button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - button->set_size(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))->get_size()); - spin->add_theme_color_override("label_color", base); - } break; - } -} - -void OpenTypeFeaturesEditor::_remove_feature() { - get_edited_object()->set(get_edited_property(), -1); -} - -void OpenTypeFeaturesEditor::_bind_methods() { -} - -OpenTypeFeaturesEditor::OpenTypeFeaturesEditor() { - HBoxContainer *bc = memnew(HBoxContainer); - add_child(bc); - - spin = memnew(EditorSpinSlider); - spin->set_flat(true); - bc->add_child(spin); - add_focusable(spin); - spin->connect("value_changed", callable_mp(this, &OpenTypeFeaturesEditor::_value_changed)); - spin->set_h_size_flags(SIZE_EXPAND_FILL); - - spin->set_min(0); - spin->set_max(65536); - spin->set_step(1); - spin->set_hide_slider(false); - spin->set_allow_greater(false); - spin->set_allow_lesser(false); - - button = memnew(Button); - button->set_tooltip(RTR("Remove feature")); - button->set_flat(true); - bc->add_child(button); - - button->connect("pressed", callable_mp(this, &OpenTypeFeaturesEditor::_remove_feature)); - - setting = false; -} - -/*************************************************************************/ - -void OpenTypeFeaturesAdd::_add_feature(int p_option) { - edited_object->set("opentype_features/" + TS->tag_to_name(p_option), 1); -} - -void OpenTypeFeaturesAdd::_features_menu() { - Size2 size = get_size(); - menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y)); - menu->reset_size(); - menu->popup(); -} - -void OpenTypeFeaturesAdd::setup(Object *p_object) { - edited_object = p_object; - - menu->clear(); - menu_ss->clear(); - menu_cv->clear(); - menu_cu->clear(); - bool have_ss = false; - bool have_cv = false; - bool have_cu = false; - - Ref<Font> font; - - Control *ctrl = Object::cast_to<Control>(edited_object); - if (ctrl != nullptr) { - font = ctrl->get_theme_font(SNAME("font")); - } - Label3D *l3d = Object::cast_to<Label3D>(edited_object); - if (l3d != nullptr) { - font = l3d->_get_font_or_default(); - } - TextMesh *tm = Object::cast_to<TextMesh>(edited_object); - if (tm != nullptr) { - font = tm->_get_font_or_default(); - } - - if (font.is_null()) { - return; - } - - Dictionary features = font->get_feature_list(); - - for (const Variant *ftr = features.next(nullptr); ftr != nullptr; ftr = features.next(ftr)) { - String ftr_name = TS->tag_to_name(*ftr); - if (ftr_name.begins_with("stylistic_set_")) { - menu_ss->add_item(ftr_name.capitalize(), (int32_t)*ftr); - have_ss = true; - } else if (ftr_name.begins_with("character_variant_")) { - menu_cv->add_item(ftr_name.capitalize(), (int32_t)*ftr); - have_cv = true; - } else if (ftr_name.begins_with("custom_")) { - menu_cu->add_item(ftr_name.replace("custom_", ""), (int32_t)*ftr); - have_cu = true; - } else { - menu->add_item(ftr_name.capitalize(), (int32_t)*ftr); - } - } - if (have_ss) { - menu->add_submenu_item(RTR("Stylistic Sets"), "SSMenu"); - } - if (have_cv) { - menu->add_submenu_item(RTR("Character Variants"), "CVMenu"); - } - if (have_cu) { - menu->add_submenu_item(RTR("Custom"), "CUMenu"); - } -} - -void OpenTypeFeaturesAdd::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - connect("pressed", callable_mp(this, &OpenTypeFeaturesAdd::_features_menu)); - [[fallthrough]]; - } - case NOTIFICATION_THEME_CHANGED: { - set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - } break; - } -} - -void OpenTypeFeaturesAdd::_bind_methods() { -} - -OpenTypeFeaturesAdd::OpenTypeFeaturesAdd() { - set_text(TTR("Add Feature...")); - - menu = memnew(PopupMenu); - add_child(menu); - - menu_cv = memnew(PopupMenu); - menu_cv->set_name("CVMenu"); - menu->add_child(menu_cv); - - menu_ss = memnew(PopupMenu); - menu_ss->set_name("SSMenu"); - menu->add_child(menu_ss); - - menu_cu = memnew(PopupMenu); - menu_cu->set_name("CUMenu"); - menu->add_child(menu_cu); - - menu->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature)); - menu_cv->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature)); - menu_ss->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature)); - menu_cu->connect("id_pressed", callable_mp(this, &OpenTypeFeaturesAdd::_add_feature)); -} - -/*************************************************************************/ - -bool EditorInspectorPluginOpenTypeFeatures::can_handle(Object *p_object) { - return (Object::cast_to<Control>(p_object) != nullptr) || (Object::cast_to<Label3D>(p_object) != nullptr) || (Object::cast_to<TextMesh>(p_object) != nullptr); -} - -bool EditorInspectorPluginOpenTypeFeatures::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide) { - if (p_path == "opentype_features/_new") { - OpenTypeFeaturesAdd *editor = memnew(OpenTypeFeaturesAdd); - editor->setup(p_object); - add_custom_control(editor); - return true; - } else if (p_path.begins_with("opentype_features")) { - OpenTypeFeaturesEditor *editor = memnew(OpenTypeFeaturesEditor); - add_property_editor(p_path, editor); - return true; - } - return false; -} - -/*************************************************************************/ - -OpenTypeFeaturesEditorPlugin::OpenTypeFeaturesEditorPlugin() { - Ref<EditorInspectorPluginOpenTypeFeatures> ftr_plugin; - ftr_plugin.instantiate(); - EditorInspector::add_inspector_plugin(ftr_plugin); -} diff --git a/editor/plugins/ot_features_plugin.h b/editor/plugins/ot_features_plugin.h deleted file mode 100644 index 6639148080..0000000000 --- a/editor/plugins/ot_features_plugin.h +++ /dev/null @@ -1,102 +0,0 @@ -/*************************************************************************/ -/* ot_features_plugin.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef OT_FEATURES_PLUGIN_H -#define OT_FEATURES_PLUGIN_H - -#include "editor/editor_plugin.h" -#include "editor/editor_properties.h" - -/*************************************************************************/ - -class OpenTypeFeaturesEditor : public EditorProperty { - GDCLASS(OpenTypeFeaturesEditor, EditorProperty); - EditorSpinSlider *spin = nullptr; - bool setting = true; - void _value_changed(double p_val); - Button *button = nullptr; - - void _remove_feature(); - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - virtual void update_property() override; - OpenTypeFeaturesEditor(); -}; - -/*************************************************************************/ - -class OpenTypeFeaturesAdd : public Button { - GDCLASS(OpenTypeFeaturesAdd, Button); - - Object *edited_object = nullptr; - PopupMenu *menu = nullptr; - PopupMenu *menu_ss = nullptr; - PopupMenu *menu_cv = nullptr; - PopupMenu *menu_cu = nullptr; - - void _add_feature(int p_option); - void _features_menu(); - -protected: - void _notification(int p_what); - static void _bind_methods(); - -public: - void setup(Object *p_object); - - OpenTypeFeaturesAdd(); -}; - -/*************************************************************************/ - -class EditorInspectorPluginOpenTypeFeatures : public EditorInspectorPlugin { - GDCLASS(EditorInspectorPluginOpenTypeFeatures, EditorInspectorPlugin); - -public: - virtual bool can_handle(Object *p_object) override; - virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const uint32_t p_usage, const bool p_wide = false) override; -}; - -/*************************************************************************/ - -class OpenTypeFeaturesEditorPlugin : public EditorPlugin { - GDCLASS(OpenTypeFeaturesEditorPlugin, EditorPlugin); - -public: - OpenTypeFeaturesEditorPlugin(); - - virtual String get_name() const override { return "OpenTypeFeatures"; } -}; - -#endif // OT_FEATURES_PLUGIN_H diff --git a/editor/plugins/text_control_editor_plugin.cpp b/editor/plugins/text_control_editor_plugin.cpp deleted file mode 100644 index 2a5faba4a2..0000000000 --- a/editor/plugins/text_control_editor_plugin.cpp +++ /dev/null @@ -1,660 +0,0 @@ -/*************************************************************************/ -/* text_control_editor_plugin.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "text_control_editor_plugin.h" - -#include "editor/editor_node.h" -#include "editor/editor_scale.h" -#include "editor/multi_node_edit.h" - -void TextControlEditor::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - if (!EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts))) { - EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts), make_binds("")); - } - [[fallthrough]]; - } - case NOTIFICATION_THEME_CHANGED: { - clear_formatting->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - } break; - - case NOTIFICATION_EXIT_TREE: { - if (EditorFileSystem::get_singleton()->is_connected("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts))) { - EditorFileSystem::get_singleton()->disconnect("filesystem_changed", callable_mp(this, &TextControlEditor::_reload_fonts)); - } - } break; - } -} - -void TextControlEditor::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_control"), &TextControlEditor::_update_control); -} - -void TextControlEditor::_find_resources(EditorFileSystemDirectory *p_dir) { - for (int i = 0; i < p_dir->get_subdir_count(); i++) { - _find_resources(p_dir->get_subdir(i)); - } - - for (int i = 0; i < p_dir->get_file_count(); i++) { - if (p_dir->get_file_type(i) == "FontData") { - Ref<FontData> fd = ResourceLoader::load(p_dir->get_file_path(i)); - if (fd.is_valid()) { - String name = fd->get_font_name(); - String sty = fd->get_font_style_name(); - if (sty.is_empty()) { - sty = "Default"; - } - fonts[name][sty] = p_dir->get_file_path(i); - } - } - } -} - -void TextControlEditor::_reload_fonts(const String &p_path) { - fonts.clear(); - _find_resources(EditorFileSystem::get_singleton()->get_filesystem()); - _update_control(); -} - -void TextControlEditor::_update_fonts_menu() { - font_list->clear(); - font_list->add_item(TTR("[Theme Default]"), FONT_INFO_THEME_DEFAULT); - if (custom_font.is_valid()) { - font_list->add_item(TTR("[Custom Font]"), FONT_INFO_USER_CUSTOM); - } - - int id = FONT_INFO_ID; - for (const KeyValue<String, HashMap<String, String>> &E : fonts) { - font_list->add_item(E.key, id++); - } - - if (font_list->get_item_count() > 1) { - font_list->show(); - } else { - font_list->hide(); - } -} - -void TextControlEditor::_update_styles_menu() { - font_style_list->clear(); - if ((font_list->get_selected_id() >= FONT_INFO_ID)) { - const String &name = font_list->get_item_text(font_list->get_selected()); - for (KeyValue<String, String> &E : fonts[name]) { - font_style_list->add_item(E.key); - } - } else if (font_list->get_selected() >= 0) { - font_style_list->add_item("Default"); - } - - if (font_style_list->get_item_count() > 1) { - font_style_list->show(); - } else { - font_style_list->hide(); - } -} - -void TextControlEditor::_update_control() { - if (!edited_controls.is_empty()) { - String font_selected; - bool same_font = true; - String style_selected; - bool same_style = true; - int font_size = 0; - bool same_font_size = true; - int outline_size = 0; - bool same_outline_size = true; - Color font_color = Color{ 1.0f, 1.0f, 1.0f }; - bool same_font_color = true; - Color outline_color = Color{ 1.0f, 1.0f, 1.0f }; - bool same_outline_color = true; - - int count = edited_controls.size(); - for (int i = 0; i < count; ++i) { - Control *edited_control = edited_controls[i]; - - StringName edited_color; - StringName edited_font; - StringName edited_font_size; - - // Get override names. - if (Object::cast_to<RichTextLabel>(edited_control)) { - edited_color = SNAME("default_color"); - edited_font = SNAME("normal_font"); - edited_font_size = SNAME("normal_font_size"); - } else { - edited_color = SNAME("font_color"); - edited_font = SNAME("font"); - edited_font_size = SNAME("font_size"); - } - - // Get font override. - Ref<Font> font; - if (edited_control->has_theme_font_override(edited_font)) { - font = edited_control->get_theme_font(edited_font); - } - - if (font.is_valid()) { - if (font->get_data_count() != 1) { - if (i > 0) { - same_font = same_font && (custom_font == font); - } - custom_font = font; - - font_selected = TTR("[Custom Font]"); - same_style = false; - } else { - String name = font->get_data(0)->get_font_name(); - String style = font->get_data(0)->get_font_style_name(); - if (fonts.has(name) && fonts[name].has(style)) { - if (i > 0) { - same_font = same_font && (name == font_selected); - same_style = same_style && (style == style_selected); - } - font_selected = name; - style_selected = style; - } else { - if (i > 0) { - same_font = same_font && (custom_font == font); - } - custom_font = font; - - font_selected = TTR("[Custom Font]"); - same_style = false; - } - } - } else { - if (i > 0) { - same_font = same_font && (font_selected == TTR("[Theme Default]")); - } - - font_selected = TTR("[Theme Default]"); - same_style = false; - } - - int current_font_size = edited_control->get_theme_font_size(edited_font_size); - int current_outline_size = edited_control->get_theme_constant(SNAME("outline_size")); - Color current_font_color = edited_control->get_theme_color(edited_color); - Color current_outline_color = edited_control->get_theme_color(SNAME("font_outline_color")); - if (i > 0) { - same_font_size = same_font_size && (font_size == current_font_size); - same_outline_size = same_outline_size && (outline_size == current_outline_size); - same_font_color = same_font_color && (font_color == current_font_color); - same_outline_color = same_outline_color && (outline_color == current_outline_color); - } - - font_size = current_font_size; - outline_size = current_outline_size; - font_color = current_font_color; - outline_color = current_outline_color; - } - _update_fonts_menu(); - if (same_font) { - for (int j = 0; j < font_list->get_item_count(); j++) { - if (font_list->get_item_text(j) == font_selected) { - font_list->select(j); - break; - } - } - } else { - custom_font = Ref<Font>(); - font_list->select(-1); - } - - _update_styles_menu(); - if (same_style) { - for (int j = 0; j < font_style_list->get_item_count(); j++) { - if (font_style_list->get_item_text(j) == style_selected) { - font_style_list->select(j); - break; - } - } - } else { - font_style_list->select(-1); - } - - // Get other theme overrides. - font_size_list->set_block_signals(true); - if (same_font_size) { - font_size_list->get_line_edit()->set_text(String::num_uint64(font_size)); - font_size_list->set_value(font_size); - } else { - font_size_list->get_line_edit()->set_text(""); - } - font_size_list->set_block_signals(false); - - outline_size_list->set_block_signals(true); - if (same_outline_size) { - outline_size_list->get_line_edit()->set_text(String::num_uint64(outline_size)); - outline_size_list->set_value(outline_size); - } else { - outline_size_list->get_line_edit()->set_text(""); - } - outline_size_list->set_block_signals(false); - - if (!same_font_color) { - font_color = Color{ 1.0f, 1.0f, 1.0f }; - } - font_color_picker->set_pick_color(font_color); - - if (!same_outline_color) { - outline_color = Color{ 1.0f, 1.0f, 1.0f }; - } - outline_color_picker->set_pick_color(outline_color); - } -} - -void TextControlEditor::_font_selected(int p_id) { - _update_styles_menu(); - _set_font(); -} - -void TextControlEditor::_font_style_selected(int p_id) { - _set_font(); -} - -void TextControlEditor::_set_font() { - if (edited_controls.is_empty()) { - return; - } - - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Set Font")); - - int count = edited_controls.size(); - for (int i = 0; i < count; ++i) { - Control *edited_control = edited_controls[i]; - - StringName edited_font; - if (Object::cast_to<RichTextLabel>(edited_control)) { - edited_font = SNAME("normal_font"); - } else { - edited_font = SNAME("font"); - } - - if (font_list->get_selected_id() == FONT_INFO_THEME_DEFAULT) { - // Remove font override. - ur->add_do_method(edited_control, "remove_theme_font_override", edited_font); - } else if (font_list->get_selected_id() == FONT_INFO_USER_CUSTOM) { - // Restore "custom_font". - ur->add_do_method(edited_control, "add_theme_font_override", edited_font, custom_font); - } else if (font_list->get_selected() >= 0) { - // Load new font resource using selected name and style. - String name = font_list->get_item_text(font_list->get_selected()); - String style = font_style_list->get_item_text(font_style_list->get_selected()); - if (style.is_empty()) { - style = "Default"; - } - if (fonts.has(name)) { - Ref<FontData> fd = ResourceLoader::load(fonts[name][style]); - if (fd.is_valid()) { - Ref<Font> font; - font.instantiate(); - font->add_data(fd); - ur->add_do_method(edited_control, "add_theme_font_override", edited_font, font); - } - } - } - - if (edited_control->has_theme_font_override(edited_font)) { - ur->add_undo_method(edited_control, "add_theme_font_override", edited_font, edited_control->get_theme_font(edited_font)); - } else { - ur->add_undo_method(edited_control, "remove_theme_font_override", edited_font); - } - } - - ur->add_do_method(this, "_update_control"); - ur->add_undo_method(this, "_update_control"); - - ur->commit_action(); -} - -void TextControlEditor::_font_size_selected(double p_size) { - if (edited_controls.is_empty()) { - return; - } - - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Set Font Size")); - - int count = edited_controls.size(); - for (int i = 0; i < count; ++i) { - Control *edited_control = edited_controls[i]; - - StringName edited_font_size; - if (Object::cast_to<RichTextLabel>(edited_control)) { - edited_font_size = SNAME("normal_font_size"); - } else { - edited_font_size = SNAME("font_size"); - } - - ur->add_do_method(edited_control, "add_theme_font_size_override", edited_font_size, p_size); - if (edited_control->has_theme_font_size_override(edited_font_size)) { - ur->add_undo_method(edited_control, "add_theme_font_size_override", edited_font_size, edited_control->get_theme_font_size(edited_font_size)); - } else { - ur->add_undo_method(edited_control, "remove_theme_font_size_override", edited_font_size); - } - } - - ur->add_do_method(this, "_update_control"); - ur->add_undo_method(this, "_update_control"); - - ur->commit_action(); -} - -void TextControlEditor::_outline_size_selected(double p_size) { - if (edited_controls.is_empty()) { - return; - } - - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Set Font Outline Size")); - - int count = edited_controls.size(); - for (int i = 0; i < count; ++i) { - Control *edited_control = edited_controls[i]; - - ur->add_do_method(edited_control, "add_theme_constant_override", "outline_size", p_size); - if (edited_control->has_theme_constant_override("outline_size")) { - ur->add_undo_method(edited_control, "add_theme_constant_override", "outline_size", edited_control->get_theme_constant(SNAME("outline_size"))); - } else { - ur->add_undo_method(edited_control, "remove_theme_constant_override", "outline_size"); - } - } - - ur->add_do_method(this, "_update_control"); - ur->add_undo_method(this, "_update_control"); - - ur->commit_action(); -} - -void TextControlEditor::_font_color_changed(const Color &p_color) { - if (edited_controls.is_empty()) { - return; - } - - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Set Font Color"), UndoRedo::MERGE_ENDS); - - int count = edited_controls.size(); - for (int i = 0; i < count; ++i) { - Control *edited_control = edited_controls[i]; - - StringName edited_color; - if (Object::cast_to<RichTextLabel>(edited_control)) { - edited_color = SNAME("default_color"); - } else { - edited_color = SNAME("font_color"); - } - - ur->add_do_method(edited_control, "add_theme_color_override", edited_color, p_color); - if (edited_control->has_theme_color_override(edited_color)) { - ur->add_undo_method(edited_control, "add_theme_color_override", edited_color, edited_control->get_theme_color(edited_color)); - } else { - ur->add_undo_method(edited_control, "remove_theme_color_override", edited_color); - } - } - - ur->add_do_method(this, "_update_control"); - ur->add_undo_method(this, "_update_control"); - - ur->commit_action(); -} - -void TextControlEditor::_outline_color_changed(const Color &p_color) { - if (edited_controls.is_empty()) { - return; - } - - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Set Font Outline Color"), UndoRedo::MERGE_ENDS); - - int count = edited_controls.size(); - for (int i = 0; i < count; ++i) { - Control *edited_control = edited_controls[i]; - - ur->add_do_method(edited_control, "add_theme_color_override", "font_outline_color", p_color); - if (edited_control->has_theme_color_override("font_outline_color")) { - ur->add_undo_method(edited_control, "add_theme_color_override", "font_outline_color", edited_control->get_theme_color(SNAME("font_outline_color"))); - } else { - ur->add_undo_method(edited_control, "remove_theme_color_override", "font_outline_color"); - } - } - - ur->add_do_method(this, "_update_control"); - ur->add_undo_method(this, "_update_control"); - - ur->commit_action(); -} - -void TextControlEditor::_clear_formatting() { - if (edited_controls.is_empty()) { - return; - } - - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Clear Control Formatting")); - - int count = edited_controls.size(); - for (int i = 0; i < count; ++i) { - Control *edited_control = edited_controls[i]; - - StringName edited_color; - StringName edited_font; - StringName edited_font_size; - - // Get override names. - if (Object::cast_to<RichTextLabel>(edited_control)) { - edited_color = SNAME("default_color"); - edited_font = SNAME("normal_font"); - edited_font_size = SNAME("normal_font_size"); - } else { - edited_color = SNAME("font_color"); - edited_font = SNAME("font"); - edited_font_size = SNAME("font_size"); - } - - ur->add_do_method(edited_control, "begin_bulk_theme_override"); - ur->add_undo_method(edited_control, "begin_bulk_theme_override"); - - ur->add_do_method(edited_control, "remove_theme_font_override", edited_font); - if (edited_control->has_theme_font_override(edited_font)) { - ur->add_undo_method(edited_control, "add_theme_font_override", edited_font, edited_control->get_theme_font(edited_font)); - } - - ur->add_do_method(edited_control, "remove_theme_font_size_override", edited_font_size); - if (edited_control->has_theme_font_size_override(edited_font_size)) { - ur->add_undo_method(edited_control, "add_theme_font_size_override", edited_font_size, edited_control->get_theme_font_size(edited_font_size)); - } - - ur->add_do_method(edited_control, "remove_theme_color_override", edited_color); - if (edited_control->has_theme_color_override(edited_color)) { - ur->add_undo_method(edited_control, "add_theme_color_override", edited_color, edited_control->get_theme_color(edited_color)); - } - - ur->add_do_method(edited_control, "remove_theme_color_override", "font_outline_color"); - if (edited_control->has_theme_color_override("font_outline_color")) { - ur->add_undo_method(edited_control, "add_theme_color_override", "font_outline_color", edited_control->get_theme_color(SNAME("font_outline_color"))); - } - - ur->add_do_method(edited_control, "remove_theme_constant_override", "outline_size"); - if (edited_control->has_theme_constant_override("outline_size")) { - ur->add_undo_method(edited_control, "add_theme_constant_override", "outline_size", edited_control->get_theme_constant(SNAME("outline_size"))); - } - - ur->add_do_method(edited_control, "end_bulk_theme_override"); - ur->add_undo_method(edited_control, "end_bulk_theme_override"); - } - - ur->add_do_method(this, "_update_control"); - ur->add_undo_method(this, "_update_control"); - - ur->commit_action(); -} - -void TextControlEditor::edit(Object *p_object) { - Control *ctrl = Object::cast_to<Control>(p_object); - MultiNodeEdit *multi_node = Object::cast_to<MultiNodeEdit>(p_object); - - edited_controls.clear(); - custom_font = Ref<Font>(); - if (ctrl) { - edited_controls.append(ctrl); - _update_control(); - } else if (multi_node && handles(multi_node)) { - int count = multi_node->get_node_count(); - Node *scene = EditorNode::get_singleton()->get_edited_scene(); - - for (int i = 0; i < count; ++i) { - Control *child = Object::cast_to<Control>(scene->get_node(multi_node->get_node(i))); - edited_controls.append(child); - } - _update_control(); - } -} - -bool TextControlEditor::handles(Object *p_object) const { - Control *ctrl = Object::cast_to<Control>(p_object); - MultiNodeEdit *multi_node = Object::cast_to<MultiNodeEdit>(p_object); - - if (!ctrl && !multi_node) { - return false; - } else if (ctrl) { - bool valid = false; - ctrl->get("text", &valid); - return valid; - } else { - bool valid = true; - int count = multi_node->get_node_count(); - Node *scene = EditorNode::get_singleton()->get_edited_scene(); - - for (int i = 0; i < count; ++i) { - bool temp_valid = false; - Control *child = Object::cast_to<Control>(scene->get_node(multi_node->get_node(i))); - if (child) { - child->get("text", &temp_valid); - } - valid = valid && temp_valid; - - if (!valid) { - break; - } - } - - return valid; - } -} - -TextControlEditor::TextControlEditor() { - add_child(memnew(VSeparator)); - - font_list = memnew(OptionButton); - font_list->set_flat(true); - font_list->set_tooltip(TTR("Font")); - add_child(font_list); - font_list->connect("item_selected", callable_mp(this, &TextControlEditor::_font_selected)); - - font_style_list = memnew(OptionButton); - font_style_list->set_flat(true); - font_style_list->set_tooltip(TTR("Font style")); - font_style_list->set_toggle_mode(true); - add_child(font_style_list); - font_style_list->connect("item_selected", callable_mp(this, &TextControlEditor::_font_style_selected)); - - font_size_list = memnew(SpinBox); - font_size_list->set_tooltip(TTR("Font Size")); - font_size_list->get_line_edit()->add_theme_constant_override("minimum_character_width", 2); - font_size_list->set_min(6); - font_size_list->set_step(1); - font_size_list->set_max(96); - font_size_list->get_line_edit()->set_flat(true); - add_child(font_size_list); - font_size_list->connect("value_changed", callable_mp(this, &TextControlEditor::_font_size_selected)); - - font_color_picker = memnew(ColorPickerButton); - font_color_picker->set_custom_minimum_size(Size2(20, 0) * EDSCALE); - font_color_picker->set_flat(true); - font_color_picker->set_tooltip(TTR("Text Color")); - add_child(font_color_picker); - font_color_picker->connect("color_changed", callable_mp(this, &TextControlEditor::_font_color_changed)); - - add_child(memnew(VSeparator)); - - outline_size_list = memnew(SpinBox); - outline_size_list->set_tooltip(TTR("Outline Size")); - outline_size_list->get_line_edit()->add_theme_constant_override("minimum_character_width", 2); - outline_size_list->set_min(0); - outline_size_list->set_step(1); - outline_size_list->set_max(96); - outline_size_list->get_line_edit()->set_flat(true); - add_child(outline_size_list); - outline_size_list->connect("value_changed", callable_mp(this, &TextControlEditor::_outline_size_selected)); - - outline_color_picker = memnew(ColorPickerButton); - outline_color_picker->set_custom_minimum_size(Size2(20, 0) * EDSCALE); - outline_color_picker->set_flat(true); - outline_color_picker->set_tooltip(TTR("Outline Color")); - add_child(outline_color_picker); - outline_color_picker->connect("color_changed", callable_mp(this, &TextControlEditor::_outline_color_changed)); - - add_child(memnew(VSeparator)); - - clear_formatting = memnew(Button); - clear_formatting->set_flat(true); - clear_formatting->set_tooltip(TTR("Clear Formatting")); - add_child(clear_formatting); - clear_formatting->connect("pressed", callable_mp(this, &TextControlEditor::_clear_formatting)); -} - -/*************************************************************************/ - -void TextControlEditorPlugin::edit(Object *p_object) { - text_ctl_editor->edit(p_object); -} - -bool TextControlEditorPlugin::handles(Object *p_object) const { - return text_ctl_editor->handles(p_object); -} - -void TextControlEditorPlugin::make_visible(bool p_visible) { - if (p_visible) { - text_ctl_editor->show(); - } else { - text_ctl_editor->hide(); - text_ctl_editor->edit(nullptr); - } -} - -TextControlEditorPlugin::TextControlEditorPlugin() { - text_ctl_editor = memnew(TextControlEditor); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(text_ctl_editor); - - text_ctl_editor->hide(); -} diff --git a/editor/plugins/text_control_editor_plugin.h b/editor/plugins/text_control_editor_plugin.h deleted file mode 100644 index cf069338b6..0000000000 --- a/editor/plugins/text_control_editor_plugin.h +++ /dev/null @@ -1,115 +0,0 @@ -/*************************************************************************/ -/* text_control_editor_plugin.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef TEXT_CONTROL_EDITOR_PLUGIN_H -#define TEXT_CONTROL_EDITOR_PLUGIN_H - -#include "canvas_item_editor_plugin.h" -#include "editor/editor_file_system.h" -#include "editor/editor_inspector.h" -#include "editor/editor_plugin.h" -#include "scene/gui/color_picker.h" -#include "scene/gui/color_rect.h" -#include "scene/gui/menu_button.h" -#include "scene/gui/option_button.h" -#include "scene/gui/popup_menu.h" - -/*************************************************************************/ - -class TextControlEditor : public HBoxContainer { - GDCLASS(TextControlEditor, HBoxContainer); - - enum FontInfoID { - FONT_INFO_THEME_DEFAULT = 0, - FONT_INFO_USER_CUSTOM = 1, - FONT_INFO_ID = 100, - }; - - HashMap<String, HashMap<String, String>> fonts; - - OptionButton *font_list = nullptr; - SpinBox *font_size_list = nullptr; - OptionButton *font_style_list = nullptr; - ColorPickerButton *font_color_picker = nullptr; - SpinBox *outline_size_list = nullptr; - ColorPickerButton *outline_color_picker = nullptr; - Button *clear_formatting = nullptr; - - Vector<Control *> edited_controls; - Ref<Font> custom_font; - -protected: - void _notification(int p_what); - static void _bind_methods(); - - void _find_resources(EditorFileSystemDirectory *p_dir); - void _reload_fonts(const String &p_path); - - void _update_fonts_menu(); - void _update_styles_menu(); - void _update_control(); - - void _font_selected(int p_id); - void _font_style_selected(int p_id); - void _set_font(); - - void _font_size_selected(double p_size); - void _outline_size_selected(double p_size); - - void _font_color_changed(const Color &p_color); - void _outline_color_changed(const Color &p_color); - - void _clear_formatting(); - -public: - void edit(Object *p_object); - bool handles(Object *p_object) const; - - TextControlEditor(); -}; - -/*************************************************************************/ - -class TextControlEditorPlugin : public EditorPlugin { - GDCLASS(TextControlEditorPlugin, EditorPlugin); - - TextControlEditor *text_ctl_editor = nullptr; - -public: - virtual String get_name() const override { return "TextControlFontEditor"; } - bool has_main_screen() const override { return false; } - virtual void edit(Object *p_object) override; - virtual bool handles(Object *p_object) const override; - virtual void make_visible(bool p_visible) override; - - TextControlEditorPlugin(); -}; - -#endif // TEXT_CONTROL_EDITOR_PLUGIN_H diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index c7dc61b3a8..b01b90cd08 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -2931,10 +2931,6 @@ void ThemeTypeEditor::_item_remove_cbk(int p_data_type, String p_item_name) { ur->add_undo_method(*edited_theme, "set_font", p_item_name, edited_type, Ref<Font>()); } } break; - case Theme::DATA_TYPE_FONT_SIZE: { - ur->add_do_method(*edited_theme, "clear_font_size", p_item_name, edited_type); - ur->add_undo_method(*edited_theme, "set_font_size", p_item_name, edited_type, edited_theme->get_font_size(p_item_name, edited_type)); - } break; case Theme::DATA_TYPE_ICON: { ur->add_do_method(*edited_theme, "clear_icon", p_item_name, edited_type); if (edited_theme->has_icon(p_item_name, edited_type)) { @@ -3698,7 +3694,7 @@ bool ThemeEditorPlugin::handles(Object *p_node) const { // If we are editing a theme already and this particular resource happens to belong to it, // then we just keep editing it, despite not being able to directly handle it. - // This only goes one layer deep, but if required this can be extended to support, say, FontData inside of Font. + // This only goes one layer deep, but if required this can be extended to support, say, Font inside of Font. bool belongs_to_theme = false; if (Object::cast_to<Font>(p_node)) { diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp index a6e34cf5e0..826631d750 100644 --- a/editor/plugins/theme_editor_preview.cpp +++ b/editor/plugins/theme_editor_preview.cpp @@ -126,7 +126,7 @@ void ThemeEditorPreview::_draw_picker_overlay() { } Rect2 highlight_label_rect = highlight_rect; - highlight_label_rect.size = theme_cache.preview_picker_font->get_string_size(highlight_name, theme_cache.font_size); + highlight_label_rect.size = theme_cache.preview_picker_font->get_string_size(highlight_name, HORIZONTAL_ALIGNMENT_LEFT, -1, theme_cache.font_size); int margin_top = theme_cache.preview_picker_label->get_margin(SIDE_TOP); int margin_left = theme_cache.preview_picker_label->get_margin(SIDE_LEFT); diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index 468681c967..1263ee5758 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -218,7 +218,7 @@ void GenericTilePolygonEditor::_base_control_draw() { Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label")); int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label")); String text = multiple_polygon_mode ? vformat("%d:%d", tinted_polygon_index, tinted_point_index) : vformat("%d", tinted_point_index); - Size2 text_size = font->get_string_size(text, font_size); + Size2 text_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); base_control->draw_string(font, xform.xform(polygons[tinted_polygon_index][tinted_point_index]) - text_size * 0.5, text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color(1.0, 1.0, 1.0, 0.5)); } @@ -1116,8 +1116,9 @@ void TileDataDefaultEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform2 } } - Vector2 string_size = font->get_string_size(text, font_size); - p_canvas_item->draw_string(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1)); + Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); + p_canvas_item->draw_string_outline(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1)); + p_canvas_item->draw_string(font, p_transform.get_origin() + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color); } } @@ -1727,8 +1728,9 @@ void TileDataTerrainsEditor::forward_draw_over_atlas(TileAtlasView *p_tile_atlas } else { text = "-"; } - Vector2 string_size = font->get_string_size(text, font_size); - p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1)); + Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); + p_canvas_item->draw_string_outline(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1)); + p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color); } } } @@ -1918,8 +1920,9 @@ void TileDataTerrainsEditor::forward_draw_over_alternatives(TileAtlasView *p_til } else { text = "-"; } - Vector2 string_size = font->get_string_size(text, font_size); - p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color, 1, Color(0, 0, 0, 1)); + Vector2 string_size = font->get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size); + p_canvas_item->draw_string_outline(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, 1, Color(0, 0, 0, 1)); + p_canvas_item->draw_string(font, p_transform.xform(position) + Vector2i(-string_size.x / 2, string_size.y / 2), text, HORIZONTAL_ALIGNMENT_CENTER, string_size.x, font_size, color); } } } |