diff options
Diffstat (limited to 'scene')
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; |