[Complex Text Layouts] Refactor Font class, default themes and controls to use Text Server interface.

Implement interface mirroring.
Add TextLine and TextParagraph classes.
Handle UTF-16 input on macOS and Windows.
This commit is contained in:
bruvzg 2020-09-03 14:22:16 +03:00
parent 07d14f5bb8
commit 99666de00f
No known key found for this signature in database
GPG Key ID: FCED35F1CECE0D3A
162 changed files with 7008 additions and 3564 deletions

View File

@ -128,6 +128,7 @@ void register_global_constants() {
BIND_CORE_ENUM_CONSTANT(HALIGN_LEFT);
BIND_CORE_ENUM_CONSTANT(HALIGN_CENTER);
BIND_CORE_ENUM_CONSTANT(HALIGN_RIGHT);
BIND_CORE_ENUM_CONSTANT(HALIGN_FILL);
BIND_CORE_ENUM_CONSTANT(VALIGN_TOP);
BIND_CORE_ENUM_CONSTANT(VALIGN_CENTER);

View File

@ -73,7 +73,8 @@ enum Orientation {
enum HAlign {
HALIGN_LEFT,
HALIGN_CENTER,
HALIGN_RIGHT
HALIGN_RIGHT,
HALIGN_FILL,
};
enum VAlign {

View File

@ -34,6 +34,11 @@
#include "core/io/resource_loader.h"
#include "core/os/os.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_settings.h"
#include "main/main.h"
#endif
// ISO 639-1 language codes, with the addition of glibc locales with their
// regional identifiers. This list must match the language names (in English)
// of locale_names.
@ -1214,6 +1219,22 @@ void TranslationServer::set_tool_translation(const Ref<Translation> &p_translati
tool_translation = p_translation;
}
Ref<Translation> TranslationServer::get_tool_translation() const {
return tool_translation;
}
String TranslationServer::get_tool_locale() {
#ifdef TOOLS_ENABLED
if (TranslationServer::get_singleton()->get_tool_translation().is_valid() && (Engine::get_singleton()->is_editor_hint() || Main::is_project_manager())) {
return tool_translation->get_locale();
} else {
#else
{
#endif
return get_locale();
}
}
StringName TranslationServer::tool_translate(const StringName &p_message, const StringName &p_context) const {
if (tool_translation.is_valid()) {
StringName r = tool_translation->get_message(p_message, p_context);

View File

@ -110,7 +110,9 @@ public:
static String standardize_locale(const String &p_locale);
static String get_language_code(const String &p_locale);
String get_tool_locale();
void set_tool_translation(const Ref<Translation> &p_translation);
Ref<Translation> get_tool_translation() const;
StringName tool_translate(const StringName &p_message, const StringName &p_context = "") const;
StringName tool_translate_plural(const StringName &p_message, const StringName &p_message_plural, int p_n, const StringName &p_context = "") const;
void set_doc_translation(const Ref<Translation> &p_translation);

View File

@ -114,6 +114,24 @@ static inline uint32_t make_uint32_t(T p_in) {
return _u._u32;
}
static inline uint64_t hash_djb2_one_float_64(double p_in, uint64_t p_prev = 5381) {
union {
double d;
uint64_t i;
} u;
// Normalize +/- 0.0 and NaN values so they hash the same.
if (p_in == 0.0f) {
u.d = 0.0;
} else if (Math::is_nan(p_in)) {
u.d = Math_NAN;
} else {
u.d = p_in;
}
return ((p_prev << 5) + p_prev) + u.i;
}
static inline uint64_t hash_djb2_one_64(uint64_t p_in, uint64_t p_prev = 5381) {
return ((p_prev << 5) + p_prev) + p_in;
}

View File

@ -1,112 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="BitmapFont" inherits="Font" version="4.0">
<brief_description>
Renders text using fonts under the [url=https://www.angelcode.com/products/bmfont/]BMFont[/url] format.
Handles files with the [code].fnt[/code] extension.
</brief_description>
<description>
Renders text using [code]*.fnt[/code] fonts containing texture atlases. Supports distance fields. For using vector font files like TTF directly, see [DynamicFont].
</description>
<tutorials>
</tutorials>
<methods>
<method name="add_char">
<return type="void">
</return>
<argument index="0" name="character" type="int">
</argument>
<argument index="1" name="texture" type="int">
</argument>
<argument index="2" name="rect" type="Rect2">
</argument>
<argument index="3" name="align" type="Vector2" default="Vector2( 0, 0 )">
</argument>
<argument index="4" name="advance" type="float" default="-1">
</argument>
<description>
Adds a character to the font, where [code]character[/code] is the Unicode value, [code]texture[/code] is the texture index, [code]rect[/code] is the region in the texture (in pixels!), [code]align[/code] is the (optional) alignment for the character and [code]advance[/code] is the (optional) advance.
</description>
</method>
<method name="add_kerning_pair">
<return type="void">
</return>
<argument index="0" name="char_a" type="int">
</argument>
<argument index="1" name="char_b" type="int">
</argument>
<argument index="2" name="kerning" type="int">
</argument>
<description>
Adds a kerning pair to the [BitmapFont] as a difference. Kerning pairs are special cases where a typeface advance is determined by the next character.
</description>
</method>
<method name="add_texture">
<return type="void">
</return>
<argument index="0" name="texture" type="Texture2D">
</argument>
<description>
Adds a texture to the [BitmapFont].
</description>
</method>
<method name="clear">
<return type="void">
</return>
<description>
Clears all the font data and settings.
</description>
</method>
<method name="create_from_fnt">
<return type="int" enum="Error">
</return>
<argument index="0" name="path" type="String">
</argument>
<description>
Creates a BitmapFont from the [code]*.fnt[/code] file at [code]path[/code].
</description>
</method>
<method name="get_kerning_pair" qualifiers="const">
<return type="int">
</return>
<argument index="0" name="char_a" type="int">
</argument>
<argument index="1" name="char_b" type="int">
</argument>
<description>
Returns a kerning pair as a difference.
</description>
</method>
<method name="get_texture" qualifiers="const">
<return type="Texture2D">
</return>
<argument index="0" name="idx" type="int">
</argument>
<description>
Returns the font atlas texture at index [code]idx[/code].
</description>
</method>
<method name="get_texture_count" qualifiers="const">
<return type="int">
</return>
<description>
Returns the number of textures in the BitmapFont atlas.
</description>
</method>
</methods>
<members>
<member name="ascent" type="float" setter="set_ascent" getter="get_ascent" default="0.0">
Ascent (number of pixels above the baseline).
</member>
<member name="distance_field" type="bool" setter="set_distance_field_hint" getter="is_distance_field_hint" default="false">
If [code]true[/code], distance field hint is enabled.
</member>
<member name="fallback" type="BitmapFont" setter="set_fallback" getter="get_fallback">
The fallback font.
</member>
<member name="height" type="float" setter="set_height" getter="get_height" default="1.0">
Total font height (ascent plus descent) in pixels.
</member>
</members>
<constants>
</constants>
</class>

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="DynamicFontData" inherits="Resource" version="4.0">
<brief_description>
Used with [DynamicFont] to describe the location of a font file.
</brief_description>
<description>
Used with [DynamicFont] to describe the location of a vector font file for dynamic rendering at runtime.
</description>
<tutorials>
<link title="3D Voxel Demo">https://godotengine.org/asset-library/asset/676</link>
</tutorials>
<methods>
</methods>
<members>
<member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased" default="true">
If [code]true[/code], the font is rendered with anti-aliasing. This property applies both to the main font and its outline (if it has one).
</member>
<member name="font_path" type="String" setter="set_font_path" getter="get_font_path" default="&quot;&quot;">
The path to the vector font file.
</member>
<member name="hinting" type="int" setter="set_hinting" getter="get_hinting" enum="DynamicFontData.Hinting" default="2">
The font hinting mode used by FreeType. See [enum Hinting] for options.
</member>
</members>
<constants>
<constant name="HINTING_NONE" value="0" enum="Hinting">
Disables font hinting (smoother but less crisp).
</constant>
<constant name="HINTING_LIGHT" value="1" enum="Hinting">
Use the light font hinting mode.
</constant>
<constant name="HINTING_NORMAL" value="2" enum="Hinting">
Use the default font hinting mode (crisper but less smooth).
</constant>
</constants>
</class>

View File

@ -1,128 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Font" inherits="Resource" version="4.0">
<brief_description>
Internationalized font and text drawing support.
</brief_description>
<description>
Font contains a Unicode-compatible character set, as well as the ability to draw it with variable width, ascent, descent and kerning. For creating fonts from TTF files (or other font formats), see the editor support for fonts.
[b]Note:[/b] If a DynamicFont doesn't contain a character used in a string, the character in question will be replaced with codepoint [code]0xfffd[/code] if it's available in the DynamicFont. If this replacement character isn't available in the DynamicFont, the character will be hidden without displaying any replacement character in the string.
[b]Note:[/b] If a BitmapFont doesn't contain a character used in a string, the character in question will be hidden without displaying any replacement character in the string.
</description>
<tutorials>
</tutorials>
<methods>
<method name="draw" qualifiers="const">
<return type="void">
</return>
<argument index="0" name="canvas_item" type="RID">
</argument>
<argument index="1" name="position" type="Vector2">
</argument>
<argument index="2" name="string" type="String">
</argument>
<argument index="3" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
</argument>
<argument index="4" name="clip_w" type="int" default="-1">
</argument>
<argument index="5" name="outline_modulate" type="Color" default="Color( 1, 1, 1, 1 )">
</argument>
<description>
Draw [code]string[/code] into a canvas item using the font at a given position, with [code]modulate[/code] color, and optionally clipping the width. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
See also [method CanvasItem.draw_string].
</description>
</method>
<method name="draw_char" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="canvas_item" type="RID">
</argument>
<argument index="1" name="position" type="Vector2">
</argument>
<argument index="2" name="char" type="int">
</argument>
<argument index="3" name="next" type="int" default="-1">
</argument>
<argument index="4" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
</argument>
<argument index="5" name="outline" type="bool" default="false">
</argument>
<description>
Draw character [code]char[/code] into a canvas item using the font at a given position, with [code]modulate[/code] color, and optionally kerning if [code]next[/code] is passed. clipping the width. [code]position[/code] specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis. The width used by the character is returned, making this function useful for drawing strings character by character.
</description>
</method>
<method name="get_ascent" qualifiers="const">
<return type="float">
</return>
<description>
Returns the font ascent (number of pixels above the baseline).
</description>
</method>
<method name="get_char_size" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="char" type="int">
</argument>
<argument index="1" name="next" type="int" default="0">
</argument>
<description>
Returns the size of a character, optionally taking kerning into account if the next character is provided.
</description>
</method>
<method name="get_descent" qualifiers="const">
<return type="float">
</return>
<description>
Returns the font descent (number of pixels below the baseline).
</description>
</method>
<method name="get_height" qualifiers="const">
<return type="float">
</return>
<description>
Returns the total font height (ascent plus descent) in pixels.
</description>
</method>
<method name="get_string_size" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="string" type="String">
</argument>
<description>
Returns the size of a string, taking kerning and advance into account.
</description>
</method>
<method name="get_wordwrap_string_size" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="string" type="String">
</argument>
<argument index="1" name="width" type="float">
</argument>
<description>
Returns the size that the string would have with word wrapping enabled with a fixed [code]width[/code].
</description>
</method>
<method name="has_outline" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the font has an outline.
</description>
</method>
<method name="is_distance_field_hint" qualifiers="const">
<return type="bool">
</return>
<description>
</description>
</method>
<method name="update_changes">
<return type="void">
</return>
<description>
After editing a font (changing size, ascent, char rects, etc.). Call this function to propagate changes to controls that might use it.
</description>
</method>
</methods>
<constants>
</constants>
</class>

View File

@ -111,7 +111,7 @@
[Color] of the text's shadow effect.
</theme_item>
<theme_item name="font_outline_modulate" type="Color" default="Color( 1, 1, 1, 1 )">
The tint of [Font]'s outline. See [member DynamicFont.outline_color].
The tint of [Font]'s outline.
</theme_item>
<theme_item name="line_spacing" type="int" default="3">
Vertical space between lines in multiline [Label].

View File

@ -32,6 +32,7 @@
#include "editor/editor_node.h"
#include "editor_scale.h"
#include "scene/resources/text_line.h"
float AnimationBezierTrackEdit::_bezier_h_to_pixel(float p_h) {
float h = p_h;
@ -247,6 +248,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
}
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
Color color = get_theme_color("font_color", "Label");
int hsep = get_theme_constant("hseparation", "ItemList");
int vsep = get_theme_constant("vseparation", "ItemList");
@ -286,26 +288,27 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
String text;
int h = font->get_height();
if (node) {
int ofs = 0;
Ref<Texture2D> icon = EditorNode::get_singleton()->get_object_icon(node, "Node");
h = MAX(h, icon->get_height());
text = node->get_name();
ofs += hsep;
ofs += icon->get_width();
TextLine text_buf = TextLine(text, font, font_size);
text_buf.set_width(limit - ofs - hsep);
int h = MAX(text_buf.get_size().y, icon->get_height());
draw_texture(icon, Point2(ofs, vofs + int(h - icon->get_height()) / 2));
margin = icon->get_width();
text = node->get_name();
ofs += hsep;
ofs += icon->get_width();
Vector2 string_pos = Point2(ofs, vofs + (h - font->get_height()) / 2 + font->get_ascent());
Vector2 string_pos = Point2(ofs, vofs + (h - text_buf.get_size().y) / 2 + text_buf.get_line_ascent());
string_pos = string_pos.floor();
draw_string(font, string_pos, text, color, limit - ofs - hsep);
text_buf.draw(get_canvas_item(), string_pos, color);
vofs += h + vsep;
}
@ -327,7 +330,10 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
path = path.replace_first(base_path, "");
Color cc = color;
Rect2 rect = Rect2(margin, vofs, limit - margin - hsep, font->get_height() + vsep);
TextLine text_buf = TextLine(path, font, font_size);
text_buf.set_width(limit - margin - hsep);
Rect2 rect = Rect2(margin, vofs, limit - margin - hsep, text_buf.get_size().y + vsep);
if (i != track) {
cc.a *= 0.7;
uint32_t hash = path.hash();
@ -338,7 +344,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
Color subcolor;
subcolor.set_hsv(h, 0.2, 0.8);
subcolor.a = 0.5;
draw_rect(Rect2(0, vofs + font->get_height() * 0.1, margin - hsep, font->get_height() * 0.8), subcolor);
draw_rect(Rect2(0, vofs + text_buf.get_size().y * 0.1, margin - hsep, text_buf.get_size().y * 0.8), subcolor);
subtrack_colors[i] = subcolor;
subtracks[i] = rect;
@ -347,15 +353,17 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
ac.a = 0.5;
draw_rect(rect, ac);
}
draw_string(font, Point2(margin, vofs + font->get_ascent()), path, cc, limit - margin - hsep);
vofs += font->get_height() + vsep;
Vector2 string_pos = Point2(margin, vofs + text_buf.get_line_ascent());
text_buf.draw(get_canvas_item(), string_pos, cc);
vofs += text_buf.get_size().y + vsep;
}
Color accent = get_theme_color("accent_color", "Editor");
{ //guides
float min_left_scale = font->get_height() + vsep;
float min_left_scale = font->get_height(font_size) + vsep;
float scale = (min_left_scale * 2) * v_zoom;
float step = Math::pow(10.0, Math::round(Math::log(scale / 5.0) / Math::log(10.0))) * 5.0;
@ -367,7 +375,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
bool first = true;
int prev_iv = 0;
for (int i = font->get_height(); i < get_size().height; i++) {
for (int i = font->get_height(font_size); i < get_size().height; i++) {
float ofs = get_size().height / 2 - i;
ofs *= v_zoom;
ofs += v_scroll;
@ -382,7 +390,7 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
draw_line(Point2(limit, i), Point2(right_limit, i), lc);
Color c = color;
c.a *= 0.5;
draw_string(font, Point2(limit + 8, i - 2), rtos(Math::stepify((iv + 1) * scale, step)), c);
draw_string(font, Point2(limit + 8, i - 2), TS->format_number(rtos(Math::stepify((iv + 1) * scale, step))), HALIGN_LEFT, -1, font_size, c);
}
first = false;
@ -453,8 +461,8 @@ void AnimationBezierTrackEdit::_notification(int p_what) {
ep.point_rect.size = bezier_icon->get_size();
if (selection.has(i)) {
draw_texture(selected_icon, ep.point_rect.position);
draw_string(font, ep.point_rect.position + Vector2(8, -font->get_height() - 4), TTR("Time:") + " " + rtos(Math::stepify(offset, 0.001)), accent);
draw_string(font, ep.point_rect.position + Vector2(8, -8), TTR("Value:") + " " + rtos(Math::stepify(value, 0.001)), accent);
draw_string(font, ep.point_rect.position + Vector2(8, -font->get_height(font_size) - 4), TTR("Time:") + " " + TS->format_number(rtos(Math::stepify(offset, 0.001))), HALIGN_LEFT, -1, font_size, accent);
draw_string(font, ep.point_rect.position + Vector2(8, -8), TTR("Value:") + " " + TS->format_number(rtos(Math::stepify(value, 0.001))), HALIGN_LEFT, -1, font_size, accent);
} else {
draw_texture(bezier_icon, ep.point_rect.position);
}

View File

@ -1397,6 +1397,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
}
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
Color color = get_theme_color("font_color", "Label");
int zoomw = key_range;
@ -1488,10 +1489,10 @@ void AnimationTimelineEdit::_notification(int p_what) {
int decimals = 2;
bool step_found = false;
const int period_width = font->get_char_size('.').width;
int max_digit_width = font->get_char_size('0').width;
const int period_width = font->get_char_size('.', 0, font_size).width;
int max_digit_width = font->get_char_size('0', 0, font_size).width;
for (int i = 1; i <= 9; i++) {
const int digit_width = font->get_char_size('0' + i).width;
const int digit_width = font->get_char_size('0' + i, 0, font_size).width;
max_digit_width = MAX(digit_width, max_digit_width);
}
const int max_sc = int(Math::ceil(zoomw / scale));
@ -1538,8 +1539,8 @@ void AnimationTimelineEdit::_notification(int p_what) {
if (frame != prev_frame && i >= prev_frame_ofs) {
draw_line(Point2(get_name_limit() + i, 0), Point2(get_name_limit() + i, h), linecolor, Math::round(EDSCALE));
draw_string(font, Point2(get_name_limit() + i + 3 * EDSCALE, (h - font->get_height()) / 2 + font->get_ascent()).floor(), itos(frame), sub ? color_time_dec : color_time_sec, zoomw - i);
prev_frame_ofs = i + font->get_string_size(itos(frame)).x + 5 * EDSCALE;
draw_string(font, Point2(get_name_limit() + i + 3 * EDSCALE, (h - font->get_height(font_size)) / 2 + font->get_ascent(font_size)).floor(), itos(frame), HALIGN_LEFT, zoomw - i, font_size, sub ? color_time_dec : color_time_sec);
prev_frame_ofs = i + font->get_string_size(itos(frame), font_size).x + 5 * EDSCALE;
}
}
}
@ -1556,7 +1557,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
if ((sc / step) != (prev_sc / step) || (prev_sc < 0 && sc >= 0)) {
int scd = sc < 0 ? prev_sc : sc;
draw_line(Point2(get_name_limit() + i, 0), Point2(get_name_limit() + i, h), linecolor, Math::round(EDSCALE));
draw_string(font, Point2(get_name_limit() + i + 3, (h - font->get_height()) / 2 + font->get_ascent()).floor(), String::num((scd - (scd % step)) / double(SC_ADJ), decimals), sub ? color_time_dec : color_time_sec, zoomw - i);
draw_string(font, Point2(get_name_limit() + i + 3, (h - font->get_height(font_size)) / 2 + font->get_ascent(font_size)).floor(), String::num((scd - (scd % step)) / double(SC_ADJ), decimals), HALIGN_LEFT, zoomw - i, font_size, sub ? color_time_dec : color_time_sec);
}
}
}
@ -1583,7 +1584,8 @@ void AnimationTimelineEdit::set_animation(const Ref<Animation> &p_animation) {
Size2 AnimationTimelineEdit::get_minimum_size() const {
Size2 ms = add_track->get_minimum_size();
Ref<Font> font = get_theme_font("font", "Label");
ms.height = MAX(ms.height, font->get_height());
int font_size = get_theme_font_size("font_size", "Label");
ms.height = MAX(ms.height, font->get_height(font_size));
ms.width = get_buttons_width() + add_track->get_minimum_size().width + get_theme_icon("Hsize", "EditorIcons")->get_width() + 2;
return ms;
}
@ -1798,6 +1800,8 @@ AnimationTimelineEdit::AnimationTimelineEdit() {
panning_timeline = false;
dragging_timeline = false;
dragging_hsize = false;
set_layout_direction(Control::LAYOUT_DIRECTION_LTR);
}
////////////////////////////////////
@ -1819,6 +1823,7 @@ void AnimationTrackEdit::_notification(int p_what) {
}
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
Color color = get_theme_color("font_color", "Label");
Ref<Texture2D> type_icons[6] = {
get_theme_icon("KeyValue", "EditorIcons"),
@ -1890,9 +1895,9 @@ void AnimationTrackEdit::_notification(int p_what) {
path_rect = Rect2(ofs, 0, limit - ofs - hsep, get_size().height);
Vector2 string_pos = Point2(ofs, (get_size().height - font->get_height()) / 2 + font->get_ascent());
Vector2 string_pos = Point2(ofs, (get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size));
string_pos = string_pos.floor();
draw_string(font, string_pos, text, text_color, limit - ofs - hsep);
draw_string(font, string_pos, text, HALIGN_LEFT, limit - ofs - hsep, font_size, text_color);
draw_line(Point2(limit, 0), Point2(limit, get_size().height), linecolor, Math::round(EDSCALE));
}
@ -2173,6 +2178,7 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool
if (animation->track_get_type(track) == Animation::TYPE_METHOD) {
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
Color color = get_theme_color("font_color", "Label");
color.a = 0.5;
@ -2197,7 +2203,7 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool
int limit = MAX(0, p_clip_right - p_x - icon_to_draw->get_width());
if (limit > 0) {
draw_string(font, Vector2(p_x + icon_to_draw->get_width(), int(get_size().height - font->get_height()) / 2 + font->get_ascent()), text, color, limit);
draw_string(font, Vector2(p_x + icon_to_draw->get_width(), int(get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size)), text, HALIGN_LEFT, limit, font_size, color);
}
}
@ -2302,9 +2308,10 @@ NodePath AnimationTrackEdit::get_path() const {
Size2 AnimationTrackEdit::get_minimum_size() const {
Ref<Texture2D> texture = get_theme_icon("Object", "EditorIcons");
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
int separation = get_theme_constant("vseparation", "ItemList");
int max_h = MAX(texture->get_height(), font->get_height());
int max_h = MAX(texture->get_height(), font->get_height(font_size));
max_h = MAX(max_h, get_key_height());
return Vector2(1, max_h + separation);
@ -3036,6 +3043,7 @@ AnimationTrackEdit *AnimationTrackEditPlugin::create_animation_track_edit(Object
void AnimationTrackEditGroup::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
int separation = get_theme_constant("hseparation", "ItemList");
Color color = get_theme_color("font_color", "Label");
@ -3059,7 +3067,7 @@ void AnimationTrackEditGroup::_notification(int p_what) {
int ofs = 0;
draw_texture(icon, Point2(ofs, int(get_size().height - icon->get_height()) / 2));
ofs += separation + icon->get_width();
draw_string(font, Point2(ofs, int(get_size().height - font->get_height()) / 2 + font->get_ascent()), node_name, color, timeline->get_name_limit() - ofs);
draw_string(font, Point2(ofs, int(get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size)), node_name, HALIGN_LEFT, timeline->get_name_limit() - ofs, font_size, color);
int px = (-timeline->get_value() + timeline->get_play_position()) * timeline->get_zoom_scale() + timeline->get_name_limit();
@ -3080,9 +3088,10 @@ void AnimationTrackEditGroup::set_type_and_name(const Ref<Texture2D> &p_type, co
Size2 AnimationTrackEditGroup::get_minimum_size() const {
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
int separation = get_theme_constant("vseparation", "ItemList");
return Vector2(0, MAX(font->get_height(), icon->get_height()) + separation);
return Vector2(0, MAX(font->get_height(font_size), icon->get_height()) + separation);
}
void AnimationTrackEditGroup::set_timeline(AnimationTimelineEdit *p_timeline) {

View File

@ -37,6 +37,7 @@
#include "scene/2d/sprite_2d.h"
#include "scene/3d/sprite_3d.h"
#include "scene/animation/animation_player.h"
#include "scene/resources/text_line.h"
#include "servers/audio/audio_stream.h"
/// BOOL ///
@ -80,12 +81,14 @@ void AnimationTrackEditBool::draw_key(int p_index, float p_pixels_sec, int p_x,
int AnimationTrackEditColor::get_key_height() const {
Ref<Font> font = get_theme_font("font", "Label");
return font->get_height() * 0.8;
int font_size = get_theme_font_size("font_size", "Label");
return font->get_height(font_size) * 0.8;
}
Rect2 AnimationTrackEditColor::get_key_rect(int p_index, float p_pixels_sec) {
Ref<Font> font = get_theme_font("font", "Label");
int fh = font->get_height() * 0.8;
int font_size = get_theme_font_size("font_size", "Label");
int fh = font->get_height(font_size) * 0.8;
return Rect2(-fh / 2, 0, fh, get_size().height);
}
@ -95,7 +98,8 @@ bool AnimationTrackEditColor::is_key_selectable_by_distance() const {
void AnimationTrackEditColor::draw_key_link(int p_index, float p_pixels_sec, int p_x, int p_next_x, int p_clip_left, int p_clip_right) {
Ref<Font> font = get_theme_font("font", "Label");
int fh = (font->get_height() * 0.8);
int font_size = get_theme_font_size("font_size", "Label");
int fh = (font->get_height(font_size) * 0.8);
int x_from = p_x + fh / 2 - 1;
int x_to = p_next_x - fh / 2 + 1;
@ -144,7 +148,8 @@ void AnimationTrackEditColor::draw_key(int p_index, float p_pixels_sec, int p_x,
Color color = get_animation()->track_get_key_value(get_track(), p_index);
Ref<Font> font = get_theme_font("font", "Label");
int fh = font->get_height() * 0.8;
int font_size = get_theme_font_size("font_size", "Label");
int fh = font->get_height(font_size) * 0.8;
Rect2 rect(Vector2(p_x - fh / 2, int(get_size().height - fh) / 2), Size2(fh, fh));
@ -182,7 +187,8 @@ int AnimationTrackEditAudio::get_key_height() const {
}
Ref<Font> font = get_theme_font("font", "Label");
return int(font->get_height() * 1.5);
int font_size = get_theme_font_size("font_size", "Label");
return int(font->get_height(font_size) * 1.5);
}
Rect2 AnimationTrackEditAudio::get_key_rect(int p_index, float p_pixels_sec) {
@ -214,7 +220,8 @@ Rect2 AnimationTrackEditAudio::get_key_rect(int p_index, float p_pixels_sec) {
return Rect2(0, 0, len * p_pixels_sec, get_size().height);
} else {
Ref<Font> font = get_theme_font("font", "Label");
int fh = font->get_height() * 0.8;
int font_size = get_theme_font_size("font_size", "Label");
int fh = font->get_height(font_size) * 0.8;
return Rect2(0, 0, fh, get_size().height);
}
}
@ -277,7 +284,8 @@ void AnimationTrackEditAudio::draw_key(int p_index, float p_pixels_sec, int p_x,
}
Ref<Font> font = get_theme_font("font", "Label");
float fh = int(font->get_height() * 1.5);
int font_size = get_theme_font_size("font_size", "Label");
float fh = int(font->get_height(font_size) * 1.5);
Rect2 rect = Rect2(from_x, (get_size().height - fh) / 2, to_x - from_x, fh);
draw_rect(rect, Color(0.25, 0.25, 0.25));
@ -307,7 +315,8 @@ void AnimationTrackEditAudio::draw_key(int p_index, float p_pixels_sec, int p_x,
}
} else {
Ref<Font> font = get_theme_font("font", "Label");
int fh = font->get_height() * 0.8;
int font_size = get_theme_font_size("font_size", "Label");
int fh = font->get_height(font_size) * 0.8;
Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh));
Color color = get_theme_color("font_color", "Label");
@ -339,7 +348,8 @@ int AnimationTrackEditSpriteFrame::get_key_height() const {
}
Ref<Font> font = get_theme_font("font", "Label");
return int(font->get_height() * 2);
int font_size = get_theme_font_size("font_size", "Label");
return int(font->get_height(font_size) * 2);
}
Rect2 AnimationTrackEditSpriteFrame::get_key_rect(int p_index, float p_pixels_sec) {
@ -406,7 +416,8 @@ Rect2 AnimationTrackEditSpriteFrame::get_key_rect(int p_index, float p_pixels_se
size = size.floor();
Ref<Font> font = get_theme_font("font", "Label");
int height = int(font->get_height() * 2);
int font_size = get_theme_font_size("font_size", "Label");
int height = int(font->get_height(font_size) * 2);
int width = height * size.width / size.height;
return Rect2(0, 0, width, get_size().height);
@ -496,7 +507,8 @@ void AnimationTrackEditSpriteFrame::draw_key(int p_index, float p_pixels_sec, in
}
Ref<Font> font = get_theme_font("font", "Label");
int height = int(font->get_height() * 2);
int font_size = get_theme_font_size("font_size", "Label");
int height = int(font->get_height(font_size) * 2);
int width = height * region.size.width / region.size.height;
@ -539,7 +551,8 @@ int AnimationTrackEditSubAnim::get_key_height() const {
}
Ref<Font> font = get_theme_font("font", "Label");
return int(font->get_height() * 1.5);
int font_size = get_theme_font_size("font_size", "Label");
return int(font->get_height(font_size) * 1.5);
}
Rect2 AnimationTrackEditSubAnim::get_key_rect(int p_index, float p_pixels_sec) {
@ -567,7 +580,8 @@ Rect2 AnimationTrackEditSubAnim::get_key_rect(int p_index, float p_pixels_sec) {
return Rect2(0, 0, len * p_pixels_sec, get_size().height);
} else {
Ref<Font> font = get_theme_font("font", "Label");
int fh = font->get_height() * 0.8;
int font_size = get_theme_font_size("font_size", "Label");
int fh = font->get_height(font_size) * 0.8;
return Rect2(0, 0, fh, get_size().height);
}
}
@ -621,7 +635,8 @@ void AnimationTrackEditSubAnim::draw_key(int p_index, float p_pixels_sec, int p_
}
Ref<Font> font = get_theme_font("font", "Label");
int fh = font->get_height() * 1.5;
int font_size = get_theme_font_size("font_size", "Label");
int fh = font->get_height(font_size) * 1.5;
Rect2 rect(from_x, int(get_size().height - fh) / 2, to_x - from_x, fh);
@ -664,7 +679,7 @@ void AnimationTrackEditSubAnim::draw_key(int p_index, float p_pixels_sec, int p_
int limit = to_x - from_x - 4;
if (limit > 0) {
draw_string(font, Point2(from_x + 2, int(get_size().height - font->get_height()) / 2 + font->get_ascent()), anim, color);
draw_string(font, Point2(from_x + 2, int(get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size)), anim, HALIGN_LEFT, -1, font_size, color);
}
if (p_selected) {
@ -673,7 +688,8 @@ void AnimationTrackEditSubAnim::draw_key(int p_index, float p_pixels_sec, int p_
}
} else {
Ref<Font> font = get_theme_font("font", "Label");
int fh = font->get_height() * 0.8;
int font_size = get_theme_font_size("font_size", "Label");
int fh = font->get_height(font_size) * 0.8;
Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh));
Color color = get_theme_color("font_color", "Label");
@ -771,7 +787,8 @@ void AnimationTrackEditTypeAudio::_preview_changed(ObjectID p_which) {
int AnimationTrackEditTypeAudio::get_key_height() const {
Ref<Font> font = get_theme_font("font", "Label");
return int(font->get_height() * 1.5);
int font_size = get_theme_font_size("font_size", "Label");
return int(font->get_height(font_size) * 1.5);
}
Rect2 AnimationTrackEditTypeAudio::get_key_rect(int p_index, float p_pixels_sec) {
@ -835,7 +852,8 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int
}
Ref<Font> font = get_theme_font("font", "Label");
float fh = int(font->get_height() * 1.5);
int font_size = get_theme_font_size("font_size", "Label");
float fh = int(font->get_height(font_size) * 1.5);
float len = stream->get_length();
@ -1104,7 +1122,8 @@ int AnimationTrackEditTypeAnimation::get_key_height() const {
}
Ref<Font> font = get_theme_font("font", "Label");
return int(font->get_height() * 1.5);
int font_size = get_theme_font_size("font_size", "Label");
return int(font->get_height(font_size) * 1.5);
}
Rect2 AnimationTrackEditTypeAnimation::get_key_rect(int p_index, float p_pixels_sec) {
@ -1132,7 +1151,8 @@ Rect2 AnimationTrackEditTypeAnimation::get_key_rect(int p_index, float p_pixels_
return Rect2(0, 0, len * p_pixels_sec, get_size().height);
} else {
Ref<Font> font = get_theme_font("font", "Label");
int fh = font->get_height() * 0.8;
int font_size = get_theme_font_size("font_size", "Label");
int fh = font->get_height(font_size) * 0.8;
return Rect2(0, 0, fh, get_size().height);
}
}
@ -1186,7 +1206,8 @@ void AnimationTrackEditTypeAnimation::draw_key(int p_index, float p_pixels_sec,
}
Ref<Font> font = get_theme_font("font", "Label");
int fh = font->get_height() * 1.5;
int font_size = get_theme_font_size("font_size", "Label");
int fh = font->get_height(font_size) * 1.5;
Rect2 rect(from_x, int(get_size().height - fh) / 2, to_x - from_x, fh);
@ -1229,7 +1250,7 @@ void AnimationTrackEditTypeAnimation::draw_key(int p_index, float p_pixels_sec,
int limit = to_x - from_x - 4;
if (limit > 0) {
draw_string(font, Point2(from_x + 2, int(get_size().height - font->get_height()) / 2 + font->get_ascent()), anim, color);
draw_string(font, Point2(from_x + 2, int(get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size)), anim, HALIGN_LEFT, -1, font_size, color);
}
if (p_selected) {
@ -1238,7 +1259,8 @@ void AnimationTrackEditTypeAnimation::draw_key(int p_index, float p_pixels_sec,
}
} else {
Ref<Font> font = get_theme_font("font", "Label");
int fh = font->get_height() * 0.8;
int font_size = get_theme_font_size("font_size", "Label");
int fh = font->get_height(font_size) * 0.8;
Rect2 rect(Vector2(p_x, int(get_size().height - fh) / 2), Size2(fh, fh));
Color color = get_theme_color("font_color", "Label");

View File

@ -38,7 +38,7 @@
#include "editor_settings.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/separator.h"
#include "scene/resources/dynamic_font.h"
#include "scene/resources/font.h"
void GotoLineDialog::popup_find_line(CodeEdit *p_edit) {
text_editor = p_edit;
@ -731,6 +731,7 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMagnifyGesture> magnify_gesture = p_event;
if (magnify_gesture.is_valid()) {
/*
Ref<DynamicFont> font = text_editor->get_theme_font("font");
if (font.is_valid()) {
@ -742,6 +743,8 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
_add_font_size((int)font_size - font->get_size());
}
*/
//TODO move size to draw functions
return;
}
@ -764,27 +767,15 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
void CodeTextEditor::_zoom_in() {
font_resize_val += MAX(EDSCALE, 1.0f);
_zoom_changed();
}
void CodeTextEditor::_zoom_out() {
font_resize_val -= MAX(EDSCALE, 1.0f);
_zoom_changed();
}
void CodeTextEditor::_zoom_changed() {
if (font_resize_timer->get_time_left() == 0) {
font_resize_timer->start();
}
}
void CodeTextEditor::_reset_zoom() {
Ref<DynamicFont> font = text_editor->get_theme_font("font"); // Reset source font size to default.
if (font.is_valid()) {
EditorSettings::get_singleton()->set("interface/editor/code_font_size", 14);
font->set_size(14);
}
font_resize_val = 1.0f;
//TODO MOVE size to draw functions
}
void CodeTextEditor::_line_col_changed() {
@ -893,29 +884,6 @@ Ref<Texture2D> CodeTextEditor::_get_completion_icon(const ScriptCodeCompletionOp
return tex;
}
void CodeTextEditor::_font_resize_timeout() {
if (_add_font_size(font_resize_val)) {
font_resize_val = 0;
}
}
bool CodeTextEditor::_add_font_size(int p_delta) {
Ref<DynamicFont> font = text_editor->get_theme_font("font");
if (font.is_valid()) {
int new_size = CLAMP(font->get_size() + p_delta, 8 * EDSCALE, 96 * EDSCALE);
if (new_size != font->get_size()) {
EditorSettings::get_singleton()->set("interface/editor/code_font_size", new_size / EDSCALE);
font->set_size(new_size);
}
return true;
} else {
return false;
}
}
void CodeTextEditor::update_editor_settings() {
completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
completion_string_color = EDITOR_GET("text_editor/highlighting/string_color");
@ -1486,17 +1454,22 @@ void CodeTextEditor::goto_error() {
void CodeTextEditor::_update_font() {
text_editor->add_theme_font_override("font", get_theme_font("source", "EditorFonts"));
text_editor->add_theme_font_size_override("font_size", get_theme_font_size("source_size", "EditorFonts"));
error->add_theme_font_override("font", get_theme_font("status_source", "EditorFonts"));
error->add_theme_font_size_override("font_size", get_theme_font_size("status_source_size", "EditorFonts"));
error->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
Ref<Font> status_bar_font = get_theme_font("status_source", "EditorFonts");
int status_bar_font_size = get_theme_font_size("status_source_size", "EditorFonts");
error->add_theme_font_override("font", status_bar_font);
error->add_theme_font_size_override("font_size", status_bar_font_size);
int count = status_bar->get_child_count();
for (int i = 0; i < count; i++) {
Control *n = Object::cast_to<Control>(status_bar->get_child(i));
if (n) {
n->add_theme_font_override("font", status_bar_font);
n->add_theme_font_size_override("font_size", status_bar_font_size);
}
}
}
@ -1547,7 +1520,11 @@ void CodeTextEditor::_set_show_warnings_panel(bool p_show) {
}
void CodeTextEditor::_toggle_scripts_pressed() {
toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->toggle_scripts_panel() ? get_theme_icon("Back", "EditorIcons") : get_theme_icon("Forward", "EditorIcons"));
if (is_layout_rtl()) {
toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->toggle_scripts_panel() ? get_theme_icon("Back", "EditorIcons") : get_theme_icon("Forward", "EditorIcons"));
} else {
toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->toggle_scripts_panel() ? get_theme_icon("Forward", "EditorIcons") : get_theme_icon("Back", "EditorIcons"));
}
}
void CodeTextEditor::_error_pressed(const Ref<InputEvent> &p_event) {
@ -1668,7 +1645,11 @@ void CodeTextEditor::show_toggle_scripts_button() {
}
void CodeTextEditor::update_toggle_scripts_button() {
toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? get_theme_icon("Back", "EditorIcons") : get_theme_icon("Forward", "EditorIcons"));
if (is_layout_rtl()) {
toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? get_theme_icon("Back", "EditorIcons") : get_theme_icon("Forward", "EditorIcons"));
} else {
toggle_scripts_button->set_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? get_theme_icon("Forward", "EditorIcons") : get_theme_icon("Back", "EditorIcons"));
}
toggle_scripts_button->set_tooltip(TTR("Toggle Scripts Panel") + " (" + ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text() + ")");
}
@ -1750,6 +1731,7 @@ CodeTextEditor::CodeTextEditor() {
warning_count_label->set_tooltip(TTR("Warnings"));
warning_count_label->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("warning_color", "Editor"));
warning_count_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts"));
warning_count_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("status_source_size", "EditorFonts"));
warning_count_label->connect("gui_input", callable_mp(this, &CodeTextEditor::_warning_label_gui_input));
is_warnings_panel_opened = false;
@ -1760,6 +1742,7 @@ CodeTextEditor::CodeTextEditor() {
status_bar->add_child(line_and_col_txt);
line_and_col_txt->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER);
line_and_col_txt->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts"));
line_and_col_txt->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("status_source_size", "EditorFonts"));
line_and_col_txt->set_tooltip(TTR("Line and column numbers."));
line_and_col_txt->set_mouse_filter(MOUSE_FILTER_STOP);
@ -1781,11 +1764,6 @@ CodeTextEditor::CodeTextEditor() {
font_resize_val = 0;
font_size = EditorSettings::get_singleton()->get("interface/editor/code_font_size");
font_resize_timer = memnew(Timer);
add_child(font_resize_timer);
font_resize_timer->set_one_shot(true);
font_resize_timer->set_wait_time(0.07);
font_resize_timer->connect("timeout", callable_mp(this, &CodeTextEditor::_font_resize_timeout));
EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &CodeTextEditor::_on_settings_change));
}

View File

@ -151,7 +151,6 @@ class CodeTextEditor : public VBoxContainer {
Timer *idle;
Timer *code_complete_timer;
Timer *font_resize_timer;
int font_resize_val;
real_t font_size;
@ -164,14 +163,11 @@ class CodeTextEditor : public VBoxContainer {
void _update_font();
void _complete_request();
Ref<Texture2D> _get_completion_icon(const ScriptCodeCompletionOption &p_option);
void _font_resize_timeout();
bool _add_font_size(int p_delta);
void _input(const Ref<InputEvent> &event);
void _text_editor_gui_input(const Ref<InputEvent> &p_event);
void _zoom_in();
void _zoom_out();
void _zoom_changed();
void _reset_zoom();
Color completion_font_color;

View File

@ -82,10 +82,10 @@ String EditorPerformanceProfiler::_create_label(float p_value, Performance::Moni
return String::humanize_size(p_value);
}
case Performance::MONITOR_TYPE_TIME: {
return rtos(p_value * 1000).pad_decimals(2) + " ms";
return TS->format_number(rtos(p_value * 1000).pad_decimals(2)) + " " + RTR("ms");
}
default: {
return rtos(p_value);
return TS->format_number(rtos(p_value));
}
}
}
@ -111,6 +111,7 @@ void EditorPerformanceProfiler::_monitor_draw() {
Ref<StyleBox> graph_style_box = get_theme_stylebox("normal", "TextEdit");
Ref<Font> graph_font = get_theme_font("font", "TextEdit");
int font_size = get_theme_font_size("font_size", "TextEdit");
int columns = int(Math::ceil(Math::sqrt(float(active.size()))));
int rows = int(Math::ceil(float(active.size()) / float(columns)));
@ -131,19 +132,19 @@ void EditorPerformanceProfiler::_monitor_draw() {
rect.size -= graph_style_box->get_minimum_size();
Color draw_color = get_theme_color("accent_color", "Editor");
draw_color.set_hsv(Math::fmod(hue_shift * float(current.frame_index), 0.9f), draw_color.get_s() * 0.9f, draw_color.get_v() * value_multiplier, 0.6f);
monitor_draw->draw_string(graph_font, rect.position + Point2(0, graph_font->get_ascent()), current.item->get_text(0), draw_color, rect.size.x);
monitor_draw->draw_string(graph_font, rect.position + Point2(0, graph_font->get_ascent(font_size)), current.item->get_text(0), HALIGN_LEFT, rect.size.x, font_size, draw_color);
draw_color.a = 0.9f;
float value_position = rect.size.width - graph_font->get_string_size(current.item->get_text(1)).width;
float value_position = rect.size.width - graph_font->get_string_size(current.item->get_text(1), font_size).width;
if (value_position < 0) {
value_position = 0;
}
monitor_draw->draw_string(graph_font, rect.position + Point2(value_position, graph_font->get_ascent()), current.item->get_text(1), draw_color, rect.size.x);
monitor_draw->draw_string(graph_font, rect.position + Point2(value_position, graph_font->get_ascent(font_size)), current.item->get_text(1), HALIGN_LEFT, rect.size.x, font_size, draw_color);
rect.position.y += graph_font->get_height();
rect.size.height -= graph_font->get_height();
rect.position.y += graph_font->get_height(font_size);
rect.size.height -= graph_font->get_height(font_size);
int line_count = rect.size.height / (graph_font->get_height() * 2);
int line_count = rect.size.height / (graph_font->get_height(font_size) * 2);
if (line_count > 5) {
line_count = 5;
}
@ -151,12 +152,12 @@ void EditorPerformanceProfiler::_monitor_draw() {
Color horizontal_line_color;
horizontal_line_color.set_hsv(draw_color.get_h(), draw_color.get_s() * 0.5f, draw_color.get_v() * 0.5f, 0.3f);
monitor_draw->draw_line(rect.position, rect.position + Vector2(rect.size.width, 0), horizontal_line_color, Math::round(EDSCALE));
monitor_draw->draw_string(graph_font, rect.position + Vector2(0, graph_font->get_ascent()), _create_label(current.max, current.type), horizontal_line_color, rect.size.width);
monitor_draw->draw_string(graph_font, rect.position + Vector2(0, graph_font->get_ascent(font_size)), _create_label(current.max, current.type), HALIGN_LEFT, rect.size.width, font_size, horizontal_line_color);
for (int j = 0; j < line_count; j++) {
Vector2 y_offset = Vector2(0, rect.size.height * (1.0f - float(j) / float(line_count)));
monitor_draw->draw_line(rect.position + y_offset, rect.position + Vector2(rect.size.width, 0) + y_offset, horizontal_line_color, Math::round(EDSCALE));
monitor_draw->draw_string(graph_font, rect.position - Vector2(0, graph_font->get_descent()) + y_offset, _create_label(current.max * float(j) / float(line_count), current.type), horizontal_line_color, rect.size.width);
monitor_draw->draw_string(graph_font, rect.position - Vector2(0, graph_font->get_descent(font_size)) + y_offset, _create_label(current.max * float(j) / float(line_count), current.type), HALIGN_LEFT, rect.size.width, font_size, horizontal_line_color);
}
}
@ -182,7 +183,7 @@ void EditorPerformanceProfiler::_monitor_draw() {
monitor_draw->draw_line(rect.position + Point2(from, 0), rect.position + Point2(from, rect.size.y), line_color, Math::round(EDSCALE));
String label = _create_label(e->get(), current.type);
Size2 size = graph_font->get_string_size(label);
Size2 size = graph_font->get_string_size(label, font_size);
Vector2 text_top_left_position = Vector2(from, h2) - (size + Vector2(MARKER_MARGIN, MARKER_MARGIN));
if (text_top_left_position.x < 0) {
text_top_left_position.x = from + MARKER_MARGIN;
@ -190,7 +191,7 @@ void EditorPerformanceProfiler::_monitor_draw() {
if (text_top_left_position.y < 0) {
text_top_left_position.y = h2 + MARKER_MARGIN;
}
monitor_draw->draw_string(graph_font, rect.position + text_top_left_position + Point2(0, graph_font->get_ascent()), label, line_color, rect.size.x);
monitor_draw->draw_string(graph_font, rect.position + text_top_left_position + Point2(0, graph_font->get_ascent(font_size)), label, HALIGN_LEFT, rect.size.x, font_size, line_color);
}
prev = h2;
e = e->next();

View File

@ -103,19 +103,19 @@ static String _get_percent_txt(float p_value, float p_total) {
p_total = 0.00001;
}
return String::num((p_value / p_total) * 100, 1) + "%";
return TS->format_number(String::num((p_value / p_total) * 100, 1)) + TS->percent_sign();
}
String EditorProfiler::_get_time_as_text(const Metric &m, float p_time, int p_calls) {
const int dmode = display_mode->get_selected();
if (dmode == DISPLAY_FRAME_TIME) {
return rtos(p_time * 1000).pad_decimals(2) + " ms";
return TS->format_number(rtos(p_time * 1000).pad_decimals(2)) + " " + RTR("ms");
} else if (dmode == DISPLAY_AVERAGE_TIME) {
if (p_calls == 0) {
return "0.00 ms";
return TS->format_number("0.00") + " " + RTR("ms");
} else {
return rtos((p_time / p_calls) * 1000).pad_decimals(2) + " ms";
return TS->format_number(rtos((p_time / p_calls) * 1000).pad_decimals(2)) + " " + RTR("ms");
}
} else if (dmode == DISPLAY_FRAME_PERCENT) {
return _get_percent_txt(p_time, m.frame_time);
@ -423,7 +423,7 @@ void EditorProfiler::_clear_pressed() {
}
void EditorProfiler::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
activate->set_icon(get_theme_icon("Play", "EditorIcons"));
clear_button->set_icon(get_theme_icon("Clear", "EditorIcons"));
}

View File

@ -114,9 +114,9 @@ String EditorVisualProfiler::_get_time_as_text(float p_time) {
int dmode = display_mode->get_selected();
if (dmode == DISPLAY_FRAME_TIME) {
return rtos(p_time) + "ms";
return TS->format_number(rtos(p_time)) + " " + RTR("ms");
} else if (dmode == DISPLAY_FRAME_PERCENT) {
return String::num(p_time * 100 / graph_limit, 2) + "%";
return TS->format_number(String::num(p_time * 100 / graph_limit, 2)) + " " + TS->percent_sign();
}
return "err";
@ -423,8 +423,12 @@ void EditorVisualProfiler::_clear_pressed() {
}
void EditorVisualProfiler::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
activate->set_icon(get_theme_icon("Play", "EditorIcons"));
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
if (is_layout_rtl()) {
activate->set_icon(get_theme_icon("PlayBackwards", "EditorIcons"));
} else {
activate->set_icon(get_theme_icon("Play", "EditorIcons"));
}
clear_button->set_icon(get_theme_icon("Clear", "EditorIcons"));
}
}
@ -434,6 +438,7 @@ void EditorVisualProfiler::_graph_tex_draw() {
return;
}
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
if (seeking) {
int max_frames = frame_metrics.size();
int frame = cursor_metric_edit->get_value() - (frame_metrics[last_metric].frame_number - max_frames + 1);
@ -457,7 +462,7 @@ void EditorVisualProfiler::_graph_tex_draw() {
graph->draw_line(Vector2(0, frame_y), Vector2(half_width, frame_y), Color(1, 1, 1, 0.3));
String limit_str = String::num(graph_limit, 2);
graph->draw_string(font, Vector2(half_width - font->get_string_size(limit_str).x - 2, frame_y - 2), limit_str, Color(1, 1, 1, 0.6));
graph->draw_string(font, Vector2(half_width - font->get_string_size(limit_str, font_size).x - 2, frame_y - 2), limit_str, HALIGN_LEFT, -1, font_size, Color(1, 1, 1, 0.6));
}
if (graph_height_gpu > 0) {
@ -468,11 +473,11 @@ void EditorVisualProfiler::_graph_tex_draw() {
graph->draw_line(Vector2(half_width, frame_y), Vector2(graph->get_size().x, frame_y), Color(1, 1, 1, 0.3));
String limit_str = String::num(graph_limit, 2);
graph->draw_string(font, Vector2(half_width * 2 - font->get_string_size(limit_str).x - 2, frame_y - 2), limit_str, Color(1, 1, 1, 0.6));
graph->draw_string(font, Vector2(half_width * 2 - font->get_string_size(limit_str, font_size).x - 2, frame_y - 2), limit_str, HALIGN_LEFT, -1, font_size, Color(1, 1, 1, 0.6));
}
graph->draw_string(font, Vector2(font->get_string_size("X").x, font->get_ascent() + 2), "CPU:", Color(1, 1, 1, 0.8));
graph->draw_string(font, Vector2(font->get_string_size("X").x + graph->get_size().width / 2, font->get_ascent() + 2), "GPU:", Color(1, 1, 1, 0.8));
graph->draw_string(font, Vector2(font->get_string_size("X", font_size).x, font->get_ascent(font_size) + 2), "CPU:", HALIGN_LEFT, -1, font_size, Color(1, 1, 1, 0.8));
graph->draw_string(font, Vector2(font->get_string_size("X", font_size).x + graph->get_size().width / 2, font->get_ascent(font_size) + 2), "GPU:", HALIGN_LEFT, -1, font_size, Color(1, 1, 1, 0.8));
/*
if (hover_metric != -1 && frame_metrics[hover_metric].valid) {

View File

@ -523,6 +523,14 @@ void DocData::generate(bool p_basic_types) {
c.theme_properties.push_back(pd);
}
l.clear();
Theme::get_default()->get_font_size_list(cname, &l);
for (List<StringName>::Element *E = l.front(); E; E = E->next()) {
PropertyDoc pd;
pd.name = E->get();
pd.type = "int";
c.theme_properties.push_back(pd);
}
l.clear();
Theme::get_default()->get_stylebox_list(cname, &l);
for (List<StringName>::Element *E = l.front(); E; E = E->next()) {
PropertyDoc pd;

View File

@ -40,9 +40,12 @@
void EditorAbout::_theme_changed() {
Control *base = EditorNode::get_singleton()->get_gui_base();
Ref<Font> font = base->get_theme_font("source", "EditorFonts");
int font_size = base->get_theme_font_size("source_size", "EditorFonts");
_tpl_text->add_theme_font_override("normal_font", font);
_tpl_text->add_theme_font_size_override("normal_font_size", font_size);
_tpl_text->add_theme_constant_override("line_separation", 6 * EDSCALE);
_license_text->add_theme_font_override("normal_font", font);
_license_text->add_theme_font_size_override("normal_font_size", font_size);
_license_text->add_theme_constant_override("line_separation", 6 * EDSCALE);
_logo->set_texture(base->get_theme_icon("Logo", "EditorIcons"));
}
@ -213,7 +216,7 @@ EditorAbout::EditorAbout() {
for (int component_index = 0; component_index < COPYRIGHT_INFO_COUNT; component_index++) {
const ComponentCopyright &component = COPYRIGHT_INFO[component_index];
TreeItem *ti = _tpl_tree->create_item(tpl_ti_tp);
String component_name = component.name;
String component_name = String::utf8(component.name);
ti->set_text(0, component_name);
String text = component_name + "\n";
long_text += "- " + component_name + "\n";
@ -221,7 +224,7 @@ EditorAbout::EditorAbout() {
const ComponentCopyrightPart &part = component.parts[part_index];
text += "\n Files:";
for (int file_num = 0; file_num < part.file_count; file_num++) {
text += "\n " + String(part.files[file_num]);
text += "\n " + String::utf8(part.files[file_num]);
}
String copyright;
for (int copyright_index = 0; copyright_index < part.copyright_count; copyright_index++) {
@ -229,7 +232,7 @@ EditorAbout::EditorAbout() {
}
text += copyright;
long_text += copyright;
String license = "\n License: " + String(part.license) + "\n";
String license = "\n License: " + String::utf8(part.license) + "\n";
text += license;
long_text += license + "\n";
}
@ -237,10 +240,10 @@ EditorAbout::EditorAbout() {
}
for (int i = 0; i < LICENSE_COUNT; i++) {
TreeItem *ti = _tpl_tree->create_item(tpl_ti_lc);
String licensename = String(LICENSE_NAMES[i]);
String licensename = String::utf8(LICENSE_NAMES[i]);
ti->set_text(0, licensename);
long_text += "- " + licensename + "\n\n";
String licensebody = String(LICENSE_BODIES[i]);
String licensebody = String::utf8(LICENSE_BODIES[i]);
ti->set_metadata(0, licensebody);
long_text += " " + licensebody.replace("\n", "\n ") + "\n\n";
}

View File

@ -1379,14 +1379,15 @@ void EditorAudioMeterNotches::add_notch(float p_normalized_offset, float p_db_va
Size2 EditorAudioMeterNotches::get_minimum_size() const {
Ref<Font> font = get_theme_font("font", "Label");
float font_height = font->get_height();
int font_size = get_theme_font_size("font_size", "Label");
float font_height = font->get_height(font_size);
float width = 0;
float height = top_padding + btm_padding;
for (int i = 0; i < notches.size(); i++) {
if (notches[i].render_db_value) {
width = MAX(width, font->get_string_size(String::num(Math::abs(notches[i].db_value)) + "dB").x);
width = MAX(width, font->get_string_size(String::num(Math::abs(notches[i].db_value)) + "dB", font_size).x);
height += font_height;
}
}
@ -1413,7 +1414,8 @@ void EditorAudioMeterNotches::_notification(int p_what) {
void EditorAudioMeterNotches::_draw_audio_notches() {
Ref<Font> font = get_theme_font("font", "Label");
float font_height = font->get_height();
int font_size = get_theme_font_size("font_size", "Label");
float font_height = font->get_height(font_size);
for (int i = 0; i < notches.size(); i++) {
AudioNotch n = notches[i];
@ -1427,6 +1429,7 @@ void EditorAudioMeterNotches::_draw_audio_notches() {
Vector2(line_length + label_space,
(1.0f - n.relative_position) * (get_size().y - btm_padding - top_padding) + (font_height / 4) + top_padding),
String::num(Math::abs(n.db_value)) + "dB",
HALIGN_LEFT, -1, font_size,
notch_color);
}
}

View File

@ -398,7 +398,11 @@ Error EditorExportPlatform::_save_zip_file(void *p_userdata, const String &p_pat
Ref<ImageTexture> EditorExportPlatform::get_option_icon(int p_index) const {
Ref<Theme> theme = EditorNode::get_singleton()->get_editor_theme();
ERR_FAIL_COND_V(theme.is_null(), Ref<ImageTexture>());
return theme->get_icon("Play", "EditorIcons");
if (EditorNode::get_singleton()->get_viewport()->is_layout_rtl()) {
return theme->get_icon("PlayBackwards", "EditorIcons");
} else {
return theme->get_icon("Play", "EditorIcons");
}
}
String EditorExportPlatform::find_export_template(String template_file_name, String *err) const {
@ -972,6 +976,15 @@ Error EditorExportPlatform::export_project_files(const Ref<EditorExportPreset> &
p_func(p_udata, splash, array, idx, total, enc_in_filters, enc_ex_filters, key);
}
// Store text server data if exists.
if (TS->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) {
String ts_data = "res://" + TS->get_support_data_filename();
if (FileAccess::exists(ts_data)) {
Vector<uint8_t> array = FileAccess::get_file_as_array(ts_data);
p_func(p_udata, ts_data, array, idx, total, enc_in_filters, enc_ex_filters, key);
}
}
String config_file = "project.binary";
String engine_cfb = EditorSettings::get_singleton()->get_cache_dir().plus_file("tmp" + config_file);
ProjectSettings::get_singleton()->save_custom(engine_cfb, custom_map, custom_list);

View File

@ -59,12 +59,17 @@ VBoxContainer *EditorFileDialog::get_vbox() {
}
void EditorFileDialog::_notification(int p_what) {
if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_THEME_CHANGED) {
if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_THEME_CHANGED || p_what == Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
// Update icons.
mode_thumbnails->set_icon(item_list->get_theme_icon("FileThumbnail", "EditorIcons"));
mode_list->set_icon(item_list->get_theme_icon("FileList", "EditorIcons"));
dir_prev->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
dir_next->set_icon(item_list->get_theme_icon("Forward", "EditorIcons"));
if (is_layout_rtl()) {
dir_prev->set_icon(item_list->get_theme_icon("Forward", "EditorIcons"));
dir_next->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
} else {
dir_prev->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
dir_next->set_icon(item_list->get_theme_icon("Forward", "EditorIcons"));
}
dir_up->set_icon(item_list->get_theme_icon("ArrowUp", "EditorIcons"));
refresh->set_icon(item_list->get_theme_icon("Reload", "EditorIcons"));
favorite->set_icon(item_list->get_theme_icon("Favorites", "EditorIcons"));
@ -97,8 +102,13 @@ void EditorFileDialog::_notification(int p_what) {
// Update icons.
mode_thumbnails->set_icon(item_list->get_theme_icon("FileThumbnail", "EditorIcons"));
mode_list->set_icon(item_list->get_theme_icon("FileList", "EditorIcons"));
dir_prev->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
dir_next->set_icon(item_list->get_theme_icon("Forward", "EditorIcons"));
if (is_layout_rtl()) {
dir_prev->set_icon(item_list->get_theme_icon("Forward", "EditorIcons"));
dir_next->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
} else {
dir_prev->set_icon(item_list->get_theme_icon("Back", "EditorIcons"));
dir_next->set_icon(item_list->get_theme_icon("Forward", "EditorIcons"));
}
dir_up->set_icon(item_list->get_theme_icon("ArrowUp", "EditorIcons"));
refresh->set_icon(item_list->get_theme_icon("Reload", "EditorIcons"));
favorite->set_icon(item_list->get_theme_icon("Favorites", "EditorIcons"));
@ -1486,6 +1496,7 @@ EditorFileDialog::EditorFileDialog() {
pathhb->add_child(drives_container);
dir = memnew(LineEdit);
dir->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
pathhb->add_child(dir);
dir->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@ -1624,6 +1635,7 @@ EditorFileDialog::EditorFileDialog() {
file_box = memnew(HBoxContainer);
file_box->add_child(memnew(Label(TTR("File:"))));
file = memnew(LineEdit);
file->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
file->set_stretch_ratio(4);
file->set_h_size_flags(Control::SIZE_EXPAND_FILL);
file_box->add_child(file);
@ -1662,6 +1674,7 @@ EditorFileDialog::EditorFileDialog() {
makedialog->add_child(makevb);
makedirname = memnew(LineEdit);
makedirname->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
makevb->add_margin_child(TTR("Name:"), makedirname);
add_child(makedialog);
makedialog->register_text_enter(makedirname);

View File

@ -35,57 +35,61 @@
#include "editor_scale.h"
#include "editor_settings.h"
#include "scene/resources/default_theme/default_theme.h"
#include "scene/resources/dynamic_font.h"
#include "scene/resources/font.h"
#define MAKE_FALLBACKS(m_name) \
m_name->add_fallback(FontArabic); \
m_name->add_fallback(FontHebrew); \
m_name->add_fallback(FontThai); \
m_name->add_fallback(FontHindi); \
m_name->add_fallback(FontJapanese); \
m_name->add_fallback(FontFallback);
#define MAKE_FALLBACKS(m_name) \
m_name->add_data(FontArabic); \
m_name->add_data(FontBengali); \
m_name->add_data(FontGeorgian); \
m_name->add_data(FontMalayalam); \
m_name->add_data(FontOriya); \
m_name->add_data(FontSinhala); \
m_name->add_data(FontTamil); \
m_name->add_data(FontTelugu); \
m_name->add_data(FontHebrew); \
m_name->add_data(FontThai); \
m_name->add_data(FontHindi); \
m_name->add_data(FontJapanese); \
m_name->add_data(FontFallback);
// the custom spacings might only work with Noto Sans
#define MAKE_DEFAULT_FONT(m_name, m_size) \
Ref<DynamicFont> m_name; \
m_name.instance(); \
m_name->set_size(m_size); \
if (CustomFont.is_valid()) { \
m_name->set_font_data(CustomFont); \
m_name->add_fallback(DefaultFont); \
} else { \
m_name->set_font_data(DefaultFont); \
} \
m_name->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE); \
#define MAKE_DEFAULT_FONT(m_name) \
Ref<Font> m_name; \
m_name.instance(); \
if (CustomFont.is_valid()) { \
m_name->add_data(CustomFont); \
m_name->add_data(DefaultFont); \
} else { \
m_name->add_data(DefaultFont); \
} \
m_name->set_spacing(Font::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(Font::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS(m_name);
#define MAKE_BOLD_FONT(m_name, m_size) \
Ref<DynamicFont> m_name; \
m_name.instance(); \
m_name->set_size(m_size); \
if (CustomFontBold.is_valid()) { \
m_name->set_font_data(CustomFontBold); \
m_name->add_fallback(DefaultFontBold); \
} else { \
m_name->set_font_data(DefaultFontBold); \
} \
m_name->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE); \
#define MAKE_BOLD_FONT(m_name) \
Ref<Font> m_name; \
m_name.instance(); \
if (CustomFontBold.is_valid()) { \
m_name->add_data(CustomFontBold); \
m_name->add_data(DefaultFontBold); \
} else { \
m_name->add_data(DefaultFontBold); \
} \
m_name->set_spacing(Font::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(Font::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS(m_name);
#define MAKE_SOURCE_FONT(m_name, m_size) \
Ref<DynamicFont> m_name; \
m_name.instance(); \
m_name->set_size(m_size); \
if (CustomFontSource.is_valid()) { \
m_name->set_font_data(CustomFontSource); \
m_name->add_fallback(dfmono); \
} else { \
m_name->set_font_data(dfmono); \
} \
m_name->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE); \
#define MAKE_SOURCE_FONT(m_name) \
Ref<Font> m_name; \
m_name.instance(); \
if (CustomFontSource.is_valid()) { \
m_name->add_data(CustomFontSource); \
m_name->add_data(dfmono); \
} else { \
m_name->add_data(dfmono); \
} \
m_name->set_spacing(Font::SPACING_TOP, -EDSCALE); \
m_name->set_spacing(Font::SPACING_BOTTOM, -EDSCALE); \
MAKE_FALLBACKS(m_name);
void editor_register_fonts(Ref<Theme> p_theme) {
@ -96,7 +100,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
bool font_antialiased = (bool)EditorSettings::get_singleton()->get("interface/editor/font_antialiased");
int font_hinting_setting = (int)EditorSettings::get_singleton()->get("interface/editor/font_hinting");
DynamicFontData::Hinting font_hinting;
TextServer::Hinting font_hinting;
switch (font_hinting_setting) {
case 0:
// The "Auto" setting uses the setting that best matches the OS' font rendering:
@ -104,29 +108,31 @@ void editor_register_fonts(Ref<Theme> p_theme) {
// - Windows uses ClearType, which is in between "Light" and "Normal" hinting.
// - Linux has configurable font hinting, but most distributions including Ubuntu default to "Light".
#ifdef OSX_ENABLED
font_hinting = DynamicFontData::HINTING_NONE;
font_hinting = TextServer::HINTING_NONE;
#else
font_hinting = DynamicFontData::HINTING_LIGHT;
font_hinting = TextServer::HINTING_LIGHT;
#endif
break;
case 1:
font_hinting = DynamicFontData::HINTING_NONE;
font_hinting = TextServer::HINTING_NONE;
break;
case 2:
font_hinting = DynamicFontData::HINTING_LIGHT;
font_hinting = TextServer::HINTING_LIGHT;
break;
default:
font_hinting = DynamicFontData::HINTING_NORMAL;
font_hinting = TextServer::HINTING_NORMAL;
break;
}
int default_font_size = int(EDITOR_GET("interface/editor/main_font_size")) * EDSCALE;
String custom_font_path = EditorSettings::get_singleton()->get("interface/editor/main_font");
Ref<DynamicFontData> CustomFont;
Ref<FontData> CustomFont;
if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) {
CustomFont.instance();
CustomFont->load_resource(custom_font_path, default_font_size);
CustomFont->set_antialiased(font_antialiased);
CustomFont->set_hinting(font_hinting);
CustomFont->set_font_path(custom_font_path);
CustomFont->set_force_autohinter(true); //just looks better..i think?
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font", "");
@ -135,12 +141,12 @@ void editor_register_fonts(Ref<Theme> p_theme) {
/* Custom Bold font */
String custom_font_path_bold = EditorSettings::get_singleton()->get("interface/editor/main_font_bold");
Ref<DynamicFontData> CustomFontBold;
Ref<FontData> CustomFontBold;
if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) {
CustomFontBold.instance();
CustomFontBold->load_resource(custom_font_path_bold, default_font_size);
CustomFontBold->set_antialiased(font_antialiased);
CustomFontBold->set_hinting(font_hinting);
CustomFontBold->set_font_path(custom_font_path_bold);
CustomFontBold->set_force_autohinter(true); //just looks better..i think?
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/main_font_bold", "");
@ -149,12 +155,12 @@ void editor_register_fonts(Ref<Theme> p_theme) {
/* Custom source code font */
String custom_font_path_source = EditorSettings::get_singleton()->get("interface/editor/code_font");
Ref<DynamicFontData> CustomFontSource;
Ref<FontData> CustomFontSource;
if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) {
CustomFontSource.instance();
CustomFontSource->load_resource(custom_font_path_source, default_font_size);
CustomFontSource->set_antialiased(font_antialiased);
CustomFontSource->set_hinting(font_hinting);
CustomFontSource->set_font_path(custom_font_path_source);
} else {
EditorSettings::get_singleton()->set_manually("interface/editor/code_font", "");
}
@ -163,115 +169,167 @@ void editor_register_fonts(Ref<Theme> p_theme) {
/* Droid Sans */
Ref<DynamicFontData> DefaultFont;
Ref<FontData> DefaultFont;
DefaultFont.instance();
DefaultFont->load_memory(_font_NotoSansUI_Regular, _font_NotoSansUI_Regular_size, "ttf", default_font_size);
DefaultFont->set_antialiased(font_antialiased);
DefaultFont->set_hinting(font_hinting);
DefaultFont->set_font_ptr(_font_NotoSansUI_Regular, _font_NotoSansUI_Regular_size);
DefaultFont->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> DefaultFontBold;
Ref<FontData> DefaultFontBold;
DefaultFontBold.instance();
DefaultFontBold->load_memory(_font_NotoSansUI_Bold, _font_NotoSansUI_Bold_size, "ttf", default_font_size);
DefaultFontBold->set_antialiased(font_antialiased);
DefaultFontBold->set_hinting(font_hinting);
DefaultFontBold->set_font_ptr(_font_NotoSansUI_Bold, _font_NotoSansUI_Bold_size);
DefaultFontBold->set_force_autohinter(true); // just looks better..i think?
Ref<DynamicFontData> FontFallback;
Ref<FontData> FontFallback;
FontFallback.instance();
FontFallback->load_memory(_font_DroidSansFallback, _font_DroidSansFallback_size, "ttf", default_font_size);
FontFallback->set_antialiased(font_antialiased);
FontFallback->set_hinting(font_hinting);
FontFallback->set_font_ptr(_font_DroidSansFallback, _font_DroidSansFallback_size);
FontFallback->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontJapanese;
Ref<FontData> FontJapanese;
FontJapanese.instance();
FontJapanese->load_memory(_font_DroidSansJapanese, _font_DroidSansJapanese_size, "ttf", default_font_size);
FontJapanese->set_antialiased(font_antialiased);
FontJapanese->set_hinting(font_hinting);
FontJapanese->set_font_ptr(_font_DroidSansJapanese, _font_DroidSansJapanese_size);
FontJapanese->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontArabic;
Ref<FontData> FontArabic;
FontArabic.instance();
FontArabic->load_memory(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, "ttf", default_font_size);
FontArabic->set_antialiased(font_antialiased);
FontArabic->set_hinting(font_hinting);
FontArabic->set_font_ptr(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size);
FontArabic->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontHebrew;
Ref<FontData> FontBengali;
FontBengali.instance();
FontBengali->load_memory(_font_NotoSansBengali_Regular, _font_NotoSansBengali_Regular_size, "ttf", default_font_size);
FontBengali->set_antialiased(font_antialiased);
FontBengali->set_hinting(font_hinting);
FontBengali->set_force_autohinter(true); //just looks better..i think?
Ref<FontData> FontGeorgian;
FontGeorgian.instance();
FontGeorgian->load_memory(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, "ttf", default_font_size);
FontGeorgian->set_antialiased(font_antialiased);
FontGeorgian->set_hinting(font_hinting);
FontGeorgian->set_force_autohinter(true); //just looks better..i think?
Ref<FontData> FontHebrew;
FontHebrew.instance();
FontHebrew->load_memory(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, "ttf", default_font_size);
FontHebrew->set_antialiased(font_antialiased);
FontHebrew->set_hinting(font_hinting);
FontHebrew->set_font_ptr(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size);
FontHebrew->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontThai;
Ref<FontData> FontMalayalam;
FontMalayalam.instance();
FontMalayalam->load_memory(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, "ttf", default_font_size);
FontMalayalam->set_antialiased(font_antialiased);
FontMalayalam->set_hinting(font_hinting);
FontMalayalam->set_force_autohinter(true); //just looks better..i think?
Ref<FontData> FontOriya;
FontOriya.instance();
FontOriya->load_memory(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, "ttf", default_font_size);
FontOriya->set_antialiased(font_antialiased);
FontOriya->set_hinting(font_hinting);
FontOriya->set_force_autohinter(true); //just looks better..i think?
Ref<FontData> FontSinhala;
FontSinhala.instance();
FontSinhala->load_memory(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, "ttf", default_font_size);
FontSinhala->set_antialiased(font_antialiased);
FontSinhala->set_hinting(font_hinting);
FontSinhala->set_force_autohinter(true); //just looks better..i think?
Ref<FontData> FontTamil;
FontTamil.instance();
FontTamil->load_memory(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, "ttf", default_font_size);
FontTamil->set_antialiased(font_antialiased);
FontTamil->set_hinting(font_hinting);
FontTamil->set_force_autohinter(true); //just looks better..i think?
Ref<FontData> FontTelugu;
FontTelugu.instance();
FontTelugu->load_memory(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, "ttf", default_font_size);
FontTelugu->set_antialiased(font_antialiased);
FontTelugu->set_hinting(font_hinting);
FontTelugu->set_force_autohinter(true); //just looks better..i think?
Ref<FontData> FontThai;
FontThai.instance();
FontThai->load_memory(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, "ttf", default_font_size);
FontThai->set_antialiased(font_antialiased);
FontThai->set_hinting(font_hinting);
FontThai->set_font_ptr(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size);
FontThai->set_force_autohinter(true); //just looks better..i think?
Ref<DynamicFontData> FontHindi;
Ref<FontData> FontHindi;
FontHindi.instance();
FontHindi->load_memory(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, "ttf", default_font_size);
FontHindi->set_antialiased(font_antialiased);
FontHindi->set_hinting(font_hinting);
FontHindi->set_font_ptr(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size);
FontHindi->set_force_autohinter(true); //just looks better..i think?
/* Hack */
Ref<DynamicFontData> dfmono;
Ref<FontData> dfmono;
dfmono.instance();
dfmono->load_memory(_font_Hack_Regular, _font_Hack_Regular_size, "ttf", default_font_size);
dfmono->set_antialiased(font_antialiased);
dfmono->set_hinting(font_hinting);
dfmono->set_font_ptr(_font_Hack_Regular, _font_Hack_Regular_size);
int default_font_size = int(EDITOR_GET("interface/editor/main_font_size")) * EDSCALE;
// Default font
MAKE_DEFAULT_FONT(df, default_font_size);
p_theme->set_default_font(df); // Default theme font
MAKE_DEFAULT_FONT(df);
p_theme->set_default_theme_font(df); // Default theme font
p_theme->set_default_theme_font_size(default_font_size);
p_theme->set_font_size("main_size", "EditorFonts", default_font_size);
p_theme->set_font("main", "EditorFonts", df);
// Bold font
MAKE_BOLD_FONT(df_bold, default_font_size);
MAKE_BOLD_FONT(df_bold);
p_theme->set_font_size("bold_size", "EditorFonts", default_font_size);
p_theme->set_font("bold", "EditorFonts", df_bold);
// Title font
MAKE_BOLD_FONT(df_title, default_font_size + 2 * EDSCALE);
p_theme->set_font("title", "EditorFonts", df_title);
p_theme->set_font_size("title_size", "EditorFonts", default_font_size + 2 * EDSCALE);
p_theme->set_font("title", "EditorFonts", df_bold);
// Documentation fonts
MAKE_DEFAULT_FONT(df_doc, int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE);
MAKE_BOLD_FONT(df_doc_bold, int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE);
MAKE_BOLD_FONT(df_doc_title, int(EDITOR_GET("text_editor/help/help_title_font_size")) * EDSCALE);
MAKE_SOURCE_FONT(df_doc_code, int(EDITOR_GET("text_editor/help/help_source_font_size")) * EDSCALE);
MAKE_SOURCE_FONT(df_doc_kbd, (int(EDITOR_GET("text_editor/help/help_source_font_size")) - 1) * EDSCALE);
p_theme->set_font("doc", "EditorFonts", df_doc);
p_theme->set_font("doc_bold", "EditorFonts", df_doc_bold);
p_theme->set_font("doc_title", "EditorFonts", df_doc_title);
p_theme->set_font("doc_source", "EditorFonts", df_doc_code);
p_theme->set_font("doc_keyboard", "EditorFonts", df_doc_kbd);
MAKE_SOURCE_FONT(df_code);
p_theme->set_font_size("doc_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE);
p_theme->set_font("doc", "EditorFonts", df);
p_theme->set_font_size("doc_bold_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE);
p_theme->set_font("doc_bold", "EditorFonts", df_bold);
p_theme->set_font_size("doc_title_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_title_font_size")) * EDSCALE);
p_theme->set_font("doc_title", "EditorFonts", df_bold);
p_theme->set_font_size("doc_source_size", "EditorFonts", int(EDITOR_GET("text_editor/help/help_source_font_size")) * EDSCALE);
p_theme->set_font("doc_source", "EditorFonts", df_code);
p_theme->set_font_size("doc_keyboard_size", "EditorFonts", (int(EDITOR_GET("text_editor/help/help_source_font_size")) - 1) * EDSCALE);
p_theme->set_font("doc_keyboard", "EditorFonts", df_code);
// Ruler font
MAKE_DEFAULT_FONT(df_rulers, 8 * EDSCALE);
p_theme->set_font("rulers", "EditorFonts", df_rulers);
p_theme->set_font_size("rulers_size", "EditorFonts", 8 * EDSCALE);
p_theme->set_font("rulers", "EditorFonts", df);
// Rotation widget font
MAKE_DEFAULT_FONT(df_rotation_control, 14 * EDSCALE);
p_theme->set_font("rotation_control", "EditorFonts", df_rotation_control);
p_theme->set_font_size("rotation_control_size", "EditorFonts", 14 * EDSCALE);
p_theme->set_font("rotation_control", "EditorFonts", df);
// Code font
MAKE_SOURCE_FONT(df_code, int(EDITOR_GET("interface/editor/code_font_size")) * EDSCALE);
p_theme->set_font_size("source_size", "EditorFonts", int(EDITOR_GET("interface/editor/code_font_size")) * EDSCALE);
p_theme->set_font("source", "EditorFonts", df_code);
MAKE_SOURCE_FONT(df_expression, (int(EDITOR_GET("interface/editor/code_font_size")) - 1) * EDSCALE);
p_theme->set_font("expression", "EditorFonts", df_expression);
p_theme->set_font_size("expression_size", "EditorFonts", (int(EDITOR_GET("interface/editor/code_font_size")) - 1) * EDSCALE);
p_theme->set_font("expression", "EditorFonts", df_code);
MAKE_SOURCE_FONT(df_output_code, int(EDITOR_GET("run/output/font_size")) * EDSCALE);
p_theme->set_font("output_source", "EditorFonts", df_output_code);
p_theme->set_font_size("output_source_size", "EditorFonts", int(EDITOR_GET("run/output/font_size")) * EDSCALE);
p_theme->set_font("output_source", "EditorFonts", df_code);
MAKE_SOURCE_FONT(df_text_editor_status_code, default_font_size);
p_theme->set_font("status_source", "EditorFonts", df_text_editor_status_code);
p_theme->set_font_size("status_source_size", "EditorFonts", default_font_size);
p_theme->set_font("status_source", "EditorFonts", df_code);
}

View File

@ -168,7 +168,8 @@ void EditorHelp::_class_desc_resized() {
// Add extra horizontal margins for better readability.
// The margins increase as the width of the editor help container increases.
Ref<Font> doc_code_font = get_theme_font("doc_source", "EditorFonts");
real_t char_width = doc_code_font->get_char_size('x').width;
int font_size = get_theme_font_size("doc_source_size", "EditorFonts");
real_t char_width = doc_code_font->get_char_size('x', 0, font_size).width;
const int display_margin = MAX(30 * EDSCALE, get_parent_anchorable_rect().size.width - char_width * 120 * EDSCALE) * 0.5;
Ref<StyleBox> class_desc_stylebox = EditorNode::get_singleton()->get_theme_base()->get_theme_stylebox("normal", "RichTextLabel")->duplicate();

View File

@ -41,7 +41,8 @@
Size2 EditorProperty::get_minimum_size() const {
Size2 ms;
Ref<Font> font = get_theme_font("font", "Tree");
ms.height = font->get_height();
int font_size = get_theme_font_size("font_size", "Tree");
ms.height = font->get_height(font_size);
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@ -108,7 +109,8 @@ void EditorProperty::_notification(int p_what) {
{
int child_room = size.width * (1.0 - split_ratio);
Ref<Font> font = get_theme_font("font", "Tree");
int height = font->get_height();
int font_size = get_theme_font_size("font_size", "Tree");
int height = font->get_height(font_size);
bool no_children = true;
//compute room needed
@ -135,7 +137,11 @@ void EditorProperty::_notification(int p_what) {
rect = Rect2(size.width - 1, 0, 1, height);
} else {
text_size = MAX(0, size.width - (child_room + 4 * EDSCALE));
rect = Rect2(size.width - child_room, 0, child_room, height);
if (is_layout_rtl()) {
rect = Rect2(1, 0, child_room, height);
} else {
rect = Rect2(size.width - child_room, 0, child_room, height);
}
}
if (bottom_editor) {
@ -154,6 +160,9 @@ void EditorProperty::_notification(int p_what) {
}
rect.size.x -= key->get_width() + get_theme_constant("hseparator", "Tree");
if (is_layout_rtl()) {
rect.position.x += key->get_width() + get_theme_constant("hseparator", "Tree");
}
if (no_children) {
text_size -= key->get_width() + 4 * EDSCALE;
@ -167,6 +176,10 @@ void EditorProperty::_notification(int p_what) {
rect.size.x -= close->get_width() + get_theme_constant("hseparator", "Tree");
if (is_layout_rtl()) {
rect.position.x += close->get_width() + get_theme_constant("hseparator", "Tree");
}
if (no_children) {
text_size -= close->get_width() + 4 * EDSCALE;
}
@ -200,7 +213,9 @@ void EditorProperty::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
Ref<Font> font = get_theme_font("font", "Tree");
int font_size = get_theme_font_size("font_size", "Tree");
Color dark_color = get_theme_color("dark_color_2", "Editor");
bool rtl = is_layout_rtl();
Size2 size = get_size();
if (bottom_editor) {
@ -249,7 +264,11 @@ void EditorProperty::_notification(int p_what) {
color2.b *= 1.2;
}
check_rect = Rect2(ofs, ((size.height - checkbox->get_height()) / 2), checkbox->get_width(), checkbox->get_height());
draw_texture(checkbox, check_rect.position, color2);
if (rtl) {
draw_texture(checkbox, Vector2(size.width - check_rect.position.x - checkbox->get_width(), check_rect.position.y), color2);
} else {
draw_texture(checkbox, check_rect.position, color2);
}
ofs += get_theme_constant("hseparator", "Tree") + checkbox->get_width() + get_theme_constant("hseparation", "CheckBox");
text_limit -= ofs;
} else {
@ -267,14 +286,21 @@ void EditorProperty::_notification(int p_what) {
color2.g *= 1.2;
color2.b *= 1.2;
}
draw_texture(reload_icon, revert_rect.position, color2);
if (rtl) {
draw_texture(reload_icon, Vector2(size.width - revert_rect.position.x - reload_icon->get_width(), revert_rect.position.y), color2);
} else {
draw_texture(reload_icon, revert_rect.position, color2);
}
} else {
revert_rect = Rect2();
}
int v_ofs = (size.height - font->get_height()) / 2;
draw_string(font, Point2(ofs, v_ofs + font->get_ascent()), label, color, text_limit);
int v_ofs = (size.height - font->get_height(font_size)) / 2;
if (rtl) {
draw_string(font, Point2(size.width - ofs - text_limit, v_ofs + font->get_ascent(font_size)), label, HALIGN_RIGHT, text_limit, font_size, color);
} else {
draw_string(font, Point2(ofs, v_ofs + font->get_ascent(font_size)), label, HALIGN_LEFT, text_limit, font_size, color);
}
if (keying) {
Ref<Texture2D> key;
@ -294,7 +320,12 @@ void EditorProperty::_notification(int p_what) {
color2.b *= 1.2;
}
keying_rect = Rect2(ofs, ((size.height - key->get_height()) / 2), key->get_width(), key->get_height());
draw_texture(key, keying_rect.position, color2);
if (rtl) {
draw_texture(key, Vector2(size.width - keying_rect.position.x - key->get_width(), keying_rect.position.y), color2);
} else {
draw_texture(key, keying_rect.position, color2);
}
} else {
keying_rect = Rect2();
}
@ -313,7 +344,11 @@ void EditorProperty::_notification(int p_what) {
color2.b *= 1.2;
}
delete_rect = Rect2(ofs, ((size.height - close->get_height()) / 2), close->get_width(), close->get_height());
draw_texture(close, delete_rect.position, color2);
if (rtl) {
draw_texture(close, Vector2(size.width - delete_rect.position.x - close->get_width(), delete_rect.position.y), color2);
} else {
draw_texture(close, delete_rect.position, color2);
}
} else {
delete_rect = Rect2();
}
@ -648,27 +683,31 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouse> me = p_event;
if (me.is_valid()) {
Vector2 mpos = me->get_position();
if (is_layout_rtl()) {
mpos.x = get_size().x - mpos.x;
}
bool button_left = me->get_button_mask() & BUTTON_MASK_LEFT;
bool new_keying_hover = keying_rect.has_point(me->get_position()) && !button_left;
bool new_keying_hover = keying_rect.has_point(mpos) && !button_left;
if (new_keying_hover != keying_hover) {
keying_hover = new_keying_hover;
update();
}
bool new_delete_hover = delete_rect.has_point(me->get_position()) && !button_left;
bool new_delete_hover = delete_rect.has_point(mpos) && !button_left;
if (new_delete_hover != delete_hover) {
delete_hover = new_delete_hover;
update();
}
bool new_revert_hover = revert_rect.has_point(me->get_position()) && !button_left;
bool new_revert_hover = revert_rect.has_point(mpos) && !button_left;
if (new_revert_hover != revert_hover) {
revert_hover = new_revert_hover;
update();
}
bool new_check_hover = check_rect.has_point(me->get_position()) && !button_left;
bool new_check_hover = check_rect.has_point(mpos) && !button_left;
if (new_check_hover != check_hover) {
check_hover = new_check_hover;
update();
@ -678,13 +717,18 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
Vector2 mpos = mb->get_position();
if (is_layout_rtl()) {
mpos.x = get_size().x - mpos.x;
}
if (!selected && selectable) {
selected = true;
emit_signal("selected", property, -1);
update();
}
if (keying_rect.has_point(mb->get_position())) {
if (keying_rect.has_point(mpos)) {
emit_signal("property_keyed", property, use_keying_next());
if (use_keying_next()) {
@ -704,11 +748,11 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
call_deferred("update_property");
}
}
if (delete_rect.has_point(mb->get_position())) {
if (delete_rect.has_point(mpos)) {
emit_signal("property_deleted", property);
}
if (revert_rect.has_point(mb->get_position())) {
if (revert_rect.has_point(mpos)) {
Variant vorig;
Node *node = Object::cast_to<Node>(object);
@ -744,7 +788,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
}
if (check_rect.has_point(mb->get_position())) {
if (check_rect.has_point(mpos)) {
checked = !checked;
update();
emit_signal("property_checked", property, checked);
@ -1024,10 +1068,11 @@ void EditorInspectorCategory::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
draw_rect(Rect2(Vector2(), get_size()), bg_color);
Ref<Font> font = get_theme_font("font", "Tree");
int font_size = get_theme_font_size("font_size", "Tree");
int hs = get_theme_constant("hseparation", "Tree");
int w = font->get_string_size(label).width;
int w = font->get_string_size(label, font_size).width;
if (icon.is_valid()) {
w += hs + icon->get_width();
}
@ -1040,7 +1085,7 @@ void EditorInspectorCategory::_notification(int p_what) {
}
Color color = get_theme_color("font_color", "Tree");
draw_string(font, Point2(ofs, font->get_ascent() + (get_size().height - font->get_height()) / 2).floor(), label, color, get_size().width);
draw_string(font, Point2(ofs, font->get_ascent(font_size) + (get_size().height - font->get_height(font_size)) / 2).floor(), label, HALIGN_LEFT, get_size().width, font_size, color);
}
}
@ -1069,10 +1114,11 @@ Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) cons
Size2 EditorInspectorCategory::get_minimum_size() const {
Ref<Font> font = get_theme_font("font", "Tree");
int font_size = get_theme_font_size("font_size", "Tree");
Size2 ms;
ms.width = 1;
ms.height = font->get_height();
ms.height = font->get_height(font_size);
if (icon.is_valid()) {
ms.height = MAX(icon->get_height(), ms.height);
}
@ -1105,19 +1151,24 @@ void EditorInspectorSection::_test_unfold() {
void EditorInspectorSection::_notification(int p_what) {
if (p_what == NOTIFICATION_SORT_CHILDREN) {
Ref<Font> font = get_theme_font("font", "Tree");
int font_size = get_theme_font_size("font_size", "Tree");
Ref<Texture2D> arrow;
if (foldable) {
if (object->editor_is_section_unfolded(section)) {
arrow = get_theme_icon("arrow", "Tree");
} else {
arrow = get_theme_icon("arrow_collapsed", "Tree");
if (is_layout_rtl()) {
arrow = get_theme_icon("arrow_collapsed_mirrored", "Tree");
} else {
arrow = get_theme_icon("arrow_collapsed", "Tree");
}
}
}
Size2 size = get_size();
Point2 offset;
offset.y = font->get_height();
offset.y = font->get_height(font_size);
if (arrow.is_valid()) {
offset.y = MAX(offset.y, arrow->get_height());
}
@ -1148,18 +1199,20 @@ void EditorInspectorSection::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
Ref<Texture2D> arrow;
bool rtl = is_layout_rtl();
if (foldable) {
if (object->editor_is_section_unfolded(section)) {
arrow = get_theme_icon("arrow", "Tree");
if (rtl) {
arrow = get_theme_icon("arrow_collapsed_mirrored", "Tree");
} else {
arrow = get_theme_icon("arrow_collapsed", "Tree");
}
}
Ref<Font> font = get_theme_font("font", "Tree");
int font_size = get_theme_font_size("font_size", "Tree");
int h = font->get_height();
int h = font->get_height(font_size);
if (arrow.is_valid()) {
h = MAX(h, arrow->get_height());
}
@ -1169,10 +1222,15 @@ void EditorInspectorSection::_notification(int p_what) {
const int arrow_margin = 3;
Color color = get_theme_color("font_color", "Tree");
draw_string(font, Point2(Math::round((16 + arrow_margin) * EDSCALE), font->get_ascent() + (h - font->get_height()) / 2).floor(), label, color, get_size().width);
float text_width = get_size().width - Math::round((16 + arrow_margin) * EDSCALE);
draw_string(font, Point2(rtl ? 0 : Math::round((16 + arrow_margin) * EDSCALE), font->get_ascent(font_size) + (h - font->get_height(font_size)) / 2).floor(), label, rtl ? HALIGN_RIGHT : HALIGN_LEFT, text_width, font_size, color);
if (arrow.is_valid()) {
draw_texture(arrow, Point2(Math::round(arrow_margin * EDSCALE), (h - arrow->get_height()) / 2).floor());
if (rtl) {
draw_texture(arrow, Point2(get_size().width - arrow->get_width() - Math::round(arrow_margin * EDSCALE), (h - arrow->get_height()) / 2).floor());
} else {
draw_texture(arrow, Point2(Math::round(arrow_margin * EDSCALE), (h - arrow->get_height()) / 2).floor());
}
}
if (dropping && !vbox->is_visible_in_tree()) {
@ -1237,7 +1295,8 @@ Size2 EditorInspectorSection::get_minimum_size() const {
}
Ref<Font> font = get_theme_font("font", "Tree");
ms.height += font->get_height() + get_theme_constant("vseparation", "Tree");
int font_size = get_theme_font_size("font_size", "Tree");
ms.height += font->get_height(font_size) + get_theme_constant("vseparation", "Tree");
ms.width += get_theme_constant("inspector_margin", "Editor");
return ms;
@ -1273,7 +1332,8 @@ void EditorInspectorSection::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
Ref<Font> font = get_theme_font("font", "Tree");
if (mb->get_position().y > font->get_height()) { //clicked outside
int font_size = get_theme_font_size("font_size", "Tree");
if (mb->get_position().y > font->get_height(font_size)) { //clicked outside
return;
}

View File

@ -69,13 +69,13 @@ private:
Rect2 bottom_child_rect;
Rect2 keying_rect;
bool keying_hover;
bool keying_hover = false;
Rect2 revert_rect;
bool revert_hover;
bool revert_hover = false;
Rect2 check_rect;
bool check_hover;
bool check_hover = false;
Rect2 delete_rect;
bool delete_hover;
bool delete_hover = false;
bool can_revert;

View File

@ -35,7 +35,7 @@
#include "editor_node.h"
#include "editor_scale.h"
#include "scene/gui/center_container.h"
#include "scene/resources/dynamic_font.h"
#include "scene/resources/font.h"
void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_file, int p_line, const char *p_error, const char *p_errorexp, ErrorHandlerType p_type) {
EditorLog *self = (EditorLog *)p_self;
@ -61,12 +61,14 @@ void EditorLog::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
//button->set_icon(get_icon("Console","EditorIcons"));
log->add_theme_font_override("normal_font", get_theme_font("output_source", "EditorFonts"));
log->add_theme_font_size_override("normal_font_size", get_theme_font_size("output_source_size", "EditorFonts"));
log->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4));
} else if (p_what == NOTIFICATION_THEME_CHANGED) {
Ref<DynamicFont> df_output_code = get_theme_font("output_source", "EditorFonts");
Ref<Font> df_output_code = get_theme_font("output_source", "EditorFonts");
if (df_output_code.is_valid()) {
if (log != nullptr) {
log->add_theme_font_override("normal_font", get_theme_font("output_source", "EditorFonts"));
log->add_theme_font_size_override("normal_font_size", get_theme_font_size("output_source_size", "EditorFonts"));
log->add_theme_color_override("selection_color", get_theme_color("accent_color", "Editor") * Color(1, 1, 1, 0.4));
}
}

View File

@ -125,6 +125,7 @@
#include "editor/plugins/debugger_editor_plugin.h"
#include "editor/plugins/editor_debugger_plugin.h"
#include "editor/plugins/editor_preview_plugins.h"
#include "editor/plugins/font_editor_plugin.h"
#include "editor/plugins/gi_probe_editor_plugin.h"
#include "editor/plugins/gpu_particles_2d_editor_plugin.h"
#include "editor/plugins/gpu_particles_3d_editor_plugin.h"
@ -140,6 +141,7 @@
#include "editor/plugins/multimesh_editor_plugin.h"
#include "editor/plugins/navigation_polygon_editor_plugin.h"
#include "editor/plugins/node_3d_editor_plugin.h"
#include "editor/plugins/ot_features_plugin.h"
#include "editor/plugins/packed_scene_translation_parser_plugin.h"
#include "editor/plugins/path_2d_editor_plugin.h"
#include "editor/plugins/path_3d_editor_plugin.h"
@ -336,7 +338,11 @@ void EditorNode::_update_scene_tabs() {
if (scene_tabs->get_offset_buttons_visible()) {
// move add button to fixed position on the tabbar
if (scene_tab_add->get_parent() == scene_tabs) {
scene_tab_add->set_position(Point2(0, 0));
if (scene_tabs->is_layout_rtl()) {
scene_tab_add->set_position(Point2(tabbar_container->get_size().x - scene_tab_add->get_size().x, 0));
} else {
scene_tab_add->set_position(Point2(0, 0));
}
scene_tabs->remove_child(scene_tab_add);
tabbar_container->add_child(scene_tab_add);
tabbar_container->move_child(scene_tab_add, 1);
@ -351,7 +357,11 @@ void EditorNode::_update_scene_tabs() {
if (scene_tabs->get_tab_count() != 0) {
last_tab = scene_tabs->get_tab_rect(scene_tabs->get_tab_count() - 1);
}
scene_tab_add->set_position(Point2(last_tab.get_position().x + last_tab.get_size().x + 3, last_tab.get_position().y));
if (scene_tabs->is_layout_rtl()) {
scene_tab_add->set_position(Point2(last_tab.get_position().x - scene_tab_add->get_size().x - 3, last_tab.get_position().y));
} else {
scene_tab_add->set_position(Point2(last_tab.get_position().x + last_tab.get_size().x + 3, last_tab.get_position().y));
}
}
}
@ -647,8 +657,13 @@ void EditorNode::_notification(int p_what) {
bottom_panel_raise->set_icon(gui_base->get_theme_icon("ExpandBottomDock", "EditorIcons"));
// clear_button->set_icon(gui_base->get_icon("Close", "EditorIcons")); don't have access to that node. needs to become a class property
dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons"));
dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons"));
if (gui_base->is_layout_rtl()) {
dock_tab_move_left->set_icon(theme->get_icon("Forward", "EditorIcons"));
dock_tab_move_right->set_icon(theme->get_icon("Back", "EditorIcons"));
} else {
dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons"));
dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons"));
}
PopupMenu *p = help_menu->get_popup();
p->set_item_icon(p->get_item_index(HELP_SEARCH), gui_base->get_theme_icon("HelpSearch", "EditorIcons"));
@ -5878,7 +5893,11 @@ EditorNode::EditorNode() {
HBoxContainer *dock_hb = memnew(HBoxContainer);
dock_tab_move_left = memnew(Button);
dock_tab_move_left->set_flat(true);
dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons"));
if (gui_base->is_layout_rtl()) {
dock_tab_move_left->set_icon(theme->get_icon("Forward", "EditorIcons"));
} else {
dock_tab_move_left->set_icon(theme->get_icon("Back", "EditorIcons"));
}
dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE);
dock_tab_move_left->connect("pressed", callable_mp(this, &EditorNode::_dock_move_left));
dock_hb->add_child(dock_tab_move_left);
@ -5891,7 +5910,11 @@ EditorNode::EditorNode() {
dock_tab_move_right = memnew(Button);
dock_tab_move_right->set_flat(true);
dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons"));
if (gui_base->is_layout_rtl()) {
dock_tab_move_right->set_icon(theme->get_icon("Forward", "EditorIcons"));
} else {
dock_tab_move_right->set_icon(theme->get_icon("Back", "EditorIcons"));
}
dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE);
dock_tab_move_right->connect("pressed", callable_mp(this, &EditorNode::_dock_move_right));
@ -6349,6 +6372,7 @@ EditorNode::EditorNode() {
video_driver->set_focus_mode(Control::FOCUS_NONE);
video_driver->connect("item_selected", callable_mp(this, &EditorNode::_video_driver_selected));
video_driver->add_theme_font_override("font", gui_base->get_theme_font("bold", "EditorFonts"));
video_driver->add_theme_font_size_override("font_size", gui_base->get_theme_font_size("bold_size", "EditorFonts"));
// TODO re-enable when GLES2 is ported
video_driver->set_disabled(true);
right_menu_hb->add_child(video_driver);
@ -6648,6 +6672,8 @@ EditorNode::EditorNode() {
add_editor_plugin(memnew(GradientEditorPlugin(this)));
add_editor_plugin(memnew(CollisionShape2DEditorPlugin(this)));
add_editor_plugin(memnew(CurveEditorPlugin(this)));
add_editor_plugin(memnew(FontEditorPlugin(this)));
add_editor_plugin(memnew(OpenTypeFeaturesEditorPlugin(this)));
add_editor_plugin(memnew(TextureEditorPlugin(this)));
add_editor_plugin(memnew(TextureLayeredEditorPlugin(this)));
add_editor_plugin(memnew(Texture3DEditorPlugin(this)));

View File

@ -36,7 +36,7 @@
#include "editor_properties_array_dict.h"
#include "editor_scale.h"
#include "scene/main/window.h"
#include "scene/resources/dynamic_font.h"
#include "scene/resources/font.h"
///////////////////// NULL /////////////////////////
@ -146,7 +146,8 @@ void EditorPropertyMultilineText::_notification(int p_what) {
Ref<Texture2D> df = get_theme_icon("DistractionFree", "EditorIcons");
open_big_text->set_icon(df);
Ref<Font> font = get_theme_font("font", "Label");
text->set_custom_minimum_size(Vector2(0, font->get_height() * 6));
int font_size = get_theme_font_size("font_size", "Label");
text->set_custom_minimum_size(Vector2(0, font->get_height(font_size) * 6));
} break;
}
@ -290,6 +291,7 @@ EditorPropertyPath::EditorPropertyPath() {
HBoxContainer *path_hb = memnew(HBoxContainer);
add_child(path_hb);
path = memnew(LineEdit);
path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
path_hb->add_child(path);
path->connect("text_entered", callable_mp(this, &EditorPropertyPath::_path_selected));
path->connect("focus_exited", callable_mp(this, &EditorPropertyPath::_path_focus_exited));
@ -587,7 +589,8 @@ public:
virtual Size2 get_minimum_size() const override {
Ref<Font> font = get_theme_font("font", "Label");
return Vector2(0, font->get_height() * 2);
int font_size = get_theme_font_size("font_size", "Label");
return Vector2(0, font->get_height(font_size) * 2);
}
virtual String get_tooltip(const Point2 &p_pos) const override {
@ -985,6 +988,7 @@ void EditorPropertyEasing::_draw_easing() {
const float exp = get_edited_object()->get(get_edited_property());
const Ref<Font> f = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
const Color font_color = get_theme_color("font_color", "Label");
Color line_color;
if (dragging) {
@ -1022,7 +1026,7 @@ void EditorPropertyEasing::_draw_easing() {
} else {
decimals = 1;
}
f->draw(ci, Point2(10, 10 + f->get_ascent()), rtos(exp).pad_decimals(decimals), font_color);
f->draw_string(ci, Point2(10, 10 + f->get_ascent(font_size)), TS->format_number(rtos(exp).pad_decimals(decimals)), HALIGN_LEFT, -1, font_size, font_color);
}
void EditorPropertyEasing::update_property() {
@ -1039,7 +1043,7 @@ void EditorPropertyEasing::_set_preset(int p_preset) {
void EditorPropertyEasing::_setup_spin() {
setting = true;
spin->setup_and_show();
spin->get_line_edit()->set_text(rtos(get_edited_object()->get(get_edited_property())));
spin->get_line_edit()->set_text(TS->format_number(rtos(get_edited_object()->get(get_edited_property()))));
setting = false;
spin->show();
}
@ -1088,7 +1092,7 @@ void EditorPropertyEasing::_notification(int p_what) {
preset->add_icon_item(get_theme_icon("CurveInOut", "EditorIcons"), "In-Out", EASING_IN_OUT);
preset->add_icon_item(get_theme_icon("CurveOutIn", "EditorIcons"), "Out-In", EASING_OUT_IN);
}
easing_draw->set_custom_minimum_size(Size2(0, get_theme_font("font", "Label")->get_height() * 2));
easing_draw->set_custom_minimum_size(Size2(0, get_theme_font("font", "Label")->get_height(get_theme_font_size("font_size", "Label")) * 2));
} break;
}
}
@ -3016,7 +3020,7 @@ bool EditorPropertyResource::_is_drop_valid(const Dictionary &p_drag_data) const
} else if (at == "ShaderMaterial") {
allowed_types.append("Shader");
} else if (at == "Font") {
allowed_types.append("DynamicFontData");
allowed_types.append("FontData");
}
}
@ -3115,9 +3119,9 @@ void EditorPropertyResource::drop_data_fw(const Point2 &p_point, const Variant &
break;
}
if (at == "Font" && ClassDB::is_parent_class(res->get_class(), "DynamicFontData")) {
Ref<DynamicFont> font = memnew(DynamicFont);
font->set_font_data(res);
if (at == "Font" && ClassDB::is_parent_class(res->get_class(), "FontData")) {
Ref<Font> font = memnew(Font);
font->add_data(res);
res = font;
break;
}

View File

@ -262,13 +262,30 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
String host_lang = OS::get_singleton()->get_locale();
host_lang = TranslationServer::standardize_locale(host_lang);
// Some locales are not properly supported currently in Godot due to lack of font shaping
// (e.g. Arabic or Hindi), so even though we have work in progress translations for them,
// we skip them as they don't render properly. (GH-28577)
const Vector<String> locales_to_skip = String("ar,bn,fa,he,hi,ml,si,ta,te,ur").split(",");
// Skip locales if Text server lack required features.
Vector<String> locales_to_skip;
if (!TS->has_feature(TextServer::FEATURE_BIDI_LAYOUT) || !TS->has_feature(TextServer::FEATURE_SHAPING)) {
locales_to_skip.push_back("ar"); // Arabic
locales_to_skip.push_back("fa"); // Persian
locales_to_skip.push_back("ur"); // Urdu
}
if (!TS->has_feature(TextServer::FEATURE_BIDI_LAYOUT)) {
locales_to_skip.push_back("he"); // Hebrew
}
if (!TS->has_feature(TextServer::FEATURE_SHAPING)) {
locales_to_skip.push_back("bn"); // Bengali
locales_to_skip.push_back("hi"); // Hindi
locales_to_skip.push_back("ml"); // Malayalam
locales_to_skip.push_back("si"); // Sinhala
locales_to_skip.push_back("ta"); // Tamil
locales_to_skip.push_back("te"); // Telugu
}
if (!locales_to_skip.empty()) {
WARN_PRINT("Some locales are not properly supported by selected Text Server and are disabled.");
}
String best;
EditorTranslationList *etl = _editor_translations;
while (etl->data) {
@ -316,6 +333,9 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["interface/editor/main_font_size"] = PropertyInfo(Variant::INT, "interface/editor/main_font_size", PROPERTY_HINT_RANGE, "8,48,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/code_font_size", 14);
hints["interface/editor/code_font_size"] = PropertyInfo(Variant::INT, "interface/editor/code_font_size", PROPERTY_HINT_RANGE, "8,48,1", PROPERTY_USAGE_DEFAULT);
_initial_set("interface/editor/code_font_contextual_ligatures", 0);
hints["interface/editor/code_font_contextual_ligatures"] = PropertyInfo(Variant::INT, "interface/editor/code_font_contextual_ligatures", PROPERTY_HINT_ENUM, "Default,Disable contextual alternates (coding ligatures),Use custom OpenType feature set", PROPERTY_USAGE_DEFAULT);
_initial_set("interface/editor/code_font_custom_opentype_features", "");
_initial_set("interface/editor/font_antialiased", true);
_initial_set("interface/editor/font_hinting", 0);
hints["interface/editor/font_hinting"] = PropertyInfo(Variant::INT, "interface/editor/font_hinting", PROPERTY_HINT_ENUM, "Auto,None,Light,Normal", PROPERTY_USAGE_DEFAULT);

View File

@ -37,13 +37,13 @@
String EditorSpinSlider::get_tooltip(const Point2 &p_pos) const {
if (grabber->is_visible()) {
return rtos(get_value()) + "\n\n" + TTR("Hold Ctrl to round to integers. Hold Shift for more precise changes.");
return TS->format_number(rtos(get_value())) + "\n\n" + TTR("Hold Ctrl to round to integers. Hold Shift for more precise changes.");
}
return rtos(get_value());
return TS->format_number(rtos(get_value()));
}
String EditorSpinSlider::get_text_value() const {
return String::num(get_value(), Math::range_step_decimals(get_step()));
return TS->format_number(String::num(get_value(), Math::range_step_decimals(get_step())));
}
void EditorSpinSlider::_gui_input(const Ref<InputEvent> &p_event) {
@ -214,10 +214,11 @@ void EditorSpinSlider::_notification(int p_what) {
draw_style_box(sb, Rect2(Vector2(), get_size()));
}
Ref<Font> font = get_theme_font("font", "LineEdit");
int font_size = get_theme_font_size("font_size", "LineEdit");
int sep_base = 4 * EDSCALE;
int sep = sep_base + sb->get_offset().x; //make it have the same margin on both sides, looks better
int string_width = font->get_string_size(label).width;
int string_width = font->get_string_size(label, font_size).width;
int number_width = get_size().width - sb->get_minimum_size().width - string_width - sep;
Ref<Texture2D> updown = get_theme_icon("updown", "SpinBox");
@ -228,7 +229,7 @@ void EditorSpinSlider::_notification(int p_what) {
String numstr = get_text_value();
int vofs = (get_size().height - font->get_height()) / 2 + font->get_ascent();
int vofs = (get_size().height - font->get_height(font_size)) / 2 + font->get_ascent(font_size);
Color fc = get_theme_color("font_color", "LineEdit");
Color lc;
@ -248,9 +249,9 @@ void EditorSpinSlider::_notification(int p_what) {
draw_style_box(focus, Rect2(Vector2(), get_size()));
}
draw_string(font, Vector2(Math::round(sb->get_offset().x), vofs), label, lc * Color(1, 1, 1, 0.5));
draw_string(font, Vector2(Math::round(sb->get_offset().x), vofs), label, HALIGN_LEFT, -1, font_size, lc * Color(1, 1, 1, 0.5));
draw_string(font, Vector2(Math::round(sb->get_offset().x + string_width + sep), vofs), numstr, fc, number_width);
draw_string(font, Vector2(Math::round(sb->get_offset().x + string_width + sep), vofs), numstr, HALIGN_LEFT, number_width, font_size, fc);
if (get_step() == 1) {
Ref<Texture2D> updown2 = get_theme_icon("updown", "SpinBox");
@ -330,9 +331,10 @@ void EditorSpinSlider::_notification(int p_what) {
Size2 EditorSpinSlider::get_minimum_size() const {
Ref<StyleBox> sb = get_theme_stylebox("normal", "LineEdit");
Ref<Font> font = get_theme_font("font", "LineEdit");
int font_size = get_theme_font_size("font_size", "LineEdit");
Size2 ms = sb->get_minimum_size();
ms.height += font->get_height();
ms.height += font->get_height(font_size);
return ms;
}
@ -360,7 +362,7 @@ void EditorSpinSlider::_evaluate_input_text() {
// This prevents using functions like `pow()`, but using functions
// in EditorSpinSlider is a barely known (and barely used) feature.
// Instead, we'd rather support German/French keyboard layouts out of the box.
const String text = value_input->get_text().replace(",", ".");
const String text = TS->parse_number(value_input->get_text().replace(",", "."));
Ref<Expression> expr;
expr.instance();

View File

@ -600,12 +600,18 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("icon_color_pressed", "Button", icon_color_pressed);
// OptionButton
theme->set_stylebox("focus", "OptionButton", style_widget_focus);
theme->set_stylebox("normal", "OptionButton", style_widget);
theme->set_stylebox("hover", "OptionButton", style_widget_hover);
theme->set_stylebox("pressed", "OptionButton", style_widget_pressed);
theme->set_stylebox("focus", "OptionButton", style_widget_focus);
theme->set_stylebox("disabled", "OptionButton", style_widget_disabled);
theme->set_stylebox("normal_mirrored", "OptionButton", style_widget);
theme->set_stylebox("hover_mirrored", "OptionButton", style_widget_hover);
theme->set_stylebox("pressed_mirrored", "OptionButton", style_widget_pressed);
theme->set_stylebox("disabled_mirrored", "OptionButton", style_widget_disabled);
theme->set_color("font_color", "OptionButton", font_color);
theme->set_color("font_color_hover", "OptionButton", font_color_hl);
theme->set_color("font_color_pressed", "OptionButton", accent_color);
@ -627,6 +633,11 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("off", "CheckButton", theme->get_icon("GuiToggleOff", "EditorIcons"));
theme->set_icon("off_disabled", "CheckButton", theme->get_icon("GuiToggleOffDisabled", "EditorIcons"));
theme->set_icon("on_mirrored", "CheckButton", theme->get_icon("GuiToggleOnMirrored", "EditorIcons"));
theme->set_icon("on_disabled_mirrored", "CheckButton", theme->get_icon("GuiToggleOnDisabledMirrored", "EditorIcons"));
theme->set_icon("off_mirrored", "CheckButton", theme->get_icon("GuiToggleOffMirrored", "EditorIcons"));
theme->set_icon("off_disabled_mirrored", "CheckButton", theme->get_icon("GuiToggleOffDisabledMirrored", "EditorIcons"));
theme->set_color("font_color", "CheckButton", font_color);
theme->set_color("font_color_hover", "CheckButton", font_color_hl);
theme->set_color("font_color_pressed", "CheckButton", accent_color);
@ -679,6 +690,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("radio_checked", "PopupMenu", theme->get_icon("GuiRadioChecked", "EditorIcons"));
theme->set_icon("radio_unchecked", "PopupMenu", theme->get_icon("GuiRadioUnchecked", "EditorIcons"));
theme->set_icon("submenu", "PopupMenu", theme->get_icon("ArrowRight", "EditorIcons"));
theme->set_icon("submenu_mirrored", "PopupMenu", theme->get_icon("ArrowLeft", "EditorIcons"));
theme->set_icon("visibility_hidden", "PopupMenu", theme->get_icon("GuiVisibilityHidden", "EditorIcons"));
theme->set_icon("visibility_visible", "PopupMenu", theme->get_icon("GuiVisibilityVisible", "EditorIcons"));
theme->set_icon("visibility_xray", "PopupMenu", theme->get_icon("GuiVisibilityXray", "EditorIcons"));
@ -707,6 +719,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("unchecked", "Tree", theme->get_icon("GuiUnchecked", "EditorIcons"));
theme->set_icon("arrow", "Tree", theme->get_icon("GuiTreeArrowDown", "EditorIcons"));
theme->set_icon("arrow_collapsed", "Tree", theme->get_icon("GuiTreeArrowRight", "EditorIcons"));
theme->set_icon("arrow_collapsed_mirrored", "Tree", theme->get_icon("GuiTreeArrowLeft", "EditorIcons"));
theme->set_icon("updown", "Tree", theme->get_icon("GuiTreeUpdown", "EditorIcons"));
theme->set_icon("select_arrow", "Tree", theme->get_icon("GuiDropdown", "EditorIcons"));
theme->set_stylebox("bg_focus", "Tree", style_focus);
@ -851,7 +864,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("DebuggerPanel", "EditorStyles", style_panel_debugger);
Ref<StyleBoxFlat> style_panel_invisible_top = style_content_panel->duplicate();
int stylebox_offset = theme->get_font("tab_fg", "TabContainer")->get_height() + theme->get_stylebox("tab_fg", "TabContainer")->get_minimum_size().height + theme->get_stylebox("panel", "TabContainer")->get_default_margin(MARGIN_TOP);
int stylebox_offset = theme->get_font("tab_fg", "TabContainer")->get_height(theme->get_font_size("tab_fg", "TabContainer")) + theme->get_stylebox("tab_fg", "TabContainer")->get_minimum_size().height + theme->get_stylebox("panel", "TabContainer")->get_default_margin(MARGIN_TOP);
style_panel_invisible_top->set_expand_margin_size(MARGIN_TOP, -stylebox_offset);
style_panel_invisible_top->set_default_margin(MARGIN_TOP, 0);
theme->set_stylebox("BottomPanelDebuggerOverride", "EditorStyles", style_panel_invisible_top);
@ -931,6 +944,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("title_height", "Window", 24 * EDSCALE);
theme->set_constant("resize_margin", "Window", 4 * EDSCALE);
theme->set_font("title_font", "Window", theme->get_font("title", "EditorFonts"));
theme->set_font_size("title_font_size", "Window", theme->get_font_size("title_size", "EditorFonts"));
// complex window, for now only Editor settings and Project settings
Ref<StyleBoxFlat> style_complex_window = style_window->duplicate();

View File

@ -68,6 +68,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
}
subdirectory_item->set_text(0, dname);
subdirectory_item->set_structured_text_bidi_override(0, STRUCTURED_TEXT_FILE);
subdirectory_item->set_icon(0, get_theme_icon("Folder", "EditorIcons"));
subdirectory_item->set_icon_modulate(0, get_theme_color("folder_icon_modulate", "FileDialog"));
subdirectory_item->set_selectable(0, true);
@ -136,6 +137,7 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
TreeItem *file_item = tree->create_item(subdirectory_item);
file_item->set_text(0, fi.name);
file_item->set_structured_text_bidi_override(0, STRUCTURED_TEXT_FILE);
file_item->set_icon(0, _get_tree_item_icon(!fi.import_broken, fi.type));
String file_metadata = lpath.plus_file(fi.name);
file_item->set_metadata(0, file_metadata);
@ -320,6 +322,8 @@ void FileSystemDock::_update_display_mode(bool p_force) {
void FileSystemDock::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_ENTER_TREE: {
if (initialized) {
return;
@ -348,8 +352,13 @@ void FileSystemDock::_notification(int p_what) {
file_list_search_box->set_clear_button_enabled(true);
file_list_button_sort->set_icon(get_theme_icon("Sort", ei));
button_hist_next->set_icon(get_theme_icon("Forward", ei));
button_hist_prev->set_icon(get_theme_icon("Back", ei));
if (is_layout_rtl()) {
button_hist_next->set_icon(get_theme_icon("Back", ei));
button_hist_prev->set_icon(get_theme_icon("Forward", ei));
} else {
button_hist_next->set_icon(get_theme_icon("Forward", ei));
button_hist_prev->set_icon(get_theme_icon("Back", ei));
}
file_list_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_list_rmb_option));
tree_popup->connect("id_pressed", callable_mp(this, &FileSystemDock::_tree_rmb_option));
@ -402,8 +411,13 @@ void FileSystemDock::_notification(int p_what) {
String ei = "EditorIcons";
button_reload->set_icon(get_theme_icon("Reload", ei));
button_toggle_display_mode->set_icon(get_theme_icon("Panels2", ei));
button_hist_next->set_icon(get_theme_icon("Forward", ei));
button_hist_prev->set_icon(get_theme_icon("Back", ei));
if (is_layout_rtl()) {
button_hist_next->set_icon(get_theme_icon("Back", ei));
button_hist_prev->set_icon(get_theme_icon("Forward", ei));
} else {
button_hist_next->set_icon(get_theme_icon("Forward", ei));
button_hist_prev->set_icon(get_theme_icon("Back", ei));
}
if (file_list_display_mode == FILE_LIST_DISPLAY_LIST) {
button_file_list_display_mode->set_icon(get_theme_icon("FileThumbnail", "EditorIcons"));
} else {
@ -2693,6 +2707,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
toolbar_hbc->add_child(button_hist_next);
current_path = memnew(LineEdit);
current_path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
current_path->set_h_size_flags(SIZE_EXPAND_FILL);
_set_current_path_text(path);
toolbar_hbc->add_child(current_path);

View File

@ -571,6 +571,7 @@ FindInFilesPanel::FindInFilesPanel() {
_search_text_label = memnew(Label);
_search_text_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("source", "EditorFonts"));
_search_text_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("source_size", "EditorFonts"));
hbc->add_child(_search_text_label);
_progress_bar = memnew(ProgressBar);
@ -599,6 +600,7 @@ FindInFilesPanel::FindInFilesPanel() {
_results_display = memnew(Tree);
_results_display->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("source", "EditorFonts"));
_results_display->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("source_size", "EditorFonts"));
_results_display->set_v_size_flags(SIZE_EXPAND_FILL);
_results_display->connect("item_selected", callable_mp(this, &FindInFilesPanel::_on_result_selected));
_results_display->connect("item_edited", callable_mp(this, &FindInFilesPanel::_on_item_edited));
@ -755,10 +757,11 @@ void FindInFilesPanel::draw_result_text(Object *item_obj, Rect2 rect) {
Result r = E->value();
String item_text = item->get_text(_with_replace ? 1 : 0);
Ref<Font> font = _results_display->get_theme_font("font");
int font_size = _results_display->get_theme_font_size("font_size");
Rect2 match_rect = rect;
match_rect.position.x += font->get_string_size(item_text.left(r.begin_trimmed)).x;
match_rect.size.x = font->get_string_size(_search_text_label->get_text()).x;
match_rect.position.x += font->get_string_size(item_text.left(r.begin_trimmed), font_size).x;
match_rect.size.x = font->get_string_size(_search_text_label->get_text(), font_size).x;
match_rect.position.y += 1 * EDSCALE;
match_rect.size.y -= 2 * EDSCALE;

View File

@ -361,9 +361,16 @@ void GroupDialog::_delete_group_item(const String &p_name) {
void GroupDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED:
case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_ENTER_TREE: {
add_button->set_icon(groups->get_theme_icon("Forward", "EditorIcons"));
remove_button->set_icon(groups->get_theme_icon("Back", "EditorIcons"));
if (is_layout_rtl()) {
add_button->set_icon(groups->get_theme_icon("Back", "EditorIcons"));
remove_button->set_icon(groups->get_theme_icon("Forward", "EditorIcons"));
} else {
add_button->set_icon(groups->get_theme_icon("Forward", "EditorIcons"));
remove_button->set_icon(groups->get_theme_icon("Back", "EditorIcons"));
}
add_filter->set_right_icon(groups->get_theme_icon("Search", "EditorIcons"));
add_filter->set_clear_button_enabled(true);

View File

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m2 14c-.552262-.000055-.999945-.447738-1-1v-10c.000055-.5522619.447738-.9999448 1-1h8c.303863-.0001753.591325.1378063.78125.375l4 5c.291397.3649711.291397.8830289 0 1.248l-4 5c-.189538.237924-.477058.376652-.78125.37695h-8zm1-2h6.5195004l3.1991996-4-3.1991996-4h-6.5195004zm6.0000004-2v-4l1.9999996 2z" fill-rule="evenodd"/><path d="m3.8685125 4.9095434h4.1550816v1.1637426h-2.6154217v1.1117544h2.4594562v1.1637428h-2.4594562v1.3676976h2.7034024v1.1637432h-4.2430623z" stroke-width=".204755"/></g></svg>

After

Width:  |  Height:  |  Size: 614 B

View File

@ -0,0 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13.999798 2a-1.0001 1.0001 0 0 1 1 1v10a-1.0001 1.0001 0 0 1 -1 1h-8.0000003a-1.0001 1.0001 0 0 1 -.78125-.375l-4-5a-1.0001 1.0001 0 0 1 0-1.248l4-5a-1.0001 1.0001 0 0 1 .78125-.37695h8.0000003zm-1 2h-6.5195003l-3.1992 4 3.1992 4h6.5195003zm-3.0000003 1c1.1046003 0 2.0000003.8954 2.0000003 2v4h-1v-2h-2.0000003v2h-1v-4c0-1.1046.89543-2 2-2zm0 1a-1 1 0 0 0 -1 1v1h2.0000003v-1a-1 1 0 0 0 -1.0000003-1zm-3 0v4l-2-2z" fill="#e0e0e0" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 552 B

View File

@ -1 +0,0 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1 1037.4v4h1v-1h1v-1h4v10h-1v1h-1v1h6v-1h-1v-1h-1v-10h4v1h1v1h1v-4z" fill="#84c2ff" transform="translate(0 -1036.4)"/></svg>

Before

Width:  |  Height:  |  Size: 218 B

View File

@ -1 +0,0 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g transform="translate(0 -1036.4)"><path d="m1 1037.4v2 1h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1 -1 1v1h1 2 1v-1a1 1 0 0 1 -1-1v-6h2a1 1 0 0 1 1 1h1v-1-2h-4-2z" fill="#e0e0e0"/><path d="m4 5v2 1h1a1 1 0 0 1 1-1h2v6a1 1 0 0 1 -1 1v1h1 2 1v-1a1 1 0 0 1 -1-1v-6h2a1 1 0 0 1 1 1h1v-1-2h-4-2z" fill="#84c2ff" transform="translate(0 1036.4)"/></g></svg>

Before

Width:  |  Height:  |  Size: 423 B

View File

Before

Width:  |  Height:  |  Size: 394 B

After

Width:  |  Height:  |  Size: 394 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill-opacity=".588" fill="#fff" d="M4 3a1 1 0 0 1 1 1v6h6a1 1 0 0 1 0 2H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/></svg>

After

Width:  |  Height:  |  Size: 183 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8"><path fill-opacity=".196" fill="#fff" d="M2 0v8H0V0zm5.014.002a-1 1 0 0 1 .693.291-1 1 0 0 1 0 1.414L5.414 4l2.293 2.293a-1 1 0 0 1 0 1.414-1 1 0 0 1-1.414 0l-3-3a-1 1 0 0 1 0-1.414l3-3a-1 1 0 0 1 .72-.29z"/></svg>

After

Width:  |  Height:  |  Size: 276 B

View File

@ -0,0 +1 @@
<svg height="26" width="42" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0" transform="matrix(-1 0 0 1 42 0)"><rect fill-opacity=".188" height="16" rx="9" width="38" x="2" y="5"/><circle cx="10" cy="13" r="5"/></g></svg>

After

Width:  |  Height:  |  Size: 226 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="42" height="26"><path fill="#e0e0e0" d="M31 5c4.986 0 9 3.568 9 8s-4.014 8-9 8H11c-4.986 0-9-3.568-9-8s4.014-8 9-8zM10 8a-5 5 0 0 0-5 5-5 5 0 0 0 5 5-5 5 0 0 0 5-5-5 5 0 0 0-5-5z"/></svg>

After

Width:  |  Height:  |  Size: 235 B

View File

@ -0,0 +1 @@
<svg height="12" width="12" xmlns="http://www.w3.org/2000/svg"><path d="m7 9-3-3 3-3" style="fill:none;stroke:#fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:.392"/></svg>

After

Width:  |  Height:  |  Size: 202 B

View File

@ -332,13 +332,20 @@ Container *InspectorDock::get_addon_area() {
void InspectorDock::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
set_theme(editor->get_gui_base()->get_theme());
resource_new_button->set_icon(get_theme_icon("New", "EditorIcons"));
resource_load_button->set_icon(get_theme_icon("Load", "EditorIcons"));
resource_save_button->set_icon(get_theme_icon("Save", "EditorIcons"));
backward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
forward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
if (is_layout_rtl()) {
backward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
forward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
} else {
backward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
forward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
}
history_menu->set_icon(get_theme_icon("History", "EditorIcons"));
object_menu->set_icon(get_theme_icon("Tools", "EditorIcons"));
warning->set_icon(get_theme_icon("NodeWarning", "EditorIcons"));
@ -524,7 +531,11 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
backward_button = memnew(Button);
backward_button->set_flat(true);
general_options_hb->add_child(backward_button);
backward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
if (is_layout_rtl()) {
backward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
} else {
backward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
}
backward_button->set_flat(true);
backward_button->set_tooltip(TTR("Go to the previous edited object in history."));
backward_button->set_disabled(true);
@ -533,7 +544,11 @@ InspectorDock::InspectorDock(EditorNode *p_editor, EditorData &p_editor_data) {
forward_button = memnew(Button);
forward_button->set_flat(true);
general_options_hb->add_child(forward_button);
forward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
if (is_layout_rtl()) {
forward_button->set_icon(get_theme_icon("Back", "EditorIcons"));
} else {
forward_button->set_icon(get_theme_icon("Forward", "EditorIcons"));
}
forward_button->set_flat(true);
forward_button->set_tooltip(TTR("Go to the next edited object in history."));
forward_button->set_disabled(true);

View File

@ -37,6 +37,24 @@
#include "scene/gui/control.h"
void LocalizationEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_TEXT_SERVER_CHANGED) {
ts_name->set_text(TTR("Text server: ") + TS->get_name());
FileAccessRef file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
if (TS->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) {
if (file_check->file_exists("res://" + TS->get_support_data_filename())) {
ts_data_status->set_text(TTR("Support data: ") + TTR("Installed"));
ts_install->set_disabled(true);
} else {
ts_data_status->set_text(TTR("Support data: ") + TTR("Not installed"));
ts_install->set_disabled(false);
}
} else {
ts_data_status->set_text(TTR("Support data: ") + TTR("Not supported"));
ts_install->set_disabled(false);
}
ts_data_info->set_text(TTR("Info: ") + TS->get_support_data_info());
}
if (p_what == NOTIFICATION_ENTER_TREE) {
translation_list->connect("button_pressed", callable_mp(this, &LocalizationEditor::_translation_delete));
translation_pot_list->connect("button_pressed", callable_mp(this, &LocalizationEditor::_pot_delete));
@ -622,6 +640,26 @@ void LocalizationEditor::update_translations() {
updating_translations = false;
}
void LocalizationEditor::_install_ts_data() {
if (TS->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) {
TS->save_support_data("res://" + TS->get_support_data_filename());
}
FileAccessRef file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
if (TS->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) {
if (file_check->file_exists("res://" + TS->get_support_data_filename())) {
ts_data_status->set_text(TTR("Support data: ") + TTR("Installed"));
ts_install->set_disabled(true);
} else {
ts_data_status->set_text(TTR("Support data: ") + TTR("Not installed"));
ts_install->set_disabled(false);
}
} else {
ts_data_status->set_text(TTR("Support data: ") + TTR("Not supported"));
ts_install->set_disabled(false);
}
}
void LocalizationEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("update_translations"), &LocalizationEditor::update_translations);
@ -791,4 +829,37 @@ LocalizationEditor::LocalizationEditor() {
pot_file_open_dialog->connect("file_selected", callable_mp(this, &LocalizationEditor::_pot_add));
add_child(pot_file_open_dialog);
}
{
VBoxContainer *tvb = memnew(VBoxContainer);
tvb->set_name(TTR("Text Server Data"));
translations->add_child(tvb);
ts_name = memnew(Label(TTR("Text server: ") + TS->get_name()));
tvb->add_child(ts_name);
ts_data_status = memnew(Label(TTR("Support data: ")));
tvb->add_child(ts_data_status);
ts_data_info = memnew(Label(TTR("Info: ") + TS->get_support_data_info()));
tvb->add_child(ts_data_info);
ts_install = memnew(Button(TTR("Install support data...")));
ts_install->connect("pressed", callable_mp(this, &LocalizationEditor::_install_ts_data));
tvb->add_child(ts_install);
FileAccessRef file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
if (TS->has_feature(TextServer::FEATURE_USE_SUPPORT_DATA)) {
if (file_check->file_exists("res://" + TS->get_support_data_filename())) {
ts_data_status->set_text(TTR("Support data: ") + TTR("Installed"));
ts_install->set_disabled(true);
} else {
ts_data_status->set_text(TTR("Support data: ") + TTR("Not installed"));
ts_install->set_disabled(false);
}
} else {
ts_data_status->set_text(TTR("Support data: ") + TTR("Not supported"));
ts_install->set_disabled(false);
}
}
}

View File

@ -58,6 +58,11 @@ class LocalizationEditor : public VBoxContainer {
Vector<TreeItem *> translation_filter_treeitems;
Vector<int> translation_locales_idxs_remap;
Label *ts_name;
Label *ts_data_status;
Label *ts_data_info;
Button *ts_install;
Tree *translation_pot_list;
EditorFileDialog *pot_file_open_dialog;
EditorFileDialog *pot_generate_dialog;
@ -89,6 +94,8 @@ class LocalizationEditor : public VBoxContainer {
void _pot_generate(const String &p_file);
void _update_pot_file_extensions();
void _install_ts_data();
protected:
void _notification(int p_what);
static void _bind_methods();

View File

@ -551,9 +551,10 @@ void AbstractPolygon2DEditor::forward_canvas_draw_over_viewport(Control *p_overl
if (vertex == hover_point) {
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
String num = String::num(vertex.vertex);
Size2 num_size = font->get_string_size(num);
p_overlay->draw_string(font, point - num_size * 0.5, num, Color(1.0, 1.0, 1.0, 0.5));
Size2 num_size = font->get_string_size(num, font_size);
p_overlay->draw_string(font, point - num_size * 0.5, num, HALIGN_LEFT, -1, font_size, Color(1.0, 1.0, 1.0, 0.5));
}
}
}

View File

@ -201,6 +201,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
linecolor_soft.a *= 0.5;
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
Ref<Texture2D> icon = get_theme_icon("KeyValue", "EditorIcons");
Ref<Texture2D> icon_selected = get_theme_icon("KeySelected", "EditorIcons");
@ -221,7 +222,7 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() {
float x = point;
blend_space_draw->draw_line(Point2(x, s.height - 1), Point2(x, s.height - 5 * EDSCALE), linecolor);
blend_space_draw->draw_string(font, Point2(x + 2 * EDSCALE, s.height - 2 * EDSCALE - font->get_height() + font->get_ascent()), "0", linecolor);
blend_space_draw->draw_string(font, Point2(x + 2 * EDSCALE, s.height - 2 * EDSCALE - font->get_height(font_size) + font->get_ascent(font_size)), "0", HALIGN_LEFT, -1, font_size, linecolor);
blend_space_draw->draw_line(Point2(x, s.height - 5 * EDSCALE), Point2(x, 0), linecolor_soft);
}

View File

@ -396,6 +396,7 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
Color linecolor_soft = linecolor;
linecolor_soft.a *= 0.5;
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
Ref<Texture2D> icon = get_theme_icon("KeyValue", "EditorIcons");
Ref<Texture2D> icon_selected = get_theme_icon("KeySelected", "EditorIcons");
@ -412,14 +413,14 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() {
if (blend_space->get_min_space().y < 0) {
int y = (blend_space->get_max_space().y / (blend_space->get_max_space().y - blend_space->get_min_space().y)) * s.height;
blend_space_draw->draw_line(Point2(0, y), Point2(5 * EDSCALE, y), linecolor);
blend_space_draw->draw_string(font, Point2(2 * EDSCALE, y - font->get_height() + font->get_ascent()), "0", linecolor);
blend_space_draw->draw_string(font, Point2(2 * EDSCALE, y - font->get_height(font_size) + font->get_ascent(font_size)), "0", HALIGN_LEFT, -1, font_size, linecolor);
blend_space_draw->draw_line(Point2(5 * EDSCALE, y), Point2(s.width, y), linecolor_soft);
}
if (blend_space->get_min_space().x < 0) {
int x = (-blend_space->get_min_space().x / (blend_space->get_max_space().x - blend_space->get_min_space().x)) * s.width;
blend_space_draw->draw_line(Point2(x, s.height - 1), Point2(x, s.height - 5 * EDSCALE), linecolor);
blend_space_draw->draw_string(font, Point2(x + 2 * EDSCALE, s.height - 2 * EDSCALE - font->get_height() + font->get_ascent()), "0", linecolor);
blend_space_draw->draw_string(font, Point2(x + 2 * EDSCALE, s.height - 2 * EDSCALE - font->get_height(font_size) + font->get_ascent(font_size)), "0", HALIGN_LEFT, -1, font_size, linecolor);
blend_space_draw->draw_line(Point2(x, s.height - 5 * EDSCALE), Point2(x, 0), linecolor_soft);
}

View File

@ -105,6 +105,8 @@ void AnimationPlayerEditor::_notification(int p_what) {
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
add_theme_style_override("panel", editor->get_gui_base()->get_theme_stylebox("panel", "Panel"));
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
autoplay->set_icon(get_theme_icon("AutoPlay", "EditorIcons"));

View File

@ -559,6 +559,7 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
Ref<StyleBox> style_selected = get_theme_stylebox("state_machine_selectedframe", "GraphNode");
Ref<Font> font = get_theme_font("title_font", "GraphNode");
int font_size = get_theme_font_size("title_font_size", "GraphNode");
Color font_color = get_theme_color("title_color", "GraphNode");
Ref<Texture2D> play = get_theme_icon("Play", "EditorIcons");
Ref<Texture2D> auto_play = get_theme_icon("AutoPlay", "EditorIcons");
@ -612,9 +613,9 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
Ref<StyleBox> sb = E->get() == selected_node ? style_selected : style;
Size2 s = sb->get_minimum_size();
int strsize = font->get_string_size(name).width;
int strsize = font->get_string_size(name, font_size).width;
s.width += strsize;
s.height += MAX(font->get_height(), play->get_height());
s.height += MAX(font->get_height(font_size), play->get_height());
s.width += sep + play->get_width();
if (needs_editor) {
s.width += sep + edit->get_width();
@ -741,7 +742,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 = name == selected_node ? style_selected : style;
int strsize = font->get_string_size(name).width;
int strsize = font->get_string_size(name, font_size).width;
NodeRect &nr = node_rects.write[i];
@ -759,12 +760,12 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
bool onstart = state_machine->get_start_node() == name;
if (onstart) {
state_machine_draw->draw_string(font, offset + Vector2(0, -font->get_height() - 3 * EDSCALE + font->get_ascent()), TTR("Start"), font_color);
state_machine_draw->draw_string(font, offset + Vector2(0, -font->get_height(font_size) - 3 * EDSCALE + font->get_ascent(font_size)), TTR("Start"), HALIGN_LEFT, -1, font_size, font_color);
}
if (state_machine->get_end_node() == name) {
int endofs = nr.node.size.x - font->get_string_size(TTR("End")).x;
state_machine_draw->draw_string(font, offset + Vector2(endofs, -font->get_height() - 3 * EDSCALE + font->get_ascent()), TTR("End"), font_color);
int endofs = nr.node.size.x - font->get_string_size(TTR("End"), font_size).x;
state_machine_draw->draw_string(font, offset + Vector2(endofs, -font->get_height(font_size) - 3 * EDSCALE + font->get_ascent(font_size)), TTR("End"), HALIGN_LEFT, -1, font_size, font_color);
}
offset.x += sb->get_offset().x;
@ -781,10 +782,10 @@ void AnimationNodeStateMachineEditor::_state_machine_draw() {
}
offset.x += sep + play->get_width();
nr.name.position = offset + Vector2(0, (h - font->get_height()) / 2).floor();
nr.name.size = Vector2(strsize, font->get_height());
nr.name.position = offset + Vector2(0, (h - font->get_height(font_size)) / 2).floor();
nr.name.size = Vector2(strsize, font->get_height(font_size));
state_machine_draw->draw_string(font, nr.name.position + Vector2(0, font->get_ascent()), name, font_color);
state_machine_draw->draw_string(font, nr.name.position + Vector2(0, font->get_ascent(font_size)), name, HALIGN_LEFT, -1, font_size, font_color);
offset.x += strsize + sep;
if (needs_editor) {
@ -880,7 +881,7 @@ void AnimationNodeStateMachineEditor::_update_graph() {
}
void AnimationNodeStateMachineEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || p_what == NOTIFICATION_TRANSLATION_CHANGED) {
error_panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));
error_label->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
panel->add_theme_style_override("panel", get_theme_stylebox("bg", "Tree"));

View File

@ -236,11 +236,13 @@ AudioStreamEditor::AudioStreamEditor() {
_current_label->set_align(Label::ALIGN_RIGHT);
_current_label->set_h_size_flags(SIZE_EXPAND_FILL);
_current_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts"));
_current_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("status_source_size", "EditorFonts"));
_current_label->set_modulate(Color(1, 1, 1, 0.5));
hbox->add_child(_current_label);
_duration_label = memnew(Label);
_duration_label->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("status_source", "EditorFonts"));
_duration_label->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("status_source_size", "EditorFonts"));
hbox->add_child(_duration_label);
}

View File

@ -52,7 +52,6 @@
#include "scene/gui/subviewport_container.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/window.h"
#include "scene/resources/dynamic_font.h"
#include "scene/resources/packed_scene.h"
// Min and Max are power of two in order to play nicely with successive increment.
@ -857,7 +856,11 @@ Vector2 CanvasItemEditor::_anchor_to_position(const Control *p_control, Vector2
Transform2D parent_transform = p_control->get_transform().affine_inverse();
Rect2 parent_rect = p_control->get_parent_anchorable_rect();
return parent_transform.xform(parent_rect.position + Vector2(parent_rect.size.x * anchor.x, parent_rect.size.y * anchor.y));
if (p_control->is_layout_rtl()) {
return parent_transform.xform(parent_rect.position + Vector2(parent_rect.size.x - parent_rect.size.x * anchor.x, parent_rect.size.y * anchor.y));
} else {
return parent_transform.xform(parent_rect.position + Vector2(parent_rect.size.x * anchor.x, parent_rect.size.y * anchor.y));
}
}
Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 position) {
@ -866,7 +869,11 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2
Rect2 parent_rect = p_control->get_parent_anchorable_rect();
Vector2 output = Vector2();
output.x = (parent_rect.size.x == 0) ? 0.0 : (p_control->get_transform().xform(position).x - parent_rect.position.x) / parent_rect.size.x;
if (p_control->is_layout_rtl()) {
output.x = (parent_rect.size.x == 0) ? 0.0 : (parent_rect.size.x - p_control->get_transform().xform(position).x - parent_rect.position.x) / parent_rect.size.x;
} else {
output.x = (parent_rect.size.x == 0) ? 0.0 : (p_control->get_transform().xform(position).x - parent_rect.position.x) / parent_rect.size.x;
}
output.y = (parent_rect.size.y == 0) ? 0.0 : (p_control->get_transform().xform(position).y - parent_rect.position.y) / parent_rect.size.y;
return output;
}
@ -1628,7 +1635,11 @@ bool CanvasItemEditor::_gui_input_anchors(const Ref<InputEvent> &p_event) {
for (int i = 0; i < 4; i++) {
anchor_pos[i] = (transform * control->get_global_transform_with_canvas()).xform(_anchor_to_position(control, anchor_pos[i]));
anchor_rects[i] = Rect2(anchor_pos[i], anchor_handle->get_size());
anchor_rects[i].position -= anchor_handle->get_size() * Vector2(float(i == 0 || i == 3), float(i <= 1));
if (control->is_layout_rtl()) {
anchor_rects[i].position -= anchor_handle->get_size() * Vector2(float(i == 1 || i == 2), float(i <= 1));
} else {
anchor_rects[i].position -= anchor_handle->get_size() * Vector2(float(i == 0 || i == 3), float(i <= 1));
}
}
DragType dragger[] = {
@ -2771,7 +2782,8 @@ void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string
Color color = get_theme_color("font_color", "Editor");
color.a = 0.8;
Ref<Font> font = get_theme_font("font", "Label");
Size2 text_size = font->get_string_size(p_string);
int font_size = get_theme_font_size("font_size", "Label");
Size2 text_size = font->get_string_size(p_string, font_size);
switch (p_side) {
case MARGIN_LEFT:
p_position += Vector2(-text_size.x - 5, text_size.y / 2);
@ -2786,18 +2798,18 @@ void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string
p_position += Vector2(-text_size.x / 2, text_size.y + 5);
break;
}
viewport->draw_string(font, p_position, p_string, color);
viewport->draw_string(font, p_position, p_string, HALIGN_LEFT, -1, font_size, color);
}
void CanvasItemEditor::_draw_margin_at_position(int p_value, Point2 p_position, Margin p_side) {
String str = vformat("%d px", p_value);
String str = TS->format_number(vformat("%d " + TTR("px"), p_value));
if (p_value != 0) {
_draw_text_at_position(p_position, str, p_side);
}
}
void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side) {
String str = vformat("%.1f %%", p_value * 100.0);
String str = TS->format_number(vformat("%.1f ", p_value * 100.0)) + TS->percent_sign();
if (p_value != 0) {
_draw_text_at_position(p_position, str, p_side);
}
@ -2841,17 +2853,19 @@ void CanvasItemEditor::_draw_guides() {
Color text_color = get_theme_color("font_color", "Editor");
text_color.a = 0.5;
if (drag_type == DRAG_DOUBLE_GUIDE || drag_type == DRAG_V_GUIDE) {
String str = vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x));
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).x)));
Ref<Font> font = get_theme_font("font", "Label");
Size2 text_size = font->get_string_size(str);
viewport->draw_string(font, Point2(dragged_guide_pos.x + 10, RULER_WIDTH + text_size.y / 2 + 10), str, text_color);
int font_size = get_theme_font_size("font_size", "Label");
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, HALIGN_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 = vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y));
String str = TS->format_number(vformat("%d px", Math::round(xform.affine_inverse().xform(dragged_guide_pos).y)));
Ref<Font> font = get_theme_font("font", "Label");
Size2 text_size = font->get_string_size(str);
viewport->draw_string(font, Point2(RULER_WIDTH + 10, dragged_guide_pos.y + text_size.y / 2 + 10), str, text_color);
int font_size = get_theme_font_size("font_size", "Label");
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, HALIGN_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));
}
}
@ -2876,6 +2890,7 @@ void CanvasItemEditor::_draw_rulers() {
Color font_color = get_theme_color("font_color", "Editor");
font_color.a = 0.8;
Ref<Font> font = get_theme_font("rulers", "EditorFonts");
int font_size = get_theme_font_size("rulers_size", "EditorFonts");
// The rule transform
Transform2D ruler_transform = Transform2D();
@ -2922,7 +2937,7 @@ void CanvasItemEditor::_draw_rulers() {
if (i % (major_subdivision * minor_subdivision) == 0) {
viewport->draw_line(Point2(position.x, 0), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE));
float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x;
viewport->draw_string(font, Point2(position.x + 2, font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
viewport->draw_string(font, Point2(position.x + 2, font->get_height(font_size)), TS->format_number(vformat(((int)val == val) ? "%d" : "%.1f", val)), HALIGN_LEFT, -1, font_size, font_color);
} else {
if (i % minor_subdivision == 0) {
viewport->draw_line(Point2(position.x, RULER_WIDTH * 0.33), Point2(position.x, RULER_WIDTH), graduation_color, Math::round(EDSCALE));
@ -2940,9 +2955,9 @@ void CanvasItemEditor::_draw_rulers() {
viewport->draw_line(Point2(0, position.y), Point2(RULER_WIDTH, position.y), graduation_color, Math::round(EDSCALE));
float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y;
Transform2D text_xform = Transform2D(-Math_PI / 2.0, Point2(font->get_height(), position.y - 2));
Transform2D text_xform = Transform2D(-Math_PI / 2.0, Point2(font->get_height(font_size), position.y - 2));
viewport->draw_set_transform_matrix(viewport->get_transform() * text_xform);
viewport->draw_string(font, Point2(), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
viewport->draw_string(font, Point2(), TS->format_number(vformat(((int)val == val) ? "%d" : "%.1f", val)), HALIGN_LEFT, -1, font_size, font_color);
viewport->draw_set_transform_matrix(viewport->get_transform());
} else {
@ -3054,17 +3069,18 @@ void CanvasItemEditor::_draw_ruler_tool() {
}
Ref<Font> font = get_theme_font("bold", "EditorFonts");
int font_size = get_theme_font_size("bold_size", "EditorFonts");
Color font_color = get_theme_color("font_color", "Editor");
Color font_secondary_color = font_color;
font_secondary_color.a = 0.5;
float text_height = font->get_height();
float text_height = font->get_height(font_size);
const float text_width = 76;
const float angle_text_width = 54;
Point2 text_pos = (begin + end) / 2 - Vector2(text_width / 2, text_height / 2);
text_pos.x = CLAMP(text_pos.x, text_width / 2, viewport->get_rect().size.x - text_width * 1.5);
text_pos.y = CLAMP(text_pos.y, text_height * 1.5, viewport->get_rect().size.y - text_height * 1.5);
viewport->draw_string(font, text_pos, vformat("%.2f px", length_vector.length()), font_color);
viewport->draw_string(font, text_pos, TS->format_number(vformat("%.2f " + TTR("px"), length_vector.length())), HALIGN_LEFT, -1, font_size, font_color);
if (draw_secondary_lines) {
const float horizontal_angle_rad = atan2(length_vector.y, length_vector.x);
@ -3074,16 +3090,16 @@ 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, vformat("%.2f px", length_vector.y), font_secondary_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.2f " + TTR("px"), length_vector.y)), HALIGN_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, vformat("%d deg", vertical_angle), font_secondary_color);
viewport->draw_string(font, v_angle_text_pos, TS->format_number(vformat("%d " + TTR("deg"), vertical_angle)), HALIGN_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, vformat("%.2f px", length_vector.x), font_secondary_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.2f " + TTR("px"), length_vector.x)), HALIGN_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);
@ -3100,7 +3116,7 @@ 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, vformat("%d deg", horizontal_angle), font_secondary_color);
viewport->draw_string(font, h_angle_text_pos, TS->format_number(vformat("%d " + TTR("deg"), horizontal_angle)), HALIGN_LEFT, -1, font_size, font_secondary_color);
// Angle arcs
int arc_point_count = 8;
@ -3137,17 +3153,17 @@ 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, vformat("%.2f units", (length_vector / grid_step).length()), font_color);
viewport->draw_string(font, text_pos, TS->format_number(vformat("%.2f " + TTR("units"), (length_vector / grid_step).length())), HALIGN_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, vformat("%d units", roundf(length_vector.y / grid_step.y)), font_secondary_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.y / grid_step.y))), HALIGN_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, vformat("%d units", roundf(length_vector.x / grid_step.x)), font_secondary_color);
viewport->draw_string(font, text_pos2, TS->format_number(vformat("%d " + TTR("units"), roundf(length_vector.x / grid_step.x))), HALIGN_LEFT, -1, font_size, font_secondary_color);
} else {
viewport->draw_string(font, text_pos, vformat("%d units", roundf((length_vector / grid_step).length())), font_color);
viewport->draw_string(font, text_pos, TS->format_number(vformat("%d " + TTR("units"), roundf((length_vector / grid_step).length()))), HALIGN_LEFT, -1, font_size, font_color);
}
}
} else {
@ -3177,10 +3193,17 @@ void CanvasItemEditor::_draw_control_anchors(Control *control) {
// Draw the anchors handles
Rect2 anchor_rects[4];
anchor_rects[0] = Rect2(anchors_pos[0] - anchor_handle->get_size(), anchor_handle->get_size());
anchor_rects[1] = Rect2(anchors_pos[1] - Vector2(0.0, anchor_handle->get_size().y), Point2(-anchor_handle->get_size().x, anchor_handle->get_size().y));
anchor_rects[2] = Rect2(anchors_pos[2], -anchor_handle->get_size());
anchor_rects[3] = Rect2(anchors_pos[3] - Vector2(anchor_handle->get_size().x, 0.0), Point2(anchor_handle->get_size().x, -anchor_handle->get_size().y));
if (control->is_layout_rtl()) {
anchor_rects[0] = Rect2(anchors_pos[0] - Vector2(0.0, anchor_handle->get_size().y), Point2(-anchor_handle->get_size().x, anchor_handle->get_size().y));
anchor_rects[1] = Rect2(anchors_pos[1] - anchor_handle->get_size(), anchor_handle->get_size());
anchor_rects[2] = Rect2(anchors_pos[2] - Vector2(anchor_handle->get_size().x, 0.0), Point2(anchor_handle->get_size().x, -anchor_handle->get_size().y));
anchor_rects[3] = Rect2(anchors_pos[3], -anchor_handle->get_size());
} else {
anchor_rects[0] = Rect2(anchors_pos[0] - anchor_handle->get_size(), anchor_handle->get_size());
anchor_rects[1] = Rect2(anchors_pos[1] - Vector2(0.0, anchor_handle->get_size().y), Point2(-anchor_handle->get_size().x, anchor_handle->get_size().y));
anchor_rects[2] = Rect2(anchors_pos[2], -anchor_handle->get_size());
anchor_rects[3] = Rect2(anchors_pos[3] - Vector2(anchor_handle->get_size().x, 0.0), Point2(anchor_handle->get_size().x, -anchor_handle->get_size().y));
}
for (int i = 0; i < 4; i++) {
anchor_handle->draw_rect(ci, anchor_rects[i]);
@ -3744,6 +3767,7 @@ void CanvasItemEditor::_draw_hover() {
String node_name = hovering_results[i].name;
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
Size2 node_name_size = font->get_string_size(node_name);
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));
@ -3761,7 +3785,7 @@ void CanvasItemEditor::_draw_hover() {
viewport->draw_texture(node_icon, pos, Color(1.0, 1.0, 1.0, 0.5));
// Draw name
viewport->draw_string(font, pos + Point2(node_icon->get_size().x + 4, item_size.y - 3), node_name, Color(1.0, 1.0, 1.0, 0.5));
viewport->draw_string(font, pos + Point2(node_icon->get_size().x + 4, item_size.y - 3), node_name, HALIGN_LEFT, -1, font_size, Color(1.0, 1.0, 1.0, 0.5));
}
}
@ -4342,8 +4366,13 @@ void CanvasItemEditor::_update_scrollbars() {
}
// Move and resize the scrollbars, avoiding overlap.
v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? RULER_WIDTH : 0));
v_scroll->set_end(Point2(size.width, size.height - (h_scroll->is_visible() ? hmin.height : 0)));
if (is_layout_rtl()) {
v_scroll->set_begin(Point2(0, (show_rulers) ? RULER_WIDTH : 0));
v_scroll->set_end(Point2(vmin.width, size.height - (h_scroll->is_visible() ? hmin.height : 0)));
} else {
v_scroll->set_begin(Point2(size.width - vmin.width, (show_rulers) ? RULER_WIDTH : 0));
v_scroll->set_end(Point2(size.width, size.height - (h_scroll->is_visible() ? hmin.height : 0)));
}
h_scroll->set_begin(Point2((show_rulers) ? RULER_WIDTH : 0, size.height - hmin.height));
h_scroll->set_end(Point2(size.width - (v_scroll->is_visible() ? vmin.width : 0), size.height));
@ -4540,9 +4569,9 @@ void CanvasItemEditor::_update_zoom_label() {
// even if their display doesn't have a particularly low DPI.
if (zoom >= 10) {
// Don't show a decimal when the zoom level is higher than 1000 %.
zoom_text = rtos(Math::round((zoom / MAX(1, EDSCALE)) * 100)) + " %";
zoom_text = TS->format_number(rtos(Math::round((zoom / MAX(1, EDSCALE)) * 100))) + " " + TS->percent_sign();
} else {
zoom_text = rtos(Math::stepify((zoom / MAX(1, EDSCALE)) * 100, 0.1)) + " %";
zoom_text = TS->format_number(rtos(Math::stepify((zoom / MAX(1, EDSCALE)) * 100, 0.1))) + " " + TS->percent_sign();
}
zoom_reset->set_text(zoom_text);
@ -5703,6 +5732,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
warning_child_of_container->set_text(TTR("Warning: Children of a container get their position and size determined only by their parent."));
warning_child_of_container->add_theme_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_theme_color("warning_color", "Editor"));
warning_child_of_container->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts"));
warning_child_of_container->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("main_size", "EditorFonts"));
add_control_to_info_overlay(warning_child_of_container);
h_scroll = memnew(HScrollBar);
@ -5727,10 +5757,8 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
zoom_reset = memnew(Button);
zoom_reset->set_flat(true);
zoom_hb->add_child(zoom_reset);
Ref<DynamicFont> font = zoom_reset->get_theme_font("font")->duplicate(false);
font->set_outline_size(1);
font->set_outline_color(Color(0, 0, 0));
zoom_reset->add_theme_font_override("font", font);
zoom_reset->add_theme_constant_override("outline_size", 1);
zoom_reset->add_theme_color_override("font_outline_modulate", Color(0, 0, 0));
zoom_reset->add_theme_color_override("font_color", Color(1, 1, 1));
zoom_reset->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_zoom_reset));
zoom_reset->set_shortcut(ED_SHORTCUT("canvas_item_editor/zoom_reset", TTR("Zoom Reset"), KEY_MASK_CMD | KEY_0));

View File

@ -518,7 +518,9 @@ void CurveEditor::set_hover_point_index(int index) {
void CurveEditor::update_view_transform() {
Ref<Font> font = get_theme_font("font", "Label");
const real_t margin = font->get_height() + 2 * EDSCALE;
int font_size = get_theme_font_size("font_size", "Label");
const real_t margin = font->get_height(font_size) + 2 * EDSCALE;
float min_y = 0;
float max_y = 1;
@ -662,18 +664,19 @@ void CurveEditor::_draw() {
draw_set_transform_matrix(Transform2D());
Ref<Font> font = get_theme_font("font", "Label");
float font_height = font->get_height();
int font_size = get_theme_font_size("font_size", "Label");
float font_height = font->get_height(font_size);
Color text_color = get_theme_color("font_color", "Editor");
{
// X axis
float y = curve.get_min_value();
Vector2 off(0, font_height - 1);
draw_string(font, get_view_pos(Vector2(0, y)) + off, "0.0", text_color);
draw_string(font, get_view_pos(Vector2(0.25, y)) + off, "0.25", text_color);
draw_string(font, get_view_pos(Vector2(0.5, y)) + off, "0.5", text_color);
draw_string(font, get_view_pos(Vector2(0.75, y)) + off, "0.75", text_color);
draw_string(font, get_view_pos(Vector2(1, y)) + off, "1.0", text_color);
draw_string(font, get_view_pos(Vector2(0, y)) + off, "0.0", HALIGN_LEFT, -1, font_size, text_color);
draw_string(font, get_view_pos(Vector2(0.25, y)) + off, "0.25", HALIGN_LEFT, -1, font_size, text_color);
draw_string(font, get_view_pos(Vector2(0.5, y)) + off, "0.5", HALIGN_LEFT, -1, font_size, text_color);
draw_string(font, get_view_pos(Vector2(0.75, y)) + off, "0.75", HALIGN_LEFT, -1, font_size, text_color);
draw_string(font, get_view_pos(Vector2(1, y)) + off, "1.0", HALIGN_LEFT, -1, font_size, text_color);
}
{
@ -682,9 +685,9 @@ void CurveEditor::_draw() {
float m1 = 0.5 * (curve.get_min_value() + curve.get_max_value());
float m2 = curve.get_max_value();
Vector2 off(1, -1);
draw_string(font, get_view_pos(Vector2(0, m0)) + off, String::num(m0, 2), text_color);
draw_string(font, get_view_pos(Vector2(0, m1)) + off, String::num(m1, 2), text_color);
draw_string(font, get_view_pos(Vector2(0, m2)) + off, String::num(m2, 3), text_color);
draw_string(font, get_view_pos(Vector2(0, m0)) + off, String::num(m0, 2), HALIGN_LEFT, -1, font_size, text_color);
draw_string(font, get_view_pos(Vector2(0, m1)) + off, String::num(m1, 2), HALIGN_LEFT, -1, font_size, text_color);
draw_string(font, get_view_pos(Vector2(0, m2)) + off, String::num(m2, 3), HALIGN_LEFT, -1, font_size, text_color);
}
// Draw tangents for current point
@ -744,10 +747,10 @@ void CurveEditor::_draw() {
if (_selected_point > 0 && _selected_point + 1 < curve.get_point_count()) {
text_color.a *= 0.4;
draw_string(font, Vector2(50 * EDSCALE, font_height), TTR("Hold Shift to edit tangents individually"), text_color);
draw_string(font, Vector2(50 * EDSCALE, font_height), TTR("Hold Shift to edit tangents individually"), HALIGN_LEFT, -1, font_size, text_color);
} else if (curve.get_point_count() == 0) {
text_color.a *= 0.4;
draw_string(font, Vector2(50 * EDSCALE, font_height), TTR("Right click to add point"), text_color);
draw_string(font, Vector2(50 * EDSCALE, font_height), TTR("Right click to add point"), HALIGN_LEFT, -1, font_size, text_color);
}
}

View File

@ -37,7 +37,7 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#include "scene/resources/bit_map.h"
#include "scene/resources/dynamic_font.h"
#include "scene/resources/font.h"
#include "scene/resources/material.h"
#include "scene/resources/mesh.h"
#include "servers/audio/audio_stream.h"
@ -798,25 +798,79 @@ void EditorFontPreviewPlugin::_bind_methods() {
}
bool EditorFontPreviewPlugin::handles(const String &p_type) const {
return ClassDB::is_parent_class(p_type, "DynamicFontData") || ClassDB::is_parent_class(p_type, "DynamicFont");
return ClassDB::is_parent_class(p_type, "FontData") || ClassDB::is_parent_class(p_type, "Font");
}
struct FSample {
String script;
String sample;
};
static FSample _samples[] = {
{ "hani", U"漢語" },
{ "armn", U"Աբ" },
{ "copt", U"Αα" },
{ "cyrl", U"Аб" },
{ "grek", U"Αα" },
{ "hebr", U"אב" },
{ "arab", U"اب" },
{ "syrc", U"ܐܒ" },
{ "thaa", U"ހށ" },
{ "deva", U"" },
{ "beng", U"" },
{ "guru", U"" },
{ "gujr", U"" },
{ "orya", U"" },
{ "taml", U"" },
{ "telu", U"" },
{ "knda", U"" },
{ "mylm", U"" },
{ "sinh", U"" },
{ "thai", U"กิ" },
{ "laoo", U"ກິ" },
{ "tibt", U"" },
{ "mymr", U"က" },
{ "geor", U"Ⴀა" },
{ "hang", U"한글" },
{ "ethi", U"" },
{ "cher", U"" },
{ "cans", U"" },
{ "ogam", U"" },
{ "runr", U"" },
{ "tglg", U"" },
{ "hano", U"" },
{ "buhd", U"" },
{ "tagb", U"" },
{ "khmr", U"" },
{ "mong", U"" },
{ "limb", U"" },
{ "tale", U"" },
{ "latn", U"Ab" },
{ "zyyy", U"😀" },
{ "", U"" }
};
Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path, const Size2 &p_size) const {
RES res = ResourceLoader::load(p_path);
Ref<DynamicFont> sampled_font;
if (res->is_class("DynamicFont")) {
Ref<Font> sampled_font;
if (res->is_class("Font")) {
sampled_font = res->duplicate();
if (sampled_font->get_outline_color() == Color(1, 1, 1, 1)) {
sampled_font->set_outline_color(Color(0, 0, 0, 1));
}
} else if (res->is_class("DynamicFontData")) {
} else if (res->is_class("FontData")) {
sampled_font.instance();
sampled_font->set_font_data(res);
sampled_font->add_data(res->duplicate());
}
sampled_font->set_size(50);
String sampled_text = "Abg";
Vector2 size = sampled_font->get_string_size(sampled_text);
String sample;
for (int j = 0; j < sampled_font->get_data_count(); j++) {
for (int i = 0; _samples[i].script != String(); i++) {
if (sampled_font->get_data(j)->is_script_supported(_samples[i].script)) {
if (sampled_font->get_data(j)->has_char(_samples[i].sample[0])) {
sample += _samples[i].sample;
}
}
}
}
Vector2 size = sampled_font->get_string_size(sample, 50);
Vector2 pos;
@ -825,7 +879,7 @@ Ref<Texture2D> EditorFontPreviewPlugin::generate_from_path(const String &p_path,
Ref<Font> font = sampled_font;
font->draw(canvas_item, pos, sampled_text);
font->draw_string(canvas_item, pos, sample, HALIGN_LEFT, -1.f, 50, Color(1, 1, 1));
preview_done = false;
RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture

View File

@ -0,0 +1,331 @@
/*************************************************************************/
/* font_editor_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 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) {
if (p_what == NOTIFICATION_DRAW) {
Color text_color = get_theme_color("font_color", "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);
}
}
void FontDataPreview::_bind_methods() {}
Size2 FontDataPreview::get_minimum_size() const {
return Vector2(64, 64) * EDSCALE;
}
struct FSample {
String script;
String sample;
};
static FSample _samples[] = {
{ "hani", U"漢語" },
{ "armn", U"Աբ" },
{ "copt", U"Αα" },
{ "cyrl", U"Аб" },
{ "grek", U"Αα" },
{ "hebr", U"אב" },
{ "arab", U"اب" },
{ "syrc", U"ܐܒ" },
{ "thaa", U"ހށ" },
{ "deva", U"" },
{ "beng", U"" },
{ "guru", U"" },
{ "gujr", U"" },
{ "orya", U"" },
{ "taml", U"" },
{ "telu", U"" },
{ "knda", U"" },
{ "mylm", U"" },
{ "sinh", U"" },
{ "thai", U"กิ" },
{ "laoo", U"ກິ" },
{ "tibt", U"" },
{ "mymr", U"က" },
{ "geor", U"Ⴀა" },
{ "hang", U"한글" },
{ "ethi", U"" },
{ "cher", U"" },
{ "cans", U"" },
{ "ogam", U"" },
{ "runr", U"" },
{ "tglg", U"" },
{ "hano", U"" },
{ "buhd", U"" },
{ "tagb", U"" },
{ "khmr", U"" },
{ "mong", U"" },
{ "limb", U"" },
{ "tale", U"" },
{ "latn", U"Ab" },
{ "zyyy", U"😀" },
{ "", U"" }
};
void FontDataPreview::set_data(const Ref<FontData> &p_data) {
Ref<Font> f = memnew(Font);
f->add_data(p_data);
line->clear();
String sample;
for (int i = 0; _samples[i].script != String(); i++) {
if (p_data->is_script_supported(_samples[i].script)) {
if (p_data->has_char(_samples[i].sample[0])) {
sample += _samples[i].sample;
}
}
}
line->add_string(sample, f, 72);
update();
}
FontDataPreview::FontDataPreview() {
line.instance();
}
/*************************************************************************/
void FontDataEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_SORT_CHILDREN) {
int split_width = get_name_split_ratio() * get_size().width;
button->set_size(Size2(get_theme_icon("Add", "EditorIcons")->get_width(), get_size().height));
if (is_layout_rtl()) {
if (le != nullptr) {
fit_child_in_rect(le, Rect2(Vector2(split_width, 0), Size2(split_width, get_size().height)));
}
fit_child_in_rect(chk, Rect2(Vector2(split_width - chk->get_size().x, 0), Size2(chk->get_size().x, get_size().height)));
fit_child_in_rect(button, Rect2(Vector2(0, 0), Size2(button->get_size().width, get_size().height)));
} else {
if (le != nullptr) {
fit_child_in_rect(le, Rect2(Vector2(0, 0), Size2(split_width, get_size().height)));
}
fit_child_in_rect(chk, Rect2(Vector2(split_width, 0), Size2(chk->get_size().x, get_size().height)));
fit_child_in_rect(button, Rect2(Vector2(get_size().width - button->get_size().width, 0), Size2(button->get_size().width, get_size().height)));
}
update();
}
if (p_what == NOTIFICATION_DRAW) {
int split_width = get_name_split_ratio() * get_size().width;
Color dark_color = get_theme_color("dark_color_2", "Editor");
if (is_layout_rtl()) {
draw_rect(Rect2(Vector2(0, 0), Size2(split_width, get_size().height)), dark_color);
} else {
draw_rect(Rect2(Vector2(split_width, 0), Size2(split_width, get_size().height)), dark_color);
}
}
if (p_what == NOTIFICATION_THEME_CHANGED) {
if (le != nullptr) {
button->set_icon(get_theme_icon("Add", "EditorIcons"));
} else {
button->set_icon(get_theme_icon("Remove", "EditorIcons"));
}
queue_sort();
}
if (p_what == NOTIFICATION_RESIZED) {
queue_sort();
}
}
void FontDataEditor::update_property() {
if (le == nullptr) {
bool c = get_edited_object()->get(get_edited_property());
chk->set_pressed(c);
chk->set_disabled(is_read_only());
}
}
Size2 FontDataEditor::get_minimum_size() const {
return Size2(0, 60);
}
void FontDataEditor::_bind_methods() {
}
void FontDataEditor::init_lang_add() {
le = memnew(LineEdit);
le->set_placeholder("Language code");
le->set_custom_minimum_size(Size2(get_size().width / 2, 0));
le->set_editable(true);
add_child(le);
button->set_icon(get_theme_icon("Add", "EditorIcons"));
button->connect("pressed", callable_mp(this, &FontDataEditor::add_lang));
}
void FontDataEditor::init_lang_edit() {
button->set_icon(get_theme_icon("Remove", "EditorIcons"));
button->connect("pressed", callable_mp(this, &FontDataEditor::remove_lang));
chk->connect("toggled", callable_mp(this, &FontDataEditor::toggle_lang));
}
void FontDataEditor::init_script_add() {
le = memnew(LineEdit);
le->set_placeholder("Script code");
le->set_custom_minimum_size(Size2(get_size().width / 2, 0));
le->set_editable(true);
add_child(le);
button->set_icon(get_theme_icon("Add", "EditorIcons"));
button->connect("pressed", callable_mp(this, &FontDataEditor::add_script));
}
void FontDataEditor::init_script_edit() {
button->set_icon(get_theme_icon("Remove", "EditorIcons"));
button->connect("pressed", callable_mp(this, &FontDataEditor::remove_script));
chk->connect("toggled", callable_mp(this, &FontDataEditor::toggle_script));
}
void FontDataEditor::add_lang() {
FontData *fd = Object::cast_to<FontData>(get_edited_object());
if (fd != nullptr && !le->get_text().empty()) {
fd->set_language_support_override(le->get_text(), chk->is_pressed());
le->set_text("");
chk->set_pressed(false);
}
}
void FontDataEditor::add_script() {
FontData *fd = Object::cast_to<FontData>(get_edited_object());
if (fd != nullptr && le->get_text().length() == 4) {
fd->set_script_support_override(le->get_text(), chk->is_pressed());
le->set_text("");
chk->set_pressed(false);
}
}
void FontDataEditor::toggle_lang(bool p_pressed) {
FontData *fd = Object::cast_to<FontData>(get_edited_object());
if (fd != nullptr) {
String lang = String(get_edited_property()).replace("language_support_override/", "");
fd->set_language_support_override(lang, p_pressed);
}
}
void FontDataEditor::toggle_script(bool p_pressed) {
FontData *fd = Object::cast_to<FontData>(get_edited_object());
if (fd != nullptr) {
String script = String(get_edited_property()).replace("script_support_override/", "");
fd->set_script_support_override(script, p_pressed);
}
}
void FontDataEditor::remove_lang() {
FontData *fd = Object::cast_to<FontData>(get_edited_object());
if (fd != nullptr) {
String lang = String(get_edited_property()).replace("language_support_override/", "");
fd->remove_language_support_override(lang);
}
}
void FontDataEditor::remove_script() {
FontData *fd = Object::cast_to<FontData>(get_edited_object());
if (fd != nullptr) {
String script = String(get_edited_property()).replace("script_support_override/", "");
fd->remove_script_support_override(script);
}
}
FontDataEditor::FontDataEditor() {
chk = memnew(CheckBox);
chk->set_text(TTR("On"));
chk->set_flat(true);
add_child(chk);
button = memnew(Button);
button->set_flat(true);
add_child(button);
}
/*************************************************************************/
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, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
if (p_path.begins_with("language_support_override/") && p_object->is_class("FontData")) {
String lang = p_path.replace("language_support_override/", "");
FontDataEditor *editor = memnew(FontDataEditor);
if (lang != "_new") {
editor->init_lang_edit();
} else {
editor->init_lang_add();
}
add_property_editor(p_path, editor);
return true;
}
if (p_path.begins_with("script_support_override/") && p_object->is_class("FontData")) {
String script = p_path.replace("script_support_override/", "");
FontDataEditor *editor = memnew(FontDataEditor);
if (script != "_new") {
editor->init_script_edit();
} else {
editor->init_script_add();
}
add_property_editor(p_path, editor);
return true;
}
return false;
}
/*************************************************************************/
FontEditorPlugin::FontEditorPlugin(EditorNode *p_node) {
Ref<EditorInspectorPluginFont> fd_plugin;
fd_plugin.instance();
EditorInspector::add_inspector_plugin(fd_plugin);
}

View File

@ -0,0 +1,111 @@
/*************************************************************************/
/* font_editor_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 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_node.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 FontDataEditor : public EditorProperty {
GDCLASS(FontDataEditor, EditorProperty);
LineEdit *le = nullptr;
CheckBox *chk = nullptr;
Button *button = nullptr;
void toggle_lang(bool p_pressed);
void toggle_script(bool p_pressed);
void add_lang();
void add_script();
void remove_lang();
void remove_script();
protected:
void _notification(int p_what);
static void _bind_methods();
public:
virtual Size2 get_minimum_size() const override;
virtual void update_property() override;
void init_lang_add();
void init_lang_edit();
void init_script_add();
void init_script_edit();
FontDataEditor();
};
/*************************************************************************/
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, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) override;
};
/*************************************************************************/
class FontEditorPlugin : public EditorPlugin {
GDCLASS(FontEditorPlugin, EditorPlugin);
public:
FontEditorPlugin(EditorNode *p_node);
virtual String get_name() const override { return "Font"; }
};
#endif // FONT_EDITOR_PLUGIN_H

View File

@ -138,7 +138,7 @@ void ViewportRotationControl::_draw_axis(const Axis2D &p_axis) {
if (front) {
String axis_name = direction == 0 ? "X" : (direction == 1 ? "Y" : "Z");
draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS, c);
draw_char(get_theme_font("rotation_control", "EditorFonts"), p_axis.screen_point + Vector2i(-4, 5) * EDSCALE, axis_name, "", Color(0.3, 0.3, 0.3));
draw_char(get_theme_font("rotation_control", "EditorFonts"), p_axis.screen_point + Vector2i(-4, 5) * EDSCALE, axis_name, "", get_theme_font_size("rotation_control_size", "EditorFonts"), Color(0.3, 0.3, 0.3));
} else {
draw_circle(p_axis.screen_point, AXIS_CIRCLE_RADIUS * (0.55 + (0.2 * (1.0 + p_axis.z_axis))), c);
}
@ -2593,7 +2593,7 @@ void Node3DEditorViewport::_notification(int p_what) {
}
}
static void draw_indicator_bar(Control &surface, real_t fill, const Ref<Texture2D> icon, const Ref<Font> font, const String &text) {
static void draw_indicator_bar(Control &surface, real_t fill, const Ref<Texture2D> icon, const Ref<Font> font, int font_size, const String &text) {
// Adjust bar size from control height
const Vector2 surface_size = surface.get_size();
const real_t h = surface_size.y / 2.0;
@ -2613,7 +2613,7 @@ static void draw_indicator_bar(Control &surface, real_t fill, const Ref<Texture2
surface.draw_texture(icon, icon_pos);
// Draw text below the bar (for speed/zoom information).
surface.draw_string(font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), text);
surface.draw_string(font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), text, HALIGN_LEFT, -1.f, font_size);
}
void Node3DEditorViewport::_draw() {
@ -2651,10 +2651,11 @@ void Node3DEditorViewport::_draw() {
if (message_time > 0) {
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
Point2 msgpos = Point2(5, get_size().y - 20);
font->draw(ci, msgpos + Point2(1, 1), message, Color(0, 0, 0, 0.8));
font->draw(ci, msgpos + Point2(-1, -1), message, Color(0, 0, 0, 0.8));
font->draw(ci, msgpos, message, Color(1, 1, 1, 1));
font->draw_string(ci, msgpos + Point2(1, 1), message, HALIGN_LEFT, -1, font_size, Color(0, 0, 0, 0.8));
font->draw_string(ci, msgpos + Point2(-1, -1), message, HALIGN_LEFT, -1, font_size, Color(0, 0, 0, 0.8));
font->draw_string(ci, msgpos, message, HALIGN_LEFT, -1, font_size, Color(1, 1, 1, 1));
}
if (_edit.mode == TRANSFORM_ROTATE) {
@ -2717,6 +2718,7 @@ void Node3DEditorViewport::_draw() {
1.0 - logscale_t,
get_theme_icon("ViewportSpeed", "EditorIcons"),
get_theme_font("font", "Label"),
get_theme_font_size("font_size", "Label"),
vformat("%s u/s", String::num(freelook_speed).pad_decimals(precision)));
}
@ -2743,6 +2745,7 @@ void Node3DEditorViewport::_draw() {
logscale_t,
get_theme_icon("ViewportZoom", "EditorIcons"),
get_theme_font("font", "Label"),
get_theme_font_size("font_size", "Label"),
vformat("%s u", String::num(cursor.distance).pad_decimals(precision)));
}
}

View File

@ -0,0 +1,213 @@
/*************************************************************************/
/* ot_features_plugin.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 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 "editor/editor_scale.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) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
Color base = get_theme_color("accent_color", "Editor");
button->set_icon(get_theme_icon("Remove", "EditorIcons"));
button->set_size(get_theme_icon("Remove", "EditorIcons")->get_size());
spin->set_custom_label_color(true, base);
}
}
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) {
get_edited_object()->set("opentype_features/" + TS->tag_to_name(p_option), 1);
}
void OpenTypeFeaturesAdd::update_property() {
menu->clear();
menu_ss->clear();
menu_cv->clear();
menu_cu->clear();
bool have_ss = false;
bool have_cv = false;
bool have_cu = false;
Dictionary features = Object::cast_to<Control>(get_edited_object())->get_theme_font("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::_features_menu() {
Size2 size = get_size();
menu->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
menu->popup();
}
void OpenTypeFeaturesAdd::_notification(int p_what) {
if (p_what == NOTIFICATION_THEME_CHANGED || p_what == NOTIFICATION_ENTER_TREE) {
set_label("");
button->set_icon(get_theme_icon("Add", "EditorIcons"));
button->set_size(get_theme_icon("Add", "EditorIcons")->get_size());
}
}
void OpenTypeFeaturesAdd::_bind_methods() {
}
OpenTypeFeaturesAdd::OpenTypeFeaturesAdd() {
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);
button = memnew(Button);
button->set_flat(true);
button->set_text(RTR("Add feature..."));
button->set_tooltip(RTR("Add feature..."));
add_child(button);
button->connect("pressed", callable_mp(this, &OpenTypeFeaturesAdd::_features_menu));
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);
}
void EditorInspectorPluginOpenTypeFeatures::parse_begin(Object *p_object) {
}
void EditorInspectorPluginOpenTypeFeatures::parse_category(Object *p_object, const String &p_parse_category) {
}
bool EditorInspectorPluginOpenTypeFeatures::parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) {
if (p_path == "opentype_features/_new") {
OpenTypeFeaturesAdd *editor = memnew(OpenTypeFeaturesAdd);
add_property_editor(p_path, 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(EditorNode *p_node) {
Ref<EditorInspectorPluginOpenTypeFeatures> ftr_plugin;
ftr_plugin.instance();
EditorInspector::add_inspector_plugin(ftr_plugin);
}

View File

@ -0,0 +1,105 @@
/*************************************************************************/
/* ot_features_plugin.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 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_node.h"
#include "editor/editor_plugin.h"
#include "editor/editor_properties.h"
/*************************************************************************/
class OpenTypeFeaturesEditor : public EditorProperty {
GDCLASS(OpenTypeFeaturesEditor, EditorProperty);
EditorSpinSlider *spin;
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 EditorProperty {
GDCLASS(OpenTypeFeaturesAdd, EditorProperty);
Button *button = 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:
virtual void update_property() override;
OpenTypeFeaturesAdd();
};
/*************************************************************************/
class EditorInspectorPluginOpenTypeFeatures : public EditorInspectorPlugin {
GDCLASS(EditorInspectorPluginOpenTypeFeatures, EditorInspectorPlugin);
public:
virtual bool can_handle(Object *p_object) override;
virtual void parse_begin(Object *p_object) override;
virtual void parse_category(Object *p_object, const String &p_parse_category) override;
virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage, bool p_wide) override;
};
/*************************************************************************/
class OpenTypeFeaturesEditorPlugin : public EditorPlugin {
GDCLASS(OpenTypeFeaturesEditorPlugin, EditorPlugin);
public:
OpenTypeFeaturesEditorPlugin(EditorNode *p_node);
virtual String get_name() const override { return "OpenTypeFeatures"; }
};
#endif // OT_FEATURES_PLUGIN_H

View File

@ -1485,12 +1485,19 @@ void ScriptEditor::_notification(int p_what) {
EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &ScriptEditor::_filesystem_changed));
[[fallthrough]];
}
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
help_search->set_icon(get_theme_icon("HelpSearch", "EditorIcons"));
site_search->set_icon(get_theme_icon("Instance", "EditorIcons"));
script_forward->set_icon(get_theme_icon("Forward", "EditorIcons"));
script_back->set_icon(get_theme_icon("Back", "EditorIcons"));
if (is_layout_rtl()) {
script_forward->set_icon(get_theme_icon("Back", "EditorIcons"));
script_back->set_icon(get_theme_icon("Forward", "EditorIcons"));
} else {
script_forward->set_icon(get_theme_icon("Forward", "EditorIcons"));
script_back->set_icon(get_theme_icon("Back", "EditorIcons"));
}
members_overview_alphabeta_sort_button->set_icon(get_theme_icon("Sort", "EditorIcons"));

View File

@ -1697,6 +1697,8 @@ void ScriptTextEditor::_enable_code_editor() {
editor_box->add_child(warnings_panel);
warnings_panel->add_theme_font_override(
"normal_font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts"));
warnings_panel->add_theme_font_size_override(
"normal_font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("main_size", "EditorFonts"));
warnings_panel->connect("meta_clicked", callable_mp(this, &ScriptTextEditor::_warning_clicked));
add_child(context_menu);

View File

@ -114,10 +114,11 @@ void BoneTransformEditor::_notification(int p_what) {
}
case NOTIFICATION_SORT_CHILDREN: {
const Ref<Font> font = get_theme_font("font", "Tree");
int font_size = get_theme_font_size("font_size", "Tree");
Point2 buffer;
buffer.x += get_theme_constant("inspector_margin", "Editor");
buffer.y += font->get_height();
buffer.y += font->get_height(font_size);
buffer.y += get_theme_constant("vseparation", "Tree");
const float vector_height = translation_property->get_size().y;

View File

@ -79,6 +79,7 @@ void TextureEditor::_notification(int p_what) {
draw_texture_rect(texture, Rect2(ofs_x, ofs_y, tex_width, tex_height));
Ref<Font> font = get_theme_font("font", "Label");
int font_size = get_theme_font_size("font_size", "Label");
String format;
if (Object::cast_to<ImageTexture>(*texture)) {
@ -90,16 +91,16 @@ void TextureEditor::_notification(int p_what) {
}
String text = itos(texture->get_width()) + "x" + itos(texture->get_height()) + " " + format;
Size2 rect = font->get_string_size(text);
Size2 rect = font->get_string_size(text, font_size);
Vector2 draw_from = size - rect + Size2(-2, font->get_ascent() - 2);
Vector2 draw_from = size - rect + Size2(-2, font->get_ascent(font_size) - 2);
if (draw_from.x < 0) {
draw_from.x = 0;
}
draw_string(font, draw_from + Vector2(2, 2), text, Color(0, 0, 0, 0.5), size.width);
draw_string(font, draw_from - Vector2(2, 2), text, Color(0, 0, 0, 0.5), size.width);
draw_string(font, draw_from, text, Color(1, 1, 1, 1), size.width);
draw_string(font, draw_from + Vector2(2, 2), text, HALIGN_LEFT, size.width, font_size, Color(0, 0, 0, 0.5));
draw_string(font, draw_from - Vector2(2, 2), text, HALIGN_LEFT, size.width, font_size, Color(0, 0, 0, 0.5));
draw_string(font, draw_from, text, HALIGN_LEFT, size.width, font_size, Color(1, 1, 1, 1));
}
}

View File

@ -78,9 +78,12 @@ void ThemeEditor::_name_menu_about_to_show() {
Theme::get_default()->get_font_list(fromtype, &names);
break;
case 3:
Theme::get_default()->get_color_list(fromtype, &names);
Theme::get_default()->get_font_size_list(fromtype, &names);
break;
case 4:
Theme::get_default()->get_color_list(fromtype, &names);
break;
case 5:
Theme::get_default()->get_constant_list(fromtype, &names);
break;
}
@ -88,6 +91,7 @@ void ThemeEditor::_name_menu_about_to_show() {
theme->get_icon_list(fromtype, &names);
theme->get_stylebox_list(fromtype, &names);
theme->get_font_list(fromtype, &names);
theme->get_font_size_list(fromtype, &names);
theme->get_color_list(fromtype, &names);
theme->get_constant_list(fromtype, &names);
}
@ -120,6 +124,7 @@ struct _TECategory {
Set<RefItem<StyleBox>> stylebox_items;
Set<RefItem<Font>> font_items;
Set<Item<int>> font_size_items;
Set<RefItem<Texture2D>> icon_items;
Set<Item<Color>> color_items;
@ -160,6 +165,15 @@ void ThemeEditor::_save_template_cbk(String fname) {
tc.font_items.insert(it);
}
List<StringName> font_size_list;
Theme::get_default()->get_font_size_list(E->key(), &font_list);
for (List<StringName>::Element *F = font_size_list.front(); F; F = F->next()) {
_TECategory::Item<int> it;
it.name = F->get();
it.item = Theme::get_default()->get_font_size(F->get(), E->key());
tc.font_size_items.insert(it);
}
List<StringName> icon_list;
Theme::get_default()->get_icon_list(E->key(), &icon_list);
for (List<StringName>::Element *F = icon_list.front(); F; F = F->next()) {
@ -284,6 +298,14 @@ void ThemeEditor::_save_template_cbk(String fname) {
file->store_line(E->key() + "." + F->get().name + " = default");
}
if (tc.font_size_items.size()) {
file->store_line("\n; Font Size Items:\n");
}
for (Set<_TECategory::Item<int>>::Element *F = tc.font_size_items.front(); F; F = F->next()) {
file->store_line(E->key() + "." + F->get().name + " = default");
}
if (tc.icon_items.size()) {
file->store_line("\n; Icon Items:\n");
}
@ -327,9 +349,12 @@ void ThemeEditor::_dialog_cbk() {
theme->set_font(name_edit->get_text(), type_edit->get_text(), Ref<Font>());
break;
case 3:
theme->set_color(name_edit->get_text(), type_edit->get_text(), Color());
theme->set_font_size(name_edit->get_text(), type_edit->get_text(), -1);
break;
case 4:
theme->set_color(name_edit->get_text(), type_edit->get_text(), Color());
break;
case 5:
theme->set_constant(name_edit->get_text(), type_edit->get_text(), 0);
break;
}
@ -360,6 +385,13 @@ void ThemeEditor::_dialog_cbk() {
theme->set_font(E->get(), fromtype, Ref<Font>());
}
}
{
names.clear();
Theme::get_default()->get_font_size_list(fromtype, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
theme->set_font_size(E->get(), fromtype, Theme::get_default()->get_font_size(E->get(), fromtype));
}
}
{
names.clear();
Theme::get_default()->get_color_list(fromtype, &names);
@ -387,9 +419,12 @@ void ThemeEditor::_dialog_cbk() {
theme->clear_font(name_edit->get_text(), type_edit->get_text());
break;
case 3:
theme->clear_color(name_edit->get_text(), type_edit->get_text());
theme->clear_font_size(name_edit->get_text(), type_edit->get_text());
break;
case 4:
theme->clear_color(name_edit->get_text(), type_edit->get_text());
break;
case 5:
theme->clear_constant(name_edit->get_text(), type_edit->get_text());
break;
}
@ -420,6 +455,13 @@ void ThemeEditor::_dialog_cbk() {
theme->clear_font(E->get(), fromtype);
}
}
{
names.clear();
Theme::get_default()->get_font_size_list(fromtype, &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
theme->clear_font_size(E->get(), fromtype);
}
}
{
names.clear();
Theme::get_default()->get_color_list(fromtype, &names);
@ -486,6 +528,13 @@ void ThemeEditor::_theme_menu_cbk(int p_option) {
theme->set_font(E->get(), type, Ref<Font>());
}
List<StringName> font_sizes;
base_theme->get_font_size_list(type, &font_sizes);
for (List<StringName>::Element *E = font_sizes.front(); E; E = E->next()) {
theme->set_font_size(E->get(), type, base_theme->get_font_size(E->get(), type));
}
List<StringName> colors;
base_theme->get_color_list(type, &colors);
@ -860,6 +909,7 @@ ThemeEditor::ThemeEditor() {
type_select->add_item(TTR("Icon"));
type_select->add_item(TTR("Style"));
type_select->add_item(TTR("Font"));
type_select->add_item(TTR("Font Size"));
type_select->add_item(TTR("Color"));
type_select->add_item(TTR("Constant"));

View File

@ -2165,6 +2165,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
tile_info->set_modulate(Color(1, 1, 1, 0.8));
tile_info->set_mouse_filter(MOUSE_FILTER_IGNORE);
tile_info->add_theme_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_theme_font("main", "EditorFonts"));
tile_info->add_theme_font_size_override("font_size", EditorNode::get_singleton()->get_gui_base()->get_theme_font_size("main_size", "EditorFonts"));
// The tile info is only displayed after a tile has been hovered.
tile_info->hide();
CanvasItemEditor::get_singleton()->add_control_to_info_overlay(tile_info);

View File

@ -279,6 +279,8 @@ void TileSetEditor::_notification(int p_what) {
case NOTIFICATION_READY: {
add_theme_constant_override("autohide", 1); // Fixes the dragger always showing up.
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
tileset_toolbar_buttons[TOOL_TILESET_ADD_TEXTURE]->set_icon(get_theme_icon("ToolAddNode", "EditorIcons"));
@ -296,8 +298,13 @@ void TileSetEditor::_notification(int p_what) {
tools[BITMASK_CLEAR]->set_icon(get_theme_icon("Clear", "EditorIcons"));
tools[SHAPE_NEW_POLYGON]->set_icon(get_theme_icon("CollisionPolygon2D", "EditorIcons"));
tools[SHAPE_NEW_RECTANGLE]->set_icon(get_theme_icon("CollisionShape2D", "EditorIcons"));
tools[SELECT_PREVIOUS]->set_icon(get_theme_icon("ArrowLeft", "EditorIcons"));
tools[SELECT_NEXT]->set_icon(get_theme_icon("ArrowRight", "EditorIcons"));
if (is_layout_rtl()) {
tools[SELECT_PREVIOUS]->set_icon(get_theme_icon("ArrowLeft", "EditorIcons"));
tools[SELECT_NEXT]->set_icon(get_theme_icon("ArrowRight", "EditorIcons"));
} else {
tools[SELECT_PREVIOUS]->set_icon(get_theme_icon("ArrowRight", "EditorIcons"));
tools[SELECT_NEXT]->set_icon(get_theme_icon("ArrowLeft", "EditorIcons"));
}
tools[SHAPE_DELETE]->set_icon(get_theme_icon("Remove", "EditorIcons"));
tools[SHAPE_KEEP_INSIDE_TILE]->set_icon(get_theme_icon("Snap", "EditorIcons"));
tools[TOOL_GRID_SNAP]->set_icon(get_theme_icon("SnapGrid", "EditorIcons"));
@ -1173,11 +1180,12 @@ void TileSetEditor::_on_workspace_overlay_draw() {
}
String tile_id_name = String::num(t_id, 0) + ": " + tileset->tile_get_name(t_id);
Ref<Font> font = get_theme_font("font", "Label");
region.set_size(font->get_string_size(tile_id_name));
int font_size = get_theme_font_size("font_size", "Label");
region.set_size(font->get_string_size(tile_id_name, font_size));
workspace_overlay->draw_rect(region, c);
region.position.y += region.size.y - 2;
c = Color(0.1, 0.1, 0.1);
workspace_overlay->draw_string(font, region.position, tile_id_name, c);
workspace_overlay->draw_string(font, region.position, tile_id_name, HALIGN_LEFT, -1, font_size, c);
}
delete tiles;
}

View File

@ -713,6 +713,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) {
}
expression_box->add_theme_font_override("font", VisualShaderEditor::get_singleton()->get_theme_font("expression", "EditorFonts"));
expression_box->add_theme_font_size_override("font_size", VisualShaderEditor::get_singleton()->get_theme_font_size("expression_size", "EditorFonts"));
expression_box->add_theme_color_override("font_color", text_color);
expression_syntax_highlighter->set_number_color(number_color);
expression_syntax_highlighter->set_symbol_color(symbol_color);
@ -2237,6 +2238,7 @@ void VisualShaderEditor::_notification(int p_what) {
}
preview_text->add_theme_font_override("font", get_theme_font("expression", "EditorFonts"));
preview_text->add_theme_font_size_override("font_size", get_theme_font_size("expression_size", "EditorFonts"));
preview_text->add_theme_color_override("font_color", text_color);
syntax_highlighter->set_number_color(number_color);
syntax_highlighter->set_symbol_color(symbol_color);
@ -2247,6 +2249,7 @@ void VisualShaderEditor::_notification(int p_what) {
syntax_highlighter->add_color_region("//", "", comment_color, true);
error_text->add_theme_font_override("font", get_theme_font("status_source", "EditorFonts"));
error_text->add_theme_font_size_override("font_size", get_theme_font_size("status_source_size", "EditorFonts"));
error_text->add_theme_color_override("font_color", get_theme_color("error_color", "Editor"));
}

View File

@ -804,6 +804,7 @@ public:
project_path = memnew(LineEdit);
project_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
project_path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
pphb->add_child(project_path);
install_path_container = memnew(VBoxContainer);
@ -818,6 +819,7 @@ public:
install_path = memnew(LineEdit);
install_path->set_h_size_flags(Control::SIZE_EXPAND_FILL);
install_path->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
iphb->add_child(install_path);
// status icon
@ -956,7 +958,7 @@ public:
} break;
case NOTIFICATION_DRAW: {
if (hover) {
draw_style_box(get_theme_stylebox("hover", "Tree"), Rect2(Point2(), get_size() - Size2(10, 0) * EDSCALE));
draw_style_box(get_theme_stylebox("hover", "Tree"), Rect2(Point2(), get_size()));
}
} break;
}
@ -1367,6 +1369,7 @@ void ProjectList::create_project_item_control(int p_index) {
vb->add_child(ec);
Label *title = memnew(Label(!item.missing ? item.project_name : TTR("Missing Project")));
title->add_theme_font_override("font", get_theme_font("title", "EditorFonts"));
title->add_theme_font_size_override("font_size", get_theme_font_size("title_size", "EditorFonts"));
title->add_theme_color_override("font_color", font_color);
title->set_clip_text(true);
vb->add_child(title);
@ -1393,6 +1396,7 @@ void ProjectList::create_project_item_control(int p_index) {
}
Label *fpath = memnew(Label(item.path));
fpath->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
path_hb->add_child(fpath);
fpath->set_h_size_flags(Control::SIZE_EXPAND_FILL);
fpath->set_modulate(Color(1, 1, 1, 0.5));
@ -1723,12 +1727,16 @@ void ProjectList::erase_selected_projects() {
void ProjectList::_panel_draw(Node *p_hb) {
Control *hb = Object::cast_to<Control>(p_hb);
hb->draw_line(Point2(0, hb->get_size().y + 1), Point2(hb->get_size().x - 10, hb->get_size().y + 1), get_theme_color("guide_color", "Tree"));
if (is_layout_rtl() && get_v_scrollbar()->is_visible_in_tree()) {
hb->draw_line(Point2(get_v_scrollbar()->get_minimum_size().x, hb->get_size().y + 1), Point2(hb->get_size().x, hb->get_size().y + 1), get_theme_color("guide_color", "Tree"));
} else {
hb->draw_line(Point2(0, hb->get_size().y + 1), Point2(hb->get_size().x, hb->get_size().y + 1), get_theme_color("guide_color", "Tree"));
}
String key = _projects[p_hb->get_index()].project_key;
if (_selected_project_keys.has(key)) {
hb->draw_style_box(get_theme_stylebox("selected", "Tree"), Rect2(Point2(), hb->get_size() - Size2(10, 0) * EDSCALE));
hb->draw_style_box(get_theme_stylebox("selected", "Tree"), Rect2(Point2(), hb->get_size()));
}
}
@ -1814,6 +1822,11 @@ void ProjectList::_bind_methods() {
void ProjectManager::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
settings_hb->set_anchors_and_margins_preset(Control::PRESET_TOP_RIGHT);
update();
} break;
case NOTIFICATION_ENTER_TREE: {
search_box->set_right_icon(get_theme_icon("Search", "EditorIcons"));
search_box->set_clear_button_enabled(true);
@ -2417,10 +2430,13 @@ ProjectManager::ProjectManager() {
DisplayServer::get_singleton()->window_set_size(DisplayServer::get_singleton()->window_get_size() * MAX(1, EDSCALE));
}
String cp;
cp += 0xA9;
// TRANSLATORS: This refers to the application where users manage their Godot projects.
DisplayServer::get_singleton()->window_set_title(VERSION_NAME + String(" - ") + TTR("Project Manager") + " - " + cp + " 2007-2020 Juan Linietsky, Ariel Manzur & Godot Contributors");
if (TS->is_locale_right_to_left(TranslationServer::get_singleton()->get_tool_locale())) {
// For RTL languages, embed translated part of the title (using control characters) to ensure correct order.
DisplayServer::get_singleton()->window_set_title(VERSION_NAME + String(" - ") + String::chr(0x202B) + TTR("Project Manager") + String::chr(0x202C) + String::chr(0x200E) + " - " + String::chr(0xA9) + " 2007-2020 Juan Linietsky, Ariel Manzur & Godot Contributors");
} else {
DisplayServer::get_singleton()->window_set_title(VERSION_NAME + String(" - ") + TTR("Project Manager") + " - " + String::chr(0xA9) + " 2007-2020 Juan Linietsky, Ariel Manzur & Godot Contributors");
}
FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files"));
@ -2552,9 +2568,10 @@ ProjectManager::ProjectManager() {
{
// Version info and language options
HBoxContainer *settings_hb = memnew(HBoxContainer);
settings_hb = memnew(HBoxContainer);
settings_hb->set_alignment(BoxContainer::ALIGN_END);
settings_hb->set_h_grow_direction(Control::GROW_DIRECTION_BEGIN);
settings_hb->set_anchors_and_margins_preset(Control::PRESET_TOP_RIGHT);
Label *version_label = memnew(Label);
String hash = String(VERSION_HASH);
@ -2598,7 +2615,6 @@ ProjectManager::ProjectManager() {
settings_hb->add_child(language_btn);
center_box->add_child(settings_hb);
settings_hb->set_anchors_and_margins_preset(Control::PRESET_TOP_RIGHT);
}
if (StreamPeerSSL::is_available()) {

View File

@ -74,6 +74,8 @@ class ProjectManager : public Control {
ConfirmationDialog *ask_update_settings;
ConfirmationDialog *open_templates;
HBoxContainer *settings_hb;
AcceptDialog *run_error_diag;
AcceptDialog *dialog_error;
ProjectDialog *npdialog;

View File

@ -501,7 +501,7 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
List<String> names;
names.push_back("value:");
config_value_editors(1, 1, 50, names);
value_editor[0]->set_text(String::num(v));
value_editor[0]->set_text(TS->format_number(String::num(v)));
}
} break;
@ -1389,6 +1389,7 @@ void CustomPropertyEditor::_draw_easing() {
bool flip = hint_text == "attenuation";
Ref<Font> f = easing_draw->get_theme_font("font", "Label");
int font_size = easing_draw->get_theme_font_size("font_size", "Label");
Color color = easing_draw->get_theme_color("font_color", "Label");
for (int i = 1; i <= points; i++) {
@ -1406,7 +1407,7 @@ void CustomPropertyEditor::_draw_easing() {
prev = h;
}
f->draw(ci, Point2(10, 10 + f->get_ascent()), String::num(exp, 2), color);
f->draw_string(ci, Point2(10, 10 + f->get_ascent(font_size)), String::num(exp, 2), HALIGN_LEFT, -1, font_size, color);
}
void CustomPropertyEditor::_text_edit_changed() {
@ -1432,7 +1433,7 @@ void CustomPropertyEditor::_modified(String p_string) {
updating = true;
switch (type) {
case Variant::INT: {
String text = value_editor[0]->get_text();
String text = TS->parse_number(value_editor[0]->get_text());
Ref<Expression> expr;
expr.instance();
Error err = expr->parse(text);
@ -1447,7 +1448,7 @@ void CustomPropertyEditor::_modified(String p_string) {
} break;
case Variant::FLOAT: {
if (hint != PROPERTY_HINT_EXP_EASING) {
String text = value_editor[0]->get_text();
String text = TS->parse_number(value_editor[0]->get_text());
v = _parse_real_expression(text);
emit_signal("variant_changed");
}

View File

@ -1990,6 +1990,9 @@ void SceneTreeDock::_do_create(Node *p_parent) {
if (ms.height < 4) {
ms.height = 40;
}
if (ct->is_layout_rtl()) {
ct->set_position(ct->get_position() - Vector2(ms.x, 0));
}
ct->set_size(ms);
}
}

View File

@ -483,5 +483,8 @@ ShaderGlobalsEditor::ShaderGlobalsEditor() {
}
ShaderGlobalsEditor::~ShaderGlobalsEditor() {
if (is_visible_in_tree()) {
inspector->edit(nullptr);
}
memdelete(interface);
}

View File

@ -124,6 +124,7 @@ static bool _start_success = false;
// Drivers
String text_driver = "";
static int text_driver_idx = -1;
static int display_driver_idx = -1;
static int audio_driver_idx = -1;
@ -310,14 +311,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --rendering-driver <driver> Rendering driver (depends on display driver).\n");
OS::get_singleton()->print(" --text-driver <driver> Text driver (Fonts, BiDi, shaping) [");
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
if (i > 0) {
OS::get_singleton()->print(", ");
}
OS::get_singleton()->print("'%s'", TextServerManager::get_interface_name(i).utf8().get_data());
}
OS::get_singleton()->print("].\n");
OS::get_singleton()->print(" --text-driver <driver> Text driver (Fonts, BiDi, shaping)\n");
OS::get_singleton()->print("\n");
@ -558,7 +552,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
I = args.front();
String text_driver = "";
String display_driver = "";
String audio_driver = "";
String tablet_driver = "";
@ -667,32 +660,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
} else if (I->get() == "--text-driver") {
if (I->next()) {
text_driver = I->next()->get();
bool found = false;
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
if (text_driver == TextServerManager::get_interface_name(i)) {
found = true;
}
}
if (!found) {
OS::get_singleton()->print("Unknown text driver '%s', aborting.\nValid options are ",
text_driver.utf8().get_data());
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
if (i == TextServerManager::get_interface_count() - 1) {
OS::get_singleton()->print(" and ");
} else if (i != 0) {
OS::get_singleton()->print(", ");
}
OS::get_singleton()->print("'%s'", TextServerManager::get_interface_name(i).utf8().get_data());
}
OS::get_singleton()->print(".\n");
goto error;
}
N = I->next()->next();
} else {
OS::get_singleton()->print("Missing text driver argument, aborting.\n");
@ -1208,11 +1175,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->set_cmdline(execpath, main_args);
GLOBAL_DEF("display/window/text_name", "");
if (text_driver == "") {
text_driver = GLOBAL_GET("display/window/text_name");
}
GLOBAL_DEF("rendering/quality/driver/driver_name", "Vulkan");
ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/driver/driver_name",
PropertyInfo(Variant::STRING,
@ -1282,6 +1244,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
}
GLOBAL_DEF("display/window/force_right_to_left_layout_direction", false);
if (!force_lowdpi) {
OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false);
}
@ -1343,35 +1307,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->_render_thread_mode = OS::RenderThreadMode(rtm);
}
/* Determine text driver */
if (text_driver != "") {
/* Load user selected text server. */
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
if (text_driver == TextServerManager::get_interface_name(i)) {
text_driver_idx = i;
break;
}
}
}
if (text_driver_idx < 0) {
/* If not selected, use one with the most features available. */
int max_features = 0;
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
uint32_t ftrs = TextServerManager::get_interface_features(i);
int features = 0;
while (ftrs) {
features += ftrs & 1;
ftrs >>= 1;
}
if (features >= max_features) {
max_features = features;
text_driver_idx = i;
}
}
}
/* Determine audio and video drivers */
for (int i = 0; i < DisplayServer::get_create_function_count(); i++) {
@ -1533,6 +1468,41 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
Thread::_main_thread_id = p_main_tid_override;
}
/* Determine text driver */
GLOBAL_DEF("display/window/text_name", "");
if (text_driver == "") {
text_driver = GLOBAL_GET("display/window/text_name");
}
if (text_driver != "") {
/* Load user selected text server. */
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
if (text_driver == TextServerManager::get_interface_name(i)) {
text_driver_idx = i;
break;
}
}
}
if (text_driver_idx < 0) {
/* If not selected, use one with the most features available. */
int max_features = 0;
for (int i = 0; i < TextServerManager::get_interface_count(); i++) {
uint32_t ftrs = TextServerManager::get_interface_features(i);
int features = 0;
while (ftrs) {
features += ftrs & 1;
ftrs >>= 1;
}
if (features >= max_features) {
max_features = features;
text_driver_idx = i;
}
}
}
printf("Using %s text server...\n", TextServerManager::get_interface_name(text_driver_idx).utf8().get_data());
/* Initialize Text Server */
{

View File

@ -228,6 +228,18 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
}
}
} break;
case CompletionKind::THEME_FONT_SIZES: {
Ref<Script> script = ResourceLoader::load(p_script_file.simplify_path());
Node *base = _try_find_owner_node_in_tree(script);
if (base && Object::cast_to<Control>(base)) {
List<StringName> sn;
Theme::get_default()->get_font_size_list(base->get_class(), &sn);
for (List<StringName>::Element *E = sn.front(); E; E = E->next()) {
suggestions.push_back(quoted(E->get()));
}
}
} break;
case CompletionKind::THEME_STYLES: {
Ref<Script> script = ResourceLoader::load(p_script_file.simplify_path());
Node *base = _try_find_owner_node_in_tree(script);

View File

@ -46,6 +46,7 @@ enum class CompletionKind {
THEME_COLORS,
THEME_CONSTANTS,
THEME_FONTS,
THEME_FONT_SIZES,
THEME_STYLES
};

View File

@ -719,6 +719,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
line_edit->set_text(node->get_text());
line_edit->set_expand_to_text_length(true);
line_edit->add_theme_font_override("font", get_theme_font("source", "EditorFonts"));
line_edit->add_theme_font_size_override("font_size", get_theme_font_size("source_size", "EditorFonts"));
gnode->add_child(line_edit);
line_edit->connect("text_changed", callable_mp(this, &VisualScriptEditor::_expression_text_changed), varray(E->get()));
} else {

View File

@ -498,9 +498,28 @@ void DisplayServerAndroid::_set_key_modifier_state(Ref<InputEventWithModifiers>
}
void DisplayServerAndroid::process_key_event(int p_keycode, int p_scancode, int p_unicode_char, bool p_pressed) {
static char32_t prev_wc = 0;
char32_t unicode = p_unicode_char;
if ((p_unicode_char & 0xfffffc00) == 0xd800) {
if (prev_wc != 0) {
ERR_PRINT("invalid utf16 surrogate input");
}
prev_wc = unicode;
return; // Skip surrogate.
} else if ((unicode & 0xfffffc00) == 0xdc00) {
if (prev_wc == 0) {
ERR_PRINT("invalid utf16 surrogate input");
return; // Skip invalid surrogate.
}
unicode = (prev_wc << 10UL) + unicode - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
prev_wc = 0;
} else {
prev_wc = 0;
}
Ref<InputEventKey> ev;
ev.instance();
int val = p_unicode_char;
int val = unicode;
int keycode = android_get_keysym(p_keycode);
int phy_keycode = android_get_keysym(p_scancode);

View File

@ -701,8 +701,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
characters = (NSString *)aString;
}
NSUInteger i, length = [characters length];
NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet];
NSCharacterSet *wsnlChars = [NSCharacterSet whitespaceAndNewlineCharacterSet];
if ([characters rangeOfCharacterFromSet:ctrlChars].length && [characters rangeOfCharacterFromSet:wsnlChars].length == 0) {
@ -712,8 +710,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
return;
}
for (i = 0; i < length; i++) {
const unichar codepoint = [characters characterAtIndex:i];
Char16String text;
text.resize([characters length] + 1);
[characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])];
String u32text;
u32text.parse_utf16(text.ptr(), text.length());
for (int i = 0; i < u32text.length(); i++) {
const char32_t codepoint = u32text[i];
if ((codepoint & 0xFF00) == 0xF700) {
continue;
}
@ -1315,7 +1320,16 @@ static int remapKey(unsigned int key, unsigned int state) {
if (!wd.im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode], [event modifierFlags]))) {
// Fallback unicode character handler used if IME is not active
for (NSUInteger i = 0; i < length; i++) {
Char16String text;
text.resize([characters length] + 1);
[characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])];
String u32text;
u32text.parse_utf16(text.ptr(), text.length());
for (int i = 0; i < u32text.length(); i++) {
const char32_t codepoint = u32text[i];
DisplayServerOSX::KeyEvent ke;
ke.window_id = window_id;
@ -1325,7 +1339,7 @@ static int remapKey(unsigned int key, unsigned int state) {
ke.keycode = remapKey([event keyCode], [event modifierFlags]);
ke.physical_keycode = translateKey([event keyCode]);
ke.raw = true;
ke.unicode = [characters characterAtIndex:i];
ke.unicode = codepoint;
_push_to_key_event_buffer(ke);
}
@ -1417,7 +1431,15 @@ static int remapKey(unsigned int key, unsigned int state) {
// Fallback unicode character handler used if IME is not active
if (!wd.im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode], [event modifierFlags]))) {
for (NSUInteger i = 0; i < length; i++) {
Char16String text;
text.resize([characters length] + 1);
[characters getCharacters:(unichar *)text.ptrw() range:NSMakeRange(0, [characters length])];
String u32text;
u32text.parse_utf16(text.ptr(), text.length());
for (int i = 0; i < u32text.length(); i++) {
const char32_t codepoint = u32text[i];
DisplayServerOSX::KeyEvent ke;
ke.window_id = window_id;
@ -1427,7 +1449,7 @@ static int remapKey(unsigned int key, unsigned int state) {
ke.keycode = remapKey([event keyCode], [event modifierFlags]);
ke.physical_keycode = translateKey([event keyCode]);
ke.raw = true;
ke.unicode = [characters characterAtIndex:i];
ke.unicode = codepoint;
_push_to_key_event_buffer(ke);
}

View File

@ -2792,6 +2792,24 @@ void DisplayServerWindows::_process_key_events() {
case WM_CHAR: {
// extended keys should only be processed as WM_KEYDOWN message.
if (!KeyMappingWindows::is_extended_key(ke.wParam) && ((i == 0 && ke.uMsg == WM_CHAR) || (i > 0 && key_event_buffer[i - 1].uMsg == WM_CHAR))) {
static char32_t prev_wc = 0;
char32_t unicode = ke.wParam;
if ((unicode & 0xfffffc00) == 0xd800) {
if (prev_wc != 0) {
ERR_PRINT("invalid utf16 surrogate input");
}
prev_wc = unicode;
break; // Skip surrogate.
} else if ((unicode & 0xfffffc00) == 0xdc00) {
if (prev_wc == 0) {
ERR_PRINT("invalid utf16 surrogate input");
break; // Skip invalid surrogate.
}
unicode = (prev_wc << 10UL) + unicode - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
prev_wc = 0;
} else {
prev_wc = 0;
}
Ref<InputEventKey> k;
k.instance();
@ -2803,7 +2821,7 @@ void DisplayServerWindows::_process_key_events() {
k->set_pressed(true);
k->set_keycode(KeyMappingWindows::get_keysym(ke.wParam));
k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)));
k->set_unicode(ke.wParam);
k->set_unicode(unicode);
if (k->get_unicode() && gr_mem) {
k->set_alt(false);
k->set_control(false);
@ -2840,7 +2858,25 @@ void DisplayServerWindows::_process_key_events() {
k->set_physical_keycode(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)));
if (i + 1 < key_event_pos && key_event_buffer[i + 1].uMsg == WM_CHAR) {
k->set_unicode(key_event_buffer[i + 1].wParam);
char32_t unicode = key_event_buffer[i + 1].wParam;
static char32_t prev_wck = 0;
if ((unicode & 0xfffffc00) == 0xd800) {
if (prev_wck != 0) {
ERR_PRINT("invalid utf16 surrogate input");
}
prev_wck = unicode;
break; // Skip surrogate.
} else if ((unicode & 0xfffffc00) == 0xdc00) {
if (prev_wck == 0) {
ERR_PRINT("invalid utf16 surrogate input");
break; // Skip invalid surrogate.
}
unicode = (prev_wck << 10UL) + unicode - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
prev_wck = 0;
} else {
prev_wck = 0;
}
k->set_unicode(unicode);
}
if (k->get_unicode() && gr_mem) {
k->set_alt(false);

View File

@ -73,6 +73,7 @@ void AspectRatioContainer::set_alignment_vertical(AlignMode p_alignment_vertical
void AspectRatioContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
bool rtl = is_layout_rtl();
Size2 size = get_size();
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@ -130,7 +131,11 @@ void AspectRatioContainer::_notification(int p_what) {
}
Vector2 offset = (size - child_size) * Vector2(align_x, align_y);
fit_child_in_rect(c, Rect2(offset, child_size));
if (rtl) {
fit_child_in_rect(c, Rect2(Vector2(size.x - offset.x - child_size.x, offset.y), child_size));
} else {
fit_child_in_rect(c, Rect2(offset, child_size));
}
}
} break;
}

View File

@ -44,6 +44,7 @@ void BoxContainer::_resort() {
Size2i new_size = get_size();
int sep = get_theme_constant("separation"); //,vertical?"VBoxContainer":"HBoxContainer");
bool rtl = is_layout_rtl();
bool first = true;
int children_count = 0;
@ -152,22 +153,53 @@ void BoxContainer::_resort() {
int ofs = 0;
if (!has_stretched) {
switch (align) {
case ALIGN_BEGIN:
break;
case ALIGN_CENTER:
ofs = stretch_diff / 2;
break;
case ALIGN_END:
ofs = stretch_diff;
break;
if (!vertical) {
switch (align) {
case ALIGN_BEGIN:
if (rtl) {
ofs = stretch_diff;
}
break;
case ALIGN_CENTER:
ofs = stretch_diff / 2;
break;
case ALIGN_END:
if (!rtl) {
ofs = stretch_diff;
}
break;
}
} else {
switch (align) {
case ALIGN_BEGIN:
break;
case ALIGN_CENTER:
ofs = stretch_diff / 2;
break;
case ALIGN_END:
ofs = stretch_diff;
break;
}
}
}
first = true;
int idx = 0;
for (int i = 0; i < get_child_count(); i++) {
int start;
int end;
int delta;
if (!rtl || vertical) {
start = 0;
end = get_child_count();
delta = +1;
} else {
start = get_child_count() - 1;
end = -1;
delta = -1;
}
for (int i = start; i != end; i += delta) {
Control *c = Object::cast_to<Control>(get_child(i));
if (!c || !c->is_visible_in_tree()) {
continue;
@ -265,6 +297,10 @@ void BoxContainer::_notification(int p_what) {
case NOTIFICATION_THEME_CHANGED: {
minimum_size_changed();
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
queue_sort();
} break;
}
}

View File

@ -34,7 +34,7 @@
#include "servers/rendering_server.h"
Size2 Button::get_minimum_size() const {
Size2 minsize = get_theme_font("font")->get_string_size(xl_text);
Size2 minsize = text_buf->get_size();
if (clip_text) {
minsize.width = 0;
}
@ -65,8 +65,19 @@ void Button::_set_internal_margin(Margin p_margin, float p_value) {
void Button::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
update();
} break;
case NOTIFICATION_TRANSLATION_CHANGED: {
xl_text = tr(text);
_shape();
minimum_size_changed();
update();
} break;
case NOTIFICATION_THEME_CHANGED: {
_shape();
minimum_size_changed();
update();
} break;
@ -77,10 +88,16 @@ void Button::_notification(int p_what) {
Color color_icon(1, 1, 1, 1);
Ref<StyleBox> style = get_theme_stylebox("normal");
bool rtl = is_layout_rtl();
switch (get_draw_mode()) {
case DRAW_NORMAL: {
style = get_theme_stylebox("normal");
if (rtl && has_theme_stylebox("normal_mirrored")) {
style = get_theme_stylebox("normal_mirrored");
} else {
style = get_theme_stylebox("normal");
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
@ -91,7 +108,12 @@ void Button::_notification(int p_what) {
} break;
case DRAW_HOVER_PRESSED: {
if (has_theme_stylebox("hover_pressed") && has_theme_stylebox_override("hover_pressed")) {
style = get_theme_stylebox("hover_pressed");
if (rtl && has_theme_stylebox("hover_pressed_mirrored")) {
style = get_theme_stylebox("hover_pressed_mirrored");
} else {
style = get_theme_stylebox("hover_pressed");
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
@ -109,7 +131,12 @@ void Button::_notification(int p_what) {
[[fallthrough]];
}
case DRAW_PRESSED: {
style = get_theme_stylebox("pressed");
if (rtl && has_theme_stylebox("pressed_mirrored")) {
style = get_theme_stylebox("pressed_mirrored");
} else {
style = get_theme_stylebox("pressed");
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
@ -124,7 +151,12 @@ void Button::_notification(int p_what) {
} break;
case DRAW_HOVER: {
style = get_theme_stylebox("hover");
if (rtl && has_theme_stylebox("hover_mirrored")) {
style = get_theme_stylebox("hover_mirrored");
} else {
style = get_theme_stylebox("hover");
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
@ -135,7 +167,12 @@ void Button::_notification(int p_what) {
} break;
case DRAW_DISABLED: {
style = get_theme_stylebox("disabled");
if (rtl && has_theme_stylebox("disabled_mirrored")) {
style = get_theme_stylebox("disabled_mirrored");
} else {
style = get_theme_stylebox("disabled");
}
if (!flat) {
style->draw(ci, Rect2(Point2(0, 0), size));
}
@ -152,7 +189,6 @@ void Button::_notification(int p_what) {
style2->draw(ci, Rect2(Point2(), size));
}
Ref<Font> font = get_theme_font("font");
Ref<Texture2D> _icon;
if (icon.is_null() && has_theme_icon("icon")) {
_icon = Control::get_theme_icon("icon");
@ -168,15 +204,21 @@ void Button::_notification(int p_what) {
}
float icon_ofs_region = 0;
if (_internal_margin[MARGIN_LEFT] > 0) {
icon_ofs_region = _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation");
if (rtl) {
if (_internal_margin[MARGIN_RIGHT] > 0) {
icon_ofs_region = _internal_margin[MARGIN_RIGHT] + get_theme_constant("hseparation");
}
} else {
if (_internal_margin[MARGIN_LEFT] > 0) {
icon_ofs_region = _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation");
}
}
if (expand_icon) {
Size2 _size = get_size() - style->get_offset() * 2;
_size.width -= get_theme_constant("hseparation") + icon_ofs_region;
if (!clip_text) {
_size.width -= get_theme_font("font")->get_string_size(xl_text).width;
_size.width -= text_buf->get_size().width;
}
float icon_width = _icon->get_width() * _size.height / _icon->get_height();
float icon_height = _size.height;
@ -186,14 +228,26 @@ void Button::_notification(int p_what) {
icon_height = _icon->get_height() * icon_width / _icon->get_width();
}
icon_region = Rect2(style->get_offset() + Point2(icon_ofs_region, (_size.height - icon_height) / 2), Size2(icon_width, icon_height));
if (rtl) {
icon_region = Rect2(Point2(size.width - (icon_ofs_region + icon_width + style->get_margin(MARGIN_RIGHT)), style->get_margin(MARGIN_TOP) + (_size.height - icon_height) / 2), Size2(icon_width, icon_height));
} else {
icon_region = Rect2(style->get_offset() + Point2(icon_ofs_region, (_size.height - icon_height) / 2), Size2(icon_width, icon_height));
}
} else {
icon_region = Rect2(style->get_offset() + Point2(icon_ofs_region, Math::floor((valign - _icon->get_height()) / 2.0)), _icon->get_size());
if (rtl) {
icon_region = Rect2(Point2(size.width - (icon_ofs_region + _icon->get_size().width + style->get_margin(MARGIN_RIGHT)), style->get_margin(MARGIN_TOP) + Math::floor((valign - _icon->get_height()) / 2.0)), _icon->get_size());
} else {
icon_region = Rect2(style->get_offset() + Point2(icon_ofs_region, Math::floor((valign - _icon->get_height()) / 2.0)), _icon->get_size());
}
}
}
Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_theme_constant("hseparation"), 0) : Point2();
int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width;
text_buf->set_width(clip_text ? text_clip : -1);
int text_width = clip_text ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x;
if (_internal_margin[MARGIN_LEFT] > 0) {
text_clip -= _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation");
}
@ -201,14 +255,22 @@ void Button::_notification(int p_what) {
text_clip -= _internal_margin[MARGIN_RIGHT] + get_theme_constant("hseparation");
}
Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - font->get_string_size(xl_text) - Point2(_internal_margin[MARGIN_RIGHT] - _internal_margin[MARGIN_LEFT], 0)) / 2.0;
Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - text_buf->get_size() - Point2(_internal_margin[MARGIN_RIGHT] - _internal_margin[MARGIN_LEFT], 0)) / 2.0;
switch (align) {
case ALIGN_LEFT: {
if (_internal_margin[MARGIN_LEFT] > 0) {
text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x + _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation");
if (rtl) {
if (_internal_margin[MARGIN_RIGHT] > 0) {
text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - text_width - _internal_margin[MARGIN_RIGHT] - get_theme_constant("hseparation");
} else {
text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - text_width;
}
} else {
text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x;
if (_internal_margin[MARGIN_LEFT] > 0) {
text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x + _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation");
} else {
text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x;
}
}
text_ofs.y += style->get_offset().y;
} break;
@ -220,17 +282,34 @@ void Button::_notification(int p_what) {
text_ofs += style->get_offset();
} break;
case ALIGN_RIGHT: {
if (_internal_margin[MARGIN_RIGHT] > 0) {
text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x - _internal_margin[MARGIN_RIGHT] - get_theme_constant("hseparation");
if (rtl) {
if (_internal_margin[MARGIN_LEFT] > 0) {
text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x + _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation");
} else {
text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x;
}
} else {
text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x;
if (_internal_margin[MARGIN_RIGHT] > 0) {
text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - text_width - _internal_margin[MARGIN_RIGHT] - get_theme_constant("hseparation");
} else {
text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - text_width;
}
}
text_ofs.y += style->get_offset().y;
} break;
}
text_ofs.y += font->get_ascent();
font->draw(ci, text_ofs.floor(), xl_text, color, clip_text ? text_clip : -1);
if (rtl) {
text_ofs.x -= icon_ofs.x;
}
Color font_outline_modulate = get_theme_color("font_outline_modulate");
int outline_size = get_theme_constant("outline_size");
if (outline_size > 0 && font_outline_modulate.a > 0) {
text_buf->draw_outline(ci, text_ofs.floor(), outline_size, font_outline_modulate);
}
text_buf->draw(ci, text_ofs.floor(), color);
if (!_icon.is_null() && icon_region.size.width > 0) {
draw_texture_rect_region(_icon, icon_region, Rect2(Point2(), _icon->get_size()), color_icon);
@ -239,29 +318,90 @@ void Button::_notification(int p_what) {
}
}
void Button::set_text(const String &p_text) {
if (text == p_text) {
return;
void Button::_shape() {
Ref<Font> font = get_theme_font("font");
int font_size = get_theme_font_size("font_size");
text_buf->clear();
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else {
text_buf->set_direction((TextServer::Direction)text_direction);
}
text_buf->add_string(xl_text, font, font_size, opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
}
void Button::set_text(const String &p_text) {
if (text != p_text) {
text = p_text;
xl_text = tr(text);
_shape();
update();
_change_notify("text");
minimum_size_changed();
}
text = p_text;
xl_text = tr(p_text);
update();
_change_notify("text");
minimum_size_changed();
}
String Button::get_text() const {
return text;
}
void Button::set_icon(const Ref<Texture2D> &p_icon) {
if (icon == p_icon) {
return;
void Button::set_text_direction(Control::TextDirection p_text_direction) {
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
if (text_direction != p_text_direction) {
text_direction = p_text_direction;
_shape();
update();
}
icon = p_icon;
}
Control::TextDirection Button::get_text_direction() const {
return text_direction;
}
void Button::clear_opentype_features() {
opentype_features.clear();
_shape();
update();
_change_notify("icon");
minimum_size_changed();
}
void Button::set_opentype_feature(const String &p_name, int p_value) {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
opentype_features[tag] = p_value;
_shape();
update();
}
}
int Button::get_opentype_feature(const String &p_name) const {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag)) {
return -1;
}
return opentype_features[tag];
}
void Button::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
_shape();
update();
}
}
String Button::get_language() const {
return language;
}
void Button::set_icon(const Ref<Texture2D> &p_icon) {
if (icon != p_icon) {
icon = p_icon;
update();
_change_notify("icon");
minimum_size_changed();
}
}
Ref<Texture2D> Button::get_icon() const {
@ -269,9 +409,11 @@ Ref<Texture2D> Button::get_icon() const {
}
void Button::set_expand_icon(bool p_expand_icon) {
expand_icon = p_expand_icon;
update();
minimum_size_changed();
if (expand_icon != p_expand_icon) {
expand_icon = p_expand_icon;
update();
minimum_size_changed();
}
}
bool Button::is_expand_icon() const {
@ -279,9 +421,11 @@ bool Button::is_expand_icon() const {
}
void Button::set_flat(bool p_flat) {
flat = p_flat;
update();
_change_notify("flat");
if (flat != p_flat) {
flat = p_flat;
update();
_change_notify("flat");
}
}
bool Button::is_flat() const {
@ -289,9 +433,11 @@ bool Button::is_flat() const {
}
void Button::set_clip_text(bool p_clip_text) {
clip_text = p_clip_text;
update();
minimum_size_changed();
if (clip_text != p_clip_text) {
clip_text = p_clip_text;
update();
minimum_size_changed();
}
}
bool Button::get_clip_text() const {
@ -299,17 +445,76 @@ bool Button::get_clip_text() const {
}
void Button::set_text_align(TextAlign p_align) {
align = p_align;
update();
if (align != p_align) {
align = p_align;
update();
}
}
Button::TextAlign Button::get_text_align() const {
return align;
}
bool Button::_set(const StringName &p_name, const Variant &p_value) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
double value = p_value;
if (value == -1) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
_shape();
update();
}
} else {
if ((double)opentype_features[tag] != value) {
opentype_features[tag] = value;
_shape();
update();
}
}
_change_notify();
return true;
}
return false;
}
bool Button::_get(const StringName &p_name, Variant &r_ret) const {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
if (opentype_features.has(tag)) {
r_ret = opentype_features[tag];
return true;
} else {
r_ret = -1;
return true;
}
}
return false;
}
void Button::_get_property_list(List<PropertyInfo> *p_list) const {
for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
String name = TS->tag_to_name(*ftr);
p_list->push_back(PropertyInfo(Variant::FLOAT, "opentype_features/" + name));
}
p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
}
void Button::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_text", "text"), &Button::set_text);
ClassDB::bind_method(D_METHOD("get_text"), &Button::get_text);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &Button::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &Button::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &Button::set_opentype_feature);
ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &Button::get_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_opentype_features"), &Button::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &Button::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &Button::get_language);
ClassDB::bind_method(D_METHOD("set_button_icon", "texture"), &Button::set_icon);
ClassDB::bind_method(D_METHOD("get_button_icon"), &Button::get_icon);
ClassDB::bind_method(D_METHOD("set_expand_icon"), &Button::set_expand_icon);
@ -325,7 +530,9 @@ void Button::_bind_methods() {
BIND_ENUM_CONSTANT(ALIGN_CENTER);
BIND_ENUM_CONSTANT(ALIGN_RIGHT);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_DEFAULT_INTL), "set_text", "get_text");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_button_icon", "get_button_icon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text");
@ -334,6 +541,9 @@ void Button::_bind_methods() {
}
Button::Button(const String &p_text) {
text_buf.instance();
text_buf->set_flags(TextServer::BREAK_MANDATORY);
flat = false;
clip_text = false;
expand_icon = false;

View File

@ -32,6 +32,7 @@
#define BUTTON_H
#include "scene/gui/base_button.h"
#include "scene/resources/text_paragraph.h"
class Button : public BaseButton {
GDCLASS(Button, BaseButton);
@ -47,23 +48,45 @@ private:
bool flat;
String text;
String xl_text;
Ref<TextParagraph> text_buf;
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
Ref<Texture2D> icon;
bool expand_icon;
bool clip_text;
TextAlign align;
float _internal_margin[4];
void _shape();
protected:
void _set_internal_margin(Margin p_margin, float p_value);
void _notification(int p_what);
static void _bind_methods();
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
public:
virtual Size2 get_minimum_size() const override;
void set_text(const String &p_text);
String get_text() const;
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
void set_opentype_feature(const String &p_name, int p_value);
int get_opentype_feature(const String &p_name) const;
void clear_opentype_features();
void set_language(const String &p_language);
String get_language() const;
void set_icon(const Ref<Texture2D> &p_icon);
Ref<Texture2D> get_icon() const;

View File

@ -68,8 +68,14 @@ Size2 CheckBox::get_minimum_size() const {
}
void CheckBox::_notification(int p_what) {
if (p_what == NOTIFICATION_THEME_CHANGED) {
_set_internal_margin(MARGIN_LEFT, get_icon_size().width);
if ((p_what == NOTIFICATION_THEME_CHANGED) || (p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED || (p_what == NOTIFICATION_TRANSLATION_CHANGED))) {
if (is_layout_rtl()) {
_set_internal_margin(MARGIN_LEFT, 0.f);
_set_internal_margin(MARGIN_RIGHT, get_icon_size().width);
} else {
_set_internal_margin(MARGIN_LEFT, get_icon_size().width);
_set_internal_margin(MARGIN_RIGHT, 0.f);
}
} else if (p_what == NOTIFICATION_DRAW) {
RID ci = get_canvas_item();
@ -78,7 +84,11 @@ void CheckBox::_notification(int p_what) {
Ref<StyleBox> sb = get_theme_stylebox("normal");
Vector2 ofs;
ofs.x = sb->get_margin(MARGIN_LEFT);
if (is_layout_rtl()) {
ofs.x = get_size().x - sb->get_margin(MARGIN_RIGHT) - get_icon_size().width;
} else {
ofs.x = sb->get_margin(MARGIN_LEFT);
}
ofs.y = int((get_size().height - get_icon_size().height) / 2) + get_theme_constant("check_vadjust");
if (is_pressed()) {
@ -96,8 +106,14 @@ bool CheckBox::is_radio() {
CheckBox::CheckBox(const String &p_text) :
Button(p_text) {
set_toggle_mode(true);
set_text_align(ALIGN_LEFT);
_set_internal_margin(MARGIN_LEFT, get_icon_size().width);
if (is_layout_rtl()) {
_set_internal_margin(MARGIN_RIGHT, get_icon_size().width);
} else {
_set_internal_margin(MARGIN_LEFT, get_icon_size().width);
}
}
CheckBox::~CheckBox() {

View File

@ -61,19 +61,40 @@ Size2 CheckButton::get_minimum_size() const {
}
void CheckButton::_notification(int p_what) {
if (p_what == NOTIFICATION_THEME_CHANGED) {
_set_internal_margin(MARGIN_RIGHT, get_icon_size().width);
if ((p_what == NOTIFICATION_THEME_CHANGED) || (p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED) || (p_what == NOTIFICATION_TRANSLATION_CHANGED)) {
if (is_layout_rtl()) {
_set_internal_margin(MARGIN_LEFT, get_icon_size().width);
_set_internal_margin(MARGIN_RIGHT, 0.f);
} else {
_set_internal_margin(MARGIN_LEFT, 0.f);
_set_internal_margin(MARGIN_RIGHT, get_icon_size().width);
}
} else if (p_what == NOTIFICATION_DRAW) {
RID ci = get_canvas_item();
bool rtl = is_layout_rtl();
Ref<Texture2D> on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on");
Ref<Texture2D> off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off");
Ref<Texture2D> on;
if (rtl) {
on = Control::get_theme_icon(is_disabled() ? "on_disabled_mirrored" : "on_mirrored");
} else {
on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on");
}
Ref<Texture2D> off;
if (rtl) {
off = Control::get_theme_icon(is_disabled() ? "off_disabled_mirrored" : "off_mirrored");
} else {
off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off");
}
Ref<StyleBox> sb = get_theme_stylebox("normal");
Vector2 ofs;
Size2 tex_size = get_icon_size();
ofs.x = get_size().width - (tex_size.width + sb->get_margin(MARGIN_RIGHT));
if (rtl) {
ofs.x = sb->get_margin(MARGIN_LEFT);
} else {
ofs.x = get_size().width - (tex_size.width + sb->get_margin(MARGIN_RIGHT));
}
ofs.y = (get_size().height - tex_size.height) / 2 + get_theme_constant("check_vadjust");
if (is_pressed()) {
@ -87,8 +108,11 @@ void CheckButton::_notification(int p_what) {
CheckButton::CheckButton() {
set_toggle_mode(true);
set_text_align(ALIGN_LEFT);
_set_internal_margin(MARGIN_RIGHT, get_icon_size().width);
if (is_layout_rtl()) {
_set_internal_margin(MARGIN_LEFT, get_icon_size().width);
} else {
_set_internal_margin(MARGIN_RIGHT, get_icon_size().width);
}
}
CheckButton::~CheckButton() {

View File

@ -241,7 +241,7 @@ void CodeEdit::_line_number_draw_callback(int p_line, int p_gutter, const Rect2
if (number_color == Color(1, 1, 1)) {
number_color = line_number_color;
}
cache.font->draw(get_canvas_item(), Point2(p_region.position.x, yofs + cache.font->get_ascent()), fc, number_color);
cache.font->draw_string(get_canvas_item(), Point2(p_region.position.x, yofs + cache.font->get_ascent()), fc, HALIGN_LEFT, -1, cache.font_size, number_color);
}
/* Fold Gutter */

View File

@ -121,12 +121,7 @@ void Container::fit_child_in_rect(Control *p_child, const Rect2 &p_rect) {
}
}
for (int i = 0; i < 4; i++) {
p_child->set_anchor(Margin(i), ANCHOR_BEGIN);
}
p_child->set_position(r.position);
p_child->set_size(r.size);
p_child->set_rect(r);
p_child->set_rotation(0);
p_child->set_scale(Vector2(1, 1));
}

View File

@ -36,12 +36,15 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
#include "core/string/translation.h"
#include "scene/gui/label.h"
#include "scene/gui/panel.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/window.h"
#include "scene/scene_string_names.h"
#include "servers/rendering_server.h"
#include "servers/text_server.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_settings.h"
@ -241,6 +244,10 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) {
}
data.font_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
} else if (name.begins_with("custom_font_sizes/")) {
String dname = name.get_slicec('/', 1);
data.font_size_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
} else if (name.begins_with("custom_colors/")) {
String dname = name.get_slicec('/', 1);
data.color_override.erase(dname);
@ -266,6 +273,9 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) {
} else if (name.begins_with("custom_fonts/")) {
String dname = name.get_slicec('/', 1);
add_theme_font_override(dname, p_value);
} else if (name.begins_with("custom_font_sizes/")) {
String dname = name.get_slicec('/', 1);
add_theme_font_size_override(dname, p_value);
} else if (name.begins_with("custom_colors/")) {
String dname = name.get_slicec('/', 1);
add_theme_color_override(dname, p_value);
@ -307,20 +317,19 @@ bool Control::_get(const StringName &p_name, Variant &r_ret) const {
if (sname.begins_with("custom_icons/")) {
String name = sname.get_slicec('/', 1);
r_ret = data.icon_override.has(name) ? Variant(data.icon_override[name]) : Variant();
} else if (sname.begins_with("custom_shaders/")) {
String name = sname.get_slicec('/', 1);
r_ret = data.shader_override.has(name) ? Variant(data.shader_override[name]) : Variant();
} else if (sname.begins_with("custom_styles/")) {
String name = sname.get_slicec('/', 1);
r_ret = data.style_override.has(name) ? Variant(data.style_override[name]) : Variant();
} else if (sname.begins_with("custom_fonts/")) {
String name = sname.get_slicec('/', 1);
r_ret = data.font_override.has(name) ? Variant(data.font_override[name]) : Variant();
} else if (sname.begins_with("custom_font_sizes/")) {
String name = sname.get_slicec('/', 1);
r_ret = data.font_size_override.has(name) ? Variant(data.font_size_override[name]) : Variant();
} else if (sname.begins_with("custom_colors/")) {
String name = sname.get_slicec('/', 1);
r_ret = data.color_override.has(name) ? Variant(data.color_override[name]) : Variant();
@ -393,6 +402,18 @@ void Control::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::OBJECT, "custom_fonts/" + E->get(), PROPERTY_HINT_RESOURCE_TYPE, "Font", hint));
}
}
{
List<StringName> names;
theme->get_font_size_list(get_class_name(), &names);
for (List<StringName>::Element *E = names.front(); E; E = E->next()) {
uint32_t hint = PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_CHECKABLE;
if (data.font_size_override.has(E->get())) {
hint |= PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_CHECKED;
}
p_list->push_back(PropertyInfo(Variant::INT, "custom_font_sizes/" + E->get(), PROPERTY_HINT_NONE, "", hint));
}
}
{
List<StringName> names;
theme->get_color_list(get_class_name(), &names);
@ -423,6 +444,43 @@ Control *Control::get_parent_control() const {
return data.parent;
}
void Control::set_layout_direction(Control::LayoutDirection p_direction) {
ERR_FAIL_INDEX((int)p_direction, 4);
data.layout_dir = p_direction;
propagate_notification(NOTIFICATION_LAYOUT_DIRECTION_CHANGED);
}
Control::LayoutDirection Control::get_layout_direction() const {
return data.layout_dir;
}
bool Control::is_layout_rtl() const {
if (data.layout_dir == LAYOUT_DIRECTION_INHERITED) {
Window *parent_window = Object::cast_to<Window>(get_parent());
Control *parent_control = get_parent_control();
if (parent_control) {
return parent_control->is_layout_rtl();
} else if (parent_window) {
return parent_window->is_layout_rtl();
} else {
if (GLOBAL_GET("display/window/force_right_to_left_layout_direction")) {
return true;
}
String locale = TranslationServer::get_singleton()->get_tool_locale();
return TS->is_locale_right_to_left(locale);
}
} else if (data.layout_dir == LAYOUT_DIRECTION_LOCALE) {
if (GLOBAL_GET("display/window/force_right_to_left_layout_direction")) {
return true;
}
String locale = TranslationServer::get_singleton()->get_tool_locale();
return TS->is_locale_right_to_left(locale);
} else {
return (data.layout_dir == LAYOUT_DIRECTION_RTL);
}
}
void Control::_resize(const Size2 &p_size) {
_size_changed();
}
@ -581,7 +639,6 @@ void Control::_notification(int p_notification) {
case NOTIFICATION_FOCUS_EXIT: {
emit_signal(SceneStringNames::get_singleton()->focus_exited);
update();
} break;
case NOTIFICATION_THEME_CHANGED: {
minimum_size_changed();
@ -601,6 +658,10 @@ void Control::_notification(int p_notification) {
}
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
_size_changed();
} break;
}
}
@ -911,6 +972,19 @@ Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_
return get_fonts(data.theme_owner, data.theme_owner_window, p_name, type);
}
int Control::get_theme_font_size(const StringName &p_name, const StringName &p_node_type) const {
if (p_node_type == StringName() || p_node_type == get_class_name()) {
const int *font_size = data.font_size_override.getptr(p_name);
if (font_size) {
return *font_size;
}
}
StringName type = p_node_type ? p_node_type : get_class_name();
return get_font_sizes(data.theme_owner, data.theme_owner_window, p_name, type);
}
Ref<Font> Control::get_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
Ref<Font> font;
@ -927,6 +1001,22 @@ Ref<Font> Control::get_fonts(Control *p_theme_owner, Window *p_theme_owner_windo
return Theme::get_default()->get_font(p_name, p_node_type);
}
int Control::get_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
int font_size;
if (_find_theme_item(p_theme_owner, p_theme_owner_window, font_size, &Theme::get_font_size, &Theme::has_font_size, p_name, p_node_type)) {
return font_size;
}
if (Theme::get_project_default().is_valid()) {
if (Theme::get_project_default()->has_font_size(p_name, p_node_type)) {
return Theme::get_project_default()->get_font_size(p_name, p_node_type);
}
}
return Theme::get_default()->get_font_size(p_name, p_node_type);
}
Color Control::get_theme_color(const StringName &p_name, const StringName &p_node_type) const {
if (p_node_type == StringName() || p_node_type == get_class_name()) {
const Color *color = data.color_override.getptr(p_name);
@ -1003,6 +1093,11 @@ bool Control::has_theme_font_override(const StringName &p_name) const {
return font != nullptr;
}
bool Control::has_theme_font_size_override(const StringName &p_name) const {
const int *font_size = data.font_size_override.getptr(p_name);
return font_size != nullptr;
}
bool Control::has_theme_color_override(const StringName &p_name) const {
const Color *color = data.color_override.getptr(p_name);
return color != nullptr;
@ -1113,6 +1208,31 @@ bool Control::has_fonts(Control *p_theme_owner, Window *p_theme_owner_window, co
return Theme::get_default()->has_font(p_name, p_node_type);
}
bool Control::has_theme_font_size(const StringName &p_name, const StringName &p_node_type) const {
if (p_node_type == StringName() || p_node_type == get_class_name()) {
if (has_theme_font_size_override(p_name)) {
return true;
}
}
StringName type = p_node_type ? p_node_type : get_class_name();
return has_font_sizes(data.theme_owner, data.theme_owner_window, p_name, type);
}
bool Control::has_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type) {
if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_font_size, p_name, p_node_type)) {
return true;
}
if (Theme::get_project_default().is_valid()) {
if (Theme::get_project_default()->has_font_size(p_name, p_node_type)) {
return true;
}
}
return Theme::get_default()->has_font_size(p_name, p_node_type);
}
bool Control::has_theme_color(const StringName &p_name, const StringName &p_node_type) const {
if (p_node_type == StringName() || p_node_type == get_class_name()) {
if (has_theme_color_override(p_name)) {
@ -1217,6 +1337,10 @@ void Control::_size_changed() {
new_size_cache.width = minimum_size.width;
}
if (is_layout_rtl()) {
new_pos_cache.x = parent_rect.size.x - new_pos_cache.x - new_size_cache.x;
}
if (minimum_size.height > new_size_cache.height) {
if (data.v_grow == GROW_DIRECTION_BEGIN) {
new_pos_cache.y += new_size_cache.height - minimum_size.height;
@ -1426,6 +1550,10 @@ void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz
Rect2 parent_rect = get_parent_anchorable_rect();
float x = parent_rect.size.x;
if (is_layout_rtl()) {
x = parent_rect.size.x - x - new_size.x;
}
//Left
switch (p_preset) {
case PRESET_TOP_LEFT:
@ -1436,21 +1564,21 @@ void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz
case PRESET_LEFT_WIDE:
case PRESET_HCENTER_WIDE:
case PRESET_WIDE:
data.margin[0] = parent_rect.size.x * (0.0 - data.anchor[0]) + p_margin + parent_rect.position.x;
data.margin[0] = x * (0.0 - data.anchor[0]) + p_margin + parent_rect.position.x;
break;
case PRESET_CENTER_TOP:
case PRESET_CENTER_BOTTOM:
case PRESET_CENTER:
case PRESET_VCENTER_WIDE:
data.margin[0] = parent_rect.size.x * (0.5 - data.anchor[0]) - new_size.x / 2 + parent_rect.position.x;
data.margin[0] = x * (0.5 - data.anchor[0]) - new_size.x / 2 + parent_rect.position.x;
break;
case PRESET_TOP_RIGHT:
case PRESET_BOTTOM_RIGHT:
case PRESET_CENTER_RIGHT:
case PRESET_RIGHT_WIDE:
data.margin[0] = parent_rect.size.x * (1.0 - data.anchor[0]) - new_size.x - p_margin + parent_rect.position.x;
data.margin[0] = x * (1.0 - data.anchor[0]) - new_size.x - p_margin + parent_rect.position.x;
break;
}
@ -1488,14 +1616,14 @@ void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz
case PRESET_BOTTOM_LEFT:
case PRESET_CENTER_LEFT:
case PRESET_LEFT_WIDE:
data.margin[2] = parent_rect.size.x * (0.0 - data.anchor[2]) + new_size.x + p_margin + parent_rect.position.x;
data.margin[2] = x * (0.0 - data.anchor[2]) + new_size.x + p_margin + parent_rect.position.x;
break;
case PRESET_CENTER_TOP:
case PRESET_CENTER_BOTTOM:
case PRESET_CENTER:
case PRESET_VCENTER_WIDE:
data.margin[2] = parent_rect.size.x * (0.5 - data.anchor[2]) + new_size.x / 2 + parent_rect.position.x;
data.margin[2] = x * (0.5 - data.anchor[2]) + new_size.x / 2 + parent_rect.position.x;
break;
case PRESET_TOP_RIGHT:
@ -1506,7 +1634,7 @@ void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resiz
case PRESET_BOTTOM_WIDE:
case PRESET_HCENTER_WIDE:
case PRESET_WIDE:
data.margin[2] = parent_rect.size.x * (1.0 - data.anchor[2]) - p_margin + parent_rect.position.x;
data.margin[2] = x * (1.0 - data.anchor[2]) - p_margin + parent_rect.position.x;
break;
}
@ -1629,17 +1757,26 @@ void Control::_compute_anchors(Rect2 p_rect, const float p_margins[4], float (&r
ERR_FAIL_COND(parent_rect_size.x == 0.0);
ERR_FAIL_COND(parent_rect_size.y == 0.0);
r_anchors[0] = (p_rect.position.x - p_margins[0]) / parent_rect_size.x;
float x = p_rect.position.x;
if (is_layout_rtl()) {
x = parent_rect_size.x - x - p_rect.size.x;
}
r_anchors[0] = (x - p_margins[0]) / parent_rect_size.x;
r_anchors[1] = (p_rect.position.y - p_margins[1]) / parent_rect_size.y;
r_anchors[2] = (p_rect.position.x + p_rect.size.x - p_margins[2]) / parent_rect_size.x;
r_anchors[2] = (x + p_rect.size.x - p_margins[2]) / parent_rect_size.x;
r_anchors[3] = (p_rect.position.y + p_rect.size.y - p_margins[3]) / parent_rect_size.y;
}
void Control::_compute_margins(Rect2 p_rect, const float p_anchors[4], float (&r_margins)[4]) {
Size2 parent_rect_size = get_parent_anchorable_rect().size;
r_margins[0] = p_rect.position.x - (p_anchors[0] * parent_rect_size.x);
float x = p_rect.position.x;
if (is_layout_rtl()) {
x = parent_rect_size.x - x - p_rect.size.x;
}
r_margins[0] = x - (p_anchors[0] * parent_rect_size.x);
r_margins[1] = p_rect.position.y - (p_anchors[1] * parent_rect_size.y);
r_margins[2] = p_rect.position.x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x);
r_margins[2] = x + p_rect.size.x - (p_anchors[2] * parent_rect_size.x);
r_margins[3] = p_rect.position.y + p_rect.size.y - (p_anchors[3] * parent_rect_size.y);
}
@ -1660,6 +1797,17 @@ void Control::set_position(const Size2 &p_point, bool p_keep_margins) {
_size_changed();
}
void Control::set_rect(const Rect2 &p_rect) {
for (int i = 0; i < 4; i++) {
data.anchor[i] = ANCHOR_BEGIN;
}
_compute_margins(p_rect, data.anchor, data.margin);
if (is_inside_tree()) {
_size_changed();
}
}
void Control::_set_size(const Size2 &p_size) {
set_size(p_size);
}
@ -1794,6 +1942,11 @@ void Control::add_theme_font_override(const StringName &p_name, const Ref<Font>
notification(NOTIFICATION_THEME_CHANGED);
}
void Control::add_theme_font_size_override(const StringName &p_name, int p_font_size) {
data.font_size_override[p_name] = p_font_size;
notification(NOTIFICATION_THEME_CHANGED);
}
void Control::add_theme_color_override(const StringName &p_name, const Color &p_color) {
data.color_override[p_name] = p_color;
notification(NOTIFICATION_THEME_CHANGED);
@ -2436,6 +2589,95 @@ bool Control::is_text_field() const {
return false;
}
Vector<Vector2i> Control::structured_text_parser(StructuredTextParser p_node_type, const Array &p_args, const String p_text) const {
Vector<Vector2i> ret;
switch (p_node_type) {
case STRUCTURED_TEXT_URI: {
int prev = 0;
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == '.') || (p_text[i] == ':') || (p_text[i] == '&') || (p_text[i] == '=') || (p_text[i] == '@') || (p_text[i] == '?') || (p_text[i] == '#')) {
if (prev != i) {
ret.push_back(Vector2i(prev, i));
}
ret.push_back(Vector2i(i, i + 1));
prev = i + 1;
}
}
if (prev != p_text.length()) {
ret.push_back(Vector2i(prev, p_text.length()));
}
} break;
case STRUCTURED_TEXT_FILE: {
int prev = 0;
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '\\') || (p_text[i] == '/') || (p_text[i] == ':')) {
if (prev != i) {
ret.push_back(Vector2i(prev, i));
}
ret.push_back(Vector2i(i, i + 1));
prev = i + 1;
}
}
if (prev != p_text.length()) {
ret.push_back(Vector2i(prev, p_text.length()));
}
} break;
case STRUCTURED_TEXT_EMAIL: {
bool local = true;
int prev = 0;
for (int i = 0; i < p_text.length(); i++) {
if ((p_text[i] == '@') && local) { // Add full "local" as single context.
local = false;
ret.push_back(Vector2i(prev, i));
ret.push_back(Vector2i(i, i + 1));
prev = i + 1;
} else if (!local & (p_text[i] == '.')) { // Add each dot separated "domain" part as context.
if (prev != i) {
ret.push_back(Vector2i(prev, i));
}
ret.push_back(Vector2i(i, i + 1));
prev = i + 1;
}
}
if (prev != p_text.length()) {
ret.push_back(Vector2i(prev, p_text.length()));
}
} break;
case STRUCTURED_TEXT_LIST: {
if (p_args.size() == 1 && p_args[0].get_type() == Variant::STRING) {
Vector<String> tags = p_text.split(String(p_args[0]));
int prev = 0;
for (int i = 0; i < tags.size(); i++) {
if (prev != i) {
ret.push_back(Vector2i(prev, prev + tags[i].length()));
}
ret.push_back(Vector2i(prev + tags[i].length(), prev + tags[i].length() + 1));
prev = prev + tags[i].length() + 1;
}
}
} break;
case STRUCTURED_TEXT_CUSTOM: {
if (get_script_instance()) {
Variant data = get_script_instance()->call(SceneStringNames::get_singleton()->_structured_text_parser, p_args, p_text);
if (data.get_type() == Variant::ARRAY) {
Array _data = data;
for (int i = 0; i < _data.size(); i++) {
if (_data[i].get_type() == Variant::VECTOR2I) {
ret.push_back(Vector2i(_data[i]));
}
}
}
}
} break;
case STRUCTURED_TEXT_NONE:
case STRUCTURED_TEXT_DEFAULT:
default: {
ret.push_back(Vector2i(0, p_text.length()));
}
}
return ret;
}
void Control::set_rotation(float p_radians) {
data.rotation = p_radians;
update();
@ -2544,6 +2786,8 @@ void Control::get_argument_options(const StringName &p_function, int p_idx, List
Theme::get_default()->get_stylebox_list(get_class(), &sn);
} else if (pf == "add_font_override" || pf == "has_font" || pf == "has_font_override" || pf == "get_font") {
Theme::get_default()->get_font_list(get_class(), &sn);
} else if (pf == "add_font_size_override" || pf == "has_font_size" || pf == "has_font_size_override" || pf == "get_font_size") {
Theme::get_default()->get_font_size_list(get_class(), &sn);
} else if (pf == "add_constant_override" || pf == "has_constant" || pf == "has_constant_override" || pf == "get_constant") {
Theme::get_default()->get_constant_list(get_class(), &sn);
}
@ -2664,27 +2908,31 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_theme_shader_override", "name", "shader"), &Control::add_theme_shader_override);
ClassDB::bind_method(D_METHOD("add_theme_stylebox_override", "name", "stylebox"), &Control::add_theme_style_override);
ClassDB::bind_method(D_METHOD("add_theme_font_override", "name", "font"), &Control::add_theme_font_override);
ClassDB::bind_method(D_METHOD("add_theme_font_size_override", "name", "font_size"), &Control::add_theme_font_size_override);
ClassDB::bind_method(D_METHOD("add_theme_color_override", "name", "color"), &Control::add_theme_color_override);
ClassDB::bind_method(D_METHOD("add_theme_constant_override", "name", "constant"), &Control::add_theme_constant_override);
ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "type"), &Control::get_theme_icon, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "type"), &Control::get_theme_stylebox, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_font", "name", "type"), &Control::get_theme_font, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_color", "name", "type"), &Control::get_theme_color, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "type"), &Control::get_theme_constant, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "node_type"), &Control::get_theme_icon, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "node_type"), &Control::get_theme_stylebox, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_font", "name", "node_type"), &Control::get_theme_font, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_font_size", "name", "node_type"), &Control::get_theme_font_size, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_color", "name", "node_type"), &Control::get_theme_color, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "node_type"), &Control::get_theme_constant, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_icon_override", "name"), &Control::has_theme_icon_override);
ClassDB::bind_method(D_METHOD("has_theme_shader_override", "name"), &Control::has_theme_shader_override);
ClassDB::bind_method(D_METHOD("has_theme_stylebox_override", "name"), &Control::has_theme_stylebox_override);
ClassDB::bind_method(D_METHOD("has_theme_font_override", "name"), &Control::has_theme_font_override);
ClassDB::bind_method(D_METHOD("has_theme_font_size_override", "name"), &Control::has_theme_font_size_override);
ClassDB::bind_method(D_METHOD("has_theme_color_override", "name"), &Control::has_theme_color_override);
ClassDB::bind_method(D_METHOD("has_theme_constant_override", "name"), &Control::has_theme_constant_override);
ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "type"), &Control::has_theme_icon, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "type"), &Control::has_theme_stylebox, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_font", "name", "type"), &Control::has_theme_font, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_color", "name", "type"), &Control::has_theme_color, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "type"), &Control::has_theme_constant, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "node_type"), &Control::has_theme_icon, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "node_type"), &Control::has_theme_stylebox, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_font", "name", "node_type"), &Control::has_theme_font, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_font_size", "name", "node_type"), &Control::has_theme_font_size, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_color", "name", "node_type"), &Control::has_theme_color, DEFVAL(""));
ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "node_type"), &Control::has_theme_constant, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_parent_control"), &Control::get_parent_control);
@ -2728,6 +2976,12 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("minimum_size_changed"), &Control::minimum_size_changed);
ClassDB::bind_method(D_METHOD("set_layout_direction", "direction"), &Control::set_layout_direction);
ClassDB::bind_method(D_METHOD("get_layout_direction"), &Control::get_layout_direction);
ClassDB::bind_method(D_METHOD("is_layout_rtl"), &Control::is_layout_rtl);
BIND_VMETHOD(MethodInfo("_structured_text_parser", PropertyInfo(Variant::ARRAY, "args"), PropertyInfo(Variant::STRING, "text")));
BIND_VMETHOD(MethodInfo("_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_get_minimum_size"));
@ -2758,6 +3012,9 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_horizontal", PROPERTY_HINT_ENUM, "Begin,End,Both"), "set_h_grow_direction", "get_h_grow_direction");
ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Begin,End,Both"), "set_v_grow_direction", "get_v_grow_direction");
ADD_GROUP("Layout Direction", "layout_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-right,Right-to-left"), "set_layout_direction", "get_layout_direction");
ADD_GROUP("Rect", "rect_");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_position", "get_position");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_global_position", PROPERTY_HINT_NONE, "", 0), "_set_global_position", "get_global_position");
@ -2804,6 +3061,7 @@ void Control::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_THEME_CHANGED);
BIND_CONSTANT(NOTIFICATION_SCROLL_BEGIN);
BIND_CONSTANT(NOTIFICATION_SCROLL_END);
BIND_CONSTANT(NOTIFICATION_LAYOUT_DIRECTION_CHANGED);
BIND_ENUM_CONSTANT(CURSOR_ARROW);
BIND_ENUM_CONSTANT(CURSOR_IBEAM);
@ -2862,6 +3120,24 @@ void Control::_bind_methods() {
BIND_ENUM_CONSTANT(ANCHOR_BEGIN);
BIND_ENUM_CONSTANT(ANCHOR_END);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_INHERITED);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LOCALE);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_LTR);
BIND_ENUM_CONSTANT(LAYOUT_DIRECTION_RTL);
BIND_ENUM_CONSTANT(TEXT_DIRECTION_INHERITED);
BIND_ENUM_CONSTANT(TEXT_DIRECTION_AUTO);
BIND_ENUM_CONSTANT(TEXT_DIRECTION_LTR);
BIND_ENUM_CONSTANT(TEXT_DIRECTION_RTL);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_DEFAULT);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_URI);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_FILE);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_EMAIL);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_LIST);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_NONE);
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_CUSTOM);
ADD_SIGNAL(MethodInfo("resized"));
ADD_SIGNAL(MethodInfo("gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
ADD_SIGNAL(MethodInfo("mouse_entered"));
@ -2884,6 +3160,7 @@ Control::Control() {
data.theme_owner = nullptr;
data.theme_owner_window = nullptr;
data.default_cursor = CURSOR_ARROW;
data.layout_dir = LAYOUT_DIRECTION_INHERITED;
data.h_size_flags = SIZE_FILL;
data.v_size_flags = SIZE_FILL;
data.expand = 1;

View File

@ -127,6 +127,30 @@ public:
PRESET_MODE_KEEP_SIZE
};
enum LayoutDirection {
LAYOUT_DIRECTION_INHERITED,
LAYOUT_DIRECTION_LOCALE,
LAYOUT_DIRECTION_LTR,
LAYOUT_DIRECTION_RTL
};
enum TextDirection {
TEXT_DIRECTION_AUTO = TextServer::DIRECTION_AUTO,
TEXT_DIRECTION_LTR = TextServer::DIRECTION_LTR,
TEXT_DIRECTION_RTL = TextServer::DIRECTION_RTL,
TEXT_DIRECTION_INHERITED,
};
enum StructuredTextParser {
STRUCTURED_TEXT_DEFAULT,
STRUCTURED_TEXT_URI,
STRUCTURED_TEXT_FILE,
STRUCTURED_TEXT_EMAIL,
STRUCTURED_TEXT_LIST,
STRUCTURED_TEXT_NONE,
STRUCTURED_TEXT_CUSTOM
};
private:
struct CComparator {
bool operator()(const Control *p_a, const Control *p_b) const {
@ -153,6 +177,8 @@ private:
GrowDirection h_grow;
GrowDirection v_grow;
LayoutDirection layout_dir;
float rotation;
Vector2 scale;
Vector2 pivot_offset;
@ -189,6 +215,7 @@ private:
HashMap<StringName, Ref<Shader>> shader_override;
HashMap<StringName, Ref<StyleBox>> style_override;
HashMap<StringName, Ref<Font>> font_override;
HashMap<StringName, int> font_size_override;
HashMap<StringName, Color> color_override;
HashMap<StringName, int> constant_override;
@ -240,6 +267,7 @@ private:
static Ref<Shader> get_shaders(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
static Ref<StyleBox> get_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
static Ref<Font> get_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
static int get_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
static Color get_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
static int get_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
@ -247,6 +275,7 @@ private:
static bool has_shaders(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
static bool has_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
static bool has_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
static bool has_font_sizes(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
static bool has_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
static bool has_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_node_type = StringName());
@ -256,6 +285,8 @@ protected:
//virtual void _window_gui_input(InputEvent p_event);
virtual Vector<Vector2i> structured_text_parser(StructuredTextParser p_node_type, const Array &p_args, const String p_text) const;
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
@ -278,6 +309,7 @@ public:
NOTIFICATION_THEME_CHANGED = 45,
NOTIFICATION_SCROLL_BEGIN = 47,
NOTIFICATION_SCROLL_END = 48,
NOTIFICATION_LAYOUT_DIRECTION_CHANGED = 49,
};
@ -325,6 +357,10 @@ public:
Control *get_parent_control() const;
void set_layout_direction(LayoutDirection p_direction);
LayoutDirection get_layout_direction() const;
virtual bool is_layout_rtl() const;
/* POSITIONING */
void set_anchors_preset(LayoutPreset p_preset, bool p_keep_margins = true);
@ -360,6 +396,8 @@ public:
Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the visual server
Rect2 get_anchorable_rect() const override;
void set_rect(const Rect2 &p_rect); // Reset anchors to begin and set rect, for faster container children sorting.
void set_rotation(float p_radians);
void set_rotation_degrees(float p_degrees);
float get_rotation() const;
@ -421,6 +459,7 @@ public:
void add_theme_shader_override(const StringName &p_name, const Ref<Shader> &p_shader);
void add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style);
void add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font);
void add_theme_font_size_override(const StringName &p_name, int p_font_size);
void add_theme_color_override(const StringName &p_name, const Color &p_color);
void add_theme_constant_override(const StringName &p_name, int p_constant);
@ -428,6 +467,7 @@ public:
Ref<Shader> get_theme_shader(const StringName &p_name, const StringName &p_node_type = StringName()) const;
Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_node_type = StringName()) const;
Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_node_type = StringName()) const;
int get_theme_font_size(const StringName &p_name, const StringName &p_node_type = StringName()) const;
Color get_theme_color(const StringName &p_name, const StringName &p_node_type = StringName()) const;
int get_theme_constant(const StringName &p_name, const StringName &p_node_type = StringName()) const;
@ -435,6 +475,7 @@ public:
bool has_theme_shader_override(const StringName &p_name) const;
bool has_theme_stylebox_override(const StringName &p_name) const;
bool has_theme_font_override(const StringName &p_name) const;
bool has_theme_font_size_override(const StringName &p_name) const;
bool has_theme_color_override(const StringName &p_name) const;
bool has_theme_constant_override(const StringName &p_name) const;
@ -442,6 +483,7 @@ public:
bool has_theme_shader(const StringName &p_name, const StringName &p_node_type = StringName()) const;
bool has_theme_stylebox(const StringName &p_name, const StringName &p_node_type = StringName()) const;
bool has_theme_font(const StringName &p_name, const StringName &p_node_type = StringName()) const;
bool has_theme_font_size(const StringName &p_name, const StringName &p_node_type = StringName()) const;
bool has_theme_color(const StringName &p_name, const StringName &p_node_type = StringName()) const;
bool has_theme_constant(const StringName &p_name, const StringName &p_node_type = StringName()) const;
@ -496,5 +538,8 @@ VARIANT_ENUM_CAST(Control::LayoutPresetMode);
VARIANT_ENUM_CAST(Control::MouseFilter);
VARIANT_ENUM_CAST(Control::GrowDirection);
VARIANT_ENUM_CAST(Control::Anchor);
VARIANT_ENUM_CAST(Control::LayoutDirection);
VARIANT_ENUM_CAST(Control::TextDirection);
VARIANT_ENUM_CAST(Control::StructuredTextParser);
#endif

View File

@ -879,6 +879,7 @@ FileDialog::FileDialog() {
hbc->add_child(drives);
dir = memnew(LineEdit);
dir->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
hbc->add_child(dir);
dir->set_h_size_flags(Control::SIZE_EXPAND_FILL);
@ -912,6 +913,7 @@ FileDialog::FileDialog() {
file_box = memnew(HBoxContainer);
file_box->add_child(memnew(Label(RTR("File:"))));
file = memnew(LineEdit);
file->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
file->set_stretch_ratio(4);
file->set_h_size_flags(Control::SIZE_EXPAND_FILL);
file_box->add_child(file);
@ -947,6 +949,7 @@ FileDialog::FileDialog() {
makedialog->add_child(makevb);
makedirname = memnew(LineEdit);
makedirname->set_structured_text_bidi_override(Control::STRUCTURED_TEXT_FILE);
makevb->add_margin_child(RTR("Name:"), makedirname);
add_child(makedialog);
makedialog->register_text_enter(makedirname);

View File

@ -30,13 +30,37 @@
#include "graph_node.h"
#include "core/string/translation.h"
bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
if (!p_name.operator String().begins_with("slot/")) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
double value = p_value;
if (value == -1) {
if (opentype_features.has(tag)) {
opentype_features.erase(tag);
_shape();
update();
}
} else {
if ((double)opentype_features[tag] != value) {
opentype_features[tag] = value;
_shape();
update();
}
}
_change_notify();
return true;
}
if (!str.begins_with("slot/")) {
return false;
}
int idx = p_name.operator String().get_slice("/", 1).to_int();
String what = p_name.operator String().get_slice("/", 2);
int idx = str.get_slice("/", 1).to_int();
String what = str.get_slice("/", 2);
Slot si;
if (slot_info.has(idx)) {
@ -65,12 +89,25 @@ bool GraphNode::_set(const StringName &p_name, const Variant &p_value) {
}
bool GraphNode::_get(const StringName &p_name, Variant &r_ret) const {
if (!p_name.operator String().begins_with("slot/")) {
String str = p_name;
if (str.begins_with("opentype_features/")) {
String name = str.get_slicec('/', 1);
int32_t tag = TS->name_to_tag(name);
if (opentype_features.has(tag)) {
r_ret = opentype_features[tag];
return true;
} else {
r_ret = -1;
return true;
}
}
if (!str.begins_with("slot/")) {
return false;
}
int idx = p_name.operator String().get_slice("/", 1).to_int();
String what = p_name.operator String().get_slice("/", 2);
int idx = str.get_slice("/", 1).to_int();
String what = str.get_slice("/", 2);
Slot si;
if (slot_info.has(idx)) {
@ -97,6 +134,12 @@ bool GraphNode::_get(const StringName &p_name, Variant &r_ret) const {
}
void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const {
for (const Variant *ftr = opentype_features.next(nullptr); ftr != nullptr; ftr = opentype_features.next(ftr)) {
String name = TS->tag_to_name(*ftr);
p_list->push_back(PropertyInfo(Variant::FLOAT, "opentype_features/" + name));
}
p_list->push_back(PropertyInfo(Variant::NIL, "opentype_features/_new", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR));
int idx = 0;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
@ -213,7 +256,6 @@ void GraphNode::_notification(int p_what) {
int close_h_offset = get_theme_constant("close_h_offset");
Color close_color = get_theme_color("close_color");
Color resizer_color = get_theme_color("resizer_color");
Ref<Font> title_font = get_theme_font("title_font");
int title_offset = get_theme_constant("title_offset");
int title_h_offset = get_theme_constant("title_h_offset");
Color title_color = get_theme_color("title_color");
@ -241,7 +283,8 @@ void GraphNode::_notification(int p_what) {
w -= close->get_width();
}
draw_string(title_font, Point2(sb->get_margin(MARGIN_LEFT) + title_h_offset, -title_font->get_height() + title_font->get_ascent() + title_offset), title, title_color, w);
title_buf->set_width(w);
title_buf->draw(get_canvas_item(), Point2(sb->get_margin(MARGIN_LEFT) + title_h_offset, -title_buf->get_size().y + title_offset), title_color);
if (show_close) {
Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT) + close_h_offset, -close->get_height() + close_offset);
draw_texture(close, cpos, close_color);
@ -285,12 +328,30 @@ void GraphNode::_notification(int p_what) {
_resort();
} break;
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_THEME_CHANGED: {
_shape();
minimum_size_changed();
update();
} break;
}
}
void GraphNode::_shape() {
Ref<Font> font = get_theme_font("title_font");
int font_size = get_theme_font_size("title_font_size");
title_buf->clear();
if (text_direction == Control::TEXT_DIRECTION_INHERITED) {
title_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else {
title_buf->set_direction((TextServer::Direction)text_direction);
}
title_buf->add_string(title, font, font_size, opentype_features, (language != "") ? language : TranslationServer::get_singleton()->get_tool_locale());
}
void GraphNode::set_slot(int p_idx, bool p_enable_left, int p_type_left, const Color &p_color_left, bool p_enable_right, int p_type_right, const Color &p_color_right, const Ref<Texture2D> &p_custom_left, const Ref<Texture2D> &p_custom_right) {
ERR_FAIL_COND(p_idx < 0);
@ -368,14 +429,12 @@ Color GraphNode::get_slot_color_right(int p_idx) const {
}
Size2 GraphNode::get_minimum_size() const {
Ref<Font> title_font = get_theme_font("title_font");
int sep = get_theme_constant("separation");
Ref<StyleBox> sb = get_theme_stylebox("frame");
bool first = true;
Size2 minsize;
minsize.x = title_font->get_string_size(title).x;
minsize.x = title_buf->get_size().x;
if (show_close) {
Ref<Texture2D> close = get_theme_icon("close");
minsize.x += sep + close->get_width();
@ -410,6 +469,8 @@ void GraphNode::set_title(const String &p_title) {
return;
}
title = p_title;
_shape();
update();
_change_notify("title");
minimum_size_changed();
@ -419,6 +480,54 @@ String GraphNode::get_title() const {
return title;
}
void GraphNode::set_text_direction(Control::TextDirection p_text_direction) {
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
if (text_direction != p_text_direction) {
text_direction = p_text_direction;
_shape();
update();
}
}
Control::TextDirection GraphNode::get_text_direction() const {
return text_direction;
}
void GraphNode::clear_opentype_features() {
opentype_features.clear();
_shape();
update();
}
void GraphNode::set_opentype_feature(const String &p_name, int p_value) {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag) || (int)opentype_features[tag] != p_value) {
opentype_features[tag] = p_value;
_shape();
update();
}
}
int GraphNode::get_opentype_feature(const String &p_name) const {
int32_t tag = TS->name_to_tag(p_name);
if (!opentype_features.has(tag)) {
return -1;
}
return opentype_features[tag];
}
void GraphNode::set_language(const String &p_language) {
if (language != p_language) {
language = p_language;
_shape();
update();
}
}
String GraphNode::get_language() const {
return language;
}
void GraphNode::set_offset(const Vector2 &p_offset) {
offset = p_offset;
emit_signal("offset_changed");
@ -658,6 +767,14 @@ bool GraphNode::is_resizable() const {
void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_title", "title"), &GraphNode::set_title);
ClassDB::bind_method(D_METHOD("get_title"), &GraphNode::get_title);
ClassDB::bind_method(D_METHOD("set_text_direction", "direction"), &GraphNode::set_text_direction);
ClassDB::bind_method(D_METHOD("get_text_direction"), &GraphNode::get_text_direction);
ClassDB::bind_method(D_METHOD("set_opentype_feature", "tag", "value"), &GraphNode::set_opentype_feature);
ClassDB::bind_method(D_METHOD("get_opentype_feature", "tag"), &GraphNode::get_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_opentype_features"), &GraphNode::clear_opentype_features);
ClassDB::bind_method(D_METHOD("set_language", "language"), &GraphNode::set_language);
ClassDB::bind_method(D_METHOD("get_language"), &GraphNode::get_language);
ClassDB::bind_method(D_METHOD("_gui_input"), &GraphNode::_gui_input);
ClassDB::bind_method(D_METHOD("set_slot", "idx", "enable_left", "type_left", "color_left", "enable_right", "type_right", "color_right", "custom_left", "custom_right"), &GraphNode::set_slot, DEFVAL(Ref<Texture2D>()), DEFVAL(Ref<Texture2D>()));
@ -699,6 +816,8 @@ void GraphNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_overlay"), &GraphNode::get_overlay);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,LTR,RTL,Inherited"), "set_text_direction", "get_text_direction");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "language"), "set_language", "get_language");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable"), "set_resizable", "is_resizable");
@ -718,6 +837,7 @@ void GraphNode::_bind_methods() {
}
GraphNode::GraphNode() {
title_buf.instance();
overlay = OVERLAY_DISABLED;
show_close = false;
connpos_dirty = true;

View File

@ -32,6 +32,7 @@
#define GRAPH_NODE_H
#include "scene/gui/container.h"
#include "scene/resources/text_line.h"
class GraphNode : public Container {
GDCLASS(GraphNode, Container);
@ -65,6 +66,12 @@ private:
};
String title;
Ref<TextLine> title_buf;
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
bool show_close;
Vector2 offset;
bool comment;
@ -93,6 +100,7 @@ private:
void _connpos_update();
void _resort();
void _shape();
Vector2 drag_from;
bool selected;
@ -124,6 +132,16 @@ public:
void set_title(const String &p_title);
String get_title() const;
void set_text_direction(TextDirection p_text_direction);
TextDirection get_text_direction() const;
void set_opentype_feature(const String &p_name, int p_value);
int get_opentype_feature(const String &p_name) const;
void clear_opentype_features();
void set_language(const String &p_language);
String get_language() const;
void set_offset(const Vector2 &p_offset);
Vector2 get_offset() const;

View File

@ -141,6 +141,7 @@ void GridContainer::_notification(int p_what) {
// Finally, fit the nodes.
int col_expand = col_expanded.size() > 0 ? remaining_space.width / col_expanded.size() : 0;
int row_expand = row_expanded.size() > 0 ? remaining_space.height / row_expanded.size() : 0;
bool rtl = is_layout_rtl();
int col_ofs = 0;
int row_ofs = 0;
@ -156,24 +157,37 @@ void GridContainer::_notification(int p_what) {
valid_controls_index++;
if (col == 0) {
col_ofs = 0;
if (rtl) {
col_ofs = get_size().width;
} else {
col_ofs = 0;
}
if (row > 0) {
row_ofs += (row_expanded.has(row - 1) ? row_expand : row_minh[row - 1]) + vsep;
}
}
Point2 p(col_ofs, row_ofs);
Size2 s(col_expanded.has(col) ? col_expand : col_minw[col], row_expanded.has(row) ? row_expand : row_minh[row]);
fit_child_in_rect(c, Rect2(p, s));
col_ofs += s.width + hsep;
if (rtl) {
Size2 s(col_expanded.has(col) ? col_expand : col_minw[col], row_expanded.has(row) ? row_expand : row_minh[row]);
Point2 p(col_ofs - s.width, row_ofs);
fit_child_in_rect(c, Rect2(p, s));
col_ofs -= s.width + hsep;
} else {
Point2 p(col_ofs, row_ofs);
Size2 s(col_expanded.has(col) ? col_expand : col_minw[col], row_expanded.has(row) ? row_expand : row_minh[row]);
fit_child_in_rect(c, Rect2(p, s));
col_ofs += s.width + hsep;
}
}
} break;
case NOTIFICATION_THEME_CHANGED: {
minimum_size_changed();
} break;
case NOTIFICATION_TRANSLATION_CHANGED:
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
queue_sort();
} break;
}
}

View File

@ -31,6 +31,24 @@
#include "item_list.h"
#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "core/string/translation.h"
void ItemList::_shape(int p_idx) {
Item &item = items.write[p_idx];
item.text_buf->clear();
if (item.text_direction == Control::TEXT_DIRECTION_INHERITED) {
item.text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
} else {
item.text_buf->set_direction((TextServer::Direction)item.text_direction);
}
item.text_buf->add_string(item.text, get_theme_font("font"), get_theme_font_size("font_size"), item.opentype_features, (item.language != "") ? item.language : TranslationServer::get_singleton()->get_tool_locale());
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
item.text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
} else {
item.text_buf->set_flags(TextServer::BREAK_NONE);
}
}
void ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, bool p_selectable) {
Item item;
@ -39,6 +57,7 @@ void ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, b
item.icon_region = Rect2i();
item.icon_modulate = Color(1, 1, 1, 1);
item.text = p_item;
item.text_buf.instance();
item.selectable = p_selectable;
item.selected = false;
item.disabled = false;
@ -46,6 +65,8 @@ void ItemList::add_item(const String &p_item, const Ref<Texture2D> &p_texture, b
item.custom_bg = Color(0, 0, 0, 0);
items.push_back(item);
_shape(items.size() - 1);
update();
shape_changed = true;
}
@ -72,6 +93,7 @@ void ItemList::set_item_text(int p_idx, const String &p_text) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].text = p_text;
_shape(p_idx);
update();
shape_changed = true;
}
@ -81,6 +103,61 @@ String ItemList::get_item_text(int p_idx) const {
return items[p_idx].text;
}
void ItemList::set_item_text_direction(int p_idx, Control::TextDirection p_text_direction) {
ERR_FAIL_INDEX(p_idx, items.size());
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
if (items[p_idx].text_direction != p_text_direction) {
items.write[p_idx].text_direction = p_text_direction;
_shape(p_idx);
update();
}
}
Control::TextDirection ItemList::get_item_text_direction(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), TEXT_DIRECTION_INHERITED);
return items[p_idx].text_direction;
}
void ItemList::clear_item_opentype_features(int p_idx) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].opentype_features.clear();
_shape(p_idx);
update();
}
void ItemList::set_item_opentype_feature(int p_idx, const String &p_name, int p_value) {
ERR_FAIL_INDEX(p_idx, items.size());
int32_t tag = TS->name_to_tag(p_name);
if (!items[p_idx].opentype_features.has(tag) || (int)items[p_idx].opentype_features[tag] != p_value) {
items.write[p_idx].opentype_features[tag] = p_value;
_shape(p_idx);
update();
}
}
int ItemList::get_item_opentype_feature(int p_idx, const String &p_name) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), -1);
int32_t tag = TS->name_to_tag(p_name);
if (!items[p_idx].opentype_features.has(tag)) {
return -1;
}
return items[p_idx].opentype_features[tag];
}
void ItemList::set_item_language(int p_idx, const String &p_language) {
ERR_FAIL_INDEX(p_idx, items.size());
if (items[p_idx].language != p_language) {
items.write[p_idx].language = p_language;
_shape(p_idx);
update();
}
}
String ItemList::get_item_language(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), "");
return items[p_idx].language;
}
void ItemList::set_item_tooltip_enabled(int p_idx, const bool p_enabled) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].tooltip_enabled = p_enabled;
@ -361,9 +438,18 @@ bool ItemList::is_same_column_width() const {
void ItemList::set_max_text_lines(int p_lines) {
ERR_FAIL_COND(p_lines < 1);
max_text_lines = p_lines;
update();
shape_changed = true;
if (max_text_lines != p_lines) {
max_text_lines = p_lines;
for (int i = 0; i < items.size(); i++) {
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
items.write[i].text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
} else {
items.write[i].text_buf->set_flags(TextServer::BREAK_NONE);
}
}
shape_changed = true;
update();
}
}
int ItemList::get_max_text_lines() const {
@ -392,9 +478,18 @@ ItemList::SelectMode ItemList::get_select_mode() const {
void ItemList::set_icon_mode(IconMode p_mode) {
ERR_FAIL_INDEX((int)p_mode, 2);
icon_mode = p_mode;
update();
shape_changed = true;
if (icon_mode != p_mode) {
icon_mode = p_mode;
for (int i = 0; i < items.size(); i++) {
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
items.write[i].text_buf->set_flags(TextServer::BREAK_MANDATORY | TextServer::BREAK_WORD_BOUND | TextServer::BREAK_GRAPHEME_BOUND);
} else {
items.write[i].text_buf->set_flags(TextServer::BREAK_NONE);
}
}
shape_changed = true;
update();
}
}
ItemList::IconMode ItemList::get_icon_mode() const {
@ -455,6 +550,10 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
pos -= bg->get_offset();
pos.y += scroll_bar->get_value();
if (is_layout_rtl()) {
pos.x = get_size().width - pos.x;
}
int closest = -1;
for (int i = 0; i < items.size(); i++) {
@ -749,6 +848,14 @@ void ItemList::_notification(int p_what) {
update();
}
if ((p_what == NOTIFICATION_LAYOUT_DIRECTION_CHANGED) || (p_what == NOTIFICATION_TRANSLATION_CHANGED) || (p_what == NOTIFICATION_THEME_CHANGED)) {
for (int i = 0; i < items.size(); i++) {
_shape(i);
}
shape_changed = true;
update();
}
if (p_what == NOTIFICATION_DRAW) {
Ref<StyleBox> bg = get_theme_stylebox("bg");
@ -774,19 +881,11 @@ void ItemList::_notification(int p_what) {
Ref<StyleBox> sbsel = has_focus() ? get_theme_stylebox("selected_focus") : get_theme_stylebox("selected");
Ref<StyleBox> cursor = has_focus() ? get_theme_stylebox("cursor") : get_theme_stylebox("cursor_unfocused");
bool rtl = is_layout_rtl();
Ref<Font> font = get_theme_font("font");
Color guide_color = get_theme_color("guide_color");
Color font_color = get_theme_color("font_color");
Color font_color_selected = get_theme_color("font_color_selected");
int font_height = font->get_height();
Vector<int> line_size_cache;
Vector<int> line_limit_cache;
if (max_text_lines) {
line_size_cache.resize(max_text_lines);
line_limit_cache.resize(max_text_lines);
}
if (has_focus()) {
RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), true);
@ -817,13 +916,13 @@ void ItemList::_notification(int p_what) {
}
if (items[i].text != "") {
Size2 s = font->get_string_size(items[i].text);
Size2 s = items[i].text_buf->get_size();
//s.width=MIN(s.width,fixed_column_width);
if (icon_mode == ICON_MODE_TOP) {
minsize.x = MAX(minsize.x, s.width);
if (max_text_lines > 0) {
minsize.y += (font_height + line_separation) * max_text_lines;
minsize.y += s.height + line_separation * max_text_lines;
} else {
minsize.y += s.height;
}
@ -986,6 +1085,10 @@ void ItemList::_notification(int p_what) {
r.position.x -= hseparation / 2;
r.size.x += hseparation;
if (rtl) {
r.position.x = size.width - r.position.x - r.size.x;
}
draw_style_box(sbsel, r);
}
if (items[i].custom_bg.a > 0.001) {
@ -998,6 +1101,10 @@ void ItemList::_notification(int p_what) {
r.position.x -= hseparation / 2;
r.size.x += hseparation;
if (rtl) {
r.position.x = size.width - r.position.x - r.size.x;
}
draw_rect(r, items[i].custom_bg);
}
@ -1049,17 +1156,25 @@ void ItemList::_notification(int p_what) {
}
Rect2 region = (items[i].icon_region.size.x == 0 || items[i].icon_region.size.y == 0) ? Rect2(Vector2(), items[i].icon->get_size()) : Rect2(items[i].icon_region);
if (rtl) {
draw_rect.position.x = size.width - draw_rect.position.x - draw_rect.size.x;
}
draw_texture_rect_region(items[i].icon, draw_rect, region, modulate, items[i].icon_transposed);
}
if (items[i].tag_icon.is_valid()) {
draw_texture(items[i].tag_icon, items[i].rect_cache.position + base_ofs);
Point2 draw_pos = items[i].rect_cache.position;
if (rtl) {
draw_pos.x = size.width - draw_pos.x - items[i].tag_icon->get_width();
}
draw_texture(items[i].tag_icon, draw_pos + base_ofs);
}
if (items[i].text != "") {
int max_len = -1;
Vector2 size2 = font->get_string_size(items[i].text);
Vector2 size2 = items[i].text_buf->get_size();
if (fixed_column_width) {
max_len = fixed_column_width;
} else if (same_column_width) {
@ -1074,45 +1189,18 @@ void ItemList::_notification(int p_what) {
}
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
int ss = items[i].text.length();
float ofs = 0;
int line = 0;
for (int j = 0; j <= ss; j++) {
int cs = j < ss ? font->get_char_size(items[i].text[j], items[i].text[j + 1]).x : 0;
if (ofs + cs > max_len || j == ss) {
line_limit_cache.write[line] = j;
line_size_cache.write[line] = ofs;
line++;
ofs = 0;
if (line >= max_text_lines) {
break;
}
} else {
ofs += cs;
}
}
line = 0;
ofs = 0;
text_ofs.y += font->get_ascent();
text_ofs = text_ofs.floor();
text_ofs += base_ofs;
text_ofs += items[i].rect_cache.position;
FontDrawer drawer(font, Color(1, 1, 1));
for (int j = 0; j < ss; j++) {
if (j == line_limit_cache[line]) {
line++;
ofs = 0;
if (line >= max_text_lines) {
break;
}
}
ofs += drawer.draw_char(get_canvas_item(), text_ofs + Vector2(ofs + (max_len - line_size_cache[line]) / 2, line * (font_height + line_separation)).floor(), items[i].text[j], items[i].text[j + 1], modulate);
if (rtl) {
text_ofs.x = size.width - text_ofs.x - max_len;
}
//special multiline mode
items.write[i].text_buf->set_width(max_len);
items.write[i].text_buf->set_align(HALIGN_CENTER);
items[i].text_buf->draw(get_canvas_item(), text_ofs, modulate);
} else {
if (fixed_column_width > 0) {
size2.x = MIN(size2.x, fixed_column_width);
@ -1124,12 +1212,22 @@ void ItemList::_notification(int p_what) {
text_ofs.y += (items[i].rect_cache.size.height - size2.y) / 2;
}
text_ofs.y += font->get_ascent();
text_ofs = text_ofs.floor();
text_ofs += base_ofs;
text_ofs += items[i].rect_cache.position;
draw_string(font, text_ofs, items[i].text, modulate, max_len + 1);
if (rtl) {
text_ofs.x = size.width - text_ofs.x - max_len;
}
items.write[i].text_buf->set_width(max_len);
if (rtl) {
items.write[i].text_buf->set_align(HALIGN_RIGHT);
} else {
items.write[i].text_buf->set_align(HALIGN_LEFT);
}
items[i].text_buf->draw(get_canvas_item(), text_ofs, modulate);
}
}
@ -1140,6 +1238,11 @@ void ItemList::_notification(int p_what) {
r.size.y += vseparation;
r.position.x -= hseparation / 2;
r.size.x += hseparation;
if (rtl) {
r.position.x = size.width - r.position.x - r.size.x;
}
draw_style_box(cursor, r);
}
}
@ -1181,6 +1284,10 @@ int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const {
pos -= bg->get_offset();
pos.y += scroll_bar->get_value();
if (is_layout_rtl()) {
pos.x = get_size().width - pos.x;
}
int closest = -1;
int closest_dist = 0x7FFFFFFF;
@ -1215,6 +1322,10 @@ bool ItemList::is_pos_at_end_of_items(const Point2 &p_pos) const {
pos -= bg->get_offset();
pos.y += scroll_bar->get_value();
if (is_layout_rtl()) {
pos.x = get_size().width - pos.x;
}
Rect2 endrect = items[items.size() - 1].rect_cache;
return (pos.y > endrect.position.y + endrect.size.y);
}
@ -1366,6 +1477,16 @@ void ItemList::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_icon", "idx", "icon"), &ItemList::set_item_icon);
ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &ItemList::get_item_icon);
ClassDB::bind_method(D_METHOD("set_item_text_direction", "idx", "direction"), &ItemList::set_item_text_direction);
ClassDB::bind_method(D_METHOD("get_item_text_direction", "idx"), &ItemList::get_item_text_direction);
ClassDB::bind_method(D_METHOD("set_item_opentype_feature", "idx", "tag", "value"), &ItemList::set_item_opentype_feature);
ClassDB::bind_method(D_METHOD("get_item_opentype_feature", "idx", "tag"), &ItemList::get_item_opentype_feature);
ClassDB::bind_method(D_METHOD("clear_item_opentype_features", "idx"), &ItemList::clear_item_opentype_features);
ClassDB::bind_method(D_METHOD("set_item_language", "idx", "language"), &ItemList::set_item_language);
ClassDB::bind_method(D_METHOD("get_item_language", "idx"), &ItemList::get_item_language);
ClassDB::bind_method(D_METHOD("set_item_icon_transposed", "idx", "transposed"), &ItemList::set_item_icon_transposed);
ClassDB::bind_method(D_METHOD("is_item_icon_transposed", "idx"), &ItemList::is_item_icon_transposed);

View File

@ -33,6 +33,7 @@
#include "scene/gui/control.h"
#include "scene/gui/scroll_bar.h"
#include "scene/resources/text_paragraph.h"
class ItemList : public Control {
GDCLASS(ItemList, Control);
@ -56,6 +57,11 @@ private:
Color icon_modulate;
Ref<Texture2D> tag_icon;
String text;
Ref<TextParagraph> text_buf;
Dictionary opentype_features;
String language;
TextDirection text_direction = TEXT_DIRECTION_AUTO;
bool selectable;
bool selected;
bool disabled;
@ -117,6 +123,7 @@ private:
void _scroll_changed(double);
void _gui_input(const Ref<InputEvent> &p_event);
void _shape(int p_idx);
protected:
void _notification(int p_what);
@ -129,6 +136,16 @@ public:
void set_item_text(int p_idx, const String &p_text);
String get_item_text(int p_idx) const;
void set_item_text_direction(int p_idx, TextDirection p_text_direction);
TextDirection get_item_text_direction(int p_idx) const;
void set_item_opentype_feature(int p_idx, const String &p_name, int p_value);
int get_item_opentype_feature(int p_idx, const String &p_name) const;
void clear_item_opentype_features(int p_idx);
void set_item_language(int p_idx, const String &p_language);
String get_item_language(int p_idx) const;
void set_item_icon(int p_idx, const Ref<Texture2D> &p_icon);
Ref<Texture2D> get_item_icon(int p_idx) const;

View File

@ -93,16 +93,17 @@ void Label::_notification(int p_what) {
Size2 size = get_size();
Ref<StyleBox> style = get_theme_stylebox("normal");
Ref<Font> font = get_theme_font("font");
int font_size = get_theme_font_size("font_size");
Color font_color = get_theme_color("font_color");
Color font_color_shadow = get_theme_color("font_color_shadow");
bool use_outline = get_theme_constant("shadow_as_outline");
Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y"));
int line_spacing = get_theme_constant("line_spacing");
Color font_outline_modulate = get_theme_color("font_outline_modulate");
//Color font_outline_modulate = get_theme_color("font_outline_modulate");
style->draw(ci, Rect2(Point2(0, 0), get_size()));
RenderingServer::get_singleton()->canvas_item_set_distance_field_mode(get_canvas_item(), font.is_valid() && font->is_distance_field_hint());
//RenderingServer::get_singleton()->canvas_item_set_distance_field_mode(get_canvas_item(), font.is_valid() && font->is_distance_field_hint());
int font_h = font->get_height() + line_spacing;
@ -155,7 +156,7 @@ void Label::_notification(int p_what) {
int line = 0;
int line_to = lines_skipped + (lines_visible > 0 ? lines_visible : 1);
FontDrawer drawer(font, font_outline_modulate);
//FontDrawer drawer(font, font_outline_modulate);
while (wc) {
/* handle lines not meant to be drawn quickly */
if (line >= line_to) {
@ -242,11 +243,12 @@ void Label::_notification(int p_what) {
n = String::char_uppercase(n);
}
float move = drawer.draw_char(ci, Point2(x_ofs_shadow, y_ofs) + shadow_ofs, c, n, font_color_shadow);
//TODO replace with TS
float move = font->draw_char(ci, Point2(x_ofs_shadow, y_ofs) + shadow_ofs, c, n, font_size, font_color_shadow);
if (use_outline) {
drawer.draw_char(ci, Point2(x_ofs_shadow, y_ofs) + Vector2(-shadow_ofs.x, shadow_ofs.y), c, n, font_color_shadow);
drawer.draw_char(ci, Point2(x_ofs_shadow, y_ofs) + Vector2(shadow_ofs.x, -shadow_ofs.y), c, n, font_color_shadow);
drawer.draw_char(ci, Point2(x_ofs_shadow, y_ofs) + Vector2(-shadow_ofs.x, -shadow_ofs.y), c, n, font_color_shadow);
font->draw_char(ci, Point2(x_ofs_shadow, y_ofs) + Vector2(-shadow_ofs.x, shadow_ofs.y), c, n, font_size, font_color_shadow);
font->draw_char(ci, Point2(x_ofs_shadow, y_ofs) + Vector2(shadow_ofs.x, -shadow_ofs.y), c, n, font_size, font_color_shadow);
font->draw_char(ci, Point2(x_ofs_shadow, y_ofs) + Vector2(-shadow_ofs.x, -shadow_ofs.y), c, n, font_size, font_color_shadow);
}
x_ofs_shadow += move;
chars_total_shadow++;
@ -262,7 +264,7 @@ void Label::_notification(int p_what) {
n = String::char_uppercase(n);
}
x_ofs += drawer.draw_char(ci, Point2(x_ofs, y_ofs), c, n, font_color);
x_ofs += font->draw_char(ci, Point2(x_ofs, y_ofs), c, n, font_size, font_color);
chars_total++;
}
}

View File

@ -719,6 +719,7 @@ void LineEdit::_notification(int p_what) {
}
Ref<Font> font = get_theme_font("font");
int font_size = get_theme_font_size("font_size");
style->draw(ci, Rect2(Point2(), size));
@ -792,8 +793,10 @@ void LineEdit::_notification(int p_what) {
}
int caret_height = font->get_height() > y_area ? y_area : font->get_height();
FontDrawer drawer(font, Color(1, 1, 1));
//FontDrawer drawer(font, Color(1, 1, 1));
while (true) {
//TODO replace with TS
// End of string, break.
if (char_ofs >= t.length()) {
break;
@ -822,7 +825,7 @@ void LineEdit::_notification(int p_what) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 1)), font_color);
}
drawer.draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, font_color);
font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, font_size, font_color);
x_ofs += im_char_width;
ofs++;
@ -846,7 +849,7 @@ void LineEdit::_notification(int p_what) {
}
int yofs = y_ofs + (caret_height - font->get_height()) / 2;
drawer.draw_char(ci, Point2(x_ofs, yofs + font_ascent), cchar, next, selected ? font_color_selected : font_color);
font->draw_char(ci, Point2(x_ofs, yofs + font_ascent), cchar, next, font_size, selected ? font_color_selected : font_color);
if (char_ofs == cursor_pos && draw_caret && !using_placeholder) {
if (ime_text.length() == 0) {
@ -885,7 +888,7 @@ void LineEdit::_notification(int p_what) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 1)), font_color);
}
drawer.draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, font_color);
font->draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, font_size, font_color);
x_ofs += im_char_width;
ofs++;
@ -1427,6 +1430,7 @@ void LineEdit::clear_internal() {
Size2 LineEdit::get_minimum_size() const {
Ref<StyleBox> style = get_theme_stylebox("normal");
Ref<Font> font = get_theme_font("font");
int font_size = get_theme_font_size("font_size");
Size2 min_size;
@ -1436,7 +1440,7 @@ Size2 LineEdit::get_minimum_size() const {
if (expand_to_text_length) {
// Add a space because some fonts are too exact, and because cursor needs a bit more when at the end.
min_size.width = MAX(min_size.width, font->get_string_size(text).x + space_size);
min_size.width = MAX(min_size.width, font->get_string_size(text, font_size).x + space_size);
}
min_size.height = font->get_height();

Some files were not shown because too many files have changed in this diff Show More