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/cpu_particles_3d.cpp4
-rw-r--r--scene/3d/cpu_particles_3d.h1
-rw-r--r--scene/3d/decal.cpp4
-rw-r--r--scene/3d/decal.h1
-rw-r--r--scene/3d/fog_volume.h1
-rw-r--r--scene/3d/gpu_particles_3d.cpp4
-rw-r--r--scene/3d/gpu_particles_3d.h1
-rw-r--r--scene/3d/gpu_particles_collision_3d.h4
-rw-r--r--scene/3d/light_3d.cpp19
-rw-r--r--scene/3d/light_3d.h5
-rw-r--r--scene/3d/lightmap_gi.cpp4
-rw-r--r--scene/3d/lightmap_gi.h1
-rw-r--r--scene/3d/mesh_instance_3d.cpp12
-rw-r--r--scene/3d/mesh_instance_3d.h1
-rw-r--r--scene/3d/multimesh_instance_3d.cpp4
-rw-r--r--scene/3d/multimesh_instance_3d.h2
-rw-r--r--scene/3d/occluder_instance_3d.cpp4
-rw-r--r--scene/3d/occluder_instance_3d.h1
-rw-r--r--scene/3d/physics_body_3d.cpp2
-rw-r--r--scene/3d/reflection_probe.cpp4
-rw-r--r--scene/3d/reflection_probe.h1
-rw-r--r--scene/3d/sprite_3d.cpp4
-rw-r--r--scene/3d/sprite_3d.h2
-rw-r--r--scene/3d/visible_on_screen_notifier_3d.cpp4
-rw-r--r--scene/3d/visible_on_screen_notifier_3d.h2
-rw-r--r--scene/3d/visual_instance_3d.cpp9
-rw-r--r--scene/3d/visual_instance_3d.h4
-rw-r--r--scene/3d/voxel_gi.cpp4
-rw-r--r--scene/3d/voxel_gi.h1
-rw-r--r--scene/animation/animation_player.cpp63
-rw-r--r--scene/animation/animation_tree.cpp56
-rw-r--r--scene/animation/root_motion_view.cpp4
-rw-r--r--scene/animation/root_motion_view.h1
-rw-r--r--scene/debugger/scene_debugger.cpp33
-rw-r--r--scene/debugger/scene_debugger.h4
-rw-r--r--scene/gui/base_button.cpp4
-rw-r--r--scene/gui/base_button.h2
-rw-r--r--scene/gui/button.cpp2
-rw-r--r--scene/gui/color_picker.cpp2
-rw-r--r--scene/gui/control.cpp58
-rw-r--r--scene/gui/file_dialog.cpp8
-rw-r--r--scene/gui/file_dialog.h1
-rw-r--r--scene/gui/graph_edit.cpp2
-rw-r--r--scene/gui/item_list.cpp48
-rw-r--r--scene/gui/line_edit.cpp8
-rw-r--r--scene/gui/menu_button.cpp2
-rw-r--r--scene/gui/popup.cpp4
-rw-r--r--scene/gui/popup.h2
-rw-r--r--scene/gui/popup_menu.cpp62
-rw-r--r--scene/gui/range.cpp5
-rw-r--r--scene/gui/range.h4
-rw-r--r--scene/gui/rich_text_label.cpp27
-rw-r--r--scene/gui/spin_box.cpp3
-rw-r--r--scene/gui/spin_box.h2
-rw-r--r--scene/gui/tab_bar.cpp87
-rw-r--r--scene/gui/tab_bar.h6
-rw-r--r--scene/gui/tab_container.cpp7
-rw-r--r--scene/gui/text_edit.cpp6
-rw-r--r--scene/gui/tree.cpp2
-rw-r--r--scene/main/canvas_item.cpp2
-rw-r--r--scene/main/node.cpp68
-rw-r--r--scene/main/node.h28
-rw-r--r--scene/main/scene_tree.cpp49
-rw-r--r--scene/main/scene_tree.h23
-rw-r--r--scene/main/viewport.cpp33
-rw-r--r--scene/main/viewport.h4
-rw-r--r--scene/multiplayer/scene_rpc_interface.cpp6
-rw-r--r--scene/register_scene_types.cpp107
-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/material.cpp36
-rw-r--r--scene/resources/material.h13
-rw-r--r--scene/resources/mesh.cpp131
-rw-r--r--scene/resources/mesh.h63
-rw-r--r--scene/resources/primitive_meshes.cpp12
-rw-r--r--scene/resources/primitive_meshes.h3
-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/style_box.cpp33
-rw-r--r--scene/resources/style_box.h10
-rw-r--r--scene/resources/texture.cpp252
-rw-r--r--scene/resources/texture.h62
-rw-r--r--scene/resources/visual_shader.cpp619
-rw-r--r--scene/resources/visual_shader.h170
-rw-r--r--scene/resources/visual_shader_nodes.cpp6
93 files changed, 1894 insertions, 627 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/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp
index a02b5f48a1..ab28a83806 100644
--- a/scene/3d/cpu_particles_3d.cpp
+++ b/scene/3d/cpu_particles_3d.cpp
@@ -39,10 +39,6 @@ AABB CPUParticles3D::get_aabb() const {
return AABB();
}
-Vector<Face3> CPUParticles3D::get_faces(uint32_t p_usage_particle_flags) const {
- return Vector<Face3>();
-}
-
void CPUParticles3D::set_emitting(bool p_emitting) {
if (emitting == p_emitting) {
return;
diff --git a/scene/3d/cpu_particles_3d.h b/scene/3d/cpu_particles_3d.h
index bd736bdf24..5eeb5e75d3 100644
--- a/scene/3d/cpu_particles_3d.h
+++ b/scene/3d/cpu_particles_3d.h
@@ -201,7 +201,6 @@ protected:
public:
AABB get_aabb() const override;
- Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
diff --git a/scene/3d/decal.cpp b/scene/3d/decal.cpp
index dfac9055f5..8d0edfd1f3 100644
--- a/scene/3d/decal.cpp
+++ b/scene/3d/decal.cpp
@@ -152,10 +152,6 @@ AABB Decal::get_aabb() const {
return aabb;
}
-Vector<Face3> Decal::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void Decal::_validate_property(PropertyInfo &property) const {
if (!distance_fade_enabled && (property.name == "distance_fade_begin" || property.name == "distance_fade_length")) {
property.usage = PROPERTY_USAGE_NO_EDITOR;
diff --git a/scene/3d/decal.h b/scene/3d/decal.h
index 740dd2c407..d5990272c6 100644
--- a/scene/3d/decal.h
+++ b/scene/3d/decal.h
@@ -104,7 +104,6 @@ public:
uint32_t get_cull_mask() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
Decal();
~Decal();
diff --git a/scene/3d/fog_volume.h b/scene/3d/fog_volume.h
index 68d5c58169..556a92ad3f 100644
--- a/scene/3d/fog_volume.h
+++ b/scene/3d/fog_volume.h
@@ -62,7 +62,6 @@ public:
Ref<Material> get_material() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); }
TypedArray<String> get_configuration_warnings() const override;
FogVolume();
diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp
index 4e35f37291..9fe2210de6 100644
--- a/scene/3d/gpu_particles_3d.cpp
+++ b/scene/3d/gpu_particles_3d.cpp
@@ -36,10 +36,6 @@ AABB GPUParticles3D::get_aabb() const {
return AABB();
}
-Vector<Face3> GPUParticles3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void GPUParticles3D::set_emitting(bool p_emitting) {
RS::get_singleton()->particles_set_emitting(particles, p_emitting);
diff --git a/scene/3d/gpu_particles_3d.h b/scene/3d/gpu_particles_3d.h
index 54ae84628a..f3eb52d124 100644
--- a/scene/3d/gpu_particles_3d.h
+++ b/scene/3d/gpu_particles_3d.h
@@ -98,7 +98,6 @@ protected:
public:
AABB get_aabb() const override;
- Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
void set_emitting(bool p_emitting);
void set_amount(int p_amount);
diff --git a/scene/3d/gpu_particles_collision_3d.h b/scene/3d/gpu_particles_collision_3d.h
index b6de1d83fc..fdd2fa4b18 100644
--- a/scene/3d/gpu_particles_collision_3d.h
+++ b/scene/3d/gpu_particles_collision_3d.h
@@ -50,8 +50,6 @@ public:
void set_cull_mask(uint32_t p_cull_mask);
uint32_t get_cull_mask() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); }
-
~GPUParticlesCollision3D();
};
@@ -274,8 +272,6 @@ public:
void set_directionality(real_t p_directionality);
real_t get_directionality() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override { return Vector<Face3>(); }
-
~GPUParticlesAttractor3D();
};
diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp
index 0dd3fc8a23..e7e164d7da 100644
--- a/scene/3d/light_3d.cpp
+++ b/scene/3d/light_3d.cpp
@@ -131,15 +131,6 @@ Color Light3D::get_color() const {
return color;
}
-void Light3D::set_shadow_color(const Color &p_shadow_color) {
- shadow_color = p_shadow_color;
- RS::get_singleton()->light_set_shadow_color(light, p_shadow_color);
-}
-
-Color Light3D::get_shadow_color() const {
- return shadow_color;
-}
-
void Light3D::set_shadow_reverse_cull_face(bool p_enable) {
reverse_cull = p_enable;
RS::get_singleton()->light_set_reverse_cull_face_mode(light, reverse_cull);
@@ -165,10 +156,6 @@ AABB Light3D::get_aabb() const {
return AABB();
}
-Vector<Face3> Light3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void Light3D::set_bake_mode(BakeMode p_mode) {
bake_mode = p_mode;
RS::get_singleton()->light_set_bake_mode(light, RS::LightBakeMode(p_mode));
@@ -232,7 +219,7 @@ bool Light3D::is_editor_only() const {
}
void Light3D::_validate_property(PropertyInfo &property) const {
- if (!shadow && (property.name == "shadow_color" || property.name == "shadow_bias" || property.name == "shadow_normal_bias" || property.name == "shadow_reverse_cull_face" || property.name == "shadow_transmittance_bias" || property.name == "shadow_fog_fade" || property.name == "shadow_blur" || property.name == "distance_fade_shadow")) {
+ if (!shadow && (property.name == "shadow_bias" || property.name == "shadow_normal_bias" || property.name == "shadow_reverse_cull_face" || property.name == "shadow_transmittance_bias" || property.name == "shadow_fog_fade" || property.name == "shadow_blur" || property.name == "distance_fade_shadow")) {
property.usage = PROPERTY_USAGE_NO_EDITOR;
}
@@ -282,9 +269,6 @@ void Light3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_shadow_reverse_cull_face", "enable"), &Light3D::set_shadow_reverse_cull_face);
ClassDB::bind_method(D_METHOD("get_shadow_reverse_cull_face"), &Light3D::get_shadow_reverse_cull_face);
- ClassDB::bind_method(D_METHOD("set_shadow_color", "shadow_color"), &Light3D::set_shadow_color);
- ClassDB::bind_method(D_METHOD("get_shadow_color"), &Light3D::get_shadow_color);
-
ClassDB::bind_method(D_METHOD("set_bake_mode", "bake_mode"), &Light3D::set_bake_mode);
ClassDB::bind_method(D_METHOD("get_bake_mode"), &Light3D::get_bake_mode);
@@ -304,7 +288,6 @@ void Light3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_cull_mask", PROPERTY_HINT_LAYERS_3D_RENDER), "set_cull_mask", "get_cull_mask");
ADD_GROUP("Shadow", "shadow_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_enabled"), "set_shadow", "has_shadow");
- ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_shadow_color", "get_shadow_color");
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_BIAS);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "shadow_normal_bias", PROPERTY_HINT_RANGE, "0,10,0.001"), "set_param", "get_param", PARAM_SHADOW_NORMAL_BIAS);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shadow_reverse_cull_face"), "set_shadow_reverse_cull_face", "get_shadow_reverse_cull_face");
diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h
index 21d785e2f7..ed9e0bdfff 100644
--- a/scene/3d/light_3d.h
+++ b/scene/3d/light_3d.h
@@ -70,7 +70,6 @@ public:
private:
Color color;
real_t param[PARAM_MAX] = {};
- Color shadow_color;
bool shadow = false;
bool negative = false;
bool reverse_cull = false;
@@ -129,9 +128,6 @@ public:
void set_color(const Color &p_color);
Color get_color() const;
- void set_shadow_color(const Color &p_shadow_color);
- Color get_shadow_color() const;
-
void set_shadow_reverse_cull_face(bool p_enable);
bool get_shadow_reverse_cull_face() const;
@@ -142,7 +138,6 @@ public:
Ref<Texture2D> get_projector() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
Light3D();
~Light3D();
diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp
index 07f41c0bf9..c74654b4bd 100644
--- a/scene/3d/lightmap_gi.cpp
+++ b/scene/3d/lightmap_gi.cpp
@@ -1263,10 +1263,6 @@ AABB LightmapGI::get_aabb() const {
return AABB();
}
-Vector<Face3> LightmapGI::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void LightmapGI::set_use_denoiser(bool p_enable) {
use_denoiser = p_enable;
}
diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h
index 66acf4f487..d29d7a7c28 100644
--- a/scene/3d/lightmap_gi.h
+++ b/scene/3d/lightmap_gi.h
@@ -267,7 +267,6 @@ public:
GenerateProbes get_generate_probes() const;
AABB get_aabb() const override;
- Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
BakeError bake(Node *p_from_node, String p_image_data_path = "", Lightmapper::BakeStepFunc p_bake_step = nullptr, void *p_bake_userdata = nullptr);
LightmapGI();
diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp
index fddfa17dbb..31c33a6b61 100644
--- a/scene/3d/mesh_instance_3d.cpp
+++ b/scene/3d/mesh_instance_3d.cpp
@@ -219,18 +219,6 @@ AABB MeshInstance3D::get_aabb() const {
return AABB();
}
-Vector<Face3> MeshInstance3D::get_faces(uint32_t p_usage_flags) const {
- if (!(p_usage_flags & (FACES_SOLID | FACES_ENCLOSING))) {
- return Vector<Face3>();
- }
-
- if (mesh.is_null()) {
- return Vector<Face3>();
- }
-
- return mesh->get_faces();
-}
-
Node *MeshInstance3D::create_trimesh_collision_node() {
if (mesh.is_null()) {
return nullptr;
diff --git a/scene/3d/mesh_instance_3d.h b/scene/3d/mesh_instance_3d.h
index 03ee3cd608..0bf5c32410 100644
--- a/scene/3d/mesh_instance_3d.h
+++ b/scene/3d/mesh_instance_3d.h
@@ -93,7 +93,6 @@ public:
void create_debug_tangents();
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
MeshInstance3D();
~MeshInstance3D();
diff --git a/scene/3d/multimesh_instance_3d.cpp b/scene/3d/multimesh_instance_3d.cpp
index 34b1e86435..d197388fad 100644
--- a/scene/3d/multimesh_instance_3d.cpp
+++ b/scene/3d/multimesh_instance_3d.cpp
@@ -49,10 +49,6 @@ Ref<MultiMesh> MultiMeshInstance3D::get_multimesh() const {
return multimesh;
}
-Vector<Face3> MultiMeshInstance3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
AABB MultiMeshInstance3D::get_aabb() const {
if (multimesh.is_null()) {
return AABB();
diff --git a/scene/3d/multimesh_instance_3d.h b/scene/3d/multimesh_instance_3d.h
index d03b24eb4e..111f1e9c09 100644
--- a/scene/3d/multimesh_instance_3d.h
+++ b/scene/3d/multimesh_instance_3d.h
@@ -44,8 +44,6 @@ protected:
// bind helpers
public:
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
-
void set_multimesh(const Ref<MultiMesh> &p_multimesh);
Ref<MultiMesh> get_multimesh() const;
diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp
index 855922c341..b82f05544b 100644
--- a/scene/3d/occluder_instance_3d.cpp
+++ b/scene/3d/occluder_instance_3d.cpp
@@ -433,10 +433,6 @@ AABB OccluderInstance3D::get_aabb() const {
return AABB();
}
-Vector<Face3> OccluderInstance3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void OccluderInstance3D::set_occluder(const Ref<Occluder3D> &p_occluder) {
if (occluder == p_occluder) {
return;
diff --git a/scene/3d/occluder_instance_3d.h b/scene/3d/occluder_instance_3d.h
index 669ddba775..ed6610074e 100644
--- a/scene/3d/occluder_instance_3d.h
+++ b/scene/3d/occluder_instance_3d.h
@@ -194,7 +194,6 @@ public:
Ref<Occluder3D> get_occluder() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
void set_bake_mask(uint32_t p_mask);
uint32_t get_bake_mask() const;
diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp
index c1f5ab1d32..47baa9e023 100644
--- a/scene/3d/physics_body_3d.cpp
+++ b/scene/3d/physics_body_3d.cpp
@@ -1425,7 +1425,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
const PhysicsServer3D::MotionCollision &collision = result.collisions[0];
Vector3 slide_motion = result.remainder.slide(collision.normal);
- if (collision_state.floor && !collision_state.wall) {
+ if (collision_state.floor && !collision_state.wall && !motion_slide_up.is_equal_approx(Vector3())) {
// Slide using the intersection between the motion plane and the floor plane,
// in order to keep the direction intact.
real_t motion_length = slide_motion.length();
diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp
index be655e71db..1bebd8e335 100644
--- a/scene/3d/reflection_probe.cpp
+++ b/scene/3d/reflection_probe.cpp
@@ -178,10 +178,6 @@ AABB ReflectionProbe::get_aabb() const {
return aabb;
}
-Vector<Face3> ReflectionProbe::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void ReflectionProbe::_validate_property(PropertyInfo &property) const {
if (property.name == "interior/ambient_color" || property.name == "interior/ambient_color_energy") {
if (ambient_mode != AMBIENT_COLOR) {
diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h
index d0643496a4..424976d895 100644
--- a/scene/3d/reflection_probe.h
+++ b/scene/3d/reflection_probe.h
@@ -113,7 +113,6 @@ public:
UpdateMode get_update_mode() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
ReflectionProbe();
~ReflectionProbe();
diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp
index ce281c79bc..514bd4aba0 100644
--- a/scene/3d/sprite_3d.cpp
+++ b/scene/3d/sprite_3d.cpp
@@ -177,10 +177,6 @@ AABB SpriteBase3D::get_aabb() const {
return aabb;
}
-Vector<Face3> SpriteBase3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const {
if (triangle_mesh.is_valid()) {
return triangle_mesh;
diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h
index 985103e190..92dbef0855 100644
--- a/scene/3d/sprite_3d.h
+++ b/scene/3d/sprite_3d.h
@@ -137,7 +137,7 @@ public:
virtual Rect2 get_item_rect() const = 0;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
+
Ref<TriangleMesh> generate_triangle_mesh() const;
SpriteBase3D();
diff --git a/scene/3d/visible_on_screen_notifier_3d.cpp b/scene/3d/visible_on_screen_notifier_3d.cpp
index 11367d7ca9..41cd604a4f 100644
--- a/scene/3d/visible_on_screen_notifier_3d.cpp
+++ b/scene/3d/visible_on_screen_notifier_3d.cpp
@@ -89,10 +89,6 @@ void VisibleOnScreenNotifier3D::_bind_methods() {
ADD_SIGNAL(MethodInfo("screen_exited"));
}
-Vector<Face3> VisibleOnScreenNotifier3D::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
VisibleOnScreenNotifier3D::VisibleOnScreenNotifier3D() {
RID notifier = RS::get_singleton()->visibility_notifier_create();
RS::get_singleton()->visibility_notifier_set_aabb(notifier, aabb);
diff --git a/scene/3d/visible_on_screen_notifier_3d.h b/scene/3d/visible_on_screen_notifier_3d.h
index 852c7e2ed3..fe17f1e444 100644
--- a/scene/3d/visible_on_screen_notifier_3d.h
+++ b/scene/3d/visible_on_screen_notifier_3d.h
@@ -57,8 +57,6 @@ public:
virtual AABB get_aabb() const override;
bool is_on_screen() const;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
-
VisibleOnScreenNotifier3D();
~VisibleOnScreenNotifier3D();
};
diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp
index d8dffe6c7d..b8a68cdca9 100644
--- a/scene/3d/visual_instance_3d.cpp
+++ b/scene/3d/visual_instance_3d.cpp
@@ -32,6 +32,14 @@
#include "scene/scene_string_names.h"
+AABB VisualInstance3D::get_aabb() const {
+ AABB ret;
+ if (GDVIRTUAL_CALL(_get_aabb, ret)) {
+ return ret;
+ }
+ return AABB();
+}
+
AABB VisualInstance3D::get_transformed_aabb() const {
return get_global_transform().xform(get_aabb());
}
@@ -115,6 +123,7 @@ void VisualInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_transformed_aabb"), &VisualInstance3D::get_transformed_aabb);
+ GDVIRTUAL_BIND(_get_aabb);
ADD_PROPERTY(PropertyInfo(Variant::INT, "layers", PROPERTY_HINT_LAYERS_3D_RENDER), "set_layer_mask", "get_layer_mask");
}
diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h
index 02f62b41e5..1c044ba681 100644
--- a/scene/3d/visual_instance_3d.h
+++ b/scene/3d/visual_instance_3d.h
@@ -49,6 +49,7 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ GDVIRTUAL0RC(AABB, _get_aabb)
public:
enum GetFacesFlags {
FACES_SOLID = 1, // solid geometry
@@ -58,8 +59,7 @@ public:
};
RID get_instance() const;
- virtual AABB get_aabb() const = 0;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const = 0;
+ virtual AABB get_aabb() const;
virtual AABB get_transformed_aabb() const; // helper
diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp
index bfe3c80a4f..6840d15f78 100644
--- a/scene/3d/voxel_gi.cpp
+++ b/scene/3d/voxel_gi.cpp
@@ -450,10 +450,6 @@ AABB VoxelGI::get_aabb() const {
return AABB(-extents, extents * 2);
}
-Vector<Face3> VoxelGI::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
TypedArray<String> VoxelGI::get_configuration_warnings() const {
TypedArray<String> warnings = Node::get_configuration_warnings();
diff --git a/scene/3d/voxel_gi.h b/scene/3d/voxel_gi.h
index 3678bd4f3b..e1a38dd7a0 100644
--- a/scene/3d/voxel_gi.h
+++ b/scene/3d/voxel_gi.h
@@ -149,7 +149,6 @@ public:
void bake(Node *p_from_node = nullptr, bool p_create_visual_debug = false);
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
TypedArray<String> get_configuration_warnings() const override;
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index e243915c13..402418e5a9 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -401,6 +401,22 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim, Node *p_root_ov
}
}
+static void _call_object(Object *p_object, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred) {
+ // Separate function to use alloca() more efficiently
+ const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * p_params.size());
+ const Variant *args = p_params.ptr();
+ uint32_t argcount = p_params.size();
+ for (uint32_t i = 0; i < argcount; i++) {
+ argptrs[i] = &args[i];
+ }
+ if (p_deferred) {
+ MessageQueue::get_singleton()->push_callp(p_object, p_method, argptrs, argcount);
+ } else {
+ Callable::CallError ce;
+ p_object->callp(p_method, argptrs, argcount, ce);
+ }
+}
+
void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double p_time, double p_delta, float p_interp, bool p_is_current, bool p_seeked, bool p_started, int p_pingponged) {
_ensure_node_caches(p_anim);
ERR_FAIL_COND(p_anim->node_cache.size() != p_anim->animation->get_track_count());
@@ -677,41 +693,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
StringName method = a->method_track_get_name(i, E);
Vector<Variant> params = a->method_track_get_params(i, E);
- int s = params.size();
-
- ERR_CONTINUE(s > VARIANT_ARG_MAX);
#ifdef DEBUG_ENABLED
if (!nc->node->has_method(method)) {
ERR_PRINT("Invalid method call '" + method + "'. '" + a->get_name() + "' at node '" + get_path() + "'.");
}
#endif
- static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
if (can_call) {
- if (method_call_mode == ANIMATION_METHOD_CALL_DEFERRED) {
- MessageQueue::get_singleton()->push_call(
- nc->node,
- method,
- s >= 1 ? params[0] : Variant(),
- s >= 2 ? params[1] : Variant(),
- s >= 3 ? params[2] : Variant(),
- s >= 4 ? params[3] : Variant(),
- s >= 5 ? params[4] : Variant(),
- s >= 6 ? params[5] : Variant(),
- s >= 7 ? params[6] : Variant(),
- s >= 8 ? params[7] : Variant());
- } else {
- nc->node->call(
- method,
- s >= 1 ? params[0] : Variant(),
- s >= 2 ? params[1] : Variant(),
- s >= 3 ? params[2] : Variant(),
- s >= 4 ? params[3] : Variant(),
- s >= 5 ? params[4] : Variant(),
- s >= 6 ? params[5] : Variant(),
- s >= 7 ? params[6] : Variant(),
- s >= 8 ? params[7] : Variant());
- }
+ _call_object(nc->node, method, params, method_call_mode == ANIMATION_METHOD_CALL_DEFERRED);
}
}
@@ -754,7 +743,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
if (!stream.is_valid()) {
- nc->node->call("stop");
+ nc->node->call(SNAME("stop"));
nc->audio_playing = false;
playing_caches.erase(nc);
} else {
@@ -764,14 +753,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
float len = stream->get_length();
if (start_ofs > len - end_ofs) {
- nc->node->call("stop");
+ nc->node->call(SNAME("stop"));
nc->audio_playing = false;
playing_caches.erase(nc);
continue;
}
- nc->node->call("set_stream", stream);
- nc->node->call("play", start_ofs);
+ nc->node->call(SNAME("set_stream"), stream);
+ nc->node->call(SNAME("play"), start_ofs);
nc->audio_playing = true;
playing_caches.insert(nc);
@@ -793,7 +782,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
if (!stream.is_valid()) {
- nc->node->call("stop");
+ nc->node->call(SNAME("stop"));
nc->audio_playing = false;
playing_caches.erase(nc);
} else {
@@ -801,8 +790,8 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
float end_ofs = a->audio_track_get_key_end_offset(i, idx);
float len = stream->get_length();
- nc->node->call("set_stream", stream);
- nc->node->call("play", start_ofs);
+ nc->node->call(SNAME("set_stream"), stream);
+ nc->node->call(SNAME("play"), start_ofs);
nc->audio_playing = true;
playing_caches.insert(nc);
@@ -833,7 +822,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double
if (stop) {
//time to stop
- nc->node->call("stop");
+ nc->node->call(SNAME("stop"));
nc->audio_playing = false;
playing_caches.erase(nc);
}
@@ -1544,7 +1533,7 @@ void AnimationPlayer::_animation_changed() {
void AnimationPlayer::_stop_playing_caches() {
for (Set<TrackNodeCache *>::Element *E = playing_caches.front(); E; E = E->next()) {
if (E->get()->node && E->get()->audio_playing) {
- E->get()->node->call("stop");
+ E->get()->node->call(SNAME("stop"));
}
if (E->get()->node && E->get()->animation_playing) {
AnimationPlayer *player = Object::cast_to<AnimationPlayer>(E->get()->node);
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp
index a50618182d..e0e94d8632 100644
--- a/scene/animation/animation_tree.cpp
+++ b/scene/animation/animation_tree.cpp
@@ -490,7 +490,7 @@ void AnimationTree::set_active(bool p_active) {
if (!active && is_inside_tree()) {
for (Set<TrackCache *>::Element *E = playing_caches.front(); E; E = E->next()) {
if (ObjectDB::get_instance(E->get()->object_id)) {
- E->get()->object->call("stop");
+ E->get()->object->call(SNAME("stop"));
}
}
@@ -796,6 +796,21 @@ void AnimationTree::_clear_caches() {
cache_valid = false;
}
+static void _call_object(Object *p_object, const StringName &p_method, const Vector<Variant> &p_params, bool p_deferred) {
+ // Separate function to use alloca() more efficiently
+ const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant **) * p_params.size());
+ const Variant *args = p_params.ptr();
+ uint32_t argcount = p_params.size();
+ for (uint32_t i = 0; i < argcount; i++) {
+ argptrs[i] = &args[i];
+ }
+ if (p_deferred) {
+ MessageQueue::get_singleton()->push_callp(p_object, p_method, argptrs, argcount);
+ } else {
+ Callable::CallError ce;
+ p_object->callp(p_method, argptrs, argcount, ce);
+ }
+}
void AnimationTree::_process_graph(double p_delta) {
_update_properties(); //if properties need updating, update them
@@ -1286,25 +1301,10 @@ void AnimationTree::_process_graph(double p_delta) {
for (int &F : indices) {
StringName method = a->method_track_get_name(i, F);
Vector<Variant> params = a->method_track_get_params(i, F);
-
- int s = params.size();
-
- static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
- ERR_CONTINUE(s > VARIANT_ARG_MAX);
if (can_call) {
- t->object->call_deferred(
- method,
- s >= 1 ? params[0] : Variant(),
- s >= 2 ? params[1] : Variant(),
- s >= 3 ? params[2] : Variant(),
- s >= 4 ? params[3] : Variant(),
- s >= 5 ? params[4] : Variant(),
- s >= 6 ? params[5] : Variant(),
- s >= 7 ? params[6] : Variant(),
- s >= 8 ? params[7] : Variant());
+ _call_object(t->object, method, params, true);
}
}
-
} break;
case Animation::TYPE_BEZIER: {
TrackCacheBezier *t = static_cast<TrackCacheBezier *>(track);
@@ -1331,7 +1331,7 @@ void AnimationTree::_process_graph(double p_delta) {
Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
if (!stream.is_valid()) {
- t->object->call("stop");
+ t->object->call(SNAME("stop"));
t->playing = false;
playing_caches.erase(t);
} else {
@@ -1341,14 +1341,14 @@ void AnimationTree::_process_graph(double p_delta) {
double len = stream->get_length();
if (start_ofs > len - end_ofs) {
- t->object->call("stop");
+ t->object->call(SNAME("stop"));
t->playing = false;
playing_caches.erase(t);
continue;
}
- t->object->call("set_stream", stream);
- t->object->call("play", start_ofs);
+ t->object->call(SNAME("set_stream"), stream);
+ t->object->call(SNAME("play"), start_ofs);
t->playing = true;
playing_caches.insert(t);
@@ -1370,7 +1370,7 @@ void AnimationTree::_process_graph(double p_delta) {
Ref<AudioStream> stream = a->audio_track_get_key_stream(i, idx);
if (!stream.is_valid()) {
- t->object->call("stop");
+ t->object->call(SNAME("stop"));
t->playing = false;
playing_caches.erase(t);
} else {
@@ -1378,8 +1378,8 @@ void AnimationTree::_process_graph(double p_delta) {
double end_ofs = a->audio_track_get_key_end_offset(i, idx);
double len = stream->get_length();
- t->object->call("set_stream", stream);
- t->object->call("play", start_ofs);
+ t->object->call(SNAME("set_stream"), stream);
+ t->object->call(SNAME("play"), start_ofs);
t->playing = true;
playing_caches.insert(t);
@@ -1416,7 +1416,7 @@ void AnimationTree::_process_graph(double p_delta) {
if (stop) {
//time to stop
- t->object->call("stop");
+ t->object->call(SNAME("stop"));
t->playing = false;
playing_caches.erase(t);
}
@@ -1424,10 +1424,10 @@ void AnimationTree::_process_graph(double p_delta) {
}
real_t db = Math::linear2db(MAX(blend, 0.00001));
- if (t->object->has_method("set_unit_db")) {
- t->object->call("set_unit_db", db);
+ if (t->object->has_method(SNAME("set_unit_db"))) {
+ t->object->call(SNAME("set_unit_db"), db);
} else {
- t->object->call("set_volume_db", db);
+ t->object->call(SNAME("set_volume_db"), db);
}
} break;
case Animation::TYPE_ANIMATION: {
diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp
index 46fe832cf5..42adc1ea02 100644
--- a/scene/animation/root_motion_view.cpp
+++ b/scene/animation/root_motion_view.cpp
@@ -166,10 +166,6 @@ AABB RootMotionView::get_aabb() const {
return AABB(Vector3(-radius, 0, -radius), Vector3(radius * 2, 0.001, radius * 2));
}
-Vector<Face3> RootMotionView::get_faces(uint32_t p_usage_flags) const {
- return Vector<Face3>();
-}
-
void RootMotionView::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_animation_path", "path"), &RootMotionView::set_animation_path);
ClassDB::bind_method(D_METHOD("get_animation_path"), &RootMotionView::get_animation_path);
diff --git a/scene/animation/root_motion_view.h b/scene/animation/root_motion_view.h
index e8b141c1fd..8cb8ea8a9a 100644
--- a/scene/animation/root_motion_view.h
+++ b/scene/animation/root_motion_view.h
@@ -71,7 +71,6 @@ public:
bool get_zero_y() const;
virtual AABB get_aabb() const override;
- virtual Vector<Face3> get_faces(uint32_t p_usage_flags) const override;
RootMotionView();
~RootMotionView();
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index e5b81f9d8d..ac0d017a23 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -34,6 +34,7 @@
#include "core/debugger/engine_profiler.h"
#include "core/io/marshalls.h"
#include "core/object/script_language.h"
+#include "core/templates/local_vector.h"
#include "scene/main/scene_tree.h"
#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
@@ -236,12 +237,28 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra
live_editor->_res_set_func(p_args[0], p_args[1], p_args[2]);
} else if (p_msg == "live_node_call") {
- ERR_FAIL_COND_V(p_args.size() < 10, ERR_INVALID_DATA);
- live_editor->_node_call_func(p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5], p_args[6], p_args[7], p_args[8], p_args[9]);
+ LocalVector<Variant> args;
+ LocalVector<Variant *> argptrs;
+ args.resize(p_args.size() - 2);
+ argptrs.resize(args.size());
+ for (uint32_t i = 0; i < args.size(); i++) {
+ args[i] = p_args[i + 2];
+ argptrs[i] = &args[i];
+ }
+ live_editor->_node_call_func(p_args[0], p_args[1], (const Variant **)argptrs.ptr(), argptrs.size());
} else if (p_msg == "live_res_call") {
ERR_FAIL_COND_V(p_args.size() < 10, ERR_INVALID_DATA);
- live_editor->_res_call_func(p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5], p_args[6], p_args[7], p_args[8], p_args[9]);
+
+ LocalVector<Variant> args;
+ LocalVector<Variant *> argptrs;
+ args.resize(p_args.size() - 2);
+ argptrs.resize(args.size());
+ for (uint32_t i = 0; i < args.size(); i++) {
+ args[i] = p_args[i + 2];
+ argptrs[i] = &args[i];
+ }
+ live_editor->_res_call_func(p_args[0], p_args[1], (const Variant **)argptrs.ptr(), argptrs.size());
} else if (p_msg == "live_create_node") {
ERR_FAIL_COND_V(p_args.size() < 3, ERR_INVALID_DATA);
@@ -636,7 +653,7 @@ void LiveEditor::_node_set_res_func(int p_id, const StringName &p_prop, const St
_node_set_func(p_id, p_prop, r);
}
-void LiveEditor::_node_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
+void LiveEditor::_node_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount) {
SceneTree *scene_tree = SceneTree::get_singleton();
if (!scene_tree) {
return;
@@ -668,7 +685,8 @@ void LiveEditor::_node_call_func(int p_id, const StringName &p_method, VARIANT_A
}
Node *n2 = n->get_node(np);
- n2->call(p_method, VARIANT_ARG_PASS);
+ Callable::CallError ce;
+ n2->callp(p_method, p_args, p_argcount, ce);
}
}
@@ -699,7 +717,7 @@ void LiveEditor::_res_set_res_func(int p_id, const StringName &p_prop, const Str
_res_set_func(p_id, p_prop, r);
}
-void LiveEditor::_res_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
+void LiveEditor::_res_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount) {
if (!live_edit_resource_cache.has(p_id)) {
return;
}
@@ -715,7 +733,8 @@ void LiveEditor::_res_call_func(int p_id, const StringName &p_method, VARIANT_AR
return;
}
- r->call(p_method, VARIANT_ARG_PASS);
+ Callable::CallError ce;
+ r->callp(p_method, p_args, p_argcount, ce);
}
void LiveEditor::_root_func(const NodePath &p_scene_path, const String &p_scene_from) {
diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h
index dd0a17c2dc..29d7da7d11 100644
--- a/scene/debugger/scene_debugger.h
+++ b/scene/debugger/scene_debugger.h
@@ -148,10 +148,10 @@ private:
void _node_set_func(int p_id, const StringName &p_prop, const Variant &p_value);
void _node_set_res_func(int p_id, const StringName &p_prop, const String &p_value);
- void _node_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE);
+ void _node_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount);
void _res_set_func(int p_id, const StringName &p_prop, const Variant &p_value);
void _res_set_res_func(int p_id, const StringName &p_prop, const String &p_value);
- void _res_call_func(int p_id, const StringName &p_method, VARIANT_ARG_DECLARE);
+ void _res_call_func(int p_id, const StringName &p_method, const Variant **p_args, int p_argcount);
void _root_func(const NodePath &p_scene_path, const String &p_scene_from);
void _create_node_func(const NodePath &p_parent, const String &p_type, const String &p_name);
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 0338326bbe..ab86face7e 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -349,7 +349,7 @@ Ref<Shortcut> BaseButton::get_shortcut() const {
void BaseButton::unhandled_key_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
- if (!_is_focus_owner_in_shorcut_context()) {
+ if (!_is_focus_owner_in_shortcut_context()) {
return;
}
@@ -404,7 +404,7 @@ Node *BaseButton::get_shortcut_context() const {
return ctx_node;
}
-bool BaseButton::_is_focus_owner_in_shorcut_context() const {
+bool BaseButton::_is_focus_owner_in_shortcut_context() const {
if (shortcut_context == ObjectID()) {
// No context, therefore global - always "in" context.
return true;
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index 6bfffe7575..a2b6ee0845 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -80,7 +80,7 @@ protected:
virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
void _notification(int p_what);
- bool _is_focus_owner_in_shorcut_context() const;
+ bool _is_focus_owner_in_shortcut_context() const;
GDVIRTUAL0(_pressed)
GDVIRTUAL1(_toggled, bool)
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/color_picker.cpp b/scene/gui/color_picker.cpp
index aa4391e9f1..9f32ac223c 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -1304,7 +1304,7 @@ void ColorPickerButton::pressed() {
Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale();
- popup->set_as_minsize();
+ popup->reset_size();
picker->_update_presets();
Rect2i usable_rect = popup->get_usable_parent_rect();
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 46f60c92d9..d2d1b5e9b7 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -190,10 +190,10 @@ String Control::properties_managed_by_container[] = {
"anchor_top",
"anchor_right",
"anchor_bottom",
- "rect_position",
- "rect_rotation",
- "rect_scale",
- "rect_size"
+ "position",
+ "rotation",
+ "scale",
+ "size"
};
void Control::accept_event() {
@@ -250,42 +250,41 @@ Transform2D Control::_get_internal_transform() const {
bool Control::_set(const StringName &p_name, const Variant &p_value) {
String name = p_name;
- // Prefixes "custom_*" are supported for compatibility with 3.x.
- if (!name.begins_with("theme_override") && !name.begins_with("custom")) {
+ if (!name.begins_with("theme_override")) {
return false;
}
if (p_value.get_type() == Variant::NIL || (p_value.get_type() == Variant::OBJECT && (Object *)p_value == nullptr)) {
- if (name.begins_with("theme_override_icons/") || name.begins_with("custom_icons/")) {
+ if (name.begins_with("theme_override_icons/")) {
String dname = name.get_slicec('/', 1);
if (data.icon_override.has(dname)) {
data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed));
}
data.icon_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
- } else if (name.begins_with("theme_override_styles/") || name.begins_with("custom_styles/")) {
+ } else if (name.begins_with("theme_override_styles/")) {
String dname = name.get_slicec('/', 1);
if (data.style_override.has(dname)) {
data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed));
}
data.style_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
- } else if (name.begins_with("theme_override_fonts/") || name.begins_with("custom_fonts/")) {
+ } else if (name.begins_with("theme_override_fonts/")) {
String dname = name.get_slicec('/', 1);
if (data.font_override.has(dname)) {
data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_override_changed));
}
data.font_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
- } else if (name.begins_with("theme_override_font_sizes/") || name.begins_with("custom_font_sizes/")) {
+ } else if (name.begins_with("theme_override_font_sizes/")) {
String dname = name.get_slicec('/', 1);
data.font_size_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
- } else if (name.begins_with("theme_override_colors/") || name.begins_with("custom_colors/")) {
+ } else if (name.begins_with("theme_override_colors/")) {
String dname = name.get_slicec('/', 1);
data.color_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
- } else if (name.begins_with("theme_override_constants/") || name.begins_with("custom_constants/")) {
+ } else if (name.begins_with("theme_override_constants/")) {
String dname = name.get_slicec('/', 1);
data.constant_override.erase(dname);
notification(NOTIFICATION_THEME_CHANGED);
@@ -294,22 +293,22 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) {
}
} else {
- if (name.begins_with("theme_override_icons/") || name.begins_with("custom_icons/")) {
+ if (name.begins_with("theme_override_icons/")) {
String dname = name.get_slicec('/', 1);
add_theme_icon_override(dname, p_value);
- } else if (name.begins_with("theme_override_styles/") || name.begins_with("custom_styles/")) {
+ } else if (name.begins_with("theme_override_styles/")) {
String dname = name.get_slicec('/', 1);
add_theme_style_override(dname, p_value);
- } else if (name.begins_with("theme_override_fonts/") || name.begins_with("custom_fonts/")) {
+ } else if (name.begins_with("theme_override_fonts/")) {
String dname = name.get_slicec('/', 1);
add_theme_font_override(dname, p_value);
- } else if (name.begins_with("theme_override_font_sizes/") || name.begins_with("custom_font_sizes/")) {
+ } else if (name.begins_with("theme_override_font_sizes/")) {
String dname = name.get_slicec('/', 1);
add_theme_font_size_override(dname, p_value);
- } else if (name.begins_with("theme_override_colors/") || name.begins_with("custom_colors/")) {
+ } else if (name.begins_with("theme_override_colors/")) {
String dname = name.get_slicec('/', 1);
add_theme_color_override(dname, p_value);
- } else if (name.begins_with("theme_override_constants/") || name.begins_with("custom_constants/")) {
+ } else if (name.begins_with("theme_override_constants/")) {
String dname = name.get_slicec('/', 1);
add_theme_constant_override(dname, p_value);
} else {
@@ -491,7 +490,7 @@ void Control::_validate_property(PropertyInfo &property) const {
} else if (Object::cast_to<Container>(parent_node)) {
// If the parent is a container, display only container-related properties.
if (property.name.begins_with("anchor_") || property.name.begins_with("offset_") || property.name.begins_with("grow_") || property.name == "anchors_preset" ||
- (property.name.begins_with("rect_") && property.name != "rect_min_size" && property.name != "rect_clip_content" && property.name != "rect_global_position")) {
+ property.name == "position" || property.name == "rotation" || property.name == "scale" || property.name == "size" || property.name == "pivot_offset") {
property.usage ^= PROPERTY_USAGE_EDITOR;
} else if (property.name == "layout_mode") {
@@ -3225,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);
@@ -3343,8 +3343,8 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_auto_translating"), &Control::is_auto_translating);
ADD_GROUP("Layout", "");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rect_clip_content"), "set_clip_contents", "is_clipping_contents");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_min_size"), "set_custom_minimum_size", "get_custom_minimum_size");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_contents"), "set_clip_contents", "is_clipping_contents");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "minimum_size"), "set_custom_minimum_size", "get_custom_minimum_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_direction", PROPERTY_HINT_ENUM, "Inherited,Locale,Left-to-Right,Right-to-Left"), "set_layout_direction", "get_layout_direction");
ADD_PROPERTY(PropertyInfo(Variant::INT, "layout_mode", PROPERTY_HINT_ENUM, "Position,Anchors,Container,Uncontrolled", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_layout_mode", "_get_layout_mode");
ADD_PROPERTY_DEFAULT("layout_mode", LayoutMode::LAYOUT_MODE_POSITION);
@@ -3373,15 +3373,13 @@ void Control::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_horizontal", PROPERTY_HINT_ENUM, "Left,Right,Both"), "set_h_grow_direction", "get_h_grow_direction");
ADD_PROPERTY(PropertyInfo(Variant::INT, "grow_vertical", PROPERTY_HINT_ENUM, "Top,Bottom,Both"), "set_v_grow_direction", "get_v_grow_direction");
- ADD_SUBGROUP("Rectangle", "rect_");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_position", "get_position");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_global_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "_set_global_position", "get_global_position");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_size", "get_size");
-
- ADD_SUBGROUP("Transform", "rect_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rect_rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_scale"), "set_scale", "get_scale");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "rect_pivot_offset"), "set_pivot_offset", "get_pivot_offset");
+ ADD_SUBGROUP("Transform", "");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "_set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "global_position", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "_set_global_position", "get_global_position");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians"), "set_rotation", "get_rotation");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "pivot_offset"), "set_pivot_offset", "get_pivot_offset");
ADD_SUBGROUP("Container Sizing", "size_flags_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "size_flags_horizontal", PROPERTY_HINT_FLAGS, "Fill:1,Expand:2,Shrink Center:4,Shrink End:8"), "set_h_size_flags", "get_h_size_flags");
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/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/line_edit.cpp b/scene/gui/line_edit.cpp
index 6ad296d7c7..da39a3d387 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -647,8 +647,8 @@ void LineEdit::_notification(int p_what) {
#ifdef TOOLS_ENABLED
case NOTIFICATION_ENTER_TREE: {
if (Engine::get_singleton()->is_editor_hint() && !get_tree()->is_node_being_edited(this)) {
- set_caret_blink_enabled(EDITOR_DEF("text_editor/appearance/caret/caret_blink", false));
- set_caret_blink_speed(EDITOR_DEF("text_editor/appearance/caret/caret_blink_speed", 0.65));
+ set_caret_blink_enabled(EDITOR_GET("text_editor/appearance/caret/caret_blink"));
+ set_caret_blink_speed(EDITOR_GET("text_editor/appearance/caret/caret_blink_speed"));
if (!EditorSettings::get_singleton()->is_connected("settings_changed", callable_mp(this, &LineEdit::_editor_settings_changed))) {
EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &LineEdit::_editor_settings_changed));
@@ -1944,8 +1944,8 @@ PopupMenu *LineEdit::get_menu() const {
void LineEdit::_editor_settings_changed() {
#ifdef TOOLS_ENABLED
- set_caret_blink_enabled(EDITOR_DEF("text_editor/appearance/caret/caret_blink", false));
- set_caret_blink_speed(EDITOR_DEF("text_editor/appearance/caret/caret_blink_speed", 0.65));
+ set_caret_blink_enabled(EDITOR_GET("text_editor/appearance/caret/caret_blink"));
+ set_caret_blink_speed(EDITOR_GET("text_editor/appearance/caret/caret_blink_speed"));
#endif
}
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index c04690cdb3..7e724e4d71 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -36,7 +36,7 @@
void MenuButton::unhandled_key_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
- if (!_is_focus_owner_in_shorcut_context()) {
+ if (!_is_focus_owner_in_shortcut_context()) {
return;
}
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 24b91cd16a..b9e3e7814e 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -111,10 +111,6 @@ void Popup::_close_pressed() {
call_deferred(SNAME("hide"));
}
-void Popup::set_as_minsize() {
- set_size(get_contents_minimum_size());
-}
-
void Popup::_bind_methods() {
ADD_SIGNAL(MethodInfo("popup_hide"));
}
diff --git a/scene/gui/popup.h b/scene/gui/popup.h
index a3c56c9ff1..c45f4ddc24 100644
--- a/scene/gui/popup.h
+++ b/scene/gui/popup.h
@@ -58,8 +58,6 @@ protected:
static void _bind_methods();
public:
- void set_as_minsize();
-
Popup();
~Popup();
};
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index af2edfa090..4220066b20 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -186,7 +186,7 @@ void PopupMenu::_activate_submenu(int p_over) {
float scroll_offset = control->get_position().y;
- submenu_popup->set_as_minsize(); // Shrink the popup size to its contents.
+ submenu_popup->reset_size(); // Shrink the popup size to its contents.
Size2 submenu_size = submenu_popup->get_size();
Point2 submenu_pos;
@@ -999,6 +999,9 @@ 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());
items.write[p_idx].text = p_text;
items.write[p_idx].xl_text = atr(p_text);
@@ -1009,6 +1012,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 +1025,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 +1035,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 +1048,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 +1060,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 +1071,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 +1083,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 +1094,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 +1106,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 +1116,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 +1126,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 +1237,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 +1251,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 +1297,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 +1307,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/range.cpp b/scene/gui/range.cpp
index 879f25c8d8..2fb6452a97 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -40,6 +40,9 @@ TypedArray<String> Range::get_configuration_warnings() const {
return warnings;
}
+void Range::_value_changed(double p_value) {
+ GDVIRTUAL_CALL(_value_changed, p_value);
+}
void Range::_value_changed_notify() {
_value_changed(shared->val);
emit_signal(SNAME("value_changed"), shared->val);
@@ -279,6 +282,8 @@ void Range::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_greater"), "set_allow_greater", "is_greater_allowed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "allow_lesser"), "set_allow_lesser", "is_lesser_allowed");
+ GDVIRTUAL_BIND(_value_changed);
+
ADD_LINKED_PROPERTY("min_value", "value");
ADD_LINKED_PROPERTY("min_value", "max_value");
ADD_LINKED_PROPERTY("min_value", "page");
diff --git a/scene/gui/range.h b/scene/gui/range.h
index c27eeee13c..597c50ca26 100644
--- a/scene/gui/range.h
+++ b/scene/gui/range.h
@@ -62,12 +62,14 @@ class Range : public Control {
void _validate_values();
protected:
- virtual void _value_changed(double) {}
+ virtual void _value_changed(double p_value);
static void _bind_methods();
bool _rounded_values = false;
+ GDVIRTUAL1(_value_changed, double)
+
public:
void set_value(double p_val);
void set_min(double p_min);
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 1c9eb14a24..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++;
@@ -3250,6 +3253,10 @@ void RichTextLabel::append_text(const String &p_bbcode) {
push_paragraph(HORIZONTAL_ALIGNMENT_FILL);
pos = brk_end + 1;
tag_stack.push_front(tag);
+ } else if (tag == "left") {
+ push_paragraph(HORIZONTAL_ALIGNMENT_LEFT);
+ pos = brk_end + 1;
+ tag_stack.push_front(tag);
} else if (tag == "right") {
push_paragraph(HORIZONTAL_ALIGNMENT_RIGHT);
pos = brk_end + 1;
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 5fd31c5416..e50d7e765c 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -39,7 +39,7 @@ Size2 SpinBox::get_minimum_size() const {
return ms;
}
-void SpinBox::_value_changed(double) {
+void SpinBox::_value_changed(double p_value) {
String value = TS->format_number(String::num(get_value(), Math::range_step_decimals(get_step())));
if (!prefix.is_empty()) {
value = prefix + " " + value;
@@ -48,6 +48,7 @@ void SpinBox::_value_changed(double) {
value += " " + suffix;
}
line_edit->set_text(value);
+ Range::_value_changed(p_value);
}
void SpinBox::_text_submitted(const String &p_string) {
diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h
index 0691a4b48d..a15e3fe5f5 100644
--- a/scene/gui/spin_box.h
+++ b/scene/gui/spin_box.h
@@ -47,7 +47,7 @@ class SpinBox : public Range {
void _release_mouse();
void _text_submitted(const String &p_string);
- virtual void _value_changed(double) override;
+ virtual void _value_changed(double p_value) override;
void _text_changed(const String &p_string);
String prefix;
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp
index a11248ec6b..af314b9545 100644
--- a/scene/gui/tab_bar.cpp
+++ b/scene/gui/tab_bar.cpp
@@ -71,7 +71,7 @@ Size2 TabBar::get_minimum_size() const {
Ref<Texture2D> tex = tabs[i].icon;
if (tex.is_valid()) {
- ms.height = MAX(ms.height, tex->get_size().height);
+ ms.height = MAX(ms.height, tex->get_size().height + y_margin);
ms.width += tex->get_size().width + hseparation;
}
@@ -91,13 +91,13 @@ Size2 TabBar::get_minimum_size() const {
ms.width += button_highlight->get_margin(SIDE_LEFT) + rb->get_width() + hseparation;
}
- ms.height = MAX(rb->get_height() + style->get_minimum_size().height, ms.height);
+ ms.height = MAX(ms.height, rb->get_height() + y_margin);
}
if (close_visible) {
ms.width += button_highlight->get_margin(SIDE_LEFT) + close->get_width() + hseparation;
- ms.height = MAX(close->get_height() + style->get_minimum_size().height, ms.height);
+ ms.height = MAX(ms.height, close->get_height() + y_margin);
}
if (ms.width - ofs > style->get_minimum_size().width) {
@@ -827,78 +827,52 @@ void TabBar::_update_cache() {
int limit_minus_buttons = limit - incr->get_width() - decr->get_width();
int w = 0;
- int mw = 0;
- int size_fixed = 0;
- int count_resize = 0;
+
+ max_drawn_tab = tabs.size() - 1;
for (int i = 0; i < tabs.size(); i++) {
- tabs.write[i].size_text = Math::ceil(tabs[i].text_buf->get_size().x);
tabs.write[i].text_buf->set_width(-1);
-
- tabs.write[i].ofs_cache = 0;
+ tabs.write[i].size_text = Math::ceil(tabs[i].text_buf->get_size().x);
tabs.write[i].size_cache = get_tab_width(i);
- if (!tabs[i].hidden) {
- mw += tabs[i].size_cache;
+ if (max_width > 0 && tabs[i].size_cache > max_width) {
+ int size_textless = tabs[i].size_cache - tabs[i].size_text;
+ int mw = MAX(size_textless, max_width);
- if (tabs[i].size_cache <= min_width || i == current) {
- size_fixed += tabs[i].size_cache;
- } else {
- count_resize++;
- }
+ tabs.write[i].size_text = MAX(mw - size_textless, 1);
+ tabs.write[i].text_buf->set_width(tabs[i].size_text);
+ tabs.write[i].size_cache = size_textless + tabs[i].size_text;
}
- }
-
- int m_width = min_width;
- if (count_resize > 0) {
- m_width = MAX((limit_minus_buttons - size_fixed) / count_resize, min_width);
- }
-
- for (int i = offset; i < tabs.size(); i++) {
- if (tabs[i].hidden) {
- tabs.write[i].ofs_cache = w;
- max_drawn_tab = i;
+ if (i < offset || i > max_drawn_tab) {
+ tabs.write[i].ofs_cache = 0;
continue;
}
- int lsize = tabs[i].size_cache;
- int slen = tabs[i].size_text;
+ tabs.write[i].ofs_cache = w;
- // FIXME: This is completely broken.
- if (min_width > 0 && (mw > limit || (offset > 0 && mw > limit_minus_buttons)) && i != current && lsize > m_width) {
- slen = MAX(m_width - tabs[i].size_cache + tabs[i].size_text, 1);
- lsize = m_width;
+ if (tabs[i].hidden) {
+ continue;
}
- tabs.write[i].ofs_cache = w;
- tabs.write[i].size_cache = lsize;
- tabs.write[i].size_text = slen;
- tabs.write[i].text_buf->set_width(slen);
-
- w += lsize;
- max_drawn_tab = i;
+ w += tabs[i].size_cache;
// Check if all tabs would fit inside the area.
if (clip_tabs && i > offset && (w > limit || (offset > 0 && w > limit_minus_buttons))) {
tabs.write[i].ofs_cache = 0;
- tabs.write[i].text_buf->set_width(-1);
w -= tabs[i].size_cache;
- max_drawn_tab--;
+ max_drawn_tab = i - 1;
while (w > limit_minus_buttons && max_drawn_tab > offset) {
tabs.write[max_drawn_tab].ofs_cache = 0;
if (!tabs[max_drawn_tab].hidden) {
- tabs.write[max_drawn_tab].text_buf->set_width(-1);
w -= tabs[max_drawn_tab].size_cache;
}
max_drawn_tab--;
}
-
- break;
}
}
@@ -938,12 +912,11 @@ void TabBar::_on_mouse_exited() {
void TabBar::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
Tab t;
t.text = p_str;
- t.xl_text = atr(p_str);
t.text_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR);
- t.text_buf->add_string(t.xl_text, get_theme_font(SNAME("font")), get_theme_font_size(SNAME("font_size")), Dictionary(), TranslationServer::get_singleton()->get_tool_locale());
t.icon = p_icon;
tabs.push_back(t);
+ _shape(tabs.size() - 1);
_update_cache();
if (scroll_to_selected) {
ensure_tab_visible(current);
@@ -1379,8 +1352,21 @@ TabBar::CloseButtonDisplayPolicy TabBar::get_tab_close_display_policy() const {
return cb_displaypolicy;
}
-void TabBar::set_min_width(int p_width) {
- min_width = p_width;
+void TabBar::set_max_tab_width(int p_width) {
+ ERR_FAIL_COND(p_width < 0);
+ max_width = p_width;
+
+ _update_cache();
+ _ensure_no_over_offset();
+ if (scroll_to_selected) {
+ ensure_tab_visible(current);
+ }
+ update();
+ update_minimum_size();
+}
+
+int TabBar::get_max_tab_width() const {
+ return max_width;
}
void TabBar::set_scrolling_enabled(bool p_enabled) {
@@ -1515,6 +1501,8 @@ void TabBar::_bind_methods() {
ClassDB::bind_method(D_METHOD("move_tab", "from", "to"), &TabBar::move_tab);
ClassDB::bind_method(D_METHOD("set_tab_close_display_policy", "policy"), &TabBar::set_tab_close_display_policy);
ClassDB::bind_method(D_METHOD("get_tab_close_display_policy"), &TabBar::get_tab_close_display_policy);
+ ClassDB::bind_method(D_METHOD("set_max_tab_width", "width"), &TabBar::set_max_tab_width);
+ ClassDB::bind_method(D_METHOD("get_max_tab_width"), &TabBar::get_max_tab_width);
ClassDB::bind_method(D_METHOD("set_scrolling_enabled", "enabled"), &TabBar::set_scrolling_enabled);
ClassDB::bind_method(D_METHOD("get_scrolling_enabled"), &TabBar::get_scrolling_enabled);
ClassDB::bind_method(D_METHOD("set_drag_to_rearrange_enabled", "enabled"), &TabBar::set_drag_to_rearrange_enabled);
@@ -1539,6 +1527,7 @@ void TabBar::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_alignment", "get_tab_alignment");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_tabs"), "set_clip_tabs", "get_clip_tabs");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "max_tab_width", PROPERTY_HINT_RANGE, "0,99999,1"), "set_max_tab_width", "get_max_tab_width");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_rearrange_group"), "set_tabs_rearrange_group", "get_tabs_rearrange_group");
diff --git a/scene/gui/tab_bar.h b/scene/gui/tab_bar.h
index 82ae8bce3f..0f2184aca7 100644
--- a/scene/gui/tab_bar.h
+++ b/scene/gui/tab_bar.h
@@ -98,7 +98,7 @@ private:
CloseButtonDisplayPolicy cb_displaypolicy = CLOSE_BUTTON_SHOW_NEVER;
int hover = -1; // Hovered tab.
- int min_width = 0;
+ int max_width = 0;
bool scrolling_enabled = true;
bool drag_to_rearrange_enabled = false;
bool scroll_to_selected = true;
@@ -198,7 +198,9 @@ public:
bool get_select_with_rmb() const;
void ensure_tab_visible(int p_idx);
- void set_min_width(int p_width);
+
+ void set_max_tab_width(int p_width);
+ int get_max_tab_width() const;
Rect2 get_tab_rect(int p_tab) const;
Size2 get_minimum_size() const override;
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 102fe18502..ee61c862b7 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -624,7 +624,7 @@ void TabContainer::set_all_tabs_in_front(bool p_in_front) {
all_tabs_in_front = p_in_front;
remove_child(tab_bar);
- add_child(tab_bar, false, all_tabs_in_front ? INTERNAL_MODE_BACK : INTERNAL_MODE_FRONT);
+ add_child(tab_bar, false, all_tabs_in_front ? INTERNAL_MODE_FRONT : INTERNAL_MODE_BACK);
}
bool TabContainer::is_all_tabs_in_front() const {
@@ -635,14 +635,13 @@ void TabContainer::set_tab_title(int p_tab, const String &p_title) {
Control *child = get_tab_control(p_tab);
ERR_FAIL_COND(!child);
- if (p_title.is_empty()) {
- tab_bar->set_tab_title(p_tab, String(child->get_name()));
+ tab_bar->set_tab_title(p_tab, p_title);
+ if (p_title == child->get_name()) {
if (child->has_meta("_tab_name")) {
child->remove_meta("_tab_name");
}
} else {
- tab_bar->set_tab_title(p_tab, p_title);
child->set_meta("_tab_name", p_title);
}
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/gui/tree.cpp b/scene/gui/tree.cpp
index 5afc37061b..ff8d2b88b1 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1186,7 +1186,7 @@ void recursive_call_aux(TreeItem *p_item, const StringName &p_method, const Vari
if (!p_item) {
return;
}
- p_item->call(p_method, p_args, p_argcount, r_error);
+ p_item->callp(p_method, p_args, p_argcount, r_error);
TreeItem *c = p_item->get_first_child();
while (c) {
recursive_call_aux(c, p_method, p_args, p_argcount, r_error);
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index d2f5b52dbf..1d263ba858 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);
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 211667ce38..208bbe4d72 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -211,7 +211,7 @@ void Node::_propagate_enter_tree() {
if (data.parent) {
Variant c = this;
const Variant *cptr = &c;
- data.parent->emit_signal(SNAME("child_entered_tree"), &cptr, 1);
+ data.parent->emit_signalp(SNAME("child_entered_tree"), &cptr, 1);
}
data.blocked++;
@@ -287,7 +287,7 @@ void Node::_propagate_exit_tree() {
if (data.parent) {
Variant c = this;
const Variant *cptr = &c;
- data.parent->emit_signal(SNAME("child_exited_tree"), &cptr, 1);
+ data.parent->emit_signalp(SNAME("child_exited_tree"), &cptr, 1);
}
// exit groups
@@ -582,34 +582,6 @@ uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc
/***** RPC FUNCTIONS ********/
-void Node::rpc(const StringName &p_method, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS;
-
- int argc = 0;
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- argc++;
- }
-
- rpcp(0, p_method, argptr, argc);
-}
-
-void Node::rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE) {
- VARIANT_ARGPTRS;
-
- int argc = 0;
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- argc++;
- }
-
- rpcp(p_peer_id, p_method, argptr, argc);
-}
-
Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
if (p_argcount < 1) {
r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
@@ -2389,42 +2361,6 @@ void Node::_replace_connections_target(Node *p_new_target) {
}
}
-Vector<Variant> Node::make_binds(VARIANT_ARG_DECLARE) {
- Vector<Variant> ret;
-
- if (p_arg1.get_type() == Variant::NIL) {
- return ret;
- } else {
- ret.push_back(p_arg1);
- }
-
- if (p_arg2.get_type() == Variant::NIL) {
- return ret;
- } else {
- ret.push_back(p_arg2);
- }
-
- if (p_arg3.get_type() == Variant::NIL) {
- return ret;
- } else {
- ret.push_back(p_arg3);
- }
-
- if (p_arg4.get_type() == Variant::NIL) {
- return ret;
- } else {
- ret.push_back(p_arg4);
- }
-
- if (p_arg5.get_type() == Variant::NIL) {
- return ret;
- } else {
- ret.push_back(p_arg5);
- }
-
- return ret;
-}
-
bool Node::has_node_and_resource(const NodePath &p_path) const {
if (!has_node(p_path)) {
return false;
diff --git a/scene/main/node.h b/scene/main/node.h
index 8e49f871a7..f5fbcf6587 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -420,7 +420,11 @@ public:
void set_scene_instance_load_placeholder(bool p_enable);
bool get_scene_instance_load_placeholder() const;
- static Vector<Variant> make_binds(VARIANT_ARG_LIST);
+ template <typename... VarArgs>
+ Vector<Variant> make_binds(VarArgs... p_args) {
+ Vector<Variant> binds = { p_args... };
+ return binds;
+ }
void replace_by(Node *p_node, bool p_keep_data = false);
@@ -472,8 +476,26 @@ public:
uint16_t rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, bool p_call_local = false, Multiplayer::TransferMode p_transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE, int p_channel = 0); // config a local method for RPC
Vector<Multiplayer::RPCConfig> get_node_rpc_methods() const;
- void rpc(const StringName &p_method, VARIANT_ARG_LIST); // RPC, honors RPCMode, TransferMode, channel
- void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); // RPC to specific peer(s), honors RPCMode, TransferMode, channel
+ template <typename... VarArgs>
+ void rpc(const StringName &p_method, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ rpcp(0, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+ }
+
+ template <typename... VarArgs>
+ void rpc_id(int p_peer_id, const StringName &p_method, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ rpcp(p_peer_id, p_method, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+ }
+
void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount);
Ref<MultiplayerAPI> get_multiplayer() const;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index d1e8b477a6..3ddce28b69 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -175,13 +175,13 @@ void SceneTree::_flush_ugc() {
while (unique_group_calls.size()) {
Map<UGCall, Vector<Variant>>::Element *E = unique_group_calls.front();
- Variant v[VARIANT_ARG_MAX];
+ const Variant **argptrs = (const Variant **)alloca(E->get().size() * sizeof(Variant *));
+
for (int i = 0; i < E->get().size(); i++) {
- v[i] = E->get()[i];
+ argptrs[i] = &E->get()[i];
}
- static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
- call_group_flags(GROUP_CALL_REALTIME, E->key().group, E->key().call, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+ call_group_flagsp(GROUP_CALL_REALTIME, E->key().group, E->key().call, argptrs, E->get().size());
unique_group_calls.erase(E);
}
@@ -210,7 +210,7 @@ void SceneTree::_update_group_order(Group &g, bool p_use_priority) {
g.changed = false;
}
-void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, VARIANT_ARG_DECLARE) {
+void SceneTree::call_group_flagsp(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, const Variant **p_args, int p_argcount) {
Map<StringName, Group>::Element *E = group_map.find(p_group);
if (!E) {
return;
@@ -231,14 +231,9 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou
return;
}
- VARIANT_ARGPTRS;
-
Vector<Variant> args;
- for (int i = 0; i < VARIANT_ARG_MAX; i++) {
- if (argptr[i]->get_type() == Variant::NIL) {
- break;
- }
- args.push_back(*argptr[i]);
+ for (int i = 0; i < p_argcount; i++) {
+ args.push_back(*p_args[i]);
}
unique_group_calls[ug] = args;
@@ -260,9 +255,10 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou
}
if (p_call_flags & GROUP_CALL_REALTIME) {
- nodes[i]->call(p_function, VARIANT_ARG_PASS);
+ Callable::CallError ce;
+ nodes[i]->callp(p_function, p_args, p_argcount, ce);
} else {
- MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS);
+ MessageQueue::get_singleton()->push_callp(nodes[i], p_function, p_args, p_argcount);
}
}
@@ -273,9 +269,10 @@ void SceneTree::call_group_flags(uint32_t p_call_flags, const StringName &p_grou
}
if (p_call_flags & GROUP_CALL_REALTIME) {
- nodes[i]->call(p_function, VARIANT_ARG_PASS);
+ Callable::CallError ce;
+ nodes[i]->callp(p_function, p_args, p_argcount, ce);
} else {
- MessageQueue::get_singleton()->push_call(nodes[i], p_function, VARIANT_ARG_PASS);
+ MessageQueue::get_singleton()->push_callp(nodes[i], p_function, p_args, p_argcount);
}
}
}
@@ -388,10 +385,6 @@ void SceneTree::set_group_flags(uint32_t p_call_flags, const StringName &p_group
}
}
-void SceneTree::call_group(const StringName &p_group, const StringName &p_function, VARIANT_ARG_DECLARE) {
- call_group_flags(0, p_group, p_function, VARIANT_ARG_PASS);
-}
-
void SceneTree::notify_group(const StringName &p_group, int p_notification) {
notify_group_flags(0, p_group, p_notification);
}
@@ -930,14 +923,8 @@ Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Cal
int flags = *p_args[0];
StringName group = *p_args[1];
StringName method = *p_args[2];
- Variant v[VARIANT_ARG_MAX];
-
- for (int i = 0; i < MIN(p_argcount - 3, 5); i++) {
- v[i] = *p_args[i + 3];
- }
- static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
- call_group_flags(flags, group, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+ call_group_flagsp(flags, group, method, p_args + 3, p_argcount - 3);
return Variant();
}
@@ -950,14 +937,8 @@ Variant SceneTree::_call_group(const Variant **p_args, int p_argcount, Callable:
StringName group = *p_args[0];
StringName method = *p_args[1];
- Variant v[VARIANT_ARG_MAX];
-
- for (int i = 0; i < MIN(p_argcount - 2, 5); i++) {
- v[i] = *p_args[i + 2];
- }
- static_assert(VARIANT_ARG_MAX == 8, "This code needs to be updated if VARIANT_ARG_MAX != 8");
- call_group_flags(0, group, method, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
+ call_group_flagsp(0, group, method, p_args + 2, p_argcount - 2);
return Variant();
}
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 5f7c1729e8..6197e52fc1 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -229,14 +229,33 @@ public:
_FORCE_INLINE_ Window *get_root() const { return root; }
- void call_group_flags(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, VARIANT_ARG_LIST);
+ void call_group_flagsp(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, const Variant **p_args, int p_argcount);
void notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification);
void set_group_flags(uint32_t p_call_flags, const StringName &p_group, const String &p_name, const Variant &p_value);
- void call_group(const StringName &p_group, const StringName &p_function, VARIANT_ARG_LIST);
void notify_group(const StringName &p_group, int p_notification);
void set_group(const StringName &p_group, const String &p_name, const Variant &p_value);
+ template <typename... VarArgs>
+ void call_group(const StringName &p_group, const StringName &p_function, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ call_group_flagsp(0, p_group, p_function, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+ }
+
+ template <typename... VarArgs>
+ void call_group_flags(uint32_t p_flags, const StringName &p_group, const StringName &p_function, VarArgs... p_args) {
+ Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported.
+ const Variant *argptrs[sizeof...(p_args) + 1];
+ for (uint32_t i = 0; i < sizeof...(p_args); i++) {
+ argptrs[i] = &args[i];
+ }
+ call_group_flagsp(p_flags, p_group, p_function, sizeof...(p_args) == 0 ? nullptr : (const Variant **)argptrs, sizeof...(p_args));
+ }
+
void flush_transform_notifications();
virtual void initialize() override;
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/multiplayer/scene_rpc_interface.cpp b/scene/multiplayer/scene_rpc_interface.cpp
index 2239a5d81c..84700a82f3 100644
--- a/scene/multiplayer/scene_rpc_interface.cpp
+++ b/scene/multiplayer/scene_rpc_interface.cpp
@@ -278,7 +278,7 @@ void SceneRPCInterface::_process_rpc(Node *p_node, const uint16_t p_rpc_method_i
Callable::CallError ce;
- p_node->call(config.name, (const Variant **)argp.ptr(), argc, ce);
+ p_node->callp(config.name, (const Variant **)argp.ptr(), argc, ce);
if (ce.error != Callable::CallError::CALL_OK) {
String error = Variant::get_call_error_text(p_node, config.name, (const Variant **)argp.ptr(), argc, ce);
error = "RPC - " + error;
@@ -480,7 +480,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
Callable::CallError ce;
multiplayer->set_remote_sender_override(peer->get_unique_id());
- node->call(p_method, p_arg, p_argcount, ce);
+ node->callp(p_method, p_arg, p_argcount, ce);
multiplayer->set_remote_sender_override(0);
if (ce.error != Callable::CallError::CALL_OK) {
@@ -496,7 +496,7 @@ void SceneRPCInterface::rpcp(Object *p_obj, int p_peer_id, const StringName &p_m
ce.error = Callable::CallError::CALL_OK;
multiplayer->set_remote_sender_override(peer->get_unique_id());
- node->get_script_instance()->call(p_method, p_arg, p_argcount, ce);
+ node->get_script_instance()->callp(p_method, p_arg, p_argcount, ce);
multiplayer->set_remote_sender_override(0);
if (ce.error != Callable::CallError::CALL_OK) {
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 228733c4c2..fb5d57ab9e 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -300,9 +300,9 @@ void register_scene_types() {
GDREGISTER_CLASS(Object);
GDREGISTER_CLASS(Node);
- GDREGISTER_VIRTUAL_CLASS(InstancePlaceholder);
+ GDREGISTER_ABSTRACT_CLASS(InstancePlaceholder);
- GDREGISTER_VIRTUAL_CLASS(Viewport);
+ GDREGISTER_ABSTRACT_CLASS(Viewport);
GDREGISTER_CLASS(SubViewport);
GDREGISTER_CLASS(ViewportTexture);
GDREGISTER_CLASS(HTTPRequest);
@@ -324,11 +324,11 @@ void register_scene_types() {
GDREGISTER_CLASS(Control);
GDREGISTER_CLASS(Button);
GDREGISTER_CLASS(Label);
- GDREGISTER_VIRTUAL_CLASS(ScrollBar);
+ GDREGISTER_ABSTRACT_CLASS(ScrollBar);
GDREGISTER_CLASS(HScrollBar);
GDREGISTER_CLASS(VScrollBar);
GDREGISTER_CLASS(ProgressBar);
- GDREGISTER_VIRTUAL_CLASS(Slider);
+ GDREGISTER_ABSTRACT_CLASS(Slider);
GDREGISTER_CLASS(HSlider);
GDREGISTER_CLASS(VSlider);
GDREGISTER_CLASS(Popup);
@@ -349,19 +349,19 @@ void register_scene_types() {
GDREGISTER_CLASS(AspectRatioContainer);
GDREGISTER_CLASS(TabContainer);
GDREGISTER_CLASS(TabBar);
- GDREGISTER_VIRTUAL_CLASS(Separator);
+ GDREGISTER_ABSTRACT_CLASS(Separator);
GDREGISTER_CLASS(HSeparator);
GDREGISTER_CLASS(VSeparator);
GDREGISTER_CLASS(TextureButton);
GDREGISTER_CLASS(Container);
- GDREGISTER_VIRTUAL_CLASS(BoxContainer);
+ GDREGISTER_ABSTRACT_CLASS(BoxContainer);
GDREGISTER_CLASS(HBoxContainer);
GDREGISTER_CLASS(VBoxContainer);
GDREGISTER_CLASS(GridContainer);
GDREGISTER_CLASS(CenterContainer);
GDREGISTER_CLASS(ScrollContainer);
GDREGISTER_CLASS(PanelContainer);
- GDREGISTER_VIRTUAL_CLASS(FlowContainer);
+ GDREGISTER_ABSTRACT_CLASS(FlowContainer);
GDREGISTER_CLASS(HFlowContainer);
GDREGISTER_CLASS(VFlowContainer);
@@ -384,7 +384,7 @@ void register_scene_types() {
GDREGISTER_CLASS(SyntaxHighlighter);
GDREGISTER_CLASS(CodeHighlighter);
- GDREGISTER_VIRTUAL_CLASS(TreeItem);
+ GDREGISTER_ABSTRACT_CLASS(TreeItem);
GDREGISTER_CLASS(OptionButton);
GDREGISTER_CLASS(SpinBox);
GDREGISTER_CLASS(ColorPicker);
@@ -398,7 +398,7 @@ void register_scene_types() {
GDREGISTER_CLASS(MarginContainer);
GDREGISTER_CLASS(SubViewportContainer);
- GDREGISTER_VIRTUAL_CLASS(SplitContainer);
+ GDREGISTER_ABSTRACT_CLASS(SplitContainer);
GDREGISTER_CLASS(HSplitContainer);
GDREGISTER_CLASS(VSplitContainer);
@@ -418,7 +418,7 @@ void register_scene_types() {
GDREGISTER_CLASS(AnimationPlayer);
GDREGISTER_CLASS(Tween);
- GDREGISTER_VIRTUAL_CLASS(Tweener);
+ GDREGISTER_ABSTRACT_CLASS(Tweener);
GDREGISTER_CLASS(PropertyTweener);
GDREGISTER_CLASS(IntervalTweener);
GDREGISTER_CLASS(CallbackTweener);
@@ -453,9 +453,9 @@ void register_scene_types() {
#ifndef _3D_DISABLED
GDREGISTER_CLASS(Node3D);
- GDREGISTER_VIRTUAL_CLASS(Node3DGizmo);
+ GDREGISTER_ABSTRACT_CLASS(Node3DGizmo);
GDREGISTER_CLASS(Skin);
- GDREGISTER_VIRTUAL_CLASS(SkinReference);
+ GDREGISTER_ABSTRACT_CLASS(SkinReference);
GDREGISTER_CLASS(Skeleton3D);
GDREGISTER_CLASS(ImporterMesh);
GDREGISTER_CLASS(ImporterMeshInstance3D);
@@ -464,22 +464,22 @@ void register_scene_types() {
GDREGISTER_CLASS(Camera3D);
GDREGISTER_CLASS(AudioListener3D);
GDREGISTER_CLASS(XRCamera3D);
- GDREGISTER_VIRTUAL_CLASS(XRNode3D);
+ GDREGISTER_ABSTRACT_CLASS(XRNode3D);
GDREGISTER_CLASS(XRController3D);
GDREGISTER_CLASS(XRAnchor3D);
GDREGISTER_CLASS(XROrigin3D);
GDREGISTER_CLASS(MeshInstance3D);
GDREGISTER_CLASS(OccluderInstance3D);
- GDREGISTER_VIRTUAL_CLASS(Occluder3D);
+ GDREGISTER_ABSTRACT_CLASS(Occluder3D);
GDREGISTER_CLASS(ArrayOccluder3D);
GDREGISTER_CLASS(QuadOccluder3D);
GDREGISTER_CLASS(BoxOccluder3D);
GDREGISTER_CLASS(SphereOccluder3D);
GDREGISTER_CLASS(PolygonOccluder3D);
- GDREGISTER_VIRTUAL_CLASS(SpriteBase3D);
+ GDREGISTER_ABSTRACT_CLASS(SpriteBase3D);
GDREGISTER_CLASS(Sprite3D);
GDREGISTER_CLASS(AnimatedSprite3D);
- GDREGISTER_VIRTUAL_CLASS(Light3D);
+ GDREGISTER_ABSTRACT_CLASS(Light3D);
GDREGISTER_CLASS(DirectionalLight3D);
GDREGISTER_CLASS(OmniLight3D);
GDREGISTER_CLASS(SpotLight3D);
@@ -490,14 +490,14 @@ void register_scene_types() {
GDREGISTER_CLASS(LightmapGI);
GDREGISTER_CLASS(LightmapGIData);
GDREGISTER_CLASS(LightmapProbe);
- GDREGISTER_VIRTUAL_CLASS(Lightmapper);
+ GDREGISTER_ABSTRACT_CLASS(Lightmapper);
GDREGISTER_CLASS(GPUParticles3D);
- GDREGISTER_VIRTUAL_CLASS(GPUParticlesCollision3D);
+ GDREGISTER_ABSTRACT_CLASS(GPUParticlesCollision3D);
GDREGISTER_CLASS(GPUParticlesCollisionBox3D);
GDREGISTER_CLASS(GPUParticlesCollisionSphere3D);
GDREGISTER_CLASS(GPUParticlesCollisionSDF3D);
GDREGISTER_CLASS(GPUParticlesCollisionHeightField3D);
- GDREGISTER_VIRTUAL_CLASS(GPUParticlesAttractor3D);
+ GDREGISTER_ABSTRACT_CLASS(GPUParticlesAttractor3D);
GDREGISTER_CLASS(GPUParticlesAttractorBox3D);
GDREGISTER_CLASS(GPUParticlesAttractorSphere3D);
GDREGISTER_CLASS(GPUParticlesAttractorVectorField3D);
@@ -509,8 +509,8 @@ void register_scene_types() {
OS::get_singleton()->yield(); // may take time to init
- GDREGISTER_VIRTUAL_CLASS(CollisionObject3D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsBody3D);
+ GDREGISTER_ABSTRACT_CLASS(CollisionObject3D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsBody3D);
GDREGISTER_CLASS(StaticBody3D);
GDREGISTER_CLASS(AnimatableBody3D);
GDREGISTER_CLASS(RigidDynamicBody3D);
@@ -542,7 +542,7 @@ void register_scene_types() {
GDREGISTER_CLASS(FogMaterial);
GDREGISTER_CLASS(RemoteTransform3D);
- GDREGISTER_VIRTUAL_CLASS(Joint3D);
+ GDREGISTER_ABSTRACT_CLASS(Joint3D);
GDREGISTER_CLASS(PinJoint3D);
GDREGISTER_CLASS(HingeJoint3D);
GDREGISTER_CLASS(SliderJoint3D);
@@ -560,14 +560,14 @@ void register_scene_types() {
GDREGISTER_CLASS(Shader);
GDREGISTER_CLASS(VisualShader);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNode);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNode);
GDREGISTER_CLASS(VisualShaderNodeCustom);
GDREGISTER_CLASS(VisualShaderNodeInput);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeOutput);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeResizableBase);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeGroupBase);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeConstant);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeVectorBase);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeOutput);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeResizableBase);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeGroupBase);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeConstant);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeVectorBase);
GDREGISTER_CLASS(VisualShaderNodeComment);
GDREGISTER_CLASS(VisualShaderNodeFloatConstant);
GDREGISTER_CLASS(VisualShaderNodeIntConstant);
@@ -607,11 +607,11 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeTexture);
GDREGISTER_CLASS(VisualShaderNodeCurveTexture);
GDREGISTER_CLASS(VisualShaderNodeCurveXYZTexture);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeSample3D);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeSample3D);
GDREGISTER_CLASS(VisualShaderNodeTexture2DArray);
GDREGISTER_CLASS(VisualShaderNodeTexture3D);
GDREGISTER_CLASS(VisualShaderNodeCubemap);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeUniform);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeUniform);
GDREGISTER_CLASS(VisualShaderNodeUniformRef);
GDREGISTER_CLASS(VisualShaderNodeFloatUniform);
GDREGISTER_CLASS(VisualShaderNodeIntUniform);
@@ -634,6 +634,9 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeCompare);
GDREGISTER_CLASS(VisualShaderNodeMultiplyAdd);
GDREGISTER_CLASS(VisualShaderNodeBillboard);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeVarying);
+ GDREGISTER_CLASS(VisualShaderNodeVaryingSetter);
+ GDREGISTER_CLASS(VisualShaderNodeVaryingGetter);
GDREGISTER_CLASS(VisualShaderNodeSDFToScreenUV);
GDREGISTER_CLASS(VisualShaderNodeScreenUVToSDF);
@@ -642,7 +645,7 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeSDFRaymarch);
GDREGISTER_CLASS(VisualShaderNodeParticleOutput);
- GDREGISTER_VIRTUAL_CLASS(VisualShaderNodeParticleEmitter);
+ GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeParticleEmitter);
GDREGISTER_CLASS(VisualShaderNodeParticleSphereEmitter);
GDREGISTER_CLASS(VisualShaderNodeParticleBoxEmitter);
GDREGISTER_CLASS(VisualShaderNodeParticleRingEmitter);
@@ -654,7 +657,7 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeParticleEmit);
GDREGISTER_CLASS(ShaderMaterial);
- GDREGISTER_VIRTUAL_CLASS(CanvasItem);
+ GDREGISTER_ABSTRACT_CLASS(CanvasItem);
GDREGISTER_CLASS(CanvasTexture);
GDREGISTER_CLASS(CanvasItemMaterial);
SceneTree::add_idle_callback(CanvasItemMaterial::flush_changes);
@@ -673,8 +676,8 @@ void register_scene_types() {
GDREGISTER_CLASS(Line2D);
GDREGISTER_CLASS(MeshInstance2D);
GDREGISTER_CLASS(MultiMeshInstance2D);
- GDREGISTER_VIRTUAL_CLASS(CollisionObject2D);
- GDREGISTER_VIRTUAL_CLASS(PhysicsBody2D);
+ GDREGISTER_ABSTRACT_CLASS(CollisionObject2D);
+ GDREGISTER_ABSTRACT_CLASS(PhysicsBody2D);
GDREGISTER_CLASS(StaticBody2D);
GDREGISTER_CLASS(AnimatableBody2D);
GDREGISTER_CLASS(RigidDynamicBody2D);
@@ -690,7 +693,7 @@ void register_scene_types() {
GDREGISTER_CLASS(Polygon2D);
GDREGISTER_CLASS(Skeleton2D);
GDREGISTER_CLASS(Bone2D);
- GDREGISTER_VIRTUAL_CLASS(Light2D);
+ GDREGISTER_ABSTRACT_CLASS(Light2D);
GDREGISTER_CLASS(PointLight2D);
GDREGISTER_CLASS(DirectionalLight2D);
GDREGISTER_CLASS(LightOccluder2D);
@@ -701,12 +704,12 @@ void register_scene_types() {
GDREGISTER_CLASS(Camera2D);
GDREGISTER_CLASS(AudioListener2D);
- GDREGISTER_VIRTUAL_CLASS(Joint2D);
+ GDREGISTER_ABSTRACT_CLASS(Joint2D);
GDREGISTER_CLASS(PinJoint2D);
GDREGISTER_CLASS(GrooveJoint2D);
GDREGISTER_CLASS(DampedSpringJoint2D);
GDREGISTER_CLASS(TileSet);
- GDREGISTER_VIRTUAL_CLASS(TileSetSource);
+ GDREGISTER_ABSTRACT_CLASS(TileSetSource);
GDREGISTER_CLASS(TileSetAtlasSource);
GDREGISTER_CLASS(TileSetScenesCollectionSource);
GDREGISTER_CLASS(TileMapPattern);
@@ -733,7 +736,7 @@ void register_scene_types() {
/* REGISTER RESOURCES */
- GDREGISTER_VIRTUAL_CLASS(Shader);
+ GDREGISTER_ABSTRACT_CLASS(Shader);
GDREGISTER_CLASS(ParticlesMaterial);
SceneTree::add_idle_callback(ParticlesMaterial::flush_changes);
ParticlesMaterial::init_shaders();
@@ -762,7 +765,7 @@ void register_scene_types() {
GDREGISTER_CLASS(RibbonTrailMesh);
GDREGISTER_CLASS(PointMesh);
GDREGISTER_VIRTUAL_CLASS(Material);
- GDREGISTER_VIRTUAL_CLASS(BaseMaterial3D);
+ GDREGISTER_ABSTRACT_CLASS(BaseMaterial3D);
GDREGISTER_CLASS(StandardMaterial3D);
GDREGISTER_CLASS(ORMMaterial3D);
SceneTree::add_idle_callback(BaseMaterial3D::flush_changes);
@@ -772,7 +775,7 @@ void register_scene_types() {
OS::get_singleton()->yield(); // may take time to init
- GDREGISTER_VIRTUAL_CLASS(Shape3D);
+ GDREGISTER_ABSTRACT_CLASS(Shape3D);
GDREGISTER_CLASS(SeparationRayShape3D);
GDREGISTER_CLASS(SphereShape3D);
GDREGISTER_CLASS(BoxShape3D);
@@ -817,14 +820,14 @@ void register_scene_types() {
GDREGISTER_CLASS(AnimatedTexture);
GDREGISTER_CLASS(CameraTexture);
GDREGISTER_VIRTUAL_CLASS(TextureLayered);
- GDREGISTER_VIRTUAL_CLASS(ImageTextureLayered);
+ GDREGISTER_ABSTRACT_CLASS(ImageTextureLayered);
GDREGISTER_VIRTUAL_CLASS(Texture3D);
GDREGISTER_CLASS(ImageTexture3D);
GDREGISTER_CLASS(CompressedTexture3D);
GDREGISTER_CLASS(Cubemap);
GDREGISTER_CLASS(CubemapArray);
GDREGISTER_CLASS(Texture2DArray);
- GDREGISTER_VIRTUAL_CLASS(CompressedTextureLayered);
+ GDREGISTER_ABSTRACT_CLASS(CompressedTextureLayered);
GDREGISTER_CLASS(CompressedCubemap);
GDREGISTER_CLASS(CompressedCubemapArray);
GDREGISTER_CLASS(CompressedTexture2DArray);
@@ -857,12 +860,12 @@ void register_scene_types() {
#ifndef _3D_DISABLED
GDREGISTER_CLASS(AudioStreamPlayer3D);
#endif
- GDREGISTER_VIRTUAL_CLASS(VideoStream);
+ GDREGISTER_ABSTRACT_CLASS(VideoStream);
GDREGISTER_CLASS(AudioStreamSample);
OS::get_singleton()->yield(); // may take time to init
- GDREGISTER_VIRTUAL_CLASS(Shape2D);
+ GDREGISTER_ABSTRACT_CLASS(Shape2D);
GDREGISTER_CLASS(WorldBoundaryShape2D);
GDREGISTER_CLASS(SegmentShape2D);
GDREGISTER_CLASS(SeparationRayShape2D);
@@ -883,11 +886,11 @@ void register_scene_types() {
OS::get_singleton()->yield(); // may take time to init
- GDREGISTER_VIRTUAL_CLASS(SceneState);
+ GDREGISTER_ABSTRACT_CLASS(SceneState);
GDREGISTER_CLASS(PackedScene);
GDREGISTER_CLASS(SceneTree);
- GDREGISTER_VIRTUAL_CLASS(SceneTreeTimer); // sorry, you can't create it
+ GDREGISTER_ABSTRACT_CLASS(SceneTreeTimer); // sorry, you can't create it
#ifndef DISABLE_DEPRECATED
// Dropped in 4.0, near approximation.
@@ -925,8 +928,6 @@ void register_scene_types() {
ClassDB::add_compatibility_class("ARVRServer", "XRServer");
ClassDB::add_compatibility_class("BoneAttachment", "BoneAttachment3D");
ClassDB::add_compatibility_class("BoxShape", "BoxShape3D");
- ClassDB::add_compatibility_class("BulletPhysicsDirectBodyState", "BulletPhysicsDirectBodyState3D");
- ClassDB::add_compatibility_class("BulletPhysicsServer", "BulletPhysicsServer3D");
ClassDB::add_compatibility_class("Camera", "Camera3D");
ClassDB::add_compatibility_class("CapsuleShape", "CapsuleShape3D");
ClassDB::add_compatibility_class("ClippedCamera", "ClippedCamera3D");
@@ -1013,7 +1014,7 @@ void register_scene_types() {
ClassDB::add_compatibility_class("SpringArm", "SpringArm3D");
ClassDB::add_compatibility_class("Sprite", "Sprite2D");
ClassDB::add_compatibility_class("StaticBody", "StaticBody3D");
- ClassDB::add_compatibility_class("CompressedTexture", "CompressedTexture2D");
+ ClassDB::add_compatibility_class("StreamTexture", "CompressedTexture2D");
ClassDB::add_compatibility_class("TextureProgress", "TextureProgressBar");
ClassDB::add_compatibility_class("VehicleBody", "VehicleBody3D");
ClassDB::add_compatibility_class("VehicleWheel", "VehicleWheel3D");
@@ -1043,6 +1044,14 @@ void register_scene_types() {
ClassDB::add_compatibility_class("VisualShaderNodeScalarDerivativeFunc", "VisualShaderNodeDerivativeFunc");
ClassDB::add_compatibility_class("VisualShaderNodeVectorDerivativeFunc", "VisualShaderNodeDerivativeFunc");
ClassDB::add_compatibility_class("World", "World3D");
+
+ // Renamed during 4.0 alpha, added to ease transition between alphas.
+ ClassDB::add_compatibility_class("StreamCubemap", "CompressedCubemap");
+ ClassDB::add_compatibility_class("StreamCubemapArray", "CompressedCubemapArray");
+ ClassDB::add_compatibility_class("StreamTexture2D", "CompressedTexture2D");
+ ClassDB::add_compatibility_class("StreamTexture2DArray", "CompressedTexture2DArray");
+ ClassDB::add_compatibility_class("StreamTexture3D", "CompressedTexture3D");
+ ClassDB::add_compatibility_class("StreamTextureLayered", "CompressedTextureLayered");
#endif /* DISABLE_DEPRECATED */
OS::get_singleton()->yield(); // may take time to init
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/material.cpp b/scene/resources/material.cpp
index 6fb0c0468d..a0e6cc28ce 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -88,6 +88,37 @@ void Material::inspect_native_shader_code() {
}
}
+RID Material::get_shader_rid() const {
+ RID ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_shader_rid, ret)) {
+ return ret;
+ }
+ return RID();
+}
+Shader::Mode Material::get_shader_mode() const {
+ Shader::Mode ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_shader_mode, ret)) {
+ return ret;
+ }
+
+ return Shader::MODE_MAX;
+}
+
+bool Material::_can_do_next_pass() const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_can_do_next_pass, ret)) {
+ return ret;
+ }
+ return false;
+}
+bool Material::_can_use_render_priority() const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_can_use_render_priority, ret)) {
+ return ret;
+ }
+ return false;
+}
+
void Material::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_next_pass", "next_pass"), &Material::set_next_pass);
ClassDB::bind_method(D_METHOD("get_next_pass"), &Material::get_next_pass);
@@ -103,6 +134,11 @@ void Material::_bind_methods() {
BIND_CONSTANT(RENDER_PRIORITY_MAX);
BIND_CONSTANT(RENDER_PRIORITY_MIN);
+
+ GDVIRTUAL_BIND(_get_shader_rid)
+ GDVIRTUAL_BIND(_get_shader_mode)
+ GDVIRTUAL_BIND(_can_do_next_pass)
+ GDVIRTUAL_BIND(_can_use_render_priority)
}
Material::Material() {
diff --git a/scene/resources/material.h b/scene/resources/material.h
index a79f072f9a..07227c037c 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -51,11 +51,15 @@ class Material : public Resource {
protected:
_FORCE_INLINE_ RID _get_material() const { return material; }
static void _bind_methods();
- virtual bool _can_do_next_pass() const { return false; }
- virtual bool _can_use_render_priority() const { return false; }
+ virtual bool _can_do_next_pass() const;
+ virtual bool _can_use_render_priority() const;
void _validate_property(PropertyInfo &property) const override;
+ GDVIRTUAL0RC(RID, _get_shader_rid)
+ GDVIRTUAL0RC(Shader::Mode, _get_shader_mode)
+ GDVIRTUAL0RC(bool, _can_do_next_pass)
+ GDVIRTUAL0RC(bool, _can_use_render_priority)
public:
enum {
RENDER_PRIORITY_MAX = RS::MATERIAL_RENDER_PRIORITY_MAX,
@@ -68,9 +72,8 @@ public:
int get_render_priority() const;
virtual RID get_rid() const override;
- virtual RID get_shader_rid() const = 0;
-
- virtual Shader::Mode get_shader_mode() const = 0;
+ virtual RID get_shader_rid() const;
+ virtual Shader::Mode get_shader_mode() const;
Material();
virtual ~Material();
};
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 6b44b05e02..3c67a20f50 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -40,6 +40,122 @@
Mesh::ConvexDecompositionFunc Mesh::convex_decomposition_function = nullptr;
+int Mesh::get_surface_count() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_surface_count, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int Mesh::surface_get_array_len(int p_idx) const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_array_len, p_idx, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int Mesh::surface_get_array_index_len(int p_idx) const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_array_index_len, p_idx, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+Array Mesh::surface_get_arrays(int p_surface) const {
+ Array ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_arrays, p_surface, ret)) {
+ return ret;
+ }
+ return Array();
+}
+
+Array Mesh::surface_get_blend_shape_arrays(int p_surface) const {
+ Array ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_blend_shape_arrays, p_surface, ret)) {
+ return ret;
+ }
+
+ return Array();
+}
+
+Dictionary Mesh::surface_get_lods(int p_surface) const {
+ Dictionary ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_lods, p_surface, ret)) {
+ return ret;
+ }
+
+ return Dictionary();
+}
+
+uint32_t Mesh::surface_get_format(int p_idx) const {
+ uint32_t ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_format, p_idx, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+
+Mesh::PrimitiveType Mesh::surface_get_primitive_type(int p_idx) const {
+ uint32_t ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_primitive_type, p_idx, ret)) {
+ return (Mesh::PrimitiveType)ret;
+ }
+
+ return PRIMITIVE_MAX;
+}
+
+void Mesh::surface_set_material(int p_idx, const Ref<Material> &p_material) {
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_set_material, p_idx, p_material)) {
+ return;
+ }
+}
+
+Ref<Material> Mesh::surface_get_material(int p_idx) const {
+ Ref<Material> ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_surface_get_material, p_idx, ret)) {
+ return ret;
+ }
+
+ return Ref<Material>();
+}
+
+int Mesh::get_blend_shape_count() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_count, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+
+StringName Mesh::get_blend_shape_name(int p_index) const {
+ StringName ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_name, p_index, ret)) {
+ return ret;
+ }
+
+ return StringName();
+}
+
+void Mesh::set_blend_shape_name(int p_index, const StringName &p_name) {
+ if (GDVIRTUAL_REQUIRED_CALL(_set_blend_shape_name, p_index, p_name)) {
+ return;
+ }
+}
+
+AABB Mesh::get_aabb() const {
+ AABB ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_aabb, ret)) {
+ return ret;
+ }
+
+ return AABB();
+}
+
Ref<TriangleMesh> Mesh::generate_triangle_mesh() const {
if (triangle_mesh.is_valid()) {
return triangle_mesh;
@@ -502,6 +618,21 @@ void Mesh::_bind_methods() {
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED);
BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE);
+
+ GDVIRTUAL_BIND(_get_surface_count)
+ GDVIRTUAL_BIND(_surface_get_array_len, "index")
+ GDVIRTUAL_BIND(_surface_get_array_index_len, "index")
+ GDVIRTUAL_BIND(_surface_get_arrays, "index")
+ GDVIRTUAL_BIND(_surface_get_blend_shape_arrays, "index")
+ GDVIRTUAL_BIND(_surface_get_lods, "index")
+ GDVIRTUAL_BIND(_surface_get_format, "index")
+ GDVIRTUAL_BIND(_surface_get_primitive_type, "index")
+ GDVIRTUAL_BIND(_surface_set_material, "index", "material")
+ GDVIRTUAL_BIND(_surface_get_material, "index")
+ GDVIRTUAL_BIND(_get_blend_shape_count)
+ GDVIRTUAL_BIND(_get_blend_shape_name, "index")
+ GDVIRTUAL_BIND(_set_blend_shape_name, "index", "name")
+ GDVIRTUAL_BIND(_get_aabb)
}
void Mesh::clear_cache() const {
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 08d834bdb9..652c045a24 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -45,9 +45,34 @@ class Mesh : public Resource {
mutable Vector<Vector3> debug_lines;
Size2i lightmap_size_hint;
+public:
+ enum PrimitiveType {
+ PRIMITIVE_POINTS = RenderingServer::PRIMITIVE_POINTS,
+ PRIMITIVE_LINES = RenderingServer::PRIMITIVE_LINES,
+ PRIMITIVE_LINE_STRIP = RenderingServer::PRIMITIVE_LINE_STRIP,
+ PRIMITIVE_TRIANGLES = RenderingServer::PRIMITIVE_TRIANGLES,
+ PRIMITIVE_TRIANGLE_STRIP = RenderingServer::PRIMITIVE_TRIANGLE_STRIP,
+ PRIMITIVE_MAX = RenderingServer::PRIMITIVE_MAX,
+ };
+
protected:
static void _bind_methods();
+ GDVIRTUAL0RC(int, _get_surface_count)
+ GDVIRTUAL1RC(int, _surface_get_array_len, int)
+ GDVIRTUAL1RC(int, _surface_get_array_index_len, int)
+ GDVIRTUAL1RC(Array, _surface_get_arrays, int)
+ GDVIRTUAL1RC(Array, _surface_get_blend_shape_arrays, int)
+ GDVIRTUAL1RC(Dictionary, _surface_get_lods, int)
+ GDVIRTUAL1RC(uint32_t, _surface_get_format, int)
+ GDVIRTUAL1RC(uint32_t, _surface_get_primitive_type, int)
+ GDVIRTUAL2(_surface_set_material, int, Ref<Material>)
+ GDVIRTUAL1RC(Ref<Material>, _surface_get_material, int)
+ GDVIRTUAL0RC(int, _get_blend_shape_count)
+ GDVIRTUAL1RC(StringName, _get_blend_shape_name, int)
+ GDVIRTUAL2(_set_blend_shape_name, int, StringName)
+ GDVIRTUAL0RC(AABB, _get_aabb)
+
public:
enum {
NO_INDEX_ARRAY = RenderingServer::NO_INDEX_ARRAY,
@@ -120,28 +145,20 @@ public:
};
- enum PrimitiveType {
- PRIMITIVE_POINTS = RenderingServer::PRIMITIVE_POINTS,
- PRIMITIVE_LINES = RenderingServer::PRIMITIVE_LINES,
- PRIMITIVE_LINE_STRIP = RenderingServer::PRIMITIVE_LINE_STRIP,
- PRIMITIVE_TRIANGLES = RenderingServer::PRIMITIVE_TRIANGLES,
- PRIMITIVE_TRIANGLE_STRIP = RenderingServer::PRIMITIVE_TRIANGLE_STRIP,
- PRIMITIVE_MAX = RenderingServer::PRIMITIVE_MAX,
- };
-
- virtual int get_surface_count() const = 0;
- virtual int surface_get_array_len(int p_idx) const = 0;
- virtual int surface_get_array_index_len(int p_idx) const = 0;
- virtual Array surface_get_arrays(int p_surface) const = 0;
- virtual Array surface_get_blend_shape_arrays(int p_surface) const = 0;
- virtual Dictionary surface_get_lods(int p_surface) const = 0;
- virtual uint32_t surface_get_format(int p_idx) const = 0;
- virtual PrimitiveType surface_get_primitive_type(int p_idx) const = 0;
- virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) = 0;
- virtual Ref<Material> surface_get_material(int p_idx) const = 0;
- virtual int get_blend_shape_count() const = 0;
- virtual StringName get_blend_shape_name(int p_index) const = 0;
- virtual void set_blend_shape_name(int p_index, const StringName &p_name) = 0;
+ virtual int get_surface_count() const;
+ virtual int surface_get_array_len(int p_idx) const;
+ virtual int surface_get_array_index_len(int p_idx) const;
+ virtual Array surface_get_arrays(int p_surface) const;
+ virtual Array surface_get_blend_shape_arrays(int p_surface) const;
+ virtual Dictionary surface_get_lods(int p_surface) const;
+ virtual uint32_t surface_get_format(int p_idx) const;
+ virtual PrimitiveType surface_get_primitive_type(int p_idx) const;
+ virtual void surface_set_material(int p_idx, const Ref<Material> &p_material);
+ virtual Ref<Material> surface_get_material(int p_idx) const;
+ virtual int get_blend_shape_count() const;
+ virtual StringName get_blend_shape_name(int p_index) const;
+ virtual void set_blend_shape_name(int p_index, const StringName &p_name);
+ virtual AABB get_aabb() const;
Vector<Face3> get_faces() const;
Ref<TriangleMesh> generate_triangle_mesh() const;
@@ -153,8 +170,6 @@ public:
Ref<Mesh> create_outline(float p_margin) const;
- virtual AABB get_aabb() const = 0;
-
void set_lightmap_size_hint(const Size2i &p_size);
Size2i get_lightmap_size_hint() const;
void clear_cache() const;
diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp
index 38acd0af0a..781e219f1f 100644
--- a/scene/resources/primitive_meshes.cpp
+++ b/scene/resources/primitive_meshes.cpp
@@ -36,11 +36,17 @@
*/
void PrimitiveMesh::_update() const {
Array arr;
- arr.resize(RS::ARRAY_MAX);
- _create_mesh_array(arr);
+ if (GDVIRTUAL_CALL(_create_mesh_array, arr)) {
+ ERR_FAIL_COND_MSG(arr.size() != RS::ARRAY_MAX, "_create_mesh_array must return an array of Mesh.ARRAY_MAX elements.");
+ } else {
+ arr.resize(RS::ARRAY_MAX);
+ _create_mesh_array(arr);
+ }
Vector<Vector3> points = arr[RS::ARRAY_VERTEX];
+ ERR_FAIL_COND_MSG(points.size() == 0, "_create_mesh_array must return at least a vertex array.");
+
aabb = AABB();
int pc = points.size();
@@ -210,6 +216,8 @@ void PrimitiveMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial"), "set_material", "get_material");
ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb", PROPERTY_HINT_NONE, ""), "set_custom_aabb", "get_custom_aabb");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flip_faces"), "set_flip_faces", "get_flip_faces");
+
+ GDVIRTUAL_BIND(_create_mesh_array);
}
void PrimitiveMesh::set_material(const Ref<Material> &p_material) {
diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h
index 3fc5fd4a16..eef5eb3f7d 100644
--- a/scene/resources/primitive_meshes.h
+++ b/scene/resources/primitive_meshes.h
@@ -64,8 +64,9 @@ protected:
static void _bind_methods();
- virtual void _create_mesh_array(Array &p_arr) const = 0;
+ virtual void _create_mesh_array(Array &p_arr) const {}
void _request_update();
+ GDVIRTUAL0RC(Array, _create_mesh_array)
public:
virtual int get_surface_count() const override;
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/style_box.cpp b/scene/resources/style_box.cpp
index 5afd424e03..fe52761482 100644
--- a/scene/resources/style_box.cpp
+++ b/scene/resources/style_box.cpp
@@ -34,10 +34,28 @@
#include <limits.h>
+float StyleBox::get_style_margin(Side p_side) const {
+ float ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_style_margin, p_side, ret)) {
+ return ret;
+ }
+ return 0;
+}
bool StyleBox::test_mask(const Point2 &p_point, const Rect2 &p_rect) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_test_mask, p_point, p_rect, ret)) {
+ return ret;
+ }
+
return true;
}
+void StyleBox::draw(RID p_canvas_item, const Rect2 &p_rect) const {
+ if (GDVIRTUAL_REQUIRED_CALL(_draw, p_canvas_item, p_rect)) {
+ return;
+ }
+}
+
void StyleBox::set_default_margin(Side p_side, float p_value) {
ERR_FAIL_INDEX((int)p_side, 4);
@@ -74,10 +92,19 @@ Point2 StyleBox::get_offset() const {
}
Size2 StyleBox::get_center_size() const {
+ Size2 ret;
+ if (GDVIRTUAL_CALL(_get_center_size, ret)) {
+ return ret;
+ }
+
return Size2();
}
Rect2 StyleBox::get_draw_rect(const Rect2 &p_rect) const {
+ Rect2 ret;
+ if (GDVIRTUAL_CALL(_get_draw_rect, p_rect, ret)) {
+ return ret;
+ }
return p_rect;
}
@@ -100,6 +127,12 @@ void StyleBox::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_right", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", SIDE_RIGHT);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_top", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", SIDE_TOP);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "content_margin_bottom", PROPERTY_HINT_RANGE, "-1,2048,1"), "set_default_margin", "get_default_margin", SIDE_BOTTOM);
+
+ GDVIRTUAL_BIND(_get_style_margin, "side")
+ GDVIRTUAL_BIND(_test_mask, "point", "rect")
+ GDVIRTUAL_BIND(_get_center_size)
+ GDVIRTUAL_BIND(_get_draw_rect, "rect")
+ GDVIRTUAL_BIND(_draw, "to_canvas_item", "rect")
}
StyleBox::StyleBox() {
diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h
index 4c41f42293..68ad41b69c 100644
--- a/scene/resources/style_box.h
+++ b/scene/resources/style_box.h
@@ -44,9 +44,15 @@ class StyleBox : public Resource {
float margin[4];
protected:
- virtual float get_style_margin(Side p_side) const = 0;
+ virtual float get_style_margin(Side p_side) const;
static void _bind_methods();
+ GDVIRTUAL1RC(float, _get_style_margin, Side)
+ GDVIRTUAL2RC(bool, _test_mask, Point2, Rect2)
+ GDVIRTUAL0RC(Size2, _get_center_size)
+ GDVIRTUAL1RC(Rect2, _get_draw_rect, Rect2)
+ GDVIRTUAL2C(_draw, RID, Rect2)
+
public:
virtual bool test_mask(const Point2 &p_point, const Rect2 &p_rect) const;
@@ -56,7 +62,7 @@ public:
virtual Size2 get_center_size() const;
virtual Rect2 get_draw_rect(const Rect2 &p_rect) const;
- virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const = 0;
+ virtual void draw(RID p_canvas_item, const Rect2 &p_rect) const;
CanvasItem *get_current_item_drawn() const;
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 1ab1d81355..1930fa2682 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -38,23 +38,61 @@
#include "scene/resources/bit_map.h"
#include "servers/camera/camera_feed.h"
+int Texture2D::get_width() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int Texture2D::get_height() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
Size2 Texture2D::get_size() const {
return Size2(get_width(), get_height());
}
bool Texture2D::is_pixel_opaque(int p_x, int p_y) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_is_pixel_opaque, p_x, p_y, ret)) {
+ return ret;
+ }
+
+ return true;
+}
+bool Texture2D::has_alpha() const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_has_alpha, ret)) {
+ return ret;
+ }
+
return true;
}
void Texture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const {
+ if (GDVIRTUAL_CALL(_draw, p_canvas_item, p_pos, p_modulate, p_transpose)) {
+ return;
+ }
RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), get_rid(), false, p_modulate, p_transpose);
}
void Texture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const {
+ if (GDVIRTUAL_CALL(_draw_rect, p_canvas_item, p_rect, p_tile, p_modulate, p_transpose)) {
+ return;
+ }
RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose);
}
void Texture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const {
+ if (GDVIRTUAL_CALL(_draw_rect_region, p_canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_clip_uv)) {
+ return;
+ }
RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose, p_clip_uv);
}
@@ -75,6 +113,15 @@ void Texture2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_image"), &Texture2D::get_image);
ADD_GROUP("", "");
+
+ GDVIRTUAL_BIND(_get_width);
+ GDVIRTUAL_BIND(_get_height);
+ GDVIRTUAL_BIND(_is_pixel_opaque, "x", "y");
+ GDVIRTUAL_BIND(_has_alpha);
+
+ GDVIRTUAL_BIND(_draw, "to_canvas_item", "pos", "modulate", "transpose")
+ GDVIRTUAL_BIND(_draw_rect, "to_canvas_item", "rect", "tile", "modulate", "transpose")
+ GDVIRTUAL_BIND(_draw_rect_region, "tp_canvas_item", "rect", "src_rect", "modulate", "transpose", "clip_uv");
}
Texture2D::Texture2D() {
@@ -435,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;
@@ -475,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();
@@ -740,7 +787,7 @@ String ResourceFormatLoaderCompressedTexture2D::get_resource_type(const String &
////////////////////////////////////
-TypedArray<Image> Texture3D::_get_data() const {
+TypedArray<Image> Texture3D::_get_datai() const {
Vector<Ref<Image>> data = get_data();
TypedArray<Image> ret;
@@ -751,13 +798,73 @@ TypedArray<Image> Texture3D::_get_data() const {
return ret;
}
+Image::Format Texture3D::get_format() const {
+ Image::Format ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_format, ret)) {
+ return ret;
+ }
+ return Image::FORMAT_MAX;
+}
+
+int Texture3D::get_width() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int Texture3D::get_height() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int Texture3D::get_depth() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_depth, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+
+bool Texture3D::has_mipmaps() const {
+ bool ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+Vector<Ref<Image>> Texture3D::get_data() const {
+ TypedArray<Image> ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_data, ret)) {
+ Vector<Ref<Image>> data;
+ data.resize(ret.size());
+ for (int i = 0; i < data.size(); i++) {
+ data.write[i] = ret[i];
+ }
+ return data;
+ }
+ return Vector<Ref<Image>>();
+}
void Texture3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_format"), &Texture3D::get_format);
ClassDB::bind_method(D_METHOD("get_width"), &Texture3D::get_width);
ClassDB::bind_method(D_METHOD("get_height"), &Texture3D::get_height);
ClassDB::bind_method(D_METHOD("get_depth"), &Texture3D::get_depth);
ClassDB::bind_method(D_METHOD("has_mipmaps"), &Texture3D::has_mipmaps);
- ClassDB::bind_method(D_METHOD("get_data"), &Texture3D::_get_data);
+ ClassDB::bind_method(D_METHOD("get_data"), &Texture3D::_get_datai);
+
+ GDVIRTUAL_BIND(_get_format);
+ GDVIRTUAL_BIND(_get_width);
+ GDVIRTUAL_BIND(_get_height);
+ GDVIRTUAL_BIND(_get_depth);
+ GDVIRTUAL_BIND(_has_mipmaps);
+ GDVIRTUAL_BIND(_get_data);
}
//////////////////////////////////////////
@@ -866,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
@@ -1022,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 {
@@ -1030,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 "";
@@ -2446,6 +2553,63 @@ AnimatedTexture::~AnimatedTexture() {
///////////////////////////////
+Image::Format TextureLayered::get_format() const {
+ Image::Format ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_format, ret)) {
+ return ret;
+ }
+ return Image::FORMAT_MAX;
+}
+
+TextureLayered::LayeredType TextureLayered::get_layered_type() const {
+ uint32_t ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_layered_type, ret)) {
+ return (LayeredType)ret;
+ }
+ return LAYERED_TYPE_2D_ARRAY;
+}
+
+int TextureLayered::get_width() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int TextureLayered::get_height() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) {
+ return ret;
+ }
+ return 0;
+}
+
+int TextureLayered::get_layers() const {
+ int ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_layers, ret)) {
+ return ret;
+ }
+
+ return 0;
+}
+
+bool TextureLayered::has_mipmaps() const {
+ bool ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+Ref<Image> TextureLayered::get_layer_data(int p_layer) const {
+ Ref<Image> ret;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_layer_data, p_layer, ret)) {
+ return ret;
+ }
+ return Ref<Image>();
+}
+
void TextureLayered::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_format"), &TextureLayered::get_format);
ClassDB::bind_method(D_METHOD("get_layered_type"), &TextureLayered::get_layered_type);
@@ -2458,6 +2622,14 @@ void TextureLayered::_bind_methods() {
BIND_ENUM_CONSTANT(LAYERED_TYPE_2D_ARRAY);
BIND_ENUM_CONSTANT(LAYERED_TYPE_CUBEMAP);
BIND_ENUM_CONSTANT(LAYERED_TYPE_CUBEMAP_ARRAY);
+
+ GDVIRTUAL_BIND(_get_format);
+ GDVIRTUAL_BIND(_get_layered_type);
+ GDVIRTUAL_BIND(_get_width);
+ GDVIRTUAL_BIND(_get_height);
+ GDVIRTUAL_BIND(_get_layers);
+ GDVIRTUAL_BIND(_has_mipmaps);
+ GDVIRTUAL_BIND(_get_layer_data, "layer_index");
}
///////////////////////////////
@@ -2620,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
@@ -2767,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;
}
@@ -2794,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 {
@@ -2808,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 "";
diff --git a/scene/resources/texture.h b/scene/resources/texture.h
index a3c147610d..1e07b83547 100644
--- a/scene/resources/texture.h
+++ b/scene/resources/texture.h
@@ -57,14 +57,23 @@ class Texture2D : public Texture {
protected:
static void _bind_methods();
+ GDVIRTUAL0RC(int, _get_width)
+ GDVIRTUAL0RC(int, _get_height)
+ GDVIRTUAL2RC(bool, _is_pixel_opaque, int, int)
+ GDVIRTUAL0RC(bool, _has_alpha)
+
+ GDVIRTUAL4C(_draw, RID, Point2, Color, bool)
+ GDVIRTUAL5C(_draw_rect, RID, Rect2, bool, Color, bool)
+ GDVIRTUAL6C(_draw_rect_region, RID, Rect2, Rect2, Color, bool, bool)
+
public:
- virtual int get_width() const = 0;
- virtual int get_height() const = 0;
+ virtual int get_width() const;
+ virtual int get_height() const;
virtual Size2 get_size() const;
virtual bool is_pixel_opaque(int p_x, int p_y) const;
- virtual bool has_alpha() const = 0;
+ virtual bool has_alpha() const;
virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const;
virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) const;
@@ -300,6 +309,13 @@ class TextureLayered : public Texture {
protected:
static void _bind_methods();
+ GDVIRTUAL0RC(Image::Format, _get_format)
+ GDVIRTUAL0RC(uint32_t, _get_layered_type)
+ GDVIRTUAL0RC(int, _get_width)
+ GDVIRTUAL0RC(int, _get_height)
+ GDVIRTUAL0RC(int, _get_layers)
+ GDVIRTUAL0RC(bool, _has_mipmaps)
+ GDVIRTUAL1RC(Ref<Image>, _get_layer_data, int)
public:
enum LayeredType {
LAYERED_TYPE_2D_ARRAY,
@@ -307,13 +323,15 @@ public:
LAYERED_TYPE_CUBEMAP_ARRAY
};
- virtual Image::Format get_format() const = 0;
- virtual LayeredType get_layered_type() const = 0;
- virtual int get_width() const = 0;
- virtual int get_height() const = 0;
- virtual int get_layers() const = 0;
- virtual bool has_mipmaps() const = 0;
- virtual Ref<Image> get_layer_data(int p_layer) const = 0;
+ virtual Image::Format get_format() const;
+ virtual LayeredType get_layered_type() const;
+ virtual int get_width() const;
+ virtual int get_height() const;
+ virtual int get_layers() const;
+ virtual bool has_mipmaps() const;
+ virtual Ref<Image> get_layer_data(int p_layer) const;
+
+ TextureLayered() {}
};
VARIANT_ENUM_CAST(TextureLayered::LayeredType)
@@ -474,15 +492,21 @@ class Texture3D : public Texture {
protected:
static void _bind_methods();
- TypedArray<Image> _get_data() const;
-
-public:
- virtual Image::Format get_format() const = 0;
- virtual int get_width() const = 0;
- virtual int get_height() const = 0;
- virtual int get_depth() const = 0;
- virtual bool has_mipmaps() const = 0;
- virtual Vector<Ref<Image>> get_data() const = 0;
+ TypedArray<Image> _get_datai() const;
+
+ GDVIRTUAL0RC(Image::Format, _get_format)
+ GDVIRTUAL0RC(int, _get_width)
+ GDVIRTUAL0RC(int, _get_height)
+ GDVIRTUAL0RC(int, _get_depth)
+ GDVIRTUAL0RC(bool, _has_mipmaps)
+ GDVIRTUAL0RC(TypedArray<Image>, _get_data)
+public:
+ virtual Image::Format get_format() const;
+ virtual int get_width() const;
+ virtual int get_height() const;
+ virtual int get_depth() const;
+ virtual bool has_mipmaps() const;
+ virtual Vector<Ref<Image>> get_data() const;
};
class ImageTexture3D : public Texture3D {
diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp
index 47ca643029..d3e61dbc84 100644
--- a/scene/resources/visual_shader.cpp
+++ b/scene/resources/visual_shader.cpp
@@ -455,32 +455,69 @@ String VisualShaderNodeCustom::generate_code(Shader::Mode p_mode, VisualShader::
for (int i = 0; i < get_output_port_count(); i++) {
output_vars.push_back(p_output_vars[i]);
}
- String code = " {\n";
+
String _code;
GDVIRTUAL_CALL(_get_code, input_vars, output_vars, p_mode, p_type, _code);
- bool nend = _code.ends_with("\n");
- _code = _code.insert(0, " ");
- _code = _code.replace("\n", "\n ");
- code += _code;
- if (!nend) {
- code += "\n }";
- } else {
- code.remove_at(code.size() - 1);
- code += "}";
+ if (_is_valid_code(_code)) {
+ String code = " {\n";
+ bool nend = _code.ends_with("\n");
+ _code = _code.insert(0, " ");
+ _code = _code.replace("\n", "\n ");
+ code += _code;
+ if (!nend) {
+ code += "\n }";
+ } else {
+ code.remove_at(code.size() - 1);
+ code += "}";
+ }
+ code += "\n";
+ return code;
}
- code += "\n";
- return code;
+ return String();
}
String VisualShaderNodeCustom::generate_global_per_node(Shader::Mode p_mode, int p_id) const {
- String ret;
- if (GDVIRTUAL_CALL(_get_global_code, p_mode, ret)) {
- String code = "// " + get_caption() + "\n";
- code += ret;
- code += "\n";
- return code;
+ String _code;
+ if (GDVIRTUAL_CALL(_get_global_code, p_mode, _code)) {
+ if (_is_valid_code(_code)) {
+ String code = "// " + get_caption() + "\n";
+ code += _code;
+ code += "\n";
+ return code;
+ }
}
- return "";
+ return String();
+}
+
+String VisualShaderNodeCustom::generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ String _code;
+ if (GDVIRTUAL_CALL(_get_func_code, p_mode, p_type, _code)) {
+ if (_is_valid_code(_code)) {
+ bool nend = _code.ends_with("\n");
+ String code = "// " + get_caption() + "\n";
+ code += " {\n";
+ _code = _code.insert(0, " ");
+ _code = _code.replace("\n", "\n ");
+ code += _code;
+ if (!nend) {
+ code += "\n }";
+ } else {
+ code.remove_at(code.size() - 1);
+ code += "}";
+ }
+ code += "\n";
+ return code;
+ }
+ }
+ return String();
+}
+
+bool VisualShaderNodeCustom::is_available(Shader::Mode p_mode, VisualShader::Type p_type) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_is_available, p_mode, p_type, ret)) {
+ return ret;
+ }
+ return true;
}
void VisualShaderNodeCustom::set_input_port_default_value(int p_port, const Variant &p_value, const Variant &p_prev_value) {
@@ -511,6 +548,13 @@ void VisualShaderNodeCustom::_set_input_port_default_value(int p_port, const Var
VisualShaderNode::set_input_port_default_value(p_port, p_value);
}
+bool VisualShaderNodeCustom::_is_valid_code(const String &p_code) const {
+ if (p_code.is_empty() || p_code == "null") {
+ return false;
+ }
+ return true;
+}
+
bool VisualShaderNodeCustom::_is_initialized() {
return is_initialized;
}
@@ -531,8 +575,10 @@ void VisualShaderNodeCustom::_bind_methods() {
GDVIRTUAL_BIND(_get_output_port_type, "port");
GDVIRTUAL_BIND(_get_output_port_name, "port");
GDVIRTUAL_BIND(_get_code, "input_vars", "output_vars", "mode", "type");
+ GDVIRTUAL_BIND(_get_func_code, "mode", "type");
GDVIRTUAL_BIND(_get_global_code, "mode");
GDVIRTUAL_BIND(_is_highend);
+ GDVIRTUAL_BIND(_is_available, "mode", "type");
ClassDB::bind_method(D_METHOD("_set_initialized", "enabled"), &VisualShaderNodeCustom::_set_initialized);
ClassDB::bind_method(D_METHOD("_is_initialized"), &VisualShaderNodeCustom::_is_initialized);
@@ -555,6 +601,72 @@ VisualShader::Type VisualShader::get_shader_type() const {
return current_type;
}
+void VisualShader::add_varying(const String &p_name, VaryingMode p_mode, VaryingType p_type) {
+ ERR_FAIL_COND(!p_name.is_valid_identifier());
+ ERR_FAIL_INDEX((int)p_mode, (int)VARYING_MODE_MAX);
+ ERR_FAIL_INDEX((int)p_type, (int)VARYING_TYPE_MAX);
+ ERR_FAIL_COND(varyings.has(p_name));
+ Varying var = Varying(p_name, p_mode, p_type);
+ varyings[p_name] = var;
+ varyings_list.push_back(var);
+ _queue_update();
+}
+
+void VisualShader::remove_varying(const String &p_name) {
+ ERR_FAIL_COND(!varyings.has(p_name));
+ varyings.erase(p_name);
+ for (List<Varying>::Element *E = varyings_list.front(); E; E = E->next()) {
+ if (E->get().name == p_name) {
+ varyings_list.erase(E);
+ break;
+ }
+ }
+ _queue_update();
+}
+
+bool VisualShader::has_varying(const String &p_name) const {
+ return varyings.has(p_name);
+}
+
+int VisualShader::get_varyings_count() const {
+ return varyings_list.size();
+}
+
+const VisualShader::Varying *VisualShader::get_varying_by_index(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, varyings_list.size(), nullptr);
+ return &varyings_list[p_idx];
+}
+
+void VisualShader::set_varying_mode(const String &p_name, VaryingMode p_mode) {
+ ERR_FAIL_INDEX((int)p_mode, (int)VARYING_MODE_MAX);
+ ERR_FAIL_COND(!varyings.has(p_name));
+ if (varyings[p_name].mode == p_mode) {
+ return;
+ }
+ varyings[p_name].mode = p_mode;
+ _queue_update();
+}
+
+VisualShader::VaryingMode VisualShader::get_varying_mode(const String &p_name) {
+ ERR_FAIL_COND_V(!varyings.has(p_name), VARYING_MODE_MAX);
+ return varyings[p_name].mode;
+}
+
+void VisualShader::set_varying_type(const String &p_name, VaryingType p_type) {
+ ERR_FAIL_INDEX((int)p_type, (int)VARYING_TYPE_MAX);
+ ERR_FAIL_COND(!varyings.has(p_name));
+ if (varyings[p_name].type == p_type) {
+ return;
+ }
+ varyings[p_name].type = p_type;
+ _queue_update();
+}
+
+VisualShader::VaryingType VisualShader::get_varying_type(const String &p_name) {
+ ERR_FAIL_COND_V(!varyings.has(p_name), VARYING_TYPE_MAX);
+ return varyings[p_name].type;
+}
+
void VisualShader::set_engine_version(const Dictionary &p_engine_version) {
ERR_FAIL_COND(!p_engine_version.has("major"));
ERR_FAIL_COND(!p_engine_version.has("minor"));
@@ -1072,7 +1184,7 @@ String VisualShader::generate_preview_shader(Type p_type, int p_node, int p_port
code += "\nvoid fragment() {\n";
Set<int> processed;
- Error err = _write_node(p_type, global_code, global_code_per_node, global_code_per_func, code, default_tex_params, input_connections, output_connections, p_node, processed, true, classes);
+ Error err = _write_node(p_type, &global_code, &global_code_per_node, &global_code_per_func, code, default_tex_params, input_connections, output_connections, p_node, processed, true, classes);
ERR_FAIL_COND_V(err != OK, String());
switch (node->get_output_port_type(p_port)) {
@@ -1253,6 +1365,16 @@ bool VisualShader::_set(const StringName &p_name, const Variant &p_value) {
}
_queue_update();
return true;
+ } else if (name.begins_with("varyings/")) {
+ String var_name = name.get_slicec('/', 1);
+ Varying value = Varying();
+ value.name = var_name;
+ if (value.from_string(p_value) && !varyings.has(var_name)) {
+ varyings[var_name] = value;
+ varyings_list.push_back(value);
+ }
+ _queue_update();
+ return true;
} else if (name.begins_with("nodes/")) {
String typestr = name.get_slicec('/', 1);
Type type = TYPE_VERTEX;
@@ -1317,6 +1439,14 @@ bool VisualShader::_get(const StringName &p_name, Variant &r_ret) const {
r_ret = 0;
}
return true;
+ } else if (name.begins_with("varyings/")) {
+ String var_name = name.get_slicec('/', 1);
+ if (varyings.has(var_name)) {
+ r_ret = varyings[var_name].to_string();
+ } else {
+ r_ret = String();
+ }
+ return true;
} else if (name.begins_with("nodes/")) {
String typestr = name.get_slicec('/', 1);
Type type = TYPE_VERTEX;
@@ -1411,6 +1541,10 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
p_list->push_back(PropertyInfo(Variant::BOOL, "flags/" + E->get()));
}
+ for (const KeyValue<String, Varying> &E : varyings) {
+ p_list->push_back(PropertyInfo(Variant::STRING, "varyings/" + E.key));
+ }
+
for (int i = 0; i < TYPE_MAX; i++) {
for (const KeyValue<int, Node> &E : graph[i].nodes) {
String prop_name = "nodes/";
@@ -1435,7 +1569,7 @@ void VisualShader::_get_property_list(List<PropertyInfo> *p_list) const {
}
}
-Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<VisualShader::DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const {
+Error VisualShader::_write_node(Type type, StringBuilder *global_code, StringBuilder *global_code_per_node, Map<Type, StringBuilder> *global_code_per_func, StringBuilder &code, Vector<VisualShader::DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const {
const Ref<VisualShaderNode> vsnode = graph[type].nodes[node].node;
if (vsnode->is_disabled()) {
@@ -1477,7 +1611,9 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
if (!skip_global) {
Ref<VisualShaderNodeUniform> uniform = vsnode;
if (!uniform.is_valid() || !uniform->is_global_code_generated()) {
- global_code += vsnode->generate_global(get_mode(), type, node);
+ if (global_code) {
+ *global_code += vsnode->generate_global(get_mode(), type, node);
+ }
}
String class_name = vsnode->get_class_name();
@@ -1485,9 +1621,13 @@ Error VisualShader::_write_node(Type type, StringBuilder &global_code, StringBui
class_name = vsnode->get_script_instance()->get_script()->get_path();
}
if (!r_classes.has(class_name)) {
- global_code_per_node += vsnode->generate_global_per_node(get_mode(), node);
+ if (global_code_per_node) {
+ *global_code_per_node += vsnode->generate_global_per_node(get_mode(), node);
+ }
for (int i = 0; i < TYPE_MAX; i++) {
- global_code_per_func[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), node);
+ if (global_code_per_func) {
+ (*global_code_per_func)[Type(i)] += vsnode->generate_global_per_func(get_mode(), Type(i), node);
+ }
}
r_classes.insert(class_name);
}
@@ -1940,6 +2080,7 @@ void VisualShader::_update_shader() const {
Set<String> used_uniform_names;
List<VisualShaderNodeUniform *> uniforms;
Map<int, List<int>> emitters;
+ Map<int, List<int>> varying_setters;
for (int i = 0, index = 0; i < TYPE_MAX; i++) {
if (!has_func_name(RenderingServer::ShaderMode(shader_mode), func_name[i])) {
@@ -1964,18 +2105,19 @@ void VisualShader::_update_shader() const {
if (uniform.is_valid()) {
uniforms.push_back(uniform.ptr());
}
+ Ref<VisualShaderNodeVaryingSetter> varying_setter = Object::cast_to<VisualShaderNodeVaryingSetter>(E->get().node.ptr());
+ if (varying_setter.is_valid() && varying_setter->is_input_port_connected(0)) {
+ if (!varying_setters.has(i)) {
+ varying_setters.insert(i, List<int>());
+ }
+ varying_setters[i].push_back(E->key());
+ }
Ref<VisualShaderNodeParticleEmit> emit_particle = Object::cast_to<VisualShaderNodeParticleEmit>(E->get().node.ptr());
if (emit_particle.is_valid()) {
if (!emitters.has(i)) {
emitters.insert(i, List<int>());
}
-
- for (const KeyValue<int, Node> &M : graph[i].nodes) {
- if (M.value.node == emit_particle.ptr()) {
- emitters[i].push_back(M.key);
- break;
- }
- }
+ emitters[i].push_back(E->key());
}
}
}
@@ -1990,6 +2132,36 @@ void VisualShader::_update_shader() const {
}
}
+ if (!varyings.is_empty()) {
+ global_code += "\n// Varyings\n";
+
+ for (const KeyValue<String, Varying> &E : varyings) {
+ global_code += "varying ";
+ switch (E.value.type) {
+ case VaryingType::VARYING_TYPE_FLOAT:
+ global_code += "float ";
+ break;
+ case VaryingType::VARYING_TYPE_VECTOR_2D:
+ global_code += "vec2 ";
+ break;
+ case VaryingType::VARYING_TYPE_VECTOR_3D:
+ global_code += "vec3 ";
+ break;
+ case VaryingType::VARYING_TYPE_COLOR:
+ global_code += "vec4 ";
+ break;
+ case VaryingType::VARYING_TYPE_TRANSFORM:
+ global_code += "mat4 ";
+ break;
+ default:
+ break;
+ }
+ global_code += E.key + ";\n";
+ }
+
+ global_code += "\n";
+ }
+
Map<int, String> code_map;
Set<int> empty_funcs;
@@ -2003,12 +2175,54 @@ void VisualShader::_update_shader() const {
VMap<ConnectionKey, const List<Connection>::Element *> output_connections;
StringBuilder func_code;
+ Set<int> processed;
bool is_empty_func = false;
if (shader_mode != Shader::MODE_PARTICLES && shader_mode != Shader::MODE_SKY && shader_mode != Shader::MODE_FOG) {
is_empty_func = true;
}
+ String varying_code;
+ if (shader_mode == Shader::MODE_SPATIAL || shader_mode == Shader::MODE_CANVAS_ITEM) {
+ for (const KeyValue<String, Varying> &E : varyings) {
+ if ((E.value.mode == VARYING_MODE_VERTEX_TO_FRAG_LIGHT && i == TYPE_VERTEX) || (E.value.mode == VARYING_MODE_FRAG_TO_LIGHT && i == TYPE_FRAGMENT)) {
+ bool found = false;
+ for (int key : varying_setters[i]) {
+ Ref<VisualShaderNodeVaryingSetter> setter = Object::cast_to<VisualShaderNodeVaryingSetter>(const_cast<VisualShaderNode *>(graph[i].nodes[key].node.ptr()));
+ if (setter.is_valid() && E.value.name == setter->get_varying_name()) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ String code2;
+ switch (E.value.type) {
+ case VaryingType::VARYING_TYPE_FLOAT:
+ code2 += "0.0";
+ break;
+ case VaryingType::VARYING_TYPE_VECTOR_2D:
+ code2 += "vec2(0.0)";
+ break;
+ case VaryingType::VARYING_TYPE_VECTOR_3D:
+ code2 += "vec3(0.0)";
+ break;
+ case VaryingType::VARYING_TYPE_COLOR:
+ code2 += "vec4(0.0)";
+ break;
+ case VaryingType::VARYING_TYPE_TRANSFORM:
+ code2 += "mat4(1.0)";
+ break;
+ default:
+ break;
+ }
+ varying_code += vformat(" %s = %s;\n", E.key, code2);
+ }
+ is_empty_func = false;
+ }
+ }
+ }
+
for (const List<Connection>::Element *E = graph[i].connections.front(); E; E = E->next()) {
ConnectionKey from_key;
from_key.node = E->get().from_node;
@@ -2037,13 +2251,19 @@ void VisualShader::_update_shader() const {
}
insertion_pos.insert(i, code.get_string_length() + func_code.get_string_length());
- Set<int> processed;
- Error err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes);
+ Error err = _write_node(Type(i), &global_code, &global_code_per_node, &global_code_per_func, func_code, default_tex_params, input_connections, output_connections, NODE_ID_OUTPUT, processed, false, classes);
ERR_FAIL_COND(err != OK);
+ if (varying_setters.has(i)) {
+ for (int &E : varying_setters[i]) {
+ err = _write_node(Type(i), nullptr, nullptr, nullptr, func_code, default_tex_params, input_connections, output_connections, E, processed, false, classes);
+ ERR_FAIL_COND(err != OK);
+ }
+ }
+
if (emitters.has(i)) {
for (int &E : emitters[i]) {
- err = _write_node(Type(i), global_code, global_code_per_node, global_code_per_func, func_code, default_tex_params, input_connections, output_connections, E, processed, false, classes);
+ err = _write_node(Type(i), &global_code, &global_code_per_node, &global_code_per_func, func_code, default_tex_params, input_connections, output_connections, E, processed, false, classes);
ERR_FAIL_COND(err != OK);
}
}
@@ -2051,6 +2271,7 @@ void VisualShader::_update_shader() const {
if (shader_mode == Shader::MODE_PARTICLES) {
code_map.insert(i, func_code);
} else {
+ func_code += varying_code;
func_code += "}\n";
code += func_code;
}
@@ -2276,6 +2497,10 @@ void VisualShader::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_graph_offset", "offset"), &VisualShader::set_graph_offset);
ClassDB::bind_method(D_METHOD("get_graph_offset"), &VisualShader::get_graph_offset);
+ ClassDB::bind_method(D_METHOD("add_varying", "name", "mode", "type"), &VisualShader::add_varying);
+ ClassDB::bind_method(D_METHOD("remove_varying", "name"), &VisualShader::remove_varying);
+ ClassDB::bind_method(D_METHOD("has_varying", "name"), &VisualShader::has_varying);
+
ClassDB::bind_method(D_METHOD("_update_shader"), &VisualShader::_update_shader);
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "graph_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_graph_offset", "get_graph_offset");
@@ -2295,6 +2520,17 @@ void VisualShader::_bind_methods() {
BIND_ENUM_CONSTANT(TYPE_FOG);
BIND_ENUM_CONSTANT(TYPE_MAX);
+ BIND_ENUM_CONSTANT(VARYING_MODE_VERTEX_TO_FRAG_LIGHT);
+ BIND_ENUM_CONSTANT(VARYING_MODE_FRAG_TO_LIGHT);
+ BIND_ENUM_CONSTANT(VARYING_MODE_MAX);
+
+ BIND_ENUM_CONSTANT(VARYING_TYPE_FLOAT);
+ BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_2D);
+ BIND_ENUM_CONSTANT(VARYING_TYPE_VECTOR_3D);
+ BIND_ENUM_CONSTANT(VARYING_TYPE_COLOR);
+ BIND_ENUM_CONSTANT(VARYING_TYPE_TRANSFORM);
+ BIND_ENUM_CONSTANT(VARYING_TYPE_MAX);
+
BIND_CONSTANT(NODE_ID_INVALID);
BIND_CONSTANT(NODE_ID_OUTPUT);
}
@@ -2327,6 +2563,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
// Node3D, Vertex
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "vertex", "VERTEX" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "tangent", "TANGENT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "binormal", "BINORMAL" },
@@ -2348,6 +2585,9 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_2D, "viewport_size", "VIEWPORT_SIZE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "output_is_srgb", "OUTPUT_IS_SRGB" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
// Node3D, Fragment
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" },
@@ -2374,6 +2614,9 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "screen_texture", "SCREEN_TEXTURE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "normal_roughness_texture", "NORMAL_ROUGHNESS_TEXTURE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SAMPLER, "depth_texture", "DEPTH_TEXTURE" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_index", "VIEW_INDEX" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_mono_left", "VIEW_MONO_LEFT" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR_INT, "view_right", "VIEW_RIGHT" },
// Node3D, Light
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" },
@@ -2384,6 +2627,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light", "LIGHT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "light_color", "LIGHT_COLOR" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_SCALAR, "attenuation", "ATTENUATION" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "shadow_attenuation", "SHADOW_ATTENUATION" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "albedo", "ALBEDO" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "backlight", "BACKLIGHT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_LIGHT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "diffuse", "DIFFUSE_LIGHT" },
@@ -2415,6 +2659,8 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = {
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_BOOLEAN, "at_light_pass", "AT_LIGHT_PASS" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "instance_custom", "INSTANCE_CUSTOM.rgb" },
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "instance_custom_alpha", "INSTANCE_CUSTOM.a" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "instance_id", "INSTANCE_ID" },
+ { Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "vertex_id", "VERTEX_ID" },
// Canvas Item, Fragment
{ Shader::MODE_CANVAS_ITEM, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "fragcoord", "FRAGCOORD.xyz" },
@@ -3144,6 +3390,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "color", "COLOR.rgb" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "alpha", "COLOR.a" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "roughness", "ROUGHNESS" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "point_size", "POINT_SIZE" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "model_view_matrix", "MODELVIEW_MATRIX" },
////////////////////////////////////////////////////////////////////////
// Node3D, Fragment.
@@ -3155,6 +3402,7 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "specular", "SPECULAR" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "emission", "EMISSION" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "ao", "AO" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "ao_light_affect", "AO_LIGHT_AFFECT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal", "NORMAL" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "normal_map", "NORMAL_MAP" },
@@ -3170,7 +3418,10 @@ const VisualShaderNodeOutput::Port VisualShaderNodeOutput::ports[] = {
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_3D, "backlight", "BACKLIGHT" },
{ Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_scissor_threshold", "ALPHA_SCISSOR_THRESHOLD" },
- { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "ao_light_affect", "AO_LIGHT_AFFECT" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_hash_scale", "ALPHA_HASH_SCALE" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_SCALAR, "alpha_aa_edge", "ALPHA_ANTIALIASING_EDGE" },
+ { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_2D, "alpha_uv", "ALPHA_TEXTURE_COORDINATE" },
+
////////////////////////////////////////////////////////////////////////
// Node3D, Light.
////////////////////////////////////////////////////////////////////////
@@ -3294,7 +3545,7 @@ bool VisualShaderNodeOutput::is_port_separator(int p_index) const {
}
if (shader_mode == Shader::MODE_SPATIAL && shader_type == VisualShader::TYPE_FRAGMENT) {
String name = get_input_port_name(p_index);
- return bool(name == "Normal" || name == "Rim" || name == "Alpha Scissor Threshold");
+ return bool(name == "Ao" || name == "Normal" || name == "Rim" || name == "Clearcoat" || name == "Anisotropy" || name == "Subsurf Scatter" || name == "Alpha Scissor Threshold");
}
return false;
}
@@ -4199,3 +4450,299 @@ String VisualShaderNodeGlobalExpression::generate_global(Shader::Mode p_mode, Vi
VisualShaderNodeGlobalExpression::VisualShaderNodeGlobalExpression() {
set_editable(false);
}
+
+////////////// Varying
+
+List<VisualShaderNodeVarying::Varying> varyings;
+
+void VisualShaderNodeVarying::add_varying(const String &p_name, VisualShader::VaryingMode p_mode, VisualShader::VaryingType p_type) { // static
+ varyings.push_back({ p_name, p_mode, p_type });
+}
+
+void VisualShaderNodeVarying::clear_varyings() { // static
+ varyings.clear();
+}
+
+bool VisualShaderNodeVarying::has_varying(const String &p_name) { // static
+ for (const VisualShaderNodeVarying::Varying &E : varyings) {
+ if (E.name == p_name) {
+ return true;
+ }
+ }
+ return false;
+}
+
+int VisualShaderNodeVarying::get_varyings_count() const {
+ return varyings.size();
+}
+
+String VisualShaderNodeVarying::get_varying_name_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < varyings.size()) {
+ return varyings[p_idx].name;
+ }
+ return "";
+}
+
+VisualShader::VaryingType VisualShaderNodeVarying::get_varying_type_by_name(const String &p_name) const {
+ for (int i = 0; i < varyings.size(); i++) {
+ if (varyings[i].name == p_name) {
+ return varyings[i].type;
+ }
+ }
+ return VisualShader::VARYING_TYPE_FLOAT;
+}
+
+VisualShader::VaryingType VisualShaderNodeVarying::get_varying_type_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < varyings.size()) {
+ return varyings[p_idx].type;
+ }
+ return VisualShader::VARYING_TYPE_FLOAT;
+}
+
+VisualShader::VaryingMode VisualShaderNodeVarying::get_varying_mode_by_name(const String &p_name) const {
+ for (int i = 0; i < varyings.size(); i++) {
+ if (varyings[i].name == p_name) {
+ return varyings[i].mode;
+ }
+ }
+ return VisualShader::VARYING_MODE_VERTEX_TO_FRAG_LIGHT;
+}
+
+VisualShader::VaryingMode VisualShaderNodeVarying::get_varying_mode_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < varyings.size()) {
+ return varyings[p_idx].mode;
+ }
+ return VisualShader::VARYING_MODE_VERTEX_TO_FRAG_LIGHT;
+}
+
+VisualShaderNodeVarying::PortType VisualShaderNodeVarying::get_port_type_by_index(int p_idx) const {
+ if (p_idx >= 0 && p_idx < varyings.size()) {
+ return get_port_type(varyings[p_idx].type, 0);
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+//////////////
+
+void VisualShaderNodeVarying::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_varying_name", "name"), &VisualShaderNodeVarying::set_varying_name);
+ ClassDB::bind_method(D_METHOD("get_varying_name"), &VisualShaderNodeVarying::get_varying_name);
+
+ ClassDB::bind_method(D_METHOD("set_varying_type", "type"), &VisualShaderNodeVarying::set_varying_type);
+ ClassDB::bind_method(D_METHOD("get_varying_type"), &VisualShaderNodeVarying::get_varying_type);
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "varying_name"), "set_varying_name", "get_varying_name");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "varying_type", PROPERTY_HINT_ENUM, "Float,Vector,Transform"), "set_varying_type", "get_varying_type");
+}
+
+String VisualShaderNodeVarying::get_type_str() const {
+ switch (varying_type) {
+ case VisualShader::VARYING_TYPE_FLOAT:
+ return "float";
+ case VisualShader::VARYING_TYPE_VECTOR_2D:
+ return "vec2";
+ case VisualShader::VARYING_TYPE_VECTOR_3D:
+ return "vec3";
+ case VisualShader::VARYING_TYPE_COLOR:
+ return "vec4";
+ case VisualShader::VARYING_TYPE_TRANSFORM:
+ return "mat4";
+ default:
+ break;
+ }
+ return "";
+}
+
+VisualShaderNodeVarying::PortType VisualShaderNodeVarying::get_port_type(VisualShader::VaryingType p_type, int p_port) const {
+ switch (p_type) {
+ case VisualShader::VARYING_TYPE_VECTOR_2D:
+ return PORT_TYPE_VECTOR_2D;
+ case VisualShader::VARYING_TYPE_VECTOR_3D:
+ return PORT_TYPE_VECTOR_3D;
+ case VisualShader::VARYING_TYPE_COLOR:
+ if (p_port == 1) {
+ break; // scalar
+ }
+ return PORT_TYPE_VECTOR_3D;
+ case VisualShader::VARYING_TYPE_TRANSFORM:
+ return PORT_TYPE_TRANSFORM;
+ default:
+ break;
+ }
+ return PORT_TYPE_SCALAR;
+}
+
+void VisualShaderNodeVarying::set_varying_name(String p_varying_name) {
+ if (varying_name == p_varying_name) {
+ return;
+ }
+ varying_name = p_varying_name;
+ emit_changed();
+}
+
+String VisualShaderNodeVarying::get_varying_name() const {
+ return varying_name;
+}
+
+void VisualShaderNodeVarying::set_varying_type(VisualShader::VaryingType p_varying_type) {
+ ERR_FAIL_INDEX(p_varying_type, VisualShader::VARYING_TYPE_MAX);
+ if (varying_type == p_varying_type) {
+ return;
+ }
+ varying_type = p_varying_type;
+ emit_changed();
+}
+
+VisualShader::VaryingType VisualShaderNodeVarying::get_varying_type() const {
+ return varying_type;
+}
+
+VisualShaderNodeVarying::VisualShaderNodeVarying() {
+}
+
+////////////// Varying Setter
+
+String VisualShaderNodeVaryingSetter::get_caption() const {
+ return vformat("VaryingSetter");
+}
+
+int VisualShaderNodeVaryingSetter::get_input_port_count() const {
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ return 2;
+ }
+ return 1;
+}
+
+VisualShaderNodeVaryingSetter::PortType VisualShaderNodeVaryingSetter::get_input_port_type(int p_port) const {
+ return get_port_type(varying_type, p_port);
+}
+
+String VisualShaderNodeVaryingSetter::get_input_port_name(int p_port) const {
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ if (p_port == 0) {
+ return "color";
+ } else {
+ return "alpha";
+ }
+ }
+ return "";
+}
+
+int VisualShaderNodeVaryingSetter::get_output_port_count() const {
+ return 0;
+}
+
+VisualShaderNodeVaryingSetter::PortType VisualShaderNodeVaryingSetter::get_output_port_type(int p_port) const {
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeVaryingSetter::get_output_port_name(int p_port) const {
+ return "";
+}
+
+String VisualShaderNodeVaryingSetter::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
+ return vformat("varying %s %s;\n", get_type_str(), varying_name);
+}
+
+String VisualShaderNodeVaryingSetter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String code;
+ if (varying_name == "[None]") {
+ return code;
+ }
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ code += vformat(" %s = vec4(%s, %s);\n", varying_name, p_input_vars[0], p_input_vars[1]);
+ } else {
+ code += vformat(" %s = %s;\n", varying_name, p_input_vars[0]);
+ }
+ return code;
+}
+
+VisualShaderNodeVaryingSetter::VisualShaderNodeVaryingSetter() {
+}
+
+////////////// Varying Getter
+
+String VisualShaderNodeVaryingGetter::get_caption() const {
+ return vformat("VaryingGetter");
+}
+
+int VisualShaderNodeVaryingGetter::get_input_port_count() const {
+ return 0;
+}
+
+VisualShaderNodeVaryingGetter::PortType VisualShaderNodeVaryingGetter::get_input_port_type(int p_port) const {
+ return PORT_TYPE_SCALAR;
+}
+
+String VisualShaderNodeVaryingGetter::get_input_port_name(int p_port) const {
+ return "";
+}
+
+int VisualShaderNodeVaryingGetter::get_output_port_count() const {
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ return 2;
+ }
+ return 1;
+}
+
+VisualShaderNodeVaryingGetter::PortType VisualShaderNodeVaryingGetter::get_output_port_type(int p_port) const {
+ return get_port_type(varying_type, p_port);
+}
+
+String VisualShaderNodeVaryingGetter::get_output_port_name(int p_port) const {
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ if (p_port == 0) {
+ return "color";
+ } else {
+ return "alpha";
+ }
+ }
+ return "";
+}
+
+bool VisualShaderNodeVaryingGetter::has_output_port_preview(int p_port) const {
+ return false;
+}
+
+String VisualShaderNodeVaryingGetter::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
+ String from = varying_name;
+ String from2;
+
+ if (varying_name == "[None]") {
+ switch (varying_type) {
+ case VisualShader::VARYING_TYPE_FLOAT:
+ from = "0.0";
+ break;
+ case VisualShader::VARYING_TYPE_VECTOR_2D:
+ from = "vec2(0.0)";
+ break;
+ case VisualShader::VARYING_TYPE_VECTOR_3D:
+ from = "vec3(0.0)";
+ break;
+ case VisualShader::VARYING_TYPE_COLOR:
+ from = "vec3(0.0)";
+ from2 = "0.0";
+ break;
+ case VisualShader::VARYING_TYPE_TRANSFORM:
+ from = "mat4(1.0)";
+ break;
+ default:
+ break;
+ }
+ } else if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ from = varying_name + ".rgb";
+ from2 = varying_name + ".a";
+ }
+
+ if (varying_type == VisualShader::VARYING_TYPE_COLOR) {
+ String code;
+ code += vformat(" %s = %s;\n", p_output_vars[0], from);
+ code += vformat(" %s = %s;\n", p_output_vars[1], from2);
+ return code;
+ }
+ return vformat(" %s = %s;\n", p_output_vars[0], from);
+}
+
+VisualShaderNodeVaryingGetter::VisualShaderNodeVaryingGetter() {
+ varying_name = "[None]";
+}
diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h
index d3b5365893..2d4b2852e9 100644
--- a/scene/resources/visual_shader.h
+++ b/scene/resources/visual_shader.h
@@ -73,6 +73,49 @@ public:
List<Ref<Texture2D>> params;
};
+ enum VaryingMode {
+ VARYING_MODE_VERTEX_TO_FRAG_LIGHT,
+ VARYING_MODE_FRAG_TO_LIGHT,
+ VARYING_MODE_MAX,
+ };
+
+ enum VaryingType {
+ VARYING_TYPE_FLOAT,
+ VARYING_TYPE_VECTOR_2D,
+ VARYING_TYPE_VECTOR_3D,
+ VARYING_TYPE_COLOR,
+ VARYING_TYPE_TRANSFORM,
+ VARYING_TYPE_MAX,
+ };
+
+ struct Varying {
+ String name;
+ VaryingMode mode;
+ VaryingType type;
+
+ Varying() {
+ }
+
+ Varying(String p_name, VaryingMode p_mode, VaryingType p_type) :
+ name(p_name), mode(p_mode), type(p_type) {}
+
+ bool from_string(const String &p_str) {
+ Vector<String> arr = p_str.split(",");
+ if (arr.size() != 2) {
+ return false;
+ }
+
+ mode = (VaryingMode)arr[0].to_int();
+ type = (VaryingType)arr[1].to_int();
+
+ return true;
+ }
+
+ String to_string() const {
+ return vformat("%s,%s", itos((int)mode), itos((int)type));
+ }
+ };
+
private:
Type current_type;
@@ -94,14 +137,12 @@ private:
Vector2 graph_offset;
- struct RenderModeEnums {
- Shader::Mode mode = Shader::Mode::MODE_MAX;
- const char *string;
- };
-
HashMap<String, int> modes;
Set<StringName> flags;
+ Map<String, Varying> varyings;
+ List<Varying> varyings_list;
+
mutable SafeFlag dirty;
void _queue_update();
@@ -116,7 +157,7 @@ private:
}
};
- Error _write_node(Type p_type, StringBuilder &global_code, StringBuilder &global_code_per_node, Map<Type, StringBuilder> &global_code_per_func, StringBuilder &code, Vector<DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const;
+ Error _write_node(Type p_type, StringBuilder *global_code, StringBuilder *global_code_per_node, Map<Type, StringBuilder> *global_code_per_func, StringBuilder &code, Vector<DefaultTextureParam> &def_tex_params, const VMap<ConnectionKey, const List<Connection>::Element *> &input_connections, const VMap<ConnectionKey, const List<Connection>::Element *> &output_connections, int node, Set<int> &processed, bool for_preview, Set<StringName> &r_classes) const;
void _input_type_changed(Type p_type, int p_id);
bool has_func_name(RenderingServer::ShaderMode p_mode, const String &p_func_name) const;
@@ -151,6 +192,18 @@ public:
void add_node(Type p_type, const Ref<VisualShaderNode> &p_node, const Vector2 &p_position, int p_id);
void set_node_position(Type p_type, int p_id, const Vector2 &p_position);
+ void add_varying(const String &p_name, VaryingMode p_mode, VaryingType p_type);
+ void remove_varying(const String &p_name);
+ bool has_varying(const String &p_name) const;
+ int get_varyings_count() const;
+ const Varying *get_varying_by_index(int p_idx) const;
+
+ void set_varying_mode(const String &p_name, VaryingMode p_mode);
+ VaryingMode get_varying_mode(const String &p_name);
+
+ void set_varying_type(const String &p_name, VaryingType p_type);
+ VaryingType get_varying_type(const String &p_name);
+
Vector2 get_node_position(Type p_type, int p_id) const;
Ref<VisualShaderNode> get_node(Type p_type, int p_id) const;
@@ -190,6 +243,8 @@ public:
};
VARIANT_ENUM_CAST(VisualShader::Type)
+VARIANT_ENUM_CAST(VisualShader::VaryingMode)
+VARIANT_ENUM_CAST(VisualShader::VaryingType)
///
///
///
@@ -328,14 +383,20 @@ protected:
GDVIRTUAL1RC(int, _get_output_port_type, int)
GDVIRTUAL1RC(String, _get_output_port_name, int)
GDVIRTUAL4RC(String, _get_code, TypedArray<String>, TypedArray<String>, Shader::Mode, VisualShader::Type)
+ GDVIRTUAL2RC(String, _get_func_code, Shader::Mode, VisualShader::Type)
GDVIRTUAL1RC(String, _get_global_code, Shader::Mode)
GDVIRTUAL0RC(bool, _is_highend)
+ GDVIRTUAL2RC(bool, _is_available, Shader::Mode, VisualShader::Type)
+
+ bool _is_valid_code(const String &p_code) const;
protected:
void _set_input_port_default_value(int p_port, const Variant &p_value);
+ bool is_available(Shader::Mode p_mode, VisualShader::Type p_type) const;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override;
+ virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
static void _bind_methods();
@@ -697,6 +758,103 @@ public:
VisualShaderNodeGlobalExpression();
};
+class VisualShaderNodeVarying : public VisualShaderNode {
+ GDCLASS(VisualShaderNodeVarying, VisualShaderNode);
+
+public:
+ struct Varying {
+ String name;
+ VisualShader::VaryingMode mode;
+ VisualShader::VaryingType type;
+ bool assigned = false;
+ };
+
+protected:
+ VisualShader::VaryingType varying_type = VisualShader::VARYING_TYPE_FLOAT;
+ String varying_name = "[None]";
+
+public: // internal
+ static void add_varying(const String &p_name, VisualShader::VaryingMode p_mode, VisualShader::VaryingType p_type);
+ static void clear_varyings();
+ static bool has_varying(const String &p_name);
+
+ int get_varyings_count() const;
+ String get_varying_name_by_index(int p_idx) const;
+ VisualShader::VaryingMode get_varying_mode_by_name(const String &p_name) const;
+ VisualShader::VaryingMode get_varying_mode_by_index(int p_idx) const;
+ VisualShader::VaryingType get_varying_type_by_name(const String &p_name) const;
+ VisualShader::VaryingType get_varying_type_by_index(int p_idx) const;
+ PortType get_port_type_by_index(int p_idx) const;
+
+protected:
+ static void _bind_methods();
+
+protected:
+ String get_type_str() const;
+ PortType get_port_type(VisualShader::VaryingType p_type, int p_port) const;
+
+public:
+ virtual String get_caption() const override = 0;
+
+ virtual int get_input_port_count() const override = 0;
+ virtual PortType get_input_port_type(int p_port) const override = 0;
+ virtual String get_input_port_name(int p_port) const override = 0;
+
+ virtual int get_output_port_count() const override = 0;
+ virtual PortType get_output_port_type(int p_port) const override = 0;
+ virtual String get_output_port_name(int p_port) const override = 0;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override = 0;
+
+ void set_varying_name(String p_varying_name);
+ String get_varying_name() const;
+
+ void set_varying_type(VisualShader::VaryingType p_varying_type);
+ VisualShader::VaryingType get_varying_type() const;
+
+ VisualShaderNodeVarying();
+};
+
+class VisualShaderNodeVaryingSetter : public VisualShaderNodeVarying {
+ GDCLASS(VisualShaderNodeVaryingSetter, VisualShaderNodeVarying);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+
+ virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeVaryingSetter();
+};
+
+class VisualShaderNodeVaryingGetter : public VisualShaderNodeVarying {
+ GDCLASS(VisualShaderNodeVaryingGetter, VisualShaderNodeVarying);
+
+public:
+ virtual String get_caption() const override;
+
+ virtual int get_input_port_count() const override;
+ virtual PortType get_input_port_type(int p_port) const override;
+ virtual String get_input_port_name(int p_port) const override;
+
+ virtual int get_output_port_count() const override;
+ virtual PortType get_output_port_type(int p_port) const override;
+ virtual String get_output_port_name(int p_port) const override;
+ virtual bool has_output_port_preview(int p_port) const override;
+
+ virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;
+
+ VisualShaderNodeVaryingGetter();
+};
+
extern String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name);
#endif // VISUAL_SHADER_H
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index a6aa6d8c49..7b4d7e66d4 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -5696,7 +5696,7 @@ String VisualShaderNodeTextureUniformTriplanar::get_input_port_name(int p_port)
String VisualShaderNodeTextureUniformTriplanar::generate_global_per_node(Shader::Mode p_mode, int p_id) const {
String code;
- code += "// TRIPLANAR FUNCTION GLOBAL CODE\n";
+ code += "// " + get_caption() + "\n";
code += " vec4 triplanar_texture(sampler2D p_sampler, vec3 p_weights, vec3 p_triplanar_pos) {\n";
code += " vec4 samp = vec4(0.0);\n";
code += " samp += texture(p_sampler, p_triplanar_pos.xy) * p_weights.z;\n";
@@ -5719,11 +5719,13 @@ String VisualShaderNodeTextureUniformTriplanar::generate_global_per_func(Shader:
String code;
if (p_type == VisualShader::TYPE_VERTEX) {
- code += " // TRIPLANAR FUNCTION VERTEX CODE\n";
+ code += "// " + get_caption() + "\n";
+ code += " {\n";
code += " triplanar_power_normal = pow(abs(NORMAL), vec3(triplanar_sharpness));\n";
code += " triplanar_power_normal /= dot(triplanar_power_normal, vec3(1.0));\n";
code += " triplanar_pos = VERTEX * triplanar_scale + triplanar_offset;\n";
code += " triplanar_pos *= vec3(1.0, -1.0, 1.0);\n";
+ code += " }\n";
}
return code;