summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/camera_2d.cpp19
-rw-r--r--scene/2d/camera_2d.h1
-rw-r--r--scene/2d/line_2d.cpp6
-rw-r--r--scene/2d/node_2d.cpp3
-rw-r--r--scene/2d/polygon_2d.cpp4
-rw-r--r--scene/3d/soft_dynamic_body_3d.cpp14
-rw-r--r--scene/3d/soft_dynamic_body_3d.h4
-rw-r--r--scene/3d/voxelizer.cpp2
-rw-r--r--scene/animation/animation_tree.cpp96
-rw-r--r--scene/animation/animation_tree.h5
-rw-r--r--scene/gui/button.cpp2
-rw-r--r--scene/gui/control.cpp1
-rw-r--r--scene/gui/file_dialog.cpp8
-rw-r--r--scene/gui/file_dialog.h1
-rw-r--r--scene/gui/flow_container.cpp9
-rw-r--r--scene/gui/graph_edit.cpp2
-rw-r--r--scene/gui/item_list.cpp48
-rw-r--r--scene/gui/option_button.cpp10
-rw-r--r--scene/gui/option_button.h2
-rw-r--r--scene/gui/popup_menu.cpp64
-rw-r--r--scene/gui/rich_text_label.cpp23
-rw-r--r--scene/gui/text_edit.cpp6
-rw-r--r--scene/main/canvas_item.cpp9
-rw-r--r--scene/main/viewport.cpp33
-rw-r--r--scene/main/viewport.h4
-rw-r--r--scene/resources/default_theme/default_theme.cpp37
-rw-r--r--scene/resources/default_theme/default_theme.h2
-rw-r--r--scene/resources/font.cpp42
-rw-r--r--scene/resources/font.h8
-rw-r--r--scene/resources/resource_format_text.cpp3
-rw-r--r--scene/resources/sky_material.cpp33
-rw-r--r--scene/resources/sky_material.h8
-rw-r--r--scene/resources/texture.cpp78
33 files changed, 427 insertions, 160 deletions
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index 390e6685b1..efde8d8a2b 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -79,6 +79,7 @@ void Camera2D::set_zoom(const Vector2 &p_zoom) {
ERR_FAIL_COND_MSG(Math::is_zero_approx(p_zoom.x) || Math::is_zero_approx(p_zoom.y), "Zoom level must be different from 0 (can be negative).");
zoom = p_zoom;
+ zoom_scale = Vector2(1, 1) / zoom;
Point2 old_smoothed_camera_pos = smoothed_camera_pos;
_update_scroll();
smoothed_camera_pos = old_smoothed_camera_pos;
@@ -103,8 +104,8 @@ Transform2D Camera2D::get_camera_transform() {
if (!first) {
if (anchor_mode == ANCHOR_MODE_DRAG_CENTER) {
if (drag_horizontal_enabled && !Engine::get_singleton()->is_editor_hint() && !drag_horizontal_offset_changed) {
- camera_pos.x = MIN(camera_pos.x, (new_camera_pos.x + screen_size.x * 0.5 * zoom.x * drag_margin[SIDE_LEFT]));
- camera_pos.x = MAX(camera_pos.x, (new_camera_pos.x - screen_size.x * 0.5 * zoom.x * drag_margin[SIDE_RIGHT]));
+ camera_pos.x = MIN(camera_pos.x, (new_camera_pos.x + screen_size.x * 0.5 * zoom_scale.x * drag_margin[SIDE_LEFT]));
+ camera_pos.x = MAX(camera_pos.x, (new_camera_pos.x - screen_size.x * 0.5 * zoom_scale.x * drag_margin[SIDE_RIGHT]));
} else {
if (drag_horizontal_offset < 0) {
camera_pos.x = new_camera_pos.x + screen_size.x * 0.5 * drag_margin[SIDE_RIGHT] * drag_horizontal_offset;
@@ -116,8 +117,8 @@ Transform2D Camera2D::get_camera_transform() {
}
if (drag_vertical_enabled && !Engine::get_singleton()->is_editor_hint() && !drag_vertical_offset_changed) {
- camera_pos.y = MIN(camera_pos.y, (new_camera_pos.y + screen_size.y * 0.5 * zoom.y * drag_margin[SIDE_TOP]));
- camera_pos.y = MAX(camera_pos.y, (new_camera_pos.y - screen_size.y * 0.5 * zoom.y * drag_margin[SIDE_BOTTOM]));
+ camera_pos.y = MIN(camera_pos.y, (new_camera_pos.y + screen_size.y * 0.5 * zoom_scale.y * drag_margin[SIDE_TOP]));
+ camera_pos.y = MAX(camera_pos.y, (new_camera_pos.y - screen_size.y * 0.5 * zoom_scale.y * drag_margin[SIDE_BOTTOM]));
} else {
if (drag_vertical_offset < 0) {
@@ -133,8 +134,8 @@ Transform2D Camera2D::get_camera_transform() {
camera_pos = new_camera_pos;
}
- Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom) : Point2());
- Rect2 screen_rect(-screen_offset + camera_pos, screen_size * zoom);
+ Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom_scale) : Point2());
+ Rect2 screen_rect(-screen_offset + camera_pos, screen_size * zoom_scale);
if (limit_smoothing_enabled) {
if (screen_rect.position.x < limit[SIDE_LEFT]) {
@@ -168,14 +169,14 @@ Transform2D Camera2D::get_camera_transform() {
first = false;
}
- Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom) : Point2());
+ Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom_scale) : Point2());
real_t angle = get_global_rotation();
if (rotating) {
screen_offset = screen_offset.rotated(angle);
}
- Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom);
+ Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom_scale);
if (!smoothing_enabled || !limit_smoothing_enabled) {
if (screen_rect.position.x < limit[SIDE_LEFT]) {
@@ -202,7 +203,7 @@ Transform2D Camera2D::get_camera_transform() {
camera_screen_center = screen_rect.get_center();
Transform2D xform;
- xform.scale_basis(zoom);
+ xform.scale_basis(zoom_scale);
if (rotating) {
xform.set_rotation(angle);
}
diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h
index 662bee3612..294a6fcb80 100644
--- a/scene/2d/camera_2d.h
+++ b/scene/2d/camera_2d.h
@@ -61,6 +61,7 @@ protected:
RID canvas;
Vector2 offset;
Vector2 zoom = Vector2(1, 1);
+ Vector2 zoom_scale = Vector2(1, 1);
AnchorMode anchor_mode = ANCHOR_MODE_DRAG_CENTER;
bool rotating = false;
bool current = false;
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index 2716bb2e25..8cbcc9acf6 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -265,15 +265,15 @@ bool Line2D::get_antialiased() const {
}
void Line2D::_draw() {
- if (_points.size() <= 1 || _width == 0.f) {
+ int len = _points.size();
+ if (len <= 1 || _width == 0.f) {
return;
}
// TODO Is this really needed?
// Copy points for faster access
Vector<Vector2> points;
- points.resize(_points.size());
- int len = points.size();
+ points.resize(len);
{
const Vector2 *points_read = _points.ptr();
for (int i = 0; i < len; ++i) {
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 9d26543243..dd88bda304 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -244,10 +244,9 @@ Point2 Node2D::get_global_position() const {
}
void Node2D::set_global_position(const Point2 &p_pos) {
- Transform2D inv;
CanvasItem *pi = get_parent_item();
if (pi) {
- inv = pi->get_global_transform().affine_inverse();
+ Transform2D inv = pi->get_global_transform().affine_inverse();
set_position(inv.xform(p_pos));
} else {
set_position(p_pos);
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 1fe4adb4db..f9986c2f30 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -295,14 +295,14 @@ void Polygon2D::_notification(int p_what) {
}
Vector<Color> colors;
+ colors.resize(len);
+
if (vertex_colors.size() == points.size()) {
- colors.resize(len);
const Color *color_r = vertex_colors.ptr();
for (int i = 0; i < len; i++) {
colors.write[i] = color_r[i];
}
} else {
- colors.resize(len);
for (int i = 0; i < len; i++) {
colors.write[i] = color;
}
diff --git a/scene/3d/soft_dynamic_body_3d.cpp b/scene/3d/soft_dynamic_body_3d.cpp
index 8ee777bcbf..eafb74f203 100644
--- a/scene/3d/soft_dynamic_body_3d.cpp
+++ b/scene/3d/soft_dynamic_body_3d.cpp
@@ -417,8 +417,8 @@ void SoftDynamicBody3D::_draw_soft_mesh() {
PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh_rid);
}
- if (!rendering_server_handler.is_ready(mesh_rid)) {
- rendering_server_handler.prepare(mesh_rid, 0);
+ if (!rendering_server_handler->is_ready(mesh_rid)) {
+ rendering_server_handler->prepare(mesh_rid, 0);
/// Necessary in order to render the mesh correctly (Soft body nodes are in global space)
simulation_started = true;
@@ -428,11 +428,11 @@ void SoftDynamicBody3D::_draw_soft_mesh() {
_update_physics_server();
- rendering_server_handler.open();
- PhysicsServer3D::get_singleton()->soft_body_update_rendering_server(physics_rid, &rendering_server_handler);
- rendering_server_handler.close();
+ rendering_server_handler->open();
+ PhysicsServer3D::get_singleton()->soft_body_update_rendering_server(physics_rid, rendering_server_handler);
+ rendering_server_handler->close();
- rendering_server_handler.commit_changes();
+ rendering_server_handler->commit_changes();
}
void SoftDynamicBody3D::_prepare_physics_server() {
@@ -688,10 +688,12 @@ bool SoftDynamicBody3D::is_ray_pickable() const {
SoftDynamicBody3D::SoftDynamicBody3D() :
physics_rid(PhysicsServer3D::get_singleton()->soft_body_create()) {
+ rendering_server_handler = memnew(SoftDynamicBodyRenderingServerHandler);
PhysicsServer3D::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id());
}
SoftDynamicBody3D::~SoftDynamicBody3D() {
+ memdelete(rendering_server_handler);
PhysicsServer3D::get_singleton()->free(physics_rid);
}
diff --git a/scene/3d/soft_dynamic_body_3d.h b/scene/3d/soft_dynamic_body_3d.h
index c30ec701c7..e11e5c73df 100644
--- a/scene/3d/soft_dynamic_body_3d.h
+++ b/scene/3d/soft_dynamic_body_3d.h
@@ -36,7 +36,7 @@
class SoftDynamicBody3D;
-class SoftDynamicBodyRenderingServerHandler : public RenderingServerHandler {
+class SoftDynamicBodyRenderingServerHandler : public PhysicsServer3DRenderingServerHandler {
friend class SoftDynamicBody3D;
RID mesh;
@@ -84,7 +84,7 @@ public:
};
private:
- SoftDynamicBodyRenderingServerHandler rendering_server_handler;
+ SoftDynamicBodyRenderingServerHandler *rendering_server_handler = nullptr;
RID physics_rid;
diff --git a/scene/3d/voxelizer.cpp b/scene/3d/voxelizer.cpp
index f56e3caa4b..bda3868fbb 100644
--- a/scene/3d/voxelizer.cpp
+++ b/scene/3d/voxelizer.cpp
@@ -872,7 +872,7 @@ Vector<uint8_t> Voxelizer::get_sdf_3d_image() const {
if (d == 0) {
w[i] = 0;
} else {
- w[i] = MIN(d, 254) + 1;
+ w[i] = MIN(d, 254u) + 1;
}
}
}
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index e0e94d8632..309c2b5245 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -273,10 +273,6 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri
}
}
- if (!p_seek && p_optimize && !any_valid) { //pointless to go on, all are zero
- return 0;
- }
-
String new_path;
AnimationNode *new_parent;
@@ -289,6 +285,10 @@ double AnimationNode::_blend_node(const StringName &p_subpath, const Vector<Stri
new_parent = parent;
new_path = String(parent->base_path) + String(p_subpath) + "/";
}
+
+ if (!p_seek && p_optimize && !any_valid) {
+ return p_node->_pre_process(new_path, new_parent, state, 0, p_seek, p_connections);
+ }
return p_node->_pre_process(new_path, new_parent, state, p_time, p_seek, p_connections);
}
@@ -618,6 +618,11 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
int bone_idx = sk->find_bone(path.get_subname(0));
if (bone_idx != -1) {
track_xform->bone_idx = bone_idx;
+ Transform3D rest = sk->get_bone_rest(bone_idx);
+ track_xform->init_loc = rest.origin;
+ track_xform->ref_rot = rest.basis.get_rotation_quaternion();
+ track_xform->init_rot = track_xform->ref_rot.log();
+ track_xform->init_scale = rest.basis.get_scale();
}
}
@@ -644,7 +649,6 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) {
} break;
case Animation::TYPE_BLEND_SHAPE: {
#ifndef _3D_DISABLED
-
if (path.get_subname_count() != 1) {
ERR_PRINT("AnimationTree: '" + String(E) + "', blend shape track does not contain a blend shape subname: '" + String(path) + "'");
continue;
@@ -942,23 +946,16 @@ void AnimationTree::_process_graph(double p_delta) {
real_t blend = (*as.track_blends)[blend_idx] * weight;
- if (blend < CMP_EPSILON) {
- continue; //nothing to blend
- }
-
switch (ttype) {
case Animation::TYPE_POSITION_3D: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
-
if (t->process_pass != process_pass) {
t->process_pass = process_pass;
- t->loc = Vector3();
- t->rot = Quaternion();
- t->rot_blend_accum = 0;
- t->scale = Vector3(1, 1, 1);
+ t->loc = t->init_loc;
+ t->rot = t->init_rot;
+ t->scale = t->init_scale;
}
-
if (track->root_motion) {
double prev_time = time - delta;
if (!backward) {
@@ -1036,22 +1033,19 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
- t->loc = t->loc.lerp(loc, blend);
+ t->loc += (loc - t->init_loc) * blend;
}
#endif // _3D_DISABLED
} break;
case Animation::TYPE_ROTATION_3D: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
-
if (t->process_pass != process_pass) {
t->process_pass = process_pass;
- t->loc = Vector3();
- t->rot = Quaternion();
- t->rot_blend_accum = 0;
- t->scale = Vector3(1, 1, 1);
+ t->loc = t->init_loc;
+ t->rot = t->init_rot;
+ t->scale = t->init_scale;
}
-
if (track->root_motion) {
double prev_time = time - delta;
if (!backward) {
@@ -1097,8 +1091,7 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
a->rotation_track_interpolate(i, (double)a->get_length(), &rot[1]);
- Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
- t->rot = (t->rot * q).normalized();
+ t->rot += (rot[1].log() - rot[0].log()) * blend;
prev_time = 0;
}
} else {
@@ -1108,8 +1101,7 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
a->rotation_track_interpolate(i, 0, &rot[1]);
- Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
- t->rot = (t->rot * q).normalized();
+ t->rot += (rot[1].log() - rot[0].log()) * blend;
prev_time = 0;
}
}
@@ -1120,8 +1112,7 @@ void AnimationTree::_process_graph(double p_delta) {
}
a->rotation_track_interpolate(i, time, &rot[1]);
- Quaternion q = Quaternion().slerp(rot[0].normalized().inverse() * rot[1].normalized(), blend).normalized();
- t->rot = (t->rot * q).normalized();
+ t->rot += (rot[1].log() - rot[0].log()) * blend;
prev_time = !backward ? 0 : (double)a->get_length();
} else {
@@ -1132,29 +1123,22 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
- if (t->rot_blend_accum == 0) {
- t->rot = rot;
- t->rot_blend_accum = blend;
- } else {
- real_t rot_total = t->rot_blend_accum + blend;
- t->rot = rot.slerp(t->rot, t->rot_blend_accum / rot_total).normalized();
- t->rot_blend_accum = rot_total;
+ if (signbit(rot.dot(t->ref_rot))) {
+ rot = -rot;
}
+ t->rot += (rot.log() - t->init_rot) * blend;
}
#endif // _3D_DISABLED
} break;
case Animation::TYPE_SCALE_3D: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
-
if (t->process_pass != process_pass) {
t->process_pass = process_pass;
- t->loc = Vector3();
- t->rot = Quaternion();
- t->rot_blend_accum = 0;
- t->scale = Vector3(1, 1, 1);
+ t->loc = t->init_loc;
+ t->rot = t->init_rot;
+ t->scale = t->init_scale;
}
-
if (track->root_motion) {
double prev_time = time - delta;
if (!backward) {
@@ -1232,7 +1216,7 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
- t->scale = t->scale.lerp(scale, blend);
+ t->scale += (scale - t->init_scale) * blend;
}
#endif // _3D_DISABLED
} break;
@@ -1254,7 +1238,7 @@ void AnimationTree::_process_graph(double p_delta) {
continue;
}
- t->value = Math::lerp(t->value, value, (float)blend);
+ t->value += value * blend;
#endif // _3D_DISABLED
} break;
case Animation::TYPE_VALUE: {
@@ -1271,13 +1255,16 @@ void AnimationTree::_process_graph(double p_delta) {
}
if (t->process_pass != process_pass) {
- t->value = value;
t->process_pass = process_pass;
+ t->value = value;
+ t->value.zero();
}
- Variant::interpolate(t->value, value, blend, t->value);
-
+ Variant::blend(t->value, value, blend, t->value);
} else {
+ if (blend < CMP_EPSILON) {
+ continue; //nothing to blend
+ }
List<int> indices;
a->value_track_get_key_indices(i, time, delta, &indices, pingponged);
@@ -1289,7 +1276,10 @@ void AnimationTree::_process_graph(double p_delta) {
} break;
case Animation::TYPE_METHOD: {
- if (delta == 0) {
+ if (blend < CMP_EPSILON) {
+ continue; //nothing to blend
+ }
+ if (!seeked && Math::is_zero_approx(delta)) {
continue;
}
TrackCacheMethod *t = static_cast<TrackCacheMethod *>(track);
@@ -1312,14 +1302,16 @@ void AnimationTree::_process_graph(double p_delta) {
real_t bezier = a->bezier_track_interpolate(i, time);
if (t->process_pass != process_pass) {
- t->value = bezier;
t->process_pass = process_pass;
+ t->value = 0;
}
- t->value = Math::lerp(t->value, bezier, blend);
-
+ t->value += bezier * blend;
} break;
case Animation::TYPE_AUDIO: {
+ if (blend < CMP_EPSILON) {
+ continue; //nothing to blend
+ }
TrackCacheAudio *t = static_cast<TrackCacheAudio *>(track);
if (seeked) {
@@ -1431,6 +1423,9 @@ void AnimationTree::_process_graph(double p_delta) {
}
} break;
case Animation::TYPE_ANIMATION: {
+ if (blend < CMP_EPSILON) {
+ continue; //nothing to blend
+ }
TrackCacheAnimation *t = static_cast<TrackCacheAnimation *>(track);
AnimationPlayer *player2 = Object::cast_to<AnimationPlayer>(t->object);
@@ -1521,6 +1516,7 @@ void AnimationTree::_process_graph(double p_delta) {
case Animation::TYPE_POSITION_3D: {
#ifndef _3D_DISABLED
TrackCacheTransform *t = static_cast<TrackCacheTransform *>(track);
+ t->rot = t->rot.exp();
if (t->root_motion) {
Transform3D xform;
diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h
index 705ee91c76..3ccb6be073 100644
--- a/scene/animation/animation_tree.h
+++ b/scene/animation/animation_tree.h
@@ -197,9 +197,12 @@ private:
bool loc_used = false;
bool rot_used = false;
bool scale_used = false;
+ Vector3 init_loc = Vector3(0, 0, 0);
+ Quaternion ref_rot = Quaternion(0, 0, 0, 1);
+ Quaternion init_rot = Quaternion(0, 0, 0, 0);
+ Vector3 init_scale = Vector3(1, 1, 1);
Vector3 loc;
Quaternion rot;
- real_t rot_blend_accum = 0.0;
Vector3 scale;
TrackCacheTransform() {
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 724714b93b..29a0681f9c 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -293,7 +293,7 @@ void Button::_notification(int p_what) {
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;
+ int text_width = MAX(1, clip_text ? MIN(text_clip, text_buf->get_size().x) : text_buf->get_size().x);
if (_internal_margin[SIDE_LEFT] > 0) {
text_clip -= _internal_margin[SIDE_LEFT] + get_theme_constant(SNAME("hseparation"));
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index d8659b1f18..d2d1b5e9b7 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -3224,6 +3224,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size);
ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_parent_area_size);
ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position);
+ ClassDB::bind_method(D_METHOD("get_screen_position"), &Control::get_screen_position);
ClassDB::bind_method(D_METHOD("get_rect"), &Control::get_rect);
ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect);
ClassDB::bind_method(D_METHOD("set_focus_mode", "mode"), &Control::set_focus_mode);
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 678229683f..e71ab64535 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -176,7 +176,7 @@ void FileDialog::update_dir() {
if (dir_access->get_current_dir().is_network_share_path()) {
_update_drives(false);
drives->add_item(RTR("Network"));
- drives->set_item_disabled(drives->get_item_count() - 1, true);
+ drives->set_item_disabled(-1, true);
drives->select(drives->get_item_count() - 1);
} else {
drives->select(dir_access->get_current_drive());
@@ -919,9 +919,9 @@ void FileDialog::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir"), "set_current_dir", "get_current_dir");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file"), "set_current_file", "get_current_file");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path"), "set_current_path", "get_current_path");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR, "", PROPERTY_USAGE_NONE), "set_current_dir", "get_current_dir");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file", PROPERTY_HINT_FILE, "*", PROPERTY_USAGE_NONE), "set_current_file", "get_current_file");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_current_path", "get_current_path");
ADD_SIGNAL(MethodInfo("file_selected", PropertyInfo(Variant::STRING, "path")));
ADD_SIGNAL(MethodInfo("files_selected", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths")));
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 36a6b262b0..7a50efe40f 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -70,7 +70,6 @@ private:
Button *makedir;
Access access = ACCESS_RESOURCES;
- //Button *action;
VBoxContainer *vbox;
FileMode mode;
LineEdit *dir;
diff --git a/scene/gui/flow_container.cpp b/scene/gui/flow_container.cpp
index 3bd21f96b2..40aca555db 100644
--- a/scene/gui/flow_container.cpp
+++ b/scene/gui/flow_container.cpp
@@ -39,6 +39,11 @@ struct _LineData {
};
void FlowContainer::_resort() {
+ // Avoid resorting if invisible.
+ if (!is_visible_in_tree()) {
+ return;
+ }
+
int separation_horizontal = get_theme_constant(SNAME("hseparation"));
int separation_vertical = get_theme_constant(SNAME("vseparation"));
@@ -58,7 +63,7 @@ void FlowContainer::_resort() {
// First pass for line wrapping and minimum size calculation.
for (int i = 0; i < get_child_count(); i++) {
Control *child = Object::cast_to<Control>(get_child(i));
- if (!child || !child->is_visible_in_tree()) {
+ if (!child || !child->is_visible()) {
continue;
}
if (child->is_set_as_top_level()) {
@@ -128,7 +133,7 @@ void FlowContainer::_resort() {
for (int i = 0; i < get_child_count(); i++) {
Control *child = Object::cast_to<Control>(get_child(i));
- if (!child || !child->is_visible_in_tree()) {
+ if (!child || !child->is_visible()) {
continue;
}
if (child->is_set_as_top_level()) {
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index ab21c747cf..1394b4192f 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -1170,7 +1170,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) {
if (connecting) {
force_connection_drag_end();
} else {
- emit_signal(SNAME("popup_request"), get_screen_position() + b->get_position());
+ emit_signal(SNAME("popup_request"), b->get_position());
}
}
}
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index e83524b06c..8c0f696a9f 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -83,6 +83,9 @@ int ItemList::add_icon_item(const Ref<Texture2D> &p_item, bool p_selectable) {
}
void ItemList::set_item_text(int p_idx, const String &p_text) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].text = p_text;
@@ -97,6 +100,9 @@ String ItemList::get_item_text(int p_idx) const {
}
void ItemList::set_item_text_direction(int p_idx, Control::TextDirection p_text_direction) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
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) {
@@ -119,6 +125,9 @@ void ItemList::clear_item_opentype_features(int p_idx) {
}
void ItemList::set_item_opentype_feature(int p_idx, const String &p_name, int p_value) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
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) {
@@ -138,6 +147,9 @@ int ItemList::get_item_opentype_feature(int p_idx, const String &p_name) const {
}
void ItemList::set_item_language(int p_idx, const String &p_language) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
if (items[p_idx].language != p_language) {
items.write[p_idx].language = p_language;
@@ -152,6 +164,9 @@ String ItemList::get_item_language(int p_idx) const {
}
void ItemList::set_item_tooltip_enabled(int p_idx, const bool p_enabled) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].tooltip_enabled = p_enabled;
}
@@ -162,6 +177,9 @@ bool ItemList::is_item_tooltip_enabled(int p_idx) const {
}
void ItemList::set_item_tooltip(int p_idx, const String &p_tooltip) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].tooltip = p_tooltip;
@@ -175,6 +193,9 @@ String ItemList::get_item_tooltip(int p_idx) const {
}
void ItemList::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].icon = p_icon;
@@ -189,6 +210,9 @@ Ref<Texture2D> ItemList::get_item_icon(int p_idx) const {
}
void ItemList::set_item_icon_transposed(int p_idx, const bool p_transposed) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].icon_transposed = p_transposed;
@@ -203,6 +227,9 @@ bool ItemList::is_item_icon_transposed(int p_idx) const {
}
void ItemList::set_item_icon_region(int p_idx, const Rect2 &p_region) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].icon_region = p_region;
@@ -217,6 +244,9 @@ Rect2 ItemList::get_item_icon_region(int p_idx) const {
}
void ItemList::set_item_icon_modulate(int p_idx, const Color &p_modulate) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].icon_modulate = p_modulate;
@@ -230,6 +260,9 @@ Color ItemList::get_item_icon_modulate(int p_idx) const {
}
void ItemList::set_item_custom_bg_color(int p_idx, const Color &p_custom_bg_color) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].custom_bg = p_custom_bg_color;
@@ -243,6 +276,9 @@ Color ItemList::get_item_custom_bg_color(int p_idx) const {
}
void ItemList::set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_color) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].custom_fg = p_custom_fg_color;
@@ -256,6 +292,9 @@ Color ItemList::get_item_custom_fg_color(int p_idx) const {
}
void ItemList::set_item_tag_icon(int p_idx, const Ref<Texture2D> &p_tag_icon) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].tag_icon = p_tag_icon;
@@ -270,6 +309,9 @@ Ref<Texture2D> ItemList::get_item_tag_icon(int p_idx) const {
}
void ItemList::set_item_selectable(int p_idx, bool p_selectable) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].selectable = p_selectable;
@@ -281,6 +323,9 @@ bool ItemList::is_item_selectable(int p_idx) const {
}
void ItemList::set_item_disabled(int p_idx, bool p_disabled) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].disabled = p_disabled;
@@ -293,6 +338,9 @@ bool ItemList::is_item_disabled(int p_idx) const {
}
void ItemList::set_item_metadata(int p_idx, const Variant &p_metadata) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].metadata = p_metadata;
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index b3804e73d9..37d75cea6a 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -240,6 +240,10 @@ void OptionButton::set_item_metadata(int p_idx, const Variant &p_metadata) {
popup->set_item_metadata(p_idx, p_metadata);
}
+void OptionButton::set_item_tooltip(int p_idx, const String &p_tooltip) {
+ popup->set_item_tooltip(p_idx, p_tooltip);
+}
+
void OptionButton::set_item_disabled(int p_idx, bool p_disabled) {
popup->set_item_disabled(p_idx, p_disabled);
}
@@ -268,6 +272,10 @@ Variant OptionButton::get_item_metadata(int p_idx) const {
return popup->get_item_metadata(p_idx);
}
+String OptionButton::get_item_tooltip(int p_idx) const {
+ return popup->get_item_tooltip(p_idx);
+}
+
bool OptionButton::is_item_disabled(int p_idx) const {
return popup->is_item_disabled(p_idx);
}
@@ -385,11 +393,13 @@ void OptionButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_disabled", "idx", "disabled"), &OptionButton::set_item_disabled);
ClassDB::bind_method(D_METHOD("set_item_id", "idx", "id"), &OptionButton::set_item_id);
ClassDB::bind_method(D_METHOD("set_item_metadata", "idx", "metadata"), &OptionButton::set_item_metadata);
+ ClassDB::bind_method(D_METHOD("set_item_tooltip", "idx", "tooltip"), &OptionButton::set_item_tooltip);
ClassDB::bind_method(D_METHOD("get_item_text", "idx"), &OptionButton::get_item_text);
ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &OptionButton::get_item_icon);
ClassDB::bind_method(D_METHOD("get_item_id", "idx"), &OptionButton::get_item_id);
ClassDB::bind_method(D_METHOD("get_item_index", "id"), &OptionButton::get_item_index);
ClassDB::bind_method(D_METHOD("get_item_metadata", "idx"), &OptionButton::get_item_metadata);
+ ClassDB::bind_method(D_METHOD("get_item_tooltip", "idx"), &OptionButton::get_item_tooltip);
ClassDB::bind_method(D_METHOD("is_item_disabled", "idx"), &OptionButton::is_item_disabled);
ClassDB::bind_method(D_METHOD("add_separator"), &OptionButton::add_separator);
ClassDB::bind_method(D_METHOD("clear"), &OptionButton::clear);
diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h
index 5352fe18a6..0a3c8cdb17 100644
--- a/scene/gui/option_button.h
+++ b/scene/gui/option_button.h
@@ -68,6 +68,7 @@ public:
void set_item_id(int p_idx, int p_id);
void set_item_metadata(int p_idx, const Variant &p_metadata);
void set_item_disabled(int p_idx, bool p_disabled);
+ void set_item_tooltip(int p_idx, const String &p_tooltip);
String get_item_text(int p_idx) const;
Ref<Texture2D> get_item_icon(int p_idx) const;
@@ -75,6 +76,7 @@ public:
int get_item_index(int p_id) const;
Variant get_item_metadata(int p_idx) const;
bool is_item_disabled(int p_idx) const;
+ String get_item_tooltip(int p_idx) const;
void set_item_count(int p_count);
int get_item_count() const;
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 840c3d5c31..9fc1fb072c 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -999,9 +999,16 @@ void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu,
/* Methods to modify existing items. */
void PopupMenu::set_item_text(int p_idx, const String &p_text) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
+ if (items[p_idx].text == p_text) {
+ return;
+ }
items.write[p_idx].text = p_text;
items.write[p_idx].xl_text = atr(p_text);
+ items.write[p_idx].dirty = true;
_shape_item(p_idx);
control->update();
@@ -1009,6 +1016,9 @@ void PopupMenu::set_item_text(int p_idx, const String &p_text) {
}
void PopupMenu::set_item_text_direction(int p_item, Control::TextDirection p_text_direction) {
+ if (p_item < 0) {
+ p_item += get_item_count();
+ }
ERR_FAIL_INDEX(p_item, items.size());
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
if (items[p_item].text_direction != p_text_direction) {
@@ -1019,6 +1029,9 @@ void PopupMenu::set_item_text_direction(int p_item, Control::TextDirection p_tex
}
void PopupMenu::clear_item_opentype_features(int p_item) {
+ if (p_item < 0) {
+ p_item += get_item_count();
+ }
ERR_FAIL_INDEX(p_item, items.size());
items.write[p_item].opentype_features.clear();
items.write[p_item].dirty = true;
@@ -1026,6 +1039,9 @@ void PopupMenu::clear_item_opentype_features(int p_item) {
}
void PopupMenu::set_item_opentype_feature(int p_item, const String &p_name, int p_value) {
+ if (p_item < 0) {
+ p_item += get_item_count();
+ }
ERR_FAIL_INDEX(p_item, items.size());
int32_t tag = TS->name_to_tag(p_name);
if (!items[p_item].opentype_features.has(tag) || (int)items[p_item].opentype_features[tag] != p_value) {
@@ -1036,6 +1052,9 @@ void PopupMenu::set_item_opentype_feature(int p_item, const String &p_name, int
}
void PopupMenu::set_item_language(int p_item, const String &p_language) {
+ if (p_item < 0) {
+ p_item += get_item_count();
+ }
ERR_FAIL_INDEX(p_item, items.size());
if (items[p_item].language != p_language) {
items.write[p_item].language = p_language;
@@ -1045,6 +1064,9 @@ void PopupMenu::set_item_language(int p_item, const String &p_language) {
}
void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].icon = p_icon;
@@ -1053,6 +1075,9 @@ void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
}
void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].checked = p_checked;
@@ -1062,6 +1087,9 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
}
void PopupMenu::set_item_id(int p_idx, int p_id) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].id = p_id;
@@ -1070,6 +1098,9 @@ void PopupMenu::set_item_id(int p_idx, int p_id) {
}
void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].accel = p_accel;
items.write[p_idx].dirty = true;
@@ -1079,6 +1110,9 @@ void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) {
}
void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].metadata = p_meta;
control->update();
@@ -1086,6 +1120,9 @@ void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) {
}
void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].disabled = p_disabled;
control->update();
@@ -1093,6 +1130,9 @@ void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) {
}
void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].submenu = p_submenu;
control->update();
@@ -1201,6 +1241,9 @@ int PopupMenu::get_item_state(int p_idx) const {
}
void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].separator = p_separator;
control->update();
@@ -1212,24 +1255,36 @@ bool PopupMenu::is_item_separator(int p_idx) const {
}
void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE;
control->update();
}
void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE;
control->update();
}
void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].tooltip = p_tooltip;
control->update();
}
void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bool p_global) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
if (items[p_idx].shortcut.is_valid()) {
_unref_shortcut(items[p_idx].shortcut);
@@ -1246,6 +1301,9 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bo
}
void PopupMenu::set_item_h_offset(int p_idx, int p_offset) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].h_ofs = p_offset;
control->update();
@@ -1253,12 +1311,18 @@ void PopupMenu::set_item_h_offset(int p_idx, int p_offset) {
}
void PopupMenu::set_item_multistate(int p_idx, int p_state) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].state = p_state;
control->update();
}
void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) {
+ if (p_idx < 0) {
+ p_idx += get_item_count();
+ }
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].shortcut_is_disabled = p_disabled;
control->update();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index bad7be7d42..0a36176c98 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -902,9 +902,10 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
for (int i = 0; i < gl_size; i++) {
Item *it = _get_item_at_pos(it_from, it_to, glyphs[i].start);
int size = _find_outline_size(it, p_outline_size);
- Color font_color = _find_outline_color(it, p_outline_color);
+ Color font_color = _find_color(it, p_base_color);
+ Color font_outline_color = _find_outline_color(it, p_outline_color);
Color font_shadow_color = p_font_shadow_color;
- if ((size <= 0 || font_color.a == 0) && (font_shadow_color.a == 0)) {
+ if ((size <= 0 || font_outline_color.a == 0) && (font_shadow_color.a == 0)) {
gloff.x += glyphs[i].advance;
continue;
}
@@ -950,11 +951,11 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
faded_visibility -= (float)(glyphs[i].start - fade->starting_index) / (float)fade->length;
faded_visibility = faded_visibility < 0.0f ? 0.0f : faded_visibility;
}
- font_color.a = faded_visibility;
+ font_outline_color.a = faded_visibility;
font_shadow_color.a = faded_visibility;
}
- bool visible = (font_color.a != 0) || (font_shadow_color.a != 0);
+ bool visible = (font_outline_color.a != 0) || (font_shadow_color.a != 0);
for (int j = 0; j < fx_stack.size(); j++) {
ItemFX *item_fx = fx_stack[j];
@@ -1024,18 +1025,20 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o
}
// Draw glyph outlines.
+ const Color modulated_outline_color = font_outline_color * Color(1, 1, 1, font_color.a);
+ const Color modulated_shadow_color = font_shadow_color * Color(1, 1, 1, font_color.a);
for (int j = 0; j < glyphs[i].repeat; j++) {
if (visible) {
bool skip = (trim_chars && l.char_offset + glyphs[i].end > visible_characters) || (trim_glyphs_ltr && (processed_glyphs_ol >= visible_glyphs)) || (trim_glyphs_rtl && (processed_glyphs_ol < total_glyphs - visible_glyphs));
if (!skip && frid != RID()) {
- if (font_shadow_color.a > 0) {
- TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, font_shadow_color);
+ if (modulated_shadow_color.a > 0) {
+ TS->font_draw_glyph(frid, ci, glyphs[i].font_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, modulated_shadow_color);
}
- if (font_shadow_color.a > 0 && p_shadow_outline_size > 0) {
- TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, p_shadow_outline_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, font_shadow_color);
+ if (modulated_shadow_color.a > 0 && p_shadow_outline_size > 0) {
+ TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, p_shadow_outline_size, p_ofs + fx_offset + gloff + p_shadow_ofs, gl, modulated_shadow_color);
}
- if (font_color.a != 0.0 && size > 0) {
- TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff, gl, font_color);
+ if (modulated_outline_color.a != 0.0 && size > 0) {
+ TS->font_draw_glyph_outline(frid, ci, glyphs[i].font_size, size, p_ofs + fx_offset + gloff, gl, modulated_outline_color);
}
}
processed_glyphs_ol++;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 05fda7128c..3c80e3f987 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -4469,7 +4469,11 @@ int TextEdit::get_visible_line_count() const {
int TextEdit::get_visible_line_count_in_range(int p_from_line, int p_to_line) const {
ERR_FAIL_INDEX_V(p_from_line, text.size(), 0);
ERR_FAIL_INDEX_V(p_to_line, text.size(), 0);
- ERR_FAIL_COND_V(p_from_line > p_to_line, 0);
+
+ // So we can handle inputs in whatever order
+ if (p_from_line > p_to_line) {
+ SWAP(p_from_line, p_to_line);
+ }
/* Returns the total number of (lines + wrapped - hidden). */
if (!_is_hiding_enabled() && get_line_wrapping_mode() == LineWrappingMode::LINE_WRAPPING_NONE) {
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index d2f5b52dbf..ec0821557b 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -866,7 +866,6 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_on_top", "on_top"), &CanvasItem::_set_on_top);
ClassDB::bind_method(D_METHOD("_is_on_top"), &CanvasItem::_is_on_top);
- //ClassDB::bind_method(D_METHOD("get_transform"),&CanvasItem::get_transform);
ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width"), &CanvasItem::draw_line, DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false));
@@ -899,6 +898,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_viewport_transform"), &CanvasItem::get_viewport_transform);
ClassDB::bind_method(D_METHOD("get_viewport_rect"), &CanvasItem::get_viewport_rect);
ClassDB::bind_method(D_METHOD("get_canvas_transform"), &CanvasItem::get_canvas_transform);
+ ClassDB::bind_method(D_METHOD("get_screen_transform"), &CanvasItem::get_screen_transform);
ClassDB::bind_method(D_METHOD("get_local_mouse_position"), &CanvasItem::get_local_mouse_position);
ClassDB::bind_method(D_METHOD("get_global_mouse_position"), &CanvasItem::get_global_mouse_position);
ClassDB::bind_method(D_METHOD("get_canvas"), &CanvasItem::get_canvas);
@@ -995,12 +995,7 @@ Transform2D CanvasItem::get_viewport_transform() const {
ERR_FAIL_COND_V(!is_inside_tree(), Transform2D());
if (canvas_layer) {
- if (get_viewport()) {
- return get_viewport()->get_final_transform() * canvas_layer->get_transform();
- } else {
- return canvas_layer->get_transform();
- }
-
+ return get_viewport()->get_final_transform() * canvas_layer->get_transform();
} else {
return get_viewport()->get_final_transform() * get_viewport()->get_canvas_transform();
}
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index de6aa2b139..ec33e5752e 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -2033,6 +2033,17 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
}
+void Viewport::_gui_cleanup_internal_state(Ref<InputEvent> p_event) {
+ ERR_FAIL_COND(p_event.is_null());
+
+ Ref<InputEventMouseButton> mb = p_event;
+ if (mb.is_valid()) {
+ if (!mb->is_pressed()) {
+ gui.mouse_focus_mask &= ~mouse_button_to_mask(mb->get_button_index()); // Remove from mask.
+ }
+ }
+}
+
List<Control *>::Element *Viewport::_gui_add_root_control(Control *p_control) {
gui.roots_order_dirty = true;
return gui.roots.push_back(p_control);
@@ -2695,6 +2706,9 @@ void Viewport::push_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
if (!is_input_handled()) {
_gui_input_event(ev);
+ } else {
+ // Cleanup internal GUI state after accepting event during _input().
+ _gui_cleanup_internal_state(ev);
}
event_count++;
@@ -2768,6 +2782,14 @@ Vector2 Viewport::get_camera_rect_size() const {
}
void Viewport::set_disable_input(bool p_disable) {
+ if (p_disable == disable_input) {
+ return;
+ }
+ if (p_disable) {
+ _drop_mouse_focus();
+ _drop_mouse_over();
+ _gui_cancel_tooltip();
+ }
disable_input = p_disable;
}
@@ -3040,14 +3062,10 @@ Viewport *Viewport::get_parent_viewport() const {
return get_parent()->get_viewport();
}
-void Viewport::set_embed_subwindows_hint(bool p_embed) {
+void Viewport::set_embedding_subwindows(bool p_embed) {
gui.embed_subwindows_hint = p_embed;
}
-bool Viewport::get_embed_subwindows_hint() const {
- return gui.embed_subwindows_hint;
-}
-
bool Viewport::is_embedding_subwindows() const {
return gui.embed_subwindows_hint;
}
@@ -3638,8 +3656,7 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_filter", "mode"), &Viewport::set_default_canvas_item_texture_filter);
ClassDB::bind_method(D_METHOD("get_default_canvas_item_texture_filter"), &Viewport::get_default_canvas_item_texture_filter);
- ClassDB::bind_method(D_METHOD("set_embed_subwindows_hint", "enable"), &Viewport::set_embed_subwindows_hint);
- ClassDB::bind_method(D_METHOD("get_embed_subwindows_hint"), &Viewport::get_embed_subwindows_hint);
+ ClassDB::bind_method(D_METHOD("set_embedding_subwindows", "enable"), &Viewport::set_embedding_subwindows);
ClassDB::bind_method(D_METHOD("is_embedding_subwindows"), &Viewport::is_embedding_subwindows);
ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_repeat", "mode"), &Viewport::set_default_canvas_item_texture_repeat);
@@ -3721,7 +3738,7 @@ void Viewport::_bind_methods() {
ADD_GROUP("GUI", "gui_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_embed_subwindows"), "set_embed_subwindows_hint", "get_embed_subwindows_hint");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_embed_subwindows"), "set_embedding_subwindows", "is_embedding_subwindows");
ADD_GROUP("SDF", "sdf_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_oversize", PROPERTY_HINT_ENUM, "100%,120%,150%,200%"), "set_sdf_oversize", "get_sdf_oversize");
ADD_PROPERTY(PropertyInfo(Variant::INT, "sdf_scale", PROPERTY_HINT_ENUM, "100%,50%,25%"), "set_sdf_scale", "get_sdf_scale");
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 93e42f1838..e4912f31c5 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -388,6 +388,7 @@ private:
Control *_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform, Transform2D &r_inv_xform);
void _gui_input_event(Ref<InputEvent> p_event);
+ void _gui_cleanup_internal_state(Ref<InputEvent> p_event);
_FORCE_INLINE_ Transform2D _get_input_pre_xform() const;
@@ -600,8 +601,7 @@ public:
virtual DisplayServer::WindowID get_window_id() const = 0;
- void set_embed_subwindows_hint(bool p_embed);
- bool get_embed_subwindows_hint() const;
+ void set_embedding_subwindows(bool p_embed);
bool is_embedding_subwindows() const;
Viewport *get_parent_viewport() const;
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 61114333fb..da37228ed9 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -103,7 +103,7 @@ static Ref<StyleBox> make_empty_stylebox(float p_margin_left = -1, float p_margi
return style;
}
-void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) {
+void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale) {
scale = p_scale;
// Font colors
@@ -924,9 +924,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Te
theme->set_stylebox("normal", "RichTextLabel", make_empty_stylebox(0, 0, 0, 0));
theme->set_font("normal_font", "RichTextLabel", Ref<Font>());
- theme->set_font("bold_font", "RichTextLabel", Ref<Font>());
- theme->set_font("italics_font", "RichTextLabel", Ref<Font>());
- theme->set_font("bold_italics_font", "RichTextLabel", Ref<Font>());
+ theme->set_font("bold_font", "RichTextLabel", bold_font);
+ theme->set_font("italics_font", "RichTextLabel", italics_font);
+ theme->set_font("bold_italics_font", "RichTextLabel", bold_italics_font);
theme->set_font("mono_font", "RichTextLabel", Ref<Font>());
theme->set_font_size("normal_font_size", "RichTextLabel", -1);
@@ -1025,6 +1025,9 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
Ref<StyleBox> default_style;
Ref<Texture2D> default_icon;
Ref<Font> default_font;
+ Ref<Font> bold_font;
+ Ref<Font> bold_italics_font;
+ Ref<Font> italics_font;
float default_scale = CLAMP(p_scale, 0.5, 8.0);
if (p_font.is_valid()) {
@@ -1048,7 +1051,31 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos
default_font = dynamic_font;
}
- fill_default_theme(t, default_font, default_icon, default_style, default_scale);
+ if (default_font.is_valid()) {
+ bold_font.instantiate();
+ for (int i = 0; i < default_font->get_data_count(); i++) {
+ Ref<FontData> data = default_font->get_data(i)->duplicate();
+ data->set_embolden(1.2);
+ bold_font->add_data(data);
+ }
+
+ bold_italics_font.instantiate();
+ for (int i = 0; i < default_font->get_data_count(); i++) {
+ Ref<FontData> data = default_font->get_data(i)->duplicate();
+ data->set_embolden(1.2);
+ data->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0));
+ bold_italics_font->add_data(data);
+ }
+
+ italics_font.instantiate();
+ for (int i = 0; i < default_font->get_data_count(); i++) {
+ Ref<FontData> data = default_font->get_data(i)->duplicate();
+ data->set_transform(Transform2D(1.0, 0.4, 0.0, 1.0, 0.0, 0.0));
+ italics_font->add_data(data);
+ }
+ }
+
+ fill_default_theme(t, default_font, bold_font, bold_italics_font, italics_font, default_icon, default_style, default_scale);
Theme::set_default(t);
Theme::set_fallback_base_scale(default_scale);
diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h
index 28afd5f5e1..a9e21dda3f 100644
--- a/scene/resources/default_theme/default_theme.h
+++ b/scene/resources/default_theme/default_theme.h
@@ -35,7 +35,7 @@
const int default_font_size = 16;
-void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale);
+void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale);
void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_subpixel, TextServer::Hinting p_hinting, bool p_aa);
void clear_default_theme();
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index 5b57e93950..ce2a675854 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -61,6 +61,8 @@ _FORCE_INLINE_ void FontData::_ensure_rid(int p_cache_index) const {
TS->font_set_force_autohinter(cache[p_cache_index], force_autohinter);
TS->font_set_hinting(cache[p_cache_index], hinting);
TS->font_set_subpixel_positioning(cache[p_cache_index], subpixel_positioning);
+ TS->font_set_embolden(cache[p_cache_index], embolden);
+ TS->font_set_transform(cache[p_cache_index], transform);
TS->font_set_oversampling(cache[p_cache_index], oversampling);
}
}
@@ -105,6 +107,12 @@ void FontData::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_subpixel_positioning", "subpixel_positioning"), &FontData::set_subpixel_positioning);
ClassDB::bind_method(D_METHOD("get_subpixel_positioning"), &FontData::get_subpixel_positioning);
+ ClassDB::bind_method(D_METHOD("set_embolden", "strength"), &FontData::set_embolden);
+ ClassDB::bind_method(D_METHOD("get_embolden"), &FontData::get_embolden);
+
+ ClassDB::bind_method(D_METHOD("set_transform", "transform"), &FontData::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"), &FontData::get_transform);
+
ClassDB::bind_method(D_METHOD("set_oversampling", "oversampling"), &FontData::set_oversampling);
ClassDB::bind_method(D_METHOD("get_oversampling"), &FontData::get_oversampling);
@@ -209,6 +217,8 @@ void FontData::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name");
ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style");
ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One half of a pixel,One quarter of a pixel", PROPERTY_USAGE_STORAGE), "set_subpixel_positioning", "get_subpixel_positioning");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "embolden", PROPERTY_HINT_RANGE, "-2,2,0.01", PROPERTY_USAGE_STORAGE), "set_embolden", "get_embolden");
+ ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_transform", "get_transform");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_pixel_range", "get_msdf_pixel_range");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msdf_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_msdf_size", "get_msdf_size");
@@ -439,6 +449,8 @@ void FontData::reset_state() {
msdf_pixel_range = 14;
msdf_size = 128;
fixed_size = 0;
+ embolden = 0.f;
+ transform = Transform2D();
oversampling = 0.f;
}
@@ -1385,6 +1397,36 @@ TextServer::SubpixelPositioning FontData::get_subpixel_positioning() const {
return subpixel_positioning;
}
+void FontData::set_embolden(float p_strength) {
+ if (embolden != p_strength) {
+ embolden = p_strength;
+ for (int i = 0; i < cache.size(); i++) {
+ _ensure_rid(i);
+ TS->font_set_embolden(cache[i], embolden);
+ }
+ emit_changed();
+ }
+}
+
+float FontData::get_embolden() const {
+ return embolden;
+}
+
+void FontData::set_transform(Transform2D p_transform) {
+ if (transform != p_transform) {
+ transform = p_transform;
+ for (int i = 0; i < cache.size(); i++) {
+ _ensure_rid(i);
+ TS->font_set_transform(cache[i], transform);
+ }
+ emit_changed();
+ }
+}
+
+Transform2D FontData::get_transform() const {
+ return transform;
+}
+
void FontData::set_oversampling(real_t p_oversampling) {
if (oversampling != p_oversampling) {
oversampling = p_oversampling;
diff --git a/scene/resources/font.h b/scene/resources/font.h
index aaf0a7fe7b..0185b019f1 100644
--- a/scene/resources/font.h
+++ b/scene/resources/font.h
@@ -57,6 +57,8 @@ class FontData : public Resource {
TextServer::Hinting hinting = TextServer::HINTING_LIGHT;
TextServer::SubpixelPositioning subpixel_positioning = TextServer::SUBPIXEL_POSITIONING_AUTO;
real_t oversampling = 0.f;
+ real_t embolden = 0.f;
+ Transform2D transform;
// Cache.
mutable Vector<RID> cache;
@@ -122,6 +124,12 @@ public:
virtual void set_subpixel_positioning(TextServer::SubpixelPositioning p_subpixel);
virtual TextServer::SubpixelPositioning get_subpixel_positioning() const;
+ virtual void set_embolden(float p_strength);
+ virtual float get_embolden() const;
+
+ virtual void set_transform(Transform2D p_transform);
+ virtual Transform2D get_transform() const;
+
virtual void set_oversampling(real_t p_oversampling);
virtual real_t get_oversampling() const;
diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp
index d9ac967699..fd6f018651 100644
--- a/scene/resources/resource_format_text.cpp
+++ b/scene/resources/resource_format_text.cpp
@@ -908,10 +908,9 @@ Error ResourceLoaderText::rename_dependencies(FileAccess *p_f, const String &p_p
return ERR_CANT_CREATE;
}
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
da->remove(p_path);
da->rename(p_path + ".depren", p_path);
- memdelete(da);
return OK;
}
diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp
index 8e633a4075..54543782f6 100644
--- a/scene/resources/sky_material.cpp
+++ b/scene/resources/sky_material.cpp
@@ -71,6 +71,25 @@ float ProceduralSkyMaterial::get_sky_energy() const {
return sky_energy;
}
+void ProceduralSkyMaterial::set_sky_cover(const Ref<Texture2D> &p_sky_cover) {
+ sky_cover = p_sky_cover;
+ RID tex_rid = p_sky_cover.is_valid() ? p_sky_cover->get_rid() : RID();
+ RS::get_singleton()->material_set_param(_get_material(), "sky_cover", tex_rid);
+}
+
+Ref<Texture2D> ProceduralSkyMaterial::get_sky_cover() const {
+ return sky_cover;
+}
+
+void ProceduralSkyMaterial::set_sky_cover_modulate(const Color &p_sky_cover_modulate) {
+ sky_cover_modulate = p_sky_cover_modulate;
+ RS::get_singleton()->material_set_param(_get_material(), "sky_cover_modulate", sky_cover_modulate);
+}
+
+Color ProceduralSkyMaterial::get_sky_cover_modulate() const {
+ return sky_cover_modulate;
+}
+
void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) {
ground_bottom_color = p_ground_bottom;
RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color);
@@ -156,6 +175,12 @@ void ProceduralSkyMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_sky_energy", "energy"), &ProceduralSkyMaterial::set_sky_energy);
ClassDB::bind_method(D_METHOD("get_sky_energy"), &ProceduralSkyMaterial::get_sky_energy);
+ ClassDB::bind_method(D_METHOD("set_sky_cover", "sky_cover"), &ProceduralSkyMaterial::set_sky_cover);
+ ClassDB::bind_method(D_METHOD("get_sky_cover"), &ProceduralSkyMaterial::get_sky_cover);
+
+ ClassDB::bind_method(D_METHOD("set_sky_cover_modulate", "color"), &ProceduralSkyMaterial::set_sky_cover_modulate);
+ ClassDB::bind_method(D_METHOD("get_sky_cover_modulate"), &ProceduralSkyMaterial::get_sky_cover_modulate);
+
ClassDB::bind_method(D_METHOD("set_ground_bottom_color", "color"), &ProceduralSkyMaterial::set_ground_bottom_color);
ClassDB::bind_method(D_METHOD("get_ground_bottom_color"), &ProceduralSkyMaterial::get_ground_bottom_color);
@@ -179,6 +204,8 @@ void ProceduralSkyMaterial::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_horizon_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_sky_horizon_color", "get_sky_horizon_color");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_curve", PROPERTY_HINT_EXP_EASING), "set_sky_curve", "get_sky_curve");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "sky_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_sky_energy", "get_sky_energy");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sky_cover", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_sky_cover", "get_sky_cover");
+ ADD_PROPERTY(PropertyInfo(Variant::COLOR, "sky_cover_modulate"), "set_sky_cover_modulate", "get_sky_cover_modulate");
ADD_GROUP("Ground", "ground_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "ground_bottom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_ground_bottom_color", "get_ground_bottom_color");
@@ -212,6 +239,8 @@ uniform vec4 sky_top_color : hint_color = vec4(0.385, 0.454, 0.55, 1.0);
uniform vec4 sky_horizon_color : hint_color = vec4(0.646, 0.656, 0.67, 1.0);
uniform float sky_curve : hint_range(0, 1) = 0.15;
uniform float sky_energy = 1.0;
+uniform sampler2D sky_cover : hint_black_albedo;
+uniform vec4 sky_cover_modulate : hint_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform vec4 ground_bottom_color : hint_color = vec4(0.2, 0.169, 0.133, 1.0);
uniform vec4 ground_horizon_color : hint_color = vec4(0.646, 0.656, 0.67, 1.0);
uniform float ground_curve : hint_range(0, 1) = 0.02;
@@ -265,6 +294,9 @@ void sky() {
}
}
+ vec4 sky_cover_texture = texture(sky_cover, SKY_COORDS);
+ sky += (sky_cover_texture.rgb * sky_cover_modulate.rgb) * sky_cover_texture.a * sky_cover_modulate.a * sky_energy;
+
c = (v_angle - (PI * 0.5)) / (PI * 0.5);
vec3 ground = mix(ground_horizon_color.rgb, ground_bottom_color.rgb, clamp(1.0 - pow(1.0 - c, 1.0 / ground_curve), 0.0, 1.0));
ground *= ground_energy;
@@ -281,6 +313,7 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() {
set_sky_horizon_color(Color(0.6463, 0.6558, 0.6708));
set_sky_curve(0.15);
set_sky_energy(1.0);
+ set_sky_cover_modulate(Color(1, 1, 1));
set_ground_bottom_color(Color(0.2, 0.169, 0.133));
set_ground_horizon_color(Color(0.6463, 0.6558, 0.6708));
diff --git a/scene/resources/sky_material.h b/scene/resources/sky_material.h
index 7f421beb8d..5c791a185a 100644
--- a/scene/resources/sky_material.h
+++ b/scene/resources/sky_material.h
@@ -42,6 +42,8 @@ private:
Color sky_horizon_color;
float sky_curve;
float sky_energy;
+ Ref<Texture2D> sky_cover;
+ Color sky_cover_modulate;
Color ground_bottom_color;
Color ground_horizon_color;
@@ -72,6 +74,12 @@ public:
void set_sky_energy(float p_energy);
float get_sky_energy() const;
+ void set_sky_cover(const Ref<Texture2D> &p_sky_cover);
+ Ref<Texture2D> get_sky_cover() const;
+
+ void set_sky_cover_modulate(const Color &p_sky_cover_modulate);
+ Color get_sky_cover_modulate() const;
+
void set_ground_bottom_color(const Color &p_ground_bottom);
Color get_ground_bottom_color() const;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index d541284381..3113987fbc 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -212,7 +212,7 @@ void ImageTexture::update(const Ref<Image> &p_image) {
ERR_FAIL_COND_MSG(mipmaps != p_image->has_mipmaps(),
"The new image mipmaps configuration must match the texture's image mipmaps configuration");
- RenderingServer::get_singleton()->texture_2d_update(texture, p_image);
+ RS::get_singleton()->texture_2d_update(texture, p_image);
notify_property_list_changed();
emit_changed();
@@ -482,24 +482,24 @@ void CompressedTexture2D::set_path(const String &p_path, bool p_take_over) {
}
void CompressedTexture2D::_requested_3d(void *p_ud) {
- CompressedTexture2D *st = (CompressedTexture2D *)p_ud;
- Ref<CompressedTexture2D> stex(st);
+ CompressedTexture2D *ct = (CompressedTexture2D *)p_ud;
+ Ref<CompressedTexture2D> ctex(ct);
ERR_FAIL_COND(!request_3d_callback);
- request_3d_callback(stex);
+ request_3d_callback(ctex);
}
void CompressedTexture2D::_requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel) {
- CompressedTexture2D *st = (CompressedTexture2D *)p_ud;
- Ref<CompressedTexture2D> stex(st);
+ CompressedTexture2D *ct = (CompressedTexture2D *)p_ud;
+ Ref<CompressedTexture2D> ctex(ct);
ERR_FAIL_COND(!request_roughness_callback);
- request_roughness_callback(stex, p_normal_path, p_roughness_channel);
+ request_roughness_callback(ctex, p_normal_path, p_roughness_channel);
}
void CompressedTexture2D::_requested_normal(void *p_ud) {
- CompressedTexture2D *st = (CompressedTexture2D *)p_ud;
- Ref<CompressedTexture2D> stex(st);
+ CompressedTexture2D *ct = (CompressedTexture2D *)p_ud;
+ Ref<CompressedTexture2D> ctex(ct);
ERR_FAIL_COND(!request_normal_callback);
- request_normal_callback(stex);
+ request_normal_callback(ctex);
}
CompressedTexture2D::TextureFormatRequestCallback CompressedTexture2D::request_3d_callback = nullptr;
@@ -522,14 +522,14 @@ Error CompressedTexture2D::_load_data(const String &p_path, int &r_width, int &r
f->get_buffer(header, 4);
if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != '2') {
memdelete(f);
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is corrupt (Bad header).");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is corrupt (Bad header).");
}
uint32_t version = f->get_32();
if (version > FORMAT_VERSION) {
memdelete(f);
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new.");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new.");
}
r_width = f->get_32();
r_height = f->get_32();
@@ -973,11 +973,11 @@ Error CompressedTexture3D::_load_data(const String &p_path, Vector<Ref<Image>> &
f->get_buffer(header, 4);
ERR_FAIL_COND_V(header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L', ERR_FILE_UNRECOGNIZED);
- //stored as stream textures (used for lossless and lossy compression)
+ //stored as compressed textures (used for lossless and lossy compression)
uint32_t version = f->get_32();
if (version > FORMAT_VERSION) {
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new.");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new.");
}
r_depth = f->get_32(); //depth
@@ -1129,7 +1129,7 @@ RES ResourceFormatLoaderCompressedTexture3D::load(const String &p_path, const St
}
void ResourceFormatLoaderCompressedTexture3D::get_recognized_extensions(List<String> *p_extensions) const {
- p_extensions->push_back("stex3d");
+ p_extensions->push_back("ctex3d");
}
bool ResourceFormatLoaderCompressedTexture3D::handles_type(const String &p_type) const {
@@ -1137,7 +1137,7 @@ bool ResourceFormatLoaderCompressedTexture3D::handles_type(const String &p_type)
}
String ResourceFormatLoaderCompressedTexture3D::get_resource_type(const String &p_path) const {
- if (p_path.get_extension().to_lower() == "stex3d") {
+ if (p_path.get_extension().to_lower() == "ctex3d") {
return "CompressedTexture3D";
}
return "";
@@ -2792,13 +2792,13 @@ Error CompressedTextureLayered::_load_data(const String &p_path, Vector<Ref<Imag
uint8_t header[4];
f->get_buffer(header, 4);
if (header[0] != 'G' || header[1] != 'S' || header[2] != 'T' || header[3] != 'L') {
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture layered file is corrupt (Bad header).");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture layered file is corrupt (Bad header).");
}
uint32_t version = f->get_32();
if (version > FORMAT_VERSION) {
- ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Stream texture file is too new.");
+ ERR_FAIL_V_MSG(ERR_FILE_CORRUPT, "Compressed texture file is too new.");
}
uint32_t layer_count = f->get_32(); //layer count
@@ -2939,26 +2939,26 @@ CompressedTextureLayered::~CompressedTextureLayered() {
/////////////////////////////////////////////////
RES ResourceFormatLoaderCompressedTextureLayered::load(const String &p_path, const String &p_original_path, Error *r_error, bool p_use_sub_threads, float *r_progress, CacheMode p_cache_mode) {
- Ref<CompressedTextureLayered> st;
- if (p_path.get_extension().to_lower() == "stexarray") {
- Ref<CompressedTexture2DArray> s;
- s.instantiate();
- st = s;
- } else if (p_path.get_extension().to_lower() == "scube") {
- Ref<CompressedCubemap> s;
- s.instantiate();
- st = s;
- } else if (p_path.get_extension().to_lower() == "scubearray") {
- Ref<CompressedCubemapArray> s;
- s.instantiate();
- st = s;
+ Ref<CompressedTextureLayered> ct;
+ if (p_path.get_extension().to_lower() == "ctexarray") {
+ Ref<CompressedTexture2DArray> c;
+ c.instantiate();
+ ct = c;
+ } else if (p_path.get_extension().to_lower() == "ccube") {
+ Ref<CompressedCubemap> c;
+ c.instantiate();
+ ct = c;
+ } else if (p_path.get_extension().to_lower() == "ccubearray") {
+ Ref<CompressedCubemapArray> c;
+ c.instantiate();
+ ct = c;
} else {
if (r_error) {
*r_error = ERR_FILE_UNRECOGNIZED;
}
return RES();
}
- Error err = st->load(p_path);
+ Error err = ct->load(p_path);
if (r_error) {
*r_error = err;
}
@@ -2966,13 +2966,13 @@ RES ResourceFormatLoaderCompressedTextureLayered::load(const String &p_path, con
return RES();
}
- return st;
+ return ct;
}
void ResourceFormatLoaderCompressedTextureLayered::get_recognized_extensions(List<String> *p_extensions) const {
- p_extensions->push_back("stexarray");
- p_extensions->push_back("scube");
- p_extensions->push_back("scubearray");
+ p_extensions->push_back("ctexarray");
+ p_extensions->push_back("ccube");
+ p_extensions->push_back("ccubearray");
}
bool ResourceFormatLoaderCompressedTextureLayered::handles_type(const String &p_type) const {
@@ -2980,13 +2980,13 @@ bool ResourceFormatLoaderCompressedTextureLayered::handles_type(const String &p_
}
String ResourceFormatLoaderCompressedTextureLayered::get_resource_type(const String &p_path) const {
- if (p_path.get_extension().to_lower() == "stexarray") {
+ if (p_path.get_extension().to_lower() == "ctexarray") {
return "CompressedTexture2DArray";
}
- if (p_path.get_extension().to_lower() == "scube") {
+ if (p_path.get_extension().to_lower() == "ccube") {
return "CompressedCubemap";
}
- if (p_path.get_extension().to_lower() == "scubearray") {
+ if (p_path.get_extension().to_lower() == "ccubearray") {
return "CompressedCubemapArray";
}
return "";