Backport Label3D node implementation and Sprite*3D material render priority.

This commit is contained in:
bruvzg 2022-05-21 20:12:12 +03:00
parent 241c267d9c
commit dc6d8d6098
No known key found for this signature in database
GPG Key ID: 7960FCF39844EC38
20 changed files with 2011 additions and 27 deletions

View File

@ -51,6 +51,51 @@
Returns the size of a character, optionally taking kerning into account if the next character is provided. Note that the height returned is the font height (see [method get_height]) and has no relation to the glyph height.
</description>
</method>
<method name="get_char_texture" qualifiers="const">
<return type="RID" />
<argument index="0" name="char" type="int" />
<argument index="1" name="next" type="int" default="0" />
<argument index="2" name="outline" type="bool" default="false" />
<description>
Returns resource id of the cache texture containing the char.
</description>
</method>
<method name="get_char_texture_size" qualifiers="const">
<return type="Vector2" />
<argument index="0" name="char" type="int" />
<argument index="1" name="next" type="int" default="0" />
<argument index="2" name="outline" type="bool" default="false" />
<description>
Returns size of the cache texture containing the char.
</description>
</method>
<method name="get_char_tx_offset" qualifiers="const">
<return type="Vector2" />
<argument index="0" name="char" type="int" />
<argument index="1" name="next" type="int" default="0" />
<argument index="2" name="outline" type="bool" default="false" />
<description>
Returns char offset from the baseline.
</description>
</method>
<method name="get_char_tx_size" qualifiers="const">
<return type="Vector2" />
<argument index="0" name="char" type="int" />
<argument index="1" name="next" type="int" default="0" />
<argument index="2" name="outline" type="bool" default="false" />
<description>
Returns size of the char.
</description>
</method>
<method name="get_char_tx_uv_rect" qualifiers="const">
<return type="Rect2" />
<argument index="0" name="char" type="int" />
<argument index="1" name="next" type="int" default="0" />
<argument index="2" name="outline" type="bool" default="false" />
<description>
Returns rectangle in the cache texture containing the char.
</description>
</method>
<method name="get_descent" qualifiers="const">
<return type="float" />
<description>

156
doc/classes/Label3D.xml Normal file
View File

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Label3D" inherits="GeometryInstance" version="3.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
Displays plain text in a 3D world.
</brief_description>
<description>
Label3D displays plain text in a 3D world. It gives you control over the horizontal and vertical alignment.
</description>
<tutorials>
</tutorials>
<methods>
<method name="generate_triangle_mesh" qualifiers="const">
<return type="TriangleMesh" />
<description>
Returns a [TriangleMesh] with the label's vertices following its current configuration (such as its [member pixel_size]).
</description>
</method>
<method name="get_draw_flag" qualifiers="const">
<return type="bool" />
<argument index="0" name="flag" type="int" enum="Label3D.DrawFlags" />
<description>
Returns the value of the specified flag.
</description>
</method>
<method name="set_draw_flag">
<return type="void" />
<argument index="0" name="flag" type="int" enum="Label3D.DrawFlags" />
<argument index="1" name="enabled" type="bool" />
<description>
If [code]true[/code], the specified flag will be enabled. See [enum Label3D.DrawFlags] for a list of flags.
</description>
</method>
</methods>
<members>
<member name="alpha_cut" type="int" setter="set_alpha_cut_mode" getter="get_alpha_cut_mode" enum="Label3D.AlphaCutMode" default="0">
The alpha cutting mode to use for the sprite. See [enum AlphaCutMode] for possible values.
</member>
<member name="alpha_scissor_threshold" type="float" setter="set_alpha_scissor_threshold" getter="get_alpha_scissor_threshold" default="0.5">
Threshold at which the alpha scissor will discard values.
</member>
<member name="autowrap" type="bool" setter="set_autowrap" getter="get_autowrap" default="false">
If [code]true[/code], wraps the text to the [member width].
</member>
<member name="billboard" type="int" setter="set_billboard_mode" getter="get_billboard_mode" enum="SpatialMaterial.BillboardMode" default="0">
The billboard mode to use for the label. See [enum SpatialMaterial.BillboardMode] for possible values.
</member>
<member name="double_sided" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="true">
If [code]true[/code], text can be seen from the back as well, if [code]false[/code], it is invisible when looking at it from behind.
</member>
<member name="fixed_size" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
If [code]true[/code], the label is rendered at the same size regardless of distance.
</member>
<member name="font" type="Font" setter="set_font" getter="get_font">
[Font] used for the [Label3D]'s text.
</member>
<member name="horizontal_alignment" type="int" setter="set_horizontal_alignment" getter="get_horizontal_alignment" enum="Label3D.Align" default="1">
Controls the text's horizontal alignment. Supports left, center, right. Set it to one of the [enum Align] constants.
</member>
<member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0">
Vertical space between lines in multiline [Label3D].
</member>
<member name="modulate" type="Color" setter="set_modulate" getter="get_modulate" default="Color( 1, 1, 1, 1 )">
Text [Color] of the [Label3D].
</member>
<member name="no_depth_test" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
If [code]true[/code], depth testing is disabled and the object will be drawn in render order.
</member>
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2( 0, 0 )">
The text drawing offset (in pixels).
</member>
<member name="outline_modulate" type="Color" setter="set_outline_modulate" getter="get_outline_modulate" default="Color( 0, 0, 0, 1 )">
The tint of [Font]'s outline.
</member>
<member name="outline_render_priority" type="int" setter="set_outline_render_priority" getter="get_outline_render_priority" default="-1">
Sets the render priority for the text outline. Higher priority objects will be sorted in front of lower priority objects.
[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value).
[b]Note:[/b] This only applies to sorting of transparent objects. This will not impact how transparent objects are sorted relative to opaque objects. This is because opaque objects are not sorted, while transparent objects are sorted from back to front (subject to priority).
</member>
<member name="pixel_size" type="float" setter="set_pixel_size" getter="get_pixel_size" default="0.01">
The size of one pixel's width on the label to scale it in 3D.
</member>
<member name="render_priority" type="int" setter="set_render_priority" getter="get_render_priority" default="0">
Sets the render priority for the text. Higher priority objects will be sorted in front of lower priority objects.
[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value).
[b]Note:[/b] This only applies to sorting of transparent objects. This will not impact how transparent objects are sorted relative to opaque objects. This is because opaque objects are not sorted, while transparent objects are sorted from back to front (subject to priority).
</member>
<member name="shaded" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
If [code]true[/code], the [Light] in the [Environment] has effects on the label.
</member>
<member name="text" type="String" setter="set_text" getter="get_text" default="&quot;&quot;">
The text to display on screen.
</member>
<member name="uppercase" type="bool" setter="set_uppercase" getter="is_uppercase" default="false">
If [code]true[/code], all the text displays as UPPERCASE.
</member>
<member name="vertical_alignment" type="int" setter="set_vertical_alignment" getter="get_vertical_alignment" enum="Label3D.VAlign" default="1">
Controls the text's vertical alignment. Supports top, center, bottom. Set it to one of the [enum VAlign] constants.
</member>
<member name="width" type="float" setter="set_width" getter="get_width" default="500.0">
Text width (in pixels), used for autowrap and fill alignment.
</member>
</members>
<constants>
<constant name="FLAG_SHADED" value="0" enum="DrawFlags">
If set, lights in the environment affect the label.
</constant>
<constant name="FLAG_DOUBLE_SIDED" value="1" enum="DrawFlags">
If set, text can be seen from the back as well. If not, the texture is invisible when looking at it from behind.
</constant>
<constant name="FLAG_DISABLE_DEPTH_TEST" value="2" enum="DrawFlags">
Disables the depth test, so this object is drawn on top of all others. However, objects drawn after it in the draw order may cover it.
</constant>
<constant name="FLAG_FIXED_SIZE" value="3" enum="DrawFlags">
Label is scaled by depth so that it always appears the same size on screen.
</constant>
<constant name="FLAG_MAX" value="4" enum="DrawFlags">
Represents the size of the [enum DrawFlags] enum.
</constant>
<constant name="ALPHA_CUT_DISABLED" value="0" enum="AlphaCutMode">
This mode performs standard alpha blending. It can display translucent areas, but transparency sorting issues may be visible when multiple transparent materials are overlapping.
</constant>
<constant name="ALPHA_CUT_DISCARD" value="1" enum="AlphaCutMode">
This mode only allows fully transparent or fully opaque pixels. This mode is also known as [i]alpha testing[/i] or [i]1-bit transparency[/i].
[b]Note:[/b] This mode might have issues with anti-aliased fonts and outlines, try adjusting [member alpha_scissor_threshold] or using SDF font.
[b]Note:[/b] When using text with overlapping glyphs (e.g., cursive scripts), this mode might have transparency sorting issues between the main text and the outline.
</constant>
<constant name="ALPHA_CUT_OPAQUE_PREPASS" value="2" enum="AlphaCutMode">
This mode draws fully opaque pixels in the depth prepass. This is slower than [constant ALPHA_CUT_DISABLED] or [constant ALPHA_CUT_DISCARD], but it allows displaying translucent areas and smooth edges while using proper sorting.
[b]Note:[/b] When using text with overlapping glyphs (e.g., cursive scripts), this mode might have transparency sorting issues between the main text and the outline.
</constant>
<constant name="ALIGN_LEFT" value="0" enum="Align">
Align rows to the left (default).
</constant>
<constant name="ALIGN_CENTER" value="1" enum="Align">
Align rows centered.
</constant>
<constant name="ALIGN_RIGHT" value="2" enum="Align">
Align rows to the right.
</constant>
<constant name="ALIGN_FILL" value="3" enum="Align">
Expand row whitespaces to fit the width.
</constant>
<constant name="VALIGN_TOP" value="0" enum="VAlign">
Align the whole text to the top.
</constant>
<constant name="VALIGN_CENTER" value="1" enum="VAlign">
Align the whole text to the center.
</constant>
<constant name="VALIGN_BOTTOM" value="2" enum="VAlign">
Align the whole text to the bottom.
</constant>
<constant name="VALIGN_FILL" value="3" enum="VAlign">
Align the whole text by spreading the rows.
</constant>
</constants>
</class>

View File

@ -183,6 +183,9 @@
<member name="flags_albedo_tex_force_srgb" type="bool" setter="set_flag" getter="get_flag" default="false">
Forces a conversion of the [member albedo_texture] from sRGB space to linear space.
</member>
<member name="flags_albedo_tex_msdf" type="bool" setter="set_flag" getter="get_flag" default="false">
Enables signed distance field rendering shader.
</member>
<member name="flags_disable_ambient_light" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], the object receives no ambient light.
</member>
@ -570,7 +573,10 @@
<constant name="FLAG_USE_SHADOW_TO_OPACITY" value="18" enum="Flags">
Enables the shadow to opacity feature.
</constant>
<constant name="FLAG_MAX" value="19" enum="Flags">
<constant name="FLAG_ALBEDO_TEXTURE_SDF" value="19" enum="Flags">
Enables signed distance field rendering shader.
</constant>
<constant name="FLAG_MAX" value="20" enum="Flags">
Represents the size of the [enum Flags] enum.
</constant>
<constant name="DIFFUSE_BURLEY" value="0" enum="DiffuseMode">

View File

@ -50,6 +50,9 @@
<member name="double_sided" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="true">
If [code]true[/code], texture can be seen from the back as well, if [code]false[/code], it is invisible when looking at it from behind.
</member>
<member name="fixed_size" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
If [code]true[/code], the label is rendered at the same size regardless of distance.
</member>
<member name="flip_h" type="bool" setter="set_flip_h" getter="is_flipped_h" default="false">
If [code]true[/code], texture is flipped horizontally.
</member>
@ -60,6 +63,9 @@
A color value used to [i]multiply[/i] the texture's colors. Can be used for mood-coloring or to simulate the color of light.
[b]Note:[/b] If a [member GeometryInstance.material_override] is defined on the [SpriteBase3D], the material override must be configured to take vertex colors into account for albedo. Otherwise, the color defined in [member modulate] will be ignored. For a [SpatialMaterial], [member SpatialMaterial.vertex_color_use_as_albedo] must be [code]true[/code]. For a [ShaderMaterial], [code]ALBEDO *= COLOR.rgb;[/code] must be inserted in the shader's [code]fragment()[/code] function.
</member>
<member name="no_depth_test" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
If [code]true[/code], depth testing is disabled and the object will be drawn in render order.
</member>
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2( 0, 0 )">
The texture's drawing offset.
</member>
@ -70,6 +76,11 @@
<member name="pixel_size" type="float" setter="set_pixel_size" getter="get_pixel_size" default="0.01">
The size of one pixel's width on the sprite to scale it in 3D.
</member>
<member name="render_priority" type="int" setter="set_render_priority" getter="get_render_priority" default="0">
Sets the render priority for the sprite. Higher priority objects will be sorted in front of lower priority objects.
[b]Node:[/b] This only applies if [member alpha_cut] is set to [constant ALPHA_CUT_DISABLED] (default value).
[b]Note:[/b] This only applies to sorting of transparent objects. This will not impact how transparent objects are sorted relative to opaque objects. This is because opaque objects are not sorted, while transparent objects are sorted from back to front (subject to priority).
</member>
<member name="shaded" type="bool" setter="set_draw_flag" getter="get_draw_flag" default="false">
If [code]true[/code], the [Light] in the [Environment] has effects on the sprite.
</member>
@ -87,7 +98,13 @@
<constant name="FLAG_DOUBLE_SIDED" value="2" enum="DrawFlags">
If set, texture can be seen from the back as well, if not, it is invisible when looking at it from behind.
</constant>
<constant name="FLAG_MAX" value="3" enum="DrawFlags">
<constant name="FLAG_DISABLE_DEPTH_TEST" value="3" enum="DrawFlags">
Disables the depth test, so this object is drawn on top of all others. However, objects drawn after it in the draw order may cover it.
</constant>
<constant name="FLAG_FIXED_SIZE" value="4" enum="DrawFlags">
Sprite is scaled by depth so that it always appears the same size on screen.
</constant>
<constant name="FLAG_MAX" value="5" enum="DrawFlags">
Represents the size of the [enum DrawFlags] enum.
</constant>
<constant name="ALPHA_CUT_DISABLED" value="0" enum="AlphaCutMode">

View File

@ -0,0 +1 @@
<svg stroke-miterlimit="10" style="fill-rule:nonzero;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:vectornator="http://vectornator.io"><path d="M6 3a1 1 0 0 0-.707.293l-4 4a1 1 0 0 0 0 1.414l4 4A1 1 0 0 0 6 13h8a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H6ZM5 7a1 1 0 1 1 0 2 1 1 0 0 1 0-2Z" fill="#fc7f7f" fill-rule="evenodd" vectornator:layerName="Untitled"/></svg>

After

Width:  |  Height:  |  Size: 453 B

View File

@ -6488,6 +6488,7 @@ void SpatialEditor::_register_all_gizmos() {
add_gizmo_plugin(Ref<MeshInstanceSpatialGizmoPlugin>(memnew(MeshInstanceSpatialGizmoPlugin)));
add_gizmo_plugin(Ref<SoftBodySpatialGizmoPlugin>(memnew(SoftBodySpatialGizmoPlugin)));
add_gizmo_plugin(Ref<Sprite3DSpatialGizmoPlugin>(memnew(Sprite3DSpatialGizmoPlugin)));
add_gizmo_plugin(Ref<Label3DSpatialGizmoPlugin>(memnew(Label3DSpatialGizmoPlugin)));
add_gizmo_plugin(Ref<SkeletonSpatialGizmoPlugin>(memnew(SkeletonSpatialGizmoPlugin)));
add_gizmo_plugin(Ref<Position3DSpatialGizmoPlugin>(memnew(Position3DSpatialGizmoPlugin)));
add_gizmo_plugin(Ref<RayCastSpatialGizmoPlugin>(memnew(RayCastSpatialGizmoPlugin)));

View File

@ -38,6 +38,7 @@
#include "scene/3d/collision_shape.h"
#include "scene/3d/cpu_particles.h"
#include "scene/3d/gi_probe.h"
#include "scene/3d/label_3d.h"
#include "scene/3d/light.h"
#include "scene/3d/listener.h"
#include "scene/3d/mesh_instance.h"
@ -1563,6 +1564,38 @@ void Sprite3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
///
Label3DSpatialGizmoPlugin::Label3DSpatialGizmoPlugin() {
}
bool Label3DSpatialGizmoPlugin::has_gizmo(Spatial *p_spatial) {
return Object::cast_to<Label3D>(p_spatial) != nullptr;
}
String Label3DSpatialGizmoPlugin::get_name() const {
return "Label3D";
}
int Label3DSpatialGizmoPlugin::get_priority() const {
return -1;
}
bool Label3DSpatialGizmoPlugin::can_be_hidden() const {
return false;
}
void Label3DSpatialGizmoPlugin::redraw(EditorSpatialGizmo *p_gizmo) {
Label3D *label = Object::cast_to<Label3D>(p_gizmo->get_spatial_node());
p_gizmo->clear();
Ref<TriangleMesh> tm = label->generate_triangle_mesh();
if (tm.is_valid()) {
p_gizmo->add_collision_triangles(tm);
}
}
///
Position3DSpatialGizmoPlugin::Position3DSpatialGizmoPlugin() {
pos3d_mesh = Ref<ArrayMesh>(memnew(ArrayMesh));
cursor_points = Vector<Vector3>();

View File

@ -126,6 +126,19 @@ public:
Sprite3DSpatialGizmoPlugin();
};
class Label3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin {
GDCLASS(Label3DSpatialGizmoPlugin, EditorSpatialGizmoPlugin);
public:
bool has_gizmo(Spatial *p_spatial);
String get_name() const;
int get_priority() const;
bool can_be_hidden() const;
void redraw(EditorSpatialGizmo *p_gizmo);
Label3DSpatialGizmoPlugin();
};
class Position3DSpatialGizmoPlugin : public EditorSpatialGizmoPlugin {
GDCLASS(Position3DSpatialGizmoPlugin, EditorSpatialGizmoPlugin);

1051
scene/3d/label_3d.cpp Normal file

File diff suppressed because it is too large Load Diff

228
scene/3d/label_3d.h Normal file
View File

@ -0,0 +1,228 @@
/*************************************************************************/
/* label_3d.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef LABEL_3D_H
#define LABEL_3D_H
#include "scene/3d/visual_instance.h"
#include "scene/resources/font.h"
class Label3D : public GeometryInstance {
GDCLASS(Label3D, GeometryInstance);
public:
enum DrawFlags {
FLAG_SHADED,
FLAG_DOUBLE_SIDED,
FLAG_DISABLE_DEPTH_TEST,
FLAG_FIXED_SIZE,
FLAG_MAX
};
enum AlphaCutMode {
ALPHA_CUT_DISABLED,
ALPHA_CUT_DISCARD,
ALPHA_CUT_OPAQUE_PREPASS
};
enum Align {
ALIGN_LEFT,
ALIGN_CENTER,
ALIGN_RIGHT,
ALIGN_FILL
};
enum VAlign {
VALIGN_TOP,
VALIGN_CENTER,
VALIGN_BOTTOM,
VALIGN_FILL
};
private:
real_t pixel_size = 0.01;
bool flags[FLAG_MAX] = {};
AlphaCutMode alpha_cut = ALPHA_CUT_DISABLED;
float alpha_scissor_threshold = 0.5;
AABB aabb;
mutable Ref<TriangleMesh> triangle_mesh;
RID mesh;
struct SurfaceData {
PoolVector3Array mesh_vertices;
PoolVector3Array mesh_normals;
PoolRealArray mesh_tangents;
PoolColorArray mesh_colors;
PoolVector2Array mesh_uvs;
PoolIntArray indices;
int offset = 0;
float z_shift = 0.0;
RID material;
};
HashMap<uint64_t, SurfaceData> surfaces;
struct WordCache {
enum {
CHAR_NEWLINE = -1,
CHAR_WRAPLINE = -2
};
int char_pos; // if -1, then newline
int word_len;
int pixel_width;
int space_count;
WordCache *next;
WordCache() {
char_pos = 0;
word_len = 0;
pixel_width = 0;
next = nullptr;
space_count = 0;
}
};
bool word_cache_dirty = true;
WordCache *word_cache = nullptr;
int line_count = 0;
Align horizontal_alignment = ALIGN_CENTER;
VAlign vertical_alignment = VALIGN_CENTER;
String text;
String xl_text;
bool uppercase = false;
bool autowrap = false;
float width = 500.0;
Ref<Font> font_override;
Color modulate = Color(1, 1, 1, 1);
Point2 lbl_offset;
int outline_render_priority = -1;
int render_priority = 0;
Color outline_modulate = Color(0, 0, 0, 1);
float line_spacing = 0.f;
RID base_material;
SpatialMaterial::BillboardMode billboard_mode = SpatialMaterial::BILLBOARD_DISABLED;
bool pending_update = false;
void regenerate_word_cache();
int get_longest_line_width() const;
float _generate_glyph_surfaces(const Ref<Font> &p_font, CharType p_char, CharType p_next, Vector2 p_offset, const Color &p_modulate, int p_priority, bool p_outline);
protected:
void _notification(int p_what);
static void _bind_methods();
void _validate_property(PropertyInfo &property) const;
void _im_update();
void _font_changed();
void _queue_update();
void _shape();
public:
void set_horizontal_alignment(Align p_alignment);
Align get_horizontal_alignment() const;
void set_vertical_alignment(VAlign p_alignment);
VAlign get_vertical_alignment() const;
void set_render_priority(int p_priority);
int get_render_priority() const;
void set_outline_render_priority(int p_priority);
int get_outline_render_priority() const;
void set_text(const String &p_string);
String get_text() const;
void set_uppercase(bool p_uppercase);
bool is_uppercase() const;
void set_font(const Ref<Font> &p_font);
Ref<Font> get_font() const;
Ref<Font> _get_font_or_default() const;
void set_line_spacing(float p_size);
float get_line_spacing() const;
void set_modulate(const Color &p_color);
Color get_modulate() const;
void set_outline_modulate(const Color &p_color);
Color get_outline_modulate() const;
void set_autowrap(bool p_mode);
bool get_autowrap() const;
void set_width(float p_width);
float get_width() const;
void set_pixel_size(real_t p_amount);
real_t get_pixel_size() const;
void set_offset(const Point2 &p_offset);
Point2 get_offset() const;
void set_draw_flag(DrawFlags p_flag, bool p_enable);
bool get_draw_flag(DrawFlags p_flag) const;
void set_alpha_cut_mode(AlphaCutMode p_mode);
AlphaCutMode get_alpha_cut_mode() const;
void set_alpha_scissor_threshold(float p_threshold);
float get_alpha_scissor_threshold() const;
void set_billboard_mode(SpatialMaterial::BillboardMode p_mode);
SpatialMaterial::BillboardMode get_billboard_mode() const;
virtual AABB get_aabb() const;
Ref<TriangleMesh> generate_triangle_mesh() const;
virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const;
Label3D();
~Label3D();
};
VARIANT_ENUM_CAST(Label3D::DrawFlags);
VARIANT_ENUM_CAST(Label3D::AlphaCutMode);
VARIANT_ENUM_CAST(Label3D::Align);
VARIANT_ENUM_CAST(Label3D::VAlign);
#endif // LABEL_3D_H

View File

@ -132,6 +132,16 @@ Color SpriteBase3D::get_modulate() const {
return modulate;
}
void SpriteBase3D::set_render_priority(int p_priority) {
ERR_FAIL_COND(p_priority < VS::MATERIAL_RENDER_PRIORITY_MIN || p_priority > VS::MATERIAL_RENDER_PRIORITY_MAX);
render_priority = p_priority;
_queue_update();
}
int SpriteBase3D::get_render_priority() const {
return render_priority;
}
void SpriteBase3D::set_pixel_size(float p_amount) {
pixel_size = p_amount;
_queue_update();
@ -296,6 +306,9 @@ void SpriteBase3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_opacity", "opacity"), &SpriteBase3D::set_opacity);
ClassDB::bind_method(D_METHOD("get_opacity"), &SpriteBase3D::get_opacity);
ClassDB::bind_method(D_METHOD("set_render_priority", "priority"), &SpriteBase3D::set_render_priority);
ClassDB::bind_method(D_METHOD("get_render_priority"), &SpriteBase3D::get_render_priority);
ClassDB::bind_method(D_METHOD("set_pixel_size", "pixel_size"), &SpriteBase3D::set_pixel_size);
ClassDB::bind_method(D_METHOD("get_pixel_size"), &SpriteBase3D::get_pixel_size);
@ -330,11 +343,16 @@ void SpriteBase3D::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transparent"), "set_draw_flag", "get_draw_flag", FLAG_TRANSPARENT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "shaded"), "set_draw_flag", "get_draw_flag", FLAG_SHADED);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "double_sided"), "set_draw_flag", "get_draw_flag", FLAG_DOUBLE_SIDED);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "no_depth_test"), "set_draw_flag", "get_draw_flag", FLAG_DISABLE_DEPTH_TEST);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "fixed_size"), "set_draw_flag", "get_draw_flag", FLAG_FIXED_SIZE);
ADD_PROPERTY(PropertyInfo(Variant::INT, "alpha_cut", PROPERTY_HINT_ENUM, "Disabled,Discard,Opaque Pre-Pass"), "set_alpha_cut_mode", "get_alpha_cut_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "render_priority", PROPERTY_HINT_RANGE, itos(VS::MATERIAL_RENDER_PRIORITY_MIN) + "," + itos(VS::MATERIAL_RENDER_PRIORITY_MAX) + ",1"), "set_render_priority", "get_render_priority");
BIND_ENUM_CONSTANT(FLAG_TRANSPARENT);
BIND_ENUM_CONSTANT(FLAG_SHADED);
BIND_ENUM_CONSTANT(FLAG_DOUBLE_SIDED);
BIND_ENUM_CONSTANT(FLAG_DISABLE_DEPTH_TEST);
BIND_ENUM_CONSTANT(FLAG_FIXED_SIZE);
BIND_ENUM_CONSTANT(FLAG_MAX);
BIND_ENUM_CONSTANT(ALPHA_CUT_DISABLED);
@ -581,9 +599,12 @@ void Sprite3D::_draw() {
VS::get_singleton()->mesh_set_custom_aabb(mesh, aabb);
set_aabb(aabb);
RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y);
RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE));
VS::get_singleton()->material_set_shader(get_material(), VS::get_singleton()->material_get_shader(mat));
VS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid());
if (get_alpha_cut_mode() == ALPHA_CUT_DISABLED) {
VS::get_singleton()->material_set_render_priority(get_material(), get_render_priority());
}
VS::get_singleton()->instance_set_surface_material(get_instance(), 0, get_material());
}
@ -924,9 +945,12 @@ void AnimatedSprite3D::_draw() {
VS::get_singleton()->mesh_set_custom_aabb(mesh, aabb);
set_aabb(aabb);
RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y);
RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE));
VS::get_singleton()->material_set_shader(get_material(), VS::get_singleton()->material_get_shader(mat));
VS::get_singleton()->material_set_param(get_material(), "texture_albedo", texture->get_rid());
if (get_alpha_cut_mode() == ALPHA_CUT_DISABLED) {
VS::get_singleton()->material_set_render_priority(get_material(), get_render_priority());
}
VS::get_singleton()->instance_set_surface_material(get_instance(), 0, get_material());
}

View File

@ -44,6 +44,8 @@ public:
FLAG_TRANSPARENT,
FLAG_SHADED,
FLAG_DOUBLE_SIDED,
FLAG_DISABLE_DEPTH_TEST,
FLAG_FIXED_SIZE,
FLAG_MAX
};
@ -69,6 +71,7 @@ private:
bool vflip;
Color modulate;
int render_priority = 0;
float opacity;
Vector3::Axis axis;
@ -121,6 +124,9 @@ public:
void set_opacity(float p_amount);
float get_opacity() const;
void set_render_priority(int p_priority);
int get_render_priority() const;
void set_pixel_size(float p_amount);
float get_pixel_size() const;

View File

@ -195,7 +195,7 @@ void Label::_notification(int p_what) {
to = to->next;
}
bool can_fill = to && to->char_pos == WordCache::CHAR_WRAPLINE;
bool can_fill = to && (to->char_pos == WordCache::CHAR_WRAPLINE || to->char_pos == WordCache::CHAR_NEWLINE);
float x_ofs = 0;

View File

@ -190,6 +190,7 @@
#include "scene/3d/gi_probe.h"
#include "scene/3d/immediate_geometry.h"
#include "scene/3d/interpolated_camera.h"
#include "scene/3d/label_3d.h"
#include "scene/3d/light.h"
#include "scene/3d/listener.h"
#include "scene/3d/mesh_instance.h"
@ -441,6 +442,7 @@ void register_scene_types() {
ClassDB::register_virtual_class<SpriteBase3D>();
ClassDB::register_class<Sprite3D>();
ClassDB::register_class<AnimatedSprite3D>();
ClassDB::register_class<Label3D>();
ClassDB::register_virtual_class<Light>();
ClassDB::register_class<DirectionalLight>();
ClassDB::register_class<OmniLight>();

View File

@ -334,6 +334,147 @@ void DynamicFontAtSize::set_texture_flags(uint32_t p_flags) {
}
}
RID DynamicFontAtSize::get_char_texture(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const {
if (!valid) {
return RID();
}
int32_t c = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
c = (p_char << 10UL) + p_next - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
}
if ((p_char & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
return RID();
}
const_cast<DynamicFontAtSize *>(this)->_update_char(c);
Pair<const Character *, DynamicFontAtSize *> char_pair_with_font = _find_char_with_font(c, p_fallbacks);
const Character *ch = char_pair_with_font.first;
DynamicFontAtSize *font = char_pair_with_font.second;
ERR_FAIL_COND_V(!ch, RID());
if (ch->found) {
ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= font->textures.size(), RID());
if (ch->texture_idx != -1) {
return font->textures[ch->texture_idx].texture->get_rid();
}
}
return RID();
}
Size2 DynamicFontAtSize::get_char_texture_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const {
if (!valid) {
return Size2();
}
int32_t c = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
c = (p_char << 10UL) + p_next - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
}
if ((p_char & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
return Size2();
}
const_cast<DynamicFontAtSize *>(this)->_update_char(c);
Pair<const Character *, DynamicFontAtSize *> char_pair_with_font = _find_char_with_font(c, p_fallbacks);
const Character *ch = char_pair_with_font.first;
DynamicFontAtSize *font = char_pair_with_font.second;
ERR_FAIL_COND_V(!ch, Size2());
if (ch->found) {
ERR_FAIL_COND_V(ch->texture_idx < -1 || ch->texture_idx >= font->textures.size(), Size2());
if (ch->texture_idx != -1) {
return font->textures[ch->texture_idx].texture->get_size();
}
}
return Size2();
}
Vector2 DynamicFontAtSize::get_char_tx_offset(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const {
if (!valid) {
return Vector2();
}
int32_t c = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
c = (p_char << 10UL) + p_next - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
}
if ((p_char & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
return Vector2();
}
const_cast<DynamicFontAtSize *>(this)->_update_char(c);
Pair<const Character *, DynamicFontAtSize *> char_pair_with_font = _find_char_with_font(c, p_fallbacks);
const Character *ch = char_pair_with_font.first;
DynamicFontAtSize *font = char_pair_with_font.second;
ERR_FAIL_COND_V(!ch, Vector2());
if (ch->found) {
Point2 cpos;
cpos.x += ch->h_align;
cpos.y -= font->get_ascent();
cpos.y += ch->v_align;
return cpos;
}
return Vector2();
}
Size2 DynamicFontAtSize::get_char_tx_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const {
if (!valid) {
return Size2();
}
int32_t c = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
c = (p_char << 10UL) + p_next - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
}
if ((p_char & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
return Size2();
}
const_cast<DynamicFontAtSize *>(this)->_update_char(c);
Pair<const Character *, DynamicFontAtSize *> char_pair_with_font = _find_char_with_font(c, p_fallbacks);
const Character *ch = char_pair_with_font.first;
ERR_FAIL_COND_V(!ch, Size2());
if (ch->found) {
return ch->rect_uv.size;
}
return Size2();
}
Rect2 DynamicFontAtSize::get_char_tx_uv_rect(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const {
if (!valid) {
return Rect2();
}
int32_t c = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
c = (p_char << 10UL) + p_next - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
}
if ((p_char & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
return Rect2();
}
const_cast<DynamicFontAtSize *>(this)->_update_char(c);
Pair<const Character *, DynamicFontAtSize *> char_pair_with_font = _find_char_with_font(c, p_fallbacks);
const Character *ch = char_pair_with_font.first;
ERR_FAIL_COND_V(!ch, Rect2());
if (ch->found) {
return ch->rect_uv;
}
return Rect2();
}
float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only, bool p_outline) const {
if (!valid) {
return 0;
@ -942,6 +1083,81 @@ bool DynamicFont::has_outline() const {
return outline_cache_id.outline_size > 0;
}
RID DynamicFont::get_char_texture(CharType p_char, CharType p_next, bool p_outline) const {
if (!data_at_size.is_valid()) {
return RID();
}
if (p_outline) {
if (outline_data_at_size.is_valid() && outline_cache_id.outline_size > 0) {
return outline_data_at_size->get_char_texture(p_char, p_next, fallback_outline_data_at_size);
}
return RID();
} else {
return data_at_size->get_char_texture(p_char, p_next, fallback_data_at_size);
}
}
Size2 DynamicFont::get_char_texture_size(CharType p_char, CharType p_next, bool p_outline) const {
if (!data_at_size.is_valid()) {
return Size2();
}
if (p_outline) {
if (outline_data_at_size.is_valid() && outline_cache_id.outline_size > 0) {
return outline_data_at_size->get_char_texture_size(p_char, p_next, fallback_outline_data_at_size);
}
return Size2();
} else {
return data_at_size->get_char_texture_size(p_char, p_next, fallback_data_at_size);
}
}
Vector2 DynamicFont::get_char_tx_offset(CharType p_char, CharType p_next, bool p_outline) const {
if (!data_at_size.is_valid()) {
return Vector2();
}
if (p_outline) {
if (outline_data_at_size.is_valid() && outline_cache_id.outline_size > 0) {
return outline_data_at_size->get_char_tx_offset(p_char, p_next, fallback_outline_data_at_size);
}
return Vector2();
} else {
return data_at_size->get_char_tx_offset(p_char, p_next, fallback_data_at_size);
}
}
Size2 DynamicFont::get_char_tx_size(CharType p_char, CharType p_next, bool p_outline) const {
if (!data_at_size.is_valid()) {
return Size2();
}
if (p_outline) {
if (outline_data_at_size.is_valid() && outline_cache_id.outline_size > 0) {
return outline_data_at_size->get_char_tx_size(p_char, p_next, fallback_outline_data_at_size);
}
return Size2();
} else {
return data_at_size->get_char_tx_size(p_char, p_next, fallback_data_at_size);
}
}
Rect2 DynamicFont::get_char_tx_uv_rect(CharType p_char, CharType p_next, bool p_outline) const {
if (!data_at_size.is_valid()) {
return Rect2();
}
if (p_outline) {
if (outline_data_at_size.is_valid() && outline_cache_id.outline_size > 0) {
return outline_data_at_size->get_char_tx_uv_rect(p_char, p_next, fallback_outline_data_at_size);
}
return Rect2();
} else {
return data_at_size->get_char_tx_uv_rect(p_char, p_next, fallback_data_at_size);
}
}
float DynamicFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, bool p_outline) const {
if (!data_at_size.is_valid()) {
return 0;

View File

@ -195,6 +195,13 @@ public:
float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks, bool p_advance_only = false, bool p_outline = false) const;
RID get_char_texture(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const;
Size2 get_char_texture_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const;
Vector2 get_char_tx_offset(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const;
Size2 get_char_tx_size(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const;
Rect2 get_char_tx_uv_rect(CharType p_char, CharType p_next, const Vector<Ref<DynamicFontAtSize>> &p_fallbacks) const;
void set_texture_flags(uint32_t p_flags);
void update_oversampling();
@ -286,6 +293,13 @@ public:
virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const;
RID get_char_texture(CharType p_char, CharType p_next, bool p_outline) const;
Size2 get_char_texture_size(CharType p_char, CharType p_next, bool p_outline) const;
Vector2 get_char_tx_offset(CharType p_char, CharType p_next, bool p_outline) const;
Size2 get_char_tx_size(CharType p_char, CharType p_next, bool p_outline) const;
Rect2 get_char_tx_uv_rect(CharType p_char, CharType p_next, bool p_outline) const;
SelfList<DynamicFont> font_list;
static Mutex dynamic_font_mutex;

View File

@ -98,6 +98,13 @@ void Font::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_wordwrap_string_size", "string", "width"), &Font::get_wordwrap_string_size);
ClassDB::bind_method(D_METHOD("has_outline"), &Font::has_outline);
ClassDB::bind_method(D_METHOD("draw_char", "canvas_item", "position", "char", "next", "modulate", "outline"), &Font::draw_char, DEFVAL(-1), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_char_texture", "char", "next", "outline"), &Font::get_char_texture, DEFVAL(0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_char_texture_size", "char", "next", "outline"), &Font::get_char_texture_size, DEFVAL(0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_char_tx_offset", "char", "next", "outline"), &Font::get_char_tx_offset, DEFVAL(0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_char_tx_size", "char", "next", "outline"), &Font::get_char_tx_size, DEFVAL(0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_char_tx_uv_rect", "char", "next", "outline"), &Font::get_char_tx_uv_rect, DEFVAL(0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("update_changes"), &Font::update_changes);
}
@ -523,6 +530,140 @@ Ref<BitmapFont> BitmapFont::get_fallback() const {
return fallback;
}
RID BitmapFont::get_char_texture(CharType p_char, CharType p_next, bool p_outline) const {
int32_t ch = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
ch = (p_char << 10UL) + p_next - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
}
if ((p_char & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
return RID();
}
const Character *c = char_map.getptr(ch);
if (!c) {
if (fallback.is_valid()) {
return fallback->get_char_texture(p_char, p_next, p_outline);
}
return RID();
}
ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), RID());
if (!p_outline && c->texture_idx != -1) {
return textures[c->texture_idx]->get_rid();
} else {
return RID();
}
}
Size2 BitmapFont::get_char_texture_size(CharType p_char, CharType p_next, bool p_outline) const {
int32_t ch = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
ch = (p_char << 10UL) + p_next - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
}
if ((p_char & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
return Size2();
}
const Character *c = char_map.getptr(ch);
if (!c) {
if (fallback.is_valid()) {
return fallback->get_char_texture_size(p_char, p_next, p_outline);
}
return Size2();
}
ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), Size2());
if (!p_outline && c->texture_idx != -1) {
return textures[c->texture_idx]->get_size();
} else {
return Size2();
}
}
Vector2 BitmapFont::get_char_tx_offset(CharType p_char, CharType p_next, bool p_outline) const {
int32_t ch = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
ch = (p_char << 10UL) + p_next - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
}
if ((p_char & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
return Vector2();
}
const Character *c = char_map.getptr(ch);
if (!c) {
if (fallback.is_valid()) {
return fallback->get_char_tx_offset(p_char, p_next, p_outline);
}
return Vector2();
}
ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), Vector2());
if (!p_outline && c->texture_idx != -1) {
Point2 cpos;
cpos.x += c->h_align;
cpos.y -= ascent;
cpos.y += c->v_align;
return cpos;
} else {
return Vector2();
}
}
Size2 BitmapFont::get_char_tx_size(CharType p_char, CharType p_next, bool p_outline) const {
int32_t ch = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
ch = (p_char << 10UL) + p_next - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
}
if ((p_char & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
return Size2();
}
const Character *c = char_map.getptr(ch);
if (!c) {
if (fallback.is_valid()) {
return fallback->get_char_tx_size(p_char, p_next, p_outline);
}
return Size2();
}
ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), Size2());
if (!p_outline && c->texture_idx != -1) {
return c->rect.size;
} else {
return Size2();
}
}
Rect2 BitmapFont::get_char_tx_uv_rect(CharType p_char, CharType p_next, bool p_outline) const {
int32_t ch = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.
ch = (p_char << 10UL) + p_next - ((0xd800 << 10UL) + 0xdc00 - 0x10000);
}
if ((p_char & 0xfffffc00) == 0xdc00) { // skip trail surrogate.
return Rect2();
}
const Character *c = char_map.getptr(ch);
if (!c) {
if (fallback.is_valid()) {
return fallback->get_char_tx_uv_rect(p_char, p_next, p_outline);
}
return Rect2();
}
ERR_FAIL_COND_V(c->texture_idx < -1 || c->texture_idx >= textures.size(), Rect2());
if (!p_outline && c->texture_idx != -1) {
return c->rect;
} else {
return Rect2();
}
}
float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next, const Color &p_modulate, bool p_outline) const {
int32_t ch = p_char;
if (((p_char & 0xfffffc00) == 0xd800) && (p_next & 0xfffffc00) == 0xdc00) { // decode surrogate pair.

View File

@ -59,6 +59,13 @@ public:
virtual bool has_outline() const { return false; }
virtual float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const = 0;
virtual RID get_char_texture(CharType p_char, CharType p_next, bool p_outline) const = 0;
virtual Size2 get_char_texture_size(CharType p_char, CharType p_next, bool p_outline) const = 0;
virtual Vector2 get_char_tx_offset(CharType p_char, CharType p_next, bool p_outline) const = 0;
virtual Size2 get_char_tx_size(CharType p_char, CharType p_next, bool p_outline) const = 0;
virtual Rect2 get_char_tx_uv_rect(CharType p_char, CharType p_next, bool p_outline) const = 0;
void update_changes();
Font();
};
@ -190,6 +197,13 @@ public:
float draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_char, CharType p_next = 0, const Color &p_modulate = Color(1, 1, 1), bool p_outline = false) const;
RID get_char_texture(CharType p_char, CharType p_next, bool p_outline) const;
Size2 get_char_texture_size(CharType p_char, CharType p_next, bool p_outline) const;
Vector2 get_char_tx_offset(CharType p_char, CharType p_next, bool p_outline) const;
Size2 get_char_tx_size(CharType p_char, CharType p_next, bool p_outline) const;
Rect2 get_char_tx_uv_rect(CharType p_char, CharType p_next, bool p_outline) const;
BitmapFont();
~BitmapFont();
};

View File

@ -347,12 +347,10 @@ void SpatialMaterial::init_shaders() {
shader_names->texture_names[TEXTURE_DETAIL_NORMAL] = "texture_detail_normal";
}
Ref<SpatialMaterial> SpatialMaterial::materials_for_2d[SpatialMaterial::MAX_MATERIALS_FOR_2D];
HashMap<uint64_t, Ref<SpatialMaterial>> SpatialMaterial::materials_for_2d;
void SpatialMaterial::finish_shaders() {
for (int i = 0; i < MAX_MATERIALS_FOR_2D; i++) {
materials_for_2d[i].unref();
}
materials_for_2d.clear();
memdelete(dirty_materials);
dirty_materials = nullptr;
@ -813,7 +811,12 @@ void SpatialMaterial::_update_shader() {
}
}
if (flags[FLAG_ALBEDO_TEXTURE_FORCE_SRGB]) {
if (flags[FLAG_ALBEDO_TEXTURE_SDF]) {
code += "\tconst float smoothing = 0.125;\n";
code += "\tfloat dist = albedo_tex.a;\n";
code += "\talbedo_tex.a = smoothstep(0.5 - smoothing, 0.5 + smoothing, dist);\n";
code += "\talbedo_tex.rgb = vec3(1.0);\n";
} else if (flags[FLAG_ALBEDO_TEXTURE_FORCE_SRGB]) {
code += "\talbedo_tex.rgb = mix(pow((albedo_tex.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)),vec3(2.4)),albedo_tex.rgb.rgb * (1.0 / 12.92),lessThan(albedo_tex.rgb,vec3(0.04045)));\n";
}
@ -1728,32 +1731,41 @@ SpatialMaterial::TextureChannel SpatialMaterial::get_refraction_texture_channel(
return refraction_texture_channel;
}
RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y) {
int version = 0;
RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y, bool p_no_depth_test, bool p_fixed_size, bool p_sdf) {
uint64_t hash = 0;
if (p_shaded) {
version = 1;
hash |= 1 << 0;
}
if (p_transparent) {
version |= 2;
hash |= 1 << 1;
}
if (p_cut_alpha) {
version |= 4;
hash |= 1 << 2;
}
if (p_opaque_prepass) {
version |= 8;
hash |= 1 << 3;
}
if (p_double_sided) {
version |= 16;
hash |= 1 << 4;
}
if (p_billboard) {
version |= 32;
hash |= 1 << 5;
}
if (p_billboard_y) {
version |= 64;
hash |= 1 << 6;
}
if (p_no_depth_test) {
hash |= 1 << 7;
}
if (p_fixed_size) {
hash |= 1 << 8;
}
if (p_sdf) {
hash |= 1 << 9;
}
if (materials_for_2d[version].is_valid()) {
return materials_for_2d[version]->get_rid();
if (materials_for_2d.has(hash)) {
return materials_for_2d[hash]->get_rid();
}
Ref<SpatialMaterial> material;
@ -1766,16 +1778,19 @@ RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent,
material->set_flag(FLAG_SRGB_VERTEX_COLOR, true);
material->set_flag(FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
material->set_flag(FLAG_USE_ALPHA_SCISSOR, p_cut_alpha);
material->set_flag(FLAG_DISABLE_DEPTH_TEST, p_no_depth_test);
material->set_flag(FLAG_FIXED_SIZE, p_fixed_size);
material->set_flag(FLAG_ALBEDO_TEXTURE_SDF, p_sdf);
if (p_billboard || p_billboard_y) {
material->set_flag(FLAG_BILLBOARD_KEEP_SCALE, true);
material->set_billboard_mode(p_billboard_y ? BILLBOARD_FIXED_Y : BILLBOARD_ENABLED);
}
materials_for_2d[version] = material;
materials_for_2d[hash] = material;
// flush before using so we can access the shader right away
flush_changes();
return materials_for_2d[version]->get_rid();
return materials_for_2d[hash]->get_rid();
}
void SpatialMaterial::set_on_top_of_alpha() {
@ -2047,6 +2062,7 @@ void SpatialMaterial::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_do_not_receive_shadows"), "set_flag", "get_flag", FLAG_DONT_RECEIVE_SHADOWS);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_disable_ambient_light"), "set_flag", "get_flag", FLAG_DISABLE_AMBIENT_LIGHT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_ensure_correct_normals"), "set_flag", "get_flag", FLAG_ENSURE_CORRECT_NORMALS);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_albedo_tex_msdf"), "set_flag", "get_flag", FLAG_ALBEDO_TEXTURE_SDF);
ADD_GROUP("Vertex Color", "vertex_color");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_use_as_albedo"), "set_flag", "get_flag", FLAG_ALBEDO_FROM_VERTEX_COLOR);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_is_srgb"), "set_flag", "get_flag", FLAG_SRGB_VERTEX_COLOR);
@ -2246,6 +2262,7 @@ void SpatialMaterial::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_DISABLE_AMBIENT_LIGHT);
BIND_ENUM_CONSTANT(FLAG_ENSURE_CORRECT_NORMALS);
BIND_ENUM_CONSTANT(FLAG_USE_SHADOW_TO_OPACITY);
BIND_ENUM_CONSTANT(FLAG_ALBEDO_TEXTURE_SDF);
BIND_ENUM_CONSTANT(FLAG_MAX);
BIND_ENUM_CONSTANT(DIFFUSE_BURLEY);

View File

@ -191,6 +191,7 @@ public:
FLAG_ENSURE_CORRECT_NORMALS,
FLAG_DISABLE_AMBIENT_LIGHT,
FLAG_USE_SHADOW_TO_OPACITY,
FLAG_ALBEDO_TEXTURE_SDF,
FLAG_MAX
};
@ -445,9 +446,7 @@ private:
_FORCE_INLINE_ void _validate_feature(const String &text, Feature feature, PropertyInfo &property) const;
static const int MAX_MATERIALS_FOR_2D = 128;
static Ref<SpatialMaterial> materials_for_2d[MAX_MATERIALS_FOR_2D]; //used by Sprite3D and other stuff
static HashMap<uint64_t, Ref<SpatialMaterial>> materials_for_2d; //used by Sprite3D and other stuff
void _validate_high_end(const String &text, PropertyInfo &property) const;
@ -635,7 +634,7 @@ public:
static void finish_shaders();
static void flush_changes();
static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false);
static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false, bool p_no_depth_test = false, bool p_fixed_size = false, bool p_sdf = false);
RID get_shader_rid() const;