diff options
Diffstat (limited to 'scene')
51 files changed, 580 insertions, 238 deletions
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 0f4e3c8bed..70c7e48fd4 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -268,7 +268,7 @@ uint32_t CollisionObject2D::create_shape_owner(Object *p_owner) { id = shapes.back()->key() + 1; } - sd.owner = p_owner; + sd.owner_id = p_owner ? p_owner->get_instance_id() : ObjectID(); shapes[id] = sd; @@ -382,7 +382,7 @@ Transform2D CollisionObject2D::shape_owner_get_transform(uint32_t p_owner) const Object *CollisionObject2D::shape_owner_get_owner(uint32_t p_owner) const { ERR_FAIL_COND_V(!shapes.has(p_owner), nullptr); - return shapes[p_owner].owner; + return ObjectDB::get_instance(shapes[p_owner].owner_id); } void CollisionObject2D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape2D> &p_shape) { diff --git a/scene/2d/collision_object_2d.h b/scene/2d/collision_object_2d.h index 9463b2c429..f2b7eecc7b 100644 --- a/scene/2d/collision_object_2d.h +++ b/scene/2d/collision_object_2d.h @@ -59,7 +59,7 @@ private: PhysicsServer2D::BodyMode body_mode = PhysicsServer2D::BODY_MODE_STATIC; struct ShapeData { - Object *owner = nullptr; + ObjectID owner_id; Transform2D xform; struct Shape { Ref<Shape2D> shape; diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index b6d1e5c934..11c036ac9c 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -335,6 +335,42 @@ Ref<Texture2D> GPUParticles2D::get_texture() const { void GPUParticles2D::_validate_property(PropertyInfo &property) const { } +void GPUParticles2D::emit_particle(const Transform2D &p_transform2d, const Vector2 &p_velocity2d, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags) { + Transform3D transform; + transform.basis.set_axis(0, Vector3(p_transform2d.get_axis(0).x, p_transform2d.get_axis(0).y, 0)); + transform.basis.set_axis(1, Vector3(p_transform2d.get_axis(1).x, p_transform2d.get_axis(1).y, 0)); + transform.set_origin(Vector3(p_transform2d.get_origin().x, p_transform2d.get_origin().y, 0)); + Vector3 velocity = Vector3(p_velocity2d.x, p_velocity2d.y, 0); + + RS::get_singleton()->particles_emit(particles, transform, velocity, p_color, p_custom, p_emit_flags); +} + +void GPUParticles2D::_attach_sub_emitter() { + Node *n = get_node_or_null(sub_emitter); + if (n) { + GPUParticles2D *sen = Object::cast_to<GPUParticles2D>(n); + if (sen && sen != this) { + RS::get_singleton()->particles_set_subemitter(particles, sen->particles); + } + } +} + +void GPUParticles2D::set_sub_emitter(const NodePath &p_path) { + if (is_inside_tree()) { + RS::get_singleton()->particles_set_subemitter(particles, RID()); + } + + sub_emitter = p_path; + + if (is_inside_tree() && sub_emitter != NodePath()) { + _attach_sub_emitter(); + } +} + +NodePath GPUParticles2D::get_sub_emitter() const { + return sub_emitter; +} + void GPUParticles2D::restart() { RS::get_singleton()->particles_restart(particles); RS::get_singleton()->particles_set_emitting(particles, true); @@ -462,6 +498,16 @@ void GPUParticles2D::_notification(int p_what) { #endif } + if (p_what == NOTIFICATION_ENTER_TREE) { + if (sub_emitter != NodePath()) { + _attach_sub_emitter(); + } + } + + if (p_what == NOTIFICATION_EXIT_TREE) { + RS::get_singleton()->particles_set_subemitter(particles, RID()); + } + if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { if (can_process()) { RS::get_singleton()->particles_set_speed_scale(particles, speed_scale); @@ -523,6 +569,11 @@ void GPUParticles2D::_bind_methods() { ClassDB::bind_method(D_METHOD("restart"), &GPUParticles2D::restart); + ClassDB::bind_method(D_METHOD("set_sub_emitter", "path"), &GPUParticles2D::set_sub_emitter); + ClassDB::bind_method(D_METHOD("get_sub_emitter"), &GPUParticles2D::get_sub_emitter); + + ClassDB::bind_method(D_METHOD("emit_particle", "xform", "velocity", "color", "custom", "flags"), &GPUParticles2D::emit_particle); + ClassDB::bind_method(D_METHOD("set_trail_enabled", "enabled"), &GPUParticles2D::set_trail_enabled); ClassDB::bind_method(D_METHOD("set_trail_length", "secs"), &GPUParticles2D::set_trail_length); @@ -538,6 +589,7 @@ void GPUParticles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "emitting"), "set_emitting", "is_emitting"); ADD_PROPERTY_DEFAULT("emitting", true); // Workaround for doctool in headless mode, as dummy rasterizer always returns false. ADD_PROPERTY(PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "1,1000000,1,exp"), "set_amount", "get_amount"); + ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "sub_emitter", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "GPUParticles2D"), "set_sub_emitter", "get_sub_emitter"); ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime", PROPERTY_HINT_RANGE, "0.01,600.0,0.01,or_greater"), "set_lifetime", "get_lifetime"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "get_one_shot"); @@ -566,6 +618,12 @@ void GPUParticles2D::_bind_methods() { BIND_ENUM_CONSTANT(DRAW_ORDER_INDEX); BIND_ENUM_CONSTANT(DRAW_ORDER_LIFETIME); BIND_ENUM_CONSTANT(DRAW_ORDER_REVERSE_LIFETIME); + + BIND_ENUM_CONSTANT(EMIT_FLAG_POSITION); + BIND_ENUM_CONSTANT(EMIT_FLAG_ROTATION_SCALE); + BIND_ENUM_CONSTANT(EMIT_FLAG_VELOCITY); + BIND_ENUM_CONSTANT(EMIT_FLAG_COLOR); + BIND_ENUM_CONSTANT(EMIT_FLAG_CUSTOM); } GPUParticles2D::GPUParticles2D() { diff --git a/scene/2d/gpu_particles_2d.h b/scene/2d/gpu_particles_2d.h index aa9a8da129..fc95ae27b2 100644 --- a/scene/2d/gpu_particles_2d.h +++ b/scene/2d/gpu_particles_2d.h @@ -79,6 +79,8 @@ private: RID mesh; + void _attach_sub_emitter(); + protected: static void _bind_methods(); virtual void _validate_property(PropertyInfo &property) const override; @@ -139,6 +141,19 @@ public: TypedArray<String> get_configuration_warnings() const override; + void set_sub_emitter(const NodePath &p_path); + NodePath get_sub_emitter() const; + + enum EmitFlags { + EMIT_FLAG_POSITION = RS::PARTICLES_EMIT_FLAG_POSITION, + EMIT_FLAG_ROTATION_SCALE = RS::PARTICLES_EMIT_FLAG_ROTATION_SCALE, + EMIT_FLAG_VELOCITY = RS::PARTICLES_EMIT_FLAG_VELOCITY, + EMIT_FLAG_COLOR = RS::PARTICLES_EMIT_FLAG_COLOR, + EMIT_FLAG_CUSTOM = RS::PARTICLES_EMIT_FLAG_CUSTOM + }; + + void emit_particle(const Transform2D &p_transform, const Vector2 &p_velocity, const Color &p_color, const Color &p_custom, uint32_t p_emit_flags); + void restart(); Rect2 capture_rect() const; GPUParticles2D(); @@ -146,5 +161,6 @@ public: }; VARIANT_ENUM_CAST(GPUParticles2D::DrawOrder) +VARIANT_ENUM_CAST(GPUParticles2D::EmitFlags) #endif // PARTICLES_2D_H diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 9331340e1b..9d26543243 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -413,7 +413,7 @@ void Node2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_relative_transform_to_parent", "parent"), &Node2D::get_relative_transform_to_parent); ADD_GROUP("Transform", ""); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0,or_lesser,or_greater,noslider,suffix:px"), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_lesser,or_greater,noslider,suffix:px"), "set_position", "get_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::FLOAT, "skew", PROPERTY_HINT_RANGE, "-89.9,89.9,0.1,radians"), "set_skew", "get_skew"); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index b2cc8164b6..01fa109384 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1162,7 +1162,7 @@ bool CharacterBody2D::move_and_slide() { if (motion_mode == MOTION_MODE_GROUNDED) { _move_and_slide_grounded(delta, was_on_floor); } else { - _move_and_slide_free(delta); + _move_and_slide_floating(delta); } // Compute real velocity. @@ -1350,7 +1350,7 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo } } -void CharacterBody2D::_move_and_slide_free(double p_delta) { +void CharacterBody2D::_move_and_slide_floating(double p_delta) { Vector2 motion = motion_velocity * p_delta; platform_rid = RID(); @@ -1376,7 +1376,7 @@ void CharacterBody2D::_move_and_slide_free(double p_delta) { break; } - if (free_mode_min_slide_angle != 0 && result.get_angle(-motion_velocity.normalized()) < free_mode_min_slide_angle + FLOOR_ANGLE_THRESHOLD) { + if (wall_min_slide_angle != 0 && result.get_angle(-motion_velocity.normalized()) < wall_min_slide_angle + FLOOR_ANGLE_THRESHOLD) { motion = Vector2(); } else if (first_slide) { Vector2 motion_slide_norm = result.remainder.slide(result.collision_normal).normalized(); @@ -1668,12 +1668,12 @@ void CharacterBody2D::set_floor_snap_length(real_t p_floor_snap_length) { floor_snap_length = p_floor_snap_length; } -real_t CharacterBody2D::get_free_mode_min_slide_angle() const { - return free_mode_min_slide_angle; +real_t CharacterBody2D::get_wall_min_slide_angle() const { + return wall_min_slide_angle; } -void CharacterBody2D::set_free_mode_min_slide_angle(real_t p_radians) { - free_mode_min_slide_angle = p_radians; +void CharacterBody2D::set_wall_min_slide_angle(real_t p_radians) { + wall_min_slide_angle = p_radians; } const Vector2 &CharacterBody2D::get_up_direction() const { @@ -1681,7 +1681,7 @@ const Vector2 &CharacterBody2D::get_up_direction() const { } void CharacterBody2D::set_up_direction(const Vector2 &p_up_direction) { - ERR_FAIL_COND_MSG(p_up_direction == Vector2(), "up_direction can't be equal to Vector2.ZERO, consider using Free motion mode instead."); + ERR_FAIL_COND_MSG(p_up_direction == Vector2(), "up_direction can't be equal to Vector2.ZERO, consider using Floating motion mode instead."); up_direction = p_up_direction.normalized(); } @@ -1728,8 +1728,8 @@ void CharacterBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_floor_max_angle", "radians"), &CharacterBody2D::set_floor_max_angle); ClassDB::bind_method(D_METHOD("get_floor_snap_length"), &CharacterBody2D::get_floor_snap_length); ClassDB::bind_method(D_METHOD("set_floor_snap_length", "floor_snap_length"), &CharacterBody2D::set_floor_snap_length); - ClassDB::bind_method(D_METHOD("get_free_mode_min_slide_angle"), &CharacterBody2D::get_free_mode_min_slide_angle); - ClassDB::bind_method(D_METHOD("set_free_mode_min_slide_angle", "radians"), &CharacterBody2D::set_free_mode_min_slide_angle); + ClassDB::bind_method(D_METHOD("get_wall_min_slide_angle"), &CharacterBody2D::get_wall_min_slide_angle); + ClassDB::bind_method(D_METHOD("set_wall_min_slide_angle", "radians"), &CharacterBody2D::set_wall_min_slide_angle); ClassDB::bind_method(D_METHOD("get_up_direction"), &CharacterBody2D::get_up_direction); ClassDB::bind_method(D_METHOD("set_up_direction", "up_direction"), &CharacterBody2D::set_up_direction); ClassDB::bind_method(D_METHOD("set_motion_mode", "mode"), &CharacterBody2D::set_motion_mode); @@ -1754,14 +1754,12 @@ void CharacterBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody2D::_get_slide_collision); ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &CharacterBody2D::_get_last_slide_collision); - ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Free", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Floating", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "up_direction"), "set_up_direction", "get_up_direction"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_motion_velocity", "get_motion_velocity"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides"); - - ADD_GROUP("Free Mode", "free_mode_"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "free_mode_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians", PROPERTY_USAGE_DEFAULT), "set_free_mode_min_slide_angle", "get_free_mode_min_slide_angle"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wall_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians", PROPERTY_USAGE_DEFAULT), "set_wall_min_slide_angle", "get_wall_min_slide_angle"); ADD_GROUP("Floor", "floor_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_stop_on_slope"), "set_floor_stop_on_slope_enabled", "is_floor_stop_on_slope_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_constant_speed"), "set_floor_constant_speed_enabled", "is_floor_constant_speed_enabled"); @@ -1775,7 +1773,7 @@ void CharacterBody2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED); - BIND_ENUM_CONSTANT(MOTION_MODE_FREE); + BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING); BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_ALWAYS); BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY); @@ -1783,12 +1781,12 @@ void CharacterBody2D::_bind_methods() { } void CharacterBody2D::_validate_property(PropertyInfo &property) const { - if (motion_mode == MOTION_MODE_FREE) { + if (motion_mode == MOTION_MODE_FLOATING) { if (property.name.begins_with("floor_") || property.name == "up_direction" || property.name == "slide_on_ceiling") { property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } else { - if (property.name == "free_mode_min_slide_angle") { + if (property.name == "wall_min_slide_angle") { property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } } diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 649d67d759..f1cc100a58 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -328,7 +328,7 @@ class CharacterBody2D : public PhysicsBody2D { public: enum MotionMode { MOTION_MODE_GROUNDED, - MOTION_MODE_FREE, + MOTION_MODE_FLOATING, }; enum MovingPlatformApplyVelocityOnLeave { PLATFORM_VEL_ON_LEAVE_ALWAYS, @@ -374,7 +374,7 @@ private: int platform_layer = 0; real_t floor_max_angle = Math::deg2rad((real_t)45.0); real_t floor_snap_length = 1; - real_t free_mode_min_slide_angle = Math::deg2rad((real_t)15.0); + real_t wall_min_slide_angle = Math::deg2rad((real_t)15.0); Vector2 up_direction = Vector2(0.0, -1.0); uint32_t moving_platform_floor_layers = UINT32_MAX; uint32_t moving_platform_wall_layers = 0; @@ -420,8 +420,8 @@ private: real_t get_floor_snap_length(); void set_floor_snap_length(real_t p_floor_snap_length); - real_t get_free_mode_min_slide_angle() const; - void set_free_mode_min_slide_angle(real_t p_radians); + real_t get_wall_min_slide_angle() const; + void set_wall_min_slide_angle(real_t p_radians); uint32_t get_moving_platform_floor_layers() const; void set_moving_platform_floor_layers(const uint32_t p_exclude_layer); @@ -435,7 +435,7 @@ private: void set_moving_platform_apply_velocity_on_leave(MovingPlatformApplyVelocityOnLeave p_on_leave_velocity); MovingPlatformApplyVelocityOnLeave get_moving_platform_apply_velocity_on_leave() const; - void _move_and_slide_free(double p_delta); + void _move_and_slide_floating(double p_delta); void _move_and_slide_grounded(double p_delta, bool p_was_on_floor); Ref<KinematicCollision2D> _get_slide_collision(int p_bounce); diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 5857b6710f..25c83b0c8f 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -2725,7 +2725,7 @@ void TileMap::_get_property_list(List<PropertyInfo> *p_list) const { } Vector2 TileMap::map_to_world(const Vector2i &p_pos) const { - // SHOULD RETURN THE CENTER OF THE TILE + // SHOULD RETURN THE CENTER OF THE CELL ERR_FAIL_COND_V(!tile_set.is_valid(), Vector2()); Vector2 ret = p_pos; diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index df7c044f9e..3ab09550fa 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -484,7 +484,7 @@ uint32_t CollisionObject3D::create_shape_owner(Object *p_owner) { id = shapes.back()->key() + 1; } - sd.owner = p_owner; + sd.owner_id = p_owner ? p_owner->get_instance_id() : ObjectID(); shapes[id] = sd; @@ -563,7 +563,7 @@ Transform3D CollisionObject3D::shape_owner_get_transform(uint32_t p_owner) const Object *CollisionObject3D::shape_owner_get_owner(uint32_t p_owner) const { ERR_FAIL_COND_V(!shapes.has(p_owner), nullptr); - return shapes[p_owner].owner; + return ObjectDB::get_instance(shapes[p_owner].owner_id); } void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Ref<Shape3D> &p_shape) { diff --git a/scene/3d/collision_object_3d.h b/scene/3d/collision_object_3d.h index f560753543..e92843d784 100644 --- a/scene/3d/collision_object_3d.h +++ b/scene/3d/collision_object_3d.h @@ -57,7 +57,7 @@ private: PhysicsServer3D::BodyMode body_mode = PhysicsServer3D::BODY_MODE_STATIC; struct ShapeData { - Object *owner = nullptr; + ObjectID owner_id; Transform3D xform; struct ShapeBase { RID debug_shape; diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 0a0507207a..d88bb815bc 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -247,7 +247,7 @@ void Light3D::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_angular_distance", PROPERTY_HINT_RANGE, "0,90,0.01"), "set_param", "get_param", PARAM_SIZE); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "light_negative"), "set_negative", "is_negative"); ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "light_specular", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param", "get_param", PARAM_SPECULAR); - ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Dynamic,Static"), "set_bake_mode", "get_bake_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "light_bake_mode", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI/SDFGI only)"), "set_bake_mode", "get_bake_mode"); 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"); @@ -284,8 +284,8 @@ void Light3D::_bind_methods() { BIND_ENUM_CONSTANT(PARAM_MAX); BIND_ENUM_CONSTANT(BAKE_DISABLED); - BIND_ENUM_CONSTANT(BAKE_DYNAMIC); BIND_ENUM_CONSTANT(BAKE_STATIC); + BIND_ENUM_CONSTANT(BAKE_DYNAMIC); } Light3D::Light3D(RenderingServer::LightType p_type) { diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index 93dc8155bb..d5d2aee43d 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -63,8 +63,8 @@ public: enum BakeMode { BAKE_DISABLED, + BAKE_STATIC, BAKE_DYNAMIC, - BAKE_STATIC }; private: diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index 715c421632..825742da35 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -217,7 +217,7 @@ LightmapGIData::~LightmapGIData() { void LightmapGI::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights, Vector<Vector3> &probes) { MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node); - if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) { + if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { bool all_have_uv2_and_normal = true; diff --git a/scene/3d/node_3d.cpp b/scene/3d/node_3d.cpp index a992d2aaf2..515d2cfdc7 100644 --- a/scene/3d/node_3d.cpp +++ b/scene/3d/node_3d.cpp @@ -990,7 +990,7 @@ void Node3D::_bind_methods() { ADD_GROUP("Transform", ""); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_transform", "get_transform"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "global_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_transform", "get_global_transform"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0,or_greater,or_lesser,noslider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "position", PROPERTY_HINT_RANGE, "-99999,99999,0.001,or_greater,or_lesser,noslider,suffix:m", PROPERTY_USAGE_EDITOR), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "rotation", PROPERTY_HINT_RANGE, "-360,360,0.1,or_lesser,or_greater,radians", PROPERTY_USAGE_EDITOR), "set_rotation", "get_rotation"); ADD_PROPERTY(PropertyInfo(Variant::QUATERNION, "quaternion", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_quaternion", "get_quaternion"); ADD_PROPERTY(PropertyInfo(Variant::BASIS, "basis", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR), "set_basis", "get_basis"); diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index b3192a5bb5..1a707024c5 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -1233,7 +1233,7 @@ bool CharacterBody3D::move_and_slide() { if (motion_mode == MOTION_MODE_GROUNDED) { _move_and_slide_grounded(delta, was_on_floor); } else { - _move_and_slide_free(delta); + _move_and_slide_floating(delta); } // Compute real velocity. @@ -1512,7 +1512,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo } } -void CharacterBody3D::_move_and_slide_free(double p_delta) { +void CharacterBody3D::_move_and_slide_floating(double p_delta) { Vector3 motion = motion_velocity * p_delta; platform_rid = RID(); @@ -1929,7 +1929,7 @@ const Vector3 &CharacterBody3D::get_up_direction() const { } void CharacterBody3D::set_up_direction(const Vector3 &p_up_direction) { - ERR_FAIL_COND_MSG(p_up_direction == Vector3(), "up_direction can't be equal to Vector3.ZERO, consider using Free motion mode instead."); + ERR_FAIL_COND_MSG(p_up_direction == Vector3(), "up_direction can't be equal to Vector3.ZERO, consider using Floating motion mode instead."); up_direction = p_up_direction.normalized(); } @@ -2000,12 +2000,11 @@ void CharacterBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &CharacterBody3D::_get_slide_collision); ClassDB::bind_method(D_METHOD("get_last_slide_collision"), &CharacterBody3D::_get_last_slide_collision); - ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Free", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "motion_mode", PROPERTY_HINT_ENUM, "Grounded,Floating", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_motion_mode", "get_motion_mode"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_direction"), "set_up_direction", "get_up_direction"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "slide_on_ceiling"), "set_slide_on_ceiling_enabled", "is_slide_on_ceiling_enabled"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion_velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_motion_velocity", "get_motion_velocity"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_slides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_max_slides", "get_max_slides"); - ADD_GROUP("Free Mode", "free_mode_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wall_min_slide_angle", PROPERTY_HINT_RANGE, "0,180,0.1,radians", PROPERTY_USAGE_DEFAULT), "set_wall_min_slide_angle", "get_wall_min_slide_angle"); ADD_GROUP("Floor", "floor_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "floor_stop_on_slope"), "set_floor_stop_on_slope_enabled", "is_floor_stop_on_slope_enabled"); @@ -2020,7 +2019,7 @@ void CharacterBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); BIND_ENUM_CONSTANT(MOTION_MODE_GROUNDED); - BIND_ENUM_CONSTANT(MOTION_MODE_FREE); + BIND_ENUM_CONSTANT(MOTION_MODE_FLOATING); BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_ALWAYS); BIND_ENUM_CONSTANT(PLATFORM_VEL_ON_LEAVE_UPWARD_ONLY); @@ -2028,7 +2027,7 @@ void CharacterBody3D::_bind_methods() { } void CharacterBody3D::_validate_property(PropertyInfo &property) const { - if (motion_mode == MOTION_MODE_FREE) { + if (motion_mode == MOTION_MODE_FLOATING) { if (property.name.begins_with("floor_") || property.name == "up_direction" || property.name == "slide_on_ceiling") { property.usage = PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL; } diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index e37b841117..65a763b21e 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -345,7 +345,7 @@ class CharacterBody3D : public PhysicsBody3D { public: enum MotionMode { MOTION_MODE_GROUNDED, - MOTION_MODE_FREE, + MOTION_MODE_FLOATING, }; enum MovingPlatformApplyVelocityOnLeave { PLATFORM_VEL_ON_LEAVE_ALWAYS, @@ -468,7 +468,7 @@ private: void set_moving_platform_apply_velocity_on_leave(MovingPlatformApplyVelocityOnLeave p_on_leave_velocity); MovingPlatformApplyVelocityOnLeave get_moving_platform_apply_velocity_on_leave() const; - void _move_and_slide_free(double p_delta); + void _move_and_slide_floating(double p_delta); void _move_and_slide_grounded(double p_delta, bool p_was_on_floor); Ref<KinematicCollision3D> _get_slide_collision(int p_bounce); diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index 0db2fe9fc6..005bb5a737 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -247,7 +247,7 @@ bool GeometryInstance3D::_set(const StringName &p_name, const Variant &p_value) } #ifndef DISABLE_DEPRECATED if (p_name == SceneStringNames::get_singleton()->use_in_baked_light && bool(p_value)) { - set_gi_mode(GI_MODE_BAKED); + set_gi_mode(GI_MODE_STATIC); return true; } @@ -358,7 +358,7 @@ void GeometryInstance3D::set_gi_mode(GIMode p_mode) { RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false); RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_DYNAMIC_GI, false); } break; - case GI_MODE_BAKED: { + case GI_MODE_STATIC: { RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_BAKED_LIGHT, true); RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_USE_DYNAMIC_GI, false); @@ -462,7 +462,7 @@ void GeometryInstance3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_bias", PROPERTY_HINT_RANGE, "0.001,128,0.001"), "set_lod_bias", "get_lod_bias"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_occlusion_culling"), "set_ignore_occlusion_culling", "is_ignoring_occlusion_culling"); ADD_GROUP("Global Illumination", "gi_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Baked,Dynamic"), "set_gi_mode", "get_gi_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_mode", PROPERTY_HINT_ENUM, "Disabled,Static (VoxelGI/SDFGI/LightmapGI),Dynamic (VoxelGI only)"), "set_gi_mode", "get_gi_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "gi_lightmap_scale", PROPERTY_HINT_ENUM, String::utf8("1×,2×,4×,8×")), "set_lightmap_scale", "get_lightmap_scale"); ADD_GROUP("Visibility Range", "visibility_range_"); @@ -479,7 +479,7 @@ void GeometryInstance3D::_bind_methods() { BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY); BIND_ENUM_CONSTANT(GI_MODE_DISABLED); - BIND_ENUM_CONSTANT(GI_MODE_BAKED); + BIND_ENUM_CONSTANT(GI_MODE_STATIC); BIND_ENUM_CONSTANT(GI_MODE_DYNAMIC); BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_1X); diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index dd0eb25001..be964e5080 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -89,7 +89,7 @@ public: enum GIMode { GI_MODE_DISABLED, - GI_MODE_BAKED, + GI_MODE_STATIC, GI_MODE_DYNAMIC }; diff --git a/scene/3d/voxel_gi.cpp b/scene/3d/voxel_gi.cpp index 35ac1792e9..bfe3c80a4f 100644 --- a/scene/3d/voxel_gi.cpp +++ b/scene/3d/voxel_gi.cpp @@ -282,7 +282,7 @@ Vector3 VoxelGI::get_extents() const { void VoxelGI::_find_meshes(Node *p_at_node, List<PlotMesh> &plot_meshes) { MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node); - if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_BAKED && mi->is_visible_in_tree()) { + if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { AABB aabb = mesh->get_aabb(); diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index 2740103a4a..9d37b2d6ac 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -371,6 +371,8 @@ void AnimationNodeOneShot::_bind_methods() { ClassDB::bind_method(D_METHOD("set_use_sync", "enable"), &AnimationNodeOneShot::set_use_sync); ClassDB::bind_method(D_METHOD("is_using_sync"), &AnimationNodeOneShot::is_using_sync); + ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_mode", PROPERTY_HINT_ENUM, "Blend,Add"), "set_mix_mode", "get_mix_mode"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadein_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_fadein_time", "get_fadein_time"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fadeout_time", PROPERTY_HINT_RANGE, "0,60,0.01,or_greater"), "set_fadeout_time", "get_fadeout_time"); diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index eee7663b09..5f937acb8d 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -382,8 +382,11 @@ Ref<ButtonGroup> BaseButton::get_button_group() const { } void BaseButton::set_shortcut_context(Node *p_node) { - ERR_FAIL_NULL_MSG(p_node, "Shortcut context node can't be null."); - shortcut_context = p_node->get_instance_id(); + if (p_node != nullptr) { + shortcut_context = p_node->get_instance_id(); + } else { + shortcut_context = ObjectID(); + } } Node *BaseButton::get_shortcut_context() const { @@ -444,7 +447,7 @@ void BaseButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disabled"), "set_disabled", "is_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "toggle_mode"), "set_toggle_mode", "is_toggle_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_in_tooltip"), "set_shortcut_in_tooltip", "is_shortcut_in_tooltip_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "button_pressed"), "set_pressed", "is_pressed"); ADD_PROPERTY(PropertyInfo(Variant::INT, "action_mode", PROPERTY_HINT_ENUM, "Button Press,Button Release"), "set_action_mode", "get_action_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "button_mask", PROPERTY_HINT_FLAGS, "Mouse Left, Mouse Right, Mouse Middle"), "set_button_mask", "get_button_mask"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_pressed_outside"), "set_keep_pressed_outside", "is_keep_pressed_outside"); diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index b3754ba6db..8924c37c50 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -937,8 +937,10 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) { return; } - const int cc = get_caret_column(); + /* When not splitting the line, we need to factor in indentation from the end of the current line. */ + const int cc = p_split_current_line ? get_caret_column() : get_line(get_caret_line()).length(); const int cl = get_caret_line(); + const String line = get_line(cl); String ins = "\n"; @@ -1012,6 +1014,8 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) { bool first_line = false; if (!p_split_current_line) { + deselect(); + if (p_above) { if (cl > 0) { set_caret_line(cl - 1, false); @@ -1793,7 +1797,7 @@ void CodeEdit::request_code_completion(bool p_force) { } if (p_force) { - emit_signal(SNAME("request_code_completion")); + emit_signal(SNAME("code_completion_requested")); return; } @@ -1801,9 +1805,9 @@ void CodeEdit::request_code_completion(bool p_force) { int ofs = CLAMP(get_caret_column(), 0, line.length()); if (ofs > 0 && (is_in_string(get_caret_line(), ofs) != -1 || _is_char(line[ofs - 1]) || code_completion_prefixes.has(line[ofs - 1]))) { - emit_signal(SNAME("request_code_completion")); + emit_signal(SNAME("code_completion_requested")); } else if (ofs > 1 && line[ofs - 1] == ' ' && code_completion_prefixes.has(line[ofs - 2])) { - emit_signal(SNAME("request_code_completion")); + emit_signal(SNAME("code_completion_requested")); } } @@ -2261,7 +2265,7 @@ void CodeEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "line"))); /* Code Completion */ - ADD_SIGNAL(MethodInfo("request_code_completion")); + ADD_SIGNAL(MethodInfo("code_completion_requested")); /* Symbol lookup */ ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "column"))); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index f167062f7d..562ea8a8f7 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -240,7 +240,7 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) { return false; } - if (p_value.get_type() == Variant::NIL) { + 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/")) { String dname = name.get_slicec('/', 1); if (data.icon_override.has(dname)) { diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 44ef641cb8..e5bd6f4882 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -110,6 +110,9 @@ void FileDialog::_notification(int p_what) { show_hidden->set_icon(vbox->get_theme_icon(SNAME("toggle_hidden"), SNAME("FileDialog"))); _theme_changed(); } + if (p_what == NOTIFICATION_TRANSLATION_CHANGED) { + update_filters(); + } } void FileDialog::unhandled_input(const Ref<InputEvent> &p_event) { @@ -638,7 +641,7 @@ void FileDialog::update_filters() { all_filters += ", ..."; } - filter->add_item(String(TTRC("All Recognized")) + " (" + all_filters + ")"); + filter->add_item(RTR("All Recognized") + " (" + all_filters + ")"); } for (int i = 0; i < filters.size(); i++) { String flt = filters[i].get_slice(";", 0).strip_edges(); @@ -650,7 +653,7 @@ void FileDialog::update_filters() { } } - filter->add_item(TTRC("All Files (*)")); + filter->add_item(RTR("All Files") + " (*)"); } void FileDialog::clear_filters() { diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 79b73f7cc3..2be76473b0 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -1070,7 +1070,9 @@ void GraphEdit::set_selected(Node *p_child) { void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { ERR_FAIL_COND(p_ev.is_null()); - panner->gui_input(p_ev); + if (panner->gui_input(p_ev, warped_panning ? get_global_rect() : Rect2())) { + return; + } Ref<InputEventMouseMotion> mm = p_ev; @@ -1272,7 +1274,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { if (_filter_input(b->get_position())) { return; } - if (Input::get_singleton()->is_key_pressed(Key::SPACE)) { + if (panner->is_panning()) { return; } @@ -1354,7 +1356,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { } } -void GraphEdit::_scroll_callback(Vector2 p_scroll_vec) { +void GraphEdit::_scroll_callback(Vector2 p_scroll_vec, bool p_alt) { if (p_scroll_vec.x != 0) { h_scroll->set_value(h_scroll->get_value() + (h_scroll->get_page() * Math::abs(p_scroll_vec.x) / 8) * SIGN(p_scroll_vec.x)); } else { @@ -1367,7 +1369,7 @@ void GraphEdit::_pan_callback(Vector2 p_scroll_vec) { v_scroll->set_value(v_scroll->get_value() - p_scroll_vec.y); } -void GraphEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin) { +void GraphEdit::_zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt) { set_zoom_custom(p_scroll_vec.y < 0 ? zoom * zoom_step : zoom / zoom_step, p_origin); } @@ -1678,6 +1680,14 @@ HBoxContainer *GraphEdit::get_zoom_hbox() { return zoom_hb; } +Ref<ViewPanner> GraphEdit::get_panner() { + return panner; +} + +void GraphEdit::set_warped_panning(bool p_warped) { + warped_panning = p_warped; +} + int GraphEdit::_set_operations(SET_OPERATIONS p_operation, Set<StringName> &r_u, const Set<StringName> &r_v) { switch (p_operation) { case GraphEdit::IS_EQUAL: { @@ -2305,7 +2315,6 @@ GraphEdit::GraphEdit() { panner.instantiate(); panner->set_callbacks(callable_mp(this, &GraphEdit::_scroll_callback), callable_mp(this, &GraphEdit::_pan_callback), callable_mp(this, &GraphEdit::_zoom_callback)); - panner->set_disable_rmb(true); top_layer = memnew(GraphEditFilter(this)); add_child(top_layer, false, INTERNAL_MODE_BACK); @@ -2313,6 +2322,7 @@ GraphEdit::GraphEdit() { top_layer->set_anchors_and_offsets_preset(Control::PRESET_WIDE); top_layer->connect("draw", callable_mp(this, &GraphEdit::_top_layer_draw)); top_layer->connect("gui_input", callable_mp(this, &GraphEdit::_top_layer_input)); + top_layer->connect("focus_exited", callable_mp(panner.ptr(), &ViewPanner::release_pan_key)); connections_layer = memnew(Control); add_child(connections_layer, false, INTERNAL_MODE_FRONT); diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 4e998d30a7..da973b46f0 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -130,9 +130,10 @@ private: float port_grab_distance_vertical; Ref<ViewPanner> panner; - void _scroll_callback(Vector2 p_scroll_vec); + bool warped_panning = true; + void _scroll_callback(Vector2 p_scroll_vec, bool p_alt); void _pan_callback(Vector2 p_scroll_vec); - void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin); + void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); bool connecting = false; String connecting_from; @@ -348,6 +349,8 @@ public: bool is_connection_lines_antialiased() const; HBoxContainer *get_zoom_hbox(); + Ref<ViewPanner> get_panner(); + void set_warped_panning(bool p_warped); void arrange_nodes(); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index d7139d0140..c9fddc3e17 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1403,12 +1403,12 @@ void PopupMenu::activate_item(int p_item) { need_hide = false; } - emit_signal(SNAME("id_pressed"), id); - emit_signal(SNAME("index_pressed"), p_item); - if (need_hide) { hide(); } + + emit_signal(SNAME("id_pressed"), id); + emit_signal(SNAME("index_pressed"), p_item); } void PopupMenu::remove_item(int p_idx) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index b50fad0e42..e9d346f943 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -330,7 +330,7 @@ void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> table->columns.write[column].width = MAX(table->columns.write[column].width, ceil(frame->lines[i].text_buf->get_size().x)); if (i > 0) { - frame->lines.write[i].offset.y = frame->lines[i - 1].offset.y + frame->lines[i - 1].text_buf->get_size().y + get_theme_constant(SNAME("line_separation")); + frame->lines.write[i].offset.y = frame->lines[i - 1].offset.y + frame->lines[i - 1].text_buf->get_size().y + frame->lines[i - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } else { frame->lines.write[i].offset.y = 0; } @@ -370,7 +370,7 @@ void RichTextLabel::_resize_line(ItemFrame *p_frame, int p_line, const Ref<Font> } if (p_line > 0) { - l.offset.y = p_frame->lines[p_line - 1].offset.y + p_frame->lines[p_line - 1].text_buf->get_size().y + get_theme_constant(SNAME("line_separation")); + l.offset.y = p_frame->lines[p_line - 1].offset.y + p_frame->lines[p_line - 1].text_buf->get_size().y + p_frame->lines[p_line - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } else { l.offset.y = 0; } @@ -583,7 +583,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> table->columns.write[column].width = MAX(table->columns.write[column].width, ceil(frame->lines[i].text_buf->get_size().x)); if (i > 0) { - frame->lines.write[i].offset.y = frame->lines[i - 1].offset.y + frame->lines[i - 1].text_buf->get_size().y + get_theme_constant(SNAME("line_separation")); + frame->lines.write[i].offset.y = frame->lines[i - 1].offset.y + frame->lines[i - 1].text_buf->get_size().y + frame->lines[i - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } else { frame->lines.write[i].offset.y = 0; } @@ -631,7 +631,7 @@ void RichTextLabel::_shape_line(ItemFrame *p_frame, int p_line, const Ref<Font> *r_char_offset = l.char_offset + l.char_count; if (p_line > 0) { - l.offset.y = p_frame->lines[p_line - 1].offset.y + p_frame->lines[p_line - 1].text_buf->get_size().y + get_theme_constant(SNAME("line_separation")); + l.offset.y = p_frame->lines[p_line - 1].offset.y + p_frame->lines[p_line - 1].text_buf->get_size().y + p_frame->lines[p_line - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } else { l.offset.y = 0; } @@ -1198,7 +1198,7 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item //TODO, change to binary search ? while (from_line < main->lines.size()) { - if (main->lines[from_line].offset.y + main->lines[from_line].text_buf->get_size().y >= vofs) { + if (main->lines[from_line].offset.y + main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")) >= vofs) { break; } from_line++; @@ -1211,7 +1211,7 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item Point2 ofs = text_rect.get_position() + Vector2(0, main->lines[from_line].offset.y - vofs); while (ofs.y < size.height && from_line < main->lines.size()) { _find_click_in_line(p_frame, from_line, ofs, text_rect.size.x, p_click, r_click_frame, r_click_line, r_click_item, r_click_char); - ofs.y += main->lines[from_line].text_buf->get_size().y + get_theme_constant(SNAME("line_separation")); + ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); if (((r_click_item != nullptr) && ((*r_click_item) != nullptr)) || ((r_click_frame != nullptr) && ((*r_click_frame) != nullptr))) { if (r_outside != nullptr) { *r_outside = false; @@ -1330,7 +1330,7 @@ float RichTextLabel::_find_click_in_line(ItemFrame *p_frame, int p_line, const V if (rect.has_point(p_click) && !table_hit) { char_pos = TS->shaped_text_hit_test_position(rid, p_click.x - rect.position.x); } - off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom(); + off.y += TS->shaped_text_get_descent(rid) + l.text_buf->get_spacing_bottom() + get_theme_constant(SNAME("line_separation")); } if (char_pos >= 0) { @@ -1494,7 +1494,7 @@ void RichTextLabel::_notification(int p_what) { //TODO, change to binary search ? while (from_line < main->lines.size()) { - if (main->lines[from_line].offset.y + main->lines[from_line].text_buf->get_size().y >= vofs) { + if (main->lines[from_line].offset.y + main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")) >= vofs) { break; } from_line++; @@ -1520,7 +1520,7 @@ void RichTextLabel::_notification(int p_what) { while (ofs.y < size.height && from_line < main->lines.size()) { visible_paragraph_count++; visible_line_count += _draw_line(main, from_line, ofs, text_rect.size.x, base_color, outline_size, outline_color, font_shadow_color, shadow_outline_size, shadow_ofs, processed_glyphs); - ofs.y += main->lines[from_line].text_buf->get_size().y + get_theme_constant(SNAME("line_separation")); + ofs.y += main->lines[from_line].text_buf->get_size().y + main->lines[from_line].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); from_line++; } } break; @@ -2208,7 +2208,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { int total_height = 0; if (p_frame->lines.size()) { - total_height = p_frame->lines[p_frame->lines.size() - 1].offset.y + p_frame->lines[p_frame->lines.size() - 1].text_buf->get_size().y; + total_height = p_frame->lines[p_frame->lines.size() - 1].offset.y + p_frame->lines[p_frame->lines.size() - 1].text_buf->get_size().y * p_frame->lines[p_frame->lines.size() - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } p_frame->first_resized_line = p_frame->lines.size(); @@ -2240,7 +2240,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) { int total_height = 0; if (p_frame->lines.size()) { - total_height = p_frame->lines[p_frame->lines.size() - 1].offset.y + p_frame->lines[p_frame->lines.size() - 1].text_buf->get_size().y; + total_height = p_frame->lines[p_frame->lines.size() - 1].offset.y + p_frame->lines[p_frame->lines.size() - 1].text_buf->get_size().y + p_frame->lines[p_frame->lines.size() - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } p_frame->first_invalid_line = p_frame->lines.size(); @@ -4066,7 +4066,7 @@ void RichTextLabel::install_effect(const Variant effect) { int RichTextLabel::get_content_height() const { int total_height = 0; if (main->lines.size()) { - total_height = main->lines[main->lines.size() - 1].offset.y + main->lines[main->lines.size() - 1].text_buf->get_size().y; + total_height = main->lines[main->lines.size() - 1].offset.y + main->lines[main->lines.size() - 1].text_buf->get_size().y * main->lines[main->lines.size() - 1].text_buf->get_line_count() * get_theme_constant(SNAME("line_separation")); } return total_height; } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index d6b449abd1..7db1fae2b6 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -128,6 +128,10 @@ void TextEdit::Text::set_width(float p_width) { width = p_width; } +float TextEdit::Text::get_width() const { + return width; +} + int TextEdit::Text::get_line_wrap_amount(int p_line) const { ERR_FAIL_INDEX_V(p_line, text.size(), 0); @@ -646,6 +650,8 @@ void TextEdit::_notification(int p_what) { } } + bool draw_placeholder = text.size() == 1 && text[0].length() == 0; + // Get the highlighted words. String highlighted_text = get_selected_text(); @@ -656,7 +662,7 @@ void TextEdit::_notification(int p_what) { int first_visible_line = get_first_visible_line() - 1; int draw_amount = visible_rows + (smooth_scroll_enabled ? 1 : 0); - draw_amount += get_line_wrap_count(first_visible_line + 1); + draw_amount += draw_placeholder ? placeholder_wraped_rows.size() - 1 : get_line_wrap_count(first_visible_line + 1); // Draw minimap. if (draw_minimap) { @@ -841,7 +847,7 @@ void TextEdit::_notification(int p_what) { // Draw main text. caret.visible = false; line_drawing_cache.clear(); - int row_height = get_line_height(); + int row_height = draw_placeholder ? placeholder_line_height + line_spacing : get_line_height(); int line = first_visible_line; for (int i = 0; i < draw_amount; i++) { line++; @@ -867,11 +873,14 @@ void TextEdit::_notification(int p_what) { // Ensure we at least use the font color. Color current_color = !editable ? font_readonly_color : font_color; + if (draw_placeholder) { + current_color.a *= placeholder_alpha; + } - const Ref<TextParagraph> ldata = text.get_line_data(line); + const Ref<TextParagraph> ldata = draw_placeholder ? placeholder_data_buf : text.get_line_data(line); - Vector<String> wrap_rows = get_line_wrapped_text(line); - int line_wrap_amount = get_line_wrap_count(line); + Vector<String> wrap_rows = draw_placeholder ? placeholder_wraped_rows : get_line_wrapped_text(line); + int line_wrap_amount = draw_placeholder ? placeholder_wraped_rows.size() - 1 : get_line_wrap_count(line); for (int line_wrap_index = 0; line_wrap_index <= line_wrap_amount; line_wrap_index++) { if (line_wrap_index != 0) { @@ -1385,7 +1394,9 @@ void TextEdit::_notification(int p_what) { } } - line_drawing_cache[line] = cache_entry; + if (draw_placeholder) { + line_drawing_cache[line] = cache_entry; + } } if (has_focus()) { @@ -2047,6 +2058,7 @@ void TextEdit::_new_line(bool p_split_current_line, bool p_above) { bool first_line = false; if (!p_split_current_line) { + deselect(); if (p_above) { if (caret.line > 0) { set_caret_line(caret.line - 1, false); @@ -2432,6 +2444,47 @@ void TextEdit::_move_caret_document_end(bool p_select) { } } +void TextEdit::_update_placeholder() { + if (font.is_null() || font_size <= 0) { + return; // Not in tree? + } + + // Placeholder is generally smaller then text docuemnts, and updates less so this should be fast enough for now. + placeholder_data_buf->clear(); + placeholder_data_buf->set_width(text.get_width()); + placeholder_data_buf->set_direction((TextServer::Direction)text_direction); + placeholder_data_buf->set_preserve_control(draw_control_chars); + placeholder_data_buf->add_string(placeholder_text, font, font_size, opentype_features, language); + + placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_text); + if (placeholder_bidi_override.is_empty()) { + TS->shaped_text_set_bidi_override(placeholder_data_buf->get_rid(), placeholder_bidi_override); + } + + if (get_tab_size() > 0) { + Vector<float> tabs; + tabs.push_back(font->get_char_size(' ', 0, font_size).width * get_tab_size()); + placeholder_data_buf->tab_align(tabs); + } + + // Update height. + const int wrap_amount = placeholder_data_buf->get_line_count() - 1; + placeholder_line_height = font->get_height(font_size); + for (int i = 0; i <= wrap_amount; i++) { + placeholder_line_height = MAX(placeholder_line_height, placeholder_data_buf->get_line_size(i).y); + } + + // Update width. + placeholder_max_width = placeholder_data_buf->get_size().x; + + // Update wrapped rows. + placeholder_wraped_rows.clear(); + for (int i = 0; i <= wrap_amount; i++) { + Vector2i line_range = placeholder_data_buf->get_line_range(i); + placeholder_wraped_rows.push_back(placeholder_text.substr(line_range.x, line_range.y - line_range.x)); + } +} + void TextEdit::_update_caches() { /* Internal API for CodeEdit. */ brace_mismatch_color = get_theme_color(SNAME("brace_mismatch_color"), SNAME("CodeEdit")); @@ -2485,6 +2538,7 @@ void TextEdit::_update_caches() { text.set_font(font); text.set_font_size(font_size); text.invalidate_all(); + _update_placeholder(); /* Syntax highlighting. */ if (syntax_highlighter.is_valid()) { @@ -2664,6 +2718,7 @@ void TextEdit::set_text_direction(Control::TextDirection p_text_direction) { } text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale()); text.invalidate_all(); + _update_placeholder(); if (menu_dir) { menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_INHERITED), text_direction == TEXT_DIRECTION_INHERITED); @@ -2685,6 +2740,7 @@ void TextEdit::set_opentype_feature(const String &p_name, int p_value) { opentype_features[tag] = p_value; text.set_font_features(opentype_features); text.invalidate_all(); + _update_placeholder(); update(); } } @@ -2701,6 +2757,7 @@ void TextEdit::clear_opentype_features() { opentype_features.clear(); text.set_font_features(opentype_features); text.invalidate_all(); + _update_placeholder(); update(); } @@ -2715,6 +2772,7 @@ void TextEdit::set_language(const String &p_language) { } text.set_direction_and_language(dir, (!language.is_empty()) ? language : TranslationServer::get_singleton()->get_tool_locale()); text.invalidate_all(); + _update_placeholder(); update(); } } @@ -2756,6 +2814,7 @@ void TextEdit::set_tab_size(const int p_size) { } text.set_tab_size(p_size); text.invalidate_all_lines(); + _update_placeholder(); update(); } @@ -2878,6 +2937,25 @@ int TextEdit::get_line_count() const { return text.size(); } +void TextEdit::set_placeholder(const String &p_text) { + placeholder_text = p_text; + _update_placeholder(); + update(); +} + +String TextEdit::get_placeholder() const { + return placeholder_text; +} + +void TextEdit::set_placeholder_alpha(float p_alpha) { + placeholder_alpha = p_alpha; + update(); +} + +float TextEdit::get_placeholder_alpha() const { + return placeholder_alpha; +} + void TextEdit::set_line(int p_line, const String &p_new_text) { if (p_line < 0 || p_line >= text.size()) { return; @@ -4783,6 +4861,7 @@ void TextEdit::set_draw_control_chars(bool p_enabled) { } text.set_draw_control_chars(draw_control_chars); text.invalidate_all(); + _update_placeholder(); update(); } } @@ -4862,6 +4941,12 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_text"), &TextEdit::get_text); ClassDB::bind_method(D_METHOD("get_line_count"), &TextEdit::get_line_count); + ClassDB::bind_method(D_METHOD("set_placeholder", "text"), &TextEdit::set_placeholder); + ClassDB::bind_method(D_METHOD("get_placeholder"), &TextEdit::get_placeholder); + + ClassDB::bind_method(D_METHOD("set_placeholder_alpha", "alpha"), &TextEdit::set_placeholder_alpha); + ClassDB::bind_method(D_METHOD("get_placeholder_alpha"), &TextEdit::get_placeholder_alpha); + ClassDB::bind_method(D_METHOD("set_line", "line", "new_text"), &TextEdit::set_line); ClassDB::bind_method(D_METHOD("get_line", "line"), &TextEdit::get_line); @@ -5170,6 +5255,8 @@ void TextEdit::_bind_methods() { /* Inspector */ ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "placeholder_text", PROPERTY_HINT_MULTILINE_TEXT), "set_placeholder", "get_placeholder"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "placeholder_alpha", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_placeholder_alpha", "get_placeholder_alpha"); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); @@ -5245,6 +5332,7 @@ bool TextEdit::_set(const StringName &p_name, const Variant &p_value) { opentype_features.erase(tag); text.set_font_features(opentype_features); text.invalidate_all(); + _update_placeholder(); update(); } } else { @@ -5252,6 +5340,7 @@ bool TextEdit::_set(const StringName &p_name, const Variant &p_value) { opentype_features[tag] = value; text.set_font_features(opentype_features); text.invalidate_all(); + _update_placeholder(); update(); } } @@ -5903,6 +5992,7 @@ void TextEdit::_update_wrap_at_column(bool p_force) { text.set_width(-1); } text.invalidate_all_lines(); + _update_placeholder(); } _update_caret_wrap_offset(); @@ -5930,14 +6020,16 @@ void TextEdit::_update_scrollbars() { h_scroll->set_begin(Point2(0, size.height - hmin.height)); h_scroll->set_end(Point2(size.width - vmin.width, size.height)); + bool draw_placeholder = text.size() == 1 && text[0].length() == 0; + int visible_rows = get_visible_line_count(); - int total_rows = get_total_visible_line_count(); + int total_rows = draw_placeholder ? placeholder_wraped_rows.size() - 1 : get_total_visible_line_count(); if (scroll_past_end_of_file_enabled) { total_rows += visible_rows - 1; } int visible_width = size.width - style_normal->get_minimum_size().width; - int total_width = text.get_max_width() + vmin.x + gutters_width + gutter_padding; + int total_width = (draw_placeholder ? placeholder_max_width : text.get_max_width()) + vmin.x + gutters_width + gutter_padding; if (draw_minimap) { total_width += minimap_width; @@ -6009,20 +6101,22 @@ void TextEdit::_scroll_moved(double p_to_val) { } if (v_scroll->is_visible_in_tree()) { // Set line ofs and wrap ofs. + bool draw_placeholder = text.size() == 1 && text[0].length() == 0; + int v_scroll_i = floor(get_v_scroll()); int sc = 0; int n_line; for (n_line = 0; n_line < text.size(); n_line++) { if (!_is_line_hidden(n_line)) { sc++; - sc += get_line_wrap_count(n_line); + sc += draw_placeholder ? placeholder_wraped_rows.size() - 1 : get_line_wrap_count(n_line); if (sc > v_scroll_i) { break; } } } n_line = MIN(n_line, text.size() - 1); - int line_wrap_amount = get_line_wrap_count(n_line); + int line_wrap_amount = draw_placeholder ? placeholder_wraped_rows.size() - 1 : get_line_wrap_count(n_line); int wi = line_wrap_amount - (sc - v_scroll_i - 1); wi = CLAMP(wi, 0, line_wrap_amount); @@ -6450,6 +6544,8 @@ void TextEdit::_base_remove_text(int p_from_line, int p_from_column, int p_to_li } TextEdit::TextEdit() { + placeholder_data_buf.instantiate(); + clear(); set_focus_mode(FOCUS_ALL); _update_caches(); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 0d0f4f6dba..fdaa928598 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -189,6 +189,7 @@ private: int get_max_width() const; void set_width(float p_width); + float get_width() const; int get_line_wrap_amount(int p_line) const; Vector<Vector2i> get_line_wrap_ranges(int p_line) const; @@ -249,6 +250,19 @@ private: String ime_text = ""; Point2 ime_selection; + // Placeholder + float placeholder_alpha = 0.6; + + String placeholder_text = ""; + Array placeholder_bidi_override; + Ref<TextParagraph> placeholder_data_buf; + int placeholder_line_height = -1; + int placeholder_max_width = -1; + + Vector<String> placeholder_wraped_rows; + + void _update_placeholder(); + /* Initialise to opposite first, so we get past the early-out in set_editable. */ bool editable = false; @@ -667,6 +681,12 @@ public: String get_text() const; int get_line_count() const; + void set_placeholder(const String &p_text); + String get_placeholder() const; + + void set_placeholder_alpha(float p_alpha); + float get_placeholder_alpha() const; + void set_line(int p_line, const String &p_new_text); String get_line(int p_line) const; diff --git a/scene/gui/view_panner.cpp b/scene/gui/view_panner.cpp index ba5e8d4a17..71865b4864 100644 --- a/scene/gui/view_panner.cpp +++ b/scene/gui/view_panner.cpp @@ -31,22 +31,18 @@ #include "view_panner.h" #include "core/input/input.h" +#include "core/input/shortcut.h" #include "core/os/keyboard.h" bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - // Alt modifier is unused, so ignore such events. - if (mb->is_alt_pressed()) { - return false; - } - Vector2i scroll_vec = Vector2((mb->get_button_index() == MouseButton::WHEEL_RIGHT) - (mb->get_button_index() == MouseButton::WHEEL_LEFT), (mb->get_button_index() == MouseButton::WHEEL_DOWN) - (mb->get_button_index() == MouseButton::WHEEL_UP)); if (scroll_vec != Vector2()) { if (control_scheme == SCROLL_PANS) { if (mb->is_ctrl_pressed()) { scroll_vec.y *= mb->get_factor(); - callback_helper(zoom_callback, scroll_vec, mb->get_position()); + callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed())); return true; } else { Vector2 panning; @@ -57,7 +53,7 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) panning.y += mb->get_factor() * scroll_vec.y; panning.x += mb->get_factor() * scroll_vec.x; } - callback_helper(scroll_callback, panning); + callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed())); return true; } } else { @@ -70,23 +66,33 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) panning.y += mb->get_factor() * scroll_vec.y; panning.x += mb->get_factor() * scroll_vec.x; } - callback_helper(scroll_callback, panning); + callback_helper(scroll_callback, varray(panning, mb->is_alt_pressed())); return true; } else if (!mb->is_shift_pressed()) { scroll_vec.y *= mb->get_factor(); - callback_helper(zoom_callback, scroll_vec, mb->get_position()); + callback_helper(zoom_callback, varray(scroll_vec, mb->get_position(), mb->is_alt_pressed())); return true; } } } - if (mb->get_button_index() == MouseButton::MIDDLE || (mb->get_button_index() == MouseButton::RIGHT && !disable_rmb) || (mb->get_button_index() == MouseButton::LEFT && (Input::get_singleton()->is_key_pressed(Key::SPACE) || (is_dragging && !mb->is_pressed())))) { + // Alt is not used for button presses, so ignore it. + if (mb->is_alt_pressed()) { + return false; + } + + bool is_drag_event = mb->get_button_index() == MouseButton::MIDDLE || + (enable_rmb && mb->get_button_index() == MouseButton::RIGHT) || + (!simple_panning_enabled && mb->get_button_index() == MouseButton::LEFT && is_panning()) || + (force_drag && mb->get_button_index() == MouseButton::LEFT); + + if (is_drag_event) { if (mb->is_pressed()) { is_dragging = true; } else { is_dragging = false; } - return true; + return mb->get_button_index() != MouseButton::LEFT || mb->is_pressed(); // Don't consume LMB release events (it fixes some selection problems). } } @@ -94,9 +100,20 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) if (mm.is_valid()) { if (is_dragging) { if (p_canvas_rect != Rect2()) { - callback_helper(pan_callback, Input::get_singleton()->warp_mouse_motion(mm, p_canvas_rect)); + callback_helper(pan_callback, varray(Input::get_singleton()->warp_mouse_motion(mm, p_canvas_rect))); } else { - callback_helper(pan_callback, mm->get_relative()); + callback_helper(pan_callback, varray(mm->get_relative())); + } + return true; + } + } + + Ref<InputEventKey> k = p_event; + if (k.is_valid()) { + if (pan_view_shortcut.is_valid() && pan_view_shortcut->matches_event(k)) { + pan_key_pressed = k->is_pressed(); + if (simple_panning_enabled || (Input::get_singleton()->get_mouse_button_mask() & MouseButton::LEFT) != MouseButton::NONE) { + is_dragging = pan_key_pressed; } return true; } @@ -105,26 +122,20 @@ bool ViewPanner::gui_input(const Ref<InputEvent> &p_event, Rect2 p_canvas_rect) return false; } -void ViewPanner::callback_helper(Callable p_callback, Vector2 p_arg1, Vector2 p_arg2) { - if (p_callback == zoom_callback) { - const Variant **argptr = (const Variant **)alloca(sizeof(Variant *) * 2); - Variant var1 = p_arg1; - argptr[0] = &var1; - Variant var2 = p_arg2; - argptr[1] = &var2; - - Variant result; - Callable::CallError ce; - p_callback.call(argptr, 2, result, ce); - } else { - const Variant **argptr = (const Variant **)alloca(sizeof(Variant *)); - Variant var = p_arg1; - argptr[0] = &var; - - Variant result; - Callable::CallError ce; - p_callback.call(argptr, 1, result, ce); +void ViewPanner::release_pan_key() { + pan_key_pressed = false; + is_dragging = false; +} + +void ViewPanner::callback_helper(Callable p_callback, Vector<Variant> p_args) { + const Variant **argptr = (const Variant **)alloca(sizeof(Variant *) * p_args.size()); + for (int i = 0; i < p_args.size(); i++) { + argptr[i] = &p_args[i]; } + + Variant result; + Callable::CallError ce; + p_callback.call(argptr, p_args.size(), result, ce); } void ViewPanner::set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback) { @@ -137,6 +148,37 @@ void ViewPanner::set_control_scheme(ControlScheme p_scheme) { control_scheme = p_scheme; } -void ViewPanner::set_disable_rmb(bool p_disable) { - disable_rmb = p_disable; +void ViewPanner::set_enable_rmb(bool p_enable) { + enable_rmb = p_enable; +} + +void ViewPanner::set_pan_shortcut(Ref<Shortcut> p_shortcut) { + pan_view_shortcut = p_shortcut; + pan_key_pressed = false; +} + +void ViewPanner::set_simple_panning_enabled(bool p_enabled) { + simple_panning_enabled = p_enabled; +} + +void ViewPanner::setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning) { + set_control_scheme(p_scheme); + set_pan_shortcut(p_shortcut); + set_simple_panning_enabled(p_simple_panning); +} + +bool ViewPanner::is_panning() const { + return is_dragging || pan_key_pressed; +} + +void ViewPanner::set_force_drag(bool p_force) { + force_drag = p_force; +} + +ViewPanner::ViewPanner() { + Array inputs; + inputs.append(InputEventKey::create_reference(Key::SPACE)); + + pan_view_shortcut.instantiate(); + pan_view_shortcut->set_events(inputs); } diff --git a/scene/gui/view_panner.h b/scene/gui/view_panner.h index 0a92cb3dfd..5b820c5f8f 100644 --- a/scene/gui/view_panner.h +++ b/scene/gui/view_panner.h @@ -34,6 +34,7 @@ #include "core/object/ref_counted.h" class InputEvent; +class Shortcut; class ViewPanner : public RefCounted { GDCLASS(ViewPanner, RefCounted); @@ -46,23 +47,37 @@ public: private: bool is_dragging = false; - bool disable_rmb = false; + bool pan_key_pressed = false; + bool force_drag = false; + + bool enable_rmb = false; + bool simple_panning_enabled = false; + + Ref<Shortcut> pan_view_shortcut; Callable scroll_callback; Callable pan_callback; Callable zoom_callback; - void callback_helper(Callable p_callback, Vector2 p_arg1, Vector2 p_arg2 = Vector2()); + void callback_helper(Callable p_callback, Vector<Variant> p_args); ControlScheme control_scheme = SCROLL_ZOOMS; public: void set_callbacks(Callable p_scroll_callback, Callable p_pan_callback, Callable p_zoom_callback); void set_control_scheme(ControlScheme p_scheme); - void set_disable_rmb(bool p_disable); + void set_enable_rmb(bool p_enable); + void set_pan_shortcut(Ref<Shortcut> p_shortcut); + void set_simple_panning_enabled(bool p_enabled); - bool is_panning() const { return is_dragging; } + void setup(ControlScheme p_scheme, Ref<Shortcut> p_shortcut, bool p_simple_panning); + + bool is_panning() const; + void set_force_drag(bool p_force); bool gui_input(const Ref<InputEvent> &p_ev, Rect2 p_canvas_rect = Rect2()); + void release_pan_key(); + + ViewPanner(); }; #endif // VIEW_PANNER_H diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 34cc4aceb8..65d210983e 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -442,30 +442,25 @@ void HTTPRequest::_request_done(int p_status, int p_code, const PackedStringArra is_compressed = false; } - const PackedByteArray *data = nullptr; - if (accept_gzip && is_compressed && p_data.size() > 0) { // Decompress request body - PackedByteArray *decompressed = memnew(PackedByteArray); - int result = Compression::decompress_dynamic(decompressed, body_size_limit, p_data.ptr(), p_data.size(), mode); + PackedByteArray decompressed; + int result = Compression::decompress_dynamic(&decompressed, body_size_limit, p_data.ptr(), p_data.size(), mode); if (result == OK) { - data = decompressed; + emit_signal(SNAME("request_completed"), p_status, p_code, p_headers, decompressed); + return; } else if (result == -5) { WARN_PRINT("Decompressed size of HTTP response body exceeded body_size_limit"); p_status = RESULT_BODY_SIZE_LIMIT_EXCEEDED; // Just return the raw data if we failed to decompress it - data = &p_data; } else { WARN_PRINT("Failed to decompress HTTP response body"); p_status = RESULT_BODY_DECOMPRESS_FAILED; // Just return the raw data if we failed to decompress it - data = &p_data; } - } else { - data = &p_data; } - emit_signal(SNAME("request_completed"), p_status, p_code, p_headers, *data); + emit_signal(SNAME("request_completed"), p_status, p_code, p_headers, p_data); } void HTTPRequest::_notification(int p_what) { diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 416dec3e4f..a2415442f8 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2188,7 +2188,7 @@ void Node::remap_node_resources(Node *p_node, const Map<RES, RES> &p_resource_re } Variant v = p_node->get(E.name); - if (v.is_ref()) { + if (v.is_ref_counted()) { RES res = v; if (res.is_valid()) { if (p_resource_remap.has(res)) { @@ -2214,7 +2214,7 @@ void Node::remap_nested_resources(RES p_resource, const Map<RES, RES> &p_resourc } Variant v = p_resource->get(E.name); - if (v.is_ref()) { + if (v.is_ref_counted()) { RES res = v; if (res.is_valid()) { if (p_resource_remap.has(res)) { diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index cafa4a43fd..0c92dcae11 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -1328,6 +1328,8 @@ SceneTree::SceneTree() { root = memnew(Window); root->set_process_mode(Node::PROCESS_MODE_PAUSABLE); root->set_name("root"); + root->set_title(ProjectSettings::get_singleton()->get("application/config/name")); + #ifndef _3D_DISABLED if (!root->get_world_3d().is_valid()) { root->set_world_3d(Ref<World3D>(memnew(World3D))); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 2cdafefba7..1244e0c028 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -523,6 +523,13 @@ void Viewport::_process_picking() { _drop_physics_mouseover(true); +#ifndef _3D_DISABLED + Vector2 last_pos(1e20, 1e20); + CollisionObject3D *last_object = nullptr; + ObjectID last_id; + PhysicsDirectSpaceState3D::RayResult result; +#endif // _3D_DISABLED + PhysicsDirectSpaceState2D *ss2d = PhysicsServer2D::get_singleton()->space_get_direct_state(find_world_2d()->get_space()); if (physics_has_last_mousepos) { @@ -690,10 +697,6 @@ void Viewport::_process_picking() { } #ifndef _3D_DISABLED - Vector2 last_pos(1e20, 1e20); - CollisionObject3D *last_object = nullptr; - ObjectID last_id; - PhysicsDirectSpaceState3D::RayResult result; bool captured = false; if (physics_object_capture.is_valid()) { @@ -790,7 +793,7 @@ void Viewport::update_canvas_items() { } void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated) { - if (size == p_size && size_allocated == p_allocated && stretch_transform == p_stretch_transform && p_size_2d_override == size_2d_override && to_screen_rect != p_to_screen_rect) { + if (size == p_size && size_allocated == p_allocated && stretch_transform == p_stretch_transform && p_size_2d_override == size_2d_override && to_screen_rect == p_to_screen_rect) { return; } @@ -1090,7 +1093,7 @@ Transform2D Viewport::_get_input_pre_xform() const { if (to_screen_rect.size.x != 0 && to_screen_rect.size.y != 0) { pre_xf.elements[2] = -to_screen_rect.position; - pre_xf.scale(size / to_screen_rect.size); + pre_xf.scale(Vector2(size) / to_screen_rect.size); } return pre_xf; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 532b457843..fbc0bc5301 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -41,7 +41,16 @@ void Window::set_title(const String &p_title) { if (embedder) { embedder->_sub_window_update(this); } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { - DisplayServer::get_singleton()->window_set_title(atr(p_title), window_id); + String tr_title = atr(p_title); +#ifdef DEBUG_ENABLED + if (window_id == DisplayServer::MAIN_WINDOW_ID) { + // Append a suffix to the window title to denote that the project is running + // from a debug build (including the editor). Since this results in lower performance, + // this should be clearly presented to the user. + tr_title = vformat("%s (DEBUG)", tr_title); + } +#endif + DisplayServer::get_singleton()->window_set_title(tr_title, window_id); } } @@ -234,7 +243,16 @@ void Window::_make_window() { DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id); DisplayServer::get_singleton()->window_set_max_size(max_size, window_id); DisplayServer::get_singleton()->window_set_min_size(min_size, window_id); - DisplayServer::get_singleton()->window_set_title(atr(title), window_id); + String tr_title = atr(title); +#ifdef DEBUG_ENABLED + if (window_id == DisplayServer::MAIN_WINDOW_ID) { + // Append a suffix to the window title to denote that the project is running + // from a debug build (including the editor). Since this results in lower performance, + // this should be clearly presented to the user. + tr_title = vformat("%s (DEBUG)", tr_title); + } +#endif + DisplayServer::get_singleton()->window_set_title(tr_title, window_id); DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id); _update_window_size(); @@ -773,7 +791,16 @@ void Window::_notification(int p_what) { if (embedder) { embedder->_sub_window_update(this); } else if (window_id != DisplayServer::INVALID_WINDOW_ID) { - DisplayServer::get_singleton()->window_set_title(atr(title), window_id); + String tr_title = atr(title); +#ifdef DEBUG_ENABLED + if (window_id == DisplayServer::MAIN_WINDOW_ID) { + // Append a suffix to the window title to denote that the project is running + // from a debug build (including the editor). Since this results in lower performance, + // this should be clearly presented to the user. + tr_title = vformat("%s (DEBUG)", tr_title); + } +#endif + DisplayServer::get_singleton()->window_set_title(tr_title, window_id); } child_controls_changed(); diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index 25f169b6a2..c2988c2e8c 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -667,11 +667,13 @@ void BitMap::_bind_methods() { ClassDB::bind_method(D_METHOD("get_true_bit_count"), &BitMap::get_true_bit_count); ClassDB::bind_method(D_METHOD("get_size"), &BitMap::get_size); + ClassDB::bind_method(D_METHOD("resize", "new_size"), &BitMap::resize); ClassDB::bind_method(D_METHOD("_set_data"), &BitMap::_set_data); ClassDB::bind_method(D_METHOD("_get_data"), &BitMap::_get_data); ClassDB::bind_method(D_METHOD("grow_mask", "pixels", "rect"), &BitMap::grow_mask); + ClassDB::bind_method(D_METHOD("convert_to_image"), &BitMap::convert_to_image); ClassDB::bind_method(D_METHOD("opaque_to_polygons", "rect", "epsilon"), &BitMap::_opaque_to_polygons_bind, DEFVAL(2.0)); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp index cb8a189116..4d2698d27d 100644 --- a/scene/resources/capsule_shape_2d.cpp +++ b/scene/resources/capsule_shape_2d.cpp @@ -84,13 +84,11 @@ real_t CapsuleShape2D::get_height() const { void CapsuleShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector<Vector2> points = _get_points(); - Vector<Color> col; - col.push_back(p_color); + Vector<Color> col = { p_color }; RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); if (is_collision_outline_enabled()) { + points.push_back(points[0]); RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col); - // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`. - RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color); } } diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp index 68ee1be9f9..9c16ac2eed 100644 --- a/scene/resources/circle_shape_2d.cpp +++ b/scene/resources/circle_shape_2d.cpp @@ -71,18 +71,19 @@ real_t CircleShape2D::get_enclosing_radius() const { void CircleShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector<Vector2> points; + points.resize(24); + const real_t turn_step = Math_TAU / 24.0; for (int i = 0; i < 24; i++) { - points.push_back(Vector2(Math::cos(i * turn_step), Math::sin(i * turn_step)) * get_radius()); + points.write[i] = Vector2(Math::cos(i * turn_step), Math::sin(i * turn_step)) * get_radius(); } - Vector<Color> col; - col.push_back(p_color); + Vector<Color> col = { p_color }; RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); + if (is_collision_outline_enabled()) { + points.push_back(points[0]); RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col); - // Draw the last segment as it's not drawn by `canvas_item_add_polyline()`. - RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color); } } diff --git a/scene/resources/mesh_library.cpp b/scene/resources/mesh_library.cpp index 3db839a1d0..5168bf83eb 100644 --- a/scene/resources/mesh_library.cpp +++ b/scene/resources/mesh_library.cpp @@ -30,6 +30,8 @@ #include "mesh_library.h" +#include "box_shape_3d.h" + bool MeshLibrary::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; if (name.begins_with("item/")) { @@ -255,12 +257,35 @@ int MeshLibrary::get_last_unused_item_id() const { } void MeshLibrary::_set_item_shapes(int p_item, const Array &p_shapes) { - ERR_FAIL_COND(p_shapes.size() & 1); + Array arr_shapes = p_shapes; + int size = p_shapes.size(); + if (size & 1) { + ERR_FAIL_COND_MSG(!item_map.has(p_item), "Requested for nonexistent MeshLibrary item '" + itos(p_item) + "'."); + int prev_size = item_map[p_item].shapes.size() * 2; + + if (prev_size < size) { + // Check if last element is a shape. + Ref<Shape3D> shape = arr_shapes[size - 1]; + if (shape.is_null()) { + Ref<BoxShape3D> box_shape; + box_shape.instantiate(); + arr_shapes[size - 1] = box_shape; + } + + // Make sure the added element is a Transform3D. + arr_shapes.push_back(Transform3D()); + size++; + } else { + size--; + arr_shapes.resize(size); + } + } + Vector<ShapeData> shapes; - for (int i = 0; i < p_shapes.size(); i += 2) { + for (int i = 0; i < size; i += 2) { ShapeData sd; - sd.shape = p_shapes[i + 0]; - sd.local_transform = p_shapes[i + 1]; + sd.shape = arr_shapes[i + 0]; + sd.local_transform = arr_shapes[i + 1]; if (sd.shape.is_valid()) { shapes.push_back(sd); diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index 6ec16f12df..c5d5ba2912 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -292,7 +292,6 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() { } ProceduralSkyMaterial::~ProceduralSkyMaterial() { - RS::get_singleton()->material_set_shader(_get_material(), RID()); } ///////////////////////////////////////// @@ -389,7 +388,6 @@ PanoramaSkyMaterial::PanoramaSkyMaterial() { } PanoramaSkyMaterial::~PanoramaSkyMaterial() { - RS::get_singleton()->material_set_shader(_get_material(), RID()); } ////////////////////////////////// diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index cc7322476f..0677d9c1a8 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -30,7 +30,6 @@ #include "surface_tool.h" -#define _VERTEX_SNAP 0.0001 #define EQ_VERTEX_DIST 0.00001 SurfaceTool::OptimizeVertexCacheFunc SurfaceTool::optimize_vertex_cache_func = nullptr; diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index ece1ba1972..4bc62e7617 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -231,8 +231,8 @@ String VisualShaderNode::get_warning(Shader::Mode p_mode, VisualShader::Type p_t return String(); } -String VisualShaderNode::get_input_port_default_hint(int p_port) const { - return ""; +bool VisualShaderNode::is_input_port_default(int p_port, Shader::Mode p_mode) const { + return false; } void VisualShaderNode::_bind_methods() { @@ -2312,7 +2312,6 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR, "object_position", "OBJECT_POSITION" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR, "uvw", "UVW" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_VECTOR, "extents", "EXTENTS" }, - { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_TRANSFORM, "transform", "TRANSFORM" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "sdf", "SDF" }, { Shader::MODE_FOG, VisualShader::TYPE_FOG, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, @@ -3402,7 +3401,6 @@ bool VisualShaderNodeGroupBase::is_valid_port_name(const String &p_name) const { } void VisualShaderNodeGroupBase::add_input_port(int p_id, int p_type, const String &p_name) { - ERR_FAIL_COND(has_input_port(p_id)); ERR_FAIL_INDEX(p_type, int(PORT_TYPE_MAX)); ERR_FAIL_COND(!is_valid_port_name(p_name)); @@ -3478,7 +3476,6 @@ bool VisualShaderNodeGroupBase::has_input_port(int p_id) const { } void VisualShaderNodeGroupBase::add_output_port(int p_id, int p_type, const String &p_name) { - ERR_FAIL_COND(has_output_port(p_id)); ERR_FAIL_INDEX(p_type, int(PORT_TYPE_MAX)); ERR_FAIL_COND(!is_valid_port_name(p_name)); diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 066c18e3bc..acb33efd30 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -240,7 +240,7 @@ public: virtual PortType get_output_port_type(int p_port) const = 0; virtual String get_output_port_name(int p_port) const = 0; - virtual String get_input_port_default_hint(int p_port) const; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const; void set_output_port_for_preview(int p_index); int get_output_port_for_preview() const; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index b61e3f5d14..0cfa9f31f7 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -487,11 +487,13 @@ bool VisualShaderNodeTexture::is_output_port_expandable(int p_port) const { return false; } -String VisualShaderNodeTexture::get_input_port_default_hint(int p_port) const { - if (p_port == 0) { - return "default"; +bool VisualShaderNodeTexture::is_input_port_default(int p_port, Shader::Mode p_mode) const { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + if (p_port == 0) { + return true; + } } - return ""; + return false; } Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture::get_default_texture_parameters(VisualShader::Type p_type, int p_id) const { @@ -526,7 +528,7 @@ String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShade String VisualShaderNodeTexture::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 default_uv; - if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { default_uv = "UV.xy"; } else { default_uv = "vec2(0.0)"; @@ -1052,16 +1054,18 @@ bool VisualShaderNodeSample3D::is_output_port_expandable(int p_port) const { return false; } -String VisualShaderNodeSample3D::get_input_port_default_hint(int p_port) const { - if (p_port == 0) { - return "default"; +bool VisualShaderNodeSample3D::is_input_port_default(int p_port, Shader::Mode p_mode) const { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + if (p_port == 0) { + return true; + } } - return ""; + return false; } String VisualShaderNodeSample3D::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 default_uv; - if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { default_uv = "vec3(UV, 0.0)"; } else { default_uv = "vec3(0.0)"; @@ -1346,7 +1350,7 @@ String VisualShaderNodeCubemap::generate_global(Shader::Mode p_mode, VisualShade String VisualShaderNodeCubemap::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 default_uv; - if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { default_uv = "vec3(UV, 0.0)"; } else { default_uv = "vec3(0.0)"; @@ -1393,11 +1397,13 @@ String VisualShaderNodeCubemap::generate_code(Shader::Mode p_mode, VisualShader: return code; } -String VisualShaderNodeCubemap::get_input_port_default_hint(int p_port) const { - if (p_port == 0) { - return "default"; +bool VisualShaderNodeCubemap::is_input_port_default(int p_port, Shader::Mode p_mode) const { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + if (p_port == 0) { + return true; + } } - return ""; + return false; } void VisualShaderNodeCubemap::set_source(Source p_source) { @@ -2781,11 +2787,13 @@ String VisualShaderNodeUVFunc::get_input_port_name(int p_port) const { return ""; } -String VisualShaderNodeUVFunc::get_input_port_default_hint(int p_port) const { - if (p_port == 0) { - return "UV"; +bool VisualShaderNodeUVFunc::is_input_port_default(int p_port, Shader::Mode p_mode) const { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + if (p_port == 0) { + return true; + } } - return ""; + return false; } int VisualShaderNodeUVFunc::get_output_port_count() const { @@ -2809,7 +2817,11 @@ String VisualShaderNodeUVFunc::generate_code(Shader::Mode p_mode, VisualShader:: String uv; if (p_input_vars[0].is_empty()) { - uv = "vec3(UV.xy, 0.0)"; + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + uv = "vec3(UV.xy, 0.0)"; + } else { + uv = "vec3(0.0)"; + } } else { uv = vformat("%s", p_input_vars[0]); } @@ -4966,7 +4978,7 @@ bool VisualShaderNodeTextureUniform::is_code_generated() const { String VisualShaderNodeTextureUniform::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 default_uv; - if (p_mode != Shader::MODE_PARTICLES && p_mode != Shader::MODE_SKY) { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { default_uv = "UV.xy"; } else { default_uv = "vec2(0.0)"; @@ -5112,11 +5124,13 @@ void VisualShaderNodeTextureUniform::_bind_methods() { BIND_ENUM_CONSTANT(REPEAT_MAX); } -String VisualShaderNodeTextureUniform::get_input_port_default_hint(int p_port) const { - if (p_port == 0) { - return "default"; +bool VisualShaderNodeTextureUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + if (p_port == 0) { + return true; + } } - return ""; + return false; } bool VisualShaderNodeTextureUniform::is_qualifier_supported(Qualifier p_qual) const { @@ -5224,13 +5238,13 @@ String VisualShaderNodeTextureUniformTriplanar::generate_code(Shader::Mode p_mod return code; } -String VisualShaderNodeTextureUniformTriplanar::get_input_port_default_hint(int p_port) const { +bool VisualShaderNodeTextureUniformTriplanar::is_input_port_default(int p_port, Shader::Mode p_mode) const { if (p_port == 0) { - return "default"; + return true; } else if (p_port == 1) { - return "default"; + return true; } - return ""; + return false; } VisualShaderNodeTextureUniformTriplanar::VisualShaderNodeTextureUniformTriplanar() { @@ -5266,8 +5280,8 @@ String VisualShaderNodeTexture2DArrayUniform::get_input_port_name(int p_port) co return ""; } -String VisualShaderNodeTexture2DArrayUniform::get_input_port_default_hint(int p_port) const { - return ""; +bool VisualShaderNodeTexture2DArrayUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { + return false; } String VisualShaderNodeTexture2DArrayUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { @@ -5339,8 +5353,8 @@ String VisualShaderNodeTexture3DUniform::get_input_port_name(int p_port) const { return ""; } -String VisualShaderNodeTexture3DUniform::get_input_port_default_hint(int p_port) const { - return ""; +bool VisualShaderNodeTexture3DUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { + return false; } String VisualShaderNodeTexture3DUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { @@ -5412,8 +5426,8 @@ String VisualShaderNodeCubemapUniform::get_input_port_name(int p_port) const { return ""; } -String VisualShaderNodeCubemapUniform::get_input_port_default_hint(int p_port) const { - return ""; +bool VisualShaderNodeCubemapUniform::is_input_port_default(int p_port, Shader::Mode p_mode) const { + return false; } String VisualShaderNodeCubemapUniform::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const { @@ -5738,12 +5752,20 @@ String VisualShaderNodeFresnel::generate_code(Shader::Mode p_mode, VisualShader: String normal; String view; if (p_input_vars[0].is_empty()) { - normal = "NORMAL"; + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + normal = "NORMAL"; + } else { + normal = "vec3(0.0)"; + } } else { normal = p_input_vars[0]; } if (p_input_vars[1].is_empty()) { - view = "VIEW"; + if (p_mode == Shader::MODE_SPATIAL) { + view = "VIEW"; + } else { + view = "vec3(0.0)"; + } } else { view = p_input_vars[1]; } @@ -5759,13 +5781,17 @@ String VisualShaderNodeFresnel::generate_code(Shader::Mode p_mode, VisualShader: } } -String VisualShaderNodeFresnel::get_input_port_default_hint(int p_port) const { +bool VisualShaderNodeFresnel::is_input_port_default(int p_port, Shader::Mode p_mode) const { if (p_port == 0) { - return "default"; + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + return true; + } } else if (p_port == 1) { - return "default"; + if (p_mode == Shader::MODE_SPATIAL) { + return true; + } } - return ""; + return false; } VisualShaderNodeFresnel::VisualShaderNodeFresnel() { diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index f1dda634f1..bf5777a3fb 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -280,7 +280,7 @@ public: virtual String get_output_port_name(int p_port) const override; virtual bool is_output_port_expandable(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual Vector<VisualShader::DefaultTextureParam> get_default_texture_parameters(VisualShader::Type p_type, int p_id) const override; virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; @@ -392,7 +392,7 @@ public: 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 String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; @@ -488,7 +488,7 @@ public: 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 String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; @@ -1103,7 +1103,7 @@ public: 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 String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; @@ -1986,7 +1986,7 @@ public: 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 String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual int get_output_port_count() const override; virtual PortType get_output_port_type(int p_port) const override; @@ -2036,7 +2036,7 @@ public: virtual PortType get_input_port_type(int p_port) const override; virtual String get_input_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual String generate_global_per_node(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override; @@ -2061,7 +2061,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) 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; @@ -2084,7 +2084,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) 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; @@ -2107,7 +2107,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) 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; @@ -2200,7 +2200,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; virtual bool is_generate_input_var(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; diff --git a/scene/resources/visual_shader_particle_nodes.cpp b/scene/resources/visual_shader_particle_nodes.cpp index c970b9c08b..fbac92a06d 100644 --- a/scene/resources/visual_shader_particle_nodes.cpp +++ b/scene/resources/visual_shader_particle_nodes.cpp @@ -1448,22 +1448,22 @@ bool VisualShaderNodeParticleEmit::is_generate_input_var(int p_port) const { return true; } -String VisualShaderNodeParticleEmit::get_input_port_default_hint(int p_port) const { +bool VisualShaderNodeParticleEmit::is_input_port_default(int p_port, Shader::Mode p_mode) const { switch (p_port) { case 1: - return "default"; + return true; case 2: - return "default"; + return true; case 3: - return "default"; + return true; case 4: - return "default"; + return true; case 5: - return "default"; + return true; case 6: - return "default"; + return true; } - return String(); + return false; } String VisualShaderNodeParticleEmit::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 { diff --git a/scene/resources/visual_shader_particle_nodes.h b/scene/resources/visual_shader_particle_nodes.h index add6928841..ce0d896c01 100644 --- a/scene/resources/visual_shader_particle_nodes.h +++ b/scene/resources/visual_shader_particle_nodes.h @@ -342,7 +342,7 @@ public: virtual bool is_show_prop_names() const override; virtual bool is_generate_input_var(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) 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; VisualShaderNodeParticleEmit(); diff --git a/scene/resources/visual_shader_sdf_nodes.cpp b/scene/resources/visual_shader_sdf_nodes.cpp index 1b43fda4c5..6654e2319b 100644 --- a/scene/resources/visual_shader_sdf_nodes.cpp +++ b/scene/resources/visual_shader_sdf_nodes.cpp @@ -97,11 +97,11 @@ String VisualShaderNodeScreenUVToSDF::get_output_port_name(int p_port) const { return ""; } -String VisualShaderNodeScreenUVToSDF::get_input_port_default_hint(int p_port) const { +bool VisualShaderNodeScreenUVToSDF::is_input_port_default(int p_port, Shader::Mode p_mode) const { if (p_port == 0) { - return "default"; + return true; } - return ""; + return false; } String VisualShaderNodeScreenUVToSDF::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 { diff --git a/scene/resources/visual_shader_sdf_nodes.h b/scene/resources/visual_shader_sdf_nodes.h index d2d1dde4ea..7c1f695423 100644 --- a/scene/resources/visual_shader_sdf_nodes.h +++ b/scene/resources/visual_shader_sdf_nodes.h @@ -66,7 +66,7 @@ public: virtual PortType get_output_port_type(int p_port) const override; virtual String get_output_port_name(int p_port) const override; - virtual String get_input_port_default_hint(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) 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; VisualShaderNodeScreenUVToSDF(); |