Merge pull request #59109 from akien-mga/3.4-cherrypicks
This commit is contained in:
commit
1f4dda2138
|
@ -17,7 +17,7 @@
|
||||||
<argument index="2" name="out" type="Vector2" default="Vector2( 0, 0 )" />
|
<argument index="2" name="out" type="Vector2" default="Vector2( 0, 0 )" />
|
||||||
<argument index="3" name="at_position" type="int" default="-1" />
|
<argument index="3" name="at_position" type="int" default="-1" />
|
||||||
<description>
|
<description>
|
||||||
Adds a point to a curve at [code]position[/code], with control points [code]in[/code] and [code]out[/code].
|
Adds a point to a curve at [code]position[/code] relative to the [Curve2D]'s position, with control points [code]in[/code] and [code]out[/code].
|
||||||
If [code]at_position[/code] is given, the point is inserted before the point number [code]at_position[/code], moving that point (and every point after) after the inserted point. If [code]at_position[/code] is not given, or is an illegal value ([code]at_position <0[/code] or [code]at_position >= [method get_point_count][/code]), the point will be appended at the end of the point list.
|
If [code]at_position[/code] is given, the point is inserted before the point number [code]at_position[/code], moving that point (and every point after) after the inserted point. If [code]at_position[/code] is not given, or is an illegal value ([code]at_position <0[/code] or [code]at_position >= [method get_point_count][/code]), the point will be appended at the end of the point list.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<argument index="2" name="out" type="Vector3" default="Vector3( 0, 0, 0 )" />
|
<argument index="2" name="out" type="Vector3" default="Vector3( 0, 0, 0 )" />
|
||||||
<argument index="3" name="at_position" type="int" default="-1" />
|
<argument index="3" name="at_position" type="int" default="-1" />
|
||||||
<description>
|
<description>
|
||||||
Adds a point to a curve at [code]position[/code], with control points [code]in[/code] and [code]out[/code].
|
Adds a point to a curve at [code]position[/code] relative to the [Curve3D]'s position, with control points [code]in[/code] and [code]out[/code].
|
||||||
If [code]at_position[/code] is given, the point is inserted before the point number [code]at_position[/code], moving that point (and every point after) after the inserted point. If [code]at_position[/code] is not given, or is an illegal value ([code]at_position <0[/code] or [code]at_position >= [method get_point_count][/code]), the point will be appended at the end of the point list.
|
If [code]at_position[/code] is given, the point is inserted before the point number [code]at_position[/code], moving that point (and every point after) after the inserted point. If [code]at_position[/code] is not given, or is an illegal value ([code]at_position <0[/code] or [code]at_position >= [method get_point_count][/code]), the point will be appended at the end of the point list.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
|
|
@ -302,7 +302,8 @@
|
||||||
</members>
|
</members>
|
||||||
<constants>
|
<constants>
|
||||||
<constant name="BG_KEEP" value="5" enum="BGMode">
|
<constant name="BG_KEEP" value="5" enum="BGMode">
|
||||||
Keeps on screen every pixel drawn in the background. This is the fastest background mode, but it can only be safely used in fully-interior scenes (no visible sky or sky reflections). If enabled in a scene where the background is visible, "ghost trail" artifacts will be visible when moving the camera.
|
Keeps on screen every pixel drawn in the background. Only select this mode if you really need to keep the old data. On modern GPUs it will generally not be faster than clearing the background, and can be significantly slower, particularly on mobile.
|
||||||
|
It can only be safely used in fully-interior scenes (no visible sky or sky reflections). If enabled in a scene where the background is visible, "ghost trail" artifacts will be visible when moving the camera.
|
||||||
</constant>
|
</constant>
|
||||||
<constant name="BG_CLEAR_COLOR" value="0" enum="BGMode">
|
<constant name="BG_CLEAR_COLOR" value="0" enum="BGMode">
|
||||||
Clears the background using the clear color defined in [member ProjectSettings.rendering/environment/default_clear_color].
|
Clears the background using the clear color defined in [member ProjectSettings.rendering/environment/default_clear_color].
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
Height map data, pool array must be of [member map_width] * [member map_depth] size.
|
Height map data, pool array must be of [member map_width] * [member map_depth] size.
|
||||||
</member>
|
</member>
|
||||||
<member name="map_depth" type="int" setter="set_map_depth" getter="get_map_depth" default="2">
|
<member name="map_depth" type="int" setter="set_map_depth" getter="get_map_depth" default="2">
|
||||||
Depth of the height map data. Changing this will resize the [member map_data].
|
Number of vertices in the depth of the height map. Changing this will resize the [member map_data].
|
||||||
</member>
|
</member>
|
||||||
<member name="map_width" type="int" setter="set_map_width" getter="get_map_width" default="2">
|
<member name="map_width" type="int" setter="set_map_width" getter="get_map_width" default="2">
|
||||||
Width of the height map data. Changing this will resize the [member map_data].
|
Number of vertices in the width of the height map. Changing this will resize the [member map_data].
|
||||||
</member>
|
</member>
|
||||||
</members>
|
</members>
|
||||||
<constants>
|
<constants>
|
||||||
|
|
|
@ -1952,7 +1952,7 @@ void RasterizerStorageGLES2::_update_material(Material *p_material) {
|
||||||
|
|
||||||
if (p_material->shader && p_material->shader->mode == VS::SHADER_SPATIAL) {
|
if (p_material->shader && p_material->shader->mode == VS::SHADER_SPATIAL) {
|
||||||
if (p_material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
|
if (p_material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
|
||||||
(!p_material->shader->spatial.uses_alpha || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
|
(!(p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
|
||||||
can_cast_shadow = true;
|
can_cast_shadow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3153,7 +3153,7 @@ void RasterizerStorageGLES3::_update_material(Material *material) {
|
||||||
|
|
||||||
if (material->shader && material->shader->mode == VS::SHADER_SPATIAL) {
|
if (material->shader && material->shader->mode == VS::SHADER_SPATIAL) {
|
||||||
if (material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
|
if (material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
|
||||||
(!material->shader->spatial.uses_alpha || material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
|
(!(material->shader->spatial.uses_alpha && !material->shader->spatial.uses_alpha_scissor) || material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
|
||||||
can_cast_shadow = true;
|
can_cast_shadow = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1241,6 +1241,8 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref<InputEvent> &p_eve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
snap_target[0] = SNAP_TARGET_NONE;
|
||||||
|
snap_target[1] = SNAP_TARGET_NONE;
|
||||||
drag_type = DRAG_NONE;
|
drag_type = DRAG_NONE;
|
||||||
viewport->update();
|
viewport->update();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -273,7 +273,7 @@ void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const f
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSGShape::_update_shape() {
|
void CSGShape::_update_shape() {
|
||||||
if (parent || !is_inside_tree()) {
|
if (parent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,6 +296,7 @@ void CSGShape::_update_shape() {
|
||||||
ERR_CONTINUE(mat < -1 || mat >= face_count.size());
|
ERR_CONTINUE(mat < -1 || mat >= face_count.size());
|
||||||
int idx = mat == -1 ? face_count.size() - 1 : mat;
|
int idx = mat == -1 ? face_count.size() - 1 : mat;
|
||||||
|
|
||||||
|
if (n->faces[i].smooth) {
|
||||||
Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]);
|
Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]);
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
|
@ -308,6 +309,7 @@ void CSGShape::_update_shape() {
|
||||||
}
|
}
|
||||||
vec_map.set(v, add);
|
vec_map.set(v, add);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
face_count.write[idx]++;
|
face_count.write[idx]++;
|
||||||
}
|
}
|
||||||
|
@ -1577,6 +1579,9 @@ CSGBrush *CSGTorus::_build_brush() {
|
||||||
for (int i = 0; i < sides; i++) {
|
for (int i = 0; i < sides; i++) {
|
||||||
float inci = float(i) / sides;
|
float inci = float(i) / sides;
|
||||||
float inci_n = float((i + 1)) / sides;
|
float inci_n = float((i + 1)) / sides;
|
||||||
|
if (i == sides - 1) {
|
||||||
|
inci_n = 0;
|
||||||
|
}
|
||||||
|
|
||||||
float angi = inci * Math_PI * 2.0;
|
float angi = inci * Math_PI * 2.0;
|
||||||
float angi_n = inci_n * Math_PI * 2.0;
|
float angi_n = inci_n * Math_PI * 2.0;
|
||||||
|
@ -1587,6 +1592,9 @@ CSGBrush *CSGTorus::_build_brush() {
|
||||||
for (int j = 0; j < ring_sides; j++) {
|
for (int j = 0; j < ring_sides; j++) {
|
||||||
float incj = float(j) / ring_sides;
|
float incj = float(j) / ring_sides;
|
||||||
float incj_n = float((j + 1)) / ring_sides;
|
float incj_n = float((j + 1)) / ring_sides;
|
||||||
|
if (j == ring_sides - 1) {
|
||||||
|
incj_n = 0;
|
||||||
|
}
|
||||||
|
|
||||||
float angj = incj * Math_PI * 2.0;
|
float angj = incj * Math_PI * 2.0;
|
||||||
float angj_n = incj_n * Math_PI * 2.0;
|
float angj_n = incj_n * Math_PI * 2.0;
|
||||||
|
|
|
@ -3758,9 +3758,11 @@ static String get_mountpoint(const String &p_path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Error OS_X11::move_to_trash(const String &p_path) {
|
Error OS_X11::move_to_trash(const String &p_path) {
|
||||||
|
String path = p_path.rstrip("/"); // Strip trailing slash when path points to a directory
|
||||||
|
|
||||||
int err_code;
|
int err_code;
|
||||||
List<String> args;
|
List<String> args;
|
||||||
args.push_back(p_path);
|
args.push_back(path);
|
||||||
args.push_front("trash"); // The command is `gio trash <file_name>` so we need to add it to args.
|
args.push_front("trash"); // The command is `gio trash <file_name>` so we need to add it to args.
|
||||||
Error result = execute("gio", args, true, nullptr, nullptr, &err_code); // For GNOME based machines.
|
Error result = execute("gio", args, true, nullptr, nullptr, &err_code); // For GNOME based machines.
|
||||||
if (result == OK && !err_code) {
|
if (result == OK && !err_code) {
|
||||||
|
@ -3790,14 +3792,14 @@ Error OS_X11::move_to_trash(const String &p_path) {
|
||||||
|
|
||||||
// If the commands `kioclient5`, `gio` or `gvfs-trash` don't exist on the system we do it manually.
|
// If the commands `kioclient5`, `gio` or `gvfs-trash` don't exist on the system we do it manually.
|
||||||
String trash_path = "";
|
String trash_path = "";
|
||||||
String mnt = get_mountpoint(p_path);
|
String mnt = get_mountpoint(path);
|
||||||
|
|
||||||
// If there is a directory "[Mountpoint]/.Trash-[UID], use it as the trash can.
|
// If there is a directory "[Mountpoint]/.Trash-[UID], use it as the trash can.
|
||||||
if (mnt != "") {
|
if (mnt != "") {
|
||||||
String path(mnt + "/.Trash-" + itos(getuid()));
|
String mountpoint_trash_path(mnt + "/.Trash-" + itos(getuid()));
|
||||||
struct stat s;
|
struct stat s;
|
||||||
if (!stat(path.utf8().get_data(), &s)) {
|
if (!stat(mountpoint_trash_path.utf8().get_data(), &s)) {
|
||||||
trash_path = path;
|
trash_path = mountpoint_trash_path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3828,18 +3830,15 @@ Error OS_X11::move_to_trash(const String &p_path) {
|
||||||
// Issue an error if trash can is not created proprely.
|
// Issue an error if trash can is not created proprely.
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"");
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"");
|
||||||
err = dir_access->make_dir_recursive(trash_path + "/files");
|
err = dir_access->make_dir_recursive(trash_path + "/files");
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/files");
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "/files\"");
|
||||||
err = dir_access->make_dir_recursive(trash_path + "/info");
|
err = dir_access->make_dir_recursive(trash_path + "/info");
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/info");
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "/info\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
// The trash can is successfully created, now we check that we don't exceed our file name length limit.
|
// The trash can is successfully created, now we check that we don't exceed our file name length limit.
|
||||||
// If the file name is too long trim it so we can add the identifying number and ".trashinfo".
|
// If the file name is too long trim it so we can add the identifying number and ".trashinfo".
|
||||||
// Assumes that the file name length limit is 255 characters.
|
// Assumes that the file name length limit is 255 characters.
|
||||||
String file_name = p_path.get_file();
|
String file_name = path.get_file();
|
||||||
if (file_name.length() == 0) {
|
|
||||||
file_name = p_path.get_base_dir().get_file();
|
|
||||||
}
|
|
||||||
if (file_name.length() > 240) {
|
if (file_name.length() > 240) {
|
||||||
file_name = file_name.substr(0, file_name.length() - 15);
|
file_name = file_name.substr(0, file_name.length() - 15);
|
||||||
}
|
}
|
||||||
|
@ -3862,29 +3861,31 @@ Error OS_X11::move_to_trash(const String &p_path) {
|
||||||
}
|
}
|
||||||
file_name = fn;
|
file_name = fn;
|
||||||
|
|
||||||
|
String renamed_path = path.get_base_dir() + "/" + file_name;
|
||||||
|
|
||||||
// Generates the .trashinfo file
|
// Generates the .trashinfo file
|
||||||
OS::Date date = OS::get_singleton()->get_date(false);
|
OS::Date date = OS::get_singleton()->get_date(false);
|
||||||
OS::Time time = OS::get_singleton()->get_time(false);
|
OS::Time time = OS::get_singleton()->get_time(false);
|
||||||
String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, (int)date.month, date.day, time.hour, time.min);
|
String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, (int)date.month, date.day, time.hour, time.min);
|
||||||
timestamp = vformat("%s%02d", timestamp, time.sec); // vformat only supports up to 6 arguments.
|
timestamp = vformat("%s%02d", timestamp, time.sec); // vformat only supports up to 6 arguments.
|
||||||
String trash_info = "[Trash Info]\nPath=" + p_path.http_escape() + "\nDeletionDate=" + timestamp + "\n";
|
String trash_info = "[Trash Info]\nPath=" + path.http_escape() + "\nDeletionDate=" + timestamp + "\n";
|
||||||
{
|
{
|
||||||
Error err;
|
Error err;
|
||||||
FileAccessRef file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
|
FileAccessRef file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file:" + trash_path + "/info/" + file_name + ".trashinfo");
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file: \"" + trash_path + "/info/" + file_name + ".trashinfo\"");
|
||||||
file->store_string(trash_info);
|
file->store_string(trash_info);
|
||||||
file->close();
|
file->close();
|
||||||
|
|
||||||
// Rename our resource before moving it to the trash can.
|
// Rename our resource before moving it to the trash can.
|
||||||
DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||||
err = dir_access->rename(p_path, p_path.get_base_dir() + "/" + file_name);
|
err = dir_access->rename(path, renamed_path);
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + p_path + "\"");
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + path + "\" to \"" + renamed_path + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the given resource to the trash can.
|
// Move the given resource to the trash can.
|
||||||
// Do not use DirAccess:rename() because it can't move files across multiple mountpoints.
|
// Do not use DirAccess:rename() because it can't move files across multiple mountpoints.
|
||||||
List<String> mv_args;
|
List<String> mv_args;
|
||||||
mv_args.push_back(p_path.get_base_dir() + "/" + file_name);
|
mv_args.push_back(renamed_path);
|
||||||
mv_args.push_back(trash_path + "/files");
|
mv_args.push_back(trash_path + "/files");
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -3892,11 +3893,11 @@ Error OS_X11::move_to_trash(const String &p_path) {
|
||||||
|
|
||||||
// Issue an error if "mv" failed to move the given resource to the trash can.
|
// Issue an error if "mv" failed to move the given resource to the trash can.
|
||||||
if (err != OK || retval != 0) {
|
if (err != OK || retval != 0) {
|
||||||
ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_path + "/files\"");
|
ERR_PRINT("move_to_trash: Could not move the resource \"" + path + "\" to the trash can \"" + trash_path + "/files\"");
|
||||||
DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||||
err = dir_access->rename(p_path.get_base_dir() + "/" + file_name, p_path);
|
err = dir_access->rename(renamed_path, path);
|
||||||
memdelete(dir_access);
|
memdelete(dir_access);
|
||||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not rename " + p_path.get_base_dir() + "/" + file_name + " back to its original name:" + p_path);
|
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not rename \"" + renamed_path + "\" back to its original name: \"" + path + "\"");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -591,21 +591,24 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
|
||||||
draw_rect(Rect2(p_ofs.x + pofs, p_ofs.y + y, cw, lh), selection_bg);
|
draw_rect(Rect2(p_ofs.x + pofs, p_ofs.y + y, cw, lh), selection_bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_font_color_shadow.a > 0) {
|
const Color char_color = selected && override_selected_font_color ? selection_fg : fx_color;
|
||||||
|
const Color shadow_color = p_font_color_shadow * Color(1, 1, 1, char_color.a);
|
||||||
|
|
||||||
|
if (shadow_color.a > 0) {
|
||||||
const Point2 shadow_base_pos = p_ofs + Point2(align_ofs + pofs, y + lh - line_descent);
|
const Point2 shadow_base_pos = p_ofs + Point2(align_ofs + pofs, y + lh - line_descent);
|
||||||
font->draw_char(ci, shadow_base_pos + shadow_ofs + fx_offset, fx_char, c[i + 1], p_font_color_shadow);
|
font->draw_char(ci, shadow_base_pos + shadow_ofs + fx_offset, fx_char, c[i + 1], shadow_color);
|
||||||
|
|
||||||
if (p_shadow_as_outline) {
|
if (p_shadow_as_outline) {
|
||||||
font->draw_char(ci, shadow_base_pos + Vector2(-shadow_ofs.x, shadow_ofs.y) + fx_offset, fx_char, c[i + 1], p_font_color_shadow);
|
font->draw_char(ci, shadow_base_pos + Vector2(-shadow_ofs.x, shadow_ofs.y) + fx_offset, fx_char, c[i + 1], shadow_color);
|
||||||
font->draw_char(ci, shadow_base_pos + Vector2(shadow_ofs.x, -shadow_ofs.y) + fx_offset, fx_char, c[i + 1], p_font_color_shadow);
|
font->draw_char(ci, shadow_base_pos + Vector2(shadow_ofs.x, -shadow_ofs.y) + fx_offset, fx_char, c[i + 1], shadow_color);
|
||||||
font->draw_char(ci, shadow_base_pos + Vector2(-shadow_ofs.x, -shadow_ofs.y) + fx_offset, fx_char, c[i + 1], p_font_color_shadow);
|
font->draw_char(ci, shadow_base_pos + Vector2(-shadow_ofs.x, -shadow_ofs.y) + fx_offset, fx_char, c[i + 1], shadow_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
drawer.draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent), fx_char, c[i + 1], override_selected_font_color ? selection_fg : fx_color);
|
drawer.draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent), fx_char, c[i + 1], char_color);
|
||||||
} else {
|
} else {
|
||||||
cw = drawer.draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent) + fx_offset, fx_char, c[i + 1], fx_color);
|
cw = drawer.draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent) + fx_offset, fx_char, c[i + 1], char_color);
|
||||||
}
|
}
|
||||||
} else if (previously_visible && c[i] != '\t') {
|
} else if (previously_visible && c[i] != '\t') {
|
||||||
backtrack += font->get_char_size(fx_char, c[i + 1]).x;
|
backtrack += font->get_char_size(fx_char, c[i + 1]).x;
|
||||||
|
|
Loading…
Reference in New Issue